blob: 0e8a20f5dd00402371c18efd3398934364cbc20f [file]
// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0
//! AST10x0 data-cache maintenance.
use super::registers::ScuRegisters;
impl ScuRegisters {
/// Invalidate the entire AST10x0 data cache.
///
/// Toggles `DCACHE_CLEAN` (SCUA58 bit 1) low→high, mirroring the Zephyr
/// authority `cache_data_invd_all()` (`drivers/cache/cache_aspeed.c`, also
/// called after every crypto operation in `hace_aspeed.c:140`).
///
/// Required after any HACE DMA write into cacheable SRAM (below
/// `0x000A0000`): the engine's writes bypass the CPU cache, so the CPU
/// would read stale pre-operation cache lines without this invalidation.
#[inline]
pub fn dcache_invd_all(&self) {
const DCACHE_CLEAN: u32 = 1 << 1;
// SAFETY: SCU MMIO read-modify-write; DSB only orders memory accesses.
unsafe {
let ctrl = self.regs().scua58().read().bits();
self.regs().scua58().write(|w| w.bits(ctrl & !DCACHE_CLEAN));
core::arch::asm!("dsb sy", options(nostack, preserves_flags));
self.regs().scua58().write(|w| w.bits(ctrl | DCACHE_CLEAN));
core::arch::asm!("dsb sy", options(nostack, preserves_flags));
}
}
}
/// Thin free-function wrapper around [`ScuRegisters::dcache_invd_all`].
///
/// Exists solely so the function can be stored as a bare `fn()` pointer in
/// [`HaceDevice::cache_flush`], which is wired at construction by the board
/// crate. All SCU register access goes through [`ScuRegisters`].
pub fn dcache_invd_all() {
// SAFETY: singleton SCU; single-threaded HACE use is upheld by HaceDevice's
// single-instance contract.
unsafe { ScuRegisters::new_global() }.dcache_invd_all();
}