axplat_aarch64_peripherals/pl031.rs
1//! PL031 Real Time Clock (RTC) driver.
2
3use arm_pl031::Rtc;
4use axplat::mem::VirtAddr;
5
6use crate::generic_timer::{current_ticks, ticks_to_nanos};
7
8/// RTC wall time offset in nanoseconds at monotonic time base.
9static mut RTC_EPOCHOFFSET_NANOS: u64 = 0;
10
11/// Return epoch offset in nanoseconds (wall time offset to monotonic clock start).
12#[inline]
13pub fn epochoffset_nanos() -> u64 {
14 unsafe { RTC_EPOCHOFFSET_NANOS }
15}
16
17/// Early stage initialization of the RTC driver.
18///
19/// It reads the current real time and calculates the epoch offset.
20pub fn init_early(rtc_base: VirtAddr) {
21 // Make sure `RTC_PADDR` is valid in platform config file.
22 if rtc_base.as_usize() == 0 {
23 return;
24 }
25
26 let rtc = unsafe { Rtc::new(rtc_base.as_mut_ptr() as _) };
27
28 // Get the current time in microseconds since the epoch (1970-01-01) from the aarch64 pl031 RTC.
29 // Subtract the timer ticks to get the actual time when ArceOS was booted.
30 let epoch_time_nanos = rtc.get_unix_timestamp() as u64 * 1_000_000_000;
31
32 unsafe {
33 RTC_EPOCHOFFSET_NANOS = epoch_time_nanos - ticks_to_nanos(current_ticks());
34 }
35}