[U-Boot] [PATCH v2 1/4] sf: Fix quad bit set for micron devices

Setting up quad bit for micron devices need to do the same way as other flash devices like spansion, winbond etc does using enhanced volatile config register so this patch adds this support instead of printing "QEB is volatile"
Cc: Simon Glass sjg@chromium.org Cc: Bin Meng bmeng.cn@gmail.com Cc: Peter Pan peterpandong@micron.com Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Jagan Teki jteki@openedev.com --- Changes for v2: - none
drivers/mtd/spi/sf_internal.h | 3 +++ drivers/mtd/spi/spi_flash.c | 62 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 561abc3..55ba81e 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -77,6 +77,7 @@ enum spi_nor_option_flags { #define CMD_WRITE_DISABLE 0x04 #define CMD_WRITE_ENABLE 0x06 #define CMD_QUAD_PAGE_PROGRAM 0x32 +#define CMD_WRITE_EVCR 0x61
/* Read commands */ #define CMD_READ_ARRAY_SLOW 0x03 @@ -90,6 +91,7 @@ enum spi_nor_option_flags { #define CMD_READ_STATUS1 0x35 #define CMD_READ_CONFIG 0x35 #define CMD_FLAG_STATUS 0x70 +#define CMD_READ_EVCR 0x65
/* Bank addr access commands */ #ifdef CONFIG_SPI_FLASH_BAR @@ -104,6 +106,7 @@ enum spi_nor_option_flags { #define STATUS_QEB_WINSPAN BIT(1) #define STATUS_QEB_MXIC BIT(6) #define STATUS_PEC BIT(7) +#define STATUS_QEB_MICRON BIT(7) #define SR_BP0 BIT(2) /* Block protect 0 */ #define SR_BP1 BIT(3) /* Block protect 1 */ #define SR_BP2 BIT(4) /* Block protect 2 */ diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 6fe8c9d..8e8b89f 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -111,6 +111,37 @@ static int write_cr(struct spi_flash *flash, u8 wc) } #endif
+#ifdef CONFIG_SPI_FLASH_STMICRO +static int read_evcr(struct spi_flash *flash, u8 *evcr) +{ + int ret; + const u8 cmd = CMD_READ_EVCR; + + ret = spi_flash_read_common(flash, &cmd, 1, evcr, 1); + if (ret < 0) { + debug("SF: error reading EVCR\n"); + return ret; + } + + return 0; +} + +static int write_evcr(struct spi_flash *flash, u8 evcr) +{ + u8 cmd; + int ret; + + cmd = CMD_WRITE_EVCR; + ret = spi_flash_write_common(flash, &cmd, 1, &evcr, 1); + if (ret < 0) { + debug("SF: error while writing EVCR register\n"); + return ret; + } + + return 0; +} +#endif + #ifdef CONFIG_SPI_FLASH_BAR static int spi_flash_write_bar(struct spi_flash *flash, u32 offset) { @@ -843,6 +874,34 @@ static int spansion_quad_enable(struct spi_flash *flash) } #endif
+#ifdef CONFIG_SPI_FLASH_STMICRO +static int micron_quad_enable(struct spi_flash *flash) +{ + u8 qeb_status; + int ret; + + ret = read_evcr(flash, &qeb_status); + if (ret < 0) + return ret; + + if (!(qeb_status & STATUS_QEB_MICRON)) + return 0; + + ret = write_evcr(flash, qeb_status & ~STATUS_QEB_MICRON); + if (ret < 0) + return ret; + + /* read EVCR and check it */ + ret = read_evcr(flash, &qeb_status); + if (!(ret > 0 && !(qeb_status & STATUS_QEB_MICRON))) { + printf("SF: Micron EVCR Quad bit not clear\n"); + return -EINVAL; + } + + return ret; +} +#endif + static int set_quad_mode(struct spi_flash *flash, u8 idcode0) { switch (idcode0) { @@ -857,8 +916,7 @@ static int set_quad_mode(struct spi_flash *flash, u8 idcode0) #endif #ifdef CONFIG_SPI_FLASH_STMICRO case SPI_FLASH_CFI_MFR_STMICRO: - debug("SF: QEB is volatile for %02x flash\n", idcode0); - return 0; + return micron_quad_enable(flash); #endif default: printf("SF: Need set QEB func for %02x flash\n", idcode0);

One spansion quad bit set using CR, it's good to read back and check the written bit and also if it's already been set check for the bit and return.
Cc: Vignesh R vigneshr@ti.com Cc: Mugunthan V N mugunthanvnm@ti.com Cc: Simon Glass sjg@chromium.org Cc: Bin Meng bmeng.cn@gmail.com Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Jagan Teki jteki@openedev.com --- Changes for v2: - none
drivers/mtd/spi/spi_flash.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 8e8b89f..ba6651e 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -862,12 +862,18 @@ static int spansion_quad_enable(struct spi_flash *flash) if (ret < 0) return ret;
- if (qeb_status & STATUS_QEB_WINSPAN) { - debug("SF: winspan: QEB is already set\n"); - } else { - ret = write_cr(flash, STATUS_QEB_WINSPAN); - if (ret < 0) - return ret; + if (qeb_status & STATUS_QEB_WINSPAN) + return 0; + + ret = write_cr(flash, STATUS_QEB_WINSPAN); + if (ret < 0) + return ret; + + /* read CR and check it */ + ret = read_cr(flash, &qeb_status); + if (!(ret > 0 && (qeb_status & STATUS_QEB_WINSPAN))) { + printf("SF: Spansion CR Quad bit not clear\n"); + return -EINVAL; }
return ret;

One macronix quad bit set using SR, it's good to read back and check the written bit and also if it's already been set check for the bit and return.
Cc: Vignesh R vigneshr@ti.com Cc: Mugunthan V N mugunthanvnm@ti.com Cc: Simon Glass sjg@chromium.org Cc: Bin Meng bmeng.cn@gmail.com Signed-off-by: Jagan Teki jteki@openedev.com --- Changes for v2: - none
drivers/mtd/spi/spi_flash.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index ba6651e..c922322 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -840,12 +840,18 @@ static int macronix_quad_enable(struct spi_flash *flash) if (ret < 0) return ret;
- if (qeb_status & STATUS_QEB_MXIC) { - debug("SF: mxic: QEB is already set\n"); - } else { - ret = write_sr(flash, STATUS_QEB_MXIC); - if (ret < 0) - return ret; + if (qeb_status & STATUS_QEB_MXIC) + return 0; + + ret = write_sr(flash, STATUS_QEB_MXIC); + if (ret < 0) + return ret; + + /* read SR and check it */ + ret = read_sr(flash, &qeb_status); + if (!(ret > 0 && (qeb_status & STATUS_QEB_MXIC))) { + printf("SF: Macronix SR Quad bit not clear\n"); + return -EINVAL; }
return ret;

On Wednesday 16 December 2015 02:31 PM, Jagan Teki wrote:
One macronix quad bit set using SR, it's good to read back and check the written bit and also if it's already been set check for the bit and return.
Cc: Vignesh R vigneshr@ti.com Cc: Mugunthan V N mugunthanvnm@ti.com Cc: Simon Glass sjg@chromium.org Cc: Bin Meng bmeng.cn@gmail.com Signed-off-by: Jagan Teki jteki@openedev.com
Changes for v2:
- none
drivers/mtd/spi/spi_flash.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index ba6651e..c922322 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -840,12 +840,18 @@ static int macronix_quad_enable(struct spi_flash *flash) if (ret < 0) return ret;
- if (qeb_status & STATUS_QEB_MXIC) {
debug("SF: mxic: QEB is already set\n");
- } else {
ret = write_sr(flash, STATUS_QEB_MXIC);
if (ret < 0)
return ret;
- if (qeb_status & STATUS_QEB_MXIC)
return 0;
- ret = write_sr(flash, STATUS_QEB_MXIC);
- if (ret < 0)
return ret;
- /* read SR and check it */
- ret = read_sr(flash, &qeb_status);
- if (!(ret > 0 && (qeb_status & STATUS_QEB_MXIC))) {
This error check is wrong, it can be either one of the below
if (!(ret >= 0 && (qeb_status & STATUS_QEB_MXIC))) { or if (ret < 0 || !(qeb_status & STATUS_QEB_MXIC)) {
Regards Mugunthan V N
printf("SF: Macronix SR Quad bit not clear\n");
return -EINVAL;
}
return ret;

On 23 December 2015 at 13:22, Mugunthan V N mugunthanvnm@ti.com wrote:
On Wednesday 16 December 2015 02:31 PM, Jagan Teki wrote:
One macronix quad bit set using SR, it's good to read back and check the written bit and also if it's already been set check for the bit and return.
Cc: Vignesh R vigneshr@ti.com Cc: Mugunthan V N mugunthanvnm@ti.com Cc: Simon Glass sjg@chromium.org Cc: Bin Meng bmeng.cn@gmail.com Signed-off-by: Jagan Teki jteki@openedev.com
Changes for v2: - none
drivers/mtd/spi/spi_flash.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index ba6651e..c922322 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -840,12 +840,18 @@ static int macronix_quad_enable(struct spi_flash *flash) if (ret < 0) return ret;
if (qeb_status & STATUS_QEB_MXIC) {
debug("SF: mxic: QEB is already set\n");
} else {
ret = write_sr(flash, STATUS_QEB_MXIC);
if (ret < 0)
return ret;
if (qeb_status & STATUS_QEB_MXIC)
return 0;
ret = write_sr(flash, STATUS_QEB_MXIC);
if (ret < 0)
return ret;
/* read SR and check it */
ret = read_sr(flash, &qeb_status);
if (!(ret > 0 && (qeb_status & STATUS_QEB_MXIC))) {
This error check is wrong, it can be either one of the below
if (!(ret >= 0 && (qeb_status & STATUS_QEB_MXIC))) {
So =0 is a success case, this is what you pointing to correct? did you test this?
or if (ret < 0 || !(qeb_status & STATUS_QEB_MXIC)) {
Regards Mugunthan V N
printf("SF: Macronix SR Quad bit not clear\n");
return -EINVAL; } return ret;
thanks!

On Wednesday 23 December 2015 01:51 PM, Jagan Teki wrote:
On 23 December 2015 at 13:22, Mugunthan V N mugunthanvnm@ti.com wrote:
On Wednesday 16 December 2015 02:31 PM, Jagan Teki wrote:
One macronix quad bit set using SR, it's good to read back and check the written bit and also if it's already been set check for the bit and return.
Cc: Vignesh R vigneshr@ti.com Cc: Mugunthan V N mugunthanvnm@ti.com Cc: Simon Glass sjg@chromium.org Cc: Bin Meng bmeng.cn@gmail.com Signed-off-by: Jagan Teki jteki@openedev.com
Changes for v2: - none
drivers/mtd/spi/spi_flash.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index ba6651e..c922322 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -840,12 +840,18 @@ static int macronix_quad_enable(struct spi_flash *flash) if (ret < 0) return ret;
if (qeb_status & STATUS_QEB_MXIC) {
debug("SF: mxic: QEB is already set\n");
} else {
ret = write_sr(flash, STATUS_QEB_MXIC);
if (ret < 0)
return ret;
if (qeb_status & STATUS_QEB_MXIC)
return 0;
ret = write_sr(flash, STATUS_QEB_MXIC);
if (ret < 0)
return ret;
/* read SR and check it */
ret = read_sr(flash, &qeb_status);
if (!(ret > 0 && (qeb_status & STATUS_QEB_MXIC))) {
This error check is wrong, it can be either one of the below
if (!(ret >= 0 && (qeb_status & STATUS_QEB_MXIC))) {
So =0 is a success case, this is what you pointing to correct? did you test this?
Yeah, I have tested this on am437x-sk evm.
The same fix has to be done for spansion flash as well!
Regards Mugunthan V N

While setting quad bit on spansion, macronix code is writing only particular quad bit this may give wrong functionality with other register bits, So this patch fix the issue where it with write previous read reg status along particular quad bit.
Cc: Vignesh R vigneshr@ti.com Cc: Mugunthan V N mugunthanvnm@ti.com Cc: Simon Glass sjg@chromium.org Cc: Bin Meng bmeng.cn@gmail.com Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Jagan Teki jteki@openedev.com --- Changes for v2: - newly added
drivers/mtd/spi/spi_flash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index c922322..1ba6222 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -843,7 +843,7 @@ static int macronix_quad_enable(struct spi_flash *flash) if (qeb_status & STATUS_QEB_MXIC) return 0;
- ret = write_sr(flash, STATUS_QEB_MXIC); + ret = write_sr(flash, qeb_status | STATUS_QEB_MXIC); if (ret < 0) return ret;
@@ -871,7 +871,7 @@ static int spansion_quad_enable(struct spi_flash *flash) if (qeb_status & STATUS_QEB_WINSPAN) return 0;
- ret = write_cr(flash, STATUS_QEB_WINSPAN); + ret = write_cr(flash, qeb_status | STATUS_QEB_WINSPAN); if (ret < 0) return ret;
participants (2)
-
Jagan Teki
-
Mugunthan V N