[U-Boot] [PATCH v4 14/14] sf: Add Flag status register polling support

Flag status register polling is required for micron 512Mb flash devices onwards, for performing erase/program operations.
Like polling for WIP(Write-In-Progress) bit in read status register, spi_flash_cmd_wait_ready will poll for PEC(Program-Erase-Control) bit in flag status register.
Signed-off-by: Jagannadha Sutradharudu Teki jaganna@xilinx.com Reviewed-by: Simon Glass sjg@chromium.org --- Changes for v4: - Remove STMICRO config, discover poll_cmd at probe Changes for v3: - none Changes for v2: - none
drivers/mtd/spi/spi_flash.c | 21 +++++++++++++++++---- drivers/mtd/spi/spi_flash_internal.h | 2 ++ include/spi_flash.h | 3 +++ 3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index e5b401f..c439601 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -200,12 +200,19 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) unsigned long timebase; int ret; u8 status; + u8 check_status = 0x0; u8 poll_bit = STATUS_WIP; - u8 cmd = CMD_READ_STATUS; + u8 cmd = flash->poll_cmd; + + if (cmd == CMD_FLAG_STATUS) { + poll_bit = STATUS_PEC; + check_status = poll_bit; + }
ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); if (ret) { - debug("SF: Failed to send command %02x: %d\n", cmd, ret); + debug("SF: fail to read %s status register\n", + cmd == CMD_READ_STATUS ? "read" : "flag"); return ret; }
@@ -217,14 +224,14 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) if (ret) return -1;
- if ((status & poll_bit) == 0) + if ((status & poll_bit) == check_status) break;
} while (get_timer(timebase) < timeout);
spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
- if ((status & poll_bit) == 0) + if ((status & poll_bit) == check_status) return 0;
/* Timed out */ @@ -542,6 +549,12 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_manufacturer_probe; #endif
+ /* Discover the poll_cmd, as STMICRO is something different */ + flash->poll_cmd = CMD_READ_STATUS; + if ((*idp == SPI_FLASH_STMICRO_IDCODE0) && + (flash->size >= 0x4000000)) + flash->poll_cmd = CMD_FLAG_STATUS; + #ifdef CONFIG_OF_CONTROL if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { debug("SF: FDT decode error\n"); diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index e9b85bf..8147f27 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -22,6 +22,7 @@ #define CMD_PAGE_PROGRAM 0x02 #define CMD_WRITE_DISABLE 0x04 #define CMD_READ_STATUS 0x05 +#define CMD_FLAG_STATUS 0x70 #define CMD_WRITE_ENABLE 0x06 #define CMD_ERASE_4K 0x20 #define CMD_ERASE_32K 0x52 @@ -45,6 +46,7 @@
/* Common status */ #define STATUS_WIP 0x01 +#define STATUS_PEC 0x80
/* Send a single-byte command to the device and read the response */ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); diff --git a/include/spi_flash.h b/include/spi_flash.h index 1de193a..e94e59c 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -44,6 +44,9 @@ struct spi_flash { /* Current flash bank */ u8 bank_curr; #endif + /* Poll cmd - for flash erase/program */ + u8 poll_cmd; + void *memory_map; /* Address of read-only SPI flash access */ int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);

Hi Jagan,
On Thu, Jun 13, 2013 at 1:55 PM, Jagannadha Sutradharudu Teki < jagannadha.sutradharudu-teki@xilinx.com> wrote:
Flag status register polling is required for micron 512Mb flash devices onwards, for performing erase/program operations.
Like polling for WIP(Write-In-Progress) bit in read status register, spi_flash_cmd_wait_ready will poll for PEC(Program-Erase-Control) bit in flag status register.
Signed-off-by: Jagannadha Sutradharudu Teki jaganna@xilinx.com Reviewed-by: Simon Glass sjg@chromium.org
Changes for v4: - Remove STMICRO config, discover poll_cmd at probe Changes for v3: - none Changes for v2: - none
drivers/mtd/spi/spi_flash.c | 21 +++++++++++++++++---- drivers/mtd/spi/spi_flash_internal.h | 2 ++ include/spi_flash.h | 3 +++ 3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index e5b401f..c439601 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -200,12 +200,19 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) unsigned long timebase; int ret; u8 status;
u8 check_status = 0x0; u8 poll_bit = STATUS_WIP;
u8 cmd = CMD_READ_STATUS;
u8 cmd = flash->poll_cmd;
if (cmd == CMD_FLAG_STATUS) {
poll_bit = STATUS_PEC;
check_status = poll_bit;
} ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); if (ret) {
debug("SF: Failed to send command %02x: %d\n", cmd, ret);
debug("SF: fail to read %s status register\n",
cmd == CMD_READ_STATUS ? "read" : "flag"); return ret; }
@@ -217,14 +224,14 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) if (ret) return -1;
if ((status & poll_bit) == 0)
if ((status & poll_bit) == check_status) break; } while (get_timer(timebase) < timeout); spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
if ((status & poll_bit) == 0)
if ((status & poll_bit) == check_status) return 0; /* Timed out */
@@ -542,6 +549,12 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_manufacturer_probe; #endif
/* Discover the poll_cmd, as STMICRO is something different */
flash->poll_cmd = CMD_READ_STATUS;
Move this line into spi_flash_do_alloc()
+ if ((*idp == SPI_FLASH_STMICRO_IDCODE0) &&
(flash->size >= 0x4000000))
flash->poll_cmd = CMD_FLAG_STATUS;
...and the above into the stmicro.c's probe handler
#ifdef CONFIG_OF_CONTROL if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { debug("SF: FDT decode error\n"); diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index e9b85bf..8147f27 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -22,6 +22,7 @@ #define CMD_PAGE_PROGRAM 0x02 #define CMD_WRITE_DISABLE 0x04 #define CMD_READ_STATUS 0x05 +#define CMD_FLAG_STATUS 0x70 #define CMD_WRITE_ENABLE 0x06 #define CMD_ERASE_4K 0x20 #define CMD_ERASE_32K 0x52 @@ -45,6 +46,7 @@
/* Common status */ #define STATUS_WIP 0x01 +#define STATUS_PEC 0x80
/* Send a single-byte command to the device and read the response */ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); diff --git a/include/spi_flash.h b/include/spi_flash.h index 1de193a..e94e59c 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -44,6 +44,9 @@ struct spi_flash { /* Current flash bank */ u8 bank_curr; #endif
/* Poll cmd - for flash erase/program */
u8 poll_cmd;
void *memory_map; /* Address of read-only SPI flash access */ int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);
-- 1.8.3
Regards,
Simon

On Wed, Jun 19, 2013 at 10:00 AM, Simon Glass sjg@chromium.org wrote:
Hi Jagan,
On Thu, Jun 13, 2013 at 1:55 PM, Jagannadha Sutradharudu Teki < jagannadha.sutradharudu-teki@xilinx.com> wrote:
Flag status register polling is required for micron 512Mb flash devices onwards, for performing erase/program operations.
Like polling for WIP(Write-In-Progress) bit in read status register, spi_flash_cmd_wait_ready will poll for PEC(Program-Erase-Control) bit in flag status register.
Signed-off-by: Jagannadha Sutradharudu Teki jaganna@xilinx.com Reviewed-by: Simon Glass sjg@chromium.org
Changes for v4: - Remove STMICRO config, discover poll_cmd at probe Changes for v3: - none Changes for v2: - none
drivers/mtd/spi/spi_flash.c | 21 +++++++++++++++++---- drivers/mtd/spi/spi_flash_internal.h | 2 ++ include/spi_flash.h | 3 +++ 3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index e5b401f..c439601 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -200,12 +200,19 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) unsigned long timebase; int ret; u8 status;
u8 check_status = 0x0; u8 poll_bit = STATUS_WIP;
u8 cmd = CMD_READ_STATUS;
u8 cmd = flash->poll_cmd;
if (cmd == CMD_FLAG_STATUS) {
poll_bit = STATUS_PEC;
check_status = poll_bit;
} ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); if (ret) {
debug("SF: Failed to send command %02x: %d\n", cmd, ret);
debug("SF: fail to read %s status register\n",
cmd == CMD_READ_STATUS ? "read" : "flag"); return ret; }
@@ -217,14 +224,14 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) if (ret) return -1;
if ((status & poll_bit) == 0)
if ((status & poll_bit) == check_status) break; } while (get_timer(timebase) < timeout); spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
if ((status & poll_bit) == 0)
if ((status & poll_bit) == check_status) return 0; /* Timed out */
@@ -542,6 +549,12 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_manufacturer_probe; #endif
/* Discover the poll_cmd, as STMICRO is something different */
flash->poll_cmd = CMD_READ_STATUS;
Move this line into spi_flash_do_alloc()
if ((*idp == SPI_FLASH_STMICRO_IDCODE0) &&
(flash->size >= 0x4000000))
flash->poll_cmd = CMD_FLAG_STATUS;
...and the above into the stmicro.c's probe handler
Sound reasonable- Will do it.
-- Thanks, Jagan.
#ifdef CONFIG_OF_CONTROL if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { debug("SF: FDT decode error\n"); diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index e9b85bf..8147f27 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -22,6 +22,7 @@ #define CMD_PAGE_PROGRAM 0x02 #define CMD_WRITE_DISABLE 0x04 #define CMD_READ_STATUS 0x05 +#define CMD_FLAG_STATUS 0x70 #define CMD_WRITE_ENABLE 0x06 #define CMD_ERASE_4K 0x20 #define CMD_ERASE_32K 0x52 @@ -45,6 +46,7 @@
/* Common status */ #define STATUS_WIP 0x01 +#define STATUS_PEC 0x80
/* Send a single-byte command to the device and read the response */ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); diff --git a/include/spi_flash.h b/include/spi_flash.h index 1de193a..e94e59c 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -44,6 +44,9 @@ struct spi_flash { /* Current flash bank */ u8 bank_curr; #endif
/* Poll cmd - for flash erase/program */
u8 poll_cmd;
void *memory_map; /* Address of read-only SPI flash access */ int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);
-- 1.8.3
Regards,
Simon
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
participants (3)
-
Jagan Teki
-
Jagannadha Sutradharudu Teki
-
Simon Glass