Skip to content

Commit 2757024

Browse files
committed
feat(09): Implement RP1 GPIO driver
Adds the GPIO driver for the Raspberry Pi 5's RP1 I/O controller. The RP1 requires a two-step GPIO setup for peripherals. This driver handles the logic for both the PADS_BANK0 and IO_BANK0 register blocks. The build system is modified to conditionally compile this driver when the 'bsp_rpi5' feature is enabled.
1 parent d6f19ce commit 2757024

File tree

3 files changed

+189
-3
lines changed

3 files changed

+189
-3
lines changed
Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
// SPDX-License-Identifier: MIT OR Apache-2.0
22
//
3-
// Copyright (c) 2018-2023 Andre Richter <[email protected]>
3+
// Copyright (c) 2018-2025 Andre Richter <[email protected]>
44

55
//! Device driver.
66
7-
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
7+
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4", feature = "bsp_rpi5"))]
88
mod bcm;
9+
#[cfg(feature = "bsp_rpi5")]
10+
mod rp1_gpio;
11+
912
mod common;
1013

14+
// For RPi3 and RPi4, re-export everything from the `bcm` module, which includes
15+
// both the GPIO and UART drivers.
1116
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
1217
pub use bcm::*;
18+
19+
// For RPi5, re-export only the drivers it uses: the common PL011Uart from the bcm
20+
// module and its specific GPIO driver from the rp1_gpio module.
21+
#[cfg(feature = "bsp_rpi5")]
22+
pub use bcm::PL011Uart;
23+
#[cfg(feature = "bsp_rpi5")]
24+
pub use rp1_gpio::GPIO;
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
// SPDX-License-Identifier: MIT OR Apache-2.0
22
//
3-
// Copyright (c) 2018-2023 Andre Richter <[email protected]>
3+
// Copyright (c) 2018-2025 Andre Richter <[email protected]>
44

55
//! BCM driver top level.
66
7+
// The bcm2xxx_gpio driver is only for RPi3 and RPi4.
8+
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
79
mod bcm2xxx_gpio;
10+
11+
// The PL011 UART is used by all supported RPi versions.
812
mod bcm2xxx_pl011_uart;
913

14+
// Re-export the GPIO driver only for RPi3 and RPi4.
15+
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
1016
pub use bcm2xxx_gpio::*;
17+
18+
// Re-export the UART driver for all.
1119
pub use bcm2xxx_pl011_uart::*;
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
//
3+
// Copyright (c) 2025 Devansh Lodha <[email protected]>
4+
// Copyright (c) 2018-2025 Andre Richter <[email protected]>
5+
6+
//! RP1 GPIO Driver for Raspberry Pi 5.
7+
8+
use crate::{
9+
bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
10+
synchronization::NullLock,
11+
};
12+
use tock_registers::{
13+
interfaces::{Readable, Writeable},
14+
register_structs,
15+
registers::ReadWrite,
16+
};
17+
18+
//--------------------------------------------------------------------------------------------------
19+
// Private Definitions
20+
//--------------------------------------------------------------------------------------------------
21+
22+
// Describes the layout of the IO_BANK0 registers.
23+
// Found in the "RP1 Peripherals" datasheet, section 3.1.4, Table 6.
24+
register_structs! {
25+
#[allow(non_snake_case)]
26+
IoBank0RegisterBlock {
27+
(0x000 => _reserved1),
28+
(0x074 => GPIO14_CTRL: ReadWrite<u32>), // GPIO 14 Control Register
29+
(0x078 => _reserved2),
30+
(0x07c => GPIO15_CTRL: ReadWrite<u32>), // GPIO 15 Control Register
31+
(0x080 => @END),
32+
}
33+
}
34+
35+
// Describes the layout of the PADS_BANK0 registers.
36+
// Found in the "RP1 Peripherals" datasheet, section 3.1.4, Table 19.
37+
register_structs! {
38+
#[allow(non_snake_case)]
39+
PadsBank0RegisterBlock {
40+
(0x000 => _reserved1),
41+
(0x03c => GPIO14: ReadWrite<u32>), // Pad control for GPIO 14
42+
(0x040 => GPIO15: ReadWrite<u32>), // Pad control for GPIO 15
43+
(0x044 => @END),
44+
}
45+
}
46+
47+
/// Abstraction for the IO_BANK0 registers.
48+
type IoBank0Registers = MMIODerefWrapper<IoBank0RegisterBlock>;
49+
50+
/// Abstraction for the PADS_BANK0 registers.
51+
type PadsBank0Registers = MMIODerefWrapper<PadsBank0RegisterBlock>;
52+
53+
// The inner state of the GPIO driver.
54+
struct GPIOInner {
55+
io_bank0: IoBank0Registers,
56+
pads_bank0: PadsBank0Registers,
57+
}
58+
59+
//--------------------------------------------------------------------------------------------------
60+
// Public Definitions
61+
//--------------------------------------------------------------------------------------------------
62+
63+
/// Representation of the GPIO peripheral.
64+
pub struct GPIO {
65+
inner: NullLock<GPIOInner>,
66+
}
67+
68+
//--------------------------------------------------------------------------------------------------
69+
// Implementation
70+
//--------------------------------------------------------------------------------------------------
71+
72+
impl GPIOInner {
73+
/// Create an instance.
74+
///
75+
/// # Safety
76+
///
77+
/// - The user must ensure to provide correct MMIO start addresses.
78+
pub const unsafe fn new(
79+
io_bank0_mmio_start_addr: usize,
80+
pads_bank0_mmio_start_addr: usize,
81+
) -> Self {
82+
Self {
83+
io_bank0: IoBank0Registers::new(io_bank0_mmio_start_addr),
84+
pads_bank0: PadsBank0Registers::new(pads_bank0_mmio_start_addr),
85+
}
86+
}
87+
88+
/// Map PL011 UART to GPIO pins 14 and 15.
89+
pub fn map_pl011_uart(&mut self) {
90+
// From RP1 Peripherals datasheet, Table 21: PADS_BANK0 GPIO0 Register
91+
const BIT_PADS_OD: u32 = 1 << 7; // Output Disable
92+
const BIT_PADS_IE: u32 = 1 << 6; // Input Enable
93+
const BIT_PADS_PUE: u32 = 1 << 3; // Pull-Up Enable
94+
95+
// From RP1 Peripherals datasheet, Table 4: GPIO function selection
96+
const FUNCSEL_FIELD_LSB: u32 = 0;
97+
const FUNCSEL_FIELD_MASK: u32 = 0x1F << FUNCSEL_FIELD_LSB;
98+
const FUNC_UART0: u32 = 4; // UART0 is alternate function 4
99+
100+
// --- Configure GPIO 14 as UART0 TX ---
101+
102+
// 1. Set pad electrical properties in PADS_BANK0.
103+
// - Clear Output Disable (OD) bit to enable output.
104+
let mut pads14_val = self.pads_bank0.GPIO14.get();
105+
pads14_val &= !BIT_PADS_OD;
106+
self.pads_bank0.GPIO14.set(pads14_val);
107+
108+
// 2. Set pin function in IO_BANK0.
109+
let mut io14_val = self.io_bank0.GPIO14_CTRL.get();
110+
io14_val &= !FUNCSEL_FIELD_MASK; // Clear the function field.
111+
io14_val |= FUNC_UART0 << FUNCSEL_FIELD_LSB; // Set to UART0.
112+
self.io_bank0.GPIO14_CTRL.set(io14_val);
113+
114+
// --- Configure GPIO 15 as UART0 RX ---
115+
116+
// 1. Set pad electrical properties.
117+
// - Set Input Enable (IE) bit.
118+
// - Set Pull-Up Enable (PUE) as per datasheet recommendation.
119+
let mut pads15_val = self.pads_bank0.GPIO15.get();
120+
pads15_val |= BIT_PADS_IE | BIT_PADS_PUE;
121+
self.pads_bank0.GPIO15.set(pads15_val);
122+
123+
// 2. Set pin function.
124+
let mut io15_val = self.io_bank0.GPIO15_CTRL.get();
125+
io15_val &= !FUNCSEL_FIELD_MASK; // Clear the function field.
126+
io15_val |= FUNC_UART0 << FUNCSEL_FIELD_LSB; // Set to UART0.
127+
self.io_bank0.GPIO15_CTRL.set(io15_val);
128+
}
129+
}
130+
131+
impl GPIO {
132+
pub const COMPATIBLE: &'static str = "RP1 GPIO";
133+
134+
/// Create an instance.
135+
///
136+
/// # Safety
137+
///
138+
/// - The user must ensure to provide correct MMIO start addresses for both register blocks.
139+
pub const unsafe fn new(
140+
io_bank0_mmio_start_addr: usize,
141+
pads_bank0_mmio_start_addr: usize,
142+
) -> Self {
143+
Self {
144+
inner: NullLock::new(GPIOInner::new(
145+
io_bank0_mmio_start_addr,
146+
pads_bank0_mmio_start_addr,
147+
)),
148+
}
149+
}
150+
151+
/// Concurrency-safe version of `GPIOInner.map_pl011_uart()`.
152+
pub fn map_pl011_uart(&self) {
153+
self.inner.lock(|inner| inner.map_pl011_uart())
154+
}
155+
}
156+
157+
//------------------------------------------------------------------------------
158+
// OS Interface Code
159+
//------------------------------------------------------------------------------
160+
use synchronization::interface::Mutex;
161+
162+
impl driver::interface::DeviceDriver for GPIO {
163+
fn compatible(&self) -> &'static str {
164+
Self::COMPATIBLE
165+
}
166+
}

0 commit comments

Comments
 (0)