diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 7815bdc269..69345dbf07 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -347,6 +347,22 @@ static int do_spi_flash_erase(int argc, char * const argv[]) return ret == 0 ? 0 : 1; } +static int do_spi_flash_berase(int argc, char * const argv[]) +{ + switch (spi_flash_berase(flash)) { + case 0: + return 0; + case -ENOTSUPP: + printf("SPI flash %s not supported\n", argv[0]); + return 1; + default: + printf("SPI flash %s failed\n", argv[0]); + return 1; + } + + return 1; +} + static int do_spi_protect(int argc, char * const argv[]) { int ret = 0; @@ -576,6 +592,8 @@ static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, else if (!strcmp(cmd, "test")) ret = do_spi_flash_test(argc, argv); #endif + else if (strcmp(cmd, "bulkerase") == 0) + ret = do_spi_flash_berase(argc, argv); else ret = -1; @@ -613,5 +631,7 @@ U_BOOT_CMD( " or to start of mtd `partition'\n" "sf protect lock/unlock sector len - protect/unprotect 'len' bytes starting\n" " at address 'sector'\n" + "sf bulkerase - Erase entire flash chip\n" + " (Not supported on all devices)\n" SF_TEST_HELP ); diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index d58d84155c..ecc2b57394 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -12,6 +12,7 @@ #include #include +#include /* Dual SPI flash memories - see SPI_COMM_DUAL_... */ enum spi_dual_flash { @@ -115,6 +116,7 @@ enum spi_nor_option_flags { #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) +#define SPI_FLASH_BERASE_TIMEOUT(f) ((f)->berase_timeout * CONFIG_SYS_HZ) /* SST specific */ #ifdef CONFIG_SPI_FLASH_SST @@ -147,6 +149,7 @@ struct spi_flash_params { u32 nr_sectors; u8 e_rd_cmd; u16 flags; + u16 bulkerase_timeout; /* in seconds */ }; extern const struct spi_flash_params spi_flash_params_table[]; diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c index 3f141e221b..7739f4aa94 100644 --- a/drivers/mtd/spi/sf_params.c +++ b/drivers/mtd/spi/sf_params.c @@ -72,9 +72,9 @@ const struct spi_flash_params spi_flash_params_table[] = { {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, RD_FULL, WR_QPP}, {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, RD_FULL, WR_QPP}, {"S25FL128S_256K", 0x012018, 0x4d00, 256 * 1024, 64, RD_FULL, WR_QPP}, - {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, RD_FULL, WR_QPP}, + {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, RD_FULL, WR_QPP, 180}, {"S25FL256S_256K", 0x010219, 0x4d00, 256 * 1024, 128, RD_FULL, WR_QPP}, - {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, RD_FULL, WR_QPP}, + {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, RD_FULL, WR_QPP, 360}, {"S25FL512S_256K", 0x010220, 0x4d00, 256 * 1024, 256, RD_FULL, WR_QPP}, {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL, WR_QPP}, {"S25FL512S_512K", 0x010220, 0x4f00, 256 * 1024, 256, RD_FULL, WR_QPP}, diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 2b9217f787..73c44fe9a6 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -19,6 +19,10 @@ #include "sf_internal.h" +#if defined CONFIG_SPI_FLASH_SPANSION +#define CMD_S25FSXX_BE 0x60 +#endif + DECLARE_GLOBAL_DATA_PTR; static void spi_flash_addr(struct spi_flash *flash, u32 addr, u8 *cmd) @@ -266,6 +270,37 @@ static int spi_flash_cmd_wait_ready(struct spi_flash *flash, return -ETIMEDOUT; } +#if defined CONFIG_SPI_FLASH_SPANSION +int spi_flash_cmd_berase(struct spi_flash *flash, u8 erase_cmd) +{ + int ret; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + ret = spi_flash_cmd_write_enable(flash); + if (ret) + goto out; + + ret = spi_flash_cmd_write(flash->spi, &erase_cmd, 1, NULL, 0); + if (ret) + goto out; + + ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_BERASE_TIMEOUT(flash)); +out: + spi_release_bus(flash->spi); + return ret; +} + +static int bulk_erase(struct spi_flash *flash) +{ + return spi_flash_cmd_berase(flash, CMD_S25FSXX_BE); +} +#endif + int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, const void *buf, size_t buf_len) { @@ -1161,5 +1196,12 @@ print_sf_info: } #endif +#if defined CONFIG_SPI_FLASH_SPANSION + if (params->bulkerase_timeout) { + flash->berase = bulk_erase; + flash->berase_timeout = params->bulkerase_timeout; + } +#endif + return ret; } diff --git a/include/spi_flash.h b/include/spi_flash.h index 995d1232fb..1e05be230c 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -114,6 +114,9 @@ struct spi_flash { const void *buf); int (*erase)(struct spi_flash *flash, u32 offset, size_t len); #endif + + u16 berase_timeout; /* Bulk erase timeout */ + int (*berase)(struct spi_flash *flash); /* Bulk Erase */ }; struct dm_spi_flash_ops { @@ -249,6 +252,14 @@ static inline int spi_flash_protect(struct spi_flash *flash, u32 ofs, u32 len, return flash->flash_unlock(flash, ofs, len); } +static inline int spi_flash_berase(struct spi_flash *flash) +{ + if (!flash->berase) + return -ENOTSUPP; + + return flash->berase(flash); +} + void spi_boot(void) __noreturn; void spi_spl_load_image(uint32_t offs, unsigned int size, void *vdst);