Re: [PATCH v2] mtd: rawnand: denali: add more delays before latching incoming data
From: Helen
Date: Wed Mar 04 2026 - 00:53:43 EST
On Mon, Jul 05, 2021 at 14:48 PM Ralph Siemsen <ralph.siemsen@xxxxxxxxxx> wrote:
>
>Yes, it does seem to work with this value increased to 10001.
>
>Looking more closely, I compared timing parameters in struct
>denali_chip_sel, for the kernel 5.4 (which works), for 5.10 (which
>fails), and also for 5.10 with data_setup_host=10001 (which works).
> 5.4 5.10 5.10+10001
>acc_clks 2 3 4
>rdwr_en_lo_cnt 3 2 3
>cs_setup_cnt 1 0 0
>
>So it seems that on my hardware, rdwr_en_lo_cnt must be >= 3.
I'm using a Cyclone V SoC system, the NAND device is Micron MT29F8G08ABACAWP,
NAND driver fails with "timeout while waiting for irq 0x4", which found in 2021:
https://lore.kernel.org/linux-mtd/20210705144823.GA1459782@xxxxxxxxxxxxxxxxxxx/
It worked fine in Mode5 in 5.10 kernels without the commit below:
https://github.com/torvalds/linux/commit/5756f2e8dad46eba6e2d3e530243b8eff4dd5a42
But after upgrading to 6.12 kernel, include this commit with data_setup_on_host=10001,
the NAND driver still fails with "timeout while waiting for irq 0x4".
Add some print to timing calculations, it seems the deletion of the line in the commit:
- rdwr_en_lo_hi = max_t(int, rdwr_en_lo_hi, mult_x);
cause rdwr_en_lo_hi changed from 4 to 1 and indirectly changed rdwr_en_lo from 3 to 2.
It seems on my hardware rdwr_en_lo_cnt must be >= 3, nand works if add this line back.
I'd like to know why delete it?
Linux 5.10 without commit:
rdwr_en_hi = DIV_ROUD_UP(max(timings->tREH_min, timings->tWH_min), t_x);
0x1 = (7000 + 20000 - 1)/20000 =
acc_clks = DIV_ROUND_UP(timings->tREA_max, t_x);
0x1 = DIV_ROUND_UP(16000, 20000);
rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), t_x);
0x1 = DIV_ROUND_UP(max(10000, 10000), 20000);
rdwr_en_lo_hi = DIV_ROUND_UP(max(timings->tRC_min, timings->tWC_min), t_x);
0x1 = DIV_ROUND_UP(max(2000, 2000), 20000);
rdwr_en_lo_hi = max_t(int, rdwr_en_lo_hi, mult_x);
0x4 = max_t(int, 0x1, 0x4);
rdwr_en_lo = max(rdwr_en_lo, rdwr_en_lo_hi - rdwr_en_hi);
0x3 = max(0x1, 0x4 - 0x1)
rdwr_en_lo = min_t(int, rdwr_en_lo, RDWR_EN_LO_CNT__VALUE);
0x3 = min_t(int, 0x3, mask);
Linux 6.12 with commit + 10001:
static const unsigned int data_setup_on_host = 10001;
rdwr_en_hi = DIV_ROUD_UP(max(timings->tREH_min, timings->tWH_min), t_x);
0x1 = (7000 + 20000 - 1)/20000
acc_clks = DIV_ROUND_UP(timings->tREA_max + data_setup_on_host, t_x);
0x2 = (16000 + 10001 + 20000 - 1)/20000
rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), t_x);
0x1 = (10000 + 20000 -1)/20000
rdwr_en_lo = max_t(int, rdwr_en_lo, acc_clks - timings->tRHOH_min / t_x);
0x2 = max_t(int, 0x1, 0x2 - 15000 / 20000);
rdwr_en_lo_hi = DIV_ROUND_UP(max(timings->tRC_min, timings->tWC_min), t_x);
0x1 = (20000 + 20000 - 1)/20000
rdwr_en_lo = max(rdwr_en_lo, rdwr_en_lo_hi - rdwr_en_hi);
0x2 = max(0x2, 0x2 - 0x1);
rdwr_en_lo = min_t(int, rdwr_en_lo, RDWR_EN_LO_CNT__VALUE);
0x2 = min_t(int, 0x2, mask);
BR,
Helen