strat9_bus_drivers/
arm_integrator_lm.rs1use 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 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 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 pub fn slot_base(slot: usize) -> u64 {
40 INTEGRATOR_AP_EXP_BASE + (slot as u64) * INTEGRATOR_AP_EXP_STRIDE
41 }
42
43 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 fn name(&self) -> &str {
52 "arm-integrator-lm"
53 }
54
55 fn compatible(&self) -> &[&str] {
57 COMPATIBLE
58 }
59
60 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 fn shutdown(&mut self) -> Result<(), BusError> {
70 self.power_state = PowerState::Off;
71 Ok(())
72 }
73
74 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 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 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}