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 v5.15.]
Signed-off-by: Ruiqiang Hao <[email protected]>
---
 drivers/mtd/spi-nor/core.c     | 45 +++++++++++++++++++++++++++++++++-
 drivers/mtd/spi-nor/spansion.c |  6 ++---
 include/linux/mtd/spi-nor.h    |  1 +
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 479f22c2dc01..b87d11c54b2a 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -676,6 +676,40 @@ static void spi_nor_clear_sr(struct spi_nor *nor)
                dev_dbg(nor->dev, "error %d clearing SR\n", ret);
 }
 
+static const struct flash_info *spi_nor_read_id(struct spi_nor *nor);
+/*
+ * 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);
+}
+
 /**
  * spi_nor_sr_ready() - Query the Status Register to see if the flash is ready
  * for new commands.
@@ -685,7 +719,16 @@ static void spi_nor_clear_sr(struct spi_nor *nor)
  */
 static int spi_nor_sr_ready(struct spi_nor *nor)
 {
-       int ret = spi_nor_read_sr(nor, nor->bouncebuf);
+       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)
                return ret;
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 036095cb68bb..a9cdb3099eb3 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -267,13 +267,13 @@ static const struct flash_info spansion_parts[] = {
                             SECT_4K | SPI_NOR_DUAL_READ) },
        { "s25fl064l",  INFO(0x016017,      0,  64 * 1024, 128,
                             SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-                            SPI_NOR_4B_OPCODES) },
+                            SPI_NOR_4B_OPCODES | USE_CLSR) },
        { "s25fl128l",  INFO(0x016018,      0,  64 * 1024, 256,
                             SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-                            SPI_NOR_4B_OPCODES) },
+                            SPI_NOR_4B_OPCODES | USE_CLSR) },
        { "s25fl256l",  INFO(0x016019,      0,  64 * 1024, 512,
                             SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-                            SPI_NOR_4B_OPCODES) },
+                            SPI_NOR_4B_OPCODES | USE_CLSR) },
        { "cy15x104q",  INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1,
                              SPI_NOR_NO_ERASE) },
        { "s28hs512t",   INFO(0x345b1a,      0, 256 * 1024, 256,
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index cd84afa17663..385edb74fd52 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -102,6 +102,7 @@
 /* Used for Spansion flashes only. */
 #define SPINOR_OP_BRWR         0x17    /* Bank register write */
 #define SPINOR_OP_CLSR         0x30    /* Clear status register 1 */
+#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 (#12418): 
https://lists.yoctoproject.org/g/linux-yocto/message/12418
Mute This Topic: https://lists.yoctoproject.org/mt/98443644/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to