mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
add kpc_aoint abstraction layers
This commit is contained in:
parent
1ca144f47f
commit
40c94b5abc
2 changed files with 144 additions and 0 deletions
110
libs/bao1x-hal/src/kpc_aoint.rs
Normal file
110
libs/bao1x-hal/src/kpc_aoint.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
use std::pin::Pin;
|
||||
|
||||
use arbitrary_int::u4;
|
||||
use bao1x_api::IrqNotification;
|
||||
use bitbybit::bitfield;
|
||||
use utralib::*;
|
||||
|
||||
#[bitfield(u32)]
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
// this is the AOFR register - ao_sysctrl::SFR_AOFR
|
||||
pub struct AoIntStatus {
|
||||
#[bit(6, rw)]
|
||||
ao_pad_in0: bool,
|
||||
#[bit(5, rw)]
|
||||
ao_pad_in1: bool,
|
||||
#[bit(4, rw)]
|
||||
wakeup_valid: bool,
|
||||
#[bit(3, rw)]
|
||||
kpc_interrupt: bool,
|
||||
#[bit(2, rw)]
|
||||
timer_interrupt: bool,
|
||||
#[bit(1, rw)]
|
||||
rtc_interrupt: bool,
|
||||
#[bit(0, rw)]
|
||||
wdt_reset: bool,
|
||||
}
|
||||
|
||||
// Numbers here are relative to the bit position within the IRQ2 register
|
||||
#[repr(u32)]
|
||||
pub enum IrqMapping {
|
||||
// AoWakeup triggers based on either of PI0 or PI1 going low, plus a subset of internal wakeup sources
|
||||
AoWakeup = 15,
|
||||
// This is the subset of internal sources
|
||||
AoInt = 14,
|
||||
Watchdog = 13,
|
||||
Timer1 = 12,
|
||||
Timer0 = 11,
|
||||
Reram = 22,
|
||||
Mailbox3 = 5,
|
||||
Mailbox2 = 4,
|
||||
Mailbox1 = 3,
|
||||
Mailbox0 = 2,
|
||||
Mdma = 1,
|
||||
Qfc = 0,
|
||||
}
|
||||
/// This structure is only available in `std` environment due to the very different
|
||||
/// way in which interrupts are handled between the two environments.
|
||||
pub struct KpcAoInt {
|
||||
pub kpc: CSR<u32>,
|
||||
pub ao: CSR<u32>,
|
||||
pub irq: CSR<u32>,
|
||||
pub args: Vec<IrqNotification>,
|
||||
enable: u32,
|
||||
}
|
||||
|
||||
impl KpcAoInt {
|
||||
pub fn new(handler: Option<fn(usize, *mut usize)>) -> Pin<Box<Self>> {
|
||||
let mem = xous::map_memory(
|
||||
xous::MemoryAddress::new(utra::dkpc::HW_DKPC_BASE),
|
||||
None,
|
||||
4096,
|
||||
xous::MemoryFlags::R | xous::MemoryFlags::W,
|
||||
)
|
||||
.expect("Couldn't map dkpc range");
|
||||
let irq = xous::map_memory(
|
||||
xous::MemoryAddress::new(utra::irqarray2::HW_IRQARRAY2_BASE),
|
||||
None,
|
||||
4096,
|
||||
xous::MemoryFlags::R | xous::MemoryFlags::W,
|
||||
)
|
||||
.expect("Couldn't map irq2 range");
|
||||
let ao = xous::map_memory(
|
||||
xous::MemoryAddress::new(utra::ao_sysctrl::HW_AO_SYSCTRL_BASE),
|
||||
None,
|
||||
4096,
|
||||
xous::MemoryFlags::R | xous::MemoryFlags::W,
|
||||
)
|
||||
.expect("Couldn't map ao_sysctrl range");
|
||||
|
||||
let mut kpc_aoint = Box::pin(KpcAoInt {
|
||||
kpc: CSR::new(mem.as_ptr() as *mut u32),
|
||||
irq: CSR::new(irq.as_ptr() as *mut u32),
|
||||
ao: CSR::new(ao.as_ptr() as *mut u32),
|
||||
args: Vec::new(),
|
||||
enable: 0,
|
||||
});
|
||||
|
||||
if let Some(handler) = handler {
|
||||
xous::claim_interrupt(
|
||||
utra::irqarray2::IRQARRAY2_IRQ,
|
||||
handler,
|
||||
Pin::as_mut(&mut kpc_aoint).get_mut() as *mut KpcAoInt as *mut usize,
|
||||
)
|
||||
.expect("couldn't claim ao/kpc handler interrupt");
|
||||
}
|
||||
kpc_aoint
|
||||
}
|
||||
|
||||
/// Adds a notifier to the IRQ stack. Does not also enable the IRQ.
|
||||
pub fn add_irq_notifier(&mut self, notification: IrqNotification) { self.args.push(notification) }
|
||||
|
||||
pub fn modify_irq_ena(&mut self, bit: u4, enable: bool) {
|
||||
if enable {
|
||||
self.enable |= 1 << bit.value() as u32;
|
||||
} else {
|
||||
self.enable &= !(1 << bit.value() as u32);
|
||||
}
|
||||
self.irq.wo(utra::irqarray2::EV_ENABLE, self.enable);
|
||||
}
|
||||
}
|
||||
34
services/bao1x-hal-service/src/kpc_aoint.rs
Normal file
34
services/bao1x-hal-service/src/kpc_aoint.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use bao1x_hal::kpc_aoint::KpcAoInt;
|
||||
use utralib::utra::irqarray2;
|
||||
|
||||
pub fn handler(_irq_no: usize, arg: *mut usize) {
|
||||
let kpc_aoint = unsafe { &mut *(arg as *mut KpcAoInt) };
|
||||
let pending = kpc_aoint.irq.r(irqarray2::EV_PENDING);
|
||||
// clear all pending interrupts
|
||||
kpc_aoint.irq.wo(irqarray2::EV_PENDING, pending);
|
||||
|
||||
// Note to self: this routine might need augmentation if the interrupt source also
|
||||
// has to be *disabled*. This would be necessary if the interrupt persists as asserted
|
||||
// instead of being a pulse, to prevent re-entrant interrupting.
|
||||
|
||||
for bit in 0..16u32 {
|
||||
let mask = 1u32 << bit;
|
||||
if (pending & mask) != 0 {
|
||||
for notifier in kpc_aoint.args.iter() {
|
||||
if notifier.bit.value() as u32 == bit {
|
||||
xous::try_send_message(
|
||||
notifier.conn,
|
||||
xous::Message::new_scalar(
|
||||
notifier.opcode,
|
||||
pending as usize,
|
||||
notifier.args[1],
|
||||
notifier.args[2],
|
||||
notifier.args[3],
|
||||
),
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue