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

Hou Zhiqiang B48286 at freescale.com
Thu Jul 23 11:42:21 CEST 2015


Hi Jagan,

Tested the latest source code, after running the 'reboot' command, the sf 
commands executed incorrectly due to the reboot process is a warm boot, 
during the process system will keep the power supply, so the SPI flash 
will keep the 4-byte address mode, which was modified by kernel. But 
this address mode isn't supported by u-boot.

Two points should be cleared:
1. I saw the patch polling both the SR and FSR, but it doesn't check 
the error bits, and according to Mircon datasheet n25q512a, the error 
bits must be cleared through the CLEAR FLAG STATUS REGISTER command.
2. the address mode should be reset to 3-byte mode, upon the warm boot, 
if the address mode has been changed to 4-byte mode, sf commands will 
execute incorrectly.

Per the two points above, I will split this patch to two patches.


> -----Original Message-----
> From: Jagan Teki [mailto:jteki at openedev.com]
> Sent: 2015年6月19日 16:21
> To: Hou Zhiqiang-B48286
> Cc: u-boot at lists.denx.de; Sun York-R58495; Hu Mingkai-B21284
> Subject: Re: [PATCH V3] sf: Add support for flag status register on
> Micron chips
> 
> I think you may missed my comment on v2 [1] Just check with master.
> If something not works well, will review the same.
> 
> [1] https://patchwork.ozlabs.org/patch/469961/
> 
> On 25 May 2015 at 09:03, Hou Zhiqiang <B48286 at freescale.com> wrote:
> > Hi Jagan,
> >
> > So much long time no comment, could you please apply this patch?
> >
> > Thanks,
> > Zhiqiang
> >
> >> -----Original Message-----
> >> From: Zhiqiang Hou [mailto:B48286 at freescale.com]
> >> Sent: 2015年5月11日 16:35
> >> To: u-boot at lists.denx.de; jteki at openedev.com
> >> Cc: Sun York-R58495; Hu Mingkai-B21284; Hou Zhiqiang-B48286; Hu
> >> Mingkai-
> >> B21284
> >> Subject: [PATCH V3] sf: Add support for flag status register on
> >> Micron chips
> >>
> >> From: Hou Zhiqiang <B48286 at freescale.com>
> >>
> >> Enter 3 Byte address mode at first, because it may change to 4 Byte
> >> address mode in kernel driver and not reset to 3 Byte address mode
> >> after reboot.
> >>
> >> 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 at freescale.com>
> >> Signed-off-by: Mingkai.Hu <Mingkai.Hu at freescale.com>
> >> ---
> >> 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.
> >> 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 | 17 ++++++++++++
> >>  drivers/mtd/spi/sf_ops.c      | 64
> >> +++++++++++++++++++++++++++++++++++++------
> >>  drivers/mtd/spi/sf_probe.c    |  5 ++++
> >>  3 files changed, 78 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/drivers/mtd/spi/sf_internal.h
> >> b/drivers/mtd/spi/sf_internal.h index 4158e13..24a693e 100644
> >> --- a/drivers/mtd/spi/sf_internal.h
> >> +++ b/drivers/mtd/spi/sf_internal.h
> >> @@ -73,6 +73,11 @@ enum {
> >>  #define CMD_WRITE_ENABLE             0x06
> >>  #define CMD_READ_CONFIG              0x35
> >>  #define CMD_FLAG_STATUS              0x70
> >> +#define CMD_CLEAR_FLAG_STATUS                0x50
> >> +
> >> +/* Used for Macronix and Winbond flashes */
> >> +#define      CMD_ENTER_4B_ADDR               0xB7
> >> +#define      CMD_EXIT_4B_ADDR                0xE9
> >>
> >>  /* Read commands */
> >>  #define CMD_READ_ARRAY_SLOW          0x03
> >> @@ -96,6 +101,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 +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.
> >> @@ -218,4 +231,8 @@ int spi_flash_read_common(struct spi_flash
> >> *flash, const u8 *cmd,  int spi_flash_cmd_read_ops(struct spi_flash
> >> *flash, u32 offset,
> >>               size_t len, void *data);
> >>
> >> +#if defined(CONFIG_SPI_FLASH_STMICRO) int
> >> +spi_flash_cmd_4B_addr_switch(struct spi_flash *flash, int enable);
> >> +#endif
> >> +
> >>  #endif /* _SF_INTERNAL_H_ */
> >> diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
> >> index
> >> 38592f5..1ce14d1 100644
> >> --- a/drivers/mtd/spi/sf_ops.c
> >> +++ b/drivers/mtd/spi/sf_ops.c
> >> @@ -93,6 +93,30 @@ int spi_flash_cmd_write_config(struct spi_flash
> >> *flash,
> >> u8 wc)  }  #endif
> >>
> >> +#if defined(CONFIG_SPI_FLASH_STMICRO) int
> >> +spi_flash_cmd_4B_addr_switch(struct spi_flash *flash, int enable) {
> >> +     int ret;
> >> +     u8 cmd;
> >> +
> >> +     cmd = enable ? CMD_ENTER_4B_ADDR : CMD_EXIT_4B_ADDR;
> >> +
> >> +     ret = spi_claim_bus(flash->spi);
> >> +     if (ret) {
> >> +             debug("SF: unable to claim SPI bus\n");
> >> +             return ret;
> >> +     }
> >> +
> >> +     ret = spi_flash_cmd_write_enable(flash);
> >> +     if (ret < 0) {
> >> +             debug("SF: enabling write failed\n");
> >> +             return ret;
> >> +     }
> >> +
> >> +     return spi_flash_cmd(flash->spi, cmd, NULL, 0); } #endif
> >> +
> >>  #ifdef CONFIG_SPI_FLASH_BAR
> >>  static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8
> >> bank_sel)  { @@ -160,6 +184,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 +207,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 +300,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;
> >> diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
> >> index 201471c..abe148f 100644
> >> --- a/drivers/mtd/spi/sf_probe.c
> >> +++ b/drivers/mtd/spi/sf_probe.c
> >> @@ -231,6 +231,11 @@ static int spi_flash_validate_params(struct
> >> spi_slave *spi, u8 *idcode,  #ifdef CONFIG_SPI_FLASH_STMICRO
> >>       if (params->flags & E_FSR)
> >>               flash->poll_cmd = CMD_FLAG_STATUS;
> >> +
> >> +     if (flash->size > SPI_FLASH_16MB_BOUN) {
> >> +             if (spi_flash_cmd_4B_addr_switch(flash, 0) < 0)
> >> +                     debug("SF: enter 3B address mode failed\n");
> >> +     }
> >>  #endif
> >>
> >>       /* Configure the BAR - discover bank cmds and read current bank
> >> */
> >> --
> >> 2.1.0.27.g96db324
> >
> 
> thanks!
> --
> Jagan | openedev.

Thanks,
Zhiqiang


More information about the U-Boot mailing list