Linux-mtd Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC v2] mtd: spinand: winbond: add support for W25N04LW
@ 2026-08-12  4:14 Dominique Martinet
  2026-08-12  5:04 ` Dominique Martinet
  0 siblings, 1 reply; 4+ messages in thread
From: Dominique Martinet @ 2026-08-12  4:14 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 defined to only show ECC-protected "user data I", leaving
"user data II" unavailable.

Signed-off-by: Daisuke Mizobuchi <mizo@atmark-techno.com>
Signed-off-by: Dominique Martinet <dominique.martinet@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

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 <dominique.martinet@atmark-techno.com>



______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH RFC v2] mtd: spinand: winbond: add support for W25N04LW
  2026-08-12  4:14 [PATCH RFC v2] mtd: spinand: winbond: add support for W25N04LW Dominique Martinet
@ 2026-08-12  5:04 ` Dominique Martinet
  2026-08-12  7:35   ` Miquel Raynal
  0 siblings, 1 reply; 4+ messages in thread
From: Dominique Martinet @ 2026-08-12  5:04 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Md Sadre Alam,
	Vignesh Raghavendra
  Cc: linux-mtd, linux-kernel, Daisuke Mizobuchi

Dominique Martinet wrote on Wed, Aug 12, 2026 at 04:14:02AM +0000:
> +	// 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

(will fix to use block comment like the rest of the file + latter typo
as per Sashiko comment in v3, after we've reached an agreement on what
to do here -- there were no other Sashiko comment)

-- 
Dominique



______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH RFC v2] mtd: spinand: winbond: add support for W25N04LW
  2026-08-12  5:04 ` Dominique Martinet
@ 2026-08-12  7:35   ` Miquel Raynal
  2026-08-12  8:08     ` Dominique Martinet
  0 siblings, 1 reply; 4+ messages in thread
From: Miquel Raynal @ 2026-08-12  7:35 UTC (permalink / raw)
  To: Dominique Martinet
  Cc: Richard Weinberger, Md Sadre Alam, Vignesh Raghavendra, linux-mtd,
	linux-kernel, Daisuke Mizobuchi

On 12/08/2026 at 14:04:30 +09, Dominique Martinet <dominique.martinet@atmark-techno.com> wrote:

> Dominique Martinet wrote on Wed, Aug 12, 2026 at 04:14:02AM +0000:
>> +	// 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
>
> (will fix to use block comment like the rest of the file + latter typo
> as per Sashiko comment in v3, after we've reached an agreement on what
> to do here -- there were no other Sashiko comment)

I haven't checked the diff yet, but the commit message contains a SoB
from anther person which is listed first. You must be Author + first SoB or
you can give someone else authorship + first SoB and take 2nd SoB (which
means you carried the patch without changing it). If you want to credit
another person, please have a look at the Co-developed-by wording.

Thanks!
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH RFC v2] mtd: spinand: winbond: add support for W25N04LW
  2026-08-12  7:35   ` Miquel Raynal
@ 2026-08-12  8:08     ` Dominique Martinet
  0 siblings, 0 replies; 4+ messages in thread
From: Dominique Martinet @ 2026-08-12  8:08 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Richard Weinberger, Md Sadre Alam, Vignesh Raghavendra, linux-mtd,
	linux-kernel, Daisuke Mizobuchi

Miquel Raynal wrote on Wed, Aug 12, 2026 at 09:35:55AM +0200:
> On 12/08/2026 at 14:04:30 +09, Dominique Martinet <dominique.martinet@atmark-techno.com> wrote:
> 
> > Dominique Martinet wrote on Wed, Aug 12, 2026 at 04:14:02AM +0000:
> >> +	// 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
> >
> > (will fix to use block comment like the rest of the file + latter typo
> > as per Sashiko comment in v3, after we've reached an agreement on what
> > to do here -- there were no other Sashiko comment)
> 
> I haven't checked the diff yet, but the commit message contains a SoB
> from anther person which is listed first. You must be Author + first SoB or
> you can give someone else authorship + first SoB and take 2nd SoB (which
> means you carried the patch without changing it). If you want to credit
> another person, please have a look at the Co-developed-by wording.

Thanks, will add a Co-developed-by tag for them in v3 after other
discussions are settled


I've also been stressing/torturing the nand a bit and I'm noticing a lot
of ECC errors (regardless of erase cycle count); all ECC errors are
apparently focused on two bits regardless of the sector the error
happened on (bit 0x20 at offset either 0x7e or 0x80 in any sector,
from checking data with nanddump -n and diffing the output)

This error is reliably readable so it happened on write, but
erase+nandwrite properly clears the error, and there's just too many
(~20-40 over 1MB of data, so 2048 512 bytes sectors), so I think that's
worth investigating further before applying even if I don't see what
could possibly cause this in the nand code

(Well, I guess it could also just be how this batch turned out, but I'm
surprised that the errors would always happen on the same two bits...
It didn't happen with the 04KW so hopefully not a SPI bug either...)

I need to wait next week to test on different hardware to rule out a
hardware bug and I'll reach out to our contact at winbond as well

Thanks,
-- 
Dominique



______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

end of thread, other threads:[~2026-08-12  8:08 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-12  4:14 [PATCH RFC v2] mtd: spinand: winbond: add support for W25N04LW Dominique Martinet
2026-08-12  5:04 ` Dominique Martinet
2026-08-12  7:35   ` Miquel Raynal
2026-08-12  8:08     ` Dominique Martinet

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