blob: 3c1d01e163a5db0d38b8d0f76f007a76fe0ca3ed [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
Imre Kis7c36bde2024-09-26 11:20:06 +020010use core::{
11 marker::PhantomData,
12 ops::{Deref, DerefMut},
13};
Imre Kis9c084c02024-08-14 15:53:45 +020014
15use spin::mutex::Mutex;
16
17use arm_gic::GICDRegisters;
18use arm_pl011::PL011Registers;
19use arm_sp805::SP805Registers;
20
21/// UART0 - PL011
22pub struct UART0 {
23 _marker: PhantomData<*const ()>,
24}
25
26impl UART0 {
Imre Kis7c36bde2024-09-26 11:20:06 +020027 pub const PTR: *mut PL011Registers = 0x1c09_0000 as *mut _;
Imre Kis9c084c02024-08-14 15:53:45 +020028}
29
30impl Deref for UART0 {
31 type Target = PL011Registers;
32
33 #[inline(always)]
34 fn deref(&self) -> &Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +020035 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis9c084c02024-08-14 15:53:45 +020036 unsafe { &*Self::PTR }
37 }
38}
39
Imre Kis7c36bde2024-09-26 11:20:06 +020040impl DerefMut for UART0 {
41 #[inline(always)]
42 fn deref_mut(&mut self) -> &mut Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +020043 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis7c36bde2024-09-26 11:20:06 +020044 unsafe { &mut *Self::PTR }
45 }
46}
47
Imre Kis75a43542024-10-02 14:11:25 +020048// SAFETY: The peripheral is accessible from any core/thread.
Imre Kis9c084c02024-08-14 15:53:45 +020049unsafe impl Send for UART0 {}
50
51/// UART1 - PL011
52pub struct UART1 {
53 _marker: PhantomData<*const ()>,
54}
55
56impl UART1 {
Imre Kis7c36bde2024-09-26 11:20:06 +020057 pub const PTR: *mut PL011Registers = 0x1c0a_0000 as *mut _;
Imre Kis9c084c02024-08-14 15:53:45 +020058}
59
60impl Deref for UART1 {
61 type Target = PL011Registers;
62
63 #[inline(always)]
64 fn deref(&self) -> &Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +020065 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis9c084c02024-08-14 15:53:45 +020066 unsafe { &*Self::PTR }
67 }
68}
69
Imre Kis7c36bde2024-09-26 11:20:06 +020070impl DerefMut for UART1 {
71 #[inline(always)]
72 fn deref_mut(&mut self) -> &mut Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +020073 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis7c36bde2024-09-26 11:20:06 +020074 unsafe { &mut *Self::PTR }
75 }
76}
77
Imre Kis75a43542024-10-02 14:11:25 +020078// SAFETY: The peripheral is accessible from any core/thread.
Imre Kis9c084c02024-08-14 15:53:45 +020079unsafe impl Send for UART1 {}
80
81/// UART2 - PL011
82pub struct UART2 {
83 _marker: PhantomData<*const ()>,
84}
85
86impl UART2 {
Imre Kis7c36bde2024-09-26 11:20:06 +020087 pub const PTR: *mut PL011Registers = 0x1c0b_0000 as *mut _;
Imre Kis9c084c02024-08-14 15:53:45 +020088}
89
90impl Deref for UART2 {
91 type Target = PL011Registers;
92
93 #[inline(always)]
94 fn deref(&self) -> &Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +020095 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis9c084c02024-08-14 15:53:45 +020096 unsafe { &*Self::PTR }
97 }
98}
99
Imre Kis7c36bde2024-09-26 11:20:06 +0200100impl DerefMut for UART2 {
101 #[inline(always)]
102 fn deref_mut(&mut self) -> &mut Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +0200103 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis7c36bde2024-09-26 11:20:06 +0200104 unsafe { &mut *Self::PTR }
105 }
106}
107
Imre Kis75a43542024-10-02 14:11:25 +0200108// SAFETY: The peripheral is accessible from any core/thread.
Imre Kis9c084c02024-08-14 15:53:45 +0200109unsafe impl Send for UART2 {}
110
111/// UART3 - PL011
112pub struct UART3 {
113 _marker: PhantomData<*const ()>,
114}
115
116impl UART3 {
Imre Kis7c36bde2024-09-26 11:20:06 +0200117 pub const PTR: *mut PL011Registers = 0x1c0c_0000 as *mut _;
Imre Kis9c084c02024-08-14 15:53:45 +0200118}
119
120impl Deref for UART3 {
121 type Target = PL011Registers;
122
123 #[inline(always)]
124 fn deref(&self) -> &Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +0200125 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis9c084c02024-08-14 15:53:45 +0200126 unsafe { &*Self::PTR }
127 }
128}
129
Imre Kis7c36bde2024-09-26 11:20:06 +0200130impl DerefMut for UART3 {
131 #[inline(always)]
132 fn deref_mut(&mut self) -> &mut Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +0200133 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis7c36bde2024-09-26 11:20:06 +0200134 unsafe { &mut *Self::PTR }
135 }
136}
137
Imre Kis75a43542024-10-02 14:11:25 +0200138// SAFETY: The peripheral is accessible from any core/thread.
Imre Kis9c084c02024-08-14 15:53:45 +0200139unsafe impl Send for UART3 {}
140
141/// Watchdog - SP805
142#[allow(clippy::upper_case_acronyms)]
143pub struct WATCHDOG {
144 _marker: PhantomData<*const ()>,
145}
146
147impl WATCHDOG {
Imre Kis7c36bde2024-09-26 11:20:06 +0200148 pub const PTR: *mut SP805Registers = 0x1c0f_0000 as *mut _;
Imre Kis9c084c02024-08-14 15:53:45 +0200149}
150
151impl Deref for WATCHDOG {
152 type Target = SP805Registers;
153
154 #[inline(always)]
155 fn deref(&self) -> &Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +0200156 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis9c084c02024-08-14 15:53:45 +0200157 unsafe { &*Self::PTR }
158 }
159}
160
Imre Kis7c36bde2024-09-26 11:20:06 +0200161impl DerefMut for WATCHDOG {
162 #[inline(always)]
163 fn deref_mut(&mut self) -> &mut Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +0200164 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis7c36bde2024-09-26 11:20:06 +0200165 unsafe { &mut *Self::PTR }
166 }
167}
168
Imre Kis75a43542024-10-02 14:11:25 +0200169// SAFETY: The peripheral is accessible from any core/thread.
Imre Kis9c084c02024-08-14 15:53:45 +0200170unsafe impl Send for WATCHDOG {}
171
172/// GIC Distributor
173#[allow(clippy::upper_case_acronyms)]
174pub struct GICD {
175 _marker: PhantomData<*const ()>,
176}
177
178impl GICD {
Imre Kis7c36bde2024-09-26 11:20:06 +0200179 pub const PTR: *mut GICDRegisters = 0x2f00_0000 as *mut _;
Imre Kis9c084c02024-08-14 15:53:45 +0200180}
181
182impl Deref for GICD {
183 type Target = GICDRegisters;
184
185 #[inline(always)]
186 fn deref(&self) -> &Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +0200187 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis9c084c02024-08-14 15:53:45 +0200188 unsafe { &*Self::PTR }
189 }
190}
191
Imre Kis7c36bde2024-09-26 11:20:06 +0200192impl DerefMut for GICD {
193 #[inline(always)]
194 fn deref_mut(&mut self) -> &mut Self::Target {
Imre Kis75a43542024-10-02 14:11:25 +0200195 // SAFETY: Self::PTR points to a valid peripheral register block on the Arm FVP platform.
Imre Kis7c36bde2024-09-26 11:20:06 +0200196 unsafe { &mut *Self::PTR }
197 }
198}
199
Imre Kis75a43542024-10-02 14:11:25 +0200200// SAFETY: The peripheral is accessible from any core/thread.
Imre Kis9c084c02024-08-14 15:53:45 +0200201unsafe impl Send for GICD {}
202
203static PERIPHERALS_TAKEN: Mutex<bool> = Mutex::new(false);
204
205/// FVP peripherals
206#[allow(non_snake_case)]
207pub struct Peripherals {
208 pub UART0: UART0,
209 pub UART1: UART1,
210 pub UART2: UART2,
211 pub UART3: UART3,
212 pub WATCHDOG: WATCHDOG,
213 pub GICD: GICD,
214}
215
216impl Peripherals {
217 /// Take the peripherals once
218 pub fn take() -> Option<Self> {
219 if !*PERIPHERALS_TAKEN.lock() {
Imre Kis75a43542024-10-02 14:11:25 +0200220 // SAFETY: PERIPHERALS_TAKEN ensures that this is only called once.
Imre Kis9c084c02024-08-14 15:53:45 +0200221 Some(unsafe { Self::steal() })
222 } else {
223 None
224 }
225 }
226
227 /// Unsafe version of take()
228 ///
229 /// # Safety
230 /// The caller has to ensure that each peripheral is only used once.
231 pub unsafe fn steal() -> Self {
232 *PERIPHERALS_TAKEN.lock() = true;
233
234 Peripherals {
235 UART0: UART0 {
236 _marker: PhantomData,
237 },
238 UART1: UART1 {
239 _marker: PhantomData,
240 },
241 UART2: UART2 {
242 _marker: PhantomData,
243 },
244 UART3: UART3 {
245 _marker: PhantomData,
246 },
247 WATCHDOG: WATCHDOG {
248 _marker: PhantomData,
249 },
250 GICD: GICD {
251 _marker: PhantomData,
252 },
253 }
254 }
255}