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        Ok(self.syscon_regs.read32(offset))
80    }
81
82    /// Writes reg.
83    fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
84        if !self.syscon_regs.is_valid() {
85            return Err(BusError::InitFailed);
86        }
87        self.syscon_regs.write32(offset, value);
88        Ok(())
89    }
90
91    /// Performs the children operation.
92    fn children(&self) -> Vec<BusChild> {
93        let mut children = Vec::new();
94        for i in 0..NUM_SLOTS {
95            if self.slots_present[i] {
96                children.push(BusChild {
97                    name: alloc::format!("lm{}", i),
98                    base_addr: Self::slot_base(i),
99                    size: INTEGRATOR_AP_EXP_STRIDE,
100                });
101            }
102        }
103        children
104    }
105}