rtc: implement google,goldfish-rtc
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
use alloc::sync::Arc;
|
||||
use device_api::device::{Device, DeviceInitContext};
|
||||
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
|
||||
use libk::{
|
||||
error::Error,
|
||||
fs::sysfs::{self, nodes::SysfsRtcNode},
|
||||
};
|
||||
use libk_mm::device::DeviceMemoryIo;
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
use tock_registers::{
|
||||
interfaces::Readable,
|
||||
register_structs,
|
||||
registers::{ReadOnly, ReadWrite},
|
||||
};
|
||||
use yggdrasil_abi::time::NANOSECONDS_IN_SECOND;
|
||||
|
||||
register_structs! {
|
||||
#[allow(non_snake_case)]
|
||||
Regs {
|
||||
(0x00 => TIME_LOW: ReadOnly<u32>),
|
||||
(0x04 => TIME_HIGH: ReadOnly<u32>),
|
||||
(0x08 => ALARM_LOW: ReadWrite<u32>),
|
||||
(0x0C => ALARM_HIGH: ReadWrite<u32>),
|
||||
(0x10 => IRQ_ENABLED: ReadWrite<u32>),
|
||||
(0x14 => CLEAR_ALARM: ReadWrite<u32>),
|
||||
(0x18 => ALARM_STATUS: ReadOnly<u32>),
|
||||
(0x1C => CLEAR_INTERRUPT: ReadWrite<u32>),
|
||||
(0x20 => @END),
|
||||
}
|
||||
}
|
||||
|
||||
struct Rtc {
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
}
|
||||
|
||||
impl SysfsRtcNode for Rtc {
|
||||
fn read(&self) -> Result<u64, Error> {
|
||||
let regs = self.regs.lock();
|
||||
let low = regs.TIME_LOW.get();
|
||||
let high = regs.TIME_HIGH.get();
|
||||
let t = ((high as u64) << 32) | (low as u64);
|
||||
Ok(t / NANOSECONDS_IN_SECOND)
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Rtc {
|
||||
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
|
||||
sysfs::nodes::add_rtc_node(self.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
"Google Goldfish RTC"
|
||||
}
|
||||
}
|
||||
|
||||
device_tree_driver! {
|
||||
compatible: ["google,goldfish-rtc"],
|
||||
driver: {
|
||||
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
|
||||
let base = node.map_base(context, 0)?;
|
||||
|
||||
let regs = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?;
|
||||
|
||||
let rtc = Arc::new(Rtc { regs: IrqSafeSpinlock::new(regs) });
|
||||
|
||||
Some(rtc)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,5 @@
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
mod goldfish_rtc;
|
||||
mod plic;
|
||||
|
||||
Reference in New Issue
Block a user