sf: unify erase functions

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
master
Mike Frysinger 14 years ago committed by Wolfgang Denk
parent 6163045bcd
commit e7b44eddbe
  1. 55
      drivers/mtd/spi/eon.c
  2. 60
      drivers/mtd/spi/macronix.c
  3. 57
      drivers/mtd/spi/spansion.c
  4. 58
      drivers/mtd/spi/spi_flash.c
  5. 5
      drivers/mtd/spi/spi_flash_internal.h
  6. 63
      drivers/mtd/spi/sst.c
  7. 59
      drivers/mtd/spi/stmicro.c
  8. 61
      drivers/mtd/spi/winbond.c

@ -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)

@ -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)

@ -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)

@ -14,6 +14,14 @@
#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
*

@ -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);

@ -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

@ -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)

@ -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)

Loading…
Cancel
Save