]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
sf: Fix dual parallel erase/program on micron devices
authorJagannadha Sutradharudu Teki <jagannadha.sutradharudu-teki@xilinx.com>
Mon, 30 Sep 2013 20:16:46 +0000 (01:46 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Wed, 2 Oct 2013 05:53:58 +0000 (07:53 +0200)
Usually by polling flag status register is enough to erase/program
die based micron flashes instead of read status register.

But dual parallel with die based micron topology doesn't works
with this setup instead it requires both the registers need to poll.

So, updated the code for polling read and flag status register for
die based micron flash devices.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
Acked-by: Punnaiah Choudary Kalluri <punnaia@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/mtd/spi/spi_flash.c
drivers/mtd/spi/stmicro.c

index 6c266ac1a3656a04adfd810f31d82bf4b0d9999f..314391ba946d58b7dd5d2c9493c9bb164b8fe50c 100644 (file)
@@ -71,46 +71,57 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
        return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
 }
 
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+static int spi_flash_get_status(struct spi_flash *flash, u8 cmd, u8 *resp)
 {
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
        int ret;
-       u8 status;
-       u8 check_status = 0x0;
-       u8 poll_bit = STATUS_WIP;
-       u8 cmd = flash->poll_cmd;
-
-       if (cmd == CMD_FLAG_STATUS) {
-               poll_bit = STATUS_PEC;
-               check_status = poll_bit;
-       }
+       struct spi_slave *spi = flash->spi;
 
        ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
        if (ret) {
                debug("SF: fail to read %s status register\n",
-                       cmd == CMD_READ_STATUS ? "read" : "flag");
+                     cmd == CMD_READ_STATUS ? "read" : "flag");
                return ret;
        }
 
+       WATCHDOG_RESET();
+
+       ret = spi_xfer(spi, 8, NULL, resp, 0);
+       if (ret)
+               return -1;
+
+       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+
+       return 0;
+}
+
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+{
+       unsigned long timebase;
+       u8 status;
+       int ret;
+
        timebase = get_timer(0);
        do {
-               WATCHDOG_RESET();
-
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
+               ret = spi_flash_get_status(flash, CMD_READ_STATUS, &status);
                if (ret)
                        return -1;
 
-               if ((status & poll_bit) == check_status)
-                       break;
-
+               if ((status & STATUS_WIP) == 0) {
+#ifdef CONFIG_SPI_FLASH_STMICRO
+                       if (flash->poll_cmd == CMD_FLAG_STATUS) {
+                               ret = spi_flash_get_status(flash,
+                                               CMD_FLAG_STATUS, &status);
+                               if (ret)
+                                       return -1;
+
+                               if ((status & STATUS_PEC) == STATUS_PEC)
+                                       return 0;
+                       }
+#endif
+                       return 0;
+               }
        } while (get_timer(timebase) < timeout);
 
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if ((status & poll_bit) == check_status)
-               return 0;
-
        /* Timed out */
        debug("SF: time out!\n");
        return -1;
@@ -708,7 +719,6 @@ void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi,
        /* Set up some basic fields - caller will sort out sizes */
        flash->spi = spi;
        flash->name = name;
-       flash->poll_cmd = CMD_READ_STATUS;
 
        flash->read = spi_flash_cmd_read_fast;
        flash->write = spi_flash_cmd_write_multi;
index f7ebcee20e9c3f4fe6229b5b043bba201c3af650..1d75b3477cb21b73034b6cef404da66ab8d78661 100644 (file)
@@ -252,5 +252,9 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
        if (flash->spi->is_dual == MODE_DUAL_STACKED)
                flash->size *= 2;
 
+       /* Poll for flag status, for 256MB devices onwards */
+       if (flash->size >= 0x2000000)
+               flash->poll_cmd = CMD_FLAG_STATUS;
+
        return flash;
 }