@@ -1596,6 +1596,24 @@ void hal_prepare_boot(void)
15961596 mDev .qnx = NULL ;
15971597 }
15981598#endif
1599+
1600+ /* Clean and invalidate caches for the loaded application.
1601+ * The application was written to RAM via D-cache, but the CPU will
1602+ * fetch instructions via I-cache from main memory. We must:
1603+ * 1. Clean D-cache (flush dirty data to memory)
1604+ * 2. Invalidate I-cache (ensure fresh instruction fetch) */
1605+ __asm__ volatile ("dsb sy" );
1606+ {
1607+ uintptr_t addr ;
1608+ uintptr_t end = WOLFBOOT_LOAD_ADDRESS + APP_CACHE_FLUSH_SIZE ;
1609+ for (addr = WOLFBOOT_LOAD_ADDRESS ; addr < end ; addr += CACHE_LINE_SIZE ) {
1610+ __asm__ volatile ("dc cvac, %0" : : "r" (addr ));
1611+ }
1612+ }
1613+ __asm__ volatile ("dsb sy" );
1614+ __asm__ volatile ("ic iallu" );
1615+ __asm__ volatile ("dsb sy" );
1616+ __asm__ volatile ("isb" );
15991617}
16001618
16011619/* Flash functions must be relocated to RAM for execution */
@@ -1866,6 +1884,16 @@ static int test_ext_flash(QspiDev_t* dev)
18661884
18671885#define CADENCE_SRS_OFFSET 0x200
18681886
1887+ /* Legacy SDMA system address register (standard SDHCI offset 0x00).
1888+ * The Arasan SDHCI v3.0 on ZynqMP does not support Host Version 4 Enable
1889+ * (HV4E) mode. The generic SDHCI driver uses HV4E-style 64-bit DMA
1890+ * addressing via SRS22/SRS23 (offsets 0x58/0x5C), but on this controller
1891+ * we must use the legacy SRS00 register (offset 0x00) for SDMA addresses.
1892+ * The platform reg_read/reg_write functions transparently redirect
1893+ * SRS22 <-> SRS00, making legacy SDMA work without changes to sdhci.c. */
1894+ #define STD_SDHCI_SDMA_ADDR 0x00 /* SDMA System Address (32-bit) */
1895+ #define STD_SDHCI_HOST_CTRL2 0x3C /* Auto CMD Err(16) + Host Ctrl 2(16) */
1896+
18691897/* Standard SDHCI register offsets (byte addresses within the controller) */
18701898#define STD_SDHCI_HOST_CTRL1 0x28 /* Host Control 1 (8-bit) */
18711899#define STD_SDHCI_POWER_CTRL 0x29 /* Power Control (8-bit) */
@@ -1939,8 +1967,25 @@ uint32_t sdhci_reg_read(uint32_t offset)
19391967
19401968 /* Cadence SRS registers (0x200+) -> standard SDHCI (subtract 0x200) */
19411969 if (offset >= CADENCE_SRS_OFFSET ) {
1942- /* 32-bit reads work for all SDHCI registers */
1943- return * ((volatile uint32_t * )(base + offset - CADENCE_SRS_OFFSET ));
1970+ uint32_t std_off = offset - CADENCE_SRS_OFFSET ;
1971+
1972+ /* SRS22 (0x58) -> SRS00 (0x00): Legacy SDMA address register */
1973+ if (std_off == 0x58 ) {
1974+ return * ((volatile uint32_t * )(base + STD_SDHCI_SDMA_ADDR ));
1975+ }
1976+ /* SRS23 (0x5C) -> 0: No 64-bit addressing on SDHCI v3.0 */
1977+ if (std_off == 0x5C ) {
1978+ return 0 ;
1979+ }
1980+
1981+ {
1982+ uint32_t val = * ((volatile uint32_t * )(base + std_off ));
1983+ /* Mask out A64S from Capabilities to prevent HV4E init */
1984+ if (std_off == 0x40 ) { /* SRS16 - Capabilities */
1985+ val &= ~SDHCI_SRS16_A64S ;
1986+ }
1987+ return val ;
1988+ }
19441989 }
19451990 /* Cadence HRS registers (0x000-0x1FF) -> translate to standard equivalents */
19461991 return zynqmp_sdhci_hrs_read (offset );
@@ -1984,6 +2029,27 @@ void sdhci_reg_write(uint32_t offset, uint32_t val)
19842029 return ;
19852030 }
19862031
2032+ /* SRS22 (0x58) -> SRS00 (0x00): Legacy SDMA address register.
2033+ * The generic driver writes the DMA buffer address here for HV4E mode.
2034+ * Redirect to SRS00 which is the legacy SDMA system address register.
2035+ * Writing SRS00 also restarts DMA after a boundary interrupt. */
2036+ if (std_off == 0x58 ) {
2037+ * ((volatile uint32_t * )(base + STD_SDHCI_SDMA_ADDR )) = val ;
2038+ return ;
2039+ }
2040+ /* SRS23 (0x5C) -> no-op: No 64-bit addressing on SDHCI v3.0 */
2041+ if (std_off == 0x5C ) {
2042+ return ;
2043+ }
2044+
2045+ /* SRS15 (0x3C) -> mask out HV4E and A64 bits.
2046+ * The generic driver enables HV4E for SDMA, but the Arasan SDHCI v3.0
2047+ * does not support it. These are reserved bits on v3.0 and must not
2048+ * be set. */
2049+ if (std_off == STD_SDHCI_HOST_CTRL2 ) {
2050+ val &= ~(SDHCI_SRS15_HV4E | SDHCI_SRS15_A64 );
2051+ }
2052+
19872053 /* All other SRS registers: 32-bit write */
19882054 * ((volatile uint32_t * )(base + std_off )) = val ;
19892055 return ;
@@ -2010,22 +2076,35 @@ void sdhci_platform_init(void)
20102076{
20112077 uint32_t reg ;
20122078 volatile int i ;
2079+ uint32_t slot_mask ;
2080+ uint32_t slot_shift ;
2081+ uint32_t reset_bit ;
20132082
2014- /* Set SD1 slot type to "Embedded Slot for One Device" (01).
2083+ /* Set the selected SDx slot type to "Embedded Slot for One Device" (01).
20152084 * This feeds into the SDHCI Capabilities register bits 31:30 and makes
20162085 * the controller report card as always present, bypassing the physical
20172086 * CD pin that is not connected to the SDHCI controller on ZCU102. */
2087+ if (ZYNQMP_SDHCI_BASE == ZYNQMP_SD0_BASE ) {
2088+ slot_mask = SD_CONFIG_REG2_SD0_SLOTTYPE_MASK ;
2089+ slot_shift = SD_CONFIG_REG2_SD0_SLOTTYPE_SHIFT ;
2090+ reset_bit = RST_LPD_IOU2_SDIO0 ;
2091+ } else {
2092+ slot_mask = SD_CONFIG_REG2_SD1_SLOTTYPE_MASK ;
2093+ slot_shift = SD_CONFIG_REG2_SD1_SLOTTYPE_SHIFT ;
2094+ reset_bit = RST_LPD_IOU2_SDIO1 ;
2095+ }
2096+
20182097 reg = IOU_SLCR_SD_CONFIG_REG2 ;
2019- reg &= ~SD_CONFIG_REG2_SD1_SLOTTYPE_MASK ;
2020- reg |= (1UL << SD_CONFIG_REG2_SD1_SLOTTYPE_SHIFT ); /* 01 = Embedded */
2098+ reg &= ~slot_mask ;
2099+ reg |= (1UL << slot_shift ); /* 01 = Embedded */
20212100 IOU_SLCR_SD_CONFIG_REG2 = reg ;
20222101
20232102 /* The SDHCI Capabilities register latches IOU_SLCR values on controller
2024- * reset. Issue SDIO1 reset via CRL_APB so the controller picks up the
2103+ * reset. Issue SDIOx reset via CRL_APB so the controller picks up the
20252104 * new slot type configuration. */
2026- RST_LPD_IOU2 |= RST_LPD_IOU2_SDIO1 ; /* Assert SDIO1 reset */
2105+ RST_LPD_IOU2 |= reset_bit ; /* Assert SDIOx reset */
20272106 for (i = 0 ; i < 100 ; i ++ ) {} /* Brief delay */
2028- RST_LPD_IOU2 &= ~RST_LPD_IOU2_SDIO1 ; /* De-assert SDIO1 reset */
2107+ RST_LPD_IOU2 &= ~reset_bit ; /* De-assert SDIOx reset */
20292108 for (i = 0 ; i < 1000 ; i ++ ) {} /* Wait for controller ready */
20302109
20312110#ifdef DEBUG_SDHCI
@@ -2068,6 +2147,45 @@ void sdhci_platform_set_bus_mode(int is_emmc)
20682147 wolfBoot_printf ("sdhci_platform_set_bus_mode: is_emmc=%d\n" , is_emmc );
20692148#endif
20702149}
2150+
2151+ /* DMA cache maintenance - called from sdhci_transfer() around SDMA operations.
2152+ * The SDMA engine transfers data directly to/from physical memory, bypassing
2153+ * the CPU's L1/L2 caches. We must ensure cache coherency:
2154+ * - Before DMA write (card←memory): clean D-cache so DMA reads correct data
2155+ * - After DMA read (card→memory): invalidate D-cache so CPU sees new data */
2156+ void sdhci_platform_dma_prepare (void * buf , uint32_t sz , int is_write )
2157+ {
2158+ uintptr_t addr ;
2159+ uintptr_t start = (uintptr_t )buf & ~(CACHE_LINE_SIZE - 1 );
2160+ uintptr_t end = (uintptr_t )buf + sz ;
2161+
2162+ if (is_write ) {
2163+ /* Clean D-cache: flush dirty lines to memory for DMA to read */
2164+ for (addr = start ; addr < end ; addr += CACHE_LINE_SIZE ) {
2165+ __asm__ volatile ("dc cvac, %0" : : "r" (addr ) : "memory" );
2166+ }
2167+ } else {
2168+ /* Invalidate D-cache: discard stale lines before DMA writes to memory */
2169+ for (addr = start ; addr < end ; addr += CACHE_LINE_SIZE ) {
2170+ __asm__ volatile ("dc civac, %0" : : "r" (addr ) : "memory" );
2171+ }
2172+ }
2173+ __asm__ volatile ("dsb sy" : : : "memory" );
2174+ }
2175+
2176+ void sdhci_platform_dma_complete (void * buf , uint32_t sz , int is_write )
2177+ {
2178+ (void )is_write ;
2179+ /* After DMA: clean and invalidate to ensure CPU sees DMA-written data */
2180+ uintptr_t addr ;
2181+ uintptr_t start = (uintptr_t )buf & ~(CACHE_LINE_SIZE - 1 );
2182+ uintptr_t end = (uintptr_t )buf + sz ;
2183+
2184+ for (addr = start ; addr < end ; addr += CACHE_LINE_SIZE ) {
2185+ __asm__ volatile ("dc civac, %0" : : "r" (addr ) : "memory" );
2186+ }
2187+ __asm__ volatile ("dsb sy" : : : "memory" );
2188+ }
20712189#endif /* DISK_SDCARD || DISK_EMMC */
20722190
20732191
0 commit comments