os/device/rtc/
rtc_goldfish.rs1use alloc::{string::String, sync::Arc};
2use fdt::node::FdtNode;
3
4use crate::{
5 device::{
6 DRIVERS, DeviceType, Driver, RTC_DRIVERS, device_tree::DEVICE_TREE_REGISTRY, rtc::RtcDriver,
7 },
8 kernel::current_memory_space,
9 mm::address::{Paddr, UsizeConvert},
10 pr_info, pr_warn,
11 util::read,
12};
13
14const TIMER_TIME_LOW: usize = 0x00;
15const TIMER_TIME_HIGH: usize = 0x04;
16
17pub struct RtcGoldfish {
18 base: usize,
19}
20
21impl Driver for RtcGoldfish {
22 fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
23 false
24 }
25
26 fn device_type(&self) -> DeviceType {
27 DeviceType::Rtc
28 }
29
30 fn get_id(&self) -> String {
31 String::from("rtc_goldfish")
32 }
33
34 fn as_rtc(&self) -> Option<&dyn RtcDriver> {
35 Some(self)
36 }
37}
38
39impl RtcDriver for RtcGoldfish {
40 fn read_epoch(&self) -> u64 {
42 let low: u32 = read(self.base + TIMER_TIME_LOW);
43 let high: u32 = read(self.base + TIMER_TIME_HIGH);
44 let ns = ((high as u64) << 32) | (low as u64);
45 ns / 1_000_000_000u64
46 }
47}
48
49fn init_dt(dt: &FdtNode) {
50 let reg = dt
51 .reg()
52 .and_then(|mut reg| reg.next())
53 .expect("No reg property found for goldfish-rtc");
54 let paddr = reg.starting_address as usize;
55 let size = reg.size.unwrap_or(0);
56 if size == 0 {
57 pr_warn!(
58 "[Device] goldfish-rtc device tree node {} has no size",
59 dt.name
60 );
61 return;
62 }
63 let vaddr = current_memory_space()
64 .lock()
65 .map_mmio(Paddr::from_usize(paddr), size)
66 .ok()
67 .expect("Failed to map MMIO region for goldfish-rtc");
68 let rtc = Arc::new(RtcGoldfish {
69 base: vaddr.as_usize(),
70 });
71 DRIVERS.write().push(rtc.clone());
72 RTC_DRIVERS.write().push(rtc);
73 pr_info!("[Device] RTC Goldfish initialized");
74}
75
76pub fn driver_init() {
77 DEVICE_TREE_REGISTRY
78 .write()
79 .insert("google,goldfish-rtc", init_dt);
80}