Message ID | 20220503081627.341870-9-tudor.ambarus@microchip.com |
---|---|
State | Changes Requested |
Delegated to: | Pratyush Yadav |
Headers | show |
Series | mtd: spi-nor: Add support for Infineon s25hl-t/s25hs-t | expand |
Hi Tudor, On 5/3/2022 5:16 PM, Tudor Ambarus wrote: > From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> > > The S25HL-T/S25HS-T family is the Infineon SEMPER Flash with Quad SPI. > > These Infineon chips support volatile version of configuration registers > and it is recommended to update volatile registers in the field application > due to a risk of the non-volatile registers corruption by power interrupt. > Add support for volatile QE bit. > > For the single-die package parts (512Mb and 1Gb), only bottom 4KB and > uniform sector sizes are supported. This is due to missing or incorrect > entries in SMPT. Fixup for other sector sizes configurations will be > followed up as needed. > > Tested on Xilinx Zynq-7000 FPGA board. > > Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> > Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> > --- > drivers/mtd/spi-nor/spansion.c | 125 +++++++++++++++++++++++++++++++++ > 1 file changed, 125 insertions(+) > > diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c > index e130f5398763..f78a15b985ea 100644 > --- a/drivers/mtd/spi-nor/spansion.c > +++ b/drivers/mtd/spi-nor/spansion.c > @@ -14,6 +14,8 @@ > #define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */ > #define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */ > #define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */ > +#define SPINOR_REG_CYPRESS_CFR1V 0x00800002 > +#define SPINOR_REG_CYPRESS_CFR1V_QUAD_EN BIT(1) /* Quad Enable */ > #define SPINOR_REG_CYPRESS_CFR2V 0x00800003 > #define SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24 0xb > #define SPINOR_REG_CYPRESS_CFR3V 0x00800004 > @@ -113,6 +115,63 @@ static int cypress_nor_octal_dtr_dis(struct spi_nor *nor) > return 0; > } > > +/** > + * cypress_nor_quad_enable_volatile() - enable Quad I/O mode in volatile > + * register. > + * @nor: pointer to a 'struct spi_nor' > + * > + * It is recommended to update volatile registers in the field application due > + * to a risk of the non-volatile registers corruption by power interrupt. This > + * function sets Quad Enable bit in CFR1 volatile. If users set the Quad Enable > + * bit in the CFR1 non-volatile in advance (typically by a Flash programmer > + * before mounting Flash on PCB), the Quad Enable bit in the CFR1 volatile is > + * also set during Flash power-up. > + * > + * Return: 0 on success, -errno otherwise. > + */ > +static int cypress_nor_quad_enable_volatile(struct spi_nor *nor) > +{ > + struct spi_mem_op op; > + u8 cfr1v_written; > + int ret; > + > + op = (struct spi_mem_op) > + CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_nbytes, > + SPINOR_REG_CYPRESS_CFR1V, > + nor->bouncebuf); > + The following lines are missing. ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); if (ret) return ret; > + if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR1V_QUAD_EN) > + return 0; > + > + /* Update the Quad Enable bit. */ > + nor->bouncebuf[0] |= SPINOR_REG_CYPRESS_CFR1V_QUAD_EN; > + op = (struct spi_mem_op) > + CYPRESS_NOR_WR_ANY_REG_OP(nor->params->addr_nbytes, > + SPINOR_REG_CYPRESS_CFR1V, 1, > + nor->bouncebuf); > + ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto); > + if (ret) > + return ret; > + > + cfr1v_written = nor->bouncebuf[0]; > + > + /* Read back and check it. */ > + op = (struct spi_mem_op) > + CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_nbytes, > + SPINOR_REG_CYPRESS_CFR1V, > + nor->bouncebuf); > + ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); > + if (ret) > + return ret; > + > + if (nor->bouncebuf[0] != cfr1v_written) { > + dev_err(nor->dev, "CFR1: Read back test failed\n"); > + return -EIO; > + } > + > + return 0; > +} > + Thanks, Takahiro
On 5/4/22 10:38, Takahiro Kuwano wrote: > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe > > Hi Tudor, Hi! > > On 5/3/2022 5:16 PM, Tudor Ambarus wrote: >> From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> >> >> The S25HL-T/S25HS-T family is the Infineon SEMPER Flash with Quad SPI. >> >> These Infineon chips support volatile version of configuration registers >> and it is recommended to update volatile registers in the field application >> due to a risk of the non-volatile registers corruption by power interrupt. >> Add support for volatile QE bit. >> >> For the single-die package parts (512Mb and 1Gb), only bottom 4KB and >> uniform sector sizes are supported. This is due to missing or incorrect >> entries in SMPT. Fixup for other sector sizes configurations will be >> followed up as needed. >> >> Tested on Xilinx Zynq-7000 FPGA board. >> >> Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> >> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> >> --- >> drivers/mtd/spi-nor/spansion.c | 125 +++++++++++++++++++++++++++++++++ >> 1 file changed, 125 insertions(+) >> >> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c >> index e130f5398763..f78a15b985ea 100644 >> --- a/drivers/mtd/spi-nor/spansion.c >> +++ b/drivers/mtd/spi-nor/spansion.c >> @@ -14,6 +14,8 @@ >> #define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */ >> #define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */ >> #define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */ >> +#define SPINOR_REG_CYPRESS_CFR1V 0x00800002 >> +#define SPINOR_REG_CYPRESS_CFR1V_QUAD_EN BIT(1) /* Quad Enable */ >> #define SPINOR_REG_CYPRESS_CFR2V 0x00800003 >> #define SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24 0xb >> #define SPINOR_REG_CYPRESS_CFR3V 0x00800004 >> @@ -113,6 +115,63 @@ static int cypress_nor_octal_dtr_dis(struct spi_nor *nor) >> return 0; >> } >> >> +/** >> + * cypress_nor_quad_enable_volatile() - enable Quad I/O mode in volatile >> + * register. >> + * @nor: pointer to a 'struct spi_nor' >> + * >> + * It is recommended to update volatile registers in the field application due >> + * to a risk of the non-volatile registers corruption by power interrupt. This >> + * function sets Quad Enable bit in CFR1 volatile. If users set the Quad Enable >> + * bit in the CFR1 non-volatile in advance (typically by a Flash programmer >> + * before mounting Flash on PCB), the Quad Enable bit in the CFR1 volatile is >> + * also set during Flash power-up. >> + * >> + * Return: 0 on success, -errno otherwise. >> + */ >> +static int cypress_nor_quad_enable_volatile(struct spi_nor *nor) >> +{ >> + struct spi_mem_op op; >> + u8 cfr1v_written; >> + int ret; >> + >> + op = (struct spi_mem_op) >> + CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_nbytes, >> + SPINOR_REG_CYPRESS_CFR1V, >> + nor->bouncebuf); >> + > The following lines are missing. > > ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); > if (ret) > return ret; Sorry, I'll add them in the next version, seems that I handled the conflicts badly :). Does it work with the read? Have you tested the patch set? > >> + if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR1V_QUAD_EN) >> + return 0; >> + >> + /* Update the Quad Enable bit. */ >> + nor->bouncebuf[0] |= SPINOR_REG_CYPRESS_CFR1V_QUAD_EN; >> + op = (struct spi_mem_op) >> + CYPRESS_NOR_WR_ANY_REG_OP(nor->params->addr_nbytes, >> + SPINOR_REG_CYPRESS_CFR1V, 1, >> + nor->bouncebuf); >> + ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto); >> + if (ret) >> + return ret; >> + >> + cfr1v_written = nor->bouncebuf[0]; >> + >> + /* Read back and check it. */ >> + op = (struct spi_mem_op) >> + CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_nbytes, >> + SPINOR_REG_CYPRESS_CFR1V, >> + nor->bouncebuf); >> + ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); >> + if (ret) >> + return ret; >> + >> + if (nor->bouncebuf[0] != cfr1v_written) { >> + dev_err(nor->dev, "CFR1: Read back test failed\n"); >> + return -EIO; >> + } >> + >> + return 0; >> +} >> + > Thanks, > Takahiro
On 5/4/2022 4:47 PM, Tudor.Ambarus@microchip.com wrote: > On 5/4/22 10:38, Takahiro Kuwano wrote: >> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe >> >> Hi Tudor, > > Hi! > >> >> On 5/3/2022 5:16 PM, Tudor Ambarus wrote: >>> From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> >>> >>> The S25HL-T/S25HS-T family is the Infineon SEMPER Flash with Quad SPI. >>> >>> These Infineon chips support volatile version of configuration registers >>> and it is recommended to update volatile registers in the field application >>> due to a risk of the non-volatile registers corruption by power interrupt. >>> Add support for volatile QE bit. >>> >>> For the single-die package parts (512Mb and 1Gb), only bottom 4KB and >>> uniform sector sizes are supported. This is due to missing or incorrect >>> entries in SMPT. Fixup for other sector sizes configurations will be >>> followed up as needed. >>> >>> Tested on Xilinx Zynq-7000 FPGA board. >>> >>> Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> >>> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> >>> --- >>> drivers/mtd/spi-nor/spansion.c | 125 +++++++++++++++++++++++++++++++++ >>> 1 file changed, 125 insertions(+) >>> >>> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c >>> index e130f5398763..f78a15b985ea 100644 >>> --- a/drivers/mtd/spi-nor/spansion.c >>> +++ b/drivers/mtd/spi-nor/spansion.c >>> @@ -14,6 +14,8 @@ >>> #define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */ >>> #define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */ >>> #define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */ >>> +#define SPINOR_REG_CYPRESS_CFR1V 0x00800002 >>> +#define SPINOR_REG_CYPRESS_CFR1V_QUAD_EN BIT(1) /* Quad Enable */ >>> #define SPINOR_REG_CYPRESS_CFR2V 0x00800003 >>> #define SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24 0xb >>> #define SPINOR_REG_CYPRESS_CFR3V 0x00800004 >>> @@ -113,6 +115,63 @@ static int cypress_nor_octal_dtr_dis(struct spi_nor *nor) >>> return 0; >>> } >>> >>> +/** >>> + * cypress_nor_quad_enable_volatile() - enable Quad I/O mode in volatile >>> + * register. >>> + * @nor: pointer to a 'struct spi_nor' >>> + * >>> + * It is recommended to update volatile registers in the field application due >>> + * to a risk of the non-volatile registers corruption by power interrupt. This >>> + * function sets Quad Enable bit in CFR1 volatile. If users set the Quad Enable >>> + * bit in the CFR1 non-volatile in advance (typically by a Flash programmer >>> + * before mounting Flash on PCB), the Quad Enable bit in the CFR1 volatile is >>> + * also set during Flash power-up. >>> + * >>> + * Return: 0 on success, -errno otherwise. >>> + */ >>> +static int cypress_nor_quad_enable_volatile(struct spi_nor *nor) >>> +{ >>> + struct spi_mem_op op; >>> + u8 cfr1v_written; >>> + int ret; >>> + >>> + op = (struct spi_mem_op) >>> + CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_nbytes, >>> + SPINOR_REG_CYPRESS_CFR1V, >>> + nor->bouncebuf); >>> + >> The following lines are missing. >> >> ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); >> if (ret) >> return ret; > > Sorry, I'll add them in the next version, seems that I handled the conflicts > badly :). Does it work with the read? Have you tested the patch set? > No problem. Yes, I tested and it's working. Thanks again, Takahiro
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c index e130f5398763..f78a15b985ea 100644 --- a/drivers/mtd/spi-nor/spansion.c +++ b/drivers/mtd/spi-nor/spansion.c @@ -14,6 +14,8 @@ #define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */ #define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */ #define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */ +#define SPINOR_REG_CYPRESS_CFR1V 0x00800002 +#define SPINOR_REG_CYPRESS_CFR1V_QUAD_EN BIT(1) /* Quad Enable */ #define SPINOR_REG_CYPRESS_CFR2V 0x00800003 #define SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24 0xb #define SPINOR_REG_CYPRESS_CFR3V 0x00800004 @@ -113,6 +115,63 @@ static int cypress_nor_octal_dtr_dis(struct spi_nor *nor) return 0; } +/** + * cypress_nor_quad_enable_volatile() - enable Quad I/O mode in volatile + * register. + * @nor: pointer to a 'struct spi_nor' + * + * It is recommended to update volatile registers in the field application due + * to a risk of the non-volatile registers corruption by power interrupt. This + * function sets Quad Enable bit in CFR1 volatile. If users set the Quad Enable + * bit in the CFR1 non-volatile in advance (typically by a Flash programmer + * before mounting Flash on PCB), the Quad Enable bit in the CFR1 volatile is + * also set during Flash power-up. + * + * Return: 0 on success, -errno otherwise. + */ +static int cypress_nor_quad_enable_volatile(struct spi_nor *nor) +{ + struct spi_mem_op op; + u8 cfr1v_written; + int ret; + + op = (struct spi_mem_op) + CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_nbytes, + SPINOR_REG_CYPRESS_CFR1V, + nor->bouncebuf); + + if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR1V_QUAD_EN) + return 0; + + /* Update the Quad Enable bit. */ + nor->bouncebuf[0] |= SPINOR_REG_CYPRESS_CFR1V_QUAD_EN; + op = (struct spi_mem_op) + CYPRESS_NOR_WR_ANY_REG_OP(nor->params->addr_nbytes, + SPINOR_REG_CYPRESS_CFR1V, 1, + nor->bouncebuf); + ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto); + if (ret) + return ret; + + cfr1v_written = nor->bouncebuf[0]; + + /* Read back and check it. */ + op = (struct spi_mem_op) + CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_nbytes, + SPINOR_REG_CYPRESS_CFR1V, + nor->bouncebuf); + ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); + if (ret) + return ret; + + if (nor->bouncebuf[0] != cfr1v_written) { + dev_err(nor->dev, "CFR1: Read back test failed\n"); + return -EIO; + } + + return 0; +} + /** * cypress_nor_set_page_size() - Set page size which corresponds to the flash * configuration. @@ -144,6 +203,56 @@ static int cypress_nor_set_page_size(struct spi_nor *nor) return 0; } +static int +s25hx_t_post_bfpt_fixup(struct spi_nor *nor, + const struct sfdp_parameter_header *bfpt_header, + const struct sfdp_bfpt *bfpt) +{ + /* Replace Quad Enable with volatile version */ + nor->params->quad_enable = cypress_nor_quad_enable_volatile; + + return cypress_nor_set_page_size(nor); +} + +static void s25hx_t_post_sfdp_fixup(struct spi_nor *nor) +{ + struct spi_nor_erase_type *erase_type = + nor->params->erase_map.erase_type; + int i; + + /* + * In some parts, 3byte erase opcodes are advertised by 4BAIT. + * Convert them to 4byte erase opcodes. + */ + for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) { + switch (erase_type[i].opcode) { + case SPINOR_OP_SE: + erase_type[i].opcode = SPINOR_OP_SE_4B; + break; + case SPINOR_OP_BE_4K: + erase_type[i].opcode = SPINOR_OP_BE_4K_4B; + break; + default: + break; + } + } +} + +static void s25hx_t_late_init(struct spi_nor *nor) +{ + /* Fast Read 4B requires mode cycles */ + nor->params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8; + + /* The writesize should be ECC data unit size */ + nor->params->writesize = 16; +} + +static struct spi_nor_fixups s25hx_t_fixups = { + .post_bfpt = s25hx_t_post_bfpt_fixup, + .post_sfdp = s25hx_t_post_sfdp_fixup, + .late_init = s25hx_t_late_init, +}; + /** * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes. * @nor: pointer to a 'struct spi_nor' @@ -320,6 +429,22 @@ static const struct flash_info spansion_nor_parts[] = { { "s25fl256l", INFO(0x016019, 0, 64 * 1024, 512) NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) FIXUP_FLAGS(SPI_NOR_4B_OPCODES) }, + { "s25hl512t", INFO6(0x342a1a, 0x0f0390, 256 * 1024, 256) + PARSE_SFDP + MFR_FLAGS(USE_CLSR) + .fixups = &s25hx_t_fixups }, + { "s25hl01gt", INFO6(0x342a1b, 0x0f0390, 256 * 1024, 512) + PARSE_SFDP + MFR_FLAGS(USE_CLSR) + .fixups = &s25hx_t_fixups }, + { "s25hs512t", INFO6(0x342b1a, 0x0f0390, 256 * 1024, 256) + PARSE_SFDP + MFR_FLAGS(USE_CLSR) + .fixups = &s25hx_t_fixups }, + { "s25hs01gt", INFO6(0x342b1b, 0x0f0390, 256 * 1024, 512) + PARSE_SFDP + MFR_FLAGS(USE_CLSR) + .fixups = &s25hx_t_fixups }, { "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1) FLAGS(SPI_NOR_NO_ERASE) }, { "s28hs512t", INFO(0x345b1a, 0, 256 * 1024, 256)