Skip to main content

strat9_bus_drivers/
arm_integrator_lm.rs

1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const INTEGRATOR_SC_DEC_OFFSET: usize = 0x10;
5const INTEGRATOR_AP_EXP_BASE: u64 = 0xC000_0000;
6const INTEGRATOR_AP_EXP_STRIDE: u64 = 0x1000_0000;
7const NUM_SLOTS: usize = 4;
8
9const COMPATIBLE: &[&str] = &["arm,integrator-ap-lm"];
10
11pub struct ArmIntegratorLm {
12    syscon_regs: MmioRegion,
13    slots_present: [bool; NUM_SLOTS],
14    power_state: PowerState,
15}
16
17impl ArmIntegratorLm {
18    /// Creates a new instance.
19    pub fn new() -> Self {
20        Self {
21            syscon_regs: MmioRegion::new(),
22            slots_present: [false; NUM_SLOTS],
23            power_state: PowerState::Off,
24        }
25    }
26
27    /// Performs the detect modules operation.
28    fn detect_modules(&mut self) {
29        if !self.syscon_regs.is_valid() {
30            return;
31        }
32        let val = self.syscon_regs.read32(INTEGRATOR_SC_DEC_OFFSET);
33        for i in 0..NUM_SLOTS {
34            self.slots_present[i] = (val & (1 << (4 + i))) != 0;
35        }
36    }
37
38    /// Performs the slot base operation.
39    pub fn slot_base(slot: usize) -> u64 {
40        INTEGRATOR_AP_EXP_BASE + (slot as u64) * INTEGRATOR_AP_EXP_STRIDE
41    }
42
43    /// Returns whether slot present.
44    pub fn is_slot_present(&self, slot: usize) -> bool {
45        slot < NUM_SLOTS && self.slots_present[slot]
46    }
47}
48
49impl BusDriver for ArmIntegratorLm {
50    /// Performs the name operation.
51    fn name(&self) -> &str {
52        "arm-integrator-lm"
53    }
54
55    /// Performs the compatible operation.
56    fn compatible(&self) -> &[&str] {
57        COMPATIBLE
58    }
59
60    /// Performs the init operation.
61    fn init(&mut self, base: usize) -> Result<(), BusError> {
62        self.syscon_regs.init(base, 0x100);
63        self.detect_modules();
64        self.power_state = PowerState::On;
65        Ok(())
66    }
67
68    /// Performs the shutdown operation.
69    fn shutdown(&mut self) -> Result<(), BusError> {
70        self.power_state = PowerState::Off;
71        Ok(())
72    }
73
74    /// Reads reg.
75    fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
76        if !self.syscon_regs.is_valid() {
77            return Err(BusError::InitFailed);
78        }
79        self.syscon_regs.check_user_offset(offset)?;
80        Ok(self.syscon_regs.read32(offset))
81    }
82
83    /// Writes reg.
84    fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
85        if !self.syscon_regs.is_valid() {
86            return Err(BusError::InitFailed);
87        }
88        self.syscon_regs.check_user_offset(offset)?;
89        self.syscon_regs.write32(offset, value);
90        Ok(())
91    }
92
93    /// Performs the children operation.
94    fn children(&self) -> Vec<BusChild> {
95        let mut children = Vec::new();
96        for i in 0..NUM_SLOTS {
97            if self.slots_present[i] {
98                children.push(BusChild {
99                    name: alloc::format!("lm{}", i),
100                    base_addr: Self::slot_base(i),
101                    size: INTEGRATOR_AP_EXP_STRIDE,
102                });
103            }
104        }
105        children
106    }
107}