From: Sascha Hauer <s.hauer@pengutronix.de>
To: BAREBOX <barebox@lists.infradead.org>
Subject: [PATCH 10/27] mtd: nand: mrvl_nfc: keep the ready latch across a STATUS command
Date: Sun, 16 Aug 2026 19:56:30 +0200 [thread overview]
Message-ID: <20260816-pxa3xx-v1-10-f3c3d7a6c43f@pengutronix.de> (raw)
In-Reply-To: <20260816-pxa3xx-v1-0-f3c3d7a6c43f@pengutronix.de>
Every block erase and every page program took 400ms, so writing a
bootloader image to NAND took minutes. That 400ms is nand_wait()'s
timeout, hit in full every single time.
NDSR's per-chipselect ready bits latch the flash's busy-to-ready
transition rather than reporting its current level, and nand_wait()
polls them through mrvl_nand_ready() to find out when an erase or a
program has finished. It issues a STATUS command before it starts
polling, though, and every command clears NDSR on its way through
mrvl_nand_start() - so the transition it was about to wait for was gone
before it ever looked. It never saw a ready chip, ran its timeout out,
and only then fell through to read the status byte. That last read is
correct, which is why this showed up as NAND writes being unusably slow
rather than as an error.
Keep the ready bits across a STATUS command, and go on clearing them for
the commands that make the flash busy in the first place, so what
nand_wait() observes is that command's own completion.
Measured on a Raumfeld speaker (PXA303, 128KiB erase blocks): a block
erase goes from 400ms to under a millisecond and a 128KiB write from
25.6s to 28ms. Reads were never affected.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mtd/nand/raw/nand_mrvl_nfc.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/raw/nand_mrvl_nfc.c b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
index ebb1fd81fb..b1532dbf1b 100644
--- a/drivers/mtd/nand/raw/nand_mrvl_nfc.c
+++ b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
@@ -472,8 +472,9 @@ static unsigned int mrvl_datasize(struct mrvl_nand_host *host)
* We enable all the interrupt at the same time, and
* let mrvl_nand_irq to handle all logic.
*/
-static void mrvl_nand_start(struct mrvl_nand_host *host)
+static void mrvl_nand_start(struct mrvl_nand_host *host, unsigned command)
{
+ uint32_t ndsr_clear = NDSR_MASK;
uint32_t ndcr;
if (host->hwflags & HWFLAGS_ECC_BCH) {
@@ -503,9 +504,27 @@ static void mrvl_nand_start(struct mrvl_nand_host *host)
ndcr &= ~NDCR_ND_RUN;
ndcr |= NDCR_INT_MASK;
+ /*
+ * NDSR's per-chipselect ready bits latch the flash's busy-to-ready
+ * transition, they do not report its current level. nand_wait() polls
+ * them through mrvl_nand_ready() to find out when an erase or a page
+ * program has finished - but it issues a STATUS command first, and
+ * clearing the latch here would wipe the very transition it is about
+ * to wait for. It would then never see a ready chip and spend its
+ * full 400ms timeout on every block erase and every page program
+ * before falling through to read the status byte, which is why this
+ * only ever showed up as NAND writes being unusably slow rather than
+ * as an error.
+ *
+ * So leave the latch alone for STATUS, and keep clearing it for the
+ * commands that make the flash busy in the first place.
+ */
+ if (command == NAND_CMD_STATUS)
+ ndsr_clear &= ~(NDSR_RDY | NDSR_FLASH_RDY);
+
/* clear status bits and run */
nand_writel(host, NDCR, ndcr);
- nand_writel(host, NDSR, NDSR_MASK);
+ nand_writel(host, NDSR, ndsr_clear);
nand_writel(host, NDCR, ndcr | NDCR_ND_RUN);
if (wait_on_timeout(host->chip.legacy.chip_delay * USECOND,
@@ -817,7 +836,7 @@ static void mrvl_nand_cmdfunc(struct nand_chip *chip, unsigned command,
prepare_start_command(host, command);
if (prepare_set_command(host, command, 0, column, page_addr)) {
- mrvl_nand_start(host);
+ mrvl_nand_start(host, command);
mrvl_data_stage(host);
mrvl_nand_wait_cmd_done(host, command);
}
--
2.47.3
next prev parent reply other threads:[~2026-08-16 18:02 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
2026-08-16 17:56 ` [PATCH 01/27] ARM: pxa: remove PXA25x and PXA27x support Sascha Hauer
2026-08-16 17:56 ` [PATCH 02/27] video: remove the PXA framebuffer driver Sascha Hauer
2026-08-16 17:56 ` [PATCH 03/27] ARM: cache: drive the XSC3 cache with the ARMv4 functions Sascha Hauer
2026-08-16 17:56 ` [PATCH 04/27] mci: pxamci: get the clock from the clk API Sascha Hauer
2026-08-16 17:56 ` [PATCH 05/27] pwm: pxa: " Sascha Hauer
2026-08-16 17:56 ` [PATCH 06/27] serial: " Sascha Hauer
2026-08-16 17:56 ` [PATCH 07/27] clk: pxa: add a device tree clock driver for PXA3xx Sascha Hauer
2026-08-16 17:56 ` [PATCH 08/27] mtd: nand: nand_mrvl_nfc: honour marvell,nand-keep-config Sascha Hauer
2026-08-16 17:56 ` [PATCH 09/27] mtd: nand: nand_mrvl_nfc: support the nand-controller bindings Sascha Hauer
2026-08-16 17:56 ` Sascha Hauer [this message]
2026-08-16 17:56 ` [PATCH 11/27] mtd: nand: mrvl_nfc: do not report a command timeout as an error Sascha Hauer
2026-08-16 17:56 ` [PATCH 12/27] mci: pxamci: probe from the device tree Sascha Hauer
2026-08-16 17:56 ` [PATCH 13/27] serial: pxa: add device tree support Sascha Hauer
2026-08-16 17:56 ` [PATCH 14/27] serial: pxa: provide the Linux console name Sascha Hauer
2026-08-16 17:56 ` [PATCH 15/27] gpio: pxa: add a driver and switch the architecture to GPIOLIB Sascha Hauer
2026-08-16 17:56 ` [PATCH 16/27] ARM: pxa: add DEBUG_LL support Sascha Hauer
2026-08-16 17:56 ` [PATCH 17/27] ARM: pxa: let the board select the SoC Sascha Hauer
2026-08-16 17:56 ` [PATCH 18/27] ARM: pxa: enable device tree support Sascha Hauer
2026-08-16 17:56 ` [PATCH 19/27] scripts: add pxa-image Sascha Hauer
2026-08-16 17:56 ` [PATCH 20/27] ARM: pxa: add a NAND first stage loader Sascha Hauer
2026-08-16 17:56 ` [PATCH 21/27] filetype: detect PXA3xx NTIM images Sascha Hauer
2026-08-16 17:56 ` [PATCH 22/27] ARM: pxa: add a barebox update handler for NAND Sascha Hauer
2026-08-16 17:56 ` [PATCH 23/27] clocksource: add a driver for the PXA OS timer and its watchdog Sascha Hauer
2026-08-16 17:56 ` [PATCH 24/27] ARM: pxa: move over to MULTIARCH Sascha Hauer
2026-08-16 17:56 ` [PATCH 25/27] ARM: pxa: reset straight away and without complaining Sascha Hauer
2026-08-16 17:56 ` [PATCH 26/27] ARM: pxa: add Raumfeld Speaker board support Sascha Hauer
2026-08-16 17:56 ` [PATCH 27/27] ARM: multi_v5_v6_defconfig: enable PXA support Sascha Hauer
2026-08-17 7:35 ` [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Ahmad Fatoum
2026-08-19 9:26 ` Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260816-pxa3xx-v1-10-f3c3d7a6c43f@pengutronix.de \
--to=s.hauer@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox