From ee7296bbcd6bae3ded087cb56c786da10aa6fc6a Mon Sep 17 00:00:00 2001 From: Takahiro Kuwano Date: Fri, 20 Jan 2023 12:28:21 +0900 Subject: mtd: spi-nor-core: Consider reserved bits in CFR5 register CFR5[6] is reserved bit and must be always 1. Set it to comply with flash requirements. While fixing SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN definition, stop using magic numbers and describe the missing bit fields in CFR5 register. This is useful for both readability and future possible addition of Octal STR mode support. Fixes: ea9a22f7e79c ("mtd: spi-nor-core: Add support for Cypress Semper flash") Suggested-by: Tudor Ambarus Signed-off-by: Takahiro Kuwano Reviewed-by: Tudor Ambarus Reviewed-by: Dhruva Gole Reviewed-by: Jagan Teki --- include/linux/mtd/spi-nor.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 30f15452aa6..2fb4595fc75 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -194,7 +194,12 @@ #define SPINOR_REG_CYPRESS_CFR3V_PGSZ BIT(4) /* Page size. */ #define SPINOR_REG_CYPRESS_CFR3V_UNISECT BIT(3) /* Uniform sector mode */ #define SPINOR_REG_CYPRESS_CFR5V 0x00800006 -#define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN 0x3 +#define SPINOR_REG_CYPRESS_CFR5_BIT6 BIT(6) +#define SPINOR_REG_CYPRESS_CFR5_DDR BIT(1) +#define SPINOR_REG_CYPRESS_CFR5_OPI BIT(0) +#define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN \ + (SPINOR_REG_CYPRESS_CFR5_BIT6 | SPINOR_REG_CYPRESS_CFR5_DDR | \ + SPINOR_REG_CYPRESS_CFR5_OPI) #define SPINOR_OP_CYPRESS_RD_FAST 0xee /* Supported SPI protocols */ -- cgit v1.3.1 From da16d72efd004e046b8b4f98a662afd4bef09206 Mon Sep 17 00:00:00 2001 From: Takahiro Kuwano Date: Fri, 20 Jan 2023 12:28:22 +0900 Subject: mtd: spi-nor-core: Make CFRx reg fields generic Cypress defines two flavors of configuration registers, volatile and non volatile, and both use the same bit fields. Rename the bitfields in the configuration registers so that they can be used for both flavors. Suggested-by: Tudor Ambarus Signed-off-by: Takahiro Kuwano Reviewed-by: Tudor Ambarus Reviewed-by: Dhruva Gole Reviewed-by: Jagan Teki --- drivers/mtd/spi/spi-nor-core.c | 8 ++++---- include/linux/mtd/spi-nor.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 1ea8363d9f8..a3198253ca6 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -3373,7 +3373,7 @@ static int spi_nor_cypress_octal_dtr_enable(struct spi_nor *nor) if (ret) return ret; - buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24; + buf = SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24; op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1), SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR2V, 1), SPI_MEM_OP_NO_DUMMY, @@ -3396,7 +3396,7 @@ static int spi_nor_cypress_octal_dtr_enable(struct spi_nor *nor) if (ret) return ret; - buf = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN; + buf = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN; op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1), SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR5V, 1), SPI_MEM_OP_NO_DUMMY, @@ -3444,7 +3444,7 @@ static int s28hx_t_setup(struct spi_nor *nor, const struct flash_info *info, if (ret) return ret; - if (!(buf & SPINOR_REG_CYPRESS_CFR3V_UNISECT)) + if (!(buf & SPINOR_REG_CYPRESS_CFR3_UNISECT)) nor->erase = s28hx_t_erase_non_uniform; return spi_nor_default_setup(nor, info, params); @@ -3511,7 +3511,7 @@ static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor, if (ret) return ret; - if (buf & SPINOR_REG_CYPRESS_CFR3V_PGSZ) + if (buf & SPINOR_REG_CYPRESS_CFR3_PGSZ) params->page_size = 512; else params->page_size = 256; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 2fb4595fc75..605cddef4d0 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -189,15 +189,15 @@ #define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */ #define SPINOR_OP_S28_SE_4K 0x21 #define SPINOR_REG_CYPRESS_CFR2V 0x00800003 -#define SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24 0xb +#define SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24 0xb #define SPINOR_REG_CYPRESS_CFR3V 0x00800004 -#define SPINOR_REG_CYPRESS_CFR3V_PGSZ BIT(4) /* Page size. */ -#define SPINOR_REG_CYPRESS_CFR3V_UNISECT BIT(3) /* Uniform sector mode */ +#define SPINOR_REG_CYPRESS_CFR3_PGSZ BIT(4) /* Page size. */ +#define SPINOR_REG_CYPRESS_CFR3_UNISECT BIT(3) /* Uniform sector mode */ #define SPINOR_REG_CYPRESS_CFR5V 0x00800006 #define SPINOR_REG_CYPRESS_CFR5_BIT6 BIT(6) #define SPINOR_REG_CYPRESS_CFR5_DDR BIT(1) #define SPINOR_REG_CYPRESS_CFR5_OPI BIT(0) -#define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN \ +#define SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN \ (SPINOR_REG_CYPRESS_CFR5_BIT6 | SPINOR_REG_CYPRESS_CFR5_DDR | \ SPINOR_REG_CYPRESS_CFR5_OPI) #define SPINOR_OP_CYPRESS_RD_FAST 0xee -- cgit v1.3.1 From 87a6d86571268be4e354fe030c53745a54f4ed8e Mon Sep 17 00:00:00 2001 From: Takahiro Kuwano Date: Mon, 19 Dec 2022 10:28:21 +0900 Subject: 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(-) (limited to 'include/linux') diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 7d42ba9ff8f..2c3116ee530 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 5f8f3ec955d..a862fbd707b 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 605cddef4d0..2861b73edbc 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 */ -- cgit v1.3.1