Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 1 | // SPDX-FileCopyrightText: Copyright 2023-2024 Arm Limited and/or its affiliates <open-source-office@arm.com> |
| 2 | // 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 Kis | 7c36bde | 2024-09-26 11:20:06 +0200 | [diff] [blame] | 10 | use core::{ |
Andrew Walbran | 1a289d1 | 2025-02-11 14:55:39 +0000 | [diff] [blame] | 11 | fmt::{self, Debug, Formatter}, |
Imre Kis | 7c36bde | 2024-09-26 11:20:06 +0200 | [diff] [blame] | 12 | marker::PhantomData, |
Imre Kis | 7c36bde | 2024-09-26 11:20:06 +0200 | [diff] [blame] | 13 | }; |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 14 | |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 15 | use arm_gic::GICDRegisters; |
Balint Dobszay | 4292ed4 | 2025-01-09 13:52:32 +0100 | [diff] [blame] | 16 | use arm_pl011_uart::PL011Registers; |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 17 | use arm_sp805::SP805Registers; |
Andrew Walbran | 1a289d1 | 2025-02-11 14:55:39 +0000 | [diff] [blame] | 18 | use spin::mutex::Mutex; |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 19 | |
| 20 | static PERIPHERALS_TAKEN: Mutex<bool> = Mutex::new(false); |
| 21 | |
Andrew Walbran | 1a289d1 | 2025-02-11 14:55:39 +0000 | [diff] [blame] | 22 | /// The physical instance of some device's MMIO space. |
| 23 | pub struct PhysicalInstance<T> { |
| 24 | pa: usize, |
| 25 | _phantom: PhantomData<T>, |
| 26 | } |
| 27 | |
| 28 | impl<T> Debug for PhysicalInstance<T> { |
| 29 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
| 30 | f.debug_struct("PhysicalInstance") |
| 31 | .field("pa", &self.pa) |
| 32 | .field("size", &size_of::<T>()) |
| 33 | .finish() |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | impl<T> PhysicalInstance<T> { |
| 38 | /// # Safety |
| 39 | /// |
| 40 | /// This must refer to the physical address of a real set of device registers of type `T`, and |
| 41 | /// there must only ever be a single `PhysicalInstance` for those device registers. |
| 42 | pub unsafe fn new(pa: usize) -> Self { |
| 43 | Self { |
| 44 | pa, |
| 45 | _phantom: PhantomData, |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | /// Returns the physical base address of the device's registers. |
| 50 | pub fn pa(&self) -> usize { |
| 51 | self.pa |
| 52 | } |
| 53 | } |
| 54 | |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 55 | /// FVP peripherals |
Andrew Walbran | 1a289d1 | 2025-02-11 14:55:39 +0000 | [diff] [blame] | 56 | #[derive(Debug)] |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 57 | pub struct Peripherals { |
Andrew Walbran | 1a289d1 | 2025-02-11 14:55:39 +0000 | [diff] [blame] | 58 | pub uart0: PhysicalInstance<PL011Registers>, |
| 59 | pub uart1: PhysicalInstance<PL011Registers>, |
| 60 | pub uart2: PhysicalInstance<PL011Registers>, |
| 61 | pub uart3: PhysicalInstance<PL011Registers>, |
| 62 | pub watchdog: PhysicalInstance<SP805Registers>, |
| 63 | pub gicd: PhysicalInstance<GICDRegisters>, |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | impl Peripherals { |
| 67 | /// Take the peripherals once |
| 68 | pub fn take() -> Option<Self> { |
| 69 | if !*PERIPHERALS_TAKEN.lock() { |
Imre Kis | 75a4354 | 2024-10-02 14:11:25 +0200 | [diff] [blame] | 70 | // SAFETY: PERIPHERALS_TAKEN ensures that this is only called once. |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 71 | Some(unsafe { Self::steal() }) |
| 72 | } else { |
| 73 | None |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | /// Unsafe version of take() |
| 78 | /// |
| 79 | /// # Safety |
Andrew Walbran | 1a289d1 | 2025-02-11 14:55:39 +0000 | [diff] [blame] | 80 | /// |
| 81 | /// The caller must ensure that each peripheral is only used once. |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 82 | pub unsafe fn steal() -> Self { |
| 83 | *PERIPHERALS_TAKEN.lock() = true; |
| 84 | |
| 85 | Peripherals { |
Andrew Walbran | 1a289d1 | 2025-02-11 14:55:39 +0000 | [diff] [blame] | 86 | uart0: PhysicalInstance::new(0x1c09_0000), |
| 87 | uart1: PhysicalInstance::new(0x1c0a_0000), |
| 88 | uart2: PhysicalInstance::new(0x1c0b_0000), |
| 89 | uart3: PhysicalInstance::new(0x1c0c_0000), |
| 90 | watchdog: PhysicalInstance::new(0x1c0f_0000), |
| 91 | gicd: PhysicalInstance::new(0x2f00_0000), |
Imre Kis | 9c084c0 | 2024-08-14 15:53:45 +0200 | [diff] [blame] | 92 | } |
| 93 | } |
| 94 | } |