[U-Boot] [PATCH] sf: Add support for flag status register on Micron chips

Add clear flag status register operation that some Micron SPI flash chips required after reading the flag status register to check some operations completion.
Signed-off-by: Hou Zhiqiang B48286@freescale.com --- Based on git://git.denx.de/u-boot.git. It also can be applied to git://www.denx.de/git/u-boot-mpc85xx.git. Tested on board T2080QDS and T2080RDB.
drivers/mtd/spi/sf_internal.h | 9 +++++++++ drivers/mtd/spi/sf_ops.c | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 6bcd522..162dd87 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -36,6 +36,7 @@ #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 @@ -59,6 +60,8 @@ #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) @@ -120,6 +123,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_flash *flash) +{ + return spi_flash_cmd(flash->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 85cf22d..08ff1df 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -160,6 +160,7 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, 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; u8 poll_bit = STATUS_WIP; @@ -186,22 +187,41 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, 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"); + 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(flash) < 0) { + debug("SF: clear flag status failed\n"); + ret = -1; + } + } +#endif + return ret; }
int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, @@ -234,7 +254,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;

On 29 August 2014 12:24, Hou Zhiqiang B48286@freescale.com wrote:
Add clear flag status register operation that some Micron SPI flash chips required after reading the flag status register to check some operations completion.
Signed-off-by: Hou Zhiqiang B48286@freescale.com
Based on git://git.denx.de/u-boot.git. It also can be applied to git://www.denx.de/git/u-boot-mpc85xx.git. Tested on board T2080QDS and T2080RDB.
Flag status register support is been added for stmicro flashes which are >= 512MB sizes.
#ifdef CONFIG_SPI_FLASH_STMICRO if (params->flags & E_FSR) flash->poll_cmd = CMD_FLAG_STATUS; #endif
Please check the condition on current tree bases, and let me know for any questions.
drivers/mtd/spi/sf_internal.h | 9 +++++++++ drivers/mtd/spi/sf_ops.c | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 6bcd522..162dd87 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -36,6 +36,7 @@ #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 @@ -59,6 +60,8 @@ #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) @@ -120,6 +123,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_flash *flash) +{
return spi_flash_cmd(flash->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 85cf22d..08ff1df 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -160,6 +160,7 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, 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; u8 poll_bit = STATUS_WIP;
@@ -186,22 +187,41 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, 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");
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(flash) < 0) {
debug("SF: clear flag status failed\n");
ret = -1;
}
}
+#endif
return ret;
}
int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, @@ -234,7 +254,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;
-- 1.8.5
thanks!
participants (2)
-
Hou Zhiqiang
-
Jagan Teki