diff --git a/kernel/src/arch/aarch64/mach_orangepi3/gpio.rs b/kernel/src/arch/aarch64/mach_orangepi3/gpio.rs index c975bad..ed43263 100644 --- a/kernel/src/arch/aarch64/mach_orangepi3/gpio.rs +++ b/kernel/src/arch/aarch64/mach_orangepi3/gpio.rs @@ -1,3 +1,10 @@ +//! Allwinner H6 GPIO port controller driver. +//! +//! GPIO ports are split into two register groups: +//! +//! 1. CPUS-PORT (TODO PL, PM) +//! 2. CPUX-PORT (PC, PD, PF, PG, PH) +//! use crate::arch::MemoryIo; use crate::dev::{ gpio::{GpioDevice, PinConfig, PinMode, PullMode}, @@ -21,29 +28,33 @@ register_structs! { } struct CpuxGpio { - regs: MemoryIo<[CpuxPortRegs; 5]>, + regs: MemoryIo<[CpuxPortRegs; 8]>, } -pub(super) struct Gpio { +pub struct Gpio { cpux: IrqSafeNullLock, } +/// Structure combining bank and pin numbers #[repr(transparent)] #[derive(Clone, Copy)] pub struct PinAddress(u32); impl PinAddress { + /// Constructs a new pin address from `bank` and `pin` numbers #[inline(always)] pub const fn new(bank: u32, pin: u32) -> Self { // TODO sanity checks Self((bank << 16) | pin) } + /// Returns bank number of this pin #[inline(always)] pub const fn bank(self) -> usize { (self.0 >> 16) as usize } + /// Returns pin number of this pin #[inline(always)] pub const fn pin(self) -> u32 { self.0 & 0xFFFF @@ -70,7 +81,6 @@ impl CpuxPortRegs { impl CpuxGpio { unsafe fn set_pin_config(&self, bank: usize, pin: u32, cfg: &PinConfig) -> Result<(), Errno> { - assert!((0..=7).contains(&bank)); let regs = &self.regs[bank]; let pull = match cfg.pull { @@ -144,8 +154,8 @@ impl GpioDevice for Gpio { let pin = pin.pin(); match bank { - 2..=7 => self.cpux.lock().set_pin_config(bank - 2, pin, cfg), - _ => unimplemented!(), + 0 | 1 | 4 => unimplemented!(), + _ => self.cpux.lock().set_pin_config(bank, pin, cfg), } } @@ -158,8 +168,8 @@ impl GpioDevice for Gpio { let pin = pin.pin(); match bank { - 2..=7 => self.cpux.lock().write_pin(bank - 2, pin, state), - _ => unimplemented!(), + 0 | 1 | 4 => unimplemented!(), + _ => self.cpux.lock().write_pin(bank, pin, state), } } @@ -168,8 +178,8 @@ impl GpioDevice for Gpio { let pin = pin.pin(); match bank { - 2..=7 => self.cpux.lock().toggle_pin(bank - 2, pin), - _ => unimplemented!(), + 0 | 1 | 4 => unimplemented!(), + _ => self.cpux.lock().toggle_pin(bank, pin), } } @@ -178,8 +188,8 @@ impl GpioDevice for Gpio { let pin = pin.pin(); match bank { - 2..=7 => Ok(self.cpux.lock().read_pin(bank - 2, pin)), - _ => unimplemented!(), + 0 | 1 | 4 => unimplemented!(), + _ => Ok(self.cpux.lock().read_pin(bank, pin)), } } } diff --git a/kernel/src/arch/aarch64/mach_orangepi3/mod.rs b/kernel/src/arch/aarch64/mach_orangepi3/mod.rs index af05dd2..f1697ec 100644 --- a/kernel/src/arch/aarch64/mach_orangepi3/mod.rs +++ b/kernel/src/arch/aarch64/mach_orangepi3/mod.rs @@ -5,6 +5,7 @@ use crate::arch::aarch64::{ timer::GenericTimer, }; use crate::dev::{ + gpio::{GpioDevice, PinConfig}, irq::{IntController, IntSource}, serial::SerialDevice, timer::TimestampSource, @@ -16,6 +17,7 @@ mod gpio; mod uart; pub use gic::IrqNumber; +pub use gpio::PinAddress; use gpio::Gpio; use uart::Uart; @@ -25,6 +27,7 @@ pub fn init_board() -> Result<(), Errno> { GIC.enable()?; GPIO.cfg_uart0_ph0_ph1()?; + GPIO.set_pin_config(PinAddress::new(3, 26), &PinConfig::out_pull_down())?; UART0.enable()?; UART0.init_irqs()?; @@ -57,5 +60,5 @@ pub fn intc() -> &'static impl IntController { static UART0: Uart = unsafe { Uart::new(UART0_BASE, IrqNumber::new(32)) }; static LOCAL_TIMER: GenericTimer = GenericTimer {}; -static GPIO: Gpio = unsafe { Gpio::new(PIO_BASE) }; +pub(super) static GPIO: Gpio = unsafe { Gpio::new(PIO_BASE) }; static GIC: Gic = unsafe { Gic::new(GICD_BASE, GICC_BASE) }; diff --git a/kernel/src/arch/aarch64/mach_orangepi3/uart.rs b/kernel/src/arch/aarch64/mach_orangepi3/uart.rs index 8b661b1..a5ebadc 100644 --- a/kernel/src/arch/aarch64/mach_orangepi3/uart.rs +++ b/kernel/src/arch/aarch64/mach_orangepi3/uart.rs @@ -113,6 +113,8 @@ impl IntSource for Uart { let regs = self.regs.lock(); let byte = regs.DR_DLL.get(); debugln!("irq byte = {:#04x}!", byte); + use crate::dev::gpio::{GpioDevice}; + machine::GPIO.toggle_pin(machine::PinAddress::new(3, 26)); Ok(()) }