The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v3] mtd: spinand: winbond: add support for W25N04LW
@ 2026-08-14  8:12 Dominique Martinet
  2026-08-17  5:21 ` Dominique Martinet
  0 siblings, 1 reply; 2+ messages in thread
From: Dominique Martinet @ 2026-08-14  8:12 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Md Sadre Alam,
	Vignesh Raghavendra
  Cc: linux-mtd, linux-kernel, Daisuke Mizobuchi, Dominique Martinet

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 kept compatible with previous models (exposing both user
data I and II), dependent on mtd->oobsize.

Co-developed-by: Daisuke Mizobuchi <mizo@atmark-techno.com>
Signed-off-by: Daisuke Mizobuchi <mizo@atmark-techno.com>
Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
---
Changes in v3:
- Fixed Co-authored-by / comment style
- Merged ooblayout helper with w25n02kv_ooblayout, using mtd->oobsize
(with an extra comment describing User Data I/II, but keeping current
behaviour)
- Link to v2: https://patch.msgid.link/20260812-w25n04lw-v2-1-deee97602fc4@atmark-techno.com

Changes in v2:
- Link to v1: https://patch.msgid.link/ansYUoNKJyDQ+6f2@hu-mdalam-blr.qualcomm.com
- fixed oob layout
- fixed NAND_MEMORG oob size

Testwise:
- debugfs ooblayout_ecc/ooblayout_free is fine with new version
- I still need to check about the high number of ecc errors next week,
but I don't think it's likely to be related to this patch so sending
ahead... Feel free to wait a bit (there's no hurry on my end for this to
get into 7.3; it's fine to skip a cycle as you see fit)
- I checked the SPINAND_INFO_OP_VARIANTS and there is no problem with
current values for this model.

Thanks!

-Dominique
---
 drivers/mtd/nand/spi/winbond.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index 9b78c1e6cbc9..171f4c264220 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -314,10 +314,11 @@ static int w25n01kv_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section,
 				  struct mtd_oob_region *region)
 {
-	if (section > 3)
+	/* 4 sections for 128 bytes, 8 for 256 */
+	if (section >= mtd->oobsize / 32)
 		return -ERANGE;
 
-	region->offset = 64 + (16 * section);
+	region->offset = (mtd->oobsize / 2) + (16 * section);
 	region->length = 13;
 
 	return 0;
@@ -326,9 +327,16 @@ static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section,
 				   struct mtd_oob_region *region)
 {
-	if (section > 3)
+	if (section >= mtd->oobsize / 32)
 		return -ERANGE;
 
+	/*
+	 * For at least W25N04KW and W25N04LW, this region is actually
+	 * split in two:
+	 * ECC-protected "User Data I" at + 4 offset, length 12
+	 * unprotected "User Data II" at + 2 offset, length 2
+	 * This returns the full region for backwards compatibility.
+	 */
 	region->offset = (16 * section) + 2;
 	region->length = 14;
 
@@ -768,6 +776,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(&w25n02kv_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 <dominique.martinet@atmark-techno.com>



^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-17  5:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-14  8:12 [PATCH v3] mtd: spinand: winbond: add support for W25N04LW Dominique Martinet
2026-08-17  5:21 ` Dominique Martinet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox