use aarch64_cpu::registers::{CNTPCT_EL0, Readable};
use aarch64_sysreg::SystemRegType;
use axdevice_base::{
AccessWidth, BusAccess, BusKind, BusResponse, Device, DeviceAccess, DeviceError, DeviceResult,
Resource,
};
use log::debug;
const CNTPCT_EL0_ADDR: u32 = SystemRegType::CNTPCT_EL0 as u32;
impl SysCntpctEl0 {
pub fn read_register(&self, _width: AccessWidth) -> DeviceResult<usize> {
Ok(CNTPCT_EL0.get() as usize)
}
pub fn write_register(&self, _width: AccessWidth, val: usize) -> DeviceResult {
debug!("Write to read-only virtual counter register CNTPCT_EL0, value: {val}");
Ok(())
}
}
pub struct SysCntpctEl0 {
resources: [Resource; 1],
}
impl SysCntpctEl0 {
pub fn new() -> Self {
Self {
resources: [Resource::SysReg {
addr: CNTPCT_EL0_ADDR,
count: 1,
}],
}
}
}
impl Default for SysCntpctEl0 {
fn default() -> Self {
Self::new()
}
}
impl Device for SysCntpctEl0 {
fn name(&self) -> &str {
"aarch64-cntpct-el0"
}
fn resources(&self) -> &[Resource] {
&self.resources
}
fn access(
&self,
access: &BusAccess,
_context: &mut dyn DeviceAccess,
) -> Result<BusResponse, DeviceError> {
if access.kind != BusKind::SysReg || access.addr != CNTPCT_EL0_ADDR as u64 {
return Err(DeviceError::OutOfRange { addr: access.addr });
}
if access.is_read {
self.read_register(access.width)
.map(|value| BusResponse::Read {
value: value as u64,
})
} else {
self.write_register(access.width, access.data as usize)
.map(|_| BusResponse::Write)
}
}
}