@@ -1289,7 +1289,22 @@ static int sdhci_transfer(int dir, uint32_t cmd_index, uint32_t block_addr,
12891289 #endif /* !SDHCI_SDMA_DISABLED */
12901290 }
12911291 else {
1292- /* Blocking mode - buffer ready flag differs for read vs write */
1292+ /* PIO (Programmed I/O) mode — reads/writes data word-by-word via
1293+ * the SRS08 data port register.
1294+ *
1295+ * CAUTION: On Arasan SDHCI v3.0 (ZynqMP, Versal), multi-block PIO
1296+ * reads (CMD18) have a known race condition under compiler
1297+ * optimization (-Os/-O2). After reading one block, the BRR (Buffer
1298+ * Read Ready) flag in SRS12 may still be set from the previous
1299+ * block when the outer loop re-checks it. The optimized code
1300+ * re-polls so quickly that BRR has not yet auto-cleared, causing
1301+ * the next 512-byte read from SRS08 to return stale/partial data.
1302+ * This corrupts the loaded firmware image.
1303+ *
1304+ * Workaround: Set SDHCI_DMA_THRESHOLD low (default 4KB) so that
1305+ * multi-block reads use SDMA instead of this PIO path. The eMMC
1306+ * path manually clears BRR between blocks (W1C write below),
1307+ * which also avoids the race. */
12931308 uint32_t buf_ready_flag = (dir == SDHCI_DIR_READ ) ?
12941309 SDHCI_SRS12_BRR : SDHCI_SRS12_BWR ;
12951310
@@ -1531,15 +1546,21 @@ int sdhci_init(void)
15311546 }
15321547
15331548#ifdef DEBUG_SDHCI
1534- {
1535- const char * card_type ;
1536- #ifdef DISK_EMMC
1537- card_type = "eMMC" ;
1538- #else
1539- card_type = "SD" ;
1540- #endif
1541- wolfBoot_printf ("sdhci_init: %s status: %d\n" , card_type , status );
1549+ if (status == 0 ) {
1550+ wolfBoot_printf ("SDHCI: DMA (threshold: %dKB, buf boundary: %dKB)\n" ,
1551+ SDHCI_DMA_THRESHOLD / 1024 ,
1552+ (4 << ((SDHCI_DMA_BUFF_BOUNDARY >> 12 ) & 0x7 ))
1553+ );
15421554 }
1555+
1556+ wolfBoot_printf ("SDHCI: %s init, status %d\n" ,
1557+ #ifdef DISK_EMMC
1558+ "eMMC"
1559+ #else
1560+ "SD"
1561+ #endif
1562+ , status
1563+ );
15431564#endif
15441565
15451566 return status ;
0 commit comments