From mboxrd@z Thu Jan 1 00:00:00 1970 From: Rajat Srivastava Date: Wed, 17 Oct 2018 11:52:26 +0000 Subject: [U-Boot] [PATCH v3] sf: Add auto detection of 4-byte mode (vs standard 3-byte mode) Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Stefan Sorry for top-posting. Why can't we read SFDP parameters from flash and auto-detect 3-byte/4-byte addressing mode? Using address width information we can support both types of flash i.e. flashes supporting 3-byte addressing mode as well as flashes supporting 4-byte addressing mode. I've floated a similar patch in U-boot that reads and parses SFDP parameters from flash and auto-detects its addressing mode. It send commands according to the address width it detects. Please find the patch set at: https://patchwork.ozlabs.org/cover/985326/ https://patchwork.ozlabs.org/patch/985327/ https://patchwork.ozlabs.org/patch/985329/ https://patchwork.ozlabs.org/patch/985328/ Thanks Rajat > -----Original Message----- > From: U-Boot On Behalf Of Stefan Roese > Sent: Thursday, October 11, 2018 8:20 PM > To: u-boot at lists.denx.de > Cc: Jagan Teki > Subject: [U-Boot] [PATCH v3] sf: Add auto detection of 4-byte mode (vs > standard 3-byte mode) > > Some SPI NOR chips only support 4-byte mode addressing. Here the > default 3- byte mode does not work and leads to incorrect accesses. > This patch now reads the 4-byte mode status bit (in this case in the > CR register of the Macronix SPI > NOR) and configures the SPI transfers accordingly. > > This was noticed on the LinkIt Smart 7688 modul, which is equipped > with an Macronix MX25L25635F device. But this device does *NOT* > support switching to 3-byte mode via the EX4B command. > > This should also work when the bootrom configures the SPI flash to > 4-byte mode and runs U-Boot after this. U-Boot should dectect this > mode (if the 4-byte mode detection is available for this chip) and use the correct OPs in this case. > > Signed-off-by: Stefan Roese > Cc: Jagan Teki > Tested-by: Simon Goldschmidt > --- > v3: > - Rebased on latest version (merge conflict because of new patches > from Simon Glass) > - Added Tested-by tag from Simon Goldschmidt > > v2: > - Integrated STMICRO 4-byte detection from Simon > > drivers/mtd/spi/sf_internal.h | 3 +- > drivers/mtd/spi/spi_flash.c | 131 ++++++++++++++++++++++++++++------ > include/spi_flash.h | 5 ++ > 3 files changed, 118 insertions(+), 21 deletions(-) > > diff --git a/drivers/mtd/spi/sf_internal.h > b/drivers/mtd/spi/sf_internal.h index > 4f63cacc64..eb076401d1 100644 > --- a/drivers/mtd/spi/sf_internal.h > +++ b/drivers/mtd/spi/sf_internal.h > @@ -26,7 +26,8 @@ enum spi_nor_option_flags { }; > > #define SPI_FLASH_3B_ADDR_LEN 3 > -#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) > +#define SPI_FLASH_4B_ADDR_LEN 4 > +#define SPI_FLASH_CMD_MAX_LEN (1 + > SPI_FLASH_4B_ADDR_LEN) > #define SPI_FLASH_16MB_BOUN 0x1000000 > > /* CFI Manufacture ID's */ > diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c > index 9230060364..b22eea2d1c 100644 > --- a/drivers/mtd/spi/spi_flash.c > +++ b/drivers/mtd/spi/spi_flash.c > @@ -20,12 +20,19 @@ > > #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; > + if (flash->in_4byte_mode) { > + cmd[1] = addr >> 24; > + cmd[2] = addr >> 16; > + cmd[3] = addr >> 8; > + cmd[4] = addr >> 0; > + } else { > + cmd[1] = addr >> 16; > + cmd[2] = addr >> 8; > + cmd[3] = addr >> 0; > + } > } > > static int read_sr(struct spi_flash *flash, u8 *rs) @@ -110,6 +117,72 > @@ static int write_cr(struct spi_flash *flash, u8 wc) } #endif > > +#if defined(CONFIG_SPI_FLASH_MACRONIX) > +static bool flash_in_4byte_mode_macronix(struct spi_flash *flash) { > + int ret; > + u8 cr; > + u8 cmd; > + > + cmd = 0x15; /* Macronix: read configuration register RDCR */ > + ret = spi_flash_read_common(flash, &cmd, 1, &cr, 1); > + if (ret < 0) { > + debug("SF: fail to read config register\n"); > + return false; > + } > + > + /* Return true, if 4-byte mode is enabled */ > + if (cr & BIT(5)) > + return true; > + > + return false; > +} > +#else > +static bool flash_in_4byte_mode_macronix(struct spi_flash *flash) { > + return false; > +} > +#endif > + > +#if defined(CONFIG_SPI_FLASH_STMICRO) static bool > +flash_in_4byte_mode_stmicro(struct spi_flash *flash) { > + int ret; > + u8 fsr; > + u8 cmd; > + > + cmd = 0x70; /* STMicro/Micron: read flag status register */ > + ret = spi_flash_read_common(flash, &cmd, 1, &fsr, 1); > + if (ret < 0) { > + debug("SF: fail to read config register\n"); > + return false; > + } > + > + /* Return true, if 4-byte mode is enabled */ > + if (fsr & BIT(0)) > + return true; > + > + return false; > +} > +#else > +static bool flash_in_4byte_mode_stmicro(struct spi_flash *flash) { > + return false; > +} > +#endif > + > +static bool flash_in_4byte_mode(struct spi_flash *flash, > + const struct spi_flash_info *info) { > + if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MACRONIX) > + return flash_in_4byte_mode_macronix(flash); > + > + if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_STMICRO) > + return flash_in_4byte_mode_stmicro(flash); > + > + return false; > +} > + > #ifdef CONFIG_SPI_FLASH_BAR > /* > * This "clean_bar" is necessary in a situation when one was > accessing @@ - > 314,7 +387,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 +417,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->cmdlen, > + NULL, 0); > if (ret < 0) { > debug("SF: erase failed\n"); > break; > @@ -373,7 +447,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; > @@ -404,15 +478,15 @@ int spi_flash_cmd_write_ops(struct spi_flash > *flash, > u32 offset, > > if (spi->max_write_size) > chunk_len = min(chunk_len, > - spi->max_write_size - sizeof(cmd)); > + spi->max_write_size - flash->cmdlen); > > - 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->cmdlen, > + buf + actual, chunk_len); > if (ret < 0) { > debug("SF: write failed\n"); > break; > @@ -469,9 +543,11 @@ int spi_flash_cmd_read_ops(struct spi_flash > *flash, > u32 offset, { > struct spi_slave *spi = flash->spi; > u8 cmdsz; > - u32 remain_len, read_len, read_addr; > + u64 remain_len; > + u32 read_len, read_addr; > int bank_sel = 0; > int ret = 0; > + int shift; > > /* Handle memory-mapped SPI */ > if (flash->memory_map) { > @@ -487,7 +563,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->cmdlen + flash->dummy_byte; > u8 cmd[cmdsz]; > > cmd[0] = flash->read_cmd; > @@ -504,8 +580,13 @@ 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; > + shift = flash->shift; > + if (flash->in_4byte_mode) > + shift += 8; > + > + remain_len = (((u64)SPI_FLASH_16MB_BOUN << shift) * > + (bank_sel + 1)) - offset; > + > if (len < remain_len) > read_len = len; > else > @@ -514,7 +595,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) { > @@ -1155,6 +1236,13 @@ int spi_flash_scan(struct spi_flash *flash) > write_sr(flash, sr); > } > > + /* Set default value for cmd length */ > + flash->cmdlen = 1 + SPI_FLASH_3B_ADDR_LEN; > + if (flash_in_4byte_mode(flash, info)) { > + flash->in_4byte_mode = true; > + flash->cmdlen = 1 + SPI_FLASH_4B_ADDR_LEN; > + } > + > flash->name = info->name; > flash->memory_map = spi->memory_map; > > @@ -1306,14 +1394,17 @@ int spi_flash_scan(struct spi_flash *flash) > print_size(flash->size, ""); > if (flash->memory_map) > printf(", mapped at %p", flash->memory_map); > + if (flash->in_4byte_mode) > + printf(" (4-byte mode)"); > puts("\n"); > #endif > > #ifndef CONFIG_SPI_FLASH_BAR > - if (((flash->dual_flash == SF_SINGLE_FLASH) && > - (flash->size > SPI_FLASH_16MB_BOUN)) || > + if ((((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))) { > + (flash->size > SPI_FLASH_16MB_BOUN << 1))) && > + !flash->in_4byte_mode) { > puts("SF: Warning - Only lower 16MiB accessible,"); > puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); > } > diff --git a/include/spi_flash.h b/include/spi_flash.h index > 0ec98fb55d..b5bc4a85f6 100644 > --- a/include/spi_flash.h > +++ b/include/spi_flash.h > @@ -36,6 +36,8 @@ struct spi_slave; > * @dual_flash: Indicates dual flash memories - dual stacked, parallel > * @shift: Flash shift useful in dual parallel > * @flags: Indication of spi flash flags > + * @in_4byte_mode: True if flash is detected to be in 4-byte mode > + * @cmdlen: CMD length (3-byte vs 4-byte mode) > * @size: Total flash size > * @page_size: Write (page) size > * @sector_size: Sector size > @@ -69,6 +71,9 @@ struct spi_flash { > u8 shift; > u16 flags; > > + bool in_4byte_mode; > + int cmdlen; > + > u32 size; > u32 page_size; > u32 sector_size; > -- > 2.19.1 > > _______________________________________________ > U-Boot mailing list > U-Boot at lists.denx.de > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flis > ts.de > nx.de%2Flistinfo%2Fu- > boot&data=02%7C01%7Cprabhakar.kushwaha%40nxp.com%7C532d6ed3 > ad764b27306b08d62f88d688%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0 > %7C0%7C636748662097523237&sdata=FpR4s4evDeod9zQPSTMSjigIIAn > mOj50aFqqH21Ofms%3D&reserved=0