[PATCH 2/5] mtd: spi-nor: Add support for the new JESD216 rev F QER field
From: Miquel Raynal
Date: Fri May 29 2026 - 12:38:10 EST
Revision F of the JEDEC JESD216 standard includes yet another
supported setting in the QER 3-bit bitfield: 110b.
This setting implies that the QE bit is bit 1 of SR2 (which is an
already supported case) but this time it makes it very clear that both
reading and writing to SR2 is supported, but not with the usual
opcodes. The write operation uses an alternate WRSR2 opcode:
0x31 (instead of 0x3E) and both the reads and writes manipulate a single
register at a time.
Signed-off-by: Miquel Raynal <miquel.raynal@xxxxxxxxxxx>
---
drivers/mtd/spi-nor/sfdp.c | 9 +++++++++
drivers/mtd/spi-nor/sfdp.h | 8 ++++++++
include/linux/mtd/spi-nor.h | 1 +
3 files changed, 18 insertions(+)
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 23b809cc958f..04580f78b62b 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -626,6 +626,15 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
params->qe_mask[1] = BIT(1);
break;
+ case BFPT_DWORD15_QER_SR2_BIT1_1B:
+ nor->flags &= ~SNOR_F_HAS_16BIT_SR;
+ params->qe_mask[0] = 0;
+ params->qe_mask[1] = BIT(1);
+ params->read_srs_opcode = 0;
+ params->write_srs_opcode = 0;
+ params->write_sr2_opcode = SPINOR_OP_WRSR2_ALT;
+ break;
+
default:
dev_dbg(nor->dev, "BFPT QER reserved value used\n");
break;
diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h
index f74a0eb339ea..7e52e00cbae0 100644
--- a/drivers/mtd/spi-nor/sfdp.h
+++ b/drivers/mtd/spi-nor/sfdp.h
@@ -12,6 +12,7 @@
#define SFDP_JESD216_MINOR 0
#define SFDP_JESD216A_MINOR 5
#define SFDP_JESD216B_MINOR 6
+#define SFDP_JESD216F_MINOR 10
/* SFDP DWORDS are indexed from 1 but C arrays are indexed from 0. */
#define SFDP_DWORD(i) ((i) - 1)
@@ -81,6 +82,12 @@ struct sfdp_bfpt {
* instruction 35h. QE is set via Write Status instruction 01h with
* two data bytes where bit 1 of the second byte is one.
* [...]
+ * (from JESD216 rev F)
+ * - 110b: QE is bit 1 of status register 2. Status register 1 is read using
+ * Read Status instruction 05h. Status register2 is read using
+ * instruction 35h, and status register 3 is read using instruction 15h.
+ * QE is set via Write Status Register instruction 31h with one data
+ * byte.
*/
#define BFPT_DWORD15_QER_MASK GENMASK(22, 20)
#define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */
@@ -89,6 +96,7 @@ struct sfdp_bfpt {
#define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20)
#define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20)
#define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */
+#define BFPT_DWORD15_QER_SR2_BIT1_1B (0x6UL << 20) /* Winbond */
#define BFPT_DWORD16_EN4B_MASK GENMASK(31, 24)
#define BFPT_DWORD16_EN4B_ALWAYS_4B BIT(30)
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index f0b5a1989881..3a55d76ea77d 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -25,6 +25,7 @@
#define SPINOR_OP_WRSR 0x01 /* Write status register 1 */
#define SPINOR_OP_RDSR2 0x3f /* Read status register 2 */
#define SPINOR_OP_WRSR2 0x3e /* Write status register 2 */
+#define SPINOR_OP_WRSR2_ALT 0x31 /* Write status register 2 (alternative) */
#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */
--
2.53.0