zynq7000_hal/
l2_cache.rs

1//! # L2 cache module
2use core::sync::atomic::compiler_fence;
3
4use arbitrary_int::{u2, u3};
5pub use zynq7000::l2_cache::LatencyConfig;
6use zynq7000::l2_cache::{
7    Associativity, AuxControl, Control, InterruptControl, MmioL2Cache, ReplacementPolicy, WaySize,
8};
9
10use crate::slcr::Slcr;
11
12/// This is the default configuration used by Xilinx/AMD.
13pub const AUX_CTRL_DEFAULT: AuxControl = AuxControl::builder()
14    .with_early_bresp_enable(true)
15    .with_isntruction_prefetch_enable(true)
16    .with_data_prefetch_enable(true)
17    .with_nonsec_interrupt_access_control(false)
18    .with_nonsec_lockdown_enable(false)
19    .with_cache_replace_policy(ReplacementPolicy::RoundRobin)
20    .with_force_write_alloc(u2::new(0))
21    .with_shared_attr_override(false)
22    .with_parity_enable(true)
23    .with_event_monitor_bus_enable(true)
24    .with_way_size(WaySize::_64kB)
25    .with_associativity(Associativity::_8Way)
26    .with_shared_attribute_invalidate(false)
27    .with_exclusive_cache_config(false)
28    .with_store_buff_device_limitation_enable(false)
29    .with_high_priority_so_dev_reads(false)
30    .with_full_line_zero_enable(false)
31    .build();
32
33/// Xilinx/AMD default configuration. 2 cycles for setup, write and read.
34pub const DEFAULT_TAG_RAM_LATENCY: LatencyConfig = LatencyConfig::builder()
35    .with_write_access_latency(u3::new(0b001))
36    .with_read_access_latency(u3::new(0b001))
37    .with_setup_latency(u3::new(0b001))
38    .build();
39
40/// Xilinx/AMD default configuration. 2 cycles for setup and write, 3 cycles for read.
41pub const DEFAULT_DATA_RAM_LATENCY: LatencyConfig = LatencyConfig::builder()
42    .with_write_access_latency(u3::new(0b001))
43    .with_read_access_latency(u3::new(0b010))
44    .with_setup_latency(u3::new(0b001))
45    .build();
46
47// SLCR L2C ram configuration.
48pub const SLCR_L2C_CONFIG_MAGIC_VALUE: u32 = 0x00020202;
49
50/// Similar to [init], but uses Xilinx/AMD defaults for the latency configurations.
51pub fn init_with_defaults(l2c_mmio: &mut MmioL2Cache<'static>) {
52    init(l2c_mmio, DEFAULT_TAG_RAM_LATENCY, DEFAULT_DATA_RAM_LATENCY);
53}
54
55/// Generic intializer function for the L2 cache.
56///
57/// This function is based on the initialization sequence specified in the TRM p.94 and on
58/// the runtime initialization provided by Xilinx/AMD.
59pub fn init(
60    l2c_mmio: &mut MmioL2Cache<'static>,
61    tag_ram_latency: LatencyConfig,
62    data_ram_latency: LatencyConfig,
63) {
64    l2c_mmio.write_control(Control::new_disabled());
65    l2c_mmio.write_aux_control(AUX_CTRL_DEFAULT);
66    l2c_mmio.write_tag_ram_latency(tag_ram_latency);
67    l2c_mmio.write_data_ram_latency(data_ram_latency);
68
69    // Invalidate the whole cache.
70    l2c_mmio.write_clean_invalidate_by_way(0xffff);
71    while l2c_mmio.read_cache_sync().busy() {}
72    compiler_fence(core::sync::atomic::Ordering::SeqCst);
73
74    let pending = l2c_mmio.read_interrupt_raw_status();
75    l2c_mmio.write_interrupt_clear(InterruptControl::new_with_raw_value(pending.raw_value()));
76    unsafe {
77        Slcr::with(|slcr| {
78            slcr.write_magic_l2c_register(SLCR_L2C_CONFIG_MAGIC_VALUE);
79        });
80    }
81    l2c_mmio.write_control(Control::new_enabled());
82}