]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mtd: spi-nor: spansion: Fixup params->set_4byte_addr_mode for SEMPER
authorTakahiro Kuwano <Takahiro.Kuwano@infineon.com>
Thu, 12 Jun 2025 07:44:27 +0000 (16:44 +0900)
committerPratyush Yadav <pratyush@kernel.org>
Thu, 3 Jul 2025 14:57:12 +0000 (16:57 +0200)
Infineon SEMPER flash family does not support E9h opcode as Exit 4-byte
mode (EX4B). Therefore, params->set_4byte_addr_mode is not determined by
BFPT parse. Fixup it up by introducing vendor specific EX4B opcode (B8h)
and function.

Fixes: c87c9b11c53ce ("mtd: spi-nor: spansion: Determine current address mode")
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Acked-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Acked-by: Pratyush Yadav <pratyush@kernel.org>
Signed-off-by: Pratyush Yadav <pratyush@kernel.org>
Link: https://lore.kernel.org/r/20250612074427.22263-1-Takahiro.Kuwano@infineon.com
drivers/mtd/spi-nor/spansion.c

index 920bb8dd5dc2929e63303be5cf3cf012b012170b..a0296c871634678be509cb30d26e18debff3066d 100644 (file)
@@ -17,6 +17,7 @@
 
 #define SPINOR_OP_CLSR         0x30    /* Clear status register 1 */
 #define SPINOR_OP_CLPEF                0x82    /* Clear program/erase failure flags */
+#define SPINOR_OP_CYPRESS_EX4B 0xB8    /* Exit 4-byte address mode */
 #define SPINOR_OP_CYPRESS_DIE_ERASE            0x61    /* Chip (die) erase */
 #define SPINOR_OP_RD_ANY_REG                   0x65    /* Read any register */
 #define SPINOR_OP_WR_ANY_REG                   0x71    /* Write any register */
                   SPI_MEM_OP_DUMMY(ndummy, 0),                         \
                   SPI_MEM_OP_DATA_IN(1, buf, 0))
 
+#define CYPRESS_NOR_EN4B_EX4B_OP(enable)                               \
+       SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B :             \
+                                          SPINOR_OP_CYPRESS_EX4B, 0),  \
+                  SPI_MEM_OP_NO_ADDR,                                  \
+                  SPI_MEM_OP_NO_DUMMY,                                 \
+                  SPI_MEM_OP_NO_DATA)
+
 #define SPANSION_OP(opcode)                                            \
        SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),                           \
                   SPI_MEM_OP_NO_ADDR,                                  \
@@ -356,6 +364,20 @@ static int cypress_nor_quad_enable_volatile(struct spi_nor *nor)
        return 0;
 }
 
+static int cypress_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
+{
+       int ret;
+       struct spi_mem_op op = CYPRESS_NOR_EN4B_EX4B_OP(enable);
+
+       spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
+
+       ret = spi_mem_exec_op(nor->spimem, &op);
+       if (ret)
+               dev_dbg(nor->dev, "error %d setting 4-byte mode\n", ret);
+
+       return ret;
+}
+
 /**
  * cypress_nor_determine_addr_mode_by_sr1() - Determine current address mode
  *                                            (3 or 4-byte) by querying status
@@ -526,6 +548,9 @@ s25fs256t_post_bfpt_fixup(struct spi_nor *nor,
        struct spi_mem_op op;
        int ret;
 
+       /* Assign 4-byte address mode method that is not determined in BFPT */
+       nor->params->set_4byte_addr_mode = cypress_nor_set_4byte_addr_mode;
+
        ret = cypress_nor_set_addr_mode_nbytes(nor);
        if (ret)
                return ret;
@@ -591,6 +616,9 @@ s25hx_t_post_bfpt_fixup(struct spi_nor *nor,
 {
        int ret;
 
+       /* Assign 4-byte address mode method that is not determined in BFPT */
+       nor->params->set_4byte_addr_mode = cypress_nor_set_4byte_addr_mode;
+
        ret = cypress_nor_set_addr_mode_nbytes(nor);
        if (ret)
                return ret;
@@ -718,6 +746,9 @@ static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
                                   const struct sfdp_parameter_header *bfpt_header,
                                   const struct sfdp_bfpt *bfpt)
 {
+       /* Assign 4-byte address mode method that is not determined in BFPT */
+       nor->params->set_4byte_addr_mode = cypress_nor_set_4byte_addr_mode;
+
        return cypress_nor_set_addr_mode_nbytes(nor);
 }