From: Yaliang Wang <[email protected]>

In Cypress FL-L product family, P_ERR or E_ERR bits are shifted to SR2V,
and are actually being used. Which means we need cope this special
condition accordingly.

Signed-off-by: Yaliang Wang <[email protected]>
[RQ: adjust code structure to fit kernel v6.1.]
Signed-off-by: Ruiqiang Hao <[email protected]>
---
 drivers/mtd/spi-nor/spansion.c | 46 +++++++++++++++++++++++++++++++---
 include/linux/mtd/spi-nor.h    |  1 +
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 7e7c68fc7776..5853b1232f9b 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -441,13 +441,13 @@ static const struct flash_info spansion_nor_parts[] = {
                NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
        { "s25fl064l",  INFO(0x016017,      0,  64 * 1024, 128)
                NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
-               FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
+               FIXUP_FLAGS(SPI_NOR_4B_OPCODES | USE_CLSR) },
        { "s25fl128l",  INFO(0x016018,      0,  64 * 1024, 256)
                NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
-               FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
+               FIXUP_FLAGS(SPI_NOR_4B_OPCODES | USE_CLSR) },
        { "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) },
+               FIXUP_FLAGS(SPI_NOR_4B_OPCODES | USE_CLSR) },
        { "s25hl512t",  INFO6(0x342a1a, 0x0f0390, 256 * 1024, 256)
                PARSE_SFDP
                MFR_FLAGS(USE_CLSR)
@@ -495,6 +495,39 @@ static void spansion_nor_clear_sr(struct spi_nor *nor)
                dev_dbg(nor->dev, "error %d clearing SR\n", ret);
 }
 
+/*
+ * Cypress FL-L series devices have redesigned the status register,
+ * P_ERR and E_ERR bits are shifted to the status register 2.
+ */
+static int spi_nor_s25fl_l_sr_ready(struct spi_nor *nor)
+{
+       u8 sr1, sr2;
+       int ret;
+
+       ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDSR, &sr1, 1);
+       if (ret < 0) {
+               pr_err("error %d reading SR\n", (int) ret);
+               return ret;
+       }
+       ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDSR2_FL_L, &sr2, 1);
+       if (ret < 0) {
+               pr_err("error %d reading SR2\n", (int) ret);
+               return ret;
+       }
+
+       if (nor->flags & SNOR_F_USE_CLSR && sr2 & (SR_E_ERR | SR_P_ERR)) {
+               if (sr2 & SR_E_ERR)
+                       dev_err(nor->dev, "Erase Error occurred\n");
+               else
+                       dev_err(nor->dev, "Programming Error occurred\n");
+
+               nor->controller_ops->write_reg(nor, SPINOR_OP_CLSR, NULL, 0);
+               return -EIO;
+       }
+
+       return !(sr1 & SR_WIP);
+}
+
 /**
  * spansion_nor_sr_ready_and_clear() - Query the Status Register to see if the
  * flash is ready for new commands and clear it if there are any errors.
@@ -505,6 +538,13 @@ static void spansion_nor_clear_sr(struct spi_nor *nor)
 static int spansion_nor_sr_ready_and_clear(struct spi_nor *nor)
 {
        int ret;
+       const struct flash_info *tmpinfo = (nor->info == NULL) ? nor->info : 
spi_nor_read_id(nor);
+
+       if (!IS_ERR_OR_NULL(tmpinfo)){
+               if (!strcmp(tmpinfo->name, "s25fl064l") || 
!strcmp(tmpinfo->name, "s25fl128l") || !strcmp(tmpinfo->name, "s25fl256l")){
+                       return spi_nor_s25fl_l_sr_ready(nor);
+               }
+       }
 
        ret = spi_nor_read_sr(nor, nor->bouncebuf);
        if (ret)
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index fb8a0b8ed242..c21d4aa2be6d 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -87,6 +87,7 @@
 
 /* Used for Spansion flashes only. */
 #define SPINOR_OP_BRWR         0x17    /* Bank register write */
+#define SPINOR_OP_RDSR2_FL_L   0x07    /* Read status register 2 */
 
 /* Used for Micron flashes only. */
 #define SPINOR_OP_RD_EVCR      0x65    /* Read EVCR register */
-- 
2.35.5

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#12859): 
https://lists.yoctoproject.org/g/linux-yocto/message/12859
Mute This Topic: https://lists.yoctoproject.org/mt/100189439/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to