[PATCH 0/4] mtd: spi-nor: add generic flash driver

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
The goal of series is to port spi-nor-generic feature based on SFDP parsing. This feature will suppress the increase of spi_nor_ids{} size and reduce our effort to maintain it.
We need to rework 4-byte address mode entry/exit functions and enhance SFDP parsing to select proper 4-byte address mode method. After that, add spi-nor-generic structure and fallback logic in spi_nor_read_id().
Most of the code in this series are from Linux commits with some modification to address gap between u-boot and Linux implementation.
It may be better to sync whole SPI NOR framework with Linux. That will be done incrementally by separate series.
Tested with CYRS17B512 SPI NOR Flash which supports SFDP but not listed in spi_nor_ids[]. https://www.infineon.com/dgdl/Infineon-CYRS17B512_512_MB_64_MB_SERIAL_NOR_FL...
Takahiro Kuwano (4): mtd: spi-nor: Rework set_4byte() mtd: spi-nor: Set the 4-Byte Address Mode method based on SFDP data mtd: spi-nor: Remove SPI_NOR_SKIP_SFDP flag mtd: spi-nor: add generic flash driver
drivers/mtd/spi/sf_internal.h | 10 +- drivers/mtd/spi/spi-nor-core.c | 317 +++++++++++++++++++++++++-------- include/linux/mtd/spi-nor.h | 3 + 3 files changed, 252 insertions(+), 78 deletions(-)

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Synchronize set_4byte() with Linux v6.10 as much as possible.
Introduce {nor, params}->set_4byte_addr_mode(). The params->set_4byte_addr_mode is initialized with one of the manufacturer specific methods, copied to nor->set_4byte_addr_mode, then it is called from spi_nor_set_4byte_addr_mode() renamed from set_4byte().
There are still manufacturer checks here and there. And The set_4byte_addr_mode() method in both nor-> and params-> looks redundant. Those should be cleaned up separately in another patch set.
The following commits in Linux are related to this patch. 64c160f32235 ("mtd: spi-nor: Create a ->set_4byte() method") 81924dae5194 ("mtd: spi-nor: Emphasise which is the genericset_4byte_addr_mode() method") 076aa4eac8b3 ("mtd: spi-nor: core: Move generic method to core - micron_st_nor_set_4byte_addr_mode") 288df4378319 ("mtd: spi-nor: core: Update name and description of micron_st_nor_set_4byte_addr_mode") f1f1976224f3 ("mtd: spi-nor: core: Update name and description of spansion_set_4byte_addr_mode") b6094ac83dd4 ("mtd: spi-nor: core: Introduce spi_nor_set_4byte_addr_mode()")
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/spi-nor-core.c | 179 +++++++++++++++++++++++++-------- include/linux/mtd/spi-nor.h | 3 + 2 files changed, 138 insertions(+), 44 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 8d2afaa0e2..d523c045f4 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -680,54 +680,123 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, } #endif /* !CONFIG_SPI_FLASH_BAR */
-/* Enable/disable 4-byte addressing mode. */ -static int set_4byte(struct spi_nor *nor, const struct flash_info *info, - int enable) +/** + * spi_nor_set_4byte_addr_mode_en4b_ex4b() - Enter/Exit 4-byte address mode + * using SPINOR_OP_EN4B/SPINOR_OP_EX4B. Typically used by + * Winbond and Macronix. Cypress also uses SPINOR_OP_EN4B + * to enter, but not SPINOR_OP_EX4B to exit. + * @nor: pointer to 'struct spi_nor'. + * @enable: true to enter the 4-byte address mode, false to exit the 4-byte + * address mode. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_set_4byte_addr_mode_en4b_ex4b(struct spi_nor *nor, + bool enable) { - int status; - bool need_wren = false; - u8 cmd; + u8 opcode; + int ret;
- switch (JEDEC_MFR(info)) { - case SNOR_MFR_ST: - case SNOR_MFR_MICRON: - /* Some Micron need WREN command; all will accept it */ - need_wren = true; - fallthrough; - case SNOR_MFR_ISSI: - case SNOR_MFR_MACRONIX: - case SNOR_MFR_WINBOND: - if (need_wren) - write_enable(nor); + if (enable) + opcode = SPINOR_OP_EN4B; + else if (JEDEC_MFR(nor->info) == SNOR_MFR_CYPRESS) + opcode = SPINOR_OP_EX4B_CYPRESS; + else + opcode = SPINOR_OP_EX4B;
- cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; - status = nor->write_reg(nor, cmd, NULL, 0); - if (need_wren) - write_disable(nor); + ret = nor->write_reg(nor, opcode, NULL, 0); + if (ret) + return ret;
- if (!status && !enable && - JEDEC_MFR(info) == SNOR_MFR_WINBOND) { - /* - * On Winbond W25Q256FV, leaving 4byte mode causes - * the Extended Address Register to be set to 1, so all - * 3-byte-address reads come from the second 16M. - * We must clear the register to enable normal behavior. - */ - write_enable(nor); - nor->cmd_buf[0] = 0; - nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1); - write_disable(nor); - } + /* + * On Winbond W25Q256FV, leaving 4byte mode causes the Extended + * Address Register to be set to 1, so all 3-byte-address reads + * come from the second 16M. We must clear the register to + * enable normal behavior. + */ + if (!enable && JEDEC_MFR(nor->info) == SNOR_MFR_WINBOND) { + ret = write_enable(nor); + if (ret) + return ret;
- return status; - case SNOR_MFR_CYPRESS: - cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B_CYPRESS; - return nor->write_reg(nor, cmd, NULL, 0); - default: - /* Spansion style */ - nor->cmd_buf[0] = enable << 7; - return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); + nor->cmd_buf[0] = 0; + ret = nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, + 1); + if (ret) + return ret; + + ret = write_disable(nor); + if (ret) + return ret; + } + + return 0; +} + +/** + * spi_nor_set_4byte_addr_mode_wren_en4b_ex4b() - Set 4-byte address mode using + * SPINOR_OP_WREN followed by SPINOR_OP_EN4B or + * SPINOR_OP_EX4B. Typically used by ST and Micron flashes. + * @nor: pointer to 'struct spi_nor'. + * @enable: true to enter the 4-byte address mode, false to exit the 4-byte + * address mode. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_set_4byte_addr_mode_wren_en4b_ex4b(struct spi_nor *nor, + bool enable) +{ + int ret; + + ret = write_enable(nor); + if (ret) + return ret; + + ret = spi_nor_set_4byte_addr_mode_en4b_ex4b(nor, enable); + if (ret) + return ret; + + return write_disable(nor); +} + +/** + * spi_nor_set_4byte_addr_mode_brwr() - Set 4-byte address mode using + * SPINOR_OP_BRWR. Typically used by Spansion flashes. + * @nor: pointer to 'struct spi_nor'. + * @enable: true to enter the 4-byte address mode, false to exit the 4-byte + * address mode. + * + * 8-bit volatile bank register used to define A[30:A24] bits. MSB (bit[7]) is + * used to enable/disable 4-byte address mode. When MSB is set to ‘1’, 4-byte + * address mode is active and A[30:24] bits are don’t care. Write instruction is + * SPINOR_OP_BRWR(17h) with 1 byte of data. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_set_4byte_addr_mode_brwr(struct spi_nor *nor, bool enable) +{ + nor->cmd_buf[0] = enable ? BIT(7) : 0; + return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); +} + +/* Enable/disable 4-byte addressing mode. */ +static int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable) +{ + int ret; + + ret = nor->set_4byte_addr_mode(nor, enable); + if (ret) + return ret; + + if (enable) { + nor->addr_width = 4; + nor->addr_mode_nbytes = 4; + } else { + nor->addr_width = 3; + nor->addr_mode_nbytes = 3; } + + return 0; }
#ifdef CONFIG_SPI_FLASH_SPANSION @@ -2884,6 +2953,25 @@ static int spi_nor_init_params(struct spi_nor *nor, } }
+ /* Select the procedure to enter/exit 4-byte address mode. */ + switch (JEDEC_MFR(info)) { + case SNOR_MFR_ST: + case SNOR_MFR_MICRON: + params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b; + break; + + case SNOR_MFR_ISSI: + case SNOR_MFR_MACRONIX: + case SNOR_MFR_WINBOND: + case SNOR_MFR_CYPRESS: + params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b; + break; + + default: + params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_brwr; + break; + } + /* Override the parameters with data read from SFDP tables. */ nor->addr_width = 0; nor->mtd.erasesize = 0; @@ -3272,6 +3360,9 @@ static int spi_nor_default_setup(struct spi_nor *nor, else nor->quad_enable = NULL;
+ /* Enter/Exit 4-byte address mode */ + nor->set_4byte_addr_mode = params->set_4byte_addr_mode; + return 0; }
@@ -3504,7 +3595,7 @@ static int s25_s28_post_bfpt_fixup(struct spi_nor *nor, */ if (params->size > SZ_128M) { if (bfpt->dwords[BFPT_DWORD(16)] & BFPT_DWORD16_EX4B_PWRCYC) { - ret = set_4byte(nor, nor->info, 1); + ret = spi_nor_set_4byte_addr_mode(nor, true); if (ret) return ret; } @@ -3923,7 +4014,7 @@ static int spi_nor_init(struct spi_nor *nor) */ if (nor->flags & SNOR_F_BROKEN_RESET) debug("enabling reset hack; may not recover from unexpected reboots\n"); - set_4byte(nor, nor->info, 1); + return spi_nor_set_4byte_addr_mode(nor, true); }
return 0; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 0d37a806c4..f5d26447c2 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -446,6 +446,7 @@ struct spi_nor_flash_parameter { struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];
int (*quad_enable)(struct spi_nor *nor); + int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable); };
/** @@ -528,6 +529,7 @@ struct spi_flash { * @flash_is_unlocked: [FLASH-SPECIFIC] check if a region of the SPI NOR is * completely unlocked * @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode + * @set_4byte_addr_mode:[FLASH-SPECIFIC] enter/exit 4-byte address mode * @octal_dtr_enable: [FLASH-SPECIFIC] enables SPI NOR octal DTR mode. * @ready: [FLASH-SPECIFIC] check if the flash is ready * @dirmap: pointers to struct spi_mem_dirmap_desc for reads/writes. @@ -579,6 +581,7 @@ struct spi_nor { int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); int (*flash_is_unlocked)(struct spi_nor *nor, loff_t ofs, uint64_t len); int (*quad_enable)(struct spi_nor *nor); + int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable); int (*octal_dtr_enable)(struct spi_nor *nor); int (*ready)(struct spi_nor *nor);

On 08.08.2024 09:00, tkuw584924@gmail.com wrote:
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Synchronize set_4byte() with Linux v6.10 as much as possible.
Let's aim for spi-nor/for-v6.12.
Introduce {nor, params}->set_4byte_addr_mode(). The params->set_4byte_addr_mode is initialized with one of the manufacturer specific methods, copied to nor->set_4byte_addr_mode, then it is called from spi_nor_set_4byte_addr_mode() renamed from set_4byte().
this happens indeed. We need to explain why: we aim to split the manufacturer specific code out of the core, thus introduce set_4byte_addr_mode hook so that the manufacturers/SFDP be empowered to pin point a specific 4byte addr mode method.
There are still manufacturer checks here and there.
unfortunately.
And The set_4byte_addr_mode() method in both nor-> and params-> looks redundant. Those should be cleaned up separately in another patch set.
then don't introduce it in the first place :)
The following commits in Linux are related to this patch. 64c160f32235 ("mtd: spi-nor: Create a ->set_4byte() method") 81924dae5194 ("mtd: spi-nor: Emphasise which is the genericset_4byte_addr_mode() method") 076aa4eac8b3 ("mtd: spi-nor: core: Move generic method to core - micron_st_nor_set_4byte_addr_mode") 288df4378319 ("mtd: spi-nor: core: Update name and description of micron_st_nor_set_4byte_addr_mode") f1f1976224f3 ("mtd: spi-nor: core: Update name and description of spansion_set_4byte_addr_mode") b6094ac83dd4 ("mtd: spi-nor: core: Introduce spi_nor_set_4byte_addr_mode()")
yeah, these are good for reference.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com
drivers/mtd/spi/spi-nor-core.c | 179 +++++++++++++++++++++++++-------- include/linux/mtd/spi-nor.h | 3 + 2 files changed, 138 insertions(+), 44 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 8d2afaa0e2..d523c045f4 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -680,54 +680,123 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, } #endif /* !CONFIG_SPI_FLASH_BAR */
-/* Enable/disable 4-byte addressing mode. */ -static int set_4byte(struct spi_nor *nor, const struct flash_info *info,
int enable)
+/**
- spi_nor_set_4byte_addr_mode_en4b_ex4b() - Enter/Exit 4-byte address mode
using SPINOR_OP_EN4B/SPINOR_OP_EX4B. Typically used by
Winbond and Macronix. Cypress also uses SPINOR_OP_EN4B
to enter, but not SPINOR_OP_EX4B to exit.
- @nor: pointer to 'struct spi_nor'.
- @enable: true to enter the 4-byte address mode, false to exit the 4-byte
address mode.
- Return: 0 on success, -errno otherwise.
- */
+static int spi_nor_set_4byte_addr_mode_en4b_ex4b(struct spi_nor *nor,
bool enable)
{
- int status;
- bool need_wren = false;
- u8 cmd;
- u8 opcode;
- int ret;
- switch (JEDEC_MFR(info)) {
- case SNOR_MFR_ST:
- case SNOR_MFR_MICRON:
/* Some Micron need WREN command; all will accept it */
need_wren = true;
fallthrough;
- case SNOR_MFR_ISSI:
- case SNOR_MFR_MACRONIX:
- case SNOR_MFR_WINBOND:
if (need_wren)
write_enable(nor);
- if (enable)
opcode = SPINOR_OP_EN4B;
- else if (JEDEC_MFR(nor->info) == SNOR_MFR_CYPRESS)
opcode = SPINOR_OP_EX4B_CYPRESS;
- else
opcode = SPINOR_OP_EX4B;
cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B;
status = nor->write_reg(nor, cmd, NULL, 0);
if (need_wren)
write_disable(nor);
- ret = nor->write_reg(nor, opcode, NULL, 0);
- if (ret)
return ret;
if (!status && !enable &&
JEDEC_MFR(info) == SNOR_MFR_WINBOND) {
/*
* On Winbond W25Q256FV, leaving 4byte mode causes
* the Extended Address Register to be set to 1, so all
* 3-byte-address reads come from the second 16M.
* We must clear the register to enable normal behavior.
*/
write_enable(nor);
nor->cmd_buf[0] = 0;
nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1);
write_disable(nor);
}
- /*
* On Winbond W25Q256FV, leaving 4byte mode causes the Extended
please follow linux, and introduce winbond_nor_set_4byte_addr_mode() for the chunk below.
* Address Register to be set to 1, so all 3-byte-address reads
* come from the second 16M. We must clear the register to
* enable normal behavior.
*/
- if (!enable && JEDEC_MFR(nor->info) == SNOR_MFR_WINBOND) {
ret = write_enable(nor);
if (ret)
return ret;
return status;
- case SNOR_MFR_CYPRESS:
cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B_CYPRESS;
return nor->write_reg(nor, cmd, NULL, 0);
- default:
/* Spansion style */
nor->cmd_buf[0] = enable << 7;
return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1);
nor->cmd_buf[0] = 0;
ret = nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf,
1);
if (ret)
return ret;
ret = write_disable(nor);
if (ret)
return ret;
- }
- return 0;
+}
+/**
- spi_nor_set_4byte_addr_mode_wren_en4b_ex4b() - Set 4-byte address mode using
SPINOR_OP_WREN followed by SPINOR_OP_EN4B or
SPINOR_OP_EX4B. Typically used by ST and Micron flashes.
- @nor: pointer to 'struct spi_nor'.
- @enable: true to enter the 4-byte address mode, false to exit the 4-byte
address mode.
- Return: 0 on success, -errno otherwise.
- */
+static int spi_nor_set_4byte_addr_mode_wren_en4b_ex4b(struct spi_nor *nor,
bool enable)
+{
- int ret;
- ret = write_enable(nor);
- if (ret)
return ret;
- ret = spi_nor_set_4byte_addr_mode_en4b_ex4b(nor, enable);
- if (ret)
return ret;
- return write_disable(nor);
+}
+/**
- spi_nor_set_4byte_addr_mode_brwr() - Set 4-byte address mode using
SPINOR_OP_BRWR. Typically used by Spansion flashes.
- @nor: pointer to 'struct spi_nor'.
- @enable: true to enter the 4-byte address mode, false to exit the 4-byte
address mode.
- 8-bit volatile bank register used to define A[30:A24] bits. MSB (bit[7]) is
- used to enable/disable 4-byte address mode. When MSB is set to ‘1’, 4-byte
- address mode is active and A[30:24] bits are don’t care. Write instruction is
- SPINOR_OP_BRWR(17h) with 1 byte of data.
- Return: 0 on success, -errno otherwise.
- */
+static int spi_nor_set_4byte_addr_mode_brwr(struct spi_nor *nor, bool enable) +{
- nor->cmd_buf[0] = enable ? BIT(7) : 0;
what's wrong with enable << 7? Keep the code as it was, don't update it on the fly.
- return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1);
+}
+/* Enable/disable 4-byte addressing mode. */ +static int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable) +{
- int ret;
follow linux and do the if (nor->flags & SNOR_F_BROKEN_RESET) check here. You'll have a good debug message for your flashes too ...
- ret = nor->set_4byte_addr_mode(nor, enable);
- if (ret)
return ret;
- if (enable) {
nor->addr_width = 4;
nor->addr_mode_nbytes = 4;
- } else {
nor->addr_width = 3;
}nor->addr_mode_nbytes = 3;
I don't see where were these done previously. Thus don't introduce new code. If needed, make a dedicated patch and explain why you need these.
- return 0;
}
#ifdef CONFIG_SPI_FLASH_SPANSION @@ -2884,6 +2953,25 @@ static int spi_nor_init_params(struct spi_nor *nor, } }
- /* Select the procedure to enter/exit 4-byte address mode. */
- switch (JEDEC_MFR(info)) {
- case SNOR_MFR_ST:
- case SNOR_MFR_MICRON:
params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b;
break;
- case SNOR_MFR_ISSI:
- case SNOR_MFR_MACRONIX:
- case SNOR_MFR_WINBOND:
- case SNOR_MFR_CYPRESS:
params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
break;
- default:
params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_brwr;
break;
- }
follow linux, you need to set these after parsing SFDP
/* Override the parameters with data read from SFDP tables. */ nor->addr_width = 0; nor->mtd.erasesize = 0; @@ -3272,6 +3360,9 @@ static int spi_nor_default_setup(struct spi_nor *nor, else nor->quad_enable = NULL;
- /* Enter/Exit 4-byte address mode */
- nor->set_4byte_addr_mode = params->set_4byte_addr_mode;
you won't need nor->set_4byte_addr_mode, don't introduce it.
As a general comment, follow linux, just move code, don't introduce new code. No changes in functionality shall be expected with this rework.
Looking good, thanks for working on this. Cheers, ta

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
This patch partially ports the Linux commit: 4e53ab0c292d ("mtd: spi-nor: Set the 4-Byte Address Mode method based on SFDP data")
BFPT[DWORD(16)] defines the methods to enter and exit the 4-Byte Address Mode. Parse BFPT to determine the method. Will rename the methods with generic names in a further patch, to keep things trackable in this one.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/spi-nor-core.c | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index d523c045f4..54fd2869a2 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -96,6 +96,7 @@ struct sfdp_header { */ #define BFPT_DWORD(i) ((i) - 1) #define BFPT_DWORD_MAX 20 +#define BFPT_MASK_CHECK(dword, mask) (((dword) & (mask)) == (mask))
/* The first version of JESB216 defined only 9 DWORDs. */ #define BFPT_DWORD_MAX_JESD216 9 @@ -161,6 +162,32 @@ struct sfdp_header { #define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20) #define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */
+#define BFPT_DWORD16_EN4B_MASK GENMASK(31, 24) +#define BFPT_DWORD16_EN4B_ALWAYS_4B BIT(30) +#define BFPT_DWORD16_EN4B_4B_OPCODES BIT(29) +#define BFPT_DWORD16_EN4B_16BIT_NV_CR BIT(28) +#define BFPT_DWORD16_EN4B_BRWR BIT(27) +#define BFPT_DWORD16_EN4B_WREAR BIT(26) +#define BFPT_DWORD16_EN4B_WREN_EN4B BIT(25) +#define BFPT_DWORD16_EN4B_EN4B BIT(24) +#define BFPT_DWORD16_EX4B_MASK GENMASK(18, 14) +#define BFPT_DWORD16_EX4B_16BIT_NV_CR BIT(18) +#define BFPT_DWORD16_EX4B_BRWR BIT(17) +#define BFPT_DWORD16_EX4B_WREAR BIT(16) +#define BFPT_DWORD16_EX4B_WREN_EX4B BIT(15) +#define BFPT_DWORD16_EX4B_EX4B BIT(14) +#define BFPT_DWORD16_4B_ADDR_MODE_MASK \ + (BFPT_DWORD16_EN4B_MASK | BFPT_DWORD16_EX4B_MASK) +#define BFPT_DWORD16_4B_ADDR_MODE_16BIT_NV_CR \ + (BFPT_DWORD16_EN4B_16BIT_NV_CR | BFPT_DWORD16_EX4B_16BIT_NV_CR) +#define BFPT_DWORD16_4B_ADDR_MODE_BRWR \ + (BFPT_DWORD16_EN4B_BRWR | BFPT_DWORD16_EX4B_BRWR) +#define BFPT_DWORD16_4B_ADDR_MODE_WREAR \ + (BFPT_DWORD16_EN4B_WREAR | BFPT_DWORD16_EX4B_WREAR) +#define BFPT_DWORD16_4B_ADDR_MODE_WREN_EN4B_EX4B \ + (BFPT_DWORD16_EN4B_WREN_EN4B | BFPT_DWORD16_EX4B_WREN_EX4B) +#define BFPT_DWORD16_4B_ADDR_MODE_EN4B_EX4B \ + (BFPT_DWORD16_EN4B_EN4B | BFPT_DWORD16_EX4B_EX4B) #define BFPT_DWORD16_SOFT_RST BIT(12) #define BFPT_DWORD16_EX4B_PWRCYC BIT(21)
@@ -2372,7 +2399,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, struct sfdp_bfpt bfpt; size_t len; int i, cmd, err; - u32 addr; + u32 addr, dword; u16 half;
/* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */ @@ -2510,6 +2537,17 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, break; }
+ /* 4-byte address mode entry */ + dword = bfpt.dwords[BFPT_DWORD(16)] & BFPT_DWORD16_4B_ADDR_MODE_MASK; + if (BFPT_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_BRWR)) + params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_brwr; + else if (BFPT_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_WREN_EN4B_EX4B)) + params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b; + else if (BFPT_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_EN4B_EX4B)) + params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b; + else + dev_dbg(nor->dev, "BFPT: 4-Byte Address Mode method is not recognized or not implemented\n"); + /* Soft Reset support. */ if (bfpt.dwords[BFPT_DWORD(16)] & BFPT_DWORD16_SOFT_RST) nor->flags |= SNOR_F_SOFT_RESET;

On 08.08.2024 09:00, tkuw584924@gmail.com wrote:
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
This patch partially ports the Linux commit: 4e53ab0c292d ("mtd: spi-nor: Set the 4-Byte Address Mode method based on SFDP data")
BFPT[DWORD(16)] defines the methods to enter and exit the 4-Byte Address Mode. Parse BFPT to determine the method. Will rename the methods with generic names in a further patch, to keep things trackable in this one.
aren't the names already generic?
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com
drivers/mtd/spi/spi-nor-core.c | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index d523c045f4..54fd2869a2 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -96,6 +96,7 @@ struct sfdp_header { */ #define BFPT_DWORD(i) ((i) - 1) #define BFPT_DWORD_MAX 20 +#define BFPT_MASK_CHECK(dword, mask) (((dword) & (mask)) == (mask))
follow linux, what was wrong with SFDP_MASK_CHECK, why did you rename it?
/* The first version of JESB216 defined only 9 DWORDs. */ #define BFPT_DWORD_MAX_JESD216 9 @@ -161,6 +162,32 @@ struct sfdp_header { #define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20) #define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */
+#define BFPT_DWORD16_EN4B_MASK GENMASK(31, 24) +#define BFPT_DWORD16_EN4B_ALWAYS_4B BIT(30) +#define BFPT_DWORD16_EN4B_4B_OPCODES BIT(29) +#define BFPT_DWORD16_EN4B_16BIT_NV_CR BIT(28) +#define BFPT_DWORD16_EN4B_BRWR BIT(27) +#define BFPT_DWORD16_EN4B_WREAR BIT(26) +#define BFPT_DWORD16_EN4B_WREN_EN4B BIT(25) +#define BFPT_DWORD16_EN4B_EN4B BIT(24) +#define BFPT_DWORD16_EX4B_MASK GENMASK(18, 14) +#define BFPT_DWORD16_EX4B_16BIT_NV_CR BIT(18) +#define BFPT_DWORD16_EX4B_BRWR BIT(17) +#define BFPT_DWORD16_EX4B_WREAR BIT(16) +#define BFPT_DWORD16_EX4B_WREN_EX4B BIT(15) +#define BFPT_DWORD16_EX4B_EX4B BIT(14) +#define BFPT_DWORD16_4B_ADDR_MODE_MASK \
- (BFPT_DWORD16_EN4B_MASK | BFPT_DWORD16_EX4B_MASK)
+#define BFPT_DWORD16_4B_ADDR_MODE_16BIT_NV_CR \
- (BFPT_DWORD16_EN4B_16BIT_NV_CR | BFPT_DWORD16_EX4B_16BIT_NV_CR)
+#define BFPT_DWORD16_4B_ADDR_MODE_BRWR \
- (BFPT_DWORD16_EN4B_BRWR | BFPT_DWORD16_EX4B_BRWR)
+#define BFPT_DWORD16_4B_ADDR_MODE_WREAR \
- (BFPT_DWORD16_EN4B_WREAR | BFPT_DWORD16_EX4B_WREAR)
+#define BFPT_DWORD16_4B_ADDR_MODE_WREN_EN4B_EX4B \
- (BFPT_DWORD16_EN4B_WREN_EN4B | BFPT_DWORD16_EX4B_WREN_EX4B)
+#define BFPT_DWORD16_4B_ADDR_MODE_EN4B_EX4B \
- (BFPT_DWORD16_EN4B_EN4B | BFPT_DWORD16_EX4B_EX4B)
#define BFPT_DWORD16_SOFT_RST BIT(12) #define BFPT_DWORD16_EX4B_PWRCYC BIT(21)
@@ -2372,7 +2399,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, struct sfdp_bfpt bfpt; size_t len; int i, cmd, err;
- u32 addr;
u32 addr, dword; u16 half;
/* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */
@@ -2510,6 +2537,17 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, break; }
- /* 4-byte address mode entry */
- dword = bfpt.dwords[BFPT_DWORD(16)] & BFPT_DWORD16_4B_ADDR_MODE_MASK;
- if (BFPT_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_BRWR))
params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_brwr;
- else if (BFPT_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_WREN_EN4B_EX4B))
params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b;
- else if (BFPT_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_EN4B_EX4B))
params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
- else
dev_dbg(nor->dev, "BFPT: 4-Byte Address Mode method is not recognized or not implemented\n");
you need to specify in the commit message whether SFDP parsing can change the set_4byte_addr_mode set based on MFR and explain what happens.
/* Soft Reset support. */ if (bfpt.dwords[BFPT_DWORD(16)] & BFPT_DWORD16_SOFT_RST) nor->flags |= SNOR_F_SOFT_RESET;

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
This flag is not used in INFO table so checking info->flags has no effect.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/sf_internal.h | 9 ++++----- drivers/mtd/spi/spi-nor-core.c | 5 ++--- 2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index d3ef69ec74..57608750c9 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -64,11 +64,10 @@ struct flash_info { * to support memory size above 128Mib. */ #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ -#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ -#define USE_CLSR BIT(14) /* use CLSR command */ -#define SPI_NOR_HAS_SST26LOCK BIT(15) /* Flash supports lock/unlock via BPR */ -#define SPI_NOR_OCTAL_READ BIT(16) /* Flash supports Octal Read */ -#define SPI_NOR_OCTAL_DTR_READ BIT(17) /* Flash supports Octal DTR Read */ +#define USE_CLSR BIT(13) /* use CLSR command */ +#define SPI_NOR_HAS_SST26LOCK BIT(14) /* Flash supports lock/unlock via BPR */ +#define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */ +#define SPI_NOR_OCTAL_DTR_READ BIT(16) /* Flash supports Octal DTR Read */ };
extern const struct flash_info spi_nor_ids[]; diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 54fd2869a2..feafc48a49 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -3013,9 +3013,8 @@ static int spi_nor_init_params(struct spi_nor *nor, /* Override the parameters with data read from SFDP tables. */ nor->addr_width = 0; nor->mtd.erasesize = 0; - if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | - SPI_NOR_OCTAL_DTR_READ)) && - !(info->flags & SPI_NOR_SKIP_SFDP)) { + if (info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_OCTAL_DTR_READ)) { struct spi_nor_flash_parameter sfdp_params;
memcpy(&sfdp_params, params, sizeof(sfdp_params));

On 08.08.2024 09:00, tkuw584924@gmail.com wrote:
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
This flag is not used in INFO table so checking info->flags has no effect.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com
this patch can be send on its own I guess. Maybe Jagan can take it now:
Reviewed-by: Tudor Ambarus tudor.ambarus@linaro.org
drivers/mtd/spi/sf_internal.h | 9 ++++----- drivers/mtd/spi/spi-nor-core.c | 5 ++--- 2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index d3ef69ec74..57608750c9 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -64,11 +64,10 @@ struct flash_info { * to support memory size above 128Mib. */ #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ -#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ -#define USE_CLSR BIT(14) /* use CLSR command */ -#define SPI_NOR_HAS_SST26LOCK BIT(15) /* Flash supports lock/unlock via BPR */ -#define SPI_NOR_OCTAL_READ BIT(16) /* Flash supports Octal Read */ -#define SPI_NOR_OCTAL_DTR_READ BIT(17) /* Flash supports Octal DTR Read */ +#define USE_CLSR BIT(13) /* use CLSR command */ +#define SPI_NOR_HAS_SST26LOCK BIT(14) /* Flash supports lock/unlock via BPR */ +#define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */ +#define SPI_NOR_OCTAL_DTR_READ BIT(16) /* Flash supports Octal DTR Read */ };
extern const struct flash_info spi_nor_ids[]; diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 54fd2869a2..feafc48a49 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -3013,9 +3013,8 @@ static int spi_nor_init_params(struct spi_nor *nor, /* Override the parameters with data read from SFDP tables. */ nor->addr_width = 0; nor->mtd.erasesize = 0;
- if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_OCTAL_DTR_READ)) &&
!(info->flags & SPI_NOR_SKIP_SFDP)) {
if (info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_OCTAL_DTR_READ)) {
struct spi_nor_flash_parameter sfdp_params;
memcpy(&sfdp_params, params, sizeof(sfdp_params));

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Our SFDP parsing is everything we need to support all basic operations of a flash device. If the flash isn't found in our in-kernel flash database, gracefully fall back to a driver described solely by its SFDP tables.
This patch ports the commit in Linux: 773bbe104497 ("mtd: spi-nor: add generic flash driver")
A new flag named SPI_NOR_PARSE_SFDP is defined to perform SFDP parse for the spi-nor-generic. And spi_nor_read_id() is moved to later part than SFDP functions.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/sf_internal.h | 1 + drivers/mtd/spi/spi-nor-core.c | 95 ++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 26 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 57608750c9..f7b0cea983 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -68,6 +68,7 @@ struct flash_info { #define SPI_NOR_HAS_SST26LOCK BIT(14) /* Flash supports lock/unlock via BPR */ #define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */ #define SPI_NOR_OCTAL_DTR_READ BIT(16) /* Flash supports Octal DTR Read */ +#define SPI_NOR_PARSE_SFDP BIT(17) /* Parse SFDP tables */ };
extern const struct flash_info spi_nor_ids[]; diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index feafc48a49..c1186271a4 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -1509,31 +1509,6 @@ static int stm_is_unlocked(struct spi_nor *nor, loff_t ofs, uint64_t len) #endif /* CONFIG_SPI_FLASH_STMICRO */ #endif
-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) -{ - int tmp; - u8 id[SPI_NOR_MAX_ID_LEN]; - const struct flash_info *info; - - 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); - return ERR_PTR(tmp); - } - - info = spi_nor_ids; - for (; info->name; info++) { - if (info->id_len) { - if (!memcmp(info->id, id, info->id_len)) - return info; - } - } - - dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", - id[0], id[1], id[2]); - return ERR_PTR(-ENODEV); -} - static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { @@ -2154,6 +2129,17 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, }
#if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) + +static const struct flash_info spi_nor_generic_flash = { + .name = "spi-nor-generic", + /* + * JESD216 rev A doesn't specify the page size, therefore we need a + * sane default. + */ + .page_size = 256, + .flags = SPI_NOR_PARSE_SFDP, +}; + /* * Serial Flash Discoverable Parameters (SFDP) parsing. */ @@ -2724,6 +2710,32 @@ out: return ret; }
+/** + * spi_nor_check_sfdp_signature() - check for a valid SFDP signature + * @nor: pointer to a 'struct spi_nor' + * + * Used to detect if the flash supports the RDSFDP command as well as the + * presence of a valid SFDP table. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_check_sfdp_signature(struct spi_nor *nor) +{ + u32 signature; + int err; + + /* Get the SFDP header. */ + err = spi_nor_read_sfdp(nor, 0, sizeof(signature), &signature); + if (err < 0) + return err; + + /* Check the SFDP signature. */ + if (le32_to_cpu(signature) != SFDP_SIGNATURE) + return -EINVAL; + + return 0; +} + /** * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. * @nor: pointer to a 'struct spi_nor' @@ -3014,7 +3026,7 @@ static int spi_nor_init_params(struct spi_nor *nor, nor->addr_width = 0; nor->mtd.erasesize = 0; if (info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | - SPI_NOR_OCTAL_DTR_READ)) { + SPI_NOR_OCTAL_DTR_READ | SPI_NOR_PARSE_SFDP)) { struct spi_nor_flash_parameter sfdp_params;
memcpy(&sfdp_params, params, sizeof(sfdp_params)); @@ -4170,6 +4182,37 @@ void spi_nor_set_fixups(struct spi_nor *nor) #endif /* SPI_FLASH_MACRONIX */ }
+static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) +{ + int tmp; + u8 id[SPI_NOR_MAX_ID_LEN]; + const struct flash_info *info; + + 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); + return ERR_PTR(tmp); + } + + info = spi_nor_ids; + for (; info->name; info++) { + if (info->id_len) { + if (!memcmp(info->id, id, info->id_len)) + return info; + } + } + +#if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) + /* Fallback to a generic flash described only by its SFDP data. */ + if (!spi_nor_check_sfdp_signature(nor)) + return &spi_nor_generic_flash; +#endif + + dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", + id[0], id[1], id[2]); + return ERR_PTR(-ENODEV); +} + int spi_nor_scan(struct spi_nor *nor) { struct spi_nor_flash_parameter params;

On 08.08.2024 09:00, tkuw584924@gmail.com wrote:
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Our SFDP parsing is everything we need to support all basic operations of a flash device. If the flash isn't found in our in-kernel flash database, gracefully fall back to a driver described solely by its SFDP tables.
This patch ports the commit in Linux: 773bbe104497 ("mtd: spi-nor: add generic flash driver")
This info shall be the first info in the commit message.
A new flag named SPI_NOR_PARSE_SFDP is defined to perform SFDP parse for the spi-nor-generic. And spi_nor_read_id() is moved to later part than SFDP functions.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com
drivers/mtd/spi/sf_internal.h | 1 + drivers/mtd/spi/spi-nor-core.c | 95 ++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 26 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 57608750c9..f7b0cea983 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -68,6 +68,7 @@ struct flash_info { #define SPI_NOR_HAS_SST26LOCK BIT(14) /* Flash supports lock/unlock via BPR */ #define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */ #define SPI_NOR_OCTAL_DTR_READ BIT(16) /* Flash supports Octal DTR Read */ +#define SPI_NOR_PARSE_SFDP BIT(17) /* Parse SFDP tables */ };
extern const struct flash_info spi_nor_ids[]; diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index feafc48a49..c1186271a4 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -1509,31 +1509,6 @@ static int stm_is_unlocked(struct spi_nor *nor, loff_t ofs, uint64_t len) #endif /* CONFIG_SPI_FLASH_STMICRO */ #endif
-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) -{
- int tmp;
- u8 id[SPI_NOR_MAX_ID_LEN];
- const struct flash_info *info;
- 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);
return ERR_PTR(tmp);
- }
- info = spi_nor_ids;
- for (; info->name; info++) {
if (info->id_len) {
if (!memcmp(info->id, id, info->id_len))
return info;
}
- }
- dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n",
id[0], id[1], id[2]);
- return ERR_PTR(-ENODEV);
-}
the linux commit didn't move code around, so don't do it here. If needed specify why and do it in a dedicated commit. If you care about not mixing sfdp code with core code, let's late on introduce sfdp.c.
static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { @@ -2154,6 +2129,17 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, }
#if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT)
+static const struct flash_info spi_nor_generic_flash = {
- .name = "spi-nor-generic",
- /*
* JESD216 rev A doesn't specify the page size, therefore we need a
* sane default.
*/
- .page_size = 256,
- .flags = SPI_NOR_PARSE_SFDP,
what was wrong with .parse_sfdp = true ?
participants (2)
-
tkuw584924@gmail.com
-
Tudor Ambarus