From e7b44eddbef88b1a922f8d82088ba236aad01caf Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 10 Jan 2011 02:20:13 -0500 Subject: [PATCH] sf: unify erase functions Signed-off-by: Mike Frysinger --- drivers/mtd/spi/eon.c | 55 ++---------------------- drivers/mtd/spi/macronix.c | 60 ++------------------------ drivers/mtd/spi/spansion.c | 57 ++----------------------- drivers/mtd/spi/spi_flash.c | 58 +++++++++++++++++++++++++ drivers/mtd/spi/spi_flash_internal.h | 5 +++ drivers/mtd/spi/sst.c | 63 ++-------------------------- drivers/mtd/spi/stmicro.c | 59 ++------------------------ drivers/mtd/spi/winbond.c | 61 ++------------------------- 8 files changed, 83 insertions(+), 335 deletions(-) diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c index 4af1e068c3..0c0b05f010 100644 --- a/drivers/mtd/spi/eon.c +++ b/drivers/mtd/spi/eon.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) diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c index 291fd17de9..573e1dba7e 100644 --- a/drivers/mtd/spi/macronix.c +++ b/drivers/mtd/spi/macronix.c @@ -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) diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index d0f03ffafa..be4fc67ef7 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -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) diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index e483ce4af3..ca4bbb206a 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -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 * diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 440c044f76..114b63459a 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -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); diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c index 4a82f8a3a1..d55055035c 100644 --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -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 diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 02da8b2fdc..494005c4a4 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -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) diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index d8c1cb12d9..8470a826bf 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -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) -- 2.30.2