Add PhysicalInstance type rather than using Deref for physical addresses.
Change-Id: I4eef9bfcab726dcc7bdcf166075065a3e355b8fd
Signed-off-by: Andrew Walbran <qwandor@google.com>
diff --git a/src/lib.rs b/src/lib.rs
index 2845da4..5c67eaa 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,209 +8,59 @@
#![no_std]
use core::{
+ fmt::{self, Debug, Formatter},
marker::PhantomData,
- ops::{Deref, DerefMut},
};
-use spin::mutex::Mutex;
-
use arm_gic::GICDRegisters;
use arm_pl011_uart::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 {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &*Self::PTR }
- }
-}
-
-impl DerefMut for UART0 {
- #[inline(always)]
- fn deref_mut(&mut self) -> &mut Self::Target {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &mut *Self::PTR }
- }
-}
-
-// SAFETY: The peripheral is accessible from any core/thread.
-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 {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &*Self::PTR }
- }
-}
-
-impl DerefMut for UART1 {
- #[inline(always)]
- fn deref_mut(&mut self) -> &mut Self::Target {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &mut *Self::PTR }
- }
-}
-
-// SAFETY: The peripheral is accessible from any core/thread.
-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 {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &*Self::PTR }
- }
-}
-
-impl DerefMut for UART2 {
- #[inline(always)]
- fn deref_mut(&mut self) -> &mut Self::Target {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &mut *Self::PTR }
- }
-}
-
-// SAFETY: The peripheral is accessible from any core/thread.
-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 {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &*Self::PTR }
- }
-}
-
-impl DerefMut for UART3 {
- #[inline(always)]
- fn deref_mut(&mut self) -> &mut Self::Target {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &mut *Self::PTR }
- }
-}
-
-// SAFETY: The peripheral is accessible from any core/thread.
-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 {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &*Self::PTR }
- }
-}
-
-impl DerefMut for WATCHDOG {
- #[inline(always)]
- fn deref_mut(&mut self) -> &mut Self::Target {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &mut *Self::PTR }
- }
-}
-
-// SAFETY: The peripheral is accessible from any core/thread.
-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 {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &*Self::PTR }
- }
-}
-
-impl DerefMut for GICD {
- #[inline(always)]
- fn deref_mut(&mut self) -> &mut Self::Target {
- // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
- unsafe { &mut *Self::PTR }
- }
-}
-
-// SAFETY: The peripheral is accessible from any core/thread.
-unsafe impl Send for GICD {}
+use spin::mutex::Mutex;
static PERIPHERALS_TAKEN: Mutex<bool> = Mutex::new(false);
+/// The physical instance of some device's MMIO space.
+pub struct PhysicalInstance<T> {
+ pa: usize,
+ _phantom: PhantomData<T>,
+}
+
+impl<T> Debug for PhysicalInstance<T> {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.debug_struct("PhysicalInstance")
+ .field("pa", &self.pa)
+ .field("size", &size_of::<T>())
+ .finish()
+ }
+}
+
+impl<T> PhysicalInstance<T> {
+ /// # Safety
+ ///
+ /// This must refer to the physical address of a real set of device registers of type `T`, and
+ /// there must only ever be a single `PhysicalInstance` for those device registers.
+ pub unsafe fn new(pa: usize) -> Self {
+ Self {
+ pa,
+ _phantom: PhantomData,
+ }
+ }
+
+ /// Returns the physical base address of the device's registers.
+ pub fn pa(&self) -> usize {
+ self.pa
+ }
+}
+
/// FVP peripherals
-#[allow(non_snake_case)]
+#[derive(Debug)]
pub struct Peripherals {
- pub UART0: UART0,
- pub UART1: UART1,
- pub UART2: UART2,
- pub UART3: UART3,
- pub WATCHDOG: WATCHDOG,
- pub GICD: GICD,
+ pub uart0: PhysicalInstance<PL011Registers>,
+ pub uart1: PhysicalInstance<PL011Registers>,
+ pub uart2: PhysicalInstance<PL011Registers>,
+ pub uart3: PhysicalInstance<PL011Registers>,
+ pub watchdog: PhysicalInstance<SP805Registers>,
+ pub gicd: PhysicalInstance<GICDRegisters>,
}
impl Peripherals {
@@ -227,29 +77,18 @@
/// Unsafe version of take()
///
/// # Safety
- /// The caller has to ensure that each peripheral is only used once.
+ ///
+ /// The caller must 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,
- },
+ uart0: PhysicalInstance::new(0x1c09_0000),
+ uart1: PhysicalInstance::new(0x1c0a_0000),
+ uart2: PhysicalInstance::new(0x1c0b_0000),
+ uart3: PhysicalInstance::new(0x1c0c_0000),
+ watchdog: PhysicalInstance::new(0x1c0f_0000),
+ gicd: PhysicalInstance::new(0x2f00_0000),
}
}
}