> -----Original Message----- > From: Vignesh R <vigne...@ti.com> > Sent: Friday, November 16, 2018 8:56 PM > To: Rajat Srivastava <rajat.srivast...@nxp.com>; Simon Goldschmidt > <simon.k.r.goldschm...@gmail.com>; U-Boot Mailing List <u- > b...@lists.denx.de> > Cc: Jagan Teki <ja...@openedev.com> > Subject: Re: [U-Boot] [PATCH v2 1/2] mtd/spi: Add JEDEC SFDP support in SPI > framework > > On 16-Nov-18 6:29 PM, Rajat Srivastava wrote: > >> On Fri, Nov 16, 2018 at 11:19 AM Vignesh R <vigne...@ti.com> wrote: > >>> On 16/11/18 3:10 PM, Rajat Srivastava wrote: > >>>>> Hi Rajat, > >>>>> > >>>>> On 13/11/18 5:30 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. > >>>>>> SFDP parsing is made default but already existing method for > >>>>>> parsing these parameters are not deprecated. > >>>>>> A flag is created to skip SFDP parsing for a particular flash, if > >>>>>> required. > >>>>>> > >>>>>> 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> > >>>>>> --- > >>>>>> Changes in v2: > >>>>>> - Make SFDP parsing the default method. > >>>>>> - Change SPI_FLASH_USE_SFDP flag to SPI_FLASH_USE_SFDP to > >> provide > >>>>>> an option to skip SFDP parsing for a particular flash. > >>>>>> --- > >>>>> > >>>>> [...] > >>>>>> +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; > >>>>>> + > >>>>> > >>>>> I see your are updating flash->addr_width to 4 bytes here. But I > >>>>> don't see any code in this patch that changes flash->read_cmd (and > >>>>> write/erase > >>>>> cmds) to use 4B addressing opcodes. Also, I dont see any code that > >>>>> bypasses BAR register configuration when CONFIG_SPI_FLASH_BAR is > >>>>> defined and SFDP is available. > >>>> > >>>> We don't have any flash that supports CONFIG_SPI_FLASH_BAR. What > do > >> you suggest, shall we skip SFDP parsing in case CONFIG_SPI_FLASH_BAR > >> is defined? > >>>> > >>> > >>> I suggest skipping BAR configuration completely if flash supports > >>> address width of 4 as per SFDP. BAR configuration is only needed if > >>> flash does not support 4 byte addressing and flash size is > 16MB > >>> > >>>>> This patch will most certainly break SPI controller drivers(like > >>>>> cadence_qspi.c) that expect sf layer to provide correct read > >>>>> opcode and address width information, since there will be mismatch > >>>>> wrt opcode used and number of address byte sent. > >>>>> Not sure how this patch was tested, but I guess fsl_qspi modifies > >>>>> read opcode internal to the driver and gets away with it. > >>>>> Please modify the patch to update read_cmd/erase_cmd/write_cmd > to > >>>>> use > >>>>> 4 byte addressing opcodes > >>>> > >>>> If the flash supports only supports 4-byte opcodes then there will > >>>> be no mismatch wrt opcode used and number of address bytes sent > >>>> since all of the opcodes that the flash supports will be 4-bytes opcodes. > >>>> But if the flash supports both 3-byte as well as 4-byte address > >>>> widths (which is a separate case) then this code will default the > >>>> address mode to 4-byte but gives an option to use 3-byte by setting > >> addrwd_3_in_use flag. > >>>> > >>> > >>> Lets assume flash supports both 3 and 4 byte addressing (AFAIK, > >>> majority of flash parts do that). In this case, this patch is > >>> defaulting to 4 byte address width but > >>> flash->read_cmd/write_cmd/erase_cmd are still set to 3 byte > >>> flash->addressing > >> opcodes. > >>> So, SPI controller would end up send 3 addressing byte opcode but 4 > >>> byte of address. The flash would interpret last byte of address as > >>> first byte of data and thus lead to data corruption in case of write. > >>> Isn't that a problem? > > > > Ok. But I'm curious if a flash supports both 3 and 4 byte address > > widths (and it does not have BAR support), then why would one use 3-byte > read/write/erase commands? > > How would one access >16 MB in such case? > > > > Unfortunately thats a problem with U-Boot spi_flash layer today. Many > newer flashes like Micron's mt35x series dont support BAR registers. > Accessing above 16MB is broken for such flashes today. > > > Also, initially I wanted to make SFDP optional so that none of the drivers > are affected > > and one could enable it using a flag as per requirement. Shall we get back > to making > > this optional (similar to v1 of this patch)? > > > > How does that help? With opt-in approach you mark some flash devices as > SFDP capable, but you still don't update opcodes, thus breaking boards > that have such flash devices. So, porting full bfpt parsing and always > using opcode to 4 byte addressing opcodes when available will be needed. > Thus you would end up with SFDP as default instead of opt-in.
Hi Vignesh Porting full bftp parsing requires time. I am seeing a conflict with a patch of yours https://patchwork.ozlabs.org/cover/1012146/ It seem above RFC patch will bring SFDP to U-boot. Do you still want me to put effort in porting SFDP in current version? Regards Rajat > > > Regards > > Rajat > > > >> > >> Additionally, there are flash chips with a 3-/4-byte mode change > instruction. > >> But using 4-byte opcodes should be preferred. > >> > >> Simon > >> > >>> > >>> In particular you are not parsing entire bfpt like in [1] and will > >>> break flash operations > >>> > >>> > >> > [1]https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2F > >>> elixir.bootlin.com%2Flinux%2Flatest%2Fsource%2Fdrivers%2Fmtd%2Fspi- > >> nor > >>> %2Fspi- > >> nor.c%23L2259&data=02%7C01%7Crajat.srivastava%40nxp.com%7Ca > >>> > >> > cee153f50194bba71c808d64bad8d2e%7C686ea1d3bc2b4c6fa92cd99c5c30163 > 5 > >> %7C0 > >>> > >> > %7C0%7C636779606107591743&sdata=UACl919%2BMQmdtBo5GUTAy > >> M428u1bT1bU > >>> rXuX2GsSjb0%3D&reserved=0 > >>> > >>> Regards > >>> Vignesh > >>> > >>>> Regards > >>>> Rajat > >>>> > >>>>> > >>>>> Regards > >>>>> Vigensh > >>>>> > >>>>> > >>>>>> + 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) { @@ > >>>>>> -1130,7 > >>>>> +1366,7 @@ int > >>>>>> spi_flash_scan(struct spi_flash *flash) { > >>>>>> struct spi_slave *spi = flash->spi; > >>>>>> const struct spi_flash_info *info = NULL; > >>>>>> - int ret; > >>>>>> + int ret, sfdp = 0; > >>>>>> > >>>>>> info = spi_flash_read_id(flash); > >>>>>> if (IS_ERR_OR_NULL(info)) > >>>>>> @@ -1196,9 +1432,28 @@ 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_SKIP_SFDP)) { > >>>>>> + flash->size = 0; > >>>>>> + sfdp = spi_flash_parse_sfdp(flash); > >>>>>> + if (sfdp < 0) > >>>>>> + debug("Unable to get SFDP information\n"); > >>>>>> + } > >>>>>> + > >>>>>> /* 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_SKIP_SFDP || sfdp < 0) { > >>>>>> + 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 +1468,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_SKIP_SFDP || sfdp < 0) { > >>>>>> + 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 +1570,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_SKIP_SFDP || sfdp < 0) && > >>>>>> + (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://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flis > >>> ts.denx.de%2Flistinfo%2Fu- > >> boot&data=02%7C01%7Crajat.srivastava%40n > >>> > >> > xp.com%7Cacee153f50194bba71c808d64bad8d2e%7C686ea1d3bc2b4c6fa92c > >> d99c5c > >>> > >> > 301635%7C0%7C0%7C636779606107591743&sdata=u9H5PMJiRNVKyyFI7 > >> y5eCmDx > >>> 0KPmAHXvF8kusaJVUdM%3D&reserved=0 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot