From: Hou Zhiqiang <b48...@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 <b48...@freescale.com>
Signed-off-by: Mingkai.Hu <mingkai...@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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to