1#![no_std]
5#![doc = include_str!("../README.md")]
6#![deny(clippy::undocumented_unsafe_blocks)]
7#![cfg_attr(docsrs, feature(doc_cfg))]
8
9#[cfg(all(feature = "base-revc", feature = "base-r"))]
10compile_error!("must only choose one of these Cargo features: `base-revc`; `base-r`");
11
12pub mod power_controller;
13pub mod system;
14
15#[cfg(feature = "base-revc")]
17pub use arm_cci;
18pub use arm_generic_timer;
19pub use arm_gic;
20pub use arm_pl011_uart;
21pub use arm_sp805;
22pub use arm_tzc;
23
24pub use safe_mmio::{PhysicalInstance, UniqueMmioPointer};
25
26#[cfg(feature = "base-revc")]
27use arm_cci::Cci5x0Registers;
28use arm_generic_timer::memory_mapped::{CntBase, CntControlBase, CntCtlBase, CntReadBase};
29use arm_gic::{
30 IntId,
31 gicv3::registers::{Gicd, GicrSgi},
32};
33use arm_pl011_uart::PL011Registers;
34use arm_sp805::SP805Registers;
35use arm_tzc::TzcRegisters;
36use core::{fmt::Debug, ops::RangeInclusive};
37use power_controller::FvpPowerControllerRegisters;
38use spin::mutex::Mutex;
39use system::FvpSystemRegisters;
40
41static PERIPHERALS_TAKEN: Mutex<bool> = Mutex::new(false);
42
43pub struct MemoryMap;
47
48#[allow(unused)]
49impl MemoryMap {
50 pub const TRUSTED_BOOT_ROM: RangeInclusive<usize> = flip(0x00_0000_0000..=0x00_03FF_FFFF);
51 pub const TRUSTED_SRAM: RangeInclusive<usize> = flip(0x00_0400_0000..=0x00_0407_FFFF);
52 pub const TRUSTED_DRAM: RangeInclusive<usize> = flip(0x00_0600_0000..=0x00_07FF_FFFF);
53 pub const NOR_FLASH0: RangeInclusive<usize> = flip(0x00_0800_0000..=0x00_0BFF_FFFF);
54 pub const NOR_FLASH1: RangeInclusive<usize> = flip(0x00_0C00_0000..=0x00_0FFF_FFFF);
55 pub const PSRAM: RangeInclusive<usize> = flip(0x00_1400_0000..=0x00_17FF_FFFF);
56 pub const VRAM: RangeInclusive<usize> = flip(0x00_1800_0000..=0x00_19FF_FFFF);
57 pub const ETHERNET: RangeInclusive<usize> = flip(0x00_1A00_0000..=0x00_1AFF_FFFF);
58 pub const USB: RangeInclusive<usize> = flip(0x00_1B00_0000..=0x00_1BFF_FFFF);
59 pub const VE_SYSTEM: RangeInclusive<usize> = flip(0x00_1C01_0000..=0x00_1C01_FFFF);
60 pub const SYSTEM_CONTROLLER: RangeInclusive<usize> = flip(0x00_1C02_0000..=0x00_1C02_FFFF);
61 pub const AACI: RangeInclusive<usize> = flip(0x00_1C04_0000..=0x00_1C04_FFFF);
62 pub const MCI: RangeInclusive<usize> = flip(0x00_1C05_0000..=0x00_1C05_FFFF);
63 pub const KMI_KEYBOARD: RangeInclusive<usize> = flip(0x00_1C06_0000..=0x00_1C06_FFFF);
64 pub const KMI_MOUSE: RangeInclusive<usize> = flip(0x00_1C07_0000..=0x00_1C07_FFFF);
65 pub const UART0: RangeInclusive<usize> = flip(0x00_1C09_0000..=0x00_1C09_FFFF);
66 pub const UART1: RangeInclusive<usize> = flip(0x00_1C0A_0000..=0x00_1C0A_FFFF);
67 pub const UART2: RangeInclusive<usize> = flip(0x00_1C0B_0000..=0x00_1C0B_FFFF);
68 pub const UART3: RangeInclusive<usize> = flip(0x00_1C0C_0000..=0x00_1C0C_FFFF);
69 pub const VFS2: RangeInclusive<usize> = flip(0x00_1C0D_0000..=0x00_1C0D_FFFF);
70 pub const WATCHDOG: RangeInclusive<usize> = flip(0x00_1C0F_0000..=0x00_1C0F_FFFF);
71 pub const POWER_CONTROLLER: RangeInclusive<usize> = flip(0x00_1C10_0000..=0x00_1C10_FFFF);
72 pub const DUAL_TIMER0: RangeInclusive<usize> = flip(0x00_1C11_0000..=0x00_1C11_FFFF);
73 pub const DUAL_TIMER1: RangeInclusive<usize> = flip(0x00_1C12_0000..=0x00_1C12_FFFF);
74 pub const VIRTIO_BLOCK_DEVICE: RangeInclusive<usize> = flip(0x00_1C13_0000..=0x00_1C13_FFFF);
75 pub const VIRTIO_PLAN9_DEVICE: RangeInclusive<usize> = flip(0x00_1C14_0000..=0x00_1C14_FFFF);
76 pub const VIRTIO_NET_DEVICE: RangeInclusive<usize> = flip(0x00_1C15_0000..=0x00_1C15_FFFF);
77 pub const RTC: RangeInclusive<usize> = flip(0x00_1C17_0000..=0x00_1C17_FFFF);
78 pub const CF_CARD: RangeInclusive<usize> = flip(0x00_1C1A_0000..=0x00_1C1A_FFFF);
79 pub const CLCD_CONTROLLER: RangeInclusive<usize> = flip(0x00_1C1F_0000..=0x00_1C1F_FFFF);
80 pub const VIRTIO_RNG: RangeInclusive<usize> = flip(0x00_1C20_0000..=0x00_1C20_FFFF);
81 pub const LS64_TESTING_FIFO: RangeInclusive<usize> = flip(0x00_1D00_0000..=0x00_1D00_FFFF);
82 pub const UTILITY_BUS: RangeInclusive<usize> = flip(0x00_1E00_0000..=0x00_1EFF_FFFF);
83 pub const NON_TRUSTED_ROM: RangeInclusive<usize> = flip(0x00_1F00_0000..=0x00_1F00_0FFF);
84 pub const CORESIGHT: RangeInclusive<usize> = flip(0x00_2000_0000..=0x00_27FF_FFFF);
85 #[cfg(feature = "base-revc")]
86 pub const CCI_550: RangeInclusive<usize> = flip(0x00_2A00_0000..=0x00_2A09_FFFF);
87 pub const REFCLK_CNTCONTROL: RangeInclusive<usize> = flip(0x00_2A43_0000..=0x00_2A43_FFFF);
88 pub const EL2_WATCHDOG_CONTROL: RangeInclusive<usize> = flip(0x00_2A44_0000..=0x00_2A44_FFFF);
89 pub const EL2_WATCHDOG_REFRESH: RangeInclusive<usize> = flip(0x00_2A45_0000..=0x00_2A45_FFFF);
90 pub const TRUSTED_WATCHDOG: RangeInclusive<usize> = flip(0x00_2A49_0000..=0x00_2A49_FFFF);
91 pub const TRUSTZONE_CONTROLLER: RangeInclusive<usize> = flip(0x00_2A4A_0000..=0x00_2A4A_FFFF);
92 pub const REFCLK_CNTREAD: RangeInclusive<usize> = flip(0x00_2A80_0000..=0x00_2A80_FFFF);
93 pub const AP_REFCLK_CNTCTL: RangeInclusive<usize> = flip(0x00_2A81_0000..=0x00_2A81_FFFF);
94 pub const AP_REFCLK_CNTBASE0: RangeInclusive<usize> = flip(0x00_2A82_0000..=0x00_2A82_FFFF);
95 pub const AP_REFCLK_CNTBASE1: RangeInclusive<usize> = flip(0x00_2A83_0000..=0x00_2A83_FFFF);
96 pub const DMC_400_CFG: RangeInclusive<usize> = flip(0x00_2B0A_0000..=0x00_2B0A_FFFF);
97 #[cfg(feature = "base-revc")]
98 pub const SMMUV3_AEM: RangeInclusive<usize> = flip(0x00_2B40_0000..=0x00_2B4F_FFFF);
99 #[cfg(feature = "base-revc")]
100 pub const DMA330X4: RangeInclusive<usize> = flip(0x00_2B50_0000..=0x00_2B5F_FFFF);
101 pub const GICC: RangeInclusive<usize> = flip(0x00_2C00_0000..=0x00_2C00_1FFF);
102 pub const GICH: RangeInclusive<usize> = flip(0x00_2C01_0000..=0x00_2C01_0FFF);
103 pub const GICV: RangeInclusive<usize> = flip(0x00_2C02_F000..=0x00_2C03_0FFF);
104 #[cfg(not(feature = "base-revc"))]
105 pub const CCI_400: RangeInclusive<usize> = flip(0x00_2C09_0000..=0x00_2C09_FFFF);
106 #[cfg(feature = "base-revc")]
107 pub const MALI_G76: RangeInclusive<usize> = flip(0x00_2D00_0000..=0x00_2DFF_0000);
108 pub const NON_TRUSTED_SRAM: RangeInclusive<usize> = flip(0x00_2E00_0000..=0x00_2E00_FFFF);
109 pub const GICD: RangeInclusive<usize> = flip(0x00_2F00_0000..=0x00_2F00_FFFF);
110 pub const GITS: RangeInclusive<usize> = flip(0x00_2F02_0000..=0x00_2F03_FFFF);
111 pub const GICR: RangeInclusive<usize> = flip(0x00_2F10_0000..=0x00_2F1F_FFFF);
112 #[cfg(feature = "base-revc")]
113 pub const PCIE_CONFIG_REGION: RangeInclusive<usize> = flip(0x00_4000_0000..=0x00_4FFF_FFFF);
114 #[cfg(feature = "base-revc")]
115 pub const PCIE_MEMORY_REGION1: RangeInclusive<usize> = flip(0x00_5000_0000..=0x00_5FFF_FFFF);
116 pub const TRUSTED_RNG: RangeInclusive<usize> = flip(0x00_7FE6_0000..=0x00_7FE6_0FFF);
117 pub const TRUSTED_NV_COUNTERS: RangeInclusive<usize> = flip(0x00_7FE7_0000..=0x00_7FE7_0FFF);
118 pub const TRUSTED_ROOT_KEY_STORAGE: RangeInclusive<usize> =
119 flip(0x00_7FE8_0000..=0x00_7FE8_0FFF);
120 pub const DDR3_PHY: RangeInclusive<usize> = flip(0x00_7FEF_0000..=0x00_7FEF_FFFF);
121 pub const HDLCD_CONTROLLER: RangeInclusive<usize> = flip(0x00_7FF6_0000..=0x00_7FF6_FFFF);
122 pub const DRAM0: RangeInclusive<usize> = flip(0x00_8000_0000..=0x00_FFFF_FFFF);
123 pub const DRAM1: RangeInclusive<usize> = flip(0x08_8000_0000..=0x0F_FFFF_FFFF);
124 #[cfg(feature = "base-revc")]
125 pub const PCIE_MEMORY_REGION2: RangeInclusive<usize> = flip(0x40_0000_0000..=0x7F_FFFF_FFFF);
126 pub const DRAM2: RangeInclusive<usize> = flip(0x88_0000_0000..=0xFF_FFFF_FFFF);
127 pub const DRAM3: RangeInclusive<usize> = flip(0x00_0880_0000_0000..=0x00_0FFF_FFFF_FFFF);
128 pub const DRAM4: RangeInclusive<usize> = flip(0x00_8800_0000_0000..=0x00_FFFF_FFFF_FFFF);
129 pub const DRAM5: RangeInclusive<usize> = flip(0x08_8000_0000_0000..=0x0F_FFFF_FFFF_FFFF);
130 pub const DRAM6: RangeInclusive<usize> = flip(0x88_0000_0000_0000..=0x8F_FFFF_FFFF_FFFF);
131}
132
133#[derive(Debug)]
135pub struct Peripherals {
136 pub system: PhysicalInstance<FvpSystemRegisters>,
137 pub uart0: PhysicalInstance<PL011Registers>,
138 pub uart1: PhysicalInstance<PL011Registers>,
139 pub uart2: PhysicalInstance<PL011Registers>,
140 pub uart3: PhysicalInstance<PL011Registers>,
141 pub watchdog: PhysicalInstance<SP805Registers>,
142 pub power_controller: PhysicalInstance<FvpPowerControllerRegisters>,
143 #[cfg(feature = "base-revc")]
145 pub cci_550: PhysicalInstance<Cci5x0Registers>,
146 pub refclk_cntcontrol: PhysicalInstance<CntControlBase>,
147 pub trusted_watchdog: PhysicalInstance<SP805Registers>,
148 pub trustzone_controller: PhysicalInstance<TzcRegisters>,
149 pub refclk_cntread: PhysicalInstance<CntReadBase>,
150 pub ap_refclk_cntctl: PhysicalInstance<CntCtlBase>,
151 pub ap_refclk_cntbase0: PhysicalInstance<CntBase>,
152 pub ap_refclk_cntbase1: PhysicalInstance<CntBase>,
153 pub gicd: PhysicalInstance<Gicd>,
154 pub gicr: PhysicalInstance<GicrSgi>,
155}
156
157impl Peripherals {
158 pub fn take() -> Option<Self> {
160 if !*PERIPHERALS_TAKEN.lock() {
161 Some(unsafe { Self::steal() })
163 } else {
164 None
165 }
166 }
167
168 pub unsafe fn steal() -> Self {
175 *PERIPHERALS_TAKEN.lock() = true;
176
177 unsafe {
179 Peripherals {
180 system: PhysicalInstance::new(*MemoryMap::VE_SYSTEM.start()),
181 uart0: PhysicalInstance::new(*MemoryMap::UART0.start()),
182 uart1: PhysicalInstance::new(*MemoryMap::UART1.start()),
183 uart2: PhysicalInstance::new(*MemoryMap::UART2.start()),
184 uart3: PhysicalInstance::new(*MemoryMap::UART3.start()),
185 watchdog: PhysicalInstance::new(*MemoryMap::WATCHDOG.start()),
186 power_controller: PhysicalInstance::new(*MemoryMap::POWER_CONTROLLER.start()),
187 #[cfg(feature = "base-revc")]
188 cci_550: PhysicalInstance::new(*MemoryMap::CCI_550.start()),
189 refclk_cntcontrol: PhysicalInstance::new(*MemoryMap::REFCLK_CNTCONTROL.start()),
190 trusted_watchdog: PhysicalInstance::new(*MemoryMap::TRUSTED_WATCHDOG.start()),
191 trustzone_controller: PhysicalInstance::new(
192 *MemoryMap::TRUSTZONE_CONTROLLER.start(),
193 ),
194 refclk_cntread: PhysicalInstance::new(*MemoryMap::REFCLK_CNTREAD.start()),
195 ap_refclk_cntctl: PhysicalInstance::new(*MemoryMap::AP_REFCLK_CNTCTL.start()),
196 ap_refclk_cntbase0: PhysicalInstance::new(*MemoryMap::AP_REFCLK_CNTBASE0.start()),
197 ap_refclk_cntbase1: PhysicalInstance::new(*MemoryMap::AP_REFCLK_CNTBASE1.start()),
198 gicd: PhysicalInstance::new(*MemoryMap::GICD.start()),
199 gicr: PhysicalInstance::new(*MemoryMap::GICR.start()),
200 }
201 }
202 }
203}
204
205#[cfg(feature = "base-revc")]
207pub struct Cci550Map;
208
209#[cfg(feature = "base-revc")]
210impl Cci550Map {
211 pub const CLUSTER0: usize = 5;
213 pub const CLUSTER1: usize = 6;
215}
216
217pub struct TzcFilter;
219
220impl TzcFilter {
221 pub const DEFAULT: usize = 0;
223 pub const LCD: usize = 2;
225}
226
227pub struct TzcNsaid;
229
230impl TzcNsaid {
231 pub const DEFAULT: usize = 0;
233 pub const APPLICATION_PROCESSORS: usize = 9;
235 pub const VIRTIO: usize = 8;
237 pub const PCI: usize = 1;
239 pub const CLCD: usize = 7;
241 pub const HDLCD0: usize = 2;
243}
244
245pub struct PrivatePeripheralInterrupts;
247
248impl PrivatePeripheralInterrupts {
249 pub const SECURE_HYPERVISOR_VIRTUAL_TIMER: IntId = IntId::ppi(3);
250 pub const SECURE_HYPERVISOR_PHYSICAL_TIMER: IntId = IntId::ppi(4);
251 pub const SPU: IntId = IntId::ppi(5);
252 pub const DCC_COMMS_CHANNEL: IntId = IntId::ppi(6);
253 pub const PMU_OVERFLOW: IntId = IntId::ppi(7);
254 pub const CTI: IntId = IntId::ppi(8);
255 pub const VIRTUAL_CPU_INTERFACE_MAINTENANCE: IntId = IntId::ppi(9);
256 pub const HYPERVISOR_TIMER: IntId = IntId::ppi(10);
257 pub const VIRTUAL_TIMER: IntId = IntId::ppi(11);
258 pub const HYPERVISOR_VIRTUAL_TIMER: IntId = IntId::ppi(12);
259 pub const SECURE_PHYSICAL_TIMER: IntId = IntId::ppi(13);
260 pub const NONSECURE_PHYSICAL_TIMER: IntId = IntId::ppi(14);
261 pub const TRBU: IntId = IntId::ppi(15);
262}
263
264pub struct SharedPeripheralInterrupts;
266
267impl SharedPeripheralInterrupts {
268 pub const WATCHDOG: IntId = IntId::spi(0);
269 pub const DUAL_TIMER0: IntId = IntId::spi(2);
270 pub const DUAL_TIMER1: IntId = IntId::spi(3);
271 pub const RTC: IntId = IntId::spi(4);
272 pub const UART0: IntId = IntId::spi(5);
273 pub const UART1: IntId = IntId::spi(6);
274 pub const UART2: IntId = IntId::spi(7);
275 pub const UART3: IntId = IntId::spi(8);
276 pub const MCIINTR0: IntId = IntId::spi(9);
277 pub const MCIINTR1: IntId = IntId::spi(10);
278 pub const AACI: IntId = IntId::spi(11);
279 pub const KMI_KEYBOARD: IntId = IntId::spi(12);
280 pub const KMI_MOUSE: IntId = IntId::spi(13);
281 pub const CLCD: IntId = IntId::spi(14);
282 pub const CLCD_CONTROLLER: IntId = Self::CLCD;
283 pub const ETHERNET: IntId = IntId::spi(15);
284 pub const TRUSTED_WATCHDOG: IntId = IntId::spi(24);
285 pub const CNTPSIRQ: IntId = IntId::spi(25);
286 pub const CNTPSIRQ1: IntId = IntId::spi(26);
287 pub const EL2_WATCHDOG_WS0: IntId = IntId::spi(27);
288 pub const EL2_WATCHDOG_WS1: IntId = IntId::spi(28);
289 pub const VIRTIO_BLOCK_DEVICE: IntId = IntId::spi(42);
290 pub const VIRTIO_PLAN9_DEVICE: IntId = IntId::spi(43);
291 pub const VIRTIO_NET_DEVICE: IntId = IntId::spi(44);
292 pub const VIRTIO_RNG: IntId = IntId::spi(46);
293 pub const TRUSTZONE_CONTROLLER: IntId = IntId::spi(48);
294 pub const PMUIRQ_CL0_CPU0: IntId = IntId::spi(60);
295 pub const PMUIRQ_CL0_CPU1: IntId = IntId::spi(61);
296 pub const PMUIRQ_CL0_CPU2: IntId = IntId::spi(62);
297 pub const PMUIRQ_CL0_CPU3: IntId = IntId::spi(63);
298 pub const PMUIRQ_CL1_CPU0: IntId = IntId::spi(64);
299 pub const PMUIRQ_CL1_CPU1: IntId = IntId::spi(65);
300 pub const PMUIRQ_CL1_CPU2: IntId = IntId::spi(66);
301 pub const PMUIRQ_CL1_CPU3: IntId = IntId::spi(67);
302 pub const HDLCD_CONTROLLER: IntId = IntId::spi(85);
303 pub const TRUSTED_RNG: IntId = IntId::spi(107);
304}
305
306#[cfg(feature = "base-revc")]
307impl SharedPeripheralInterrupts {
308 pub const SMMUV3_NONSECURE_COMBINED: IntId = IntId::spi(71);
309 pub const SMMUV3_SECURE_COMBINED: IntId = IntId::spi(72);
310 pub const SMMUV3_SECURE_EVENT_QUEUE: IntId = IntId::spi(73);
311 pub const SMMUV3_NONSECURE_EVENT_QUEUE: IntId = IntId::spi(74);
312 pub const SMMUV3_PRI_QUEUE: IntId = IntId::spi(75);
313 pub const SMMUV3_SECURE_COMMAND_QUEUE_SYNC: IntId = IntId::spi(76);
314 pub const SMMUV3_NONSECURE_COMMAND_QUEUE_SYNC: IntId = IntId::spi(77);
315 pub const SMMUV3_SECURE_GERROR: IntId = IntId::spi(78);
316 pub const SMMUV3_NONSECURE_GERROR: IntId = IntId::spi(79);
317 pub const MALI_G76_GPU: IntId = IntId::spi(160);
318 pub const MALI_G76_GPU_JOB: IntId = IntId::spi(161);
319 pub const MALI_G76_GPU_MMU: IntId = IntId::spi(162);
320 pub const PCIE_INTA: IntId = IntId::spi(168);
321 pub const PCIE_INTB: IntId = IntId::spi(169);
322 pub const PCIE_INTC: IntId = IntId::spi(170);
323 pub const PCIE_INTD: IntId = IntId::spi(171);
324 pub const PCIE_SERR: IntId = IntId::spi(175);
325}
326
327const fn flip(range: RangeInclusive<usize>) -> RangeInclusive<usize> {
331 const LIMIT_4GB: usize = 0x1_0000_0000;
332 #[cfg(feature = "base-r")]
333 const FLIP_BIT: usize = 0x8000_0000;
334 #[cfg(not(feature = "base-r"))]
335 const FLIP_BIT: usize = 0x0000_0000;
336
337 let mut start = *range.start();
338 let mut end = *range.end();
339 if start < LIMIT_4GB && end < LIMIT_4GB {
340 start ^= FLIP_BIT;
341 end ^= FLIP_BIT;
342 };
343 start..=end
344}