Linux-mtd Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization
@ 2026-07-03 14:29 Michael Walle
  2026-07-03 14:29 ` [PATCH v1 1/8] mtd: spi-nor: spansion: s25fl256s0: remove SKIP_SFDP flag Michael Walle
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Michael Walle @ 2026-07-03 14:29 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus
  Cc: linux-mtd, Cheng Ming Lin, linux-kernel

Try to simplify the flash initialization and get rid of the legacy
handling. As default, all the flags of the in-kernel database are
taken and amended with the SFDP data.

This might have the consequence that all the flashes now get a
RDSFPD opcode which might be an unknown opcode. But that was already
the case for any flashes which were unknown to the linux kernel. So
far, there was not a single complaint. See patch 8 for more
information.

Sashiko found that not everything is rolled back in case of a SFDP
parsing failure. Thus there are now 5 additional patches which will
move the discovered parameters into spi_nor_flash_parameter which is
rolled back. The new rule is now:

  SFDP parsing and the per-flash SFDP fixups must only change the
  spi_nor_flash_parameter data.

changes since the RFC:
 - new patches to address the rollback issue, as pointed out by
   Sashiko
 - remove SKIP_SFDP from kerneldoc, as pointed out by Sashiko
 - mention issuing the potential unsupported RDSFPD command in the
   commit message, as pointed out by Tudor

Michael Walle (8):
  mtd: spi-nor: spansion: s25fl256s0: remove SKIP_SFDP flag
  mtd: spi-nor: don't clear the SNOR_F_4B_OPCODES flag on failure
  mtd: spi-nor: move cmd_ext_type into spi_nor_flash_parameter
  mtd: spi-nor: move flags into spi_nor_flash_parameter
  mtd: spi-nor: move spi_nor_post_bfpt_fixups() into sfdp
  mtd: spi-nor: spansion: s25fs256t: move ARCFN check into .late_init
  mtd: spi-nor: push the rollback mechanism into the sfdp module
  mtd: spi-nor: rework flash parameter initialization

 drivers/mtd/spi-nor/core.c      | 178 +++++++++++---------------------
 drivers/mtd/spi-nor/core.h      |  13 +--
 drivers/mtd/spi-nor/debugfs.c   |   6 +-
 drivers/mtd/spi-nor/macronix.c  |   2 +-
 drivers/mtd/spi-nor/micron-st.c |   8 +-
 drivers/mtd/spi-nor/sfdp.c      |  70 ++++++++++---
 drivers/mtd/spi-nor/spansion.c  |  36 ++++---
 drivers/mtd/spi-nor/swp.c       |  52 ++++++----
 drivers/mtd/spi-nor/winbond.c   |   4 +-
 include/linux/mtd/spi-nor.h     |   4 -
 10 files changed, 185 insertions(+), 188 deletions(-)

-- 
2.47.3


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v1 1/8] mtd: spi-nor: spansion: s25fl256s0: remove SKIP_SFDP flag
  2026-07-03 14:29 [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization Michael Walle
@ 2026-07-03 14:29 ` Michael Walle
  2026-07-03 14:29 ` [PATCH v1 2/8] mtd: spi-nor: don't clear the SNOR_F_4B_OPCODES flag on failure Michael Walle
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Michael Walle @ 2026-07-03 14:29 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus
  Cc: linux-mtd, Cheng Ming Lin, linux-kernel

That flag was added in [1] to not "issue any non supported commands".
But since we now have the generic SFDP driver, we'll issue the RDSFDP
command on most flashes anyway and there was no single complaint. Remove
the only user of this flag so we can rework the parameter initialization
in the core.

[1] https://lore.kernel.org/linux-mtd/20211207140254.87681-13-tudor.ambarus@microchip.com/

Signed-off-by: Michael Walle <mwalle@kernel.org>
Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
---
 drivers/mtd/spi-nor/spansion.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 65227d989de1..092450375d4e 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -868,7 +868,7 @@ static const struct flash_info spansion_nor_parts[] = {
 		.name = "s25fl256s0",
 		.size = SZ_32M,
 		.sector_size = SZ_256K,
-		.no_sfdp_flags = SPI_NOR_SKIP_SFDP | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+		.no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
 		.mfr_flags = USE_CLSR,
 	}, {
 		.id = SNOR_ID(0x01, 0x02, 0x19, 0x4d, 0x00, 0x81),
-- 
2.47.3


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v1 2/8] mtd: spi-nor: don't clear the SNOR_F_4B_OPCODES flag on failure
  2026-07-03 14:29 [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization Michael Walle
  2026-07-03 14:29 ` [PATCH v1 1/8] mtd: spi-nor: spansion: s25fl256s0: remove SKIP_SFDP flag Michael Walle
@ 2026-07-03 14:29 ` Michael Walle
  2026-07-03 14:29 ` [PATCH v1 3/8] mtd: spi-nor: move cmd_ext_type into spi_nor_flash_parameter Michael Walle
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Michael Walle @ 2026-07-03 14:29 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus
  Cc: linux-mtd, Cheng Ming Lin, linux-kernel

This was introduced in commit 548ed6847f530 ("mtd: spi-nor: Add the
SNOR_F_4B_OPCODES flag"). It looks like it was the rollback mechanism if
parsing the SFDP failed, but was setting that flag first. Nowadays, that
flag can only be set if spi_nor_parse_4bait() was successful. IOW, the
flags won't be left in an undefined state if parsing SFDP fails.

Remove the unneeded code to be able to rework spi_nor_init_params().

Signed-off-by: Michael Walle <mwalle@kernel.org>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
---
 drivers/mtd/spi-nor/core.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 4046e137531f..fbf8c2d9c6b5 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3066,10 +3066,8 @@ static void spi_nor_sfdp_init_params_deprecated(struct spi_nor *nor)
 
 	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
 
-	if (spi_nor_parse_sfdp(nor)) {
+	if (spi_nor_parse_sfdp(nor))
 		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
-		nor->flags &= ~SNOR_F_4B_OPCODES;
-	}
 }
 
 /**
-- 
2.47.3


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v1 3/8] mtd: spi-nor: move cmd_ext_type into spi_nor_flash_parameter
  2026-07-03 14:29 [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization Michael Walle
  2026-07-03 14:29 ` [PATCH v1 1/8] mtd: spi-nor: spansion: s25fl256s0: remove SKIP_SFDP flag Michael Walle
  2026-07-03 14:29 ` [PATCH v1 2/8] mtd: spi-nor: don't clear the SNOR_F_4B_OPCODES flag on failure Michael Walle
@ 2026-07-03 14:29 ` Michael Walle
  2026-07-03 14:29 ` [PATCH v1 4/8] mtd: spi-nor: move flags " Michael Walle
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Michael Walle @ 2026-07-03 14:29 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus
  Cc: linux-mtd, Cheng Ming Lin, linux-kernel, Sashiko

Right now the SFDP parsing code is modifying both members of
struct spi_nor_flash_parameter and struct spi_nor. This may lead to
inconsistencies if the parsing fails because only the flash parameters
are rolled back.

To fix this, move cmd_ext_type into the struct spi_nor_flash_parameter.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260601125438.3481722-1-mwalle%40kernel.org?part=3
Signed-off-by: Michael Walle <mwalle@kernel.org>
---
 drivers/mtd/spi-nor/core.c      | 2 +-
 drivers/mtd/spi-nor/core.h      | 2 ++
 drivers/mtd/spi-nor/debugfs.c   | 2 +-
 drivers/mtd/spi-nor/micron-st.c | 2 +-
 drivers/mtd/spi-nor/sfdp.c      | 4 ++--
 include/linux/mtd/spi-nor.h     | 2 --
 6 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index fbf8c2d9c6b5..8ccd7d520791 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -59,7 +59,7 @@
 static u8 spi_nor_get_cmd_ext(const struct spi_nor *nor,
 			      const struct spi_mem_op *op)
 {
-	switch (nor->cmd_ext_type) {
+	switch (nor->params->cmd_ext_type) {
 	case SPI_NOR_EXT_INVERT:
 		return ~op->cmd.opcode;
 
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 2ebc5c3caca1..835076d86e3b 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -370,6 +370,7 @@ struct spi_nor_otp {
  *                      in the array, the higher priority.
  * @page_programs:	page program capabilities ordered by priority: the
  *                      higher index in the array, the higher priority.
+ * @cmd_ext_type:	the command opcode extension type for DTR mode.
  * @erase_map:		the erase map parsed from the SFDP Sector Map Parameter
  *                      Table.
  * @otp:		SPI NOR OTP info.
@@ -399,6 +400,7 @@ struct spi_nor_flash_parameter {
 	struct spi_nor_hwcaps		hwcaps;
 	struct spi_nor_read_command	reads[SNOR_CMD_READ_MAX];
 	struct spi_nor_pp_command	page_programs[SNOR_CMD_PP_MAX];
+	enum spi_nor_cmd_ext		cmd_ext_type;
 
 	struct spi_nor_erase_map        erase_map;
 	struct spi_nor_otp		otp;
diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c
index 090049b67044..dc2ed784f519 100644
--- a/drivers/mtd/spi-nor/debugfs.c
+++ b/drivers/mtd/spi-nor/debugfs.c
@@ -109,7 +109,7 @@ static int spi_nor_params_show(struct seq_file *s, void *data)
 	seq_printf(s, " erase\t\t0x%02x\n", nor->erase_opcode);
 	seq_printf(s, " program\t0x%02x\n", nor->program_opcode);
 
-	switch (nor->cmd_ext_type) {
+	switch (params->cmd_ext_type) {
 	case SPI_NOR_EXT_NONE:
 		str = "none";
 		break;
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index c75b0a1cd567..186362066c6b 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -177,7 +177,7 @@ static int mt35xu512aba_post_sfdp_fixup(struct spi_nor *nor)
 	spi_nor_set_pp_settings(&nor->params->page_programs[SNOR_CMD_PP_8_8_8_DTR],
 				SPINOR_OP_PP_4B, SNOR_PROTO_8_8_8_DTR);
 
-	nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
+	nor->params->cmd_ext_type = SPI_NOR_EXT_REPEAT;
 	nor->params->rdsr_dummy = 8;
 	nor->params->rdsr_addr_nbytes = 0;
 
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 00a66d13cbff..7e44d3c4d89a 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -664,11 +664,11 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 	/* 8D-8D-8D command extension. */
 	switch (bfpt.dwords[SFDP_DWORD(18)] & BFPT_DWORD18_CMD_EXT_MASK) {
 	case BFPT_DWORD18_CMD_EXT_REP:
-		nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
+		params->cmd_ext_type = SPI_NOR_EXT_REPEAT;
 		break;
 
 	case BFPT_DWORD18_CMD_EXT_INV:
-		nor->cmd_ext_type = SPI_NOR_EXT_INVERT;
+		params->cmd_ext_type = SPI_NOR_EXT_INVERT;
 		break;
 
 	case BFPT_DWORD18_CMD_EXT_RES:
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 4b92494827b1..e75c1b4cb4c0 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -366,7 +366,6 @@ struct spi_nor_flash_parameter;
  * @program_opcode:	the program opcode
  * @sst_write_second:	used by the SST write operation
  * @flags:		flag options for the current SPI NOR (SNOR_F_*)
- * @cmd_ext_type:	the command opcode extension type for DTR mode.
  * @read_proto:		the SPI protocol for read operations
  * @write_proto:	the SPI protocol for write operations
  * @reg_proto:		the SPI protocol for read_reg/write_reg/erase operations
@@ -408,7 +407,6 @@ struct spi_nor {
 	enum spi_nor_protocol	reg_proto;
 	bool			sst_write_second;
 	u32			flags;
-	enum spi_nor_cmd_ext	cmd_ext_type;
 	struct sfdp		*sfdp;
 	struct dentry		*debugfs_root;
 	u8			dfs_sr_cache[2];
-- 
2.47.3


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v1 4/8] mtd: spi-nor: move flags into spi_nor_flash_parameter
  2026-07-03 14:29 [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization Michael Walle
                   ` (2 preceding siblings ...)
  2026-07-03 14:29 ` [PATCH v1 3/8] mtd: spi-nor: move cmd_ext_type into spi_nor_flash_parameter Michael Walle
@ 2026-07-03 14:29 ` Michael Walle
  2026-07-03 14:29 ` [PATCH v1 5/8] mtd: spi-nor: move spi_nor_post_bfpt_fixups() into sfdp Michael Walle
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Michael Walle @ 2026-07-03 14:29 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus
  Cc: linux-mtd, Cheng Ming Lin, linux-kernel, Sashiko

Right now the SFDP parsing code is modifying both members of
struct spi_nor_flash_parameter and struct spi_nor. This may lead to
inconsistencies if the parsing fails because only the flash parameters
are rolled back.

To fix this, move the flags into the struct spi_nor_flash_parameter.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260601125438.3481722-1-mwalle%40kernel.org?part=3
Signed-off-by: Michael Walle <mwalle@kernel.org>
---
 drivers/mtd/spi-nor/core.c      | 83 ++++++++++++++++++---------------
 drivers/mtd/spi-nor/core.h      |  2 +
 drivers/mtd/spi-nor/debugfs.c   |  4 +-
 drivers/mtd/spi-nor/macronix.c  |  2 +-
 drivers/mtd/spi-nor/micron-st.c |  6 +--
 drivers/mtd/spi-nor/sfdp.c      | 16 +++----
 drivers/mtd/spi-nor/spansion.c  |  4 +-
 drivers/mtd/spi-nor/swp.c       | 52 +++++++++++++--------
 drivers/mtd/spi-nor/winbond.c   |  4 +-
 include/linux/mtd/spi-nor.h     |  2 -
 10 files changed, 98 insertions(+), 77 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 8ccd7d520791..d5f37b6cd76b 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -83,6 +83,7 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
 			     struct spi_mem_op *op,
 			     const enum spi_nor_protocol proto)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	u8 ext;
 
 	op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(proto);
@@ -116,7 +117,7 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
 		op->cmd.nbytes = 2;
 	}
 
-	if (proto == SNOR_PROTO_8_8_8_DTR && nor->flags & SNOR_F_SWAP16)
+	if (proto == SNOR_PROTO_8_8_8_DTR && params->flags & SNOR_F_SWAP16)
 		op->data.swap16 = true;
 }
 
@@ -633,7 +634,7 @@ int spi_nor_sr_ready(struct spi_nor *nor)
  */
 static bool spi_nor_use_parallel_locking(struct spi_nor *nor)
 {
-	return nor->flags & SNOR_F_RWW;
+	return nor->params->flags & SNOR_F_RWW;
 }
 
 /* Locking helpers for status read operations */
@@ -860,12 +861,13 @@ static int spi_nor_write_sr1_and_check(struct spi_nor *nor, u8 sr1)
  */
 static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	int ret;
 	u8 *sr_cr = nor->bouncebuf;
 	u8 cr_written;
 
 	/* Make sure we don't overwrite the contents of Status Register 2. */
-	if (!(nor->flags & SNOR_F_NO_READ_CR)) {
+	if (!(params->flags & SNOR_F_NO_READ_CR)) {
 		ret = spi_nor_read_cr(nor, &sr_cr[1]);
 		if (ret)
 			return ret;
@@ -906,7 +908,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
 		return -EIO;
 	}
 
-	if (nor->flags & SNOR_F_NO_READ_CR)
+	if (params->flags & SNOR_F_NO_READ_CR)
 		return 0;
 
 	cr_written = sr_cr[1];
@@ -961,7 +963,7 @@ int spi_nor_write_16bit_cr_and_check(struct spi_nor *nor, u8 cr)
 		return -EIO;
 	}
 
-	if (nor->flags & SNOR_F_NO_READ_CR)
+	if (nor->params->flags & SNOR_F_NO_READ_CR)
 		return 0;
 
 	ret = spi_nor_read_cr(nor, &sr_cr[1]);
@@ -1009,7 +1011,7 @@ static int spi_nor_write_16bit_sr_cr_and_check(struct spi_nor *nor, const u8 *re
 		return -EIO;
 	}
 
-	if (nor->flags & SNOR_F_NO_READ_CR)
+	if (nor->params->flags & SNOR_F_NO_READ_CR)
 		return 0;
 
 	ret = spi_nor_read_cr(nor, &nor->bouncebuf[1]);
@@ -1035,7 +1037,7 @@ static int spi_nor_write_16bit_sr_cr_and_check(struct spi_nor *nor, const u8 *re
  */
 int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1)
 {
-	if (nor->flags & SNOR_F_HAS_16BIT_SR)
+	if (nor->params->flags & SNOR_F_HAS_16BIT_SR)
 		return spi_nor_write_16bit_sr_and_check(nor, sr1);
 
 	return spi_nor_write_sr1_and_check(nor, sr1);
@@ -1052,7 +1054,7 @@ int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1)
  */
 int spi_nor_write_sr_cr_and_check(struct spi_nor *nor, const u8 *regs)
 {
-	if (nor->flags & SNOR_F_HAS_16BIT_SR)
+	if (nor->params->flags & SNOR_F_HAS_16BIT_SR)
 		return spi_nor_write_16bit_sr_cr_and_check(nor, regs);
 
 	return spi_nor_write_sr1_and_check(nor, regs[0]);
@@ -1821,6 +1823,7 @@ static int spi_nor_erase_dice(struct spi_nor *nor, loff_t addr,
 static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	struct spi_nor_flash_parameter *params = nor->params;
 	u8 n_dice = nor->params->n_dice;
 	bool multi_die_erase = false;
 	u32 addr, len, rem;
@@ -1852,7 +1855,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 		return ret;
 
 	/* chip (die) erase? */
-	if ((len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) ||
+	if ((len == mtd->size && !(params->flags & SNOR_F_NO_OP_CHIP_ERASE)) ||
 	    multi_die_erase) {
 		ret = spi_nor_erase_dice(nor, addr, len, die_size);
 		if (ret)
@@ -1942,7 +1945,7 @@ int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor)
 {
 	int ret;
 
-	if (nor->flags & SNOR_F_NO_READ_CR)
+	if (nor->params->flags & SNOR_F_NO_READ_CR)
 		return spi_nor_write_16bit_cr_and_check(nor, SR2_QUAD_EN_BIT1);
 
 	ret = spi_nor_read_cr(nor, nor->bouncebuf);
@@ -2502,7 +2505,7 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
 	 * If the reset line is broken, we do not want to enter a stateful
 	 * mode.
 	 */
-	if (nor->flags & SNOR_F_BROKEN_RESET)
+	if (params->flags & SNOR_F_BROKEN_RESET)
 		*hwcaps &= ~(SNOR_HWCAPS_X_X_X | SNOR_HWCAPS_X_X_X_DTR);
 
 	for (cap = 0; cap < sizeof(*hwcaps) * BITS_PER_BYTE; cap++) {
@@ -2526,13 +2529,13 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
 	}
 
 	/* Some SPI controllers might not support CR read opcode. */
-	if (!(nor->flags & SNOR_F_NO_READ_CR)) {
+	if (!(params->flags & SNOR_F_NO_READ_CR)) {
 		struct spi_mem_op op = SPI_NOR_RDCR_OP(nor->bouncebuf);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
 		if (!spi_mem_supports_op(nor->spimem, &op))
-			nor->flags |= SNOR_F_NO_READ_CR;
+			params->flags |= SNOR_F_NO_READ_CR;
 	}
 }
 
@@ -2749,6 +2752,8 @@ static int spi_nor_select_erase(struct spi_nor *nor)
 
 static int spi_nor_set_addr_nbytes(struct spi_nor *nor)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
+
 	if (nor->params->addr_nbytes) {
 		nor->addr_nbytes = nor->params->addr_nbytes;
 	} else if (nor->read_proto == SNOR_PROTO_8_8_8_DTR) {
@@ -2783,8 +2788,8 @@ static int spi_nor_set_addr_nbytes(struct spi_nor *nor)
 	}
 
 	/* Set 4byte opcodes when possible. */
-	if (nor->addr_nbytes == 4 && nor->flags & SNOR_F_4B_OPCODES &&
-	    !(nor->flags & SNOR_F_HAS_4BAIT))
+	if (nor->addr_nbytes == 4 && params->flags & SNOR_F_4B_OPCODES &&
+	    !(params->flags & SNOR_F_HAS_4BAIT))
 		spi_nor_set_4byte_opcodes(nor);
 
 	return 0;
@@ -2947,39 +2952,40 @@ static void spi_nor_no_sfdp_init_params(struct spi_nor *nor)
  */
 static void spi_nor_init_flags(struct spi_nor *nor)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	struct device_node *np = spi_nor_get_flash_node(nor);
 	const u16 flags = nor->info->flags;
 
 	if (of_property_read_bool(np, "broken-flash-reset"))
-		nor->flags |= SNOR_F_BROKEN_RESET;
+		params->flags |= SNOR_F_BROKEN_RESET;
 
 	if (of_property_read_bool(np, "no-wp"))
-		nor->flags |= SNOR_F_NO_WP;
+		params->flags |= SNOR_F_NO_WP;
 
 	if (flags & SPI_NOR_SWP_IS_VOLATILE)
-		nor->flags |= SNOR_F_SWP_IS_VOLATILE;
+		params->flags |= SNOR_F_SWP_IS_VOLATILE;
 
 	if (flags & SPI_NOR_HAS_LOCK)
-		nor->flags |= SNOR_F_HAS_LOCK;
+		params->flags |= SNOR_F_HAS_LOCK;
 
 	if (flags & SPI_NOR_HAS_TB) {
-		nor->flags |= SNOR_F_HAS_SR_TB;
+		params->flags |= SNOR_F_HAS_SR_TB;
 		if (flags & SPI_NOR_TB_SR_BIT6)
-			nor->flags |= SNOR_F_HAS_SR_TB_BIT6;
+			params->flags |= SNOR_F_HAS_SR_TB_BIT6;
 	}
 
 	if (flags & SPI_NOR_4BIT_BP) {
-		nor->flags |= SNOR_F_HAS_4BIT_BP;
+		params->flags |= SNOR_F_HAS_4BIT_BP;
 		if (flags & SPI_NOR_BP3_SR_BIT6)
-			nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
+			params->flags |= SNOR_F_HAS_SR_BP3_BIT6;
 	}
 
 	if (flags & SPI_NOR_HAS_CMP)
-		nor->flags |= SNOR_F_HAS_SR2_CMP_BIT6;
+		params->flags |= SNOR_F_HAS_SR2_CMP_BIT6;
 
 	if (flags & SPI_NOR_RWW && nor->params->n_banks > 1 &&
 	    !nor->controller_ops)
-		nor->flags |= SNOR_F_RWW;
+		params->flags |= SNOR_F_RWW;
 }
 
 /**
@@ -2992,13 +2998,14 @@ static void spi_nor_init_flags(struct spi_nor *nor)
  */
 static void spi_nor_init_fixup_flags(struct spi_nor *nor)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	const u8 fixup_flags = nor->info->fixup_flags;
 
 	if (fixup_flags & SPI_NOR_4B_OPCODES)
-		nor->flags |= SNOR_F_4B_OPCODES;
+		params->flags |= SNOR_F_4B_OPCODES;
 
 	if (fixup_flags & SPI_NOR_IO_MODE_EN_VOLATILE)
-		nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
+		params->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
 }
 
 /**
@@ -3043,7 +3050,7 @@ static int spi_nor_late_init_params(struct spi_nor *nor)
 	 * NOR protection support. When locking_ops are not provided, we pick
 	 * the default ones.
 	 */
-	if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
+	if (params->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
 		spi_nor_init_default_locking_ops(nor);
 
 	if (params->n_banks > 1)
@@ -3108,7 +3115,7 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
 	params->otp.org = info->otp;
 
 	/* Default to 16-bit Write Status (01h) Command */
-	nor->flags |= SNOR_F_HAS_16BIT_SR;
+	params->flags |= SNOR_F_HAS_16BIT_SR;
 
 	/* Set SPI NOR sizes. */
 	params->writesize = 1;
@@ -3229,7 +3236,7 @@ static int spi_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
 	      nor->write_proto == SNOR_PROTO_8_8_8_DTR))
 		return 0;
 
-	if (!(nor->flags & SNOR_F_IO_MODE_EN_VOLATILE))
+	if (!(nor->params->flags & SNOR_F_IO_MODE_EN_VOLATILE))
 		return 0;
 
 	ret = nor->params->set_octal_dtr(nor, enable);
@@ -3282,7 +3289,7 @@ int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
 		 * reboots (e.g., crashes). Warn the user (or hopefully, system
 		 * designer) that this is bad.
 		 */
-		WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
+		WARN_ONCE(nor->params->flags & SNOR_F_BROKEN_RESET,
 			  "enabling reset hack; may not recover from unexpected reboots\n");
 	}
 
@@ -3303,6 +3310,7 @@ int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
 
 static int spi_nor_init(struct spi_nor *nor)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	int err;
 
 	err = spi_nor_set_octal_dtr(nor, true);
@@ -3330,13 +3338,13 @@ static int spi_nor_init(struct spi_nor *nor)
 	spi_nor_cache_sr_lock_bits(nor, NULL);
 	if (IS_ENABLED(CONFIG_MTD_SPI_NOR_SWP_DISABLE) ||
 	    (IS_ENABLED(CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE) &&
-	     nor->flags & SNOR_F_SWP_IS_VOLATILE)) {
+	     params->flags & SNOR_F_SWP_IS_VOLATILE)) {
 		spi_nor_try_unlock_all(nor);
 	}
 
 	if (nor->addr_nbytes == 4 &&
 	    nor->read_proto != SNOR_PROTO_8_8_8_DTR &&
-	    !(nor->flags & SNOR_F_4B_OPCODES))
+	    !(params->flags & SNOR_F_4B_OPCODES))
 		return spi_nor_set_4byte_addr_mode(nor, true);
 
 	return 0;
@@ -3451,11 +3459,12 @@ static void spi_nor_put_device(struct mtd_info *mtd)
 
 static void spi_nor_restore(struct spi_nor *nor)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	int ret;
 
 	/* restore the addressing mode */
-	if (nor->addr_nbytes == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
-	    nor->flags & SNOR_F_BROKEN_RESET) {
+	if (nor->addr_nbytes == 4 && !(params->flags & SNOR_F_4B_OPCODES) &&
+	    params->flags & SNOR_F_BROKEN_RESET) {
 		ret = spi_nor_set_4byte_addr_mode(nor, false);
 		if (ret)
 			/*
@@ -3466,7 +3475,7 @@ static void spi_nor_restore(struct spi_nor *nor)
 			dev_err(nor->dev, "Failed to exit 4-byte address mode, err = %d\n", ret);
 	}
 
-	if (nor->flags & SNOR_F_SOFT_RESET)
+	if (params->flags & SNOR_F_SOFT_RESET)
 		spi_nor_soft_reset(nor);
 }
 
@@ -3590,7 +3599,7 @@ static int spi_nor_set_mtd_info(struct spi_nor *nor)
 	mtd->type = MTD_NORFLASH;
 	mtd->flags = MTD_CAP_NORFLASH;
 	/* Unset BIT_WRITEABLE to enable JFFS2 write buffer for ECC'd NOR */
-	if (nor->flags & SNOR_F_ECC)
+	if (nor->params->flags & SNOR_F_ECC)
 		mtd->flags &= ~MTD_BIT_WRITEABLE;
 	if (nor->info->flags & SPI_NOR_NO_ERASE)
 		mtd->flags |= MTD_NO_ERASE;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 835076d86e3b..99aa6753149f 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -348,6 +348,7 @@ struct spi_nor_otp {
  *
  * @bank_size:		the flash memory bank density in bytes.
  * @size:		the total flash memory density in bytes.
+ * @flags:		flag options for the current SPI NOR (SNOR_F_*)
  * @writesize		Minimal writable flash unit size. Defaults to 1. Set to
  *			ECC unit size for ECC-ed flashes.
  * @page_size:		the page size of the SPI NOR flash memory.
@@ -386,6 +387,7 @@ struct spi_nor_otp {
 struct spi_nor_flash_parameter {
 	u64				bank_size;
 	u64				size;
+	u32				flags;
 	u32				writesize;
 	u32				page_size;
 	u8				addr_nbytes;
diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c
index dc2ed784f519..2bdeba60c286 100644
--- a/drivers/mtd/spi-nor/debugfs.c
+++ b/drivers/mtd/spi-nor/debugfs.c
@@ -99,7 +99,7 @@ static int spi_nor_params_show(struct seq_file *s, void *data)
 	seq_printf(s, "address nbytes\t%u\n", nor->addr_nbytes);
 
 	seq_puts(s, "flags\t\t");
-	spi_nor_print_flags(s, nor->flags, snor_f_names,
+	spi_nor_print_flags(s, params->flags, snor_f_names,
 			    ARRAY_SIZE(snor_f_names));
 	seq_puts(s, "\n");
 
@@ -144,7 +144,7 @@ static int spi_nor_params_show(struct seq_file *s, void *data)
 		}
 	}
 
-	if (!(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
+	if (!(params->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
 		string_get_size(params->size, 1, STRING_UNITS_2, buf, sizeof(buf));
 		seq_printf(s, " %02x (%s)\n", params->die_erase_opcode, buf);
 	}
diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index e97f5cbd9aad..53b0fde832e1 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -40,7 +40,7 @@ mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
 	 * its BFPT table.
 	 */
 	if (bfpt->dwords[SFDP_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
-		nor->flags |= SNOR_F_4B_OPCODES;
+		nor->params->flags |= SNOR_F_4B_OPCODES;
 
 	return 0;
 }
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index 186362066c6b..ca2ce18050df 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -229,7 +229,7 @@ static int mt25qu512a_post_bfpt_fixup(struct spi_nor *nor,
 				      const struct sfdp_parameter_header *bfpt_header,
 				      const struct sfdp_bfpt *bfpt)
 {
-	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
+	nor->params->flags &= ~SNOR_F_HAS_16BIT_SR;
 	return 0;
 }
 
@@ -632,8 +632,8 @@ static int micron_st_nor_ready(struct spi_nor *nor)
 
 static void micron_st_nor_default_init(struct spi_nor *nor)
 {
-	nor->flags |= SNOR_F_HAS_LOCK;
-	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
+	nor->params->flags |= SNOR_F_HAS_LOCK;
+	nor->params->flags &= ~SNOR_F_HAS_16BIT_SR;
 	nor->params->quad_enable = NULL;
 }
 
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 7e44d3c4d89a..56aa12423603 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -586,17 +586,17 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 		 * Read Configuration Register (35h) instruction is not
 		 * supported.
 		 */
-		nor->flags |= SNOR_F_HAS_16BIT_SR | SNOR_F_NO_READ_CR;
+		params->flags |= SNOR_F_HAS_16BIT_SR | SNOR_F_NO_READ_CR;
 		params->quad_enable = spi_nor_sr2_bit1_quad_enable;
 		break;
 
 	case BFPT_DWORD15_QER_SR1_BIT6:
-		nor->flags &= ~SNOR_F_HAS_16BIT_SR;
+		params->flags &= ~SNOR_F_HAS_16BIT_SR;
 		params->quad_enable = spi_nor_sr1_bit6_quad_enable;
 		break;
 
 	case BFPT_DWORD15_QER_SR2_BIT7:
-		nor->flags &= ~SNOR_F_HAS_16BIT_SR;
+		params->flags &= ~SNOR_F_HAS_16BIT_SR;
 		params->quad_enable = spi_nor_sr2_bit7_quad_enable;
 		break;
 
@@ -607,7 +607,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 		 * Register 2, so let's be cautious and keep the default
 		 * assumption of a 16-bit Write Status (01h) command.
 		 */
-		nor->flags |= SNOR_F_HAS_16BIT_SR;
+		params->flags |= SNOR_F_HAS_16BIT_SR;
 
 		params->quad_enable = spi_nor_sr2_bit1_quad_enable;
 		break;
@@ -629,7 +629,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 
 	/* Soft Reset support. */
 	if (bfpt.dwords[SFDP_DWORD(16)] & BFPT_DWORD16_SWRST_EN_RST)
-		nor->flags |= SNOR_F_SOFT_RESET;
+		params->flags |= SNOR_F_SOFT_RESET;
 
 	/* Stop here if not JESD216 rev C or later. */
 	if (bfpt_header->length == BFPT_DWORD_MAX_JESD216B)
@@ -682,7 +682,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 
 	/* Byte order in 8D-8D-8D mode */
 	if (bfpt.dwords[SFDP_DWORD(18)] & BFPT_DWORD18_BYTE_ORDER_SWAPPED)
-		nor->flags |= SNOR_F_SWAP16;
+		params->flags |= SNOR_F_SWAP16;
 
 	return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt);
 }
@@ -1169,7 +1169,7 @@ static int spi_nor_parse_4bait(struct spi_nor *nor,
 	 * SFDP compliant memories.
 	 */
 	params->addr_nbytes = 4;
-	nor->flags |= SNOR_F_4B_OPCODES | SNOR_F_HAS_4BAIT;
+	params->flags |= SNOR_F_4B_OPCODES | SNOR_F_HAS_4BAIT;
 
 	/* fall through */
 out:
@@ -1315,7 +1315,7 @@ static int spi_nor_parse_sccr(struct spi_nor *nor,
 
 	if (FIELD_GET(SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE,
 		      dwords[SFDP_DWORD(22)]))
-		nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
+		params->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
 
 out:
 	kfree(dwords);
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 092450375d4e..fc5da04aff07 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -537,7 +537,7 @@ static void cypress_nor_ecc_init(struct spi_nor *nor)
 	 * same ECC data unit without an erase are not allowed.
 	 */
 	nor->params->writesize = 16;
-	nor->flags |= SNOR_F_ECC;
+	nor->params->flags |= SNOR_F_ECC;
 }
 
 static int
@@ -1139,7 +1139,7 @@ static int spansion_nor_late_init(struct spi_nor *nor)
 	u8 mfr_flags = nor->info->mfr_flags;
 
 	if (params->size > SZ_16M) {
-		nor->flags |= SNOR_F_4B_OPCODES;
+		params->flags |= SNOR_F_4B_OPCODES;
 		/* No small sector erase for 4-byte command set */
 		nor->erase_opcode = SPINOR_OP_SE;
 		nor->mtd.erasesize = nor->info->sector_size ?:
diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c
index 235070b215d1..62720045a9ab 100644
--- a/drivers/mtd/spi-nor/swp.c
+++ b/drivers/mtd/spi-nor/swp.c
@@ -13,12 +13,13 @@
 
 static u8 spi_nor_get_sr_bp_mask(struct spi_nor *nor)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
 
-	if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6)
+	if (params->flags & SNOR_F_HAS_SR_BP3_BIT6)
 		return mask | SR_BP3_BIT6;
 
-	if (nor->flags & SNOR_F_HAS_4BIT_BP)
+	if (params->flags & SNOR_F_HAS_4BIT_BP)
 		return mask | SR_BP3;
 
 	return mask;
@@ -26,9 +27,11 @@ static u8 spi_nor_get_sr_bp_mask(struct spi_nor *nor)
 
 static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor)
 {
-	if (nor->flags & SNOR_F_HAS_SR_TB_BIT6)
+	struct spi_nor_flash_parameter *params = nor->params;
+
+	if (params->flags & SNOR_F_HAS_SR_TB_BIT6)
 		return SR_TB_BIT6;
-	else if (nor->flags & SNOR_F_HAS_SR_TB)
+	else if (params->flags & SNOR_F_HAS_SR_TB)
 		return SR_TB_BIT5;
 	else
 		return 0;
@@ -36,8 +39,10 @@ static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor)
 
 static u8 spi_nor_get_sr_cmp_mask(struct spi_nor *nor)
 {
-	if (!(nor->flags & SNOR_F_NO_READ_CR) &&
-	    nor->flags & SNOR_F_HAS_SR2_CMP_BIT6)
+	struct spi_nor_flash_parameter *params = nor->params;
+
+	if (!(params->flags & SNOR_F_NO_READ_CR) &&
+	    params->flags & SNOR_F_HAS_SR2_CMP_BIT6)
 		return SR2_CMP_BIT6;
 	else
 		return 0;
@@ -67,15 +72,16 @@ u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor)
 void spi_nor_get_locked_range_sr(struct spi_nor *nor, const u8 *sr, loff_t *ofs,
 				 u64 *len)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	u64 min_prot_len;
 	u8 bp_mask = spi_nor_get_sr_bp_mask(nor);
 	u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
 	u8 cmp_mask = spi_nor_get_sr_cmp_mask(nor);
 	u8 bp, val = sr[0] & bp_mask;
-	bool tb = (nor->flags & SNOR_F_HAS_SR_TB) ? sr[0] & tb_mask : 0;
+	bool tb = (params->flags & SNOR_F_HAS_SR_TB) ? sr[0] & tb_mask : 0;
 	bool cmp = sr[1] & cmp_mask;
 
-	if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3_BIT6)
+	if (params->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3_BIT6)
 		val = (val & ~SR_BP3_BIT6) | SR_BP3;
 
 	bp = val >> SR_BP_SHIFT;
@@ -153,10 +159,11 @@ static bool spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, u64 len,
 
 static int spi_nor_sr_set_bp_mask(struct spi_nor *nor, u8 *sr, u8 pow)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	u8 mask = spi_nor_get_sr_bp_mask(nor);
 	u8 val = pow << SR_BP_SHIFT;
 
-	if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
+	if (params->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
 		val = (val & ~SR_BP3) | SR_BP3_BIT6;
 
 	if (val & ~mask)
@@ -200,6 +207,7 @@ static int spi_nor_build_sr(struct spi_nor *nor, const u8 *old_sr, u8 *new_sr,
  */
 void spi_nor_cache_sr_lock_bits(struct spi_nor *nor, u8 *sr)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	u8 bp_mask = spi_nor_get_sr_bp_mask(nor);
 	u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
 	u8 cmp_mask = spi_nor_get_sr_cmp_mask(nor);
@@ -212,7 +220,7 @@ void spi_nor_cache_sr_lock_bits(struct spi_nor *nor, u8 *sr)
 
 		sr_cr[0] = nor->bouncebuf[0];
 
-		if (!(nor->flags & SNOR_F_NO_READ_CR)) {
+		if (!(params->flags & SNOR_F_NO_READ_CR)) {
 			if (spi_nor_read_cr(nor, nor->bouncebuf))
 				return;
 		}
@@ -261,13 +269,14 @@ void spi_nor_cache_sr_lock_bits(struct spi_nor *nor, u8 *sr)
  */
 static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	u64 min_prot_len = spi_nor_get_min_prot_length_sr(nor);
 	u8 status_old[2] = {}, status_new[2] = {}, status_new_cmp[2] = {};
 	u8 *best_status_new = status_new;
 	loff_t ofs_old, ofs_new, ofs_new_cmp;
 	u64 len_old, len_new, len_new_cmp;
 	loff_t lock_len;
-	bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB,
+	bool can_be_top = true, can_be_bottom = params->flags & SNOR_F_HAS_SR_TB,
 		can_be_cmp = spi_nor_get_sr_cmp_mask(nor);
 	bool use_top;
 	int ret;
@@ -279,7 +288,7 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len)
 
 	status_old[0] = nor->bouncebuf[0];
 
-	if (!(nor->flags & SNOR_F_NO_READ_CR)) {
+	if (!(params->flags & SNOR_F_NO_READ_CR)) {
 		ret = spi_nor_read_cr(nor, nor->bouncebuf);
 		if (ret)
 			return ret;
@@ -313,7 +322,7 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len)
 		lock_len = ofs + len;
 
 	if (lock_len == nor->params->size)
-		pow = (nor->flags & SNOR_F_HAS_4BIT_BP) ? GENMASK(3, 0) : GENMASK(2, 0);
+		pow = (params->flags & SNOR_F_HAS_4BIT_BP) ? GENMASK(3, 0) : GENMASK(2, 0);
 	else
 		pow = ilog2(lock_len) - ilog2(min_prot_len) + 1;
 
@@ -359,7 +368,7 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len)
 	 * wrongly tied to GND (that includes internal pull-downs).
 	 * WP# pin hard strapped to GND can be a valid use case.
 	 */
-	if (!(nor->flags & SNOR_F_NO_WP))
+	if (!(params->flags & SNOR_F_NO_WP))
 		best_status_new[0] |= SR_SRWD;
 
 	spi_nor_get_locked_range_sr(nor, status_old, &ofs_old, &len_old);
@@ -378,7 +387,7 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len)
 	    (ofs_old < ofs_new || (ofs_new + len_new) < (ofs_old + len_old)))
 		return -EINVAL;
 
-	if (nor->flags & SNOR_F_NO_READ_CR)
+	if (params->flags & SNOR_F_NO_READ_CR)
 		ret = spi_nor_write_sr_and_check(nor, best_status_new[0]);
 	else
 		ret = spi_nor_write_sr_cr_and_check(nor, best_status_new);
@@ -397,13 +406,14 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len)
  */
 static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, u64 len)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	u64 min_prot_len = spi_nor_get_min_prot_length_sr(nor);
 	u8 status_old[2] = {}, status_new[2] = {}, status_new_cmp[2] = {};
 	u8 *best_status_new = status_new;
 	loff_t ofs_old, ofs_new, ofs_new_cmp;
 	u64 len_old, len_new, len_new_cmp;
 	loff_t lock_len;
-	bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB,
+	bool can_be_top = true, can_be_bottom = params->flags & SNOR_F_HAS_SR_TB,
 		can_be_cmp = spi_nor_get_sr_cmp_mask(nor);
 	bool use_top;
 	int ret;
@@ -415,7 +425,7 @@ static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, u64 len)
 
 	status_old[0] = nor->bouncebuf[0];
 
-	if (!(nor->flags & SNOR_F_NO_READ_CR)) {
+	if (!(params->flags & SNOR_F_NO_READ_CR)) {
 		ret = spi_nor_read_cr(nor, nor->bouncebuf);
 		if (ret)
 			return ret;
@@ -512,7 +522,7 @@ static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, u64 len)
 	    (ofs_new < ofs_old || (ofs_old + len_old) < (ofs_new + len_new)))
 		return -EINVAL;
 
-	if (nor->flags & SNOR_F_NO_READ_CR)
+	if (params->flags & SNOR_F_NO_READ_CR)
 		ret = spi_nor_write_sr_and_check(nor, best_status_new[0]);
 	else
 		ret = spi_nor_write_sr_cr_and_check(nor, best_status_new);
@@ -533,6 +543,7 @@ static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, u64 len)
  */
 static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, u64 len)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	u8 sr_cr[2] = {};
 	int ret;
 
@@ -542,7 +553,7 @@ static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, u64 len)
 
 	sr_cr[0] = nor->bouncebuf[0];
 
-	if (!(nor->flags & SNOR_F_NO_READ_CR)) {
+	if (!(params->flags & SNOR_F_NO_READ_CR)) {
 		ret = spi_nor_read_cr(nor, nor->bouncebuf);
 		if (ret)
 			return ret;
@@ -628,9 +639,10 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, u64 len)
  */
 void spi_nor_try_unlock_all(struct spi_nor *nor)
 {
+	struct spi_nor_flash_parameter *params = nor->params;
 	int ret;
 
-	if (!(nor->flags & SNOR_F_HAS_LOCK))
+	if (!(params->flags & SNOR_F_HAS_LOCK))
 		return;
 
 	dev_dbg(nor->dev, "Unprotecting entire flash array\n");
diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
index 45f17eb89a45..afb55698f5c3 100644
--- a/drivers/mtd/spi-nor/winbond.c
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -64,7 +64,7 @@ w25q256_post_bfpt_fixups(struct spi_nor *nor,
 	 */
 	if (bfpt_header->major == SFDP_JESD216_MAJOR &&
 	    bfpt_header->minor == SFDP_JESD216A_MINOR)
-		nor->flags |= SNOR_F_4B_OPCODES;
+		nor->params->flags |= SNOR_F_4B_OPCODES;
 
 	return 0;
 }
@@ -84,7 +84,7 @@ winbond_rdcr_post_bfpt_fixup(struct spi_nor *nor,
 	 * both incorrect and impractical, as the chip features a CMP bit for its
 	 * locking scheme that lays in the Control Register, and needs to be read.
 	 */
-	nor->flags &= ~SNOR_F_NO_READ_CR;
+	nor->params->flags &= ~SNOR_F_NO_READ_CR;
 
 	return 0;
 }
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index e75c1b4cb4c0..099c5016b485 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -365,7 +365,6 @@ struct spi_nor_flash_parameter;
  * @read_dummy:		the dummy needed by the read operation
  * @program_opcode:	the program opcode
  * @sst_write_second:	used by the SST write operation
- * @flags:		flag options for the current SPI NOR (SNOR_F_*)
  * @read_proto:		the SPI protocol for read operations
  * @write_proto:	the SPI protocol for write operations
  * @reg_proto:		the SPI protocol for read_reg/write_reg/erase operations
@@ -406,7 +405,6 @@ struct spi_nor {
 	enum spi_nor_protocol	write_proto;
 	enum spi_nor_protocol	reg_proto;
 	bool			sst_write_second;
-	u32			flags;
 	struct sfdp		*sfdp;
 	struct dentry		*debugfs_root;
 	u8			dfs_sr_cache[2];
-- 
2.47.3


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v1 5/8] mtd: spi-nor: move spi_nor_post_bfpt_fixups() into sfdp
  2026-07-03 14:29 [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization Michael Walle
                   ` (3 preceding siblings ...)
  2026-07-03 14:29 ` [PATCH v1 4/8] mtd: spi-nor: move flags " Michael Walle
@ 2026-07-03 14:29 ` Michael Walle
  2026-07-03 14:29 ` [PATCH v1 6/8] mtd: spi-nor: spansion: s25fs256t: move ARCFN check into .late_init Michael Walle
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Michael Walle @ 2026-07-03 14:29 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus
  Cc: linux-mtd, Cheng Ming Lin, linux-kernel

Move spi_nor_post_bfpt_fixups() into the sfdp module because it's
really only needed there. While at it, add some documentation.

Signed-off-by: Michael Walle <mwalle@kernel.org>
---
 drivers/mtd/spi-nor/core.c | 20 --------------------
 drivers/mtd/spi-nor/core.h |  4 ----
 drivers/mtd/spi-nor/sfdp.c | 31 +++++++++++++++++++++++++++++++
 3 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index d5f37b6cd76b..8cbe44e12385 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2581,26 +2581,6 @@ void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map,
 	map->n_regions = 1;
 }
 
-int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
-			     const struct sfdp_parameter_header *bfpt_header,
-			     const struct sfdp_bfpt *bfpt)
-{
-	int ret;
-
-	if (nor->manufacturer && nor->manufacturer->fixups &&
-	    nor->manufacturer->fixups->post_bfpt) {
-		ret = nor->manufacturer->fixups->post_bfpt(nor, bfpt_header,
-							   bfpt);
-		if (ret)
-			return ret;
-	}
-
-	if (nor->info->fixups && nor->info->fixups->post_bfpt)
-		return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt);
-
-	return 0;
-}
-
 static int spi_nor_select_read(struct spi_nor *nor,
 			       u32 shared_hwcaps)
 {
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 99aa6753149f..3d0bdb320721 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -687,10 +687,6 @@ void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase);
 void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map,
 				    u8 erase_mask, u64 flash_size);
 
-int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
-			     const struct sfdp_parameter_header *bfpt_header,
-			     const struct sfdp_bfpt *bfpt);
-
 void spi_nor_init_default_locking_ops(struct spi_nor *nor);
 bool spi_nor_has_default_locking_ops(struct spi_nor *nor);
 void spi_nor_try_unlock_all(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 56aa12423603..5ffd695d1e8b 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -401,6 +401,37 @@ static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map)
 	}
 }
 
+/**
+ * spi_nor_post_bfpt_fixups() - Updates the flash's parameters and settings
+ * after BFPT has been parsed. Called only for flashes that define JESD216 SFDP
+ * tables.
+ * @nor:	pointer to a 'struct spi_nor'
+ * @bfpt_header:	pointer to the 'struct sfdp_parameter_header' describing
+ *			the Basic Flash Parameter Table length and version
+ *
+ * Used to tweak various flash parameters when information provided by the SFDP
+ * tables are wrong.
+ */
+static int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
+				    const struct sfdp_parameter_header *bfpt_header,
+				    const struct sfdp_bfpt *bfpt)
+{
+	int ret;
+
+	if (nor->manufacturer && nor->manufacturer->fixups &&
+	    nor->manufacturer->fixups->post_bfpt) {
+		ret = nor->manufacturer->fixups->post_bfpt(nor, bfpt_header,
+							   bfpt);
+		if (ret)
+			return ret;
+	}
+
+	if (nor->info->fixups && nor->info->fixups->post_bfpt)
+		return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt);
+
+	return 0;
+}
+
 /**
  * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table.
  * @nor:		pointer to a 'struct spi_nor'
-- 
2.47.3


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v1 6/8] mtd: spi-nor: spansion: s25fs256t: move ARCFN check into .late_init
  2026-07-03 14:29 [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization Michael Walle
                   ` (4 preceding siblings ...)
  2026-07-03 14:29 ` [PATCH v1 5/8] mtd: spi-nor: move spi_nor_post_bfpt_fixups() into sfdp Michael Walle
@ 2026-07-03 14:29 ` Michael Walle
  2026-07-03 14:29 ` [PATCH v1 7/8] mtd: spi-nor: push the rollback mechanism into the sfdp module Michael Walle
  2026-07-03 14:29 ` [PATCH v1 8/8] mtd: spi-nor: rework flash parameter initialization Michael Walle
  7 siblings, 0 replies; 9+ messages in thread
From: Michael Walle @ 2026-07-03 14:29 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus
  Cc: linux-mtd, Cheng Ming Lin, linux-kernel

The SFPD parsing is optional. It not meant to fail if something is wrong
with the chip (except for the SFDP itself). Thus it doesn't make any
sense to return -ENODEV.

Move that check to late_init(), which might fail and abort the flash
probing.

Cc: Takahiro Kuwano <takahiro.kuwano@infineon.com>
Signed-off-by: Michael Walle <mwalle@kernel.org>
---
 drivers/mtd/spi-nor/spansion.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index fc5da04aff07..40d3236c723b 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -545,7 +545,6 @@ s25fs256t_post_bfpt_fixup(struct spi_nor *nor,
 			  const struct sfdp_parameter_header *bfpt_header,
 			  const struct sfdp_bfpt *bfpt)
 {
-	struct spi_mem_op op;
 	int ret;
 
 	/* Assign 4-byte address mode method that is not determined in BFPT */
@@ -555,19 +554,6 @@ s25fs256t_post_bfpt_fixup(struct spi_nor *nor,
 	if (ret)
 		return ret;
 
-	/* Read Architecture Configuration Register (ARCFN) */
-	op = (struct spi_mem_op)
-		CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes,
-					  SPINOR_REG_CYPRESS_ARCFN, 1,
-					  nor->bouncebuf);
-	ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
-	if (ret)
-		return ret;
-
-	/* ARCFN value must be 0 if uniform sector is selected  */
-	if (nor->bouncebuf[0])
-		return -ENODEV;
-
 	return 0;
 }
 
@@ -598,6 +584,22 @@ static int s25fs256t_post_sfdp_fixup(struct spi_nor *nor)
 
 static int s25fs256t_late_init(struct spi_nor *nor)
 {
+	struct spi_mem_op op;
+	int ret;
+
+	/* Read Architecture Configuration Register (ARCFN) */
+	op = (struct spi_mem_op)
+		CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes,
+					  SPINOR_REG_CYPRESS_ARCFN, 1,
+					  nor->bouncebuf);
+	ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
+	if (ret)
+		return ret;
+
+	/* ARCFN value must be 0 if uniform sector is selected  */
+	if (nor->bouncebuf[0])
+		return -ENODEV;
+
 	cypress_nor_ecc_init(nor);
 
 	return 0;
-- 
2.47.3


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v1 7/8] mtd: spi-nor: push the rollback mechanism into the sfdp module
  2026-07-03 14:29 [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization Michael Walle
                   ` (5 preceding siblings ...)
  2026-07-03 14:29 ` [PATCH v1 6/8] mtd: spi-nor: spansion: s25fs256t: move ARCFN check into .late_init Michael Walle
@ 2026-07-03 14:29 ` Michael Walle
  2026-07-03 14:29 ` [PATCH v1 8/8] mtd: spi-nor: rework flash parameter initialization Michael Walle
  7 siblings, 0 replies; 9+ messages in thread
From: Michael Walle @ 2026-07-03 14:29 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus
  Cc: linux-mtd, Cheng Ming Lin, linux-kernel

Right now, the core is handling the rollback of the parameters. But it
doesn't have the knowledge what has to be rolled back. And in fact,
havent rolled back everything. Push it down to the called function and
make it mandatory, that this function has no side effects if it fails.

Funny enough, there is a comment in the SFDP table handing code that
each table parser is responsible to roll back any changes. But none of
them did. So while add it, expand the logic to that and roll it back for
them. There is one simple rule though:

  SFDP parsing and fixups may only modify the spi_nor_flash_parameters.

Signed-off-by: Michael Walle <mwalle@kernel.org>
---
 drivers/mtd/spi-nor/core.c | 20 +-------------------
 drivers/mtd/spi-nor/sfdp.c | 19 +++++++++++++++++--
 2 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 8cbe44e12385..8446b7b39f55 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3039,24 +3039,6 @@ static int spi_nor_late_init_params(struct spi_nor *nor)
 	return 0;
 }
 
-/**
- * spi_nor_sfdp_init_params_deprecated() - Deprecated way of initializing flash
- * parameters and settings based on JESD216 SFDP standard.
- * @nor:	pointer to a 'struct spi_nor'.
- *
- * The method has a roll-back mechanism: in case the SFDP parsing fails, the
- * legacy flash parameters and settings will be restored.
- */
-static void spi_nor_sfdp_init_params_deprecated(struct spi_nor *nor)
-{
-	struct spi_nor_flash_parameter sfdp_params;
-
-	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
-
-	if (spi_nor_parse_sfdp(nor))
-		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
-}
-
 /**
  * spi_nor_init_params_deprecated() - Deprecated way of initializing flash
  * parameters and settings.
@@ -3076,7 +3058,7 @@ static void spi_nor_init_params_deprecated(struct spi_nor *nor)
 					SPI_NOR_QUAD_READ |
 					SPI_NOR_OCTAL_READ |
 					SPI_NOR_OCTAL_DTR_READ))
-		spi_nor_sfdp_init_params_deprecated(nor);
+		spi_nor_parse_sfdp(nor);
 }
 
 /**
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 5ffd695d1e8b..a48bd74f3cef 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -1473,12 +1473,16 @@ int spi_nor_check_sfdp_signature(struct spi_nor *nor)
  * runtime the main parameters needed to perform basic SPI flash operations such
  * as Fast Read, Page Program or Sector Erase commands.
  *
+ * Because the parsing is optional, all the settings have to be reverted. IOW,
+ * nothing of struct spi_nor shall be changed.
+ *
  * Return: 0 on success, -errno otherwise.
  */
 int spi_nor_parse_sfdp(struct spi_nor *nor)
 {
 	const struct sfdp_parameter_header *param_header, *bfpt_header;
 	struct sfdp_parameter_header *param_headers = NULL;
+	struct spi_nor_flash_parameter params;
 	struct sfdp_header header;
 	struct device *dev = nor->dev;
 	struct sfdp *sfdp;
@@ -1486,6 +1490,12 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
 	size_t psize;
 	int i, err;
 
+	/*
+	 * Get a backup of all the parameter to roll back to in case of an
+	 * error.
+	 */
+	memcpy(&params, nor->params, sizeof(params));
+
 	/* Get the SFDP header. */
 	err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
 	if (err < 0)
@@ -1607,6 +1617,7 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
 
 	/* Parse optional parameter tables. */
 	for (i = 0; i < header.nph; i++) {
+		memcpy(&params, nor->params, sizeof(params));
 		param_header = &param_headers[i];
 
 		switch (SFDP_PARAM_HEADER_ID(param_header)) {
@@ -1640,15 +1651,19 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
 			/*
 			 * Let's not drop all information we extracted so far
 			 * if optional table parsers fail. In case of failing,
-			 * each optional parser is responsible to roll back to
-			 * the previously known spi_nor data.
+			 * roll back to the previously known
+			 * spi_nor_flash_parameter data.
 			 */
 			err = 0;
+			memcpy(nor->params, &params, sizeof(*nor->params));
 		}
 	}
 
 	err = spi_nor_post_sfdp_fixups(nor);
 exit:
 	kfree(param_headers);
+	if (err)
+		memcpy(nor->params, &params, sizeof(*nor->params));
+
 	return err;
 }
-- 
2.47.3


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v1 8/8] mtd: spi-nor: rework flash parameter initialization
  2026-07-03 14:29 [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization Michael Walle
                   ` (6 preceding siblings ...)
  2026-07-03 14:29 ` [PATCH v1 7/8] mtd: spi-nor: push the rollback mechanism into the sfdp module Michael Walle
@ 2026-07-03 14:29 ` Michael Walle
  7 siblings, 0 replies; 9+ messages in thread
From: Michael Walle @ 2026-07-03 14:29 UTC (permalink / raw)
  To: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus
  Cc: linux-mtd, Cheng Ming Lin, linux-kernel

Rework how the flash parameters are initialized. It used to make a
difference whether a flash is in the in-kernel database, whether it
supports multi I/O and so on. Recently, that makes more and more
problems because flash IDs are reused among legacy flashes (w/o SFDP
support) and newer flashes [1,2,3,4].

Simplify the whole parameter initialization, by starting with the
parameters we have in the in-kernel database and the try to parse SFDP
(and let it override any settings).

This has the consequence that all the flashes now get a RDSFPD opcode
which might be an unknown opcode from the perspective of the flash. With
the generic SPI NOR flash driver, this was already the case for any
flashes not listed in the in-kernel database. So far, there was not a
single complaint.

[1] https://lore.kernel.org/linux-mtd/CAAyq3SYX9UPwhC_Ume_S2yxhQwimRvB=Y6O_+FFqokhNmw7jQg@mail.gmail.com/
[2] https://lore.kernel.org/linux-mtd/DGB4745HRCFI.1DRYTHXURWZJO@kernel.org/
[3] https://lore.kernel.org/linux-mtd/DD10GE4EOCD7.CPTN7198QFUV@kernel.org/
[4] https://lore.kernel.org/linux-mtd/DD6SI06QNEE4.2YCRTWJHEAAQM@kernel.org/

Signed-off-by: Michael Walle <mwalle@kernel.org>
Tested-by: Cheng Ming Lin <chengminglin@mxic.com.tw>
Tested-by: Miquel Raynal <miquel.raynal@bootlin.com> # w/ W25Q02JVFIM
---
 drivers/mtd/spi-nor/core.c | 53 ++++++++++----------------------------
 drivers/mtd/spi-nor/core.h |  5 +---
 2 files changed, 15 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 8446b7b39f55..dffa81ec89f7 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2853,11 +2853,10 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 
 /**
  * spi_nor_no_sfdp_init_params() - Initialize the flash's parameters and
- * settings based on nor->info->sfdp_flags. This method should be called only by
- * flashes that do not define SFDP tables. If the flash supports SFDP but the
- * information is wrong and the settings from this function can not be retrieved
- * by parsing SFDP, one should instead use the fixup hooks and update the wrong
- * bits.
+ * settings based on nor->info->sfdp_flags.
+ * If the flash supports SFDP but the information is wrong and the settings from
+ * this function can not be retrieved by parsing SFDP, one should instead use
+ * the fixup hooks and update the wrong bits.
  * @nor:	pointer to a 'struct spi_nor'.
  */
 static void spi_nor_no_sfdp_init_params(struct spi_nor *nor)
@@ -3039,28 +3038,6 @@ static int spi_nor_late_init_params(struct spi_nor *nor)
 	return 0;
 }
 
-/**
- * spi_nor_init_params_deprecated() - Deprecated way of initializing flash
- * parameters and settings.
- * @nor:	pointer to a 'struct spi_nor'.
- *
- * The method assumes that flash doesn't support SFDP so it initializes flash
- * parameters in spi_nor_no_sfdp_init_params() which later on can be overwritten
- * when parsing SFDP, if supported.
- */
-static void spi_nor_init_params_deprecated(struct spi_nor *nor)
-{
-	spi_nor_no_sfdp_init_params(nor);
-
-	spi_nor_manufacturer_init_params(nor);
-
-	if (nor->info->no_sfdp_flags & (SPI_NOR_DUAL_READ |
-					SPI_NOR_QUAD_READ |
-					SPI_NOR_OCTAL_READ |
-					SPI_NOR_OCTAL_DTR_READ))
-		spi_nor_parse_sfdp(nor);
-}
-
 /**
  * spi_nor_init_default_params() - Default initialization of flash parameters
  * and settings. Done for all flashes, regardless is they define SFDP tables
@@ -3121,7 +3098,8 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
  *
  * 1/ Default flash parameters initialization. The initializations are done
  *    based on nor->info data:
- *		spi_nor_info_init_params()
+ *		spi_nor_init_default_params()
+ *		spi_nor_no_sfdp_init_params()
  *
  * which can be overwritten by:
  * 2/ Manufacturer flash parameters initialization. The initializations are
@@ -3132,7 +3110,7 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
  * which can be overwritten by:
  * 3/ SFDP flash parameters initialization. JESD216 SFDP is a standard and
  *    should be more accurate that the above.
- *		spi_nor_parse_sfdp() or spi_nor_no_sfdp_init_params()
+ *		spi_nor_parse_sfdp()
  *
  *    Please note that there is a ->post_bfpt() fixup hook that can overwrite
  *    the flash parameters and settings immediately after parsing the Basic
@@ -3158,17 +3136,14 @@ static int spi_nor_init_params(struct spi_nor *nor)
 		return -ENOMEM;
 
 	spi_nor_init_default_params(nor);
+	spi_nor_no_sfdp_init_params(nor);
+	spi_nor_manufacturer_init_params(nor);
 
-	if (spi_nor_needs_sfdp(nor)) {
-		ret = spi_nor_parse_sfdp(nor);
-		if (ret) {
-			dev_err(nor->dev, "BFPT parsing failed. Please consider using SPI_NOR_SKIP_SFDP when declaring the flash\n");
-			return ret;
-		}
-	} else if (nor->info->no_sfdp_flags & SPI_NOR_SKIP_SFDP) {
-		spi_nor_no_sfdp_init_params(nor);
-	} else {
-		spi_nor_init_params_deprecated(nor);
+	ret = spi_nor_parse_sfdp(nor);
+	if (ret && spi_nor_needs_sfdp(nor)) {
+		dev_err(nor->dev,
+			"SFDP parsing failed. You need to manually declare the flash parameters.\n");
+		return ret;
 	}
 
 	ret = spi_nor_late_init_params(nor);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 3d0bdb320721..0e554d3d4aa0 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -502,9 +502,7 @@ struct spi_nor_id {
  *                            be used with SPI_NOR_HAS_LOCK.
  *
  * @no_sfdp_flags:  flags that indicate support that can be discovered via SFDP.
- *                  Used when SFDP tables are not defined in the flash. These
- *                  flags are used together with the SPI_NOR_SKIP_SFDP flag.
- *   SPI_NOR_SKIP_SFDP:       skip parsing of SFDP tables.
+ *                  Used when SFDP tables are not defined in the flash.
  *   SECT_4K:                 SPINOR_OP_BE_4K works uniformly.
  *   SPI_NOR_DUAL_READ:       flash supports Dual Read.
  *   SPI_NOR_QUAD_READ:       flash supports Quad Read.
@@ -552,7 +550,6 @@ struct flash_info {
 #define SPI_NOR_HAS_CMP			BIT(10)
 
 	u8 no_sfdp_flags;
-#define SPI_NOR_SKIP_SFDP		BIT(0)
 #define SECT_4K				BIT(1)
 #define SPI_NOR_DUAL_READ		BIT(3)
 #define SPI_NOR_QUAD_READ		BIT(4)
-- 
2.47.3


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

end of thread, other threads:[~2026-07-03 14:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-03 14:29 [PATCH v1 0/8] mtd: spi-nor: Rework flash parameter initialization Michael Walle
2026-07-03 14:29 ` [PATCH v1 1/8] mtd: spi-nor: spansion: s25fl256s0: remove SKIP_SFDP flag Michael Walle
2026-07-03 14:29 ` [PATCH v1 2/8] mtd: spi-nor: don't clear the SNOR_F_4B_OPCODES flag on failure Michael Walle
2026-07-03 14:29 ` [PATCH v1 3/8] mtd: spi-nor: move cmd_ext_type into spi_nor_flash_parameter Michael Walle
2026-07-03 14:29 ` [PATCH v1 4/8] mtd: spi-nor: move flags " Michael Walle
2026-07-03 14:29 ` [PATCH v1 5/8] mtd: spi-nor: move spi_nor_post_bfpt_fixups() into sfdp Michael Walle
2026-07-03 14:29 ` [PATCH v1 6/8] mtd: spi-nor: spansion: s25fs256t: move ARCFN check into .late_init Michael Walle
2026-07-03 14:29 ` [PATCH v1 7/8] mtd: spi-nor: push the rollback mechanism into the sfdp module Michael Walle
2026-07-03 14:29 ` [PATCH v1 8/8] mtd: spi-nor: rework flash parameter initialization Michael Walle

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