feat: orangepi3 rtc tick

This commit is contained in:
2021-10-07 17:20:31 +03:00
parent 3a142fbe34
commit eb3460a010
2 changed files with 107 additions and 0 deletions
@@ -15,11 +15,13 @@ use error::Errno;
mod gpio;
mod uart;
mod rtc;
pub use gic::IrqNumber;
pub use gpio::PinAddress;
use gpio::Gpio;
use uart::Uart;
use rtc::Rtc;
#[allow(missing_docs)]
pub fn init_board() -> Result<(), Errno> {
@@ -31,11 +33,15 @@ pub fn init_board() -> Result<(), Errno> {
UART0.enable()?;
UART0.init_irqs()?;
RTC.enable()?;
RTC.init_irqs()?;
}
Ok(())
}
const UART0_BASE: usize = 0x05000000;
const RTC_BASE: usize = 0x07000000;
const PIO_BASE: usize = 0x0300B000;
const GICD_BASE: usize = 0x03021000;
const GICC_BASE: usize = 0x03022000;
@@ -61,4 +67,5 @@ pub fn intc() -> &'static impl IntController<IrqNumber = IrqNumber> {
static UART0: Uart = unsafe { Uart::new(UART0_BASE, IrqNumber::new(32)) };
static LOCAL_TIMER: GenericTimer = GenericTimer {};
pub(super) static GPIO: Gpio = unsafe { Gpio::new(PIO_BASE) };
static RTC: Rtc = unsafe { Rtc::new(RTC_BASE, IrqNumber::new(133)) };
static GIC: Gic = unsafe { Gic::new(GICD_BASE, GICC_BASE) };
@@ -0,0 +1,100 @@
use crate::dev::{Device, rtc::RtcDevice, irq::{IntController, IntSource}};
use crate::arch::{MemoryIo, machine::{self, IrqNumber}};
use crate::sync::IrqSafeNullLock;
use error::Errno;
use tock_registers::{
interfaces::{Readable, Writeable, ReadWriteable},
register_bitfields, register_structs,
registers::{ReadOnly, ReadWrite, WriteOnly},
};
register_bitfields! {
u32,
ALARM0_IRQ_EN [
ALARM0_IRQ_EN OFFSET(0) NUMBITS(1) []
],
ALARM0_ENABLE [
ALM_0_EN OFFSET(0) NUMBITS(1) []
],
ALARM0_IRQ_STA [
ALARM0_IRQ_PEND OFFSET(0) NUMBITS(1) []
]
}
register_structs! {
#[allow(non_snake_case)]
Regs {
(0x00 => LOSC_CTRL: ReadWrite<u32>),
(0x04 => LOSC_AUTO_SWT_STA: ReadWrite<u32>),
(0x08 => INTOSC_CLK_PRESCAL: ReadWrite<u32>),
(0x0C => INTOSC_CLK_AUTO_CALI: ReadWrite<u32>),
(0x10 => RTC_YY_MM_DD: ReadWrite<u32>),
(0x14 => RTC_HH_MM_SS: ReadWrite<u32>),
(0x18 => _res0),
(0x20 => ALARM0_COUNTER: ReadWrite<u32>),
(0x24 => ALARM0_CUR_VLU: ReadOnly<u32>),
(0x28 => ALARM0_ENABLE: ReadWrite<u32, ALARM0_ENABLE::Register>),
(0x2C => ALARM0_IRQ_EN: ReadWrite<u32, ALARM0_IRQ_EN::Register>),
(0x30 => ALARM0_IRQ_STA: ReadWrite<u32, ALARM0_IRQ_STA::Register>),
(0x34 => @END),
}
}
pub struct Rtc {
regs: IrqSafeNullLock<MemoryIo<Regs>>,
irq: IrqNumber
}
impl Regs {
fn arm_alarm0_irq(&self, sec: u32) {
// Clear IRQ pending status
if sec == 0 {
return;
}
self.ALARM0_IRQ_STA.write(ALARM0_IRQ_STA::ALARM0_IRQ_PEND::SET);
self.ALARM0_IRQ_EN.write(ALARM0_IRQ_EN::ALARM0_IRQ_EN::SET);
self.ALARM0_COUNTER.set(self.ALARM0_CUR_VLU.get() + sec - 1);
self.ALARM0_ENABLE.write(ALARM0_ENABLE::ALM_0_EN::SET);
}
}
impl RtcDevice for Rtc {}
impl IntSource for Rtc {
fn handle_irq(&self) -> Result<(), Errno> {
self.regs.lock().arm_alarm0_irq(1);
Ok(())
}
fn init_irqs(&'static self) -> Result<(), Errno> {
machine::intc().register_handler(self.irq, self)?;
self.regs.lock().arm_alarm0_irq(1);
machine::intc().enable_irq(self.irq)?;
Ok(())
}
}
impl Device for Rtc {
fn name(&self) -> &'static str {
"Allwinner H6 RTC"
}
unsafe fn enable(&self) -> Result<(), Errno> {
Ok(())
}
}
impl Rtc {
/// Constructs an instance of RTC device.
///
/// # Safety
///
/// Does not perform `base` validation.
pub const unsafe fn new(base: usize, irq: IrqNumber) -> Self {
Self {
regs: IrqSafeNullLock::new(MemoryIo::new(base)),
irq
}
}
}