summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/cfi_flash.c80
-rw-r--r--drivers/mtd/spi/atmel.c49
-rw-r--r--drivers/mtd/spi/eon.c121
-rw-r--r--drivers/mtd/spi/macronix.c126
-rw-r--r--drivers/mtd/spi/spansion.c120
-rw-r--r--drivers/mtd/spi/spi_flash.c170
-rw-r--r--drivers/mtd/spi/spi_flash_internal.h23
-rw-r--r--drivers/mtd/spi/sst.c116
-rw-r--r--drivers/mtd/spi/stmicro.c125
-rw-r--r--drivers/mtd/spi/winbond.c148
10 files changed, 233 insertions, 845 deletions
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 0909fe715a..5788328ef1 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -1929,7 +1929,8 @@ ulong flash_get_size (phys_addr_t base, int banknum)
/* Do manufacturer-specific fixups */
switch (info->manufacturer_id) {
- case 0x0001:
+ case 0x0001: /* AMD */
+ case 0x0037: /* AMIC */
flash_fixup_amd(info, &qry);
break;
case 0x001f:
@@ -2085,6 +2086,46 @@ static void cfi_flash_set_config_reg(u32 base, u16 val)
/*-----------------------------------------------------------------------
*/
+
+void flash_protect_default(void)
+{
+ /* Monitor protection ON by default */
+#if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) && \
+ (!defined(CONFIG_MONITOR_IS_IN_RAM))
+ flash_protect(FLAG_PROTECT_SET,
+ CONFIG_SYS_MONITOR_BASE,
+ CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
+ flash_get_info(CONFIG_SYS_MONITOR_BASE));
+#endif
+
+ /* Environment protection ON by default */
+#ifdef CONFIG_ENV_IS_IN_FLASH
+ flash_protect(FLAG_PROTECT_SET,
+ CONFIG_ENV_ADDR,
+ CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
+ flash_get_info(CONFIG_ENV_ADDR));
+#endif
+
+ /* Redundant environment protection ON by default */
+#ifdef CONFIG_ENV_ADDR_REDUND
+ flash_protect(FLAG_PROTECT_SET,
+ CONFIG_ENV_ADDR_REDUND,
+ CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
+ flash_get_info(CONFIG_ENV_ADDR_REDUND));
+#endif
+
+#if defined(CONFIG_SYS_FLASH_AUTOPROTECT_LIST)
+ for (i = 0; i < (sizeof(apl) / sizeof(struct apl_s)); i++) {
+ debug("autoprotecting from %08x to %08x\n",
+ apl[i].start, apl[i].start + apl[i].size - 1);
+ flash_protect(FLAG_PROTECT_SET,
+ apl[i].start,
+ apl[i].start + apl[i].size - 1,
+ flash_get_info(apl[i].start));
+ }
+#endif
+}
+
unsigned long flash_init (void)
{
unsigned long size = 0;
@@ -2171,42 +2212,7 @@ unsigned long flash_init (void)
#endif /* CONFIG_SYS_FLASH_PROTECTION */
}
- /* Monitor protection ON by default */
-#if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) && \
- (!defined(CONFIG_MONITOR_IS_IN_RAM))
- flash_protect (FLAG_PROTECT_SET,
- CONFIG_SYS_MONITOR_BASE,
- CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
- flash_get_info(CONFIG_SYS_MONITOR_BASE));
-#endif
-
- /* Environment protection ON by default */
-#ifdef CONFIG_ENV_IS_IN_FLASH
- flash_protect (FLAG_PROTECT_SET,
- CONFIG_ENV_ADDR,
- CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
- flash_get_info(CONFIG_ENV_ADDR));
-#endif
-
- /* Redundant environment protection ON by default */
-#ifdef CONFIG_ENV_ADDR_REDUND
- flash_protect (FLAG_PROTECT_SET,
- CONFIG_ENV_ADDR_REDUND,
- CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
- flash_get_info(CONFIG_ENV_ADDR_REDUND));
-#endif
-
-#if defined(CONFIG_SYS_FLASH_AUTOPROTECT_LIST)
- for (i = 0; i < (sizeof(apl) / sizeof(struct apl_s)); i++) {
- debug("autoprotecting from %08x to %08x\n",
- apl[i].start, apl[i].start + apl[i].size - 1);
- flash_protect (FLAG_PROTECT_SET,
- apl[i].start,
- apl[i].start + apl[i].size - 1,
- flash_get_info(apl[i].start));
- }
-#endif
-
+ flash_protect_default();
#ifdef CONFIG_FLASH_CFI_MTD
cfi_mtd_init();
#endif
diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c
index 8d0216956d..a9910b11b8 100644
--- a/drivers/mtd/spi/atmel.c
+++ b/drivers/mtd/spi/atmel.c
@@ -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);
}
/*
@@ -170,20 +143,6 @@ static void at45_build_address(struct atmel_spi_flash *asf, u8 *cmd, u32 offset)
cmd[2] = byte_addr;
}
-static int dataflash_read_fast_p2(struct spi_flash *flash,
- u32 offset, size_t len, void *buf)
-{
- u8 cmd[5];
-
- cmd[0] = CMD_READ_ARRAY_FAST;
- cmd[1] = offset >> 16;
- cmd[2] = offset >> 8;
- cmd[3] = offset;
- cmd[4] = 0x00;
-
- return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
-}
-
static int dataflash_read_fast_at45(struct spi_flash *flash,
u32 offset, size_t len, void *buf)
{
@@ -519,7 +478,7 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
asf->flash.erase = dataflash_erase_at45;
page_size += 1 << (params->l2_page_size - 5);
} else {
- asf->flash.read = dataflash_read_fast_p2;
+ asf->flash.read = spi_flash_cmd_read_fast;
asf->flash.write = dataflash_write_p2;
asf->flash.erase = dataflash_erase_p2;
}
@@ -528,7 +487,7 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
case DF_FAMILY_AT26F:
case DF_FAMILY_AT26DF:
- asf->flash.read = dataflash_read_fast_p2;
+ asf->flash.read = spi_flash_cmd_read_fast;
break;
default:
diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c
index 02c3bb9304..01caed5abe 100644
--- a/drivers/mtd/spi/eon.c
+++ b/drivers/mtd/spi/eon.c
@@ -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,60 +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)
-{
- struct eon_spi_flash *eon = to_eon_spi_flash(flash);
- unsigned long page_addr;
- unsigned long page_size;
- u8 cmd[5];
-
- page_size = eon->params->page_size;
- page_addr = offset / page_size;
-
- cmd[0] = CMD_READ_ARRAY_FAST;
- cmd[1] = page_addr >> 8;
- cmd[2] = page_addr;
- cmd[3] = offset % page_size;
- cmd[4] = 0x00;
-
- return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
-}
-
static int eon_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
@@ -160,11 +104,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;
@@ -179,60 +121,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 = eon_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
- if (ret < 0) {
- debug("SF: EON page erase timed out\n");
- 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)
@@ -264,7 +157,7 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
eon->flash.write = eon_write;
eon->flash.erase = eon_erase;
- eon->flash.read = eon_read_fast;
+ eon->flash.read = spi_flash_cmd_read_fast;
eon->flash.size = params->page_size * params->pages_per_sector
* params->nr_sectors;
diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c
index 76d52841d1..4155d4d9a4 100644
--- a/drivers/mtd/spi/macronix.c
+++ b/drivers/mtd/spi/macronix.c
@@ -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,60 +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)
-{
- struct macronix_spi_flash *mcx = to_macronix_spi_flash(flash);
- unsigned long page_addr;
- unsigned long page_size;
- u8 cmd[5];
-
- page_size = mcx->params->page_size;
- page_addr = offset / page_size;
-
- cmd[0] = CMD_READ_ARRAY_FAST;
- cmd[1] = page_addr >> 8;
- cmd[2] = page_addr;
- cmd[3] = offset % page_size;
- cmd[4] = 0x00;
-
- return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
-}
-
static int macronix_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
@@ -216,11 +160,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;
@@ -236,64 +178,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 = macronix_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
- if (ret < 0) {
- debug("SF: Macronix page erase timed out\n");
- 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)
@@ -326,7 +214,7 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
mcx->flash.write = macronix_write;
mcx->flash.erase = macronix_erase;
- mcx->flash.read = macronix_read_fast;
+ mcx->flash.read = spi_flash_cmd_read_fast;
mcx->flash.size = params->page_size * params->pages_per_sector
* params->sectors_per_block * params->nr_blocks;
diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c
index c0900f978f..d54a5fad23 100644
--- a/drivers/mtd/spi/spansion.c
+++ b/drivers/mtd/spi/spansion.c
@@ -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,56 +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)
-{
- struct spansion_spi_flash *spsn = to_spansion_spi_flash(flash);
- unsigned long page_addr;
- unsigned long page_size;
- u8 cmd[5];
-
- page_size = spsn->params->page_size;
- page_addr = offset / page_size;
-
- cmd[0] = CMD_READ_ARRAY_FAST;
- cmd[1] = page_addr >> 8;
- cmd[2] = page_addr;
- cmd[3] = offset % page_size;
- cmd[4] = 0x00;
-
- debug
- ("READ: 0x%x => cmd = { 0x%02x 0x%02x%02x%02x%02x } len = 0x%x\n",
- offset, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], len);
-
- return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
-}
-
static int spansion_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
@@ -233,11 +181,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;
@@ -253,63 +199,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;
- }
-
- /* 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");
- 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)
@@ -347,7 +239,7 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
spsn->flash.write = spansion_write;
spsn->flash.erase = spansion_erase;
- spsn->flash.read = spansion_read_fast;
+ spsn->flash.read = spi_flash_cmd_read_fast;
spsn->flash.size = params->page_size * params->pages_per_sector
* params->nr_sectors;
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index b61d2198cd..5c261f14a6 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -14,32 +14,18 @@
#include "spi_flash_internal.h"
-int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
+static void spi_flash_addr(u32 addr, u8 *cmd)
{
- unsigned long flags = SPI_XFER_BEGIN;
- int ret;
-
- if (len == 0)
- flags |= SPI_XFER_END;
-
- ret = spi_xfer(spi, 8, &cmd, NULL, flags);
- if (ret) {
- debug("SF: Failed to send command %02x: %d\n", cmd, ret);
- return ret;
- }
-
- if (len) {
- ret = spi_xfer(spi, len * 8, NULL, response, SPI_XFER_END);
- if (ret)
- debug("SF: Failed to read response (%zu bytes): %d\n",
- len, ret);
- }
-
- return ret;
+ /* cmd[0] is actual command */
+ cmd[1] = addr >> 16;
+ cmd[2] = addr >> 8;
+ cmd[3] = addr >> 0;
}
-int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
- size_t cmd_len, void *data, size_t data_len)
+static int spi_flash_read_write(struct spi_slave *spi,
+ const u8 *cmd, size_t cmd_len,
+ const u8 *data_out, u8 *data_in,
+ size_t data_len)
{
unsigned long flags = SPI_XFER_BEGIN;
int ret;
@@ -49,52 +35,148 @@ int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
if (ret) {
- debug("SF: Failed to send read command (%zu bytes): %d\n",
+ debug("SF: Failed to send command (%zu bytes): %d\n",
cmd_len, ret);
} else if (data_len != 0) {
- ret = spi_xfer(spi, data_len * 8, NULL, data, SPI_XFER_END);
+ ret = spi_xfer(spi, data_len * 8, data_out, data_in, SPI_XFER_END);
if (ret)
- debug("SF: Failed to read %zu bytes of data: %d\n",
+ debug("SF: Failed to transfer %zu bytes of data: %d\n",
data_len, ret);
}
return ret;
}
+int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
+{
+ return spi_flash_cmd_read(spi, &cmd, 1, response, len);
+}
+
+int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
+ size_t cmd_len, void *data, size_t data_len)
+{
+ return spi_flash_read_write(spi, cmd, cmd_len, NULL, data, data_len);
+}
+
int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
const void *data, size_t data_len)
{
- unsigned long flags = SPI_XFER_BEGIN;
+ return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
+}
+
+int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
+ size_t cmd_len, void *data, size_t data_len)
+{
+ struct spi_slave *spi = flash->spi;
int ret;
- if (data_len == 0)
- flags |= SPI_XFER_END;
+ spi_claim_bus(spi);
+ ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
+ spi_release_bus(spi);
- ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
+ return ret;
+}
+
+int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
+ size_t len, void *data)
+{
+ u8 cmd[5];
+
+ cmd[0] = CMD_READ_ARRAY_FAST;
+ spi_flash_addr(offset, cmd);
+ cmd[4] = 0x00;
+
+ return spi_flash_read_common(flash, cmd, sizeof(cmd), data, len);
+}
+
+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 read command (%zu bytes): %d\n",
- cmd_len, ret);
- } else if (data_len != 0) {
- ret = spi_xfer(spi, data_len * 8, data, NULL, SPI_XFER_END);
- if (ret)
- debug("SF: Failed to read %zu bytes of data: %d\n",
- data_len, ret);
+ debug("SF: Failed to send command %02x: %d\n", cmd, ret);
+ return 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);
+}
-int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
- size_t cmd_len, void *data, size_t data_len)
+int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
+ u32 erase_size, u32 offset, size_t len)
{
- struct spi_slave *spi = flash->spi;
+ u32 start, end;
int ret;
+ u8 cmd[4];
- spi_claim_bus(spi);
- ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
- spi_release_bus(spi);
+ 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;
}
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h
index 68dcffb971..d7bcd6d6af 100644
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/spi_flash_internal.h
@@ -19,6 +19,12 @@
#define CMD_READ_ARRAY_FAST 0x0b
#define CMD_READ_ARRAY_LEGACY 0xe8
+#define CMD_READ_STATUS 0x05
+#define CMD_WRITE_ENABLE 0x06
+
+/* 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);
@@ -29,6 +35,9 @@ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
size_t cmd_len, void *data, size_t data_len);
+int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
+ size_t len, void *data);
+
/*
* Send a multi-byte command to the device followed by (optional)
* data. Used for programming the flash array, etc.
@@ -43,6 +52,20 @@ 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);
+
+/* 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);
diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c
index 25578914c6..792d04dd2b 100644
--- a/drivers/mtd/spi/sst.c
+++ b/drivers/mtd/spi/sst.c
@@ -90,41 +90,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)
{
int ret = spi_flash_cmd(flash->spi, CMD_SST_WREN, NULL, 0);
@@ -143,19 +108,6 @@ sst_disable_writing(struct spi_flash *flash)
}
static int
-sst_read_fast(struct spi_flash *flash, u32 offset, size_t len, void *buf)
-{
- u8 cmd[5] = {
- CMD_READ_ARRAY_FAST,
- offset >> 16,
- offset >> 8,
- offset,
- 0x00,
- };
- return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
-}
-
-static int
sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
{
int ret;
@@ -177,7 +129,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 +176,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;
@@ -247,67 +199,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 = sst_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
@@ -361,7 +256,6 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
stm->flash.write = sst_write;
stm->flash.erase = sst_erase;
- stm->flash.read = sst_read_fast;
stm->flash.size = SST_SECTOR_SIZE * params->nr_sectors;
printf("SF: Detected %s with page size %u, total ",
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
index 31340279cb..7ef690d9bf 100644
--- a/drivers/mtd/spi/stmicro.c
+++ b/drivers/mtd/spi/stmicro.c
@@ -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,60 +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)
-{
- struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
- unsigned long page_addr;
- unsigned long page_size;
- u8 cmd[5];
-
- page_size = stm->params->page_size;
- page_addr = offset / page_size;
-
- cmd[0] = CMD_READ_ARRAY_FAST;
- cmd[1] = page_addr >> 8;
- cmd[2] = page_addr;
- cmd[3] = offset % page_size;
- cmd[4] = 0x00;
-
- return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
-}
-
static int stmicro_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
@@ -238,11 +182,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;
@@ -258,64 +200,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 = stmicro_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
- if (ret < 0) {
- debug("SF: STMicro page erase timed out\n");
- 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)
@@ -361,7 +248,7 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
stm->flash.write = stmicro_write;
stm->flash.erase = stmicro_erase;
- stm->flash.read = stmicro_read_fast;
+ stm->flash.read = spi_flash_cmd_read_fast;
stm->flash.size = params->page_size * params->pages_per_sector
* params->nr_sectors;
diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c
index 44523555d9..e88802f0e6 100644
--- a/drivers/mtd/spi/winbond.c
+++ b/drivers/mtd/spi/winbond.c
@@ -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,81 +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.
- */
-static void winbond_build_address(struct winbond_spi_flash *stm, u8 *cmd, u32 offset)
-{
- unsigned long page_addr;
- unsigned long byte_addr;
- unsigned long page_size;
- unsigned int page_shift;
-
- /*
- * The "extra" space per page is the power-of-two page size
- * divided by 32.
- */
- page_shift = stm->params->l2_page_size;
- page_size = (1 << page_shift);
- page_addr = offset / page_size;
- byte_addr = offset % page_size;
-
- cmd[0] = page_addr >> (16 - page_shift);
- cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8);
- cmd[2] = byte_addr;
-}
-
-static int winbond_read_fast(struct spi_flash *flash,
- u32 offset, size_t len, void *buf)
-{
- struct winbond_spi_flash *stm = to_winbond_spi_flash(flash);
- u8 cmd[5];
-
- cmd[0] = CMD_READ_ARRAY_FAST;
- winbond_build_address(stm, cmd + 1, offset);
- cmd[4] = 0x00;
-
- return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
-}
-
static int winbond_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
@@ -230,11 +153,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;
@@ -252,66 +173,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 = winbond_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
- if (ret < 0) {
- debug("SF: Winbond sector erase timed out\n");
- 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)
@@ -348,7 +212,7 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
stm->flash.write = winbond_write;
stm->flash.erase = winbond_erase;
- stm->flash.read = winbond_read_fast;
+ stm->flash.read = spi_flash_cmd_read_fast;
stm->flash.size = page_size * params->pages_per_sector
* params->sectors_per_block
* params->nr_blocks;