macro_rules! generate_gic_registers {
(
// Single register definitions
singles {
$(
$single_name:ident = $single_offset:expr // Single register name and offset
),* $(,)?
}
// Range register definitions
ranges {
$(
$range_name:ident = {
offset: $range_offset:expr, // Range register base offset
size: $range_size:expr // Number of registers in the range
}
),* $(,)?
}
) => {
#[allow(clippy::enum_variant_names)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GicRegister {
$(
$single_name, )*
$(
$range_name(u32), )*
}
impl GicRegister {
pub fn from_addr(addr: u32) -> Option<Self> {
match addr {
$(
addr if addr == $single_offset => Some(Self::$single_name), )*
$(
addr if ($range_offset..$range_offset + ($range_size * 4)).contains(&addr) => {
let idx = (addr - $range_offset) / 4; if idx < $range_size {
Some(Self::$range_name(idx)) } else {
None
}
},
)*
_ => None, }
}
}
};
}
generate_gic_registers! {
singles {
GicdCtlr = 0x0000,
GicdTyper = 0x0004,
GicdIidr = 0x0008,
GicdStatusr = 0x0010,
}
ranges {
GicdIgroupr = {
offset: 0x0080,
size: 32
},
GicdIsenabler = {
offset: 0x0100,
size: 32
},
GicdIcenabler = {
offset: 0x0180,
size: 32
},
GicdIspendr = {
offset: 0x0200,
size: 32
},
GicdIcpendr = {
offset: 0x0280,
size: 32
},
GicdIsactiver = {
offset: 0x0300,
size: 32
},
GicdIcactiver = {
offset: 0x0380,
size: 32
},
GicdIpriorityr = {
offset: 0x0400,
size: 256
},
GicdItargetsr = {
offset: 0x0800,
size: 256
},
GicdIcfgr = {
offset: 0x0c00,
size: 64
},
GicdPpisr = {
offset: 0x0d00,
size: 32
},
GicdSpisr = {
offset: 0x0d04,
size: 32
},
GicdNsacr = {
offset: 0x0e00,
size: 32
},
GicdSgir = {
offset: 0x0f00,
size: 32
},
GicdCpendsgir = {
offset: 0x0f10,
size: 32
},
GicdSpendsgir = {
offset: 0x0f20,
size: 32
},
}
}