strat9_bus_drivers/
arm_cci.rs1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const CCI_PORT_CTRL: usize = 0x00;
5const CCI_CTRL_STATUS: usize = 0x0C;
6
7const CCI_ENABLE_SNOOP_REQ: u32 = 0x1;
8const CCI_ENABLE_DVM_REQ: u32 = 0x2;
9const CCI_ENABLE_REQ: u32 = CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ;
10
11const PORT_VALID_SHIFT: u32 = 31;
12const PORT_VALID: u32 = 1 << PORT_VALID_SHIFT;
13
14const MAX_PORTS: usize = 5;
15const MAX_POLL: u32 = 10000;
16
17const COMPATIBLE: &[&str] = &["arm,cci-400", "arm,cci-500", "arm,cci-550"];
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum CciPortType {
21 Ace,
22 AceLite,
23}
24
25#[derive(Clone)]
26pub struct CciPort {
27 pub port_type: CciPortType,
28 pub base_offset: usize,
29 pub enabled: bool,
30}
31
32pub struct ArmCci {
33 regs: MmioRegion,
34 ports: [Option<CciPort>; MAX_PORTS],
35 nb_ace: usize,
36 nb_ace_lite: usize,
37 power_state: PowerState,
38}
39
40impl ArmCci {
41 pub fn new() -> Self {
43 Self {
44 regs: MmioRegion::new(),
45 ports: [const { None }; MAX_PORTS],
46 nb_ace: 0,
47 nb_ace_lite: 0,
48 power_state: PowerState::Off,
49 }
50 }
51
52 pub fn set_port_counts(&mut self, ace: usize, ace_lite: usize) {
54 self.nb_ace = ace;
55 self.nb_ace_lite = ace_lite;
56 }
57
58 pub fn add_port(&mut self, index: usize, port_type: CciPortType, base_offset: usize) {
60 if index < MAX_PORTS {
61 self.ports[index] = Some(CciPort {
62 port_type,
63 base_offset,
64 enabled: false,
65 });
66 }
67 }
68
69 pub fn enable_port(&mut self, index: usize) -> Result<(), BusError> {
71 if index >= MAX_PORTS {
72 return Err(BusError::InvalidArgument);
73 }
74 let base_offset = self.ports[index]
75 .as_ref()
76 .ok_or(BusError::DeviceNotFound)?
77 .base_offset;
78 self.regs
79 .write32(base_offset + CCI_PORT_CTRL, CCI_ENABLE_REQ);
80 self.wait_for_status_clear()?;
81 let port = self.ports[index].as_mut().ok_or(BusError::DeviceNotFound)?;
82 port.enabled = true;
83 Ok(())
84 }
85
86 pub fn disable_port(&mut self, index: usize) -> Result<(), BusError> {
88 if index >= MAX_PORTS {
89 return Err(BusError::InvalidArgument);
90 }
91 let base_offset = self.ports[index]
92 .as_ref()
93 .ok_or(BusError::DeviceNotFound)?
94 .base_offset;
95 self.regs.write32(base_offset + CCI_PORT_CTRL, 0);
96 self.wait_for_status_clear()?;
97 let port = self.ports[index].as_mut().ok_or(BusError::DeviceNotFound)?;
98 port.enabled = false;
99 Ok(())
100 }
101
102 fn wait_for_status_clear(&self) -> Result<(), BusError> {
104 for _ in 0..MAX_POLL {
105 let status = self.regs.read32(CCI_CTRL_STATUS);
106 if status & 1 == 0 {
107 return Ok(());
108 }
109 }
110 Err(BusError::Timeout)
111 }
112}
113
114impl BusDriver for ArmCci {
115 fn name(&self) -> &str {
117 "arm-cci"
118 }
119
120 fn compatible(&self) -> &[&str] {
122 COMPATIBLE
123 }
124
125 fn init(&mut self, base: usize) -> Result<(), BusError> {
127 self.regs.init(base, 0x10000);
128 self.power_state = PowerState::On;
129 Ok(())
130 }
131
132 fn shutdown(&mut self) -> Result<(), BusError> {
134 for i in 0..MAX_PORTS {
135 if self.ports[i].as_ref().map_or(false, |p| p.enabled) {
136 let _ = self.disable_port(i);
137 }
138 }
139 self.power_state = PowerState::Off;
140 Ok(())
141 }
142
143 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
145 if !self.regs.is_valid() {
146 return Err(BusError::InitFailed);
147 }
148 Ok(self.regs.read32(offset))
149 }
150
151 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
153 if !self.regs.is_valid() {
154 return Err(BusError::InitFailed);
155 }
156 self.regs.write32(offset, value);
157 Ok(())
158 }
159
160 fn children(&self) -> Vec<BusChild> {
162 let mut children = Vec::new();
163 for (i, port) in self.ports.iter().enumerate() {
164 if let Some(p) = port {
165 let type_name = match p.port_type {
166 CciPortType::Ace => "ace",
167 CciPortType::AceLite => "ace-lite",
168 };
169 children.push(BusChild {
170 name: String::from(type_name),
171 base_addr: p.base_offset as u64,
172 size: 0x1000,
173 });
174 }
175 }
176 children
177 }
178}