sf: unify status polling for ready bit
authorMike Frysinger <vapier@gentoo.org>
Mon, 10 Jan 2011 07:20:12 +0000 (02:20 -0500)
committerWolfgang Denk <wd@denx.de>
Mon, 11 Apr 2011 19:00:53 +0000 (21:00 +0200)
All of the spi flash drivers implement the status register polling for
detecting the device ready state, so unify them all in a new helper
function -- spi_flash_wait_ready.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
drivers/mtd/spi/atmel.c
drivers/mtd/spi/eon.c
drivers/mtd/spi/macronix.c
drivers/mtd/spi/spansion.c
drivers/mtd/spi/spi_flash.c
drivers/mtd/spi/spi_flash_internal.h
drivers/mtd/spi/sst.c
drivers/mtd/spi/stmicro.c
drivers/mtd/spi/winbond.c

index 8d0216956d7847b0063d9acdd698f6e6ef52178e..7827b750f6b6a37bb0e2cee58332e7f390e355d5 100644 (file)
@@ -113,35 +113,8 @@ static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
 
 static int at45_wait_ready(struct spi_flash *flash, unsigned long timeout)
 {
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 cmd = CMD_AT45_READ_STATUS;
-       u8 status;
-
-       timebase = get_timer(0);
-
-       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
-       if (ret)
-               return -1;
-
-       do {
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
-               if (ret)
-                       return -1;
-
-               if (status & AT45_STATUS_READY)
-                       break;
-       } while (get_timer(timebase) < timeout);
-
-       /* Deactivate CS */
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if (status & AT45_STATUS_READY)
-               return 0;
-
-       /* Timed out */
-       return -1;
+       return spi_flash_cmd_poll_bit(flash, timeout,
+               CMD_AT45_READ_STATUS, AT45_STATUS_READY);
 }
 
 /*
index 02c3bb93047850ba2269bcf3f5d7d048cc4942db..4af1e068c371490c4e25a24d2fdec9a30a7d55be 100644 (file)
@@ -25,8 +25,6 @@
 
 #define EON_ID_EN25Q128                0x18
 
-#define EON_SR_WIP             (1 << 0)        /* Write-in-Progress */
-
 struct eon_spi_flash_params {
        u8 idcode1;
        u16 page_size;
@@ -58,40 +56,6 @@ static const struct eon_spi_flash_params eon_spi_flash_table[] = {
        },
 };
 
-static int eon_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 cmd = CMD_EN25Q128_RDSR;
-       u8 status;
-
-       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
-       if (ret) {
-               debug("SF: Failed to send command %02x: %d\n", cmd, ret);
-               return ret;
-       }
-
-       timebase = get_timer(0);
-       do {
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
-               if (ret)
-                       return -1;
-
-               if ((status & EON_SR_WIP) == 0)
-                       break;
-
-       } while (get_timer(timebase) < timeout);
-
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if ((status & EON_SR_WIP) == 0)
-               return 0;
-
-       /* Timed out */
-       return -1;
-}
-
 static int eon_read_fast(struct spi_flash *flash,
                         u32 offset, size_t len, void *buf)
 {
@@ -160,11 +124,9 @@ static int eon_write(struct spi_flash *flash,
                        break;
                }
 
-               ret = eon_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: EON page programming timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+               if (ret)
                        break;
-               }
 
                page_addr++;
                byte_addr = 0;
@@ -221,11 +183,9 @@ int eon_erase(struct spi_flash *flash, u32 offset, size_t len)
                        break;
                }
 
-               ret = eon_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: EON page erase timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
+               if (ret)
                        break;
-               }
        }
 
        debug("SF: EON: Successfully erased %u bytes @ 0x%x\n",
index 76d52841d1ccbb99a3eeb595e465de1a926a3256..291fd17de9fc8b65665c2da28a7ba39ef31f6c9a 100644 (file)
@@ -49,8 +49,6 @@
 #define CMD_MX25XX_DP          0xb9    /* Deep Power-down */
 #define CMD_MX25XX_RES         0xab    /* Release from DP, and Read Signature */
 
-#define MACRONIX_SR_WIP                (1 << 0)        /* Write-in-Progress */
-
 struct macronix_spi_flash_params {
        u16 idcode;
        u16 page_size;
@@ -114,40 +112,6 @@ static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {
        },
 };
 
-static int macronix_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 status;
-       u8 cmd = CMD_MX25XX_RDSR;
-
-       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
-       if (ret) {
-               debug("SF: Failed to send command %02x: %d\n", cmd, ret);
-               return ret;
-       }
-
-       timebase = get_timer(0);
-       do {
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
-               if (ret)
-                       return -1;
-
-               if ((status & MACRONIX_SR_WIP) == 0)
-                       break;
-
-       } while (get_timer(timebase) < timeout);
-
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if ((status & MACRONIX_SR_WIP) == 0)
-               return 0;
-
-       /* Timed out */
-       return -1;
-}
-
 static int macronix_read_fast(struct spi_flash *flash,
                              u32 offset, size_t len, void *buf)
 {
@@ -216,11 +180,9 @@ static int macronix_write(struct spi_flash *flash,
                        break;
                }
 
-               ret = macronix_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: Macronix page programming timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+               if (ret)
                        break;
-               }
 
                page_addr++;
                byte_addr = 0;
@@ -282,11 +244,9 @@ int macronix_erase(struct spi_flash *flash, u32 offset, size_t len)
                        break;
                }
 
-               ret = macronix_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: Macronix page erase timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
+               if (ret)
                        break;
-               }
        }
 
        debug("SF: Macronix: Successfully erased %u bytes @ 0x%x\n",
index c0900f978f25710bf86ecab0e62546b1d4d6fad5..d0f03ffafa2f9b2aa28ef9e69bdbaa4a9258865c 100644 (file)
@@ -54,8 +54,6 @@
 #define SPSN_EXT_ID_S25FL128P_64KB     0x0301
 #define SPSN_EXT_ID_S25FL032P          0x4d00
 
-#define SPANSION_SR_WIP                (1 << 0)        /* Write-in-Progress */
-
 struct spansion_spi_flash_params {
        u16 idcode1;
        u16 idcode2;
@@ -135,32 +133,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
        },
 };
 
-static int spansion_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 status;
-
-       timebase = get_timer(0);
-       do {
-               ret = spi_flash_cmd(spi, CMD_S25FLXX_RDSR, &status, sizeof(status));
-               if (ret)
-                       return -1;
-
-               if ((status & SPANSION_SR_WIP) == 0)
-                       break;
-
-       } while (get_timer(timebase) < timeout);
-
-
-       if ((status & SPANSION_SR_WIP) == 0)
-               return 0;
-
-       /* Timed out */
-       return -1;
-}
-
 static int spansion_read_fast(struct spi_flash *flash,
                             u32 offset, size_t len, void *buf)
 {
@@ -233,11 +205,9 @@ static int spansion_write(struct spi_flash *flash,
                        break;
                }
 
-               ret = spansion_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: SPANSION page programming timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+               if (ret)
                        break;
-               }
 
                page_addr++;
                byte_addr = 0;
@@ -297,12 +267,9 @@ int spansion_erase(struct spi_flash *flash, u32 offset, size_t len)
                        break;
                }
 
-               /* Up to 2 seconds */
-               ret = spansion_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: SPANSION page erase timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
+               if (ret)
                        break;
-               }
        }
 
        debug("SF: SPANSION: Successfully erased %u bytes @ 0x%x\n",
index 2b7f22c5990e8b5c61ff971561fc6fbf2f063354..e483ce4af3bc805a48305abacf9431fb13a92e3e 100644 (file)
@@ -69,6 +69,47 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
        return ret;
 }
 
+int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
+                          u8 cmd, u8 poll_bit)
+{
+       struct spi_slave *spi = flash->spi;
+       unsigned long timebase;
+       int ret;
+       u8 status;
+
+       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
+       if (ret) {
+               debug("SF: Failed to send command %02x: %d\n", cmd, ret);
+               return ret;
+       }
+
+       timebase = get_timer(0);
+       do {
+               ret = spi_xfer(spi, 8, NULL, &status, 0);
+               if (ret)
+                       return -1;
+
+               if ((status & poll_bit) == 0)
+                       break;
+
+       } while (get_timer(timebase) < timeout);
+
+       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+
+       if ((status & poll_bit) == 0)
+               return 0;
+
+       /* Timed out */
+       debug("SF: time out!\n");
+       return -1;
+}
+
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+{
+       return spi_flash_cmd_poll_bit(flash, timeout,
+               CMD_READ_STATUS, STATUS_WIP);
+}
+
 /*
  * The following table holds all device probe functions
  *
index 68dcffb97174bc3c17a96c74d8d2ec452ba7c315..440c044f76eb9005134ea8ef7af278ca39d85da6 100644 (file)
 #define CMD_READ_ARRAY_FAST            0x0b
 #define CMD_READ_ARRAY_LEGACY          0xe8
 
+#define CMD_READ_STATUS                        0x05
+
+/* Common status */
+#define STATUS_WIP                     0x01
+
 /* Send a single-byte command to the device and read the response */
 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
 
@@ -43,6 +48,16 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
                size_t cmd_len, void *data, size_t data_len);
 
+/* Send a command to the device and wait for some bit to clear itself. */
+int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
+                          u8 cmd, u8 poll_bit);
+
+/*
+ * Send the read status command to the device and wait for the wip
+ * (write-in-progress) bit to clear itself.
+ */
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
+
 /* Manufacturer-specific probe functions */
 struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);
 struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode);
index 25578914c68fab2b3a001b05b724e18e788b247b..4a82f8a3a141fbace4a23f678613d96656697428 100644 (file)
@@ -89,41 +89,6 @@ static const struct sst_spi_flash_params sst_spi_flash_table[] = {
        },
 };
 
-static int
-sst_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 byte = CMD_SST_RDSR;
-
-       ret = spi_xfer(spi, sizeof(byte) * 8, &byte, NULL, SPI_XFER_BEGIN);
-       if (ret) {
-               debug("SF: Failed to send command %02x: %d\n", byte, ret);
-               return ret;
-       }
-
-       timebase = get_timer(0);
-       do {
-               ret = spi_xfer(spi, sizeof(byte) * 8, NULL, &byte, 0);
-               if (ret)
-                       break;
-
-               if ((byte & SST_SR_WIP) == 0)
-                       break;
-
-       } while (get_timer(timebase) < timeout);
-
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if (!ret && (byte & SST_SR_WIP) != 0)
-               ret = -1;
-
-       if (ret)
-               debug("SF: sst wait for ready timed out\n");
-       return ret;
-}
-
 static int
 sst_enable_writing(struct spi_flash *flash)
 {
@@ -177,7 +142,7 @@ sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
        if (ret)
                return ret;
 
-       return sst_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+       return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
 }
 
 static int
@@ -224,7 +189,7 @@ sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
                        break;
                }
 
-               ret = sst_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
                if (ret)
                        break;
 
@@ -298,7 +263,7 @@ sst_erase(struct spi_flash *flash, u32 offset, size_t len)
                        break;
                }
 
-               ret = sst_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
                if (ret)
                        break;
        }
index 31340279cb872f98e0fdafe84f087ff0dc0f7786..02da8b2fdc5c09a116b680a0d3a12c2fb5d1fbda 100644 (file)
@@ -55,8 +55,6 @@
 #define STM_ID_M25P80          0x14
 #define STM_ID_M25P128         0x18
 
-#define STMICRO_SR_WIP         (1 << 0)        /* Write-in-Progress */
-
 struct stmicro_spi_flash_params {
        u8 idcode1;
        u16 page_size;
@@ -136,40 +134,6 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
        },
 };
 
-static int stmicro_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 cmd = CMD_M25PXX_RDSR;
-       u8 status;
-
-       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
-       if (ret) {
-               debug("SF: Failed to send command %02x: %d\n", cmd, ret);
-               return ret;
-       }
-
-       timebase = get_timer(0);
-       do {
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
-               if (ret)
-                       return -1;
-
-               if ((status & STMICRO_SR_WIP) == 0)
-                       break;
-
-       } while (get_timer(timebase) < timeout);
-
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if ((status & STMICRO_SR_WIP) == 0)
-               return 0;
-
-       /* Timed out */
-       return -1;
-}
-
 static int stmicro_read_fast(struct spi_flash *flash,
                             u32 offset, size_t len, void *buf)
 {
@@ -238,11 +202,9 @@ static int stmicro_write(struct spi_flash *flash,
                        break;
                }
 
-               ret = stmicro_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: STMicro page programming timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+               if (ret)
                        break;
-               }
 
                page_addr++;
                byte_addr = 0;
@@ -304,11 +266,9 @@ int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
                        break;
                }
 
-               ret = stmicro_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: STMicro page erase timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
+               if (ret)
                        break;
-               }
        }
 
        debug("SF: STMicro: Successfully erased %u bytes @ 0x%x\n",
index 44523555d9ef3eb847a33a1470bc038dca0b3d1d..d8c1cb12d925c0a807c9d8af40042dd32d80d76c 100644 (file)
@@ -24,8 +24,6 @@
 #define CMD_W25_DP             0xb9    /* Deep Power-down */
 #define CMD_W25_RES            0xab    /* Release from DP, and Read Signature */
 
-#define WINBOND_SR_WIP         (1 << 0)        /* Write-in-Progress */
-
 struct winbond_spi_flash_params {
        uint16_t        id;
        /* Log2 of page size in power-of-two mode */
@@ -107,43 +105,6 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
        },
 };
 
-static int winbond_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 status;
-       u8 cmd[4] = { CMD_W25_RDSR, 0xff, 0xff, 0xff };
-
-       ret = spi_xfer(spi, 32, &cmd[0], NULL, SPI_XFER_BEGIN);
-       if (ret) {
-               debug("SF: Failed to send command %02x: %d\n", cmd, ret);
-               return ret;
-       }
-
-       timebase = get_timer(0);
-       do {
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
-               if (ret) {
-                       debug("SF: Failed to get status for cmd %02x: %d\n", cmd, ret);
-                       return -1;
-               }
-
-               if ((status & WINBOND_SR_WIP) == 0)
-                       break;
-
-       } while (get_timer(timebase) < timeout);
-
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if ((status & WINBOND_SR_WIP) == 0)
-               return 0;
-
-       debug("SF: Timed out on command %02x: %d\n", cmd, ret);
-       /* Timed out */
-       return -1;
-}
-
 /*
  * Assemble the address part of a command for Winbond devices in
  * non-power-of-two page size mode.
@@ -230,11 +191,9 @@ static int winbond_write(struct spi_flash *flash,
                        goto out;
                }
 
-               ret = winbond_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: Winbond page programming timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+               if (ret)
                        goto out;
-               }
 
                page_addr++;
                byte_addr = 0;
@@ -298,11 +257,9 @@ int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)
                        goto out;
                }
 
-               ret = winbond_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: Winbond sector erase timed out\n");
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
+               if (ret)
                        goto out;
-               }
        }
 
        debug("SF: Winbond: Successfully erased %u bytes @ 0x%x\n",