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