From: Yaliang Wang <[email protected]>

commit b02525e1166d980d13e9ba23b0ac8ef2d688dc96 upstream

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]>
Signed-off-by: Bruce Ashfield <[email protected]>
[SG: From v5.15/standard/cn-sdkv5.4/octeon and adjusted context for v5.10.]
Signed-off-by: Stefan Ghinea <[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 d33d5d0aec26..da9fb585a4ff 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -537,6 +537,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.
@@ -546,7 +580,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 ca89e094f8bd..67c26cb1bff2 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -97,13 +97,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) },
 };
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index b5ea207fc7c4..27e91fdf30b4 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -99,6 +99,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.41.0

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

Reply via email to