diff mbox series

[1/1] mtd: rawnand: davinci: Add dummy read after sending command

Message ID 20240308074609.9056-1-bastien.curutchet@bootlin.com
State Accepted
Headers show
Series [1/1] mtd: rawnand: davinci: Add dummy read after sending command | expand

Commit Message

Bastien Curutchet March 8, 2024, 7:46 a.m. UTC
Sometimes, writes fail because the tWB_max is not correctly observed
after sending PAGEPROG. It leads to the R/B pin to be read as in
the "ready" state right after sending the command, thus preventing the
normal tPROG delay to be actually observed. This happens because the
ndelay() that waits for tWB_max starts before the command reaches the
NAND chip.

Add a dummy read when a delay is requested at the end of the executed
instruction to make sure that the sent command is received by the NAND
before starting the short ndelay() (<1us but rounded up to 1us in
practice). This read is done on the control register area because
doing it on the Async Data area would change the NAND's RE pin state.
This is not perfect as the two areas are behind two different
devm_ioremap_resource() and could possibly be located on different
interconnects (I did not find more details). This means either the
additional latency due to the load operation is enough impacting, or it
has the expected behavior of ensuring the write has been received.

This has been tested on two platforms designed off of the
DAVINCI/OMAP-L138. The first uses a Toshiba NAND Flash (TC58NYG2S3EBAI5),
the other a Macronix one (MX30UF4G18AC).

Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
---
nandtest utility sometimes fails because of write failures. It is likely
that these failures are due to a non respect of the tPROG delay
after sending PAGEPROG. I could not manage to fully prove this because
adding debugging to the code makes the failure disappear. As these
timings are really tiny, I can't measure them precisely.

 drivers/mtd/nand/raw/davinci_nand.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

Comments

Miquel Raynal March 25, 2024, 10:19 a.m. UTC | #1
On Fri, 2024-03-08 at 07:46:09 UTC, Bastien Curutchet wrote:
> Sometimes, writes fail because the tWB_max is not correctly observed
> after sending PAGEPROG. It leads to the R/B pin to be read as in
> the "ready" state right after sending the command, thus preventing the
> normal tPROG delay to be actually observed. This happens because the
> ndelay() that waits for tWB_max starts before the command reaches the
> NAND chip.
> 
> Add a dummy read when a delay is requested at the end of the executed
> instruction to make sure that the sent command is received by the NAND
> before starting the short ndelay() (<1us but rounded up to 1us in
> practice). This read is done on the control register area because
> doing it on the Async Data area would change the NAND's RE pin state.
> This is not perfect as the two areas are behind two different
> devm_ioremap_resource() and could possibly be located on different
> interconnects (I did not find more details). This means either the
> additional latency due to the load operation is enough impacting, or it
> has the expected behavior of ensuring the write has been received.
> 
> This has been tested on two platforms designed off of the
> DAVINCI/OMAP-L138. The first uses a Toshiba NAND Flash (TC58NYG2S3EBAI5),
> the other a Macronix one (MX30UF4G18AC).
> 
> Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.

Miquel
diff mbox series

Patch

diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index e75d81cf8c21..051deea768db 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -671,8 +671,11 @@  static int davinci_nand_exec_instr(struct davinci_nand_info *info,
 		break;
 	}
 
-	if (instr->delay_ns)
+	if (instr->delay_ns) {
+		/* Dummy read to be sure that command is sent before ndelay starts */
+		davinci_nand_readl(info, 0);
 		ndelay(instr->delay_ns);
+	}
 
 	return 0;
 }