From 6469914be1444764f59ce418b6f4d654e2b4cacd Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Thu, 14 Aug 2025 15:17:41 +0300 Subject: [PATCH] rtc: implement google,goldfish-rtc --- kernel/driver/bsp/riscv/src/goldfish_rtc.rs | 70 +++++++++++++++++++++ kernel/driver/bsp/riscv/src/lib.rs | 1 + 2 files changed, 71 insertions(+) create mode 100644 kernel/driver/bsp/riscv/src/goldfish_rtc.rs diff --git a/kernel/driver/bsp/riscv/src/goldfish_rtc.rs b/kernel/driver/bsp/riscv/src/goldfish_rtc.rs new file mode 100644 index 00000000..a62a3810 --- /dev/null +++ b/kernel/driver/bsp/riscv/src/goldfish_rtc.rs @@ -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), + (0x04 => TIME_HIGH: ReadOnly), + (0x08 => ALARM_LOW: ReadWrite), + (0x0C => ALARM_HIGH: ReadWrite), + (0x10 => IRQ_ENABLED: ReadWrite), + (0x14 => CLEAR_ALARM: ReadWrite), + (0x18 => ALARM_STATUS: ReadOnly), + (0x1C => CLEAR_INTERRUPT: ReadWrite), + (0x20 => @END), + } +} + +struct Rtc { + regs: IrqSafeSpinlock>, +} + +impl SysfsRtcNode for Rtc { + fn read(&self) -> Result { + 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, _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, context: &mut ProbeContext) -> Option> { + 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) + } + } +} diff --git a/kernel/driver/bsp/riscv/src/lib.rs b/kernel/driver/bsp/riscv/src/lib.rs index 98a7f8ec..d2fdadb6 100644 --- a/kernel/driver/bsp/riscv/src/lib.rs +++ b/kernel/driver/bsp/riscv/src/lib.rs @@ -3,4 +3,5 @@ extern crate alloc; +mod goldfish_rtc; mod plic;