
On 23 July 2015 at 15:24, Zhiqiang Hou B48286@freescale.com wrote:
From: Hou Zhiqiang B48286@freescale.com
Add clear flag status register operation that was required by Micron SPI flash chips after reading the flag status register to check if the erase and program operations complete or an error occur.
Flag status requires N25Q512 + parts, so clear flag status we need add only in this scenario is that true?
Signed-off-by: Hou Zhiqiang B48286@freescale.com Signed-off-by: Mingkai.Hu Mingkai.Hu@freescale.com
drivers/mtd/spi/sf_internal.h | 9 +++++++++ drivers/mtd/spi/sf_ops.c | 40 ++++++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 9fb5557..703d4a7 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -73,6 +73,7 @@ enum { #define CMD_WRITE_ENABLE 0x06 #define CMD_READ_CONFIG 0x35 #define CMD_FLAG_STATUS 0x70 +#define CMD_CLEAR_FLAG_STATUS 0x50
/* Read commands */ #define CMD_READ_ARRAY_SLOW 0x03 @@ -96,6 +97,8 @@ enum { #define STATUS_QEB_WINSPAN (1 << 1) #define STATUS_QEB_MXIC (1 << 6) #define STATUS_PEC (1 << 7) +#define STATUS_PROT (1 << 1) +#define STATUS_ERASE (1 << 5)
/* Flash timeout values */ #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) @@ -182,6 +185,12 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); }
+/* Clear flag status register */ +static inline int spi_flash_cmd_clear_flag_status(struct spi_slave *spi) +{
return spi_flash_cmd(spi, CMD_CLEAR_FLAG_STATUS, NULL, 0);
+}
/*
- Send the read status command to the device and wait for the wip
- (write-in-progress) bit to clear itself.
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 38592f5..cbb9f00 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -160,6 +160,7 @@ static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout, unsigned long timebase; unsigned long flags = SPI_XFER_BEGIN; int ret;
int out_of_time = 1; u8 status; u8 check_status = 0x0;
@@ -182,22 +183,45 @@ static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout, WATCHDOG_RESET();
ret = spi_xfer(spi, 8, NULL, &status, 0);
if (ret)
if (ret) {
spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); return -1;
}
if ((status & poll_bit) == check_status)
if ((status & poll_bit) == check_status) {
out_of_time = 0; break;
} } while (get_timer(timebase) < timeout); spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
if ((status & poll_bit) == check_status)
return 0;
if (out_of_time) {
/* Timed out */
debug("SF: time out!\n");
if (cmd == CMD_FLAG_STATUS) {
if (spi_flash_cmd_clear_flag_status(spi) < 0)
debug("SF: clear flag status failed\n");
}
ret = -1;
}
+#ifdef CONFIG_SPI_FLASH_STMICRO
else if (cmd == CMD_FLAG_STATUS) {
if (!(status & (STATUS_PROT | STATUS_ERASE))) {
ret = 0;
} else {
debug("SF: flag status error");
ret = -1;
}
/* Timed out */
debug("SF: time out!\n");
return -1;
if (spi_flash_cmd_clear_flag_status(spi) < 0) {
debug("SF: clear flag status failed\n");
ret = -1;
}
}
+#endif
return ret;
}
int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) @@ -252,7 +276,7 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
ret = spi_flash_cmd_wait_ready(flash, timeout); if (ret < 0) {
debug("SF: write %s timed out\n",
debug("SF: write %s failed\n", timeout == SPI_FLASH_PROG_TIMEOUT ? "program" : "page erase"); return ret;
-- 2.1.0.27.g96db324
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot