diff mbox series

[10/30] mtd: spi-nor: program quad enable bit for winbond flashes

Message ID 20231206053353.3745918-1-tejas.arvind.bhumkar@amd.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series Fix issues with QSPI and OSPI compare failures | expand

Commit Message

Bhumkar, Tejas Arvind Dec. 6, 2023, 5:33 a.m. UTC
From: T Karthik Reddy <t.karthik.reddy@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.reddy@xilinx.com>
Co-developed-by: Tejas Bhumkar <tejas.arvind.bhumkar@amd.com>
Signed-off-by: Tejas Bhumkar <tejas.arvind.bhumkar@amd.com>
---
 drivers/mtd/spi/spi-nor-core.c | 48 ++++++++++++++++++++++++++++++++++
 include/linux/mtd/spi-nor.h    |  2 ++
 2 files changed, 50 insertions(+)
diff mbox series

Patch

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