From: T Karthik Reddy <t.karthik.re...@xilinx.com>

Added support to program quad enable bit for Winbond flash memory.
Previously, the quad enable function from Spansion was used for
this purpose. However, for Winbond flash memory, the quad
enable bit is configured by programming the Write Status Register-2
(SR-2) rather than the Configuration Register (CR).

Signed-off-by: T Karthik Reddy <t.karthik.re...@xilinx.com>
Co-developed-by: Tejas Bhumkar <tejas.arvind.bhum...@amd.com>
Signed-off-by: Tejas Bhumkar <tejas.arvind.bhum...@amd.com>
---
 drivers/mtd/spi/spi-nor-core.c | 48 ++++++++++++++++++++++++++++++++++
 include/linux/mtd/spi-nor.h    |  2 ++
 2 files changed, 50 insertions(+)

diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index ace5da9591..454ae6cd4e 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -2141,6 +2141,49 @@ static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr)
        return 0;
 }
 
+/**
+ * winbond_quad_enable() - Set QE bit in status register-2
+ * @nor:       pointer to a 'struct spi_nor'
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int winbond_quad_enable(struct spi_nor *nor)
+{
+       int ret;
+       u8 cr = 0;
+
+       /* Check current Quad Enable bit value. */
+       cr = read_cr(nor);
+       if (cr < 0) {
+               dev_dbg(nor->dev,
+                       "error while reading configuration register\n");
+               return -EINVAL;
+       }
+
+       if (cr & SR2_QUAD_EN_BIT1)
+               return 0;
+
+       cr |= SR2_QUAD_EN_BIT1;
+
+       write_enable(nor);
+
+       ret = nor->write_reg(nor, SPINOR_OP_WIN_WRSR2, &cr, 1);
+       if (ret < 0) {
+               dev_dbg(nor->dev,
+                       "error while writing configuration register\n");
+               return -EINVAL;
+       }
+
+       ret = spi_nor_wait_till_ready(nor);
+       if (ret) {
+               dev_dbg(nor->dev,
+                       "timeout while writing configuration register\n");
+               return ret;
+       }
+
+       return write_disable(nor);
+}
+
 /**
  * spansion_read_cr_quad_enable() - set QE bit in Configuration Register.
  * @nor:       pointer to a 'struct spi_nor'
@@ -3052,6 +3095,11 @@ static int spi_nor_init_params(struct spi_nor *nor,
                case SNOR_MFR_MICRON:
                        break;
 
+#if defined(CONFIG_SPI_FLASH_WINBOND)
+               case SNOR_MFR_WINBOND:
+                       params->quad_enable = winbond_quad_enable;
+                       break;
+#endif
                default:
 #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
                        /* Kept only for backward compatibility purpose. */
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 72206f51ad..34e0aedc24 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -48,6 +48,7 @@
 #define SPINOR_OP_WRSR         0x01    /* Write status register 1 byte */
 #define SPINOR_OP_RDSR2                0x3f    /* Read status register 2 */
 #define SPINOR_OP_WRSR2                0x3e    /* Write status register 2 */
+#define SPINOR_OP_WIN_WRSR2    0x31    /* Winbond Write status register 2 */
 #define SPINOR_OP_READ         0x03    /* Read data bytes (low frequency) */
 #define SPINOR_OP_READ_FAST    0x0b    /* Read data bytes (high frequency) */
 #define SPINOR_OP_READ_1_1_2   0x3b    /* Read data bytes (Dual Output SPI) */
@@ -187,6 +188,7 @@
 
 /* Status Register 2 bits. */
 #define SR2_QUAD_EN_BIT7       BIT(7)
+#define SR2_QUAD_EN_BIT1       BIT(1)  /* Winbond Quad I/O */
 
 /*
  * Maximum number of flashes that can be connected
-- 
2.27.0

Reply via email to