use kernel::utilities::registers::interfaces::{Readable, Writeable};
use kernel::utilities::registers::{register_bitfields, ReadWrite};
use kernel::utilities::StaticRef;
#[repr(C)]
struct ClicRegisters {
clicintip: IntPendRegisters,
clicintie: IntEnableRegisters,
clicintcfg: IntConfigRegisters,
cliccfg: ConfigRegisters,
}
#[repr(C)]
struct IntPendRegisters {
_reserved0: [u8; 3],
msip: ReadWrite<u8, intpend::Register>,
_reserved1: [u8; 3],
mtip: ReadWrite<u8, intpend::Register>,
_reserved2: [u8; 3],
meip: ReadWrite<u8, intpend::Register>,
csip: ReadWrite<u8, intpend::Register>,
_reserved3: [u8; 3],
localintpend: [ReadWrite<u8, intpend::Register>; 128],
_reserved4: [u8; 880],
}
#[repr(C)]
struct IntEnableRegisters {
_reserved0: [u8; 3],
msip: ReadWrite<u8, inten::Register>,
_reserved1: [u8; 3],
mtip: ReadWrite<u8, inten::Register>,
_reserved2: [u8; 3],
meip: ReadWrite<u8, inten::Register>,
csip: ReadWrite<u8, inten::Register>,
_reserved3: [u8; 3],
localint: [ReadWrite<u8, inten::Register>; 128],
_reserved4: [u8; 880],
}
#[repr(C)]
struct IntConfigRegisters {
_reserved0: [u8; 3],
msip: ReadWrite<u8, intcon::Register>,
_reserved1: [u8; 3],
mtip: ReadWrite<u8, intcon::Register>,
_reserved2: [u8; 3],
meip: ReadWrite<u8, intcon::Register>,
csip: ReadWrite<u8, intcon::Register>,
_reserved3: [u8; 3],
localint: [ReadWrite<u8, intcon::Register>; 128],
_reserved4: [u8; 880],
}
#[repr(C)]
struct ConfigRegisters {
cliccfg: ReadWrite<u8, conreg::Register>,
}
register_bitfields![u8,
intpend [
IntPend OFFSET(0) NUMBITS(1) []
]
];
register_bitfields![u8,
inten [
IntEn OFFSET(0) NUMBITS(1) []
]
];
register_bitfields![u8,
intcon [
IntCon OFFSET(4) NUMBITS(4) []
]
];
register_bitfields![u8,
conreg [
nvbits OFFSET(0) NUMBITS(1) [],
nlbits OFFSET(1) NUMBITS(4) [],
nmbits OFFSET(5) NUMBITS(2) []
]
];
const CLIC_BASE: StaticRef<ClicRegisters> =
unsafe { StaticRef::new(0x0280_0000 as *const ClicRegisters) };
pub struct Clic {
registers: StaticRef<ClicRegisters>,
in_use_interrupts: u64,
}
impl Clic {
pub const fn new(in_use_interrupts: u64) -> Clic {
Clic {
registers: CLIC_BASE,
in_use_interrupts,
}
}
pub fn clear_all_pending(&self) {
self.registers.clicintip.msip.write(intpend::IntPend::CLEAR);
self.registers.clicintip.mtip.write(intpend::IntPend::CLEAR);
self.registers.clicintip.meip.write(intpend::IntPend::CLEAR);
self.registers.clicintip.csip.write(intpend::IntPend::CLEAR);
for pending in self.registers.clicintip.localintpend.iter() {
pending.write(intpend::IntPend::CLEAR);
}
}
pub fn enable_all(&self) {
if self.in_use_interrupts & (1 << 3) > 0 {
self.registers.clicintie.msip.write(inten::IntEn::SET);
} else if self.in_use_interrupts & (1 << 7) > 0 {
self.registers.clicintie.mtip.write(inten::IntEn::SET);
} else if self.in_use_interrupts & (1 << 11) > 0 {
self.registers.clicintie.meip.write(inten::IntEn::SET);
} else if self.in_use_interrupts & (1 << 12) > 0 {
self.registers.clicintie.csip.write(inten::IntEn::SET);
}
for (i, enable) in self.registers.clicintie.localint.iter().enumerate() {
if self.in_use_interrupts & (1 << (i + 16)) > 0 {
enable.write(inten::IntEn::SET);
}
}
}
pub fn disable_pending(&self) {
if self.registers.clicintip.msip.is_set(intpend::IntPend) {
self.registers.clicintie.msip.write(inten::IntEn::CLEAR);
} else if self.registers.clicintip.mtip.is_set(intpend::IntPend) {
self.registers.clicintie.mtip.write(inten::IntEn::CLEAR);
} else if self.registers.clicintip.meip.is_set(intpend::IntPend) {
self.registers.clicintie.meip.write(inten::IntEn::CLEAR);
} else if self.registers.clicintip.csip.is_set(intpend::IntPend) {
self.registers.clicintie.csip.write(inten::IntEn::CLEAR);
}
for (i, pending) in self.registers.clicintip.localintpend.iter().enumerate() {
if pending.is_set(intpend::IntPend)
&& self.registers.clicintie.localint[i].is_set(inten::IntEn)
{
self.registers.clicintie.localint[i].write(inten::IntEn::CLEAR);
}
}
}
pub fn disable_all(&self) {
self.registers.clicintie.msip.write(inten::IntEn::CLEAR);
self.registers.clicintie.mtip.write(inten::IntEn::CLEAR);
self.registers.clicintie.meip.write(inten::IntEn::CLEAR);
self.registers.clicintie.csip.write(inten::IntEn::CLEAR);
for enable in self.registers.clicintie.localint.iter() {
enable.write(inten::IntEn::CLEAR);
}
}
pub fn next_pending(&self) -> Option<u32> {
if self.in_use_interrupts & (1 << 3) > 0
&& self.registers.clicintip.msip.is_set(intpend::IntPend)
{
return Some(3);
} else if self.in_use_interrupts & (1 << 7) > 0
&& self.registers.clicintip.mtip.is_set(intpend::IntPend)
{
return Some(7);
} else if self.in_use_interrupts & (1 << 11) > 0
&& self.registers.clicintip.meip.is_set(intpend::IntPend)
{
return Some(11);
} else if self.in_use_interrupts & (1 << 12) > 0
&& self.registers.clicintip.csip.is_set(intpend::IntPend)
{
return Some(12);
}
for (i, pending) in self.registers.clicintip.localintpend.iter().enumerate() {
if self.in_use_interrupts & (1 << (i + 16)) > 0 && pending.is_set(intpend::IntPend) {
return Some((i + 16) as u32);
}
}
None
}
pub fn complete(&self, index: u32) {
match index {
3 => {
self.registers.clicintip.msip.write(intpend::IntPend::CLEAR);
self.registers.clicintie.msip.write(inten::IntEn::SET);
}
7 => {
self.registers.clicintip.mtip.write(intpend::IntPend::CLEAR);
self.registers.clicintie.mtip.write(inten::IntEn::SET);
}
11 => {
self.registers.clicintip.meip.write(intpend::IntPend::CLEAR);
self.registers.clicintie.meip.write(inten::IntEn::SET);
}
12 => {
self.registers.clicintip.csip.write(intpend::IntPend::CLEAR);
self.registers.clicintie.csip.write(inten::IntEn::SET);
}
16..=144 => {
self.registers.clicintip.localintpend[(index as usize) - 16]
.write(intpend::IntPend::CLEAR);
self.registers.clicintie.localint[(index as usize) - 16].write(inten::IntEn::SET);
}
_ => {}
}
}
pub fn has_pending(&self) -> bool {
self.next_pending().is_some()
}
}
pub unsafe fn disable_interrupt(index: u32) {
let regs: &ClicRegisters = &CLIC_BASE;
match index {
3 => regs.clicintie.msip.write(inten::IntEn::CLEAR),
7 => regs.clicintie.mtip.write(inten::IntEn::CLEAR),
11 => regs.clicintie.meip.write(inten::IntEn::CLEAR),
12 => regs.clicintie.csip.write(inten::IntEn::CLEAR),
16..=144 => regs.clicintie.localint[(index as usize) - 16].write(inten::IntEn::CLEAR),
_ => {}
}
}