diff mbox series

[RESEND] drivers:mtd:spi-nor:checkup FSR error bits

Message ID cf02744c9e4542dd8f3197f792e86368@SIWEX5A.sing.micron.com
State Changes Requested
Delegated to: Cyrille Pitchen
Headers show
Series [RESEND] drivers:mtd:spi-nor:checkup FSR error bits | expand

Commit Message

Bean Huo Nov. 29, 2017, 3:14 p.m. UTC
For the Micron SPI NOR, when the erase/program operation fails, especially,
for the failure results from intending to modify protected space, spi-nor
upper layers still get the return which shows the operation succeeds.
This because spi_nor_fsr_ready() only uses bit.7 to device whether ready.
For the most cases, even the error of erase/program occurs, SPI NOR device
is still ready. The device ready and the error are two different cases.
This patch is to fixup this issue and adding FSR (flag status register)
error bits checkup.
The FSR(flag status register) is a powerful tool to investigate the staus
of device, checking information regarding what is actually doing the memory
and detecting possible error conditions.

Signed-off-by: beanhuo <beanhuo@micron.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 18 ++++++++++++++++--
 include/linux/mtd/spi-nor.h   |  6 +++++-
 2 files changed, 21 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 19c00072..b87c04f 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -328,8 +328,22 @@  static inline int spi_nor_fsr_ready(struct spi_nor *nor)
 	int fsr = read_fsr(nor);
 	if (fsr < 0)
 		return fsr;
-	else
-		return fsr & FSR_READY;
+
+	if (fsr & (FSR_E_ERR | FSR_P_ERR)) {
+		if (fsr & FSR_E_ERR)
+			dev_err(nor->dev, "Erase operation failed.\n");
+		else
+			dev_err(nor->dev, "Program operation failed.\n");
+
+		if (fsr & FSR_PT_ERR)
+			dev_err(nor->dev,
+			"Attempted to modify the protected sectors.\n");
+
+		nor->write_reg(nor, SPINOR_OP_CLFSR, NULL, 0);
+		return -EIO;
+	}
+
+	return fsr & FSR_READY;
 }
 
 static int spi_nor_ready(struct spi_nor *nor)
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 1f0a7fc..b6187e3 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -61,6 +61,7 @@ 
 #define SPINOR_OP_RDSFDP	0x5a	/* Read SFDP */
 #define SPINOR_OP_RDCR		0x35	/* Read configuration register */
 #define SPINOR_OP_RDFSR		0x70	/* Read flag status register */
+#define SPINOR_OP_CLFSR		0x50	/* Clear flag status register */
 
 /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
 #define SPINOR_OP_READ_4B	0x13	/* Read data bytes (low frequency) */
@@ -130,7 +131,10 @@ 
 #define EVCR_QUAD_EN_MICRON	BIT(7)	/* Micron Quad I/O */
 
 /* Flag Status Register bits */
-#define FSR_READY		BIT(7)
+#define FSR_READY		BIT(7)	/* Device status, 0 = Busy,1 = Ready */
+#define FSR_E_ERR		BIT(5)	/* Erase operation status */
+#define FSR_P_ERR		BIT(4)	/* Program operation status */
+#define FSR_PT_ERR		BIT(1)	/* Protection error bit */
 
 /* Configuration Register bits. */
 #define CR_QUAD_EN_SPAN		BIT(1)	/* Spansion Quad I/O */