strat9_bus_drivers/
stm32_rifsc.rs1use crate::{
2 BusChild, BusDriver, BusError, PowerState,
3 mmio::MmioRegion,
4 stm32_firewall::{FirewallController, FirewallType},
5};
6use alloc::{string::String, vec::Vec};
7
8const RIFSC_RISC_SECCFGR0: usize = 0x10;
9const RIFSC_RISC_PRIVCFGR0: usize = 0x30;
10const RIFSC_RISC_PER0_CIDCFGR: usize = 0x100;
11const RIFSC_RISC_PER0_SEMCR: usize = 0x104;
12const RIFSC_RISC_HWCFGR2: usize = 0xFEC;
13
14const CIDCFGR_STRIDE: usize = 0x08;
15const CIDCFGR_CFEN: u32 = 1 << 0;
16const CIDCFGR_SEMEN: u32 = 1 << 1;
17const CIDCFGR_SEMWL_MASK: u32 = 0xFF << 16;
18const CIDCFGR_SCID_MASK: u32 = 0x7 << 4;
19const CIDCFGR_SCID_SHIFT: u32 = 4;
20
21const SEMCR_MUTEX: u32 = 1 << 0;
22
23const HWCFGR2_CONF1_MASK: u32 = 0xFFFF;
24const HWCFGR2_CONF2_MASK: u32 = 0xFF << 16;
25const HWCFGR2_CONF2_SHIFT: u32 = 16;
26const HWCFGR2_CONF3_MASK: u32 = 0xFF << 24;
27const HWCFGR2_CONF3_SHIFT: u32 = 24;
28
29const EXPECTED_CID: u32 = 1;
30
31const COMPATIBLE: &[&str] = &["st,stm32mp25-rifsc", "st,stm32mp21-rifsc"];
32
33pub struct Stm32Rifsc {
34 regs: MmioRegion,
35 nb_risup: u32,
36 nb_rimu: u32,
37 nb_risal: u32,
38 power_state: PowerState,
39 children: Vec<BusChild>,
40}
41
42impl Stm32Rifsc {
43 pub fn new() -> Self {
45 Self {
46 regs: MmioRegion::new(),
47 nb_risup: 0,
48 nb_rimu: 0,
49 nb_risal: 0,
50 power_state: PowerState::Off,
51 children: Vec::new(),
52 }
53 }
54
55 fn read_hwcfg(&mut self) {
57 let hwcfg = self.regs.read32(RIFSC_RISC_HWCFGR2);
58 self.nb_risup = hwcfg & HWCFGR2_CONF1_MASK;
59 self.nb_rimu = (hwcfg & HWCFGR2_CONF2_MASK) >> HWCFGR2_CONF2_SHIFT;
60 self.nb_risal = (hwcfg & HWCFGR2_CONF3_MASK) >> HWCFGR2_CONF3_SHIFT;
61 }
62
63 fn is_secure(&self, id: u32) -> bool {
65 let reg_idx = id / 32;
66 let bit = id % 32;
67 let val = self
68 .regs
69 .read32(RIFSC_RISC_SECCFGR0 + (reg_idx as usize) * 4);
70 (val & (1 << bit)) != 0
71 }
72
73 fn is_privileged(&self, id: u32) -> bool {
75 let reg_idx = id / 32;
76 let bit = id % 32;
77 let val = self
78 .regs
79 .read32(RIFSC_RISC_PRIVCFGR0 + (reg_idx as usize) * 4);
80 (val & (1 << bit)) != 0
81 }
82
83 fn cidcfgr_offset(id: u32) -> usize {
85 RIFSC_RISC_PER0_CIDCFGR + (id as usize) * CIDCFGR_STRIDE
86 }
87
88 fn semcr_offset(id: u32) -> usize {
90 RIFSC_RISC_PER0_SEMCR + (id as usize) * CIDCFGR_STRIDE
91 }
92
93 fn acquire_semaphore(&self, id: u32) -> Result<(), BusError> {
95 let offset = Self::semcr_offset(id);
96 self.regs.write32(offset, SEMCR_MUTEX);
97 let val = self.regs.read32(offset);
98 if val & SEMCR_MUTEX != 0 {
99 Ok(())
100 } else {
101 Err(BusError::PermissionDenied)
102 }
103 }
104
105 fn release_semaphore(&self, id: u32) {
107 let offset = Self::semcr_offset(id);
108 self.regs.write32(offset, 0);
109 }
110
111 pub fn add_child(&mut self, child: BusChild) {
113 self.children.push(child);
114 }
115}
116
117impl FirewallController for Stm32Rifsc {
118 fn name(&self) -> &str {
120 "stm32-rifsc"
121 }
122
123 fn firewall_type(&self) -> FirewallType {
125 FirewallType::Peripheral
126 }
127
128 fn max_entries(&self) -> u32 {
130 self.nb_risup
131 }
132
133 fn grant_access(&self, firewall_id: u32) -> Result<(), BusError> {
135 if firewall_id >= self.nb_risup {
136 return Err(BusError::InvalidArgument);
137 }
138
139 if self.is_secure(firewall_id) {
140 return Err(BusError::PermissionDenied);
141 }
142
143 let cidcfgr = self.regs.read32(Self::cidcfgr_offset(firewall_id));
144
145 if cidcfgr & CIDCFGR_CFEN != 0 {
146 let scid = (cidcfgr & CIDCFGR_SCID_MASK) >> CIDCFGR_SCID_SHIFT;
147
148 if cidcfgr & CIDCFGR_SEMEN != 0 {
149 let semwl = (cidcfgr & CIDCFGR_SEMWL_MASK) >> 16;
150 if semwl & (1 << EXPECTED_CID) == 0 {
151 return Err(BusError::PermissionDenied);
152 }
153 return self.acquire_semaphore(firewall_id);
154 }
155
156 if scid != EXPECTED_CID {
157 return Err(BusError::PermissionDenied);
158 }
159 }
160
161 Ok(())
162 }
163
164 fn release_access(&self, firewall_id: u32) -> Result<(), BusError> {
166 if firewall_id >= self.nb_risup {
167 return Err(BusError::InvalidArgument);
168 }
169
170 let cidcfgr = self.regs.read32(Self::cidcfgr_offset(firewall_id));
171 if cidcfgr & CIDCFGR_CFEN != 0 && cidcfgr & CIDCFGR_SEMEN != 0 {
172 self.release_semaphore(firewall_id);
173 }
174
175 Ok(())
176 }
177}
178
179impl BusDriver for Stm32Rifsc {
180 fn name(&self) -> &str {
182 "stm32-rifsc"
183 }
184
185 fn compatible(&self) -> &[&str] {
187 COMPATIBLE
188 }
189
190 fn init(&mut self, base: usize) -> Result<(), BusError> {
192 self.regs.init(base, 0x1000);
193 self.read_hwcfg();
194 self.power_state = PowerState::On;
195 Ok(())
196 }
197
198 fn shutdown(&mut self) -> Result<(), BusError> {
200 self.power_state = PowerState::Off;
201 Ok(())
202 }
203
204 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
206 if !self.regs.is_valid() {
207 return Err(BusError::InitFailed);
208 }
209 Ok(self.regs.read32(offset))
210 }
211
212 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
214 if !self.regs.is_valid() {
215 return Err(BusError::InitFailed);
216 }
217 self.regs.write32(offset, value);
218 Ok(())
219 }
220
221 fn children(&self) -> Vec<BusChild> {
223 self.children.clone()
224 }
225}