[U-Boot] [PATCH V5 1/2] sf: Add clear flag status register operation on Micron chips
Zhiqiang Hou
B48286 at freescale.com
Tue Aug 11 12:55:13 CEST 2015
From: Hou Zhiqiang <B48286 at freescale.com>
Add clear flag status register operation that was required by Micron SPI
flash chips, which support FSR. And if an error bit of FSR have been set,
it must be cleared by the clear FSR operation.
Signed-off-by: Hou Zhiqiang <B48286 at freescale.com>
Signed-off-by: Mingkai.Hu <Mingkai.Hu at freescale.com>
---
Tested on T1042RDB board.
V5:
1. Removed #ifdef for STMICRO.
2. Add checking Protection and Voltage error bits.
3. Only if there is any error bit set, issue the clear FSR command.
V4:
Split the the patch to 2 patches for clear FSR and SPI flash address mode.
V3:
Generate the patch based on the latest tree git://git.denx.de/u-boot.git.
V2:
Add the operation of enter 3 Byte address mode in probe.
V1:
Based on git://git.denx.de/u-boot.git.
drivers/mtd/spi/sf_internal.h | 13 +++++++++++++
drivers/mtd/spi/sf_ops.c | 29 +++++++++++++++++++++--------
2 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 9fb5557..1de1dac 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,12 @@ enum {
#define STATUS_QEB_WINSPAN (1 << 1)
#define STATUS_QEB_MXIC (1 << 6)
#define STATUS_PEC (1 << 7)
+#define STATUS_PROT_ERR (1 << 1)
+#define STATUS_VOLT_ERR (1 << 3)
+#define STATUS_PROG_ERR (1 << 4)
+#define STATUS_ERASE_ERR (1 << 5)
+#define FLAG_ERR_MASK (STATUS_PROT_ERR | STATUS_VOLT_ERR | \
+ STATUS_PROG_ERR | STATUS_ERASE_ERR)
/* Flash timeout values */
#define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ)
@@ -182,6 +189,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..deebcab 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,34 @@ 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");
+ ret = -1;
+ }
+
+ if (cmd == CMD_FLAG_STATUS && status & FLAG_ERR_MASK) {
+ debug("SF: flag status(0x%x) error occured!\n", status);
+ if (spi_flash_cmd_clear_flag_status(spi) < 0)
+ debug("SF: clear flag status failed!\n");
+ ret = -1;
+ }
- /* Timed out */
- debug("SF: time out!\n");
- return -1;
+ return ret;
}
int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
@@ -252,7 +265,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
More information about the U-Boot
mailing list