In U-Boot proper, enable_caches() runs from initr_caches(), before initr_dm() sets up driver model again, so it cannot find the L2 cache device and flush_dcache_all() never reaches L2. Without the I/O coherence port (IOCP), DMA masters do not snoop the CPU caches and can then read stale data from memory.
Call enable_caches() again from an EVT_DM_POST_INIT_R spy, unless SYS_DCACHE_OFF is set. In S-mode, U-Boot proper then drives the L2 controller itself, as the Linux ax45mp_cache driver does, and "dcache off" and "dcache on" turn L2 off and on. In M-mode U-Boot proper, L2 is now enabled, as enable_caches() intends. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Randolph Lin <[email protected]> --- arch/riscv/cpu/andes/cache.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/riscv/cpu/andes/cache.c b/arch/riscv/cpu/andes/cache.c index 30d766da8f9..9a1ca950e11 100644 --- a/arch/riscv/cpu/andes/cache.c +++ b/arch/riscv/cpu/andes/cache.c @@ -10,6 +10,7 @@ #include <cpu_func.h> #include <dm.h> #include <dm/uclass-internal.h> +#include <event.h> #include <asm/arch-andes/csr.h> #ifdef CONFIG_ANDES_L2_CACHE @@ -30,6 +31,20 @@ void enable_caches(void) } } +/* + * In U-Boot proper, enable_caches() runs before driver model is set up + * again after relocation and cannot find the L2 cache device. Run it + * again once driver model is ready. + */ +static int andes_l2_init_r(void) +{ + if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF)) + enable_caches(); + + return 0; +} +EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_R, andes_l2_init_r); + static void cache_ops(int (*ops)(struct udevice *dev)) { struct udevice *dev = NULL; -- 2.34.1
