blob: e58a8391d809652783e6a9381d6ae62e02a74604 [file] [log] [blame]
Imre Kis9c084c02024-08-14 15:53:45 +02001// 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
10use core::{marker::PhantomData, ops::Deref};
11
12use spin::mutex::Mutex;
13
14use arm_gic::GICDRegisters;
15use arm_pl011::PL011Registers;
16use arm_sp805::SP805Registers;
17
18/// UART0 - PL011
19pub struct UART0 {
20 _marker: PhantomData<*const ()>,
21}
22
23impl UART0 {
24 pub const PTR: *const PL011Registers = 0x1c09_0000 as *const _;
25}
26
27impl Deref for UART0 {
28 type Target = PL011Registers;
29
30 #[inline(always)]
31 fn deref(&self) -> &Self::Target {
32 unsafe { &*Self::PTR }
33 }
34}
35
36unsafe impl Send for UART0 {}
37
38/// UART1 - PL011
39pub struct UART1 {
40 _marker: PhantomData<*const ()>,
41}
42
43impl UART1 {
44 pub const PTR: *const PL011Registers = 0x1c0a_0000 as *const _;
45}
46
47impl Deref for UART1 {
48 type Target = PL011Registers;
49
50 #[inline(always)]
51 fn deref(&self) -> &Self::Target {
52 unsafe { &*Self::PTR }
53 }
54}
55
56unsafe impl Send for UART1 {}
57
58/// UART2 - PL011
59pub struct UART2 {
60 _marker: PhantomData<*const ()>,
61}
62
63impl UART2 {
64 pub const PTR: *const PL011Registers = 0x1c0b_0000 as *const _;
65}
66
67impl Deref for UART2 {
68 type Target = PL011Registers;
69
70 #[inline(always)]
71 fn deref(&self) -> &Self::Target {
72 unsafe { &*Self::PTR }
73 }
74}
75
76unsafe impl Send for UART2 {}
77
78/// UART3 - PL011
79pub struct UART3 {
80 _marker: PhantomData<*const ()>,
81}
82
83impl UART3 {
84 pub const PTR: *const PL011Registers = 0x1c0c_0000 as *const _;
85}
86
87impl Deref for UART3 {
88 type Target = PL011Registers;
89
90 #[inline(always)]
91 fn deref(&self) -> &Self::Target {
92 unsafe { &*Self::PTR }
93 }
94}
95
96unsafe impl Send for UART3 {}
97
98/// Watchdog - SP805
99#[allow(clippy::upper_case_acronyms)]
100pub struct WATCHDOG {
101 _marker: PhantomData<*const ()>,
102}
103
104impl WATCHDOG {
105 pub const PTR: *const SP805Registers = 0x1c0f_0000 as *const _;
106}
107
108impl Deref for WATCHDOG {
109 type Target = SP805Registers;
110
111 #[inline(always)]
112 fn deref(&self) -> &Self::Target {
113 unsafe { &*Self::PTR }
114 }
115}
116
117unsafe impl Send for WATCHDOG {}
118
119/// GIC Distributor
120#[allow(clippy::upper_case_acronyms)]
121pub struct GICD {
122 _marker: PhantomData<*const ()>,
123}
124
125impl GICD {
126 pub const PTR: *const GICDRegisters = 0x2f00_0000 as *const _;
127}
128
129impl Deref for GICD {
130 type Target = GICDRegisters;
131
132 #[inline(always)]
133 fn deref(&self) -> &Self::Target {
134 unsafe { &*Self::PTR }
135 }
136}
137
138unsafe impl Send for GICD {}
139
140static PERIPHERALS_TAKEN: Mutex<bool> = Mutex::new(false);
141
142/// FVP peripherals
143#[allow(non_snake_case)]
144pub struct Peripherals {
145 pub UART0: UART0,
146 pub UART1: UART1,
147 pub UART2: UART2,
148 pub UART3: UART3,
149 pub WATCHDOG: WATCHDOG,
150 pub GICD: GICD,
151}
152
153impl Peripherals {
154 /// Take the peripherals once
155 pub fn take() -> Option<Self> {
156 if !*PERIPHERALS_TAKEN.lock() {
157 Some(unsafe { Self::steal() })
158 } else {
159 None
160 }
161 }
162
163 /// Unsafe version of take()
164 ///
165 /// # Safety
166 /// The caller has to ensure that each peripheral is only used once.
167 pub unsafe fn steal() -> Self {
168 *PERIPHERALS_TAKEN.lock() = true;
169
170 Peripherals {
171 UART0: UART0 {
172 _marker: PhantomData,
173 },
174 UART1: UART1 {
175 _marker: PhantomData,
176 },
177 UART2: UART2 {
178 _marker: PhantomData,
179 },
180 UART3: UART3 {
181 _marker: PhantomData,
182 },
183 WATCHDOG: WATCHDOG {
184 _marker: PhantomData,
185 },
186 GICD: GICD {
187 _marker: PhantomData,
188 },
189 }
190 }
191}