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 = ¶m_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