public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
@ 2025-11-19  5:12 Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 01/11] spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe() Takahiro Kuwano via B4 Relay
                   ` (11 more replies)
  0 siblings, 12 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:12 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

This series suggests to isolate stacked/parallel support from
spi-nor-core by moving that to SPI controllers and new modules under
mtd/spi.

The patchset mainly focuses on removing references to stacked/parallel
related items from core. The stacked/parallel support logic itself may
have rooms to improve. Rework or further cleanup in stacked/parallel
support would be done by other patches after this series is applied.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
Takahiro Kuwano (11):
      spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe()
      spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag.
      spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode
      spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe()
      spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag.
      spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode
      mtd: spi-nor: Migrate stacked/parallel part to new modules
      mtd: spi-nor: stacked: Cleanup stacked/parallel flags
      mtd: spi-nor: parallel: Cleanup stacked/parallel flags
      mtd: spi-nor: Revert stacked/parallel related commits
      mtd: spi-nor: Call stacked/parallel post init fixups

 drivers/mtd/spi/Makefile       |   4 +
 drivers/mtd/spi/parallel.c     | 412 ++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/spi/sf_internal.h  |  18 ++
 drivers/mtd/spi/spi-nor-core.c | 422 +++++++----------------------------------
 drivers/mtd/spi/stacked.c      | 389 +++++++++++++++++++++++++++++++++++++
 drivers/spi/zynq_qspi.c        |  47 +++--
 drivers/spi/zynqmp_gqspi.c     |  55 ++++--
 include/linux/mtd/spi-nor.h    |  10 -
 include/spi.h                  |   2 -
 9 files changed, 973 insertions(+), 386 deletions(-)
---
base-commit: e2d51f8db207f7db70dd8104fa1da2cffda419f2
change-id: 20251118-amd-cleanup-c8023872e3cf

Best regards,
-- 
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>



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

* [PATCH 01/11] spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe()
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 02/11] spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag Takahiro Kuwano via B4 Relay
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

priv->is_parallel should be set at probe instead of at every exec_op().
It can be set in child_pre_probe() by checking the existence of
parallel-memories property.

Also remove GQSPI_SELECT_LOWER/UPPER_CS flags. They are problematic as
they overwrite SPI_XFER_BEGIN/END defined in spi.h.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/spi/zynqmp_gqspi.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c
index 2a095d0c58e..4a25ee0c459 100644
--- a/drivers/spi/zynqmp_gqspi.c
+++ b/drivers/spi/zynqmp_gqspi.c
@@ -89,9 +89,6 @@
 #define SPI_XFER_ON_LOWER		1
 #define SPI_XFER_ON_UPPER		2
 
-#define GQSPI_SELECT_LOWER_CS          BIT(0)
-#define GQSPI_SELECT_UPPER_CS          BIT(1)
-
 #define GQSPI_DMA_ALIGN			0x4
 #define GQSPI_MAX_BAUD_RATE_VAL		7
 #define GQSPI_DFLT_BAUD_RATE_VAL	2
@@ -439,6 +436,13 @@ static int zynqmp_qspi_child_pre_probe(struct udevice *bus)
 	slave->bytemode = SPI_4BYTE_MODE;
 	priv->max_hz = slave->max_hz;
 
+	/*
+	 * The property has values that represent flash sizes but we just need
+	 * to know the existence of the property here.
+	 */
+	priv->is_parallel = ofnode_read_bool(dev_ofnode(bus),
+					     "parallel-memories");
+
 	return 0;
 }
 
@@ -862,10 +866,6 @@ static int zynqmp_qspi_exec_op(struct spi_slave *slave,
 	else
 		priv->u_page = 0;
 
-	if ((slave->flags & GQSPI_SELECT_LOWER_CS) &&
-	    (slave->flags & GQSPI_SELECT_UPPER_CS))
-		priv->is_parallel = true;
-
 	priv->stripe = 0;
 	priv->bus = 0;
 
@@ -889,7 +889,6 @@ static int zynqmp_qspi_exec_op(struct spi_slave *slave,
 
 	zynqmp_qspi_chipselect(priv, 0);
 
-	priv->is_parallel = false;
 	slave->flags &= ~SPI_XFER_LOWER;
 
 	return ret;

-- 
2.34.1



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

* [PATCH 02/11] spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag.
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 01/11] spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe() Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 03/11] spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode Takahiro Kuwano via B4 Relay
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

SPI_XFER_LOWER is set in spi-nor-core for reading ID, SFDP and BAR.
The flag is referenced by AMD controllers only. Controller drivers can
intercept the opcode and change its settings accordingly.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/spi/zynqmp_gqspi.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c
index 4a25ee0c459..143b957516b 100644
--- a/drivers/spi/zynqmp_gqspi.c
+++ b/drivers/spi/zynqmp_gqspi.c
@@ -823,6 +823,23 @@ static int zynqmp_qspi_release_bus(struct udevice *dev)
 	return 0;
 }
 
+static bool zynqmp_qspi_is_lower_only(const struct spi_mem_op *op)
+{
+	/*
+	 * This is a list of opcodes for which we must read only from lower chip
+	 * in dual parallel mode.
+	 */
+	switch (op->cmd.opcode) {
+	case SPINOR_OP_RDID:
+	case SPINOR_OP_RDSFDP:
+	case SPINOR_OP_BRRD:
+	case SPINOR_OP_RDEAR:
+		return true;
+	}
+
+	return false;
+}
+
 static bool zynqmp_qspi_update_stripe(const struct spi_mem_op *op)
 {
 	/*
@@ -870,7 +887,7 @@ static int zynqmp_qspi_exec_op(struct spi_slave *slave,
 	priv->bus = 0;
 
 	if (priv->is_parallel) {
-		if (slave->flags & SPI_XFER_LOWER)
+		if (zynqmp_qspi_is_lower_only(op))
 			priv->bus = 1;
 		if (zynqmp_qspi_update_stripe(op))
 			priv->stripe = 1;
@@ -889,8 +906,6 @@ static int zynqmp_qspi_exec_op(struct spi_slave *slave,
 
 	zynqmp_qspi_chipselect(priv, 0);
 
-	slave->flags &= ~SPI_XFER_LOWER;
-
 	return ret;
 }
 

-- 
2.34.1



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

* [PATCH 03/11] spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 01/11] spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe() Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 02/11] spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 04/11] spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe() Takahiro Kuwano via B4 Relay
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

In parallel mode, status register value of two chips need to be read
and evaluated. Currenlty spi-nor-core takes care for that by reading
two bytes and performing logical AND of two bytes for read_sr() and
read_fsr(), assuming the controller performs byte interleaving in
parallel mode, but it depends on controller specification.

Controller driver should take care for parallel mode to read status
registers.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/spi/zynqmp_gqspi.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c
index 143b957516b..c6cd706574e 100644
--- a/drivers/spi/zynqmp_gqspi.c
+++ b/drivers/spi/zynqmp_gqspi.c
@@ -867,11 +867,23 @@ static bool zynqmp_qspi_update_stripe(const struct spi_mem_op *op)
 	}
 }
 
+static bool zynqmp_qspi_is_read_status(const struct spi_mem_op *op)
+{
+	switch (op->cmd.opcode) {
+	case SPINOR_OP_RDSR:
+	case SPINOR_OP_RDFSR:
+		return true;
+	}
+
+	return false;
+}
+
 static int zynqmp_qspi_exec_op(struct spi_slave *slave,
 			       const struct spi_mem_op *op)
 {
 	struct zynqmp_qspi_priv *priv = dev_get_priv(slave->dev->parent);
 	int ret = 0;
+	u8 sr_buf[2];
 
 	priv->op = op;
 	priv->tx_buf = op->data.buf.out;
@@ -891,6 +903,10 @@ static int zynqmp_qspi_exec_op(struct spi_slave *slave,
 			priv->bus = 1;
 		if (zynqmp_qspi_update_stripe(op))
 			priv->stripe = 1;
+		if (zynqmp_qspi_is_read_status(op)) {
+			priv->rx_buf = sr_buf;
+			priv->len = 2;
+		}
 	}
 
 	zynqmp_qspi_chipselect(priv, 1);
@@ -904,6 +920,9 @@ static int zynqmp_qspi_exec_op(struct spi_slave *slave,
 	else if (op->data.dir == SPI_MEM_DATA_OUT)
 		ret = zynqmp_qspi_genfifo_fill_tx(priv);
 
+	if (priv->is_parallel && zynqmp_qspi_is_read_status(op))
+		*(u8 *)op->data.buf.in = sr_buf[0] & sr_buf[1];
+
 	zynqmp_qspi_chipselect(priv, 0);
 
 	return ret;

-- 
2.34.1



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

* [PATCH 04/11] spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe()
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
                   ` (2 preceding siblings ...)
  2025-11-19  5:13 ` [PATCH 03/11] spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 05/11] spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag Takahiro Kuwano via B4 Relay
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

priv->is_paralle/stacked should be set at probe instead of at every
exec_op(). It can be set in child_pre_probe() by checking the existence
of parallel/stacked-memories property.

Also remove QSPI_SELECT_LOWER/UPPER_CS flags. They are problematic as
they overwrite SPI_XFER_BEGIN/END defined in spi.h.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/spi/zynq_qspi.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c
index e43dbb40c4a..a2d6d80d04e 100644
--- a/drivers/spi/zynq_qspi.c
+++ b/drivers/spi/zynq_qspi.c
@@ -46,9 +46,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #define ZYNQ_QSPI_TXD_00_11_OFFSET	0x88	/* Transmit 3-byte inst */
 #define ZYNQ_QSPI_FR_QOUT_CODE		0x6B    /* read instruction code */
 
-#define QSPI_SELECT_LOWER_CS            BIT(0)
-#define QSPI_SELECT_UPPER_CS            BIT(1)
-
 /*
  * QSPI Linear Configuration Register
  *
@@ -205,6 +202,15 @@ static int zynq_qspi_child_pre_probe(struct udevice *bus)
 	priv->max_hz = slave->max_hz;
 	slave->multi_cs_cap = true;
 
+	/*
+	 * The properties have values that represent flash sizes but we just
+	 * need to know the existence of the property here.
+	 */
+	priv->is_parallel = ofnode_read_bool(dev_ofnode(bus),
+					     "parallel-memories");
+	priv->is_stacked = ofnode_read_bool(dev_ofnode(bus),
+					    "stacked-memories");
+
 	return 0;
 }
 
@@ -757,12 +763,6 @@ static int zynq_qspi_exec_op(struct spi_slave *slave,
 	const u8 *tx_buf = NULL;
 	u8 *rx_buf = NULL;
 
-	if ((slave->flags & QSPI_SELECT_LOWER_CS) &&
-	    (slave->flags & QSPI_SELECT_UPPER_CS))
-		priv->is_parallel = true;
-	if (slave->flags & SPI_XFER_STACKED)
-		priv->is_stacked = true;
-
 	if (op->data.nbytes) {
 		if (op->data.dir == SPI_MEM_DATA_IN)
 			rx_buf = op->data.buf.in;
@@ -811,8 +811,6 @@ static int zynq_qspi_exec_op(struct spi_slave *slave,
 			return ret;
 	}
 
-	priv->is_parallel = false;
-	priv->is_stacked = false;
 	slave->flags &= ~SPI_XFER_LOWER;
 	spi_release_bus(slave);
 

-- 
2.34.1



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

* [PATCH 05/11] spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag.
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
                   ` (3 preceding siblings ...)
  2025-11-19  5:13 ` [PATCH 04/11] spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe() Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 06/11] spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode Takahiro Kuwano via B4 Relay
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

SPI_XFER_LOWER is reset at the end of exec_op() but not checked.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/spi/zynq_qspi.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c
index a2d6d80d04e..67005a3b8df 100644
--- a/drivers/spi/zynq_qspi.c
+++ b/drivers/spi/zynq_qspi.c
@@ -811,7 +811,6 @@ static int zynq_qspi_exec_op(struct spi_slave *slave,
 			return ret;
 	}
 
-	slave->flags &= ~SPI_XFER_LOWER;
 	spi_release_bus(slave);
 
 	return 0;

-- 
2.34.1



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

* [PATCH 06/11] spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
                   ` (4 preceding siblings ...)
  2025-11-19  5:13 ` [PATCH 05/11] spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 07/11] mtd: spi-nor: Migrate stacked/parallel part to new modules Takahiro Kuwano via B4 Relay
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

In parallel mode, status register value of two chips need to be read
and evaluated. Currenlty spi-nor-core takes care for that by reading
two bytes and performing logical AND of two bytes for read_sr() and
read_fsr(), assuming the controller performs byte interleaving in
parallel mode, but it depends on controller specification.

Controller driver should take care for parallel mode to read status
registers.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/spi/zynq_qspi.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c
index 67005a3b8df..3d9fc11314f 100644
--- a/drivers/spi/zynq_qspi.c
+++ b/drivers/spi/zynq_qspi.c
@@ -753,6 +753,17 @@ static bool update_stripe(const struct spi_mem_op *op)
 	return true;
 }
 
+static bool zynq_qspi_is_read_status(const struct spi_mem_op *op)
+{
+	switch (op->cmd.opcode) {
+	case SPINOR_OP_RDSR:
+	case SPINOR_OP_RDFSR:
+		return true;
+	}
+
+	return false;
+}
+
 static int zynq_qspi_exec_op(struct spi_slave *slave,
 			     const struct spi_mem_op *op)
 {
@@ -762,6 +773,7 @@ static int zynq_qspi_exec_op(struct spi_slave *slave,
 	unsigned int flag = 0;
 	const u8 *tx_buf = NULL;
 	u8 *rx_buf = NULL;
+	u8 sr_buf[2];
 
 	if (op->data.nbytes) {
 		if (op->data.dir == SPI_MEM_DATA_IN)
@@ -805,10 +817,20 @@ static int zynq_qspi_exec_op(struct spi_slave *slave,
 
 	/* 2nd transfer: rx or tx data path */
 	if (tx_buf || rx_buf) {
-		ret = zynq_qspi_xfer(slave->dev, op->data.nbytes * 8, tx_buf,
-				     rx_buf, flag | SPI_XFER_END);
+		op_len = op->data.nbytes;
+
+		if (priv->is_parallel && zynq_qspi_is_read_status(op)) {
+			rx_buf = sr_buf;
+			op_len = 2;
+		}
+
+		ret = zynq_qspi_xfer(slave->dev, op_len * 8, tx_buf, rx_buf,
+				     flag | SPI_XFER_END);
 		if (ret)
 			return ret;
+
+		if (priv->is_parallel && zynq_qspi_is_read_status(op))
+			*(u8 *)op->data.buf.in = sr_buf[0] & sr_buf[1];
 	}
 
 	spi_release_bus(slave);

-- 
2.34.1



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

* [PATCH 07/11] mtd: spi-nor: Migrate stacked/parallel part to new modules
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
                   ` (5 preceding siblings ...)
  2025-11-19  5:13 ` [PATCH 06/11] spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 08/11] mtd: spi-nor: stacked: Cleanup stacked/parallel flags Takahiro Kuwano via B4 Relay
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

Add new modules named stacked.c and parallel.c. Those are compiled along
with spi-nor-core in case CONFIG_SPI_STACKED_PARALLEL is enabled.

Copy erase/program/read and write_bar functions from core to both
modules. Some helper functions inn core are exposed.

Introduce new fixup functions, spi_nor_stacked_post_init_fixups() and
spi_nor_parallel_post_init_fixups() in each module. Those implement
ofnode property check performed in spi_nor_init_params() in core, update
size parameters with replacing params->*, and assign erase/program/read
to mtd_info. The fixups will be called from core after spi_nor_init()
call.

In stacked mode, spi_nor_init() is called twice to init upper page.
spi_nor_stacked_post_init_fixups() performs the second call of
spi_nor_init().

In parallel mode, there are size updates in spi_nor_select_erase(),
spi_nor_set_4byte_opcodes(), and spi_nor_scan(). Those are not moved to
parallel module as size update can be consolidated into one place,
spi_nor_parallel_post_init_fixups(). Besides, write_bar call performed
in read_bar() is moved to fixup as read_bar() is called once before
spi_nor_init() and shouldn't be a problem if it is called after
spi_nor_init().

At this point, keep spi-nor-core as it is, reverting stacked/parallel
related changes will be done at once in another patch.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/mtd/spi/Makefile       |   4 +
 drivers/mtd/spi/parallel.c     | 470 +++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/spi/sf_internal.h  |  15 ++
 drivers/mtd/spi/spi-nor-core.c |  22 +-
 drivers/mtd/spi/stacked.c      | 453 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 953 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index 44e67cd913a..563f61bd1aa 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -17,6 +17,10 @@ else
 spi-nor-y += spi-nor-core.o
 endif
 
+ifneq (,$(findstring spi-nor-core, $(spi-nor-y)))
+spi-nor-$(CONFIG_SPI_STACKED_PARALLEL) += stacked.o parallel.o
+endif
+
 obj-$(CONFIG_SPI_FLASH) += spi-nor.o
 obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o
 obj-$(CONFIG_$(PHASE_)SPI_FLASH_MTD) += sf_mtd.o
diff --git a/drivers/mtd/spi/parallel.c b/drivers/mtd/spi/parallel.c
new file mode 100644
index 00000000000..d884eaefcd0
--- /dev/null
+++ b/drivers/mtd/spi/parallel.c
@@ -0,0 +1,470 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2025 Infineon Technologies
+ *
+ * SPI NOR driver for parallel-memories configuration.
+ */
+
+#include <dm/device_compat.h>
+#include <linux/err.h>
+#include <linux/math64.h>
+#include <linux/sizes.h>
+#include <linux/mtd/spi-nor.h>
+#include <spi.h>
+
+#include "sf_internal.h"
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+static int write_bar(struct spi_nor *nor, u32 offset)
+{
+	u8 cmd, bank_sel, upage_curr;
+	int ret;
+	struct mtd_info *mtd = &nor->mtd;
+
+	/* Wait until previous write command is finished */
+	if (spi_nor_wait_till_ready(nor))
+		return 1;
+
+	if (nor->flags & (SNOR_F_HAS_PARALLEL | SNOR_F_HAS_STACKED) &&
+	    mtd->size <= SZ_32M)
+		return 0;
+
+	if (mtd->size <= SZ_16M)
+		return 0;
+
+	offset = offset % (u32)mtd->size;
+	bank_sel = offset >> 24;
+
+	upage_curr = nor->spi->flags & SPI_XFER_U_PAGE;
+
+	if (!(nor->flags & SNOR_F_HAS_STACKED) && bank_sel == nor->bank_curr)
+		return 0;
+	else if (upage_curr == nor->upage_prev && bank_sel == nor->bank_curr)
+		return 0;
+
+	nor->upage_prev = upage_curr;
+
+	cmd = nor->bank_write_cmd;
+	write_enable(nor);
+	ret = nor->write_reg(nor, cmd, &bank_sel, 1);
+	if (ret < 0) {
+		debug("SF: fail to write bank register\n");
+		return ret;
+	}
+
+	nor->bank_curr = bank_sel;
+
+	return write_disable(nor);
+}
+#endif
+
+static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	u32 addr, len, rem, offset, max_size;
+	bool addr_known = false;
+	int ret, err;
+
+	dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr,
+		(long long)instr->len);
+
+	div_u64_rem(instr->len, mtd->erasesize, &rem);
+	if (rem) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	addr = instr->addr;
+	len = instr->len;
+	max_size = instr->len;
+
+	instr->state = MTD_ERASING;
+	addr_known = true;
+
+	while (len) {
+		schedule();
+		if (!IS_ENABLED(CONFIG_XPL_BUILD) && ctrlc()) {
+			addr_known = false;
+			ret = -EINTR;
+			goto erase_err;
+		}
+		offset = addr;
+		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+			if (nor->flags & SNOR_F_HAS_PARALLEL)
+				offset /= 2;
+
+			if (nor->flags & SNOR_F_HAS_STACKED) {
+				if (offset >= (mtd->size / 2))
+					nor->spi->flags |= SPI_XFER_U_PAGE;
+				else
+					nor->spi->flags &= ~SPI_XFER_U_PAGE;
+			}
+		}
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+		ret = write_bar(nor, offset);
+		if (ret < 0)
+			goto erase_err;
+#endif
+		ret = write_enable(nor);
+		if (ret < 0)
+			goto erase_err;
+
+		if (len == mtd->size &&
+		    !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
+			ret = spi_nor_erase_chip(nor);
+		} else {
+			ret = spi_nor_erase_sector(nor, offset);
+		}
+		if (ret < 0)
+			goto erase_err;
+
+		addr += ret;
+		len -= ret;
+
+		if (max_size == mtd->size &&
+		    !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
+			ret = spi_nor_erase_chip_wait_till_ready(nor, mtd->size);
+		} else {
+			ret = spi_nor_wait_till_ready(nor);
+		}
+
+		if (ret)
+			goto erase_err;
+	}
+
+	addr_known = false;
+erase_err:
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+	err = clean_bar(nor);
+	if (!ret)
+		ret = err;
+#endif
+	err = write_disable(nor);
+	if (!ret)
+		ret = err;
+
+err:
+	if (ret) {
+		instr->fail_addr = addr_known ? addr : MTD_FAIL_ADDR_UNKNOWN;
+		instr->state = MTD_ERASE_FAILED;
+	} else {
+		instr->state = MTD_ERASE_DONE;
+	}
+
+	return ret;
+}
+
+static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t *retlen, u_char *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	loff_t offset = from;
+	u32 rem_bank_len = 0;
+	u32 stack_shift = 0;
+	size_t read_len;
+	u8 bank;
+	int ret;
+	bool is_ofst_odd = false;
+
+	dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
+
+	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (offset & 1)) {
+		/* We can hit this case when we use file system like ubifs */
+		from--;
+		len++;
+		is_ofst_odd = true;
+	}
+
+	while (len) {
+		read_len = len;
+		offset = from;
+
+		if (CONFIG_IS_ENABLED(SPI_FLASH_BAR)) {
+			bank = (u32)from / SZ_16M;
+			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+				if (nor->flags & SNOR_F_HAS_PARALLEL)
+					bank /= 2;
+			}
+			rem_bank_len = SZ_16M * (bank + 1);
+			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+				if (nor->flags & SNOR_F_HAS_PARALLEL)
+					rem_bank_len *= 2;
+			}
+			rem_bank_len -= from;
+		}
+
+		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+			if (nor->flags & SNOR_F_HAS_STACKED) {
+				stack_shift = 1;
+				if (offset >= (mtd->size / 2)) {
+					offset = offset - (mtd->size / 2);
+					nor->spi->flags |= SPI_XFER_U_PAGE;
+				} else {
+					nor->spi->flags &= ~SPI_XFER_U_PAGE;
+				}
+			}
+		}
+
+		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+			if (nor->flags & SNOR_F_HAS_PARALLEL)
+				offset /= 2;
+		}
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+		ret = write_bar(nor, offset);
+		if (ret < 0)
+			return log_ret(ret);
+		if (len < rem_bank_len)
+			read_len = len;
+		else
+			read_len = rem_bank_len;
+#endif
+
+		if (read_len == 0)
+			return -EIO;
+
+		ret = nor->read(nor, offset, read_len, buf);
+		if (ret == 0) {
+			/* We shouldn't see 0-length reads */
+			ret = -EIO;
+			goto read_err;
+		}
+		if (ret < 0)
+			goto read_err;
+
+		if (is_ofst_odd == true) {
+			memmove(buf, (buf + 1), (len - 1));
+			*retlen += (ret - 1);
+			buf += ret - 1;
+			is_ofst_odd = false;
+		} else {
+			*retlen += ret;
+			buf += ret;
+		}
+		from += ret;
+		len -= ret;
+	}
+	ret = 0;
+
+read_err:
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+	ret = clean_bar(nor);
+#endif
+	return ret;
+}
+
+static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
+	size_t *retlen, const u_char *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	size_t page_offset, page_remain, i;
+	ssize_t ret;
+	u32 offset;
+
+#ifdef CONFIG_SPI_FLASH_SST
+	/* sst nor chips use AAI word program */
+	if (nor->info->flags & SST_WRITE)
+		return sst_write(mtd, to, len, retlen, buf);
+#endif
+
+	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
+
+	if (!len)
+		return 0;
+
+	/*
+	 * Cannot write to odd offset in parallel mode,
+	 * so write 2 bytes first
+	 */
+	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (to & 1)) {
+		u8 two[2] = {0xff, buf[0]};
+		size_t local_retlen;
+
+		ret = spi_nor_write(mtd, to & ~1, 2, &local_retlen, two);
+		if (ret < 0)
+			return ret;
+
+		*retlen += 1; /* We've written only one actual byte */
+		buf++;
+		len--;
+		to++;
+	}
+
+	for (i = 0; i < len; ) {
+		ssize_t written;
+		loff_t addr = to + i;
+		schedule();
+
+		/*
+		 * If page_size is a power of two, the offset can be quickly
+		 * calculated with an AND operation. On the other cases we
+		 * need to do a modulus operation (more expensive).
+		 */
+		if (is_power_of_2(nor->page_size)) {
+			page_offset = addr & (nor->page_size - 1);
+		} else {
+			u64 aux = addr;
+
+			page_offset = do_div(aux, nor->page_size);
+		}
+		offset = to + i;
+		if (nor->flags & SNOR_F_HAS_PARALLEL)
+			offset /= 2;
+
+		if (nor->flags & SNOR_F_HAS_STACKED) {
+			if (offset >= (mtd->size / 2)) {
+				offset = offset - (mtd->size / 2);
+				nor->spi->flags |= SPI_XFER_U_PAGE;
+			} else {
+				nor->spi->flags &= ~SPI_XFER_U_PAGE;
+			}
+		}
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+		ret = write_bar(nor, offset);
+		if (ret < 0)
+			return ret;
+#endif
+
+		/* the size of data remaining on the first page */
+		page_remain = min_t(size_t,
+				    nor->page_size - page_offset, len - i);
+
+		write_enable(nor);
+		/*
+		 * On DTR capable flashes like Micron Xcella the writes cannot
+		 * start or end at an odd address in DTR mode. So we need to
+		 * append or prepend extra 0xff bytes to make sure the start
+		 * address and end address are even.
+		 */
+		if (spi_nor_protocol_is_dtr(nor->write_proto) &&
+		    ((offset | page_remain) & 1)) {
+			u_char *tmp;
+			size_t extra_bytes = 0;
+
+			tmp = kmalloc(nor->page_size, 0);
+			if (!tmp) {
+				ret = -ENOMEM;
+				goto write_err;
+			}
+
+			/* Prepend a 0xff byte if the start address is odd. */
+			if (offset & 1) {
+				tmp[0] = 0xff;
+				memcpy(tmp + 1, buf + i, page_remain);
+				offset--;
+				page_remain++;
+				extra_bytes++;
+			} else {
+				memcpy(tmp, buf + i, page_remain);
+			}
+
+			/* Append a 0xff byte if the end address is odd. */
+			if ((offset + page_remain) & 1) {
+				tmp[page_remain + extra_bytes] = 0xff;
+				extra_bytes++;
+				page_remain++;
+			}
+
+			ret = nor->write(nor, offset, page_remain, tmp);
+
+			kfree(tmp);
+
+			if (ret < 0)
+				goto write_err;
+
+			/*
+			 * We write extra bytes but they are not part of the
+			 * original write.
+			 */
+			written = ret - extra_bytes;
+		} else {
+			ret = nor->write(nor, offset, page_remain, buf + i);
+			if (ret < 0)
+				goto write_err;
+			written = ret;
+		}
+
+		ret = spi_nor_wait_till_ready(nor);
+		if (ret)
+			goto write_err;
+
+		*retlen += written;
+		i += written;
+	}
+
+write_err:
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+	ret = clean_bar(nor);
+#endif
+	return ret;
+}
+
+int spi_nor_parallel_post_init_fixups(struct spi_nor *nor)
+{
+	struct mtd_info *mtd = &nor->mtd;
+
+#if CONFIG_IS_ENABLED(DM_SPI)
+	u64 flash_size[SNOR_FLASH_CNT_MAX] = { 0 };
+	struct udevice *dev = nor->spi->dev;
+	u32 idx = 0, i = 0;
+	int rc;
+
+	while (i < SNOR_FLASH_CNT_MAX) {
+		rc = ofnode_read_u64_index(dev_ofnode(dev), "parallel-memories",
+					   idx, &flash_size[i]);
+		if (rc == -EINVAL) {
+			break;
+		} else if (rc == -EOVERFLOW) {
+			idx++;
+		} else {
+			idx++;
+			i++;
+			if (!(nor->flags & SNOR_F_HAS_PARALLEL))
+				nor->flags |= SNOR_F_HAS_PARALLEL;
+		}
+	}
+
+	if (nor->flags & (SNOR_F_HAS_STACKED | SNOR_F_HAS_PARALLEL)) {
+		mtd->size = 0;
+		for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++)
+			mtd->size += flash_size[idx];
+	}
+
+	/*
+	 * In parallel-memories the erase operation is
+	 * performed on both the flashes simultaneously
+	 * so, double the erasesize.
+	 */
+	if (nor->flags & SNOR_F_HAS_PARALLEL) {
+		nor->mtd.erasesize <<= 1;
+		nor->page_size <<= 1;
+		nor->mtd.writebufsize <<= 1;
+	}
+#endif
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+	/* Make sure both chips use the same BAR */
+	if (nor->flags & SNOR_F_HAS_PARALLEL) {
+		int ret;
+
+		write_enable(nor);
+		ret = nor->write_reg(nor, nor->bank_write_cmd, &nor->bank_curr,
+				     1);
+		if (ret)
+			return ret;
+
+		ret = write_disable(nor);
+		if (ret)
+			return ret;
+	}
+#endif
+
+	if (nor->flags & SNOR_F_HAS_PARALLEL) {
+		mtd->_erase = spi_nor_erase;
+		mtd->_read = spi_nor_read;
+		mtd->_write = spi_nor_write;
+	}
+
+	return 0;
+}
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 8d2249ce354..8b1a48f045a 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -93,4 +93,19 @@ static inline void spi_flash_mtd_unregister(struct spi_flash *flash)
 }
 #endif
 
+#if !CONFIG_IS_ENABLED(SPI_FLASH_TINY)
+int spi_nor_init(struct spi_nor *nor);
+int write_enable(struct spi_nor *nor);
+int write_disable(struct spi_nor *nor);
+int spi_nor_wait_till_ready(struct spi_nor *nor);
+struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd);
+#endif
+
+int spi_nor_erase_chip_wait_till_ready(struct spi_nor *nor, unsigned long size);
+int spi_nor_erase_chip(struct spi_nor *nor);
+int spi_nor_erase_sector(struct spi_nor *nor, u32 addr);
+int clean_bar(struct spi_nor *nor);
+int sst_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
+	      const u_char *buf);
+
 #endif /* _SF_INTERNAL_H_ */
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 76c33b24368..9695a706d0b 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -637,7 +637,7 @@ static int write_sr3(struct spi_nor *nor, u8 val)
  * Set write enable latch with Write Enable command.
  * Returns negative if error occurred.
  */
-static int write_enable(struct spi_nor *nor)
+int write_enable(struct spi_nor *nor)
 {
 	return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0);
 }
@@ -645,12 +645,12 @@ static int write_enable(struct spi_nor *nor)
 /*
  * Send write disable instruction to the chip.
  */
-static int write_disable(struct spi_nor *nor)
+int write_disable(struct spi_nor *nor)
 {
 	return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0);
 }
 
-static struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
+struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 {
 	return mtd->priv;
 }
@@ -910,13 +910,13 @@ static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor,
 	return -ETIMEDOUT;
 }
 
-static int spi_nor_wait_till_ready(struct spi_nor *nor)
+int spi_nor_wait_till_ready(struct spi_nor *nor)
 {
 	return spi_nor_wait_till_ready_with_timeout(nor,
 						    DEFAULT_READY_WAIT_JIFFIES);
 }
 
-static int spi_nor_erase_chip_wait_till_ready(struct spi_nor *nor, unsigned long size)
+int spi_nor_erase_chip_wait_till_ready(struct spi_nor *nor, unsigned long size)
 {
 	/*
 	 * Scale the timeout linearly with the size of the flash, with
@@ -941,7 +941,7 @@ static int spi_nor_erase_chip_wait_till_ready(struct spi_nor *nor, unsigned long
  * Otherwise, the BA24 bit may be left set and then after reset, the
  * ROM would read/write/erase SPL from 16 MiB * bank_sel address.
  */
-static int clean_bar(struct spi_nor *nor)
+int clean_bar(struct spi_nor *nor)
 {
 	u8 cmd, bank_sel = 0;
 	int ret;
@@ -1053,7 +1053,7 @@ static int read_bar(struct spi_nor *nor, const struct flash_info *info)
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_erase_chip(struct spi_nor *nor)
+int spi_nor_erase_chip(struct spi_nor *nor)
 {
 	struct spi_mem_op op =
 		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),
@@ -1075,7 +1075,7 @@ static int spi_nor_erase_chip(struct spi_nor *nor)
  * Initiate the erasure of a single sector. Returns the number of bytes erased
  * on success, a negative error code on error.
  */
-static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
+int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
 {
 	struct spi_mem_op op =
 		SPI_MEM_OP(SPI_MEM_OP_CMD(nor->erase_opcode, 0),
@@ -1885,8 +1885,8 @@ sst_write_err:
 	return ret;
 }
 
-static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
-		     size_t *retlen, const u_char *buf)
+int sst_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
+	      const u_char *buf)
 {
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 	struct spi_slave *spi = nor->spi;
@@ -4278,7 +4278,7 @@ static int spi_nor_octal_dtr_enable(struct spi_nor *nor)
 	return 0;
 }
 
-static int spi_nor_init(struct spi_nor *nor)
+int spi_nor_init(struct spi_nor *nor)
 {
 	int err;
 
diff --git a/drivers/mtd/spi/stacked.c b/drivers/mtd/spi/stacked.c
new file mode 100644
index 00000000000..e005aea1053
--- /dev/null
+++ b/drivers/mtd/spi/stacked.c
@@ -0,0 +1,453 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2025 Infineon Technologies
+ *
+ * SPI NOR driver for stacked-memories configuration.
+ */
+
+#include <dm/device_compat.h>
+#include <linux/err.h>
+#include <linux/math64.h>
+#include <linux/sizes.h>
+#include <linux/mtd/spi-nor.h>
+#include <spi.h>
+
+#include "sf_internal.h"
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+static int write_bar(struct spi_nor *nor, u32 offset)
+{
+	u8 cmd, bank_sel, upage_curr;
+	int ret;
+	struct mtd_info *mtd = &nor->mtd;
+
+	/* Wait until previous write command is finished */
+	if (spi_nor_wait_till_ready(nor))
+		return 1;
+
+	if (nor->flags & (SNOR_F_HAS_PARALLEL | SNOR_F_HAS_STACKED) &&
+	    mtd->size <= SZ_32M)
+		return 0;
+
+	if (mtd->size <= SZ_16M)
+		return 0;
+
+	offset = offset % (u32)mtd->size;
+	bank_sel = offset >> 24;
+
+	upage_curr = nor->spi->flags & SPI_XFER_U_PAGE;
+
+	if (!(nor->flags & SNOR_F_HAS_STACKED) && bank_sel == nor->bank_curr)
+		return 0;
+	else if (upage_curr == nor->upage_prev && bank_sel == nor->bank_curr)
+		return 0;
+
+	nor->upage_prev = upage_curr;
+
+	cmd = nor->bank_write_cmd;
+	write_enable(nor);
+	ret = nor->write_reg(nor, cmd, &bank_sel, 1);
+	if (ret < 0) {
+		debug("SF: fail to write bank register\n");
+		return ret;
+	}
+
+	nor->bank_curr = bank_sel;
+
+	return write_disable(nor);
+}
+#endif
+
+static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	u32 addr, len, rem, offset, max_size;
+	bool addr_known = false;
+	int ret, err;
+
+	dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr,
+		(long long)instr->len);
+
+	div_u64_rem(instr->len, mtd->erasesize, &rem);
+	if (rem) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	addr = instr->addr;
+	len = instr->len;
+	max_size = instr->len;
+
+	instr->state = MTD_ERASING;
+	addr_known = true;
+
+	while (len) {
+		schedule();
+		if (!IS_ENABLED(CONFIG_XPL_BUILD) && ctrlc()) {
+			addr_known = false;
+			ret = -EINTR;
+			goto erase_err;
+		}
+		offset = addr;
+		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+			if (nor->flags & SNOR_F_HAS_PARALLEL)
+				offset /= 2;
+
+			if (nor->flags & SNOR_F_HAS_STACKED) {
+				if (offset >= (mtd->size / 2))
+					nor->spi->flags |= SPI_XFER_U_PAGE;
+				else
+					nor->spi->flags &= ~SPI_XFER_U_PAGE;
+			}
+		}
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+		ret = write_bar(nor, offset);
+		if (ret < 0)
+			goto erase_err;
+#endif
+		ret = write_enable(nor);
+		if (ret < 0)
+			goto erase_err;
+
+		if (len == mtd->size &&
+		    !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
+			ret = spi_nor_erase_chip(nor);
+		} else {
+			ret = spi_nor_erase_sector(nor, offset);
+		}
+		if (ret < 0)
+			goto erase_err;
+
+		addr += ret;
+		len -= ret;
+
+		if (max_size == mtd->size &&
+		    !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
+			ret = spi_nor_erase_chip_wait_till_ready(nor, mtd->size);
+		} else {
+			ret = spi_nor_wait_till_ready(nor);
+		}
+
+		if (ret)
+			goto erase_err;
+	}
+
+	addr_known = false;
+erase_err:
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+	err = clean_bar(nor);
+	if (!ret)
+		ret = err;
+#endif
+	err = write_disable(nor);
+	if (!ret)
+		ret = err;
+
+err:
+	if (ret) {
+		instr->fail_addr = addr_known ? addr : MTD_FAIL_ADDR_UNKNOWN;
+		instr->state = MTD_ERASE_FAILED;
+	} else {
+		instr->state = MTD_ERASE_DONE;
+	}
+
+	return ret;
+}
+
+static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t *retlen, u_char *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	loff_t offset = from;
+	u32 rem_bank_len = 0;
+	u32 stack_shift = 0;
+	size_t read_len;
+	u8 bank;
+	int ret;
+	bool is_ofst_odd = false;
+
+	dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
+
+	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (offset & 1)) {
+		/* We can hit this case when we use file system like ubifs */
+		from--;
+		len++;
+		is_ofst_odd = true;
+	}
+
+	while (len) {
+		read_len = len;
+		offset = from;
+
+		if (CONFIG_IS_ENABLED(SPI_FLASH_BAR)) {
+			bank = (u32)from / SZ_16M;
+			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+				if (nor->flags & SNOR_F_HAS_PARALLEL)
+					bank /= 2;
+			}
+			rem_bank_len = SZ_16M * (bank + 1);
+			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+				if (nor->flags & SNOR_F_HAS_PARALLEL)
+					rem_bank_len *= 2;
+			}
+			rem_bank_len -= from;
+		}
+
+		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+			if (nor->flags & SNOR_F_HAS_STACKED) {
+				stack_shift = 1;
+				if (offset >= (mtd->size / 2)) {
+					offset = offset - (mtd->size / 2);
+					nor->spi->flags |= SPI_XFER_U_PAGE;
+				} else {
+					nor->spi->flags &= ~SPI_XFER_U_PAGE;
+				}
+			}
+		}
+
+		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
+			if (nor->flags & SNOR_F_HAS_PARALLEL)
+				offset /= 2;
+		}
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+		ret = write_bar(nor, offset);
+		if (ret < 0)
+			return log_ret(ret);
+		if (len < rem_bank_len)
+			read_len = len;
+		else
+			read_len = rem_bank_len;
+#endif
+
+		if (read_len == 0)
+			return -EIO;
+
+		ret = nor->read(nor, offset, read_len, buf);
+		if (ret == 0) {
+			/* We shouldn't see 0-length reads */
+			ret = -EIO;
+			goto read_err;
+		}
+		if (ret < 0)
+			goto read_err;
+
+		if (is_ofst_odd == true) {
+			memmove(buf, (buf + 1), (len - 1));
+			*retlen += (ret - 1);
+			buf += ret - 1;
+			is_ofst_odd = false;
+		} else {
+			*retlen += ret;
+			buf += ret;
+		}
+		from += ret;
+		len -= ret;
+	}
+	ret = 0;
+
+read_err:
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+	ret = clean_bar(nor);
+#endif
+	return ret;
+}
+
+static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
+	size_t *retlen, const u_char *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	size_t page_offset, page_remain, i;
+	ssize_t ret;
+	u32 offset;
+
+#ifdef CONFIG_SPI_FLASH_SST
+	/* sst nor chips use AAI word program */
+	if (nor->info->flags & SST_WRITE)
+		return sst_write(mtd, to, len, retlen, buf);
+#endif
+
+	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
+
+	if (!len)
+		return 0;
+
+	/*
+	 * Cannot write to odd offset in parallel mode,
+	 * so write 2 bytes first
+	 */
+	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (to & 1)) {
+		u8 two[2] = {0xff, buf[0]};
+		size_t local_retlen;
+
+		ret = spi_nor_write(mtd, to & ~1, 2, &local_retlen, two);
+		if (ret < 0)
+			return ret;
+
+		*retlen += 1; /* We've written only one actual byte */
+		buf++;
+		len--;
+		to++;
+	}
+
+	for (i = 0; i < len; ) {
+		ssize_t written;
+		loff_t addr = to + i;
+		schedule();
+
+		/*
+		 * If page_size is a power of two, the offset can be quickly
+		 * calculated with an AND operation. On the other cases we
+		 * need to do a modulus operation (more expensive).
+		 */
+		if (is_power_of_2(nor->page_size)) {
+			page_offset = addr & (nor->page_size - 1);
+		} else {
+			u64 aux = addr;
+
+			page_offset = do_div(aux, nor->page_size);
+		}
+		offset = to + i;
+		if (nor->flags & SNOR_F_HAS_PARALLEL)
+			offset /= 2;
+
+		if (nor->flags & SNOR_F_HAS_STACKED) {
+			if (offset >= (mtd->size / 2)) {
+				offset = offset - (mtd->size / 2);
+				nor->spi->flags |= SPI_XFER_U_PAGE;
+			} else {
+				nor->spi->flags &= ~SPI_XFER_U_PAGE;
+			}
+		}
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+		ret = write_bar(nor, offset);
+		if (ret < 0)
+			return ret;
+#endif
+
+		/* the size of data remaining on the first page */
+		page_remain = min_t(size_t,
+				    nor->page_size - page_offset, len - i);
+
+		write_enable(nor);
+		/*
+		 * On DTR capable flashes like Micron Xcella the writes cannot
+		 * start or end at an odd address in DTR mode. So we need to
+		 * append or prepend extra 0xff bytes to make sure the start
+		 * address and end address are even.
+		 */
+		if (spi_nor_protocol_is_dtr(nor->write_proto) &&
+		    ((offset | page_remain) & 1)) {
+			u_char *tmp;
+			size_t extra_bytes = 0;
+
+			tmp = kmalloc(nor->page_size, 0);
+			if (!tmp) {
+				ret = -ENOMEM;
+				goto write_err;
+			}
+
+			/* Prepend a 0xff byte if the start address is odd. */
+			if (offset & 1) {
+				tmp[0] = 0xff;
+				memcpy(tmp + 1, buf + i, page_remain);
+				offset--;
+				page_remain++;
+				extra_bytes++;
+			} else {
+				memcpy(tmp, buf + i, page_remain);
+			}
+
+			/* Append a 0xff byte if the end address is odd. */
+			if ((offset + page_remain) & 1) {
+				tmp[page_remain + extra_bytes] = 0xff;
+				extra_bytes++;
+				page_remain++;
+			}
+
+			ret = nor->write(nor, offset, page_remain, tmp);
+
+			kfree(tmp);
+
+			if (ret < 0)
+				goto write_err;
+
+			/*
+			 * We write extra bytes but they are not part of the
+			 * original write.
+			 */
+			written = ret - extra_bytes;
+		} else {
+			ret = nor->write(nor, offset, page_remain, buf + i);
+			if (ret < 0)
+				goto write_err;
+			written = ret;
+		}
+
+		ret = spi_nor_wait_till_ready(nor);
+		if (ret)
+			goto write_err;
+
+		*retlen += written;
+		i += written;
+	}
+
+write_err:
+#if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
+	ret = clean_bar(nor);
+#endif
+	return ret;
+}
+
+int spi_nor_stacked_post_init_fixups(struct spi_nor *nor)
+{
+	struct mtd_info *mtd = &nor->mtd;
+	int ret;
+
+#if CONFIG_IS_ENABLED(DM_SPI)
+	u64 flash_size[SNOR_FLASH_CNT_MAX] = { 0 };
+	struct udevice *dev = nor->spi->dev;
+	u32 idx = 0, i = 0;
+	int rc;
+
+	while (i < SNOR_FLASH_CNT_MAX) {
+		rc = ofnode_read_u64_index(dev_ofnode(dev), "stacked-memories",
+					   idx, &flash_size[i]);
+		if (rc == -EINVAL) {
+			break;
+		} else if (rc == -EOVERFLOW) {
+			idx++;
+		} else {
+			idx++;
+			i++;
+			if (!(nor->flags & SNOR_F_HAS_STACKED))
+				nor->flags |= SNOR_F_HAS_STACKED;
+			if (!(nor->spi->flags & SPI_XFER_STACKED))
+				nor->spi->flags |= SPI_XFER_STACKED;
+		}
+	}
+
+	if (nor->flags & (SNOR_F_HAS_STACKED | SNOR_F_HAS_PARALLEL)) {
+		mtd->size = 0;
+		for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++)
+			mtd->size += flash_size[idx];
+	}
+#endif
+
+	if (nor->flags & SNOR_F_HAS_STACKED) {
+		nor->spi->flags |= SPI_XFER_U_PAGE;
+		ret = spi_nor_init(nor);
+		if (ret)
+			return ret;
+		nor->spi->flags &= ~SPI_XFER_U_PAGE;
+	}
+
+	if (nor->flags & SNOR_F_HAS_STACKED) {
+		mtd->_erase = spi_nor_erase;
+		mtd->_read = spi_nor_read;
+		mtd->_write = spi_nor_write;
+	}
+
+	return 0;
+}

-- 
2.34.1



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

* [PATCH 08/11] mtd: spi-nor: stacked: Cleanup stacked/parallel flags
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
                   ` (6 preceding siblings ...)
  2025-11-19  5:13 ` [PATCH 07/11] mtd: spi-nor: Migrate stacked/parallel part to new modules Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 09/11] mtd: spi-nor: parallel: " Takahiro Kuwano via B4 Relay
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

Remove check of CONFIG_SPI_STACKED_PARALLEL, SNOR_F_HAS_PARALLEL, and
SNOR_F_HAS_STACKED as stacked module is only available when the config
is enabled and dedicated for stacked mode.

Keep SPI_XFER_U_PAGE as it tells controllers whether upper or lower chip
to be accessed. Also keep nor->upage_prev as it tracks previous chip
that write_bar is issued.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/mtd/spi/stacked.c | 124 +++++++++++-----------------------------------
 1 file changed, 30 insertions(+), 94 deletions(-)

diff --git a/drivers/mtd/spi/stacked.c b/drivers/mtd/spi/stacked.c
index e005aea1053..49f664bc313 100644
--- a/drivers/mtd/spi/stacked.c
+++ b/drivers/mtd/spi/stacked.c
@@ -25,11 +25,7 @@ static int write_bar(struct spi_nor *nor, u32 offset)
 	if (spi_nor_wait_till_ready(nor))
 		return 1;
 
-	if (nor->flags & (SNOR_F_HAS_PARALLEL | SNOR_F_HAS_STACKED) &&
-	    mtd->size <= SZ_32M)
-		return 0;
-
-	if (mtd->size <= SZ_16M)
+	if (mtd->size <= SZ_32M)
 		return 0;
 
 	offset = offset % (u32)mtd->size;
@@ -37,9 +33,7 @@ static int write_bar(struct spi_nor *nor, u32 offset)
 
 	upage_curr = nor->spi->flags & SPI_XFER_U_PAGE;
 
-	if (!(nor->flags & SNOR_F_HAS_STACKED) && bank_sel == nor->bank_curr)
-		return 0;
-	else if (upage_curr == nor->upage_prev && bank_sel == nor->bank_curr)
+	if (upage_curr == nor->upage_prev && bank_sel == nor->bank_curr)
 		return 0;
 
 	nor->upage_prev = upage_curr;
@@ -89,17 +83,10 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 			goto erase_err;
 		}
 		offset = addr;
-		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-			if (nor->flags & SNOR_F_HAS_PARALLEL)
-				offset /= 2;
-
-			if (nor->flags & SNOR_F_HAS_STACKED) {
-				if (offset >= (mtd->size / 2))
-					nor->spi->flags |= SPI_XFER_U_PAGE;
-				else
-					nor->spi->flags &= ~SPI_XFER_U_PAGE;
-			}
-		}
+		if (offset >= (mtd->size / 2))
+			nor->spi->flags |= SPI_XFER_U_PAGE;
+		else
+			nor->spi->flags &= ~SPI_XFER_U_PAGE;
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
 		ret = write_bar(nor, offset);
 		if (ret < 0)
@@ -168,46 +155,22 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 
 	dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
 
-	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (offset & 1)) {
-		/* We can hit this case when we use file system like ubifs */
-		from--;
-		len++;
-		is_ofst_odd = true;
-	}
-
 	while (len) {
 		read_len = len;
 		offset = from;
 
 		if (CONFIG_IS_ENABLED(SPI_FLASH_BAR)) {
 			bank = (u32)from / SZ_16M;
-			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-				if (nor->flags & SNOR_F_HAS_PARALLEL)
-					bank /= 2;
-			}
 			rem_bank_len = SZ_16M * (bank + 1);
-			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-				if (nor->flags & SNOR_F_HAS_PARALLEL)
-					rem_bank_len *= 2;
-			}
 			rem_bank_len -= from;
 		}
 
-		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-			if (nor->flags & SNOR_F_HAS_STACKED) {
-				stack_shift = 1;
-				if (offset >= (mtd->size / 2)) {
-					offset = offset - (mtd->size / 2);
-					nor->spi->flags |= SPI_XFER_U_PAGE;
-				} else {
-					nor->spi->flags &= ~SPI_XFER_U_PAGE;
-				}
-			}
-		}
-
-		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-			if (nor->flags & SNOR_F_HAS_PARALLEL)
-				offset /= 2;
+		stack_shift = 1;
+		if (offset >= (mtd->size / 2)) {
+			offset = offset - (mtd->size / 2);
+			nor->spi->flags |= SPI_XFER_U_PAGE;
+		} else {
+			nor->spi->flags &= ~SPI_XFER_U_PAGE;
 		}
 
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
@@ -272,24 +235,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 	if (!len)
 		return 0;
 
-	/*
-	 * Cannot write to odd offset in parallel mode,
-	 * so write 2 bytes first
-	 */
-	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (to & 1)) {
-		u8 two[2] = {0xff, buf[0]};
-		size_t local_retlen;
-
-		ret = spi_nor_write(mtd, to & ~1, 2, &local_retlen, two);
-		if (ret < 0)
-			return ret;
-
-		*retlen += 1; /* We've written only one actual byte */
-		buf++;
-		len--;
-		to++;
-	}
-
 	for (i = 0; i < len; ) {
 		ssize_t written;
 		loff_t addr = to + i;
@@ -308,16 +253,11 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 			page_offset = do_div(aux, nor->page_size);
 		}
 		offset = to + i;
-		if (nor->flags & SNOR_F_HAS_PARALLEL)
-			offset /= 2;
-
-		if (nor->flags & SNOR_F_HAS_STACKED) {
-			if (offset >= (mtd->size / 2)) {
-				offset = offset - (mtd->size / 2);
-				nor->spi->flags |= SPI_XFER_U_PAGE;
-			} else {
-				nor->spi->flags &= ~SPI_XFER_U_PAGE;
-			}
+		if (offset >= (mtd->size / 2)) {
+			offset = offset - (mtd->size / 2);
+			nor->spi->flags |= SPI_XFER_U_PAGE;
+		} else {
+			nor->spi->flags &= ~SPI_XFER_U_PAGE;
 		}
 
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
@@ -408,6 +348,7 @@ int spi_nor_stacked_post_init_fixups(struct spi_nor *nor)
 #if CONFIG_IS_ENABLED(DM_SPI)
 	u64 flash_size[SNOR_FLASH_CNT_MAX] = { 0 };
 	struct udevice *dev = nor->spi->dev;
+	bool is_stacked = false;
 	u32 idx = 0, i = 0;
 	int rc;
 
@@ -421,33 +362,28 @@ int spi_nor_stacked_post_init_fixups(struct spi_nor *nor)
 		} else {
 			idx++;
 			i++;
-			if (!(nor->flags & SNOR_F_HAS_STACKED))
-				nor->flags |= SNOR_F_HAS_STACKED;
-			if (!(nor->spi->flags & SPI_XFER_STACKED))
-				nor->spi->flags |= SPI_XFER_STACKED;
+			is_stacked = true;
 		}
 	}
 
-	if (nor->flags & (SNOR_F_HAS_STACKED | SNOR_F_HAS_PARALLEL)) {
+	if (is_stacked) {
 		mtd->size = 0;
 		for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++)
 			mtd->size += flash_size[idx];
 	}
 #endif
+	if (!is_stacked)
+		return 0;
 
-	if (nor->flags & SNOR_F_HAS_STACKED) {
-		nor->spi->flags |= SPI_XFER_U_PAGE;
-		ret = spi_nor_init(nor);
-		if (ret)
-			return ret;
-		nor->spi->flags &= ~SPI_XFER_U_PAGE;
-	}
+	nor->spi->flags |= SPI_XFER_U_PAGE;
+	ret = spi_nor_init(nor);
+	if (ret)
+		return ret;
+	nor->spi->flags &= ~SPI_XFER_U_PAGE;
 
-	if (nor->flags & SNOR_F_HAS_STACKED) {
-		mtd->_erase = spi_nor_erase;
-		mtd->_read = spi_nor_read;
-		mtd->_write = spi_nor_write;
-	}
+	mtd->_erase = spi_nor_erase;
+	mtd->_read = spi_nor_read;
+	mtd->_write = spi_nor_write;
 
 	return 0;
 }

-- 
2.34.1



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

* [PATCH 09/11] mtd: spi-nor: parallel: Cleanup stacked/parallel flags
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
                   ` (7 preceding siblings ...)
  2025-11-19  5:13 ` [PATCH 08/11] mtd: spi-nor: stacked: Cleanup stacked/parallel flags Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 10/11] mtd: spi-nor: Revert stacked/parallel related commits Takahiro Kuwano via B4 Relay
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

Remove check of CONFIG_SPI_STACKED_PARALLEL, SNOR_F_HAS_PARALLEL, and
SNOR_F_HAS_STACKED as paralle module is only available when the config
is enabled and dedicated for parallel mode.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/mtd/spi/parallel.c | 106 ++++++++++-----------------------------------
 1 file changed, 24 insertions(+), 82 deletions(-)

diff --git a/drivers/mtd/spi/parallel.c b/drivers/mtd/spi/parallel.c
index d884eaefcd0..decd2821337 100644
--- a/drivers/mtd/spi/parallel.c
+++ b/drivers/mtd/spi/parallel.c
@@ -17,7 +17,7 @@
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
 static int write_bar(struct spi_nor *nor, u32 offset)
 {
-	u8 cmd, bank_sel, upage_curr;
+	u8 cmd, bank_sel;
 	int ret;
 	struct mtd_info *mtd = &nor->mtd;
 
@@ -25,24 +25,14 @@ static int write_bar(struct spi_nor *nor, u32 offset)
 	if (spi_nor_wait_till_ready(nor))
 		return 1;
 
-	if (nor->flags & (SNOR_F_HAS_PARALLEL | SNOR_F_HAS_STACKED) &&
-	    mtd->size <= SZ_32M)
-		return 0;
-
-	if (mtd->size <= SZ_16M)
+	if (mtd->size <= SZ_32M)
 		return 0;
 
 	offset = offset % (u32)mtd->size;
 	bank_sel = offset >> 24;
 
-	upage_curr = nor->spi->flags & SPI_XFER_U_PAGE;
-
-	if (!(nor->flags & SNOR_F_HAS_STACKED) && bank_sel == nor->bank_curr)
+	if (bank_sel == nor->bank_curr)
 		return 0;
-	else if (upage_curr == nor->upage_prev && bank_sel == nor->bank_curr)
-		return 0;
-
-	nor->upage_prev = upage_curr;
 
 	cmd = nor->bank_write_cmd;
 	write_enable(nor);
@@ -88,18 +78,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 			ret = -EINTR;
 			goto erase_err;
 		}
-		offset = addr;
-		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-			if (nor->flags & SNOR_F_HAS_PARALLEL)
-				offset /= 2;
-
-			if (nor->flags & SNOR_F_HAS_STACKED) {
-				if (offset >= (mtd->size / 2))
-					nor->spi->flags |= SPI_XFER_U_PAGE;
-				else
-					nor->spi->flags &= ~SPI_XFER_U_PAGE;
-			}
-		}
+		offset = addr / 2;
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
 		ret = write_bar(nor, offset);
 		if (ret < 0)
@@ -160,7 +139,6 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 	loff_t offset = from;
 	u32 rem_bank_len = 0;
-	u32 stack_shift = 0;
 	size_t read_len;
 	u8 bank;
 	int ret;
@@ -168,7 +146,7 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 
 	dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
 
-	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (offset & 1)) {
+	if (offset & 1) {
 		/* We can hit this case when we use file system like ubifs */
 		from--;
 		len++;
@@ -180,35 +158,12 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 		offset = from;
 
 		if (CONFIG_IS_ENABLED(SPI_FLASH_BAR)) {
-			bank = (u32)from / SZ_16M;
-			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-				if (nor->flags & SNOR_F_HAS_PARALLEL)
-					bank /= 2;
-			}
-			rem_bank_len = SZ_16M * (bank + 1);
-			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-				if (nor->flags & SNOR_F_HAS_PARALLEL)
-					rem_bank_len *= 2;
-			}
+			bank = (u32)from / SZ_16M / 2;
+			rem_bank_len = SZ_16M * (bank + 1) * 2;
 			rem_bank_len -= from;
 		}
 
-		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-			if (nor->flags & SNOR_F_HAS_STACKED) {
-				stack_shift = 1;
-				if (offset >= (mtd->size / 2)) {
-					offset = offset - (mtd->size / 2);
-					nor->spi->flags |= SPI_XFER_U_PAGE;
-				} else {
-					nor->spi->flags &= ~SPI_XFER_U_PAGE;
-				}
-			}
-		}
-
-		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-			if (nor->flags & SNOR_F_HAS_PARALLEL)
-				offset /= 2;
-		}
+		offset /= 2;
 
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
 		ret = write_bar(nor, offset);
@@ -276,7 +231,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 	 * Cannot write to odd offset in parallel mode,
 	 * so write 2 bytes first
 	 */
-	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (to & 1)) {
+	if (to & 1) {
 		u8 two[2] = {0xff, buf[0]};
 		size_t local_retlen;
 
@@ -307,18 +262,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 
 			page_offset = do_div(aux, nor->page_size);
 		}
-		offset = to + i;
-		if (nor->flags & SNOR_F_HAS_PARALLEL)
-			offset /= 2;
-
-		if (nor->flags & SNOR_F_HAS_STACKED) {
-			if (offset >= (mtd->size / 2)) {
-				offset = offset - (mtd->size / 2);
-				nor->spi->flags |= SPI_XFER_U_PAGE;
-			} else {
-				nor->spi->flags &= ~SPI_XFER_U_PAGE;
-			}
-		}
+		offset = (to + i) / 2;
 
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
 		ret = write_bar(nor, offset);
@@ -407,6 +351,7 @@ int spi_nor_parallel_post_init_fixups(struct spi_nor *nor)
 #if CONFIG_IS_ENABLED(DM_SPI)
 	u64 flash_size[SNOR_FLASH_CNT_MAX] = { 0 };
 	struct udevice *dev = nor->spi->dev;
+	bool is_parallel = false;
 	u32 idx = 0, i = 0;
 	int rc;
 
@@ -420,32 +365,31 @@ int spi_nor_parallel_post_init_fixups(struct spi_nor *nor)
 		} else {
 			idx++;
 			i++;
-			if (!(nor->flags & SNOR_F_HAS_PARALLEL))
-				nor->flags |= SNOR_F_HAS_PARALLEL;
+			is_parallel = true;
 		}
 	}
 
-	if (nor->flags & (SNOR_F_HAS_STACKED | SNOR_F_HAS_PARALLEL)) {
+	if (is_parallel) {
 		mtd->size = 0;
 		for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++)
 			mtd->size += flash_size[idx];
-	}
 
-	/*
-	 * In parallel-memories the erase operation is
-	 * performed on both the flashes simultaneously
-	 * so, double the erasesize.
-	 */
-	if (nor->flags & SNOR_F_HAS_PARALLEL) {
+		/*
+		 * In parallel-memories the erase operation is
+		 * performed on both the flashes simultaneously
+		 * so, double the erasesize.
+		 */
 		nor->mtd.erasesize <<= 1;
 		nor->page_size <<= 1;
 		nor->mtd.writebufsize <<= 1;
 	}
 #endif
+	if (!is_parallel)
+		return 0;
 
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
 	/* Make sure both chips use the same BAR */
-	if (nor->flags & SNOR_F_HAS_PARALLEL) {
+	{
 		int ret;
 
 		write_enable(nor);
@@ -460,11 +404,9 @@ int spi_nor_parallel_post_init_fixups(struct spi_nor *nor)
 	}
 #endif
 
-	if (nor->flags & SNOR_F_HAS_PARALLEL) {
-		mtd->_erase = spi_nor_erase;
-		mtd->_read = spi_nor_read;
-		mtd->_write = spi_nor_write;
-	}
+	mtd->_erase = spi_nor_erase;
+	mtd->_read = spi_nor_read;
+	mtd->_write = spi_nor_write;
 
 	return 0;
 }

-- 
2.34.1



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

* [PATCH 10/11] mtd: spi-nor: Revert stacked/parallel related commits
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
                   ` (8 preceding siblings ...)
  2025-11-19  5:13 ` [PATCH 09/11] mtd: spi-nor: parallel: " Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-11-19  5:13 ` [PATCH 11/11] mtd: spi-nor: Call stacked/parallel post init fixups Takahiro Kuwano via B4 Relay
  2025-12-16 13:45 ` [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Begari, Padmarao
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

Revert the following commits to remove stacked/parallel mode support
from core. Exceptions are SPI_XFER_U_PAGE and nor->upage_prev that still
needed for stacked mode support.

f59cb6a6970 ("mtd: spi-nor: Remove recently added SST special case")
9bb02f7f453 ("mtd: spi-nor: Fix the spi_nor_read() when config SPI_STACKED_PARALLEL is enabled")
e61ea9f2e5d ("mtd: spi-nor: Guard SPI_STACKED_PARALLEL with DM_SPI check")
43423cdc5dc ("mtd: spi-nor: Always build SPI_STACKED_PARALLEL code")
003157bd1c2 ("mtd: spi-nor: Rewrite rem_bank_len calculation")
a21cfc4e7c5 ("mtd: spi-nor: Fix multiple coding style issues")
34cd4a72fb2 ("mtd: spi-nor: Remove recently added SST special case")
787692c8d75 ("mtd: spi-nor: Remove recently added write_disable() call")
8ef342f7cbb ("mtd: spi-nor: Remove recently added set_4byte() call")
b8807c8c406 ("mtd: spi-nor: Remove recently added spi_nor_wait_till_ready() call")
19e189b1de0 ("mtd: spi-nor: Remove recently added nor->addr_width == 3 test")
c480ec2c45b ("mtd: spi-nor: Add parallel and stacked memories support in read_bar and write_bar")
92e0ae42b47 ("mtd: spi-nor: Add parallel memories support for read_sr and read_fsr")
5d40b3d384d ("mtd: spi-nor: Add parallel and stacked memories support")

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/mtd/spi/spi-nor-core.c | 392 ++++++-----------------------------------
 include/linux/mtd/spi-nor.h    |  10 --
 include/spi.h                  |   2 -
 3 files changed, 53 insertions(+), 351 deletions(-)

diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 9695a706d0b..acfbc0bb702 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -466,9 +466,8 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
 }
 
 /*
- * Return the status register value. If the chip is parallel, then the
- * read will be striped, so we should read 2 bytes to get the sr
- * register value from both of the parallel chips.
+ * Read the status register, returning its value in the location
+ * Return the status register value.
  * Returns negative if error occurred.
  */
 static int read_sr(struct spi_nor *nor)
@@ -500,29 +499,18 @@ static int read_sr(struct spi_nor *nor)
 	if (spi_nor_protocol_is_dtr(nor->reg_proto))
 		op.data.nbytes = 2;
 
-	if (nor->flags & SNOR_F_HAS_PARALLEL) {
-		op.data.nbytes = 2;
-		ret = spi_nor_read_write_reg(nor, &op, &val[0]);
-		if (ret < 0) {
-			pr_debug("error %d reading SR\n", (int)ret);
-			return ret;
-		}
-		val[0] |= val[1];
-	} else {
-		ret = spi_nor_read_write_reg(nor, &op, &val[0]);
-		if (ret < 0) {
-			pr_debug("error %d reading SR\n", (int)ret);
-			return ret;
-		}
+	ret = spi_nor_read_write_reg(nor, &op, val);
+	if (ret < 0) {
+		pr_debug("error %d reading SR\n", (int)ret);
+		return ret;
 	}
 
-	return val[0];
+	return *val;
 }
 
 /*
- * Return the flag status register value. If the chip is parallel, then
- * the read will be striped, so we should read 2 bytes to get the fsr
- * register value from both of the parallel chips.
+ * Read the flag status register, returning its value in the location
+ * Return the status register value.
  * Returns negative if error occurred.
  */
 static int read_fsr(struct spi_nor *nor)
@@ -554,23 +542,13 @@ static int read_fsr(struct spi_nor *nor)
 	if (spi_nor_protocol_is_dtr(nor->reg_proto))
 		op.data.nbytes = 2;
 
-	if (nor->flags & SNOR_F_HAS_PARALLEL) {
-		op.data.nbytes = 2;
-		ret = spi_nor_read_write_reg(nor, &op, &val[0]);
-		if (ret < 0) {
-			pr_debug("error %d reading SR\n", (int)ret);
-			return ret;
-		}
-		val[0] &= val[1];
-	} else {
-		ret = spi_nor_read_write_reg(nor, &op, &val[0]);
-		if (ret < 0) {
-			pr_debug("error %d reading FSR\n", ret);
-			return ret;
-		}
+	ret = spi_nor_read_write_reg(nor, &op, val);
+	if (ret < 0) {
+		pr_debug("error %d reading FSR\n", ret);
+		return ret;
 	}
 
-	return val[0];
+	return *val;
 }
 
 /*
@@ -718,17 +696,12 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
 static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
 				      const struct flash_info *info)
 {
-	bool shift = 0;
-
-	if (nor->flags & SNOR_F_HAS_PARALLEL)
-		shift = 1;
-
 	/* Do some manufacturer fixups first */
 	switch (JEDEC_MFR(info)) {
 	case SNOR_MFR_SPANSION:
 		/* No small sector erase for 4-byte command set */
 		nor->erase_opcode = SPINOR_OP_SE;
-		nor->mtd.erasesize = info->sector_size << shift;
+		nor->mtd.erasesize = info->sector_size;
 		break;
 
 	default:
@@ -961,32 +934,12 @@ int clean_bar(struct spi_nor *nor)
 
 static int write_bar(struct spi_nor *nor, u32 offset)
 {
-	u8 cmd, bank_sel, upage_curr;
+	u8 cmd, bank_sel;
 	int ret;
-	struct mtd_info *mtd = &nor->mtd;
-
-	/* Wait until previous write command is finished */
-	if (spi_nor_wait_till_ready(nor))
-		return 1;
-
-	if (nor->flags & (SNOR_F_HAS_PARALLEL | SNOR_F_HAS_STACKED) &&
-	    mtd->size <= SZ_32M)
-		return 0;
 
-	if (mtd->size <= SZ_16M)
-		return 0;
-
-	offset = offset % (u32)mtd->size;
-	bank_sel = offset >> 24;
-
-	upage_curr = nor->spi->flags & SPI_XFER_U_PAGE;
-
-	if (!(nor->flags & SNOR_F_HAS_STACKED) && bank_sel == nor->bank_curr)
-		return 0;
-	else if (upage_curr == nor->upage_prev && bank_sel == nor->bank_curr)
-		return 0;
-
-	nor->upage_prev = upage_curr;
+	bank_sel = offset / SZ_16M;
+	if (bank_sel == nor->bank_curr)
+		goto bar_end;
 
 	cmd = nor->bank_write_cmd;
 	write_enable(nor);
@@ -996,19 +949,15 @@ static int write_bar(struct spi_nor *nor, u32 offset)
 		return ret;
 	}
 
+bar_end:
 	nor->bank_curr = bank_sel;
-
-	return write_disable(nor);
+	return nor->bank_curr;
 }
 
 static int read_bar(struct spi_nor *nor, const struct flash_info *info)
 {
 	u8 curr_bank = 0;
 	int ret;
-	struct mtd_info *mtd = &nor->mtd;
-
-	if (mtd->size <= SZ_16M)
-		return 0;
 
 	switch (JEDEC_MFR(info)) {
 	case SNOR_MFR_SPANSION:
@@ -1020,30 +969,15 @@ static int read_bar(struct spi_nor *nor, const struct flash_info *info)
 		nor->bank_write_cmd = SPINOR_OP_WREAR;
 	}
 
-	if (nor->flags & SNOR_F_HAS_PARALLEL)
-		nor->spi->flags |= SPI_XFER_LOWER;
-
 	ret = nor->read_reg(nor, nor->bank_read_cmd,
-			    &curr_bank, 1);
+				    &curr_bank, 1);
 	if (ret) {
 		debug("SF: fail to read bank addr register\n");
 		return ret;
 	}
 	nor->bank_curr = curr_bank;
 
-	// Make sure both chips use the same BAR
-	if (nor->flags & SNOR_F_HAS_PARALLEL) {
-		write_enable(nor);
-		ret = nor->write_reg(nor, nor->bank_write_cmd, &curr_bank, 1);
-		if (ret)
-			return ret;
-
-		ret = write_disable(nor);
-		if (ret)
-			return ret;
-	}
-
-	return ret;
+	return 0;
 }
 #endif
 
@@ -1107,8 +1041,8 @@ int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
 static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
-	u32 addr, len, rem, offset, max_size;
 	bool addr_known = false;
+	u32 addr, len, rem, max_size;
 	int ret, err;
 
 	dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr,
@@ -1134,20 +1068,8 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 			ret = -EINTR;
 			goto erase_err;
 		}
-		offset = addr;
-		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-			if (nor->flags & SNOR_F_HAS_PARALLEL)
-				offset /= 2;
-
-			if (nor->flags & SNOR_F_HAS_STACKED) {
-				if (offset >= (mtd->size / 2))
-					nor->spi->flags |= SPI_XFER_U_PAGE;
-				else
-					nor->spi->flags &= ~SPI_XFER_U_PAGE;
-			}
-		}
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
-		ret = write_bar(nor, offset);
+		ret = write_bar(nor, addr);
 		if (ret < 0)
 			goto erase_err;
 #endif
@@ -1159,7 +1081,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 		    !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
 			ret = spi_nor_erase_chip(nor);
 		} else {
-			ret = spi_nor_erase_sector(nor, offset);
+			ret = spi_nor_erase_sector(nor, addr);
 		}
 		if (ret < 0)
 			goto erase_err;
@@ -1561,9 +1483,6 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
 	u8			id[SPI_NOR_MAX_ID_LEN];
 	const struct flash_info	*info;
 
-	if (nor->flags & SNOR_F_HAS_PARALLEL)
-		nor->spi->flags |= SPI_XFER_LOWER;
-
 	tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
 	if (tmp < 0) {
 		dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp);
@@ -1587,72 +1506,29 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 			size_t *retlen, u_char *buf)
 {
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
-	loff_t offset = from;
-	u32 rem_bank_len = 0;
-	u32 stack_shift = 0;
-	size_t read_len;
-	u8 bank;
 	int ret;
-	bool is_ofst_odd = false;
 
 	dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
 
-	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (offset & 1)) {
-		/* We can hit this case when we use file system like ubifs */
-		from--;
-		len++;
-		is_ofst_odd = true;
-	}
-
 	while (len) {
-		read_len = len;
-		offset = from;
-
-		if (CONFIG_IS_ENABLED(SPI_FLASH_BAR)) {
-			bank = (u32)from / SZ_16M;
-			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-				if (nor->flags & SNOR_F_HAS_PARALLEL)
-					bank /= 2;
-			}
-			rem_bank_len = SZ_16M * (bank + 1);
-			if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-				if (nor->flags & SNOR_F_HAS_PARALLEL)
-					rem_bank_len *= 2;
-			}
-			rem_bank_len -= from;
-		}
-
-		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-			if (nor->flags & SNOR_F_HAS_STACKED) {
-				stack_shift = 1;
-				if (offset >= (mtd->size / 2)) {
-					offset = offset - (mtd->size / 2);
-					nor->spi->flags |= SPI_XFER_U_PAGE;
-				} else {
-					nor->spi->flags &= ~SPI_XFER_U_PAGE;
-				}
-			}
-		}
-
-		if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-			if (nor->flags & SNOR_F_HAS_PARALLEL)
-				offset /= 2;
-		}
+		loff_t addr = from;
+		size_t read_len = len;
 
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
-		ret = write_bar(nor, offset);
+		u32 remain_len;
+
+		ret = write_bar(nor, addr);
 		if (ret < 0)
 			return log_ret(ret);
-		if (len < rem_bank_len)
+		remain_len = (SZ_16M * (nor->bank_curr + 1)) - addr;
+
+		if (len < remain_len)
 			read_len = len;
 		else
-			read_len = rem_bank_len;
+			read_len = remain_len;
 #endif
 
-		if (read_len == 0)
-			return -EIO;
-
-		ret = nor->read(nor, offset, read_len, buf);
+		ret = nor->read(nor, addr, read_len, buf);
 		if (ret == 0) {
 			/* We shouldn't see 0-length reads */
 			ret = -EIO;
@@ -1661,15 +1537,8 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 		if (ret < 0)
 			goto read_err;
 
-		if (is_ofst_odd == true) {
-			memmove(buf, (buf + 1), (len - 1));
-			*retlen += (ret - 1);
-			buf += ret - 1;
-			is_ofst_odd = false;
-		} else {
-			*retlen += ret;
-			buf += ret;
-		}
+		*retlen += ret;
+		buf += ret;
 		from += ret;
 		len -= ret;
 	}
@@ -1969,7 +1838,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 	size_t page_offset, page_remain, i;
 	ssize_t ret;
-	u32 offset;
 
 #ifdef CONFIG_SPI_FLASH_SST
 	/* sst nor chips use AAI word program */
@@ -1979,27 +1847,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 
 	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
 
-	if (!len)
-		return 0;
-
-	/*
-	 * Cannot write to odd offset in parallel mode,
-	 * so write 2 bytes first
-	 */
-	if ((nor->flags & SNOR_F_HAS_PARALLEL) && (to & 1)) {
-		u8 two[2] = {0xff, buf[0]};
-		size_t local_retlen;
-
-		ret = spi_nor_write(mtd, to & ~1, 2, &local_retlen, two);
-		if (ret < 0)
-			return ret;
-
-		*retlen += 1; /* We've written only one actual byte */
-		buf++;
-		len--;
-		to++;
-	}
-
 	for (i = 0; i < len; ) {
 		ssize_t written;
 		loff_t addr = to + i;
@@ -2017,30 +1864,18 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 
 			page_offset = do_div(aux, nor->page_size);
 		}
-		offset = to + i;
-		if (nor->flags & SNOR_F_HAS_PARALLEL)
-			offset /= 2;
-
-		if (nor->flags & SNOR_F_HAS_STACKED) {
-			if (offset >= (mtd->size / 2)) {
-				offset = offset - (mtd->size / 2);
-				nor->spi->flags |= SPI_XFER_U_PAGE;
-			} else {
-				nor->spi->flags &= ~SPI_XFER_U_PAGE;
-			}
-		}
+		/* the size of data remaining on the first page */
+		page_remain = min_t(size_t,
+				    nor->page_size - page_offset, len - i);
 
 #if CONFIG_IS_ENABLED(SPI_FLASH_BAR)
-		ret = write_bar(nor, offset);
+		ret = write_bar(nor, addr);
 		if (ret < 0)
 			return ret;
 #endif
 
-		/* the size of data remaining on the first page */
-		page_remain = min_t(size_t,
-				    nor->page_size - page_offset, len - i);
-
 		write_enable(nor);
+
 		/*
 		 * On DTR capable flashes like Micron Xcella the writes cannot
 		 * start or end at an odd address in DTR mode. So we need to
@@ -2048,7 +1883,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 		 * address and end address are even.
 		 */
 		if (spi_nor_protocol_is_dtr(nor->write_proto) &&
-		    ((offset | page_remain) & 1)) {
+		    ((addr | page_remain) & 1)) {
 			u_char *tmp;
 			size_t extra_bytes = 0;
 
@@ -2059,10 +1894,10 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 			}
 
 			/* Prepend a 0xff byte if the start address is odd. */
-			if (offset & 1) {
+			if (addr & 1) {
 				tmp[0] = 0xff;
 				memcpy(tmp + 1, buf + i, page_remain);
-				offset--;
+				addr--;
 				page_remain++;
 				extra_bytes++;
 			} else {
@@ -2070,13 +1905,13 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 			}
 
 			/* Append a 0xff byte if the end address is odd. */
-			if ((offset + page_remain) & 1) {
+			if ((addr + page_remain) & 1) {
 				tmp[page_remain + extra_bytes] = 0xff;
 				extra_bytes++;
 				page_remain++;
 			}
 
-			ret = nor->write(nor, offset, page_remain, tmp);
+			ret = nor->write(nor, addr, page_remain, tmp);
 
 			kfree(tmp);
 
@@ -2089,7 +1924,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 			 */
 			written = ret - extra_bytes;
 		} else {
-			ret = nor->write(nor, offset, page_remain, buf + i);
+			ret = nor->write(nor, addr, page_remain, buf + i);
 			if (ret < 0)
 				goto write_err;
 			written = ret;
@@ -2098,7 +1933,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 		ret = spi_nor_wait_till_ready(nor);
 		if (ret)
 			goto write_err;
-
 		*retlen += written;
 		i += written;
 	}
@@ -2376,10 +2210,6 @@ static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr,
 	nor->read_dummy = 8;
 
 	while (len) {
-		/* Both chips are identical, so should be the SFDP data */
-		if (nor->flags & SNOR_F_HAS_PARALLEL)
-			nor->spi->flags |= SPI_XFER_LOWER;
-
 		ret = nor->read(nor, addr, len, (u8 *)buf);
 		if (!ret || ret > len) {
 			ret = -EIO;
@@ -3193,70 +3023,6 @@ static int spi_nor_init_params(struct spi_nor *nor,
 		spi_nor_post_sfdp_fixups(nor, params);
 	}
 
-#if CONFIG_IS_ENABLED(DM_SPI)
-	if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) {
-		u64 flash_size[SNOR_FLASH_CNT_MAX] = { 0 };
-		struct udevice *dev = nor->spi->dev;
-		u32 idx = 0, i = 0;
-		int rc;
-
-		/*
-		 * The flashes that are connected in stacked mode should be of same make.
-		 * Except the flash size all other properties are identical for all the
-		 * flashes connected in stacked mode.
-		 * The flashes that are connected in parallel mode should be identical.
-		 */
-		while (i < SNOR_FLASH_CNT_MAX) {
-			rc = ofnode_read_u64_index(dev_ofnode(dev), "stacked-memories",
-						   idx, &flash_size[i]);
-			if (rc == -EINVAL) {
-				break;
-			} else if (rc == -EOVERFLOW) {
-				idx++;
-			} else {
-				idx++;
-				i++;
-				if (!(nor->flags & SNOR_F_HAS_STACKED))
-					nor->flags |= SNOR_F_HAS_STACKED;
-				if (!(nor->spi->flags & SPI_XFER_STACKED))
-					nor->spi->flags |= SPI_XFER_STACKED;
-			}
-		}
-
-		i = 0;
-		idx = 0;
-		while (i < SNOR_FLASH_CNT_MAX) {
-			rc = ofnode_read_u64_index(dev_ofnode(dev), "parallel-memories",
-						   idx, &flash_size[i]);
-			if (rc == -EINVAL) {
-				break;
-			} else if (rc == -EOVERFLOW) {
-				idx++;
-			} else {
-				idx++;
-				i++;
-				if (!(nor->flags & SNOR_F_HAS_PARALLEL))
-					nor->flags |= SNOR_F_HAS_PARALLEL;
-			}
-		}
-
-		if (nor->flags & (SNOR_F_HAS_STACKED | SNOR_F_HAS_PARALLEL)) {
-			params->size = 0;
-			for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++)
-				params->size += flash_size[idx];
-		}
-		/*
-		 * In parallel-memories the erase operation is
-		 * performed on both the flashes simultaneously
-		 * so, double the erasesize.
-		 */
-		if (nor->flags & SNOR_F_HAS_PARALLEL) {
-			nor->mtd.erasesize <<= 1;
-			params->page_size <<= 1;
-		}
-	}
-#endif
-
 	spi_nor_late_init_fixups(nor, params);
 
 	return 0;
@@ -3571,54 +3337,16 @@ static int spi_nor_select_erase(struct spi_nor *nor,
 	/* prefer "small sector" erase if possible */
 	if (info->flags & SECT_4K) {
 		nor->erase_opcode = SPINOR_OP_BE_4K;
-		/*
-		 * In parallel-memories the erase operation is
-		 * performed on both the flashes simultaneously
-		 * so, double the erasesize.
-		 */
-		if (nor->flags & SNOR_F_HAS_PARALLEL)
-			mtd->erasesize = 4096 * 2;
-		else
-			mtd->erasesize = 4096;
+		mtd->erasesize = 4096;
 	} else if (info->flags & SECT_4K_PMC) {
 		nor->erase_opcode = SPINOR_OP_BE_4K_PMC;
-		/*
-		 * In parallel-memories the erase operation is
-		 * performed on both the flashes simultaneously
-		 * so, double the erasesize.
-		 */
-		if (nor->flags & SNOR_F_HAS_PARALLEL)
-			mtd->erasesize = 4096 * 2;
-		else
-			mtd->erasesize = 4096;
+		mtd->erasesize = 4096;
 	} else
 #endif
 	{
 		nor->erase_opcode = SPINOR_OP_SE;
-		/*
-		 * In parallel-memories the erase operation is
-		 * performed on both the flashes simultaneously
-		 * so, double the erasesize.
-		 */
-		if (nor->flags & SNOR_F_HAS_PARALLEL)
-			mtd->erasesize = info->sector_size * 2;
-		else
-			mtd->erasesize = info->sector_size;
-	}
-
-	if ((JEDEC_MFR(info) == SNOR_MFR_SST) && info->flags & SECT_4K) {
-		nor->erase_opcode = SPINOR_OP_BE_4K;
-		/*
-		 * In parallel-memories the erase operation is
-		 * performed on both the flashes simultaneously
-		 * so, double the erasesize.
-		 */
-		if (nor->flags & SNOR_F_HAS_PARALLEL)
-			mtd->erasesize = 4096 * 2;
-		else
-			mtd->erasesize = 4096;
+		mtd->erasesize = info->sector_size;
 	}
-
 	return 0;
 }
 
@@ -4282,9 +4010,6 @@ int spi_nor_init(struct spi_nor *nor)
 {
 	int err;
 
-	if (nor->flags & SNOR_F_HAS_PARALLEL)
-		nor->spi->flags |= SPI_NOR_ENABLE_MULTI_CS;
-
 	err = spi_nor_octal_dtr_enable(nor);
 	if (err) {
 		dev_dbg(nor->dev, "Octal DTR mode not supported\n");
@@ -4474,7 +4199,6 @@ int spi_nor_scan(struct spi_nor *nor)
 	struct spi_slave *spi = nor->spi;
 	int ret;
 	int cfi_mtd_nb = 0;
-	bool shift = 0;
 
 #ifdef CONFIG_FLASH_CFI_MTD
 	cfi_mtd_nb = CFI_FLASH_BANKS;
@@ -4612,9 +4336,7 @@ int spi_nor_scan(struct spi_nor *nor)
 		nor->addr_width = 3;
 	}
 
-	if (nor->flags & (SNOR_F_HAS_PARALLEL | SNOR_F_HAS_STACKED))
-		shift = 1;
-	if (nor->addr_width == 3 && (mtd->size >> shift) > SZ_16M) {
+	if (nor->addr_width == 3 && mtd->size > SZ_16M) {
 #if !CONFIG_IS_ENABLED(SPI_FLASH_BAR)
 		/* enable 4-byte addressing if the device exceeds 16MiB */
 		nor->addr_width = 4;
@@ -4641,14 +4363,6 @@ int spi_nor_scan(struct spi_nor *nor)
 	if (ret)
 		return ret;
 
-	if (nor->flags & SNOR_F_HAS_STACKED) {
-		nor->spi->flags |= SPI_XFER_U_PAGE;
-		ret = spi_nor_init(nor);
-		if (ret)
-			return ret;
-		nor->spi->flags &= ~SPI_XFER_U_PAGE;
-	}
-
 	nor->rdsr_dummy = params.rdsr_dummy;
 	nor->rdsr_addr_nbytes = params.rdsr_addr_nbytes;
 	nor->name = info->name;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 4eef4ab0488..ebbf6a7a944 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -13,9 +13,6 @@
 #include <linux/mtd/mtd.h>
 #include <spi-mem.h>
 
-/* In parallel configuration enable multiple CS */
-#define SPI_NOR_ENABLE_MULTI_CS	(BIT(0) | BIT(1))
-
 /*
  * Manufacturer IDs
  *
@@ -308,13 +305,6 @@ enum spi_nor_option_flags {
 	SNOR_F_BROKEN_RESET	= BIT(6),
 	SNOR_F_SOFT_RESET	= BIT(7),
 	SNOR_F_IO_MODE_EN_VOLATILE = BIT(8),
-#if defined(CONFIG_SPI_STACKED_PARALLEL)
-	SNOR_F_HAS_STACKED	= BIT(9),
-	SNOR_F_HAS_PARALLEL	= BIT(10),
-#else
-	SNOR_F_HAS_STACKED	= 0,
-	SNOR_F_HAS_PARALLEL	= 0,
-#endif
 };
 
 struct spi_nor;
diff --git a/include/spi.h b/include/spi.h
index 2783200d663..473790135b9 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -164,8 +164,6 @@ struct spi_slave {
 #define SPI_XFER_END		BIT(1)	/* Deassert CS after transfer */
 #define SPI_XFER_ONCE		(SPI_XFER_BEGIN | SPI_XFER_END)
 #define SPI_XFER_U_PAGE		BIT(4)
-#define SPI_XFER_STACKED	BIT(5)
-#define SPI_XFER_LOWER		BIT(6)
 
 	/*
 	 * Flag indicating that the spi-controller has multi chip select

-- 
2.34.1



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

* [PATCH 11/11] mtd: spi-nor: Call stacked/parallel post init fixups
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
                   ` (9 preceding siblings ...)
  2025-11-19  5:13 ` [PATCH 10/11] mtd: spi-nor: Revert stacked/parallel related commits Takahiro Kuwano via B4 Relay
@ 2025-11-19  5:13 ` Takahiro Kuwano via B4 Relay
  2025-12-16 13:45 ` [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Begari, Padmarao
  11 siblings, 0 replies; 17+ messages in thread
From: Takahiro Kuwano via B4 Relay @ 2025-11-19  5:13 UTC (permalink / raw)
  To: u-boot, Tudor Ambarus
  Cc: Jagan Teki, Michal Simek, Tom Rini, Ibai Erkiaga, Vignesh R,
	Prasad Kummari, Marek Vasut, Havish Mutya, Ashok Reddy Soma,
	Venkatesh Yadav Abbarapu, Daassi Bacem, Shinsuke Okada,
	Hiroyuki Saito, Takahiro Kuwano, Takahiro Kuwano

From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

Add support for stacked/parallel mode by calling post_init_fixups() from
core.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
 drivers/mtd/spi/sf_internal.h  |  3 +++
 drivers/mtd/spi/spi-nor-core.c | 10 ++++++++++
 2 files changed, 13 insertions(+)

diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 8b1a48f045a..a9825a0b317 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -108,4 +108,7 @@ int clean_bar(struct spi_nor *nor);
 int sst_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 	      const u_char *buf);
 
+int spi_nor_stacked_post_init_fixups(struct spi_nor *nor);
+int spi_nor_parallel_post_init_fixups(struct spi_nor *nor);
+
 #endif /* _SF_INTERNAL_H_ */
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index acfbc0bb702..f9b6971e535 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -4363,6 +4363,16 @@ int spi_nor_scan(struct spi_nor *nor)
 	if (ret)
 		return ret;
 
+#if CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)
+	ret = spi_nor_stacked_post_init_fixups(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_parallel_post_init_fixups(nor);
+	if (ret)
+		return ret;
+#endif
+
 	nor->rdsr_dummy = params.rdsr_dummy;
 	nor->rdsr_addr_nbytes = params.rdsr_addr_nbytes;
 	nor->name = info->name;

-- 
2.34.1



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

* RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
  2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
                   ` (10 preceding siblings ...)
  2025-11-19  5:13 ` [PATCH 11/11] mtd: spi-nor: Call stacked/parallel post init fixups Takahiro Kuwano via B4 Relay
@ 2025-12-16 13:45 ` Begari, Padmarao
  2026-02-23 14:12   ` Begari, Padmarao
  11 siblings, 1 reply; 17+ messages in thread
From: Begari, Padmarao @ 2025-12-16 13:45 UTC (permalink / raw)
  To: Takahiro.Kuwano@infineon.com, u-boot@lists.denx.de, Tudor Ambarus
  Cc: Jagan Teki, Simek, Michal, Tom Rini, Erkiaga Elorza, Ibai,
	Vignesh R, Kummari, Prasad, Marek Vasut, Mutya, Havish,
	Ashok Reddy Soma, Venkatesh Yadav Abbarapu, Daassi Bacem,
	Shinsuke Okada, Hiroyuki Saito, Takahiro Kuwano

[AMD Official Use Only - AMD Internal Distribution Only]

Hi Takahiro Kuwano,

Apologies for the delay in responding and thank you for sending this patch series. Since the changes are related to our AMD stacked and parallel configurations, we’ll look into it.

Thanks & Regards
Padmarao

> -----Original Message-----
> From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Takahiro Kuwano via
> B4 Relay
> Sent: Wednesday, November 19, 2025 10:43 AM
> To: u-boot@lists.denx.de; Tudor Ambarus <tudor.ambarus@linaro.org>
> Cc: Jagan Teki <jagan@amarulasolutions.com>; Simek, Michal
> <michal.simek@amd.com>; Tom Rini <trini@konsulko.com>; Erkiaga Elorza, Ibai
> <ibai.erkiaga-elorza@amd.com>; Vignesh R <vigneshr@ti.com>; Kummari, Prasad
> <Prasad.Kummari@amd.com>; Marek Vasut
> <marek.vasut+renesas@mailbox.org>; Mutya, Havish <havish.mutya@amd.com>;
> Ashok Reddy Soma <ashok.reddy.soma@amd.com>; Venkatesh Yadav Abbarapu
> <venkatesh.abbarapu@amd.com>; Daassi Bacem
> <Bacem.Daassi@infineon.com>; Shinsuke Okada
> <Shinsuke.Okada@infineon.com>; Hiroyuki Saito
> <Hiroyuki.Saito2@infineon.com>; Takahiro Kuwano <tkuw584924@gmail.com>;
> Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> Subject: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
>
> This series suggests to isolate stacked/parallel support from spi-nor-core by
> moving that to SPI controllers and new modules under mtd/spi.
>
> The patchset mainly focuses on removing references to stacked/parallel related
> items from core. The stacked/parallel support logic itself may have rooms to
> improve. Rework or further cleanup in stacked/parallel support would be done by
> other patches after this series is applied.
>
> Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> ---
> Takahiro Kuwano (11):
>       spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe()
>       spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag.
>       spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode
>       spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe()
>       spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag.
>       spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode
>       mtd: spi-nor: Migrate stacked/parallel part to new modules
>       mtd: spi-nor: stacked: Cleanup stacked/parallel flags
>       mtd: spi-nor: parallel: Cleanup stacked/parallel flags
>       mtd: spi-nor: Revert stacked/parallel related commits
>       mtd: spi-nor: Call stacked/parallel post init fixups
>
>  drivers/mtd/spi/Makefile       |   4 +
>  drivers/mtd/spi/parallel.c     | 412
> ++++++++++++++++++++++++++++++++++++++++
>  drivers/mtd/spi/sf_internal.h  |  18 ++  drivers/mtd/spi/spi-nor-core.c | 422
> +++++++----------------------------------
>  drivers/mtd/spi/stacked.c      | 389
> +++++++++++++++++++++++++++++++++++++
>  drivers/spi/zynq_qspi.c        |  47 +++--
>  drivers/spi/zynqmp_gqspi.c     |  55 ++++--
>  include/linux/mtd/spi-nor.h    |  10 -
>  include/spi.h                  |   2 -
>  9 files changed, 973 insertions(+), 386 deletions(-)
> ---
> base-commit: e2d51f8db207f7db70dd8104fa1da2cffda419f2
> change-id: 20251118-amd-cleanup-c8023872e3cf
>
> Best regards,
> --
> Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>


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

* RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
  2025-12-16 13:45 ` [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Begari, Padmarao
@ 2026-02-23 14:12   ` Begari, Padmarao
  2026-02-24  8:04     ` Takahiro.Kuwano
  0 siblings, 1 reply; 17+ messages in thread
From: Begari, Padmarao @ 2026-02-23 14:12 UTC (permalink / raw)
  To: Begari, Padmarao, Takahiro.Kuwano@infineon.com,
	u-boot@lists.denx.de, Tudor Ambarus
  Cc: Jagan Teki, Simek, Michal, Tom Rini, Erkiaga Elorza, Ibai,
	Vignesh R, Kummari, Prasad, Marek Vasut, Mutya, Havish,
	Ashok Reddy Soma, Venkatesh Yadav Abbarapu, Daassi Bacem,
	Shinsuke Okada, Hiroyuki Saito, Takahiro Kuwano

[Public]

Hi Takahiro Kuwano,

We have tested your patches with upstream u-boot and found issues with both QSPI and OSPI flashes. Below are results, 1 for QSPI and 2 for OSPI.

1). Issue : observed with QSPI flash's operating in single mode. tested below flashes

n25q00a on VCK190
mt25qu512a on ZCU102

Observed Behavior:
Data mismatch is observed in single‑mode QSPI during partial data integrity tests, such as:
9‑byte test
32‑byte test
32 MB test , etc.,
The data written to flash does not match the data read back when compared byte‑by‑byte.

Working Behavior
Full flash size data integrity test is working fine in single mode also
Dual‑mode QSPI tests working fine .
The issue is reproducible only in single‑mode QSPI partial data integrity tests

-------------------------------------------------------------------------------
U-Boot 2026.04-rc2-00046-g967458518770 (Feb 18 2026 - 16:18:41 +0530)

CPU:   Versal
Silicon: v2
Chip:  v2
CPU:   VersalSilicon: v2Chip:  v2Model: Xilinx Versal vck190 Eval board revA (QSPI)
DRAM:  2 GiB (total 8 GiB)
EL Level: EL2
Multiboot: 0
Core:  41 devices, 24 uclasses, devicetree: board
MMC:   arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
mmc@f1050000 - probe failed: -110
arasan_sdhci mmc@f1050000: Sdhci card detect state not stable

Loading Environment from nowhere... OK
In:    serial@ff000000
Out:   serial@ff000000
Loading Environment from nowhere... OKIn:    serial@ff000000Out:   serial@ff000000Err:   serial@ff000000
Bootmode: JTAG_MODE
Net:
ZYNQ GEM: ff0c0000, mdio bus ff0c0000, phyaddr 1, interface rgmii-id

Warning: ethernet@ff0c0000 (eth0) using random MAC address - 72:1e:d7:a9:9b:1a
eth0: ethernet@ff0c0000Get shared mii bus on ethernet@ff0d0000

ZYNQ GEM: ff0d0000, mdio bus ff0c0000, phyaddr 2, interface rgmii-id

Warning: ethernet@ff0d0000 (eth1) using random MAC address - da:67:b7:c3:2f:ca
, eth1: ethernet@ff0d0000
Warning: ethernet@ff0d0000 (eth1) using random MAC address - da:67:b7:c3:2f:ca, eth1: ethernet@ff0d0000arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
Cannot persist EFI variables without system partition
Missing TPMv2 device for EFI_TCG_PROTOCOL
Missing RNG device for EFI_RNG_PROTOCOL
Hit any key to stop autoboot: 0
Versal> tftpb 0x400000 test_32MB.bin
Filename 'test_32MB.bin'.
Load address: 0x400000
Loading: ##################################################  32 MiB
12.5 MiB/s
done
Bytes transferred = 33554432 (2000000 hex)
Versal> sf probe 0 0 0
SF: Detected n25q00a with page size 256 Bytes, erase size 64 KiB, total 128 MiB
Versal> sf erase 0x0 0x2000000
SF: 33554432 bytes @ 0x0 Erased: OK
Versal> sf write 0x400000 0x0 0x2000000
device 0 offset 0x0, size 0x2000000
SF: 33554432 bytes @ 0x0 Written: OK
Versal> mw.b 0x4000000 0 0x2000000
Versal> sf read 0x4000000 0x0 0x2000000
device 0 offset 0x0, size 0x2000000
SF: 33554432 bytes @ 0x0 Read: OK
Versal> cmp.b 0x400000 0x4000000 0x2000000
byte at 0x00400000 (0x14) != byte at 0x04000000 (0xc4)
Total of 0 byte(s) were the same


Versal> mw.b 0x8000 de 0x4000000
Versal> sf erase 0x4000000 0x4000000
SF: 67108864 bytes @ 0x4000000 Erased: OK
Versal> sf write 0x8000 0x4000000 0x4000000
device 0 offset 0x4000000, size 0x4000000
SF: 67108864 bytes @ 0x4000000 Written: OK
Versal> mw.b 0x20000000 0 0x4000000
Versal> sf read 0x20000000 0x4000000 0x4000000
device 0 offset 0x4000000, size 0x4000000
SF: 67108864 bytes @ 0x4000000 Read: OK
Versal> cmp.b 0x8000 0x20000000 0x4000000
cmp.b 0x8000 0x20000000 0x4000000
byte at 0x00008000 (0xde) != byte at 0x20000000 (0xce)
Total of 0 byte(s) were the same
-------------------------------------------------------------------------------


2). Issue: observed OSPI data integrity failures with MT35XU02G flash:

Versal Gen 2 SoC with single mode
Versal_net SoC with stacked mode

Observed Behavior
Data mismatch is observed in single and stacked mode OSPI during large data integrity tests, and full-size data integrity.

Working Behavior
Full flash size data integrity test is working fine in single mode on vck190 board: Versal platform. tested ospi flashes: gd55lx01g , mt35xu02g
-------------------------------------------------------------------------------
U-Boot 2026.04-rc2-00047-g413f7147bb88 (Feb 18 2026 - 17:30:17 +0530)
CPU:   Versal Gen 2
Silicon: v1.0
Chip:  v1.0
Model: X-PRC-11 revA
DRAM:  2 GiB
optee optee: OP-TEE api uid mismatch
NOT_SUPPORTED: A Firmware Framework implementation does not exist
EL Level:    EL2
Core:  48 devices, 27 uclasses, devicetree: board
MMC:   mmc@f1040000: 0
Loading Environment from nowhere... OK
In:    serial@f1920000
Out:   serial@f1920000
Err:   serial@f1920000
Bootmode: JTAG_MODE
Net:
ZYNQ GEM: f1a70000, mdio bus f1a70000, phyaddr 1, interface rgmii-idWarning: ethernet@f1a70000 (eth0) using random MAC address - 02:2b:b8:0d:92:33
eth0: ethernet@f1a70000
Hit any key to stop autoboot: 0
versal2> sf probe 0 0 0
sf probe 0 0 0
SF: Detected mt35xu02g with page size 256 Bytes, erase size 128 KiB, total 256 MiB
versal2> mw.b 0x8000 cd 0x10000000
versal2> sf erase 0x0 0x10000000
SF: 268435456 bytes @ 0x0 Erased: OK
versal2> sf write 0x8000 0x0 0x10000000
device 0 whole chip
SF: 268435456 bytes @ 0x0 Written: OK
versal2> mw.b 0x20010000 0 0x10000000
versal2> sf read 0x20010000 0x0 0x10000000
device 0 whole chip
SF: 268435456 bytes @ 0x0 Read: OK
versal2> cmp.b 0x8000 0x20010000 0x10000000
cmp.b 0x8000 0x20010000 0x10000000
byte at 0x05758240 (0xcd) != byte at 0x25760240 (0x0)
Total of 91554368 byte(s) were the same

Versal NET> sf probe 0 0 0
SF: Detected mt35xu02g with page size 256 Bytes, erase size 128 KiB, total 512 MiB
Versal NET> mw.b 0x8000 cd 0x20000000
Versal NET> sf erase 0x0 0x20000000
SF: 536870912 bytes @ 0x0 Erased: OK
Versal NET> sf write 0x8000 0x0 0x20000000
device 0 whole chip
SF: 536870912 bytes @ 0x0 Written: OK
Versal NET> mw.b 0x20010000 0 0x20000000
Versal NET> sf read 0x20010000 0x0 0x20000000
device 0 whole chip
SF: 536870912 bytes @ 0x0 Read: OK
Versal NET> cmp.b 0x8000 0x20010000 0x20000000
cmp.b 0x8000 0x20010000 0x20000000
byte at 0x00008000 (0xcd) != byte at 0x20010000 (0x0)
Total of 0 byte(s) were the same
-------------------------------------------------------------------------------

Regards
Padmarao

> From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Begari, Padmarao
> Sent: Tuesday, December 16, 2025 7:16 PM
> To: Takahiro.Kuwano@infineon.com; u-boot@lists.denx.de; Tudor Ambarus
> <tudor.ambarus@linaro.org>
> Cc: Jagan Teki <jagan@amarulasolutions.com>; Simek, Michal
> <michal.simek@amd.com>; Tom Rini <trini@konsulko.com>; Erkiaga Elorza, Ibai
> <ibai.erkiaga-elorza@amd.com>; Vignesh R <vigneshr@ti.com>; Kummari, Prasad
> <Prasad.Kummari@amd.com>; Marek Vasut <marek.vasut+renesas@mailbox.org>;
> Mutya, Havish <havish.mutya@amd.com>; Ashok Reddy Soma
> <ashok.reddy.soma@amd.com>; Venkatesh Yadav Abbarapu
> <venkatesh.abbarapu@amd.com>; Daassi Bacem <Bacem.Daassi@infineon.com>;
> Shinsuke Okada <Shinsuke.Okada@infineon.com>; Hiroyuki Saito
> <Hiroyuki.Saito2@infineon.com>; Takahiro Kuwano <tkuw584924@gmail.com>
> Subject: RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
>
>
> Hi Takahiro Kuwano,
>
> Apologies for the delay in responding and thank you for sending this patch series.
> Since the changes are related to our AMD stacked and parallel configurations, we’ll
> look into it.
>
> Thanks & Regards
> Padmarao
>
> > -----Original Message-----
> > From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Takahiro
> > Kuwano via
> > B4 Relay
> > Sent: Wednesday, November 19, 2025 10:43 AM
> > To: u-boot@lists.denx.de; Tudor Ambarus <tudor.ambarus@linaro.org>
> > Cc: Jagan Teki <jagan@amarulasolutions.com>; Simek, Michal
> > <michal.simek@amd.com>; Tom Rini <trini@konsulko.com>; Erkiaga Elorza,
> > Ibai <ibai.erkiaga-elorza@amd.com>; Vignesh R <vigneshr@ti.com>;
> > Kummari, Prasad <Prasad.Kummari@amd.com>; Marek Vasut
> > <marek.vasut+renesas@mailbox.org>; Mutya, Havish
> > <havish.mutya@amd.com>; Ashok Reddy Soma <ashok.reddy.soma@amd.com>;
> > Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>; Daassi Bacem
> > <Bacem.Daassi@infineon.com>; Shinsuke Okada
> > <Shinsuke.Okada@infineon.com>; Hiroyuki Saito
> > <Hiroyuki.Saito2@infineon.com>; Takahiro Kuwano
> > <tkuw584924@gmail.com>; Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > Subject: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support
> > from core
> >
> > This series suggests to isolate stacked/parallel support from
> > spi-nor-core by moving that to SPI controllers and new modules under mtd/spi.
> >
> > The patchset mainly focuses on removing references to stacked/parallel
> > related items from core. The stacked/parallel support logic itself may
> > have rooms to improve. Rework or further cleanup in stacked/parallel
> > support would be done by other patches after this series is applied.
> >
> > Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > ---
> > Takahiro Kuwano (11):
> >       spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe()
> >       spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag.
> >       spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode
> >       spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe()
> >       spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag.
> >       spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode
> >       mtd: spi-nor: Migrate stacked/parallel part to new modules
> >       mtd: spi-nor: stacked: Cleanup stacked/parallel flags
> >       mtd: spi-nor: parallel: Cleanup stacked/parallel flags
> >       mtd: spi-nor: Revert stacked/parallel related commits
> >       mtd: spi-nor: Call stacked/parallel post init fixups
> >
> >  drivers/mtd/spi/Makefile       |   4 +
> >  drivers/mtd/spi/parallel.c     | 412
> > ++++++++++++++++++++++++++++++++++++++++
> >  drivers/mtd/spi/sf_internal.h  |  18 ++
> > drivers/mtd/spi/spi-nor-core.c | 422
> > +++++++----------------------------------
> >  drivers/mtd/spi/stacked.c      | 389
> > +++++++++++++++++++++++++++++++++++++
> >  drivers/spi/zynq_qspi.c        |  47 +++--
> >  drivers/spi/zynqmp_gqspi.c     |  55 ++++--
> >  include/linux/mtd/spi-nor.h    |  10 -
> >  include/spi.h                  |   2 -
> >  9 files changed, 973 insertions(+), 386 deletions(-)
> > ---
> > base-commit: e2d51f8db207f7db70dd8104fa1da2cffda419f2
> > change-id: 20251118-amd-cleanup-c8023872e3cf
> >
> > Best regards,
> > --
> > Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> >


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

* RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
  2026-02-23 14:12   ` Begari, Padmarao
@ 2026-02-24  8:04     ` Takahiro.Kuwano
  2026-04-14  4:51       ` Takahiro.Kuwano
  0 siblings, 1 reply; 17+ messages in thread
From: Takahiro.Kuwano @ 2026-02-24  8:04 UTC (permalink / raw)
  To: Padmarao.Begari, u-boot, tudor.ambarus
  Cc: jagan, michal.simek, trini, ibai.erkiaga-elorza, vigneshr,
	Prasad.Kummari, marek.vasut+renesas, havish.mutya,
	ashok.reddy.soma, venkatesh.abbarapu, Bacem.Daassi,
	Shinsuke.Okada, Hiroyuki.Saito2, tkuw584924

> Hi Takahiro Kuwano,
Hi

> 
> We have tested your patches with upstream u-boot and found issues with both QSPI and OSPI flashes. Below are
> results, 1 for QSPI and 2 for OSPI.
> 
Thanks for your help!

> 1). Issue : observed with QSPI flash's operating in single mode. tested below flashes
> 
> n25q00a on VCK190
> mt25qu512a on ZCU102
> 
> Observed Behavior:
> Data mismatch is observed in single‑mode QSPI during partial data integrity tests, such as:
> 9‑byte test
> 32‑byte test
> 32 MB test , etc.,
> The data written to flash does not match the data read back when compared byte‑by‑byte.
> 
> Working Behavior
> Full flash size data integrity test is working fine in single mode also
> Dual‑mode QSPI tests working fine .
> The issue is reproducible only in single‑mode QSPI partial data integrity tests
> 
This series tries to keep single-mode QSPI unchanged.
Could you please narrow down which change in series breaks it?

> -------------------------------------------------------------------------------
> U-Boot 2026.04-rc2-00046-g967458518770 (Feb 18 2026 - 16:18:41 +0530)
> 
> CPU:   Versal
> Silicon: v2
> Chip:  v2
> CPU:   VersalSilicon: v2Chip:  v2Model: Xilinx Versal vck190 Eval board revA (QSPI)
> DRAM:  2 GiB (total 8 GiB)
> EL Level: EL2
> Multiboot: 0
> Core:  41 devices, 24 uclasses, devicetree: board
> MMC:   arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> mmc@f1050000 - probe failed: -110
> arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> 
> Loading Environment from nowhere... OK
> In:    serial@ff000000
> Out:   serial@ff000000
> Loading Environment from nowhere... OKIn:    serial@ff000000Out:   serial@ff000000Err:   serial@ff000000
> Bootmode: JTAG_MODE
> Net:
> ZYNQ GEM: ff0c0000, mdio bus ff0c0000, phyaddr 1, interface rgmii-id
> 
> Warning: ethernet@ff0c0000 (eth0) using random MAC address - 72:1e:d7:a9:9b:1a
> eth0: ethernet@ff0c0000Get shared mii bus on ethernet@ff0d0000
> 
> ZYNQ GEM: ff0d0000, mdio bus ff0c0000, phyaddr 2, interface rgmii-id
> 
> Warning: ethernet@ff0d0000 (eth1) using random MAC address - da:67:b7:c3:2f:ca
> , eth1: ethernet@ff0d0000
> Warning: ethernet@ff0d0000 (eth1) using random MAC address - da:67:b7:c3:2f:ca, eth1:
> ethernet@ff0d0000arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> Cannot persist EFI variables without system partition
> Missing TPMv2 device for EFI_TCG_PROTOCOL
> Missing RNG device for EFI_RNG_PROTOCOL
> Hit any key to stop autoboot: 0
> Versal> tftpb 0x400000 test_32MB.bin
> Filename 'test_32MB.bin'.
> Load address: 0x400000
> Loading: ##################################################  32 MiB
> 12.5 MiB/s
> done
> Bytes transferred = 33554432 (2000000 hex)
> Versal> sf probe 0 0 0
> SF: Detected n25q00a with page size 256 Bytes, erase size 64 KiB, total 128 MiB
> Versal> sf erase 0x0 0x2000000
> SF: 33554432 bytes @ 0x0 Erased: OK
> Versal> sf write 0x400000 0x0 0x2000000
> device 0 offset 0x0, size 0x2000000
> SF: 33554432 bytes @ 0x0 Written: OK
> Versal> mw.b 0x4000000 0 0x2000000
> Versal> sf read 0x4000000 0x0 0x2000000
> device 0 offset 0x0, size 0x2000000
> SF: 33554432 bytes @ 0x0 Read: OK
> Versal> cmp.b 0x400000 0x4000000 0x2000000
> byte at 0x00400000 (0x14) != byte at 0x04000000 (0xc4)
> Total of 0 byte(s) were the same
> 
> 
> Versal> mw.b 0x8000 de 0x4000000
> Versal> sf erase 0x4000000 0x4000000
> SF: 67108864 bytes @ 0x4000000 Erased: OK
> Versal> sf write 0x8000 0x4000000 0x4000000
> device 0 offset 0x4000000, size 0x4000000
> SF: 67108864 bytes @ 0x4000000 Written: OK
> Versal> mw.b 0x20000000 0 0x4000000
> Versal> sf read 0x20000000 0x4000000 0x4000000
> device 0 offset 0x4000000, size 0x4000000
> SF: 67108864 bytes @ 0x4000000 Read: OK
> Versal> cmp.b 0x8000 0x20000000 0x4000000
> cmp.b 0x8000 0x20000000 0x4000000
> byte at 0x00008000 (0xde) != byte at 0x20000000 (0xce)
> Total of 0 byte(s) were the same
> -------------------------------------------------------------------------------
> 
> 
> 2). Issue: observed OSPI data integrity failures with MT35XU02G flash:
> 
> Versal Gen 2 SoC with single mode
> Versal_net SoC with stacked mode
> 
> Observed Behavior
> Data mismatch is observed in single and stacked mode OSPI during large data integrity tests, and full-size data
> integrity.
> 
> Working Behavior
> Full flash size data integrity test is working fine in single mode on vck190 board: Versal platform. tested
> ospi flashes: gd55lx01g , mt35xu02g

So, in single mode, gd55lx01g works, but mt35xu02g doesn't, right?
I tried not to change any device specific logics.
Same like 1), please narrow down which change in this series breaks it.

Best Regards,
Takahiro

> -------------------------------------------------------------------------------
> U-Boot 2026.04-rc2-00047-g413f7147bb88 (Feb 18 2026 - 17:30:17 +0530)
> CPU:   Versal Gen 2
> Silicon: v1.0
> Chip:  v1.0
> Model: X-PRC-11 revA
> DRAM:  2 GiB
> optee optee: OP-TEE api uid mismatch
> NOT_SUPPORTED: A Firmware Framework implementation does not exist
> EL Level:    EL2
> Core:  48 devices, 27 uclasses, devicetree: board
> MMC:   mmc@f1040000: 0
> Loading Environment from nowhere... OK
> In:    serial@f1920000
> Out:   serial@f1920000
> Err:   serial@f1920000
> Bootmode: JTAG_MODE
> Net:
> ZYNQ GEM: f1a70000, mdio bus f1a70000, phyaddr 1, interface rgmii-idWarning: ethernet@f1a70000 (eth0) using
> random MAC address - 02:2b:b8:0d:92:33
> eth0: ethernet@f1a70000
> Hit any key to stop autoboot: 0
> versal2> sf probe 0 0 0
> sf probe 0 0 0
> SF: Detected mt35xu02g with page size 256 Bytes, erase size 128 KiB, total 256 MiB
> versal2> mw.b 0x8000 cd 0x10000000
> versal2> sf erase 0x0 0x10000000
> SF: 268435456 bytes @ 0x0 Erased: OK
> versal2> sf write 0x8000 0x0 0x10000000
> device 0 whole chip
> SF: 268435456 bytes @ 0x0 Written: OK
> versal2> mw.b 0x20010000 0 0x10000000
> versal2> sf read 0x20010000 0x0 0x10000000
> device 0 whole chip
> SF: 268435456 bytes @ 0x0 Read: OK
> versal2> cmp.b 0x8000 0x20010000 0x10000000
> cmp.b 0x8000 0x20010000 0x10000000
> byte at 0x05758240 (0xcd) != byte at 0x25760240 (0x0)
> Total of 91554368 byte(s) were the same
> 
> Versal NET> sf probe 0 0 0
> SF: Detected mt35xu02g with page size 256 Bytes, erase size 128 KiB, total 512 MiB
> Versal NET> mw.b 0x8000 cd 0x20000000
> Versal NET> sf erase 0x0 0x20000000
> SF: 536870912 bytes @ 0x0 Erased: OK
> Versal NET> sf write 0x8000 0x0 0x20000000
> device 0 whole chip
> SF: 536870912 bytes @ 0x0 Written: OK
> Versal NET> mw.b 0x20010000 0 0x20000000
> Versal NET> sf read 0x20010000 0x0 0x20000000
> device 0 whole chip
> SF: 536870912 bytes @ 0x0 Read: OK
> Versal NET> cmp.b 0x8000 0x20010000 0x20000000
> cmp.b 0x8000 0x20010000 0x20000000
> byte at 0x00008000 (0xcd) != byte at 0x20010000 (0x0)
> Total of 0 byte(s) were the same
> -------------------------------------------------------------------------------
> 
> Regards
> Padmarao
> 
> > From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Begari, Padmarao
> > Sent: Tuesday, December 16, 2025 7:16 PM
> > To: Takahiro.Kuwano@infineon.com; u-boot@lists.denx.de; Tudor Ambarus
> > <tudor.ambarus@linaro.org>
> > Cc: Jagan Teki <jagan@amarulasolutions.com>; Simek, Michal
> > <michal.simek@amd.com>; Tom Rini <trini@konsulko.com>; Erkiaga Elorza, Ibai
> > <ibai.erkiaga-elorza@amd.com>; Vignesh R <vigneshr@ti.com>; Kummari, Prasad
> > <Prasad.Kummari@amd.com>; Marek Vasut <marek.vasut+renesas@mailbox.org>;
> > Mutya, Havish <havish.mutya@amd.com>; Ashok Reddy Soma
> > <ashok.reddy.soma@amd.com>; Venkatesh Yadav Abbarapu
> > <venkatesh.abbarapu@amd.com>; Daassi Bacem <Bacem.Daassi@infineon.com>;
> > Shinsuke Okada <Shinsuke.Okada@infineon.com>; Hiroyuki Saito
> > <Hiroyuki.Saito2@infineon.com>; Takahiro Kuwano <tkuw584924@gmail.com>
> > Subject: RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
> >
> >
> > Hi Takahiro Kuwano,
> >
> > Apologies for the delay in responding and thank you for sending this patch series.
> > Since the changes are related to our AMD stacked and parallel configurations, we’ll
> > look into it.
> >
> > Thanks & Regards
> > Padmarao
> >
> > > -----Original Message-----
> > > From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Takahiro
> > > Kuwano via
> > > B4 Relay
> > > Sent: Wednesday, November 19, 2025 10:43 AM
> > > To: u-boot@lists.denx.de; Tudor Ambarus <tudor.ambarus@linaro.org>
> > > Cc: Jagan Teki <jagan@amarulasolutions.com>; Simek, Michal
> > > <michal.simek@amd.com>; Tom Rini <trini@konsulko.com>; Erkiaga Elorza,
> > > Ibai <ibai.erkiaga-elorza@amd.com>; Vignesh R <vigneshr@ti.com>;
> > > Kummari, Prasad <Prasad.Kummari@amd.com>; Marek Vasut
> > > <marek.vasut+renesas@mailbox.org>; Mutya, Havish
> > > <havish.mutya@amd.com>; Ashok Reddy Soma <ashok.reddy.soma@amd.com>;
> > > Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>; Daassi Bacem
> > > <Bacem.Daassi@infineon.com>; Shinsuke Okada
> > > <Shinsuke.Okada@infineon.com>; Hiroyuki Saito
> > > <Hiroyuki.Saito2@infineon.com>; Takahiro Kuwano
> > > <tkuw584924@gmail.com>; Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > > Subject: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support
> > > from core
> > >
> > > This series suggests to isolate stacked/parallel support from
> > > spi-nor-core by moving that to SPI controllers and new modules under mtd/spi.
> > >
> > > The patchset mainly focuses on removing references to stacked/parallel
> > > related items from core. The stacked/parallel support logic itself may
> > > have rooms to improve. Rework or further cleanup in stacked/parallel
> > > support would be done by other patches after this series is applied.
> > >
> > > Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > > ---
> > > Takahiro Kuwano (11):
> > >       spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe()
> > >       spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag.
> > >       spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode
> > >       spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe()
> > >       spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag.
> > >       spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode
> > >       mtd: spi-nor: Migrate stacked/parallel part to new modules
> > >       mtd: spi-nor: stacked: Cleanup stacked/parallel flags
> > >       mtd: spi-nor: parallel: Cleanup stacked/parallel flags
> > >       mtd: spi-nor: Revert stacked/parallel related commits
> > >       mtd: spi-nor: Call stacked/parallel post init fixups
> > >
> > >  drivers/mtd/spi/Makefile       |   4 +
> > >  drivers/mtd/spi/parallel.c     | 412
> > > ++++++++++++++++++++++++++++++++++++++++
> > >  drivers/mtd/spi/sf_internal.h  |  18 ++
> > > drivers/mtd/spi/spi-nor-core.c | 422
> > > +++++++----------------------------------
> > >  drivers/mtd/spi/stacked.c      | 389
> > > +++++++++++++++++++++++++++++++++++++
> > >  drivers/spi/zynq_qspi.c        |  47 +++--
> > >  drivers/spi/zynqmp_gqspi.c     |  55 ++++--
> > >  include/linux/mtd/spi-nor.h    |  10 -
> > >  include/spi.h                  |   2 -
> > >  9 files changed, 973 insertions(+), 386 deletions(-)
> > > ---
> > > base-commit: e2d51f8db207f7db70dd8104fa1da2cffda419f2
> > > change-id: 20251118-amd-cleanup-c8023872e3cf
> > >
> > > Best regards,
> > > --
> > > Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > >


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

* RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
  2026-02-24  8:04     ` Takahiro.Kuwano
@ 2026-04-14  4:51       ` Takahiro.Kuwano
  2026-04-19 14:27         ` Begari, Padmarao
  0 siblings, 1 reply; 17+ messages in thread
From: Takahiro.Kuwano @ 2026-04-14  4:51 UTC (permalink / raw)
  To: Padmarao.Begari, u-boot, tudor.ambarus
  Cc: jagan, michal.simek, trini, ibai.erkiaga-elorza, vigneshr,
	Prasad.Kummari, marek.vasut+renesas, havish.mutya,
	ashok.reddy.soma, venkatesh.abbarapu, Bacem.Daassi,
	Shinsuke.Okada, Hiroyuki.Saito2, Shivendra.Singh

Hi Padmarao and AMD team,

Could you please help to narrow down the issues?

I was acknowledged a bug in spi-nor-core [1]. It would be better to fix it in
a series of 'sync to Linux' patches after isolation of stacked/parallel,
rather than patching on top of that.

As discussed in [2], SPI-NOR subsystem in u-boot has not been maintained long
time. Generic SPI-NOR driver introduced in Linux needs to be ported into u-boot
to mitigate growing device ID table. Isolation of stacked/parallel is necessary
to move forward.

Now stacked memories support is available in Linux [3] with different approach
from the one in u-boot. Isolation is also needed as the first step to adapt the
Linux's approach to u-boot.

[1] https://lore.kernel.org/u-boot/683be5a32ef345229d54a68ea67fe64c@infineon.com/
[2] https://lore.kernel.org/u-boot/20260213164607.GI2747538@bill-the-cat/#t
[3] https://lore.kernel.org/linux-mtd/20260204-mtd-virt-concat-v17-0-5e98239bb55b@bootlin.com/

Thanks,
Takahiro

> 
> > Hi Takahiro Kuwano,
> Hi
> 
> >
> > We have tested your patches with upstream u-boot and found issues with both QSPI and OSPI flashes. Below are
> > results, 1 for QSPI and 2 for OSPI.
> >
> Thanks for your help!
> 
> > 1). Issue : observed with QSPI flash's operating in single mode. tested below flashes
> >
> > n25q00a on VCK190
> > mt25qu512a on ZCU102
> >
> > Observed Behavior:
> > Data mismatch is observed in single‑mode QSPI during partial data integrity tests, such as:
> > 9‑byte test
> > 32‑byte test
> > 32 MB test , etc.,
> > The data written to flash does not match the data read back when compared byte‑by‑byte.
> >
> > Working Behavior
> > Full flash size data integrity test is working fine in single mode also
> > Dual‑mode QSPI tests working fine .
> > The issue is reproducible only in single‑mode QSPI partial data integrity tests
> >
> This series tries to keep single-mode QSPI unchanged.
> Could you please narrow down which change in series breaks it?
> 
> > -------------------------------------------------------------------------------
> > U-Boot 2026.04-rc2-00046-g967458518770 (Feb 18 2026 - 16:18:41 +0530)
> >
> > CPU:   Versal
> > Silicon: v2
> > Chip:  v2
> > CPU:   VersalSilicon: v2Chip:  v2Model: Xilinx Versal vck190 Eval board revA (QSPI)
> > DRAM:  2 GiB (total 8 GiB)
> > EL Level: EL2
> > Multiboot: 0
> > Core:  41 devices, 24 uclasses, devicetree: board
> > MMC:   arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> > arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> > mmc@f1050000 - probe failed: -110
> > arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> >
> > Loading Environment from nowhere... OK
> > In:    serial@ff000000
> > Out:   serial@ff000000
> > Loading Environment from nowhere... OKIn:    serial@ff000000Out:   serial@ff000000Err:   serial@ff000000
> > Bootmode: JTAG_MODE
> > Net:
> > ZYNQ GEM: ff0c0000, mdio bus ff0c0000, phyaddr 1, interface rgmii-id
> >
> > Warning: ethernet@ff0c0000 (eth0) using random MAC address - 72:1e:d7:a9:9b:1a
> > eth0: ethernet@ff0c0000Get shared mii bus on ethernet@ff0d0000
> >
> > ZYNQ GEM: ff0d0000, mdio bus ff0c0000, phyaddr 2, interface rgmii-id
> >
> > Warning: ethernet@ff0d0000 (eth1) using random MAC address - da:67:b7:c3:2f:ca
> > , eth1: ethernet@ff0d0000
> > Warning: ethernet@ff0d0000 (eth1) using random MAC address - da:67:b7:c3:2f:ca, eth1:
> > ethernet@ff0d0000arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> > Cannot persist EFI variables without system partition
> > Missing TPMv2 device for EFI_TCG_PROTOCOL
> > Missing RNG device for EFI_RNG_PROTOCOL
> > Hit any key to stop autoboot: 0
> > Versal> tftpb 0x400000 test_32MB.bin
> > Filename 'test_32MB.bin'.
> > Load address: 0x400000
> > Loading: ##################################################  32 MiB
> > 12.5 MiB/s
> > done
> > Bytes transferred = 33554432 (2000000 hex)
> > Versal> sf probe 0 0 0
> > SF: Detected n25q00a with page size 256 Bytes, erase size 64 KiB, total 128 MiB
> > Versal> sf erase 0x0 0x2000000
> > SF: 33554432 bytes @ 0x0 Erased: OK
> > Versal> sf write 0x400000 0x0 0x2000000
> > device 0 offset 0x0, size 0x2000000
> > SF: 33554432 bytes @ 0x0 Written: OK
> > Versal> mw.b 0x4000000 0 0x2000000
> > Versal> sf read 0x4000000 0x0 0x2000000
> > device 0 offset 0x0, size 0x2000000
> > SF: 33554432 bytes @ 0x0 Read: OK
> > Versal> cmp.b 0x400000 0x4000000 0x2000000
> > byte at 0x00400000 (0x14) != byte at 0x04000000 (0xc4)
> > Total of 0 byte(s) were the same
> >
> >
> > Versal> mw.b 0x8000 de 0x4000000
> > Versal> sf erase 0x4000000 0x4000000
> > SF: 67108864 bytes @ 0x4000000 Erased: OK
> > Versal> sf write 0x8000 0x4000000 0x4000000
> > device 0 offset 0x4000000, size 0x4000000
> > SF: 67108864 bytes @ 0x4000000 Written: OK
> > Versal> mw.b 0x20000000 0 0x4000000
> > Versal> sf read 0x20000000 0x4000000 0x4000000
> > device 0 offset 0x4000000, size 0x4000000
> > SF: 67108864 bytes @ 0x4000000 Read: OK
> > Versal> cmp.b 0x8000 0x20000000 0x4000000
> > cmp.b 0x8000 0x20000000 0x4000000
> > byte at 0x00008000 (0xde) != byte at 0x20000000 (0xce)
> > Total of 0 byte(s) were the same
> > -------------------------------------------------------------------------------
> >
> >
> > 2). Issue: observed OSPI data integrity failures with MT35XU02G flash:
> >
> > Versal Gen 2 SoC with single mode
> > Versal_net SoC with stacked mode
> >
> > Observed Behavior
> > Data mismatch is observed in single and stacked mode OSPI during large data integrity tests, and full-size data
> > integrity.
> >
> > Working Behavior
> > Full flash size data integrity test is working fine in single mode on vck190 board: Versal platform. tested
> > ospi flashes: gd55lx01g , mt35xu02g
> 
> So, in single mode, gd55lx01g works, but mt35xu02g doesn't, right?
> I tried not to change any device specific logics.
> Same like 1), please narrow down which change in this series breaks it.
> 
> Best Regards,
> Takahiro
> 
> > -------------------------------------------------------------------------------
> > U-Boot 2026.04-rc2-00047-g413f7147bb88 (Feb 18 2026 - 17:30:17 +0530)
> > CPU:   Versal Gen 2
> > Silicon: v1.0
> > Chip:  v1.0
> > Model: X-PRC-11 revA
> > DRAM:  2 GiB
> > optee optee: OP-TEE api uid mismatch
> > NOT_SUPPORTED: A Firmware Framework implementation does not exist
> > EL Level:    EL2
> > Core:  48 devices, 27 uclasses, devicetree: board
> > MMC:   mmc@f1040000: 0
> > Loading Environment from nowhere... OK
> > In:    serial@f1920000
> > Out:   serial@f1920000
> > Err:   serial@f1920000
> > Bootmode: JTAG_MODE
> > Net:
> > ZYNQ GEM: f1a70000, mdio bus f1a70000, phyaddr 1, interface rgmii-idWarning: ethernet@f1a70000 (eth0) using
> > random MAC address - 02:2b:b8:0d:92:33
> > eth0: ethernet@f1a70000
> > Hit any key to stop autoboot: 0
> > versal2> sf probe 0 0 0
> > sf probe 0 0 0
> > SF: Detected mt35xu02g with page size 256 Bytes, erase size 128 KiB, total 256 MiB
> > versal2> mw.b 0x8000 cd 0x10000000
> > versal2> sf erase 0x0 0x10000000
> > SF: 268435456 bytes @ 0x0 Erased: OK
> > versal2> sf write 0x8000 0x0 0x10000000
> > device 0 whole chip
> > SF: 268435456 bytes @ 0x0 Written: OK
> > versal2> mw.b 0x20010000 0 0x10000000
> > versal2> sf read 0x20010000 0x0 0x10000000
> > device 0 whole chip
> > SF: 268435456 bytes @ 0x0 Read: OK
> > versal2> cmp.b 0x8000 0x20010000 0x10000000
> > cmp.b 0x8000 0x20010000 0x10000000
> > byte at 0x05758240 (0xcd) != byte at 0x25760240 (0x0)
> > Total of 91554368 byte(s) were the same
> >
> > Versal NET> sf probe 0 0 0
> > SF: Detected mt35xu02g with page size 256 Bytes, erase size 128 KiB, total 512 MiB
> > Versal NET> mw.b 0x8000 cd 0x20000000
> > Versal NET> sf erase 0x0 0x20000000
> > SF: 536870912 bytes @ 0x0 Erased: OK
> > Versal NET> sf write 0x8000 0x0 0x20000000
> > device 0 whole chip
> > SF: 536870912 bytes @ 0x0 Written: OK
> > Versal NET> mw.b 0x20010000 0 0x20000000
> > Versal NET> sf read 0x20010000 0x0 0x20000000
> > device 0 whole chip
> > SF: 536870912 bytes @ 0x0 Read: OK
> > Versal NET> cmp.b 0x8000 0x20010000 0x20000000
> > cmp.b 0x8000 0x20010000 0x20000000
> > byte at 0x00008000 (0xcd) != byte at 0x20010000 (0x0)
> > Total of 0 byte(s) were the same
> > -------------------------------------------------------------------------------
> >
> > Regards
> > Padmarao
> >
> > > From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Begari, Padmarao
> > > Sent: Tuesday, December 16, 2025 7:16 PM
> > > To: Takahiro.Kuwano@infineon.com; u-boot@lists.denx.de; Tudor Ambarus
> > > <tudor.ambarus@linaro.org>
> > > Cc: Jagan Teki <jagan@amarulasolutions.com>; Simek, Michal
> > > <michal.simek@amd.com>; Tom Rini <trini@konsulko.com>; Erkiaga Elorza, Ibai
> > > <ibai.erkiaga-elorza@amd.com>; Vignesh R <vigneshr@ti.com>; Kummari, Prasad
> > > <Prasad.Kummari@amd.com>; Marek Vasut <marek.vasut+renesas@mailbox.org>;
> > > Mutya, Havish <havish.mutya@amd.com>; Ashok Reddy Soma
> > > <ashok.reddy.soma@amd.com>; Venkatesh Yadav Abbarapu
> > > <venkatesh.abbarapu@amd.com>; Daassi Bacem <Bacem.Daassi@infineon.com>;
> > > Shinsuke Okada <Shinsuke.Okada@infineon.com>; Hiroyuki Saito
> > > <Hiroyuki.Saito2@infineon.com>; Takahiro Kuwano <tkuw584924@gmail.com>
> > > Subject: RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
> > >
> > >
> > > Hi Takahiro Kuwano,
> > >
> > > Apologies for the delay in responding and thank you for sending this patch series.
> > > Since the changes are related to our AMD stacked and parallel configurations, we’ll
> > > look into it.
> > >
> > > Thanks & Regards
> > > Padmarao
> > >
> > > > -----Original Message-----
> > > > From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Takahiro
> > > > Kuwano via
> > > > B4 Relay
> > > > Sent: Wednesday, November 19, 2025 10:43 AM
> > > > To: u-boot@lists.denx.de; Tudor Ambarus <tudor.ambarus@linaro.org>
> > > > Cc: Jagan Teki <jagan@amarulasolutions.com>; Simek, Michal
> > > > <michal.simek@amd.com>; Tom Rini <trini@konsulko.com>; Erkiaga Elorza,
> > > > Ibai <ibai.erkiaga-elorza@amd.com>; Vignesh R <vigneshr@ti.com>;
> > > > Kummari, Prasad <Prasad.Kummari@amd.com>; Marek Vasut
> > > > <marek.vasut+renesas@mailbox.org>; Mutya, Havish
> > > > <havish.mutya@amd.com>; Ashok Reddy Soma <ashok.reddy.soma@amd.com>;
> > > > Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>; Daassi Bacem
> > > > <Bacem.Daassi@infineon.com>; Shinsuke Okada
> > > > <Shinsuke.Okada@infineon.com>; Hiroyuki Saito
> > > > <Hiroyuki.Saito2@infineon.com>; Takahiro Kuwano
> > > > <tkuw584924@gmail.com>; Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > > > Subject: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support
> > > > from core
> > > >
> > > > This series suggests to isolate stacked/parallel support from
> > > > spi-nor-core by moving that to SPI controllers and new modules under mtd/spi.
> > > >
> > > > The patchset mainly focuses on removing references to stacked/parallel
> > > > related items from core. The stacked/parallel support logic itself may
> > > > have rooms to improve. Rework or further cleanup in stacked/parallel
> > > > support would be done by other patches after this series is applied.
> > > >
> > > > Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > > > ---
> > > > Takahiro Kuwano (11):
> > > >       spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe()
> > > >       spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag.
> > > >       spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode
> > > >       spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe()
> > > >       spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag.
> > > >       spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode
> > > >       mtd: spi-nor: Migrate stacked/parallel part to new modules
> > > >       mtd: spi-nor: stacked: Cleanup stacked/parallel flags
> > > >       mtd: spi-nor: parallel: Cleanup stacked/parallel flags
> > > >       mtd: spi-nor: Revert stacked/parallel related commits
> > > >       mtd: spi-nor: Call stacked/parallel post init fixups
> > > >
> > > >  drivers/mtd/spi/Makefile       |   4 +
> > > >  drivers/mtd/spi/parallel.c     | 412
> > > > ++++++++++++++++++++++++++++++++++++++++
> > > >  drivers/mtd/spi/sf_internal.h  |  18 ++
> > > > drivers/mtd/spi/spi-nor-core.c | 422
> > > > +++++++----------------------------------
> > > >  drivers/mtd/spi/stacked.c      | 389
> > > > +++++++++++++++++++++++++++++++++++++
> > > >  drivers/spi/zynq_qspi.c        |  47 +++--
> > > >  drivers/spi/zynqmp_gqspi.c     |  55 ++++--
> > > >  include/linux/mtd/spi-nor.h    |  10 -
> > > >  include/spi.h                  |   2 -
> > > >  9 files changed, 973 insertions(+), 386 deletions(-)
> > > > ---
> > > > base-commit: e2d51f8db207f7db70dd8104fa1da2cffda419f2
> > > > change-id: 20251118-amd-cleanup-c8023872e3cf
> > > >
> > > > Best regards,
> > > > --
> > > > Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > > >


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

* RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
  2026-04-14  4:51       ` Takahiro.Kuwano
@ 2026-04-19 14:27         ` Begari, Padmarao
  0 siblings, 0 replies; 17+ messages in thread
From: Begari, Padmarao @ 2026-04-19 14:27 UTC (permalink / raw)
  To: Takahiro.Kuwano@infineon.com, u-boot@lists.denx.de,
	tudor.ambarus@linaro.org
  Cc: jagan@amarulasolutions.com, Simek, Michal, trini@konsulko.com,
	Erkiaga Elorza, Ibai, vigneshr@ti.com, Kummari, Prasad,
	marek.vasut+renesas@mailbox.org, Mutya, Havish,
	ashok.reddy.soma@amd.com, venkatesh.abbarapu@amd.com,
	Bacem.Daassi@infineon.com, Shinsuke.Okada@infineon.com,
	Hiroyuki.Saito2@infineon.com, Shivendra.Singh@infineon.com

[Public]

Hi Takahiro,

> From: Takahiro.Kuwano@infineon.com <Takahiro.Kuwano@infineon.com>
> Sent: Tuesday, April 14, 2026 10:21 AM
> To: Begari, Padmarao <Padmarao.Begari@amd.com>; u-boot@lists.denx.de;
> tudor.ambarus@linaro.org
> Cc: jagan@amarulasolutions.com; Simek, Michal <michal.simek@amd.com>;
> trini@konsulko.com; Erkiaga Elorza, Ibai <ibai.erkiaga-elorza@amd.com>;
> vigneshr@ti.com; Kummari, Prasad <Prasad.Kummari@amd.com>;
> marek.vasut+renesas@mailbox.org; Mutya, Havish <havish.mutya@amd.com>;
> ashok.reddy.soma@amd.com; venkatesh.abbarapu@amd.com;
> Bacem.Daassi@infineon.com; Shinsuke.Okada@infineon.com;
> Hiroyuki.Saito2@infineon.com; Shivendra.Singh@infineon.com
> Subject: RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core
>
> Hi Padmarao and AMD team,
>
> Could you please help to narrow down the issues?
>
> I was acknowledged a bug in spi-nor-core [1]. It would be better to fix it in a series of
> 'sync to Linux' patches after isolation of stacked/parallel, rather than patching on top
> of that.
>
Yes, it should sync with Linux after isolation of stacked/parallel.

> As discussed in [2], SPI-NOR subsystem in u-boot has not been maintained long
> time. Generic SPI-NOR driver introduced in Linux needs to be ported into u-boot to
> mitigate growing device ID table. Isolation of stacked/parallel is necessary to move
> forward.
>
> Now stacked memories support is available in Linux [3] with different approach from
> the one in u-boot. Isolation is also needed as the first step to adapt the Linux's
> approach to u-boot.

The Linux stacked approach is based on the MTD framework, not the SF framework. I am working on adapting the Linux approach in our AMD internal U-Boot, and internal regression testing is currently in progress on our platforms. I will send the patches soon.

Regards
Padmarao
>
> [1] https://lore.kernel.org/u-
> boot/683be5a32ef345229d54a68ea67fe64c@infineon.com/
> [2] https://lore.kernel.org/u-boot/20260213164607.GI2747538@bill-the-cat/#t
> [3] https://lore.kernel.org/linux-mtd/20260204-mtd-virt-concat-v17-0-
> 5e98239bb55b@bootlin.com/
>
> Thanks,
> Takahiro
>
> >
> > > Hi Takahiro Kuwano,
> > Hi
> >
> > >
> > > We have tested your patches with upstream u-boot and found issues
> > > with both QSPI and OSPI flashes. Below are results, 1 for QSPI and 2 for OSPI.
> > >
> > Thanks for your help!
> >
> > > 1). Issue : observed with QSPI flash's operating in single mode.
> > > tested below flashes
> > >
> > > n25q00a on VCK190
> > > mt25qu512a on ZCU102
> > >
> > > Observed Behavior:
> > > Data mismatch is observed in single‑mode QSPI during partial data integrity
> tests, such as:
> > > 9‑byte test
> > > 32‑byte test
> > > 32 MB test , etc.,
> > > The data written to flash does not match the data read back when compared
> byte‑by‑byte.
> > >
> > > Working Behavior
> > > Full flash size data integrity test is working fine in single mode
> > > also Dual‑mode QSPI tests working fine .
> > > The issue is reproducible only in single‑mode QSPI partial data
> > > integrity tests
> > >
> > This series tries to keep single-mode QSPI unchanged.
> > Could you please narrow down which change in series breaks it?
> >
> > > --------------------------------------------------------------------
> > > ----------- U-Boot 2026.04-rc2-00046-g967458518770 (Feb 18 2026 -
> > > 16:18:41 +0530)
> > >
> > > CPU:   Versal
> > > Silicon: v2
> > > Chip:  v2
> > > CPU:   VersalSilicon: v2Chip:  v2Model: Xilinx Versal vck190 Eval board revA
> (QSPI)
> > > DRAM:  2 GiB (total 8 GiB)
> > > EL Level: EL2
> > > Multiboot: 0
> > > Core:  41 devices, 24 uclasses, devicetree: board
> > > MMC:   arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> > > arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> > > mmc@f1050000 - probe failed: -110
> > > arasan_sdhci mmc@f1050000: Sdhci card detect state not stable
> > >
> > > Loading Environment from nowhere... OK
> > > In:    serial@ff000000
> > > Out:   serial@ff000000
> > > Loading Environment from nowhere... OKIn:    serial@ff000000Out:
> serial@ff000000Err:   serial@ff000000
> > > Bootmode: JTAG_MODE
> > > Net:
> > > ZYNQ GEM: ff0c0000, mdio bus ff0c0000, phyaddr 1, interface rgmii-id
> > >
> > > Warning: ethernet@ff0c0000 (eth0) using random MAC address -
> > > 72:1e:d7:a9:9b:1a
> > > eth0: ethernet@ff0c0000Get shared mii bus on ethernet@ff0d0000
> > >
> > > ZYNQ GEM: ff0d0000, mdio bus ff0c0000, phyaddr 2, interface rgmii-id
> > >
> > > Warning: ethernet@ff0d0000 (eth1) using random MAC address -
> > > da:67:b7:c3:2f:ca , eth1: ethernet@ff0d0000
> > > Warning: ethernet@ff0d0000 (eth1) using random MAC address -
> da:67:b7:c3:2f:ca, eth1:
> > > ethernet@ff0d0000arasan_sdhci mmc@f1050000: Sdhci card detect state
> > > not stable Cannot persist EFI variables without system partition
> > > Missing TPMv2 device for EFI_TCG_PROTOCOL Missing RNG device for
> > > EFI_RNG_PROTOCOL Hit any key to stop autoboot: 0
> > > Versal> tftpb 0x400000 test_32MB.bin
> > > Filename 'test_32MB.bin'.
> > > Load address: 0x400000
> > > Loading: ##################################################  32 MiB
> > > 12.5 MiB/s
> > > done
> > > Bytes transferred = 33554432 (2000000 hex)
> > > Versal> sf probe 0 0 0
> > > SF: Detected n25q00a with page size 256 Bytes, erase size 64 KiB,
> > > total 128 MiB
> > > Versal> sf erase 0x0 0x2000000
> > > SF: 33554432 bytes @ 0x0 Erased: OK
> > > Versal> sf write 0x400000 0x0 0x2000000
> > > device 0 offset 0x0, size 0x2000000
> > > SF: 33554432 bytes @ 0x0 Written: OK
> > > Versal> mw.b 0x4000000 0 0x2000000
> > > Versal> sf read 0x4000000 0x0 0x2000000
> > > device 0 offset 0x0, size 0x2000000
> > > SF: 33554432 bytes @ 0x0 Read: OK
> > > Versal> cmp.b 0x400000 0x4000000 0x2000000
> > > byte at 0x00400000 (0x14) != byte at 0x04000000 (0xc4) Total of 0
> > > byte(s) were the same
> > >
> > >
> > > Versal> mw.b 0x8000 de 0x4000000
> > > Versal> sf erase 0x4000000 0x4000000
> > > SF: 67108864 bytes @ 0x4000000 Erased: OK
> > > Versal> sf write 0x8000 0x4000000 0x4000000
> > > device 0 offset 0x4000000, size 0x4000000
> > > SF: 67108864 bytes @ 0x4000000 Written: OK
> > > Versal> mw.b 0x20000000 0 0x4000000
> > > Versal> sf read 0x20000000 0x4000000 0x4000000
> > > device 0 offset 0x4000000, size 0x4000000
> > > SF: 67108864 bytes @ 0x4000000 Read: OK
> > > Versal> cmp.b 0x8000 0x20000000 0x4000000
> > > cmp.b 0x8000 0x20000000 0x4000000
> > > byte at 0x00008000 (0xde) != byte at 0x20000000 (0xce) Total of 0
> > > byte(s) were the same
> > > --------------------------------------------------------------------
> > > -----------
> > >
> > >
> > > 2). Issue: observed OSPI data integrity failures with MT35XU02G flash:
> > >
> > > Versal Gen 2 SoC with single mode
> > > Versal_net SoC with stacked mode
> > >
> > > Observed Behavior
> > > Data mismatch is observed in single and stacked mode OSPI during
> > > large data integrity tests, and full-size data integrity.
> > >
> > > Working Behavior
> > > Full flash size data integrity test is working fine in single mode
> > > on vck190 board: Versal platform. tested ospi flashes: gd55lx01g ,
> > > mt35xu02g
> >
> > So, in single mode, gd55lx01g works, but mt35xu02g doesn't, right?
> > I tried not to change any device specific logics.
> > Same like 1), please narrow down which change in this series breaks it.
> >
> > Best Regards,
> > Takahiro
> >
> > > --------------------------------------------------------------------
> > > ----------- U-Boot 2026.04-rc2-00047-g413f7147bb88 (Feb 18 2026 -
> > > 17:30:17 +0530)
> > > CPU:   Versal Gen 2
> > > Silicon: v1.0
> > > Chip:  v1.0
> > > Model: X-PRC-11 revA
> > > DRAM:  2 GiB
> > > optee optee: OP-TEE api uid mismatch
> > > NOT_SUPPORTED: A Firmware Framework implementation does not exist
> > > EL Level:    EL2
> > > Core:  48 devices, 27 uclasses, devicetree: board
> > > MMC:   mmc@f1040000: 0
> > > Loading Environment from nowhere... OK
> > > In:    serial@f1920000
> > > Out:   serial@f1920000
> > > Err:   serial@f1920000
> > > Bootmode: JTAG_MODE
> > > Net:
> > > ZYNQ GEM: f1a70000, mdio bus f1a70000, phyaddr 1, interface
> > > rgmii-idWarning: ethernet@f1a70000 (eth0) using random MAC address -
> > > 02:2b:b8:0d:92:33
> > > eth0: ethernet@f1a70000
> > > Hit any key to stop autoboot: 0
> > > versal2> sf probe 0 0 0
> > > sf probe 0 0 0
> > > SF: Detected mt35xu02g with page size 256 Bytes, erase size 128 KiB,
> > > total 256 MiB
> > > versal2> mw.b 0x8000 cd 0x10000000
> > > versal2> sf erase 0x0 0x10000000
> > > SF: 268435456 bytes @ 0x0 Erased: OK
> > > versal2> sf write 0x8000 0x0 0x10000000
> > > device 0 whole chip
> > > SF: 268435456 bytes @ 0x0 Written: OK
> > > versal2> mw.b 0x20010000 0 0x10000000 sf read 0x20010000 0x0
> > > versal2> 0x10000000
> > > device 0 whole chip
> > > SF: 268435456 bytes @ 0x0 Read: OK
> > > versal2> cmp.b 0x8000 0x20010000 0x10000000
> > > cmp.b 0x8000 0x20010000 0x10000000
> > > byte at 0x05758240 (0xcd) != byte at 0x25760240 (0x0) Total of
> > > 91554368 byte(s) were the same
> > >
> > > Versal NET> sf probe 0 0 0
> > > SF: Detected mt35xu02g with page size 256 Bytes, erase size 128 KiB,
> > > total 512 MiB Versal NET> mw.b 0x8000 cd 0x20000000 Versal NET> sf
> > > erase 0x0 0x20000000
> > > SF: 536870912 bytes @ 0x0 Erased: OK Versal NET> sf write 0x8000 0x0
> > > 0x20000000 device 0 whole chip
> > > SF: 536870912 bytes @ 0x0 Written: OK Versal NET> mw.b 0x20010000 0
> > > 0x20000000 Versal NET> sf read 0x20010000 0x0 0x20000000 device 0
> > > whole chip
> > > SF: 536870912 bytes @ 0x0 Read: OK
> > > Versal NET> cmp.b 0x8000 0x20010000 0x20000000 cmp.b 0x8000
> > > 0x20010000 0x20000000 byte at 0x00008000 (0xcd) != byte at
> > > 0x20010000 (0x0) Total of 0 byte(s) were the same
> > > --------------------------------------------------------------------
> > > -----------
> > >
> > > Regards
> > > Padmarao
> > >
> > > > From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Begari,
> > > > Padmarao
> > > > Sent: Tuesday, December 16, 2025 7:16 PM
> > > > To: Takahiro.Kuwano@infineon.com; u-boot@lists.denx.de; Tudor
> > > > Ambarus <tudor.ambarus@linaro.org>
> > > > Cc: Jagan Teki <jagan@amarulasolutions.com>; Simek, Michal
> > > > <michal.simek@amd.com>; Tom Rini <trini@konsulko.com>; Erkiaga
> > > > Elorza, Ibai <ibai.erkiaga-elorza@amd.com>; Vignesh R
> > > > <vigneshr@ti.com>; Kummari, Prasad <Prasad.Kummari@amd.com>; Marek
> > > > Vasut <marek.vasut+renesas@mailbox.org>;
> > > > Mutya, Havish <havish.mutya@amd.com>; Ashok Reddy Soma
> > > > <ashok.reddy.soma@amd.com>; Venkatesh Yadav Abbarapu
> > > > <venkatesh.abbarapu@amd.com>; Daassi Bacem
> > > > <Bacem.Daassi@infineon.com>; Shinsuke Okada
> > > > <Shinsuke.Okada@infineon.com>; Hiroyuki Saito
> > > > <Hiroyuki.Saito2@infineon.com>; Takahiro Kuwano
> > > > <tkuw584924@gmail.com>
> > > > Subject: RE: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel
> > > > support from core
> > > >
> > > >
> > > > Hi Takahiro Kuwano,
> > > >
> > > > Apologies for the delay in responding and thank you for sending this patch
> series.
> > > > Since the changes are related to our AMD stacked and parallel
> > > > configurations, we’ll look into it.
> > > >
> > > > Thanks & Regards
> > > > Padmarao
> > > >
> > > > > -----Original Message-----
> > > > > From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of
> > > > > Takahiro Kuwano via
> > > > > B4 Relay
> > > > > Sent: Wednesday, November 19, 2025 10:43 AM
> > > > > To: u-boot@lists.denx.de; Tudor Ambarus
> > > > > <tudor.ambarus@linaro.org>
> > > > > Cc: Jagan Teki <jagan@amarulasolutions.com>; Simek, Michal
> > > > > <michal.simek@amd.com>; Tom Rini <trini@konsulko.com>; Erkiaga
> > > > > Elorza, Ibai <ibai.erkiaga-elorza@amd.com>; Vignesh R
> > > > > <vigneshr@ti.com>; Kummari, Prasad <Prasad.Kummari@amd.com>;
> > > > > Marek Vasut <marek.vasut+renesas@mailbox.org>; Mutya, Havish
> > > > > <havish.mutya@amd.com>; Ashok Reddy Soma
> > > > > <ashok.reddy.soma@amd.com>; Venkatesh Yadav Abbarapu
> > > > > <venkatesh.abbarapu@amd.com>; Daassi Bacem
> > > > > <Bacem.Daassi@infineon.com>; Shinsuke Okada
> > > > > <Shinsuke.Okada@infineon.com>; Hiroyuki Saito
> > > > > <Hiroyuki.Saito2@infineon.com>; Takahiro Kuwano
> > > > > <tkuw584924@gmail.com>; Takahiro Kuwano
> > > > > <Takahiro.Kuwano@infineon.com>
> > > > > Subject: [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel
> > > > > support from core
> > > > >
> > > > > This series suggests to isolate stacked/parallel support from
> > > > > spi-nor-core by moving that to SPI controllers and new modules under
> mtd/spi.
> > > > >
> > > > > The patchset mainly focuses on removing references to
> > > > > stacked/parallel related items from core. The stacked/parallel
> > > > > support logic itself may have rooms to improve. Rework or
> > > > > further cleanup in stacked/parallel support would be done by other patches
> after this series is applied.
> > > > >
> > > > > Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > > > > ---
> > > > > Takahiro Kuwano (11):
> > > > >       spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe()
> > > > >       spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag.
> > > > >       spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode
> > > > >       spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe()
> > > > >       spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag.
> > > > >       spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode
> > > > >       mtd: spi-nor: Migrate stacked/parallel part to new modules
> > > > >       mtd: spi-nor: stacked: Cleanup stacked/parallel flags
> > > > >       mtd: spi-nor: parallel: Cleanup stacked/parallel flags
> > > > >       mtd: spi-nor: Revert stacked/parallel related commits
> > > > >       mtd: spi-nor: Call stacked/parallel post init fixups
> > > > >
> > > > >  drivers/mtd/spi/Makefile       |   4 +
> > > > >  drivers/mtd/spi/parallel.c     | 412
> > > > > ++++++++++++++++++++++++++++++++++++++++
> > > > >  drivers/mtd/spi/sf_internal.h  |  18 ++
> > > > > drivers/mtd/spi/spi-nor-core.c | 422
> > > > > +++++++----------------------------------
> > > > >  drivers/mtd/spi/stacked.c      | 389
> > > > > +++++++++++++++++++++++++++++++++++++
> > > > >  drivers/spi/zynq_qspi.c        |  47 +++--
> > > > >  drivers/spi/zynqmp_gqspi.c     |  55 ++++--
> > > > >  include/linux/mtd/spi-nor.h    |  10 -
> > > > >  include/spi.h                  |   2 -
> > > > >  9 files changed, 973 insertions(+), 386 deletions(-)
> > > > > ---
> > > > > base-commit: e2d51f8db207f7db70dd8104fa1da2cffda419f2
> > > > > change-id: 20251118-amd-cleanup-c8023872e3cf
> > > > >
> > > > > Best regards,
> > > > > --
> > > > > Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> > > > >


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

end of thread, other threads:[~2026-04-19 14:27 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-19  5:12 [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 01/11] spi: zynqmp-gqspi: Set priv->is_parallel in child_pre_probe() Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 02/11] spi: zynqmp_gqspi: Remove reference to SPI_XFER_LOWER flag Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 03/11] spi: zynqmp_gqspi: Read two bytes of SR and FSR in parallel mode Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 04/11] spi: zynq-qspi: Set priv->is_parallel/stacked in child_pre_probe() Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 05/11] spi: zynq_qspi: Remove reference to SPI_XFER_LOWER flag Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 06/11] spi: zynq_qspi: Read two bytes of SR and FSR in parallel mode Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 07/11] mtd: spi-nor: Migrate stacked/parallel part to new modules Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 08/11] mtd: spi-nor: stacked: Cleanup stacked/parallel flags Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 09/11] mtd: spi-nor: parallel: " Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 10/11] mtd: spi-nor: Revert stacked/parallel related commits Takahiro Kuwano via B4 Relay
2025-11-19  5:13 ` [PATCH 11/11] mtd: spi-nor: Call stacked/parallel post init fixups Takahiro Kuwano via B4 Relay
2025-12-16 13:45 ` [PATCH 00/11] mtd: spi-nor: Isolate stacked/parallel support from core Begari, Padmarao
2026-02-23 14:12   ` Begari, Padmarao
2026-02-24  8:04     ` Takahiro.Kuwano
2026-04-14  4:51       ` Takahiro.Kuwano
2026-04-19 14:27         ` Begari, Padmarao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox