Message ID | 20210811084924.52293-1-daniel@0x0f.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v3] mtd: spinand: add support for Foresee FS35ND0*G parts | expand |
Hi Daniel, Daniel Palmer <daniel@0x0f.com> wrote on Wed, 11 Aug 2021 17:49:24 +0900: > Add support for the various Foresee FS35ND0*G parts manufactured by Longsys. > > Signed-off-by: Daniel Palmer <daniel@0x0f.com> > > Link: https://datasheet.lcsc.com/szlcsc/2008121142_FORESEE-FS35ND01G-S1Y2QWFI000_C719495.pdf > --- > Changes since v2: > - Originally I only had the 1Gbit version of this chip, now I have the 2Gbit and 4Gbit > variations so I've added support for those too. There is no datasheet for the bigger > chips but they are documented in a flashing tool from an SoC vendor so I took the parameters > from there. > - Previous versions of this patch only had single io read cache variants. My SPI flash driver > now supports dual and quad io for reading so I added and tested those modes too. > My driver/hardware only supports single io for writing so those are still left out. > - Implemented proper logic for checking the ECC status. > - Combined with the previous patch for 1-filling the OOB in the page buffer before writing > I have been using this for a few months now without anything getting broken. > > drivers/mtd/nand/spi/Makefile | 2 +- > drivers/mtd/nand/spi/core.c | 1 + > drivers/mtd/nand/spi/longsys.c | 134 +++++++++++++++++++++++++++++++++ > include/linux/mtd/spinand.h | 1 + > 4 files changed, 137 insertions(+), 1 deletion(-) > create mode 100644 drivers/mtd/nand/spi/longsys.c > > diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile > index 9662b9c1d5a9..1d6819022e43 100644 > --- a/drivers/mtd/nand/spi/Makefile > +++ b/drivers/mtd/nand/spi/Makefile > @@ -1,3 +1,3 @@ > # SPDX-License-Identifier: GPL-2.0 > -spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o > +spinand-objs := core.o gigadevice.o longsys.o macronix.o micron.o paragon.o toshiba.o winbond.o > obj-$(CONFIG_MTD_SPI_NAND) += spinand.o > diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c > index 446ba8d43fbc..48f635d5c1ff 100644 > --- a/drivers/mtd/nand/spi/core.c > +++ b/drivers/mtd/nand/spi/core.c > @@ -895,6 +895,7 @@ static const struct nand_ops spinand_ops = { > > static const struct spinand_manufacturer *spinand_manufacturers[] = { > &gigadevice_spinand_manufacturer, > + &longsys_spinand_manufacturer, > ¯onix_spinand_manufacturer, > µn_spinand_manufacturer, > ¶gon_spinand_manufacturer, > diff --git a/drivers/mtd/nand/spi/longsys.c b/drivers/mtd/nand/spi/longsys.c > new file mode 100644 > index 000000000000..ee38f8728262 > --- /dev/null > +++ b/drivers/mtd/nand/spi/longsys.c > @@ -0,0 +1,134 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2020 Daniel Palmer <daniel@thingy.jp> > + * > + */ > + > +#include <linux/device.h> > +#include <linux/kernel.h> > +#include <linux/mtd/spinand.h> > + > +#define SPINAND_MFR_LONGSYS 0xCD > +#define FS35ND01G_S1Y2_STATUS_ECC_0_3_BITFLIPS (0 << 4) > +#define FS35ND01G_S1Y2_STATUS_ECC_4_BITFLIPS (1 << 4) > +#define FS35ND01G_S1Y2_STATUS_ECC_UNCORRECTABLE (2 << 4) > + > +static SPINAND_OP_VARIANTS(read_cache_variants, > + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), > + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), > + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), > + SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), > + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); > + > +static SPINAND_OP_VARIANTS(write_cache_variants, > + SPINAND_PROG_LOAD(true, 0, NULL, 0)); > + > +static SPINAND_OP_VARIANTS(update_cache_variants, > + SPINAND_PROG_LOAD(false, 0, NULL, 0)); > + > +static int fs35nd01g_s1y2_ooblayout_ecc(struct mtd_info *mtd, int section, > + struct mtd_oob_region *region) > +{ > + if (section > 3) > + return -ERANGE; > + > + /* ECC is not user accessible */ > + region->offset = 0; > + region->length = 0; Can't you just return -ERANGE directly? (maybe not). If you can't then just return -ERANGE on if (section), no need for two additional calls. > + > + return 0; > +} > + > +static int fs35nd01g_s1y2_ooblayout_free(struct mtd_info *mtd, int section, > + struct mtd_oob_region *region) > +{ > + if (section > 3) > + return -ERANGE; > + > + /* > + * No ECC data is stored in the accessible OOB so the full 16 bytes > + * of each spare region is available to the user. Apparently also > + * covered by the internal ECC. > + */ > + if (section) { > + region->offset = 16 * section; > + region->length = 16; > + } else { > + /* First byte in spare0 area is used for bad block marker */ > + region->offset = 1; So far we reserved two bytes for BBM while we know for now we only use one. > + region->length = 15; > + } You can just return if (section) return -ERANGE; offset = 2; length = (4 * 16) - offset; return 0; > + > + return 0; > +} > + > +static const struct mtd_ooblayout_ops fs35nd01g_s1y2_ooblayout = { > + .ecc = fs35nd01g_s1y2_ooblayout_ecc, > + .free = fs35nd01g_s1y2_ooblayout_free, > +}; > + > +static int fs35nd01g_s1y2_ecc_get_status(struct spinand_device *spinand, > + u8 status) > +{ > + switch (status & STATUS_ECC_MASK) { > + case FS35ND01G_S1Y2_STATUS_ECC_0_3_BITFLIPS: > + return 3; > + /* > + * The datasheet says *successful* with 4 bits flipped. > + * nandbiterrs always complains that the read reported > + * successful but the data is incorrect. > + */ > + case FS35ND01G_S1Y2_STATUS_ECC_4_BITFLIPS: > + return 4; This is a real issue. Can you use the nandflipbits tool from the mtd-utils package (you should take a recent version of the package) and try to observe what happens when you insert a 4th bitflip in a section? I generally believe the tool more than the datasheet :) > + case FS35ND01G_S1Y2_STATUS_ECC_UNCORRECTABLE: > + return -EBADMSG; > + default: > + break; > + } > + > + return -EINVAL; > +} > + > +static const struct spinand_info longsys_spinand_table[] = { > + SPINAND_INFO("FS35ND01G-S1Y2", > + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEA, 0x11), > + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), > + NAND_ECCREQ(4, 512), > + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, > + &write_cache_variants, > + &update_cache_variants), > + SPINAND_HAS_QE_BIT, > + SPINAND_ECCINFO(&fs35nd01g_s1y2_ooblayout, > + fs35nd01g_s1y2_ecc_get_status)), > + SPINAND_INFO("FS35ND02G-S3Y2", > + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB, 0x11), > + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), > + NAND_ECCREQ(4, 512), > + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, > + &write_cache_variants, > + &update_cache_variants), > + SPINAND_HAS_QE_BIT, > + SPINAND_ECCINFO(&fs35nd01g_s1y2_ooblayout, > + fs35nd01g_s1y2_ecc_get_status)), > + SPINAND_INFO("FS35ND04G-S2Y2", > + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEC, 0x11), > + NAND_MEMORG(1, 2048, 64, 64, 4096, 40, 1, 1, 1), > + NAND_ECCREQ(4, 512), > + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, > + &write_cache_variants, > + &update_cache_variants), > + SPINAND_HAS_QE_BIT, > + SPINAND_ECCINFO(&fs35nd01g_s1y2_ooblayout, > + fs35nd01g_s1y2_ecc_get_status)), > +}; > + > +static const struct spinand_manufacturer_ops longsys_spinand_manuf_ops = { > +}; > + > +const struct spinand_manufacturer longsys_spinand_manufacturer = { > + .id = SPINAND_MFR_LONGSYS, > + .name = "Longsys", > + .chips = longsys_spinand_table, > + .nchips = ARRAY_SIZE(longsys_spinand_table), > + .ops = &longsys_spinand_manuf_ops, > +}; > diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h > index 6988956b8492..f6c38528bb03 100644 > --- a/include/linux/mtd/spinand.h > +++ b/include/linux/mtd/spinand.h > @@ -261,6 +261,7 @@ struct spinand_manufacturer { > > /* SPI NAND manufacturers */ > extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; > +extern const struct spinand_manufacturer longsys_spinand_manufacturer; > extern const struct spinand_manufacturer macronix_spinand_manufacturer; > extern const struct spinand_manufacturer micron_spinand_manufacturer; > extern const struct spinand_manufacturer paragon_spinand_manufacturer; Otherwise LGTM. Thanks, Miquèl
Hi Miquel, > > + /* > > + * The datasheet says *successful* with 4 bits flipped. > > + * nandbiterrs always complains that the read reported > > + * successful but the data is incorrect. > > + */ > > + case FS35ND01G_S1Y2_STATUS_ECC_4_BITFLIPS: > > + return 4; > > This is a real issue. Can you use the nandflipbits tool from the > mtd-utils package (you should take a recent version of the package) and > try to observe what happens when you insert a 4th bitflip in a section? > > I generally believe the tool more than the datasheet :) Maybe I'm using it incorrectly but I can't get a 4 bit flipped situation to happen. I erased the paged so it's all 0xFF: # flash_erase /dev/mtd0 0x8000000 1 Erasing 128 Kibyte @ 8000000 -- 100 % complete # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 ECC failed: 0 ECC corrected: 6234 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| Then used nandflipbits to flip a bunch of bits in the first byte and then a few other bytes: # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 ECC failed: 0 ECC corrected: 6246 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: eb ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ef ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ef ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| Anyhow, I think we should probably return -EBADMSG if the 4 bit flips status appears as nandbiterrs always complains that the data is wrong. Cheers, Daniel
Hi Daniel, Daniel Palmer <daniel@0x0f.com> wrote on Mon, 23 Aug 2021 23:19:02 +0900: > Hi Miquel, > > > > + /* > > > + * The datasheet says *successful* with 4 bits flipped. > > > + * nandbiterrs always complains that the read reported > > > + * successful but the data is incorrect. > > > + */ > > > + case FS35ND01G_S1Y2_STATUS_ECC_4_BITFLIPS: > > > + return 4; > > > > This is a real issue. Can you use the nandflipbits tool from the > > mtd-utils package (you should take a recent version of the package) and > > try to observe what happens when you insert a 4th bitflip in a section? > > > > I generally believe the tool more than the datasheet :) > > Maybe I'm using it incorrectly but I can't get a 4 bit flipped > situation to happen. > > I erased the paged so it's all 0xFF: > > # flash_erase /dev/mtd0 0x8000000 1 > Erasing 128 Kibyte @ 8000000 -- 100 % complete > # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 > ECC failed: 0 > ECC corrected: 6234 > Number of bad blocks: 0 > Number of bbt blocks: 0 > Block size 131072, page size 2048, OOB size 64 > Dumping data starting at 0x08000000 and ending at 0x08000001... > ECC: 3 corrected bitflip(s) at offset 0x08000000 > 0x08000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > > Then used nandflipbits to flip a bunch of bits in the first byte and > then a few other bytes: > > # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 > ECC failed: 0 > ECC corrected: 6246 > Number of bad blocks: 0 > Number of bbt blocks: 0 > Block size 131072, page size 2048, OOB size 64 > Dumping data starting at 0x08000000 and ending at 0x08000001... > ECC: 3 corrected bitflip(s) at offset 0x08000000 > 0x08000000: f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000010: eb ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000020: ef ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000060: ef ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > > Anyhow, > I think we should probably return -EBADMSG if the 4 bit flips status > appears as nandbiterrs always complains that the data is wrong. I am not sure to follow, above the software says "3 corrected bf" while I thought the problem was when getting 4 bf, but the dump show many more. Can you show me how it behaves: * erase (like you did) * insert {1, 2, 3, 4, 5} bf and show the dump each time? Thanks, Miquèl
Hi Miquel, On Mon, 23 Aug 2021 at 23:21, Miquel Raynal <miquel.raynal@bootlin.com> wrote: > I am not sure to follow, above the software says "3 corrected bf" while Due to the status being "between 0 and 3 bitflips" I think it'll basically report 3 most of the time. As a refresher we seem to have a status for 0 - 3 flips but ok, 4 bit flips but ok, and >4 flips no go. In most cases (0 - 3) the driver is reporting 3. > I thought the problem was when getting 4 bf, but the dump show many > more. Can you show me how it behaves: > * erase (like you did) > * insert {1, 2, 3, 4, 5} bf and show the dump each time? Here's a complete log of erasing the page then flipping all the bits in the first byte. # flash_erase /dev/mtd0 0x8000000 1 Erasing 128 Kibyte @ 8000000 -- 100 % complete # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6249 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandflipbits /dev/mtd0 0@0x8000000 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6252 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: fe ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandflipbits /dev/mtd0 1@0x8000000 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6255 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: fc ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandflipbits /dev/mtd0 2@0x8000000 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6258 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: f8 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandflipbits /dev/mtd0 3@0x8000000 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6261 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandflipbits /dev/mtd0 4@0x8000000 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6264 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: e0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandflipbits /dev/mtd0 5@0x8000000 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6267 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: c0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandflipbits /dev/mtd0 6@0x8000000 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6270 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: 80 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandflipbits /dev/mtd0 7@0x8000000 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6273 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # For completeness logs of what nandbiterrs does: # flash_erase /dev/mtd0 0x8000000 1 Erasing 128 Kibyte @ 8000000 -- 100 % complete # nandbiterrs -i ^C 1024 /dev/mtd0 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6478 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandbiterrs -i -b 1024 /dev/mtd0 incremental biterrors test Read reported 3 corrected bit errors Successfully corrected 0 bit errors per subpage Inserted biterror @ 0/5 Read reported 4 corrected bit errors ECC failure, invalid data despite read success # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6488 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 4 corrected bitflip(s) at offset 0x08000000 0x08000000: 05 a5 65 e5 05 85 45 c5 b5 35 f5 75 95 15 d5 55 |..e...E..5.u...U| 0x08000010: 6d ed 2d ad 4d cd 0d 8d fd 7d bd 3d dd 5d 9d 1d |m.-.M....}.=.]..| 0x08000020: 81 01 c1 41 a1 21 e1 61 11 91 51 d1 31 b1 71 f1 |...A.!.a..Q.1.q.| 0x08000030: c9 49 89 09 e9 69 a9 29 59 d9 19 99 79 f9 39 b9 |.I...i.)Y...y.9.| 0x08000040: 77 d7 37 b7 57 d7 17 97 e7 67 a7 27 c7 47 87 07 |w.7.W....g.'.G..| 0x08000050: 3f bf 7f ff 1f 9f 5f df af 2f ef 6f 8f 0f cf 4f |?....._../.o...O| 0x08000060: d3 53 93 13 f3 73 b3 33 43 c3 03 83 63 e3 23 a3 |.S...s.3C...c.#.| 0x08000070: 9b 1b db 5b bb 3b fb 7b 0b 8b 4b cb 2b ab 6b eb |...[.;.{..K.+.k.| 0x08000080: 0c 8c 4c cc 2c ac 6c ec 9c 1c dc 5c bc 3c fc 7c |..L.,.l....\.<.|| 0x08000090: 44 c4 04 84 64 e4 24 a4 d4 54 94 14 f4 74 b4 34 |D...d.$..T...t.4| # # flash_erase /dev/mtd0 0x8000000 1 Erasing 128 Kibyte @ 8000000 -- 100 % complete # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 0 ECC corrected: 6492 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| # nandbiterrs -o -b 1024 /dev/mtd0 overwrite biterrors test Read reported 3 corrected bit errors Read reported 4 corrected bit errors Failed to recover 1 bitflips Bit error histogram (873 operations total): Page reads with 0 corrected bit errors: 0 Page reads with 1 corrected bit errors: 0 Page reads with 2 corrected bit errors: 0 Page reads with 3 corrected bit errors: 785 # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 ECC failed: 1 ECC corrected: 9202 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 64 Dumping data starting at 0x08000000 and ending at 0x08000001... ECC: 3 corrected bitflip(s) at offset 0x08000000 0x08000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| Cheers, Daniel
Hi Daniel, Daniel Palmer <daniel@0x0f.com> wrote on Mon, 23 Aug 2021 23:54:20 +0900: > Hi Miquel, > > On Mon, 23 Aug 2021 at 23:21, Miquel Raynal <miquel.raynal@bootlin.com> wrote: > > I am not sure to follow, above the software says "3 corrected bf" while > > Due to the status being "between 0 and 3 bitflips" I think it'll > basically report 3 most of the time. > As a refresher we seem to have a status for 0 - 3 flips but ok, 4 bit > flips but ok, and >4 flips no go. > In most cases (0 - 3) the driver is reporting 3. > > > I thought the problem was when getting 4 bf, but the dump show many > > more. Can you show me how it behaves: > > * erase (like you did) > > * insert {1, 2, 3, 4, 5} bf and show the dump each time? > > Here's a complete log of erasing the page then flipping all the bits > in the first byte. > > # flash_erase /dev/mtd0 0x8000000 1 > Erasing 128 Kibyte @ 8000000 -- 100 % complete > # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 > ECC failed: 0 > ECC corrected: 6249 > Number of bad blocks: 0 > Number of bbt blocks: 0 > Block size 131072, page size 2048, OOB size 64 > Dumping data starting at 0x08000000 and ending at 0x08000001... > ECC: 3 corrected bitflip(s) at offset 0x08000000 > 0x08000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > # nandflipbits /dev/mtd0 0@0x8000000 > # nanddump --bb=dumpbad -s 0x8000000 -l 1 -c -p /dev/mtd0 | head -n 10 > ECC failed: 0 > ECC corrected: 6252 > Number of bad blocks: 0 > Number of bbt blocks: 0 > Block size 131072, page size 2048, OOB size 64 > Dumping data starting at 0x08000000 and ending at 0x08000001... > ECC: 3 corrected bitflip(s) at offset 0x08000000 > 0x08000000: fe ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| How is this result possible? You are dumping with the ECC engine enabled, it reports 3 bf (meaning that it is actually running, at least the software really thinks there is an on-die engine enabled) but the data has not been corrected. I expect the first byte to be 0xFF after correction. Only with -n (raw dump) we should see this. > 0x08000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > 0x08000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| Thanks, Miquèl
Hi Miquel, Thank you for your patience on this.. On Tue, 24 Aug 2021 at 00:03, Miquel Raynal <miquel.raynal@bootlin.com> wrote: > > ECC: 3 corrected bitflip(s) at offset 0x08000000 > > 0x08000000: fe ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| > > How is this result possible? You are dumping with the ECC engine > enabled, it reports 3 bf (meaning that it is actually running, at least > the software really thinks there is an on-die engine enabled) but the > data has not been corrected. I expect the first byte to be 0xFF after > correction. Only with -n (raw dump) we should see this. I did a bit of searching to see if a newer/more detailed datasheet has come about and found some vendor code I hadn't seen before: https://github.com/100askTeam/NezaD1_u-boot-2018/blob/1f8b282626f0b9f29f96c57d6b1a5d728e523893/drivers/mtd/awnand/spinand/physic/core.c#L46 This says the ECC enable bit is non-standard and in a register that isn't documented at all in the datasheet. I guess the spi nand core isn't able to actually control the ECC on these chips at the moment and flipping the bits is updating the ECC too. Or the ECC isn't enabled at all. I couldn't see an easy way of overriding which register gets updated so I haven't tried it yet. Cheers, Daniel
diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile index 9662b9c1d5a9..1d6819022e43 100644 --- a/drivers/mtd/nand/spi/Makefile +++ b/drivers/mtd/nand/spi/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o +spinand-objs := core.o gigadevice.o longsys.o macronix.o micron.o paragon.o toshiba.o winbond.o obj-$(CONFIG_MTD_SPI_NAND) += spinand.o diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 446ba8d43fbc..48f635d5c1ff 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -895,6 +895,7 @@ static const struct nand_ops spinand_ops = { static const struct spinand_manufacturer *spinand_manufacturers[] = { &gigadevice_spinand_manufacturer, + &longsys_spinand_manufacturer, ¯onix_spinand_manufacturer, µn_spinand_manufacturer, ¶gon_spinand_manufacturer, diff --git a/drivers/mtd/nand/spi/longsys.c b/drivers/mtd/nand/spi/longsys.c new file mode 100644 index 000000000000..ee38f8728262 --- /dev/null +++ b/drivers/mtd/nand/spi/longsys.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Daniel Palmer <daniel@thingy.jp> + * + */ + +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/mtd/spinand.h> + +#define SPINAND_MFR_LONGSYS 0xCD +#define FS35ND01G_S1Y2_STATUS_ECC_0_3_BITFLIPS (0 << 4) +#define FS35ND01G_S1Y2_STATUS_ECC_4_BITFLIPS (1 << 4) +#define FS35ND01G_S1Y2_STATUS_ECC_UNCORRECTABLE (2 << 4) + +static SPINAND_OP_VARIANTS(read_cache_variants, + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); + +static SPINAND_OP_VARIANTS(write_cache_variants, + SPINAND_PROG_LOAD(true, 0, NULL, 0)); + +static SPINAND_OP_VARIANTS(update_cache_variants, + SPINAND_PROG_LOAD(false, 0, NULL, 0)); + +static int fs35nd01g_s1y2_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section > 3) + return -ERANGE; + + /* ECC is not user accessible */ + region->offset = 0; + region->length = 0; + + return 0; +} + +static int fs35nd01g_s1y2_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section > 3) + return -ERANGE; + + /* + * No ECC data is stored in the accessible OOB so the full 16 bytes + * of each spare region is available to the user. Apparently also + * covered by the internal ECC. + */ + if (section) { + region->offset = 16 * section; + region->length = 16; + } else { + /* First byte in spare0 area is used for bad block marker */ + region->offset = 1; + region->length = 15; + } + + return 0; +} + +static const struct mtd_ooblayout_ops fs35nd01g_s1y2_ooblayout = { + .ecc = fs35nd01g_s1y2_ooblayout_ecc, + .free = fs35nd01g_s1y2_ooblayout_free, +}; + +static int fs35nd01g_s1y2_ecc_get_status(struct spinand_device *spinand, + u8 status) +{ + switch (status & STATUS_ECC_MASK) { + case FS35ND01G_S1Y2_STATUS_ECC_0_3_BITFLIPS: + return 3; + /* + * The datasheet says *successful* with 4 bits flipped. + * nandbiterrs always complains that the read reported + * successful but the data is incorrect. + */ + case FS35ND01G_S1Y2_STATUS_ECC_4_BITFLIPS: + return 4; + case FS35ND01G_S1Y2_STATUS_ECC_UNCORRECTABLE: + return -EBADMSG; + default: + break; + } + + return -EINVAL; +} + +static const struct spinand_info longsys_spinand_table[] = { + SPINAND_INFO("FS35ND01G-S1Y2", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEA, 0x11), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&fs35nd01g_s1y2_ooblayout, + fs35nd01g_s1y2_ecc_get_status)), + SPINAND_INFO("FS35ND02G-S3Y2", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB, 0x11), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&fs35nd01g_s1y2_ooblayout, + fs35nd01g_s1y2_ecc_get_status)), + SPINAND_INFO("FS35ND04G-S2Y2", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEC, 0x11), + NAND_MEMORG(1, 2048, 64, 64, 4096, 40, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&fs35nd01g_s1y2_ooblayout, + fs35nd01g_s1y2_ecc_get_status)), +}; + +static const struct spinand_manufacturer_ops longsys_spinand_manuf_ops = { +}; + +const struct spinand_manufacturer longsys_spinand_manufacturer = { + .id = SPINAND_MFR_LONGSYS, + .name = "Longsys", + .chips = longsys_spinand_table, + .nchips = ARRAY_SIZE(longsys_spinand_table), + .ops = &longsys_spinand_manuf_ops, +}; diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 6988956b8492..f6c38528bb03 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -261,6 +261,7 @@ struct spinand_manufacturer { /* SPI NAND manufacturers */ extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; +extern const struct spinand_manufacturer longsys_spinand_manufacturer; extern const struct spinand_manufacturer macronix_spinand_manufacturer; extern const struct spinand_manufacturer micron_spinand_manufacturer; extern const struct spinand_manufacturer paragon_spinand_manufacturer;
Add support for the various Foresee FS35ND0*G parts manufactured by Longsys. Signed-off-by: Daniel Palmer <daniel@0x0f.com> Link: https://datasheet.lcsc.com/szlcsc/2008121142_FORESEE-FS35ND01G-S1Y2QWFI000_C719495.pdf --- Changes since v2: - Originally I only had the 1Gbit version of this chip, now I have the 2Gbit and 4Gbit variations so I've added support for those too. There is no datasheet for the bigger chips but they are documented in a flashing tool from an SoC vendor so I took the parameters from there. - Previous versions of this patch only had single io read cache variants. My SPI flash driver now supports dual and quad io for reading so I added and tested those modes too. My driver/hardware only supports single io for writing so those are still left out. - Implemented proper logic for checking the ECC status. - Combined with the previous patch for 1-filling the OOB in the page buffer before writing I have been using this for a few months now without anything getting broken. drivers/mtd/nand/spi/Makefile | 2 +- drivers/mtd/nand/spi/core.c | 1 + drivers/mtd/nand/spi/longsys.c | 134 +++++++++++++++++++++++++++++++++ include/linux/mtd/spinand.h | 1 + 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/nand/spi/longsys.c