[PATCH 0/4] mtd: spi-nor-core: Track flash's internal address mode in s25hx-t

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
For S25hx-T support in Linux (single die package only), flash's internal address mode is not changed and it is assumed as factory default. Current implementation of u-boot forces to 4-byte address mode while some parts are 3-byte address mode by default. That will cause a problem when we use u-boot to load the Linux kernel. This series tries to avoid the problem, by porting two changes from linux [0][1] and additional rework.
[0] https://patchwork.ozlabs.org/project/linux-mtd/patch/20200525091544.17270-7-... [1] https://patchwork.ozlabs.org/project/linux-mtd/patch/20220725092505.446315-6...
Takahiro Kuwano (4): mtd: spi-nor-core: Default to addr_width of 3 for configurable widths mtd: spi-nor-core: Track flash's internal address mode mtd: spi-nor-core: Rework spansion_read/write_any_reg() to use addr_mode_nbytes mtd: spi-nor-core: Rework s25hx_t_post_bfpt_fixup() for flash's internal address mode
drivers/mtd/spi/spi-nor-core.c | 42 ++++++++++++++++++++++++---------- include/linux/mtd/spi-nor.h | 5 ++++ 2 files changed, 35 insertions(+), 12 deletions(-)

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
JESD216D-01 mentions that "defaults to 3-Byte mode; enters 4-Byte mode on command."
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/spi-nor-core.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index e3c86e080a..90d0f769f0 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -2213,6 +2213,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, /* Number of address bytes. */ switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) { case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: + case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4: nor->addr_width = 3; break;

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
The nor->addr_width tracks number of address bytes used in read/program/erase ops and eventually set to 4 for >16MB chips, regardless of flash's internal address mode. For Infineon SEMPER flash's, we use Read/Write Any Register commands for configuration and status check. These commands take 3- or 4-byte address depending on flash's internal address mode.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/spi-nor-core.c | 2 ++ include/linux/mtd/spi-nor.h | 5 +++++ 2 files changed, 7 insertions(+)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 90d0f769f0..360fc9aff1 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -2215,10 +2215,12 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4: nor->addr_width = 3; + nor->addr_mode_nbytes = 3; break;
case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY: nor->addr_width = 4; + nor->addr_mode_nbytes = 4; break;
default: diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 2595bad9df..4422fd006d 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -493,6 +493,10 @@ struct spi_flash { * @rdsr_dummy dummy cycles needed for Read Status Register command. * @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register * command. + * @addr_mode_nbytes: number of address bytes of current address mode. Useful + * when the flash operates with 4B opcodes but needs the + * internal address mode for opcodes that don't have a 4B + * opcode correspondent. * @bank_read_cmd: Bank read cmd * @bank_write_cmd: Bank write cmd * @bank_curr: Current flash bank @@ -538,6 +542,7 @@ struct spi_nor { u8 program_opcode; u8 rdsr_dummy; u8 rdsr_addr_nbytes; + u8 addr_mode_nbytes; #ifdef CONFIG_SPI_FLASH_BAR u8 bank_read_cmd; u8 bank_write_cmd;

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Read/Write Any Register commands take 3- or 4- byte address depending on flash's internal address mode. The nor->addr_width tracks number of address bytes used in read/program/erase ops that can be 4 (with 4B opcodes) regardless of flash's internal address mode. The nor->addr_mode_nbytes tracks flash's internal address mode so replace nor->addr_width by that.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/spi-nor-core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 360fc9aff1..9f08970188 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -329,10 +329,10 @@ static int spansion_read_any_reg(struct spi_nor *nor, u32 addr, u8 dummy, u8 *val) { struct spi_mem_op op = - SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDAR, 1), - SPI_MEM_OP_ADDR(nor->addr_width, addr, 1), - SPI_MEM_OP_DUMMY(dummy / 8, 1), - SPI_MEM_OP_DATA_IN(1, NULL, 1)); + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDAR, 1), + SPI_MEM_OP_ADDR(nor->addr_mode_nbytes, addr, 1), + SPI_MEM_OP_DUMMY(dummy / 8, 1), + SPI_MEM_OP_DATA_IN(1, NULL, 1));
return spi_nor_read_write_reg(nor, &op, val); } @@ -340,10 +340,10 @@ static int spansion_read_any_reg(struct spi_nor *nor, u32 addr, u8 dummy, static int spansion_write_any_reg(struct spi_nor *nor, u32 addr, u8 val) { struct spi_mem_op op = - SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRAR, 1), - SPI_MEM_OP_ADDR(nor->addr_width, addr, 1), - SPI_MEM_OP_NO_DUMMY, - SPI_MEM_OP_DATA_OUT(1, NULL, 1)); + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRAR, 1), + SPI_MEM_OP_ADDR(nor->addr_mode_nbytes, addr, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(1, NULL, 1));
return spi_nor_read_write_reg(nor, &op, &val); }

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
The flash's internal address mode is tracked by nor->add_mode_nbytes and it is set to 3 in BFPT parse. SEMPER multi-die package parts (>1Gb) are 3- or 4-byte address mode by default, depending on model number. We need to make sure that 4-byte address mode is used for multi-die package parts.
For single-die package parts (<=1Gb), registers can be accessed by 3-byte address. Read, program, and erase use the 4B opcodes that always take 4-byte address regardless of flash's internal address mode.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/spi-nor-core.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 9f08970188..0cbc647710 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -161,6 +161,7 @@ struct sfdp_header { #define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */
#define BFPT_DWORD16_SOFT_RST BIT(12) +#define BFPT_DWORD16_EX4B_PWRCYC BIT(21)
#define BFPT_DWORD18_CMD_EXT_MASK GENMASK(30, 29) #define BFPT_DWORD18_CMD_EXT_REP (0x0UL << 29) /* Repeat */ @@ -3253,10 +3254,24 @@ static int s25hx_t_post_bfpt_fixup(struct spi_nor *nor, nor->erase_opcode = SPINOR_OP_SE_4B; nor->mtd.erasesize = nor->info->sector_size;
- ret = set_4byte(nor, nor->info, 1); - if (ret) - return ret; - nor->addr_width = 4; + /* + * The default address mode in multi-die package parts (>1Gb) may be + * 3- or 4-byte, depending on model number. BootROM code in some SoCs + * use 3-byte mode for backward compatibility and should switch to + * 4-byte mode after BootROM phase. Since registers in the 2nd die are + * mapped within 32-bit address space, we need to make sure the flash is + * in 4-byte address mode. The default address mode can be distinguished + * by BFPT 16th DWORD. Power cycle exits 4-byte address mode if default + * is 3-byte address mode. + */ + if (params->size > SZ_128M) { + if (bfpt->dwords[BFPT_DWORD(16)] & BFPT_DWORD16_EX4B_PWRCYC) { + ret = set_4byte(nor, nor->info, 1); + if (ret) + return ret; + } + nor->addr_mode_nbytes = 4; + }
/* * The page_size is set to 512B from BFPT, but it actually depends on

On Thu, Sep 1, 2022 at 11:36 AM tkuw584924@gmail.com wrote:
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
For S25hx-T support in Linux (single die package only), flash's internal address mode is not changed and it is assumed as factory default. Current implementation of u-boot forces to 4-byte address mode while some parts are 3-byte address mode by default. That will cause a problem when we use u-boot to load the Linux kernel. This series tries to avoid the problem, by porting two changes from linux [0][1] and additional rework.
[0] https://patchwork.ozlabs.org/project/linux-mtd/patch/20200525091544.17270-7-... [1] https://patchwork.ozlabs.org/project/linux-mtd/patch/20220725092505.446315-6...
Takahiro Kuwano (4): mtd: spi-nor-core: Default to addr_width of 3 for configurable widths mtd: spi-nor-core: Track flash's internal address mode mtd: spi-nor-core: Rework spansion_read/write_any_reg() to use addr_mode_nbytes mtd: spi-nor-core: Rework s25hx_t_post_bfpt_fixup() for flash's internal address mode
Applied to u-boot-spi/master
participants (2)
-
Jagan Teki
-
tkuw584924@gmail.com