No subject
Fri Jan 23 11:48:37 CET 2009
argument for spi flash erase, which will round up the length to the
nearest [sector|page|block]_size.
This is done by adding a new member to
struct spi_flash::u32 block_size
The name 'block_size' is chosen to mean:
"the smallest unit erase commands will check against".
If "block_size" is considered a kludgy name, please propose another.
Most of the driver (excluding atmel) will now only calculate this
unit once during probe and will be able to use it directly.
For atmel, I added code to populate the block_size structure member
but felt too ignorant to actually modify the erase unit check.
Code compiles cleanly. fo all drivers, but I can only test
stmicro (M25P40 and M25P16).
---
common/cmd_sf.c | 63 +++++++++++++++++++++++++++++++++++++++++--
drivers/mtd/spi/atmel.c | 1 +
drivers/mtd/spi/macronix.c | 4 +-
drivers/mtd/spi/spansion.c | 3 +-
drivers/mtd/spi/sst.c | 3 +-
drivers/mtd/spi/stmicro.c | 3 +-
drivers/mtd/spi/winbond.c | 6 ++--
include/spi_flash.h | 3 +-
8 files changed, 74 insertions(+), 12 deletions(-)
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index 6e7be81..b1fed6e 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -19,6 +19,59 @@
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. <cmd> offset len - operate on <'offset', 'len')
+ * 2. <cmd> 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 sector_size;
+ ulong len_arg;
+
+
+ round_up_len = 0;
+ if (arg && *arg == '+'){
+ round_up_len = 1;
+ ++arg;
+ }
+
+ len_arg = simple_strtoul(arg, &ep, 16);
+ if (ep == arg || *ep != '\0')
+ return -1;
+
+ if (round_up_len) {
+ /* Get sector size from flash and round up */
+ sector_size = flash->block_size;
+ if (sector_size > 0) {
+ *len = ((((len_arg -1)/sector_size) + 1) * sector_size);
+ if (*len > flash->size) {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ *len = len_arg;
+ }
+
+ return 1;
+}
+
static int do_spi_flash_probe(int argc, char * const argv[])
{
unsigned int bus = 0;
@@ -135,9 +188,11 @@ 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);
if (ret) {
@@ -149,6 +204,7 @@ static int do_spi_flash_erase(int argc, char * const argv[])
usage:
puts("Usage: sf erase offset len\n");
+ puts(" sf erase offset +len\n");
return 1;
}
@@ -189,5 +245,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"
);
diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c
index 8d02169..ec1a7b7 100644
--- a/drivers/mtd/spi/atmel.c
+++ b/drivers/mtd/spi/atmel.c
@@ -539,6 +539,7 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
asf->flash.size = page_size * params->pages_per_block
* params->blocks_per_sector
* params->nr_sectors;
+ asf->flash.block_size = page_size;
printf("SF: Detected %s with page size %u, total ",
params->name, page_size);
diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c
index 76d5284..98e553b 100644
--- a/drivers/mtd/spi/macronix.c
+++ b/drivers/mtd/spi/macronix.c
@@ -247,8 +247,7 @@ int macronix_erase(struct spi_flash *flash, u32 offset, size_t len)
* when possible.
*/
- sector_size = mcx->params->page_size * mcx->params->pages_per_sector
- * mcx->params->sectors_per_block;
+ sector_size = mcx->flash.block_size;
if (offset % sector_size || len % sector_size) {
debug("SF: Erase offset/length not multiple of sector size\n");
@@ -329,6 +328,7 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
mcx->flash.read = macronix_read_fast;
mcx->flash.size = params->page_size * params->pages_per_sector
* params->sectors_per_block * params->nr_blocks;
+ mcx->flash.block_size = mcx->flash.size/params->nr_blocks;
printf("SF: Detected %s with page size %u, total ",
params->name, params->page_size);
diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c
index d6c1a5f..e5ba4f4 100644
--- a/drivers/mtd/spi/spansion.c
+++ b/drivers/mtd/spi/spansion.c
@@ -255,7 +255,7 @@ int spansion_erase(struct spi_flash *flash, u32 offset, size_t len)
* when possible.
*/
- sector_size = spsn->params->page_size * spsn->params->pages_per_sector;
+ sector_size = spsn->flash.block_size;
if (offset % sector_size || len % sector_size) {
debug("SF: Erase offset/length not multiple of sector size\n");
@@ -342,6 +342,7 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
spsn->flash.read = spansion_read_fast;
spsn->flash.size = params->page_size * params->pages_per_sector
* params->nr_sectors;
+ spsn->flash.block_size = spsn->flash.size/params->nr_sectors;
printf("SF: Detected %s with page size %u, total ",
params->name, params->page_size);
diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c
index 2557891..4ac6783 100644
--- a/drivers/mtd/spi/sst.c
+++ b/drivers/mtd/spi/sst.c
@@ -261,7 +261,7 @@ sst_erase(struct spi_flash *flash, u32 offset, size_t len)
* when possible.
*/
- sector_size = SST_SECTOR_SIZE;
+ sector_size = flash->block_size;
if (offset % sector_size) {
debug("SF: Erase offset not multiple of sector size\n");
@@ -363,6 +363,7 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
stm->flash.erase = sst_erase;
stm->flash.read = sst_read_fast;
stm->flash.size = SST_SECTOR_SIZE * params->nr_sectors;
+ stm->flash.block_size = SST_SECTOR_SIZE;
printf("SF: Detected %s with page size %u, total ",
params->name, SST_SECTOR_SIZE);
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
index 3134027..8b44fb9 100644
--- a/drivers/mtd/spi/stmicro.c
+++ b/drivers/mtd/spi/stmicro.c
@@ -269,7 +269,7 @@ int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
* when possible.
*/
- sector_size = stm->params->page_size * stm->params->pages_per_sector;
+ sector_size = stm->flash.block_size;
if (offset % sector_size || len % sector_size) {
debug("SF: Erase offset/length not multiple of sector size\n");
@@ -364,6 +364,7 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
stm->flash.read = stmicro_read_fast;
stm->flash.size = params->page_size * params->pages_per_sector
* params->nr_sectors;
+ stm->flash.block_size = stm->flash.size/params->nr_sectors;
printf("SF: Detected %s with page size %u, total ",
params->name, params->page_size);
diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c
index ff1df25..f760bc2 100644
--- a/drivers/mtd/spi/winbond.c
+++ b/drivers/mtd/spi/winbond.c
@@ -225,7 +225,6 @@ 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];
@@ -236,8 +235,7 @@ int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)
* when possible.
*/
- page_shift = stm->params->l2_page_size;
- sector_size = (1 << page_shift) * stm->params->pages_per_sector;
+ sector_size = stm->flash.block_size;
if (offset % sector_size || len % sector_size) {
debug("SF: Erase offset/length not multiple of sector size\n");
@@ -324,6 +322,8 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
stm->flash.size = page_size * params->pages_per_sector
* params->sectors_per_block
* params->nr_blocks;
+ stm->flash.block_size = (1 << stm->params->l2_page_size) *
+ stm->params->pages_per_sector;
printf("SF: Detected %s with page size %u, total ",
params->name, page_size);
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 1f8ba29..462bef6 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -38,6 +38,8 @@ struct spi_flash {
u32 size;
+ u32 block_size;
+
int (*read)(struct spi_flash *flash, u32 offset,
size_t len, void *buf);
int (*write)(struct spi_flash *flash, u32 offset,
@@ -67,5 +69,4 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,
{
return flash->erase(flash, offset, len);
}
-
#endif /* _SPI_FLASH_H_ */
--
1.7.2.3
More information about the U-Boot
mailing list