diff mbox series

[v12,6/6] mtd: spi-nor: spansion: Add s25hl-t/s25hs-t IDs and fixups

Message ID ff03da96d144b74b102dadf641931f6bf5ee9c8b.1650519576.git.Takahiro.Kuwano@infineon.com
State Changes Requested
Delegated to: Pratyush Yadav
Headers show
Series mtd: spi-nor: Add support for Infineon s25hl-t/s25hs-t | expand

Commit Message

Takahiro Kuwano April 21, 2022, 6:40 a.m. UTC
From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>

The S25HL-T/S25HS-T family is the Infineon SEMPER Flash with Quad SPI.

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>
---
Changes in v12:
  - Cleanup fixups based on other patches in this series
  - Add part specific set_4byte_addr_mode()
  - Unset SNOR_F_4B_OPCODES flag to let core to call set_4byte_addr_mode
  
Changes in v11:
  - Cleanup fixups based on other patches in this series
  
Changes in v10:
  - Cleanup fixups and ID table based on other patches in this series

Changes in v9:
  - Use late_init() hook to fix mode clocks and writesize
  - Use PARSE_SFDP instead of NO_SFDP_FLAGS
  - Use MFR_FLAGS for USE_CLSR
  - Add comment block to explain about addr mode in post_bfpt_fixups()

Changes in v8:
  - Call write_disable in error case only
  - Use spi_nor_read_reg() helper
  - Use nor->bouncebuf instead of variable on stack
  - Update ID table to use FLAGS macro
  
Changes in v7:
  - Add missing device info table in v6
  
Changes in v6:
  - Remove 2Gb multi die pacakge support

Changes in v5:
  - Add NO_CHIP_ERASE flag to S25HL02GT and S25HS02GT

Changes in v4:
  - Merge block comments about SMPT in s25hx_t_post_sfdp_fixups()
  - Remove USE_CLSR flags from S25HL02GT and S25HS02GT

Changes in v3:
  - Remove S25HL256T and S25HS256T
  - Add S25HL02GT and S25HS02GT 
  - Add support for multi-die package parts support
  - Remove erase_map fix for top/split sector layout
  - Set ECC data unit size (16B) to writesize

 drivers/mtd/spi-nor/spansion.c | 64 ++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

Comments

Tudor Ambarus April 21, 2022, 7:40 a.m. UTC | #1
On 4/21/22 09:40, tkuw584924@gmail.com wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> 
> The S25HL-T/S25HS-T family is the Infineon SEMPER Flash with Quad SPI.
> 
> 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>
> ---
> Changes in v12:
>   - Cleanup fixups based on other patches in this series
>   - Add part specific set_4byte_addr_mode()
>   - Unset SNOR_F_4B_OPCODES flag to let core to call set_4byte_addr_mode
> 
> Changes in v11:
>   - Cleanup fixups based on other patches in this series
> 
> Changes in v10:
>   - Cleanup fixups and ID table based on other patches in this series
> 
> Changes in v9:
>   - Use late_init() hook to fix mode clocks and writesize
>   - Use PARSE_SFDP instead of NO_SFDP_FLAGS
>   - Use MFR_FLAGS for USE_CLSR
>   - Add comment block to explain about addr mode in post_bfpt_fixups()
> 
> Changes in v8:
>   - Call write_disable in error case only
>   - Use spi_nor_read_reg() helper
>   - Use nor->bouncebuf instead of variable on stack
>   - Update ID table to use FLAGS macro
> 
> Changes in v7:
>   - Add missing device info table in v6
> 
> Changes in v6:
>   - Remove 2Gb multi die pacakge support
> 
> Changes in v5:
>   - Add NO_CHIP_ERASE flag to S25HL02GT and S25HS02GT
> 
> Changes in v4:
>   - Merge block comments about SMPT in s25hx_t_post_sfdp_fixups()
>   - Remove USE_CLSR flags from S25HL02GT and S25HS02GT
> 
> Changes in v3:
>   - Remove S25HL256T and S25HS256T
>   - Add S25HL02GT and S25HS02GT
>   - Add support for multi-die package parts support
>   - Remove erase_map fix for top/split sector layout
>   - Set ECC data unit size (16B) to writesize
> 
>  drivers/mtd/spi-nor/spansion.c | 64 ++++++++++++++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
> 
> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
> index 248fe1b221fd..a1f6631a3449 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -14,6 +14,7 @@
>  #define CYPRESS_NOR_OP_CLSR            0x30    /* Clear status register 1 */
>  #define CYPRESS_NOR_OP_RD_ANY_REG      0x65    /* Read any register */
>  #define CYPRESS_NOR_OP_WR_ANY_REG      0x71    /* Write any register */
> +#define CYPRESS_NOR_OP_EX4B            0xB8    /* Exit 4B Addr Mode */
>  #define CYPRESS_NOR_OP_RD_FAST         0xee
> 
>  #define CYPRESS_NOR_REG_CFR1V                  0x00800002
> @@ -45,6 +46,13 @@
>                    SPI_MEM_OP_NO_DUMMY,                                 \
>                    SPI_MEM_OP_NO_DATA)
> 
> +#define CYPRESS_NOR_EN4B_EX4B_OP(enable)                               \
> +       SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B :             \
> +                                          CYPRESS_NOR_OP_EX4B, 0),     \
> +                  SPI_MEM_OP_NO_ADDR,                                  \
> +                  SPI_MEM_OP_NO_DUMMY,                                 \
> +                  SPI_MEM_OP_NO_DATA)
> +
>  static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
>  {
>         struct spi_mem_op op;
> @@ -207,6 +215,46 @@ static int cypress_nor_set_page_size(struct spi_nor *nor)
>         return 0;
>  }
> 
> +static int s25hx_t_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
> +{
> +       struct spi_mem_op op = CYPRESS_NOR_EN4B_EX4B_OP(enable);
> +
> +       spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> +
> +       return spi_mem_exec_op(nor->spimem, &op);
> +}
> +
> +static int
> +s25hx_t_post_bfpt_fixups(struct spi_nor *nor,
> +                        const struct sfdp_parameter_header *bfpt_header,
> +                        const struct sfdp_bfpt *bfpt)
> +{
> +       /* EX4B(E9h) is not supported. Use part specific method */
> +       nor->params->set_4byte_addr_mode = s25hx_t_set_4byte_addr_mode;
> +
> +       /* 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_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;
> +
> +       /* Read and Write Any Reg ops take 3B or 4B address */
> +       nor->flags &= ~SNOR_F_4B_OPCODES;

as I previously said, I'm not convinced you should enter 4byte mode
at all. Help me understand why you need it, please.

> +}
> +
> +static struct spi_nor_fixups s25hx_t_fixups = {
> +       .post_bfpt = s25hx_t_post_bfpt_fixups,
> +       .late_init = s25hx_t_late_init,
> +};
> +
>  /**
>   * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
>   * @nor:               pointer to a 'struct spi_nor'
> @@ -383,6 +431,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(CYPRESS_NOR_USE_CLSR)
> +               .fixups = &s25hx_t_fixups },
> +       { "s25hl01gt",  INFO6(0x342a1b, 0x0f0390, 256 * 1024, 512)
> +               PARSE_SFDP
> +               MFR_FLAGS(CYPRESS_NOR_USE_CLSR)
> +               .fixups = &s25hx_t_fixups },
> +       { "s25hs512t",  INFO6(0x342b1a, 0x0f0390, 256 * 1024, 256)
> +               PARSE_SFDP
> +               MFR_FLAGS(CYPRESS_NOR_USE_CLSR)
> +               .fixups = &s25hx_t_fixups },
> +       { "s25hs01gt",  INFO6(0x342b1b, 0x0f0390, 256 * 1024, 512)
> +               PARSE_SFDP
> +               MFR_FLAGS(CYPRESS_NOR_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)
> --
> 2.25.1
>
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 248fe1b221fd..a1f6631a3449 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -14,6 +14,7 @@ 
 #define CYPRESS_NOR_OP_CLSR		0x30	/* Clear status register 1 */
 #define CYPRESS_NOR_OP_RD_ANY_REG	0x65	/* Read any register */
 #define CYPRESS_NOR_OP_WR_ANY_REG	0x71	/* Write any register */
+#define CYPRESS_NOR_OP_EX4B		0xB8	/* Exit 4B Addr Mode */
 #define CYPRESS_NOR_OP_RD_FAST		0xee
 
 #define CYPRESS_NOR_REG_CFR1V			0x00800002
@@ -45,6 +46,13 @@ 
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_NO_DATA)
 
+#define CYPRESS_NOR_EN4B_EX4B_OP(enable)				\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B :		\
+					   CYPRESS_NOR_OP_EX4B, 0),	\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
@@ -207,6 +215,46 @@  static int cypress_nor_set_page_size(struct spi_nor *nor)
 	return 0;
 }
 
+static int s25hx_t_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
+{
+	struct spi_mem_op op = CYPRESS_NOR_EN4B_EX4B_OP(enable);
+
+	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+static int
+s25hx_t_post_bfpt_fixups(struct spi_nor *nor,
+			 const struct sfdp_parameter_header *bfpt_header,
+			 const struct sfdp_bfpt *bfpt)
+{
+	/* EX4B(E9h) is not supported. Use part specific method */
+	nor->params->set_4byte_addr_mode = s25hx_t_set_4byte_addr_mode;
+
+	/* 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_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;
+
+	/* Read and Write Any Reg ops take 3B or 4B address */
+	nor->flags &= ~SNOR_F_4B_OPCODES;
+}
+
+static struct spi_nor_fixups s25hx_t_fixups = {
+	.post_bfpt = s25hx_t_post_bfpt_fixups,
+	.late_init = s25hx_t_late_init,
+};
+
 /**
  * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
  * @nor:		pointer to a 'struct spi_nor'
@@ -383,6 +431,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(CYPRESS_NOR_USE_CLSR)
+		.fixups = &s25hx_t_fixups },
+	{ "s25hl01gt",  INFO6(0x342a1b, 0x0f0390, 256 * 1024, 512)
+		PARSE_SFDP
+		MFR_FLAGS(CYPRESS_NOR_USE_CLSR)
+		.fixups = &s25hx_t_fixups },
+	{ "s25hs512t",  INFO6(0x342b1a, 0x0f0390, 256 * 1024, 256)
+		PARSE_SFDP
+		MFR_FLAGS(CYPRESS_NOR_USE_CLSR)
+		.fixups = &s25hx_t_fixups },
+	{ "s25hs01gt",  INFO6(0x342b1b, 0x0f0390, 256 * 1024, 512)
+		PARSE_SFDP
+		MFR_FLAGS(CYPRESS_NOR_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)