* [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support
@ 2025-08-11 6:02 Binbin Zhou
2025-08-11 6:02 ` [PATCH v2 1/8] mtd: rawnand: loongson1: Rename the prefix from ls1x to loongson Binbin Zhou
` (7 more replies)
0 siblings, 8 replies; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 6:02 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Binbin Zhou
Hi all:
This patchset adds support for the Loongson-2K0500/Loongson-2K1000 NAND
controllers, which are similar to the Loongson-1C NAND controller.
They support a maximum capacity of 16GB FLASH per chip, with a maximum
page size of 8KB. The chip supports up to 4 chip selects and 4 RDY signals.
The key difference between the Loongson-2K NAND controllers is that the
Loongson-2K1000 explicitly configures the DMA controller routing, while
the Loongson-2K0500 defaults to using APBDMA0.
Summary of the patchset:
Ptach 1-2: Rename all prefixes from ls1x to loongson
Patch 3: Add 6-byte NAND ID reading
Patch 4: Add chip select support
Patch 5-6: Add Loongson-2K0500 NAND controller support
Patch 7-8: Add Loongson-2K1000 NAND controller support
Thanks.
-------
V2:
Based on linux-mtd/nand/next.
Patch (5/8):
- Add Acked-by tag from Rob, thanks;
Patch (7/8):
- Update reg-names attribute description.
Link to V1:
https://lore.kernel.org/all/cover.1753166096.git.zhoubinbin@loongson.cn/
Binbin Zhou (7):
mtd: rawnand: loongson1: Rename the prefix from ls1x to loongson
mtd: rawnand: loongson: Rename loongson1 to loongson
mtd: rawnand: loongson: Add nand chip select support
dt-bindings: mtd: loongson,ls1b-nand-controller: Document the
Loongson-2K0500 NAND controller
mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
dt-bindings: mtd: loongson,ls1b-nand-controller: Document the
Loongson-2K1000 NAND controller
mtd: rawnand: loongson: Add Loongson-2K1000 NAND controller support
Keguang Zhang (1):
mtd: rawnand: loongson: Add 6-byte NAND ID reading support
.../mtd/loongson,ls1b-nand-controller.yaml | 56 +-
MAINTAINERS | 2 +-
drivers/mtd/nand/raw/Kconfig | 8 +-
drivers/mtd/nand/raw/Makefile | 2 +-
.../mtd/nand/raw/loongson-nand-controller.c | 1032 +++++++++++++++++
.../mtd/nand/raw/loongson1-nand-controller.c | 836 -------------
6 files changed, 1091 insertions(+), 845 deletions(-)
create mode 100644 drivers/mtd/nand/raw/loongson-nand-controller.c
delete mode 100644 drivers/mtd/nand/raw/loongson1-nand-controller.c
base-commit: fb2fae70e7e985c4acb1ad96110d8b98bb64a87c
--
2.47.3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v2 1/8] mtd: rawnand: loongson1: Rename the prefix from ls1x to loongson
2025-08-11 6:02 [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support Binbin Zhou
@ 2025-08-11 6:02 ` Binbin Zhou
2025-08-11 6:02 ` [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 " Binbin Zhou
` (6 subsequent siblings)
7 siblings, 0 replies; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 6:02 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Binbin Zhou
I am going to introduce the NAND controllers of the Loongson-2K series
CPUs, which are similar to Loongson-1.
As preparation, first rename all prefixes from ls1x to loongson.
No functional change intended.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../mtd/nand/raw/loongson1-nand-controller.c | 337 +++++++++---------
1 file changed, 172 insertions(+), 165 deletions(-)
diff --git a/drivers/mtd/nand/raw/loongson1-nand-controller.c b/drivers/mtd/nand/raw/loongson1-nand-controller.c
index ef8e4f9ce287..b5a7be0fcacc 100644
--- a/drivers/mtd/nand/raw/loongson1-nand-controller.c
+++ b/drivers/mtd/nand/raw/loongson1-nand-controller.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * NAND Controller Driver for Loongson-1 SoC
+ * NAND Controller Driver for Loongson family chips
*
* Copyright (C) 2015-2025 Keguang Zhang <keguang.zhang@gmail.com>
*/
@@ -17,42 +17,45 @@
#include <linux/regmap.h>
#include <linux/sizes.h>
-/* Loongson-1 NAND Controller Registers */
-#define LS1X_NAND_CMD 0x0
-#define LS1X_NAND_ADDR1 0x4
-#define LS1X_NAND_ADDR2 0x8
-#define LS1X_NAND_TIMING 0xc
-#define LS1X_NAND_IDL 0x10
-#define LS1X_NAND_IDH_STATUS 0x14
-#define LS1X_NAND_PARAM 0x18
-#define LS1X_NAND_OP_NUM 0x1c
-
-/* NAND Command Register Bits */
-#define LS1X_NAND_CMD_OP_DONE BIT(10)
-#define LS1X_NAND_CMD_OP_SPARE BIT(9)
-#define LS1X_NAND_CMD_OP_MAIN BIT(8)
-#define LS1X_NAND_CMD_STATUS BIT(7)
-#define LS1X_NAND_CMD_RESET BIT(6)
-#define LS1X_NAND_CMD_READID BIT(5)
-#define LS1X_NAND_CMD_BLOCKS_ERASE BIT(4)
-#define LS1X_NAND_CMD_ERASE BIT(3)
-#define LS1X_NAND_CMD_WRITE BIT(2)
-#define LS1X_NAND_CMD_READ BIT(1)
-#define LS1X_NAND_CMD_VALID BIT(0)
-
-#define LS1X_NAND_WAIT_CYCLE_MASK GENMASK(7, 0)
-#define LS1X_NAND_HOLD_CYCLE_MASK GENMASK(15, 8)
-#define LS1X_NAND_CELL_SIZE_MASK GENMASK(11, 8)
-
-#define LS1X_NAND_COL_ADDR_CYC 2U
-#define LS1X_NAND_MAX_ADDR_CYC 5U
-
-#define BITS_PER_WORD (4 * BITS_PER_BYTE)
-
-struct ls1x_nand_host;
-
-struct ls1x_nand_op {
- char addrs[LS1X_NAND_MAX_ADDR_CYC];
+/* Loongson NAND Controller Registers */
+#define LOONGSON_NAND_CMD 0x0
+#define LOONGSON_NAND_ADDR1 0x4
+#define LOONGSON_NAND_ADDR2 0x8
+#define LOONGSON_NAND_TIMING 0xc
+#define LOONGSON_NAND_IDL 0x10
+#define LOONGSON_NAND_IDH_STATUS 0x14
+#define LOONGSON_NAND_PARAM 0x18
+#define LOONGSON_NAND_OP_NUM 0x1c
+
+/* Bitfields of nand command register */
+#define LOONGSON_NAND_CMD_OP_DONE BIT(10)
+#define LOONGSON_NAND_CMD_OP_SPARE BIT(9)
+#define LOONGSON_NAND_CMD_OP_MAIN BIT(8)
+#define LOONGSON_NAND_CMD_STATUS BIT(7)
+#define LOONGSON_NAND_CMD_RESET BIT(6)
+#define LOONGSON_NAND_CMD_READID BIT(5)
+#define LOONGSON_NAND_CMD_BLOCKS_ERASE BIT(4)
+#define LOONGSON_NAND_CMD_ERASE BIT(3)
+#define LOONGSON_NAND_CMD_WRITE BIT(2)
+#define LOONGSON_NAND_CMD_READ BIT(1)
+#define LOONGSON_NAND_CMD_VALID BIT(0)
+
+/* Bitfields of nand timing register */
+#define LOONGSON_NAND_WAIT_CYCLE_MASK GENMASK(7, 0)
+#define LOONGSON_NAND_HOLD_CYCLE_MASK GENMASK(15, 8)
+
+/* Bitfields of nand parameter register */
+#define LOONGSON_NAND_CELL_SIZE_MASK GENMASK(11, 8)
+
+#define LOONGSON_NAND_COL_ADDR_CYC 2U
+#define LOONGSON_NAND_MAX_ADDR_CYC 5U
+
+#define BITS_PER_WORD (4 * BITS_PER_BYTE)
+
+struct loongson_nand_host;
+
+struct loongson_nand_op {
+ char addrs[LOONGSON_NAND_MAX_ADDR_CYC];
unsigned int naddrs;
unsigned int addrs_offset;
unsigned int aligned_offset;
@@ -69,19 +72,19 @@ struct ls1x_nand_op {
char *buf;
};
-struct ls1x_nand_data {
+struct loongson_nand_data {
unsigned int status_field;
unsigned int op_scope_field;
unsigned int hold_cycle;
unsigned int wait_cycle;
- void (*set_addr)(struct ls1x_nand_host *host, struct ls1x_nand_op *op);
+ void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
};
-struct ls1x_nand_host {
+struct loongson_nand_host {
struct device *dev;
struct nand_chip chip;
struct nand_controller controller;
- const struct ls1x_nand_data *data;
+ const struct loongson_nand_data *data;
void __iomem *reg_base;
struct regmap *regmap;
/* DMA Engine stuff */
@@ -91,40 +94,41 @@ struct ls1x_nand_host {
struct completion dma_complete;
};
-static const struct regmap_config ls1x_nand_regmap_config = {
+static const struct regmap_config loongson_nand_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
-static int ls1x_nand_op_cmd_mapping(struct nand_chip *chip, struct ls1x_nand_op *op, u8 opcode)
+static int loongson_nand_op_cmd_mapping(struct nand_chip *chip, struct loongson_nand_op *op,
+ u8 opcode)
{
- struct ls1x_nand_host *host = nand_get_controller_data(chip);
+ struct loongson_nand_host *host = nand_get_controller_data(chip);
op->row_start = chip->page_shift + 1;
/* The controller abstracts the following NAND operations. */
switch (opcode) {
case NAND_CMD_STATUS:
- op->cmd_reg = LS1X_NAND_CMD_STATUS;
+ op->cmd_reg = LOONGSON_NAND_CMD_STATUS;
break;
case NAND_CMD_RESET:
- op->cmd_reg = LS1X_NAND_CMD_RESET;
+ op->cmd_reg = LOONGSON_NAND_CMD_RESET;
break;
case NAND_CMD_READID:
op->is_readid = true;
- op->cmd_reg = LS1X_NAND_CMD_READID;
+ op->cmd_reg = LOONGSON_NAND_CMD_READID;
break;
case NAND_CMD_ERASE1:
op->is_erase = true;
- op->addrs_offset = LS1X_NAND_COL_ADDR_CYC;
+ op->addrs_offset = LOONGSON_NAND_COL_ADDR_CYC;
break;
case NAND_CMD_ERASE2:
if (!op->is_erase)
return -EOPNOTSUPP;
/* During erasing, row_start differs from the default value. */
op->row_start = chip->page_shift;
- op->cmd_reg = LS1X_NAND_CMD_ERASE;
+ op->cmd_reg = LOONGSON_NAND_CMD_ERASE;
break;
case NAND_CMD_SEQIN:
op->is_write = true;
@@ -132,7 +136,7 @@ static int ls1x_nand_op_cmd_mapping(struct nand_chip *chip, struct ls1x_nand_op
case NAND_CMD_PAGEPROG:
if (!op->is_write)
return -EOPNOTSUPP;
- op->cmd_reg = LS1X_NAND_CMD_WRITE;
+ op->cmd_reg = LOONGSON_NAND_CMD_WRITE;
break;
case NAND_CMD_READ0:
op->is_read = true;
@@ -140,7 +144,7 @@ static int ls1x_nand_op_cmd_mapping(struct nand_chip *chip, struct ls1x_nand_op
case NAND_CMD_READSTART:
if (!op->is_read)
return -EOPNOTSUPP;
- op->cmd_reg = LS1X_NAND_CMD_READ;
+ op->cmd_reg = LOONGSON_NAND_CMD_READ;
break;
case NAND_CMD_RNDOUT:
op->is_change_column = true;
@@ -148,7 +152,7 @@ static int ls1x_nand_op_cmd_mapping(struct nand_chip *chip, struct ls1x_nand_op
case NAND_CMD_RNDOUTSTART:
if (!op->is_change_column)
return -EOPNOTSUPP;
- op->cmd_reg = LS1X_NAND_CMD_READ;
+ op->cmd_reg = LOONGSON_NAND_CMD_READ;
break;
default:
dev_dbg(host->dev, "unsupported opcode: %u\n", opcode);
@@ -158,8 +162,8 @@ static int ls1x_nand_op_cmd_mapping(struct nand_chip *chip, struct ls1x_nand_op
return 0;
}
-static int ls1x_nand_parse_instructions(struct nand_chip *chip,
- const struct nand_subop *subop, struct ls1x_nand_op *op)
+static int loongson_nand_parse_instructions(struct nand_chip *chip, const struct nand_subop *subop,
+ struct loongson_nand_op *op)
{
unsigned int op_id;
int ret;
@@ -171,14 +175,14 @@ static int ls1x_nand_parse_instructions(struct nand_chip *chip,
switch (instr->type) {
case NAND_OP_CMD_INSTR:
- ret = ls1x_nand_op_cmd_mapping(chip, op, instr->ctx.cmd.opcode);
+ ret = loongson_nand_op_cmd_mapping(chip, op, instr->ctx.cmd.opcode);
if (ret < 0)
return ret;
break;
case NAND_OP_ADDR_INSTR:
naddrs = nand_subop_get_num_addr_cyc(subop, op_id);
- if (naddrs > LS1X_NAND_MAX_ADDR_CYC)
+ if (naddrs > LOONGSON_NAND_MAX_ADDR_CYC)
return -EOPNOTSUPP;
op->naddrs = naddrs;
offset = nand_subop_get_addr_start_off(subop, op_id);
@@ -206,57 +210,57 @@ static int ls1x_nand_parse_instructions(struct nand_chip *chip,
return 0;
}
-static void ls1b_nand_set_addr(struct ls1x_nand_host *host, struct ls1x_nand_op *op)
+static void ls1b_nand_set_addr(struct loongson_nand_host *host, struct loongson_nand_op *op)
{
struct nand_chip *chip = &host->chip;
int i;
- for (i = 0; i < LS1X_NAND_MAX_ADDR_CYC; i++) {
+ for (i = 0; i < LOONGSON_NAND_MAX_ADDR_CYC; i++) {
int shift, mask, val;
- if (i < LS1X_NAND_COL_ADDR_CYC) {
+ if (i < LOONGSON_NAND_COL_ADDR_CYC) {
shift = i * BITS_PER_BYTE;
mask = (u32)0xff << shift;
mask &= GENMASK(chip->page_shift, 0);
val = (u32)op->addrs[i] << shift;
- regmap_update_bits(host->regmap, LS1X_NAND_ADDR1, mask, val);
+ regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR1, mask, val);
} else if (!op->is_change_column) {
- shift = op->row_start + (i - LS1X_NAND_COL_ADDR_CYC) * BITS_PER_BYTE;
+ shift = op->row_start + (i - LOONGSON_NAND_COL_ADDR_CYC) * BITS_PER_BYTE;
mask = (u32)0xff << shift;
val = (u32)op->addrs[i] << shift;
- regmap_update_bits(host->regmap, LS1X_NAND_ADDR1, mask, val);
+ regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR1, mask, val);
if (i == 4) {
mask = (u32)0xff >> (BITS_PER_WORD - shift);
val = (u32)op->addrs[i] >> (BITS_PER_WORD - shift);
- regmap_update_bits(host->regmap, LS1X_NAND_ADDR2, mask, val);
+ regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, mask, val);
}
}
}
}
-static void ls1c_nand_set_addr(struct ls1x_nand_host *host, struct ls1x_nand_op *op)
+static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_nand_op *op)
{
int i;
- for (i = 0; i < LS1X_NAND_MAX_ADDR_CYC; i++) {
+ for (i = 0; i < LOONGSON_NAND_MAX_ADDR_CYC; i++) {
int shift, mask, val;
- if (i < LS1X_NAND_COL_ADDR_CYC) {
+ if (i < LOONGSON_NAND_COL_ADDR_CYC) {
shift = i * BITS_PER_BYTE;
mask = (u32)0xff << shift;
val = (u32)op->addrs[i] << shift;
- regmap_update_bits(host->regmap, LS1X_NAND_ADDR1, mask, val);
+ regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR1, mask, val);
} else if (!op->is_change_column) {
- shift = (i - LS1X_NAND_COL_ADDR_CYC) * BITS_PER_BYTE;
+ shift = (i - LOONGSON_NAND_COL_ADDR_CYC) * BITS_PER_BYTE;
mask = (u32)0xff << shift;
val = (u32)op->addrs[i] << shift;
- regmap_update_bits(host->regmap, LS1X_NAND_ADDR2, mask, val);
+ regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, mask, val);
}
}
}
-static void ls1x_nand_trigger_op(struct ls1x_nand_host *host, struct ls1x_nand_op *op)
+static void loongson_nand_trigger_op(struct loongson_nand_host *host, struct loongson_nand_op *op)
{
struct nand_chip *chip = &host->chip;
struct mtd_info *mtd = nand_to_mtd(chip);
@@ -280,7 +284,7 @@ static void ls1x_nand_trigger_op(struct ls1x_nand_host *host, struct ls1x_nand_o
else
op->len = op->orig_len;
- writel(op->len, host->reg_base + LS1X_NAND_OP_NUM);
+ writel(op->len, host->reg_base + LOONGSON_NAND_OP_NUM);
/* set operation area and scope */
col = op->addrs[1] << BITS_PER_BYTE | op->addrs[0];
@@ -288,33 +292,35 @@ static void ls1x_nand_trigger_op(struct ls1x_nand_host *host, struct ls1x_nand_o
unsigned int op_scope = 0;
if (col < mtd->writesize) {
- op->cmd_reg |= LS1X_NAND_CMD_OP_MAIN;
+ op->cmd_reg |= LOONGSON_NAND_CMD_OP_MAIN;
op_scope = mtd->writesize;
}
- op->cmd_reg |= LS1X_NAND_CMD_OP_SPARE;
+ op->cmd_reg |= LOONGSON_NAND_CMD_OP_SPARE;
op_scope += mtd->oobsize;
op_scope <<= __ffs(host->data->op_scope_field);
- regmap_update_bits(host->regmap, LS1X_NAND_PARAM,
+ regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM,
host->data->op_scope_field, op_scope);
}
/* set command */
- writel(op->cmd_reg, host->reg_base + LS1X_NAND_CMD);
+ writel(op->cmd_reg, host->reg_base + LOONGSON_NAND_CMD);
/* trigger operation */
- regmap_write_bits(host->regmap, LS1X_NAND_CMD, LS1X_NAND_CMD_VALID, LS1X_NAND_CMD_VALID);
+ regmap_write_bits(host->regmap, LOONGSON_NAND_CMD, LOONGSON_NAND_CMD_VALID,
+ LOONGSON_NAND_CMD_VALID);
}
-static int ls1x_nand_wait_for_op_done(struct ls1x_nand_host *host, struct ls1x_nand_op *op)
+static int loongson_nand_wait_for_op_done(struct loongson_nand_host *host,
+ struct loongson_nand_op *op)
{
unsigned int val;
int ret = 0;
if (op->rdy_timeout_ms) {
- ret = regmap_read_poll_timeout(host->regmap, LS1X_NAND_CMD,
- val, val & LS1X_NAND_CMD_OP_DONE,
+ ret = regmap_read_poll_timeout(host->regmap, LOONGSON_NAND_CMD,
+ val, val & LOONGSON_NAND_CMD_OP_DONE,
0, op->rdy_timeout_ms * MSEC_PER_SEC);
if (ret)
dev_err(host->dev, "operation failed\n");
@@ -323,9 +329,9 @@ static int ls1x_nand_wait_for_op_done(struct ls1x_nand_host *host, struct ls1x_n
return ret;
}
-static void ls1x_nand_dma_callback(void *data)
+static void loongson_nand_dma_callback(void *data)
{
- struct ls1x_nand_host *host = (struct ls1x_nand_host *)data;
+ struct loongson_nand_host *host = (struct loongson_nand_host *)data;
struct dma_chan *chan = host->dma_chan;
struct device *dev = chan->device->dev;
enum dma_status status;
@@ -339,7 +345,7 @@ static void ls1x_nand_dma_callback(void *data)
}
}
-static int ls1x_nand_dma_transfer(struct ls1x_nand_host *host, struct ls1x_nand_op *op)
+static int loongson_nand_dma_transfer(struct loongson_nand_host *host, struct loongson_nand_op *op)
{
struct nand_chip *chip = &host->chip;
struct dma_chan *chan = host->dma_chan;
@@ -374,7 +380,7 @@ static int ls1x_nand_dma_transfer(struct ls1x_nand_host *host, struct ls1x_nand_
ret = -ENOMEM;
goto err;
}
- desc->callback = ls1x_nand_dma_callback;
+ desc->callback = loongson_nand_dma_callback;
desc->callback_param = host;
host->dma_cookie = dmaengine_submit(desc);
@@ -405,51 +411,51 @@ static int ls1x_nand_dma_transfer(struct ls1x_nand_host *host, struct ls1x_nand_
return ret;
}
-static int ls1x_nand_data_type_exec(struct nand_chip *chip, const struct nand_subop *subop)
+static int loongson_nand_data_type_exec(struct nand_chip *chip, const struct nand_subop *subop)
{
- struct ls1x_nand_host *host = nand_get_controller_data(chip);
- struct ls1x_nand_op op = {};
+ struct loongson_nand_host *host = nand_get_controller_data(chip);
+ struct loongson_nand_op op = {};
int ret;
- ret = ls1x_nand_parse_instructions(chip, subop, &op);
+ ret = loongson_nand_parse_instructions(chip, subop, &op);
if (ret)
return ret;
- ls1x_nand_trigger_op(host, &op);
+ loongson_nand_trigger_op(host, &op);
- ret = ls1x_nand_dma_transfer(host, &op);
+ ret = loongson_nand_dma_transfer(host, &op);
if (ret)
return ret;
- return ls1x_nand_wait_for_op_done(host, &op);
+ return loongson_nand_wait_for_op_done(host, &op);
}
-static int ls1x_nand_misc_type_exec(struct nand_chip *chip,
- const struct nand_subop *subop, struct ls1x_nand_op *op)
+static int loongson_nand_misc_type_exec(struct nand_chip *chip, const struct nand_subop *subop,
+ struct loongson_nand_op *op)
{
- struct ls1x_nand_host *host = nand_get_controller_data(chip);
+ struct loongson_nand_host *host = nand_get_controller_data(chip);
int ret;
- ret = ls1x_nand_parse_instructions(chip, subop, op);
+ ret = loongson_nand_parse_instructions(chip, subop, op);
if (ret)
return ret;
- ls1x_nand_trigger_op(host, op);
+ loongson_nand_trigger_op(host, op);
- return ls1x_nand_wait_for_op_done(host, op);
+ return loongson_nand_wait_for_op_done(host, op);
}
-static int ls1x_nand_zerolen_type_exec(struct nand_chip *chip, const struct nand_subop *subop)
+static int loongson_nand_zerolen_type_exec(struct nand_chip *chip, const struct nand_subop *subop)
{
- struct ls1x_nand_op op = {};
+ struct loongson_nand_op op = {};
- return ls1x_nand_misc_type_exec(chip, subop, &op);
+ return loongson_nand_misc_type_exec(chip, subop, &op);
}
-static int ls1x_nand_read_id_type_exec(struct nand_chip *chip, const struct nand_subop *subop)
+static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct nand_subop *subop)
{
- struct ls1x_nand_host *host = nand_get_controller_data(chip);
- struct ls1x_nand_op op = {};
+ struct loongson_nand_host *host = nand_get_controller_data(chip);
+ struct loongson_nand_op op = {};
int i, ret;
union {
char ids[5];
@@ -459,12 +465,12 @@ static int ls1x_nand_read_id_type_exec(struct nand_chip *chip, const struct nand
};
} nand_id;
- ret = ls1x_nand_misc_type_exec(chip, subop, &op);
+ ret = loongson_nand_misc_type_exec(chip, subop, &op);
if (ret)
return ret;
- nand_id.idl = readl(host->reg_base + LS1X_NAND_IDL);
- nand_id.idh = readb(host->reg_base + LS1X_NAND_IDH_STATUS);
+ nand_id.idl = readl(host->reg_base + LOONGSON_NAND_IDL);
+ nand_id.idh = readb(host->reg_base + LOONGSON_NAND_IDH_STATUS);
for (i = 0; i < min(sizeof(nand_id.ids), op.orig_len); i++)
op.buf[i] = nand_id.ids[sizeof(nand_id.ids) - 1 - i];
@@ -472,60 +478,61 @@ static int ls1x_nand_read_id_type_exec(struct nand_chip *chip, const struct nand
return ret;
}
-static int ls1x_nand_read_status_type_exec(struct nand_chip *chip, const struct nand_subop *subop)
+static int loongson_nand_read_status_type_exec(struct nand_chip *chip,
+ const struct nand_subop *subop)
{
- struct ls1x_nand_host *host = nand_get_controller_data(chip);
- struct ls1x_nand_op op = {};
+ struct loongson_nand_host *host = nand_get_controller_data(chip);
+ struct loongson_nand_op op = {};
int val, ret;
- ret = ls1x_nand_misc_type_exec(chip, subop, &op);
+ ret = loongson_nand_misc_type_exec(chip, subop, &op);
if (ret)
return ret;
- val = readl(host->reg_base + LS1X_NAND_IDH_STATUS);
+ val = readl(host->reg_base + LOONGSON_NAND_IDH_STATUS);
val &= ~host->data->status_field;
op.buf[0] = val << ffs(host->data->status_field);
return ret;
}
-static const struct nand_op_parser ls1x_nand_op_parser = NAND_OP_PARSER(
+static const struct nand_op_parser loongson_nand_op_parser = NAND_OP_PARSER(
NAND_OP_PARSER_PATTERN(
- ls1x_nand_read_id_type_exec,
+ loongson_nand_read_id_type_exec,
NAND_OP_PARSER_PAT_CMD_ELEM(false),
- NAND_OP_PARSER_PAT_ADDR_ELEM(false, LS1X_NAND_MAX_ADDR_CYC),
+ NAND_OP_PARSER_PAT_ADDR_ELEM(false, LOONGSON_NAND_MAX_ADDR_CYC),
NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, 8)),
NAND_OP_PARSER_PATTERN(
- ls1x_nand_read_status_type_exec,
+ loongson_nand_read_status_type_exec,
NAND_OP_PARSER_PAT_CMD_ELEM(false),
NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, 1)),
NAND_OP_PARSER_PATTERN(
- ls1x_nand_zerolen_type_exec,
+ loongson_nand_zerolen_type_exec,
NAND_OP_PARSER_PAT_CMD_ELEM(false),
NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
NAND_OP_PARSER_PATTERN(
- ls1x_nand_zerolen_type_exec,
+ loongson_nand_zerolen_type_exec,
NAND_OP_PARSER_PAT_CMD_ELEM(false),
- NAND_OP_PARSER_PAT_ADDR_ELEM(false, LS1X_NAND_MAX_ADDR_CYC),
+ NAND_OP_PARSER_PAT_ADDR_ELEM(false, LOONGSON_NAND_MAX_ADDR_CYC),
NAND_OP_PARSER_PAT_CMD_ELEM(false),
NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
NAND_OP_PARSER_PATTERN(
- ls1x_nand_data_type_exec,
+ loongson_nand_data_type_exec,
NAND_OP_PARSER_PAT_CMD_ELEM(false),
- NAND_OP_PARSER_PAT_ADDR_ELEM(false, LS1X_NAND_MAX_ADDR_CYC),
+ NAND_OP_PARSER_PAT_ADDR_ELEM(false, LOONGSON_NAND_MAX_ADDR_CYC),
NAND_OP_PARSER_PAT_CMD_ELEM(false),
NAND_OP_PARSER_PAT_WAITRDY_ELEM(true),
NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, 0)),
NAND_OP_PARSER_PATTERN(
- ls1x_nand_data_type_exec,
+ loongson_nand_data_type_exec,
NAND_OP_PARSER_PAT_CMD_ELEM(false),
- NAND_OP_PARSER_PAT_ADDR_ELEM(false, LS1X_NAND_MAX_ADDR_CYC),
+ NAND_OP_PARSER_PAT_ADDR_ELEM(false, LOONGSON_NAND_MAX_ADDR_CYC),
NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, 0),
NAND_OP_PARSER_PAT_CMD_ELEM(false),
NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)),
);
-static int ls1x_nand_is_valid_cmd(u8 opcode)
+static int loongson_nand_is_valid_cmd(u8 opcode)
{
if (opcode == NAND_CMD_STATUS || opcode == NAND_CMD_RESET || opcode == NAND_CMD_READID)
return 0;
@@ -533,7 +540,7 @@ static int ls1x_nand_is_valid_cmd(u8 opcode)
return -EOPNOTSUPP;
}
-static int ls1x_nand_is_valid_cmd_seq(u8 opcode1, u8 opcode2)
+static int loongson_nand_is_valid_cmd_seq(u8 opcode1, u8 opcode2)
{
if (opcode1 == NAND_CMD_RNDOUT && opcode2 == NAND_CMD_RNDOUTSTART)
return 0;
@@ -550,7 +557,7 @@ static int ls1x_nand_is_valid_cmd_seq(u8 opcode1, u8 opcode2)
return -EOPNOTSUPP;
}
-static int ls1x_nand_check_op(struct nand_chip *chip, const struct nand_operation *op)
+static int loongson_nand_check_op(struct nand_chip *chip, const struct nand_operation *op)
{
const struct nand_op_instr *instr1 = NULL, *instr2 = NULL;
int op_id;
@@ -572,23 +579,23 @@ static int ls1x_nand_check_op(struct nand_chip *chip, const struct nand_operatio
return -EOPNOTSUPP;
if (!instr2)
- return ls1x_nand_is_valid_cmd(instr1->ctx.cmd.opcode);
+ return loongson_nand_is_valid_cmd(instr1->ctx.cmd.opcode);
- return ls1x_nand_is_valid_cmd_seq(instr1->ctx.cmd.opcode, instr2->ctx.cmd.opcode);
+ return loongson_nand_is_valid_cmd_seq(instr1->ctx.cmd.opcode, instr2->ctx.cmd.opcode);
}
-static int ls1x_nand_exec_op(struct nand_chip *chip,
- const struct nand_operation *op, bool check_only)
+static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_operation *op,
+ bool check_only)
{
if (check_only)
- return ls1x_nand_check_op(chip, op);
+ return loongson_nand_check_op(chip, op);
- return nand_op_parser_exec_op(chip, &ls1x_nand_op_parser, op, check_only);
+ return nand_op_parser_exec_op(chip, &loongson_nand_op_parser, op, check_only);
}
-static int ls1x_nand_attach_chip(struct nand_chip *chip)
+static int loongson_nand_attach_chip(struct nand_chip *chip)
{
- struct ls1x_nand_host *host = nand_get_controller_data(chip);
+ struct loongson_nand_host *host = nand_get_controller_data(chip);
u64 chipsize = nanddev_target_size(&chip->base);
int cell_size = 0;
@@ -632,14 +639,14 @@ static int ls1x_nand_attach_chip(struct nand_chip *chip)
}
/* set cell size */
- regmap_update_bits(host->regmap, LS1X_NAND_PARAM, LS1X_NAND_CELL_SIZE_MASK,
- FIELD_PREP(LS1X_NAND_CELL_SIZE_MASK, cell_size));
+ regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM, LOONGSON_NAND_CELL_SIZE_MASK,
+ FIELD_PREP(LOONGSON_NAND_CELL_SIZE_MASK, cell_size));
- regmap_update_bits(host->regmap, LS1X_NAND_TIMING, LS1X_NAND_HOLD_CYCLE_MASK,
- FIELD_PREP(LS1X_NAND_HOLD_CYCLE_MASK, host->data->hold_cycle));
+ regmap_update_bits(host->regmap, LOONGSON_NAND_TIMING, LOONGSON_NAND_HOLD_CYCLE_MASK,
+ FIELD_PREP(LOONGSON_NAND_HOLD_CYCLE_MASK, host->data->hold_cycle));
- regmap_update_bits(host->regmap, LS1X_NAND_TIMING, LS1X_NAND_WAIT_CYCLE_MASK,
- FIELD_PREP(LS1X_NAND_WAIT_CYCLE_MASK, host->data->wait_cycle));
+ regmap_update_bits(host->regmap, LOONGSON_NAND_TIMING, LOONGSON_NAND_WAIT_CYCLE_MASK,
+ FIELD_PREP(LOONGSON_NAND_WAIT_CYCLE_MASK, host->data->wait_cycle));
chip->ecc.read_page_raw = nand_monolithic_read_page_raw;
chip->ecc.write_page_raw = nand_monolithic_write_page_raw;
@@ -647,25 +654,25 @@ static int ls1x_nand_attach_chip(struct nand_chip *chip)
return 0;
}
-static const struct nand_controller_ops ls1x_nand_controller_ops = {
- .exec_op = ls1x_nand_exec_op,
- .attach_chip = ls1x_nand_attach_chip,
+static const struct nand_controller_ops loongson_nand_controller_ops = {
+ .exec_op = loongson_nand_exec_op,
+ .attach_chip = loongson_nand_attach_chip,
};
-static void ls1x_nand_controller_cleanup(struct ls1x_nand_host *host)
+static void loongson_nand_controller_cleanup(struct loongson_nand_host *host)
{
if (host->dma_chan)
dma_release_channel(host->dma_chan);
}
-static int ls1x_nand_controller_init(struct ls1x_nand_host *host)
+static int loongson_nand_controller_init(struct loongson_nand_host *host)
{
struct device *dev = host->dev;
struct dma_chan *chan;
struct dma_slave_config cfg = {};
int ret;
- host->regmap = devm_regmap_init_mmio(dev, host->reg_base, &ls1x_nand_regmap_config);
+ host->regmap = devm_regmap_init_mmio(dev, host->reg_base, &loongson_nand_regmap_config);
if (IS_ERR(host->regmap))
return dev_err_probe(dev, PTR_ERR(host->regmap), "failed to init regmap\n");
@@ -687,7 +694,7 @@ static int ls1x_nand_controller_init(struct ls1x_nand_host *host)
return 0;
}
-static int ls1x_nand_chip_init(struct ls1x_nand_host *host)
+static int loongson_nand_chip_init(struct loongson_nand_host *host)
{
struct device *dev = host->dev;
int nchips = of_get_child_count(dev->of_node);
@@ -728,11 +735,11 @@ static int ls1x_nand_chip_init(struct ls1x_nand_host *host)
return 0;
}
-static int ls1x_nand_probe(struct platform_device *pdev)
+static int loongson_nand_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct ls1x_nand_data *data;
- struct ls1x_nand_host *host;
+ const struct loongson_nand_data *data;
+ struct loongson_nand_host *host;
struct resource *res;
int ret;
@@ -759,15 +766,15 @@ static int ls1x_nand_probe(struct platform_device *pdev)
host->dev = dev;
host->data = data;
- host->controller.ops = &ls1x_nand_controller_ops;
+ host->controller.ops = &loongson_nand_controller_ops;
nand_controller_init(&host->controller);
- ret = ls1x_nand_controller_init(host);
+ ret = loongson_nand_controller_init(host);
if (ret)
goto err;
- ret = ls1x_nand_chip_init(host);
+ ret = loongson_nand_chip_init(host);
if (ret)
goto err;
@@ -775,31 +782,31 @@ static int ls1x_nand_probe(struct platform_device *pdev)
return 0;
err:
- ls1x_nand_controller_cleanup(host);
+ loongson_nand_controller_cleanup(host);
return ret;
}
-static void ls1x_nand_remove(struct platform_device *pdev)
+static void loongson_nand_remove(struct platform_device *pdev)
{
- struct ls1x_nand_host *host = platform_get_drvdata(pdev);
+ struct loongson_nand_host *host = platform_get_drvdata(pdev);
struct nand_chip *chip = &host->chip;
int ret;
ret = mtd_device_unregister(nand_to_mtd(chip));
WARN_ON(ret);
nand_cleanup(chip);
- ls1x_nand_controller_cleanup(host);
+ loongson_nand_controller_cleanup(host);
}
-static const struct ls1x_nand_data ls1b_nand_data = {
+static const struct loongson_nand_data ls1b_nand_data = {
.status_field = GENMASK(15, 8),
.hold_cycle = 0x2,
.wait_cycle = 0xc,
.set_addr = ls1b_nand_set_addr,
};
-static const struct ls1x_nand_data ls1c_nand_data = {
+static const struct loongson_nand_data ls1c_nand_data = {
.status_field = GENMASK(23, 16),
.op_scope_field = GENMASK(29, 16),
.hold_cycle = 0x2,
@@ -807,7 +814,7 @@ static const struct ls1x_nand_data ls1c_nand_data = {
.set_addr = ls1c_nand_set_addr,
};
-static const struct of_device_id ls1x_nand_match[] = {
+static const struct of_device_id loongson_nand_match[] = {
{
.compatible = "loongson,ls1b-nand-controller",
.data = &ls1b_nand_data,
@@ -818,19 +825,19 @@ static const struct of_device_id ls1x_nand_match[] = {
},
{ /* sentinel */ }
};
-MODULE_DEVICE_TABLE(of, ls1x_nand_match);
+MODULE_DEVICE_TABLE(of, loongson_nand_match);
-static struct platform_driver ls1x_nand_driver = {
- .probe = ls1x_nand_probe,
- .remove = ls1x_nand_remove,
+static struct platform_driver loongson_nand_driver = {
+ .probe = loongson_nand_probe,
+ .remove = loongson_nand_remove,
.driver = {
.name = KBUILD_MODNAME,
- .of_match_table = ls1x_nand_match,
+ .of_match_table = loongson_nand_match,
},
};
-module_platform_driver(ls1x_nand_driver);
+module_platform_driver(loongson_nand_driver);
MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
-MODULE_DESCRIPTION("Loongson-1 NAND Controller Driver");
+MODULE_DESCRIPTION("Loongson NAND Controller Driver");
MODULE_LICENSE("GPL");
--
2.47.3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson
2025-08-11 6:02 [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support Binbin Zhou
2025-08-11 6:02 ` [PATCH v2 1/8] mtd: rawnand: loongson1: Rename the prefix from ls1x to loongson Binbin Zhou
@ 2025-08-11 6:02 ` Binbin Zhou
2025-08-11 6:36 ` Huacai Chen
2025-08-11 6:02 ` [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support Binbin Zhou
` (5 subsequent siblings)
7 siblings, 1 reply; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 6:02 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Binbin Zhou
The second step in preparing to add Loongson-2K support is to change the
names of the driver files and Kconfig options from Loongson1-specific to
Loongson-generic.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
MAINTAINERS | 2 +-
drivers/mtd/nand/raw/Kconfig | 6 +++---
drivers/mtd/nand/raw/Makefile | 2 +-
...ongson1-nand-controller.c => loongson-nand-controller.c} | 0
4 files changed, 5 insertions(+), 5 deletions(-)
rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)
diff --git a/MAINTAINERS b/MAINTAINERS
index 4bac4ea21b64..cc502582c9f1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml
F: arch/mips/include/asm/mach-loongson32/
F: arch/mips/loongson32/
F: drivers/*/*loongson1*
-F: drivers/mtd/nand/raw/loongson1-nand-controller.c
+F: drivers/mtd/nand/raw/loongson-nand-controller.c
F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
F: sound/soc/loongson/loongson1_ac97.c
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 4b99d9c422c3..d9e3f13666ac 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35
Enables support for the NAND controller found on
the Nuvoton MA35 series SoCs.
-config MTD_NAND_LOONGSON1
- tristate "Loongson1 NAND controller"
+config MTD_NAND_LOONGSON
+ tristate "Loongson NAND controller"
depends on LOONGSON1_APB_DMA || COMPILE_TEST
select REGMAP_MMIO
help
- Enables support for NAND controller on Loongson1 SoCs.
+ Enables support for NAND controller on Loongson family chips.
comment "Misc"
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 711d043ad4f8..c182b9703a9e 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o
obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o
obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o
obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o
-obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o
+obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.o
nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/loongson1-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
similarity index 100%
rename from drivers/mtd/nand/raw/loongson1-nand-controller.c
rename to drivers/mtd/nand/raw/loongson-nand-controller.c
--
2.47.3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support
2025-08-11 6:02 [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support Binbin Zhou
2025-08-11 6:02 ` [PATCH v2 1/8] mtd: rawnand: loongson1: Rename the prefix from ls1x to loongson Binbin Zhou
2025-08-11 6:02 ` [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 " Binbin Zhou
@ 2025-08-11 6:02 ` Binbin Zhou
2025-08-11 6:37 ` Huacai Chen
2025-08-11 6:03 ` [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support Binbin Zhou
` (4 subsequent siblings)
7 siblings, 1 reply; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 6:02 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Binbin Zhou
From: Keguang Zhang <keguang.zhang@gmail.com>
Loongson-1C and Loongson-2K SoCs support NAND flash chips with 6-byte ID.
However, the current implementation only handles 5-byte ID which can lead
to incorrect chip detection.
Extend loongson_nand_read_id_type_exec() to support 6-byte NAND ID.
Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../mtd/nand/raw/loongson-nand-controller.c | 29 +++++++++++++++----
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
index b5a7be0fcacc..97cd566420a8 100644
--- a/drivers/mtd/nand/raw/loongson-nand-controller.c
+++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
@@ -50,6 +50,9 @@
#define LOONGSON_NAND_COL_ADDR_CYC 2U
#define LOONGSON_NAND_MAX_ADDR_CYC 5U
+#define LOONGSON_NAND_READ_ID_SLEEP_US 1000
+#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000
+
#define BITS_PER_WORD (4 * BITS_PER_BYTE)
struct loongson_nand_host;
@@ -73,6 +76,8 @@ struct loongson_nand_op {
};
struct loongson_nand_data {
+ unsigned int max_id_cycle;
+ unsigned int id_cycle_field;
unsigned int status_field;
unsigned int op_scope_field;
unsigned int hold_cycle;
@@ -458,10 +463,10 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct
struct loongson_nand_op op = {};
int i, ret;
union {
- char ids[5];
+ char ids[6];
struct {
int idl;
- char idh;
+ u16 idh;
};
} nand_id;
@@ -469,11 +474,16 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct
if (ret)
return ret;
- nand_id.idl = readl(host->reg_base + LOONGSON_NAND_IDL);
- nand_id.idh = readb(host->reg_base + LOONGSON_NAND_IDH_STATUS);
+ ret = regmap_read_poll_timeout(host->regmap, LOONGSON_NAND_IDL, nand_id.idl, nand_id.idl,
+ LOONGSON_NAND_READ_ID_SLEEP_US,
+ LOONGSON_NAND_READ_ID_TIMEOUT_US);
+ if (ret)
+ return ret;
- for (i = 0; i < min(sizeof(nand_id.ids), op.orig_len); i++)
- op.buf[i] = nand_id.ids[sizeof(nand_id.ids) - 1 - i];
+ nand_id.idh = readw(host->reg_base + LOONGSON_NAND_IDH_STATUS);
+
+ for (i = 0; i < min(host->data->max_id_cycle, op.orig_len); i++)
+ op.buf[i] = nand_id.ids[host->data->max_id_cycle - 1 - i];
return ret;
}
@@ -676,6 +686,10 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
if (IS_ERR(host->regmap))
return dev_err_probe(dev, PTR_ERR(host->regmap), "failed to init regmap\n");
+ if (host->data->id_cycle_field)
+ regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM, host->data->id_cycle_field,
+ host->data->max_id_cycle << __ffs(host->data->id_cycle_field));
+
chan = dma_request_chan(dev, "rxtx");
if (IS_ERR(chan))
return dev_err_probe(dev, PTR_ERR(chan), "failed to request DMA channel\n");
@@ -800,6 +814,7 @@ static void loongson_nand_remove(struct platform_device *pdev)
}
static const struct loongson_nand_data ls1b_nand_data = {
+ .max_id_cycle = 5,
.status_field = GENMASK(15, 8),
.hold_cycle = 0x2,
.wait_cycle = 0xc,
@@ -807,6 +822,8 @@ static const struct loongson_nand_data ls1b_nand_data = {
};
static const struct loongson_nand_data ls1c_nand_data = {
+ .max_id_cycle = 6,
+ .id_cycle_field = GENMASK(14, 12),
.status_field = GENMASK(23, 16),
.op_scope_field = GENMASK(29, 16),
.hold_cycle = 0x2,
--
2.47.3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support
2025-08-11 6:02 [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support Binbin Zhou
` (2 preceding siblings ...)
2025-08-11 6:02 ` [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support Binbin Zhou
@ 2025-08-11 6:03 ` Binbin Zhou
2025-08-11 6:40 ` Huacai Chen
2025-08-19 9:27 ` Keguang Zhang
2025-08-11 6:03 ` [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller Binbin Zhou
` (3 subsequent siblings)
7 siblings, 2 replies; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 6:03 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Binbin Zhou
The page address register describes the page address of the starting
address for NAND read/write/erase operations.
According to the manual, it consists of two parts:
{chip select, page number}
The `chip select` is fixed at 2 bits, and the `page number` is
determined based on the actual capacity of the single-chip memory.
Therefore we need to determine the `chip select` bits base on the `page
number`.
For example, for a 1GB capacity chip (2K page size), it has 1M pages.
Thus, [19:0] is used to represent the page number, and [21:20]
represents the chip select.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++----
1 file changed, 103 insertions(+), 30 deletions(-)
diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
index 97cd566420a8..5a51c7d299cc 100644
--- a/drivers/mtd/nand/raw/loongson-nand-controller.c
+++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
@@ -82,6 +82,7 @@ struct loongson_nand_data {
unsigned int op_scope_field;
unsigned int hold_cycle;
unsigned int wait_cycle;
+ unsigned int nand_cs;
void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
};
@@ -90,6 +91,7 @@ struct loongson_nand_host {
struct nand_chip chip;
struct nand_controller controller;
const struct loongson_nand_data *data;
+ unsigned int addr_cs_field;
void __iomem *reg_base;
struct regmap *regmap;
/* DMA Engine stuff */
@@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const struct
return 0;
}
+static void loongson_nand_set_addr_cs(struct loongson_nand_host *host)
+{
+ struct nand_chip *chip = &host->chip;
+ struct mtd_info *mtd = nand_to_mtd(chip);
+
+ if (!host->data->nand_cs)
+ return;
+
+ /*
+ * The Manufacturer/Chip ID read operation precedes attach_chip, at which point
+ * information such as NAND chip selection and capacity is unknown. As a
+ * workaround, we use 128MB cellsize (2KB pagesize) as a fallback.
+ */
+ if (!mtd->writesize)
+ host->addr_cs_field = GENMASK(17, 16);
+
+ regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, host->addr_cs_field,
+ host->data->nand_cs << __ffs(host->addr_cs_field));
+}
+
static void ls1b_nand_set_addr(struct loongson_nand_host *host, struct loongson_nand_op *op)
{
struct nand_chip *chip = &host->chip;
@@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_
regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, mask, val);
}
}
+
+ loongson_nand_set_addr_cs(host);
}
static void loongson_nand_trigger_op(struct loongson_nand_host *host, struct loongson_nand_op *op)
@@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera
return nand_op_parser_exec_op(chip, &loongson_nand_op_parser, op, check_only);
}
-static int loongson_nand_attach_chip(struct nand_chip *chip)
+static int loongson_nand_get_chip_capacity(struct nand_chip *chip)
{
struct loongson_nand_host *host = nand_get_controller_data(chip);
u64 chipsize = nanddev_target_size(&chip->base);
- int cell_size = 0;
+ struct mtd_info *mtd = nand_to_mtd(chip);
- switch (chipsize) {
- case SZ_128M:
- cell_size = 0x0;
- break;
- case SZ_256M:
- cell_size = 0x1;
- break;
- case SZ_512M:
- cell_size = 0x2;
- break;
- case SZ_1G:
- cell_size = 0x3;
- break;
- case SZ_2G:
- cell_size = 0x4;
- break;
- case SZ_4G:
- cell_size = 0x5;
- break;
- case SZ_8G:
- cell_size = 0x6;
- break;
- case SZ_16G:
- cell_size = 0x7;
- break;
- default:
- dev_err(host->dev, "unsupported chip size: %llu MB\n", chipsize);
- return -EINVAL;
+ if (mtd->writesize == SZ_4K && chipsize == SZ_2G) {
+ host->addr_cs_field = GENMASK(20, 19);
+ return 0x4;
}
+ if (mtd->writesize == SZ_2K) {
+ switch (chipsize) {
+ case SZ_128M:
+ host->addr_cs_field = GENMASK(17, 16);
+ return 0;
+ case SZ_256M:
+ host->addr_cs_field = GENMASK(18, 17);
+ return 0x1;
+ case SZ_512M:
+ host->addr_cs_field = GENMASK(19, 18);
+ return 0x2;
+ case SZ_1G:
+ host->addr_cs_field = GENMASK(20, 19);
+ return 0x3;
+ default:
+ goto err;
+ }
+ }
+
+ if (mtd->writesize == SZ_8K) {
+ switch (chipsize) {
+ case SZ_4G:
+ host->addr_cs_field = GENMASK(20, 19);
+ return 0x5;
+ case SZ_8G:
+ host->addr_cs_field = GENMASK(21, 20);
+ return 0x6;
+ case SZ_16G:
+ host->addr_cs_field = GENMASK(22, 21);
+ return 0x7;
+ default:
+ goto err;
+ }
+ }
+
+ if (mtd->writesize == SZ_512) {
+ switch (chipsize) {
+ case SZ_8M:
+ host->addr_cs_field = GENMASK(15, 14);
+ return 0x9;
+ case SZ_16M:
+ host->addr_cs_field = GENMASK(16, 15);
+ return 0xa;
+ case SZ_32M:
+ host->addr_cs_field = GENMASK(17, 16);
+ return 0xb;
+ case SZ_64M:
+ host->addr_cs_field = GENMASK(18, 17);
+ return 0xc;
+ case SZ_128M:
+ host->addr_cs_field = GENMASK(19, 18);
+ return 0xd;
+ default:
+ goto err;
+ }
+ }
+
+err:
+ dev_err(host->dev, "Unsupported chip size: %llu MB with page size %u B\n",
+ chipsize, mtd->writesize);
+ return -EINVAL;
+}
+
+static int loongson_nand_attach_chip(struct nand_chip *chip)
+{
+ struct loongson_nand_host *host = nand_get_controller_data(chip);
+ int cell_size = 0;
+
+ cell_size = loongson_nand_get_chip_capacity(chip);
+ if (cell_size < 0)
+ return cell_size;
+
switch (chip->ecc.engine_type) {
case NAND_ECC_ENGINE_TYPE_NONE:
break;
@@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = {
.status_field = GENMASK(15, 8),
.hold_cycle = 0x2,
.wait_cycle = 0xc,
+ .nand_cs = 0x0,
.set_addr = ls1b_nand_set_addr,
};
@@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = {
.op_scope_field = GENMASK(29, 16),
.hold_cycle = 0x2,
.wait_cycle = 0xc,
+ .nand_cs = 0x0,
.set_addr = ls1c_nand_set_addr,
};
--
2.47.3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
2025-08-11 6:02 [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support Binbin Zhou
` (3 preceding siblings ...)
2025-08-11 6:03 ` [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support Binbin Zhou
@ 2025-08-11 6:03 ` Binbin Zhou
2025-08-11 7:32 ` Krzysztof Kozlowski
2025-08-11 6:03 ` [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support Binbin Zhou
` (2 subsequent siblings)
7 siblings, 1 reply; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 6:03 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Binbin Zhou, Rob Herring (Arm)
Add new compatible for the Loongson-2K NAND controller used for
Loongson-2K0500 SoC.
Acked-by: "Rob Herring (Arm)" <robh@kernel.org>
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../bindings/mtd/loongson,ls1b-nand-controller.yaml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml b/Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml
index a09e92e416c4..4ec2b5d1e89d 100644
--- a/Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml
@@ -4,13 +4,14 @@
$id: http://devicetree.org/schemas/mtd/loongson,ls1b-nand-controller.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Loongson-1 NAND Controller
+title: Loongson NAND Controller
maintainers:
- Keguang Zhang <keguang.zhang@gmail.com>
+ - Binbin Zhou <zhoubinbin@loongson.cn>
description:
- The Loongson-1 NAND controller abstracts all supported operations,
+ The Loongson NAND controller abstracts all supported operations,
meaning it does not support low-level access to raw NAND flash chips.
Moreover, the controller is paired with the DMA engine to perform
READ and PROGRAM functions.
@@ -24,6 +25,7 @@ properties:
- enum:
- loongson,ls1b-nand-controller
- loongson,ls1c-nand-controller
+ - loongson,ls2k0500-nand-controller
- items:
- enum:
- loongson,ls1a-nand-controller
--
2.47.3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
2025-08-11 6:02 [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support Binbin Zhou
` (4 preceding siblings ...)
2025-08-11 6:03 ` [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller Binbin Zhou
@ 2025-08-11 6:03 ` Binbin Zhou
2025-08-11 18:09 ` Yao Zi
2025-08-21 6:45 ` Keguang Zhang
2025-08-11 6:03 ` [PATCH v2 7/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller Binbin Zhou
2025-08-11 6:03 ` [PATCH v2 8/8] mtd: rawnand: loongson: Add Loongson-2K1000 NAND controller support Binbin Zhou
7 siblings, 2 replies; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 6:03 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Binbin Zhou
The Loongson-2K0500 NAND controller is similar to the Loongson-1C.
It supports a maximum capacity of 16GB FLASH per chip with a maximum
page size of 8KB, and it supports up to 4 chip selects and 4 RDY
signals.
Its DMA controller is defaulted to APBDMA0.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
drivers/mtd/nand/raw/Kconfig | 2 +-
.../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++-
2 files changed, 54 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index d9e3f13666ac..7b0c5d06aa95 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35
config MTD_NAND_LOONGSON
tristate "Loongson NAND controller"
- depends on LOONGSON1_APB_DMA || COMPILE_TEST
+ depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST
select REGMAP_MMIO
help
Enables support for NAND controller on Loongson family chips.
diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
index 5a51c7d299cc..7a15df3fcd31 100644
--- a/drivers/mtd/nand/raw/loongson-nand-controller.c
+++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
@@ -3,6 +3,7 @@
* NAND Controller Driver for Loongson family chips
*
* Copyright (C) 2015-2025 Keguang Zhang <keguang.zhang@gmail.com>
+ * Copyright (C) 2025 Binbin Zhou <zhoubinbin@loongson.cn>
*/
#include <linux/kernel.h>
@@ -26,6 +27,7 @@
#define LOONGSON_NAND_IDH_STATUS 0x14
#define LOONGSON_NAND_PARAM 0x18
#define LOONGSON_NAND_OP_NUM 0x1c
+#define LOONGSON_NAND_CS_RDY_MAP 0x20
/* Bitfields of nand command register */
#define LOONGSON_NAND_CMD_OP_DONE BIT(10)
@@ -40,6 +42,23 @@
#define LOONGSON_NAND_CMD_READ BIT(1)
#define LOONGSON_NAND_CMD_VALID BIT(0)
+/* Bitfields of nand cs/rdy map register */
+#define LOONGSON_NAND_MAP_CS1_SEL GENMASK(11, 8)
+#define LOONGSON_NAND_MAP_RDY1_SEL GENMASK(15, 12)
+#define LOONGSON_NAND_MAP_CS2_SEL GENMASK(19, 16)
+#define LOONGSON_NAND_MAP_RDY2_SEL GENMASK(23, 20)
+#define LOONGSON_NAND_MAP_CS3_SEL GENMASK(27, 24)
+#define LOONGSON_NAND_MAP_RDY3_SEL GENMASK(31, 28)
+
+#define LOONGSON_NAND_CS_SEL0 BIT(0)
+#define LOONGSON_NAND_CS_SEL1 BIT(1)
+#define LOONGSON_NAND_CS_SEL2 BIT(2)
+#define LOONGSON_NAND_CS_SEL3 BIT(3)
+#define LOONGSON_NAND_CS_RDY0 BIT(0)
+#define LOONGSON_NAND_CS_RDY1 BIT(1)
+#define LOONGSON_NAND_CS_RDY2 BIT(2)
+#define LOONGSON_NAND_CS_RDY3 BIT(3)
+
/* Bitfields of nand timing register */
#define LOONGSON_NAND_WAIT_CYCLE_MASK GENMASK(7, 0)
#define LOONGSON_NAND_HOLD_CYCLE_MASK GENMASK(15, 8)
@@ -53,6 +72,8 @@
#define LOONGSON_NAND_READ_ID_SLEEP_US 1000
#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000
+#define LOONGSON_NAND_64BIT_DMA BIT(0)
+
#define BITS_PER_WORD (4 * BITS_PER_BYTE)
struct loongson_nand_host;
@@ -83,6 +104,7 @@ struct loongson_nand_data {
unsigned int hold_cycle;
unsigned int wait_cycle;
unsigned int nand_cs;
+ unsigned int flags;
void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
};
@@ -751,7 +773,7 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
struct device *dev = host->dev;
struct dma_chan *chan;
struct dma_slave_config cfg = {};
- int ret;
+ int ret, val;
host->regmap = devm_regmap_init_mmio(dev, host->reg_base, &loongson_nand_regmap_config);
if (IS_ERR(host->regmap))
@@ -761,6 +783,9 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM, host->data->id_cycle_field,
host->data->max_id_cycle << __ffs(host->data->id_cycle_field));
+ if (host->data->flags & LOONGSON_NAND_64BIT_DMA)
+ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+
chan = dma_request_chan(dev, "rxtx");
if (IS_ERR(chan))
return dev_err_probe(dev, PTR_ERR(chan), "failed to request DMA channel\n");
@@ -776,7 +801,14 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
init_completion(&host->dma_complete);
- return 0;
+ val = FIELD_PREP(LOONGSON_NAND_MAP_CS1_SEL, LOONGSON_NAND_CS_SEL1)
+ | FIELD_PREP(LOONGSON_NAND_MAP_RDY1_SEL, LOONGSON_NAND_CS_RDY1)
+ | FIELD_PREP(LOONGSON_NAND_MAP_CS2_SEL, LOONGSON_NAND_CS_SEL2)
+ | FIELD_PREP(LOONGSON_NAND_MAP_RDY2_SEL, LOONGSON_NAND_CS_RDY2)
+ | FIELD_PREP(LOONGSON_NAND_MAP_CS3_SEL, LOONGSON_NAND_CS_SEL3)
+ | FIELD_PREP(LOONGSON_NAND_MAP_RDY3_SEL, LOONGSON_NAND_CS_RDY3);
+
+ return regmap_write(host->regmap, LOONGSON_NAND_CS_RDY_MAP, val);
}
static int loongson_nand_chip_init(struct loongson_nand_host *host)
@@ -890,6 +922,7 @@ static const struct loongson_nand_data ls1b_nand_data = {
.hold_cycle = 0x2,
.wait_cycle = 0xc,
.nand_cs = 0x0,
+ .flags = 0,
.set_addr = ls1b_nand_set_addr,
};
@@ -901,6 +934,19 @@ static const struct loongson_nand_data ls1c_nand_data = {
.hold_cycle = 0x2,
.wait_cycle = 0xc,
.nand_cs = 0x0,
+ .flags = 0,
+ .set_addr = ls1c_nand_set_addr,
+};
+
+static const struct loongson_nand_data ls2k0500_nand_data = {
+ .max_id_cycle = 6,
+ .id_cycle_field = GENMASK(14, 12),
+ .status_field = GENMASK(23, 16),
+ .op_scope_field = GENMASK(29, 16),
+ .hold_cycle = 0x4,
+ .wait_cycle = 0x12,
+ .nand_cs = 0x0,
+ .flags = LOONGSON_NAND_64BIT_DMA,
.set_addr = ls1c_nand_set_addr,
};
@@ -913,6 +959,10 @@ static const struct of_device_id loongson_nand_match[] = {
.compatible = "loongson,ls1c-nand-controller",
.data = &ls1c_nand_data,
},
+ {
+ .compatible = "loongson,ls2k0500-nand-controller",
+ .data = &ls2k0500_nand_data,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, loongson_nand_match);
@@ -929,5 +979,6 @@ static struct platform_driver loongson_nand_driver = {
module_platform_driver(loongson_nand_driver);
MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
+MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");
MODULE_DESCRIPTION("Loongson NAND Controller Driver");
MODULE_LICENSE("GPL");
--
2.47.3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 7/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller
2025-08-11 6:02 [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support Binbin Zhou
` (5 preceding siblings ...)
2025-08-11 6:03 ` [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support Binbin Zhou
@ 2025-08-11 6:03 ` Binbin Zhou
2025-08-18 15:55 ` Rob Herring (Arm)
2025-08-11 6:03 ` [PATCH v2 8/8] mtd: rawnand: loongson: Add Loongson-2K1000 NAND controller support Binbin Zhou
7 siblings, 1 reply; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 6:03 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Binbin Zhou
Add new compatible for the Loongson-2K NAND controller used for
Loongson-2K1000 SoC.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../mtd/loongson,ls1b-nand-controller.yaml | 50 ++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml b/Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml
index 4ec2b5d1e89d..cf85d0cede00 100644
--- a/Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml
@@ -26,18 +26,22 @@ properties:
- loongson,ls1b-nand-controller
- loongson,ls1c-nand-controller
- loongson,ls2k0500-nand-controller
+ - loongson,ls2k1000-nand-controller
- items:
- enum:
- loongson,ls1a-nand-controller
- const: loongson,ls1b-nand-controller
reg:
- maxItems: 2
+ minItems: 2
+ maxItems: 3
reg-names:
+ minItems: 2
items:
- const: nand
- const: nand-dma
+ - const: dma-config
dmas:
maxItems: 1
@@ -54,6 +58,27 @@ required:
unevaluatedProperties: false
+if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - loongson,ls2k1000-nand-controller
+
+then:
+ properties:
+ reg:
+ minItems: 3
+ reg-names:
+ minItems: 3
+
+else:
+ properties:
+ reg:
+ maxItems: 2
+ reg-names:
+ maxItems: 2
+
examples:
- |
nand-controller@1fe78000 {
@@ -72,3 +97,26 @@ examples:
nand-ecc-algo = "hamming";
};
};
+
+ - |
+ nand-controller@1fe26000 {
+ compatible = "loongson,ls2k1000-nand-controller";
+ reg = <0x1fe26000 0x24>,
+ <0x1fe26040 0x4>,
+ <0x1fe00438 0x8>;
+ reg-names = "nand", "nand-dma", "dma-config";
+ dmas = <&apbdma0 0>;
+ dma-names = "rxtx";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@0 {
+ reg = <0>;
+ label = "ls2k1000-nand";
+ nand-use-soft-ecc-engine;
+ nand-ecc-algo = "bch";
+ nand-ecc-strength = <8>;
+ nand-ecc-step-size = <512>;
+ };
+ };
--
2.47.3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 8/8] mtd: rawnand: loongson: Add Loongson-2K1000 NAND controller support
2025-08-11 6:02 [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support Binbin Zhou
` (6 preceding siblings ...)
2025-08-11 6:03 ` [PATCH v2 7/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller Binbin Zhou
@ 2025-08-11 6:03 ` Binbin Zhou
7 siblings, 0 replies; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 6:03 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Binbin Zhou
The Loongson-2K1000 NAND controller is also similar to the Loongson-1C.
It supports a maximum capacity of 16GB FLASH per chip with a maximum
page size of 8KB, and it supports up to 4 chip selects and 4 RDY
signals.
The key difference from the Loongson-2K0500 is that it requires explicit
configuration of the DMA control route. Typically, it is configured as
APBDMA0.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../mtd/nand/raw/loongson-nand-controller.c | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
index 7a15df3fcd31..9c377062a3a1 100644
--- a/drivers/mtd/nand/raw/loongson-nand-controller.c
+++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
@@ -73,9 +73,18 @@
#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000
#define LOONGSON_NAND_64BIT_DMA BIT(0)
+#define LOONGSON_NAND_DMA_CONFIG BIT(1)
#define BITS_PER_WORD (4 * BITS_PER_BYTE)
+/* Loongson-2K1000 NAND DMA routing register */
+#define LS2K1000_NAND_DMA_MASK GENMASK(2, 0)
+#define LS2K1000_DMA0_CONF 0x0
+#define LS2K1000_DMA1_CONF 0x1
+#define LS2K1000_DMA2_CONF 0x2
+#define LS2K1000_DMA3_CONF 0x3
+#define LS2K1000_DMA4_CONF 0x4
+
struct loongson_nand_host;
struct loongson_nand_op {
@@ -768,6 +777,23 @@ static void loongson_nand_controller_cleanup(struct loongson_nand_host *host)
dma_release_channel(host->dma_chan);
}
+static int ls2k1000_nand_apbdma_config(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ void __iomem *regs;
+ int val;
+
+ regs = devm_platform_ioremap_resource(pdev, 2);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ val = readl(regs);
+ val |= FIELD_PREP(LS2K1000_NAND_DMA_MASK, LS2K1000_DMA0_CONF);
+ writel(val, regs);
+
+ return 0;
+}
+
static int loongson_nand_controller_init(struct loongson_nand_host *host)
{
struct device *dev = host->dev;
@@ -786,6 +812,12 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
if (host->data->flags & LOONGSON_NAND_64BIT_DMA)
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (host->data->flags & LOONGSON_NAND_DMA_CONFIG) {
+ ret = ls2k1000_nand_apbdma_config(dev);
+ if (ret)
+ return ret;
+ }
+
chan = dma_request_chan(dev, "rxtx");
if (IS_ERR(chan))
return dev_err_probe(dev, PTR_ERR(chan), "failed to request DMA channel\n");
@@ -950,6 +982,18 @@ static const struct loongson_nand_data ls2k0500_nand_data = {
.set_addr = ls1c_nand_set_addr,
};
+static const struct loongson_nand_data ls2k1000_nand_data = {
+ .max_id_cycle = 6,
+ .id_cycle_field = GENMASK(14, 12),
+ .status_field = GENMASK(23, 16),
+ .op_scope_field = GENMASK(29, 16),
+ .hold_cycle = 0x4,
+ .wait_cycle = 0x12,
+ .nand_cs = 0x2,
+ .flags = LOONGSON_NAND_64BIT_DMA | LOONGSON_NAND_DMA_CONFIG,
+ .set_addr = ls1c_nand_set_addr,
+};
+
static const struct of_device_id loongson_nand_match[] = {
{
.compatible = "loongson,ls1b-nand-controller",
@@ -963,6 +1007,10 @@ static const struct of_device_id loongson_nand_match[] = {
.compatible = "loongson,ls2k0500-nand-controller",
.data = &ls2k0500_nand_data,
},
+ {
+ .compatible = "loongson,ls2k1000-nand-controller",
+ .data = &ls2k1000_nand_data,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, loongson_nand_match);
--
2.47.3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson
2025-08-11 6:02 ` [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 " Binbin Zhou
@ 2025-08-11 6:36 ` Huacai Chen
2025-08-11 9:41 ` Binbin Zhou
0 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2025-08-11 6:36 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Xuerui Wang, loongarch, devicetree,
linux-mtd
Hi, Binbin,
On Mon, Aug 11, 2025 at 2:02 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
>
> The second step in preparing to add Loongson-2K support is to change the
> names of the driver files and Kconfig options from Loongson1-specific to
> Loongson-generic.
Is it possible to merge the first two patches? If not, it is better to
use loongson1 rather than loongson in the subject line of this patch.
Huacai
>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> ---
> MAINTAINERS | 2 +-
> drivers/mtd/nand/raw/Kconfig | 6 +++---
> drivers/mtd/nand/raw/Makefile | 2 +-
> ...ongson1-nand-controller.c => loongson-nand-controller.c} | 0
> 4 files changed, 5 insertions(+), 5 deletions(-)
> rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4bac4ea21b64..cc502582c9f1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml
> F: arch/mips/include/asm/mach-loongson32/
> F: arch/mips/loongson32/
> F: drivers/*/*loongson1*
> -F: drivers/mtd/nand/raw/loongson1-nand-controller.c
> +F: drivers/mtd/nand/raw/loongson-nand-controller.c
> F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> F: sound/soc/loongson/loongson1_ac97.c
>
> diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> index 4b99d9c422c3..d9e3f13666ac 100644
> --- a/drivers/mtd/nand/raw/Kconfig
> +++ b/drivers/mtd/nand/raw/Kconfig
> @@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35
> Enables support for the NAND controller found on
> the Nuvoton MA35 series SoCs.
>
> -config MTD_NAND_LOONGSON1
> - tristate "Loongson1 NAND controller"
> +config MTD_NAND_LOONGSON
> + tristate "Loongson NAND controller"
> depends on LOONGSON1_APB_DMA || COMPILE_TEST
> select REGMAP_MMIO
> help
> - Enables support for NAND controller on Loongson1 SoCs.
> + Enables support for NAND controller on Loongson family chips.
>
> comment "Misc"
>
> diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
> index 711d043ad4f8..c182b9703a9e 100644
> --- a/drivers/mtd/nand/raw/Makefile
> +++ b/drivers/mtd/nand/raw/Makefile
> @@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o
> obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o
> obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o
> obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o
> -obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o
> +obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.o
>
> nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
> nand-objs += nand_onfi.o
> diff --git a/drivers/mtd/nand/raw/loongson1-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> similarity index 100%
> rename from drivers/mtd/nand/raw/loongson1-nand-controller.c
> rename to drivers/mtd/nand/raw/loongson-nand-controller.c
> --
> 2.47.3
>
>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support
2025-08-11 6:02 ` [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support Binbin Zhou
@ 2025-08-11 6:37 ` Huacai Chen
2025-08-19 9:12 ` Keguang Zhang
0 siblings, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2025-08-11 6:37 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Xuerui Wang, loongarch, devicetree,
linux-mtd
Hi, Binbin,
On Mon, Aug 11, 2025 at 2:02 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
>
> From: Keguang Zhang <keguang.zhang@gmail.com>
>
> Loongson-1C and Loongson-2K SoCs support NAND flash chips with 6-byte ID.
> However, the current implementation only handles 5-byte ID which can lead
> to incorrect chip detection.
>
> Extend loongson_nand_read_id_type_exec() to support 6-byte NAND ID.
>
> Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> ---
> .../mtd/nand/raw/loongson-nand-controller.c | 29 +++++++++++++++----
> 1 file changed, 23 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> index b5a7be0fcacc..97cd566420a8 100644
> --- a/drivers/mtd/nand/raw/loongson-nand-controller.c
> +++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
> @@ -50,6 +50,9 @@
> #define LOONGSON_NAND_COL_ADDR_CYC 2U
> #define LOONGSON_NAND_MAX_ADDR_CYC 5U
>
> +#define LOONGSON_NAND_READ_ID_SLEEP_US 1000
> +#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000
> +
> #define BITS_PER_WORD (4 * BITS_PER_BYTE)
>
> struct loongson_nand_host;
> @@ -73,6 +76,8 @@ struct loongson_nand_op {
> };
>
> struct loongson_nand_data {
> + unsigned int max_id_cycle;
> + unsigned int id_cycle_field;
> unsigned int status_field;
> unsigned int op_scope_field;
> unsigned int hold_cycle;
> @@ -458,10 +463,10 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct
> struct loongson_nand_op op = {};
> int i, ret;
> union {
> - char ids[5];
> + char ids[6];
> struct {
> int idl;
> - char idh;
> + u16 idh;
> };
> } nand_id;
>
> @@ -469,11 +474,16 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct
> if (ret)
> return ret;
>
> - nand_id.idl = readl(host->reg_base + LOONGSON_NAND_IDL);
> - nand_id.idh = readb(host->reg_base + LOONGSON_NAND_IDH_STATUS);
> + ret = regmap_read_poll_timeout(host->regmap, LOONGSON_NAND_IDL, nand_id.idl, nand_id.idl,
> + LOONGSON_NAND_READ_ID_SLEEP_US,
> + LOONGSON_NAND_READ_ID_TIMEOUT_US);
The last two lines can be merged.
Huacai
> + if (ret)
> + return ret;
>
> - for (i = 0; i < min(sizeof(nand_id.ids), op.orig_len); i++)
> - op.buf[i] = nand_id.ids[sizeof(nand_id.ids) - 1 - i];
> + nand_id.idh = readw(host->reg_base + LOONGSON_NAND_IDH_STATUS);
> +
> + for (i = 0; i < min(host->data->max_id_cycle, op.orig_len); i++)
> + op.buf[i] = nand_id.ids[host->data->max_id_cycle - 1 - i];
>
> return ret;
> }
> @@ -676,6 +686,10 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
> if (IS_ERR(host->regmap))
> return dev_err_probe(dev, PTR_ERR(host->regmap), "failed to init regmap\n");
>
> + if (host->data->id_cycle_field)
> + regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM, host->data->id_cycle_field,
> + host->data->max_id_cycle << __ffs(host->data->id_cycle_field));
> +
> chan = dma_request_chan(dev, "rxtx");
> if (IS_ERR(chan))
> return dev_err_probe(dev, PTR_ERR(chan), "failed to request DMA channel\n");
> @@ -800,6 +814,7 @@ static void loongson_nand_remove(struct platform_device *pdev)
> }
>
> static const struct loongson_nand_data ls1b_nand_data = {
> + .max_id_cycle = 5,
> .status_field = GENMASK(15, 8),
> .hold_cycle = 0x2,
> .wait_cycle = 0xc,
> @@ -807,6 +822,8 @@ static const struct loongson_nand_data ls1b_nand_data = {
> };
>
> static const struct loongson_nand_data ls1c_nand_data = {
> + .max_id_cycle = 6,
> + .id_cycle_field = GENMASK(14, 12),
> .status_field = GENMASK(23, 16),
> .op_scope_field = GENMASK(29, 16),
> .hold_cycle = 0x2,
> --
> 2.47.3
>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support
2025-08-11 6:03 ` [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support Binbin Zhou
@ 2025-08-11 6:40 ` Huacai Chen
2025-08-11 8:49 ` Binbin Zhou
2025-08-19 9:27 ` Keguang Zhang
1 sibling, 1 reply; 28+ messages in thread
From: Huacai Chen @ 2025-08-11 6:40 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Xuerui Wang, loongarch, devicetree,
linux-mtd
Hi, Binbin,
On Mon, Aug 11, 2025 at 2:03 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
>
> The page address register describes the page address of the starting
> address for NAND read/write/erase operations.
>
> According to the manual, it consists of two parts:
> {chip select, page number}
>
> The `chip select` is fixed at 2 bits, and the `page number` is
> determined based on the actual capacity of the single-chip memory.
> Therefore we need to determine the `chip select` bits base on the `page
> number`.
>
> For example, for a 1GB capacity chip (2K page size), it has 1M pages.
> Thus, [19:0] is used to represent the page number, and [21:20]
> represents the chip select.
>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> ---
> .../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++----
> 1 file changed, 103 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> index 97cd566420a8..5a51c7d299cc 100644
> --- a/drivers/mtd/nand/raw/loongson-nand-controller.c
> +++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
> @@ -82,6 +82,7 @@ struct loongson_nand_data {
> unsigned int op_scope_field;
> unsigned int hold_cycle;
> unsigned int wait_cycle;
> + unsigned int nand_cs;
> void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
> };
>
> @@ -90,6 +91,7 @@ struct loongson_nand_host {
> struct nand_chip chip;
> struct nand_controller controller;
> const struct loongson_nand_data *data;
> + unsigned int addr_cs_field;
> void __iomem *reg_base;
> struct regmap *regmap;
> /* DMA Engine stuff */
> @@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const struct
> return 0;
> }
>
> +static void loongson_nand_set_addr_cs(struct loongson_nand_host *host)
> +{
> + struct nand_chip *chip = &host->chip;
> + struct mtd_info *mtd = nand_to_mtd(chip);
> +
> + if (!host->data->nand_cs)
> + return;
> +
> + /*
> + * The Manufacturer/Chip ID read operation precedes attach_chip, at which point
> + * information such as NAND chip selection and capacity is unknown. As a
> + * workaround, we use 128MB cellsize (2KB pagesize) as a fallback.
> + */
> + if (!mtd->writesize)
> + host->addr_cs_field = GENMASK(17, 16);
> +
> + regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, host->addr_cs_field,
> + host->data->nand_cs << __ffs(host->addr_cs_field));
> +}
> +
> static void ls1b_nand_set_addr(struct loongson_nand_host *host, struct loongson_nand_op *op)
> {
> struct nand_chip *chip = &host->chip;
> @@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_
> regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, mask, val);
> }
> }
> +
> + loongson_nand_set_addr_cs(host);
> }
>
> static void loongson_nand_trigger_op(struct loongson_nand_host *host, struct loongson_nand_op *op)
> @@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera
> return nand_op_parser_exec_op(chip, &loongson_nand_op_parser, op, check_only);
> }
>
> -static int loongson_nand_attach_chip(struct nand_chip *chip)
> +static int loongson_nand_get_chip_capacity(struct nand_chip *chip)
> {
> struct loongson_nand_host *host = nand_get_controller_data(chip);
> u64 chipsize = nanddev_target_size(&chip->base);
> - int cell_size = 0;
> + struct mtd_info *mtd = nand_to_mtd(chip);
>
> - switch (chipsize) {
> - case SZ_128M:
> - cell_size = 0x0;
> - break;
> - case SZ_256M:
> - cell_size = 0x1;
> - break;
> - case SZ_512M:
> - cell_size = 0x2;
> - break;
> - case SZ_1G:
> - cell_size = 0x3;
> - break;
> - case SZ_2G:
> - cell_size = 0x4;
> - break;
> - case SZ_4G:
> - cell_size = 0x5;
> - break;
> - case SZ_8G:
> - cell_size = 0x6;
> - break;
> - case SZ_16G:
> - cell_size = 0x7;
> - break;
> - default:
> - dev_err(host->dev, "unsupported chip size: %llu MB\n", chipsize);
> - return -EINVAL;
> + if (mtd->writesize == SZ_4K && chipsize == SZ_2G) {
> + host->addr_cs_field = GENMASK(20, 19);
> + return 0x4;
> }
I think you want to sort this part by the return value, but "return
0x4" has already break it.
So I think it is better to use a big switch-case for writesize, and
sort the big switch-case by writesize.
Huacai
>
> + if (mtd->writesize == SZ_2K) {
> + switch (chipsize) {
> + case SZ_128M:
> + host->addr_cs_field = GENMASK(17, 16);
> + return 0;
> + case SZ_256M:
> + host->addr_cs_field = GENMASK(18, 17);
> + return 0x1;
> + case SZ_512M:
> + host->addr_cs_field = GENMASK(19, 18);
> + return 0x2;
> + case SZ_1G:
> + host->addr_cs_field = GENMASK(20, 19);
> + return 0x3;
> + default:
> + goto err;
> + }
> + }
> +
> + if (mtd->writesize == SZ_8K) {
> + switch (chipsize) {
> + case SZ_4G:
> + host->addr_cs_field = GENMASK(20, 19);
> + return 0x5;
> + case SZ_8G:
> + host->addr_cs_field = GENMASK(21, 20);
> + return 0x6;
> + case SZ_16G:
> + host->addr_cs_field = GENMASK(22, 21);
> + return 0x7;
> + default:
> + goto err;
> + }
> + }
> +
> + if (mtd->writesize == SZ_512) {
> + switch (chipsize) {
> + case SZ_8M:
> + host->addr_cs_field = GENMASK(15, 14);
> + return 0x9;
> + case SZ_16M:
> + host->addr_cs_field = GENMASK(16, 15);
> + return 0xa;
> + case SZ_32M:
> + host->addr_cs_field = GENMASK(17, 16);
> + return 0xb;
> + case SZ_64M:
> + host->addr_cs_field = GENMASK(18, 17);
> + return 0xc;
> + case SZ_128M:
> + host->addr_cs_field = GENMASK(19, 18);
> + return 0xd;
> + default:
> + goto err;
> + }
> + }
> +
> +err:
> + dev_err(host->dev, "Unsupported chip size: %llu MB with page size %u B\n",
> + chipsize, mtd->writesize);
> + return -EINVAL;
> +}
> +
> +static int loongson_nand_attach_chip(struct nand_chip *chip)
> +{
> + struct loongson_nand_host *host = nand_get_controller_data(chip);
> + int cell_size = 0;
> +
> + cell_size = loongson_nand_get_chip_capacity(chip);
> + if (cell_size < 0)
> + return cell_size;
> +
> switch (chip->ecc.engine_type) {
> case NAND_ECC_ENGINE_TYPE_NONE:
> break;
> @@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = {
> .status_field = GENMASK(15, 8),
> .hold_cycle = 0x2,
> .wait_cycle = 0xc,
> + .nand_cs = 0x0,
> .set_addr = ls1b_nand_set_addr,
> };
>
> @@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = {
> .op_scope_field = GENMASK(29, 16),
> .hold_cycle = 0x2,
> .wait_cycle = 0xc,
> + .nand_cs = 0x0,
> .set_addr = ls1c_nand_set_addr,
> };
>
> --
> 2.47.3
>
>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
2025-08-11 6:03 ` [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller Binbin Zhou
@ 2025-08-11 7:32 ` Krzysztof Kozlowski
2025-08-11 7:42 ` Binbin Zhou
0 siblings, 1 reply; 28+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-11 7:32 UTC (permalink / raw)
To: Binbin Zhou, Binbin Zhou, Huacai Chen, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Keguang Zhang, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd,
Rob Herring (Arm)
On 11/08/2025 08:03, Binbin Zhou wrote:
> Add new compatible for the Loongson-2K NAND controller used for
> Loongson-2K0500 SoC.
>
> Acked-by: "Rob Herring (Arm)" <robh@kernel.org>
Why do you add quotes?
Best regards,
Krzysztof
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
2025-08-11 7:32 ` Krzysztof Kozlowski
@ 2025-08-11 7:42 ` Binbin Zhou
2025-08-11 8:13 ` Krzysztof Kozlowski
0 siblings, 1 reply; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 7:42 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-mtd, Rob Herring (Arm)
Hi Krzysztof:
On Mon, Aug 11, 2025 at 3:32 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On 11/08/2025 08:03, Binbin Zhou wrote:
> > Add new compatible for the Loongson-2K NAND controller used for
> > Loongson-2K0500 SoC.
> >
> > Acked-by: "Rob Herring (Arm)" <robh@kernel.org>
>
>
> Why do you add quotes?
Emm...
Sorry, I didn't notice that.
I reacquired the V1 patchset using “b4 am xxx” to avoid manually
adding tags. I believe it may be caused by the `b4` command.
>
> Best regards,
> Krzysztof
--
Thanks.
Binbin
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
2025-08-11 7:42 ` Binbin Zhou
@ 2025-08-11 8:13 ` Krzysztof Kozlowski
2025-08-11 8:19 ` Binbin Zhou
0 siblings, 1 reply; 28+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-11 8:13 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-mtd, Rob Herring (Arm)
On Mon, Aug 11, 2025 at 03:42:09PM +0800, Binbin Zhou wrote:
> Hi Krzysztof:
>
> On Mon, Aug 11, 2025 at 3:32 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
> >
> > On 11/08/2025 08:03, Binbin Zhou wrote:
> > > Add new compatible for the Loongson-2K NAND controller used for
> > > Loongson-2K0500 SoC.
> > >
> > > Acked-by: "Rob Herring (Arm)" <robh@kernel.org>
> >
> >
> > Why do you add quotes?
>
> Emm...
> Sorry, I didn't notice that.
> I reacquired the V1 patchset using “b4 am xxx” to avoid manually
> adding tags. I believe it may be caused by the `b4` command.
Then aren't you using some old b4?
I just did it and look:
[PATCH v1 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
+ Acked-by: Rob Herring (Arm) <robh@kernel.org> (✓ DKIM/kernel.org)
+ Link: https://lore.kernel.org/r/588639de591ada408bdaeb0d279c5d62a4b53d61.1753166096.git.zhoubinbin@loongson.cn
+ Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
No quotes in commit msg either.
Best regards,
Krzysztof
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
2025-08-11 8:13 ` Krzysztof Kozlowski
@ 2025-08-11 8:19 ` Binbin Zhou
0 siblings, 0 replies; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 8:19 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-mtd, Rob Herring (Arm)
Hi Krzysztof:
On Mon, Aug 11, 2025 at 4:13 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Mon, Aug 11, 2025 at 03:42:09PM +0800, Binbin Zhou wrote:
> > Hi Krzysztof:
> >
> > On Mon, Aug 11, 2025 at 3:32 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
> > >
> > > On 11/08/2025 08:03, Binbin Zhou wrote:
> > > > Add new compatible for the Loongson-2K NAND controller used for
> > > > Loongson-2K0500 SoC.
> > > >
> > > > Acked-by: "Rob Herring (Arm)" <robh@kernel.org>
> > >
> > >
> > > Why do you add quotes?
> >
> > Emm...
> > Sorry, I didn't notice that.
> > I reacquired the V1 patchset using “b4 am xxx” to avoid manually
> > adding tags. I believe it may be caused by the `b4` command.
>
> Then aren't you using some old b4?
>
> I just did it and look:
>
> [PATCH v1 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
> + Acked-by: Rob Herring (Arm) <robh@kernel.org> (✓ DKIM/kernel.org)
> + Link: https://lore.kernel.org/r/588639de591ada408bdaeb0d279c5d62a4b53d61.1753166096.git.zhoubinbin@loongson.cn
> + Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Thanks for your reply and testing.
I rechecked my b4 repository, and it does need to be updated. It was my mistake.
I will fix it in the next version.
Thanks again!
>
>
> No quotes in commit msg either.
>
> Best regards,
> Krzysztof
>
--
Thanks.
Binbin
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support
2025-08-11 6:40 ` Huacai Chen
@ 2025-08-11 8:49 ` Binbin Zhou
2025-08-11 8:59 ` Huacai Chen
0 siblings, 1 reply; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 8:49 UTC (permalink / raw)
To: Huacai Chen
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Xuerui Wang, loongarch, devicetree,
linux-mtd
Hi:
On Mon, Aug 11, 2025 at 2:40 PM Huacai Chen <chenhuacai@kernel.org> wrote:
>
> Hi, Binbin,
>
> On Mon, Aug 11, 2025 at 2:03 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
> >
> > The page address register describes the page address of the starting
> > address for NAND read/write/erase operations.
> >
> > According to the manual, it consists of two parts:
> > {chip select, page number}
> >
> > The `chip select` is fixed at 2 bits, and the `page number` is
> > determined based on the actual capacity of the single-chip memory.
> > Therefore we need to determine the `chip select` bits base on the `page
> > number`.
> >
> > For example, for a 1GB capacity chip (2K page size), it has 1M pages.
> > Thus, [19:0] is used to represent the page number, and [21:20]
> > represents the chip select.
> >
> > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> > ---
> > .../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++----
> > 1 file changed, 103 insertions(+), 30 deletions(-)
> >
> > diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > index 97cd566420a8..5a51c7d299cc 100644
> > --- a/drivers/mtd/nand/raw/loongson-nand-controller.c
> > +++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > @@ -82,6 +82,7 @@ struct loongson_nand_data {
> > unsigned int op_scope_field;
> > unsigned int hold_cycle;
> > unsigned int wait_cycle;
> > + unsigned int nand_cs;
> > void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
> > };
> >
> > @@ -90,6 +91,7 @@ struct loongson_nand_host {
> > struct nand_chip chip;
> > struct nand_controller controller;
> > const struct loongson_nand_data *data;
> > + unsigned int addr_cs_field;
> > void __iomem *reg_base;
> > struct regmap *regmap;
> > /* DMA Engine stuff */
> > @@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const struct
> > return 0;
> > }
> >
> > +static void loongson_nand_set_addr_cs(struct loongson_nand_host *host)
> > +{
> > + struct nand_chip *chip = &host->chip;
> > + struct mtd_info *mtd = nand_to_mtd(chip);
> > +
> > + if (!host->data->nand_cs)
> > + return;
> > +
> > + /*
> > + * The Manufacturer/Chip ID read operation precedes attach_chip, at which point
> > + * information such as NAND chip selection and capacity is unknown. As a
> > + * workaround, we use 128MB cellsize (2KB pagesize) as a fallback.
> > + */
> > + if (!mtd->writesize)
> > + host->addr_cs_field = GENMASK(17, 16);
> > +
> > + regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, host->addr_cs_field,
> > + host->data->nand_cs << __ffs(host->addr_cs_field));
> > +}
> > +
> > static void ls1b_nand_set_addr(struct loongson_nand_host *host, struct loongson_nand_op *op)
> > {
> > struct nand_chip *chip = &host->chip;
> > @@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_
> > regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, mask, val);
> > }
> > }
> > +
> > + loongson_nand_set_addr_cs(host);
> > }
> >
> > static void loongson_nand_trigger_op(struct loongson_nand_host *host, struct loongson_nand_op *op)
> > @@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera
> > return nand_op_parser_exec_op(chip, &loongson_nand_op_parser, op, check_only);
> > }
> >
> > -static int loongson_nand_attach_chip(struct nand_chip *chip)
> > +static int loongson_nand_get_chip_capacity(struct nand_chip *chip)
> > {
> > struct loongson_nand_host *host = nand_get_controller_data(chip);
> > u64 chipsize = nanddev_target_size(&chip->base);
> > - int cell_size = 0;
> > + struct mtd_info *mtd = nand_to_mtd(chip);
> >
> > - switch (chipsize) {
> > - case SZ_128M:
> > - cell_size = 0x0;
> > - break;
> > - case SZ_256M:
> > - cell_size = 0x1;
> > - break;
> > - case SZ_512M:
> > - cell_size = 0x2;
> > - break;
> > - case SZ_1G:
> > - cell_size = 0x3;
> > - break;
> > - case SZ_2G:
> > - cell_size = 0x4;
> > - break;
> > - case SZ_4G:
> > - cell_size = 0x5;
> > - break;
> > - case SZ_8G:
> > - cell_size = 0x6;
> > - break;
> > - case SZ_16G:
> > - cell_size = 0x7;
> > - break;
> > - default:
> > - dev_err(host->dev, "unsupported chip size: %llu MB\n", chipsize);
> > - return -EINVAL;
> > + if (mtd->writesize == SZ_4K && chipsize == SZ_2G) {
> > + host->addr_cs_field = GENMASK(20, 19);
> > + return 0x4;
> > }
> I think you want to sort this part by the return value, but "return
> 0x4" has already break it.
>
> So I think it is better to use a big switch-case for writesize, and
> sort the big switch-case by writesize.
How about:
switch (mtd->writesize) {
case SZ_512:
switch (chipsize) {
case SZ_8M:
host->addr_cs_field = GENMASK(15, 14);
return 0x9;
case SZ_16M:
host->addr_cs_field = GENMASK(16, 15);
return 0xa;
case SZ_32M:
host->addr_cs_field = GENMASK(17, 16);
return 0xb;
case SZ_64M:
host->addr_cs_field = GENMASK(18, 17);
return 0xc;
case SZ_128M:
host->addr_cs_field = GENMASK(19, 18);
return 0xd;
}
break;
case SZ_2K:
switch (chipsize) {
case SZ_128M:
host->addr_cs_field = GENMASK(17, 16);
return 0;
case SZ_256M:
host->addr_cs_field = GENMASK(18, 17);
return 0x1;
case SZ_512M:
host->addr_cs_field = GENMASK(19, 18);
return 0x2;
case SZ_1G:
host->addr_cs_field = GENMASK(20, 19);
return 0x3;
}
break;
case SZ_4K:
if (chipsize == SZ_2G) {
host->addr_cs_field = GENMASK(20, 19);
return 0x4;
}
break;
case SZ_8K:
switch (chipsize) {
case SZ_4G:
host->addr_cs_field = GENMASK(20, 19);
return 0x5;
case SZ_8G:
host->addr_cs_field = GENMASK(21, 20);
return 0x6;
case SZ_16G:
host->addr_cs_field = GENMASK(22, 21);
return 0x7;
}
break;
default:
break;
}
dev_err(host->dev, "Unsupported chip size: %llu MB with page
size %u B\n",
chipsize, mtd->writesize);
>
> Huacai
>
> >
> > + if (mtd->writesize == SZ_2K) {
> > + switch (chipsize) {
> > + case SZ_128M:
> > + host->addr_cs_field = GENMASK(17, 16);
> > + return 0;
> > + case SZ_256M:
> > + host->addr_cs_field = GENMASK(18, 17);
> > + return 0x1;
> > + case SZ_512M:
> > + host->addr_cs_field = GENMASK(19, 18);
> > + return 0x2;
> > + case SZ_1G:
> > + host->addr_cs_field = GENMASK(20, 19);
> > + return 0x3;
> > + default:
> > + goto err;
> > + }
> > + }
> > +
> > + if (mtd->writesize == SZ_8K) {
> > + switch (chipsize) {
> > + case SZ_4G:
> > + host->addr_cs_field = GENMASK(20, 19);
> > + return 0x5;
> > + case SZ_8G:
> > + host->addr_cs_field = GENMASK(21, 20);
> > + return 0x6;
> > + case SZ_16G:
> > + host->addr_cs_field = GENMASK(22, 21);
> > + return 0x7;
> > + default:
> > + goto err;
> > + }
> > + }
> > +
> > + if (mtd->writesize == SZ_512) {
> > + switch (chipsize) {
> > + case SZ_8M:
> > + host->addr_cs_field = GENMASK(15, 14);
> > + return 0x9;
> > + case SZ_16M:
> > + host->addr_cs_field = GENMASK(16, 15);
> > + return 0xa;
> > + case SZ_32M:
> > + host->addr_cs_field = GENMASK(17, 16);
> > + return 0xb;
> > + case SZ_64M:
> > + host->addr_cs_field = GENMASK(18, 17);
> > + return 0xc;
> > + case SZ_128M:
> > + host->addr_cs_field = GENMASK(19, 18);
> > + return 0xd;
> > + default:
> > + goto err;
> > + }
> > + }
> > +
> > +err:
> > + dev_err(host->dev, "Unsupported chip size: %llu MB with page size %u B\n",
> > + chipsize, mtd->writesize);
> > + return -EINVAL;
> > +}
> > +
> > +static int loongson_nand_attach_chip(struct nand_chip *chip)
> > +{
> > + struct loongson_nand_host *host = nand_get_controller_data(chip);
> > + int cell_size = 0;
> > +
> > + cell_size = loongson_nand_get_chip_capacity(chip);
> > + if (cell_size < 0)
> > + return cell_size;
> > +
> > switch (chip->ecc.engine_type) {
> > case NAND_ECC_ENGINE_TYPE_NONE:
> > break;
> > @@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = {
> > .status_field = GENMASK(15, 8),
> > .hold_cycle = 0x2,
> > .wait_cycle = 0xc,
> > + .nand_cs = 0x0,
> > .set_addr = ls1b_nand_set_addr,
> > };
> >
> > @@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = {
> > .op_scope_field = GENMASK(29, 16),
> > .hold_cycle = 0x2,
> > .wait_cycle = 0xc,
> > + .nand_cs = 0x0,
> > .set_addr = ls1c_nand_set_addr,
> > };
> >
> > --
> > 2.47.3
> >
> >
--
Thanks.
Binbin
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support
2025-08-11 8:49 ` Binbin Zhou
@ 2025-08-11 8:59 ` Huacai Chen
0 siblings, 0 replies; 28+ messages in thread
From: Huacai Chen @ 2025-08-11 8:59 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Xuerui Wang, loongarch, devicetree,
linux-mtd
On Mon, Aug 11, 2025 at 4:49 PM Binbin Zhou <zhoubb.aaron@gmail.com> wrote:
>
> Hi:
>
> On Mon, Aug 11, 2025 at 2:40 PM Huacai Chen <chenhuacai@kernel.org> wrote:
> >
> > Hi, Binbin,
> >
> > On Mon, Aug 11, 2025 at 2:03 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
> > >
> > > The page address register describes the page address of the starting
> > > address for NAND read/write/erase operations.
> > >
> > > According to the manual, it consists of two parts:
> > > {chip select, page number}
> > >
> > > The `chip select` is fixed at 2 bits, and the `page number` is
> > > determined based on the actual capacity of the single-chip memory.
> > > Therefore we need to determine the `chip select` bits base on the `page
> > > number`.
> > >
> > > For example, for a 1GB capacity chip (2K page size), it has 1M pages.
> > > Thus, [19:0] is used to represent the page number, and [21:20]
> > > represents the chip select.
> > >
> > > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> > > ---
> > > .../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++----
> > > 1 file changed, 103 insertions(+), 30 deletions(-)
> > >
> > > diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > > index 97cd566420a8..5a51c7d299cc 100644
> > > --- a/drivers/mtd/nand/raw/loongson-nand-controller.c
> > > +++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > > @@ -82,6 +82,7 @@ struct loongson_nand_data {
> > > unsigned int op_scope_field;
> > > unsigned int hold_cycle;
> > > unsigned int wait_cycle;
> > > + unsigned int nand_cs;
> > > void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
> > > };
> > >
> > > @@ -90,6 +91,7 @@ struct loongson_nand_host {
> > > struct nand_chip chip;
> > > struct nand_controller controller;
> > > const struct loongson_nand_data *data;
> > > + unsigned int addr_cs_field;
> > > void __iomem *reg_base;
> > > struct regmap *regmap;
> > > /* DMA Engine stuff */
> > > @@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const struct
> > > return 0;
> > > }
> > >
> > > +static void loongson_nand_set_addr_cs(struct loongson_nand_host *host)
> > > +{
> > > + struct nand_chip *chip = &host->chip;
> > > + struct mtd_info *mtd = nand_to_mtd(chip);
> > > +
> > > + if (!host->data->nand_cs)
> > > + return;
> > > +
> > > + /*
> > > + * The Manufacturer/Chip ID read operation precedes attach_chip, at which point
> > > + * information such as NAND chip selection and capacity is unknown. As a
> > > + * workaround, we use 128MB cellsize (2KB pagesize) as a fallback.
> > > + */
> > > + if (!mtd->writesize)
> > > + host->addr_cs_field = GENMASK(17, 16);
> > > +
> > > + regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, host->addr_cs_field,
> > > + host->data->nand_cs << __ffs(host->addr_cs_field));
> > > +}
> > > +
> > > static void ls1b_nand_set_addr(struct loongson_nand_host *host, struct loongson_nand_op *op)
> > > {
> > > struct nand_chip *chip = &host->chip;
> > > @@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_
> > > regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, mask, val);
> > > }
> > > }
> > > +
> > > + loongson_nand_set_addr_cs(host);
> > > }
> > >
> > > static void loongson_nand_trigger_op(struct loongson_nand_host *host, struct loongson_nand_op *op)
> > > @@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera
> > > return nand_op_parser_exec_op(chip, &loongson_nand_op_parser, op, check_only);
> > > }
> > >
> > > -static int loongson_nand_attach_chip(struct nand_chip *chip)
> > > +static int loongson_nand_get_chip_capacity(struct nand_chip *chip)
> > > {
> > > struct loongson_nand_host *host = nand_get_controller_data(chip);
> > > u64 chipsize = nanddev_target_size(&chip->base);
> > > - int cell_size = 0;
> > > + struct mtd_info *mtd = nand_to_mtd(chip);
> > >
> > > - switch (chipsize) {
> > > - case SZ_128M:
> > > - cell_size = 0x0;
> > > - break;
> > > - case SZ_256M:
> > > - cell_size = 0x1;
> > > - break;
> > > - case SZ_512M:
> > > - cell_size = 0x2;
> > > - break;
> > > - case SZ_1G:
> > > - cell_size = 0x3;
> > > - break;
> > > - case SZ_2G:
> > > - cell_size = 0x4;
> > > - break;
> > > - case SZ_4G:
> > > - cell_size = 0x5;
> > > - break;
> > > - case SZ_8G:
> > > - cell_size = 0x6;
> > > - break;
> > > - case SZ_16G:
> > > - cell_size = 0x7;
> > > - break;
> > > - default:
> > > - dev_err(host->dev, "unsupported chip size: %llu MB\n", chipsize);
> > > - return -EINVAL;
> > > + if (mtd->writesize == SZ_4K && chipsize == SZ_2G) {
> > > + host->addr_cs_field = GENMASK(20, 19);
> > > + return 0x4;
> > > }
> > I think you want to sort this part by the return value, but "return
> > 0x4" has already break it.
> >
> > So I think it is better to use a big switch-case for writesize, and
> > sort the big switch-case by writesize.
>
> How about:
>
> switch (mtd->writesize) {
> case SZ_512:
> switch (chipsize) {
> case SZ_8M:
> host->addr_cs_field = GENMASK(15, 14);
> return 0x9;
> case SZ_16M:
> host->addr_cs_field = GENMASK(16, 15);
> return 0xa;
> case SZ_32M:
> host->addr_cs_field = GENMASK(17, 16);
> return 0xb;
> case SZ_64M:
> host->addr_cs_field = GENMASK(18, 17);
> return 0xc;
> case SZ_128M:
> host->addr_cs_field = GENMASK(19, 18);
> return 0xd;
> }
> break;
> case SZ_2K:
> switch (chipsize) {
> case SZ_128M:
> host->addr_cs_field = GENMASK(17, 16);
> return 0;
Use 0x0 for consistency.
> case SZ_256M:
> host->addr_cs_field = GENMASK(18, 17);
> return 0x1;
> case SZ_512M:
> host->addr_cs_field = GENMASK(19, 18);
> return 0x2;
> case SZ_1G:
> host->addr_cs_field = GENMASK(20, 19);
> return 0x3;
> }
> break;
> case SZ_4K:
> if (chipsize == SZ_2G) {
> host->addr_cs_field = GENMASK(20, 19);
> return 0x4;
> }
> break;
> case SZ_8K:
> switch (chipsize) {
> case SZ_4G:
> host->addr_cs_field = GENMASK(20, 19);
> return 0x5;
> case SZ_8G:
> host->addr_cs_field = GENMASK(21, 20);
> return 0x6;
> case SZ_16G:
> host->addr_cs_field = GENMASK(22, 21);
> return 0x7;
> }
> break;
> default:
> break;
The default branch is unneeded. Others are OK for me.
Huacai
> }
>
> dev_err(host->dev, "Unsupported chip size: %llu MB with page
> size %u B\n",
> chipsize, mtd->writesize);
> >
> > Huacai
> >
> > >
> > > + if (mtd->writesize == SZ_2K) {
> > > + switch (chipsize) {
> > > + case SZ_128M:
> > > + host->addr_cs_field = GENMASK(17, 16);
> > > + return 0;
> > > + case SZ_256M:
> > > + host->addr_cs_field = GENMASK(18, 17);
> > > + return 0x1;
> > > + case SZ_512M:
> > > + host->addr_cs_field = GENMASK(19, 18);
> > > + return 0x2;
> > > + case SZ_1G:
> > > + host->addr_cs_field = GENMASK(20, 19);
> > > + return 0x3;
> > > + default:
> > > + goto err;
> > > + }
> > > + }
> > > +
> > > + if (mtd->writesize == SZ_8K) {
> > > + switch (chipsize) {
> > > + case SZ_4G:
> > > + host->addr_cs_field = GENMASK(20, 19);
> > > + return 0x5;
> > > + case SZ_8G:
> > > + host->addr_cs_field = GENMASK(21, 20);
> > > + return 0x6;
> > > + case SZ_16G:
> > > + host->addr_cs_field = GENMASK(22, 21);
> > > + return 0x7;
> > > + default:
> > > + goto err;
> > > + }
> > > + }
> > > +
> > > + if (mtd->writesize == SZ_512) {
> > > + switch (chipsize) {
> > > + case SZ_8M:
> > > + host->addr_cs_field = GENMASK(15, 14);
> > > + return 0x9;
> > > + case SZ_16M:
> > > + host->addr_cs_field = GENMASK(16, 15);
> > > + return 0xa;
> > > + case SZ_32M:
> > > + host->addr_cs_field = GENMASK(17, 16);
> > > + return 0xb;
> > > + case SZ_64M:
> > > + host->addr_cs_field = GENMASK(18, 17);
> > > + return 0xc;
> > > + case SZ_128M:
> > > + host->addr_cs_field = GENMASK(19, 18);
> > > + return 0xd;
> > > + default:
> > > + goto err;
> > > + }
> > > + }
> > > +
> > > +err:
> > > + dev_err(host->dev, "Unsupported chip size: %llu MB with page size %u B\n",
> > > + chipsize, mtd->writesize);
> > > + return -EINVAL;
> > > +}
> > > +
> > > +static int loongson_nand_attach_chip(struct nand_chip *chip)
> > > +{
> > > + struct loongson_nand_host *host = nand_get_controller_data(chip);
> > > + int cell_size = 0;
> > > +
> > > + cell_size = loongson_nand_get_chip_capacity(chip);
> > > + if (cell_size < 0)
> > > + return cell_size;
> > > +
> > > switch (chip->ecc.engine_type) {
> > > case NAND_ECC_ENGINE_TYPE_NONE:
> > > break;
> > > @@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = {
> > > .status_field = GENMASK(15, 8),
> > > .hold_cycle = 0x2,
> > > .wait_cycle = 0xc,
> > > + .nand_cs = 0x0,
> > > .set_addr = ls1b_nand_set_addr,
> > > };
> > >
> > > @@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = {
> > > .op_scope_field = GENMASK(29, 16),
> > > .hold_cycle = 0x2,
> > > .wait_cycle = 0xc,
> > > + .nand_cs = 0x0,
> > > .set_addr = ls1c_nand_set_addr,
> > > };
> > >
> > > --
> > > 2.47.3
> > >
> > >
>
> --
> Thanks.
> Binbin
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson
2025-08-11 6:36 ` Huacai Chen
@ 2025-08-11 9:41 ` Binbin Zhou
2025-08-18 7:04 ` Keguang Zhang
0 siblings, 1 reply; 28+ messages in thread
From: Binbin Zhou @ 2025-08-11 9:41 UTC (permalink / raw)
To: Huacai Chen
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Xuerui Wang, loongarch, devicetree,
linux-mtd
Hi Huacai:
Thanks for your reply.
On Mon, Aug 11, 2025 at 2:36 PM Huacai Chen <chenhuacai@kernel.org> wrote:
>
> Hi, Binbin,
>
> On Mon, Aug 11, 2025 at 2:02 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
> >
> > The second step in preparing to add Loongson-2K support is to change the
> > names of the driver files and Kconfig options from Loongson1-specific to
> > Loongson-generic.
> Is it possible to merge the first two patches? If not, it is better to
> use loongson1 rather than loongson in the subject line of this patch.
At first, I thought that separating the renaming of file prefixes from
the renaming of file names would make the changes clearer. Another
point is whether renaming Kconfig items would be considered API
breaking, even though no one is currently referencing them?
Of course, if anyone thinks that separating them is unnecessary, I
will merge them in the next version.
>
> Huacai
>
> >
> > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> > ---
> > MAINTAINERS | 2 +-
> > drivers/mtd/nand/raw/Kconfig | 6 +++---
> > drivers/mtd/nand/raw/Makefile | 2 +-
> > ...ongson1-nand-controller.c => loongson-nand-controller.c} | 0
> > 4 files changed, 5 insertions(+), 5 deletions(-)
> > rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 4bac4ea21b64..cc502582c9f1 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml
> > F: arch/mips/include/asm/mach-loongson32/
> > F: arch/mips/loongson32/
> > F: drivers/*/*loongson1*
> > -F: drivers/mtd/nand/raw/loongson1-nand-controller.c
> > +F: drivers/mtd/nand/raw/loongson-nand-controller.c
> > F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > F: sound/soc/loongson/loongson1_ac97.c
> >
> > diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> > index 4b99d9c422c3..d9e3f13666ac 100644
> > --- a/drivers/mtd/nand/raw/Kconfig
> > +++ b/drivers/mtd/nand/raw/Kconfig
> > @@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35
> > Enables support for the NAND controller found on
> > the Nuvoton MA35 series SoCs.
> >
> > -config MTD_NAND_LOONGSON1
> > - tristate "Loongson1 NAND controller"
> > +config MTD_NAND_LOONGSON
> > + tristate "Loongson NAND controller"
> > depends on LOONGSON1_APB_DMA || COMPILE_TEST
> > select REGMAP_MMIO
> > help
> > - Enables support for NAND controller on Loongson1 SoCs.
> > + Enables support for NAND controller on Loongson family chips.
> >
> > comment "Misc"
> >
> > diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
> > index 711d043ad4f8..c182b9703a9e 100644
> > --- a/drivers/mtd/nand/raw/Makefile
> > +++ b/drivers/mtd/nand/raw/Makefile
> > @@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o
> > obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o
> > obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o
> > obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o
> > -obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o
> > +obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.o
> >
> > nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
> > nand-objs += nand_onfi.o
> > diff --git a/drivers/mtd/nand/raw/loongson1-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > similarity index 100%
> > rename from drivers/mtd/nand/raw/loongson1-nand-controller.c
> > rename to drivers/mtd/nand/raw/loongson-nand-controller.c
> > --
> > 2.47.3
> >
> >
--
Thanks.
Binbin
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
2025-08-11 6:03 ` [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support Binbin Zhou
@ 2025-08-11 18:09 ` Yao Zi
2025-08-12 1:46 ` Binbin Zhou
2025-08-21 6:45 ` Keguang Zhang
1 sibling, 1 reply; 28+ messages in thread
From: Yao Zi @ 2025-08-11 18:09 UTC (permalink / raw)
To: Binbin Zhou, Binbin Zhou, Huacai Chen, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Keguang Zhang, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, linux-mtd
On Mon, Aug 11, 2025 at 02:03:13PM +0800, Binbin Zhou wrote:
> The Loongson-2K0500 NAND controller is similar to the Loongson-1C.
>
> It supports a maximum capacity of 16GB FLASH per chip with a maximum
> page size of 8KB, and it supports up to 4 chip selects and 4 RDY
> signals.
>
> Its DMA controller is defaulted to APBDMA0.
>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> ---
> drivers/mtd/nand/raw/Kconfig | 2 +-
> .../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++-
> 2 files changed, 54 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> index d9e3f13666ac..7b0c5d06aa95 100644
> --- a/drivers/mtd/nand/raw/Kconfig
> +++ b/drivers/mtd/nand/raw/Kconfig
> @@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35
>
> config MTD_NAND_LOONGSON
> tristate "Loongson NAND controller"
> - depends on LOONGSON1_APB_DMA || COMPILE_TEST
> + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST
Why is this dependency necessary? I think the DMA operations are done
through DMAengine API, and thus the consumer decouples with the DMA
provider. If so, I think the depends line should be removed, instead of
extended.
Regards,
Yao Zi
> select REGMAP_MMIO
> help
> Enables support for NAND controller on Loongson family chips.
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
2025-08-11 18:09 ` Yao Zi
@ 2025-08-12 1:46 ` Binbin Zhou
0 siblings, 0 replies; 28+ messages in thread
From: Binbin Zhou @ 2025-08-12 1:46 UTC (permalink / raw)
To: Yao Zi
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Keguang Zhang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-mtd
HI Yao:
Thanks for your reply.
On Tue, Aug 12, 2025 at 2:09 AM Yao Zi <ziyao@disroot.org> wrote:
>
> On Mon, Aug 11, 2025 at 02:03:13PM +0800, Binbin Zhou wrote:
> > The Loongson-2K0500 NAND controller is similar to the Loongson-1C.
> >
> > It supports a maximum capacity of 16GB FLASH per chip with a maximum
> > page size of 8KB, and it supports up to 4 chip selects and 4 RDY
> > signals.
> >
> > Its DMA controller is defaulted to APBDMA0.
> >
> > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> > ---
> > drivers/mtd/nand/raw/Kconfig | 2 +-
> > .../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++-
> > 2 files changed, 54 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> > index d9e3f13666ac..7b0c5d06aa95 100644
> > --- a/drivers/mtd/nand/raw/Kconfig
> > +++ b/drivers/mtd/nand/raw/Kconfig
> > @@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35
> >
> > config MTD_NAND_LOONGSON
> > tristate "Loongson NAND controller"
> > - depends on LOONGSON1_APB_DMA || COMPILE_TEST
> > + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST
>
> Why is this dependency necessary? I think the DMA operations are done
> through DMAengine API, and thus the consumer decouples with the DMA
> provider. If so, I think the depends line should be removed, instead of
> extended.
This is an existing execution dependency. Although there is no
guarantee that it will work with other DMA engines in the future, only
this combination has been tested and proven to be correct at present.
Therefore, I would still like to retain this dependency.
>
> Regards,
> Yao Zi
>
> > select REGMAP_MMIO
> > help
> > Enables support for NAND controller on Loongson family chips.
--
Thanks.
Binbin
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson
2025-08-11 9:41 ` Binbin Zhou
@ 2025-08-18 7:04 ` Keguang Zhang
2025-08-18 9:40 ` Binbin Zhou
0 siblings, 1 reply; 28+ messages in thread
From: Keguang Zhang @ 2025-08-18 7:04 UTC (permalink / raw)
To: Binbin Zhou
Cc: Huacai Chen, Binbin Zhou, Huacai Chen, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra, Xuerui Wang, loongarch,
devicetree, linux-mtd
On Mon, Aug 11, 2025 at 5:42 PM Binbin Zhou <zhoubb.aaron@gmail.com> wrote:
>
> Hi Huacai:
>
> Thanks for your reply.
>
> On Mon, Aug 11, 2025 at 2:36 PM Huacai Chen <chenhuacai@kernel.org> wrote:
> >
> > Hi, Binbin,
> >
> > On Mon, Aug 11, 2025 at 2:02 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
> > >
> > > The second step in preparing to add Loongson-2K support is to change the
> > > names of the driver files and Kconfig options from Loongson1-specific to
> > > Loongson-generic.
> > Is it possible to merge the first two patches? If not, it is better to
> > use loongson1 rather than loongson in the subject line of this patch.
>
> At first, I thought that separating the renaming of file prefixes from
> the renaming of file names would make the changes clearer. Another
> point is whether renaming Kconfig items would be considered API
> breaking, even though no one is currently referencing them?
>
> Of course, if anyone thinks that separating them is unnecessary, I
> will merge them in the next version.
It’s reasonable to merge the first two patches.
I agree.
> >
> > Huacai
> >
> > >
> > > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> > > ---
> > > MAINTAINERS | 2 +-
> > > drivers/mtd/nand/raw/Kconfig | 6 +++---
> > > drivers/mtd/nand/raw/Makefile | 2 +-
> > > ...ongson1-nand-controller.c => loongson-nand-controller.c} | 0
> > > 4 files changed, 5 insertions(+), 5 deletions(-)
> > > rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)
> > >
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index 4bac4ea21b64..cc502582c9f1 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml
> > > F: arch/mips/include/asm/mach-loongson32/
> > > F: arch/mips/loongson32/
> > > F: drivers/*/*loongson1*
> > > -F: drivers/mtd/nand/raw/loongson1-nand-controller.c
> > > +F: drivers/mtd/nand/raw/loongson-nand-controller.c
> > > F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > F: sound/soc/loongson/loongson1_ac97.c
> > >
> > > diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> > > index 4b99d9c422c3..d9e3f13666ac 100644
> > > --- a/drivers/mtd/nand/raw/Kconfig
> > > +++ b/drivers/mtd/nand/raw/Kconfig
> > > @@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35
> > > Enables support for the NAND controller found on
> > > the Nuvoton MA35 series SoCs.
> > >
> > > -config MTD_NAND_LOONGSON1
> > > - tristate "Loongson1 NAND controller"
> > > +config MTD_NAND_LOONGSON
> > > + tristate "Loongson NAND controller"
> > > depends on LOONGSON1_APB_DMA || COMPILE_TEST
> > > select REGMAP_MMIO
> > > help
> > > - Enables support for NAND controller on Loongson1 SoCs.
> > > + Enables support for NAND controller on Loongson family chips.
> > >
> > > comment "Misc"
> > >
> > > diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
> > > index 711d043ad4f8..c182b9703a9e 100644
> > > --- a/drivers/mtd/nand/raw/Makefile
> > > +++ b/drivers/mtd/nand/raw/Makefile
> > > @@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o
> > > obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o
> > > obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o
> > > obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o
> > > -obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o
> > > +obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.o
> > >
> > > nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
> > > nand-objs += nand_onfi.o
> > > diff --git a/drivers/mtd/nand/raw/loongson1-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > > similarity index 100%
> > > rename from drivers/mtd/nand/raw/loongson1-nand-controller.c
> > > rename to drivers/mtd/nand/raw/loongson-nand-controller.c
> > > --
> > > 2.47.3
> > >
> > >
>
> --
> Thanks.
> Binbin
--
Best regards,
Keguang Zhang
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson
2025-08-18 7:04 ` Keguang Zhang
@ 2025-08-18 9:40 ` Binbin Zhou
0 siblings, 0 replies; 28+ messages in thread
From: Binbin Zhou @ 2025-08-18 9:40 UTC (permalink / raw)
To: Keguang Zhang
Cc: Huacai Chen, Binbin Zhou, Huacai Chen, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra, Xuerui Wang, loongarch,
devicetree, linux-mtd
Hi Keguang:
Thanks for your reply.
On Mon, Aug 18, 2025 at 3:05 PM Keguang Zhang <keguang.zhang@gmail.com> wrote:
>
> On Mon, Aug 11, 2025 at 5:42 PM Binbin Zhou <zhoubb.aaron@gmail.com> wrote:
> >
> > Hi Huacai:
> >
> > Thanks for your reply.
> >
> > On Mon, Aug 11, 2025 at 2:36 PM Huacai Chen <chenhuacai@kernel.org> wrote:
> > >
> > > Hi, Binbin,
> > >
> > > On Mon, Aug 11, 2025 at 2:02 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
> > > >
> > > > The second step in preparing to add Loongson-2K support is to change the
> > > > names of the driver files and Kconfig options from Loongson1-specific to
> > > > Loongson-generic.
> > > Is it possible to merge the first two patches? If not, it is better to
> > > use loongson1 rather than loongson in the subject line of this patch.
> >
> > At first, I thought that separating the renaming of file prefixes from
> > the renaming of file names would make the changes clearer. Another
> > point is whether renaming Kconfig items would be considered API
> > breaking, even though no one is currently referencing them?
> >
> > Of course, if anyone thinks that separating them is unnecessary, I
> > will merge them in the next version.
>
> It’s reasonable to merge the first two patches.
> I agree.
OK. I will do it in the next version.
>
> > >
> > > Huacai
> > >
> > > >
> > > > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> > > > ---
> > > > MAINTAINERS | 2 +-
> > > > drivers/mtd/nand/raw/Kconfig | 6 +++---
> > > > drivers/mtd/nand/raw/Makefile | 2 +-
> > > > ...ongson1-nand-controller.c => loongson-nand-controller.c} | 0
> > > > 4 files changed, 5 insertions(+), 5 deletions(-)
> > > > rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)
> > > >
> > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > index 4bac4ea21b64..cc502582c9f1 100644
> > > > --- a/MAINTAINERS
> > > > +++ b/MAINTAINERS
> > > > @@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml
> > > > F: arch/mips/include/asm/mach-loongson32/
> > > > F: arch/mips/loongson32/
> > > > F: drivers/*/*loongson1*
> > > > -F: drivers/mtd/nand/raw/loongson1-nand-controller.c
> > > > +F: drivers/mtd/nand/raw/loongson-nand-controller.c
> > > > F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > F: sound/soc/loongson/loongson1_ac97.c
> > > >
> > > > diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> > > > index 4b99d9c422c3..d9e3f13666ac 100644
> > > > --- a/drivers/mtd/nand/raw/Kconfig
> > > > +++ b/drivers/mtd/nand/raw/Kconfig
> > > > @@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35
> > > > Enables support for the NAND controller found on
> > > > the Nuvoton MA35 series SoCs.
> > > >
> > > > -config MTD_NAND_LOONGSON1
> > > > - tristate "Loongson1 NAND controller"
> > > > +config MTD_NAND_LOONGSON
> > > > + tristate "Loongson NAND controller"
> > > > depends on LOONGSON1_APB_DMA || COMPILE_TEST
> > > > select REGMAP_MMIO
> > > > help
> > > > - Enables support for NAND controller on Loongson1 SoCs.
> > > > + Enables support for NAND controller on Loongson family chips.
> > > >
> > > > comment "Misc"
> > > >
> > > > diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
> > > > index 711d043ad4f8..c182b9703a9e 100644
> > > > --- a/drivers/mtd/nand/raw/Makefile
> > > > +++ b/drivers/mtd/nand/raw/Makefile
> > > > @@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o
> > > > obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o
> > > > obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o
> > > > obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o
> > > > -obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o
> > > > +obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.o
> > > >
> > > > nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
> > > > nand-objs += nand_onfi.o
> > > > diff --git a/drivers/mtd/nand/raw/loongson1-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > > > similarity index 100%
> > > > rename from drivers/mtd/nand/raw/loongson1-nand-controller.c
> > > > rename to drivers/mtd/nand/raw/loongson-nand-controller.c
> > > > --
> > > > 2.47.3
> > > >
> > > >
> >
> > --
> > Thanks.
> > Binbin
>
>
>
> --
> Best regards,
>
> Keguang Zhang
--
Thanks.
Binbin
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 7/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller
2025-08-11 6:03 ` [PATCH v2 7/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller Binbin Zhou
@ 2025-08-18 15:55 ` Rob Herring (Arm)
0 siblings, 0 replies; 28+ messages in thread
From: Rob Herring (Arm) @ 2025-08-18 15:55 UTC (permalink / raw)
To: Binbin Zhou
Cc: Huacai Chen, Huacai Chen, linux-mtd, Rob Herring, Xuerui Wang,
Binbin Zhou, loongarch, Richard Weinberger, Vignesh Raghavendra,
Miquel Raynal, devicetree, Krzysztof Kozlowski, Conor Dooley,
Keguang Zhang
On Mon, 11 Aug 2025 14:03:14 +0800, Binbin Zhou wrote:
> Add new compatible for the Loongson-2K NAND controller used for
> Loongson-2K1000 SoC.
>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> ---
> .../mtd/loongson,ls1b-nand-controller.yaml | 50 ++++++++++++++++++-
> 1 file changed, 49 insertions(+), 1 deletion(-)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support
2025-08-11 6:37 ` Huacai Chen
@ 2025-08-19 9:12 ` Keguang Zhang
0 siblings, 0 replies; 28+ messages in thread
From: Keguang Zhang @ 2025-08-19 9:12 UTC (permalink / raw)
To: Huacai Chen
Cc: Binbin Zhou, Binbin Zhou, Huacai Chen, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra, Xuerui Wang, loongarch,
devicetree, linux-mtd
On Mon, Aug 11, 2025 at 2:37 PM Huacai Chen <chenhuacai@kernel.org> wrote:
>
> Hi, Binbin,
>
> On Mon, Aug 11, 2025 at 2:02 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
> >
> > From: Keguang Zhang <keguang.zhang@gmail.com>
> >
> > Loongson-1C and Loongson-2K SoCs support NAND flash chips with 6-byte ID.
> > However, the current implementation only handles 5-byte ID which can lead
> > to incorrect chip detection.
> >
> > Extend loongson_nand_read_id_type_exec() to support 6-byte NAND ID.
> >
> > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> > ---
> > .../mtd/nand/raw/loongson-nand-controller.c | 29 +++++++++++++++----
> > 1 file changed, 23 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > index b5a7be0fcacc..97cd566420a8 100644
> > --- a/drivers/mtd/nand/raw/loongson-nand-controller.c
> > +++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > @@ -50,6 +50,9 @@
> > #define LOONGSON_NAND_COL_ADDR_CYC 2U
> > #define LOONGSON_NAND_MAX_ADDR_CYC 5U
> >
> > +#define LOONGSON_NAND_READ_ID_SLEEP_US 1000
> > +#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000
> > +
> > #define BITS_PER_WORD (4 * BITS_PER_BYTE)
> >
> > struct loongson_nand_host;
> > @@ -73,6 +76,8 @@ struct loongson_nand_op {
> > };
> >
> > struct loongson_nand_data {
> > + unsigned int max_id_cycle;
> > + unsigned int id_cycle_field;
> > unsigned int status_field;
> > unsigned int op_scope_field;
> > unsigned int hold_cycle;
> > @@ -458,10 +463,10 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct
> > struct loongson_nand_op op = {};
> > int i, ret;
> > union {
> > - char ids[5];
> > + char ids[6];
> > struct {
> > int idl;
> > - char idh;
> > + u16 idh;
> > };
> > } nand_id;
> >
> > @@ -469,11 +474,16 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct
> > if (ret)
> > return ret;
> >
> > - nand_id.idl = readl(host->reg_base + LOONGSON_NAND_IDL);
> > - nand_id.idh = readb(host->reg_base + LOONGSON_NAND_IDH_STATUS);
> > + ret = regmap_read_poll_timeout(host->regmap, LOONGSON_NAND_IDL, nand_id.idl, nand_id.idl,
> > + LOONGSON_NAND_READ_ID_SLEEP_US,
> > + LOONGSON_NAND_READ_ID_TIMEOUT_US);
> The last two lines can be merged.
>
No, merging them would exceed 100 columns.
> Huacai
>
> > + if (ret)
> > + return ret;
> >
> > - for (i = 0; i < min(sizeof(nand_id.ids), op.orig_len); i++)
> > - op.buf[i] = nand_id.ids[sizeof(nand_id.ids) - 1 - i];
> > + nand_id.idh = readw(host->reg_base + LOONGSON_NAND_IDH_STATUS);
> > +
> > + for (i = 0; i < min(host->data->max_id_cycle, op.orig_len); i++)
> > + op.buf[i] = nand_id.ids[host->data->max_id_cycle - 1 - i];
> >
> > return ret;
> > }
> > @@ -676,6 +686,10 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
> > if (IS_ERR(host->regmap))
> > return dev_err_probe(dev, PTR_ERR(host->regmap), "failed to init regmap\n");
> >
> > + if (host->data->id_cycle_field)
> > + regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM, host->data->id_cycle_field,
> > + host->data->max_id_cycle << __ffs(host->data->id_cycle_field));
> > +
> > chan = dma_request_chan(dev, "rxtx");
> > if (IS_ERR(chan))
> > return dev_err_probe(dev, PTR_ERR(chan), "failed to request DMA channel\n");
> > @@ -800,6 +814,7 @@ static void loongson_nand_remove(struct platform_device *pdev)
> > }
> >
> > static const struct loongson_nand_data ls1b_nand_data = {
> > + .max_id_cycle = 5,
> > .status_field = GENMASK(15, 8),
> > .hold_cycle = 0x2,
> > .wait_cycle = 0xc,
> > @@ -807,6 +822,8 @@ static const struct loongson_nand_data ls1b_nand_data = {
> > };
> >
> > static const struct loongson_nand_data ls1c_nand_data = {
> > + .max_id_cycle = 6,
> > + .id_cycle_field = GENMASK(14, 12),
> > .status_field = GENMASK(23, 16),
> > .op_scope_field = GENMASK(29, 16),
> > .hold_cycle = 0x2,
> > --
> > 2.47.3
> >
--
Best regards,
Keguang Zhang
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support
2025-08-11 6:03 ` [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support Binbin Zhou
2025-08-11 6:40 ` Huacai Chen
@ 2025-08-19 9:27 ` Keguang Zhang
1 sibling, 0 replies; 28+ messages in thread
From: Keguang Zhang @ 2025-08-19 9:27 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-mtd
On Mon, Aug 11, 2025 at 2:03 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
>
> The page address register describes the page address of the starting
> address for NAND read/write/erase operations.
>
> According to the manual, it consists of two parts:
> {chip select, page number}
>
> The `chip select` is fixed at 2 bits, and the `page number` is
> determined based on the actual capacity of the single-chip memory.
> Therefore we need to determine the `chip select` bits base on the `page
> number`.
>
> For example, for a 1GB capacity chip (2K page size), it has 1M pages.
> Thus, [19:0] is used to represent the page number, and [21:20]
> represents the chip select.
>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> ---
> .../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++----
> 1 file changed, 103 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> index 97cd566420a8..5a51c7d299cc 100644
> --- a/drivers/mtd/nand/raw/loongson-nand-controller.c
> +++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
> @@ -82,6 +82,7 @@ struct loongson_nand_data {
> unsigned int op_scope_field;
> unsigned int hold_cycle;
> unsigned int wait_cycle;
> + unsigned int nand_cs;
> void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
> };
>
> @@ -90,6 +91,7 @@ struct loongson_nand_host {
> struct nand_chip chip;
> struct nand_controller controller;
> const struct loongson_nand_data *data;
> + unsigned int addr_cs_field;
> void __iomem *reg_base;
> struct regmap *regmap;
> /* DMA Engine stuff */
> @@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const struct
> return 0;
> }
>
> +static void loongson_nand_set_addr_cs(struct loongson_nand_host *host)
> +{
> + struct nand_chip *chip = &host->chip;
> + struct mtd_info *mtd = nand_to_mtd(chip);
> +
> + if (!host->data->nand_cs)
> + return;
> +
> + /*
> + * The Manufacturer/Chip ID read operation precedes attach_chip, at which point
> + * information such as NAND chip selection and capacity is unknown. As a
> + * workaround, we use 128MB cellsize (2KB pagesize) as a fallback.
> + */
> + if (!mtd->writesize)
> + host->addr_cs_field = GENMASK(17, 16);
> +
> + regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, host->addr_cs_field,
> + host->data->nand_cs << __ffs(host->addr_cs_field));
> +}
> +
> static void ls1b_nand_set_addr(struct loongson_nand_host *host, struct loongson_nand_op *op)
> {
> struct nand_chip *chip = &host->chip;
> @@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_
> regmap_update_bits(host->regmap, LOONGSON_NAND_ADDR2, mask, val);
> }
> }
> +
> + loongson_nand_set_addr_cs(host);
> }
>
> static void loongson_nand_trigger_op(struct loongson_nand_host *host, struct loongson_nand_op *op)
> @@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera
> return nand_op_parser_exec_op(chip, &loongson_nand_op_parser, op, check_only);
> }
>
> -static int loongson_nand_attach_chip(struct nand_chip *chip)
> +static int loongson_nand_get_chip_capacity(struct nand_chip *chip)
> {
> struct loongson_nand_host *host = nand_get_controller_data(chip);
> u64 chipsize = nanddev_target_size(&chip->base);
> - int cell_size = 0;
> + struct mtd_info *mtd = nand_to_mtd(chip);
>
> - switch (chipsize) {
> - case SZ_128M:
> - cell_size = 0x0;
> - break;
> - case SZ_256M:
> - cell_size = 0x1;
> - break;
> - case SZ_512M:
> - cell_size = 0x2;
> - break;
> - case SZ_1G:
> - cell_size = 0x3;
> - break;
> - case SZ_2G:
> - cell_size = 0x4;
> - break;
> - case SZ_4G:
> - cell_size = 0x5;
> - break;
> - case SZ_8G:
> - cell_size = 0x6;
> - break;
> - case SZ_16G:
> - cell_size = 0x7;
> - break;
> - default:
> - dev_err(host->dev, "unsupported chip size: %llu MB\n", chipsize);
> - return -EINVAL;
> + if (mtd->writesize == SZ_4K && chipsize == SZ_2G) {
> + host->addr_cs_field = GENMASK(20, 19);
> + return 0x4;
> }
>
> + if (mtd->writesize == SZ_2K) {
> + switch (chipsize) {
> + case SZ_128M:
> + host->addr_cs_field = GENMASK(17, 16);
> + return 0;
> + case SZ_256M:
> + host->addr_cs_field = GENMASK(18, 17);
> + return 0x1;
> + case SZ_512M:
> + host->addr_cs_field = GENMASK(19, 18);
> + return 0x2;
> + case SZ_1G:
> + host->addr_cs_field = GENMASK(20, 19);
> + return 0x3;
> + default:
> + goto err;
> + }
> + }
> +
> + if (mtd->writesize == SZ_8K) {
> + switch (chipsize) {
> + case SZ_4G:
> + host->addr_cs_field = GENMASK(20, 19);
> + return 0x5;
> + case SZ_8G:
> + host->addr_cs_field = GENMASK(21, 20);
> + return 0x6;
> + case SZ_16G:
> + host->addr_cs_field = GENMASK(22, 21);
> + return 0x7;
> + default:
> + goto err;
> + }
> + }
> +
> + if (mtd->writesize == SZ_512) {
> + switch (chipsize) {
> + case SZ_8M:
> + host->addr_cs_field = GENMASK(15, 14);
> + return 0x9;
> + case SZ_16M:
> + host->addr_cs_field = GENMASK(16, 15);
> + return 0xa;
> + case SZ_32M:
> + host->addr_cs_field = GENMASK(17, 16);
> + return 0xb;
> + case SZ_64M:
> + host->addr_cs_field = GENMASK(18, 17);
> + return 0xc;
> + case SZ_128M:
> + host->addr_cs_field = GENMASK(19, 18);
> + return 0xd;
> + default:
> + goto err;
> + }
> + }
> +
> +err:
> + dev_err(host->dev, "Unsupported chip size: %llu MB with page size %u B\n",
> + chipsize, mtd->writesize);
> + return -EINVAL;
> +}
> +
> +static int loongson_nand_attach_chip(struct nand_chip *chip)
> +{
> + struct loongson_nand_host *host = nand_get_controller_data(chip);
> + int cell_size = 0;
> +
> + cell_size = loongson_nand_get_chip_capacity(chip);
> + if (cell_size < 0)
> + return cell_size;
> +
> switch (chip->ecc.engine_type) {
> case NAND_ECC_ENGINE_TYPE_NONE:
> break;
> @@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = {
> .status_field = GENMASK(15, 8),
> .hold_cycle = 0x2,
> .wait_cycle = 0xc,
> + .nand_cs = 0x0,
The assignment `.nand_cs = 0x0` is redundant and can be removed.
> .set_addr = ls1b_nand_set_addr,
> };
>
> @@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = {
> .op_scope_field = GENMASK(29, 16),
> .hold_cycle = 0x2,
> .wait_cycle = 0xc,
> + .nand_cs = 0x0,
Ditto.
> .set_addr = ls1c_nand_set_addr,
> };
>
> --
> 2.47.3
>
--
Best regards,
Keguang Zhang
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
2025-08-11 6:03 ` [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support Binbin Zhou
2025-08-11 18:09 ` Yao Zi
@ 2025-08-21 6:45 ` Keguang Zhang
2025-08-21 7:13 ` Binbin Zhou
1 sibling, 1 reply; 28+ messages in thread
From: Keguang Zhang @ 2025-08-21 6:45 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-mtd
On Mon, Aug 11, 2025 at 2:03 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
>
> The Loongson-2K0500 NAND controller is similar to the Loongson-1C.
>
> It supports a maximum capacity of 16GB FLASH per chip with a maximum
> page size of 8KB, and it supports up to 4 chip selects and 4 RDY
> signals.
>
> Its DMA controller is defaulted to APBDMA0.
>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> ---
> drivers/mtd/nand/raw/Kconfig | 2 +-
> .../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++-
> 2 files changed, 54 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> index d9e3f13666ac..7b0c5d06aa95 100644
> --- a/drivers/mtd/nand/raw/Kconfig
> +++ b/drivers/mtd/nand/raw/Kconfig
> @@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35
>
> config MTD_NAND_LOONGSON
> tristate "Loongson NAND controller"
> - depends on LOONGSON1_APB_DMA || COMPILE_TEST
> + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST
> select REGMAP_MMIO
> help
> Enables support for NAND controller on Loongson family chips.
> diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> index 5a51c7d299cc..7a15df3fcd31 100644
> --- a/drivers/mtd/nand/raw/loongson-nand-controller.c
> +++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
> @@ -3,6 +3,7 @@
> * NAND Controller Driver for Loongson family chips
> *
> * Copyright (C) 2015-2025 Keguang Zhang <keguang.zhang@gmail.com>
> + * Copyright (C) 2025 Binbin Zhou <zhoubinbin@loongson.cn>
> */
>
> #include <linux/kernel.h>
> @@ -26,6 +27,7 @@
> #define LOONGSON_NAND_IDH_STATUS 0x14
> #define LOONGSON_NAND_PARAM 0x18
> #define LOONGSON_NAND_OP_NUM 0x1c
> +#define LOONGSON_NAND_CS_RDY_MAP 0x20
>
> /* Bitfields of nand command register */
> #define LOONGSON_NAND_CMD_OP_DONE BIT(10)
> @@ -40,6 +42,23 @@
> #define LOONGSON_NAND_CMD_READ BIT(1)
> #define LOONGSON_NAND_CMD_VALID BIT(0)
>
> +/* Bitfields of nand cs/rdy map register */
> +#define LOONGSON_NAND_MAP_CS1_SEL GENMASK(11, 8)
> +#define LOONGSON_NAND_MAP_RDY1_SEL GENMASK(15, 12)
> +#define LOONGSON_NAND_MAP_CS2_SEL GENMASK(19, 16)
> +#define LOONGSON_NAND_MAP_RDY2_SEL GENMASK(23, 20)
> +#define LOONGSON_NAND_MAP_CS3_SEL GENMASK(27, 24)
> +#define LOONGSON_NAND_MAP_RDY3_SEL GENMASK(31, 28)
> +
> +#define LOONGSON_NAND_CS_SEL0 BIT(0)
> +#define LOONGSON_NAND_CS_SEL1 BIT(1)
> +#define LOONGSON_NAND_CS_SEL2 BIT(2)
> +#define LOONGSON_NAND_CS_SEL3 BIT(3)
> +#define LOONGSON_NAND_CS_RDY0 BIT(0)
> +#define LOONGSON_NAND_CS_RDY1 BIT(1)
> +#define LOONGSON_NAND_CS_RDY2 BIT(2)
> +#define LOONGSON_NAND_CS_RDY3 BIT(3)
> +
> /* Bitfields of nand timing register */
> #define LOONGSON_NAND_WAIT_CYCLE_MASK GENMASK(7, 0)
> #define LOONGSON_NAND_HOLD_CYCLE_MASK GENMASK(15, 8)
> @@ -53,6 +72,8 @@
> #define LOONGSON_NAND_READ_ID_SLEEP_US 1000
> #define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000
>
> +#define LOONGSON_NAND_64BIT_DMA BIT(0)
It's strongly suggested to replace this flag with a dma_bits field in
loongson_nand_host.
Please see the comments below.
> +
> #define BITS_PER_WORD (4 * BITS_PER_BYTE)
>
> struct loongson_nand_host;
> @@ -83,6 +104,7 @@ struct loongson_nand_data {
> unsigned int hold_cycle;
> unsigned int wait_cycle;
> unsigned int nand_cs;
Add unsigned int dma_bits;
> + unsigned int flags;
> void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
> };
>
> @@ -751,7 +773,7 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
> struct device *dev = host->dev;
> struct dma_chan *chan;
> struct dma_slave_config cfg = {};
> - int ret;
> + int ret, val;
>
> host->regmap = devm_regmap_init_mmio(dev, host->reg_base, &loongson_nand_regmap_config);
> if (IS_ERR(host->regmap))
> @@ -761,6 +783,9 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
> regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM, host->data->id_cycle_field,
> host->data->max_id_cycle << __ffs(host->data->id_cycle_field));
>
> + if (host->data->flags & LOONGSON_NAND_64BIT_DMA)
> + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> +
Sorry, all platforms should call dma_set_mask_and_coherent(),
including Loongson-1, which I missed earlier.
ret = dma_set_mask_and_coherent(dev,
DMA_BIT_MASK(host->data->dma_bits));
if (ret)
return dev_err_probe(dev, ret, "failed to set DMA mask\n");
> chan = dma_request_chan(dev, "rxtx");
> if (IS_ERR(chan))
> return dev_err_probe(dev, PTR_ERR(chan), "failed to request DMA channel\n");
> @@ -776,7 +801,14 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
>
> init_completion(&host->dma_complete);
>
> - return 0;
> + val = FIELD_PREP(LOONGSON_NAND_MAP_CS1_SEL, LOONGSON_NAND_CS_SEL1)
> + | FIELD_PREP(LOONGSON_NAND_MAP_RDY1_SEL, LOONGSON_NAND_CS_RDY1)
> + | FIELD_PREP(LOONGSON_NAND_MAP_CS2_SEL, LOONGSON_NAND_CS_SEL2)
> + | FIELD_PREP(LOONGSON_NAND_MAP_RDY2_SEL, LOONGSON_NAND_CS_RDY2)
> + | FIELD_PREP(LOONGSON_NAND_MAP_CS3_SEL, LOONGSON_NAND_CS_SEL3)
> + | FIELD_PREP(LOONGSON_NAND_MAP_RDY3_SEL, LOONGSON_NAND_CS_RDY3);
> +
> + return regmap_write(host->regmap, LOONGSON_NAND_CS_RDY_MAP, val);
Chip selects should be set before requesting the DMA channel.
> }
>
> static int loongson_nand_chip_init(struct loongson_nand_host *host)
> @@ -890,6 +922,7 @@ static const struct loongson_nand_data ls1b_nand_data = {
> .hold_cycle = 0x2,
> .wait_cycle = 0xc,
> .nand_cs = 0x0,
Add .dma_bits = 32,
> + .flags = 0,
The assignment `.flags = 0x0` is redundant and can be removed.
> .set_addr = ls1b_nand_set_addr,
> };
>
> @@ -901,6 +934,19 @@ static const struct loongson_nand_data ls1c_nand_data = {
> .hold_cycle = 0x2,
> .wait_cycle = 0xc,
> .nand_cs = 0x0,
Add .dma_bits = 32,
> + .flags = 0,
Ditto.
> + .set_addr = ls1c_nand_set_addr,
> +};
> +
> +static const struct loongson_nand_data ls2k0500_nand_data = {
> + .max_id_cycle = 6,
> + .id_cycle_field = GENMASK(14, 12),
> + .status_field = GENMASK(23, 16),
> + .op_scope_field = GENMASK(29, 16),
> + .hold_cycle = 0x4,
> + .wait_cycle = 0x12,
> + .nand_cs = 0x0,
> + .flags = LOONGSON_NAND_64BIT_DMA,
Replace LOONGSON_NAND_64BIT_DMA with .dma_bits = 64,
> .set_addr = ls1c_nand_set_addr,
> };
>
> @@ -913,6 +959,10 @@ static const struct of_device_id loongson_nand_match[] = {
> .compatible = "loongson,ls1c-nand-controller",
> .data = &ls1c_nand_data,
> },
> + {
> + .compatible = "loongson,ls2k0500-nand-controller",
> + .data = &ls2k0500_nand_data,
> + },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, loongson_nand_match);
> @@ -929,5 +979,6 @@ static struct platform_driver loongson_nand_driver = {
> module_platform_driver(loongson_nand_driver);
>
> MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> +MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");
> MODULE_DESCRIPTION("Loongson NAND Controller Driver");
> MODULE_LICENSE("GPL");
> --
> 2.47.3
>
--
Best regards,
Keguang Zhang
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
2025-08-21 6:45 ` Keguang Zhang
@ 2025-08-21 7:13 ` Binbin Zhou
0 siblings, 0 replies; 28+ messages in thread
From: Binbin Zhou @ 2025-08-21 7:13 UTC (permalink / raw)
To: Keguang Zhang
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Huacai Chen, Xuerui Wang, loongarch,
devicetree, linux-mtd
Hi Keguang:
Thanks for your reply.
On Thu, Aug 21, 2025 at 2:46 PM Keguang Zhang <keguang.zhang@gmail.com> wrote:
>
> On Mon, Aug 11, 2025 at 2:03 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
> >
> > The Loongson-2K0500 NAND controller is similar to the Loongson-1C.
> >
> > It supports a maximum capacity of 16GB FLASH per chip with a maximum
> > page size of 8KB, and it supports up to 4 chip selects and 4 RDY
> > signals.
> >
> > Its DMA controller is defaulted to APBDMA0.
> >
> > Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
> > ---
> > drivers/mtd/nand/raw/Kconfig | 2 +-
> > .../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++-
> > 2 files changed, 54 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> > index d9e3f13666ac..7b0c5d06aa95 100644
> > --- a/drivers/mtd/nand/raw/Kconfig
> > +++ b/drivers/mtd/nand/raw/Kconfig
> > @@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35
> >
> > config MTD_NAND_LOONGSON
> > tristate "Loongson NAND controller"
> > - depends on LOONGSON1_APB_DMA || COMPILE_TEST
> > + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST
> > select REGMAP_MMIO
> > help
> > Enables support for NAND controller on Loongson family chips.
> > diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > index 5a51c7d299cc..7a15df3fcd31 100644
> > --- a/drivers/mtd/nand/raw/loongson-nand-controller.c
> > +++ b/drivers/mtd/nand/raw/loongson-nand-controller.c
> > @@ -3,6 +3,7 @@
> > * NAND Controller Driver for Loongson family chips
> > *
> > * Copyright (C) 2015-2025 Keguang Zhang <keguang.zhang@gmail.com>
> > + * Copyright (C) 2025 Binbin Zhou <zhoubinbin@loongson.cn>
> > */
> >
> > #include <linux/kernel.h>
> > @@ -26,6 +27,7 @@
> > #define LOONGSON_NAND_IDH_STATUS 0x14
> > #define LOONGSON_NAND_PARAM 0x18
> > #define LOONGSON_NAND_OP_NUM 0x1c
> > +#define LOONGSON_NAND_CS_RDY_MAP 0x20
> >
> > /* Bitfields of nand command register */
> > #define LOONGSON_NAND_CMD_OP_DONE BIT(10)
> > @@ -40,6 +42,23 @@
> > #define LOONGSON_NAND_CMD_READ BIT(1)
> > #define LOONGSON_NAND_CMD_VALID BIT(0)
> >
> > +/* Bitfields of nand cs/rdy map register */
> > +#define LOONGSON_NAND_MAP_CS1_SEL GENMASK(11, 8)
> > +#define LOONGSON_NAND_MAP_RDY1_SEL GENMASK(15, 12)
> > +#define LOONGSON_NAND_MAP_CS2_SEL GENMASK(19, 16)
> > +#define LOONGSON_NAND_MAP_RDY2_SEL GENMASK(23, 20)
> > +#define LOONGSON_NAND_MAP_CS3_SEL GENMASK(27, 24)
> > +#define LOONGSON_NAND_MAP_RDY3_SEL GENMASK(31, 28)
> > +
> > +#define LOONGSON_NAND_CS_SEL0 BIT(0)
> > +#define LOONGSON_NAND_CS_SEL1 BIT(1)
> > +#define LOONGSON_NAND_CS_SEL2 BIT(2)
> > +#define LOONGSON_NAND_CS_SEL3 BIT(3)
> > +#define LOONGSON_NAND_CS_RDY0 BIT(0)
> > +#define LOONGSON_NAND_CS_RDY1 BIT(1)
> > +#define LOONGSON_NAND_CS_RDY2 BIT(2)
> > +#define LOONGSON_NAND_CS_RDY3 BIT(3)
> > +
> > /* Bitfields of nand timing register */
> > #define LOONGSON_NAND_WAIT_CYCLE_MASK GENMASK(7, 0)
> > #define LOONGSON_NAND_HOLD_CYCLE_MASK GENMASK(15, 8)
> > @@ -53,6 +72,8 @@
> > #define LOONGSON_NAND_READ_ID_SLEEP_US 1000
> > #define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000
> >
> > +#define LOONGSON_NAND_64BIT_DMA BIT(0)
>
> It's strongly suggested to replace this flag with a dma_bits field in
> loongson_nand_host.
> Please see the comments below.
>
> > +
> > #define BITS_PER_WORD (4 * BITS_PER_BYTE)
> >
> > struct loongson_nand_host;
> > @@ -83,6 +104,7 @@ struct loongson_nand_data {
> > unsigned int hold_cycle;
> > unsigned int wait_cycle;
> > unsigned int nand_cs;
>
> Add unsigned int dma_bits;
>
> > + unsigned int flags;
> > void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
> > };
> >
> > @@ -751,7 +773,7 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
> > struct device *dev = host->dev;
> > struct dma_chan *chan;
> > struct dma_slave_config cfg = {};
> > - int ret;
> > + int ret, val;
> >
> > host->regmap = devm_regmap_init_mmio(dev, host->reg_base, &loongson_nand_regmap_config);
> > if (IS_ERR(host->regmap))
> > @@ -761,6 +783,9 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
> > regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM, host->data->id_cycle_field,
> > host->data->max_id_cycle << __ffs(host->data->id_cycle_field));
> >
> > + if (host->data->flags & LOONGSON_NAND_64BIT_DMA)
> > + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> > +
>
> Sorry, all platforms should call dma_set_mask_and_coherent(),
> including Loongson-1, which I missed earlier.
> ret = dma_set_mask_and_coherent(dev,
> DMA_BIT_MASK(host->data->dma_bits));
> if (ret)
> return dev_err_probe(dev, ret, "failed to set DMA mask\n");
>
OK, if it is also required by Loongson-1, I will refactor this part.
In addition, I will address all of the following comments in the V4
patchset, as the V3 patchset[1] has already been submitted.
[1]: https://lore.kernel.org/all/cover.1755757841.git.zhoubinbin@loongson.cn/
You are welcome to continue to comment on that patchset as well.
> > chan = dma_request_chan(dev, "rxtx");
> > if (IS_ERR(chan))
> > return dev_err_probe(dev, PTR_ERR(chan), "failed to request DMA channel\n");
> > @@ -776,7 +801,14 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
> >
> > init_completion(&host->dma_complete);
> >
> > - return 0;
> > + val = FIELD_PREP(LOONGSON_NAND_MAP_CS1_SEL, LOONGSON_NAND_CS_SEL1)
> > + | FIELD_PREP(LOONGSON_NAND_MAP_RDY1_SEL, LOONGSON_NAND_CS_RDY1)
> > + | FIELD_PREP(LOONGSON_NAND_MAP_CS2_SEL, LOONGSON_NAND_CS_SEL2)
> > + | FIELD_PREP(LOONGSON_NAND_MAP_RDY2_SEL, LOONGSON_NAND_CS_RDY2)
> > + | FIELD_PREP(LOONGSON_NAND_MAP_CS3_SEL, LOONGSON_NAND_CS_SEL3)
> > + | FIELD_PREP(LOONGSON_NAND_MAP_RDY3_SEL, LOONGSON_NAND_CS_RDY3);
> > +
> > + return regmap_write(host->regmap, LOONGSON_NAND_CS_RDY_MAP, val);
>
> Chip selects should be set before requesting the DMA channel.
>
> > }
> >
> > static int loongson_nand_chip_init(struct loongson_nand_host *host)
> > @@ -890,6 +922,7 @@ static const struct loongson_nand_data ls1b_nand_data = {
> > .hold_cycle = 0x2,
> > .wait_cycle = 0xc,
> > .nand_cs = 0x0,
>
> Add .dma_bits = 32,
>
> > + .flags = 0,
>
> The assignment `.flags = 0x0` is redundant and can be removed.
>
> > .set_addr = ls1b_nand_set_addr,
> > };
> >
> > @@ -901,6 +934,19 @@ static const struct loongson_nand_data ls1c_nand_data = {
> > .hold_cycle = 0x2,
> > .wait_cycle = 0xc,
> > .nand_cs = 0x0,
>
> Add .dma_bits = 32,
>
> > + .flags = 0,
>
> Ditto.
>
> > + .set_addr = ls1c_nand_set_addr,
> > +};
> > +
> > +static const struct loongson_nand_data ls2k0500_nand_data = {
> > + .max_id_cycle = 6,
> > + .id_cycle_field = GENMASK(14, 12),
> > + .status_field = GENMASK(23, 16),
> > + .op_scope_field = GENMASK(29, 16),
> > + .hold_cycle = 0x4,
> > + .wait_cycle = 0x12,
> > + .nand_cs = 0x0,
> > + .flags = LOONGSON_NAND_64BIT_DMA,
>
> Replace LOONGSON_NAND_64BIT_DMA with .dma_bits = 64,
>
> > .set_addr = ls1c_nand_set_addr,
> > };
> >
> > @@ -913,6 +959,10 @@ static const struct of_device_id loongson_nand_match[] = {
> > .compatible = "loongson,ls1c-nand-controller",
> > .data = &ls1c_nand_data,
> > },
> > + {
> > + .compatible = "loongson,ls2k0500-nand-controller",
> > + .data = &ls2k0500_nand_data,
> > + },
> > { /* sentinel */ }
> > };
> > MODULE_DEVICE_TABLE(of, loongson_nand_match);
> > @@ -929,5 +979,6 @@ static struct platform_driver loongson_nand_driver = {
> > module_platform_driver(loongson_nand_driver);
> >
> > MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > +MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");
> > MODULE_DESCRIPTION("Loongson NAND Controller Driver");
> > MODULE_LICENSE("GPL");
> > --
> > 2.47.3
> >
>
>
> --
> Best regards,
>
> Keguang Zhang
--
Thanks.
Binbin
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2025-08-21 9:39 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-11 6:02 [PATCH v2 0/8] mtd: rawnand: loongson: Add Loongson-2K nand controller support Binbin Zhou
2025-08-11 6:02 ` [PATCH v2 1/8] mtd: rawnand: loongson1: Rename the prefix from ls1x to loongson Binbin Zhou
2025-08-11 6:02 ` [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 " Binbin Zhou
2025-08-11 6:36 ` Huacai Chen
2025-08-11 9:41 ` Binbin Zhou
2025-08-18 7:04 ` Keguang Zhang
2025-08-18 9:40 ` Binbin Zhou
2025-08-11 6:02 ` [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support Binbin Zhou
2025-08-11 6:37 ` Huacai Chen
2025-08-19 9:12 ` Keguang Zhang
2025-08-11 6:03 ` [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support Binbin Zhou
2025-08-11 6:40 ` Huacai Chen
2025-08-11 8:49 ` Binbin Zhou
2025-08-11 8:59 ` Huacai Chen
2025-08-19 9:27 ` Keguang Zhang
2025-08-11 6:03 ` [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller Binbin Zhou
2025-08-11 7:32 ` Krzysztof Kozlowski
2025-08-11 7:42 ` Binbin Zhou
2025-08-11 8:13 ` Krzysztof Kozlowski
2025-08-11 8:19 ` Binbin Zhou
2025-08-11 6:03 ` [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support Binbin Zhou
2025-08-11 18:09 ` Yao Zi
2025-08-12 1:46 ` Binbin Zhou
2025-08-21 6:45 ` Keguang Zhang
2025-08-21 7:13 ` Binbin Zhou
2025-08-11 6:03 ` [PATCH v2 7/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller Binbin Zhou
2025-08-18 15:55 ` Rob Herring (Arm)
2025-08-11 6:03 ` [PATCH v2 8/8] mtd: rawnand: loongson: Add Loongson-2K1000 NAND controller support Binbin Zhou
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).