* [PATCH RFC] mtd: spinand: winbond: enable continuous read for W25N04LW
@ 2026-08-14 8:15 Dominique Martinet
2026-08-25 9:09 ` Miquel Raynal
0 siblings, 1 reply; 3+ messages in thread
From: Dominique Martinet @ 2026-08-14 8:15 UTC (permalink / raw)
To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra
Cc: linux-mtd, linux-kernel, Dominique Martinet
This enables continuous read for W25N04LW:
- The ops are basically the same as cont_read_cache_dual_quad_dtr_variants
without the speed limit (this chip has no HFREQ flag that would change
the required delays) and without DTR ops (not supported)
- w25n0xjw_set_cont_read() can be reused
Unfortunately on my system (i.MX 8ULP LPSPI) the first time continuous
read is used spinand_read_from_cache_op() falls into this if and
disables continuous read, so this didn't go any further:
/*
* Dirmap accesses are allowed to toggle the CS.
* Toggling the CS during a continuous read is forbidden.
*/
if (nbytes && req->continuous) {
/*
* Spi controller with broken support of continuous
* reading was detected. Disable future use of
* continuous reading and return -EAGAIN to retry
* reading within regular mode.
*/
spinand->cont_read_possible = false;
return -EAGAIN;
}
I'm leaving this patch for anyone who could have hardware for this (or
eventually myself after I have time to check the SPI driver...)
Fun fact:
nanddump -C is about 9% faster than nanddump on large data (tried 10MB)
even if continuous read is not supported.
Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
---
drivers/mtd/nand/spi/winbond.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index 171f4c264220..ad735f73945b 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -203,6 +203,13 @@ static SPINAND_OP_VARIANTS(cont_read_cache_dual_quad_dtr_variants,
/* The 1S_1D_1D variant would require 4.5 dummy bytes, this is not possible */
WINBOND_CONT_READ_FROM_CACHE_FAST_1S_1S_1S_OP(4, NULL, 0, 0));
+static SPINAND_OP_VARIANTS(cont_read_cache_variants,
+ WINBOND_CONT_READ_FROM_CACHE_1S_4S_4S_OP(6, NULL, 0, 0),
+ WINBOND_CONT_READ_FROM_CACHE_1S_1S_4S_OP(4, NULL, 0, 0),
+ WINBOND_CONT_READ_FROM_CACHE_1S_2S_2S_OP(4, NULL, 0, 0),
+ WINBOND_CONT_READ_FROM_CACHE_1S_1S_2S_OP(4, NULL, 0, 0),
+ WINBOND_CONT_READ_FROM_CACHE_FAST_1S_1S_1S_OP(4, NULL, 0, 0));
+
static SPINAND_OP_VARIANTS(read_cache_variants,
SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 2, NULL, 0, 0),
SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
@@ -780,11 +787,13 @@ static const struct spinand_info winbond_spinand_table[] = {
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),
+ SPINAND_INFO_OP_VARIANTS_WITH_CONT(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants,
+ &cont_read_cache_variants),
0,
- SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
+ SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status),
+ SPINAND_CONT_READ(w25n0xjw_set_cont_read)),
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: 0f1b5abff55b580facccc16324ede60b048bd23c
change-id: 20260814-w25n04lw-contread-03485e60c88e
prerequisite-change-id: 20260812-w25n04lw-3e9146d8340f:v3
prerequisite-patch-id: 3fbc1f74bfc7bbcd5dd7ecf62a7e5b0352cacbb2
Best regards,
--
Dominique Martinet <dominique.martinet@atmark-techno.com>
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH RFC] mtd: spinand: winbond: enable continuous read for W25N04LW
2026-08-14 8:15 [PATCH RFC] mtd: spinand: winbond: enable continuous read for W25N04LW Dominique Martinet
@ 2026-08-25 9:09 ` Miquel Raynal
2026-08-26 9:03 ` Dominique Martinet
0 siblings, 1 reply; 3+ messages in thread
From: Miquel Raynal @ 2026-08-25 9:09 UTC (permalink / raw)
To: Dominique Martinet
Cc: Richard Weinberger, Vignesh Raghavendra, linux-mtd, linux-kernel
Hi Dominique,
On 14/08/2026 at 08:15:58 GMT, Dominique Martinet <dominique.martinet@atmark-techno.com> wrote:
> This enables continuous read for W25N04LW:
> - The ops are basically the same as cont_read_cache_dual_quad_dtr_variants
> without the speed limit (this chip has no HFREQ flag that would change
> the required delays) and without DTR ops (not supported)
> - w25n0xjw_set_cont_read() can be reused
>
> Unfortunately on my system (i.MX 8ULP LPSPI) the first time continuous
> read is used spinand_read_from_cache_op() falls into this if and
> disables continuous read, so this didn't go any further:
Ah, too bad :-)
> /*
> * Dirmap accesses are allowed to toggle the CS.
> * Toggling the CS during a continuous read is forbidden.
> */
> if (nbytes && req->continuous) {
> /*
> * Spi controller with broken support of continuous
> * reading was detected. Disable future use of
> * continuous reading and return -EAGAIN to retry
> * reading within regular mode.
> */
> spinand->cont_read_possible = false;
> return -EAGAIN;
> }
>
> I'm leaving this patch for anyone who could have hardware for this (or
> eventually myself after I have time to check the SPI driver...)
>
> Fun fact:
> nanddump -C is about 9% faster than nanddump on large data (tried 10MB)
> even if continuous read is not supported.
That is strange. Is this really reproducible? Can you disable CPU PM and
try again? There should be no impact if continuous read is disabled.
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH RFC] mtd: spinand: winbond: enable continuous read for W25N04LW
2026-08-25 9:09 ` Miquel Raynal
@ 2026-08-26 9:03 ` Dominique Martinet
0 siblings, 0 replies; 3+ messages in thread
From: Dominique Martinet @ 2026-08-26 9:03 UTC (permalink / raw)
To: Miquel Raynal
Cc: Richard Weinberger, Vignesh Raghavendra, linux-mtd, linux-kernel
Miquel Raynal wrote on Tue, Aug 25, 2026 at 11:09:33AM +0200:
> > Unfortunately on my system (i.MX 8ULP LPSPI) the first time continuous
> > read is used spinand_read_from_cache_op() falls into this if and
> > disables continuous read, so this didn't go any further:
>
> Ah, too bad :-)
Yeah, I'll try to take some time to dig into the SPI driver to see if
that can be fixed in software but I'm afraid it'll take a while
longer...
> > Fun fact:
> > nanddump -C is about 9% faster than nanddump on large data (tried 10MB)
> > even if continuous read is not supported.
>
> That is strange. Is this really reproducible? Can you disable CPU PM and
> try again? There should be no impact if continuous read is disabled.
This system has no knob that I'm aware of (no cpufreq in
/sys/devices/system/cpu at least), but I've shoved the IRQs aside except
for the spi ones and it appears pretty stable (mtd1 is a 8MB partition)
------
localhost:/mnt/mtd-utils# taskset -c 1 hyperfine --warmup 3 -r 20 './nanddump -f /dev/null /dev/mtd1' './nanddump -C -
f /dev/null /dev/mtd1'
Benchmark 1: ./nanddump -f /dev/null /dev/mtd1
Time (mean ± σ): 511.1 ms ± 0.5 ms [User: 7.8 ms, System: 419.8 ms]
Range (min … max): 510.4 ms … 512.0 ms 20 runs
Benchmark 2: ./nanddump -C -f /dev/null /dev/mtd1
Time (mean ± σ): 480.9 ms ± 0.9 ms [User: 0.5 ms, System: 399.6 ms]
Range (min … max): 480.1 ms … 483.3 ms 20 runs
Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.
Summary
./nanddump -C -f /dev/null /dev/mtd1 ran
1.06 ± 0.00 times faster than ./nanddump -f /dev/null /dev/mtd1
------
(this is on our 6.12 tree and not on the 7.2-rc I was on earlier, so
ymmv, but iirc the 9% figure was taken on 7.2 with hyperfine so this
should be reproducible with the latest and greatest)
I have much more important things to do so I obviously had to look
further into this mystery :-), but I didn't see anything obvious...
For some reason the contiguous read variant seems to spend less time in
spinand_wait() between the load page and read from cache op (looking at
a flamegraph), but dumping the actual ops used I see very similar
sequences of load page (0x13), poll status (0xf), dirmap_read (0xeb),
so that doesn't explain the difference...
The main difference I see is that nanddump -C passes a much larger
buffer to read (observable with strace -c), so loops for reading inside
the kernel, and without -C loops in userspace: I do not see the syscall
overhead in my perf record flamegraph but perhaps that changes the
timing just enough for the nand to behave differently or something like
that?
Definitely curious, but I'm not sure if there's anything to act on
here..
Cheers,
--
Dominique
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-26 9:03 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-14 8:15 [PATCH RFC] mtd: spinand: winbond: enable continuous read for W25N04LW Dominique Martinet
2026-08-25 9:09 ` Miquel Raynal
2026-08-26 9:03 ` Dominique Martinet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox