blob: be9fe7afa1c42185f88ef641208919d28c056512 [file]
// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0
#![no_std]
use registers::pinmux;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum Pad {
// MIO Pads (0-46)
IOA0 = 0,
IOA1 = 1,
IOA2 = 2,
IOA3 = 3,
IOA4 = 4,
IOA5 = 5,
IOA6 = 6,
IOA7 = 7,
IOA8 = 8,
IOB0 = 9,
IOB1 = 10,
IOB2 = 11,
IOB3 = 12,
IOB4 = 13,
IOB5 = 14,
IOB6 = 15,
IOB7 = 16,
IOB8 = 17,
IOB9 = 18,
IOB10 = 19,
IOB11 = 20,
IOB12 = 21,
IOC0 = 22,
IOC1 = 23,
IOC2 = 24,
IOC3 = 25,
IOC4 = 26,
IOC5 = 27,
IOC6 = 28,
IOC7 = 29,
IOC8 = 30,
IOC9 = 31,
IOC10 = 32,
IOC11 = 33,
IOC12 = 34,
IOR0 = 35,
IOR1 = 36,
IOR2 = 37,
IOR3 = 38,
IOR4 = 39,
IOR5 = 40,
IOR6 = 41,
IOR7 = 42,
IOR10 = 43,
IOR11 = 44,
IOR12 = 45,
IOR13 = 46,
// DIO Pads (47-62)
DIO0 = 47,
DIO1 = 48,
DIO2 = 49,
DIO3 = 50,
DIO4 = 51,
DIO5 = 52,
DIO6 = 53,
DIO7 = 54,
DIO8 = 55,
DIO9 = 56,
DIO10 = 57,
DIO11 = 58,
DIO12 = 59,
DIO13 = 60,
DIO14 = 61,
DIO15 = 62,
}
impl Pad {
pub fn is_dio(&self) -> bool {
(*self as u32) >= 47
}
pub fn dio_index(self) -> Option<usize> {
let index = self as usize;
if index >= 47 {
Some(index - 47)
} else {
None
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Pull {
None,
Up,
Down,
}
pub struct PadConfig {
pub pull: Pull,
pub open_drain: bool,
pub invert: bool,
}
impl Default for PadConfig {
fn default() -> Self {
Self {
pull: Pull::None,
open_drain: false,
invert: false,
}
}
}
pub struct EarlGreyPinmux {
registers: pinmux::RegisterBlock<ureg::RealMmioMut<'static>>,
}
impl EarlGreyPinmux {
/// Create a new instance of the EarlGrey Pinmux driver.
///
/// # Safety
///
/// The caller must ensure that they have exclusive access to the Pinmux peripheral.
pub unsafe fn new() -> Self {
Self {
registers: unsafe { pinmux::RegisterBlock::new(pinmux::PinmuxAon::PTR) },
}
}
/// Connects a peripheral input to an MIO pad.
pub fn connect_input(&mut self, periph_input_idx: usize, pad: Pad) {
// MIO pads start at index 2 in periph_insel (0=Low, 1=High)
let periph_source = 2 + (pad as u32);
self.registers
.mio_periph_insel()
.at(periph_input_idx)
.write(|w| w.in_(periph_source));
}
/// Connects an MIO pad to a peripheral output.
pub fn connect_output(&mut self, pad: Pad, periph_output_idx: usize) {
// Peripheral outputs start at index 3 in outsel (0=Low, 1=High, 2=HighZ)
let pad_source = 3 + (periph_output_idx as u32);
self.registers
.mio_outsel()
.at(pad as usize)
.write(|w| w.out(pad_source));
}
pub fn configure_pad(&mut self, pad: Pad, config: &PadConfig) {
if let Some(dio_idx) = pad.dio_index() {
self.registers.dio_pad_attr().at(dio_idx).modify(|w| {
w.pull_en(config.pull != Pull::None)
.pull_select(|w| {
if config.pull == Pull::Up {
w.pull_up()
} else {
w.pull_down()
}
})
.od_en(config.open_drain)
.invert(config.invert)
});
} else {
self.registers.mio_pad_attr().at(pad as usize).modify(|w| {
w.pull_en(config.pull != Pull::None)
.pull_select(|w| {
if config.pull == Pull::Up {
w.pull_up()
} else {
w.pull_down()
}
})
.od_en(config.open_drain)
.invert(config.invert)
});
}
}
}