From 87a6d86571268be4e354fe030c53745a54f4ed8e Mon Sep 17 00:00:00 2001 From: Takahiro Kuwano Date: Mon, 19 Dec 2022 10:28:21 +0900 Subject: [PATCH] mtd: spi-nor: Add support for Infineon s25fs256t 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 Reviewed-by: Jagan Teki --- 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 7d42ba9ff8..2c3116ee53 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 5f8f3ec955..a862fbd707 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 605cddef4d..2861b73edb 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 */ -- 2.39.5