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}