Skip to contentSkip to conversation

mtd: rawnand: loongson: Add Loongson-2K nand controller support

PATCH Superseded Binbin Zhou 7 participants 28 messages Aug 11, 2025 – Aug 21, 2025

Subsystems (5)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v2 cover mtd: rawnand: loongson: Add Loongson-2K nand controller support

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/[email protected]/

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

Signature · 1 line
2.47.3
#1 lore raw

PATCH v2 1/8 mtd: rawnand: loongson1: Rename the prefix from ls1x to loongson

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.

---
 .../mtd/nand/raw/loongson1-nand-controller.c  | 337 +++++++++---------
 1 file changed, 172 insertions(+), 165 deletions(-)
drivers/mtd/nand/raw/loongson1-nand-controller.c +172 -165
index ef8e4f9ce287..b5a7be0fcacc 100644
@@ -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 <[email protected]>
  */
@@ -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 <[email protected]>");
-MODULE_DESCRIPTION("Loongson-1 NAND Controller Driver");
+MODULE_DESCRIPTION("Loongson NAND Controller Driver");
 MODULE_LICENSE("GPL");
Signature · 1 line
2.47.3
#2 lore raw

PATCH v2 2/8 mtd: rawnand: loongson: Rename loongson1 to loongson

In reply to 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.

---
 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%)
MAINTAINERS +1 -1
index 4bac4ea21b64..cc502582c9f1 100644
@@ -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
 
drivers/mtd/nand/raw/Kconfig +3 -3
index 4b99d9c422c3..d9e3f13666ac 100644
@@ -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"
 
drivers/mtd/nand/raw/Makefile +1 -1
index 711d043ad4f8..c182b9703a9e 100644
@@ -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
drivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0 -0
similarity index 100%
rename from drivers/mtd/nand/raw/loongson1-nand-controller.c
rename to drivers/mtd/nand/raw/loongson-nand-controller.c
Signature · 1 line
2.47.3
maintainer
#3 lore raw

Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson

Hi, Binbin,

Quoted 4 lines · 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.

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

Quoted 64 lines
---
 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%)
MAINTAINERS +1 -1
index 4bac4ea21b64..cc502582c9f1 100644
@@ -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
 
drivers/mtd/nand/raw/Kconfig +3 -3
index 4b99d9c422c3..d9e3f13666ac 100644
@@ -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"
 
drivers/mtd/nand/raw/Makefile +1 -1
index 711d043ad4f8..c182b9703a9e 100644
@@ -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
drivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0 -1
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

#4 lore raw

Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson

Hi Huacai:

Thanks for your reply.

Quoted 10 lines · Huacai Chen

Hi, Binbin,

Quoted 4 lines · 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.

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.

Quoted 57 lines

Huacai

Quoted 54 lines
---
 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%)
MAINTAINERS +1 -1
index 4bac4ea21b64..cc502582c9f1 100644
@@ -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
 
drivers/mtd/nand/raw/Kconfig +3 -3
index 4b99d9c422c3..d9e3f13666ac 100644
@@ -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"
 
drivers/mtd/nand/raw/Makefile +1 -1
index 711d043ad4f8..c182b9703a9e 100644
@@ -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
 
Quoted 10 lines
Quoted 10 lines
drivers/mtd/nand/raw/Makefile +0 -0
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
drivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0 -1
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

maintainer
#5 lore raw

Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson

Quoted 17 lines · Binbin Zhou

Hi Huacai:

Thanks for your reply.

Quoted 10 lines · Huacai Chen

Hi, Binbin,

Quoted 4 lines · 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.

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.

Quoted 7 lines

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.

Quoted 57 lines
Quoted 57 lines

Huacai

Quoted 54 lines
---
 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%)
MAINTAINERS +1 -1
index 4bac4ea21b64..cc502582c9f1 100644
@@ -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
 
drivers/mtd/nand/raw/Kconfig +3 -3
index 4b99d9c422c3..d9e3f13666ac 100644
@@ -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"
 
drivers/mtd/nand/raw/Makefile +1 -1
index 711d043ad4f8..c182b9703a9e 100644
@@ -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
 
Quoted 14 lines
Quoted 10 lines
Quoted 10 lines
drivers/mtd/nand/raw/Makefile +0 -0
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
drivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0 -1
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

#6 lore raw

Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson

Hi Keguang:

Thanks for your reply.

Quoted 24 lines · Keguang Zhang
Quoted 22 lines · Binbin Zhou

Hi Huacai:

Thanks for your reply.

Quoted 10 lines · Huacai Chen

Hi, Binbin,

Quoted 4 lines · 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.

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?

Quoted 5 lines
Quoted 2 lines

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.

Quoted 79 lines
Quoted 58 lines
Quoted 58 lines

Huacai

Quoted 54 lines
---
 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%)
MAINTAINERS +1 -1
index 4bac4ea21b64..cc502582c9f1 100644
@@ -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
 
drivers/mtd/nand/raw/Kconfig +3 -3
index 4b99d9c422c3..d9e3f13666ac 100644
@@ -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"
 
drivers/mtd/nand/raw/Makefile +1 -1
index 711d043ad4f8..c182b9703a9e 100644
@@ -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
 
Quoted 14 lines
Quoted 10 lines
Quoted 10 lines
drivers/mtd/nand/raw/Makefile +0 -0
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
drivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0 -1
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

Signature · 2 lines
Thanks.
Binbin
#7 lore raw

PATCH v2 3/8 mtd: rawnand: loongson: Add 6-byte NAND ID reading support

In reply to Binbin Zhou

From: Keguang Zhang <[email protected]>

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.

---
 .../mtd/nand/raw/loongson-nand-controller.c   | 29 +++++++++++++++----
 1 file changed, 23 insertions(+), 6 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +23 -6
index b5a7be0fcacc..97cd566420a8 100644
@@ -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,
Signature · 1 line
2.47.3
maintainer
#8 lore raw

Re: [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support

Hi, Binbin,

Quoted 52 lines · Binbin Zhou

From: Keguang Zhang <[email protected]>

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.

---
 .../mtd/nand/raw/loongson-nand-controller.c   | 29 +++++++++++++++----
 1 file changed, 23 insertions(+), 6 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +7 -2
index b5a7be0fcacc..97cd566420a8 100644
@@ -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;
 

drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct · line 479

Quoted 8 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3 -2
@@ -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

Quoted 43 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +13 -3
+       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

maintainer
#9 lore raw

Re: [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support

Quoted 59 lines · Huacai Chen

Hi, Binbin,

Quoted 55 lines · Binbin Zhou

From: Keguang Zhang <[email protected]>

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.

---
 .../mtd/nand/raw/loongson-nand-controller.c   | 29 +++++++++++++++----
 1 file changed, 23 insertions(+), 6 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +7 -2
index b5a7be0fcacc..97cd566420a8 100644
@@ -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;
 
Quoted 7 lines

drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct · line 479

Quoted 5 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3 -2
-       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.

Quoted 45 lines

Huacai

Quoted 43 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +13 -3
+       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

Signature · 3 lines
Best regards,

Keguang Zhang
#10 lore raw

PATCH v2 4/8 mtd: rawnand: loongson: Add nand chip select support

In reply to 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.

---
 .../mtd/nand/raw/loongson-nand-controller.c   | 133 ++++++++++++++----
 1 file changed, 103 insertions(+), 30 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +103 -30
index 97cd566420a8..5a51c7d299cc 100644
@@ -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,
 };
 
Signature · 1 line
2.47.3
maintainer
#11 lore raw

Re: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support

Hi, Binbin,

Quoted 111 lines · 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.

---
 .../mtd/nand/raw/loongson-nand-controller.c   | 133 ++++++++++++++----
 1 file changed, 103 insertions(+), 30 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +26 -24
index 97cd566420a8..5a51c7d299cc 100644
@@ -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;

drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera · line 639

Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3 -6
-       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

Quoted 96 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +74 -1
+       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

#12 lore raw

Re: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support

Hi:

Quoted 128 lines · Huacai Chen

Hi, Binbin,

Quoted 111 lines · 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.

---
 .../mtd/nand/raw/loongson-nand-controller.c   | 133 ++++++++++++++----
 1 file changed, 103 insertions(+), 30 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +26 -24
index 97cd566420a8..5a51c7d299cc 100644
@@ -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;

drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera · line 639

Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3 -6
-       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.

Quoted 2 lines

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);
Quoted 99 lines

Huacai

Quoted 96 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +74 -1
+       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

Signature · 2 lines
Thanks.
Binbin
maintainer
#13 lore raw

Re: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support

Quoted 154 lines · Binbin Zhou

Hi:

Quoted 128 lines · Huacai Chen

Hi, Binbin,

Quoted 111 lines · 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.

---
 .../mtd/nand/raw/loongson-nand-controller.c   | 133 ++++++++++++++----
 1 file changed, 103 insertions(+), 30 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +26 -24
index 97cd566420a8..5a51c7d299cc 100644
@@ -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;

drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera · line 639

Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3 -6
-       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.

Quoted 2 lines

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);
Quoted 8 lines
                        return 0xd;
                }
                break;
        case SZ_2K:
                switch (chipsize) {
                case SZ_128M:
                        host->addr_cs_field = GENMASK(17, 16);
                        return 0;

Use 0x0 for consistency.

Quoted 24 lines
                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);
Quoted 8 lines
                        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

Quoted 108 lines
        }

        dev_err(host->dev, "Unsupported chip size: %llu MB with page
size %u B\n",
                chipsize, mtd->writesize);
Quoted 95 lines

Huacai

Quoted 92 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +74 -0
+       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,
 };
 
Quoted 4 lines
Quoted 4 lines

--
2.47.3

--
Thanks.
Binbin

maintainer
#14 lore raw

Re: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support

In reply to Binbin Zhou
Quoted 198 lines · 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.

---
 .../mtd/nand/raw/loongson-nand-controller.c   | 133 ++++++++++++++----
 1 file changed, 103 insertions(+), 30 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +101 -30
index 97cd566420a8..5a51c7d299cc 100644
@@ -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;

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 892

Quoted 4 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -0
@@ -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.

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 903

Quoted 8 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -0
        .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.

Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0 -1
        .set_addr = ls1c_nand_set_addr,
 };
 
--

2.47.3

Signature · 3 lines
Best regards,

Keguang Zhang
#15 lore raw

PATCH v2 5/8 dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller

In reply to Binbin Zhou

Add new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.

---
 .../bindings/mtd/loongson,ls1b-nand-controller.yaml         | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml +4 -2
index a09e92e416c4..4ec2b5d1e89d 100644
@@ -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 <[email protected]>
+  - Binbin Zhou <[email protected]>
 
 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
Signature · 1 line
2.47.3
#16 lore raw

Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller

Quoted 4 lines · Binbin Zhou

Add new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.

Why do you add quotes?

Best regards,
Krzysztof

#17 lore raw

Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller

Hi Krzysztof:

Quoted 9 lines · Krzysztof Kozlowski
Quoted 4 lines · Binbin Zhou

Add new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.

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.

Quoted 3 lines

Best regards,
Krzysztof

--
Thanks.
Binbin

#18 lore raw

Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller

Quoted 11 lines · Binbin Zhou

Hi Krzysztof:

Quoted 8 lines · Krzysztof Kozlowski
Quoted 4 lines · Binbin Zhou

Add new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.

Quoted 6 lines
Quoted 1 line

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) <[email protected]> (✓ DKIM/kernel.org)
+ Link: https://lore.kernel.org/r/588639de591ada408bdaeb0d279c5d62a4b53d61.1753166096.git.zhoubinbin@loongson.cn
+ Signed-off-by: Krzysztof Kozlowski <[email protected]>

No quotes in commit msg either.

Best regards,
Krzysztof

#19 lore raw

Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller

Hi Krzysztof:

Quoted 20 lines · Krzysztof Kozlowski
Quoted 11 lines · Binbin Zhou

Hi Krzysztof:

Quoted 8 lines · Krzysztof Kozlowski
Quoted 4 lines · Binbin Zhou

Add new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.

Quoted 6 lines
Quoted 1 line

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.

Quoted 8 lines

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) <[email protected]> (✓ DKIM/kernel.org)
+ Link: https://lore.kernel.org/r/588639de591ada408bdaeb0d279c5d62a4b53d61.1753166096.git.zhoubinbin@loongson.cn
+ Signed-off-by: Krzysztof Kozlowski <[email protected]>

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!

Quoted 7 lines

No quotes in commit msg either.

Best regards,
Krzysztof

Signature · 2 lines
Thanks.
Binbin
#20 lore raw

PATCH v2 6/8 mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support

In reply to 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.

---
 drivers/mtd/nand/raw/Kconfig                  |  2 +-
 .../mtd/nand/raw/loongson-nand-controller.c   | 55 ++++++++++++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)
drivers/mtd/nand/raw/Kconfig +1 -1
index d9e3f13666ac..7b0c5d06aa95 100644
@@ -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.
drivers/mtd/nand/raw/loongson-nand-controller.c +53 -2

126 lines not on this page · raw message

Signature · 1 line
2.47.3
#21 lore raw

Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support

Quoted 19 lines · 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.

---
 drivers/mtd/nand/raw/Kconfig                  |  2 +-
 .../mtd/nand/raw/loongson-nand-controller.c   | 55 ++++++++++++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)
drivers/mtd/nand/raw/Kconfig +0 -0
index d9e3f13666ac..7b0c5d06aa95 100644

drivers/mtd/nand/raw/Kconfig config MTD_NAND_NUVOTON_MA35 · line 467

Quoted 5 lines
drivers/mtd/nand/raw/Kconfig +1 -1
@@ -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

Quoted 3 lines
drivers/mtd/nand/raw/Kconfig +0 -0
 	select REGMAP_MMIO
 	help
 	  Enables support for NAND controller on Loongson family chips.
#22 lore raw

Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support

HI Yao:

Thanks for your reply.

Quoted 22 lines · Yao Zi
Quoted 20 lines · 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.

---
 drivers/mtd/nand/raw/Kconfig                  |  2 +-
 .../mtd/nand/raw/loongson-nand-controller.c   | 55 ++++++++++++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)
drivers/mtd/nand/raw/Kconfig +0 -0
index d9e3f13666ac..7b0c5d06aa95 100644
@@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35
 
Quoted 9 lines

drivers/mtd/nand/raw/Kconfig config MTD_NAND_NUVOTON_MA35 · line 467

Quoted 4 lines
drivers/mtd/nand/raw/Kconfig +1 -1
 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.

Quoted 7 lines

Regards,
Yao Zi

Quoted 3 lines
drivers/mtd/nand/raw/Kconfig +0 -0
      select REGMAP_MMIO
      help
        Enables support for NAND controller on Loongson family chips.
Signature · 2 lines
Thanks.
Binbin
maintainer
#23 lore raw

Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support

In reply to Binbin Zhou
Quoted 73 lines · 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.

---
 drivers/mtd/nand/raw/Kconfig                  |  2 +-
 .../mtd/nand/raw/loongson-nand-controller.c   | 55 ++++++++++++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)
drivers/mtd/nand/raw/Kconfig +1 -1
index d9e3f13666ac..7b0c5d06aa95 100644
@@ -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.
drivers/mtd/nand/raw/loongson-nand-controller.c +19 -0
index 5a51c7d299cc..7a15df3fcd31 100644
@@ -3,6 +3,7 @@
  * NAND Controller Driver for Loongson family chips
  *
  * Copyright (C) 2015-2025 Keguang Zhang <[email protected]>
+ * Copyright (C) 2025 Binbin Zhou <[email protected]>
  */
 
 #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)

drivers/mtd/nand/raw/loongson-nand-controller.c line 75

Quoted 4 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -0
@@ -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.

drivers/mtd/nand/raw/loongson-nand-controller.c struct loongson_nand_data { · line 106

Quoted 8 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -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;

Add unsigned int dma_bits;

Quoted 14 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +2 -1
+       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))

drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_controller_init(struct loongson_nand_host *host) · line 788

Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3 -0
@@ -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");
Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0 -0
        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);

drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_controller_init(struct loongson_nand_host *host) · line 811

Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +8 -1
 
-       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.

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 924

Quoted 7 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0 -0
 }
 
 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,

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 925

Quoted 1 line
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -0
+       .flags = 0,

The assignment .flags = 0x0 is redundant and can be removed.

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 936

Quoted 7 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0 -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,

Add .dma_bits = 32,

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 937

Quoted 1 line
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -0
+       .flags = 0,

Ditto.

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 949

Quoted 12 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +12 -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,

Replace LOONGSON_NAND_64BIT_DMA with .dma_bits = 64,

Quoted 22 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +5 -1
        .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 <[email protected]>");
+MODULE_AUTHOR("Binbin Zhou <[email protected]>");
 MODULE_DESCRIPTION("Loongson NAND Controller Driver");
 MODULE_LICENSE("GPL");
--
Quoted 2 lines

2.47.3

--
Best regards,

Keguang Zhang

#24 lore raw

Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support

Hi Keguang:

Thanks for your reply.

Quoted 119 lines · Keguang Zhang
Quoted 73 lines · 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.

---
 drivers/mtd/nand/raw/Kconfig                  |  2 +-
 .../mtd/nand/raw/loongson-nand-controller.c   | 55 ++++++++++++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)
drivers/mtd/nand/raw/Kconfig +1 -1
index d9e3f13666ac..7b0c5d06aa95 100644
@@ -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.
drivers/mtd/nand/raw/loongson-nand-controller.c +19 -0
index 5a51c7d299cc..7a15df3fcd31 100644
@@ -3,6 +3,7 @@
  * NAND Controller Driver for Loongson family chips
  *
  * Copyright (C) 2015-2025 Keguang Zhang <[email protected]>
+ * Copyright (C) 2025 Binbin Zhou <[email protected]>
  */
 
 #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)

drivers/mtd/nand/raw/loongson-nand-controller.c line 75

Quoted 4 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -0
@@ -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.

drivers/mtd/nand/raw/loongson-nand-controller.c struct loongson_nand_data { · line 106

Quoted 8 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -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;

Add unsigned int dma_bits;

Quoted 14 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +2 -1
+       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))

drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_controller_init(struct loongson_nand_host *host) · line 788

Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3 -0
@@ -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,

Quoted 4 lines
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/[email protected]/

You are welcome to continue to comment on that patchset as well.

Quoted 92 lines
Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0 -0
        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);

drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_controller_init(struct loongson_nand_host *host) · line 811

Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +8 -1
 
-       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.

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 924

Quoted 7 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0 -0
 }
 
 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,

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 925

Quoted 1 line
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -0
+       .flags = 0,

The assignment .flags = 0x0 is redundant and can be removed.

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 936

Quoted 7 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0 -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,

Add .dma_bits = 32,

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 937

Quoted 1 line
drivers/mtd/nand/raw/loongson-nand-controller.c +1 -0
+       .flags = 0,

Ditto.

drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 949

Quoted 12 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +12 -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,

Replace LOONGSON_NAND_64BIT_DMA with .dma_bits = 64,

Quoted 22 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +5 -1
        .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 <[email protected]>");
+MODULE_AUTHOR("Binbin Zhou <[email protected]>");
 MODULE_DESCRIPTION("Loongson NAND Controller Driver");
 MODULE_LICENSE("GPL");
--
Quoted 2 lines

2.47.3

--
Best regards,

Keguang Zhang

Signature · 2 lines
Thanks.
Binbin
#25 lore raw

PATCH v2 7/8 dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller

In reply to Binbin Zhou

Add new compatible for the Loongson-2K NAND controller used for Loongson-2K1000 SoC.

---
 .../mtd/loongson,ls1b-nand-controller.yaml    | 50 ++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml +49 -1
index 4ec2b5d1e89d..cf85d0cede00 100644
@@ -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>;
+        };
+    };
Signature · 1 line
2.47.3
maintainer Reviewed-by on v2 7/8
#26 lore raw

Re: [PATCH v2 7/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller

Quoted 8 lines · Binbin Zhou

Add new compatible for the Loongson-2K NAND controller used for Loongson-2K1000 SoC.

---
 .../mtd/loongson,ls1b-nand-controller.yaml    | 50 ++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)
#27 lore raw

PATCH v2 8/8 mtd: rawnand: loongson: Add Loongson-2K1000 NAND controller support

In reply to 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.

---
 .../mtd/nand/raw/loongson-nand-controller.c   | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)
drivers/mtd/nand/raw/loongson-nand-controller.c +48 -0
index 7a15df3fcd31..9c377062a3a1 100644
@@ -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);
Signature · 1 line
2.47.3