use bitflags::bitflags;
use core::fmt::{self, Debug, Formatter};
use safe_mmio::fields::{ReadOnly, ReadPure, ReadPureWrite, WriteOnly};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Clone, Copy, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
#[repr(transparent)]
pub struct GicdCtlr(u32);
bitflags! {
impl GicdCtlr: u32 {
const EnableGrp1 = 1 << 1;
const EnableGrp0 = 1 << 0;
}
}
impl Debug for GicdCtlr {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "GicdCtlr(")?;
bitflags::parser::to_writer(self, &mut *f)?;
write!(f, ")")?;
Ok(())
}
}
#[derive(Clone, Copy, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
#[repr(transparent)]
pub struct Typer(u32);
impl Typer {
pub fn lockable_spi_count(self) -> u32 {
(self.0 >> 11) & 0b11111
}
pub fn has_security_extension(self) -> bool {
self.0 & (1 << 10) != 0
}
pub fn cpu_count(self) -> u32 {
((self.0 >> 5) & 0b111) + 1
}
pub fn num_irqs(&self) -> u32 {
((self.0 & 0b11111) + 1) * 32
}
}
#[repr(C, align(8))]
pub struct Gicd {
pub ctlr: ReadPureWrite<GicdCtlr>,
pub typer: ReadPure<Typer>,
pub iidr: ReadPure<u32>,
_reserved_0: [u32; 0x1D],
pub igroupr: [ReadPureWrite<u32>; 0x20],
pub isenabler: [ReadPureWrite<u32>; 0x20],
pub icenabler: [ReadPureWrite<u32>; 0x20],
pub ispendr: [ReadPureWrite<u32>; 0x20],
pub icpendr: [ReadPureWrite<u32>; 0x20],
pub isactiver: [ReadPureWrite<u32>; 0x20],
pub icactiver: [ReadPureWrite<u32>; 0x20],
pub ipriorityr: [ReadPureWrite<u32>; 0x100],
pub itargetsr: [u32; 0x100],
pub icfgr: [ReadPureWrite<u32>; 0x40],
_reserved_1: [u32; 0x80],
pub sgir: WriteOnly<u32>,
}
#[repr(C, align(8))]
pub struct Gicc {
pub ctlr: ReadPureWrite<u32>,
pub pmr: ReadPureWrite<u32>,
pub bpr: u32,
pub iar: ReadOnly<u32>,
pub eoir: WriteOnly<u32>,
pub rpr: u32,
pub hppir: u32,
pub abpr: u32,
pub aiar: ReadOnly<u32>,
pub aeoir: WriteOnly<u32>,
pub ahppir: u32,
_reserved_0: [u32; 0x34],
pub iidr: u32,
_reserved_1: [u32; 0x3C0],
pub dir: u32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cpu_count() {
assert_eq!(Typer(0).cpu_count(), 1);
assert_eq!(Typer(7 << 5).cpu_count(), 8);
}
#[test]
fn it_lines() {
assert_eq!(Typer(0).num_irqs(), 32);
assert_eq!(Typer(0b00011).num_irqs(), 128);
assert_eq!(Typer(0b11111).num_irqs(), 1024);
}
}