Message ID | 20210226075149.888725-1-sr@denx.de |
---|---|
State | Accepted |
Commit | 53879b17382fa4108c57128aefd9a04305607e0a |
Delegated to: | Stefan Roese |
Headers | show |
Series | [v2] cfi_flash: Fix detection of 8-bit bus flash devices via address shift | expand |
On 26.02.21 08:51, Stefan Roese wrote: > From: Jagannadha Sutradharudu Teki <jagannadha.sutradharudu-teki@xilinx.com> > > We had a problem detecting 8/16bit flash devices connected only via > 8bits to the SoC for quite a while. Commit 239cb9d9 > [mtd: cfi_flash: Fix CFI flash driver for 8-bit bus support] finally > fixed this 8-bit bus support. But also broke some other boards using > this cfi driver. So this patch had to be reverted. > > I spotted a different, simpler approach for this 8-bit bus support > on the barebox mailing list posted by > Oleksij Rempel <bug-track@fisher-privat.net>: > > http://www.spinics.net/lists/u-boot-v2/msg14687.html > > Here the commit text: > > " > Many cfi chips support 16 and 8 bit modes. Most important > difference is use of so called "Q15/A-1" pin. In 16bit mode this > pin is used for data IO. In 8bit mode, it is an address input > which add one more least significant bit (LSB). In this case > we should shift all adresses by one: > For example 0xaa << 1 = 0x154 > " > > This patch now is a port of this barebox patch to U-Boot. > > Along with the change w.r.t from barebox, > Some flash chips can support multiple bus widths, override the > interface width and limit it to the port width. > > Tested on 16-bit Spansion flash on sequoia. > Tested 8-bit flashes like 256M29EW, 512M29EW. > > Signed-off-by: Stefan Roese <sr@denx.de> > Tested-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com> > Cc: Jagannadha Sutradharudu Teki <jaganna@xilinx.com> > Cc: Aaron Williams <awilliams@marvell.com> > Cc: Chandrakala Chavva <cchavva@marvell.com> > Cc: Andre Przywara <andre.przywara@arm.com> > Cc: Vignesh Raghavendra <vigneshr@ti.com> > Cc: Simon Glass <sjg@chromium.org> > Cc: Mario Six <mario.six@gdsys.cc> > Cc: York Sun <york.sun@nxp.com> > Cc: Marek Vasut <marek.vasut+renesas@gmail.com> > --- > v2: > - Rebase on current mainline > > I've run into problems with CFI flash on the MIPS Octeon EBB7304, where > the CFI detection did not work. While testing and digging through the > very old CFI related patches, I stumbled over this patch which fixes > the problems on the EBB7304. > > I would really like to see some further testing of this patch on other > boards using CFI parallel flash though. That's why I added some > developers who did send CFI related patches in the last few years. So > please test with this patch applied if possible. > > Thanks, > Stefan Unfortunately it did not receive any tests on other platforms yet. That's why I'm pulling this patch early in the merge window, so that it has a longer time for testing in master. Applied to u-boot-cfi-flash/master Thanks, Stefan > drivers/mtd/cfi_flash.c | 37 +++++++++++++++++++++++++++++++++---- > include/flash.h | 2 ++ > 2 files changed, 35 insertions(+), 4 deletions(-) > > diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c > index b4512e3a5f..9642d7c7dc 100644 > --- a/drivers/mtd/cfi_flash.c > +++ b/drivers/mtd/cfi_flash.c > @@ -218,7 +218,7 @@ flash_map(flash_info_t *info, flash_sect_t sect, uint offset) > { > unsigned int byte_offset = offset * info->portwidth; > > - return (void *)(info->start[sect] + byte_offset); > + return (void *)(info->start[sect] + (byte_offset << info->chip_lsb)); > } > > static inline void flash_unmap(flash_info_t *info, flash_sect_t sect, > @@ -1918,12 +1918,27 @@ static int __flash_detect_cfi(flash_info_t *info, struct cfi_qry *qry) > flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP, > sizeof(struct cfi_qry)); > info->interface = le16_to_cpu(qry->interface_desc); > + /* Some flash chips can support multiple bus widths. > + * In this case, override the interface width and > + * limit it to the port width. > + */ > + if ((info->interface == FLASH_CFI_X8X16) && > + (info->portwidth == FLASH_CFI_8BIT)) { > + debug("Overriding 16-bit interface width to" > + " 8-bit port width\n"); > + info->interface = FLASH_CFI_X8; > + } else if ((info->interface == FLASH_CFI_X16X32) && > + (info->portwidth == FLASH_CFI_16BIT)) { > + debug("Overriding 16-bit interface width to" > + " 16-bit port width\n"); > + info->interface = FLASH_CFI_X16; > + } > > info->cfi_offset = flash_offset_cfi[cfi_offset]; > debug("device interface is %d\n", > info->interface); > - debug("found port %d chip %d ", > - info->portwidth, info->chipwidth); > + debug("found port %d chip %d chip_lsb %d ", > + info->portwidth, info->chipwidth, info->chip_lsb); > debug("port %d bits chip %d bits\n", > info->portwidth << CFI_FLASH_SHIFT_WIDTH, > info->chipwidth << CFI_FLASH_SHIFT_WIDTH); > @@ -1962,9 +1977,23 @@ static int flash_detect_cfi(flash_info_t *info, struct cfi_qry *qry) > info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) { > for (info->chipwidth = FLASH_CFI_BY8; > info->chipwidth <= info->portwidth; > - info->chipwidth <<= 1) > + info->chipwidth <<= 1) { > + /* > + * First, try detection without shifting the addresses > + * for 8bit devices (16bit wide connection) > + */ > + info->chip_lsb = 0; > + if (__flash_detect_cfi(info, qry)) > + return 1; > + > + /* > + * Not detected, so let's try with shifting > + * for 8bit devices > + */ > + info->chip_lsb = 1; > if (__flash_detect_cfi(info, qry)) > return 1; > + } > } > debug("not found\n"); > return 0; > diff --git a/include/flash.h b/include/flash.h > index 3bf6b22399..42b18a6047 100644 > --- a/include/flash.h > +++ b/include/flash.h > @@ -24,6 +24,8 @@ typedef struct { > #ifdef CONFIG_SYS_FLASH_CFI > uchar portwidth; /* the width of the port */ > uchar chipwidth; /* the width of the chip */ > + uchar chip_lsb; /* extra Least Significant Bit in the */ > + /* address of chip */ > ushort buffer_size; /* # of bytes in write buffer */ > ulong erase_blk_tout; /* maximum block erase timeout */ > ulong write_tout; /* maximum write timeout */ > Viele Grüße, Stefan
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index b4512e3a5f..9642d7c7dc 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -218,7 +218,7 @@ flash_map(flash_info_t *info, flash_sect_t sect, uint offset) { unsigned int byte_offset = offset * info->portwidth; - return (void *)(info->start[sect] + byte_offset); + return (void *)(info->start[sect] + (byte_offset << info->chip_lsb)); } static inline void flash_unmap(flash_info_t *info, flash_sect_t sect, @@ -1918,12 +1918,27 @@ static int __flash_detect_cfi(flash_info_t *info, struct cfi_qry *qry) flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP, sizeof(struct cfi_qry)); info->interface = le16_to_cpu(qry->interface_desc); + /* Some flash chips can support multiple bus widths. + * In this case, override the interface width and + * limit it to the port width. + */ + if ((info->interface == FLASH_CFI_X8X16) && + (info->portwidth == FLASH_CFI_8BIT)) { + debug("Overriding 16-bit interface width to" + " 8-bit port width\n"); + info->interface = FLASH_CFI_X8; + } else if ((info->interface == FLASH_CFI_X16X32) && + (info->portwidth == FLASH_CFI_16BIT)) { + debug("Overriding 16-bit interface width to" + " 16-bit port width\n"); + info->interface = FLASH_CFI_X16; + } info->cfi_offset = flash_offset_cfi[cfi_offset]; debug("device interface is %d\n", info->interface); - debug("found port %d chip %d ", - info->portwidth, info->chipwidth); + debug("found port %d chip %d chip_lsb %d ", + info->portwidth, info->chipwidth, info->chip_lsb); debug("port %d bits chip %d bits\n", info->portwidth << CFI_FLASH_SHIFT_WIDTH, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); @@ -1962,9 +1977,23 @@ static int flash_detect_cfi(flash_info_t *info, struct cfi_qry *qry) info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) { for (info->chipwidth = FLASH_CFI_BY8; info->chipwidth <= info->portwidth; - info->chipwidth <<= 1) + info->chipwidth <<= 1) { + /* + * First, try detection without shifting the addresses + * for 8bit devices (16bit wide connection) + */ + info->chip_lsb = 0; + if (__flash_detect_cfi(info, qry)) + return 1; + + /* + * Not detected, so let's try with shifting + * for 8bit devices + */ + info->chip_lsb = 1; if (__flash_detect_cfi(info, qry)) return 1; + } } debug("not found\n"); return 0; diff --git a/include/flash.h b/include/flash.h index 3bf6b22399..42b18a6047 100644 --- a/include/flash.h +++ b/include/flash.h @@ -24,6 +24,8 @@ typedef struct { #ifdef CONFIG_SYS_FLASH_CFI uchar portwidth; /* the width of the port */ uchar chipwidth; /* the width of the chip */ + uchar chip_lsb; /* extra Least Significant Bit in the */ + /* address of chip */ ushort buffer_size; /* # of bytes in write buffer */ ulong erase_blk_tout; /* maximum block erase timeout */ ulong write_tout; /* maximum write timeout */