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);
 }
 
 /*
 
 
 #define EON_ID_EN25Q128                0x18
 
-#define EON_SR_WIP             (1 << 0)        /* Write-in-Progress */
-
 struct eon_spi_flash_params {
        u8 idcode1;
        u16 page_size;
        },
 };
 
-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)
 {
                        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;
                        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",
 
 #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;
        },
 };
 
-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)
 {
                        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;
                        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",
 
 #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;
        },
 };
 
-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)
 {
                        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;
                        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",
 
        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
  *
 
 #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);
 
 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);
 
        },
 };
 
-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)
 {
        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
                        break;
                }
 
-               ret = sst_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
                if (ret)
                        break;
 
                        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;
        }
 
 #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;
        },
 };
 
-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)
 {
                        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;
                        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",
 
 #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 */
        },
 };
 
-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.
                        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;
                        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",