add basic HAL for GIC
This commit is contained in:
parent
f098689875
commit
7279c96f03
@ -19,7 +19,7 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
|||||||
|
|
||||||
#[unsafe(export_name = "main")]
|
#[unsafe(export_name = "main")]
|
||||||
pub fn main() -> ! {
|
pub fn main() -> ! {
|
||||||
let mut gpio = unsafe { zynq7000::gpio::Gpio::new_mmio() };
|
let mut gpio = unsafe { zynq7000::pac::gpio::Gpio::new_mmio() };
|
||||||
gpio.modify_dirm_0(|v| v | ZEDBOARD_LED_MASK);
|
gpio.modify_dirm_0(|v| v | ZEDBOARD_LED_MASK);
|
||||||
gpio.modify_out_en_0(|v| v | ZEDBOARD_LED_MASK);
|
gpio.modify_out_en_0(|v| v | ZEDBOARD_LED_MASK);
|
||||||
loop {
|
loop {
|
||||||
|
@ -15,6 +15,7 @@ static_assertions = "1.1"
|
|||||||
derive-mmio = { path = "../../derive-mmio", default-features = false }
|
derive-mmio = { path = "../../derive-mmio", default-features = false }
|
||||||
bitbybit = "1.3"
|
bitbybit = "1.3"
|
||||||
arbitrary-int = "1.3"
|
arbitrary-int = "1.3"
|
||||||
|
thiserror = { version = "2", default-features = false }
|
||||||
# cortex-r
|
# cortex-r
|
||||||
# defmt = { version = "0.3", optional = true }
|
# defmt = { version = "0.3", optional = true }
|
||||||
# critical-section = { version = "1", optional = true }
|
# critical-section = { version = "1", optional = true }
|
||||||
@ -22,6 +23,7 @@ arbitrary-int = "1.3"
|
|||||||
[features]
|
[features]
|
||||||
# Adds Debug implementation
|
# Adds Debug implementation
|
||||||
debug = []
|
debug = []
|
||||||
|
std = ["thiserror/std"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
76
zynq7000/src/hal/gic.rs
Normal file
76
zynq7000/src/hal/gic.rs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
use crate::pac::gic::{MmioGicc, MmioGicd};
|
||||||
|
|
||||||
|
pub struct Gic {
|
||||||
|
pub gicc: MmioGicc<'static>,
|
||||||
|
pub gicd: MmioGicd<'static>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum SpiSensitivity {
|
||||||
|
Level = 0b01,
|
||||||
|
Edge = 0b11,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const ICFR_2_FIXED_VALUE: u32 = 0b01010101010111010101010001011111;
|
||||||
|
/// This configures PL[2:0] to high-level sensitivity.
|
||||||
|
pub const ICFR_3_FIXED_VALUE: u32 = 0b01010111010101011101010101010101;
|
||||||
|
/// This configures PL[7:3] to high-level sensitivity.
|
||||||
|
pub const ICFR_4_FIXED_VALUE: u32 = 0b01110101010101010101010101010101;
|
||||||
|
/// This configures PL[15:8] to high-level sensitivity.
|
||||||
|
pub const ICFR_5_FIXED_VALUE: u32 = 0b00000011010101010101010101010101;
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[error("Invalid PL interrupt ID {0}")]
|
||||||
|
pub struct InvalidPlInterruptId(pub u32);
|
||||||
|
|
||||||
|
impl Gic {
|
||||||
|
pub fn new(gicc: MmioGicc<'static>, gicd: MmioGicd<'static>) -> Self {
|
||||||
|
Gic { gicc, gicd }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets up the GIC by configuring the required sensitivites for the shared peripheral
|
||||||
|
/// interrupts.
|
||||||
|
///
|
||||||
|
/// With a few exeception, the GIC expects software to set up the sensitivities
|
||||||
|
/// to fixed values. The only exceptions are the interupts coming from the programmable
|
||||||
|
/// logic. These are configured to high level sensitivity by this function.
|
||||||
|
/// If you need a different sensitivity, you need to update the bits using the
|
||||||
|
/// [Self::set_pl_interrupt_sensitivity] function.
|
||||||
|
pub fn initialize(&mut self) {
|
||||||
|
self.gicd.write_icfr_2_spi(ICFR_2_FIXED_VALUE);
|
||||||
|
self.gicd.write_icfr_3_spi(ICFR_3_FIXED_VALUE);
|
||||||
|
self.gicd.write_icfr_4_spi(ICFR_4_FIXED_VALUE);
|
||||||
|
self.gicd.write_icfr_5_spi(ICFR_5_FIXED_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_pl_interrupt_sensitivity(
|
||||||
|
&mut self,
|
||||||
|
pl_int_id: u32,
|
||||||
|
sensitivity: SpiSensitivity,
|
||||||
|
) -> Result<(), InvalidPlInterruptId> {
|
||||||
|
if pl_int_id >= 16 {
|
||||||
|
return Err(InvalidPlInterruptId(pl_int_id));
|
||||||
|
}
|
||||||
|
match pl_int_id {
|
||||||
|
0..=2 => {
|
||||||
|
let pos = 26 + (pl_int_id * 2);
|
||||||
|
let mask = 0b11 << pos;
|
||||||
|
self.gicd
|
||||||
|
.modify_icfr_3_spi(|v| (v & !mask) | ((sensitivity as u32) << pos));
|
||||||
|
}
|
||||||
|
3..=7 => {
|
||||||
|
let pos = pl_int_id * 2;
|
||||||
|
let mask = 0b11 << pos;
|
||||||
|
self.gicd
|
||||||
|
.modify_icfr_4_spi(|v| (v & !mask) | ((sensitivity as u32) << pos));
|
||||||
|
}
|
||||||
|
8..=15 => {
|
||||||
|
let pos = 8 + (pl_int_id * 2);
|
||||||
|
let mask = 0b11 << pos;
|
||||||
|
self.gicd
|
||||||
|
.modify_icfr_5_spi(|v| (v & !mask) | ((sensitivity as u32) << pos));
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
1
zynq7000/src/hal/mod.rs
Normal file
1
zynq7000/src/hal/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod gic;
|
@ -3,7 +3,5 @@
|
|||||||
|
|
||||||
pub const MPCORE_BASE_ADDR: usize = 0xF8F0_0000;
|
pub const MPCORE_BASE_ADDR: usize = 0xF8F0_0000;
|
||||||
|
|
||||||
pub mod gpio;
|
pub mod pac;
|
||||||
pub mod uart;
|
pub mod hal;
|
||||||
pub mod gtc;
|
|
||||||
pub mod slcr;
|
|
||||||
|
199
zynq7000/src/pac/gic.rs
Normal file
199
zynq7000/src/pac/gic.rs
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
pub use crate::pac::mpcore::{GICC_BASE_ADDR, GICD_BASE_ADDR};
|
||||||
|
use arbitrary_int::{u10, u3, u5};
|
||||||
|
use static_assertions::const_assert_eq;
|
||||||
|
|
||||||
|
/// Distributor Control Register
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct Dcr {
|
||||||
|
#[bit(1, rw)]
|
||||||
|
enable_non_secure: bool,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
enable_secure: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read only bit. This register only returns fixed constants.
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct TypeRegister {
|
||||||
|
#[bits(11..=15, r)]
|
||||||
|
lspi: u5,
|
||||||
|
#[bit(10, r)]
|
||||||
|
security_extension: bool,
|
||||||
|
#[bits(5..=7, r)]
|
||||||
|
cpu_number: u3,
|
||||||
|
#[bits(0..=4, r)]
|
||||||
|
it_lines_number: u5,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeRegister {
|
||||||
|
pub const SECURITY_EXTNS_BIT: bool = true;
|
||||||
|
/// 31 LSPIs.
|
||||||
|
pub const NUM_LSPI: usize = 0x1f;
|
||||||
|
/// Encoding: 0b001 means that the Cortex-A9 MPCore has 2 processors.
|
||||||
|
pub const CPU_NUMBER_BITS: u8 = 0b001;
|
||||||
|
/// The distributor provides 96 interrupts.
|
||||||
|
pub const IT_LINES_NUMBER: u8 = 0x2;
|
||||||
|
|
||||||
|
pub const NUM_OF_CPUS: usize = 2;
|
||||||
|
pub const NUM_OF_INTERRUPTS: usize = 96;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Typer = TypeRegister;
|
||||||
|
|
||||||
|
/// GIC Distributor registers.
|
||||||
|
#[derive(derive_mmio::Mmio)]
|
||||||
|
#[mmio(no_ctors)]
|
||||||
|
#[repr(C, align(8))]
|
||||||
|
pub struct Gicd {
|
||||||
|
/// Distributor Control Register
|
||||||
|
pub dcr: Dcr,
|
||||||
|
/// Interrupt Controller Type Register
|
||||||
|
#[mmio(RO)]
|
||||||
|
pub ictr: Typer,
|
||||||
|
/// Distributor Implementer Identification Register
|
||||||
|
#[mmio(RO)]
|
||||||
|
pub iidr: u32,
|
||||||
|
_reserved_0: [u32; 0x1D],
|
||||||
|
/// Interrupt security registers
|
||||||
|
pub isr: [u32; 3],
|
||||||
|
_reserved_1: [u32; 0x1D],
|
||||||
|
/// Interrupt Set-Enable Registers
|
||||||
|
pub iser: [u32; 0x3],
|
||||||
|
_reserved_3: [u32; 0x1D],
|
||||||
|
/// Interrupt Clear-Enable Registers
|
||||||
|
pub icer: [u32; 0x3],
|
||||||
|
_reserved_4: [u32; 0x1D],
|
||||||
|
/// Interrupt Set-Pending Registers
|
||||||
|
pub ispr: [u32; 0x3],
|
||||||
|
_reserved_5: [u32; 0x1D],
|
||||||
|
/// Interrupt Clear-Pending Registers
|
||||||
|
pub icpr: [u32; 0x3],
|
||||||
|
_reserved_6: [u32; 0x1D],
|
||||||
|
/// Active Bit Registers
|
||||||
|
pub abr: [u32; 0x3],
|
||||||
|
_reserved_10: [u32; 0x3D],
|
||||||
|
/// Interrupt Priority Registers
|
||||||
|
pub ipr: [u32; 0x18],
|
||||||
|
_reserved_11: [u32; 0xE8],
|
||||||
|
/// Interrupt Processor Targes Registers
|
||||||
|
pub iptr: [u32; 0x18],
|
||||||
|
// Those are split in the ARM documentation for some reason..
|
||||||
|
_reserved_12: [u32; 0xE8],
|
||||||
|
/// Interrupt Configuration Registers
|
||||||
|
/// Interupt sensitivity register for software generated interrupts (SGI)
|
||||||
|
#[mmio(RO)]
|
||||||
|
pub icfr_0_sgi: u32,
|
||||||
|
/// Interupt sensitivity register for private peripheral interrupts (PPI)
|
||||||
|
#[mmio(RO)]
|
||||||
|
pub icfr_1_ppi: u32,
|
||||||
|
pub icfr_2_spi: u32,
|
||||||
|
pub icfr_3_spi: u32,
|
||||||
|
pub icfr_4_spi: u32,
|
||||||
|
pub icfr_5_spi: u32,
|
||||||
|
_reserved_13: [u32; 0x3A],
|
||||||
|
pub ppi_status: u32,
|
||||||
|
pub spi_status_0: u32,
|
||||||
|
pub spi_status_1: u32,
|
||||||
|
_reserved_14: [u32; 0x7D],
|
||||||
|
/// Software Generated Interrupt Register.
|
||||||
|
pub sgir: u32,
|
||||||
|
_reserved_15: [u32; 0x33],
|
||||||
|
pub pidr_4: u32,
|
||||||
|
pub pidr_5: u32,
|
||||||
|
pub pidr_6: u32,
|
||||||
|
pub pidr_7: u32,
|
||||||
|
pub pidr_0: u32,
|
||||||
|
pub pidr_1: u32,
|
||||||
|
pub pidr_2: u32,
|
||||||
|
pub pidr_3: u32,
|
||||||
|
pub cidr: [u32; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
const_assert_eq!(core::mem::size_of::<Gicd>(), 0x1000);
|
||||||
|
|
||||||
|
impl Gicd {
|
||||||
|
/// Create a new XGPIOPS GPIO MMIO instance.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||||
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
|
/// interfere with each other.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn new_mmio() -> MmioGicd<'static> {
|
||||||
|
unsafe { Self::_new_mmio(GICD_BASE_ADDR as *mut _) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CPU interface control register.
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct Icr {
|
||||||
|
#[bit(4, rw)]
|
||||||
|
sbpr: bool,
|
||||||
|
#[bit(3, rw)]
|
||||||
|
fiq_en: bool,
|
||||||
|
#[bit(2, rw)]
|
||||||
|
ack_ctrl: bool,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
enable_non_secure: bool,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
enable_secure: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Priority Mask Register
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct PriorityRegister {
|
||||||
|
#[bits(0..=7, rw)]
|
||||||
|
priority: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interrupt acknowledge register.
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct InterruptSignalRegister {
|
||||||
|
#[bits(10..=12, rw)]
|
||||||
|
cpu_id: u3,
|
||||||
|
#[bits(0..=9, rw)]
|
||||||
|
ack_int_id: u10,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// GIC CPU interface registers.
|
||||||
|
#[derive(derive_mmio::Mmio)]
|
||||||
|
#[mmio(no_ctors)]
|
||||||
|
#[repr(C, align(8))]
|
||||||
|
pub struct Gicc {
|
||||||
|
/// CPU Interface Control Register.
|
||||||
|
pub icr: Icr,
|
||||||
|
/// Interrupt Priority Mask Register.
|
||||||
|
pub pmr: PriorityRegister,
|
||||||
|
/// Binary Point Register.
|
||||||
|
pub bpr: u32,
|
||||||
|
/// Interrupt Acknowledge Register.
|
||||||
|
pub iar: InterruptSignalRegister,
|
||||||
|
/// End of Interrupt Register.
|
||||||
|
pub eoir: InterruptSignalRegister,
|
||||||
|
/// Running Priority Register.
|
||||||
|
pub rpr: PriorityRegister,
|
||||||
|
/// Highest Pending Interrupt Register.
|
||||||
|
pub hpir: InterruptSignalRegister,
|
||||||
|
/// Aliased Binary Point Register
|
||||||
|
pub abpr: u32,
|
||||||
|
_reserved_0: [u32; 0x37],
|
||||||
|
/// CPU Interface Identification Register.
|
||||||
|
#[mmio(RO)]
|
||||||
|
pub iidr: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
const_assert_eq!(core::mem::size_of::<Gicc>(), 0x100);
|
||||||
|
|
||||||
|
impl Gicc {
|
||||||
|
/// Create a new XGPIOPS GPIO MMIO instance.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||||
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
|
/// interfere with each other.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn new_mmio() -> MmioGicc<'static> {
|
||||||
|
unsafe { Self::_new_mmio(GICC_BASE_ADDR as *mut _) }
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,12 @@
|
|||||||
//! Global timer counter module.
|
//! Global timer counter module.
|
||||||
|
|
||||||
pub const GTC_BASE_ADDR: usize = super::MPCORE_BASE_ADDR + 0x0000_0200;
|
pub const GTC_BASE_ADDR: usize = crate::pac::mpcore::MPCORE_BASE_ADDR + 0x0000_0200;
|
||||||
|
|
||||||
|
/// Global timer counter.
|
||||||
#[derive(derive_mmio::Mmio)]
|
#[derive(derive_mmio::Mmio)]
|
||||||
#[mmio(no_ctors)]
|
#[mmio(no_ctors)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct GlobalTimerCounter {
|
pub struct Gtc {
|
||||||
/// Count register 0, lower 32 bits
|
/// Count register 0, lower 32 bits
|
||||||
count_lower: u32,
|
count_lower: u32,
|
||||||
/// Count register 1, upper 32 bits
|
/// Count register 1, upper 32 bits
|
||||||
@ -19,16 +20,12 @@ pub struct GlobalTimerCounter {
|
|||||||
/// Comparator 1, upper 32 bits
|
/// Comparator 1, upper 32 bits
|
||||||
comparator_upper: u32,
|
comparator_upper: u32,
|
||||||
/// Auto-increment register
|
/// Auto-increment register
|
||||||
auto_increment: u32
|
auto_increment: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Gtc = GlobalTimerCounter;
|
|
||||||
|
|
||||||
static_assertions::const_assert_eq!(core::mem::size_of::<Gtc>(), 0x1C);
|
static_assertions::const_assert_eq!(core::mem::size_of::<Gtc>(), 0x1C);
|
||||||
|
|
||||||
pub type MmioGtc = MmioGlobalTimerCounter<'static>;
|
impl Gtc {
|
||||||
|
|
||||||
impl GlobalTimerCounter {
|
|
||||||
/// Create a new GTC MMIO instance.
|
/// Create a new GTC MMIO instance.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@ -36,7 +33,8 @@ impl GlobalTimerCounter {
|
|||||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
/// interfere with each other.
|
/// interfere with each other.
|
||||||
pub const unsafe fn new_mmio() -> MmioGtc {
|
#[inline]
|
||||||
MmioGtc { ptr: GTC_BASE_ADDR as *mut Gtc, phantom: core::marker::PhantomData }
|
pub const unsafe fn new_mmio() -> MmioGtc<'static> {
|
||||||
|
unsafe { Gtc::_new_mmio(GTC_BASE_ADDR as *mut Gtc) }
|
||||||
}
|
}
|
||||||
}
|
}
|
6
zynq7000/src/pac/mod.rs
Normal file
6
zynq7000/src/pac/mod.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
pub mod gpio;
|
||||||
|
pub mod uart;
|
||||||
|
pub mod gtc;
|
||||||
|
pub mod slcr;
|
||||||
|
pub mod mpcore;
|
||||||
|
pub mod gic;
|
82
zynq7000/src/pac/mpcore.rs
Normal file
82
zynq7000/src/pac/mpcore.rs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
use static_assertions::const_assert_eq;
|
||||||
|
|
||||||
|
use crate::pac::{
|
||||||
|
gic::{Gicc, Gicd, MmioGicc, MmioGicd},
|
||||||
|
gtc::{Gtc, MmioGtc},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MPCORE_BASE_ADDR: usize = 0xF8F0_0000;
|
||||||
|
pub const SCU_BASE_ADDR: usize = MPCORE_BASE_ADDR;
|
||||||
|
pub const GICC_BASE_ADDR: usize = MPCORE_BASE_ADDR + 0x100;
|
||||||
|
pub const GICD_BASE_ADDR: usize = MPCORE_BASE_ADDR + 0x1000;
|
||||||
|
|
||||||
|
#[derive(derive_mmio::Mmio)]
|
||||||
|
#[mmio(no_ctors)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Scu {
|
||||||
|
ctrl: u32,
|
||||||
|
config: u32,
|
||||||
|
cpu_power_status: u32,
|
||||||
|
invalidate_all_regs_in_secure_state: u32,
|
||||||
|
_reserved_0: [u32; 0xC],
|
||||||
|
filtering_start_addr: u32,
|
||||||
|
filtering_end_addr: u32,
|
||||||
|
_reserved_1: [u32; 0x2],
|
||||||
|
access_ctrl: u32,
|
||||||
|
non_secure_access_ctrl: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scu {
|
||||||
|
/// Create a new Snoop Control Unit interface.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||||
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
|
/// interfere with each other.
|
||||||
|
#[inline]
|
||||||
|
pub const unsafe fn new_mmio() -> MmioScu<'static> {
|
||||||
|
unsafe { Self::_new_mmio(MPCORE_BASE_ADDR as *mut _) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const_assert_eq!(core::mem::size_of::<Scu>(), 0x58);
|
||||||
|
|
||||||
|
#[derive(derive_mmio::Mmio)]
|
||||||
|
#[mmio(no_ctors)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Mpcore {
|
||||||
|
#[mmio(inner)]
|
||||||
|
scu: Scu,
|
||||||
|
|
||||||
|
_reserved_0: [u32; 0x2A],
|
||||||
|
|
||||||
|
#[mmio(inner)]
|
||||||
|
gicc: Gicc,
|
||||||
|
|
||||||
|
#[mmio(inner)]
|
||||||
|
gt: Gtc,
|
||||||
|
|
||||||
|
_reserved_1: [u32; 0xF9],
|
||||||
|
|
||||||
|
private_timer_load: u32,
|
||||||
|
private_timer_counter: u32,
|
||||||
|
private_timer_ctrl: u32,
|
||||||
|
private_interrupt_status: u32,
|
||||||
|
|
||||||
|
_reserved_2: [u32; 0x4],
|
||||||
|
|
||||||
|
watchdog_load: u32,
|
||||||
|
watchdog_counter: u32,
|
||||||
|
watchdog_ctrl: u32,
|
||||||
|
watchdog_interrupt_status: u32,
|
||||||
|
watchdog_reset_status: u32,
|
||||||
|
watchdog_disable: u32,
|
||||||
|
|
||||||
|
_reserved_3: [u32; 0x272],
|
||||||
|
|
||||||
|
#[mmio(inner)]
|
||||||
|
gicd: Gicd,
|
||||||
|
}
|
||||||
|
|
||||||
|
const_assert_eq!(core::mem::size_of::<Mpcore>(), 0x2000);
|
Loading…
x
Reference in New Issue
Block a user