[PATCH RFC v2] mtd: spinand: winbond: add support for W25N04LW
Dominique Martinet <[email protected]>
| Newsgroups | org.infradead.lists.linux-mtd,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Add support for Winbond W25N04LW 4Gbit SPI-NAND: > 1.8V 4G-bit > Raw serial SLC NAND flash memory > Dual/Quad SPI with 104MHz > buffer read, continuous read & sequential read Highlights copied from datasheet: – Page size: 4,352 Bytes (4096 + 256 Bytes) – Block size: 64 pages (256K + 16K Bytes) - Built-in 8-Bit ECC for memory array – ECC status bits indicate ECC results – Bad Block Management and LUT access – Software and Hardware Write-Protect – Power Supply Lock-Down and OTP protection – Unique ID and Parameter page – Ten 4KB OTP pages per die – Read Level Setting for Read Retry The 4096+256 byte page layout is as follow: - 4096 bytes ECC protected "main memory array", subdivided in 8 512 bytes sectors - 128 bytes spare array, subdivided in 8 16 bytes sectors as follow: - 2 bytes bad block marker (no ECC protection) - 2 bytes "user data II" (no ECC protection) - 12 bytes "user data I" (ECC protected) - 128 bytes parity array, subdivided in 8 16 bytes sectors: - 13 bytes ECC for main data and user data - 3 unused bytes This commit does not support most advanced features such as continuous read, LUT management and OTP pages, and only provides basic usage. OOB layout was defined to only show ECC-protected "user data I", leaving "user data II" unavailable. Signed-off-by: Daisuke Mizobuchi <[email protected]> Signed-off-by: Dominique Martinet <[email protected]> --- Changes in v2: - Link to v1: https://patch.msgid.link/[email protected] - fixed oob layout - fixed NAND_MEMORG oob size I've tested the NAND with various mtd test utils (mtd_oobtest, mtd_pagetest, mtd_subpagetest, mtd_nandbiterrs and some mtd-utils userspace counterparts) with no problem, but I'm not sure what to do with the ooblayout free() informations: as written in the commit message, this chip has 2+12 bytes of user data per sector where the first two are not ECC protected and the later 12 are. I believe user should make the choice of which oob bytes they want to use, but afaik we can't say "this is not protected", so we can't let them choose and must either say both are free or only provide one like I did here. As an extra data point, this "user area I and II" distinction is the same in W25N04KW (same 2+12), but w25n02kv_ooblayout_free() use there returns the whole 14 bytes as a single chunk, so I explicitly made a different choice here. (I believe that's not something that can be changed easily, so we should discuss this before merging) That aside: - Alam, would you like your name somewhere in the commit? I didn't keep anything from your commit because I already had one, but happy to add a Co-developed-by or something - I kept NAND_ECCREQ(8, 512) like W25N04KW but the datasheet says it's based on 8-bits/544-bytes ECC, so I should set it as (8, 544)? (since it's protecting 512+12 bytes for up to 8 bits corruption) In practice ECC is done by hardware and looks like it is correctly reported (e.g. manually overwriting a couple of bits with nandwrite and checking with nanddump properly corrects and reports number of corrected bits), but might as well get this right, even if as far as I understand nothing actually uses the ECC oob data to double-check hardware status? - I'll shamefully admit I do not understand the read / write / update_cache_variants() I copied from KW, Alam had the same but it'd be great to confirm using the same callbacks makes sense? - (I wrote about OTP in the commit message but have no plan of implementing it at this point as we have no use for it, I still intend to look at continuous read after some other work) Thanks! -Dominique --- drivers/mtd/nand/spi/winbond.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index 9b78c1e6cbc9..5b86e5cb06a3 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -335,6 +335,34 @@ static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section, return 0; } +static int w25n04lw_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section > 7) + return -ERANGE; + + region->offset = 128 + (16 * section); + region->length = 13; + + return 0; +} + +static int w25n04lw_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section > 7) + return -ERANGE; + + // the W25N04LW chip actually has two free ranges per section: + // "User Data I" at (16 * section) + 4, length 12 + // "User Data II" at (16 * section) + 2, length 2 + // The later is not ECC protected so this only returns User Data I + region->offset = (16 * section) + 4; + region->length = 12; + + return 0; +} + static const struct mtd_ooblayout_ops w25n01kv_ooblayout = { .ecc = w25n01kv_ooblayout_ecc, .free = w25n02kv_ooblayout_free, @@ -345,6 +373,11 @@ static const struct mtd_ooblayout_ops w25n02kv_ooblayout = { .free = w25n02kv_ooblayout_free, }; +static const struct mtd_ooblayout_ops w25n04lw_ooblayout = { + .ecc = w25n04lw_ooblayout_ecc, + .free = w25n04lw_ooblayout_free, +}; + static int w25n01jw_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *region) { @@ -768,6 +801,15 @@ static const struct spinand_info winbond_spinand_table[] = { &update_cache_variants), 0, SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), + SPINAND_INFO("W25N04LW", /* 1.8V */ + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb2, 0x23), + NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&w25n04lw_ooblayout, w25n02kv_ecc_get_status)), SPINAND_INFO("W35N04JW", /* 1.8V */ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x23), NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 4, 1), --- base-commit: db2ddb87143519e20a95aa36c60b36107b736a58 change-id: 20260812-w25n04lw-3e9146d8340f Best regards, -- Dominique Martinet <[email protected]> ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/