[U-Boot] [V4 1/2] sf: Add clear flag status register operation on Micron chips

Zhiqiang Hou B48286 at freescale.com
Thu Jul 23 11:54:08 CEST 2015


From: Hou Zhiqiang <B48286 at freescale.com>

Add clear flag status register operation that was required by Micron SPI
flash chips after reading the flag status register to check if the erase
and program operations complete or an error occur.

Signed-off-by: Hou Zhiqiang <B48286 at freescale.com>
Signed-off-by: Mingkai.Hu <Mingkai.Hu at freescale.com>
---
 drivers/mtd/spi/sf_internal.h |  9 +++++++++
 drivers/mtd/spi/sf_ops.c      | 40 ++++++++++++++++++++++++++++++++--------
 2 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 9fb5557..703d4a7 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -73,6 +73,7 @@ enum {
 #define CMD_WRITE_ENABLE		0x06
 #define CMD_READ_CONFIG			0x35
 #define CMD_FLAG_STATUS			0x70
+#define CMD_CLEAR_FLAG_STATUS		0x50
 
 /* Read commands */
 #define CMD_READ_ARRAY_SLOW		0x03
@@ -96,6 +97,8 @@ enum {
 #define STATUS_QEB_WINSPAN		(1 << 1)
 #define STATUS_QEB_MXIC		(1 << 6)
 #define STATUS_PEC			(1 << 7)
+#define STATUS_PROT			(1 << 1)
+#define STATUS_ERASE			(1 << 5)
 
 /* Flash timeout values */
 #define SPI_FLASH_PROG_TIMEOUT		(2 * CONFIG_SYS_HZ)
@@ -182,6 +185,12 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
 	return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0);
 }
 
+/* Clear flag status register */
+static inline int spi_flash_cmd_clear_flag_status(struct spi_slave *spi)
+{
+	return spi_flash_cmd(spi, CMD_CLEAR_FLAG_STATUS, NULL, 0);
+}
+
 /*
  * Send the read status command to the device and wait for the wip
  * (write-in-progress) bit to clear itself.
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
index 38592f5..cbb9f00 100644
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -160,6 +160,7 @@ static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
 	unsigned long timebase;
 	unsigned long flags = SPI_XFER_BEGIN;
 	int ret;
+	int out_of_time = 1;
 	u8 status;
 	u8 check_status = 0x0;
 
@@ -182,22 +183,45 @@ static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
 		WATCHDOG_RESET();
 
 		ret = spi_xfer(spi, 8, NULL, &status, 0);
-		if (ret)
+		if (ret) {
+			spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
 			return -1;
+		}
 
-		if ((status & poll_bit) == check_status)
+		if ((status & poll_bit) == check_status) {
+			out_of_time = 0;
 			break;
+		}
 
 	} while (get_timer(timebase) < timeout);
 
 	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
 
-	if ((status & poll_bit) == check_status)
-		return 0;
+	if (out_of_time) {
+		/* Timed out */
+		debug("SF: time out!\n");
+		if (cmd == CMD_FLAG_STATUS) {
+			if (spi_flash_cmd_clear_flag_status(spi) < 0)
+				debug("SF: clear flag status failed\n");
+		}
+		ret = -1;
+	}
+#ifdef CONFIG_SPI_FLASH_STMICRO
+	else if (cmd == CMD_FLAG_STATUS) {
+		if (!(status & (STATUS_PROT | STATUS_ERASE))) {
+			ret = 0;
+		} else {
+			debug("SF: flag status error");
+			ret = -1;
+		}
 
-	/* Timed out */
-	debug("SF: time out!\n");
-	return -1;
+		if (spi_flash_cmd_clear_flag_status(spi) < 0) {
+			debug("SF: clear flag status failed\n");
+			ret = -1;
+		}
+	}
+#endif
+	return ret;
 }
 
 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
@@ -252,7 +276,7 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
 
 	ret = spi_flash_cmd_wait_ready(flash, timeout);
 	if (ret < 0) {
-		debug("SF: write %s timed out\n",
+		debug("SF: write %s failed\n",
 		      timeout == SPI_FLASH_PROG_TIMEOUT ?
 			"program" : "page erase");
 		return ret;
-- 
2.1.0.27.g96db324



More information about the U-Boot mailing list