blob: 6c9551d078fc05eaf352170edcfd5f3f37d0cdb5 [file] [log] [blame]
Imre Kis55661632025-03-14 15:25:40 +01001// SPDX-FileCopyrightText: Copyright 2023-2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
Imre Kis9c084c02024-08-14 15:53:45 +02002// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! # Peripheral Access Crate fro Arm Fixed Virtual Platform
5//!
6//! The crate provides access to the peripherals of [Arm Fixed Virtual Platform](https://developer.arm.com/Tools%20and%20Software/Fixed%20Virtual%20Platforms).
7
8#![no_std]
9
Imre Kis55661632025-03-14 15:25:40 +010010// Re-export peripheral drivers and common safe-mmio types
11pub use arm_gic;
12pub use arm_pl011_uart;
13pub use arm_sp805;
14pub use safe_mmio::{PhysicalInstance, UniqueMmioPointer};
Tomás González52cb4a62025-03-19 18:41:00 +000015pub mod power_controller;
Imre Kis9c084c02024-08-14 15:53:45 +020016
Imre Kis9c084c02024-08-14 15:53:45 +020017use arm_gic::GICDRegisters;
Balint Dobszay4292ed42025-01-09 13:52:32 +010018use arm_pl011_uart::PL011Registers;
Imre Kis9c084c02024-08-14 15:53:45 +020019use arm_sp805::SP805Registers;
Imre Kis58d74c42025-03-24 17:33:15 +010020use core::{fmt::Debug, ops::RangeInclusive};
Tomás González52cb4a62025-03-19 18:41:00 +000021use power_controller::FvpPowerControllerRegisters;
Andrew Walbran1a289d12025-02-11 14:55:39 +000022use spin::mutex::Mutex;
Imre Kis9c084c02024-08-14 15:53:45 +020023
24static PERIPHERALS_TAKEN: Mutex<bool> = Mutex::new(false);
25
Imre Kis58d74c42025-03-24 17:33:15 +010026/// Memory map based on 'Table 6-5: Base Platform memory map' of 'Fast Models Version 11.28
27/// Reference Guide'. The ranges for normal memory regions are public, however the peripheral
28/// regions are private and they should be accessed through the `Peripherals` structure.
29pub struct MemoryMap;
30
31#[allow(unused)]
32impl MemoryMap {
33 pub const TRUSTED_BOOT_ROM: RangeInclusive<usize> = 0x00_0000_0000..=0x00_03FF_FFFF;
34 pub const TRUSTED_SRAM: RangeInclusive<usize> = 0x00_0400_0000..=0x00_0407_FFFF;
35 pub const TRUSTED_DRAM: RangeInclusive<usize> = 0x00_0600_0000..=0x00_07FF_FFFF;
36 pub const NOR_FLASH0: RangeInclusive<usize> = 0x00_0800_0000..=0x00_0BFF_FFFF;
37 pub const NOR_FLASH1: RangeInclusive<usize> = 0x00_0C00_0000..=0x00_0FFF_FFFF;
38 pub const PSRAM: RangeInclusive<usize> = 0x00_1400_0000..=0x00_17FF_FFFF;
39 pub const VRAM: RangeInclusive<usize> = 0x00_1800_0000..=0x00_19FF_FFFF;
40 const ETHERNET: RangeInclusive<usize> = 0x00_1A00_0000..=0x00_1AFF_FFFF;
41 const USB: RangeInclusive<usize> = 0x00_1B00_0000..=0x00_1BFF_FFFF;
42 const VE_SYSTEM: RangeInclusive<usize> = 0x00_1C01_0000..=0x00_1C01_FFFF;
43 const SYSTEM_CONTROLLER: RangeInclusive<usize> = 0x00_1C02_0000..=0x00_1C02_FFFF;
44 const AACI: RangeInclusive<usize> = 0x00_1C04_0000..=0x00_1C04_FFFF;
45 const MCI: RangeInclusive<usize> = 0x00_1C05_0000..=0x00_1C05_FFFF;
46 const KMI_KEYBOARD: RangeInclusive<usize> = 0x00_1C06_0000..=0x00_1C06_FFFF;
47 const KMI_MOUSE: RangeInclusive<usize> = 0x00_1C07_0000..=0x00_1C07_FFFF;
48 const UART0: RangeInclusive<usize> = 0x00_1C09_0000..=0x00_1C09_FFFF;
49 const UART1: RangeInclusive<usize> = 0x00_1C0A_0000..=0x00_1C0A_FFFF;
50 const UART2: RangeInclusive<usize> = 0x00_1C0B_0000..=0x00_1C0B_FFFF;
51 const UART3: RangeInclusive<usize> = 0x00_1C0C_0000..=0x00_1C0C_FFFF;
52 const VFS2: RangeInclusive<usize> = 0x00_1C0D_0000..=0x00_1C0D_FFFF;
53 const WATCHDOG: RangeInclusive<usize> = 0x00_1C0F_0000..=0x00_1C0F_FFFF;
54 const POWER_CONTROLLER: RangeInclusive<usize> = 0x00_1C10_0000..=0x00_1C10_FFFF;
55 const DUAL_TIMER0: RangeInclusive<usize> = 0x00_1C11_0000..=0x00_1C11_FFFF;
56 const DUAL_TIEMR1: RangeInclusive<usize> = 0x00_1C12_0000..=0x00_1C12_FFFF;
57 const VIRTIO_BLOCK_DEVICE: RangeInclusive<usize> = 0x00_1C13_0000..=0x00_1C13_FFFF;
58 const VIRTIO_PLAN9_DEVICE: RangeInclusive<usize> = 0x00_1C14_0000..=0x00_1C14_FFFF;
59 const VIRTIO_NET_DEVICE: RangeInclusive<usize> = 0x00_1C15_0000..=0x00_1C15_FFFF;
60 const RTC: RangeInclusive<usize> = 0x00_1C17_0000..=0x00_1C17_FFFF;
61 const CF_CARD: RangeInclusive<usize> = 0x00_1C1A_0000..=0x00_1C1A_FFFF;
62 const CLCD_CONTROLLER: RangeInclusive<usize> = 0x00_1C1F_0000..=0x00_1C1F_FFFF;
63 const VIRTIO_RNG: RangeInclusive<usize> = 0x00_1C20_0000..=0x00_1C20_FFFF;
64 const LS64_TESTING_FIFO: RangeInclusive<usize> = 0x00_1D00_0000..=0x00_1D00_FFFF;
65 const UTILITY_BUS: RangeInclusive<usize> = 0x00_1E00_0000..=0x00_1EFF_FFFF;
66 pub const NON_TRUSTED_ROM: RangeInclusive<usize> = 0x00_1F00_0000..=0x00_1F00_0FFF;
67 const CORESIGHT: RangeInclusive<usize> = 0x00_2000_0000..=0x00_27FF_FFFF;
68 const REFCLK_CNTCONTROL: RangeInclusive<usize> = 0x00_2A43_0000..=0x00_2A43_FFFF;
69 const EL2_WATCHDOG_CONTROL: RangeInclusive<usize> = 0x00_2A44_0000..=0x00_2A44_FFFF;
70 const EL2_WATCHDOG_REFRESH: RangeInclusive<usize> = 0x00_2A45_0000..=0x00_2A45_FFFF;
71 const TRUSTED_WATCHDOG: RangeInclusive<usize> = 0x00_2A49_0000..=0x00_2A49_FFFF;
72 const TRUSTZONE_CONTROLLER: RangeInclusive<usize> = 0x00_2A4A_0000..=0x00_2A4A_FFFF;
73 const REFCLK_CNTREAD: RangeInclusive<usize> = 0x00_2A80_0000..=0x00_2A80_FFFF;
74 const AP_REFCLK_CNTCTL: RangeInclusive<usize> = 0x00_2A81_0000..=0x00_2A81_FFFF;
75 const AP_REFCLK_CNTBASE0: RangeInclusive<usize> = 0x00_2A82_0000..=0x00_2A82_FFFF;
76 const AP_REFCLK_CNTBASE1: RangeInclusive<usize> = 0x00_2A83_0000..=0x00_2A83_FFFF;
77 const DMC_400_CFG: RangeInclusive<usize> = 0x00_2B0A_0000..=0x00_2B0A_FFFF;
78 const SMMUV3_AEM: RangeInclusive<usize> = 0x00_2B40_0000..=0x00_2B4F_FFFF;
79 const DMA330X4: RangeInclusive<usize> = 0x00_2B50_0000..=0x00_2B5F_FFFF;
80 const GICC: RangeInclusive<usize> = 0x00_2C00_0000..=0x00_2C00_1FFF;
81 const GICH: RangeInclusive<usize> = 0x00_2C01_0000..=0x00_2C01_0FFF;
82 const GICV: RangeInclusive<usize> = 0x00_2C02_F000..=0x00_2C03_0FFF;
83 const CCI_400: RangeInclusive<usize> = 0x00_2C09_0000..=0x00_2C09_FFFF;
84 const MALI_G76: RangeInclusive<usize> = 0x00_2D00_0000..=0x00_2DFF_0000;
85 pub const NON_TRUSTED_SRAM: RangeInclusive<usize> = 0x00_2E00_0000..=0x00_2E00_FFFF;
86 const GICD: RangeInclusive<usize> = 0x00_2F00_0000..=0x00_2F00_FFFF;
87 const GITS: RangeInclusive<usize> = 0x00_2F02_0000..=0x00_2F03_FFFF;
88 const GICR: RangeInclusive<usize> = 0x00_2F10_0000..=0x00_2F1F_FFFF;
89 const PCIE_CONFIG_REGION: RangeInclusive<usize> = 0x00_4000_0000..=0x00_4FFF_FFFF;
90 const PCIE_MEMORY_REGION1: RangeInclusive<usize> = 0x00_5000_0000..=0x00_5FFF_FFFF;
91 const TRUSTED_RNG: RangeInclusive<usize> = 0x00_7FE6_0000..=0x00_7FE6_0FFF;
92 const TRUSTED_NV_COUNTERS: RangeInclusive<usize> = 0x00_7FE7_0000..=0x00_7FE7_0FFF;
93 const TRUSTED_ROOT_KEY_STORAGE: RangeInclusive<usize> = 0x00_7FE8_0000..=0x00_7FE8_0FFF;
94 const DDR3_PHY: RangeInclusive<usize> = 0x00_7FEF_0000..=0x00_7FEF_FFFF;
95 const HDLCD_CONTROLLER: RangeInclusive<usize> = 0x00_7FF6_0000..=0x00_7FF6_FFFF;
96 pub const DRAM0: RangeInclusive<usize> = 0x00_8000_0000..=0x00_FFFF_FFFF;
97 pub const DRAM1: RangeInclusive<usize> = 0x08_8000_0000..=0x0F_FFFF_FFFF;
98 const PCIE_MEMORY_REGION2: RangeInclusive<usize> = 0x40_0000_0000..=0x7F_FFFF_FFFF;
99 pub const DRAM2: RangeInclusive<usize> = 0x88_0000_0000..=0xFF_FFFF_FFFF;
100 pub const DRAM3: RangeInclusive<usize> = 0x00_0880_0000_0000..=0x00_0FFF_FFFF_FFFF;
101 pub const DRAM4: RangeInclusive<usize> = 0x08_8000_0000_0000..=0x0F_FFFF_FFFF_FFFF;
102 pub const DRAM5: RangeInclusive<usize> = 0x88_0000_0000_0000..=0x8F_FFFF_FFFF_FFFF;
103}
104
Imre Kis9c084c02024-08-14 15:53:45 +0200105/// FVP peripherals
Andrew Walbran1a289d12025-02-11 14:55:39 +0000106#[derive(Debug)]
Imre Kis9c084c02024-08-14 15:53:45 +0200107pub struct Peripherals {
Andrew Walbran1a289d12025-02-11 14:55:39 +0000108 pub uart0: PhysicalInstance<PL011Registers>,
109 pub uart1: PhysicalInstance<PL011Registers>,
110 pub uart2: PhysicalInstance<PL011Registers>,
111 pub uart3: PhysicalInstance<PL011Registers>,
112 pub watchdog: PhysicalInstance<SP805Registers>,
113 pub gicd: PhysicalInstance<GICDRegisters>,
Tomás González52cb4a62025-03-19 18:41:00 +0000114 pub power_controller: PhysicalInstance<FvpPowerControllerRegisters>,
Imre Kis9c084c02024-08-14 15:53:45 +0200115}
116
117impl Peripherals {
118 /// Take the peripherals once
119 pub fn take() -> Option<Self> {
120 if !*PERIPHERALS_TAKEN.lock() {
Imre Kis75a43542024-10-02 14:11:25 +0200121 // SAFETY: PERIPHERALS_TAKEN ensures that this is only called once.
Imre Kis9c084c02024-08-14 15:53:45 +0200122 Some(unsafe { Self::steal() })
123 } else {
124 None
125 }
126 }
127
128 /// Unsafe version of take()
129 ///
130 /// # Safety
Andrew Walbran1a289d12025-02-11 14:55:39 +0000131 ///
132 /// The caller must ensure that each peripheral is only used once.
Imre Kis9c084c02024-08-14 15:53:45 +0200133 pub unsafe fn steal() -> Self {
134 *PERIPHERALS_TAKEN.lock() = true;
135
136 Peripherals {
Imre Kis58d74c42025-03-24 17:33:15 +0100137 uart0: PhysicalInstance::new(*MemoryMap::UART0.start()),
138 uart1: PhysicalInstance::new(*MemoryMap::UART1.start()),
139 uart2: PhysicalInstance::new(*MemoryMap::UART2.start()),
140 uart3: PhysicalInstance::new(*MemoryMap::UART3.start()),
141 watchdog: PhysicalInstance::new(*MemoryMap::WATCHDOG.start()),
142 power_controller: PhysicalInstance::new(*MemoryMap::POWER_CONTROLLER.start()),
143 gicd: PhysicalInstance::new(*MemoryMap::GICD.start()),
Imre Kis9c084c02024-08-14 15:53:45 +0200144 }
145 }
146}