blob: cd2a7e686c91d92925cf5493f4839db11315af93 [file] [log] [blame]
// SPDX-FileCopyrightText: Copyright 2023-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
// SPDX-License-Identifier: MIT OR Apache-2.0
//! # Peripheral Access Crate fro Arm Fixed Virtual Platform
//!
//! The crate provides access to the peripherals of [Arm Fixed Virtual Platform](https://developer.arm.com/Tools%20and%20Software/Fixed%20Virtual%20Platforms).
#![no_std]
use core::{
marker::PhantomData,
ops::{Deref, DerefMut},
};
use spin::mutex::Mutex;
use arm_gic::GICDRegisters;
use arm_pl011::PL011Registers;
use arm_sp805::SP805Registers;
/// UART0 - PL011
pub struct UART0 {
_marker: PhantomData<*const ()>,
}
impl UART0 {
pub const PTR: *mut PL011Registers = 0x1c09_0000 as *mut _;
}
impl Deref for UART0 {
type Target = PL011Registers;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}
impl DerefMut for UART0 {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *Self::PTR }
}
}
unsafe impl Send for UART0 {}
/// UART1 - PL011
pub struct UART1 {
_marker: PhantomData<*const ()>,
}
impl UART1 {
pub const PTR: *mut PL011Registers = 0x1c0a_0000 as *mut _;
}
impl Deref for UART1 {
type Target = PL011Registers;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}
impl DerefMut for UART1 {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *Self::PTR }
}
}
unsafe impl Send for UART1 {}
/// UART2 - PL011
pub struct UART2 {
_marker: PhantomData<*const ()>,
}
impl UART2 {
pub const PTR: *mut PL011Registers = 0x1c0b_0000 as *mut _;
}
impl Deref for UART2 {
type Target = PL011Registers;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}
impl DerefMut for UART2 {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *Self::PTR }
}
}
unsafe impl Send for UART2 {}
/// UART3 - PL011
pub struct UART3 {
_marker: PhantomData<*const ()>,
}
impl UART3 {
pub const PTR: *mut PL011Registers = 0x1c0c_0000 as *mut _;
}
impl Deref for UART3 {
type Target = PL011Registers;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}
impl DerefMut for UART3 {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *Self::PTR }
}
}
unsafe impl Send for UART3 {}
/// Watchdog - SP805
#[allow(clippy::upper_case_acronyms)]
pub struct WATCHDOG {
_marker: PhantomData<*const ()>,
}
impl WATCHDOG {
pub const PTR: *mut SP805Registers = 0x1c0f_0000 as *mut _;
}
impl Deref for WATCHDOG {
type Target = SP805Registers;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}
impl DerefMut for WATCHDOG {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *Self::PTR }
}
}
unsafe impl Send for WATCHDOG {}
/// GIC Distributor
#[allow(clippy::upper_case_acronyms)]
pub struct GICD {
_marker: PhantomData<*const ()>,
}
impl GICD {
pub const PTR: *mut GICDRegisters = 0x2f00_0000 as *mut _;
}
impl Deref for GICD {
type Target = GICDRegisters;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}
impl DerefMut for GICD {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *Self::PTR }
}
}
unsafe impl Send for GICD {}
static PERIPHERALS_TAKEN: Mutex<bool> = Mutex::new(false);
/// FVP peripherals
#[allow(non_snake_case)]
pub struct Peripherals {
pub UART0: UART0,
pub UART1: UART1,
pub UART2: UART2,
pub UART3: UART3,
pub WATCHDOG: WATCHDOG,
pub GICD: GICD,
}
impl Peripherals {
/// Take the peripherals once
pub fn take() -> Option<Self> {
if !*PERIPHERALS_TAKEN.lock() {
Some(unsafe { Self::steal() })
} else {
None
}
}
/// Unsafe version of take()
///
/// # Safety
/// The caller has to ensure that each peripheral is only used once.
pub unsafe fn steal() -> Self {
*PERIPHERALS_TAKEN.lock() = true;
Peripherals {
UART0: UART0 {
_marker: PhantomData,
},
UART1: UART1 {
_marker: PhantomData,
},
UART2: UART2 {
_marker: PhantomData,
},
UART3: UART3 {
_marker: PhantomData,
},
WATCHDOG: WATCHDOG {
_marker: PhantomData,
},
GICD: GICD {
_marker: PhantomData,
},
}
}
}