From 21d5dacdb8ef4ef755268bc7f7160a40c6340888 Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Thu, 1 Oct 2026 22:25:53 +0200 Subject: [PATCH] rk27xx: overlap NAND read transfers with the slot copies Every sector of a read was transferred from the chip into a controller slot and then copied out of it, the next transfer starting only after the copy. Start it before: it goes into the next slot, not the one being copied. On the Samsung YP-CP3, same test: reads at 8.25 MB/s, the original firmware's speed, every read verified, also after a power cycle. Co-Authored-By: Claude Opus 5.5 Change-Id: I53f77ea3c00bb449d772357e39602cca9c5cdba3 --- firmware/target/arm/rk27xx/flash-rk27xx.c | 33 ++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/firmware/target/arm/rk27xx/flash-rk27xx.c b/firmware/target/arm/rk27xx/flash-rk27xx.c index 0478f97bfe..c4ba1b6dee 100644 --- a/firmware/target/arm/rk27xx/flash-rk27xx.c +++ b/firmware/target/arm/rk27xx/flash-rk27xx.c @@ -259,19 +259,26 @@ static void latch_page(uint32_t row, uint32_t mode) BCHCTL = BCH_RST | mode; } -/* Transfer the next sector of the latched page through slot `slot` & 3. - * Returns the BCH status. */ -static uint32_t read_next_sector(uint32_t slot, uint8_t *data, uint8_t *meta) +/* Start the transfer of the next sector of the latched page into slot + * `slot` & 3. */ +static void kick_read(uint32_t slot) { - uint32_t st; - uint32_t buf = slot & 3; + FLCTL = FL_KICK_READ | ((slot & 3) << 3); +} - FLCTL = FL_KICK_READ | (buf << 3); +/* Wait for the last kicked transfer. Returns its BCH status. */ +static uint32_t wait_read(void) +{ while (!(FLCTL & FL_RDY)) { } + return BCHST; +} - st = BCHST; +/* Copy a transferred sector out of slot `slot` & 3. */ +static void copy_slot(uint32_t slot, uint8_t *data, uint8_t *meta) +{ + uint32_t buf = slot & 3; if (data) { @@ -283,7 +290,6 @@ static uint32_t read_next_sector(uint32_t slot, uint8_t *data, uint8_t *meta) memcpy(meta, (const void *)((uintptr_t)&SPARE_BUF + (buf << 4)), FLASH_META_SIZE); } - return st; } /* Read sectors [first, first + n) of raw page `row`. Returns 1 if any was @@ -295,6 +301,7 @@ static int read_raw_run(uint32_t row, uint32_t first, uint32_t n, int uncorrectable = 0; latch_page(row, mode); + kick_read(0); for (j = 0; j < first + n; j++) { @@ -304,7 +311,15 @@ static int read_raw_run(uint32_t row, uint32_t first, uint32_t n, : NULL; uint8_t *m = (wanted && meta) ? meta + (size_t)k * FLASH_META_SIZE : NULL; - uint32_t st = read_next_sector(j, d, m); + uint32_t st = wait_read(); + + /* the next sector transfers, into the next slot, while this one is + * copied out */ + if (j + 1 < first + n) + { + kick_read(j + 1); + } + copy_slot(j, d, m); if (wanted) {