blob: 1e8da79e7571b8ce23742ff857b9aa017ba9751a [file] [log] [blame]
// SPDX-FileCopyrightText: Copyright 2023-2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
// SPDX-License-Identifier: MIT OR Apache-2.0
#![no_std]
#![doc = include_str!("../README.md")]
#![deny(clippy::undocumented_unsafe_blocks)]
pub mod power_controller;
pub mod system;
// Re-export peripheral drivers and common safe-mmio types
pub use arm_gic;
pub use arm_pl011_uart;
pub use arm_sp805;
pub use safe_mmio::{PhysicalInstance, UniqueMmioPointer};
use arm_gic::GICDRegisters;
use arm_pl011_uart::PL011Registers;
use arm_sp805::SP805Registers;
use core::{fmt::Debug, ops::RangeInclusive};
use power_controller::FvpPowerControllerRegisters;
use spin::mutex::Mutex;
use system::FvpSystemRegisters;
static PERIPHERALS_TAKEN: Mutex<bool> = Mutex::new(false);
/// Memory map based on 'Table 6-5: Base Platform memory map' of 'Fast Models Version 11.28
/// Reference Guide'. The ranges for normal memory regions are public, however the peripheral
/// regions are private and they should be accessed through the `Peripherals` structure.
pub struct MemoryMap;
#[allow(unused)]
impl MemoryMap {
pub const TRUSTED_BOOT_ROM: RangeInclusive<usize> = 0x00_0000_0000..=0x00_03FF_FFFF;
pub const TRUSTED_SRAM: RangeInclusive<usize> = 0x00_0400_0000..=0x00_0407_FFFF;
pub const TRUSTED_DRAM: RangeInclusive<usize> = 0x00_0600_0000..=0x00_07FF_FFFF;
pub const NOR_FLASH0: RangeInclusive<usize> = 0x00_0800_0000..=0x00_0BFF_FFFF;
pub const NOR_FLASH1: RangeInclusive<usize> = 0x00_0C00_0000..=0x00_0FFF_FFFF;
pub const PSRAM: RangeInclusive<usize> = 0x00_1400_0000..=0x00_17FF_FFFF;
pub const VRAM: RangeInclusive<usize> = 0x00_1800_0000..=0x00_19FF_FFFF;
const ETHERNET: RangeInclusive<usize> = 0x00_1A00_0000..=0x00_1AFF_FFFF;
const USB: RangeInclusive<usize> = 0x00_1B00_0000..=0x00_1BFF_FFFF;
const VE_SYSTEM: RangeInclusive<usize> = 0x00_1C01_0000..=0x00_1C01_FFFF;
const SYSTEM_CONTROLLER: RangeInclusive<usize> = 0x00_1C02_0000..=0x00_1C02_FFFF;
const AACI: RangeInclusive<usize> = 0x00_1C04_0000..=0x00_1C04_FFFF;
const MCI: RangeInclusive<usize> = 0x00_1C05_0000..=0x00_1C05_FFFF;
const KMI_KEYBOARD: RangeInclusive<usize> = 0x00_1C06_0000..=0x00_1C06_FFFF;
const KMI_MOUSE: RangeInclusive<usize> = 0x00_1C07_0000..=0x00_1C07_FFFF;
const UART0: RangeInclusive<usize> = 0x00_1C09_0000..=0x00_1C09_FFFF;
const UART1: RangeInclusive<usize> = 0x00_1C0A_0000..=0x00_1C0A_FFFF;
const UART2: RangeInclusive<usize> = 0x00_1C0B_0000..=0x00_1C0B_FFFF;
const UART3: RangeInclusive<usize> = 0x00_1C0C_0000..=0x00_1C0C_FFFF;
const VFS2: RangeInclusive<usize> = 0x00_1C0D_0000..=0x00_1C0D_FFFF;
const WATCHDOG: RangeInclusive<usize> = 0x00_1C0F_0000..=0x00_1C0F_FFFF;
const POWER_CONTROLLER: RangeInclusive<usize> = 0x00_1C10_0000..=0x00_1C10_FFFF;
const DUAL_TIMER0: RangeInclusive<usize> = 0x00_1C11_0000..=0x00_1C11_FFFF;
const DUAL_TIEMR1: RangeInclusive<usize> = 0x00_1C12_0000..=0x00_1C12_FFFF;
const VIRTIO_BLOCK_DEVICE: RangeInclusive<usize> = 0x00_1C13_0000..=0x00_1C13_FFFF;
const VIRTIO_PLAN9_DEVICE: RangeInclusive<usize> = 0x00_1C14_0000..=0x00_1C14_FFFF;
const VIRTIO_NET_DEVICE: RangeInclusive<usize> = 0x00_1C15_0000..=0x00_1C15_FFFF;
const RTC: RangeInclusive<usize> = 0x00_1C17_0000..=0x00_1C17_FFFF;
const CF_CARD: RangeInclusive<usize> = 0x00_1C1A_0000..=0x00_1C1A_FFFF;
const CLCD_CONTROLLER: RangeInclusive<usize> = 0x00_1C1F_0000..=0x00_1C1F_FFFF;
const VIRTIO_RNG: RangeInclusive<usize> = 0x00_1C20_0000..=0x00_1C20_FFFF;
const LS64_TESTING_FIFO: RangeInclusive<usize> = 0x00_1D00_0000..=0x00_1D00_FFFF;
const UTILITY_BUS: RangeInclusive<usize> = 0x00_1E00_0000..=0x00_1EFF_FFFF;
pub const NON_TRUSTED_ROM: RangeInclusive<usize> = 0x00_1F00_0000..=0x00_1F00_0FFF;
const CORESIGHT: RangeInclusive<usize> = 0x00_2000_0000..=0x00_27FF_FFFF;
const REFCLK_CNTCONTROL: RangeInclusive<usize> = 0x00_2A43_0000..=0x00_2A43_FFFF;
const EL2_WATCHDOG_CONTROL: RangeInclusive<usize> = 0x00_2A44_0000..=0x00_2A44_FFFF;
const EL2_WATCHDOG_REFRESH: RangeInclusive<usize> = 0x00_2A45_0000..=0x00_2A45_FFFF;
const TRUSTED_WATCHDOG: RangeInclusive<usize> = 0x00_2A49_0000..=0x00_2A49_FFFF;
const TRUSTZONE_CONTROLLER: RangeInclusive<usize> = 0x00_2A4A_0000..=0x00_2A4A_FFFF;
const REFCLK_CNTREAD: RangeInclusive<usize> = 0x00_2A80_0000..=0x00_2A80_FFFF;
const AP_REFCLK_CNTCTL: RangeInclusive<usize> = 0x00_2A81_0000..=0x00_2A81_FFFF;
const AP_REFCLK_CNTBASE0: RangeInclusive<usize> = 0x00_2A82_0000..=0x00_2A82_FFFF;
const AP_REFCLK_CNTBASE1: RangeInclusive<usize> = 0x00_2A83_0000..=0x00_2A83_FFFF;
const DMC_400_CFG: RangeInclusive<usize> = 0x00_2B0A_0000..=0x00_2B0A_FFFF;
const SMMUV3_AEM: RangeInclusive<usize> = 0x00_2B40_0000..=0x00_2B4F_FFFF;
const DMA330X4: RangeInclusive<usize> = 0x00_2B50_0000..=0x00_2B5F_FFFF;
const GICC: RangeInclusive<usize> = 0x00_2C00_0000..=0x00_2C00_1FFF;
const GICH: RangeInclusive<usize> = 0x00_2C01_0000..=0x00_2C01_0FFF;
const GICV: RangeInclusive<usize> = 0x00_2C02_F000..=0x00_2C03_0FFF;
const CCI_400: RangeInclusive<usize> = 0x00_2C09_0000..=0x00_2C09_FFFF;
const MALI_G76: RangeInclusive<usize> = 0x00_2D00_0000..=0x00_2DFF_0000;
pub const NON_TRUSTED_SRAM: RangeInclusive<usize> = 0x00_2E00_0000..=0x00_2E00_FFFF;
const GICD: RangeInclusive<usize> = 0x00_2F00_0000..=0x00_2F00_FFFF;
const GITS: RangeInclusive<usize> = 0x00_2F02_0000..=0x00_2F03_FFFF;
const GICR: RangeInclusive<usize> = 0x00_2F10_0000..=0x00_2F1F_FFFF;
const PCIE_CONFIG_REGION: RangeInclusive<usize> = 0x00_4000_0000..=0x00_4FFF_FFFF;
const PCIE_MEMORY_REGION1: RangeInclusive<usize> = 0x00_5000_0000..=0x00_5FFF_FFFF;
const TRUSTED_RNG: RangeInclusive<usize> = 0x00_7FE6_0000..=0x00_7FE6_0FFF;
const TRUSTED_NV_COUNTERS: RangeInclusive<usize> = 0x00_7FE7_0000..=0x00_7FE7_0FFF;
const TRUSTED_ROOT_KEY_STORAGE: RangeInclusive<usize> = 0x00_7FE8_0000..=0x00_7FE8_0FFF;
const DDR3_PHY: RangeInclusive<usize> = 0x00_7FEF_0000..=0x00_7FEF_FFFF;
const HDLCD_CONTROLLER: RangeInclusive<usize> = 0x00_7FF6_0000..=0x00_7FF6_FFFF;
pub const DRAM0: RangeInclusive<usize> = 0x00_8000_0000..=0x00_FFFF_FFFF;
pub const DRAM1: RangeInclusive<usize> = 0x08_8000_0000..=0x0F_FFFF_FFFF;
const PCIE_MEMORY_REGION2: RangeInclusive<usize> = 0x40_0000_0000..=0x7F_FFFF_FFFF;
pub const DRAM2: RangeInclusive<usize> = 0x88_0000_0000..=0xFF_FFFF_FFFF;
pub const DRAM3: RangeInclusive<usize> = 0x00_0880_0000_0000..=0x00_0FFF_FFFF_FFFF;
pub const DRAM4: RangeInclusive<usize> = 0x08_8000_0000_0000..=0x0F_FFFF_FFFF_FFFF;
pub const DRAM5: RangeInclusive<usize> = 0x88_0000_0000_0000..=0x8F_FFFF_FFFF_FFFF;
}
/// FVP peripherals
#[derive(Debug)]
pub struct Peripherals {
pub system: PhysicalInstance<FvpSystemRegisters>,
pub uart0: PhysicalInstance<PL011Registers>,
pub uart1: PhysicalInstance<PL011Registers>,
pub uart2: PhysicalInstance<PL011Registers>,
pub uart3: PhysicalInstance<PL011Registers>,
pub watchdog: PhysicalInstance<SP805Registers>,
pub power_controller: PhysicalInstance<FvpPowerControllerRegisters>,
pub gicd: PhysicalInstance<GICDRegisters>,
}
impl Peripherals {
/// Take the peripherals once
pub fn take() -> Option<Self> {
if !*PERIPHERALS_TAKEN.lock() {
// SAFETY: PERIPHERALS_TAKEN ensures that this is only called once.
Some(unsafe { Self::steal() })
} else {
None
}
}
/// Unsafe version of take()
///
/// # Safety
///
/// The caller must ensure that each peripheral is only used once.
pub unsafe fn steal() -> Self {
*PERIPHERALS_TAKEN.lock() = true;
Peripherals {
system: PhysicalInstance::new(*MemoryMap::VE_SYSTEM.start()),
uart0: PhysicalInstance::new(*MemoryMap::UART0.start()),
uart1: PhysicalInstance::new(*MemoryMap::UART1.start()),
uart2: PhysicalInstance::new(*MemoryMap::UART2.start()),
uart3: PhysicalInstance::new(*MemoryMap::UART3.start()),
watchdog: PhysicalInstance::new(*MemoryMap::WATCHDOG.start()),
power_controller: PhysicalInstance::new(*MemoryMap::POWER_CONTROLLER.start()),
gicd: PhysicalInstance::new(*MemoryMap::GICD.start()),
}
}
}