sf: unify erase functions
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
parent
6163045bcd
commit
e7b44eddbe
|
@ -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…
Reference in New Issue