SF: Bulk Erase command support for spansion
Change-Id: Ida70d167cafc6af823f31c660d108cc25be6edff
Signed-off-by: Antony Arun T <antothom@codeaurora.org>
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index 7815bdc..69345db 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -347,6 +347,22 @@
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 @@
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 @@
" 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 d58d841..ecc2b57 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <linux/compiler.h>
+#include <linux/compat.h>
/* Dual SPI flash memories - see SPI_COMM_DUAL_... */
enum spi_dual_flash {
@@ -115,6 +116,7 @@
#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 @@
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 3f141e2..7739f4a 100644
--- a/drivers/mtd/spi/sf_params.c
+++ b/drivers/mtd/spi/sf_params.c
@@ -72,9 +72,9 @@
{"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 2b9217f..73c44fe 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 @@
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 @@
}
#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 995d123..1e05be2 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -114,6 +114,9 @@
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 @@
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);