os/device/rtc/
rtc_goldfish.rs

1use 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    // read seconds since 1970-01-01
41    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}