summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/cfi_flash.c4
-rw-r--r--drivers/mtd/spi/eeprom_m95xxx.c5
-rw-r--r--drivers/mtd/spi/eon.c102
-rw-r--r--drivers/mtd/spi/macronix.c98
-rw-r--r--drivers/mtd/spi/ramtron.c2
-rw-r--r--drivers/mtd/spi/spansion.c98
-rw-r--r--drivers/mtd/spi/spi_flash.c59
-rw-r--r--drivers/mtd/spi/spi_flash_internal.h25
-rw-r--r--drivers/mtd/spi/sst.c26
-rw-r--r--drivers/mtd/spi/stmicro.c124
-rw-r--r--drivers/mtd/spi/winbond.c104
11 files changed, 183 insertions, 464 deletions
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 929f9a9..ac91dfd 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -573,7 +573,9 @@ static int flash_status_check (flash_info_t * info, flash_sect_t sector,
#endif
/* Wait for command completion */
+#ifdef CONFIG_SYS_LOW_RES_TIMER
reset_timer();
+#endif
start = get_timer (0);
while (flash_is_busy (info, sector)) {
if (get_timer (start) > tout) {
@@ -662,7 +664,9 @@ static int flash_status_poll(flash_info_t *info, void *src, void *dst,
#endif
/* Wait for command completion */
+#ifdef CONFIG_SYS_LOW_RES_TIMER
reset_timer();
+#endif
start = get_timer(0);
while (1) {
switch (info->portwidth) {
diff --git a/drivers/mtd/spi/eeprom_m95xxx.c b/drivers/mtd/spi/eeprom_m95xxx.c
index 632db4e..ef8ed6f 100644
--- a/drivers/mtd/spi/eeprom_m95xxx.c
+++ b/drivers/mtd/spi/eeprom_m95xxx.c
@@ -75,6 +75,7 @@ ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
{
struct spi_slave *slave;
char buf[3];
+ ulong start;
slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000,
CONFIG_DEFAULT_SPI_MODE);
@@ -102,7 +103,7 @@ ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
if(spi_xfer(slave, len * 8, buffer, NULL, SPI_XFER_END))
return -1;
- reset_timer_masked();
+ start = get_timer(0);
do {
buf[0] = SPI_EEPROM_RDSR;
buf[1] = 0;
@@ -111,7 +112,7 @@ ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
if (!(buf[1] & 1))
break;
- } while (get_timer_masked() < CONFIG_SYS_SPI_WRITE_TOUT);
+ } while (get_timer(start) < CONFIG_SYS_SPI_WRITE_TOUT);
if (buf[1] & 1)
printf ("*** spi_write: Time out while writing!\n");
diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c
index e3de3aa..806b44e 100644
--- a/drivers/mtd/spi/eon.c
+++ b/drivers/mtd/spi/eon.c
@@ -23,8 +23,6 @@
#define CMD_EN25Q128_DP 0xb9 /* Deep Power-down */
#define CMD_EN25Q128_RES 0xab /* Release from DP, and Read Signature */
-#define EON_ID_EN25Q128 0x18
-
struct eon_spi_flash_params {
u8 idcode1;
u16 page_size;
@@ -34,20 +32,9 @@ struct eon_spi_flash_params {
const char *name;
};
-/* spi_flash needs to be first so upper layers can free() it */
-struct eon_spi_flash {
- struct spi_flash flash;
- const struct eon_spi_flash_params *params;
-};
-
-static inline struct eon_spi_flash *to_eon_spi_flash(struct spi_flash *flash)
-{
- return container_of(flash, struct eon_spi_flash, flash);
-}
-
static const struct eon_spi_flash_params eon_spi_flash_table[] = {
{
- .idcode1 = EON_ID_EN25Q128,
+ .idcode1 = 0x18,
.page_size = 256,
.pages_per_sector = 16,
.sectors_per_block = 16,
@@ -56,69 +43,6 @@ static const struct eon_spi_flash_params eon_spi_flash_table[] = {
},
};
-static int eon_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
-{
- struct eon_spi_flash *eon = to_eon_spi_flash(flash);
- unsigned long page_addr;
- unsigned long byte_addr;
- unsigned long page_size;
- size_t chunk_len;
- size_t actual;
- int ret;
- u8 cmd[4];
-
- page_size = eon->params->page_size;
- page_addr = offset / page_size;
- byte_addr = offset % page_size;
-
- 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 += chunk_len) {
- chunk_len = min(len - actual, page_size - byte_addr);
-
- cmd[0] = CMD_EN25Q128_PP;
- cmd[1] = page_addr >> 8;
- cmd[2] = page_addr;
- cmd[3] = byte_addr;
-
- debug
- ("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n",
- buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
-
- 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,
- buf + actual, chunk_len);
- if (ret < 0) {
- debug("SF: EON Page Program failed\n");
- break;
- }
-
- ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
- if (ret)
- break;
-
- page_addr++;
- byte_addr = 0;
- }
-
- debug("SF: EON: Successfully programmed %u bytes @ 0x%x\n",
- len, offset);
-
- spi_release_bus(flash->spi);
- return ret;
-}
-
static int eon_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_EN25Q128_BE, offset, len);
@@ -127,7 +51,7 @@ static int eon_erase(struct spi_flash *flash, u32 offset, size_t len)
struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
{
const struct eon_spi_flash_params *params;
- struct eon_spi_flash *eon;
+ struct spi_flash *flash;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(eon_spi_flash_table); ++i) {
@@ -141,23 +65,23 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- eon = malloc(sizeof(*eon));
- if (!eon) {
+ flash = malloc(sizeof(*flash));
+ if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- eon->params = params;
- eon->flash.spi = spi;
- eon->flash.name = params->name;
+ flash->spi = spi;
+ flash->name = params->name;
- eon->flash.write = eon_write;
- eon->flash.erase = eon_erase;
- eon->flash.read = spi_flash_cmd_read_fast;
- eon->flash.sector_size = params->page_size * params->pages_per_sector
+ flash->write = spi_flash_cmd_write_multi;
+ flash->erase = eon_erase;
+ flash->read = spi_flash_cmd_read_fast;
+ flash->page_size = params->page_size;
+ flash->sector_size = params->page_size * params->pages_per_sector
* params->sectors_per_block;
- eon->flash.size = params->page_size * params->pages_per_sector
+ flash->size = params->page_size * params->pages_per_sector
* params->nr_sectors;
- return &eon->flash;
+ return flash;
}
diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c
index ff66f2a..e689562 100644
--- a/drivers/mtd/spi/macronix.c
+++ b/drivers/mtd/spi/macronix.c
@@ -58,17 +58,6 @@ struct macronix_spi_flash_params {
const char *name;
};
-struct macronix_spi_flash {
- struct spi_flash flash;
- const struct macronix_spi_flash_params *params;
-};
-
-static inline struct macronix_spi_flash *to_macronix_spi_flash(struct spi_flash
- *flash)
-{
- return container_of(flash, struct macronix_spi_flash, flash);
-}
-
static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {
{
.idcode = 0x2015,
@@ -112,69 +101,6 @@ static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {
},
};
-static int macronix_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
-{
- struct macronix_spi_flash *mcx = to_macronix_spi_flash(flash);
- unsigned long page_addr;
- unsigned long byte_addr;
- unsigned long page_size;
- size_t chunk_len;
- size_t actual;
- int ret;
- u8 cmd[4];
-
- page_size = mcx->params->page_size;
- page_addr = offset / page_size;
- byte_addr = offset % page_size;
-
- 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 += chunk_len) {
- chunk_len = min(len - actual, page_size - byte_addr);
-
- cmd[0] = CMD_MX25XX_PP;
- cmd[1] = page_addr >> 8;
- cmd[2] = page_addr;
- cmd[3] = byte_addr;
-
- debug
- ("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n",
- buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
-
- 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,
- buf + actual, chunk_len);
- if (ret < 0) {
- debug("SF: Macronix Page Program failed\n");
- break;
- }
-
- ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
- if (ret)
- break;
-
- page_addr++;
- byte_addr = 0;
- }
-
- debug("SF: Macronix: Successfully programmed %u bytes @ 0x%x\n",
- len, offset);
-
- spi_release_bus(flash->spi);
- return ret;
-}
-
static int macronix_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_MX25XX_BE, offset, len);
@@ -183,7 +109,7 @@ static int macronix_erase(struct spi_flash *flash, u32 offset, size_t len)
struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
{
const struct macronix_spi_flash_params *params;
- struct macronix_spi_flash *mcx;
+ struct spi_flash *flash;
unsigned int i;
u16 id = idcode[2] | idcode[1] << 8;
@@ -198,22 +124,22 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- mcx = malloc(sizeof(*mcx));
- if (!mcx) {
+ flash = malloc(sizeof(*flash));
+ if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- mcx->params = params;
- mcx->flash.spi = spi;
- mcx->flash.name = params->name;
+ flash->spi = spi;
+ flash->name = params->name;
- mcx->flash.write = macronix_write;
- mcx->flash.erase = macronix_erase;
- mcx->flash.read = spi_flash_cmd_read_fast;
- mcx->flash.sector_size = params->page_size * params->pages_per_sector
+ flash->write = spi_flash_cmd_write_multi;
+ flash->erase = macronix_erase;
+ flash->read = spi_flash_cmd_read_fast;
+ flash->page_size = params->page_size;
+ flash->sector_size = params->page_size * params->pages_per_sector
* params->sectors_per_block;
- mcx->flash.size = mcx->flash.sector_size * params->nr_blocks;
+ flash->size = flash->sector_size * params->nr_blocks;
- return &mcx->flash;
+ return flash;
}
diff --git a/drivers/mtd/spi/ramtron.c b/drivers/mtd/spi/ramtron.c
index 078d16c..27d4039 100644
--- a/drivers/mtd/spi/ramtron.c
+++ b/drivers/mtd/spi/ramtron.c
@@ -198,7 +198,7 @@ static int ramtron_common(struct spi_flash *flash,
if (command == CMD_RAMTRON_WRITE) {
/* send WREN */
- ret = spi_flash_cmd(flash->spi, CMD_RAMTRON_WREN, NULL, 0);
+ ret = spi_flash_cmd_write_enable(flash);
if (ret < 0) {
debug("SF: Enabling Write failed\n");
goto releasebus;
diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c
index a3401b3..28bb51a 100644
--- a/drivers/mtd/spi/spansion.c
+++ b/drivers/mtd/spi/spansion.c
@@ -63,17 +63,6 @@ struct spansion_spi_flash_params {
const char *name;
};
-struct spansion_spi_flash {
- struct spi_flash flash;
- const struct spansion_spi_flash_params *params;
-};
-
-static inline struct spansion_spi_flash *to_spansion_spi_flash(struct spi_flash
- *flash)
-{
- return container_of(flash, struct spansion_spi_flash, flash);
-}
-
static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
{
.idcode1 = SPSN_ID_S25FL008A,
@@ -133,69 +122,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
},
};
-static int spansion_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
-{
- struct spansion_spi_flash *spsn = to_spansion_spi_flash(flash);
- unsigned long page_addr;
- unsigned long byte_addr;
- unsigned long page_size;
- size_t chunk_len;
- size_t actual;
- int ret;
- u8 cmd[4];
-
- page_size = spsn->params->page_size;
- page_addr = offset / page_size;
- byte_addr = offset % page_size;
-
- 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 += chunk_len) {
- chunk_len = min(len - actual, page_size - byte_addr);
-
- cmd[0] = CMD_S25FLXX_PP;
- cmd[1] = page_addr >> 8;
- cmd[2] = page_addr;
- cmd[3] = byte_addr;
-
- debug
- ("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n",
- buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
-
- 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,
- buf + actual, chunk_len);
- if (ret < 0) {
- debug("SF: SPANSION Page Program failed\n");
- break;
- }
-
- ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
- if (ret)
- break;
-
- page_addr++;
- byte_addr = 0;
- }
-
- debug("SF: SPANSION: Successfully programmed %u bytes @ 0x%x\n",
- len, offset);
-
- spi_release_bus(flash->spi);
- return ret;
-}
-
static int spansion_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, offset, len);
@@ -204,7 +130,7 @@ static int spansion_erase(struct spi_flash *flash, u32 offset, size_t len)
struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
{
const struct spansion_spi_flash_params *params;
- struct spansion_spi_flash *spsn;
+ struct spi_flash *flash;
unsigned int i;
unsigned short jedec, ext_jedec;
@@ -224,21 +150,21 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- spsn = malloc(sizeof(struct spansion_spi_flash));
- if (!spsn) {
+ flash = malloc(sizeof(*flash));
+ if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- spsn->params = params;
- spsn->flash.spi = spi;
- spsn->flash.name = params->name;
+ flash->spi = spi;
+ flash->name = params->name;
- spsn->flash.write = spansion_write;
- spsn->flash.erase = spansion_erase;
- spsn->flash.read = spi_flash_cmd_read_fast;
- spsn->flash.sector_size = params->page_size * params->pages_per_sector;
- spsn->flash.size = spsn->flash.sector_size * params->nr_sectors;
+ flash->write = spi_flash_cmd_write_multi;
+ flash->erase = spansion_erase;
+ flash->read = spi_flash_cmd_read_fast;
+ flash->page_size = params->page_size;
+ flash->sector_size = params->page_size * params->pages_per_sector;
+ flash->size = flash->sector_size * params->nr_sectors;
- return &spsn->flash;
+ return flash;
}
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 016b586..730c009 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -65,6 +65,63 @@ 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_write_multi(struct spi_flash *flash, u32 offset,
+ size_t len, const void *buf)
+{
+ unsigned long page_addr, byte_addr, page_size;
+ size_t chunk_len, actual;
+ int ret;
+ u8 cmd[4];
+
+ page_size = flash->page_size;
+ page_addr = offset / page_size;
+ byte_addr = offset % page_size;
+
+ ret = spi_claim_bus(flash->spi);
+ if (ret) {
+ debug("SF: unable to claim SPI bus\n");
+ return ret;
+ }
+
+ cmd[0] = CMD_PAGE_PROGRAM;
+ for (actual = 0; actual < len; actual += chunk_len) {
+ chunk_len = min(len - actual, page_size - byte_addr);
+
+ cmd[1] = page_addr >> 8;
+ cmd[2] = page_addr;
+ cmd[3] = byte_addr;
+
+ debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
+ buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
+
+ ret = spi_flash_cmd_write_enable(flash);
+ if (ret < 0) {
+ debug("SF: enabling write failed\n");
+ break;
+ }
+
+ ret = spi_flash_cmd_write(flash->spi, cmd, 4,
+ buf + actual, chunk_len);
+ if (ret < 0) {
+ debug("SF: write failed\n");
+ break;
+ }
+
+ ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+ if (ret)
+ break;
+
+ page_addr++;
+ byte_addr = 0;
+ }
+
+ debug("SF: program %s %zu bytes @ %#x\n",
+ ret ? "failure" : "success", len, offset);
+
+ spi_release_bus(flash->spi);
+ return ret;
+}
+
int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
size_t cmd_len, void *data, size_t data_len)
{
@@ -163,7 +220,7 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
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);
+ ret = spi_flash_cmd_write_enable(flash);
if (ret)
goto out;
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h
index fc109ce..91e036a 100644
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/spi_flash_internal.h
@@ -19,6 +19,8 @@
#define CMD_READ_ARRAY_FAST 0x0b
#define CMD_READ_ARRAY_LEGACY 0xe8
+#define CMD_PAGE_PROGRAM 0x02
+#define CMD_WRITE_DISABLE 0x04
#define CMD_READ_STATUS 0x05
#define CMD_WRITE_ENABLE 0x06
@@ -46,6 +48,29 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
const void *data, size_t data_len);
/*
+ * Write the requested data out breaking it up into multiple write
+ * commands as needed per the write size.
+ */
+int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
+ size_t len, const void *buf);
+
+/*
+ * Enable writing on the SPI flash.
+ */
+static inline int spi_flash_cmd_write_enable(struct spi_flash *flash)
+{
+ return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0);
+}
+
+/*
+ * Disable writing on the SPI flash.
+ */
+static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
+{
+ return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0);
+}
+
+/*
* Same as spi_flash_cmd_read() except it also claims/releases the SPI
* bus. Used as common part of the ->read() operation.
*/
diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c
index 4dc2db2..9559c80 100644
--- a/drivers/mtd/spi/sst.c
+++ b/drivers/mtd/spi/sst.c
@@ -36,8 +36,12 @@
#define SST_SR_AAI (1 << 6) /* Addressing mode */
#define SST_SR_BPL (1 << 7) /* BP bits lock */
+#define SST_FEAT_WP (1 << 0) /* Supports AAI word program */
+#define SST_FEAT_MBP (1 << 1) /* Supports multibyte program */
+
struct sst_spi_flash_params {
u8 idcode1;
+ u8 flags;
u16 nr_sectors;
const char *name;
};
@@ -53,41 +57,51 @@ static inline struct sst_spi_flash *to_sst_spi_flash(struct spi_flash *flash)
}
#define SST_SECTOR_SIZE (4 * 1024)
+#define SST_PAGE_SIZE 256
static const struct sst_spi_flash_params sst_spi_flash_table[] = {
{
.idcode1 = 0x8d,
+ .flags = SST_FEAT_WP,
.nr_sectors = 128,
.name = "SST25VF040B",
},{
.idcode1 = 0x8e,
+ .flags = SST_FEAT_WP,
.nr_sectors = 256,
.name = "SST25VF080B",
},{
.idcode1 = 0x41,
+ .flags = SST_FEAT_WP,
.nr_sectors = 512,
.name = "SST25VF016B",
},{
.idcode1 = 0x4a,
+ .flags = SST_FEAT_WP,
.nr_sectors = 1024,
.name = "SST25VF032B",
},{
.idcode1 = 0x4b,
+ .flags = SST_FEAT_MBP,
.nr_sectors = 2048,
.name = "SST25VF064C",
},{
.idcode1 = 0x01,
+ .flags = SST_FEAT_WP,
.nr_sectors = 16,
.name = "SST25WF512",
},{
.idcode1 = 0x02,
+ .flags = SST_FEAT_WP,
.nr_sectors = 32,
.name = "SST25WF010",
},{
.idcode1 = 0x03,
+ .flags = SST_FEAT_WP,
.nr_sectors = 64,
.name = "SST25WF020",
},{
.idcode1 = 0x04,
+ .flags = SST_FEAT_WP,
.nr_sectors = 128,
.name = "SST25WF040",
},
@@ -96,7 +110,7 @@ static const struct sst_spi_flash_params sst_spi_flash_table[] = {
static int
sst_enable_writing(struct spi_flash *flash)
{
- int ret = spi_flash_cmd(flash->spi, CMD_SST_WREN, NULL, 0);
+ int ret = spi_flash_cmd_write_enable(flash);
if (ret)
debug("SF: Enabling Write failed\n");
return ret;
@@ -105,7 +119,7 @@ sst_enable_writing(struct spi_flash *flash)
static int
sst_disable_writing(struct spi_flash *flash)
{
- int ret = spi_flash_cmd(flash->spi, CMD_SST_WRDI, NULL, 0);
+ int ret = spi_flash_cmd_write_disable(flash);
if (ret)
debug("SF: Disabling Write failed\n");
return ret;
@@ -137,7 +151,7 @@ sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
}
static int
-sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
+sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
{
size_t actual, cmd_len;
int ret;
@@ -257,9 +271,13 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
stm->flash.spi = spi;
stm->flash.name = params->name;
- stm->flash.write = sst_write;
+ if (stm->params->flags & SST_FEAT_WP)
+ stm->flash.write = sst_write_wp;
+ else
+ stm->flash.write = spi_flash_cmd_write_multi;
stm->flash.erase = sst_erase;
stm->flash.read = spi_flash_cmd_read_fast;
+ stm->flash.page_size = SST_PAGE_SIZE;
stm->flash.sector_size = SST_SECTOR_SIZE;
stm->flash.size = stm->flash.sector_size * params->nr_sectors;
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
index a1959ca..a9b33cf 100644
--- a/drivers/mtd/spi/stmicro.c
+++ b/drivers/mtd/spi/stmicro.c
@@ -46,15 +46,6 @@
#define CMD_M25PXX_DP 0xb9 /* Deep Power-down */
#define CMD_M25PXX_RES 0xab /* Release from DP, and Read Signature */
-#define STM_ID_M25P10 0x11
-#define STM_ID_M25P16 0x15
-#define STM_ID_M25P20 0x12
-#define STM_ID_M25P32 0x16
-#define STM_ID_M25P40 0x13
-#define STM_ID_M25P64 0x17
-#define STM_ID_M25P80 0x14
-#define STM_ID_M25P128 0x18
-
struct stmicro_spi_flash_params {
u8 idcode1;
u16 page_size;
@@ -63,70 +54,58 @@ struct stmicro_spi_flash_params {
const char *name;
};
-/* spi_flash needs to be first so upper layers can free() it */
-struct stmicro_spi_flash {
- struct spi_flash flash;
- const struct stmicro_spi_flash_params *params;
-};
-
-static inline struct stmicro_spi_flash *to_stmicro_spi_flash(struct spi_flash
- *flash)
-{
- return container_of(flash, struct stmicro_spi_flash, flash);
-}
-
static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
{
- .idcode1 = STM_ID_M25P10,
+ .idcode1 = 0x11,
.page_size = 256,
.pages_per_sector = 128,
.nr_sectors = 4,
.name = "M25P10",
},
{
- .idcode1 = STM_ID_M25P16,
+ .idcode1 = 0x15,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 32,
.name = "M25P16",
},
{
- .idcode1 = STM_ID_M25P20,
+ .idcode1 = 0x12,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 4,
.name = "M25P20",
},
{
- .idcode1 = STM_ID_M25P32,
+ .idcode1 = 0x16,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 64,
.name = "M25P32",
},
{
- .idcode1 = STM_ID_M25P40,
+ .idcode1 = 0x13,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 8,
.name = "M25P40",
},
{
- .idcode1 = STM_ID_M25P64,
+ .idcode1 = 0x17,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 128,
.name = "M25P64",
},
{
- .idcode1 = STM_ID_M25P80,
+ .idcode1 = 0x14,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 16,
.name = "M25P80",
},
{
- .idcode1 = STM_ID_M25P128,
+ .idcode1 = 0x18,
.page_size = 256,
.pages_per_sector = 1024,
.nr_sectors = 64,
@@ -134,69 +113,6 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
},
};
-static int stmicro_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
-{
- struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
- unsigned long page_addr;
- unsigned long byte_addr;
- unsigned long page_size;
- size_t chunk_len;
- size_t actual;
- int ret;
- u8 cmd[4];
-
- page_size = stm->params->page_size;
- page_addr = offset / page_size;
- byte_addr = offset % page_size;
-
- 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 += chunk_len) {
- chunk_len = min(len - actual, page_size - byte_addr);
-
- cmd[0] = CMD_M25PXX_PP;
- cmd[1] = page_addr >> 8;
- cmd[2] = page_addr;
- cmd[3] = byte_addr;
-
- debug
- ("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n",
- buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
-
- 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,
- buf + actual, chunk_len);
- if (ret < 0) {
- debug("SF: STMicro Page Program failed\n");
- break;
- }
-
- ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
- if (ret)
- break;
-
- page_addr++;
- byte_addr = 0;
- }
-
- debug("SF: STMicro: Successfully programmed %u bytes @ 0x%x\n",
- len, offset);
-
- spi_release_bus(flash->spi);
- return ret;
-}
-
static int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_M25PXX_SE, offset, len);
@@ -205,7 +121,7 @@ static int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
{
const struct stmicro_spi_flash_params *params;
- struct stmicro_spi_flash *stm;
+ struct spi_flash *flash;
unsigned int i;
if (idcode[0] == 0xff) {
@@ -233,21 +149,21 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
return NULL;
}
- stm = malloc(sizeof(struct stmicro_spi_flash));
- if (!stm) {
+ flash = malloc(sizeof(*flash));
+ if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- stm->params = params;
- stm->flash.spi = spi;
- stm->flash.name = params->name;
+ flash->spi = spi;
+ flash->name = params->name;
- stm->flash.write = stmicro_write;
- stm->flash.erase = stmicro_erase;
- stm->flash.read = spi_flash_cmd_read_fast;
- stm->flash.sector_size = params->page_size * params->pages_per_sector;
- stm->flash.size = stm->flash.sector_size * params->nr_sectors;
+ flash->write = spi_flash_cmd_write_multi;
+ flash->erase = stmicro_erase;
+ flash->read = spi_flash_cmd_read_fast;
+ flash->page_size = params->page_size;
+ flash->sector_size = params->page_size * params->pages_per_sector;
+ flash->size = flash->sector_size * params->nr_sectors;
- return &stm->flash;
+ return flash;
}
diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c
index e8d30ae..45bd146 100644
--- a/drivers/mtd/spi/winbond.c
+++ b/drivers/mtd/spi/winbond.c
@@ -34,18 +34,6 @@ struct winbond_spi_flash_params {
const char *name;
};
-/* spi_flash needs to be first so upper layers can free() it */
-struct winbond_spi_flash {
- struct spi_flash flash;
- const struct winbond_spi_flash_params *params;
-};
-
-static inline struct winbond_spi_flash *
-to_winbond_spi_flash(struct spi_flash *flash)
-{
- return container_of(flash, struct winbond_spi_flash, flash);
-}
-
static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
{
.id = 0x3015,
@@ -105,71 +93,6 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
},
};
-static int winbond_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
-{
- struct winbond_spi_flash *stm = to_winbond_spi_flash(flash);
- unsigned long page_addr;
- unsigned long byte_addr;
- unsigned long page_size;
- unsigned int page_shift;
- size_t chunk_len;
- size_t actual;
- int ret;
- u8 cmd[4];
-
- page_shift = stm->params->l2_page_size;
- page_size = (1 << page_shift);
- page_addr = offset / page_size;
- byte_addr = offset % page_size;
-
- ret = spi_claim_bus(flash->spi);
- if (ret) {
- debug("SF: Unable to claim SPI bus\n");
- return ret;
- }
-
- for (actual = 0; actual < len; actual += chunk_len) {
- chunk_len = min(len - actual, page_size - byte_addr);
-
- cmd[0] = CMD_W25_PP;
- cmd[1] = page_addr >> (16 - page_shift);
- cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8);
- cmd[3] = byte_addr;
- debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n",
- buf + actual,
- cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
-
- 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,
- buf + actual, chunk_len);
- if (ret < 0) {
- debug("SF: Winbond Page Program failed\n");
- goto out;
- }
-
- ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
- if (ret)
- goto out;
-
- page_addr++;
- byte_addr = 0;
- }
-
- debug("SF: Winbond: Successfully programmed %u bytes @ 0x%x\n",
- len, offset);
- ret = 0;
-
-out:
- spi_release_bus(flash->spi);
- return ret;
-}
-
static int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_W25_SE, offset, len);
@@ -178,9 +101,9 @@ static int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)
struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
{
const struct winbond_spi_flash_params *params;
- unsigned page_size;
- struct winbond_spi_flash *stm;
+ struct spi_flash *flash;
unsigned int i;
+ unsigned page_size;
for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) {
params = &winbond_spi_flash_table[i];
@@ -194,27 +117,26 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- stm = malloc(sizeof(struct winbond_spi_flash));
- if (!stm) {
+ flash = malloc(sizeof(*flash));
+ if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- stm->params = params;
- stm->flash.spi = spi;
- stm->flash.name = params->name;
+ flash->spi = spi;
+ flash->name = params->name;
/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;
- stm->flash.write = winbond_write;
- stm->flash.erase = winbond_erase;
- stm->flash.read = spi_flash_cmd_read_fast;
- stm->flash.sector_size = (1 << stm->params->l2_page_size) *
- stm->params->pages_per_sector;
- stm->flash.size = page_size * params->pages_per_sector
+ flash->write = spi_flash_cmd_write_multi;
+ flash->erase = winbond_erase;
+ flash->read = spi_flash_cmd_read_fast;
+ flash->page_size = page_size;
+ flash->sector_size = page_size * params->pages_per_sector;
+ flash->size = page_size * params->pages_per_sector
* params->sectors_per_block
* params->nr_blocks;
- return &stm->flash;
+ return flash;
}