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

Jagan Teki jteki at openedev.com
Fri Jun 19 10:21:09 CEST 2015


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.


More information about the U-Boot mailing list