From 192b639ecce29caa954482dbcaa46ae4fc4df0e7 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 26 Dec 2010 22:31:18 -0500 Subject: [PATCH 01/10] sf: punt unused spi_flash_region struct Signed-off-by: Mike Frysinger --- include/spi_flash.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/spi_flash.h b/include/spi_flash.h index 1f8ba2987..89cc3a7cc 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -26,11 +26,6 @@ #include #include -struct spi_flash_region { - unsigned int count; - unsigned int size; -}; - struct spi_flash { struct spi_slave *spi; From cdb6a00fb8f96b9259ed7d77a1eacbfa3777ddac Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 11 Apr 2011 23:39:28 -0400 Subject: [PATCH 02/10] sf: atmel: undo unification of status polling The AT45 flashes are completely different (at the command set and status register level) from all other SPI flashes, so we can't unify their logic with common code. Signed-off-by: Mike Frysinger --- drivers/mtd/spi/atmel.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c index a9910b11b..10df3879e 100644 --- a/drivers/mtd/spi/atmel.c +++ b/drivers/mtd/spi/atmel.c @@ -113,8 +113,35 @@ static const struct atmel_spi_flash_params atmel_spi_flash_table[] = { static int at45_wait_ready(struct spi_flash *flash, unsigned long timeout) { - return spi_flash_cmd_poll_bit(flash, timeout, - CMD_AT45_READ_STATUS, AT45_STATUS_READY); + 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; } /* From 4e6a515899290635bfd7fe3aef8c4d4d9e88fced Mon Sep 17 00:00:00 2001 From: Richard Retanubun Date: Wed, 16 Feb 2011 16:37:22 -0500 Subject: [PATCH 03/10] sf: add struct spi_flash.sector_size parameter This patch adds a new member to struct spi_flash (u16 sector_size) and updates the spi flash drivers to start populating it. This parameter can be used by spi flash commands that need to round up units of operation to the flash's sector_size. Having this number in one place also allows duplicated code to be further collapsed into one common location (such as erase parameter and the detected message). Signed-off-by: Richard Retanubun Signed-off-by: Mike Frysinger --- drivers/mtd/spi/atmel.c | 5 +---- drivers/mtd/spi/eon.c | 11 +++-------- drivers/mtd/spi/macronix.c | 15 ++++----------- drivers/mtd/spi/ramtron.c | 3 --- drivers/mtd/spi/spansion.c | 13 +++---------- drivers/mtd/spi/spi_flash.c | 9 +++++++-- drivers/mtd/spi/spi_flash_internal.h | 2 +- drivers/mtd/spi/sst.c | 10 +++------- drivers/mtd/spi/stmicro.c | 13 +++---------- drivers/mtd/spi/winbond.c | 11 +++-------- include/spi_flash.h | 2 ++ 11 files changed, 30 insertions(+), 64 deletions(-) diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c index 10df3879e..d17ebf616 100644 --- a/drivers/mtd/spi/atmel.c +++ b/drivers/mtd/spi/atmel.c @@ -522,14 +522,11 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode) goto err; } + asf->flash.sector_size = page_size; asf->flash.size = page_size * params->pages_per_block * params->blocks_per_sector * params->nr_sectors; - printf("SF: Detected %s with page size %u, total ", - params->name, page_size); - print_size(asf->flash.size, "\n"); - return &asf->flash; err: diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c index 01caed5ab..a3640f416 100644 --- a/drivers/mtd/spi/eon.c +++ b/drivers/mtd/spi/eon.c @@ -121,11 +121,7 @@ static int eon_write(struct spi_flash *flash, int eon_erase(struct spi_flash *flash, u32 offset, size_t len) { - struct eon_spi_flash *eon = to_eon_spi_flash(flash); - 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); + return spi_flash_cmd_erase(flash, CMD_EN25Q128_BE, offset, len); } struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) @@ -158,11 +154,10 @@ 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 = spi_flash_cmd_read_fast; + eon->flash.sector_size = params->page_size * params->pages_per_sector + * params->sectors_per_block; eon->flash.size = params->page_size * params->pages_per_sector * params->nr_sectors; - debug("SF: Detected %s with page size %u, total %u bytes\n", - params->name, params->page_size, eon->flash.size); - return &eon->flash; } diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c index 4155d4d9a..a0512d1e3 100644 --- a/drivers/mtd/spi/macronix.c +++ b/drivers/mtd/spi/macronix.c @@ -177,11 +177,7 @@ 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); - 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); + return spi_flash_cmd_erase(flash, CMD_MX25XX_BE, offset, len); } struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) @@ -215,12 +211,9 @@ 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 = spi_flash_cmd_read_fast; - mcx->flash.size = params->page_size * params->pages_per_sector - * params->sectors_per_block * params->nr_blocks; - - printf("SF: Detected %s with page size %u, total ", - params->name, params->page_size); - print_size(mcx->flash.size, "\n"); + mcx->flash.sector_size = params->page_size * params->pages_per_sector + * params->sectors_per_block; + mcx->flash.size = mcx->flash.sector_size * params->nr_blocks; return &mcx->flash; } diff --git a/drivers/mtd/spi/ramtron.c b/drivers/mtd/spi/ramtron.c index 171390d5c..453dd3f44 100644 --- a/drivers/mtd/spi/ramtron.c +++ b/drivers/mtd/spi/ramtron.c @@ -312,8 +312,5 @@ found: sn->flash.erase = ramtron_erase; sn->flash.size = params->size; - printf("SF: Detected %s with size ", params->name); - print_size(sn->flash.size, "\n"); - return &sn->flash; } diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index d54a5fad2..f138d7344 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -198,10 +198,7 @@ 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); - return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, - spsn->params->page_size * spsn->params->pages_per_sector, - offset, len); + return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, offset, len); } struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) @@ -240,12 +237,8 @@ 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 = spi_flash_cmd_read_fast; - spsn->flash.size = params->page_size * params->pages_per_sector - * params->nr_sectors; - - printf("SF: Detected %s with page size %u, total ", - params->name, params->page_size); - print_size(spsn->flash.size, "\n"); + spsn->flash.sector_size = params->page_size * params->pages_per_sector; + spsn->flash.size = spsn->flash.sector_size * params->nr_sectors; return &spsn->flash; } diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 5c261f14a..ccb7e3140 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -131,12 +131,13 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) } int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, - u32 erase_size, u32 offset, size_t len) + u32 offset, size_t len) { - u32 start, end; + u32 start, end, erase_size; int ret; u8 cmd[4]; + erase_size = flash->sector_size; if (offset % erase_size || len % erase_size) { debug("SF: Erase offset/length not multiple of erase size\n"); return -1; @@ -296,6 +297,10 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_manufacturer_probe; } + printf("SF: Detected %s with page size %u, total ", + flash->name, flash->sector_size); + print_size(flash->size, "\n"); + spi_release_bus(spi); return flash; diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index d7bcd6d6a..fc109cef5 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -64,7 +64,7 @@ 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); + u32 offset, size_t len); /* Manufacturer-specific probe functions */ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode); diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c index 792d04dd2..29bb88b53 100644 --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -201,8 +201,7 @@ sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf) int sst_erase(struct spi_flash *flash, u32 offset, size_t len) { - return spi_flash_cmd_erase(flash, CMD_SST_SE, SST_SECTOR_SIZE, - offset, len); + return spi_flash_cmd_erase(flash, CMD_SST_SE, offset, len); } static int @@ -256,11 +255,8 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode) stm->flash.write = sst_write; stm->flash.erase = sst_erase; - stm->flash.size = SST_SECTOR_SIZE * params->nr_sectors; - - printf("SF: Detected %s with page size %u, total ", - params->name, SST_SECTOR_SIZE); - print_size(stm->flash.size, "\n"); + stm->flash.sector_size = SST_SECTOR_SIZE; + stm->flash.size = stm->flash.sector_size * params->nr_sectors; /* Flash powers up read-only, so clear BP# bits */ sst_unlock(&stm->flash); diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 7ef690d9b..a1980b1ed 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -199,10 +199,7 @@ 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); - return spi_flash_cmd_erase(flash, CMD_M25PXX_SE, - stm->params->page_size * stm->params->pages_per_sector, - offset, len); + return spi_flash_cmd_erase(flash, CMD_M25PXX_SE, offset, len); } struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) @@ -249,12 +246,8 @@ 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 = spi_flash_cmd_read_fast; - stm->flash.size = params->page_size * params->pages_per_sector - * params->nr_sectors; - - printf("SF: Detected %s with page size %u, total ", - params->name, params->page_size); - print_size(stm->flash.size, "\n"); + stm->flash.sector_size = params->page_size * params->pages_per_sector; + stm->flash.size = stm->flash.sector_size * params->nr_sectors; return &stm->flash; } diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index e88802f0e..72d94ad21 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -172,10 +172,7 @@ out: int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) { - struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); - return spi_flash_cmd_erase(flash, CMD_W25_SE, - (1 << stm->params->l2_page_size) * stm->params->pages_per_sector, - offset, len); + return spi_flash_cmd_erase(flash, CMD_W25_SE, offset, len); } struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) @@ -213,13 +210,11 @@ 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 = 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 * params->sectors_per_block * params->nr_blocks; - printf("SF: Detected %s with page size %u, total ", - params->name, page_size); - print_size(stm->flash.size, "\n"); - return &stm->flash; } diff --git a/include/spi_flash.h b/include/spi_flash.h index 89cc3a7cc..a384071fb 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -33,6 +33,8 @@ struct spi_flash { u32 size; + u32 sector_size; + int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); int (*write)(struct spi_flash *flash, u32 offset, From c5910874ba418e7dc35661b98a8931cb86358f95 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 12 Apr 2011 01:34:55 -0400 Subject: [PATCH 04/10] sf: sst: setup read func The previous unification patch missed setting up the sst read func. Signed-off-by: Mike Frysinger --- drivers/mtd/spi/sst.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c index 29bb88b53..38983bd20 100644 --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -255,6 +255,7 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode) stm->flash.write = sst_write; stm->flash.erase = sst_erase; + stm->flash.read = spi_flash_cmd_read_fast; stm->flash.sector_size = SST_SECTOR_SIZE; stm->flash.size = stm->flash.sector_size * params->nr_sectors; From f8f0757dcb117664a712650f000433e765acffbd Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 12 Apr 2011 01:51:29 -0400 Subject: [PATCH 05/10] sf: localize erase funcs No need for these to be exported as they are only accessed indirectly via function pointers. Signed-off-by: Mike Frysinger --- drivers/mtd/spi/atmel.c | 4 ++-- drivers/mtd/spi/eon.c | 2 +- drivers/mtd/spi/macronix.c | 2 +- drivers/mtd/spi/ramtron.c | 2 +- drivers/mtd/spi/spansion.c | 2 +- drivers/mtd/spi/sst.c | 2 +- drivers/mtd/spi/stmicro.c | 2 +- drivers/mtd/spi/winbond.c | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c index d17ebf616..1ecece0d7 100644 --- a/drivers/mtd/spi/atmel.c +++ b/drivers/mtd/spi/atmel.c @@ -328,7 +328,7 @@ out: /* * TODO: the two erase funcs (_p2/_at45) should get unified ... */ -int dataflash_erase_p2(struct spi_flash *flash, u32 offset, size_t len) +static int dataflash_erase_p2(struct spi_flash *flash, u32 offset, size_t len) { struct atmel_spi_flash *asf = to_atmel_spi_flash(flash); unsigned long page_size; @@ -387,7 +387,7 @@ out: return ret; } -int dataflash_erase_at45(struct spi_flash *flash, u32 offset, size_t len) +static int dataflash_erase_at45(struct spi_flash *flash, u32 offset, size_t len) { struct atmel_spi_flash *asf = to_atmel_spi_flash(flash); unsigned long page_addr; diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c index a3640f416..e3de3aabb 100644 --- a/drivers/mtd/spi/eon.c +++ b/drivers/mtd/spi/eon.c @@ -119,7 +119,7 @@ static int eon_write(struct spi_flash *flash, return ret; } -int eon_erase(struct spi_flash *flash, u32 offset, size_t len) +static int eon_erase(struct spi_flash *flash, u32 offset, size_t len) { return spi_flash_cmd_erase(flash, CMD_EN25Q128_BE, offset, len); } diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c index a0512d1e3..ff66f2aa3 100644 --- a/drivers/mtd/spi/macronix.c +++ b/drivers/mtd/spi/macronix.c @@ -175,7 +175,7 @@ static int macronix_write(struct spi_flash *flash, return ret; } -int macronix_erase(struct spi_flash *flash, u32 offset, size_t len) +static int macronix_erase(struct spi_flash *flash, u32 offset, size_t len) { return spi_flash_cmd_erase(flash, CMD_MX25XX_BE, offset, len); } diff --git a/drivers/mtd/spi/ramtron.c b/drivers/mtd/spi/ramtron.c index 453dd3f44..078d16ce1 100644 --- a/drivers/mtd/spi/ramtron.c +++ b/drivers/mtd/spi/ramtron.c @@ -233,7 +233,7 @@ static int ramtron_write(struct spi_flash *flash, CMD_RAMTRON_WRITE); } -int ramtron_erase(struct spi_flash *flash, u32 offset, size_t len) +static int ramtron_erase(struct spi_flash *flash, u32 offset, size_t len) { debug("SF: Erase of RAMTRON FRAMs is pointless\n"); return -1; diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index f138d7344..a3401b32e 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -196,7 +196,7 @@ static int spansion_write(struct spi_flash *flash, return ret; } -int spansion_erase(struct spi_flash *flash, u32 offset, size_t len) +static int spansion_erase(struct spi_flash *flash, u32 offset, size_t len) { return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, offset, len); } diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c index 38983bd20..0733debc6 100644 --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -199,7 +199,7 @@ 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) +static int sst_erase(struct spi_flash *flash, u32 offset, size_t len) { return spi_flash_cmd_erase(flash, CMD_SST_SE, offset, len); } diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index a1980b1ed..a1959ca98 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -197,7 +197,7 @@ static int stmicro_write(struct spi_flash *flash, return ret; } -int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len) +static int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len) { return spi_flash_cmd_erase(flash, CMD_M25PXX_SE, offset, len); } diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index 72d94ad21..e8d30ae2b 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -170,7 +170,7 @@ out: return ret; } -int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) +static int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) { return spi_flash_cmd_erase(flash, CMD_W25_SE, offset, len); } From 334eb4b02f90c7223ee92e49307089590c77992c Mon Sep 17 00:00:00 2001 From: Richard Retanubun Date: Wed, 16 Feb 2011 16:39:44 -0500 Subject: [PATCH 06/10] cmd_sf: add handler for +len arg for erase command This patch adds [+]len handler for the erase command that will automatically round up the requested erase length to the flash's sector_size. Signed-off-by: Richard Retanubun Signed-off-by: Mike Frysinger --- common/cmd_sf.c | 51 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 6e7be818e..afbef99f1 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -19,6 +19,47 @@ static struct spi_flash *flash; + +/* + * This function computes the length argument for the erase command. + * The length on which the command is to operate can be given in two forms: + * 1. offset len - operate on <'offset', 'len') + * 2. offset +len - operate on <'offset', 'round_up(len)') + * If the second form is used and the length doesn't fall on the + * sector boundary, than it will be adjusted to the next sector boundary. + * If it isn't in the flash, the function will fail (return -1). + * Input: + * arg: length specification (i.e. both command arguments) + * Output: + * len: computed length for operation + * Return: + * 1: success + * -1: failure (bad format, bad address). + */ +static int sf_parse_len_arg(char *arg, ulong *len) +{ + char *ep; + char round_up_len; /* indicates if the "+length" form used */ + ulong len_arg; + + round_up_len = 0; + if (*arg == '+') { + round_up_len = 1; + ++arg; + } + + len_arg = simple_strtoul(arg, &ep, 16); + if (ep == arg || *ep != '\0') + return -1; + + if (round_up_len && flash->sector_size > 0) + *len = ROUND(len_arg - 1, flash->sector_size); + else + *len = len_arg; + + return 1; +} + static int do_spi_flash_probe(int argc, char * const argv[]) { unsigned int bus = 0; @@ -135,8 +176,9 @@ static int do_spi_flash_erase(int argc, char * const argv[]) offset = simple_strtoul(argv[1], &endp, 16); if (*argv[1] == 0 || *endp != 0) goto usage; - len = simple_strtoul(argv[2], &endp, 16); - if (*argv[2] == 0 || *endp != 0) + + ret = sf_parse_len_arg(argv[2], &len); + if (ret != 1) goto usage; ret = spi_flash_erase(flash, offset, len); @@ -148,7 +190,7 @@ static int do_spi_flash_erase(int argc, char * const argv[]) return 0; usage: - puts("Usage: sf erase offset len\n"); + puts("Usage: sf erase offset [+]len\n"); return 1; } @@ -189,5 +231,6 @@ U_BOOT_CMD( " `offset' to memory at `addr'\n" "sf write addr offset len - write `len' bytes from memory\n" " at `addr' to flash at `offset'\n" - "sf erase offset len - erase `len' bytes from `offset'" + "sf erase offset [+]len - erase `len' bytes from `offset'\n" + " `+len' round up `len' to block size" ); From 493c36072160d72d5a8fe5943539da47c0a702a6 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 12 Apr 2011 02:09:28 -0400 Subject: [PATCH 07/10] sf: use print_size() for sector_size output Signed-off-by: Mike Frysinger --- drivers/mtd/spi/spi_flash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index ccb7e3140..c75b716fd 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -297,8 +297,8 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_manufacturer_probe; } - printf("SF: Detected %s with page size %u, total ", - flash->name, flash->sector_size); + printf("SF: Detected %s with page size ", flash->name); + print_size(flash->sector_size, ", total "); print_size(flash->size, "\n"); spi_release_bus(spi); From 840ff998895944fc51303cc43fdb258c4f89279c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 12 Apr 2011 02:10:19 -0400 Subject: [PATCH 08/10] cmd_sf: drop device status message when probing The common spi flash layer displays useful info when probing, so no need for us to duplicate that. Signed-off-by: Mike Frysinger --- common/cmd_sf.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/common/cmd_sf.c b/common/cmd_sf.c index afbef99f1..3abc4ffe4 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -106,9 +106,6 @@ static int do_spi_flash_probe(int argc, char * const argv[]) spi_flash_free(flash); flash = new; - printf("%u KiB %s at %u:%u is now current device\n", - flash->size >> 10, flash->name, bus, cs); - return 0; usage: From 8a07de03f07f386c29198f52b2192cf378bf2d7c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 12 Apr 2011 02:21:31 -0400 Subject: [PATCH 09/10] cmd_sf: use cmd_usage() in more places Requires a little reworking of the code flow with sub-functions, but not a big deal. Signed-off-by: Mike Frysinger --- common/cmd_sf.c | 59 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 3abc4ffe4..11a491df7 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -70,30 +70,30 @@ static int do_spi_flash_probe(int argc, char * const argv[]) struct spi_flash *new; if (argc < 2) - goto usage; + return -1; cs = simple_strtoul(argv[1], &endp, 0); if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) - goto usage; + return -1; if (*endp == ':') { if (endp[1] == 0) - goto usage; + return -1; bus = cs; cs = simple_strtoul(endp + 1, &endp, 0); if (*endp != 0) - goto usage; + return -1; } if (argc >= 3) { speed = simple_strtoul(argv[2], &endp, 0); if (*argv[2] == 0 || *endp != 0) - goto usage; + return -1; } if (argc >= 4) { mode = simple_strtoul(argv[3], &endp, 16); if (*argv[3] == 0 || *endp != 0) - goto usage; + return -1; } new = spi_flash_probe(bus, cs, speed, mode); @@ -107,10 +107,6 @@ static int do_spi_flash_probe(int argc, char * const argv[]) flash = new; return 0; - -usage: - puts("Usage: sf probe [bus:]cs [hz] [mode]\n"); - return 1; } static int do_spi_flash_read_write(int argc, char * const argv[]) @@ -123,17 +119,17 @@ static int do_spi_flash_read_write(int argc, char * const argv[]) int ret; if (argc < 4) - goto usage; + return -1; addr = simple_strtoul(argv[1], &endp, 16); if (*argv[1] == 0 || *endp != 0) - goto usage; + return -1; offset = simple_strtoul(argv[2], &endp, 16); if (*argv[2] == 0 || *endp != 0) - goto usage; + return -1; len = simple_strtoul(argv[3], &endp, 16); if (*argv[3] == 0 || *endp != 0) - goto usage; + return -1; buf = map_physmem(addr, len, MAP_WRBACK); if (!buf) { @@ -154,10 +150,6 @@ static int do_spi_flash_read_write(int argc, char * const argv[]) } return 0; - -usage: - printf("Usage: sf %s addr offset len\n", argv[0]); - return 1; } static int do_spi_flash_erase(int argc, char * const argv[]) @@ -168,15 +160,15 @@ static int do_spi_flash_erase(int argc, char * const argv[]) int ret; if (argc < 3) - goto usage; + return -1; offset = simple_strtoul(argv[1], &endp, 16); if (*argv[1] == 0 || *endp != 0) - goto usage; + return -1; ret = sf_parse_len_arg(argv[2], &len); if (ret != 1) - goto usage; + return -1; ret = spi_flash_erase(flash, offset, len); if (ret) { @@ -185,24 +177,25 @@ static int do_spi_flash_erase(int argc, char * const argv[]) } return 0; - -usage: - puts("Usage: sf erase offset [+]len\n"); - return 1; } static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { const char *cmd; + int ret; /* need at least two arguments */ if (argc < 2) goto usage; cmd = argv[1]; + --argc; + ++argv; - if (strcmp(cmd, "probe") == 0) - return do_spi_flash_probe(argc - 1, argv + 1); + if (strcmp(cmd, "probe") == 0) { + ret = do_spi_flash_probe(argc, argv); + goto done; + } /* The remaining commands require a selected device */ if (!flash) { @@ -211,9 +204,15 @@ static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ } if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0) - return do_spi_flash_read_write(argc - 1, argv + 1); - if (strcmp(cmd, "erase") == 0) - return do_spi_flash_erase(argc - 1, argv + 1); + ret = do_spi_flash_read_write(argc, argv); + else if (strcmp(cmd, "erase") == 0) + ret = do_spi_flash_erase(argc, argv); + else + ret = -1; + +done: + if (ret != -1) + return ret; usage: return cmd_usage(cmdtp); From 1c091f59a03af9f2e821cb054fd555a2748dd091 Mon Sep 17 00:00:00 2001 From: James Kosin Date: Wed, 13 Apr 2011 15:12:18 -0400 Subject: [PATCH 10/10] sf: sst: add support for SST25VF064C Signed-off-by: James Kosin Signed-off-by: Mike Frysinger --- drivers/mtd/spi/sst.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c index 0733debc6..4dc2db2ba 100644 --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -70,6 +70,10 @@ static const struct sst_spi_flash_params sst_spi_flash_table[] = { .idcode1 = 0x4a, .nr_sectors = 1024, .name = "SST25VF032B", + },{ + .idcode1 = 0x4b, + .nr_sectors = 2048, + .name = "SST25VF064C", },{ .idcode1 = 0x01, .nr_sectors = 16,