strat9_bus_drivers/
vexpress_config.rs1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const SYS_MISC: usize = 0x00;
5const SYS_MISC_MASTERSITE: u32 = 1 << 14;
6
7const SYS_PROCID0: usize = 0x24;
8const SYS_PROCID1: usize = 0x28;
9const SYS_HBI_MASK: u32 = 0xFFF;
10
11const SYS_CFGDATA: usize = 0x40;
12const SYS_CFGCTRL: usize = 0x44;
13const SYS_CFGCTRL_START: u32 = 1 << 31;
14const SYS_CFGCTRL_WRITE: u32 = 1 << 30;
15const SYS_CFGSTAT: usize = 0x48;
16const SYS_CFGSTAT_ERR: u32 = 1 << 1;
17const SYS_CFGSTAT_COMPLETE: u32 = 1 << 0;
18
19const SITE_MB: u32 = 0;
20const SITE_DB1: u32 = 1;
21const SITE_DB2: u32 = 2;
22const SITE_MASTER: u32 = 0xF;
23
24const MAX_POLL_TRIES: u32 = 100;
25
26const COMPATIBLE: &[&str] = &["vexpress-syscfg"];
27
28fn cfg_ctrl_dcc(n: u32) -> u32 {
30 (n & 0xF) << 26
31}
32fn cfg_ctrl_func(n: u32) -> u32 {
34 (n & 0x3F) << 20
35}
36fn cfg_ctrl_site(n: u32) -> u32 {
38 (n & 0x3) << 16
39}
40fn cfg_ctrl_position(n: u32) -> u32 {
42 (n & 0xF) << 12
43}
44fn cfg_ctrl_device(n: u32) -> u32 {
46 n & 0xFFF
47}
48
49pub struct VexpressConfig {
50 regs: MmioRegion,
51 master_site: u32,
52 power_state: PowerState,
53}
54
55impl VexpressConfig {
56 pub fn new() -> Self {
58 Self {
59 regs: MmioRegion::new(),
60 master_site: SITE_MASTER,
61 power_state: PowerState::Off,
62 }
63 }
64
65 fn detect_master_site(&mut self) {
67 let misc = self.regs.read32(SYS_MISC);
68 self.master_site = if misc & SYS_MISC_MASTERSITE != 0 {
69 SITE_DB2
70 } else {
71 SITE_DB1
72 };
73 }
74
75 pub fn read_procid(&self, site: u32) -> u32 {
77 let offset = if site == SITE_DB1 {
78 SYS_PROCID0
79 } else {
80 SYS_PROCID1
81 };
82 self.regs.read32(offset)
83 }
84
85 pub fn hbi(&self) -> u32 {
87 let id = self.read_procid(self.master_site);
88 id & SYS_HBI_MASK
89 }
90
91 pub fn config_read(
93 &self,
94 site: u32,
95 position: u32,
96 dcc: u32,
97 function: u32,
98 device: u32,
99 ) -> Result<u32, BusError> {
100 let command = self.regs.read32(SYS_CFGCTRL);
101 if command & SYS_CFGCTRL_START != 0 {
102 return Err(BusError::Timeout);
103 }
104
105 let real_site = if site == SITE_MASTER {
106 self.master_site
107 } else {
108 site
109 };
110
111 let cmd = SYS_CFGCTRL_START
112 | cfg_ctrl_dcc(dcc)
113 | cfg_ctrl_site(real_site)
114 | cfg_ctrl_position(position)
115 | cfg_ctrl_func(function)
116 | cfg_ctrl_device(device);
117
118 self.regs.write32(SYS_CFGDATA, 0xDEAD_BEEF);
119 self.regs.write32(SYS_CFGSTAT, 0);
120 self.regs.write32(SYS_CFGCTRL, cmd);
121 crate::mmio::memory_barrier();
122
123 for _ in 0..MAX_POLL_TRIES {
124 let status = self.regs.read32(SYS_CFGSTAT);
125 if status & SYS_CFGSTAT_ERR != 0 {
126 return Err(BusError::IoError);
127 }
128 if status & SYS_CFGSTAT_COMPLETE != 0 {
129 return Ok(self.regs.read32(SYS_CFGDATA));
130 }
131 }
132
133 Err(BusError::Timeout)
134 }
135
136 pub fn config_write(
138 &self,
139 site: u32,
140 position: u32,
141 dcc: u32,
142 function: u32,
143 device: u32,
144 data: u32,
145 ) -> Result<(), BusError> {
146 let command = self.regs.read32(SYS_CFGCTRL);
147 if command & SYS_CFGCTRL_START != 0 {
148 return Err(BusError::Timeout);
149 }
150
151 let real_site = if site == SITE_MASTER {
152 self.master_site
153 } else {
154 site
155 };
156
157 let cmd = SYS_CFGCTRL_START
158 | SYS_CFGCTRL_WRITE
159 | cfg_ctrl_dcc(dcc)
160 | cfg_ctrl_site(real_site)
161 | cfg_ctrl_position(position)
162 | cfg_ctrl_func(function)
163 | cfg_ctrl_device(device);
164
165 self.regs.write32(SYS_CFGDATA, data);
166 self.regs.write32(SYS_CFGSTAT, 0);
167 self.regs.write32(SYS_CFGCTRL, cmd);
168 crate::mmio::memory_barrier();
169
170 for _ in 0..MAX_POLL_TRIES {
171 let status = self.regs.read32(SYS_CFGSTAT);
172 if status & SYS_CFGSTAT_ERR != 0 {
173 return Err(BusError::IoError);
174 }
175 if status & SYS_CFGSTAT_COMPLETE != 0 {
176 return Ok(());
177 }
178 }
179
180 Err(BusError::Timeout)
181 }
182}
183
184impl BusDriver for VexpressConfig {
185 fn name(&self) -> &str {
187 "vexpress-config"
188 }
189
190 fn compatible(&self) -> &[&str] {
192 COMPATIBLE
193 }
194
195 fn init(&mut self, base: usize) -> Result<(), BusError> {
197 self.regs.init(base, 0x100);
198 self.detect_master_site();
199 self.power_state = PowerState::On;
200 Ok(())
201 }
202
203 fn shutdown(&mut self) -> Result<(), BusError> {
205 self.power_state = PowerState::Off;
206 Ok(())
207 }
208
209 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
211 if !self.regs.is_valid() {
212 return Err(BusError::InitFailed);
213 }
214 Ok(self.regs.read32(offset))
215 }
216
217 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
219 if !self.regs.is_valid() {
220 return Err(BusError::InitFailed);
221 }
222 self.regs.write32(offset, value);
223 Ok(())
224 }
225}