mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] mtd: spi-nor: do not issue the legacy RDCR (0x35) in 8D-8D-8D mode
@ 2026-09-28 12:34 haibo.chen
  2026-09-28 13:01 ` Miquel Raynal
  0 siblings, 1 reply; 2+ messages in thread
From: haibo.chen @ 2026-09-28 12:34 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra
  Cc: linux-mtd, linux-kernel, michael, imx, Haibo Chen

From: Haibo Chen <haibo.chen@nxp.com>

spi_nor_init_default_params() unconditionally sets opcodes.read_sr2 to
the legacy RDCR opcode (0x35) for every flash. This default is meant for
the (x)STR quad-enable case (QE bit in SR2 bit1, read back via 0x35);
it was never intended for 8D-8D-8D. During spi_nor_init(),
spi_nor_cache_sr_lock_bits() reads SR1 and SR2 to seed the debugfs lock
bit cache, and this runs after the flash has already been switched to
its runtime protocol - including 8D-8D-8D (OPI/DOPI) mode.

RDCR (0x35) is the single-byte "read SR2/configuration register" opcode
and is only meaningful in the (x)STR protocols. In 8D-8D-8D mode a flash
exposes its second status/configuration register through a
vendor-specific indirect register space, or does not expose it at all,
so issuing a bare 0x35 is an unsupported command. The flash drives no
data, the controller RX FIFO stays empty and the register read times
out. On i.MX FlexSPI this is seen as a -ETIMEDOUT and a controller
WARN() during probe, e.g. with a Micron MT35xU (2c 5b 1b) and a
Macronix (c2 ..) octal flash, killing the spi-nor probe.

This is not a per-vendor quirk: it affects any octal-DTR flash that
never got a dedicated 8D-capable SR2 read opcode installed by its
manufacturer driver. Guard the read in the core instead of patching
each vendor: in spi_nor_read_sr2(), when the current register protocol
is 8D-8D-8D and read_sr2 is still the default RDCR, return -EOPNOTSUPP
rather than sending 0x35. spi_nor_read_sr2_careful() (the swp.c early
init user) now routes through spi_nor_read_sr2() and treats -EOPNOTSUPP
as "no SR2", using the QE-based guess so the lock bit caching does not
fail on OPI/DOPI flashes.

A manufacturer driver that provides a real 8D-capable SR2 read opcode
(anything other than the default RDCR) is unaffected by this guard.

Assisted-by: LLM
Fixes: b7b63475903c ("mtd: spi-nor: Create a local SR cache")
Fixes: 63489002d397 ("mtd: spi-nor: Refactor Read Status/Write Status support")
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
 drivers/mtd/spi-nor/core.c | 15 +++++++++++++++
 drivers/mtd/spi-nor/swp.c  | 21 ++++++++++++++-------
 2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 90524c58602e1c27cd83951ab0cdd3669a2ebfd6..9e176777fae35d815db53fda0056e40ad986a208 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -844,6 +844,21 @@ int spi_nor_read_sr2(struct spi_nor *nor, u8 *sr2)
 	if (!params->opcodes.read_sr2)
 		return -EINVAL;
 
+	/*
+	 * RDCR (0x35) is the legacy single-byte "read SR2/configuration
+	 * register" opcode and is only meaningful in the (x)STR protocols. In
+	 * 8D-8D-8D (OPI/DOPI) mode flashes expose their second status or
+	 * configuration register through a vendor-specific indirect register
+	 * space, or do not expose it at all, so issuing a bare 0x35 is an
+	 * unsupported command: the flash drives no data and the controller
+	 * read times out. Unless a manufacturer driver installed a dedicated
+	 * 8D-capable read_sr2 opcode (i.e. something other than the default
+	 * RDCR), skip the SR2 read in 8D mode.
+	 */
+	if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR &&
+	    params->opcodes.read_sr2 == SPINOR_OP_RDCR)
+		return -EOPNOTSUPP;
+
 	return spi_nor_read_sr_ll(nor, params->opcodes.read_sr2, sr2, 1);
 }
 
diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c
index 7e667e4ca84d5101471e60bc839b2ecc23958294..f8dea179f09930af76b8026773d8b648e620fa81 100644
--- a/drivers/mtd/spi-nor/swp.c
+++ b/drivers/mtd/spi-nor/swp.c
@@ -211,19 +211,26 @@ static int spi_nor_read_sr2_careful(struct spi_nor *nor, u8 *sr2)
 	int ret;
 
 	if (params->opcodes.read_sr2) {
-		ret = spi_nor_read_sr_ll(nor, params->opcodes.read_sr2, sr2, 1);
-		if (ret)
+		ret = spi_nor_read_sr2(nor, sr2);
+		/*
+		 * spi_nor_read_sr2() returns -EOPNOTSUPP when the only SR2
+		 * read opcode is the legacy RDCR (0x35), which cannot be
+		 * issued in 8D-8D-8D mode. In that case use the QE-based guess
+		 * below instead, so early init (SR lock bit caching) does not
+		 * fail on OPI/DOPI flashes.
+		 */
+		if (ret != -EOPNOTSUPP)
 			return ret;
-	} else if ((spi_nor_get_protocol_width(nor->read_proto) == 4 ||
-		   spi_nor_get_protocol_width(nor->write_proto) == 4) &&
-		   nor->params->quad_enable) {
+	}
+
+	if ((spi_nor_get_protocol_width(nor->read_proto) == 4 ||
+	     spi_nor_get_protocol_width(nor->write_proto) == 4) &&
+	    nor->params->quad_enable) {
 		/*
 		 * Make sure the QE bit is persistently kept. qe_mask[1] will be
 		 * 0 if the QE bit is in SR1.
 		 */
 		*sr2 = params->qe_mask[1];
-	} else {
-		return 0;
 	}
 
 	return 0;

---
base-commit: ba52b770f89bd2f3771b98edb92c4fde68ca8cc4
change-id: 20260928-spi-nor-fix-eb7ebe22a740

Best regards,
-- 
Haibo Chen <haibo.chen@nxp.com>


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

* Re: [PATCH] mtd: spi-nor: do not issue the legacy RDCR (0x35) in 8D-8D-8D mode
  2026-09-28 12:34 [PATCH] mtd: spi-nor: do not issue the legacy RDCR (0x35) in 8D-8D-8D mode haibo.chen
@ 2026-09-28 13:01 ` Miquel Raynal
  0 siblings, 0 replies; 2+ messages in thread
From: Miquel Raynal @ 2026-09-28 13:01 UTC (permalink / raw)
  To: haibo.chen
  Cc: Pratyush Yadav, Michael Walle, Takahiro Kuwano,
	Richard Weinberger, Vignesh Raghavendra, linux-mtd, linux-kernel,
	michael, imx, Haibo Chen

Hi Haibo,

> +	/*
> +	 * RDCR (0x35) is the legacy single-byte "read SR2/configuration
> +	 * register" opcode and is only meaningful in the (x)STR protocols. In
> +	 * 8D-8D-8D (OPI/DOPI) mode flashes expose their second status or
> +	 * configuration register through a vendor-specific indirect register
> +	 * space, or do not expose it at all, so issuing a bare 0x35 is an
> +	 * unsupported command: the flash drives no data and the controller
> +	 * read times out. Unless a manufacturer driver installed a dedicated
> +	 * 8D-capable read_sr2 opcode (i.e. something other than the default
> +	 * RDCR), skip the SR2 read in 8D mode.
> +	 */
> +	if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR &&
> +	    params->opcodes.read_sr2 == SPINOR_OP_RDCR)
> +		return -EOPNOTSUPP;

I believe this is not the correct solution. The correct solution would
be to clear opcodes.read_sr2 for ODTR flashes by default (if that's
really a default?) and then handle the read_sr2() error correctly in the
debugfs caching.

Also please tell your LLM not to put huge comments like that to explain
what is already in the commit log.

Thanks,
Miquèl

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

end of thread, other threads:[~2026-09-28 13:01 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-28 12:34 [PATCH] mtd: spi-nor: do not issue the legacy RDCR (0x35) in 8D-8D-8D mode haibo.chen
2026-09-28 13:01 ` Miquel Raynal

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

all inboxes | Powered by JetHome®