On 17/10/18 4:58 PM, Rajat Srivastava wrote:
> Add support for JESD216 rev B standard JEDEC Serial
> Flash Discoverable Parameters (SFDP) tables to
> dynamically initialize flash size, page size and
> address width of the flash. More parameters can be
> added as per requirement.
> Already existing method for parsing these parameters
> are not deprecated, which can be done once most flash
> start using SFDP data.
> 
> SFDP data lets us auto-detect the addressing mode
> supported by the flash which helps us access the
> flash using 4-byte address.
> 
> Add a new argument in spi_flash_addr() function to create
> commands with 3-byte or 4-byte address depending on the
> SFDP data read. Add pointer to struct spi_flash in struct
> spi_slave so that driver can have access to SFDP data.
> 
> Introduce new structures and functions to read and parse
> SFDP data. This is loosely based on Linux SFDP framework.
> 
> Signed-off-by: Rajat Srivastava <rajat.srivast...@nxp.com>
> ---
>  drivers/mtd/spi/sf_internal.h |   4 +
>  drivers/mtd/spi/spi_flash.c   | 297 
> +++++++++++++++++++++++++++++++++++++++---
>  include/spi.h                 |   2 +
>  include/spi_flash.h           | 120 +++++++++++++++++
>  4 files changed, 403 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
> index 26f5c7c995..1bb4431d84 100644
> --- a/drivers/mtd/spi/sf_internal.h
> +++ b/drivers/mtd/spi/sf_internal.h
> @@ -26,7 +26,9 @@ enum spi_nor_option_flags {
>  };
>  
>  #define SPI_FLASH_3B_ADDR_LEN                3
> +#define SPI_FLASH_4B_ADDR_LEN                4
>  #define SPI_FLASH_CMD_LEN            (1 + SPI_FLASH_3B_ADDR_LEN)
> +#define SPI_FLASH_CMD_MAX_LEN                (1 + SPI_FLASH_4B_ADDR_LEN)
>  #define SPI_FLASH_16MB_BOUN          0x1000000
>  
>  /* CFI Manufacture ID's */
> @@ -62,6 +64,7 @@ enum spi_nor_option_flags {
>  #define CMD_READ_STATUS1             0x35
>  #define CMD_READ_CONFIG                      0x35
>  #define CMD_FLAG_STATUS                      0x70
> +#define CMD_READ_SFDP                        0x5a
>  
>  /* Bank addr access commands */
>  #ifdef CONFIG_SPI_FLASH_BAR
> @@ -144,6 +147,7 @@ struct spi_flash_info {
>  #define RD_DUAL                      BIT(5)  /* use Dual Read */
>  #define RD_QUADIO            BIT(6)  /* use Quad IO Read */
>  #define RD_DUALIO            BIT(7)  /* use Dual IO Read */
> +#define SPI_FLASH_USE_SFDP   BIT(8)  /* parse SFDP to get flash info */

I suggest to SFDP not be a opt-in but default option like Linux kernel,
since that's SFDP is a standard. If flash does not support SFDP that can
be detected by looking for SFPD signature and code can fallback
gracefully. If a flash has a broken SFDP table then such parts can use
"SPI_FLASH_BROKEN_SFDP" flag or something. That way we don't need to add
above flag to almost all flash entries here.

Regards
Vignesh

>  #define RD_FULL                      (RD_QUAD | RD_DUAL | RD_QUADIO | 
> RD_DUALIO)
>  };
>  
> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
> index a87bacd4ac..5d2728cc00 100644
> --- a/drivers/mtd/spi/spi_flash.c
> +++ b/drivers/mtd/spi/spi_flash.c
> @@ -20,12 +20,24 @@
>  
>  #include "sf_internal.h"
>  
> -static void spi_flash_addr(u32 addr, u8 *cmd)
> +static void spi_flash_addr(struct spi_flash *flash, u32 addr, u8 *cmd)
>  {
>       /* cmd[0] is actual command */
> -     cmd[1] = addr >> 16;
> -     cmd[2] = addr >> 8;
> -     cmd[3] = addr >> 0;
> +     int i;
> +
> +     /* Remember to unset addrwd_3_in_use */
> +     if (flash->addrwd_3_in_use) {
> +             flash->addr_width = SPI_FLASH_3B_ADDR_LEN;
> +             debug("SF: addrwd_3_in_use flag needs to be reset to false ");
> +             debug("after the intended command is triggered to flash.\n");
> +     }
> +
> +     flash->cmd_len = 1 + flash->addr_width;
> +
> +     for (i = flash->cmd_len - 1; i > 0; i--) {
> +             cmd[i] = addr;
> +             addr = addr >> 8;
> +     }
>  }
>  
>  static int read_sr(struct spi_flash *flash, u8 *rs)
> @@ -314,7 +326,7 @@ int spi_flash_write_common(struct spi_flash *flash, const 
> u8 *cmd,
>  int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
>  {
>       u32 erase_size, erase_addr;
> -     u8 cmd[SPI_FLASH_CMD_LEN];
> +     u8 cmd[SPI_FLASH_CMD_MAX_LEN];
>       int ret = -1;
>  
>       erase_size = flash->erase_size;
> @@ -344,12 +356,13 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, 
> u32 offset, size_t len)
>               if (ret < 0)
>                       return ret;
>  #endif
> -             spi_flash_addr(erase_addr, cmd);
> +             spi_flash_addr(flash, erase_addr, cmd);
>  
>               debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
>                     cmd[2], cmd[3], erase_addr);
>  
> -             ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
> +             ret = spi_flash_write_common(flash, cmd, flash->cmd_len,
> +                                          NULL, 0);
>               if (ret < 0) {
>                       debug("SF: erase failed\n");
>                       break;
> @@ -373,7 +386,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 
> offset,
>       unsigned long byte_addr, page_size;
>       u32 write_addr;
>       size_t chunk_len, actual;
> -     u8 cmd[SPI_FLASH_CMD_LEN];
> +     u8 cmd[SPI_FLASH_CMD_MAX_LEN];
>       int ret = -1;
>  
>       page_size = flash->page_size;
> @@ -406,13 +419,13 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, 
> u32 offset,
>                       chunk_len = min(chunk_len,
>                                       spi->max_write_size - sizeof(cmd));
>  
> -             spi_flash_addr(write_addr, cmd);
> +             spi_flash_addr(flash, write_addr, cmd);
>  
>               debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = 
> %zu\n",
>                     buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
>  
> -             ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
> -                                     buf + actual, chunk_len);
> +             ret = spi_flash_write_common(flash, cmd, flash->cmd_len,
> +                                          buf + actual, chunk_len);
>               if (ret < 0) {
>                       debug("SF: write failed\n");
>                       break;
> @@ -487,7 +500,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 
> offset,
>               return 0;
>       }
>  
> -     cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
> +     cmdsz = flash->cmd_len + flash->dummy_byte;
>       u8 cmd[cmdsz];
>  
>       cmd[0] = flash->read_cmd;
> @@ -504,8 +517,11 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 
> offset,
>                       return log_ret(ret);
>               bank_sel = flash->bank_curr;
>  #endif
> -             remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
> -                             (bank_sel + 1)) - offset;
> +             if (flash->cmd_len == SPI_FLASH_CMD_MAX_LEN)
> +                     remain_len = flash->size - offset;
> +             else
> +                     remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
> +                                   (bank_sel + 1)) - offset;
>               if (len < remain_len)
>                       read_len = len;
>               else
> @@ -514,7 +530,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 
> offset,
>               if (spi->max_read_size)
>                       read_len = min(read_len, spi->max_read_size);
>  
> -             spi_flash_addr(read_addr, cmd);
> +             spi_flash_addr(flash, read_addr, cmd);
>  
>               ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
>               if (ret < 0) {
> @@ -1076,6 +1092,226 @@ static const struct spi_flash_info 
> *spi_flash_read_id(struct spi_flash *flash)
>       return ERR_PTR(-ENODEV);
>  }
>  
> +/*
> + * Serial Flash Discoverable Parameters (SFDP) parsing
> + */
> +
> +/*
> + * spi_flash_read_sfdp() - read Serial Flash Discoverable Parameters.
> + * @flash:   pointer to a 'struct spi_flash'
> + * @addr:    offset in the SFDP area to start reading data from
> + * @len:     number of bytes to read
> + * @buf:     buffer where the SFDP data are copied into
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +static int spi_flash_read_sfdp(struct spi_flash *flash, u32 addr, size_t len,
> +                            void *buf)
> +{
> +     u8 cmd[4];
> +     int ret;
> +
> +     cmd[0] = CMD_READ_SFDP;
> +
> +     /*
> +      * In case of flashes that support 3 or 4-byte addressing modes
> +      * based on command fired, CMD_READ_SFDP is a 3-byte command.
> +      * To make sure a 3-byte command is fired, change addrwd_3_in_use
> +      * to true and reset it after triggering the command.
> +      */
> +     flash->addrwd_3_in_use = true;
> +     spi_flash_addr(flash, addr, cmd);
> +     flash->addrwd_3_in_use = false;
> +
> +     ret = spi_flash_read_common(flash, cmd, 4, buf, len);
> +     if (ret)
> +             return -EIO;
> +
> +     return 0;
> +}
> +
> +/**
> + * spi_flash_parse_bfpt() - read and parse the Basic Flash Parameter Table.
> + * @flash:           pointer to a 'struct spi_flash'
> + * @bfpt_header:     pointer to the 'struct sfdp_parameter_header' describing
> + *                   the Basic Flash Parameter Table length and version
> + *
> + * The Basic Flash Parameter Table is the main and only mandatory table as
> + * defined by the SFDP (JESD216) specification.
> + * It provides us with the total size (memory density) of the data array, 
> page
> + * size and the number of address bytes to perform flash operations, among
> + * other information.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +static int spi_flash_parse_bfpt(struct spi_flash *flash,
> +                             const struct sfdp_parameter_header *bfpt_header)
> +{
> +     struct sfdp_bfpt bfpt;
> +     size_t len;
> +     int i, err;
> +     u32 addr;
> +
> +     /* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */
> +     if (bfpt_header->length < BFPT_DWORD_MAX_JESD216)
> +             return -EINVAL;
> +
> +     /* Read the Basic Flash Parameter Table. */
> +     len = min_t(size_t, sizeof(bfpt),
> +                 bfpt_header->length * sizeof(u32));
> +     addr = SFDP_PARAM_HEADER_PTP(bfpt_header);
> +     memset(&bfpt, 0, sizeof(bfpt));
> +     err = spi_flash_read_sfdp(flash, addr, len, &bfpt);
> +     if (err < 0)
> +             return err;
> +
> +     /* Fix endianness of the BFPT DWORDs. */
> +     for (i = 0; i < BFPT_DWORD_MAX; i++)
> +             bfpt.dwords[i] = le32_to_cpu(bfpt.dwords[i]);
> +
> +     /* Number of address bytes. */
> +     switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) {
> +     case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY:
> +             flash->addr_width = 3;
> +             break;
> +
> +     case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4:
> +             printf("SF: Flash defaults to 3-Byte mode; enters 4-Byte ");
> +             printf("mode on command\n");
> +             /*
> +              * By default, 4-byte addressing mode is set.
> +              * To enforce 3-byte addressing mode, set addrwd_3_in_use flag
> +              * in struct spi_flash for every command.
> +              */
> +             flash->addr_width = 4;
> +             break;
> +
> +     case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY:
> +             flash->addr_width = 4;
> +             break;
> +
> +     default:
> +             break;
> +     }
> +
> +     /* Flash Memory Density (in bits). */
> +     flash->size = bfpt.dwords[BFPT_DWORD(2)];
> +     if (flash->size & BIT(31)) {
> +             flash->size &= ~BIT(31);
> +
> +             /*
> +              * Prevent overflows on flash->size. Anyway, a NOR of 2^64
> +              * bits is unlikely to exist so this error probably means
> +              * the BFPT we are reading is corrupted/wrong.
> +              */
> +             if (flash->size > 63)
> +                     return -EINVAL;
> +
> +             flash->size = 1ULL << flash->size;
> +     } else {
> +             flash->size++;
> +     }
> +     flash->size >>= 3; /* Convert to bytes. */
> +
> +     /* Stop here if not JESD216 rev A or later. */
> +     if (bfpt_header->length < BFPT_DWORD_MAX)
> +             return 0;
> +
> +     /* Page size: this field specifies 'N' so the page size = 2^N bytes. */
> +     flash->page_size = bfpt.dwords[BFPT_DWORD(11)];
> +     flash->page_size &= BFPT_DWORD11_PAGE_SIZE_MASK;
> +     flash->page_size >>= BFPT_DWORD11_PAGE_SIZE_SHIFT;
> +     flash->page_size = 1U << flash->page_size;
> +
> +     return 0;
> +}
> +
> +/*
> + * spi_flash_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
> + * @flash:   pointer to a 'struct spi_flash'
> + *
> + * The Serial Flash Discoverable Parameters are described by the JEDEC 
> JESD216
> + * specification. This is a standard which tends to supported by almost all
> + * (Q)SPI memory manufacturers. Those hard-coded tables allow us to learn at
> + * runtime the main parameters needed to perform basic SPI flash operations.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +static int spi_flash_parse_sfdp(struct spi_flash *flash)
> +{
> +     const struct sfdp_parameter_header *param_header, *bfpt_header;
> +     struct sfdp_parameter_header *param_headers = NULL;
> +     struct sfdp_header header;
> +     size_t psize;
> +     int i, err;
> +
> +     /* Get the SFDP header. */
> +     err = spi_flash_read_sfdp(flash, 0, sizeof(header), &header);
> +     if (err < 0)
> +             return err;
> +
> +     /* Check the SFDP header version. */
> +     if (le32_to_cpu(header.signature) != SFDP_SIGNATURE ||
> +         header.major != SFDP_JESD216_MAJOR)
> +             return -EINVAL;
> +
> +     /*
> +      * Verify that the first and only mandatory parameter header is a
> +      * Basic Flash Parameter Table header as specified in JESD216.
> +      */
> +     bfpt_header = &header.bfpt_header;
> +     if (SFDP_PARAM_HEADER_ID(bfpt_header) != SFDP_BFPT_ID ||
> +         bfpt_header->major != SFDP_JESD216_MAJOR)
> +             return -EINVAL;
> +
> +     /*
> +      * Allocate memory then read all parameter headers with a single
> +      * Read SFDP command. These parameter headers will actually be parsed
> +      * twice: a first time to get the latest revision of the basic flash
> +      * parameter table, then a second time to handle the supported optional
> +      * tables.
> +      * Hence we read the parameter headers once for all to reduce the
> +      * processing time
> +      */
> +     if (header.nph) {
> +             psize = header.nph * sizeof(*param_headers);
> +
> +             param_headers = malloc(psize);
> +             if (!param_headers)
> +                     return -ENOMEM;
> +
> +             err = spi_flash_read_sfdp(flash, sizeof(header),
> +                                       psize, param_headers);
> +             if (err < 0) {
> +                     dev_err(dev, "failed to read SFDP parameter headers\n");
> +                     goto exit;
> +             }
> +     }
> +
> +     /*
> +      * Check other parameter headers to get the latest revision of
> +      * the basic flash parameter table.
> +      */
> +     for (i = 0; i < header.nph; i++) {
> +             param_header = &param_headers[i];
> +
> +             if (SFDP_PARAM_HEADER_ID(param_header) == SFDP_BFPT_ID &&
> +                 param_header->major == SFDP_JESD216_MAJOR &&
> +                 (param_header->minor > bfpt_header->minor ||
> +                  (param_header->minor == bfpt_header->minor &&
> +                   param_header->length > bfpt_header->length)))
> +                     bfpt_header = param_header;
> +     }
> +
> +     err = spi_flash_parse_bfpt(flash, bfpt_header);
> +     if (err)
> +             goto exit;
> +
> +exit:
> +     free(param_headers);
> +     return err;
> +}
> +
>  static int set_quad_mode(struct spi_flash *flash,
>                        const struct spi_flash_info *info)
>  {
> @@ -1196,9 +1432,26 @@ int spi_flash_scan(struct spi_flash *flash)
>       }
>  #endif
>  
> +     spi->flash = flash;
> +     flash->addrwd_3_in_use = false;
> +
> +     /* Read Serial Flash Discoverable Parameters and initialize
> +      * the following parameters of flash:
> +      * 1. Flash size
> +      * 2. Page size
> +      * 3. Address width to be used for commands
> +      */
> +     if (info->flags & SPI_FLASH_USE_SFDP) {
> +             flash->size = 0;
> +             spi_flash_parse_sfdp(flash);
> +     }
> +
>       /* Compute the flash size */
>       flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
> -     flash->page_size = info->page_size;
> +     if (!(info->flags & SPI_FLASH_USE_SFDP)) {
> +             flash->page_size = info->page_size;
> +             flash->addr_width = SPI_FLASH_3B_ADDR_LEN;
> +     }
>       /*
>        * The Spansion S25FS512S, S25FL032P and S25FL064P have 256b pages,
>        * yet use the 0x4d00 Extended JEDEC code. The rest of the Spansion
> @@ -1213,7 +1466,10 @@ int spi_flash_scan(struct spi_flash *flash)
>       }
>       flash->page_size <<= flash->shift;
>       flash->sector_size = info->sector_size << flash->shift;
> -     flash->size = flash->sector_size * info->n_sectors << flash->shift;
> +     if (!(info->flags & SPI_FLASH_USE_SFDP)) {
> +             flash->size = flash->sector_size * info->n_sectors <<
> +                     flash->shift;
> +     }
>  #ifdef CONFIG_SF_DUAL_FLASH
>       if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
>               flash->size <<= 1;
> @@ -1312,9 +1568,10 @@ int spi_flash_scan(struct spi_flash *flash)
>  #endif
>  
>  #ifndef CONFIG_SPI_FLASH_BAR
> -     if (((flash->dual_flash == SF_SINGLE_FLASH) &&
> -          (flash->size > SPI_FLASH_16MB_BOUN)) ||
> -          ((flash->dual_flash > SF_SINGLE_FLASH) &&
> +     if (!(info->flags & SPI_FLASH_USE_SFDP) &&
> +         (flash->dual_flash == SF_SINGLE_FLASH &&
> +          flash->size > SPI_FLASH_16MB_BOUN) ||
> +          (flash->dual_flash > SF_SINGLE_FLASH &&
>            (flash->size > SPI_FLASH_16MB_BOUN << 1))) {
>               puts("SF: Warning - Only lower 16MiB accessible,");
>               puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
> diff --git a/include/spi.h b/include/spi.h
> index 938627bc01..7189e60581 100644
> --- a/include/spi.h
> +++ b/include/spi.h
> @@ -10,6 +10,7 @@
>  #define _SPI_H_
>  
>  #include <common.h>
> +#include <spi_flash.h>
>  
>  /* SPI mode flags */
>  #define SPI_CPHA     BIT(0)                  /* clock phase */
> @@ -103,6 +104,7 @@ struct spi_slave {
>       unsigned int bus;
>       unsigned int cs;
>  #endif
> +     struct spi_flash *flash;
>       uint mode;
>       unsigned int wordlen;
>       unsigned int max_read_size;
> diff --git a/include/spi_flash.h b/include/spi_flash.h
> index 0ec98fb55d..6558a4a1d5 100644
> --- a/include/spi_flash.h
> +++ b/include/spi_flash.h
> @@ -47,6 +47,9 @@ struct spi_slave;
>   * @read_cmd:                Read cmd - Array Fast, Extn read and quad read.
>   * @write_cmd:               Write cmd - page and quad program.
>   * @dummy_byte:              Dummy cycles for read operation.
> + * @cmd_len:         Total length of command.
> + * @addr_width:              Number of address bytes.
> + * @addrwd_3_in_use: Flag to send command in 3-byte address mode.
>   * @memory_map:              Address of read-only SPI flash access
>   * @flash_lock:              lock a region of the SPI Flash
>   * @flash_unlock:    unlock a region of the SPI Flash
> @@ -82,6 +85,9 @@ struct spi_flash {
>       u8 read_cmd;
>       u8 write_cmd;
>       u8 dummy_byte;
> +     u8 cmd_len;
> +     u8 addr_width;
> +     bool addrwd_3_in_use;
>  
>       void *memory_map;
>  
> @@ -107,6 +113,120 @@ struct spi_flash {
>  #endif
>  };
>  
> +/*
> + * Serial Flash Discoverable Parameter Headers
> + */
> +struct sfdp_parameter_header {
> +     u8      id_lsb;
> +     u8      minor;
> +     u8      major;
> +     u8      length; /* in double words */
> +     u8      parameter_table_pointer[3]; /* byte address */
> +     u8      id_msb;
> +};
> +
> +struct sfdp_header {
> +     u32     signature; /* Ox50444653U <=> "SFDP" */
> +     u8      minor;
> +     u8      major;
> +     u8      nph; /* 0-base number of parameter headers */
> +     u8      unused;
> +
> +     /* Basic Flash Parameter Table. */
> +     struct sfdp_parameter_header    bfpt_header;
> +};
> +
> +#define SFDP_PARAM_HEADER_ID(p) (((p)->id_msb << 8) | (p)->id_lsb)
> +#define SFDP_PARAM_HEADER_PTP(p) \
> +     (((p)->parameter_table_pointer[2] << 16) | \
> +      ((p)->parameter_table_pointer[1] <<  8) | \
> +      ((p)->parameter_table_pointer[0] <<  0))
> +
> +#define SFDP_BFPT_ID         0xff00  /* Basic Flash Parameter Table */
> +#define SFDP_SECTOR_MAP_ID   0xff81  /* Sector Map Table */
> +
> +#define SFDP_SIGNATURE               0x50444653U
> +#define SFDP_JESD216_MAJOR   1
> +#define SFDP_JESD216_MINOR   0
> +#define SFDP_JESD216A_MINOR  5
> +#define SFDP_JESD216B_MINOR  6
> +
> +/* Basic Flash Parameter Table */
> +
> +/*
> + * JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs.
> + * They are indexed from 1 but C arrays are indexed from 0.
> + */
> +#define BFPT_DWORD(i)                ((i) - 1)
> +#define BFPT_DWORD_MAX               16
> +
> +/* The first version of JESB216 defined only 9 DWORDs. */
> +#define BFPT_DWORD_MAX_JESD216                       9
> +
> +/* 1st DWORD. */
> +#define BFPT_DWORD1_FAST_READ_1_1_2          BIT(16)
> +#define BFPT_DWORD1_ADDRESS_BYTES_MASK               GENMASK(18, 17)
> +#define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY     (0x0UL << 17)
> +#define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4     (0x1UL << 17)
> +#define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY     (0x2UL << 17)
> +#define BFPT_DWORD1_DTR                              BIT(19)
> +#define BFPT_DWORD1_FAST_READ_1_2_2          BIT(20)
> +#define BFPT_DWORD1_FAST_READ_1_4_4          BIT(21)
> +#define BFPT_DWORD1_FAST_READ_1_1_4          BIT(22)
> +
> +/* 5th DWORD. */
> +#define BFPT_DWORD5_FAST_READ_2_2_2          BIT(0)
> +#define BFPT_DWORD5_FAST_READ_4_4_4          BIT(4)
> +
> +/* 11th DWORD. */
> +#define BFPT_DWORD11_PAGE_SIZE_SHIFT         4
> +#define BFPT_DWORD11_PAGE_SIZE_MASK          GENMASK(7, 4)
> +
> +/* 15th DWORD. */
> +
> +/*
> + * (from JESD216 rev B)
> + * Quad Enable Requirements (QER):
> + * - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4
> + *         reads based on instruction. DQ3/HOLD# functions are hold during
> + *         instruction phase.
> + * - 001b: QE is bit 1 of status register 2. It is set via Write Status with
> + *         two data bytes where bit 1 of the second byte is one.
> + *         [...]
> + *         Writing only one byte to the status register has the side-effect 
> of
> + *         clearing status register 2, including the QE bit. The 100b code is
> + *         used if writing one byte to the status register does not modify
> + *         status register 2.
> + * - 010b: QE is bit 6 of status register 1. It is set via Write Status with
> + *         one data byte where bit 6 is one.
> + *         [...]
> + * - 011b: QE is bit 7 of status register 2. It is set via Write status
> + *         register 2 instruction 3Eh with one data byte where bit 7 is one.
> + *         [...]
> + *         The status register 2 is read using instruction 3Fh.
> + * - 100b: QE is bit 1 of status register 2. It is set via Write Status with
> + *         two data bytes where bit 1 of the second byte is one.
> + *         [...]
> + *         In contrast to the 001b code, writing one byte to the status
> + *         register does not modify status register 2.
> + * - 101b: QE is bit 1 of status register 2. Status register 1 is read using
> + *         Read Status instruction 05h. Status register2 is read using
> + *         instruction 35h. QE is set via Writ Status instruction 01h with
> + *         two data bytes where bit 1 of the second byte is one.
> + *         [...]
> + */
> +#define BFPT_DWORD15_QER_MASK                        GENMASK(22, 20)
> +#define BFPT_DWORD15_QER_NONE                        (0x0UL << 20) /* Micron 
> */
> +#define BFPT_DWORD15_QER_SR2_BIT1_BUGGY              (0x1UL << 20)
> +#define BFPT_DWORD15_QER_SR1_BIT6            (0x2UL << 20) /* Macronix */
> +#define BFPT_DWORD15_QER_SR2_BIT7            (0x3UL << 20)
> +#define BFPT_DWORD15_QER_SR2_BIT1_NO_RD              (0x4UL << 20)
> +#define BFPT_DWORD15_QER_SR2_BIT1            (0x5UL << 20) /* Spansion */
> +
> +struct sfdp_bfpt {
> +     u32     dwords[BFPT_DWORD_MAX];
> +};
> +
>  struct dm_spi_flash_ops {
>       int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf);
>       int (*write)(struct udevice *dev, u32 offset, size_t len,
> 

-- 
Regards
Vignesh
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to