linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/14] spi: airoha: driver fixes & improvements
@ 2025-08-20 12:33 Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 01/14] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
                   ` (14 more replies)
  0 siblings, 15 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

This patch series greatly improve airoha snfi driver and fix a
number of serious bug.

Fixed bugs:
 * Fix reading/writing of flashes with more than one plane per lun
 * Fix inability to read/write oob area
 * Fill the buffer with 0xff before writing
 * Fix reading of flashes supporting continuous reading mode
 * Fix error paths

Improvements:
 * Add support of dual/quad wires spi modes in exec_op().
 * Support of dualio/quadio flash reading commands
 * Remove dirty hack that reads flash page settings from SNFI registers
   during driver startup

Unfortunately I am unable to test the driver with linux at the moment,
so only the following testing was done:
 * Driver compiles without error.
 * All changes were tested with corresponding u-boot driver. U-Boot
   SpiNAND driver was modified as well to match linux-6.17-rc2 with
   additional fixes for continuous mode.

Changes v2:
 * minor fix
 * add comments to code

Changes v3:
 * add patch to prevent continuous reading

Mikhail Kshevetskiy (14):
  spi: airoha: return an error for continuous mode dirmap creation cases
  spi: airoha: remove unnecessary restriction length
  spi: airoha: add support of dual/quad wires spi modes
  spi: airoha: remove unnecessary switch to non-dma mode
  spi: airoha: unify dirmap read/write code
  spi: airoha: switch back to non-dma mode in the case of error
  spi: airoha: fix reading/writing of flashes with more than one plane
    per lun
  spi: airoha: support of dualio/quadio flash reading commands
  spi: airoha: allow reading/writing of oob area
  spi: airoha: buffer must be 0xff-ed before writing
  spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
  spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
    REG_SPI_NFI_SECCUS_SIZE registers
  spi: airoha: set custom sector size equal to flash page size
  spi: airoha: avoid reading flash page settings from SNFI registers
    during driver startup

 drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
 1 file changed, 260 insertions(+), 248 deletions(-)

-- 
2.50.1



^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH v3 01/14] spi: airoha: return an error for continuous mode dirmap creation cases
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 02/14] spi: airoha: remove unnecessary restriction length Mikhail Kshevetskiy
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

This driver can accelerate single page operations only, thus
continuous reading mode should not be used.

Continuous reading will use sizes up to the size of one erase block.
This size is much larger than the size of single flash page. Use this
difference to identify continuous reading and return an error.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 drivers/spi/spi-airoha-snfi.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index dbe640986825..043a03cd90a1 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -618,6 +618,10 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
 	if (desc->info.offset + desc->info.length > U32_MAX)
 		return -EINVAL;
 
+	/* continuous reading is not supported */
+	if (desc->info.length > SPI_NAND_CACHE_SIZE)
+		return -E2BIG;
+
 	if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))
 		return -EOPNOTSUPP;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 02/14] spi: airoha: remove unnecessary restriction length
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 01/14] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 03/14] spi: airoha: add support of dual/quad wires spi modes Mikhail Kshevetskiy
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

The "length < 160" restriction is not needed because airoha_snand_write_data()
and airoha_snand_read_data() will properly handle data transfers above
SPI_MAX_TRANSFER_SIZE.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 043a03cd90a1..bcc464ec9c61 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -579,13 +579,6 @@ static int airoha_snand_adjust_op_size(struct spi_mem *mem,
 
 		if (op->data.nbytes > max_len)
 			op->data.nbytes = max_len;
-	} else {
-		max_len = 1 + op->addr.nbytes + op->dummy.nbytes;
-		if (max_len >= 160)
-			return -EOPNOTSUPP;
-
-		if (op->data.nbytes > 160 - max_len)
-			op->data.nbytes = 160 - max_len;
 	}
 
 	return 0;
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 03/14] spi: airoha: add support of dual/quad wires spi modes
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 01/14] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 02/14] spi: airoha: remove unnecessary restriction length Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:48   ` Jyothi Kumar Seerapu
  2025-08-20 12:33 ` [PATCH v3 04/14] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

This patch adds support of dual and quad wires spi modes. It will
speed up flash operations on the hardware with corresponding hardware
support.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 107 +++++++++++++++++++++++++---------
 1 file changed, 80 insertions(+), 27 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index bcc464ec9c61..7aab3506834a 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -192,6 +192,14 @@
 #define SPI_NAND_OP_RESET			0xff
 #define SPI_NAND_OP_DIE_SELECT			0xc2
 
+/* SNAND FIFO commands */
+#define SNAND_FIFO_TX_BUSWIDTH_SINGLE		0x08
+#define SNAND_FIFO_TX_BUSWIDTH_DUAL		0x09
+#define SNAND_FIFO_TX_BUSWIDTH_QUAD		0x0a
+#define SNAND_FIFO_RX_BUSWIDTH_SINGLE		0x0c
+#define SNAND_FIFO_RX_BUSWIDTH_DUAL		0x0e
+#define SNAND_FIFO_RX_BUSWIDTH_QUAD		0x0f
+
 #define SPI_NAND_CACHE_SIZE			(SZ_4K + SZ_256)
 #define SPI_MAX_TRANSFER_SIZE			511
 
@@ -387,10 +395,25 @@ static int airoha_snand_set_mode(struct airoha_snand_ctrl *as_ctrl,
 	return regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0);
 }
 
-static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
-				   const u8 *data, int len)
+static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl,
+				   const u8 *data, int len, int buswidth)
 {
 	int i, data_len;
+	u8 cmd;
+
+	switch (buswidth) {
+	case 1:
+		cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE;
+		break;
+	case 2:
+		cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL;
+		break;
+	case 4:
+		cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	for (i = 0; i < len; i += data_len) {
 		int err;
@@ -409,16 +432,31 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
 	return 0;
 }
 
-static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
-				  int len)
+static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl,
+				  u8 *data, int len, int buswidth)
 {
 	int i, data_len;
+	u8 cmd;
+
+	switch (buswidth) {
+	case 1:
+		cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE;
+		break;
+	case 2:
+		cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL;
+		break;
+	case 4:
+		cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	for (i = 0; i < len; i += data_len) {
 		int err;
 
 		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
-		err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
+		err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
 		if (err)
 			return err;
 
@@ -895,12 +933,27 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 static int airoha_snand_exec_op(struct spi_mem *mem,
 				const struct spi_mem_op *op)
 {
-	u8 data[8], cmd, opcode = op->cmd.opcode;
 	struct airoha_snand_ctrl *as_ctrl;
-	int i, err;
+	char buf[20], *data;
+	int i, err, op_len, addr_len, dummy_len;
 
 	as_ctrl = spi_controller_get_devdata(mem->spi->controller);
 
+	op_len = op->cmd.nbytes;
+	addr_len = op->addr.nbytes;
+	dummy_len = op->dummy.nbytes;
+
+	if (op_len + dummy_len + addr_len > sizeof(buf))
+		return -EIO;
+
+	data = buf;
+	for (i = 0; i < op_len; i++)
+		*data++ = op->cmd.opcode >> (8 * (op_len - i - 1));
+	for (i = 0; i < addr_len; i++)
+		*data++ = op->addr.val >> (8 * (addr_len - i - 1));
+	for (i = 0; i < dummy_len; i++)
+		*data++ = 0xff;
+
 	/* switch to manual mode */
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	if (err < 0)
@@ -911,40 +964,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
 		return err;
 
 	/* opcode */
-	err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));
+	data = buf;
+	err = airoha_snand_write_data(as_ctrl, data, op_len,
+				      op->cmd.buswidth);
 	if (err)
 		return err;
 
 	/* addr part */
-	cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
-	put_unaligned_be64(op->addr.val, data);
-
-	for (i = ARRAY_SIZE(data) - op->addr.nbytes;
-	     i < ARRAY_SIZE(data); i++) {
-		err = airoha_snand_write_data(as_ctrl, cmd, &data[i],
-					      sizeof(data[0]));
+	data += op_len;
+	if (addr_len) {
+		err = airoha_snand_write_data(as_ctrl, data, addr_len,
+					      op->addr.buswidth);
 		if (err)
 			return err;
 	}
 
 	/* dummy */
-	data[0] = 0xff;
-	for (i = 0; i < op->dummy.nbytes; i++) {
-		err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],
-					      sizeof(data[0]));
+	data += addr_len;
+	if (dummy_len) {
+		err = airoha_snand_write_data(as_ctrl, data, dummy_len,
+					      op->dummy.buswidth);
 		if (err)
 			return err;
 	}
 
 	/* data */
-	if (op->data.dir == SPI_MEM_DATA_IN) {
-		err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
-					     op->data.nbytes);
-		if (err)
-			return err;
-	} else {
-		err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,
-					      op->data.nbytes);
+	if (op->data.nbytes) {
+		if (op->data.dir == SPI_MEM_DATA_IN)
+			err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
+						     op->data.nbytes,
+						     op->data.buswidth);
+		else
+			err = airoha_snand_write_data(as_ctrl, op->data.buf.out,
+						      op->data.nbytes,
+						      op->data.buswidth);
 		if (err)
 			return err;
 	}
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 04/14] spi: airoha: remove unnecessary switch to non-dma mode
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (2 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 03/14] spi: airoha: add support of dual/quad wires spi modes Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 05/14] spi: airoha: unify dirmap read/write code Mikhail Kshevetskiy
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

The code switches to dma at the start of dirmap operation and returns
to non-dma at the end of dirmap operation, so an additional switch to
non-dma at the start of dirmap write is not required.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 7aab3506834a..7f33131fb6ee 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -810,9 +810,6 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
-	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
-	if (err < 0)
-		return err;
 
 	memcpy(txrx_buf + offs, buf, len);
 	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 05/14] spi: airoha: unify dirmap read/write code
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (3 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 04/14] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 06/14] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

Makes dirmap writing looks similar to dirmap reading. Just a minor
refactoring, no behavior change is expected.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 49 ++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 7f33131fb6ee..cd0fd5c2bc98 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -670,6 +670,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	u32 val, rd_mode;
 	int err;
 
+	as_ctrl = spi_controller_get_devdata(spi->controller);
+
 	switch (op->cmd.opcode) {
 	case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
 		rd_mode = 1;
@@ -682,7 +684,6 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 		break;
 	}
 
-	as_ctrl = spi_controller_get_devdata(spi->controller);
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
 	if (err < 0)
 		return err;
@@ -745,7 +746,7 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* trigger dma start read */
+	/* trigger dma reading */
 	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
 				SPI_NFI_RD_TRIG);
 	if (err)
@@ -801,37 +802,47 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 					 u64 offs, size_t len, const void *buf)
 {
-	struct spi_mem_op *op = &desc->info.op_tmpl;
 	struct spi_device *spi = desc->mem->spi;
 	u8 *txrx_buf = spi_get_ctldata(spi);
 	struct airoha_snand_ctrl *as_ctrl;
 	dma_addr_t dma_addr;
-	u32 wr_mode, val;
+	u32 wr_mode, val, opcode;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
+	opcode = desc->info.op_tmpl.cmd.opcode;
+	switch (opcode) {
+	case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
+	case SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE:
+		wr_mode = 0;
+		break;
+	case SPI_NAND_OP_PROGRAM_LOAD_QUAD:
+	case SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD:
+		wr_mode = 2;
+		break;
+	default:
+		/* unknown opcode */
+		return -EOPNOTSUPP;
+	}
+
 	memcpy(txrx_buf + offs, buf, len);
-	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
-				  DMA_TO_DEVICE);
-	err = dma_mapping_error(as_ctrl->dev, dma_addr);
-	if (err)
-		return err;
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
 	if (err < 0)
-		goto error_dma_unmap;
+		return err;
 
 	err = airoha_snand_nfi_config(as_ctrl);
 	if (err)
-		goto error_dma_unmap;
+		return err;
 
-	if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD ||
-	    op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD)
-		wr_mode = BIT(1);
-	else
-		wr_mode = 0;
+	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
+				  DMA_TO_DEVICE);
+	err = dma_mapping_error(as_ctrl->dev, dma_addr);
+	if (err)
+		return err;
 
+	/* set dma addr */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
 			   dma_addr);
 	if (err)
@@ -845,12 +856,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
+	/* set write command */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1,
-			   FIELD_PREP(SPI_NFI_PG_LOAD_CMD,
-				      op->cmd.opcode));
+			   FIELD_PREP(SPI_NFI_PG_LOAD_CMD, opcode));
 	if (err)
 		goto error_dma_unmap;
 
+	/* set write mode */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
 			   FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode));
 	if (err)
@@ -880,6 +892,7 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
+	/* trigger dma writing */
 	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
 				SPI_NFI_WR_TRIG);
 	if (err)
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 06/14] spi: airoha: switch back to non-dma mode in the case of error
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (4 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 05/14] spi: airoha: unify dirmap read/write code Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 07/14] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

Current dirmap code does not switch back to non-dma mode in the case of
error. This is wrong.

This patch fixes dirmap read/write error path.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index cd0fd5c2bc98..3f15c26a467d 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -690,13 +690,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 
 	err = airoha_snand_nfi_config(as_ctrl);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
 				  DMA_FROM_DEVICE);
 	err = dma_mapping_error(as_ctrl->dev, dma_addr);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	/* set dma addr */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
@@ -796,6 +796,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 error_dma_unmap:
 	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
 			 DMA_FROM_DEVICE);
+error_dma_mode_off:
+	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	return err;
 }
 
@@ -834,13 +836,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 
 	err = airoha_snand_nfi_config(as_ctrl);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
 				  DMA_TO_DEVICE);
 	err = dma_mapping_error(as_ctrl->dev, dma_addr);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	/* set dma addr */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
@@ -937,6 +939,8 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 error_dma_unmap:
 	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
 			 DMA_TO_DEVICE);
+error_dma_mode_off:
+	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	return err;
 }
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 07/14] spi: airoha: fix reading/writing of flashes with more than one plane per lun
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (5 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 06/14] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 08/14] spi: airoha: support of dualio/quadio flash reading commands Mikhail Kshevetskiy
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

Reading UBI on the flash with more than one plane per lun will lead to
the following error:

ubi0: default fastmap WL pool size: 50
ubi0: attaching mtd2
ubi0 error: ubi_add_to_av: two LEBs with same sequence number 403
eraseblock attaching information dump:
        ec       1
        pnum     538
        lnum     0
        scrub    0
        sqnum    403
Volume identifier header dump:
        magic     55424921
        version   1
        vol_type  1
        copy_flag 0
        compat    0
        vol_id    1
        lnum      0
        data_size 0
        used_ebs  0
        data_pad  0
        sqnum     403
        hdr_crc   c8418a31
Volume identifier header hexdump:
00000000: 55 42 49 21 01 01 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  UBI!............................
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 93 00 00 00 00 00 00 00 00 00 00 00 00 c8 41 8a 31  .............................A.1
ubi0 error: ubi_attach_mtd_dev: failed to attach mtd2, error -22
UBI error: cannot attach mtd2
UBI error: cannot initialize UBI, error -22
UBI init error 22

looking to spi_mem_no_dirmap_read() code we'll see:

	static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
					      u64 offs, size_t len, void *buf)
	{
		struct spi_mem_op op = desc->info.op_tmpl;
		int ret;

// --- see here ---
		op.addr.val = desc->info.offset + offs;
//-----------------
		op.data.buf.in = buf;
		op.data.nbytes = len;
		ret = spi_mem_adjust_op_size(desc->mem, &op);
		if (ret)
		return ret;

		ret = spi_mem_exec_op(desc->mem, &op);
		if (ret)
			return ret;

		return op.data.nbytes;
	}

The similar happens for spi_mem_no_dirmap_write(). Thus spi read address should
take in the account the desc->info.offset.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 3f15c26a467d..7e1381c8f44b 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -725,8 +725,9 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* set read addr */
-	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);
+	/* set read addr: zero page offset + descriptor read offset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3,
+			   desc->info.offset);
 	if (err)
 		goto error_dma_unmap;
 
@@ -870,7 +871,9 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);
+	/* set write addr: zero page offset + descriptor write offset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2,
+			   desc->info.offset);
 	if (err)
 		goto error_dma_unmap;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 08/14] spi: airoha: support of dualio/quadio flash reading commands
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (6 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 07/14] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 09/14] spi: airoha: allow reading/writing of oob area Mikhail Kshevetskiy
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

Airoha snfi spi controller supports acceleration of DUAL/QUAD
operations, but does not supports DUAL_IO/QUAD_IO operations.
Luckily DUAL/QUAD operations do the same as DUAL_IO/QUAD_IO ones,
so we can issue corresponding DUAL/QUAD operation instead of
DUAL_IO/QUAD_IO one.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 7e1381c8f44b..cbdfb9051dfd 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -147,6 +147,8 @@
 #define SPI_NFI_CUS_SEC_SIZE_EN			BIT(16)
 
 #define REG_SPI_NFI_RD_CTL2			0x0510
+#define SPI_NFI_DATA_READ_CMD			GENMASK(7, 0)
+
 #define REG_SPI_NFI_RD_CTL3			0x0514
 
 #define REG_SPI_NFI_PG_CTL1			0x0524
@@ -179,7 +181,9 @@
 #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE	0x03
 #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST	0x0b
 #define SPI_NAND_OP_READ_FROM_CACHE_DUAL	0x3b
+#define SPI_NAND_OP_READ_FROM_CACHE_DUALIO	0xbb
 #define SPI_NAND_OP_READ_FROM_CACHE_QUAD	0x6b
+#define SPI_NAND_OP_READ_FROM_CACHE_QUADIO	0xeb
 #define SPI_NAND_OP_WRITE_ENABLE		0x06
 #define SPI_NAND_OP_WRITE_DISABLE		0x04
 #define SPI_NAND_OP_PROGRAM_LOAD_SINGLE		0x02
@@ -662,26 +666,38 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
 static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 					u64 offs, size_t len, void *buf)
 {
-	struct spi_mem_op *op = &desc->info.op_tmpl;
 	struct spi_device *spi = desc->mem->spi;
 	struct airoha_snand_ctrl *as_ctrl;
 	u8 *txrx_buf = spi_get_ctldata(spi);
 	dma_addr_t dma_addr;
-	u32 val, rd_mode;
+	u32 val, rd_mode, opcode;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
-	switch (op->cmd.opcode) {
+	/*
+	 * DUALIO and QUADIO opcodes are not supported by the spi controller,
+	 * replace them with supported opcodes.
+	 */
+	opcode = desc->info.op_tmpl.cmd.opcode;
+	switch (opcode) {
+	case SPI_NAND_OP_READ_FROM_CACHE_SINGLE:
+	case SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST:
+		rd_mode = 0;
+		break;
 	case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
+	case SPI_NAND_OP_READ_FROM_CACHE_DUALIO:
+		opcode = SPI_NAND_OP_READ_FROM_CACHE_DUAL;
 		rd_mode = 1;
 		break;
 	case SPI_NAND_OP_READ_FROM_CACHE_QUAD:
+	case SPI_NAND_OP_READ_FROM_CACHE_QUADIO:
+		opcode = SPI_NAND_OP_READ_FROM_CACHE_QUAD;
 		rd_mode = 2;
 		break;
 	default:
-		rd_mode = 0;
-		break;
+		/* unknown opcode */
+		return -EOPNOTSUPP;
 	}
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
@@ -715,7 +731,7 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 
 	/* set read command */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2,
-			   op->cmd.opcode);
+			   FIELD_PREP(SPI_NFI_DATA_READ_CMD, opcode));
 	if (err)
 		goto error_dma_unmap;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 09/14] spi: airoha: allow reading/writing of oob area
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (7 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 08/14] spi: airoha: support of dualio/quadio flash reading commands Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 10/14] spi: airoha: buffer must be 0xff-ed before writing Mikhail Kshevetskiy
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

Current code does not support reading/writing of oob area. Thus raw
reading/writing and bad block support is broken.

This patch fix custom sector size, so oob area will be included to
reading/writing operations.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index cbdfb9051dfd..c3348ef4fc08 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -568,7 +568,9 @@ static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
 		return err;
 
 	/* set cust sec size */
-	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, as_ctrl->nfi_cfg.sec_size);
+	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE,
+			 as_ctrl->nfi_cfg.sec_size +
+			 as_ctrl->nfi_cfg.spare_size);
 	return regmap_update_bits(as_ctrl->regmap_nfi,
 				  REG_SPI_NFI_SECCUS_SIZE,
 				  SPI_NFI_CUS_SEC_SIZE, val);
@@ -720,8 +722,9 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* set cust sec size */
-	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
+	/* number of bytes to read via dma (whole flash page + oob) */
+	val = (as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size) *
+	      as_ctrl->nfi_cfg.sec_num;
 	val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
@@ -867,8 +870,10 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM,
-			 as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
+	/* number of bytes to write via dma (whole flash page + oob) */
+	val = (as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size) *
+	      as_ctrl->nfi_cfg.sec_num;
+	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
 				 SPI_NFI_PROG_LOAD_BYTE_NUM, val);
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 10/14] spi: airoha: buffer must be 0xff-ed before writing
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (8 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 09/14] spi: airoha: allow reading/writing of oob area Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 11/14] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT Mikhail Kshevetskiy
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

During writing, the entire flash page (including OOB) will be updated
with the values from the temporary buffer, so we need to fill the
untouched areas of the buffer with 0xff value to prevent accidental
data overwriting.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index c3348ef4fc08..57eee658fb30 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -848,6 +848,9 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 		return -EOPNOTSUPP;
 	}
 
+	memset(txrx_buf, 0xff,
+	       (as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size) *
+	       as_ctrl->nfi_cfg.sec_num);
 	memcpy(txrx_buf + offs, buf, len);
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 11/14] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (9 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 10/14] spi: airoha: buffer must be 0xff-ed before writing Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 12/14] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers Mikhail Kshevetskiy
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

spi-airoha-snfi uses custom sector size in REG_SPI_NFI_SECCUS_SIZE
register, so setting of page/oob sizes in REG_SPI_NFI_PAGEFMT is not
required.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 38 -----------------------------------
 1 file changed, 38 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 57eee658fb30..5d8e1a233d98 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -516,44 +516,6 @@ static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
 	if (err)
 		return err;
 
-	/* page format */
-	switch (as_ctrl->nfi_cfg.spare_size) {
-	case 26:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x1);
-		break;
-	case 27:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x2);
-		break;
-	case 28:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x3);
-		break;
-	default:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x0);
-		break;
-	}
-
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,
-				 SPI_NFI_SPARE_SIZE, val);
-	if (err)
-		return err;
-
-	switch (as_ctrl->nfi_cfg.page_size) {
-	case 2048:
-		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x1);
-		break;
-	case 4096:
-		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x2);
-		break;
-	default:
-		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x0);
-		break;
-	}
-
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,
-				 SPI_NFI_PAGE_SIZE, val);
-	if (err)
-		return err;
-
 	/* sec num */
 	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 12/14] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (10 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 11/14] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 13/14] spi: airoha: set custom sector size equal to flash page size Mikhail Kshevetskiy
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

This just reduce the number of modification of REG_SPI_NFI_CNFG and
REG_SPI_NFI_SECCUS_SIZE registers during dirmap operation.

This patch is a necessary step to avoid reading flash page settings
from SNFI registers during driver startup.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 113 +++++++++++++++++++++++++---------
 1 file changed, 83 insertions(+), 30 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 5d8e1a233d98..10c4081d54cf 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -668,7 +668,47 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err < 0)
 		return err;
 
-	err = airoha_snand_nfi_config(as_ctrl);
+	/* NFI reset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
+	if (err)
+		goto error_dma_mode_off;
+
+	/* NFI configure:
+	 *   - No AutoFDM (custom sector size (SECCUS) register will be used)
+	 *   - No SoC's hardware ECC (flash internal ECC will be used)
+	 *   - Use burst mode (faster, but requires 16 byte alignment for addresses)
+	 *   - Setup for reading (SPI_NFI_READ_MODE)
+	 *   - Setup reading command: FIELD_PREP(SPI_NFI_OPMODE, 6)
+	 *   - Use DMA instead of PIO for data reading
+	 *   - Use AHB bus for DMA transfer
+	 */
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_READ_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 SPI_NFI_HW_ECC_EN |
+				 SPI_NFI_AUTO_FDM_EN |
+				 SPI_NFI_OPMODE,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_READ_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 FIELD_PREP(SPI_NFI_OPMODE, 6));
+
+	/* Set number of sector will be read */
+	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+				 SPI_NFI_SEC_NUM, val);
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set custom sector size */
+	val = as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size;
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
+				 SPI_NFI_CUS_SEC_SIZE |
+				 SPI_NFI_CUS_SEC_SIZE_EN,
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
 
@@ -712,18 +752,6 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* set nfi read */
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				 SPI_NFI_OPMODE,
-				 FIELD_PREP(SPI_NFI_OPMODE, 6));
-	if (err)
-		goto error_dma_unmap;
-
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-			      SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE);
-	if (err)
-		goto error_dma_unmap;
-
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0);
 	if (err)
 		goto error_dma_unmap;
@@ -819,7 +847,48 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err < 0)
 		return err;
 
-	err = airoha_snand_nfi_config(as_ctrl);
+	/* NFI reset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
+	if (err)
+		goto error_dma_mode_off;
+
+	/*
+	 * NFI configure:
+	 *   - No AutoFDM (custom sector size (SECCUS) register will be used)
+	 *   - No SoC's hardware ECC (flash internal ECC will be used)
+	 *   - Use burst mode (faster, but requires 16 byte alignment for addresses)
+	 *   - Setup for writing (SPI_NFI_READ_MODE bit is cleared)
+	 *   - Setup writing command: FIELD_PREP(SPI_NFI_OPMODE, 3)
+	 *   - Use DMA instead of PIO for data writing
+	 */
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_READ_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 SPI_NFI_HW_ECC_EN |
+				 SPI_NFI_AUTO_FDM_EN |
+				 SPI_NFI_OPMODE,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 FIELD_PREP(SPI_NFI_OPMODE, 3));
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set number of sector will be written */
+	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+				 SPI_NFI_SEC_NUM, val);
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set custom sector size */
+	val = as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size;
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
+				 SPI_NFI_CUS_SEC_SIZE |
+				 SPI_NFI_CUS_SEC_SIZE_EN,
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
 
@@ -863,22 +932,6 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				SPI_NFI_READ_MODE);
-	if (err)
-		goto error_dma_unmap;
-
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				 SPI_NFI_OPMODE,
-				 FIELD_PREP(SPI_NFI_OPMODE, 3));
-	if (err)
-		goto error_dma_unmap;
-
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-			      SPI_NFI_DMA_MODE);
-	if (err)
-		goto error_dma_unmap;
-
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80);
 	if (err)
 		goto error_dma_unmap;
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 13/14] spi: airoha: set custom sector size equal to flash page size
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (11 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 12/14] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-20 12:33 ` [PATCH v3 14/14] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup Mikhail Kshevetskiy
  2025-08-21  6:58 ` [PATCH v3 00/14] spi: airoha: driver fixes & improvements Lorenzo Bianconi
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

Set custom sector size equal to flash page size including oob. Thus we
will always read a single sector. The maximum custom sector size is
8187, so all possible flash sector sizes are supported.

This patch is a necessary step to avoid reading flash page settings
from SNFI registers during driver startup.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 38 +++++++++++++++++------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 10c4081d54cf..a02dc6de5406 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -635,10 +635,14 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	u8 *txrx_buf = spi_get_ctldata(spi);
 	dma_addr_t dma_addr;
 	u32 val, rd_mode, opcode;
+	size_t bytes;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
+	bytes = as_ctrl->nfi_cfg.sec_num *
+		(as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size);
+
 	/*
 	 * DUALIO and QUADIO opcodes are not supported by the spi controller,
 	 * replace them with supported opcodes.
@@ -696,18 +700,17 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 				 FIELD_PREP(SPI_NFI_OPMODE, 6));
 
 	/* Set number of sector will be read */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-				 SPI_NFI_SEC_NUM, val);
+				 SPI_NFI_SEC_NUM,
+				 FIELD_PREP(SPI_NFI_SEC_NUM, 1));
 	if (err)
 		goto error_dma_mode_off;
 
 	/* Set custom sector size */
-	val = as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size;
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
 				 SPI_NFI_CUS_SEC_SIZE |
 				 SPI_NFI_CUS_SEC_SIZE_EN,
-				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) |
 				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
@@ -725,12 +728,10 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 		goto error_dma_unmap;
 
 	/* number of bytes to read via dma (whole flash page + oob) */
-	val = (as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size) *
-	      as_ctrl->nfi_cfg.sec_num;
-	val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
-				 SPI_NFI_READ_DATA_BYTE_NUM, val);
+				 SPI_NFI_READ_DATA_BYTE_NUM,
+				 FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, bytes));
 	if (err)
 		goto error_dma_unmap;
 
@@ -819,10 +820,14 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	struct airoha_snand_ctrl *as_ctrl;
 	dma_addr_t dma_addr;
 	u32 wr_mode, val, opcode;
+	size_t bytes;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
+	bytes = as_ctrl->nfi_cfg.sec_num *
+		(as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size);
+
 	opcode = desc->info.op_tmpl.cmd.opcode;
 	switch (opcode) {
 	case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
@@ -838,9 +843,7 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 		return -EOPNOTSUPP;
 	}
 
-	memset(txrx_buf, 0xff,
-	       (as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size) *
-	       as_ctrl->nfi_cfg.sec_num);
+	memset(txrx_buf, 0xff, bytes);
 	memcpy(txrx_buf + offs, buf, len);
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
@@ -876,18 +879,17 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 		goto error_dma_mode_off;
 
 	/* Set number of sector will be written */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-				 SPI_NFI_SEC_NUM, val);
+				 SPI_NFI_SEC_NUM,
+				 FIELD_PREP(SPI_NFI_SEC_NUM, 1));
 	if (err)
 		goto error_dma_mode_off;
 
 	/* Set custom sector size */
-	val = as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size;
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
 				 SPI_NFI_CUS_SEC_SIZE |
 				 SPI_NFI_CUS_SEC_SIZE_EN,
-				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) |
 				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
@@ -905,12 +907,10 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 		goto error_dma_unmap;
 
 	/* number of bytes to write via dma (whole flash page + oob) */
-	val = (as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size) *
-	      as_ctrl->nfi_cfg.sec_num;
-	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
-				 SPI_NFI_PROG_LOAD_BYTE_NUM, val);
+				 SPI_NFI_PROG_LOAD_BYTE_NUM,
+				 FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, bytes));
 	if (err)
 		goto error_dma_unmap;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v3 14/14] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (12 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 13/14] spi: airoha: set custom sector size equal to flash page size Mikhail Kshevetskiy
@ 2025-08-20 12:33 ` Mikhail Kshevetskiy
  2025-08-21  6:58 ` [PATCH v3 00/14] spi: airoha: driver fixes & improvements Lorenzo Bianconi
  14 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf
  Cc: Mikhail Kshevetskiy

The spinand driver do 3 type of dirmap requests:
 * read/write whole flash page without oob
   (offs = 0, len = page_size)
 * read/write whole flash page including oob
   (offs = 0, len = page_size + oob_size)
 * read/write oob area only
   (offs = page_size, len = oob_size)

The trick is:
 * read/write a single "sector"
 * set a custom sector size equal to offs + len. It's a bit safer to
   rounded up "sector size" value 64.
 * set the transfer length equal to custom sector size

And it works!

Thus we can remove a dirty hack that reads flash page settings from
SNFI registers during driver startup. Also airoha_snand_adjust_op_size()
function becomes unnecessary.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 136 ++++++----------------------------
 1 file changed, 21 insertions(+), 115 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index a02dc6de5406..4974608423b7 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -223,13 +223,6 @@ struct airoha_snand_ctrl {
 	struct regmap *regmap_ctrl;
 	struct regmap *regmap_nfi;
 	struct clk *spi_clk;
-
-	struct {
-		size_t page_size;
-		size_t sec_size;
-		u8 sec_num;
-		u8 spare_size;
-	} nfi_cfg;
 };
 
 static int airoha_snand_set_fifo_op(struct airoha_snand_ctrl *as_ctrl,
@@ -488,56 +481,6 @@ static int airoha_snand_nfi_init(struct airoha_snand_ctrl *as_ctrl)
 				  SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN);
 }
 
-static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
-{
-	int err;
-	u32 val;
-
-	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
-	if (err)
-		return err;
-
-	/* auto FDM */
-	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				SPI_NFI_AUTO_FDM_EN);
-	if (err)
-		return err;
-
-	/* HW ECC */
-	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				SPI_NFI_HW_ECC_EN);
-	if (err)
-		return err;
-
-	/* DMA Burst */
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-			      SPI_NFI_DMA_BURST_EN);
-	if (err)
-		return err;
-
-	/* sec num */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-				 SPI_NFI_SEC_NUM, val);
-	if (err)
-		return err;
-
-	/* enable cust sec size */
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
-			      SPI_NFI_CUS_SEC_SIZE_EN);
-	if (err)
-		return err;
-
-	/* set cust sec size */
-	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE,
-			 as_ctrl->nfi_cfg.sec_size +
-			 as_ctrl->nfi_cfg.spare_size);
-	return regmap_update_bits(as_ctrl->regmap_nfi,
-				  REG_SPI_NFI_SECCUS_SIZE,
-				  SPI_NFI_CUS_SEC_SIZE, val);
-}
-
 static bool airoha_snand_is_page_ops(const struct spi_mem_op *op)
 {
 	if (op->addr.nbytes != 2)
@@ -570,26 +513,6 @@ static bool airoha_snand_is_page_ops(const struct spi_mem_op *op)
 	}
 }
 
-static int airoha_snand_adjust_op_size(struct spi_mem *mem,
-				       struct spi_mem_op *op)
-{
-	size_t max_len;
-
-	if (airoha_snand_is_page_ops(op)) {
-		struct airoha_snand_ctrl *as_ctrl;
-
-		as_ctrl = spi_controller_get_devdata(mem->spi->controller);
-		max_len = as_ctrl->nfi_cfg.sec_size;
-		max_len += as_ctrl->nfi_cfg.spare_size;
-		max_len *= as_ctrl->nfi_cfg.sec_num;
-
-		if (op->data.nbytes > max_len)
-			op->data.nbytes = max_len;
-	}
-
-	return 0;
-}
-
 static bool airoha_snand_supports_op(struct spi_mem *mem,
 				     const struct spi_mem_op *op)
 {
@@ -640,8 +563,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
-	bytes = as_ctrl->nfi_cfg.sec_num *
-		(as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size);
+	/* minimum oob size is 64 */
+	bytes = round_up(offs + len, 64);
 
 	/*
 	 * DUALIO and QUADIO opcodes are not supported by the spi controller,
@@ -727,7 +650,14 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* number of bytes to read via dma (whole flash page + oob) */
+	/*
+	 * Setup transfer length
+	 * ---------------------
+	 * The following rule MUST be met:
+	 *     transfer_length =
+	 *        = NFI_SNF_MISC_CTL2.read_data_byte_number =
+	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+	 */
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
 				 SPI_NFI_READ_DATA_BYTE_NUM,
@@ -825,8 +755,8 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
-	bytes = as_ctrl->nfi_cfg.sec_num *
-		(as_ctrl->nfi_cfg.sec_size + as_ctrl->nfi_cfg.spare_size);
+	/* minimum oob size is 64 */
+	bytes = round_up(offs + len, 64);
 
 	opcode = desc->info.op_tmpl.cmd.opcode;
 	switch (opcode) {
@@ -906,7 +836,14 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* number of bytes to write via dma (whole flash page + oob) */
+	/*
+	 * Setup transfer length
+	 * ---------------------
+	 * The following rule MUST be met:
+	 *     transfer_length =
+	 *        = NFI_SNF_MISC_CTL2.write_data_byte_number =
+	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+	 */
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
 				 SPI_NFI_PROG_LOAD_BYTE_NUM,
@@ -1062,7 +999,6 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
 }
 
 static const struct spi_controller_mem_ops airoha_snand_mem_ops = {
-	.adjust_op_size = airoha_snand_adjust_op_size,
 	.supports_op = airoha_snand_supports_op,
 	.exec_op = airoha_snand_exec_op,
 	.dirmap_create = airoha_snand_dirmap_create,
@@ -1087,36 +1023,6 @@ static int airoha_snand_setup(struct spi_device *spi)
 	return 0;
 }
 
-static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl)
-{
-	u32 val, sec_size, sec_num;
-	int err;
-
-	err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, &val);
-	if (err)
-		return err;
-
-	sec_num = FIELD_GET(SPI_NFI_SEC_NUM, val);
-
-	err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, &val);
-	if (err)
-		return err;
-
-	sec_size = FIELD_GET(SPI_NFI_CUS_SEC_SIZE, val);
-
-	/* init default value */
-	as_ctrl->nfi_cfg.sec_size = sec_size;
-	as_ctrl->nfi_cfg.sec_num = sec_num;
-	as_ctrl->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024);
-	as_ctrl->nfi_cfg.spare_size = 16;
-
-	err = airoha_snand_nfi_init(as_ctrl);
-	if (err)
-		return err;
-
-	return airoha_snand_nfi_config(as_ctrl);
-}
-
 static const struct regmap_config spi_ctrl_regmap_config = {
 	.name		= "ctrl",
 	.reg_bits	= 32,
@@ -1190,7 +1096,7 @@ static int airoha_snand_probe(struct platform_device *pdev)
 	ctrl->setup = airoha_snand_setup;
 	device_set_node(&ctrl->dev, dev_fwnode(dev));
 
-	err = airoha_snand_nfi_setup(as_ctrl);
+	err = airoha_snand_nfi_init(as_ctrl);
 	if (err)
 		return err;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 03/14] spi: airoha: add support of dual/quad wires spi modes
  2025-08-20 12:33 ` [PATCH v3 03/14] spi: airoha: add support of dual/quad wires spi modes Mikhail Kshevetskiy
@ 2025-08-20 12:48   ` Jyothi Kumar Seerapu
  0 siblings, 0 replies; 65+ messages in thread
From: Jyothi Kumar Seerapu @ 2025-08-20 12:48 UTC (permalink / raw)
  To: Mikhail Kshevetskiy, Lorenzo Bianconi, Ray Liu, Mark Brown,
	linux-arm-kernel, linux-spi, linux-kernel, Frieder Schrempf



On 8/20/2025 6:03 PM, Mikhail Kshevetskiy wrote:
> This patch adds support of dual and quad wires spi modes. It will
> speed up flash operations on the hardware with corresponding hardware
> support.
> 
> Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
> ---
>   drivers/spi/spi-airoha-snfi.c | 107 +++++++++++++++++++++++++---------
>   1 file changed, 80 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
> index bcc464ec9c61..7aab3506834a 100644
> --- a/drivers/spi/spi-airoha-snfi.c
> +++ b/drivers/spi/spi-airoha-snfi.c
> @@ -192,6 +192,14 @@
>   #define SPI_NAND_OP_RESET			0xff
>   #define SPI_NAND_OP_DIE_SELECT			0xc2
>   
> +/* SNAND FIFO commands */
> +#define SNAND_FIFO_TX_BUSWIDTH_SINGLE		0x08
> +#define SNAND_FIFO_TX_BUSWIDTH_DUAL		0x09
> +#define SNAND_FIFO_TX_BUSWIDTH_QUAD		0x0a
> +#define SNAND_FIFO_RX_BUSWIDTH_SINGLE		0x0c
> +#define SNAND_FIFO_RX_BUSWIDTH_DUAL		0x0e
> +#define SNAND_FIFO_RX_BUSWIDTH_QUAD		0x0f
> +
>   #define SPI_NAND_CACHE_SIZE			(SZ_4K + SZ_256)
>   #define SPI_MAX_TRANSFER_SIZE			511
>   
> @@ -387,10 +395,25 @@ static int airoha_snand_set_mode(struct airoha_snand_ctrl *as_ctrl,
>   	return regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0);
>   }
>   
> -static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
> -				   const u8 *data, int len)
> +static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl,
> +				   const u8 *data, int len, int buswidth)
>   {
>   	int i, data_len;
> +	u8 cmd;
> +
> +	switch (buswidth) {
> +	case 1:
> +		cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE;
> +		break;
> +	case 2:
> +		cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL;
> +		break;
> +	case 4:
> +		cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
>   
>   	for (i = 0; i < len; i += data_len) {
>   		int err;
> @@ -409,16 +432,31 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
>   	return 0;
>   }
>   
> -static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
> -				  int len)
> +static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl,
> +				  u8 *data, int len, int buswidth)
>   {
>   	int i, data_len;
> +	u8 cmd;
> +
> +	switch (buswidth) {
> +	case 1:
> +		cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE;
> +		break;
> +	case 2:
> +		cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL;
> +		break;
> +	case 4:
> +		cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD;
> +		break;
> +	default:
> +		return -EINVAL;
For unknown buswidth cases, not falling back to single lane?
What if the bus width is 0 ? (for SPI, typically default 
SPI_NBITS_SINGLE is used for buswidth 0).> +	}
>   
>   	for (i = 0; i < len; i += data_len) {
>   		int err;
>   
>   		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
> -		err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
> +		err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
>   		if (err)
>   			return err;
>   
> @@ -895,12 +933,27 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
>   static int airoha_snand_exec_op(struct spi_mem *mem,
>   				const struct spi_mem_op *op)
>   {
> -	u8 data[8], cmd, opcode = op->cmd.opcode;
>   	struct airoha_snand_ctrl *as_ctrl;
> -	int i, err;
> +	char buf[20], *data;
> +	int i, err, op_len, addr_len, dummy_len;
>   
>   	as_ctrl = spi_controller_get_devdata(mem->spi->controller);
>   
> +	op_len = op->cmd.nbytes;
> +	addr_len = op->addr.nbytes;
> +	dummy_len = op->dummy.nbytes;
> +
> +	if (op_len + dummy_len + addr_len > sizeof(buf))
> +		return -EIO;
> +
> +	data = buf;
> +	for (i = 0; i < op_len; i++)
> +		*data++ = op->cmd.opcode >> (8 * (op_len - i - 1));
> +	for (i = 0; i < addr_len; i++)
> +		*data++ = op->addr.val >> (8 * (addr_len - i - 1));
> +	for (i = 0; i < dummy_len; i++)
> +		*data++ = 0xff;
> +
>   	/* switch to manual mode */
>   	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
>   	if (err < 0)
> @@ -911,40 +964,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
>   		return err;
>   
>   	/* opcode */
> -	err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));
> +	data = buf;
> +	err = airoha_snand_write_data(as_ctrl, data, op_len,
> +				      op->cmd.buswidth);
>   	if (err)
>   		return err;
>   
>   	/* addr part */
> -	cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
> -	put_unaligned_be64(op->addr.val, data);
> -
> -	for (i = ARRAY_SIZE(data) - op->addr.nbytes;
> -	     i < ARRAY_SIZE(data); i++) {
> -		err = airoha_snand_write_data(as_ctrl, cmd, &data[i],
> -					      sizeof(data[0]));
> +	data += op_len;
> +	if (addr_len) {
> +		err = airoha_snand_write_data(as_ctrl, data, addr_len,
> +					      op->addr.buswidth);
>   		if (err)
>   			return err;
>   	}
>   
>   	/* dummy */
> -	data[0] = 0xff;
> -	for (i = 0; i < op->dummy.nbytes; i++) {
> -		err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],
> -					      sizeof(data[0]));
> +	data += addr_len;
> +	if (dummy_len) {
> +		err = airoha_snand_write_data(as_ctrl, data, dummy_len,
> +					      op->dummy.buswidth);
>   		if (err)
>   			return err;
>   	}
>   
>   	/* data */
> -	if (op->data.dir == SPI_MEM_DATA_IN) {
> -		err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
> -					     op->data.nbytes);
> -		if (err)
> -			return err;
> -	} else {
> -		err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,
> -					      op->data.nbytes);
> +	if (op->data.nbytes) {
> +		if (op->data.dir == SPI_MEM_DATA_IN)
> +			err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
> +						     op->data.nbytes,
> +						     op->data.buswidth);
> +		else
> +			err = airoha_snand_write_data(as_ctrl, op->data.buf.out,
> +						      op->data.nbytes,
> +						      op->data.buswidth);
>   		if (err)
>   			return err;
>   	}



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                   ` (13 preceding siblings ...)
  2025-08-20 12:33 ` [PATCH v3 14/14] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup Mikhail Kshevetskiy
@ 2025-08-21  6:58 ` Lorenzo Bianconi
  2025-08-21 11:13   ` Mikhail Kshevetskiy
  14 siblings, 1 reply; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-21  6:58 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf

[-- Attachment #1: Type: text/plain, Size: 2451 bytes --]

> This patch series greatly improve airoha snfi driver and fix a
> number of serious bug.
> 
> Fixed bugs:
>  * Fix reading/writing of flashes with more than one plane per lun
>  * Fix inability to read/write oob area
>  * Fill the buffer with 0xff before writing
>  * Fix reading of flashes supporting continuous reading mode
>  * Fix error paths
> 
> Improvements:
>  * Add support of dual/quad wires spi modes in exec_op().
>  * Support of dualio/quadio flash reading commands
>  * Remove dirty hack that reads flash page settings from SNFI registers
>    during driver startup
> 
> Unfortunately I am unable to test the driver with linux at the moment,
> so only the following testing was done:

It seems to me this is quite an important rework of the driver. I would prefer
to have some test results for this series. Are you able to run mtd_test kernel
module for testing?

Regards,
Lorenzo

>  * Driver compiles without error.
>  * All changes were tested with corresponding u-boot driver. U-Boot
>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
>    additional fixes for continuous mode.
> 
> Changes v2:
>  * minor fix
>  * add comments to code
> 
> Changes v3:
>  * add patch to prevent continuous reading
> 
> Mikhail Kshevetskiy (14):
>   spi: airoha: return an error for continuous mode dirmap creation cases
>   spi: airoha: remove unnecessary restriction length
>   spi: airoha: add support of dual/quad wires spi modes
>   spi: airoha: remove unnecessary switch to non-dma mode
>   spi: airoha: unify dirmap read/write code
>   spi: airoha: switch back to non-dma mode in the case of error
>   spi: airoha: fix reading/writing of flashes with more than one plane
>     per lun
>   spi: airoha: support of dualio/quadio flash reading commands
>   spi: airoha: allow reading/writing of oob area
>   spi: airoha: buffer must be 0xff-ed before writing
>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
>     REG_SPI_NFI_SECCUS_SIZE registers
>   spi: airoha: set custom sector size equal to flash page size
>   spi: airoha: avoid reading flash page settings from SNFI registers
>     during driver startup
> 
>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
>  1 file changed, 260 insertions(+), 248 deletions(-)
> 
> -- 
> 2.50.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-21  6:58 ` [PATCH v3 00/14] spi: airoha: driver fixes & improvements Lorenzo Bianconi
@ 2025-08-21 11:13   ` Mikhail Kshevetskiy
  2025-08-21 11:34     ` Lorenzo Bianconi
  0 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-21 11:13 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf


On 21.08.2025 09:58, Lorenzo Bianconi wrote:
>> This patch series greatly improve airoha snfi driver and fix a
>> number of serious bug.
>>
>> Fixed bugs:
>>  * Fix reading/writing of flashes with more than one plane per lun
>>  * Fix inability to read/write oob area
>>  * Fill the buffer with 0xff before writing
>>  * Fix reading of flashes supporting continuous reading mode
>>  * Fix error paths
>>
>> Improvements:
>>  * Add support of dual/quad wires spi modes in exec_op().
>>  * Support of dualio/quadio flash reading commands
>>  * Remove dirty hack that reads flash page settings from SNFI registers
>>    during driver startup
>>
>> Unfortunately I am unable to test the driver with linux at the moment,
>> so only the following testing was done:
> It seems to me this is quite an important rework of the driver. I would prefer
> to have some test results for this series. Are you able to run mtd_test kernel
> module for testing?

I'll try to build latest openwrt with this patches  and mtd_test kernel
module and try it on one of our boards.

Actually patches can be divided on to parts:
* fixes of current driver (patches 1-10)
* change of behavior to avoid reading flash page settings from SNFI
registers during driver startup (patches 11-14)

The changes are based on the code we are using for more than 3 years. I
adapt it to latest linux/u-boot code.

Up to now the only known issue appears on en7523 chips only. Here a
corresponding patch description (not added to this series)
====================================================== spi: airoha:
en7523: workaround flash damaging if UART_TXD was short to GND We found
that some serial console may pull TX line to GROUND during board boot
time. Airoha uses TX line as one of it's BOOT pins. This will lead to
booting in RESERVED boot mode. It was found that some flashes operates
incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
affected by the issue, Winbond flashes are NOT affected. Details:
-------- DMA reading of odd pages on affected flashes operates
incorrectly. Page reading offset (start of the page) on hardware level
is replaced by 0x10. Thus results in incorrect data reading. Usage of
UBI make things even worse. Any attempt to access UBI leads to ubi
damaging. As result OS loading becomes impossible. Non-DMA reading is
OK. =======================================================

Regards,
Mikhail


>
> Regards,
> Lorenzo
>
>>  * Driver compiles without error.
>>  * All changes were tested with corresponding u-boot driver. U-Boot
>>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
>>    additional fixes for continuous mode.
>>
>> Changes v2:
>>  * minor fix
>>  * add comments to code
>>
>> Changes v3:
>>  * add patch to prevent continuous reading
>>
>> Mikhail Kshevetskiy (14):
>>   spi: airoha: return an error for continuous mode dirmap creation cases
>>   spi: airoha: remove unnecessary restriction length
>>   spi: airoha: add support of dual/quad wires spi modes
>>   spi: airoha: remove unnecessary switch to non-dma mode
>>   spi: airoha: unify dirmap read/write code
>>   spi: airoha: switch back to non-dma mode in the case of error
>>   spi: airoha: fix reading/writing of flashes with more than one plane
>>     per lun
>>   spi: airoha: support of dualio/quadio flash reading commands
>>   spi: airoha: allow reading/writing of oob area
>>   spi: airoha: buffer must be 0xff-ed before writing
>>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
>>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
>>     REG_SPI_NFI_SECCUS_SIZE registers
>>   spi: airoha: set custom sector size equal to flash page size
>>   spi: airoha: avoid reading flash page settings from SNFI registers
>>     during driver startup
>>
>>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
>>  1 file changed, 260 insertions(+), 248 deletions(-)
>>
>> -- 
>> 2.50.1
>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-21 11:13   ` Mikhail Kshevetskiy
@ 2025-08-21 11:34     ` Lorenzo Bianconi
  2025-08-21 12:24       ` Mikhail Kshevetskiy
  2025-08-22  3:31       ` Mikhail Kshevetskiy
  0 siblings, 2 replies; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-21 11:34 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf

[-- Attachment #1: Type: text/plain, Size: 4462 bytes --]

> 
> On 21.08.2025 09:58, Lorenzo Bianconi wrote:
> >> This patch series greatly improve airoha snfi driver and fix a
> >> number of serious bug.
> >>
> >> Fixed bugs:
> >>  * Fix reading/writing of flashes with more than one plane per lun
> >>  * Fix inability to read/write oob area
> >>  * Fill the buffer with 0xff before writing
> >>  * Fix reading of flashes supporting continuous reading mode
> >>  * Fix error paths
> >>
> >> Improvements:
> >>  * Add support of dual/quad wires spi modes in exec_op().
> >>  * Support of dualio/quadio flash reading commands
> >>  * Remove dirty hack that reads flash page settings from SNFI registers
> >>    during driver startup
> >>
> >> Unfortunately I am unable to test the driver with linux at the moment,
> >> so only the following testing was done:
> > It seems to me this is quite an important rework of the driver. I would prefer
> > to have some test results for this series. Are you able to run mtd_test kernel
> > module for testing?
> 
> I'll try to build latest openwrt with this patches  and mtd_test kernel
> module and try it on one of our boards.

what board are you using for testing? If it is based on Airoha-7581 you could
use the following repo for testing.

https://github.com/Ansuel/openwrt/tree/openwrt-24.10-airoha-an7581-stable

Regards,
Lorenzo

> 
> Actually patches can be divided on to parts:
> * fixes of current driver (patches 1-10)
> * change of behavior to avoid reading flash page settings from SNFI
> registers during driver startup (patches 11-14)
> 
> The changes are based on the code we are using for more than 3 years. I
> adapt it to latest linux/u-boot code.
> 
> Up to now the only known issue appears on en7523 chips only. Here a
> corresponding patch description (not added to this series)
> ====================================================== spi: airoha:
> en7523: workaround flash damaging if UART_TXD was short to GND We found
> that some serial console may pull TX line to GROUND during board boot
> time. Airoha uses TX line as one of it's BOOT pins. This will lead to
> booting in RESERVED boot mode. It was found that some flashes operates
> incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
> affected by the issue, Winbond flashes are NOT affected. Details:
> -------- DMA reading of odd pages on affected flashes operates
> incorrectly. Page reading offset (start of the page) on hardware level
> is replaced by 0x10. Thus results in incorrect data reading. Usage of
> UBI make things even worse. Any attempt to access UBI leads to ubi
> damaging. As result OS loading becomes impossible. Non-DMA reading is
> OK. =======================================================
> 
> Regards,
> Mikhail
> 
> 
> >
> > Regards,
> > Lorenzo
> >
> >>  * Driver compiles without error.
> >>  * All changes were tested with corresponding u-boot driver. U-Boot
> >>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
> >>    additional fixes for continuous mode.
> >>
> >> Changes v2:
> >>  * minor fix
> >>  * add comments to code
> >>
> >> Changes v3:
> >>  * add patch to prevent continuous reading
> >>
> >> Mikhail Kshevetskiy (14):
> >>   spi: airoha: return an error for continuous mode dirmap creation cases
> >>   spi: airoha: remove unnecessary restriction length
> >>   spi: airoha: add support of dual/quad wires spi modes
> >>   spi: airoha: remove unnecessary switch to non-dma mode
> >>   spi: airoha: unify dirmap read/write code
> >>   spi: airoha: switch back to non-dma mode in the case of error
> >>   spi: airoha: fix reading/writing of flashes with more than one plane
> >>     per lun
> >>   spi: airoha: support of dualio/quadio flash reading commands
> >>   spi: airoha: allow reading/writing of oob area
> >>   spi: airoha: buffer must be 0xff-ed before writing
> >>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
> >>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
> >>     REG_SPI_NFI_SECCUS_SIZE registers
> >>   spi: airoha: set custom sector size equal to flash page size
> >>   spi: airoha: avoid reading flash page settings from SNFI registers
> >>     during driver startup
> >>
> >>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
> >>  1 file changed, 260 insertions(+), 248 deletions(-)
> >>
> >> -- 
> >> 2.50.1
> >>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-21 11:34     ` Lorenzo Bianconi
@ 2025-08-21 12:24       ` Mikhail Kshevetskiy
  2025-08-22  3:31       ` Mikhail Kshevetskiy
  1 sibling, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-21 12:24 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf


On 21.08.2025 14:34, Lorenzo Bianconi wrote:
>> On 21.08.2025 09:58, Lorenzo Bianconi wrote:
>>>> This patch series greatly improve airoha snfi driver and fix a
>>>> number of serious bug.
>>>>
>>>> Fixed bugs:
>>>>  * Fix reading/writing of flashes with more than one plane per lun
>>>>  * Fix inability to read/write oob area
>>>>  * Fill the buffer with 0xff before writing
>>>>  * Fix reading of flashes supporting continuous reading mode
>>>>  * Fix error paths
>>>>
>>>> Improvements:
>>>>  * Add support of dual/quad wires spi modes in exec_op().
>>>>  * Support of dualio/quadio flash reading commands
>>>>  * Remove dirty hack that reads flash page settings from SNFI registers
>>>>    during driver startup
>>>>
>>>> Unfortunately I am unable to test the driver with linux at the moment,
>>>> so only the following testing was done:
>>> It seems to me this is quite an important rework of the driver. I would prefer
>>> to have some test results for this series. Are you able to run mtd_test kernel
>>> module for testing?
>> I'll try to build latest openwrt with this patches  and mtd_test kernel
>> module and try it on one of our boards.
> what board are you using for testing? If it is based on Airoha-7581 you could
> use the following repo for testing.
>
> https://github.com/Ansuel/openwrt/tree/openwrt-24.10-airoha-an7581-stable
>
> Regards,
> Lorenzo
>
yes, it's based on Airoha-7581

>> Actually patches can be divided on to parts:
>> * fixes of current driver (patches 1-10)
>> * change of behavior to avoid reading flash page settings from SNFI
>> registers during driver startup (patches 11-14)
>>
>> The changes are based on the code we are using for more than 3 years. I
>> adapt it to latest linux/u-boot code.
>>
>> Up to now the only known issue appears on en7523 chips only. Here a
>> corresponding patch description (not added to this series)
>> ====================================================== spi: airoha:
>> en7523: workaround flash damaging if UART_TXD was short to GND We found
>> that some serial console may pull TX line to GROUND during board boot
>> time. Airoha uses TX line as one of it's BOOT pins. This will lead to
>> booting in RESERVED boot mode. It was found that some flashes operates
>> incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
>> affected by the issue, Winbond flashes are NOT affected. Details:
>> -------- DMA reading of odd pages on affected flashes operates
>> incorrectly. Page reading offset (start of the page) on hardware level
>> is replaced by 0x10. Thus results in incorrect data reading. Usage of
>> UBI make things even worse. Any attempt to access UBI leads to ubi
>> damaging. As result OS loading becomes impossible. Non-DMA reading is
>> OK. =======================================================
>>
>> Regards,
>> Mikhail
>>
>>
>>> Regards,
>>> Lorenzo
>>>
>>>>  * Driver compiles without error.
>>>>  * All changes were tested with corresponding u-boot driver. U-Boot
>>>>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
>>>>    additional fixes for continuous mode.
>>>>
>>>> Changes v2:
>>>>  * minor fix
>>>>  * add comments to code
>>>>
>>>> Changes v3:
>>>>  * add patch to prevent continuous reading
>>>>
>>>> Mikhail Kshevetskiy (14):
>>>>   spi: airoha: return an error for continuous mode dirmap creation cases
>>>>   spi: airoha: remove unnecessary restriction length
>>>>   spi: airoha: add support of dual/quad wires spi modes
>>>>   spi: airoha: remove unnecessary switch to non-dma mode
>>>>   spi: airoha: unify dirmap read/write code
>>>>   spi: airoha: switch back to non-dma mode in the case of error
>>>>   spi: airoha: fix reading/writing of flashes with more than one plane
>>>>     per lun
>>>>   spi: airoha: support of dualio/quadio flash reading commands
>>>>   spi: airoha: allow reading/writing of oob area
>>>>   spi: airoha: buffer must be 0xff-ed before writing
>>>>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
>>>>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
>>>>     REG_SPI_NFI_SECCUS_SIZE registers
>>>>   spi: airoha: set custom sector size equal to flash page size
>>>>   spi: airoha: avoid reading flash page settings from SNFI registers
>>>>     during driver startup
>>>>
>>>>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
>>>>  1 file changed, 260 insertions(+), 248 deletions(-)
>>>>
>>>> -- 
>>>> 2.50.1
>>>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-21 11:34     ` Lorenzo Bianconi
  2025-08-21 12:24       ` Mikhail Kshevetskiy
@ 2025-08-22  3:31       ` Mikhail Kshevetskiy
  2025-08-22  6:46         ` Lorenzo Bianconi
  1 sibling, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-22  3:31 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf


On 21.08.2025 14:34, Lorenzo Bianconi wrote:
>> On 21.08.2025 09:58, Lorenzo Bianconi wrote:
>>>> This patch series greatly improve airoha snfi driver and fix a
>>>> number of serious bug.
>>>>
>>>> Fixed bugs:
>>>>  * Fix reading/writing of flashes with more than one plane per lun
>>>>  * Fix inability to read/write oob area
>>>>  * Fill the buffer with 0xff before writing
>>>>  * Fix reading of flashes supporting continuous reading mode
>>>>  * Fix error paths
>>>>
>>>> Improvements:
>>>>  * Add support of dual/quad wires spi modes in exec_op().
>>>>  * Support of dualio/quadio flash reading commands
>>>>  * Remove dirty hack that reads flash page settings from SNFI registers
>>>>    during driver startup
>>>>
>>>> Unfortunately I am unable to test the driver with linux at the moment,
>>>> so only the following testing was done:
>>> It seems to me this is quite an important rework of the driver. I would prefer
>>> to have some test results for this series. Are you able to run mtd_test kernel
>>> module for testing?
>> I'll try to build latest openwrt with this patches  and mtd_test kernel
>> module and try it on one of our boards.
> what board are you using for testing? If it is based on Airoha-7581 you could
> use the following repo for testing.
>
> https://github.com/Ansuel/openwrt/tree/openwrt-24.10-airoha-an7581-stable
>
> Regards,
> Lorenzo
What tests do you suggest to run?
I have a single flash I boot from. It have only 2 mtd partitions:

[    2.980849] spi-nand spi0.0: Micron SPI NAND was found.
[    2.986102] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
2048, OOB size: 128
[    2.994493] 2 fixed-partitions partitions found on MTD device spi0.0
[    3.000856] Creating 2 MTD partitions on "spi0.0":
[    3.005651] 0x000000000000-0x000000020000 : "bl2"
[    3.011247] 0x000000020000-0x000010000000 : "ubi"

Most of tests are destructive. So If I use "bl2" or "ubi" partition for
test, next time I will be unable to boot :-(
Do you suggest to patch u-boot & linux to have more mtd partitions?

This is the results of the only read-only test I found.

root@OpenWrt:/lib/modules/6.6.79# insmod mtd_test.ko
root@OpenWrt:/lib/modules/6.6.79# insmod mtd_readtest.ko dev=1
[  159.121706]
[  159.123220] =================================================
[  159.129053] mtd_readtest: MTD device: 1
[  159.132898] mtd_readtest: MTD device size 268304384, eraseblock size
131072, page size 2048, count of eraseblocks 2047, pages per eraseblock
64, OOB size 128
[  159.147008] mtd_test: scanning for bad eraseblocks
[  159.152141] mtd_test: scanned 2047 eraseblocks, 0 are bad
[  159.157549] mtd_readtest: testing page read

Mikhail

>> Actually patches can be divided on to parts:
>> * fixes of current driver (patches 1-10)
>> * change of behavior to avoid reading flash page settings from SNFI
>> registers during driver startup (patches 11-14)
>>
>> The changes are based on the code we are using for more than 3 years. I
>> adapt it to latest linux/u-boot code.
>>
>> Up to now the only known issue appears on en7523 chips only. Here a
>> corresponding patch description (not added to this series)
>> ====================================================== spi: airoha:
>> en7523: workaround flash damaging if UART_TXD was short to GND We found
>> that some serial console may pull TX line to GROUND during board boot
>> time. Airoha uses TX line as one of it's BOOT pins. This will lead to
>> booting in RESERVED boot mode. It was found that some flashes operates
>> incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
>> affected by the issue, Winbond flashes are NOT affected. Details:
>> -------- DMA reading of odd pages on affected flashes operates
>> incorrectly. Page reading offset (start of the page) on hardware level
>> is replaced by 0x10. Thus results in incorrect data reading. Usage of
>> UBI make things even worse. Any attempt to access UBI leads to ubi
>> damaging. As result OS loading becomes impossible. Non-DMA reading is
>> OK. =======================================================
>>
>> Regards,
>> Mikhail
>>
>>
>>> Regards,
>>> Lorenzo
>>>
>>>>  * Driver compiles without error.
>>>>  * All changes were tested with corresponding u-boot driver. U-Boot
>>>>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
>>>>    additional fixes for continuous mode.
>>>>
>>>> Changes v2:
>>>>  * minor fix
>>>>  * add comments to code
>>>>
>>>> Changes v3:
>>>>  * add patch to prevent continuous reading
>>>>
>>>> Mikhail Kshevetskiy (14):
>>>>   spi: airoha: return an error for continuous mode dirmap creation cases
>>>>   spi: airoha: remove unnecessary restriction length
>>>>   spi: airoha: add support of dual/quad wires spi modes
>>>>   spi: airoha: remove unnecessary switch to non-dma mode
>>>>   spi: airoha: unify dirmap read/write code
>>>>   spi: airoha: switch back to non-dma mode in the case of error
>>>>   spi: airoha: fix reading/writing of flashes with more than one plane
>>>>     per lun
>>>>   spi: airoha: support of dualio/quadio flash reading commands
>>>>   spi: airoha: allow reading/writing of oob area
>>>>   spi: airoha: buffer must be 0xff-ed before writing
>>>>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
>>>>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
>>>>     REG_SPI_NFI_SECCUS_SIZE registers
>>>>   spi: airoha: set custom sector size equal to flash page size
>>>>   spi: airoha: avoid reading flash page settings from SNFI registers
>>>>     during driver startup
>>>>
>>>>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
>>>>  1 file changed, 260 insertions(+), 248 deletions(-)
>>>>
>>>> -- 
>>>> 2.50.1
>>>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-22  3:31       ` Mikhail Kshevetskiy
@ 2025-08-22  6:46         ` Lorenzo Bianconi
  2025-08-22 11:22           ` Mikhail Kshevetskiy
                             ` (2 more replies)
  0 siblings, 3 replies; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-22  6:46 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf

[-- Attachment #1: Type: text/plain, Size: 6328 bytes --]

> 
> On 21.08.2025 14:34, Lorenzo Bianconi wrote:
> >> On 21.08.2025 09:58, Lorenzo Bianconi wrote:
> >>>> This patch series greatly improve airoha snfi driver and fix a
> >>>> number of serious bug.
> >>>>
> >>>> Fixed bugs:
> >>>>  * Fix reading/writing of flashes with more than one plane per lun
> >>>>  * Fix inability to read/write oob area
> >>>>  * Fill the buffer with 0xff before writing
> >>>>  * Fix reading of flashes supporting continuous reading mode
> >>>>  * Fix error paths
> >>>>
> >>>> Improvements:
> >>>>  * Add support of dual/quad wires spi modes in exec_op().
> >>>>  * Support of dualio/quadio flash reading commands
> >>>>  * Remove dirty hack that reads flash page settings from SNFI registers
> >>>>    during driver startup
> >>>>
> >>>> Unfortunately I am unable to test the driver with linux at the moment,
> >>>> so only the following testing was done:
> >>> It seems to me this is quite an important rework of the driver. I would prefer
> >>> to have some test results for this series. Are you able to run mtd_test kernel
> >>> module for testing?
> >> I'll try to build latest openwrt with this patches  and mtd_test kernel
> >> module and try it on one of our boards.
> > what board are you using for testing? If it is based on Airoha-7581 you could
> > use the following repo for testing.
> >
> > https://github.com/Ansuel/openwrt/tree/openwrt-24.10-airoha-an7581-stable
> >
> > Regards,
> > Lorenzo
> What tests do you suggest to run?

IIRC I run all of them. Can you please report even if there are some
improvements (or penalties) in read/write speed?

> I have a single flash I boot from. It have only 2 mtd partitions:
> 
> [    2.980849] spi-nand spi0.0: Micron SPI NAND was found.
> [    2.986102] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
> 2048, OOB size: 128
> [    2.994493] 2 fixed-partitions partitions found on MTD device spi0.0
> [    3.000856] Creating 2 MTD partitions on "spi0.0":
> [    3.005651] 0x000000000000-0x000000020000 : "bl2"
> [    3.011247] 0x000000020000-0x000010000000 : "ubi"
> 
> Most of tests are destructive. So If I use "bl2" or "ubi" partition for
> test, next time I will be unable to boot :-(

yes, I flashed the device after carrying out the test.

Regards,
Lorenzo

> Do you suggest to patch u-boot & linux to have more mtd partitions?
> 
> This is the results of the only read-only test I found.
> 
> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_test.ko
> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_readtest.ko dev=1
> [  159.121706]
> [  159.123220] =================================================
> [  159.129053] mtd_readtest: MTD device: 1
> [  159.132898] mtd_readtest: MTD device size 268304384, eraseblock size
> 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock
> 64, OOB size 128
> [  159.147008] mtd_test: scanning for bad eraseblocks
> [  159.152141] mtd_test: scanned 2047 eraseblocks, 0 are bad
> [  159.157549] mtd_readtest: testing page read
> 
> Mikhail
> 
> >> Actually patches can be divided on to parts:
> >> * fixes of current driver (patches 1-10)
> >> * change of behavior to avoid reading flash page settings from SNFI
> >> registers during driver startup (patches 11-14)
> >>
> >> The changes are based on the code we are using for more than 3 years. I
> >> adapt it to latest linux/u-boot code.
> >>
> >> Up to now the only known issue appears on en7523 chips only. Here a
> >> corresponding patch description (not added to this series)
> >> ====================================================== spi: airoha:
> >> en7523: workaround flash damaging if UART_TXD was short to GND We found
> >> that some serial console may pull TX line to GROUND during board boot
> >> time. Airoha uses TX line as one of it's BOOT pins. This will lead to
> >> booting in RESERVED boot mode. It was found that some flashes operates
> >> incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
> >> affected by the issue, Winbond flashes are NOT affected. Details:
> >> -------- DMA reading of odd pages on affected flashes operates
> >> incorrectly. Page reading offset (start of the page) on hardware level
> >> is replaced by 0x10. Thus results in incorrect data reading. Usage of
> >> UBI make things even worse. Any attempt to access UBI leads to ubi
> >> damaging. As result OS loading becomes impossible. Non-DMA reading is
> >> OK. =======================================================
> >>
> >> Regards,
> >> Mikhail
> >>
> >>
> >>> Regards,
> >>> Lorenzo
> >>>
> >>>>  * Driver compiles without error.
> >>>>  * All changes were tested with corresponding u-boot driver. U-Boot
> >>>>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
> >>>>    additional fixes for continuous mode.
> >>>>
> >>>> Changes v2:
> >>>>  * minor fix
> >>>>  * add comments to code
> >>>>
> >>>> Changes v3:
> >>>>  * add patch to prevent continuous reading
> >>>>
> >>>> Mikhail Kshevetskiy (14):
> >>>>   spi: airoha: return an error for continuous mode dirmap creation cases
> >>>>   spi: airoha: remove unnecessary restriction length
> >>>>   spi: airoha: add support of dual/quad wires spi modes
> >>>>   spi: airoha: remove unnecessary switch to non-dma mode
> >>>>   spi: airoha: unify dirmap read/write code
> >>>>   spi: airoha: switch back to non-dma mode in the case of error
> >>>>   spi: airoha: fix reading/writing of flashes with more than one plane
> >>>>     per lun
> >>>>   spi: airoha: support of dualio/quadio flash reading commands
> >>>>   spi: airoha: allow reading/writing of oob area
> >>>>   spi: airoha: buffer must be 0xff-ed before writing
> >>>>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
> >>>>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
> >>>>     REG_SPI_NFI_SECCUS_SIZE registers
> >>>>   spi: airoha: set custom sector size equal to flash page size
> >>>>   spi: airoha: avoid reading flash page settings from SNFI registers
> >>>>     during driver startup
> >>>>
> >>>>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
> >>>>  1 file changed, 260 insertions(+), 248 deletions(-)
> >>>>
> >>>> -- 
> >>>> 2.50.1
> >>>>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-22  6:46         ` Lorenzo Bianconi
@ 2025-08-22 11:22           ` Mikhail Kshevetskiy
  2025-08-22 13:14             ` Lorenzo Bianconi
  2025-08-22 11:27           ` Mikhail Kshevetskiy
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
  2 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-22 11:22 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf


On 22.08.2025 09:46, Lorenzo Bianconi wrote:
>> On 21.08.2025 14:34, Lorenzo Bianconi wrote:
>>>> On 21.08.2025 09:58, Lorenzo Bianconi wrote:
>>>>>> This patch series greatly improve airoha snfi driver and fix a
>>>>>> number of serious bug.
>>>>>>
>>>>>> Fixed bugs:
>>>>>>  * Fix reading/writing of flashes with more than one plane per lun
>>>>>>  * Fix inability to read/write oob area
>>>>>>  * Fill the buffer with 0xff before writing
>>>>>>  * Fix reading of flashes supporting continuous reading mode
>>>>>>  * Fix error paths
>>>>>>
>>>>>> Improvements:
>>>>>>  * Add support of dual/quad wires spi modes in exec_op().
>>>>>>  * Support of dualio/quadio flash reading commands
>>>>>>  * Remove dirty hack that reads flash page settings from SNFI registers
>>>>>>    during driver startup
>>>>>>
>>>>>> Unfortunately I am unable to test the driver with linux at the moment,
>>>>>> so only the following testing was done:
>>>>> It seems to me this is quite an important rework of the driver. I would prefer
>>>>> to have some test results for this series. Are you able to run mtd_test kernel
>>>>> module for testing?
>>>> I'll try to build latest openwrt with this patches  and mtd_test kernel
>>>> module and try it on one of our boards.
>>> what board are you using for testing? If it is based on Airoha-7581 you could
>>> use the following repo for testing.
>>>
>>> https://github.com/Ansuel/openwrt/tree/openwrt-24.10-airoha-an7581-stable
>>>
>>> Regards,
>>> Lorenzo
>> What tests do you suggest to run?
> IIRC I run all of them. Can you please report even if there are some
> improvements (or penalties) in read/write speed
Do you mean to run it twice? with patches and without?
>
>> I have a single flash I boot from. It have only 2 mtd partitions:
>>
>> [    2.980849] spi-nand spi0.0: Micron SPI NAND was found.
>> [    2.986102] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
>> 2048, OOB size: 128
>> [    2.994493] 2 fixed-partitions partitions found on MTD device spi0.0
>> [    3.000856] Creating 2 MTD partitions on "spi0.0":
>> [    3.005651] 0x000000000000-0x000000020000 : "bl2"
>> [    3.011247] 0x000000020000-0x000010000000 : "ubi"
>>
>> Most of tests are destructive. So If I use "bl2" or "ubi" partition for
>> test, next time I will be unable to boot :-(
> yes, I flashed the device after carrying out the test.
>
> Regards,
> Lorenzo
>
>> Do you suggest to patch u-boot & linux to have more mtd partitions?
>>
>> This is the results of the only read-only test I found.
>>
>> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_test.ko
>> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_readtest.ko dev=1
>> [  159.121706]
>> [  159.123220] =================================================
>> [  159.129053] mtd_readtest: MTD device: 1
>> [  159.132898] mtd_readtest: MTD device size 268304384, eraseblock size
>> 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock
>> 64, OOB size 128
>> [  159.147008] mtd_test: scanning for bad eraseblocks
>> [  159.152141] mtd_test: scanned 2047 eraseblocks, 0 are bad
>> [  159.157549] mtd_readtest: testing page read
>>
>> Mikhail
>>
>>>> Actually patches can be divided on to parts:
>>>> * fixes of current driver (patches 1-10)
>>>> * change of behavior to avoid reading flash page settings from SNFI
>>>> registers during driver startup (patches 11-14)
>>>>
>>>> The changes are based on the code we are using for more than 3 years. I
>>>> adapt it to latest linux/u-boot code.
>>>>
>>>> Up to now the only known issue appears on en7523 chips only. Here a
>>>> corresponding patch description (not added to this series)
>>>> ====================================================== spi: airoha:
>>>> en7523: workaround flash damaging if UART_TXD was short to GND We found
>>>> that some serial console may pull TX line to GROUND during board boot
>>>> time. Airoha uses TX line as one of it's BOOT pins. This will lead to
>>>> booting in RESERVED boot mode. It was found that some flashes operates
>>>> incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
>>>> affected by the issue, Winbond flashes are NOT affected. Details:
>>>> -------- DMA reading of odd pages on affected flashes operates
>>>> incorrectly. Page reading offset (start of the page) on hardware level
>>>> is replaced by 0x10. Thus results in incorrect data reading. Usage of
>>>> UBI make things even worse. Any attempt to access UBI leads to ubi
>>>> damaging. As result OS loading becomes impossible. Non-DMA reading is
>>>> OK. =======================================================
>>>>
>>>> Regards,
>>>> Mikhail
>>>>
>>>>
>>>>> Regards,
>>>>> Lorenzo
>>>>>
>>>>>>  * Driver compiles without error.
>>>>>>  * All changes were tested with corresponding u-boot driver. U-Boot
>>>>>>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
>>>>>>    additional fixes for continuous mode.
>>>>>>
>>>>>> Changes v2:
>>>>>>  * minor fix
>>>>>>  * add comments to code
>>>>>>
>>>>>> Changes v3:
>>>>>>  * add patch to prevent continuous reading
>>>>>>
>>>>>> Mikhail Kshevetskiy (14):
>>>>>>   spi: airoha: return an error for continuous mode dirmap creation cases
>>>>>>   spi: airoha: remove unnecessary restriction length
>>>>>>   spi: airoha: add support of dual/quad wires spi modes
>>>>>>   spi: airoha: remove unnecessary switch to non-dma mode
>>>>>>   spi: airoha: unify dirmap read/write code
>>>>>>   spi: airoha: switch back to non-dma mode in the case of error
>>>>>>   spi: airoha: fix reading/writing of flashes with more than one plane
>>>>>>     per lun
>>>>>>   spi: airoha: support of dualio/quadio flash reading commands
>>>>>>   spi: airoha: allow reading/writing of oob area
>>>>>>   spi: airoha: buffer must be 0xff-ed before writing
>>>>>>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
>>>>>>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
>>>>>>     REG_SPI_NFI_SECCUS_SIZE registers
>>>>>>   spi: airoha: set custom sector size equal to flash page size
>>>>>>   spi: airoha: avoid reading flash page settings from SNFI registers
>>>>>>     during driver startup
>>>>>>
>>>>>>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
>>>>>>  1 file changed, 260 insertions(+), 248 deletions(-)
>>>>>>
>>>>>> -- 
>>>>>> 2.50.1
>>>>>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-22  6:46         ` Lorenzo Bianconi
  2025-08-22 11:22           ` Mikhail Kshevetskiy
@ 2025-08-22 11:27           ` Mikhail Kshevetskiy
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
  2 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-22 11:27 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf


On 22.08.2025 09:46, Lorenzo Bianconi wrote:
>> On 21.08.2025 14:34, Lorenzo Bianconi wrote:
>>>> On 21.08.2025 09:58, Lorenzo Bianconi wrote:
>>>>>> This patch series greatly improve airoha snfi driver and fix a
>>>>>> number of serious bug.
>>>>>>
>>>>>> Fixed bugs:
>>>>>>  * Fix reading/writing of flashes with more than one plane per lun
>>>>>>  * Fix inability to read/write oob area
>>>>>>  * Fill the buffer with 0xff before writing
>>>>>>  * Fix reading of flashes supporting continuous reading mode
>>>>>>  * Fix error paths
>>>>>>
>>>>>> Improvements:
>>>>>>  * Add support of dual/quad wires spi modes in exec_op().
>>>>>>  * Support of dualio/quadio flash reading commands
>>>>>>  * Remove dirty hack that reads flash page settings from SNFI registers
>>>>>>    during driver startup
>>>>>>
>>>>>> Unfortunately I am unable to test the driver with linux at the moment,
>>>>>> so only the following testing was done:
>>>>> It seems to me this is quite an important rework of the driver. I would prefer
>>>>> to have some test results for this series. Are you able to run mtd_test kernel
>>>>> module for testing?
>>>> I'll try to build latest openwrt with this patches  and mtd_test kernel
>>>> module and try it on one of our boards.
>>> what board are you using for testing? If it is based on Airoha-7581 you could
>>> use the following repo for testing.
>>>
>>> https://github.com/Ansuel/openwrt/tree/openwrt-24.10-airoha-an7581-stable
>>>
>>> Regards,
>>> Lorenzo
>> What tests do you suggest to run?
> IIRC I run all of them. Can you please report even if there are some
> improvements (or penalties) in read/write speed?
>
>> I have a single flash I boot from. It have only 2 mtd partitions:
>>
>> [    2.980849] spi-nand spi0.0: Micron SPI NAND was found.
>> [    2.986102] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
>> 2048, OOB size: 128
>> [    2.994493] 2 fixed-partitions partitions found on MTD device spi0.0
>> [    3.000856] Creating 2 MTD partitions on "spi0.0":
>> [    3.005651] 0x000000000000-0x000000020000 : "bl2"
>> [    3.011247] 0x000000020000-0x000010000000 : "ubi"
>>
>> Most of tests are destructive. So If I use "bl2" or "ubi" partition for
>> test, next time I will be unable to boot :-(
> yes, I flashed the device after carrying out the test.
>
> Regards,
> Lorenzo

Is it enough to try tests on bl2 partition or it's better the whole flash?
By the way the current partitioning is bad -- there are flashes with 256
Mb erase block size.
So ubi will not start on the erase block boundary for such flashes.

Mikhail


>
>> Do you suggest to patch u-boot & linux to have more mtd partitions?
>>
>> This is the results of the only read-only test I found.
>>
>> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_test.ko
>> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_readtest.ko dev=1
>> [  159.121706]
>> [  159.123220] =================================================
>> [  159.129053] mtd_readtest: MTD device: 1
>> [  159.132898] mtd_readtest: MTD device size 268304384, eraseblock size
>> 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock
>> 64, OOB size 128
>> [  159.147008] mtd_test: scanning for bad eraseblocks
>> [  159.152141] mtd_test: scanned 2047 eraseblocks, 0 are bad
>> [  159.157549] mtd_readtest: testing page read
>>
>> Mikhail
>>
>>>> Actually patches can be divided on to parts:
>>>> * fixes of current driver (patches 1-10)
>>>> * change of behavior to avoid reading flash page settings from SNFI
>>>> registers during driver startup (patches 11-14)
>>>>
>>>> The changes are based on the code we are using for more than 3 years. I
>>>> adapt it to latest linux/u-boot code.
>>>>
>>>> Up to now the only known issue appears on en7523 chips only. Here a
>>>> corresponding patch description (not added to this series)
>>>> ====================================================== spi: airoha:
>>>> en7523: workaround flash damaging if UART_TXD was short to GND We found
>>>> that some serial console may pull TX line to GROUND during board boot
>>>> time. Airoha uses TX line as one of it's BOOT pins. This will lead to
>>>> booting in RESERVED boot mode. It was found that some flashes operates
>>>> incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
>>>> affected by the issue, Winbond flashes are NOT affected. Details:
>>>> -------- DMA reading of odd pages on affected flashes operates
>>>> incorrectly. Page reading offset (start of the page) on hardware level
>>>> is replaced by 0x10. Thus results in incorrect data reading. Usage of
>>>> UBI make things even worse. Any attempt to access UBI leads to ubi
>>>> damaging. As result OS loading becomes impossible. Non-DMA reading is
>>>> OK. =======================================================
>>>>
>>>> Regards,
>>>> Mikhail
>>>>
>>>>
>>>>> Regards,
>>>>> Lorenzo
>>>>>
>>>>>>  * Driver compiles without error.
>>>>>>  * All changes were tested with corresponding u-boot driver. U-Boot
>>>>>>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
>>>>>>    additional fixes for continuous mode.
>>>>>>
>>>>>> Changes v2:
>>>>>>  * minor fix
>>>>>>  * add comments to code
>>>>>>
>>>>>> Changes v3:
>>>>>>  * add patch to prevent continuous reading
>>>>>>
>>>>>> Mikhail Kshevetskiy (14):
>>>>>>   spi: airoha: return an error for continuous mode dirmap creation cases
>>>>>>   spi: airoha: remove unnecessary restriction length
>>>>>>   spi: airoha: add support of dual/quad wires spi modes
>>>>>>   spi: airoha: remove unnecessary switch to non-dma mode
>>>>>>   spi: airoha: unify dirmap read/write code
>>>>>>   spi: airoha: switch back to non-dma mode in the case of error
>>>>>>   spi: airoha: fix reading/writing of flashes with more than one plane
>>>>>>     per lun
>>>>>>   spi: airoha: support of dualio/quadio flash reading commands
>>>>>>   spi: airoha: allow reading/writing of oob area
>>>>>>   spi: airoha: buffer must be 0xff-ed before writing
>>>>>>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
>>>>>>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
>>>>>>     REG_SPI_NFI_SECCUS_SIZE registers
>>>>>>   spi: airoha: set custom sector size equal to flash page size
>>>>>>   spi: airoha: avoid reading flash page settings from SNFI registers
>>>>>>     during driver startup
>>>>>>
>>>>>>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
>>>>>>  1 file changed, 260 insertions(+), 248 deletions(-)
>>>>>>
>>>>>> -- 
>>>>>> 2.50.1
>>>>>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-22 11:22           ` Mikhail Kshevetskiy
@ 2025-08-22 13:14             ` Lorenzo Bianconi
  2025-08-22 14:36               ` Mikhail Kshevetskiy
  2025-08-22 20:00               ` Mikhail Kshevetskiy
  0 siblings, 2 replies; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-22 13:14 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf

[-- Attachment #1: Type: text/plain, Size: 6884 bytes --]

> 
> On 22.08.2025 09:46, Lorenzo Bianconi wrote:
> >> On 21.08.2025 14:34, Lorenzo Bianconi wrote:
> >>>> On 21.08.2025 09:58, Lorenzo Bianconi wrote:
> >>>>>> This patch series greatly improve airoha snfi driver and fix a
> >>>>>> number of serious bug.
> >>>>>>
> >>>>>> Fixed bugs:
> >>>>>>  * Fix reading/writing of flashes with more than one plane per lun
> >>>>>>  * Fix inability to read/write oob area
> >>>>>>  * Fill the buffer with 0xff before writing
> >>>>>>  * Fix reading of flashes supporting continuous reading mode
> >>>>>>  * Fix error paths
> >>>>>>
> >>>>>> Improvements:
> >>>>>>  * Add support of dual/quad wires spi modes in exec_op().
> >>>>>>  * Support of dualio/quadio flash reading commands
> >>>>>>  * Remove dirty hack that reads flash page settings from SNFI registers
> >>>>>>    during driver startup
> >>>>>>
> >>>>>> Unfortunately I am unable to test the driver with linux at the moment,
> >>>>>> so only the following testing was done:
> >>>>> It seems to me this is quite an important rework of the driver. I would prefer
> >>>>> to have some test results for this series. Are you able to run mtd_test kernel
> >>>>> module for testing?
> >>>> I'll try to build latest openwrt with this patches  and mtd_test kernel
> >>>> module and try it on one of our boards.
> >>> what board are you using for testing? If it is based on Airoha-7581 you could
> >>> use the following repo for testing.
> >>>
> >>> https://github.com/Ansuel/openwrt/tree/openwrt-24.10-airoha-an7581-stable
> >>>
> >>> Regards,
> >>> Lorenzo
> >> What tests do you suggest to run?
> > IIRC I run all of them. Can you please report even if there are some
> > improvements (or penalties) in read/write speed
> Do you mean to run it twice? with patches and without?

I mean I would suggest to check if there are any difference in read/write
speed (so yes, you need a baseline).

Regards,
Lorenzo

> >
> >> I have a single flash I boot from. It have only 2 mtd partitions:
> >>
> >> [    2.980849] spi-nand spi0.0: Micron SPI NAND was found.
> >> [    2.986102] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
> >> 2048, OOB size: 128
> >> [    2.994493] 2 fixed-partitions partitions found on MTD device spi0.0
> >> [    3.000856] Creating 2 MTD partitions on "spi0.0":
> >> [    3.005651] 0x000000000000-0x000000020000 : "bl2"
> >> [    3.011247] 0x000000020000-0x000010000000 : "ubi"
> >>
> >> Most of tests are destructive. So If I use "bl2" or "ubi" partition for
> >> test, next time I will be unable to boot :-(
> > yes, I flashed the device after carrying out the test.
> >
> > Regards,
> > Lorenzo
> >
> >> Do you suggest to patch u-boot & linux to have more mtd partitions?
> >>
> >> This is the results of the only read-only test I found.
> >>
> >> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_test.ko
> >> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_readtest.ko dev=1
> >> [  159.121706]
> >> [  159.123220] =================================================
> >> [  159.129053] mtd_readtest: MTD device: 1
> >> [  159.132898] mtd_readtest: MTD device size 268304384, eraseblock size
> >> 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock
> >> 64, OOB size 128
> >> [  159.147008] mtd_test: scanning for bad eraseblocks
> >> [  159.152141] mtd_test: scanned 2047 eraseblocks, 0 are bad
> >> [  159.157549] mtd_readtest: testing page read
> >>
> >> Mikhail
> >>
> >>>> Actually patches can be divided on to parts:
> >>>> * fixes of current driver (patches 1-10)
> >>>> * change of behavior to avoid reading flash page settings from SNFI
> >>>> registers during driver startup (patches 11-14)
> >>>>
> >>>> The changes are based on the code we are using for more than 3 years. I
> >>>> adapt it to latest linux/u-boot code.
> >>>>
> >>>> Up to now the only known issue appears on en7523 chips only. Here a
> >>>> corresponding patch description (not added to this series)
> >>>> ====================================================== spi: airoha:
> >>>> en7523: workaround flash damaging if UART_TXD was short to GND We found
> >>>> that some serial console may pull TX line to GROUND during board boot
> >>>> time. Airoha uses TX line as one of it's BOOT pins. This will lead to
> >>>> booting in RESERVED boot mode. It was found that some flashes operates
> >>>> incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
> >>>> affected by the issue, Winbond flashes are NOT affected. Details:
> >>>> -------- DMA reading of odd pages on affected flashes operates
> >>>> incorrectly. Page reading offset (start of the page) on hardware level
> >>>> is replaced by 0x10. Thus results in incorrect data reading. Usage of
> >>>> UBI make things even worse. Any attempt to access UBI leads to ubi
> >>>> damaging. As result OS loading becomes impossible. Non-DMA reading is
> >>>> OK. =======================================================
> >>>>
> >>>> Regards,
> >>>> Mikhail
> >>>>
> >>>>
> >>>>> Regards,
> >>>>> Lorenzo
> >>>>>
> >>>>>>  * Driver compiles without error.
> >>>>>>  * All changes were tested with corresponding u-boot driver. U-Boot
> >>>>>>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
> >>>>>>    additional fixes for continuous mode.
> >>>>>>
> >>>>>> Changes v2:
> >>>>>>  * minor fix
> >>>>>>  * add comments to code
> >>>>>>
> >>>>>> Changes v3:
> >>>>>>  * add patch to prevent continuous reading
> >>>>>>
> >>>>>> Mikhail Kshevetskiy (14):
> >>>>>>   spi: airoha: return an error for continuous mode dirmap creation cases
> >>>>>>   spi: airoha: remove unnecessary restriction length
> >>>>>>   spi: airoha: add support of dual/quad wires spi modes
> >>>>>>   spi: airoha: remove unnecessary switch to non-dma mode
> >>>>>>   spi: airoha: unify dirmap read/write code
> >>>>>>   spi: airoha: switch back to non-dma mode in the case of error
> >>>>>>   spi: airoha: fix reading/writing of flashes with more than one plane
> >>>>>>     per lun
> >>>>>>   spi: airoha: support of dualio/quadio flash reading commands
> >>>>>>   spi: airoha: allow reading/writing of oob area
> >>>>>>   spi: airoha: buffer must be 0xff-ed before writing
> >>>>>>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
> >>>>>>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
> >>>>>>     REG_SPI_NFI_SECCUS_SIZE registers
> >>>>>>   spi: airoha: set custom sector size equal to flash page size
> >>>>>>   spi: airoha: avoid reading flash page settings from SNFI registers
> >>>>>>     during driver startup
> >>>>>>
> >>>>>>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
> >>>>>>  1 file changed, 260 insertions(+), 248 deletions(-)
> >>>>>>
> >>>>>> -- 
> >>>>>> 2.50.1
> >>>>>>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-22 13:14             ` Lorenzo Bianconi
@ 2025-08-22 14:36               ` Mikhail Kshevetskiy
  2025-08-22 20:00               ` Mikhail Kshevetskiy
  1 sibling, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-22 14:36 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf

patch 7 (spi: airoha: fix reading/writing of flashes with more than one
plane per lun) is absolutely necessary for my flash. Without a patch

[    2.980989] spi-nand spi0.0: Micron SPI NAND was found.
[    2.986309] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
2048, OOB size: 128
[    2.994978] 2 fixed-partitions partitions found on MTD device spi0.0
[    3.001350] Creating 2 MTD partitions on "spi0.0":
[    3.006159] 0x000000000000-0x000000020000 : "bl2"
[    3.011663] 0x000000020000-0x000010000000 : "ubi"
...
[    6.391748] ubi0: attaching mtd1
[    6.412545] ubi0 error: ubi_attach: PEB 0 contains corrupted VID
header, and the data does not contain all 0xFF
[    6.422677] ubi0 error: ubi_attach: this may be a non-UBI PEB or a
severe VID header corruption which requires manual inspection
[    6.434249] Volume identifier header dump:
[    6.438349]     magic     55424923
[    6.441482]     version   1
[    6.444007]     vol_type  0
[    6.446539]     copy_flag 0
[    6.449068]     compat    0
[    6.451594]     vol_id    0
[    6.454120]     lnum      1
[    6.456651]     data_size 4096
[    6.459442]     used_ebs  1061644134
[    6.462748]     data_pad  0
[    6.465274]     sqnum     0
[    6.467805]     hdr_crc   61169820
[    6.470943] Volume identifier header hexdump:
[    6.475308] hexdump of PEB 0 offset 4096, length 126976
[    6.507391] ubi0 warning: ubi_attach: valid VID header but corrupted
EC header at PEB 4
[    6.515415] ubi0 error: ubi_compare_lebs: unsupported on-flash UBI format
[    6.522222] ubi0 error: ubi_attach_mtd_dev: failed to attach mtd1,
error -22
[    6.529294] UBI error: cannot attach mtd1
[    6.533450] clk: Disabling unused clocks
[    6.537583] Waiting for root device /dev/ubiblock0_5...

With a patch

[    2.980791] spi-nand spi0.0: Micron SPI NAND was found.
[    2.986049] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
2048, OOB size: 128
[    2.994452] 2 fixed-partitions partitions found on MTD device spi0.0
[    3.000820] Creating 2 MTD partitions on "spi0.0":
[    3.005614] 0x000000000000-0x000000020000 : "bl2"
[    3.011209] 0x000000020000-0x000010000000 : "ubi"
...
[    6.403811] ubi0: attaching mtd1
[    7.474901] ubi0: scanning is finished
[    7.487134] ubi0: attached mtd1 (name "ubi", size 255 MiB)
[    7.492649] ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 126976
bytes
[    7.499538] ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
[    7.506326] ubi0: VID header offset: 2048 (aligned 2048), data
offset: 4096
[    7.513281] ubi0: good PEBs: 2047, bad PEBs: 0, corrupted PEBs: 0
[    7.519379] ubi0: user volume: 9, internal volumes: 1, max. volumes
count: 128
[    7.526603] ubi0: max/mean erase counter: 2/1, WL threshold: 4096,
image sequence number: 1061644134
[    7.535729] ubi0: available PEBs: 0, total reserved PEBs: 2047, PEBs
reserved for bad PEB handling: 40
[    7.545041] ubi0: background thread "ubi_bgt0d" started, PID 619
[    7.545882] block ubiblock0_5: created from ubi0:5(rootfs)
[    7.556540] ubiblock: device ubiblock0_5 (rootfs) set to be root
filesystem
[    7.563598] clk: Disabling unused clocks
[    7.573181] VFS: Mounted root (squashfs filesystem) readonly on
device 254:0.





On 22.08.2025 16:14, Lorenzo Bianconi wrote:
>> On 22.08.2025 09:46, Lorenzo Bianconi wrote:
>>>> On 21.08.2025 14:34, Lorenzo Bianconi wrote:
>>>>>> On 21.08.2025 09:58, Lorenzo Bianconi wrote:
>>>>>>>> This patch series greatly improve airoha snfi driver and fix a
>>>>>>>> number of serious bug.
>>>>>>>>
>>>>>>>> Fixed bugs:
>>>>>>>>  * Fix reading/writing of flashes with more than one plane per lun
>>>>>>>>  * Fix inability to read/write oob area
>>>>>>>>  * Fill the buffer with 0xff before writing
>>>>>>>>  * Fix reading of flashes supporting continuous reading mode
>>>>>>>>  * Fix error paths
>>>>>>>>
>>>>>>>> Improvements:
>>>>>>>>  * Add support of dual/quad wires spi modes in exec_op().
>>>>>>>>  * Support of dualio/quadio flash reading commands
>>>>>>>>  * Remove dirty hack that reads flash page settings from SNFI registers
>>>>>>>>    during driver startup
>>>>>>>>
>>>>>>>> Unfortunately I am unable to test the driver with linux at the moment,
>>>>>>>> so only the following testing was done:
>>>>>>> It seems to me this is quite an important rework of the driver. I would prefer
>>>>>>> to have some test results for this series. Are you able to run mtd_test kernel
>>>>>>> module for testing?
>>>>>> I'll try to build latest openwrt with this patches  and mtd_test kernel
>>>>>> module and try it on one of our boards.
>>>>> what board are you using for testing? If it is based on Airoha-7581 you could
>>>>> use the following repo for testing.
>>>>>
>>>>> https://github.com/Ansuel/openwrt/tree/openwrt-24.10-airoha-an7581-stable
>>>>>
>>>>> Regards,
>>>>> Lorenzo
>>>> What tests do you suggest to run?
>>> IIRC I run all of them. Can you please report even if there are some
>>> improvements (or penalties) in read/write speed
>> Do you mean to run it twice? with patches and without?
> I mean I would suggest to check if there are any difference in read/write
> speed (so yes, you need a baseline).
>
> Regards,
> Lorenzo
>
>>>> I have a single flash I boot from. It have only 2 mtd partitions:
>>>>
>>>> [    2.980849] spi-nand spi0.0: Micron SPI NAND was found.
>>>> [    2.986102] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
>>>> 2048, OOB size: 128
>>>> [    2.994493] 2 fixed-partitions partitions found on MTD device spi0.0
>>>> [    3.000856] Creating 2 MTD partitions on "spi0.0":
>>>> [    3.005651] 0x000000000000-0x000000020000 : "bl2"
>>>> [    3.011247] 0x000000020000-0x000010000000 : "ubi"
>>>>
>>>> Most of tests are destructive. So If I use "bl2" or "ubi" partition for
>>>> test, next time I will be unable to boot :-(
>>> yes, I flashed the device after carrying out the test.
>>>
>>> Regards,
>>> Lorenzo
>>>
>>>> Do you suggest to patch u-boot & linux to have more mtd partitions?
>>>>
>>>> This is the results of the only read-only test I found.
>>>>
>>>> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_test.ko
>>>> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_readtest.ko dev=1
>>>> [  159.121706]
>>>> [  159.123220] =================================================
>>>> [  159.129053] mtd_readtest: MTD device: 1
>>>> [  159.132898] mtd_readtest: MTD device size 268304384, eraseblock size
>>>> 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock
>>>> 64, OOB size 128
>>>> [  159.147008] mtd_test: scanning for bad eraseblocks
>>>> [  159.152141] mtd_test: scanned 2047 eraseblocks, 0 are bad
>>>> [  159.157549] mtd_readtest: testing page read
>>>>
>>>> Mikhail
>>>>
>>>>>> Actually patches can be divided on to parts:
>>>>>> * fixes of current driver (patches 1-10)
>>>>>> * change of behavior to avoid reading flash page settings from SNFI
>>>>>> registers during driver startup (patches 11-14)
>>>>>>
>>>>>> The changes are based on the code we are using for more than 3 years. I
>>>>>> adapt it to latest linux/u-boot code.
>>>>>>
>>>>>> Up to now the only known issue appears on en7523 chips only. Here a
>>>>>> corresponding patch description (not added to this series)
>>>>>> ====================================================== spi: airoha:
>>>>>> en7523: workaround flash damaging if UART_TXD was short to GND We found
>>>>>> that some serial console may pull TX line to GROUND during board boot
>>>>>> time. Airoha uses TX line as one of it's BOOT pins. This will lead to
>>>>>> booting in RESERVED boot mode. It was found that some flashes operates
>>>>>> incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
>>>>>> affected by the issue, Winbond flashes are NOT affected. Details:
>>>>>> -------- DMA reading of odd pages on affected flashes operates
>>>>>> incorrectly. Page reading offset (start of the page) on hardware level
>>>>>> is replaced by 0x10. Thus results in incorrect data reading. Usage of
>>>>>> UBI make things even worse. Any attempt to access UBI leads to ubi
>>>>>> damaging. As result OS loading becomes impossible. Non-DMA reading is
>>>>>> OK. =======================================================
>>>>>>
>>>>>> Regards,
>>>>>> Mikhail
>>>>>>
>>>>>>
>>>>>>> Regards,
>>>>>>> Lorenzo
>>>>>>>
>>>>>>>>  * Driver compiles without error.
>>>>>>>>  * All changes were tested with corresponding u-boot driver. U-Boot
>>>>>>>>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
>>>>>>>>    additional fixes for continuous mode.
>>>>>>>>
>>>>>>>> Changes v2:
>>>>>>>>  * minor fix
>>>>>>>>  * add comments to code
>>>>>>>>
>>>>>>>> Changes v3:
>>>>>>>>  * add patch to prevent continuous reading
>>>>>>>>
>>>>>>>> Mikhail Kshevetskiy (14):
>>>>>>>>   spi: airoha: return an error for continuous mode dirmap creation cases
>>>>>>>>   spi: airoha: remove unnecessary restriction length
>>>>>>>>   spi: airoha: add support of dual/quad wires spi modes
>>>>>>>>   spi: airoha: remove unnecessary switch to non-dma mode
>>>>>>>>   spi: airoha: unify dirmap read/write code
>>>>>>>>   spi: airoha: switch back to non-dma mode in the case of error
>>>>>>>>   spi: airoha: fix reading/writing of flashes with more than one plane
>>>>>>>>     per lun
>>>>>>>>   spi: airoha: support of dualio/quadio flash reading commands
>>>>>>>>   spi: airoha: allow reading/writing of oob area
>>>>>>>>   spi: airoha: buffer must be 0xff-ed before writing
>>>>>>>>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
>>>>>>>>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
>>>>>>>>     REG_SPI_NFI_SECCUS_SIZE registers
>>>>>>>>   spi: airoha: set custom sector size equal to flash page size
>>>>>>>>   spi: airoha: avoid reading flash page settings from SNFI registers
>>>>>>>>     during driver startup
>>>>>>>>
>>>>>>>>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
>>>>>>>>  1 file changed, 260 insertions(+), 248 deletions(-)
>>>>>>>>
>>>>>>>> -- 
>>>>>>>> 2.50.1
>>>>>>>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v3 00/14] spi: airoha: driver fixes & improvements
  2025-08-22 13:14             ` Lorenzo Bianconi
  2025-08-22 14:36               ` Mikhail Kshevetskiy
@ 2025-08-22 20:00               ` Mikhail Kshevetskiy
  1 sibling, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-22 20:00 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Ray Liu, Mark Brown, linux-arm-kernel, linux-spi, linux-kernel,
	Frieder Schrempf

patch 3 (spi: airoha: add support of dual/quad wires spi modes) is
necessary for non-dma reading. This can happen if dirmap creation fails
by some reason. In this case the kernel uses exec_op() handler to
execute dirmap requests.

According to dtb the device supports dualwire operations, so dualwire
commands issued for cache reading. Unfortunately  exec_op() handler does
not supports dual/quad operations, so flash reading fails. Here is the
corresponding boot log
-----------------------------------------------------
[    2.980719] spi-nand spi0.0: Micron SPI NAND was found.
[    2.986040] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
2048, OOB size: 128
[    2.994709] 2 fixed-partitions partitions found on MTD device spi0.0
[    3.001075] Creating 2 MTD partitions on "spi0.0":
[    3.005862] 0x000000000000-0x000000020000 : "bl2"
[    3.011272] 0x000000020000-0x000010000000 : "ubi"
...
[    6.195594] ubi0: attaching mtd1
[   13.338398] ubi0: scanning is finished
[   13.342188] ubi0 error: ubi_read_volume_table: the layout volume was
not found
[   13.349784] ubi0 error: ubi_attach_mtd_dev: failed to attach mtd1,
error -22
[   13.356897] UBI error: cannot attach mtd1
-------------------------------------------------------

If dma=off, but patch-3 is applied -- everything works (but slowly).

Here is a patch to disable DMA operations:

 --- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -618,6 +618,7 @@ static int airoha_snand_dirmap_create(struct
spi_mem_dirmap_desc *desc)
        if (desc->info.offset + desc->info.length > U32_MAX)
                return -EINVAL;
 
+       return -E2BIG;

        if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))
                return -EOPNOTSUPP;



On 22.08.2025 16:14, Lorenzo Bianconi wrote:
>> On 22.08.2025 09:46, Lorenzo Bianconi wrote:
>>>> On 21.08.2025 14:34, Lorenzo Bianconi wrote:
>>>>>> On 21.08.2025 09:58, Lorenzo Bianconi wrote:
>>>>>>>> This patch series greatly improve airoha snfi driver and fix a
>>>>>>>> number of serious bug.
>>>>>>>>
>>>>>>>> Fixed bugs:
>>>>>>>>  * Fix reading/writing of flashes with more than one plane per lun
>>>>>>>>  * Fix inability to read/write oob area
>>>>>>>>  * Fill the buffer with 0xff before writing
>>>>>>>>  * Fix reading of flashes supporting continuous reading mode
>>>>>>>>  * Fix error paths
>>>>>>>>
>>>>>>>> Improvements:
>>>>>>>>  * Add support of dual/quad wires spi modes in exec_op().
>>>>>>>>  * Support of dualio/quadio flash reading commands
>>>>>>>>  * Remove dirty hack that reads flash page settings from SNFI registers
>>>>>>>>    during driver startup
>>>>>>>>
>>>>>>>> Unfortunately I am unable to test the driver with linux at the moment,
>>>>>>>> so only the following testing was done:
>>>>>>> It seems to me this is quite an important rework of the driver. I would prefer
>>>>>>> to have some test results for this series. Are you able to run mtd_test kernel
>>>>>>> module for testing?
>>>>>> I'll try to build latest openwrt with this patches  and mtd_test kernel
>>>>>> module and try it on one of our boards.
>>>>> what board are you using for testing? If it is based on Airoha-7581 you could
>>>>> use the following repo for testing.
>>>>>
>>>>> https://github.com/Ansuel/openwrt/tree/openwrt-24.10-airoha-an7581-stable
>>>>>
>>>>> Regards,
>>>>> Lorenzo
>>>> What tests do you suggest to run?
>>> IIRC I run all of them. Can you please report even if there are some
>>> improvements (or penalties) in read/write speed
>> Do you mean to run it twice? with patches and without?
> I mean I would suggest to check if there are any difference in read/write
> speed (so yes, you need a baseline).
>
> Regards,
> Lorenzo
>
>>>> I have a single flash I boot from. It have only 2 mtd partitions:
>>>>
>>>> [    2.980849] spi-nand spi0.0: Micron SPI NAND was found.
>>>> [    2.986102] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size:
>>>> 2048, OOB size: 128
>>>> [    2.994493] 2 fixed-partitions partitions found on MTD device spi0.0
>>>> [    3.000856] Creating 2 MTD partitions on "spi0.0":
>>>> [    3.005651] 0x000000000000-0x000000020000 : "bl2"
>>>> [    3.011247] 0x000000020000-0x000010000000 : "ubi"
>>>>
>>>> Most of tests are destructive. So If I use "bl2" or "ubi" partition for
>>>> test, next time I will be unable to boot :-(
>>> yes, I flashed the device after carrying out the test.
>>>
>>> Regards,
>>> Lorenzo
>>>
>>>> Do you suggest to patch u-boot & linux to have more mtd partitions?
>>>>
>>>> This is the results of the only read-only test I found.
>>>>
>>>> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_test.ko
>>>> root@OpenWrt:/lib/modules/6.6.79# insmod mtd_readtest.ko dev=1
>>>> [  159.121706]
>>>> [  159.123220] =================================================
>>>> [  159.129053] mtd_readtest: MTD device: 1
>>>> [  159.132898] mtd_readtest: MTD device size 268304384, eraseblock size
>>>> 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock
>>>> 64, OOB size 128
>>>> [  159.147008] mtd_test: scanning for bad eraseblocks
>>>> [  159.152141] mtd_test: scanned 2047 eraseblocks, 0 are bad
>>>> [  159.157549] mtd_readtest: testing page read
>>>>
>>>> Mikhail
>>>>
>>>>>> Actually patches can be divided on to parts:
>>>>>> * fixes of current driver (patches 1-10)
>>>>>> * change of behavior to avoid reading flash page settings from SNFI
>>>>>> registers during driver startup (patches 11-14)
>>>>>>
>>>>>> The changes are based on the code we are using for more than 3 years. I
>>>>>> adapt it to latest linux/u-boot code.
>>>>>>
>>>>>> Up to now the only known issue appears on en7523 chips only. Here a
>>>>>> corresponding patch description (not added to this series)
>>>>>> ====================================================== spi: airoha:
>>>>>> en7523: workaround flash damaging if UART_TXD was short to GND We found
>>>>>> that some serial console may pull TX line to GROUND during board boot
>>>>>> time. Airoha uses TX line as one of it's BOOT pins. This will lead to
>>>>>> booting in RESERVED boot mode. It was found that some flashes operates
>>>>>> incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely
>>>>>> affected by the issue, Winbond flashes are NOT affected. Details:
>>>>>> -------- DMA reading of odd pages on affected flashes operates
>>>>>> incorrectly. Page reading offset (start of the page) on hardware level
>>>>>> is replaced by 0x10. Thus results in incorrect data reading. Usage of
>>>>>> UBI make things even worse. Any attempt to access UBI leads to ubi
>>>>>> damaging. As result OS loading becomes impossible. Non-DMA reading is
>>>>>> OK. =======================================================
>>>>>>
>>>>>> Regards,
>>>>>> Mikhail
>>>>>>
>>>>>>
>>>>>>> Regards,
>>>>>>> Lorenzo
>>>>>>>
>>>>>>>>  * Driver compiles without error.
>>>>>>>>  * All changes were tested with corresponding u-boot driver. U-Boot
>>>>>>>>    SpiNAND driver was modified as well to match linux-6.17-rc2 with
>>>>>>>>    additional fixes for continuous mode.
>>>>>>>>
>>>>>>>> Changes v2:
>>>>>>>>  * minor fix
>>>>>>>>  * add comments to code
>>>>>>>>
>>>>>>>> Changes v3:
>>>>>>>>  * add patch to prevent continuous reading
>>>>>>>>
>>>>>>>> Mikhail Kshevetskiy (14):
>>>>>>>>   spi: airoha: return an error for continuous mode dirmap creation cases
>>>>>>>>   spi: airoha: remove unnecessary restriction length
>>>>>>>>   spi: airoha: add support of dual/quad wires spi modes
>>>>>>>>   spi: airoha: remove unnecessary switch to non-dma mode
>>>>>>>>   spi: airoha: unify dirmap read/write code
>>>>>>>>   spi: airoha: switch back to non-dma mode in the case of error
>>>>>>>>   spi: airoha: fix reading/writing of flashes with more than one plane
>>>>>>>>     per lun
>>>>>>>>   spi: airoha: support of dualio/quadio flash reading commands
>>>>>>>>   spi: airoha: allow reading/writing of oob area
>>>>>>>>   spi: airoha: buffer must be 0xff-ed before writing
>>>>>>>>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
>>>>>>>>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
>>>>>>>>     REG_SPI_NFI_SECCUS_SIZE registers
>>>>>>>>   spi: airoha: set custom sector size equal to flash page size
>>>>>>>>   spi: airoha: avoid reading flash page settings from SNFI registers
>>>>>>>>     during driver startup
>>>>>>>>
>>>>>>>>  drivers/spi/spi-airoha-snfi.c | 508 +++++++++++++++++-----------------
>>>>>>>>  1 file changed, 260 insertions(+), 248 deletions(-)
>>>>>>>>
>>>>>>>> -- 
>>>>>>>> 2.50.1
>>>>>>>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH v4 00/13] spi: airoha: driver fixes & improvements
  2025-08-22  6:46         ` Lorenzo Bianconi
  2025-08-22 11:22           ` Mikhail Kshevetskiy
  2025-08-22 11:27           ` Mikhail Kshevetskiy
@ 2025-08-23  0:16           ` Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 01/13] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
                               ` (13 more replies)
  2 siblings, 14 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

This patch series greatly improve airoha snfi driver and fix a
number of serious bug.

Fixed bugs:
 * Fix reading/writing of flashes with more than one plane per lun
 * Fill the buffer with 0xff before writing
 * Fix reading of flashes supporting continuous reading mode
 * Fix error paths

Improvements:
 * Add support of dual/quad wires spi modes in exec_op(). This also
   fix flash reading/writing if dirmap can't be created.
 * Support of dualio/quadio flash reading commands
 * Remove dirty hack that reads flash page settings from SNFI registers
   during driver startup

Test results:

1) Boot without dual/quad wires spi modes support (patch-3) and disabled dirmap support

    [    2.980719] spi-nand spi0.0: Micron SPI NAND was found.
    [    2.986040] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
    [    2.994709] 2 fixed-partitions partitions found on MTD device spi0.0
    [    3.001075] Creating 2 MTD partitions on "spi0.0":
    [    3.005862] 0x000000000000-0x000000020000 : "bl2"
    [    3.011272] 0x000000020000-0x000010000000 : "ubi"
    ...
    [    6.195594] ubi0: attaching mtd1
    [   13.338398] ubi0: scanning is finished
    [   13.342188] ubi0 error: ubi_read_volume_table: the layout volume was not found
    [   13.349784] ubi0 error: ubi_attach_mtd_dev: failed to attach mtd1, error -22
    [   13.356897] UBI error: cannot attach mtd1

2) Boot without fixes for flashes with more than one plane per lun (patch-7)

    [    2.980989] spi-nand spi0.0: Micron SPI NAND was found.
    [    2.986309] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
    [    2.994978] 2 fixed-partitions partitions found on MTD device spi0.0
    [    3.001350] Creating 2 MTD partitions on "spi0.0":
    [    3.006159] 0x000000000000-0x000000020000 : "bl2"
    [    3.011663] 0x000000020000-0x000010000000 : "ubi"
    ...
    [    6.391748] ubi0: attaching mtd1
    [    6.412545] ubi0 error: ubi_attach: PEB 0 contains corrupted VID header, and the data does not contain all 0xFF
    [    6.422677] ubi0 error: ubi_attach: this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection
    [    6.434249] Volume identifier header dump:
    [    6.438349]     magic     55424923
    [    6.441482]     version   1
    [    6.444007]     vol_type  0
    [    6.446539]     copy_flag 0
    [    6.449068]     compat    0
    [    6.451594]     vol_id    0
    [    6.454120]     lnum      1
    [    6.456651]     data_size 4096
    [    6.459442]     used_ebs  1061644134
    [    6.462748]     data_pad  0
    [    6.465274]     sqnum     0
    [    6.467805]     hdr_crc   61169820
    [    6.470943] Volume identifier header hexdump:
    [    6.475308] hexdump of PEB 0 offset 4096, length 126976
    [    6.507391] ubi0 warning: ubi_attach: valid VID header but corrupted EC header at PEB 4
    [    6.515415] ubi0 error: ubi_compare_lebs: unsupported on-flash UBI format
    [    6.522222] ubi0 error: ubi_attach_mtd_dev: failed to attach mtd1, error -22
    [    6.529294] UBI error: cannot attach mtd1
    [    6.533450] clk: Disabling unused clocks
    [    6.537583] Waiting for root device /dev/ubiblock0_5...

3) patched kernel tests

    root@OpenWrt:/lib/modules/6.6.79# insmod mtd_oobtest.ko dev=1
    [  263.191711] 
    [  263.193218] =================================================
    [  263.199014] mtd_oobtest: MTD device: 1
    [  263.202768] mtd_oobtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [  263.216791] mtd_test: scanning for bad eraseblocks
    [  263.221956] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [  263.227361] mtd_oobtest: test 1 of 5
    [  265.077216] mtd_oobtest: writing OOBs of whole device
    [  265.121767] mtd_oobtest: written up to eraseblock 0
    [  275.174147] mtd_oobtest: written up to eraseblock 256
    [  285.210279] mtd_oobtest: written up to eraseblock 512
    [  295.241724] mtd_oobtest: written up to eraseblock 768
    [  305.280167] mtd_oobtest: written up to eraseblock 1024
    [  315.326883] mtd_oobtest: written up to eraseblock 1280
    [  325.364049] mtd_oobtest: written up to eraseblock 1536
    [  335.398609] mtd_oobtest: written up to eraseblock 1792
    [  345.358981] mtd_oobtest: written 2047 eraseblocks
    [  345.363694] mtd_oobtest: verifying all eraseblocks
    [  345.386088] mtd_oobtest: verified up to eraseblock 0
    [  349.830833] mtd_oobtest: verified up to eraseblock 256
    [  354.276245] mtd_oobtest: verified up to eraseblock 512
    [  358.721496] mtd_oobtest: verified up to eraseblock 768
    [  363.166881] mtd_oobtest: verified up to eraseblock 1024
    [  367.612694] mtd_oobtest: verified up to eraseblock 1280
    [  372.058211] mtd_oobtest: verified up to eraseblock 1536
    [  376.503820] mtd_oobtest: verified up to eraseblock 1792
    [  380.914843] mtd_oobtest: verified 2047 eraseblocks
    [  380.919660] mtd_oobtest: test 2 of 5
    [  384.202620] mtd_oobtest: writing OOBs of whole device
    [  384.247584] mtd_oobtest: written up to eraseblock 0
    [  394.305121] mtd_oobtest: written up to eraseblock 256
    [  404.342199] mtd_oobtest: written up to eraseblock 512
    [  414.374204] mtd_oobtest: written up to eraseblock 768
    [  424.409891] mtd_oobtest: written up to eraseblock 1024
    [  434.453378] mtd_oobtest: written up to eraseblock 1280
    [  444.494321] mtd_oobtest: written up to eraseblock 1536
    [  454.534480] mtd_oobtest: written up to eraseblock 1792
    [  464.490962] mtd_oobtest: written 2047 eraseblocks
    [  464.495681] mtd_oobtest: verifying all eraseblocks
    [  464.518015] mtd_oobtest: verified up to eraseblock 0
    [  468.955635] mtd_oobtest: verified up to eraseblock 256
    [  473.395502] mtd_oobtest: verified up to eraseblock 512
    [  477.834373] mtd_oobtest: verified up to eraseblock 768
    [  482.272717] mtd_oobtest: verified up to eraseblock 1024
    [  486.712148] mtd_oobtest: verified up to eraseblock 1280
    [  491.150704] mtd_oobtest: verified up to eraseblock 1536
    [  495.589439] mtd_oobtest: verified up to eraseblock 1792
    [  499.993138] mtd_oobtest: verified 2047 eraseblocks
    [  499.997951] mtd_oobtest: test 3 of 5
    [  503.404228] mtd_oobtest: writing OOBs of whole device
    [  503.448822] mtd_oobtest: written up to eraseblock 0
    [  513.480773] mtd_oobtest: written up to eraseblock 256
    [  523.489361] mtd_oobtest: written up to eraseblock 512
    [  533.506896] mtd_oobtest: written up to eraseblock 768
    [  543.506268] mtd_oobtest: written up to eraseblock 1024
    [  553.506503] mtd_oobtest: written up to eraseblock 1280
    [  563.511266] mtd_oobtest: written up to eraseblock 1536
    [  573.519567] mtd_oobtest: written up to eraseblock 1792
    [  583.455111] mtd_oobtest: written 2047 eraseblocks
    [  583.459837] mtd_oobtest: verifying all eraseblocks
    [  583.499358] mtd_oobtest: verified up to eraseblock 0
    [  592.382953] mtd_oobtest: verified up to eraseblock 256
    [  601.267297] mtd_oobtest: verified up to eraseblock 512
    [  610.150907] mtd_oobtest: verified up to eraseblock 768
    [  619.034702] mtd_oobtest: verified up to eraseblock 1024
    [  627.919683] mtd_oobtest: verified up to eraseblock 1280
    [  636.821168] mtd_oobtest: verified up to eraseblock 1536
    [  645.705487] mtd_oobtest: verified up to eraseblock 1792
    [  654.520336] mtd_oobtest: verified 2047 eraseblocks
    [  654.525134] mtd_oobtest: test 4 of 5
    [  657.578146] mtd_oobtest: attempting to start write past end of OOB
    [  657.584336] mtd_oobtest: an error is expected...
    [  657.588974] mtd_oobtest: error occurred as expected
    [  657.593848] mtd_oobtest: attempting to start read past end of OOB
    [  657.599953] mtd_oobtest: an error is expected...
    [  657.604569] mtd_oobtest: error occurred as expected
    [  657.609450] mtd_oobtest: attempting to write past end of device
    [  657.615367] mtd_oobtest: an error is expected...
    [  657.619990] mtd_oobtest: error occurred as expected
    [  657.624864] mtd_oobtest: attempting to read past end of device
    [  657.630715] mtd_oobtest: an error is expected...
    [  657.635333] mtd_oobtest: error occurred as expected
    [  657.641043] mtd_oobtest: attempting to write past end of device
    [  657.646966] mtd_oobtest: an error is expected...
    [  657.651574] mtd_oobtest: error occurred as expected
    [  657.656451] mtd_oobtest: attempting to read past end of device
    [  657.662277] mtd_oobtest: an error is expected...
    [  657.666901] mtd_oobtest: error occurred as expected
    [  657.671774] mtd_oobtest: test 5 of 5
    [  659.382333] mtd_oobtest: writing OOBs of whole device
    [  659.388056] mtd_oobtest: written up to eraseblock 0
    [  659.393526] mtd_oobtest: written up to eraseblock 0
    [  659.704525] mtd_oobtest: written up to eraseblock 256
    [  659.710187] mtd_oobtest: written up to eraseblock 256
    [  660.021093] mtd_oobtest: written up to eraseblock 512
    [  660.026752] mtd_oobtest: written up to eraseblock 512
    [  660.338427] mtd_oobtest: written up to eraseblock 768
    [  660.344048] mtd_oobtest: written up to eraseblock 768
    [  660.655718] mtd_oobtest: written up to eraseblock 1024
    [  660.661462] mtd_oobtest: written up to eraseblock 1024
    [  660.970676] mtd_oobtest: written up to eraseblock 1280
    [  660.976386] mtd_oobtest: written up to eraseblock 1280
    [  661.286858] mtd_oobtest: written up to eraseblock 1536
    [  661.292587] mtd_oobtest: written up to eraseblock 1536
    [  661.605397] mtd_oobtest: written up to eraseblock 1792
    [  661.611142] mtd_oobtest: written up to eraseblock 1792
    [  661.918754] mtd_oobtest: written 2046 eraseblocks
    [  661.923458] mtd_oobtest: verifying all eraseblocks
    [  661.928812] mtd_oobtest: verified up to eraseblock 0
    [  662.072499] mtd_oobtest: verified up to eraseblock 256
    [  662.216152] mtd_oobtest: verified up to eraseblock 512
    [  662.359956] mtd_oobtest: verified up to eraseblock 768
    [  662.503238] mtd_oobtest: verified up to eraseblock 1024
    [  662.646847] mtd_oobtest: verified up to eraseblock 1280
    [  662.790603] mtd_oobtest: verified up to eraseblock 1536
    [  662.934269] mtd_oobtest: verified up to eraseblock 1792
    [  663.076329] mtd_oobtest: verified 2046 eraseblocks
    [  663.081114] mtd_oobtest: finished with 0 errors
    [  663.085647] =================================================

    root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_pagetest.ko dev=1
    [ 1142.213082] 
    [ 1142.214590] =================================================
    [ 1142.220433] mtd_pagetest: MTD device: 1
    [ 1142.224278] mtd_pagetest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 1142.238388] mtd_test: scanning for bad eraseblocks
    [ 1142.243536] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 1142.248935] mtd_pagetest: erasing whole device
    [ 1143.962562] mtd_pagetest: erased 2047 eraseblocks
    [ 1143.967301] mtd_pagetest: writing whole device
    [ 1144.011729] mtd_pagetest: written up to eraseblock 0
    [ 1154.137933] mtd_pagetest: written up to eraseblock 256
    [ 1164.265201] mtd_pagetest: written up to eraseblock 512
    [ 1174.393365] mtd_pagetest: written up to eraseblock 768
    [ 1184.525700] mtd_pagetest: written up to eraseblock 1024
    [ 1194.650920] mtd_pagetest: written up to eraseblock 1280
    [ 1204.773676] mtd_pagetest: written up to eraseblock 1536
    [ 1214.896934] mtd_pagetest: written up to eraseblock 1792
    [ 1224.942600] mtd_pagetest: written 2047 eraseblocks
    [ 1224.947410] mtd_pagetest: verifying all eraseblocks
    [ 1225.053133] mtd_pagetest: verified up to eraseblock 0
    [ 1250.760034] mtd_pagetest: verified up to eraseblock 256
    [ 1276.448242] mtd_pagetest: verified up to eraseblock 512
    [ 1302.138825] mtd_pagetest: verified up to eraseblock 768
    [ 1327.824020] mtd_pagetest: verified up to eraseblock 1024
    [ 1353.532178] mtd_pagetest: verified up to eraseblock 1280
    [ 1379.234385] mtd_pagetest: verified up to eraseblock 1536
    [ 1404.943865] mtd_pagetest: verified up to eraseblock 1792
    [ 1430.468816] mtd_pagetest: verified 2047 eraseblocks
    [ 1430.473702] mtd_pagetest: crosstest
    [ 1430.477717] mtd_pagetest: reading page at 0x0
    [ 1430.482328] mtd_pagetest: reading page at 0xffdf800
    [ 1430.487469] mtd_pagetest: reading page at 0x0
    [ 1430.492084] mtd_pagetest: verifying pages read at 0x0 match
    [ 1430.497668] mtd_pagetest: crosstest ok
    [ 1430.501409] mtd_pagetest: erasecrosstest
    [ 1430.505323] mtd_pagetest: erasing block 0
    [ 1430.511511] mtd_pagetest: writing 1st page of block 0
    [ 1430.517166] mtd_pagetest: reading 1st page of block 0
    [ 1430.522505] mtd_pagetest: verifying 1st page of block 0
    [ 1430.527739] mtd_pagetest: erasing block 0
    [ 1430.532565] mtd_pagetest: writing 1st page of block 0
    [ 1430.538229] mtd_pagetest: erasing block 2046
    [ 1430.544181] mtd_pagetest: reading 1st page of block 0
    [ 1430.549498] mtd_pagetest: verifying 1st page of block 0
    [ 1430.554718] mtd_pagetest: erasecrosstest ok
    [ 1430.558900] mtd_pagetest: erasetest
    [ 1430.562381] mtd_pagetest: erasing block 0
    [ 1430.567208] mtd_pagetest: writing 1st page of block 0
    [ 1430.572858] mtd_pagetest: erasing block 0
    [ 1430.577680] mtd_pagetest: reading 1st page of block 0
    [ 1430.582990] mtd_pagetest: verifying 1st page of block 0 is all 0xff
    [ 1430.589279] mtd_pagetest: erasetest ok
    [ 1430.593023] mtd_pagetest: finished with 0 errors
    [ 1430.597651] =================================================

    root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_readtest.ko dev=1
    [ 1478.691648] 
    [ 1478.693158] =================================================
    [ 1478.698981] mtd_readtest: MTD device: 1
    [ 1478.702829] mtd_readtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 1478.716939] mtd_test: scanning for bad eraseblocks
    [ 1478.722072] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 1478.727475] mtd_readtest: testing page read
    [ 1548.352125] mtd_readtest: finished
    [ 1548.355553] =================================================

    root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_speedtest.ko dev=1
    [ 1617.353002] 
    [ 1617.354511] =================================================
    [ 1617.360332] mtd_speedtest: MTD device: 1
    [ 1617.364258] mtd_speedtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 1617.380150] mtd_test: scanning for bad eraseblocks
    [ 1617.385428] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 1621.021861] mtd_speedtest: testing eraseblock write speed
    [ 1700.915306] mtd_speedtest: eraseblock write speed is 3279 KiB/s
    [ 1700.921250] mtd_speedtest: testing eraseblock read speed
    [ 1734.931886] mtd_speedtest: eraseblock read speed is 7705 KiB/s
    [ 1738.682742] mtd_speedtest: testing page write speed
    [ 1818.818644] mtd_speedtest: page write speed is 3269 KiB/s
    [ 1818.824058] mtd_speedtest: testing page read speed
    [ 1852.913595] mtd_speedtest: page read speed is 7687 KiB/s
    [ 1856.674492] mtd_speedtest: testing 2 page write speed
    [ 1936.437284] mtd_speedtest: 2 page write speed is 3285 KiB/s
    [ 1936.442869] mtd_speedtest: testing 2 page read speed
    [ 1970.498124] mtd_speedtest: 2 page read speed is 7694 KiB/s
    [ 1970.503624] mtd_speedtest: Testing erase speed
    [ 1974.343389] mtd_speedtest: erase speed is 68316 KiB/s
    [ 1974.348479] mtd_speedtest: Testing 2x multi-block erase speed
    [ 1976.068855] mtd_speedtest: 2x multi-block erase speed is 152811 KiB/s
    [ 1976.075309] mtd_speedtest: Testing 4x multi-block erase speed
    [ 1977.790232] mtd_speedtest: 4x multi-block erase speed is 153301 KiB/s
    [ 1977.796693] mtd_speedtest: Testing 8x multi-block erase speed
    [ 1979.511905] mtd_speedtest: 8x multi-block erase speed is 153273 KiB/s
    [ 1979.518367] mtd_speedtest: Testing 16x multi-block erase speed
    [ 1981.230700] mtd_speedtest: 16x multi-block erase speed is 153539 KiB/s
    [ 1981.237249] mtd_speedtest: Testing 32x multi-block erase speed
    [ 1982.948381] mtd_speedtest: 32x multi-block erase speed is 153648 KiB/s
    [ 1982.954918] mtd_speedtest: Testing 64x multi-block erase speed
    [ 1984.665992] mtd_speedtest: 64x multi-block erase speed is 153655 KiB/s
    [ 1984.672531] mtd_speedtest: finished
    [ 1984.676054] =================================================

    root@OpenWrt:/lib/modules/6.6.79# insmod mtd_stresstest.ko dev=1
    [ 2190.651750] 
    [ 2190.653263] =================================================
    [ 2190.659087] mtd_stresstest: MTD device: 1
    [ 2190.663105] mtd_stresstest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 2190.679846] mtd_test: scanning for bad eraseblocks
    [ 2190.684981] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 2190.690389] mtd_stresstest: doing operations
    [ 2190.694655] mtd_stresstest: 0 operations done
    [ 2214.262705] mtd_stresstest: 1024 operations done
    [ 2239.019612] mtd_stresstest: 2048 operations done
    [ 2262.820899] mtd_stresstest: 3072 operations done
    [ 2285.061376] mtd_stresstest: 4096 operations done
    [ 2308.297322] mtd_stresstest: 5120 operations done
    [ 2330.530459] mtd_stresstest: 6144 operations done
    [ 2352.651759] mtd_stresstest: 7168 operations done
    [ 2375.188275] mtd_stresstest: 8192 operations done
    [ 2397.738174] mtd_stresstest: 9216 operations done
    [ 2414.792572] mtd_stresstest: finished, 10000 operations done
    [ 2414.798257] =================================================

4) Speed test of original driver (with patch to fix support of flashes
   with more than one plane per lun)

    root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_speedtest.ko dev=1
    [ 2894.142208] 
    [ 2894.143719] =================================================
    [ 2894.149556] mtd_speedtest: MTD device: 1
    [ 2894.153486] mtd_speedtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 2894.168888] mtd_test: scanning for bad eraseblocks
    [ 2894.174023] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 2897.500416] mtd_speedtest: testing eraseblock write speed
    [ 2977.807233] mtd_speedtest: eraseblock write speed is 3262 KiB/s
    [ 2977.813171] mtd_speedtest: testing eraseblock read speed
    [ 3013.906597] mtd_speedtest: eraseblock read speed is 7260 KiB/s
    [ 3017.440320] mtd_speedtest: testing page write speed
    [ 3097.833394] mtd_speedtest: page write speed is 3259 KiB/s
    [ 3097.838812] mtd_speedtest: testing page read speed
    [ 3134.004981] mtd_speedtest: page read speed is 7245 KiB/s
    [ 3137.538423] mtd_speedtest: testing 2 page write speed
    [ 3217.906288] mtd_speedtest: 2 page write speed is 3260 KiB/s
    [ 3217.911883] mtd_speedtest: testing 2 page read speed
    [ 3254.049757] mtd_speedtest: 2 page read speed is 7251 KiB/s
    [ 3254.055254] mtd_speedtest: Testing erase speed
    [ 3257.599146] mtd_speedtest: erase speed is 74027 KiB/s
    [ 3257.604213] mtd_speedtest: Testing 2x multi-block erase speed
    [ 3259.320945] mtd_speedtest: 2x multi-block erase speed is 153139 KiB/s
    [ 3259.327413] mtd_speedtest: Testing 4x multi-block erase speed
    [ 3261.044585] mtd_speedtest: 4x multi-block erase speed is 153098 KiB/s
    [ 3261.051047] mtd_speedtest: Testing 8x multi-block erase speed
    [ 3262.786520] mtd_speedtest: 8x multi-block erase speed is 151479 KiB/s
    [ 3262.792979] mtd_speedtest: Testing 16x multi-block erase speed
    [ 3264.509898] mtd_speedtest: 16x multi-block erase speed is 153130 KiB/s
    [ 3264.516454] mtd_speedtest: Testing 32x multi-block erase speed
    [ 3266.233403] mtd_speedtest: 32x multi-block erase speed is 153125 KiB/s
    [ 3266.239961] mtd_speedtest: Testing 64x multi-block erase speed
    [ 3267.957985] mtd_speedtest: 64x multi-block erase speed is 153029 KiB/s
    [ 3267.964525] mtd_speedtest: finished
    [ 3267.968039] =================================================

   It looks like a patched driver is a bit faster

    write speed: 3260 KiB/s  vs  3277 KiB/s
    read speed:  7252 KiB/s  vs  7695 KiB/s

Changes v2:
 * minor fix
 * add comments to code

Changes v3:
 * add patch to prevent continuous reading

Changes v4:
 * removed non-needed patch, other patch was a bit updated
 * treat zero buswidth as single wire buswidth (thanks to Jyothi Kumar Seerapu)
 * changes were tested with linux
 * test results was added

Mikhail Kshevetskiy (13):
  spi: airoha: return an error for continuous mode dirmap creation cases
  spi: airoha: remove unnecessary restriction length
  spi: airoha: add support of dual/quad wires spi modes
  spi: airoha: remove unnecessary switch to non-dma mode
  spi: airoha: unify dirmap read/write code
  spi: airoha: switch back to non-dma mode in the case of error
  spi: airoha: fix reading/writing of flashes with more than one plane
    per lun
  spi: airoha: support of dualio/quadio flash reading commands
  spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
  spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
    REG_SPI_NFI_SECCUS_SIZE registers
  spi: airoha: set custom sector size equal to flash page size
  spi: airoha: avoid reading flash page settings from SNFI registers
    during driver startup
  spi: airoha: buffer must be 0xff-ed before writing

 drivers/spi/spi-airoha-snfi.c | 510 +++++++++++++++++-----------------
 1 file changed, 262 insertions(+), 248 deletions(-)

-- 
2.50.1



^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH v4 01/13] spi: airoha: return an error for continuous mode dirmap creation cases
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  8:04               ` Lorenzo Bianconi
  2025-08-23  0:16             ` [PATCH v4 02/13] spi: airoha: remove unnecessary restriction length Mikhail Kshevetskiy
                               ` (12 subsequent siblings)
  13 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy, Frieder Schrempf

This driver can accelerate single page operations only, thus
continuous reading mode should not be used.

Continuous reading will use sizes up to the size of one erase block.
This size is much larger than the size of single flash page. Use this
difference to identify continuous reading and return an error.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 drivers/spi/spi-airoha-snfi.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index dbe640986825..043a03cd90a1 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -618,6 +618,10 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
 	if (desc->info.offset + desc->info.length > U32_MAX)
 		return -EINVAL;
 
+	/* continuous reading is not supported */
+	if (desc->info.length > SPI_NAND_CACHE_SIZE)
+		return -E2BIG;
+
 	if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))
 		return -EOPNOTSUPP;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 02/13] spi: airoha: remove unnecessary restriction length
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 01/13] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 03/13] spi: airoha: add support of dual/quad wires spi modes Mikhail Kshevetskiy
                               ` (11 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

The "length < 160" restriction is not needed because airoha_snand_write_data()
and airoha_snand_read_data() will properly handle data transfers above
SPI_MAX_TRANSFER_SIZE.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 043a03cd90a1..bcc464ec9c61 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -579,13 +579,6 @@ static int airoha_snand_adjust_op_size(struct spi_mem *mem,
 
 		if (op->data.nbytes > max_len)
 			op->data.nbytes = max_len;
-	} else {
-		max_len = 1 + op->addr.nbytes + op->dummy.nbytes;
-		if (max_len >= 160)
-			return -EOPNOTSUPP;
-
-		if (op->data.nbytes > 160 - max_len)
-			op->data.nbytes = 160 - max_len;
 	}
 
 	return 0;
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 03/13] spi: airoha: add support of dual/quad wires spi modes
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 01/13] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 02/13] spi: airoha: remove unnecessary restriction length Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  8:16               ` Lorenzo Bianconi
  2025-08-23  0:16             ` [PATCH v4 04/13] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
                               ` (10 subsequent siblings)
  13 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

This patch adds support of dual and quad wires spi modes. It will
speed up flash operations on the hardware with corresponding hardware
support.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 109 +++++++++++++++++++++++++---------
 1 file changed, 82 insertions(+), 27 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index bcc464ec9c61..d64a687c07de 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -192,6 +192,14 @@
 #define SPI_NAND_OP_RESET			0xff
 #define SPI_NAND_OP_DIE_SELECT			0xc2
 
+/* SNAND FIFO commands */
+#define SNAND_FIFO_TX_BUSWIDTH_SINGLE		0x08
+#define SNAND_FIFO_TX_BUSWIDTH_DUAL		0x09
+#define SNAND_FIFO_TX_BUSWIDTH_QUAD		0x0a
+#define SNAND_FIFO_RX_BUSWIDTH_SINGLE		0x0c
+#define SNAND_FIFO_RX_BUSWIDTH_DUAL		0x0e
+#define SNAND_FIFO_RX_BUSWIDTH_QUAD		0x0f
+
 #define SPI_NAND_CACHE_SIZE			(SZ_4K + SZ_256)
 #define SPI_MAX_TRANSFER_SIZE			511
 
@@ -387,10 +395,26 @@ static int airoha_snand_set_mode(struct airoha_snand_ctrl *as_ctrl,
 	return regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0);
 }
 
-static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
-				   const u8 *data, int len)
+static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl,
+				   const u8 *data, int len, int buswidth)
 {
 	int i, data_len;
+	u8 cmd;
+
+	switch (buswidth) {
+	case 0:
+	case 1:
+		cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE;
+		break;
+	case 2:
+		cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL;
+		break;
+	case 4:
+		cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	for (i = 0; i < len; i += data_len) {
 		int err;
@@ -409,16 +433,32 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
 	return 0;
 }
 
-static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
-				  int len)
+static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl,
+				  u8 *data, int len, int buswidth)
 {
 	int i, data_len;
+	u8 cmd;
+
+	switch (buswidth) {
+	case 0:
+	case 1:
+		cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE;
+		break;
+	case 2:
+		cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL;
+		break;
+	case 4:
+		cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	for (i = 0; i < len; i += data_len) {
 		int err;
 
 		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
-		err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
+		err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
 		if (err)
 			return err;
 
@@ -895,12 +935,27 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 static int airoha_snand_exec_op(struct spi_mem *mem,
 				const struct spi_mem_op *op)
 {
-	u8 data[8], cmd, opcode = op->cmd.opcode;
 	struct airoha_snand_ctrl *as_ctrl;
-	int i, err;
+	char buf[20], *data;
+	int i, err, op_len, addr_len, dummy_len;
 
 	as_ctrl = spi_controller_get_devdata(mem->spi->controller);
 
+	op_len = op->cmd.nbytes;
+	addr_len = op->addr.nbytes;
+	dummy_len = op->dummy.nbytes;
+
+	if (op_len + dummy_len + addr_len > sizeof(buf))
+		return -EIO;
+
+	data = buf;
+	for (i = 0; i < op_len; i++)
+		*data++ = op->cmd.opcode >> (8 * (op_len - i - 1));
+	for (i = 0; i < addr_len; i++)
+		*data++ = op->addr.val >> (8 * (addr_len - i - 1));
+	for (i = 0; i < dummy_len; i++)
+		*data++ = 0xff;
+
 	/* switch to manual mode */
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	if (err < 0)
@@ -911,40 +966,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
 		return err;
 
 	/* opcode */
-	err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));
+	data = buf;
+	err = airoha_snand_write_data(as_ctrl, data, op_len,
+				      op->cmd.buswidth);
 	if (err)
 		return err;
 
 	/* addr part */
-	cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
-	put_unaligned_be64(op->addr.val, data);
-
-	for (i = ARRAY_SIZE(data) - op->addr.nbytes;
-	     i < ARRAY_SIZE(data); i++) {
-		err = airoha_snand_write_data(as_ctrl, cmd, &data[i],
-					      sizeof(data[0]));
+	data += op_len;
+	if (addr_len) {
+		err = airoha_snand_write_data(as_ctrl, data, addr_len,
+					      op->addr.buswidth);
 		if (err)
 			return err;
 	}
 
 	/* dummy */
-	data[0] = 0xff;
-	for (i = 0; i < op->dummy.nbytes; i++) {
-		err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],
-					      sizeof(data[0]));
+	data += addr_len;
+	if (dummy_len) {
+		err = airoha_snand_write_data(as_ctrl, data, dummy_len,
+					      op->dummy.buswidth);
 		if (err)
 			return err;
 	}
 
 	/* data */
-	if (op->data.dir == SPI_MEM_DATA_IN) {
-		err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
-					     op->data.nbytes);
-		if (err)
-			return err;
-	} else {
-		err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,
-					      op->data.nbytes);
+	if (op->data.nbytes) {
+		if (op->data.dir == SPI_MEM_DATA_IN)
+			err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
+						     op->data.nbytes,
+						     op->data.buswidth);
+		else
+			err = airoha_snand_write_data(as_ctrl, op->data.buf.out,
+						      op->data.nbytes,
+						      op->data.buswidth);
 		if (err)
 			return err;
 	}
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 04/13] spi: airoha: remove unnecessary switch to non-dma mode
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (2 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 03/13] spi: airoha: add support of dual/quad wires spi modes Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  8:29               ` Lorenzo Bianconi
  2025-08-23  0:16             ` [PATCH v4 05/13] spi: airoha: unify dirmap read/write code Mikhail Kshevetskiy
                               ` (9 subsequent siblings)
  13 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

The code switches to dma at the start of dirmap operation and returns
to non-dma at the end of dirmap operation, so an additional switch to
non-dma at the start of dirmap write is not required.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index d64a687c07de..1ebf7def7ba7 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -812,9 +812,6 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
-	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
-	if (err < 0)
-		return err;
 
 	memcpy(txrx_buf + offs, buf, len);
 	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 05/13] spi: airoha: unify dirmap read/write code
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (3 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 04/13] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 06/13] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
                               ` (8 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

Makes dirmap writing looks similar to dirmap reading. Just a minor
refactoring, no behavior change is expected.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 49 ++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 1ebf7def7ba7..ce4026611e26 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -672,6 +672,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	u32 val, rd_mode;
 	int err;
 
+	as_ctrl = spi_controller_get_devdata(spi->controller);
+
 	switch (op->cmd.opcode) {
 	case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
 		rd_mode = 1;
@@ -684,7 +686,6 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 		break;
 	}
 
-	as_ctrl = spi_controller_get_devdata(spi->controller);
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
 	if (err < 0)
 		return err;
@@ -747,7 +748,7 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* trigger dma start read */
+	/* trigger dma reading */
 	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
 				SPI_NFI_RD_TRIG);
 	if (err)
@@ -803,37 +804,47 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 					 u64 offs, size_t len, const void *buf)
 {
-	struct spi_mem_op *op = &desc->info.op_tmpl;
 	struct spi_device *spi = desc->mem->spi;
 	u8 *txrx_buf = spi_get_ctldata(spi);
 	struct airoha_snand_ctrl *as_ctrl;
 	dma_addr_t dma_addr;
-	u32 wr_mode, val;
+	u32 wr_mode, val, opcode;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
+	opcode = desc->info.op_tmpl.cmd.opcode;
+	switch (opcode) {
+	case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
+	case SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE:
+		wr_mode = 0;
+		break;
+	case SPI_NAND_OP_PROGRAM_LOAD_QUAD:
+	case SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD:
+		wr_mode = 2;
+		break;
+	default:
+		/* unknown opcode */
+		return -EOPNOTSUPP;
+	}
+
 	memcpy(txrx_buf + offs, buf, len);
-	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
-				  DMA_TO_DEVICE);
-	err = dma_mapping_error(as_ctrl->dev, dma_addr);
-	if (err)
-		return err;
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
 	if (err < 0)
-		goto error_dma_unmap;
+		return err;
 
 	err = airoha_snand_nfi_config(as_ctrl);
 	if (err)
-		goto error_dma_unmap;
+		return err;
 
-	if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD ||
-	    op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD)
-		wr_mode = BIT(1);
-	else
-		wr_mode = 0;
+	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
+				  DMA_TO_DEVICE);
+	err = dma_mapping_error(as_ctrl->dev, dma_addr);
+	if (err)
+		return err;
 
+	/* set dma addr */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
 			   dma_addr);
 	if (err)
@@ -847,12 +858,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
+	/* set write command */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1,
-			   FIELD_PREP(SPI_NFI_PG_LOAD_CMD,
-				      op->cmd.opcode));
+			   FIELD_PREP(SPI_NFI_PG_LOAD_CMD, opcode));
 	if (err)
 		goto error_dma_unmap;
 
+	/* set write mode */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
 			   FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode));
 	if (err)
@@ -882,6 +894,7 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
+	/* trigger dma writing */
 	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
 				SPI_NFI_WR_TRIG);
 	if (err)
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 06/13] spi: airoha: switch back to non-dma mode in the case of error
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (4 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 05/13] spi: airoha: unify dirmap read/write code Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  8:34               ` Lorenzo Bianconi
  2025-08-23  0:16             ` [PATCH v4 07/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
                               ` (7 subsequent siblings)
  13 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

Current dirmap code does not switch back to non-dma mode in the case of
error. This is wrong.

This patch fixes dirmap read/write error path.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index ce4026611e26..3431a9c84679 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -692,13 +692,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 
 	err = airoha_snand_nfi_config(as_ctrl);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
 				  DMA_FROM_DEVICE);
 	err = dma_mapping_error(as_ctrl->dev, dma_addr);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	/* set dma addr */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
@@ -798,6 +798,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 error_dma_unmap:
 	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
 			 DMA_FROM_DEVICE);
+error_dma_mode_off:
+	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	return err;
 }
 
@@ -836,13 +838,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 
 	err = airoha_snand_nfi_config(as_ctrl);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
 				  DMA_TO_DEVICE);
 	err = dma_mapping_error(as_ctrl->dev, dma_addr);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	/* set dma addr */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
@@ -939,6 +941,8 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 error_dma_unmap:
 	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
 			 DMA_TO_DEVICE);
+error_dma_mode_off:
+	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	return err;
 }
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 07/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (5 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 06/13] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  8:36               ` Lorenzo Bianconi
  2025-08-23  0:16             ` [PATCH v4 08/13] spi: airoha: support of dualio/quadio flash reading commands Mikhail Kshevetskiy
                               ` (6 subsequent siblings)
  13 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

Reading UBI on the flash with more than one plane per lun will lead to
the following error:

ubi0: default fastmap WL pool size: 50
ubi0: attaching mtd2
ubi0 error: ubi_add_to_av: two LEBs with same sequence number 403
eraseblock attaching information dump:
        ec       1
        pnum     538
        lnum     0
        scrub    0
        sqnum    403
Volume identifier header dump:
        magic     55424921
        version   1
        vol_type  1
        copy_flag 0
        compat    0
        vol_id    1
        lnum      0
        data_size 0
        used_ebs  0
        data_pad  0
        sqnum     403
        hdr_crc   c8418a31
Volume identifier header hexdump:
00000000: 55 42 49 21 01 01 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  UBI!............................
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 93 00 00 00 00 00 00 00 00 00 00 00 00 c8 41 8a 31  .............................A.1
ubi0 error: ubi_attach_mtd_dev: failed to attach mtd2, error -22
UBI error: cannot attach mtd2
UBI error: cannot initialize UBI, error -22
UBI init error 22

looking to spi_mem_no_dirmap_read() code we'll see:

	static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
					      u64 offs, size_t len, void *buf)
	{
		struct spi_mem_op op = desc->info.op_tmpl;
		int ret;

// --- see here ---
		op.addr.val = desc->info.offset + offs;
//-----------------
		op.data.buf.in = buf;
		op.data.nbytes = len;
		ret = spi_mem_adjust_op_size(desc->mem, &op);
		if (ret)
		return ret;

		ret = spi_mem_exec_op(desc->mem, &op);
		if (ret)
			return ret;

		return op.data.nbytes;
	}

The similar happens for spi_mem_no_dirmap_write(). Thus spi read address should
take in the account the desc->info.offset.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 3431a9c84679..df2d3d717c00 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -727,8 +727,9 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* set read addr */
-	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);
+	/* set read addr: zero page offset + descriptor read offset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3,
+			   desc->info.offset);
 	if (err)
 		goto error_dma_unmap;
 
@@ -872,7 +873,9 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);
+	/* set write addr: zero page offset + descriptor write offset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2,
+			   desc->info.offset);
 	if (err)
 		goto error_dma_unmap;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 08/13] spi: airoha: support of dualio/quadio flash reading commands
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (6 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 07/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 09/13] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT Mikhail Kshevetskiy
                               ` (5 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

Airoha snfi spi controller supports acceleration of DUAL/QUAD
operations, but does not supports DUAL_IO/QUAD_IO operations.
Luckily DUAL/QUAD operations do the same as DUAL_IO/QUAD_IO ones,
so we can issue corresponding DUAL/QUAD operation instead of
DUAL_IO/QUAD_IO one.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index df2d3d717c00..4587147f9cd3 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -147,6 +147,8 @@
 #define SPI_NFI_CUS_SEC_SIZE_EN			BIT(16)
 
 #define REG_SPI_NFI_RD_CTL2			0x0510
+#define SPI_NFI_DATA_READ_CMD			GENMASK(7, 0)
+
 #define REG_SPI_NFI_RD_CTL3			0x0514
 
 #define REG_SPI_NFI_PG_CTL1			0x0524
@@ -179,7 +181,9 @@
 #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE	0x03
 #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST	0x0b
 #define SPI_NAND_OP_READ_FROM_CACHE_DUAL	0x3b
+#define SPI_NAND_OP_READ_FROM_CACHE_DUALIO	0xbb
 #define SPI_NAND_OP_READ_FROM_CACHE_QUAD	0x6b
+#define SPI_NAND_OP_READ_FROM_CACHE_QUADIO	0xeb
 #define SPI_NAND_OP_WRITE_ENABLE		0x06
 #define SPI_NAND_OP_WRITE_DISABLE		0x04
 #define SPI_NAND_OP_PROGRAM_LOAD_SINGLE		0x02
@@ -664,26 +668,38 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
 static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 					u64 offs, size_t len, void *buf)
 {
-	struct spi_mem_op *op = &desc->info.op_tmpl;
 	struct spi_device *spi = desc->mem->spi;
 	struct airoha_snand_ctrl *as_ctrl;
 	u8 *txrx_buf = spi_get_ctldata(spi);
 	dma_addr_t dma_addr;
-	u32 val, rd_mode;
+	u32 val, rd_mode, opcode;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
-	switch (op->cmd.opcode) {
+	/*
+	 * DUALIO and QUADIO opcodes are not supported by the spi controller,
+	 * replace them with supported opcodes.
+	 */
+	opcode = desc->info.op_tmpl.cmd.opcode;
+	switch (opcode) {
+	case SPI_NAND_OP_READ_FROM_CACHE_SINGLE:
+	case SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST:
+		rd_mode = 0;
+		break;
 	case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
+	case SPI_NAND_OP_READ_FROM_CACHE_DUALIO:
+		opcode = SPI_NAND_OP_READ_FROM_CACHE_DUAL;
 		rd_mode = 1;
 		break;
 	case SPI_NAND_OP_READ_FROM_CACHE_QUAD:
+	case SPI_NAND_OP_READ_FROM_CACHE_QUADIO:
+		opcode = SPI_NAND_OP_READ_FROM_CACHE_QUAD;
 		rd_mode = 2;
 		break;
 	default:
-		rd_mode = 0;
-		break;
+		/* unknown opcode */
+		return -EOPNOTSUPP;
 	}
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
@@ -717,7 +733,7 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 
 	/* set read command */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2,
-			   op->cmd.opcode);
+			   FIELD_PREP(SPI_NFI_DATA_READ_CMD, opcode));
 	if (err)
 		goto error_dma_unmap;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 09/13] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (7 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 08/13] spi: airoha: support of dualio/quadio flash reading commands Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 10/13] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers Mikhail Kshevetskiy
                               ` (4 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

spi-airoha-snfi uses custom sector size in REG_SPI_NFI_SECCUS_SIZE
register, so setting of page/oob sizes in REG_SPI_NFI_PAGEFMT is not
required.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 38 -----------------------------------
 1 file changed, 38 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 4587147f9cd3..c41485151787 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -518,44 +518,6 @@ static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
 	if (err)
 		return err;
 
-	/* page format */
-	switch (as_ctrl->nfi_cfg.spare_size) {
-	case 26:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x1);
-		break;
-	case 27:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x2);
-		break;
-	case 28:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x3);
-		break;
-	default:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x0);
-		break;
-	}
-
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,
-				 SPI_NFI_SPARE_SIZE, val);
-	if (err)
-		return err;
-
-	switch (as_ctrl->nfi_cfg.page_size) {
-	case 2048:
-		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x1);
-		break;
-	case 4096:
-		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x2);
-		break;
-	default:
-		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x0);
-		break;
-	}
-
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,
-				 SPI_NFI_PAGE_SIZE, val);
-	if (err)
-		return err;
-
 	/* sec num */
 	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 10/13] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (8 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 09/13] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 11/13] spi: airoha: set custom sector size equal to flash page size Mikhail Kshevetskiy
                               ` (3 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

This just reduce the number of modification of REG_SPI_NFI_CNFG and
REG_SPI_NFI_SECCUS_SIZE registers during dirmap operation.

This patch is a necessary step to avoid reading flash page settings
from SNFI registers during driver startup.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 134 +++++++++++++++++++++++++---------
 1 file changed, 101 insertions(+), 33 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index c41485151787..284ec5534693 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -668,7 +668,47 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err < 0)
 		return err;
 
-	err = airoha_snand_nfi_config(as_ctrl);
+	/* NFI reset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
+	if (err)
+		goto error_dma_mode_off;
+
+	/* NFI configure:
+	 *   - No AutoFDM (custom sector size (SECCUS) register will be used)
+	 *   - No SoC's hardware ECC (flash internal ECC will be used)
+	 *   - Use burst mode (faster, but requires 16 byte alignment for addresses)
+	 *   - Setup for reading (SPI_NFI_READ_MODE)
+	 *   - Setup reading command: FIELD_PREP(SPI_NFI_OPMODE, 6)
+	 *   - Use DMA instead of PIO for data reading
+	 *   - Use AHB bus for DMA transfer
+	 */
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_READ_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 SPI_NFI_HW_ECC_EN |
+				 SPI_NFI_AUTO_FDM_EN |
+				 SPI_NFI_OPMODE,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_READ_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 FIELD_PREP(SPI_NFI_OPMODE, 6));
+
+	/* Set number of sector will be read */
+	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+				 SPI_NFI_SEC_NUM, val);
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set custom sector size */
+	val = as_ctrl->nfi_cfg.sec_size;
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
+				 SPI_NFI_CUS_SEC_SIZE |
+				 SPI_NFI_CUS_SEC_SIZE_EN,
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
 
@@ -684,7 +724,14 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* set cust sec size */
+	/*
+	 * Setup transfer length
+	 * ---------------------
+	 * The following rule MUST be met:
+	 *     transfer_length =
+	 *        = NFI_SNF_MISC_CTL2.read_data_byte_number =
+	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+	 */
 	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
 	val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
@@ -711,18 +758,6 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* set nfi read */
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				 SPI_NFI_OPMODE,
-				 FIELD_PREP(SPI_NFI_OPMODE, 6));
-	if (err)
-		goto error_dma_unmap;
-
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-			      SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE);
-	if (err)
-		goto error_dma_unmap;
-
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0);
 	if (err)
 		goto error_dma_unmap;
@@ -815,7 +850,48 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err < 0)
 		return err;
 
-	err = airoha_snand_nfi_config(as_ctrl);
+	/* NFI reset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
+	if (err)
+		goto error_dma_mode_off;
+
+	/*
+	 * NFI configure:
+	 *   - No AutoFDM (custom sector size (SECCUS) register will be used)
+	 *   - No SoC's hardware ECC (flash internal ECC will be used)
+	 *   - Use burst mode (faster, but requires 16 byte alignment for addresses)
+	 *   - Setup for writing (SPI_NFI_READ_MODE bit is cleared)
+	 *   - Setup writing command: FIELD_PREP(SPI_NFI_OPMODE, 3)
+	 *   - Use DMA instead of PIO for data writing
+	 */
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_READ_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 SPI_NFI_HW_ECC_EN |
+				 SPI_NFI_AUTO_FDM_EN |
+				 SPI_NFI_OPMODE,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 FIELD_PREP(SPI_NFI_OPMODE, 3));
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set number of sector will be written */
+	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+				 SPI_NFI_SEC_NUM, val);
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set custom sector size */
+	val = as_ctrl->nfi_cfg.sec_size;
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
+				 SPI_NFI_CUS_SEC_SIZE |
+				 SPI_NFI_CUS_SEC_SIZE_EN,
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
 
@@ -831,8 +907,16 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM,
-			 as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
+	/*
+	 * Setup transfer length
+	 * ---------------------
+	 * The following rule MUST be met:
+	 *     transfer_length =
+	 *        = NFI_SNF_MISC_CTL2.write_data_byte_number =
+	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+	 */
+	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
+	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
 				 SPI_NFI_PROG_LOAD_BYTE_NUM, val);
@@ -857,22 +941,6 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				SPI_NFI_READ_MODE);
-	if (err)
-		goto error_dma_unmap;
-
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				 SPI_NFI_OPMODE,
-				 FIELD_PREP(SPI_NFI_OPMODE, 3));
-	if (err)
-		goto error_dma_unmap;
-
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-			      SPI_NFI_DMA_MODE);
-	if (err)
-		goto error_dma_unmap;
-
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80);
 	if (err)
 		goto error_dma_unmap;
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 11/13] spi: airoha: set custom sector size equal to flash page size
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (9 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 10/13] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 12/13] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup Mikhail Kshevetskiy
                               ` (2 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

Set custom sector size equal to flash page size including oob. Thus we
will always read a single sector. The maximum custom sector size is
8187, so all possible flash sector sizes are supported.

This patch is a necessary step to avoid reading flash page settings
from SNFI registers during driver startup.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 284ec5534693..bcecfb02497f 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -519,7 +519,7 @@ static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
 		return err;
 
 	/* sec num */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+	val = FIELD_PREP(SPI_NFI_SEC_NUM, 1);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
 				 SPI_NFI_SEC_NUM, val);
 	if (err)
@@ -532,7 +532,8 @@ static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
 		return err;
 
 	/* set cust sec size */
-	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, as_ctrl->nfi_cfg.sec_size);
+	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE,
+			 as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
 	return regmap_update_bits(as_ctrl->regmap_nfi,
 				  REG_SPI_NFI_SECCUS_SIZE,
 				  SPI_NFI_CUS_SEC_SIZE, val);
@@ -635,10 +636,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	u8 *txrx_buf = spi_get_ctldata(spi);
 	dma_addr_t dma_addr;
 	u32 val, rd_mode, opcode;
+	size_t bytes;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
+	bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
+
 	/*
 	 * DUALIO and QUADIO opcodes are not supported by the spi controller,
 	 * replace them with supported opcodes.
@@ -696,18 +700,17 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 				 FIELD_PREP(SPI_NFI_OPMODE, 6));
 
 	/* Set number of sector will be read */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-				 SPI_NFI_SEC_NUM, val);
+				 SPI_NFI_SEC_NUM,
+				 FIELD_PREP(SPI_NFI_SEC_NUM, 1));
 	if (err)
 		goto error_dma_mode_off;
 
 	/* Set custom sector size */
-	val = as_ctrl->nfi_cfg.sec_size;
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
 				 SPI_NFI_CUS_SEC_SIZE |
 				 SPI_NFI_CUS_SEC_SIZE_EN,
-				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) |
 				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
@@ -732,11 +735,10 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	 *        = NFI_SNF_MISC_CTL2.read_data_byte_number =
 	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
 	 */
-	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
-	val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
-				 SPI_NFI_READ_DATA_BYTE_NUM, val);
+				 SPI_NFI_READ_DATA_BYTE_NUM,
+				 FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, bytes));
 	if (err)
 		goto error_dma_unmap;
 
@@ -825,10 +827,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	struct airoha_snand_ctrl *as_ctrl;
 	dma_addr_t dma_addr;
 	u32 wr_mode, val, opcode;
+	size_t bytes;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
+	bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
+
 	opcode = desc->info.op_tmpl.cmd.opcode;
 	switch (opcode) {
 	case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
@@ -879,18 +884,17 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 		goto error_dma_mode_off;
 
 	/* Set number of sector will be written */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-				 SPI_NFI_SEC_NUM, val);
+				 SPI_NFI_SEC_NUM,
+				 FIELD_PREP(SPI_NFI_SEC_NUM, 1));
 	if (err)
 		goto error_dma_mode_off;
 
 	/* Set custom sector size */
-	val = as_ctrl->nfi_cfg.sec_size;
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
 				 SPI_NFI_CUS_SEC_SIZE |
 				 SPI_NFI_CUS_SEC_SIZE_EN,
-				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) |
 				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
@@ -915,11 +919,10 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	 *        = NFI_SNF_MISC_CTL2.write_data_byte_number =
 	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
 	 */
-	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
-	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
-				 SPI_NFI_PROG_LOAD_BYTE_NUM, val);
+				 SPI_NFI_PROG_LOAD_BYTE_NUM,
+				 FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, bytes));
 	if (err)
 		goto error_dma_unmap;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 12/13] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (10 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 11/13] spi: airoha: set custom sector size equal to flash page size Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23  0:16             ` [PATCH v4 13/13] spi: airoha: buffer must be 0xff-ed before writing Mikhail Kshevetskiy
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

The spinand driver do 3 type of dirmap requests:
 * read/write whole flash page without oob
   (offs = 0, len = page_size)
 * read/write whole flash page including oob
   (offs = 0, len = page_size + oob_size)
 * read/write oob area only
   (offs = page_size, len = oob_size)

The trick is:
 * read/write a single "sector"
 * set a custom sector size equal to offs + len. It's a bit safer to
   rounded up "sector size" value 64.
 * set the transfer length equal to custom sector size

And it works!

Thus we can remove a dirty hack that reads flash page settings from
SNFI registers during driver startup. Also airoha_snand_adjust_op_size()
function becomes unnecessary.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 115 ++--------------------------------
 1 file changed, 5 insertions(+), 110 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index bcecfb02497f..2388392ab5ea 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -223,13 +223,6 @@ struct airoha_snand_ctrl {
 	struct regmap *regmap_ctrl;
 	struct regmap *regmap_nfi;
 	struct clk *spi_clk;
-
-	struct {
-		size_t page_size;
-		size_t sec_size;
-		u8 sec_num;
-		u8 spare_size;
-	} nfi_cfg;
 };
 
 static int airoha_snand_set_fifo_op(struct airoha_snand_ctrl *as_ctrl,
@@ -490,55 +483,6 @@ static int airoha_snand_nfi_init(struct airoha_snand_ctrl *as_ctrl)
 				  SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN);
 }
 
-static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
-{
-	int err;
-	u32 val;
-
-	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
-	if (err)
-		return err;
-
-	/* auto FDM */
-	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				SPI_NFI_AUTO_FDM_EN);
-	if (err)
-		return err;
-
-	/* HW ECC */
-	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				SPI_NFI_HW_ECC_EN);
-	if (err)
-		return err;
-
-	/* DMA Burst */
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-			      SPI_NFI_DMA_BURST_EN);
-	if (err)
-		return err;
-
-	/* sec num */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, 1);
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-				 SPI_NFI_SEC_NUM, val);
-	if (err)
-		return err;
-
-	/* enable cust sec size */
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
-			      SPI_NFI_CUS_SEC_SIZE_EN);
-	if (err)
-		return err;
-
-	/* set cust sec size */
-	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE,
-			 as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
-	return regmap_update_bits(as_ctrl->regmap_nfi,
-				  REG_SPI_NFI_SECCUS_SIZE,
-				  SPI_NFI_CUS_SEC_SIZE, val);
-}
-
 static bool airoha_snand_is_page_ops(const struct spi_mem_op *op)
 {
 	if (op->addr.nbytes != 2)
@@ -571,26 +515,6 @@ static bool airoha_snand_is_page_ops(const struct spi_mem_op *op)
 	}
 }
 
-static int airoha_snand_adjust_op_size(struct spi_mem *mem,
-				       struct spi_mem_op *op)
-{
-	size_t max_len;
-
-	if (airoha_snand_is_page_ops(op)) {
-		struct airoha_snand_ctrl *as_ctrl;
-
-		as_ctrl = spi_controller_get_devdata(mem->spi->controller);
-		max_len = as_ctrl->nfi_cfg.sec_size;
-		max_len += as_ctrl->nfi_cfg.spare_size;
-		max_len *= as_ctrl->nfi_cfg.sec_num;
-
-		if (op->data.nbytes > max_len)
-			op->data.nbytes = max_len;
-	}
-
-	return 0;
-}
-
 static bool airoha_snand_supports_op(struct spi_mem *mem,
 				     const struct spi_mem_op *op)
 {
@@ -641,7 +565,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
-	bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
+	/* minimum oob size is 64 */
+	bytes = round_up(offs + len, 64);
 
 	/*
 	 * DUALIO and QUADIO opcodes are not supported by the spi controller,
@@ -832,7 +757,8 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
-	bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
+	/* minimum oob size is 64 */
+	bytes = round_up(offs + len, 64);
 
 	opcode = desc->info.op_tmpl.cmd.opcode;
 	switch (opcode) {
@@ -1074,7 +1000,6 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
 }
 
 static const struct spi_controller_mem_ops airoha_snand_mem_ops = {
-	.adjust_op_size = airoha_snand_adjust_op_size,
 	.supports_op = airoha_snand_supports_op,
 	.exec_op = airoha_snand_exec_op,
 	.dirmap_create = airoha_snand_dirmap_create,
@@ -1099,36 +1024,6 @@ static int airoha_snand_setup(struct spi_device *spi)
 	return 0;
 }
 
-static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl)
-{
-	u32 val, sec_size, sec_num;
-	int err;
-
-	err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, &val);
-	if (err)
-		return err;
-
-	sec_num = FIELD_GET(SPI_NFI_SEC_NUM, val);
-
-	err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, &val);
-	if (err)
-		return err;
-
-	sec_size = FIELD_GET(SPI_NFI_CUS_SEC_SIZE, val);
-
-	/* init default value */
-	as_ctrl->nfi_cfg.sec_size = sec_size;
-	as_ctrl->nfi_cfg.sec_num = sec_num;
-	as_ctrl->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024);
-	as_ctrl->nfi_cfg.spare_size = 16;
-
-	err = airoha_snand_nfi_init(as_ctrl);
-	if (err)
-		return err;
-
-	return airoha_snand_nfi_config(as_ctrl);
-}
-
 static const struct regmap_config spi_ctrl_regmap_config = {
 	.name		= "ctrl",
 	.reg_bits	= 32,
@@ -1202,7 +1097,7 @@ static int airoha_snand_probe(struct platform_device *pdev)
 	ctrl->setup = airoha_snand_setup;
 	device_set_node(&ctrl->dev, dev_fwnode(dev));
 
-	err = airoha_snand_nfi_setup(as_ctrl);
+	err = airoha_snand_nfi_init(as_ctrl);
 	if (err)
 		return err;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v4 13/13] spi: airoha: buffer must be 0xff-ed before writing
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (11 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 12/13] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup Mikhail Kshevetskiy
@ 2025-08-23  0:16             ` Mikhail Kshevetskiy
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23  0:16 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, Jyothi Kumar Seerapu,
	linux-arm-kernel, linux-spi, linux-kernel
  Cc: Mikhail Kshevetskiy

During writing, the entire flash page (including OOB) will be updated
with the values from the temporary buffer, so we need to fill the
untouched areas of the buffer with 0xff value to prevent accidental
data overwriting.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 2388392ab5ea..096c99347983 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -775,6 +775,7 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 		return -EOPNOTSUPP;
 	}
 
+	memset(txrx_buf, 0xff, bytes);
 	memcpy(txrx_buf + offs, buf, len);
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* Re: [PATCH v4 01/13] spi: airoha: return an error for continuous mode dirmap creation cases
  2025-08-23  0:16             ` [PATCH v4 01/13] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
@ 2025-08-23  8:04               ` Lorenzo Bianconi
  2025-08-23 13:52                 ` Mikhail Kshevetskiy
  0 siblings, 1 reply; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-23  8:04 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, Jyothi Kumar Seerapu, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf

[-- Attachment #1: Type: text/plain, Size: 1309 bytes --]

> This driver can accelerate single page operations only, thus
> continuous reading mode should not be used.
> 
> Continuous reading will use sizes up to the size of one erase block.
> This size is much larger than the size of single flash page. Use this
> difference to identify continuous reading and return an error.
> 
> Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
> Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>

I guess here we need to add the proper Fixes tag:

Fixes: a403997c12019 ("spi: airoha: add SPI-NAND Flash controller driver")

> ---
>  drivers/spi/spi-airoha-snfi.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
> index dbe640986825..043a03cd90a1 100644
> --- a/drivers/spi/spi-airoha-snfi.c
> +++ b/drivers/spi/spi-airoha-snfi.c
> @@ -618,6 +618,10 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
>  	if (desc->info.offset + desc->info.length > U32_MAX)
>  		return -EINVAL;
>  
> +	/* continuous reading is not supported */
> +	if (desc->info.length > SPI_NAND_CACHE_SIZE)
> +		return -E2BIG;
> +
>  	if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))
>  		return -EOPNOTSUPP;
>  
> -- 
> 2.50.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v4 03/13] spi: airoha: add support of dual/quad wires spi modes
  2025-08-23  0:16             ` [PATCH v4 03/13] spi: airoha: add support of dual/quad wires spi modes Mikhail Kshevetskiy
@ 2025-08-23  8:16               ` Lorenzo Bianconi
  2025-08-23 13:54                 ` Mikhail Kshevetskiy
  0 siblings, 1 reply; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-23  8:16 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, Jyothi Kumar Seerapu, linux-arm-kernel,
	linux-spi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4718 bytes --]

[...]
> -static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
> -				   const u8 *data, int len)
> +static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl,
> +				   const u8 *data, int len, int buswidth)
>  {
>  	int i, data_len;
> +	u8 cmd;
> +
> +	switch (buswidth) {
> +	case 0:
> +	case 1:
> +		cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE;
> +		break;
> +	case 2:
> +		cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL;
> +		break;
> +	case 4:
> +		cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}

Since this is used in airoha_snand_write_data() and in airoha_snand_read_data()
I guess you can define a routine for it.

>  
>  	for (i = 0; i < len; i += data_len) {
>  		int err;
> @@ -409,16 +433,32 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
>  	return 0;
>  }
>  
> -static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
> -				  int len)
> +static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl,
> +				  u8 *data, int len, int buswidth)
>  {
>  	int i, data_len;
> +	u8 cmd;
> +
> +	switch (buswidth) {
> +	case 0:
> +	case 1:
> +		cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE;
> +		break;
> +	case 2:
> +		cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL;
> +		break;
> +	case 4:
> +		cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
>  
>  	for (i = 0; i < len; i += data_len) {
>  		int err;
>  
>  		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
> -		err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
> +		err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
>  		if (err)
>  			return err;
>  
> @@ -895,12 +935,27 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
>  static int airoha_snand_exec_op(struct spi_mem *mem,
>  				const struct spi_mem_op *op)
>  {
> -	u8 data[8], cmd, opcode = op->cmd.opcode;
>  	struct airoha_snand_ctrl *as_ctrl;
> -	int i, err;
> +	char buf[20], *data;
> +	int i, err, op_len, addr_len, dummy_len;

nit: can you please respect the 'reverse christmas tree' here?

>  
>  	as_ctrl = spi_controller_get_devdata(mem->spi->controller);
>  
> +	op_len = op->cmd.nbytes;
> +	addr_len = op->addr.nbytes;
> +	dummy_len = op->dummy.nbytes;
> +
> +	if (op_len + dummy_len + addr_len > sizeof(buf))
> +		return -EIO;
> +
> +	data = buf;
> +	for (i = 0; i < op_len; i++)
> +		*data++ = op->cmd.opcode >> (8 * (op_len - i - 1));
> +	for (i = 0; i < addr_len; i++)
> +		*data++ = op->addr.val >> (8 * (addr_len - i - 1));
> +	for (i = 0; i < dummy_len; i++)
> +		*data++ = 0xff;
> +
>  	/* switch to manual mode */
>  	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
>  	if (err < 0)
> @@ -911,40 +966,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
>  		return err;
>  
>  	/* opcode */
> -	err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));
> +	data = buf;
> +	err = airoha_snand_write_data(as_ctrl, data, op_len,
> +				      op->cmd.buswidth);
>  	if (err)
>  		return err;
>  
>  	/* addr part */
> -	cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
> -	put_unaligned_be64(op->addr.val, data);
> -
> -	for (i = ARRAY_SIZE(data) - op->addr.nbytes;
> -	     i < ARRAY_SIZE(data); i++) {
> -		err = airoha_snand_write_data(as_ctrl, cmd, &data[i],
> -					      sizeof(data[0]));
> +	data += op_len;
> +	if (addr_len) {
> +		err = airoha_snand_write_data(as_ctrl, data, addr_len,
> +					      op->addr.buswidth);
>  		if (err)
>  			return err;
>  	}
>  
>  	/* dummy */
> -	data[0] = 0xff;
> -	for (i = 0; i < op->dummy.nbytes; i++) {
> -		err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],
> -					      sizeof(data[0]));
> +	data += addr_len;
> +	if (dummy_len) {
> +		err = airoha_snand_write_data(as_ctrl, data, dummy_len,
> +					      op->dummy.buswidth);
>  		if (err)
>  			return err;
>  	}
>  
>  	/* data */
> -	if (op->data.dir == SPI_MEM_DATA_IN) {
> -		err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
> -					     op->data.nbytes);
> -		if (err)
> -			return err;
> -	} else {
> -		err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,
> -					      op->data.nbytes);
> +	if (op->data.nbytes) {
> +		if (op->data.dir == SPI_MEM_DATA_IN)
> +			err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
> +						     op->data.nbytes,
> +						     op->data.buswidth);
> +		else
> +			err = airoha_snand_write_data(as_ctrl, op->data.buf.out,
> +						      op->data.nbytes,
> +						      op->data.buswidth);
>  		if (err)
>  			return err;
>  	}
> -- 
> 2.50.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v4 04/13] spi: airoha: remove unnecessary switch to non-dma mode
  2025-08-23  0:16             ` [PATCH v4 04/13] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
@ 2025-08-23  8:29               ` Lorenzo Bianconi
  0 siblings, 0 replies; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-23  8:29 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, Jyothi Kumar Seerapu, linux-arm-kernel,
	linux-spi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1032 bytes --]

> The code switches to dma at the start of dirmap operation and returns
> to non-dma at the end of dirmap operation, so an additional switch to
> non-dma at the start of dirmap write is not required.

Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>

> 
> Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
> ---
>  drivers/spi/spi-airoha-snfi.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
> index d64a687c07de..1ebf7def7ba7 100644
> --- a/drivers/spi/spi-airoha-snfi.c
> +++ b/drivers/spi/spi-airoha-snfi.c
> @@ -812,9 +812,6 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
>  	int err;
>  
>  	as_ctrl = spi_controller_get_devdata(spi->controller);
> -	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
> -	if (err < 0)
> -		return err;
>  
>  	memcpy(txrx_buf + offs, buf, len);
>  	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
> -- 
> 2.50.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v4 06/13] spi: airoha: switch back to non-dma mode in the case of error
  2025-08-23  0:16             ` [PATCH v4 06/13] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
@ 2025-08-23  8:34               ` Lorenzo Bianconi
  0 siblings, 0 replies; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-23  8:34 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, Jyothi Kumar Seerapu, linux-arm-kernel,
	linux-spi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2469 bytes --]

> Current dirmap code does not switch back to non-dma mode in the case of
> error. This is wrong.

Can you please add proper Fixes tag here? Probably to make backport easier,
this patch should be moved before patch 5/13. Anyway:

Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>

Regards,
Lorenzo

> 
> This patch fixes dirmap read/write error path.
> 
> Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
> ---
>  drivers/spi/spi-airoha-snfi.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
> index ce4026611e26..3431a9c84679 100644
> --- a/drivers/spi/spi-airoha-snfi.c
> +++ b/drivers/spi/spi-airoha-snfi.c
> @@ -692,13 +692,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
>  
>  	err = airoha_snand_nfi_config(as_ctrl);
>  	if (err)
> -		return err;
> +		goto error_dma_mode_off;
>  
>  	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
>  				  DMA_FROM_DEVICE);
>  	err = dma_mapping_error(as_ctrl->dev, dma_addr);
>  	if (err)
> -		return err;
> +		goto error_dma_mode_off;
>  
>  	/* set dma addr */
>  	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
> @@ -798,6 +798,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
>  error_dma_unmap:
>  	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
>  			 DMA_FROM_DEVICE);
> +error_dma_mode_off:
> +	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
>  	return err;
>  }
>  
> @@ -836,13 +838,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
>  
>  	err = airoha_snand_nfi_config(as_ctrl);
>  	if (err)
> -		return err;
> +		goto error_dma_mode_off;
>  
>  	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
>  				  DMA_TO_DEVICE);
>  	err = dma_mapping_error(as_ctrl->dev, dma_addr);
>  	if (err)
> -		return err;
> +		goto error_dma_mode_off;
>  
>  	/* set dma addr */
>  	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
> @@ -939,6 +941,8 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
>  error_dma_unmap:
>  	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
>  			 DMA_TO_DEVICE);
> +error_dma_mode_off:
> +	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
>  	return err;
>  }
>  
> -- 
> 2.50.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v4 07/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun
  2025-08-23  0:16             ` [PATCH v4 07/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
@ 2025-08-23  8:36               ` Lorenzo Bianconi
  0 siblings, 0 replies; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-23  8:36 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, Jyothi Kumar Seerapu, linux-arm-kernel,
	linux-spi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3279 bytes --]

> Reading UBI on the flash with more than one plane per lun will lead to
> the following error:
> 
> ubi0: default fastmap WL pool size: 50
> ubi0: attaching mtd2
> ubi0 error: ubi_add_to_av: two LEBs with same sequence number 403
> eraseblock attaching information dump:
>         ec       1
>         pnum     538
>         lnum     0
>         scrub    0
>         sqnum    403
> Volume identifier header dump:
>         magic     55424921
>         version   1
>         vol_type  1
>         copy_flag 0
>         compat    0
>         vol_id    1
>         lnum      0
>         data_size 0
>         used_ebs  0
>         data_pad  0
>         sqnum     403
>         hdr_crc   c8418a31
> Volume identifier header hexdump:
> 00000000: 55 42 49 21 01 01 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  UBI!............................
> 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 93 00 00 00 00 00 00 00 00 00 00 00 00 c8 41 8a 31  .............................A.1
> ubi0 error: ubi_attach_mtd_dev: failed to attach mtd2, error -22
> UBI error: cannot attach mtd2
> UBI error: cannot initialize UBI, error -22
> UBI init error 22
> 
> looking to spi_mem_no_dirmap_read() code we'll see:
> 
> 	static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
> 					      u64 offs, size_t len, void *buf)
> 	{
> 		struct spi_mem_op op = desc->info.op_tmpl;
> 		int ret;
> 
> // --- see here ---
> 		op.addr.val = desc->info.offset + offs;
> //-----------------
> 		op.data.buf.in = buf;
> 		op.data.nbytes = len;
> 		ret = spi_mem_adjust_op_size(desc->mem, &op);
> 		if (ret)
> 		return ret;
> 
> 		ret = spi_mem_exec_op(desc->mem, &op);
> 		if (ret)
> 			return ret;
> 
> 		return op.data.nbytes;
> 	}
> 
> The similar happens for spi_mem_no_dirmap_write(). Thus spi read address should
> take in the account the desc->info.offset.
> 
> Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>

Missing Fixes tag.

Regards,
Lorenzo

> ---
>  drivers/spi/spi-airoha-snfi.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
> index 3431a9c84679..df2d3d717c00 100644
> --- a/drivers/spi/spi-airoha-snfi.c
> +++ b/drivers/spi/spi-airoha-snfi.c
> @@ -727,8 +727,9 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
>  	if (err)
>  		goto error_dma_unmap;
>  
> -	/* set read addr */
> -	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);
> +	/* set read addr: zero page offset + descriptor read offset */
> +	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3,
> +			   desc->info.offset);
>  	if (err)
>  		goto error_dma_unmap;
>  
> @@ -872,7 +873,9 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
>  	if (err)
>  		goto error_dma_unmap;
>  
> -	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);
> +	/* set write addr: zero page offset + descriptor write offset */
> +	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2,
> +			   desc->info.offset);
>  	if (err)
>  		goto error_dma_unmap;
>  
> -- 
> 2.50.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v4 01/13] spi: airoha: return an error for continuous mode dirmap creation cases
  2025-08-23  8:04               ` Lorenzo Bianconi
@ 2025-08-23 13:52                 ` Mikhail Kshevetskiy
  0 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 13:52 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Ray Liu, Mark Brown, Jyothi Kumar Seerapu, linux-arm-kernel,
	linux-spi, linux-kernel, Frieder Schrempf


On 23.08.2025 11:04, Lorenzo Bianconi wrote:
>> This driver can accelerate single page operations only, thus
>> continuous reading mode should not be used.
>>
>> Continuous reading will use sizes up to the size of one erase block.
>> This size is much larger than the size of single flash page. Use this
>> difference to identify continuous reading and return an error.
>>
>> Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
>> Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> I guess here we need to add the proper Fixes tag:

Airoha spi driver was introduced in linux-6.10. Continuous reading mode
was introduced later in linux-6.12 (see: commit
631cfdd0520d19b7f4fc13b834fd9c8b46c6dbac). Continuous mode needs to be
agreed with spi controller driver because some spi drivers (like airoha
one) does not support it.

 So I don't know what should be specified in Fixes tag.

Mikhail

> Fixes: a403997c12019 ("spi: airoha: add SPI-NAND Flash controller driver")
>
>> ---
>>  drivers/spi/spi-airoha-snfi.c | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
>> index dbe640986825..043a03cd90a1 100644
>> --- a/drivers/spi/spi-airoha-snfi.c
>> +++ b/drivers/spi/spi-airoha-snfi.c
>> @@ -618,6 +618,10 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
>>  	if (desc->info.offset + desc->info.length > U32_MAX)
>>  		return -EINVAL;
>>  
>> +	/* continuous reading is not supported */
>> +	if (desc->info.length > SPI_NAND_CACHE_SIZE)
>> +		return -E2BIG;
>> +
>>  	if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))
>>  		return -EOPNOTSUPP;
>>  
>> -- 
>> 2.50.1
>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v4 03/13] spi: airoha: add support of dual/quad wires spi modes
  2025-08-23  8:16               ` Lorenzo Bianconi
@ 2025-08-23 13:54                 ` Mikhail Kshevetskiy
  2025-08-23 14:42                   ` Lorenzo Bianconi
  0 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 13:54 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Ray Liu, Mark Brown, Jyothi Kumar Seerapu, linux-arm-kernel,
	linux-spi, linux-kernel


On 23.08.2025 11:16, Lorenzo Bianconi wrote:
> [...]
>> -static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
>> -				   const u8 *data, int len)
>> +static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl,
>> +				   const u8 *data, int len, int buswidth)
>>  {
>>  	int i, data_len;
>> +	u8 cmd;
>> +
>> +	switch (buswidth) {
>> +	case 0:
>> +	case 1:
>> +		cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE;
>> +		break;
>> +	case 2:
>> +		cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL;
>> +		break;
>> +	case 4:
>> +		cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
> Since this is used in airoha_snand_write_data() and in airoha_snand_read_data()
> I guess you can define a routine for it.

It's not the same. It looks similar, but different constants are used
for rx and tx cases.

>
>>  
>>  	for (i = 0; i < len; i += data_len) {
>>  		int err;
>> @@ -409,16 +433,32 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
>>  	return 0;
>>  }
>>  
>> -static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
>> -				  int len)
>> +static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl,
>> +				  u8 *data, int len, int buswidth)
>>  {
>>  	int i, data_len;
>> +	u8 cmd;
>> +
>> +	switch (buswidth) {
>> +	case 0:
>> +	case 1:
>> +		cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE;
>> +		break;
>> +	case 2:
>> +		cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL;
>> +		break;
>> +	case 4:
>> +		cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>>  
>>  	for (i = 0; i < len; i += data_len) {
>>  		int err;
>>  
>>  		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
>> -		err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
>> +		err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
>>  		if (err)
>>  			return err;
>>  
>> @@ -895,12 +935,27 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
>>  static int airoha_snand_exec_op(struct spi_mem *mem,
>>  				const struct spi_mem_op *op)
>>  {
>> -	u8 data[8], cmd, opcode = op->cmd.opcode;
>>  	struct airoha_snand_ctrl *as_ctrl;
>> -	int i, err;
>> +	char buf[20], *data;
>> +	int i, err, op_len, addr_len, dummy_len;
> nit: can you please respect the 'reverse christmas tree' here?
will fix
>
>>  
>>  	as_ctrl = spi_controller_get_devdata(mem->spi->controller);
>>  
>> +	op_len = op->cmd.nbytes;
>> +	addr_len = op->addr.nbytes;
>> +	dummy_len = op->dummy.nbytes;
>> +
>> +	if (op_len + dummy_len + addr_len > sizeof(buf))
>> +		return -EIO;
>> +
>> +	data = buf;
>> +	for (i = 0; i < op_len; i++)
>> +		*data++ = op->cmd.opcode >> (8 * (op_len - i - 1));
>> +	for (i = 0; i < addr_len; i++)
>> +		*data++ = op->addr.val >> (8 * (addr_len - i - 1));
>> +	for (i = 0; i < dummy_len; i++)
>> +		*data++ = 0xff;
>> +
>>  	/* switch to manual mode */
>>  	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
>>  	if (err < 0)
>> @@ -911,40 +966,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
>>  		return err;
>>  
>>  	/* opcode */
>> -	err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));
>> +	data = buf;
>> +	err = airoha_snand_write_data(as_ctrl, data, op_len,
>> +				      op->cmd.buswidth);
>>  	if (err)
>>  		return err;
>>  
>>  	/* addr part */
>> -	cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
>> -	put_unaligned_be64(op->addr.val, data);
>> -
>> -	for (i = ARRAY_SIZE(data) - op->addr.nbytes;
>> -	     i < ARRAY_SIZE(data); i++) {
>> -		err = airoha_snand_write_data(as_ctrl, cmd, &data[i],
>> -					      sizeof(data[0]));
>> +	data += op_len;
>> +	if (addr_len) {
>> +		err = airoha_snand_write_data(as_ctrl, data, addr_len,
>> +					      op->addr.buswidth);
>>  		if (err)
>>  			return err;
>>  	}
>>  
>>  	/* dummy */
>> -	data[0] = 0xff;
>> -	for (i = 0; i < op->dummy.nbytes; i++) {
>> -		err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],
>> -					      sizeof(data[0]));
>> +	data += addr_len;
>> +	if (dummy_len) {
>> +		err = airoha_snand_write_data(as_ctrl, data, dummy_len,
>> +					      op->dummy.buswidth);
>>  		if (err)
>>  			return err;
>>  	}
>>  
>>  	/* data */
>> -	if (op->data.dir == SPI_MEM_DATA_IN) {
>> -		err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
>> -					     op->data.nbytes);
>> -		if (err)
>> -			return err;
>> -	} else {
>> -		err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,
>> -					      op->data.nbytes);
>> +	if (op->data.nbytes) {
>> +		if (op->data.dir == SPI_MEM_DATA_IN)
>> +			err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
>> +						     op->data.nbytes,
>> +						     op->data.buswidth);
>> +		else
>> +			err = airoha_snand_write_data(as_ctrl, op->data.buf.out,
>> +						      op->data.nbytes,
>> +						      op->data.buswidth);
>>  		if (err)
>>  			return err;
>>  	}
>> -- 
>> 2.50.1
>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v4 03/13] spi: airoha: add support of dual/quad wires spi modes
  2025-08-23 13:54                 ` Mikhail Kshevetskiy
@ 2025-08-23 14:42                   ` Lorenzo Bianconi
  0 siblings, 0 replies; 65+ messages in thread
From: Lorenzo Bianconi @ 2025-08-23 14:42 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Ray Liu, Mark Brown, Jyothi Kumar Seerapu, linux-arm-kernel,
	linux-spi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 5419 bytes --]

> 
> On 23.08.2025 11:16, Lorenzo Bianconi wrote:
> > [...]
> >> -static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
> >> -				   const u8 *data, int len)
> >> +static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl,
> >> +				   const u8 *data, int len, int buswidth)
> >>  {
> >>  	int i, data_len;
> >> +	u8 cmd;
> >> +
> >> +	switch (buswidth) {
> >> +	case 0:
> >> +	case 1:
> >> +		cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE;
> >> +		break;
> >> +	case 2:
> >> +		cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL;
> >> +		break;
> >> +	case 4:
> >> +		cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD;
> >> +		break;
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> > Since this is used in airoha_snand_write_data() and in airoha_snand_read_data()
> > I guess you can define a routine for it.
> 
> It's not the same. It looks similar, but different constants are used
> for rx and tx cases.

ops, I missed TX vs RX.

Regards,
Lorenzo

> 
> >
> >>  
> >>  	for (i = 0; i < len; i += data_len) {
> >>  		int err;
> >> @@ -409,16 +433,32 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
> >>  	return 0;
> >>  }
> >>  
> >> -static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
> >> -				  int len)
> >> +static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl,
> >> +				  u8 *data, int len, int buswidth)
> >>  {
> >>  	int i, data_len;
> >> +	u8 cmd;
> >> +
> >> +	switch (buswidth) {
> >> +	case 0:
> >> +	case 1:
> >> +		cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE;
> >> +		break;
> >> +	case 2:
> >> +		cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL;
> >> +		break;
> >> +	case 4:
> >> +		cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD;
> >> +		break;
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> >>  
> >>  	for (i = 0; i < len; i += data_len) {
> >>  		int err;
> >>  
> >>  		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
> >> -		err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
> >> +		err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
> >>  		if (err)
> >>  			return err;
> >>  
> >> @@ -895,12 +935,27 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
> >>  static int airoha_snand_exec_op(struct spi_mem *mem,
> >>  				const struct spi_mem_op *op)
> >>  {
> >> -	u8 data[8], cmd, opcode = op->cmd.opcode;
> >>  	struct airoha_snand_ctrl *as_ctrl;
> >> -	int i, err;
> >> +	char buf[20], *data;
> >> +	int i, err, op_len, addr_len, dummy_len;
> > nit: can you please respect the 'reverse christmas tree' here?
> will fix
> >
> >>  
> >>  	as_ctrl = spi_controller_get_devdata(mem->spi->controller);
> >>  
> >> +	op_len = op->cmd.nbytes;
> >> +	addr_len = op->addr.nbytes;
> >> +	dummy_len = op->dummy.nbytes;
> >> +
> >> +	if (op_len + dummy_len + addr_len > sizeof(buf))
> >> +		return -EIO;
> >> +
> >> +	data = buf;
> >> +	for (i = 0; i < op_len; i++)
> >> +		*data++ = op->cmd.opcode >> (8 * (op_len - i - 1));
> >> +	for (i = 0; i < addr_len; i++)
> >> +		*data++ = op->addr.val >> (8 * (addr_len - i - 1));
> >> +	for (i = 0; i < dummy_len; i++)
> >> +		*data++ = 0xff;
> >> +
> >>  	/* switch to manual mode */
> >>  	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
> >>  	if (err < 0)
> >> @@ -911,40 +966,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
> >>  		return err;
> >>  
> >>  	/* opcode */
> >> -	err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));
> >> +	data = buf;
> >> +	err = airoha_snand_write_data(as_ctrl, data, op_len,
> >> +				      op->cmd.buswidth);
> >>  	if (err)
> >>  		return err;
> >>  
> >>  	/* addr part */
> >> -	cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
> >> -	put_unaligned_be64(op->addr.val, data);
> >> -
> >> -	for (i = ARRAY_SIZE(data) - op->addr.nbytes;
> >> -	     i < ARRAY_SIZE(data); i++) {
> >> -		err = airoha_snand_write_data(as_ctrl, cmd, &data[i],
> >> -					      sizeof(data[0]));
> >> +	data += op_len;
> >> +	if (addr_len) {
> >> +		err = airoha_snand_write_data(as_ctrl, data, addr_len,
> >> +					      op->addr.buswidth);
> >>  		if (err)
> >>  			return err;
> >>  	}
> >>  
> >>  	/* dummy */
> >> -	data[0] = 0xff;
> >> -	for (i = 0; i < op->dummy.nbytes; i++) {
> >> -		err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],
> >> -					      sizeof(data[0]));
> >> +	data += addr_len;
> >> +	if (dummy_len) {
> >> +		err = airoha_snand_write_data(as_ctrl, data, dummy_len,
> >> +					      op->dummy.buswidth);
> >>  		if (err)
> >>  			return err;
> >>  	}
> >>  
> >>  	/* data */
> >> -	if (op->data.dir == SPI_MEM_DATA_IN) {
> >> -		err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
> >> -					     op->data.nbytes);
> >> -		if (err)
> >> -			return err;
> >> -	} else {
> >> -		err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,
> >> -					      op->data.nbytes);
> >> +	if (op->data.nbytes) {
> >> +		if (op->data.dir == SPI_MEM_DATA_IN)
> >> +			err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
> >> +						     op->data.nbytes,
> >> +						     op->data.buswidth);
> >> +		else
> >> +			err = airoha_snand_write_data(as_ctrl, op->data.buf.out,
> >> +						      op->data.nbytes,
> >> +						      op->data.buswidth);
> >>  		if (err)
> >>  			return err;
> >>  	}
> >> -- 
> >> 2.50.1
> >>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH v5 00/13] spi: airoha: driver fixes & improvements
  2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
                               ` (12 preceding siblings ...)
  2025-08-23  0:16             ` [PATCH v4 13/13] spi: airoha: buffer must be 0xff-ed before writing Mikhail Kshevetskiy
@ 2025-08-23 16:01             ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 01/13] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
                                 ` (13 more replies)
  13 siblings, 14 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

This patch series greatly improve airoha snfi driver and fix a
number of serious bugs.

Fixed bugs:
 * Fix reading/writing of flashes with more than one plane per lun
 * Fill the buffer with 0xff before writing
 * Fix reading of flashes supporting continuous reading mode
 * Fix error paths

Improvements:
 * Add support of dual/quad wires spi modes in exec_op(). This also
   fix flash reading/writing if dirmap can't be created.
 * Support of dualio/quadio flash reading commands
 * Remove dirty hack that reads flash page settings from SNFI registers
   during driver startup

Patched kernel tests:

    root@OpenWrt:/lib/modules/6.6.79# insmod mtd_oobtest.ko dev=1
    [  263.191711] 
    [  263.193218] =================================================
    [  263.199014] mtd_oobtest: MTD device: 1
    [  263.202768] mtd_oobtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [  263.216791] mtd_test: scanning for bad eraseblocks
    [  263.221956] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [  263.227361] mtd_oobtest: test 1 of 5
    [  265.077216] mtd_oobtest: writing OOBs of whole device
    [  265.121767] mtd_oobtest: written up to eraseblock 0
    [  275.174147] mtd_oobtest: written up to eraseblock 256
    [  285.210279] mtd_oobtest: written up to eraseblock 512
    [  295.241724] mtd_oobtest: written up to eraseblock 768
    [  305.280167] mtd_oobtest: written up to eraseblock 1024
    [  315.326883] mtd_oobtest: written up to eraseblock 1280
    [  325.364049] mtd_oobtest: written up to eraseblock 1536
    [  335.398609] mtd_oobtest: written up to eraseblock 1792
    [  345.358981] mtd_oobtest: written 2047 eraseblocks
    [  345.363694] mtd_oobtest: verifying all eraseblocks
    [  345.386088] mtd_oobtest: verified up to eraseblock 0
    [  349.830833] mtd_oobtest: verified up to eraseblock 256
    [  354.276245] mtd_oobtest: verified up to eraseblock 512
    [  358.721496] mtd_oobtest: verified up to eraseblock 768
    [  363.166881] mtd_oobtest: verified up to eraseblock 1024
    [  367.612694] mtd_oobtest: verified up to eraseblock 1280
    [  372.058211] mtd_oobtest: verified up to eraseblock 1536
    [  376.503820] mtd_oobtest: verified up to eraseblock 1792
    [  380.914843] mtd_oobtest: verified 2047 eraseblocks
    [  380.919660] mtd_oobtest: test 2 of 5
    [  384.202620] mtd_oobtest: writing OOBs of whole device
    [  384.247584] mtd_oobtest: written up to eraseblock 0
    [  394.305121] mtd_oobtest: written up to eraseblock 256
    [  404.342199] mtd_oobtest: written up to eraseblock 512
    [  414.374204] mtd_oobtest: written up to eraseblock 768
    [  424.409891] mtd_oobtest: written up to eraseblock 1024
    [  434.453378] mtd_oobtest: written up to eraseblock 1280
    [  444.494321] mtd_oobtest: written up to eraseblock 1536
    [  454.534480] mtd_oobtest: written up to eraseblock 1792
    [  464.490962] mtd_oobtest: written 2047 eraseblocks
    [  464.495681] mtd_oobtest: verifying all eraseblocks
    [  464.518015] mtd_oobtest: verified up to eraseblock 0
    [  468.955635] mtd_oobtest: verified up to eraseblock 256
    [  473.395502] mtd_oobtest: verified up to eraseblock 512
    [  477.834373] mtd_oobtest: verified up to eraseblock 768
    [  482.272717] mtd_oobtest: verified up to eraseblock 1024
    [  486.712148] mtd_oobtest: verified up to eraseblock 1280
    [  491.150704] mtd_oobtest: verified up to eraseblock 1536
    [  495.589439] mtd_oobtest: verified up to eraseblock 1792
    [  499.993138] mtd_oobtest: verified 2047 eraseblocks
    [  499.997951] mtd_oobtest: test 3 of 5
    [  503.404228] mtd_oobtest: writing OOBs of whole device
    [  503.448822] mtd_oobtest: written up to eraseblock 0
    [  513.480773] mtd_oobtest: written up to eraseblock 256
    [  523.489361] mtd_oobtest: written up to eraseblock 512
    [  533.506896] mtd_oobtest: written up to eraseblock 768
    [  543.506268] mtd_oobtest: written up to eraseblock 1024
    [  553.506503] mtd_oobtest: written up to eraseblock 1280
    [  563.511266] mtd_oobtest: written up to eraseblock 1536
    [  573.519567] mtd_oobtest: written up to eraseblock 1792
    [  583.455111] mtd_oobtest: written 2047 eraseblocks
    [  583.459837] mtd_oobtest: verifying all eraseblocks
    [  583.499358] mtd_oobtest: verified up to eraseblock 0
    [  592.382953] mtd_oobtest: verified up to eraseblock 256
    [  601.267297] mtd_oobtest: verified up to eraseblock 512
    [  610.150907] mtd_oobtest: verified up to eraseblock 768
    [  619.034702] mtd_oobtest: verified up to eraseblock 1024
    [  627.919683] mtd_oobtest: verified up to eraseblock 1280
    [  636.821168] mtd_oobtest: verified up to eraseblock 1536
    [  645.705487] mtd_oobtest: verified up to eraseblock 1792
    [  654.520336] mtd_oobtest: verified 2047 eraseblocks
    [  654.525134] mtd_oobtest: test 4 of 5
    [  657.578146] mtd_oobtest: attempting to start write past end of OOB
    [  657.584336] mtd_oobtest: an error is expected...
    [  657.588974] mtd_oobtest: error occurred as expected
    [  657.593848] mtd_oobtest: attempting to start read past end of OOB
    [  657.599953] mtd_oobtest: an error is expected...
    [  657.604569] mtd_oobtest: error occurred as expected
    [  657.609450] mtd_oobtest: attempting to write past end of device
    [  657.615367] mtd_oobtest: an error is expected...
    [  657.619990] mtd_oobtest: error occurred as expected
    [  657.624864] mtd_oobtest: attempting to read past end of device
    [  657.630715] mtd_oobtest: an error is expected...
    [  657.635333] mtd_oobtest: error occurred as expected
    [  657.641043] mtd_oobtest: attempting to write past end of device
    [  657.646966] mtd_oobtest: an error is expected...
    [  657.651574] mtd_oobtest: error occurred as expected
    [  657.656451] mtd_oobtest: attempting to read past end of device
    [  657.662277] mtd_oobtest: an error is expected...
    [  657.666901] mtd_oobtest: error occurred as expected
    [  657.671774] mtd_oobtest: test 5 of 5
    [  659.382333] mtd_oobtest: writing OOBs of whole device
    [  659.388056] mtd_oobtest: written up to eraseblock 0
    [  659.393526] mtd_oobtest: written up to eraseblock 0
    [  659.704525] mtd_oobtest: written up to eraseblock 256
    [  659.710187] mtd_oobtest: written up to eraseblock 256
    [  660.021093] mtd_oobtest: written up to eraseblock 512
    [  660.026752] mtd_oobtest: written up to eraseblock 512
    [  660.338427] mtd_oobtest: written up to eraseblock 768
    [  660.344048] mtd_oobtest: written up to eraseblock 768
    [  660.655718] mtd_oobtest: written up to eraseblock 1024
    [  660.661462] mtd_oobtest: written up to eraseblock 1024
    [  660.970676] mtd_oobtest: written up to eraseblock 1280
    [  660.976386] mtd_oobtest: written up to eraseblock 1280
    [  661.286858] mtd_oobtest: written up to eraseblock 1536
    [  661.292587] mtd_oobtest: written up to eraseblock 1536
    [  661.605397] mtd_oobtest: written up to eraseblock 1792
    [  661.611142] mtd_oobtest: written up to eraseblock 1792
    [  661.918754] mtd_oobtest: written 2046 eraseblocks
    [  661.923458] mtd_oobtest: verifying all eraseblocks
    [  661.928812] mtd_oobtest: verified up to eraseblock 0
    [  662.072499] mtd_oobtest: verified up to eraseblock 256
    [  662.216152] mtd_oobtest: verified up to eraseblock 512
    [  662.359956] mtd_oobtest: verified up to eraseblock 768
    [  662.503238] mtd_oobtest: verified up to eraseblock 1024
    [  662.646847] mtd_oobtest: verified up to eraseblock 1280
    [  662.790603] mtd_oobtest: verified up to eraseblock 1536
    [  662.934269] mtd_oobtest: verified up to eraseblock 1792
    [  663.076329] mtd_oobtest: verified 2046 eraseblocks
    [  663.081114] mtd_oobtest: finished with 0 errors
    [  663.085647] =================================================

    root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_pagetest.ko dev=1
    [ 1142.213082] 
    [ 1142.214590] =================================================
    [ 1142.220433] mtd_pagetest: MTD device: 1
    [ 1142.224278] mtd_pagetest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 1142.238388] mtd_test: scanning for bad eraseblocks
    [ 1142.243536] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 1142.248935] mtd_pagetest: erasing whole device
    [ 1143.962562] mtd_pagetest: erased 2047 eraseblocks
    [ 1143.967301] mtd_pagetest: writing whole device
    [ 1144.011729] mtd_pagetest: written up to eraseblock 0
    [ 1154.137933] mtd_pagetest: written up to eraseblock 256
    [ 1164.265201] mtd_pagetest: written up to eraseblock 512
    [ 1174.393365] mtd_pagetest: written up to eraseblock 768
    [ 1184.525700] mtd_pagetest: written up to eraseblock 1024
    [ 1194.650920] mtd_pagetest: written up to eraseblock 1280
    [ 1204.773676] mtd_pagetest: written up to eraseblock 1536
    [ 1214.896934] mtd_pagetest: written up to eraseblock 1792
    [ 1224.942600] mtd_pagetest: written 2047 eraseblocks
    [ 1224.947410] mtd_pagetest: verifying all eraseblocks
    [ 1225.053133] mtd_pagetest: verified up to eraseblock 0
    [ 1250.760034] mtd_pagetest: verified up to eraseblock 256
    [ 1276.448242] mtd_pagetest: verified up to eraseblock 512
    [ 1302.138825] mtd_pagetest: verified up to eraseblock 768
    [ 1327.824020] mtd_pagetest: verified up to eraseblock 1024
    [ 1353.532178] mtd_pagetest: verified up to eraseblock 1280
    [ 1379.234385] mtd_pagetest: verified up to eraseblock 1536
    [ 1404.943865] mtd_pagetest: verified up to eraseblock 1792
    [ 1430.468816] mtd_pagetest: verified 2047 eraseblocks
    [ 1430.473702] mtd_pagetest: crosstest
    [ 1430.477717] mtd_pagetest: reading page at 0x0
    [ 1430.482328] mtd_pagetest: reading page at 0xffdf800
    [ 1430.487469] mtd_pagetest: reading page at 0x0
    [ 1430.492084] mtd_pagetest: verifying pages read at 0x0 match
    [ 1430.497668] mtd_pagetest: crosstest ok
    [ 1430.501409] mtd_pagetest: erasecrosstest
    [ 1430.505323] mtd_pagetest: erasing block 0
    [ 1430.511511] mtd_pagetest: writing 1st page of block 0
    [ 1430.517166] mtd_pagetest: reading 1st page of block 0
    [ 1430.522505] mtd_pagetest: verifying 1st page of block 0
    [ 1430.527739] mtd_pagetest: erasing block 0
    [ 1430.532565] mtd_pagetest: writing 1st page of block 0
    [ 1430.538229] mtd_pagetest: erasing block 2046
    [ 1430.544181] mtd_pagetest: reading 1st page of block 0
    [ 1430.549498] mtd_pagetest: verifying 1st page of block 0
    [ 1430.554718] mtd_pagetest: erasecrosstest ok
    [ 1430.558900] mtd_pagetest: erasetest
    [ 1430.562381] mtd_pagetest: erasing block 0
    [ 1430.567208] mtd_pagetest: writing 1st page of block 0
    [ 1430.572858] mtd_pagetest: erasing block 0
    [ 1430.577680] mtd_pagetest: reading 1st page of block 0
    [ 1430.582990] mtd_pagetest: verifying 1st page of block 0 is all 0xff
    [ 1430.589279] mtd_pagetest: erasetest ok
    [ 1430.593023] mtd_pagetest: finished with 0 errors
    [ 1430.597651] =================================================

    root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_readtest.ko dev=1
    [ 1478.691648] 
    [ 1478.693158] =================================================
    [ 1478.698981] mtd_readtest: MTD device: 1
    [ 1478.702829] mtd_readtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 1478.716939] mtd_test: scanning for bad eraseblocks
    [ 1478.722072] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 1478.727475] mtd_readtest: testing page read
    [ 1548.352125] mtd_readtest: finished
    [ 1548.355553] =================================================

    root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_speedtest.ko dev=1
    [ 1617.353002] 
    [ 1617.354511] =================================================
    [ 1617.360332] mtd_speedtest: MTD device: 1
    [ 1617.364258] mtd_speedtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 1617.380150] mtd_test: scanning for bad eraseblocks
    [ 1617.385428] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 1621.021861] mtd_speedtest: testing eraseblock write speed
    [ 1700.915306] mtd_speedtest: eraseblock write speed is 3279 KiB/s
    [ 1700.921250] mtd_speedtest: testing eraseblock read speed
    [ 1734.931886] mtd_speedtest: eraseblock read speed is 7705 KiB/s
    [ 1738.682742] mtd_speedtest: testing page write speed
    [ 1818.818644] mtd_speedtest: page write speed is 3269 KiB/s
    [ 1818.824058] mtd_speedtest: testing page read speed
    [ 1852.913595] mtd_speedtest: page read speed is 7687 KiB/s
    [ 1856.674492] mtd_speedtest: testing 2 page write speed
    [ 1936.437284] mtd_speedtest: 2 page write speed is 3285 KiB/s
    [ 1936.442869] mtd_speedtest: testing 2 page read speed
    [ 1970.498124] mtd_speedtest: 2 page read speed is 7694 KiB/s
    [ 1970.503624] mtd_speedtest: Testing erase speed
    [ 1974.343389] mtd_speedtest: erase speed is 68316 KiB/s
    [ 1974.348479] mtd_speedtest: Testing 2x multi-block erase speed
    [ 1976.068855] mtd_speedtest: 2x multi-block erase speed is 152811 KiB/s
    [ 1976.075309] mtd_speedtest: Testing 4x multi-block erase speed
    [ 1977.790232] mtd_speedtest: 4x multi-block erase speed is 153301 KiB/s
    [ 1977.796693] mtd_speedtest: Testing 8x multi-block erase speed
    [ 1979.511905] mtd_speedtest: 8x multi-block erase speed is 153273 KiB/s
    [ 1979.518367] mtd_speedtest: Testing 16x multi-block erase speed
    [ 1981.230700] mtd_speedtest: 16x multi-block erase speed is 153539 KiB/s
    [ 1981.237249] mtd_speedtest: Testing 32x multi-block erase speed
    [ 1982.948381] mtd_speedtest: 32x multi-block erase speed is 153648 KiB/s
    [ 1982.954918] mtd_speedtest: Testing 64x multi-block erase speed
    [ 1984.665992] mtd_speedtest: 64x multi-block erase speed is 153655 KiB/s
    [ 1984.672531] mtd_speedtest: finished
    [ 1984.676054] =================================================

    root@OpenWrt:/lib/modules/6.6.79# insmod mtd_stresstest.ko dev=1
    [ 2190.651750] 
    [ 2190.653263] =================================================
    [ 2190.659087] mtd_stresstest: MTD device: 1
    [ 2190.663105] mtd_stresstest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 2190.679846] mtd_test: scanning for bad eraseblocks
    [ 2190.684981] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 2190.690389] mtd_stresstest: doing operations
    [ 2190.694655] mtd_stresstest: 0 operations done
    [ 2214.262705] mtd_stresstest: 1024 operations done
    [ 2239.019612] mtd_stresstest: 2048 operations done
    [ 2262.820899] mtd_stresstest: 3072 operations done
    [ 2285.061376] mtd_stresstest: 4096 operations done
    [ 2308.297322] mtd_stresstest: 5120 operations done
    [ 2330.530459] mtd_stresstest: 6144 operations done
    [ 2352.651759] mtd_stresstest: 7168 operations done
    [ 2375.188275] mtd_stresstest: 8192 operations done
    [ 2397.738174] mtd_stresstest: 9216 operations done
    [ 2414.792572] mtd_stresstest: finished, 10000 operations done
    [ 2414.798257] =================================================

Speed test of original driver (with patch to fix support of flashes
with more than one plane per lun)

    root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_speedtest.ko dev=1
    [ 2894.142208] 
    [ 2894.143719] =================================================
    [ 2894.149556] mtd_speedtest: MTD device: 1
    [ 2894.153486] mtd_speedtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
    [ 2894.168888] mtd_test: scanning for bad eraseblocks
    [ 2894.174023] mtd_test: scanned 2047 eraseblocks, 0 are bad
    [ 2897.500416] mtd_speedtest: testing eraseblock write speed
    [ 2977.807233] mtd_speedtest: eraseblock write speed is 3262 KiB/s
    [ 2977.813171] mtd_speedtest: testing eraseblock read speed
    [ 3013.906597] mtd_speedtest: eraseblock read speed is 7260 KiB/s
    [ 3017.440320] mtd_speedtest: testing page write speed
    [ 3097.833394] mtd_speedtest: page write speed is 3259 KiB/s
    [ 3097.838812] mtd_speedtest: testing page read speed
    [ 3134.004981] mtd_speedtest: page read speed is 7245 KiB/s
    [ 3137.538423] mtd_speedtest: testing 2 page write speed
    [ 3217.906288] mtd_speedtest: 2 page write speed is 3260 KiB/s
    [ 3217.911883] mtd_speedtest: testing 2 page read speed
    [ 3254.049757] mtd_speedtest: 2 page read speed is 7251 KiB/s
    [ 3254.055254] mtd_speedtest: Testing erase speed
    [ 3257.599146] mtd_speedtest: erase speed is 74027 KiB/s
    [ 3257.604213] mtd_speedtest: Testing 2x multi-block erase speed
    [ 3259.320945] mtd_speedtest: 2x multi-block erase speed is 153139 KiB/s
    [ 3259.327413] mtd_speedtest: Testing 4x multi-block erase speed
    [ 3261.044585] mtd_speedtest: 4x multi-block erase speed is 153098 KiB/s
    [ 3261.051047] mtd_speedtest: Testing 8x multi-block erase speed
    [ 3262.786520] mtd_speedtest: 8x multi-block erase speed is 151479 KiB/s
    [ 3262.792979] mtd_speedtest: Testing 16x multi-block erase speed
    [ 3264.509898] mtd_speedtest: 16x multi-block erase speed is 153130 KiB/s
    [ 3264.516454] mtd_speedtest: Testing 32x multi-block erase speed
    [ 3266.233403] mtd_speedtest: 32x multi-block erase speed is 153125 KiB/s
    [ 3266.239961] mtd_speedtest: Testing 64x multi-block erase speed
    [ 3267.957985] mtd_speedtest: 64x multi-block erase speed is 153029 KiB/s
    [ 3267.964525] mtd_speedtest: finished
    [ 3267.968039] =================================================

It looks like a patched driver is a bit faster

write speed: 3260 KiB/s  vs  3277 KiB/s
read speed:  7252 KiB/s  vs  7695 KiB/s

Changes v2:
 * minor fix
 * add comments to code

Changes v3:
 * add patch to prevent continuous reading

Changes v4:
 * removed non-needed patch, other patch was a bit updated
 * treat zero buswidth as single wire buswidth (thanks to Jyothi Kumar Seerapu)
 * changes were tested with linux
 * test results was added

Changes v5:
 * reorder patches a bit
 * improve description of some patches
 * minor fixes & improvements

Mikhail Kshevetskiy (13):
  spi: airoha: return an error for continuous mode dirmap creation cases
  spi: airoha: remove unnecessary restriction length
  spi: airoha: add support of dual/quad wires spi modes to exec_op()
    handler
  spi: airoha: remove unnecessary switch to non-dma mode
  spi: airoha: switch back to non-dma mode in the case of error
  spi: airoha: fix reading/writing of flashes with more than one plane
    per lun
  spi: airoha: unify dirmap read/write code
  spi: airoha: support of dualio/quadio flash reading commands
  spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
  spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
    REG_SPI_NFI_SECCUS_SIZE registers
  spi: airoha: set custom sector size equal to flash page size
  spi: airoha: avoid reading flash page settings from SNFI registers
    during driver startup
  spi: airoha: buffer must be 0xff-ed before writing

 drivers/spi/spi-airoha-snfi.c | 510 ++++++++++++++++++----------------
 1 file changed, 263 insertions(+), 247 deletions(-)

-- 
2.50.1



^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH v5 01/13] spi: airoha: return an error for continuous mode dirmap creation cases
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 02/13] spi: airoha: remove unnecessary restriction length Mikhail Kshevetskiy
                                 ` (12 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy, Frieder Schrempf

This driver can accelerate single page operations only, thus
continuous reading mode should not be used.

Continuous reading will use sizes up to the size of one erase block.
This size is much larger than the size of single flash page. Use this
difference to identify continuous reading and return an error.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 drivers/spi/spi-airoha-snfi.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index dbe640986825..043a03cd90a1 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -618,6 +618,10 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
 	if (desc->info.offset + desc->info.length > U32_MAX)
 		return -EINVAL;
 
+	/* continuous reading is not supported */
+	if (desc->info.length > SPI_NAND_CACHE_SIZE)
+		return -E2BIG;
+
 	if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))
 		return -EOPNOTSUPP;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 02/13] spi: airoha: remove unnecessary restriction length
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 01/13] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 03/13] spi: airoha: add support of dual/quad wires spi modes to exec_op() handler Mikhail Kshevetskiy
                                 ` (11 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

The "length < 160" restriction is not needed because airoha_snand_write_data()
and airoha_snand_read_data() will properly handle data transfers above
SPI_MAX_TRANSFER_SIZE.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 043a03cd90a1..bcc464ec9c61 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -579,13 +579,6 @@ static int airoha_snand_adjust_op_size(struct spi_mem *mem,
 
 		if (op->data.nbytes > max_len)
 			op->data.nbytes = max_len;
-	} else {
-		max_len = 1 + op->addr.nbytes + op->dummy.nbytes;
-		if (max_len >= 160)
-			return -EOPNOTSUPP;
-
-		if (op->data.nbytes > 160 - max_len)
-			op->data.nbytes = 160 - max_len;
 	}
 
 	return 0;
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 03/13] spi: airoha: add support of dual/quad wires spi modes to exec_op() handler
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 01/13] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 02/13] spi: airoha: remove unnecessary restriction length Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 04/13] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
                                 ` (10 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

Booting without this patch and disabled dirmap support results in

[    2.980719] spi-nand spi0.0: Micron SPI NAND was found.
[    2.986040] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
[    2.994709] 2 fixed-partitions partitions found on MTD device spi0.0
[    3.001075] Creating 2 MTD partitions on "spi0.0":
[    3.005862] 0x000000000000-0x000000020000 : "bl2"
[    3.011272] 0x000000020000-0x000010000000 : "ubi"
...
[    6.195594] ubi0: attaching mtd1
[   13.338398] ubi0: scanning is finished
[   13.342188] ubi0 error: ubi_read_volume_table: the layout volume was not found
[   13.349784] ubi0 error: ubi_attach_mtd_dev: failed to attach mtd1, error -22
[   13.356897] UBI error: cannot attach mtd1

If dirmap is disabled or not supported in the spi driver, the dirmap requests
will be executed via exec_op() handler. Thus, if the hardware supports
dual/quad spi modes, then corresponding requests will be sent to exec_op()
handler. Current driver does not support such requests, so error is arrised.
As result the flash can't be read/write.

This patch adds support of dual and quad wires spi modes to exec_op() handler.

Fixes: a403997c12019 ("spi: airoha: add SPI-NAND Flash controller driver")
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 108 ++++++++++++++++++++++++++--------
 1 file changed, 82 insertions(+), 26 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index bcc464ec9c61..fffed26ff990 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -192,6 +192,14 @@
 #define SPI_NAND_OP_RESET			0xff
 #define SPI_NAND_OP_DIE_SELECT			0xc2
 
+/* SNAND FIFO commands */
+#define SNAND_FIFO_TX_BUSWIDTH_SINGLE		0x08
+#define SNAND_FIFO_TX_BUSWIDTH_DUAL		0x09
+#define SNAND_FIFO_TX_BUSWIDTH_QUAD		0x0a
+#define SNAND_FIFO_RX_BUSWIDTH_SINGLE		0x0c
+#define SNAND_FIFO_RX_BUSWIDTH_DUAL		0x0e
+#define SNAND_FIFO_RX_BUSWIDTH_QUAD		0x0f
+
 #define SPI_NAND_CACHE_SIZE			(SZ_4K + SZ_256)
 #define SPI_MAX_TRANSFER_SIZE			511
 
@@ -387,10 +395,26 @@ static int airoha_snand_set_mode(struct airoha_snand_ctrl *as_ctrl,
 	return regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0);
 }
 
-static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
-				   const u8 *data, int len)
+static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl,
+				   const u8 *data, int len, int buswidth)
 {
 	int i, data_len;
+	u8 cmd;
+
+	switch (buswidth) {
+	case 0:
+	case 1:
+		cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE;
+		break;
+	case 2:
+		cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL;
+		break;
+	case 4:
+		cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	for (i = 0; i < len; i += data_len) {
 		int err;
@@ -409,16 +433,32 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
 	return 0;
 }
 
-static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
-				  int len)
+static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl,
+				  u8 *data, int len, int buswidth)
 {
 	int i, data_len;
+	u8 cmd;
+
+	switch (buswidth) {
+	case 0:
+	case 1:
+		cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE;
+		break;
+	case 2:
+		cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL;
+		break;
+	case 4:
+		cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	for (i = 0; i < len; i += data_len) {
 		int err;
 
 		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
-		err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
+		err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
 		if (err)
 			return err;
 
@@ -895,12 +935,28 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 static int airoha_snand_exec_op(struct spi_mem *mem,
 				const struct spi_mem_op *op)
 {
-	u8 data[8], cmd, opcode = op->cmd.opcode;
 	struct airoha_snand_ctrl *as_ctrl;
+	int op_len, addr_len, dummy_len;
+	u8 buf[20], *data;
 	int i, err;
 
 	as_ctrl = spi_controller_get_devdata(mem->spi->controller);
 
+	op_len = op->cmd.nbytes;
+	addr_len = op->addr.nbytes;
+	dummy_len = op->dummy.nbytes;
+
+	if (op_len + dummy_len + addr_len > sizeof(buf))
+		return -EIO;
+
+	data = buf;
+	for (i = 0; i < op_len; i++)
+		*data++ = op->cmd.opcode >> (8 * (op_len - i - 1));
+	for (i = 0; i < addr_len; i++)
+		*data++ = op->addr.val >> (8 * (addr_len - i - 1));
+	for (i = 0; i < dummy_len; i++)
+		*data++ = 0xff;
+
 	/* switch to manual mode */
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	if (err < 0)
@@ -911,40 +967,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
 		return err;
 
 	/* opcode */
-	err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));
+	data = buf;
+	err = airoha_snand_write_data(as_ctrl, data, op_len,
+				      op->cmd.buswidth);
 	if (err)
 		return err;
 
 	/* addr part */
-	cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
-	put_unaligned_be64(op->addr.val, data);
-
-	for (i = ARRAY_SIZE(data) - op->addr.nbytes;
-	     i < ARRAY_SIZE(data); i++) {
-		err = airoha_snand_write_data(as_ctrl, cmd, &data[i],
-					      sizeof(data[0]));
+	data += op_len;
+	if (addr_len) {
+		err = airoha_snand_write_data(as_ctrl, data, addr_len,
+					      op->addr.buswidth);
 		if (err)
 			return err;
 	}
 
 	/* dummy */
-	data[0] = 0xff;
-	for (i = 0; i < op->dummy.nbytes; i++) {
-		err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],
-					      sizeof(data[0]));
+	data += addr_len;
+	if (dummy_len) {
+		err = airoha_snand_write_data(as_ctrl, data, dummy_len,
+					      op->dummy.buswidth);
 		if (err)
 			return err;
 	}
 
 	/* data */
-	if (op->data.dir == SPI_MEM_DATA_IN) {
-		err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
-					     op->data.nbytes);
-		if (err)
-			return err;
-	} else {
-		err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,
-					      op->data.nbytes);
+	if (op->data.nbytes) {
+		if (op->data.dir == SPI_MEM_DATA_IN)
+			err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
+						     op->data.nbytes,
+						     op->data.buswidth);
+		else
+			err = airoha_snand_write_data(as_ctrl, op->data.buf.out,
+						      op->data.nbytes,
+						      op->data.buswidth);
 		if (err)
 			return err;
 	}
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 04/13] spi: airoha: remove unnecessary switch to non-dma mode
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (2 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 03/13] spi: airoha: add support of dual/quad wires spi modes to exec_op() handler Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 05/13] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
                                 ` (9 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

The code switches to dma at the start of dirmap operation and returns
to non-dma at the end of dirmap operation, so an additional switch to
non-dma at the start of dirmap write is not required.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/spi/spi-airoha-snfi.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index fffed26ff990..2d86dc62dbde 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -812,9 +812,6 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
-	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
-	if (err < 0)
-		return err;
 
 	memcpy(txrx_buf + offs, buf, len);
 	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 05/13] spi: airoha: switch back to non-dma mode in the case of error
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (3 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 04/13] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 06/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
                                 ` (8 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

Current dirmap code does not switch back to non-dma mode in the case of
error. This is wrong.

This patch fixes dirmap read/write error path.

Fixes: a403997c12019 ("spi: airoha: add SPI-NAND Flash controller driver")
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/spi/spi-airoha-snfi.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 2d86dc62dbde..a39c3ab4af5c 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -691,13 +691,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 
 	err = airoha_snand_nfi_config(as_ctrl);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
 				  DMA_FROM_DEVICE);
 	err = dma_mapping_error(as_ctrl->dev, dma_addr);
 	if (err)
-		return err;
+		goto error_dma_mode_off;
 
 	/* set dma addr */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
@@ -797,6 +797,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 error_dma_unmap:
 	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
 			 DMA_FROM_DEVICE);
+error_dma_mode_off:
+	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	return err;
 }
 
@@ -926,6 +928,7 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 error_dma_unmap:
 	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
 			 DMA_TO_DEVICE);
+	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	return err;
 }
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 06/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (4 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 05/13] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 07/13] spi: airoha: unify dirmap read/write code Mikhail Kshevetskiy
                                 ` (7 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

Attaching UBI on the flash with more than one plane per lun will lead to
the following error:

[    2.980989] spi-nand spi0.0: Micron SPI NAND was found.
[    2.986309] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
[    2.994978] 2 fixed-partitions partitions found on MTD device spi0.0
[    3.001350] Creating 2 MTD partitions on "spi0.0":
[    3.006159] 0x000000000000-0x000000020000 : "bl2"
[    3.011663] 0x000000020000-0x000010000000 : "ubi"
...
[    6.391748] ubi0: attaching mtd1
[    6.412545] ubi0 error: ubi_attach: PEB 0 contains corrupted VID header, and the data does not contain all 0xFF
[    6.422677] ubi0 error: ubi_attach: this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection
[    6.434249] Volume identifier header dump:
[    6.438349]     magic     55424923
[    6.441482]     version   1
[    6.444007]     vol_type  0
[    6.446539]     copy_flag 0
[    6.449068]     compat    0
[    6.451594]     vol_id    0
[    6.454120]     lnum      1
[    6.456651]     data_size 4096
[    6.459442]     used_ebs  1061644134
[    6.462748]     data_pad  0
[    6.465274]     sqnum     0
[    6.467805]     hdr_crc   61169820
[    6.470943] Volume identifier header hexdump:
[    6.475308] hexdump of PEB 0 offset 4096, length 126976
[    6.507391] ubi0 warning: ubi_attach: valid VID header but corrupted EC header at PEB 4
[    6.515415] ubi0 error: ubi_compare_lebs: unsupported on-flash UBI format
[    6.522222] ubi0 error: ubi_attach_mtd_dev: failed to attach mtd1, error -22
[    6.529294] UBI error: cannot attach mtd1

Non dirmap reading works good. Looking to spi_mem_no_dirmap_read() code we'll see:

	static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
					      u64 offs, size_t len, void *buf)
	{
		struct spi_mem_op op = desc->info.op_tmpl;
		int ret;

// --- see here ---
		op.addr.val = desc->info.offset + offs;
//-----------------
		op.data.buf.in = buf;
		op.data.nbytes = len;
		ret = spi_mem_adjust_op_size(desc->mem, &op);
		if (ret)
		return ret;

		ret = spi_mem_exec_op(desc->mem, &op);
		if (ret)
			return ret;

		return op.data.nbytes;
	}

The similar happens for spi_mem_no_dirmap_write(). Thus the address
passed to the flash should take in the account the value of
desc->info.offset.

This patch fix dirmap reading/writing of flashes with more than one
plane per lun.

Fixes: a403997c12019 ("spi: airoha: add SPI-NAND Flash controller driver")
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index a39c3ab4af5c..5ad3180ac6da 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -726,8 +726,9 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* set read addr */
-	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);
+	/* set read addr: zero page offset + descriptor read offset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3,
+			   desc->info.offset);
 	if (err)
 		goto error_dma_unmap;
 
@@ -860,7 +861,9 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);
+	/* set write addr: zero page offset + descriptor write offset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2,
+			   desc->info.offset);
 	if (err)
 		goto error_dma_unmap;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 07/13] spi: airoha: unify dirmap read/write code
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (5 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 06/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 08/13] spi: airoha: support of dualio/quadio flash reading commands Mikhail Kshevetskiy
                                 ` (6 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

Makes dirmap writing looks similar to dirmap reading. Just a minor
refactoring, no behavior change is expected.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 50 ++++++++++++++++++++++-------------
 1 file changed, 32 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 5ad3180ac6da..e90fab69d81e 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -672,6 +672,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	u32 val, rd_mode;
 	int err;
 
+	as_ctrl = spi_controller_get_devdata(spi->controller);
+
 	switch (op->cmd.opcode) {
 	case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
 		rd_mode = 1;
@@ -684,7 +686,6 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 		break;
 	}
 
-	as_ctrl = spi_controller_get_devdata(spi->controller);
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
 	if (err < 0)
 		return err;
@@ -748,7 +749,7 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* trigger dma start read */
+	/* trigger dma reading */
 	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
 				SPI_NFI_RD_TRIG);
 	if (err)
@@ -806,37 +807,47 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 					 u64 offs, size_t len, const void *buf)
 {
-	struct spi_mem_op *op = &desc->info.op_tmpl;
 	struct spi_device *spi = desc->mem->spi;
 	u8 *txrx_buf = spi_get_ctldata(spi);
 	struct airoha_snand_ctrl *as_ctrl;
 	dma_addr_t dma_addr;
-	u32 wr_mode, val;
+	u32 wr_mode, val, opcode;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
+	opcode = desc->info.op_tmpl.cmd.opcode;
+	switch (opcode) {
+	case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
+	case SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE:
+		wr_mode = 0;
+		break;
+	case SPI_NAND_OP_PROGRAM_LOAD_QUAD:
+	case SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD:
+		wr_mode = 2;
+		break;
+	default:
+		/* unknown opcode */
+		return -EOPNOTSUPP;
+	}
+
 	memcpy(txrx_buf + offs, buf, len);
-	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
-				  DMA_TO_DEVICE);
-	err = dma_mapping_error(as_ctrl->dev, dma_addr);
-	if (err)
-		return err;
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
 	if (err < 0)
-		goto error_dma_unmap;
+		return err;
 
 	err = airoha_snand_nfi_config(as_ctrl);
 	if (err)
-		goto error_dma_unmap;
+		goto error_dma_mode_off;
 
-	if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD ||
-	    op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD)
-		wr_mode = BIT(1);
-	else
-		wr_mode = 0;
+	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
+				  DMA_TO_DEVICE);
+	err = dma_mapping_error(as_ctrl->dev, dma_addr);
+	if (err)
+		goto error_dma_mode_off;
 
+	/* set dma addr */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
 			   dma_addr);
 	if (err)
@@ -850,12 +861,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
+	/* set write command */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1,
-			   FIELD_PREP(SPI_NFI_PG_LOAD_CMD,
-				      op->cmd.opcode));
+			   FIELD_PREP(SPI_NFI_PG_LOAD_CMD, opcode));
 	if (err)
 		goto error_dma_unmap;
 
+	/* set write mode */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
 			   FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode));
 	if (err)
@@ -887,6 +899,7 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
+	/* trigger dma writing */
 	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
 				SPI_NFI_WR_TRIG);
 	if (err)
@@ -931,6 +944,7 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 error_dma_unmap:
 	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
 			 DMA_TO_DEVICE);
+error_dma_mode_off:
 	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
 	return err;
 }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 08/13] spi: airoha: support of dualio/quadio flash reading commands
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (6 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 07/13] spi: airoha: unify dirmap read/write code Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 09/13] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT Mikhail Kshevetskiy
                                 ` (5 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

Airoha snfi spi controller supports acceleration of DUAL/QUAD
operations, but does not supports DUAL_IO/QUAD_IO operations.
Luckily DUAL/QUAD operations do the same as DUAL_IO/QUAD_IO ones,
so we can issue corresponding DUAL/QUAD operation instead of
DUAL_IO/QUAD_IO one.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index e90fab69d81e..744eeb2b24ef 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -147,6 +147,8 @@
 #define SPI_NFI_CUS_SEC_SIZE_EN			BIT(16)
 
 #define REG_SPI_NFI_RD_CTL2			0x0510
+#define SPI_NFI_DATA_READ_CMD			GENMASK(7, 0)
+
 #define REG_SPI_NFI_RD_CTL3			0x0514
 
 #define REG_SPI_NFI_PG_CTL1			0x0524
@@ -179,7 +181,9 @@
 #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE	0x03
 #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST	0x0b
 #define SPI_NAND_OP_READ_FROM_CACHE_DUAL	0x3b
+#define SPI_NAND_OP_READ_FROM_CACHE_DUALIO	0xbb
 #define SPI_NAND_OP_READ_FROM_CACHE_QUAD	0x6b
+#define SPI_NAND_OP_READ_FROM_CACHE_QUADIO	0xeb
 #define SPI_NAND_OP_WRITE_ENABLE		0x06
 #define SPI_NAND_OP_WRITE_DISABLE		0x04
 #define SPI_NAND_OP_PROGRAM_LOAD_SINGLE		0x02
@@ -664,26 +668,38 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
 static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 					u64 offs, size_t len, void *buf)
 {
-	struct spi_mem_op *op = &desc->info.op_tmpl;
 	struct spi_device *spi = desc->mem->spi;
 	struct airoha_snand_ctrl *as_ctrl;
 	u8 *txrx_buf = spi_get_ctldata(spi);
 	dma_addr_t dma_addr;
-	u32 val, rd_mode;
+	u32 val, rd_mode, opcode;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
-	switch (op->cmd.opcode) {
+	/*
+	 * DUALIO and QUADIO opcodes are not supported by the spi controller,
+	 * replace them with supported opcodes.
+	 */
+	opcode = desc->info.op_tmpl.cmd.opcode;
+	switch (opcode) {
+	case SPI_NAND_OP_READ_FROM_CACHE_SINGLE:
+	case SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST:
+		rd_mode = 0;
+		break;
 	case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
+	case SPI_NAND_OP_READ_FROM_CACHE_DUALIO:
+		opcode = SPI_NAND_OP_READ_FROM_CACHE_DUAL;
 		rd_mode = 1;
 		break;
 	case SPI_NAND_OP_READ_FROM_CACHE_QUAD:
+	case SPI_NAND_OP_READ_FROM_CACHE_QUADIO:
+		opcode = SPI_NAND_OP_READ_FROM_CACHE_QUAD;
 		rd_mode = 2;
 		break;
 	default:
-		rd_mode = 0;
-		break;
+		/* unknown opcode */
+		return -EOPNOTSUPP;
 	}
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
@@ -717,7 +733,7 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 
 	/* set read command */
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2,
-			   op->cmd.opcode);
+			   FIELD_PREP(SPI_NFI_DATA_READ_CMD, opcode));
 	if (err)
 		goto error_dma_unmap;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 09/13] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (7 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 08/13] spi: airoha: support of dualio/quadio flash reading commands Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 10/13] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers Mikhail Kshevetskiy
                                 ` (4 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

spi-airoha-snfi uses custom sector size in REG_SPI_NFI_SECCUS_SIZE
register, so setting of page/oob sizes in REG_SPI_NFI_PAGEFMT is not
required.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 38 -----------------------------------
 1 file changed, 38 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 744eeb2b24ef..719b424d4cce 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -518,44 +518,6 @@ static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
 	if (err)
 		return err;
 
-	/* page format */
-	switch (as_ctrl->nfi_cfg.spare_size) {
-	case 26:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x1);
-		break;
-	case 27:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x2);
-		break;
-	case 28:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x3);
-		break;
-	default:
-		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x0);
-		break;
-	}
-
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,
-				 SPI_NFI_SPARE_SIZE, val);
-	if (err)
-		return err;
-
-	switch (as_ctrl->nfi_cfg.page_size) {
-	case 2048:
-		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x1);
-		break;
-	case 4096:
-		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x2);
-		break;
-	default:
-		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x0);
-		break;
-	}
-
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,
-				 SPI_NFI_PAGE_SIZE, val);
-	if (err)
-		return err;
-
 	/* sec num */
 	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 10/13] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (8 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 09/13] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 11/13] spi: airoha: set custom sector size equal to flash page size Mikhail Kshevetskiy
                                 ` (3 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

This just reduce the number of modification of REG_SPI_NFI_CNFG and
REG_SPI_NFI_SECCUS_SIZE registers during dirmap operation.

This patch is a necessary step to avoid reading flash page settings
from SNFI registers during driver startup.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 135 +++++++++++++++++++++++++---------
 1 file changed, 102 insertions(+), 33 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 719b424d4cce..3fb76e2dd5e3 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -668,7 +668,48 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err < 0)
 		return err;
 
-	err = airoha_snand_nfi_config(as_ctrl);
+	/* NFI reset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
+	if (err)
+		goto error_dma_mode_off;
+
+	/* NFI configure:
+	 *   - No AutoFDM (custom sector size (SECCUS) register will be used)
+	 *   - No SoC's hardware ECC (flash internal ECC will be used)
+	 *   - Use burst mode (faster, but requires 16 byte alignment for addresses)
+	 *   - Setup for reading (SPI_NFI_READ_MODE)
+	 *   - Setup reading command: FIELD_PREP(SPI_NFI_OPMODE, 6)
+	 *   - Use DMA instead of PIO for data reading
+	 */
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_READ_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 SPI_NFI_HW_ECC_EN |
+				 SPI_NFI_AUTO_FDM_EN |
+				 SPI_NFI_OPMODE,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_READ_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 FIELD_PREP(SPI_NFI_OPMODE, 6));
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set number of sector will be read */
+	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+				 SPI_NFI_SEC_NUM, val);
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set custom sector size */
+	val = as_ctrl->nfi_cfg.sec_size;
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
+				 SPI_NFI_CUS_SEC_SIZE |
+				 SPI_NFI_CUS_SEC_SIZE_EN,
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
 
@@ -684,7 +725,14 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* set cust sec size */
+	/*
+	 * Setup transfer length
+	 * ---------------------
+	 * The following rule MUST be met:
+	 *     transfer_length =
+	 *        = NFI_SNF_MISC_CTL2.read_data_byte_number =
+	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+	 */
 	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
 	val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
@@ -711,18 +759,6 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	/* set nfi read */
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				 SPI_NFI_OPMODE,
-				 FIELD_PREP(SPI_NFI_OPMODE, 6));
-	if (err)
-		goto error_dma_unmap;
-
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-			      SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE);
-	if (err)
-		goto error_dma_unmap;
-
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0);
 	if (err)
 		goto error_dma_unmap;
@@ -815,7 +851,48 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err < 0)
 		return err;
 
-	err = airoha_snand_nfi_config(as_ctrl);
+	/* NFI reset */
+	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
+	if (err)
+		goto error_dma_mode_off;
+
+	/*
+	 * NFI configure:
+	 *   - No AutoFDM (custom sector size (SECCUS) register will be used)
+	 *   - No SoC's hardware ECC (flash internal ECC will be used)
+	 *   - Use burst mode (faster, but requires 16 byte alignment for addresses)
+	 *   - Setup for writing (SPI_NFI_READ_MODE bit is cleared)
+	 *   - Setup writing command: FIELD_PREP(SPI_NFI_OPMODE, 3)
+	 *   - Use DMA instead of PIO for data writing
+	 */
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_READ_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 SPI_NFI_HW_ECC_EN |
+				 SPI_NFI_AUTO_FDM_EN |
+				 SPI_NFI_OPMODE,
+				 SPI_NFI_DMA_MODE |
+				 SPI_NFI_DMA_BURST_EN |
+				 FIELD_PREP(SPI_NFI_OPMODE, 3));
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set number of sector will be written */
+	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
+				 SPI_NFI_SEC_NUM, val);
+	if (err)
+		goto error_dma_mode_off;
+
+	/* Set custom sector size */
+	val = as_ctrl->nfi_cfg.sec_size;
+	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
+				 SPI_NFI_CUS_SEC_SIZE |
+				 SPI_NFI_CUS_SEC_SIZE_EN,
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
 
@@ -831,8 +908,16 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM,
-			 as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
+	/*
+	 * Setup transfer length
+	 * ---------------------
+	 * The following rule MUST be met:
+	 *     transfer_length =
+	 *        = NFI_SNF_MISC_CTL2.write_data_byte_number =
+	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
+	 */
+	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
+	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
 				 SPI_NFI_PROG_LOAD_BYTE_NUM, val);
@@ -857,22 +942,6 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	if (err)
 		goto error_dma_unmap;
 
-	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				SPI_NFI_READ_MODE);
-	if (err)
-		goto error_dma_unmap;
-
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				 SPI_NFI_OPMODE,
-				 FIELD_PREP(SPI_NFI_OPMODE, 3));
-	if (err)
-		goto error_dma_unmap;
-
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-			      SPI_NFI_DMA_MODE);
-	if (err)
-		goto error_dma_unmap;
-
 	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80);
 	if (err)
 		goto error_dma_unmap;
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 11/13] spi: airoha: set custom sector size equal to flash page size
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (9 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 10/13] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 12/13] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup Mikhail Kshevetskiy
                                 ` (2 subsequent siblings)
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

Set custom sector size equal to flash page size including oob. Thus we
will always read a single sector. The maximum custom sector size is
8187, so all possible flash sector sizes are supported.

This patch is a necessary step to avoid reading flash page settings
from SNFI registers during driver startup.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 3fb76e2dd5e3..babf7b958dc3 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -519,7 +519,7 @@ static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
 		return err;
 
 	/* sec num */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
+	val = FIELD_PREP(SPI_NFI_SEC_NUM, 1);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
 				 SPI_NFI_SEC_NUM, val);
 	if (err)
@@ -532,7 +532,8 @@ static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
 		return err;
 
 	/* set cust sec size */
-	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, as_ctrl->nfi_cfg.sec_size);
+	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE,
+			 as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
 	return regmap_update_bits(as_ctrl->regmap_nfi,
 				  REG_SPI_NFI_SECCUS_SIZE,
 				  SPI_NFI_CUS_SEC_SIZE, val);
@@ -635,10 +636,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	u8 *txrx_buf = spi_get_ctldata(spi);
 	dma_addr_t dma_addr;
 	u32 val, rd_mode, opcode;
+	size_t bytes;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
+	bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
+
 	/*
 	 * DUALIO and QUADIO opcodes are not supported by the spi controller,
 	 * replace them with supported opcodes.
@@ -697,18 +701,17 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 		goto error_dma_mode_off;
 
 	/* Set number of sector will be read */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-				 SPI_NFI_SEC_NUM, val);
+				 SPI_NFI_SEC_NUM,
+				 FIELD_PREP(SPI_NFI_SEC_NUM, 1));
 	if (err)
 		goto error_dma_mode_off;
 
 	/* Set custom sector size */
-	val = as_ctrl->nfi_cfg.sec_size;
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
 				 SPI_NFI_CUS_SEC_SIZE |
 				 SPI_NFI_CUS_SEC_SIZE_EN,
-				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) |
 				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
@@ -733,11 +736,10 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	 *        = NFI_SNF_MISC_CTL2.read_data_byte_number =
 	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
 	 */
-	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
-	val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
-				 SPI_NFI_READ_DATA_BYTE_NUM, val);
+				 SPI_NFI_READ_DATA_BYTE_NUM,
+				 FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, bytes));
 	if (err)
 		goto error_dma_unmap;
 
@@ -826,10 +828,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	struct airoha_snand_ctrl *as_ctrl;
 	dma_addr_t dma_addr;
 	u32 wr_mode, val, opcode;
+	size_t bytes;
 	int err;
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
+	bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
+
 	opcode = desc->info.op_tmpl.cmd.opcode;
 	switch (opcode) {
 	case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
@@ -880,18 +885,17 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 		goto error_dma_mode_off;
 
 	/* Set number of sector will be written */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-				 SPI_NFI_SEC_NUM, val);
+				 SPI_NFI_SEC_NUM,
+				 FIELD_PREP(SPI_NFI_SEC_NUM, 1));
 	if (err)
 		goto error_dma_mode_off;
 
 	/* Set custom sector size */
-	val = as_ctrl->nfi_cfg.sec_size;
 	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
 				 SPI_NFI_CUS_SEC_SIZE |
 				 SPI_NFI_CUS_SEC_SIZE_EN,
-				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) |
+				 FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) |
 				 SPI_NFI_CUS_SEC_SIZE_EN);
 	if (err)
 		goto error_dma_mode_off;
@@ -916,11 +920,10 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	 *        = NFI_SNF_MISC_CTL2.write_data_byte_number =
 	 *        = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size
 	 */
-	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
-	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val);
 	err = regmap_update_bits(as_ctrl->regmap_nfi,
 				 REG_SPI_NFI_SNF_MISC_CTL2,
-				 SPI_NFI_PROG_LOAD_BYTE_NUM, val);
+				 SPI_NFI_PROG_LOAD_BYTE_NUM,
+				 FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, bytes));
 	if (err)
 		goto error_dma_unmap;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 12/13] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (10 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 11/13] spi: airoha: set custom sector size equal to flash page size Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-23 16:01               ` [PATCH v5 13/13] spi: airoha: buffer must be 0xff-ed before writing Mikhail Kshevetskiy
  2025-08-29  7:14               ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

The spinand driver do 3 type of dirmap requests:
 * read/write whole flash page without oob
   (offs = 0, len = page_size)
 * read/write whole flash page including oob
   (offs = 0, len = page_size + oob_size)
 * read/write oob area only
   (offs = page_size, len = oob_size)

The trick is:
 * read/write a single "sector"
 * set a custom sector size equal to offs + len. It's a bit safer to
   rounded up "sector size" value 64.
 * set the transfer length equal to custom sector size

And it works!

Thus we can remove a dirty hack that reads flash page settings from
SNFI registers during driver startup. Also airoha_snand_adjust_op_size()
function becomes unnecessary.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 115 ++--------------------------------
 1 file changed, 5 insertions(+), 110 deletions(-)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index babf7b958dc3..437ab6745b1a 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -223,13 +223,6 @@ struct airoha_snand_ctrl {
 	struct regmap *regmap_ctrl;
 	struct regmap *regmap_nfi;
 	struct clk *spi_clk;
-
-	struct {
-		size_t page_size;
-		size_t sec_size;
-		u8 sec_num;
-		u8 spare_size;
-	} nfi_cfg;
 };
 
 static int airoha_snand_set_fifo_op(struct airoha_snand_ctrl *as_ctrl,
@@ -490,55 +483,6 @@ static int airoha_snand_nfi_init(struct airoha_snand_ctrl *as_ctrl)
 				  SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN);
 }
 
-static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)
-{
-	int err;
-	u32 val;
-
-	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
-	if (err)
-		return err;
-
-	/* auto FDM */
-	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				SPI_NFI_AUTO_FDM_EN);
-	if (err)
-		return err;
-
-	/* HW ECC */
-	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-				SPI_NFI_HW_ECC_EN);
-	if (err)
-		return err;
-
-	/* DMA Burst */
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
-			      SPI_NFI_DMA_BURST_EN);
-	if (err)
-		return err;
-
-	/* sec num */
-	val = FIELD_PREP(SPI_NFI_SEC_NUM, 1);
-	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
-				 SPI_NFI_SEC_NUM, val);
-	if (err)
-		return err;
-
-	/* enable cust sec size */
-	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
-			      SPI_NFI_CUS_SEC_SIZE_EN);
-	if (err)
-		return err;
-
-	/* set cust sec size */
-	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE,
-			 as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
-	return regmap_update_bits(as_ctrl->regmap_nfi,
-				  REG_SPI_NFI_SECCUS_SIZE,
-				  SPI_NFI_CUS_SEC_SIZE, val);
-}
-
 static bool airoha_snand_is_page_ops(const struct spi_mem_op *op)
 {
 	if (op->addr.nbytes != 2)
@@ -571,26 +515,6 @@ static bool airoha_snand_is_page_ops(const struct spi_mem_op *op)
 	}
 }
 
-static int airoha_snand_adjust_op_size(struct spi_mem *mem,
-				       struct spi_mem_op *op)
-{
-	size_t max_len;
-
-	if (airoha_snand_is_page_ops(op)) {
-		struct airoha_snand_ctrl *as_ctrl;
-
-		as_ctrl = spi_controller_get_devdata(mem->spi->controller);
-		max_len = as_ctrl->nfi_cfg.sec_size;
-		max_len += as_ctrl->nfi_cfg.spare_size;
-		max_len *= as_ctrl->nfi_cfg.sec_num;
-
-		if (op->data.nbytes > max_len)
-			op->data.nbytes = max_len;
-	}
-
-	return 0;
-}
-
 static bool airoha_snand_supports_op(struct spi_mem *mem,
 				     const struct spi_mem_op *op)
 {
@@ -641,7 +565,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
-	bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
+	/* minimum oob size is 64 */
+	bytes = round_up(offs + len, 64);
 
 	/*
 	 * DUALIO and QUADIO opcodes are not supported by the spi controller,
@@ -833,7 +758,8 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 
 	as_ctrl = spi_controller_get_devdata(spi->controller);
 
-	bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size;
+	/* minimum oob size is 64 */
+	bytes = round_up(offs + len, 64);
 
 	opcode = desc->info.op_tmpl.cmd.opcode;
 	switch (opcode) {
@@ -1076,7 +1002,6 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
 }
 
 static const struct spi_controller_mem_ops airoha_snand_mem_ops = {
-	.adjust_op_size = airoha_snand_adjust_op_size,
 	.supports_op = airoha_snand_supports_op,
 	.exec_op = airoha_snand_exec_op,
 	.dirmap_create = airoha_snand_dirmap_create,
@@ -1101,36 +1026,6 @@ static int airoha_snand_setup(struct spi_device *spi)
 	return 0;
 }
 
-static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl)
-{
-	u32 val, sec_size, sec_num;
-	int err;
-
-	err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, &val);
-	if (err)
-		return err;
-
-	sec_num = FIELD_GET(SPI_NFI_SEC_NUM, val);
-
-	err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, &val);
-	if (err)
-		return err;
-
-	sec_size = FIELD_GET(SPI_NFI_CUS_SEC_SIZE, val);
-
-	/* init default value */
-	as_ctrl->nfi_cfg.sec_size = sec_size;
-	as_ctrl->nfi_cfg.sec_num = sec_num;
-	as_ctrl->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024);
-	as_ctrl->nfi_cfg.spare_size = 16;
-
-	err = airoha_snand_nfi_init(as_ctrl);
-	if (err)
-		return err;
-
-	return airoha_snand_nfi_config(as_ctrl);
-}
-
 static const struct regmap_config spi_ctrl_regmap_config = {
 	.name		= "ctrl",
 	.reg_bits	= 32,
@@ -1204,7 +1099,7 @@ static int airoha_snand_probe(struct platform_device *pdev)
 	ctrl->setup = airoha_snand_setup;
 	device_set_node(&ctrl->dev, dev_fwnode(dev));
 
-	err = airoha_snand_nfi_setup(as_ctrl);
+	err = airoha_snand_nfi_init(as_ctrl);
 	if (err)
 		return err;
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v5 13/13] spi: airoha: buffer must be 0xff-ed before writing
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (11 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 12/13] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup Mikhail Kshevetskiy
@ 2025-08-23 16:01               ` Mikhail Kshevetskiy
  2025-08-29  7:14               ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
  13 siblings, 0 replies; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-23 16:01 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu
  Cc: Mikhail Kshevetskiy

During writing, the entire flash page (including OOB) will be updated
with the values from the temporary buffer, so we need to fill the
untouched areas of the buffer with 0xff value to prevent accidental
data overwriting.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
---
 drivers/spi/spi-airoha-snfi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index 437ab6745b1a..57b1950e853f 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -776,6 +776,7 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
 		return -EOPNOTSUPP;
 	}
 
+	memset(txrx_buf, 0xff, bytes);
 	memcpy(txrx_buf + offs, buf, len);
 
 	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* Re: [PATCH v5 00/13] spi: airoha: driver fixes & improvements
  2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
                                 ` (12 preceding siblings ...)
  2025-08-23 16:01               ` [PATCH v5 13/13] spi: airoha: buffer must be 0xff-ed before writing Mikhail Kshevetskiy
@ 2025-08-29  7:14               ` Mikhail Kshevetskiy
  2025-08-29  8:45                 ` Mark Brown
  13 siblings, 1 reply; 65+ messages in thread
From: Mikhail Kshevetskiy @ 2025-08-29  7:14 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ray Liu, Mark Brown, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu

is there any news?

Best regards,
Mikhail Kshevetskiy

On 23.08.2025 19:01, Mikhail Kshevetskiy wrote:
> This patch series greatly improve airoha snfi driver and fix a
> number of serious bugs.
>
> Fixed bugs:
>  * Fix reading/writing of flashes with more than one plane per lun
>  * Fill the buffer with 0xff before writing
>  * Fix reading of flashes supporting continuous reading mode
>  * Fix error paths
>
> Improvements:
>  * Add support of dual/quad wires spi modes in exec_op(). This also
>    fix flash reading/writing if dirmap can't be created.
>  * Support of dualio/quadio flash reading commands
>  * Remove dirty hack that reads flash page settings from SNFI registers
>    during driver startup
>
> Patched kernel tests:
>
>     root@OpenWrt:/lib/modules/6.6.79# insmod mtd_oobtest.ko dev=1
>     [  263.191711] 
>     [  263.193218] =================================================
>     [  263.199014] mtd_oobtest: MTD device: 1
>     [  263.202768] mtd_oobtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
>     [  263.216791] mtd_test: scanning for bad eraseblocks
>     [  263.221956] mtd_test: scanned 2047 eraseblocks, 0 are bad
>     [  263.227361] mtd_oobtest: test 1 of 5
>     [  265.077216] mtd_oobtest: writing OOBs of whole device
>     [  265.121767] mtd_oobtest: written up to eraseblock 0
>     [  275.174147] mtd_oobtest: written up to eraseblock 256
>     [  285.210279] mtd_oobtest: written up to eraseblock 512
>     [  295.241724] mtd_oobtest: written up to eraseblock 768
>     [  305.280167] mtd_oobtest: written up to eraseblock 1024
>     [  315.326883] mtd_oobtest: written up to eraseblock 1280
>     [  325.364049] mtd_oobtest: written up to eraseblock 1536
>     [  335.398609] mtd_oobtest: written up to eraseblock 1792
>     [  345.358981] mtd_oobtest: written 2047 eraseblocks
>     [  345.363694] mtd_oobtest: verifying all eraseblocks
>     [  345.386088] mtd_oobtest: verified up to eraseblock 0
>     [  349.830833] mtd_oobtest: verified up to eraseblock 256
>     [  354.276245] mtd_oobtest: verified up to eraseblock 512
>     [  358.721496] mtd_oobtest: verified up to eraseblock 768
>     [  363.166881] mtd_oobtest: verified up to eraseblock 1024
>     [  367.612694] mtd_oobtest: verified up to eraseblock 1280
>     [  372.058211] mtd_oobtest: verified up to eraseblock 1536
>     [  376.503820] mtd_oobtest: verified up to eraseblock 1792
>     [  380.914843] mtd_oobtest: verified 2047 eraseblocks
>     [  380.919660] mtd_oobtest: test 2 of 5
>     [  384.202620] mtd_oobtest: writing OOBs of whole device
>     [  384.247584] mtd_oobtest: written up to eraseblock 0
>     [  394.305121] mtd_oobtest: written up to eraseblock 256
>     [  404.342199] mtd_oobtest: written up to eraseblock 512
>     [  414.374204] mtd_oobtest: written up to eraseblock 768
>     [  424.409891] mtd_oobtest: written up to eraseblock 1024
>     [  434.453378] mtd_oobtest: written up to eraseblock 1280
>     [  444.494321] mtd_oobtest: written up to eraseblock 1536
>     [  454.534480] mtd_oobtest: written up to eraseblock 1792
>     [  464.490962] mtd_oobtest: written 2047 eraseblocks
>     [  464.495681] mtd_oobtest: verifying all eraseblocks
>     [  464.518015] mtd_oobtest: verified up to eraseblock 0
>     [  468.955635] mtd_oobtest: verified up to eraseblock 256
>     [  473.395502] mtd_oobtest: verified up to eraseblock 512
>     [  477.834373] mtd_oobtest: verified up to eraseblock 768
>     [  482.272717] mtd_oobtest: verified up to eraseblock 1024
>     [  486.712148] mtd_oobtest: verified up to eraseblock 1280
>     [  491.150704] mtd_oobtest: verified up to eraseblock 1536
>     [  495.589439] mtd_oobtest: verified up to eraseblock 1792
>     [  499.993138] mtd_oobtest: verified 2047 eraseblocks
>     [  499.997951] mtd_oobtest: test 3 of 5
>     [  503.404228] mtd_oobtest: writing OOBs of whole device
>     [  503.448822] mtd_oobtest: written up to eraseblock 0
>     [  513.480773] mtd_oobtest: written up to eraseblock 256
>     [  523.489361] mtd_oobtest: written up to eraseblock 512
>     [  533.506896] mtd_oobtest: written up to eraseblock 768
>     [  543.506268] mtd_oobtest: written up to eraseblock 1024
>     [  553.506503] mtd_oobtest: written up to eraseblock 1280
>     [  563.511266] mtd_oobtest: written up to eraseblock 1536
>     [  573.519567] mtd_oobtest: written up to eraseblock 1792
>     [  583.455111] mtd_oobtest: written 2047 eraseblocks
>     [  583.459837] mtd_oobtest: verifying all eraseblocks
>     [  583.499358] mtd_oobtest: verified up to eraseblock 0
>     [  592.382953] mtd_oobtest: verified up to eraseblock 256
>     [  601.267297] mtd_oobtest: verified up to eraseblock 512
>     [  610.150907] mtd_oobtest: verified up to eraseblock 768
>     [  619.034702] mtd_oobtest: verified up to eraseblock 1024
>     [  627.919683] mtd_oobtest: verified up to eraseblock 1280
>     [  636.821168] mtd_oobtest: verified up to eraseblock 1536
>     [  645.705487] mtd_oobtest: verified up to eraseblock 1792
>     [  654.520336] mtd_oobtest: verified 2047 eraseblocks
>     [  654.525134] mtd_oobtest: test 4 of 5
>     [  657.578146] mtd_oobtest: attempting to start write past end of OOB
>     [  657.584336] mtd_oobtest: an error is expected...
>     [  657.588974] mtd_oobtest: error occurred as expected
>     [  657.593848] mtd_oobtest: attempting to start read past end of OOB
>     [  657.599953] mtd_oobtest: an error is expected...
>     [  657.604569] mtd_oobtest: error occurred as expected
>     [  657.609450] mtd_oobtest: attempting to write past end of device
>     [  657.615367] mtd_oobtest: an error is expected...
>     [  657.619990] mtd_oobtest: error occurred as expected
>     [  657.624864] mtd_oobtest: attempting to read past end of device
>     [  657.630715] mtd_oobtest: an error is expected...
>     [  657.635333] mtd_oobtest: error occurred as expected
>     [  657.641043] mtd_oobtest: attempting to write past end of device
>     [  657.646966] mtd_oobtest: an error is expected...
>     [  657.651574] mtd_oobtest: error occurred as expected
>     [  657.656451] mtd_oobtest: attempting to read past end of device
>     [  657.662277] mtd_oobtest: an error is expected...
>     [  657.666901] mtd_oobtest: error occurred as expected
>     [  657.671774] mtd_oobtest: test 5 of 5
>     [  659.382333] mtd_oobtest: writing OOBs of whole device
>     [  659.388056] mtd_oobtest: written up to eraseblock 0
>     [  659.393526] mtd_oobtest: written up to eraseblock 0
>     [  659.704525] mtd_oobtest: written up to eraseblock 256
>     [  659.710187] mtd_oobtest: written up to eraseblock 256
>     [  660.021093] mtd_oobtest: written up to eraseblock 512
>     [  660.026752] mtd_oobtest: written up to eraseblock 512
>     [  660.338427] mtd_oobtest: written up to eraseblock 768
>     [  660.344048] mtd_oobtest: written up to eraseblock 768
>     [  660.655718] mtd_oobtest: written up to eraseblock 1024
>     [  660.661462] mtd_oobtest: written up to eraseblock 1024
>     [  660.970676] mtd_oobtest: written up to eraseblock 1280
>     [  660.976386] mtd_oobtest: written up to eraseblock 1280
>     [  661.286858] mtd_oobtest: written up to eraseblock 1536
>     [  661.292587] mtd_oobtest: written up to eraseblock 1536
>     [  661.605397] mtd_oobtest: written up to eraseblock 1792
>     [  661.611142] mtd_oobtest: written up to eraseblock 1792
>     [  661.918754] mtd_oobtest: written 2046 eraseblocks
>     [  661.923458] mtd_oobtest: verifying all eraseblocks
>     [  661.928812] mtd_oobtest: verified up to eraseblock 0
>     [  662.072499] mtd_oobtest: verified up to eraseblock 256
>     [  662.216152] mtd_oobtest: verified up to eraseblock 512
>     [  662.359956] mtd_oobtest: verified up to eraseblock 768
>     [  662.503238] mtd_oobtest: verified up to eraseblock 1024
>     [  662.646847] mtd_oobtest: verified up to eraseblock 1280
>     [  662.790603] mtd_oobtest: verified up to eraseblock 1536
>     [  662.934269] mtd_oobtest: verified up to eraseblock 1792
>     [  663.076329] mtd_oobtest: verified 2046 eraseblocks
>     [  663.081114] mtd_oobtest: finished with 0 errors
>     [  663.085647] =================================================
>
>     root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_pagetest.ko dev=1
>     [ 1142.213082] 
>     [ 1142.214590] =================================================
>     [ 1142.220433] mtd_pagetest: MTD device: 1
>     [ 1142.224278] mtd_pagetest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
>     [ 1142.238388] mtd_test: scanning for bad eraseblocks
>     [ 1142.243536] mtd_test: scanned 2047 eraseblocks, 0 are bad
>     [ 1142.248935] mtd_pagetest: erasing whole device
>     [ 1143.962562] mtd_pagetest: erased 2047 eraseblocks
>     [ 1143.967301] mtd_pagetest: writing whole device
>     [ 1144.011729] mtd_pagetest: written up to eraseblock 0
>     [ 1154.137933] mtd_pagetest: written up to eraseblock 256
>     [ 1164.265201] mtd_pagetest: written up to eraseblock 512
>     [ 1174.393365] mtd_pagetest: written up to eraseblock 768
>     [ 1184.525700] mtd_pagetest: written up to eraseblock 1024
>     [ 1194.650920] mtd_pagetest: written up to eraseblock 1280
>     [ 1204.773676] mtd_pagetest: written up to eraseblock 1536
>     [ 1214.896934] mtd_pagetest: written up to eraseblock 1792
>     [ 1224.942600] mtd_pagetest: written 2047 eraseblocks
>     [ 1224.947410] mtd_pagetest: verifying all eraseblocks
>     [ 1225.053133] mtd_pagetest: verified up to eraseblock 0
>     [ 1250.760034] mtd_pagetest: verified up to eraseblock 256
>     [ 1276.448242] mtd_pagetest: verified up to eraseblock 512
>     [ 1302.138825] mtd_pagetest: verified up to eraseblock 768
>     [ 1327.824020] mtd_pagetest: verified up to eraseblock 1024
>     [ 1353.532178] mtd_pagetest: verified up to eraseblock 1280
>     [ 1379.234385] mtd_pagetest: verified up to eraseblock 1536
>     [ 1404.943865] mtd_pagetest: verified up to eraseblock 1792
>     [ 1430.468816] mtd_pagetest: verified 2047 eraseblocks
>     [ 1430.473702] mtd_pagetest: crosstest
>     [ 1430.477717] mtd_pagetest: reading page at 0x0
>     [ 1430.482328] mtd_pagetest: reading page at 0xffdf800
>     [ 1430.487469] mtd_pagetest: reading page at 0x0
>     [ 1430.492084] mtd_pagetest: verifying pages read at 0x0 match
>     [ 1430.497668] mtd_pagetest: crosstest ok
>     [ 1430.501409] mtd_pagetest: erasecrosstest
>     [ 1430.505323] mtd_pagetest: erasing block 0
>     [ 1430.511511] mtd_pagetest: writing 1st page of block 0
>     [ 1430.517166] mtd_pagetest: reading 1st page of block 0
>     [ 1430.522505] mtd_pagetest: verifying 1st page of block 0
>     [ 1430.527739] mtd_pagetest: erasing block 0
>     [ 1430.532565] mtd_pagetest: writing 1st page of block 0
>     [ 1430.538229] mtd_pagetest: erasing block 2046
>     [ 1430.544181] mtd_pagetest: reading 1st page of block 0
>     [ 1430.549498] mtd_pagetest: verifying 1st page of block 0
>     [ 1430.554718] mtd_pagetest: erasecrosstest ok
>     [ 1430.558900] mtd_pagetest: erasetest
>     [ 1430.562381] mtd_pagetest: erasing block 0
>     [ 1430.567208] mtd_pagetest: writing 1st page of block 0
>     [ 1430.572858] mtd_pagetest: erasing block 0
>     [ 1430.577680] mtd_pagetest: reading 1st page of block 0
>     [ 1430.582990] mtd_pagetest: verifying 1st page of block 0 is all 0xff
>     [ 1430.589279] mtd_pagetest: erasetest ok
>     [ 1430.593023] mtd_pagetest: finished with 0 errors
>     [ 1430.597651] =================================================
>
>     root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_readtest.ko dev=1
>     [ 1478.691648] 
>     [ 1478.693158] =================================================
>     [ 1478.698981] mtd_readtest: MTD device: 1
>     [ 1478.702829] mtd_readtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
>     [ 1478.716939] mtd_test: scanning for bad eraseblocks
>     [ 1478.722072] mtd_test: scanned 2047 eraseblocks, 0 are bad
>     [ 1478.727475] mtd_readtest: testing page read
>     [ 1548.352125] mtd_readtest: finished
>     [ 1548.355553] =================================================
>
>     root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_speedtest.ko dev=1
>     [ 1617.353002] 
>     [ 1617.354511] =================================================
>     [ 1617.360332] mtd_speedtest: MTD device: 1
>     [ 1617.364258] mtd_speedtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
>     [ 1617.380150] mtd_test: scanning for bad eraseblocks
>     [ 1617.385428] mtd_test: scanned 2047 eraseblocks, 0 are bad
>     [ 1621.021861] mtd_speedtest: testing eraseblock write speed
>     [ 1700.915306] mtd_speedtest: eraseblock write speed is 3279 KiB/s
>     [ 1700.921250] mtd_speedtest: testing eraseblock read speed
>     [ 1734.931886] mtd_speedtest: eraseblock read speed is 7705 KiB/s
>     [ 1738.682742] mtd_speedtest: testing page write speed
>     [ 1818.818644] mtd_speedtest: page write speed is 3269 KiB/s
>     [ 1818.824058] mtd_speedtest: testing page read speed
>     [ 1852.913595] mtd_speedtest: page read speed is 7687 KiB/s
>     [ 1856.674492] mtd_speedtest: testing 2 page write speed
>     [ 1936.437284] mtd_speedtest: 2 page write speed is 3285 KiB/s
>     [ 1936.442869] mtd_speedtest: testing 2 page read speed
>     [ 1970.498124] mtd_speedtest: 2 page read speed is 7694 KiB/s
>     [ 1970.503624] mtd_speedtest: Testing erase speed
>     [ 1974.343389] mtd_speedtest: erase speed is 68316 KiB/s
>     [ 1974.348479] mtd_speedtest: Testing 2x multi-block erase speed
>     [ 1976.068855] mtd_speedtest: 2x multi-block erase speed is 152811 KiB/s
>     [ 1976.075309] mtd_speedtest: Testing 4x multi-block erase speed
>     [ 1977.790232] mtd_speedtest: 4x multi-block erase speed is 153301 KiB/s
>     [ 1977.796693] mtd_speedtest: Testing 8x multi-block erase speed
>     [ 1979.511905] mtd_speedtest: 8x multi-block erase speed is 153273 KiB/s
>     [ 1979.518367] mtd_speedtest: Testing 16x multi-block erase speed
>     [ 1981.230700] mtd_speedtest: 16x multi-block erase speed is 153539 KiB/s
>     [ 1981.237249] mtd_speedtest: Testing 32x multi-block erase speed
>     [ 1982.948381] mtd_speedtest: 32x multi-block erase speed is 153648 KiB/s
>     [ 1982.954918] mtd_speedtest: Testing 64x multi-block erase speed
>     [ 1984.665992] mtd_speedtest: 64x multi-block erase speed is 153655 KiB/s
>     [ 1984.672531] mtd_speedtest: finished
>     [ 1984.676054] =================================================
>
>     root@OpenWrt:/lib/modules/6.6.79# insmod mtd_stresstest.ko dev=1
>     [ 2190.651750] 
>     [ 2190.653263] =================================================
>     [ 2190.659087] mtd_stresstest: MTD device: 1
>     [ 2190.663105] mtd_stresstest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
>     [ 2190.679846] mtd_test: scanning for bad eraseblocks
>     [ 2190.684981] mtd_test: scanned 2047 eraseblocks, 0 are bad
>     [ 2190.690389] mtd_stresstest: doing operations
>     [ 2190.694655] mtd_stresstest: 0 operations done
>     [ 2214.262705] mtd_stresstest: 1024 operations done
>     [ 2239.019612] mtd_stresstest: 2048 operations done
>     [ 2262.820899] mtd_stresstest: 3072 operations done
>     [ 2285.061376] mtd_stresstest: 4096 operations done
>     [ 2308.297322] mtd_stresstest: 5120 operations done
>     [ 2330.530459] mtd_stresstest: 6144 operations done
>     [ 2352.651759] mtd_stresstest: 7168 operations done
>     [ 2375.188275] mtd_stresstest: 8192 operations done
>     [ 2397.738174] mtd_stresstest: 9216 operations done
>     [ 2414.792572] mtd_stresstest: finished, 10000 operations done
>     [ 2414.798257] =================================================
>
> Speed test of original driver (with patch to fix support of flashes
> with more than one plane per lun)
>
>     root@OpenWrt:/lib/modules/6.6.79# insmod  mtd_speedtest.ko dev=1
>     [ 2894.142208] 
>     [ 2894.143719] =================================================
>     [ 2894.149556] mtd_speedtest: MTD device: 1
>     [ 2894.153486] mtd_speedtest: MTD device size 268304384, eraseblock size 131072, page size 2048, count of eraseblocks 2047, pages per eraseblock 64, OOB size 128
>     [ 2894.168888] mtd_test: scanning for bad eraseblocks
>     [ 2894.174023] mtd_test: scanned 2047 eraseblocks, 0 are bad
>     [ 2897.500416] mtd_speedtest: testing eraseblock write speed
>     [ 2977.807233] mtd_speedtest: eraseblock write speed is 3262 KiB/s
>     [ 2977.813171] mtd_speedtest: testing eraseblock read speed
>     [ 3013.906597] mtd_speedtest: eraseblock read speed is 7260 KiB/s
>     [ 3017.440320] mtd_speedtest: testing page write speed
>     [ 3097.833394] mtd_speedtest: page write speed is 3259 KiB/s
>     [ 3097.838812] mtd_speedtest: testing page read speed
>     [ 3134.004981] mtd_speedtest: page read speed is 7245 KiB/s
>     [ 3137.538423] mtd_speedtest: testing 2 page write speed
>     [ 3217.906288] mtd_speedtest: 2 page write speed is 3260 KiB/s
>     [ 3217.911883] mtd_speedtest: testing 2 page read speed
>     [ 3254.049757] mtd_speedtest: 2 page read speed is 7251 KiB/s
>     [ 3254.055254] mtd_speedtest: Testing erase speed
>     [ 3257.599146] mtd_speedtest: erase speed is 74027 KiB/s
>     [ 3257.604213] mtd_speedtest: Testing 2x multi-block erase speed
>     [ 3259.320945] mtd_speedtest: 2x multi-block erase speed is 153139 KiB/s
>     [ 3259.327413] mtd_speedtest: Testing 4x multi-block erase speed
>     [ 3261.044585] mtd_speedtest: 4x multi-block erase speed is 153098 KiB/s
>     [ 3261.051047] mtd_speedtest: Testing 8x multi-block erase speed
>     [ 3262.786520] mtd_speedtest: 8x multi-block erase speed is 151479 KiB/s
>     [ 3262.792979] mtd_speedtest: Testing 16x multi-block erase speed
>     [ 3264.509898] mtd_speedtest: 16x multi-block erase speed is 153130 KiB/s
>     [ 3264.516454] mtd_speedtest: Testing 32x multi-block erase speed
>     [ 3266.233403] mtd_speedtest: 32x multi-block erase speed is 153125 KiB/s
>     [ 3266.239961] mtd_speedtest: Testing 64x multi-block erase speed
>     [ 3267.957985] mtd_speedtest: 64x multi-block erase speed is 153029 KiB/s
>     [ 3267.964525] mtd_speedtest: finished
>     [ 3267.968039] =================================================
>
> It looks like a patched driver is a bit faster
>
> write speed: 3260 KiB/s  vs  3277 KiB/s
> read speed:  7252 KiB/s  vs  7695 KiB/s
>
> Changes v2:
>  * minor fix
>  * add comments to code
>
> Changes v3:
>  * add patch to prevent continuous reading
>
> Changes v4:
>  * removed non-needed patch, other patch was a bit updated
>  * treat zero buswidth as single wire buswidth (thanks to Jyothi Kumar Seerapu)
>  * changes were tested with linux
>  * test results was added
>
> Changes v5:
>  * reorder patches a bit
>  * improve description of some patches
>  * minor fixes & improvements
>
> Mikhail Kshevetskiy (13):
>   spi: airoha: return an error for continuous mode dirmap creation cases
>   spi: airoha: remove unnecessary restriction length
>   spi: airoha: add support of dual/quad wires spi modes to exec_op()
>     handler
>   spi: airoha: remove unnecessary switch to non-dma mode
>   spi: airoha: switch back to non-dma mode in the case of error
>   spi: airoha: fix reading/writing of flashes with more than one plane
>     per lun
>   spi: airoha: unify dirmap read/write code
>   spi: airoha: support of dualio/quadio flash reading commands
>   spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT
>   spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and
>     REG_SPI_NFI_SECCUS_SIZE registers
>   spi: airoha: set custom sector size equal to flash page size
>   spi: airoha: avoid reading flash page settings from SNFI registers
>     during driver startup
>   spi: airoha: buffer must be 0xff-ed before writing
>
>  drivers/spi/spi-airoha-snfi.c | 510 ++++++++++++++++++----------------
>  1 file changed, 263 insertions(+), 247 deletions(-)
>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v5 00/13] spi: airoha: driver fixes & improvements
  2025-08-29  7:14               ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
@ 2025-08-29  8:45                 ` Mark Brown
  0 siblings, 0 replies; 65+ messages in thread
From: Mark Brown @ 2025-08-29  8:45 UTC (permalink / raw)
  To: Mikhail Kshevetskiy
  Cc: Lorenzo Bianconi, Ray Liu, AngeloGioacchino Del Regno,
	Andy Shevchenko, linux-arm-kernel, linux-spi, linux-kernel,
	Jyothi Kumar Seerapu

[-- Attachment #1: Type: text/plain, Size: 1202 bytes --]

On Fri, Aug 29, 2025 at 10:14:16AM +0300, Mikhail Kshevetskiy wrote:
> is there any news?
> 
> Best regards,
> Mikhail Kshevetskiy
> 
> On 23.08.2025 19:01, Mikhail Kshevetskiy wrote:

Please don't send content free pings and please allow a reasonable time
for review.  People get busy, go on holiday, attend conferences and so 
on so unless there is some reason for urgency (like critical bug fixes)
please allow at least a couple of weeks for review.  If there have been
review comments then people may be waiting for those to be addressed.

Sending content free pings adds to the mail volume (if they are seen at
all) which is often the problem and since they can't be reviewed
directly if something has gone wrong you'll have to resend the patches
anyway, so sending again is generally a better approach though there are
some other maintainers who like them - if in doubt look at how patches
for the subsystem are normally handled.

Please don't top post, reply in line with needed context.  This allows
readers to readily follow the flow of conversation and understand what
you are talking about and also helps ensure that everything in the
discussion is being addressed.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

end of thread, other threads:[~2025-08-29  9:49 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-20 12:33 [PATCH v3 00/14] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 01/14] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 02/14] spi: airoha: remove unnecessary restriction length Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 03/14] spi: airoha: add support of dual/quad wires spi modes Mikhail Kshevetskiy
2025-08-20 12:48   ` Jyothi Kumar Seerapu
2025-08-20 12:33 ` [PATCH v3 04/14] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 05/14] spi: airoha: unify dirmap read/write code Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 06/14] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 07/14] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 08/14] spi: airoha: support of dualio/quadio flash reading commands Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 09/14] spi: airoha: allow reading/writing of oob area Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 10/14] spi: airoha: buffer must be 0xff-ed before writing Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 11/14] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 12/14] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 13/14] spi: airoha: set custom sector size equal to flash page size Mikhail Kshevetskiy
2025-08-20 12:33 ` [PATCH v3 14/14] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup Mikhail Kshevetskiy
2025-08-21  6:58 ` [PATCH v3 00/14] spi: airoha: driver fixes & improvements Lorenzo Bianconi
2025-08-21 11:13   ` Mikhail Kshevetskiy
2025-08-21 11:34     ` Lorenzo Bianconi
2025-08-21 12:24       ` Mikhail Kshevetskiy
2025-08-22  3:31       ` Mikhail Kshevetskiy
2025-08-22  6:46         ` Lorenzo Bianconi
2025-08-22 11:22           ` Mikhail Kshevetskiy
2025-08-22 13:14             ` Lorenzo Bianconi
2025-08-22 14:36               ` Mikhail Kshevetskiy
2025-08-22 20:00               ` Mikhail Kshevetskiy
2025-08-22 11:27           ` Mikhail Kshevetskiy
2025-08-23  0:16           ` [PATCH v4 00/13] " Mikhail Kshevetskiy
2025-08-23  0:16             ` [PATCH v4 01/13] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
2025-08-23  8:04               ` Lorenzo Bianconi
2025-08-23 13:52                 ` Mikhail Kshevetskiy
2025-08-23  0:16             ` [PATCH v4 02/13] spi: airoha: remove unnecessary restriction length Mikhail Kshevetskiy
2025-08-23  0:16             ` [PATCH v4 03/13] spi: airoha: add support of dual/quad wires spi modes Mikhail Kshevetskiy
2025-08-23  8:16               ` Lorenzo Bianconi
2025-08-23 13:54                 ` Mikhail Kshevetskiy
2025-08-23 14:42                   ` Lorenzo Bianconi
2025-08-23  0:16             ` [PATCH v4 04/13] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
2025-08-23  8:29               ` Lorenzo Bianconi
2025-08-23  0:16             ` [PATCH v4 05/13] spi: airoha: unify dirmap read/write code Mikhail Kshevetskiy
2025-08-23  0:16             ` [PATCH v4 06/13] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
2025-08-23  8:34               ` Lorenzo Bianconi
2025-08-23  0:16             ` [PATCH v4 07/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
2025-08-23  8:36               ` Lorenzo Bianconi
2025-08-23  0:16             ` [PATCH v4 08/13] spi: airoha: support of dualio/quadio flash reading commands Mikhail Kshevetskiy
2025-08-23  0:16             ` [PATCH v4 09/13] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT Mikhail Kshevetskiy
2025-08-23  0:16             ` [PATCH v4 10/13] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers Mikhail Kshevetskiy
2025-08-23  0:16             ` [PATCH v4 11/13] spi: airoha: set custom sector size equal to flash page size Mikhail Kshevetskiy
2025-08-23  0:16             ` [PATCH v4 12/13] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup Mikhail Kshevetskiy
2025-08-23  0:16             ` [PATCH v4 13/13] spi: airoha: buffer must be 0xff-ed before writing Mikhail Kshevetskiy
2025-08-23 16:01             ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 01/13] spi: airoha: return an error for continuous mode dirmap creation cases Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 02/13] spi: airoha: remove unnecessary restriction length Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 03/13] spi: airoha: add support of dual/quad wires spi modes to exec_op() handler Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 04/13] spi: airoha: remove unnecessary switch to non-dma mode Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 05/13] spi: airoha: switch back to non-dma mode in the case of error Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 06/13] spi: airoha: fix reading/writing of flashes with more than one plane per lun Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 07/13] spi: airoha: unify dirmap read/write code Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 08/13] spi: airoha: support of dualio/quadio flash reading commands Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 09/13] spi: airoha: avoid setting of page/oob sizes in REG_SPI_NFI_PAGEFMT Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 10/13] spi: airoha: reduce the number of modification of REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 11/13] spi: airoha: set custom sector size equal to flash page size Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 12/13] spi: airoha: avoid reading flash page settings from SNFI registers during driver startup Mikhail Kshevetskiy
2025-08-23 16:01               ` [PATCH v5 13/13] spi: airoha: buffer must be 0xff-ed before writing Mikhail Kshevetskiy
2025-08-29  7:14               ` [PATCH v5 00/13] spi: airoha: driver fixes & improvements Mikhail Kshevetskiy
2025-08-29  8:45                 ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).