[PATCH 0/2] Add support for Infineon s25fs256t

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Infineon S25FS256T is 256Mb QSPI NOR Flash. https://www.infineon.com/dgdlac/Infineon-S25FS256T_256Mb_SEMPER_Nano_Flash_Q...
Tested on Xilinx Zynq-7000 FPGA board.
Takahiro Kuwano (2): mtd: spi-nor: s/s25hx_t/s25 mtd: spi-nor: Add support for s25fs256t
drivers/mtd/spi/spi-nor-core.c | 87 ++++++++++++++++++++++------------ drivers/mtd/spi/spi-nor-ids.c | 2 + include/linux/mtd/spi-nor.h | 1 + 3 files changed, 61 insertions(+), 29 deletions(-)

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Rename s25hx_t prefix to s25 so that the single set of fixup hooks can support all other S25 families.
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/spi-nor-core.c | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 1ea8363d9f89..4e8b4a6769dd 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -3195,7 +3195,7 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, }
#ifdef CONFIG_SPI_FLASH_SPANSION -static int s25hx_t_mdp_ready(struct spi_nor *nor) +static int s25_mdp_ready(struct spi_nor *nor) { u32 addr; int ret; @@ -3209,7 +3209,7 @@ static int s25hx_t_mdp_ready(struct spi_nor *nor) return 1; }
-static int s25hx_t_quad_enable(struct spi_nor *nor) +static int s25_quad_enable(struct spi_nor *nor) { u32 addr; int ret; @@ -3223,15 +3223,15 @@ static int s25hx_t_quad_enable(struct spi_nor *nor) return 0; }
-static int s25hx_t_erase_non_uniform(struct spi_nor *nor, loff_t addr) +static int s25_erase_non_uniform(struct spi_nor *nor, loff_t addr) { /* Support 32 x 4KB sectors at bottom */ return spansion_erase_non_uniform(nor, addr, SPINOR_OP_BE_4K_4B, 0, SZ_128K); }
-static int s25hx_t_setup(struct spi_nor *nor, const struct flash_info *info, - const struct spi_nor_flash_parameter *params) +static int s25_setup(struct spi_nor *nor, const struct flash_info *info, + const struct spi_nor_flash_parameter *params) { int ret; u8 cfr3v; @@ -3247,27 +3247,27 @@ static int s25hx_t_setup(struct spi_nor *nor, const struct flash_info *info, if (ret) return ret; if (!(cfr3v & CFR3V_UNHYSA)) - nor->erase = s25hx_t_erase_non_uniform; + nor->erase = s25_erase_non_uniform;
/* * For the multi-die package parts, the ready() hook is needed to check * all dies' status via read any register. */ if (nor->mtd.size > SZ_128M) - nor->ready = s25hx_t_mdp_ready; + nor->ready = s25_mdp_ready;
return spi_nor_default_setup(nor, info, params); }
-static void s25hx_t_default_init(struct spi_nor *nor) +static void s25_default_init(struct spi_nor *nor) { - nor->setup = s25hx_t_setup; + nor->setup = s25_setup; }
-static int s25hx_t_post_bfpt_fixup(struct spi_nor *nor, - const struct sfdp_parameter_header *header, - const struct sfdp_bfpt *bfpt, - struct spi_nor_flash_parameter *params) +static int s25_post_bfpt_fixup(struct spi_nor *nor, + const struct sfdp_parameter_header *header, + const struct sfdp_bfpt *bfpt, + struct spi_nor_flash_parameter *params) { int ret; u32 addr; @@ -3318,21 +3318,21 @@ static int s25hx_t_post_bfpt_fixup(struct spi_nor *nor, return 0; }
-static void s25hx_t_post_sfdp_fixup(struct spi_nor *nor, - struct spi_nor_flash_parameter *params) +static void s25_post_sfdp_fixup(struct spi_nor *nor, + struct spi_nor_flash_parameter *params) { /* READ_FAST_4B (0Ch) requires mode cycles*/ params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8; /* PP_1_1_4 is not supported */ params->hwcaps.mask &= ~SNOR_HWCAPS_PP_1_1_4; /* Use volatile register to enable quad */ - params->quad_enable = s25hx_t_quad_enable; + params->quad_enable = s25_quad_enable; }
-static struct spi_nor_fixups s25hx_t_fixups = { - .default_init = s25hx_t_default_init, - .post_bfpt = s25hx_t_post_bfpt_fixup, - .post_sfdp = s25hx_t_post_sfdp_fixup, +static struct spi_nor_fixups s25_fixups = { + .default_init = s25_default_init, + .post_bfpt = s25_post_bfpt_fixup, + .post_sfdp = s25_post_sfdp_fixup, };
static int s25fl256l_setup(struct spi_nor *nor, const struct flash_info *info, @@ -3850,7 +3850,7 @@ void spi_nor_set_fixups(struct spi_nor *nor) switch (nor->info->id[1]) { case 0x2a: /* S25HL (QSPI, 3.3V) */ case 0x2b: /* S25HS (QSPI, 1.8V) */ - nor->fixups = &s25hx_t_fixups; + nor->fixups = &s25_fixups; break;
#ifdef CONFIG_SPI_FLASH_S28HX_T

On 19/12/22 06:58, tkuw584924@gmail.com wrote:
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Rename s25hx_t prefix to s25 so that the single set of fixup hooks can support all other S25 families.
Sure, I also think we can go for just s25 naming now instead of s25hx_t... if s25 family is similar in that aspect.
Acked-by: Dhruva Gole d-gole@ti.com
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com
drivers/mtd/spi/spi-nor-core.c | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 1ea8363d9f89..4e8b4a6769dd 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -3195,7 +3195,7 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, }
#ifdef CONFIG_SPI_FLASH_SPANSION -static int s25hx_t_mdp_ready(struct spi_nor *nor) +static int s25_mdp_ready(struct spi_nor *nor) { u32 addr; int ret; @@ -3209,7 +3209,7 @@ static int s25hx_t_mdp_ready(struct spi_nor *nor) return 1; }
-static int s25hx_t_quad_enable(struct spi_nor *nor) +static int s25_quad_enable(struct spi_nor *nor) { u32 addr; int ret; @@ -3223,15 +3223,15 @@ static int s25hx_t_quad_enable(struct spi_nor *nor) return 0; }
-static int s25hx_t_erase_non_uniform(struct spi_nor *nor, loff_t addr) +static int s25_erase_non_uniform(struct spi_nor *nor, loff_t addr) { /* Support 32 x 4KB sectors at bottom */ return spansion_erase_non_uniform(nor, addr, SPINOR_OP_BE_4K_4B, 0, SZ_128K); }
-static int s25hx_t_setup(struct spi_nor *nor, const struct flash_info *info,
const struct spi_nor_flash_parameter *params)
+static int s25_setup(struct spi_nor *nor, const struct flash_info *info,
{ int ret; u8 cfr3v;const struct spi_nor_flash_parameter *params)
@@ -3247,27 +3247,27 @@ static int s25hx_t_setup(struct spi_nor *nor, const struct flash_info *info, if (ret) return ret; if (!(cfr3v & CFR3V_UNHYSA))
nor->erase = s25hx_t_erase_non_uniform;
nor->erase = s25_erase_non_uniform;
/*
- For the multi-die package parts, the ready() hook is needed to check
- all dies' status via read any register.
*/ if (nor->mtd.size > SZ_128M)
nor->ready = s25hx_t_mdp_ready;
nor->ready = s25_mdp_ready;
return spi_nor_default_setup(nor, info, params); }
-static void s25hx_t_default_init(struct spi_nor *nor) +static void s25_default_init(struct spi_nor *nor) {
- nor->setup = s25hx_t_setup;
- nor->setup = s25_setup; }
-static int s25hx_t_post_bfpt_fixup(struct spi_nor *nor,
const struct sfdp_parameter_header *header,
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params)
+static int s25_post_bfpt_fixup(struct spi_nor *nor,
const struct sfdp_parameter_header *header,
const struct sfdp_bfpt *bfpt,
{ int ret; u32 addr;struct spi_nor_flash_parameter *params)
@@ -3318,21 +3318,21 @@ static int s25hx_t_post_bfpt_fixup(struct spi_nor *nor, return 0; }
-static void s25hx_t_post_sfdp_fixup(struct spi_nor *nor,
struct spi_nor_flash_parameter *params)
+static void s25_post_sfdp_fixup(struct spi_nor *nor,
{ /* READ_FAST_4B (0Ch) requires mode cycles*/ params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8; /* PP_1_1_4 is not supported */ params->hwcaps.mask &= ~SNOR_HWCAPS_PP_1_1_4; /* Use volatile register to enable quad */struct spi_nor_flash_parameter *params)
- params->quad_enable = s25hx_t_quad_enable;
- params->quad_enable = s25_quad_enable; }
-static struct spi_nor_fixups s25hx_t_fixups = {
- .default_init = s25hx_t_default_init,
- .post_bfpt = s25hx_t_post_bfpt_fixup,
- .post_sfdp = s25hx_t_post_sfdp_fixup,
+static struct spi_nor_fixups s25_fixups = {
.default_init = s25_default_init,
.post_bfpt = s25_post_bfpt_fixup,
.post_sfdp = s25_post_sfdp_fixup, };
static int s25fl256l_setup(struct spi_nor *nor, const struct flash_info *info,
@@ -3850,7 +3850,7 @@ void spi_nor_set_fixups(struct spi_nor *nor) switch (nor->info->id[1]) { case 0x2a: /* S25HL (QSPI, 3.3V) */ case 0x2b: /* S25HS (QSPI, 1.8V) */
nor->fixups = &s25hx_t_fixups;
nor->fixups = &s25_fixups; break;
#ifdef CONFIG_SPI_FLASH_S28HX_T

From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Infineon S25FS256T is 256Mbit Quad SPI NOR flash. The key features and differences comparing to other Spansion/Cypress flash familes are: - 4-byte address mode by factory default - Quad mode is enabled by factory default - Supports mixture of 128KB and 64KB sectors by OTP configuration (this patch supports uniform 128KB only)
Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com --- drivers/mtd/spi/spi-nor-core.c | 47 +++++++++++++++++++++++++++------- drivers/mtd/spi/spi-nor-ids.c | 2 ++ include/linux/mtd/spi-nor.h | 1 + 3 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 4e8b4a6769dd..f25b56d9c899 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -3195,6 +3195,10 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, }
#ifdef CONFIG_SPI_FLASH_SPANSION + +/* Use ID byte 4 to distinguish S25FS256T and S25Hx-T */ +#define S25FS256T_ID4 (0x08) + static int s25_mdp_ready(struct spi_nor *nor) { u32 addr; @@ -3234,19 +3238,35 @@ static int s25_setup(struct spi_nor *nor, const struct flash_info *info, const struct spi_nor_flash_parameter *params) { int ret; - u8 cfr3v; + u8 cr;
#ifdef CONFIG_SPI_FLASH_BAR return -ENOTSUPP; /* Bank Address Register is not supported */ #endif + /* + * S25FS256T has multiple sector architecture options, with selection of + * count and location of 128KB and 64KB sectors. This driver supports + * uniform 128KB only due to complexity of non-uniform layout. + */ + if (nor->info->id[4] == S25FS256T_ID4) { + ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_ARCFN, 8, &cr); + if (ret) + return ret; + + if (cr) /* Option 0 (ARCFN[7:0] == 0x00) is uniform */ + return -EOPNOTSUPP; + + return spi_nor_default_setup(nor, info, params); + } + /* * Read CFR3V to check if uniform sector is selected. If not, assign an * erase hook that supports non-uniform erase. */ - ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_CFR3V, 0, &cfr3v); + ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_CFR3V, 0, &cr); if (ret) return ret; - if (!(cfr3v & CFR3V_UNHYSA)) + if (!(cr & CFR3V_UNHYSA)) nor->erase = s25_erase_non_uniform;
/* @@ -3296,6 +3316,10 @@ static int s25_post_bfpt_fixup(struct spi_nor *nor, nor->addr_mode_nbytes = 4; }
+ /* The default address mode in S25FS256T is 4. */ + if (nor->info->id[4] == S25FS256T_ID4) + nor->addr_mode_nbytes = 4; + /* * The page_size is set to 512B from BFPT, but it actually depends on * the configuration register. Look up the CFR3V and determine the @@ -3321,12 +3345,17 @@ static int s25_post_bfpt_fixup(struct spi_nor *nor, static void s25_post_sfdp_fixup(struct spi_nor *nor, struct spi_nor_flash_parameter *params) { - /* READ_FAST_4B (0Ch) requires mode cycles*/ - params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8; - /* PP_1_1_4 is not supported */ - params->hwcaps.mask &= ~SNOR_HWCAPS_PP_1_1_4; - /* Use volatile register to enable quad */ - params->quad_enable = s25_quad_enable; + if (nor->info->id[4] == S25FS256T_ID4) { + /* PP_1_1_4 is supported */ + params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4; + } else { + /* READ_FAST_4B (0Ch) requires mode cycles*/ + params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8; + /* PP_1_1_4 is not supported */ + params->hwcaps.mask &= ~SNOR_HWCAPS_PP_1_1_4; + /* Use volatile register to enable quad */ + params->quad_enable = s25_quad_enable; + } }
static struct spi_nor_fixups s25_fixups = { diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index 5f8f3ec955d9..a862fbd707b3 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -294,6 +294,8 @@ const struct flash_info spi_nor_ids[] = { USE_CLSR) }, { INFO6("s25hs02gt", 0x342b1c, 0x0f0090, 256 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO6("s25fs256t", 0x342b19, 0x0f0890, 128 * 1024, 256, + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, #ifdef CONFIG_SPI_FLASH_S28HX_T { INFO("s28hl512t", 0x345a1a, 0, 256 * 1024, 256, SPI_NOR_OCTAL_DTR_READ) }, { INFO("s28hl01gt", 0x345a1b, 0, 256 * 1024, 512, SPI_NOR_OCTAL_DTR_READ) }, diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 30f15452aa68..13cfaf2b2da4 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -141,6 +141,7 @@ #define SPINOR_REG_ADDR_STR1V 0x00800000 #define SPINOR_REG_ADDR_CFR1V 0x00800002 #define SPINOR_REG_ADDR_CFR3V 0x00800004 +#define SPINOR_REG_ADDR_ARCFN 0x00000006 #define CFR3V_UNHYSA BIT(3) /* Uniform sectors or not */ #define CFR3V_PGMBUF BIT(4) /* Program buffer size */

On Mon, Dec 19, 2022 at 6:59 AM tkuw584924@gmail.com wrote:
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
Infineon S25FS256T is 256Mb QSPI NOR Flash. https://www.infineon.com/dgdlac/Infineon-S25FS256T_256Mb_SEMPER_Nano_Flash_Q...
Tested on Xilinx Zynq-7000 FPGA board.
Takahiro Kuwano (2): mtd: spi-nor: s/s25hx_t/s25 mtd: spi-nor: Add support for s25fs256t
Applied to u-boot-spi/master
participants (3)
-
Dhruva Gole
-
Jagan Teki
-
tkuw584924@gmail.com