sf: unify erase functions
authorMike Frysinger <vapier@gentoo.org>
Mon, 10 Jan 2011 07:20:13 +0000 (02:20 -0500)
committerWolfgang Denk <wd@denx.de>
Mon, 11 Apr 2011 19:00:54 +0000 (21:00 +0200)
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
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 4af1e06..0c0b05f 100644 (file)
@@ -141,58 +141,11 @@ static int eon_write(struct spi_flash *flash,
 
 int eon_erase(struct spi_flash *flash, u32 offset, size_t len)
 {
-       /* block erase */
        struct eon_spi_flash *eon = to_eon_spi_flash(flash);
-       unsigned long block_size;
-       size_t actual;
-       int ret;
-       u8 cmd[4];
-
-
-       block_size = eon->params->page_size * eon->params->pages_per_sector
-              * eon->params->sectors_per_block;
-
-       if (offset % block_size || len % block_size) {
-               debug("SF: Erase offset/length not multiple of block size\n");
-               return -1;
-       }
-
-       len /= block_size;
-       cmd[0] = CMD_EN25Q128_BE;
-       cmd[2] = 0x00;
-       cmd[3] = 0x00;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       ret = 0;
-       for (actual = 0; actual < len; actual++) {
-               cmd[1] = (offset / block_size) + actual;
-               ret = spi_flash_cmd(flash->spi, CMD_EN25Q128_WREN, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: Enabling Write failed\n");
-                       break;
-               }
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: EON page erase failed\n");
-                       break;
-               }
-
-               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",
-             len * block_size, offset);
-
-       spi_release_bus(flash->spi);
-       return ret;
+       return spi_flash_cmd_erase(flash, CMD_EN25Q128_BE,
+               eon->params->page_size * eon->params->pages_per_sector *
+                       eon->params->sectors_per_block;
+               offset, len);
 }
 
 struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
index 291fd17..573e1db 100644 (file)
@@ -198,62 +198,10 @@ static int macronix_write(struct spi_flash *flash,
 int macronix_erase(struct spi_flash *flash, u32 offset, size_t len)
 {
        struct macronix_spi_flash *mcx = to_macronix_spi_flash(flash);
-       unsigned long sector_size;
-       size_t actual;
-       int ret;
-       u8 cmd[4];
-
-       /*
-        * This function currently uses sector erase only.
-        * probably speed things up by using bulk erase
-        * when possible.
-        */
-
-       sector_size = mcx->params->page_size * mcx->params->pages_per_sector
-                       * mcx->params->sectors_per_block;
-
-       if (offset % sector_size || len % sector_size) {
-               debug("SF: Erase offset/length not multiple of sector size\n");
-               return -1;
-       }
-
-       len /= sector_size;
-       cmd[0] = CMD_MX25XX_BE;
-       cmd[2] = 0x00;
-       cmd[3] = 0x00;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       ret = 0;
-       for (actual = 0; actual < len; actual++) {
-               cmd[1] = (offset / sector_size) + actual;
-
-               ret = spi_flash_cmd(flash->spi, CMD_MX25XX_WREN, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: Enabling Write failed\n");
-                       break;
-               }
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: Macronix page erase failed\n");
-                       break;
-               }
-
-               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",
-             len * sector_size, offset);
-
-       spi_release_bus(flash->spi);
-       return ret;
+       return spi_flash_cmd_erase(flash, CMD_MX25XX_BE,
+               mcx->params->page_size * mcx->params->pages_per_sector *
+                       mcx->params->sectors_per_block,
+               offset, len);
 }
 
 struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
index d0f03ff..be4fc67 100644 (file)
@@ -223,60 +223,9 @@ static int spansion_write(struct spi_flash *flash,
 int spansion_erase(struct spi_flash *flash, u32 offset, size_t len)
 {
        struct spansion_spi_flash *spsn = to_spansion_spi_flash(flash);
-       unsigned long sector_size;
-       size_t actual;
-       int ret;
-       u8 cmd[4];
-
-       /*
-        * This function currently uses sector erase only.
-        * probably speed things up by using bulk erase
-        * when possible.
-        */
-
-       sector_size = spsn->params->page_size * spsn->params->pages_per_sector;
-
-       if (offset % sector_size || len % sector_size) {
-               debug("SF: Erase offset/length not multiple of sector size\n");
-               return -1;
-       }
-
-       cmd[0] = CMD_S25FLXX_SE;
-       cmd[2] = 0x00;
-       cmd[3] = 0x00;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       ret = 0;
-       for (actual = 0; actual < len; actual += sector_size) {
-               cmd[1] = (offset + actual) >> 16;
-
-               ret = spi_flash_cmd(flash->spi, CMD_S25FLXX_WREN, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: Enabling Write failed\n");
-                       break;
-               }
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: SPANSION page erase failed\n");
-                       break;
-               }
-
-               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",
-             len, offset);
-
-       spi_release_bus(flash->spi);
-       return ret;
+       return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE,
+               spsn->params->page_size * spsn->params->pages_per_sector,
+               offset, len);
 }
 
 struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
index e483ce4..ca4bbb2 100644 (file)
 
 #include "spi_flash_internal.h"
 
+static void spi_flash_addr(u32 addr, u8 *cmd)
+{
+       /* cmd[0] is actual command */
+       cmd[1] = addr >> 16;
+       cmd[2] = addr >> 8;
+       cmd[3] = addr >> 0;
+}
+
 static int spi_flash_read_write(struct spi_slave *spi,
                                const u8 *cmd, size_t cmd_len,
                                const u8 *data_out, u8 *data_in,
@@ -110,6 +118,56 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
                CMD_READ_STATUS, STATUS_WIP);
 }
 
+int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
+                       u32 erase_size, u32 offset, size_t len)
+{
+       u32 start, end;
+       int ret;
+       u8 cmd[4];
+
+       if (offset % erase_size || len % erase_size) {
+               debug("SF: Erase offset/length not multiple of erase size\n");
+               return -1;
+       }
+
+       ret = spi_claim_bus(flash->spi);
+       if (ret) {
+               debug("SF: Unable to claim SPI bus\n");
+               return ret;
+       }
+
+       cmd[0] = erase_cmd;
+       start = offset;
+       end = start + len;
+
+       while (offset < end) {
+               spi_flash_addr(offset, cmd);
+               offset += erase_size;
+
+               debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
+                     cmd[2], cmd[3], offset);
+
+               ret = spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0);
+               if (ret)
+                       goto out;
+
+               ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), NULL, 0);
+               if (ret)
+                       goto out;
+
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
+               if (ret)
+                       goto out;
+       }
+
+       debug("SF: Successfully erased %lu bytes @ %#x\n",
+             len * erase_size, start);
+
+ out:
+       spi_release_bus(flash->spi);
+       return ret;
+}
+
 /*
  * The following table holds all device probe functions
  *
index 440c044..114b634 100644 (file)
@@ -20,6 +20,7 @@
 #define CMD_READ_ARRAY_LEGACY          0xe8
 
 #define CMD_READ_STATUS                        0x05
+#define CMD_WRITE_ENABLE               0x06
 
 /* Common status */
 #define STATUS_WIP                     0x01
@@ -58,6 +59,10 @@ int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
  */
 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
 
+/* Erase sectors. */
+int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
+                       u32 erase_size, u32 offset, size_t len);
+
 /* 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 4a82f8a..d550550 100644 (file)
@@ -212,67 +212,10 @@ sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
        return ret;
 }
 
-int
-sst_erase(struct spi_flash *flash, u32 offset, size_t len)
+int sst_erase(struct spi_flash *flash, u32 offset, size_t len)
 {
-       unsigned long sector_size;
-       u32 start, end;
-       int ret;
-       u8 cmd[4];
-
-       /*
-        * This function currently uses sector erase only.
-        * Probably speed things up by using bulk erase
-        * when possible.
-        */
-
-       sector_size = SST_SECTOR_SIZE;
-
-       if (offset % sector_size) {
-               debug("SF: Erase offset not multiple of sector size\n");
-               return -1;
-       }
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       cmd[0] = CMD_SST_SE;
-       cmd[3] = 0;
-       start = offset;
-       end = start + len;
-
-       ret = 0;
-       while (offset < end) {
-               cmd[1] = offset >> 16;
-               cmd[2] = offset >> 8;
-               offset += sector_size;
-
-               debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
-                     cmd[2], cmd[3], offset);
-
-               ret = sst_enable_writing(flash);
-               if (ret)
-                       break;
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), NULL, 0);
-               if (ret) {
-                       debug("SF: sst page erase failed\n");
-                       break;
-               }
-
-               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-               if (ret)
-                       break;
-       }
-
-       debug("SF: sst: Successfully erased %lu bytes @ 0x%x\n",
-             len * sector_size, start);
-
-       spi_release_bus(flash->spi);
-       return ret;
+       return spi_flash_cmd_erase(flash, CMD_SST_SE, SST_SECTOR_SIZE,
+               offset, len);
 }
 
 static int
index 02da8b2..494005c 100644 (file)
@@ -220,62 +220,9 @@ static int stmicro_write(struct spi_flash *flash,
 int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
 {
        struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
-       unsigned long sector_size;
-       size_t actual;
-       int ret;
-       u8 cmd[4];
-
-       /*
-        * This function currently uses sector erase only.
-        * probably speed things up by using bulk erase
-        * when possible.
-        */
-
-       sector_size = stm->params->page_size * stm->params->pages_per_sector;
-
-       if (offset % sector_size || len % sector_size) {
-               debug("SF: Erase offset/length not multiple of sector size\n");
-               return -1;
-       }
-
-       len /= sector_size;
-       cmd[0] = CMD_M25PXX_SE;
-       cmd[2] = 0x00;
-       cmd[3] = 0x00;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       ret = 0;
-       for (actual = 0; actual < len; actual++) {
-               cmd[1] = offset >> 16;
-               offset += sector_size;
-
-               ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: Enabling Write failed\n");
-                       break;
-               }
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: STMicro page erase failed\n");
-                       break;
-               }
-
-               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",
-             len * sector_size, offset);
-
-       spi_release_bus(flash->spi);
-       return ret;
+       return spi_flash_cmd_erase(flash, CMD_M25PXX_SE,
+               stm->params->page_size * stm->params->pages_per_sector,
+               offset, len);
 }
 
 struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
index d8c1cb1..8470a82 100644 (file)
@@ -211,64 +211,9 @@ out:
 int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)
 {
        struct winbond_spi_flash *stm = to_winbond_spi_flash(flash);
-       unsigned long sector_size;
-       unsigned int page_shift;
-       size_t actual;
-       int ret;
-       u8 cmd[4];
-
-       /*
-        * This function currently uses sector erase only.
-        * probably speed things up by using bulk erase
-        * when possible.
-        */
-
-       page_shift = stm->params->l2_page_size;
-       sector_size = (1 << page_shift) * stm->params->pages_per_sector;
-
-       if (offset % sector_size || len % sector_size) {
-               debug("SF: Erase offset/length not multiple of sector size\n");
-               return -1;
-       }
-
-       len /= sector_size;
-       cmd[0] = CMD_W25_SE;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       for (actual = 0; actual < len; actual++) {
-               winbond_build_address(stm, &cmd[1], offset + actual * sector_size);
-               printf("Erase: %02x %02x %02x %02x\n",
-                               cmd[0], cmd[1], cmd[2], cmd[3]);
-
-               ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: Enabling Write failed\n");
-                       goto out;
-               }
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: Winbond sector erase failed\n");
-                       goto out;
-               }
-
-               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",
-                       len * sector_size, offset);
-       ret = 0;
-
-out:
-       spi_release_bus(flash->spi);
-       return ret;
+       return spi_flash_cmd_erase(flash, CMD_W25_SE,
+               (1 << stm->params->l2_page_size) * stm->params->pages_per_sector,
+               offset, len);
 }
 
 struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)