blob: 9f3ee4ffb90aaa5816730bca7bab34683bd43d33 [file]
// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0
//! Timer driver wrapper for the Earlgrey target.
use rv_timer::RvTimer;
/// A driver for the OpenTitan RISC-V timer (RvTimer).
///
/// It provides access to the 64-bit system tick counter.
pub struct EarlGreyTimer {
device: RvTimer,
}
impl EarlGreyTimer {
/// Creates a new `EarlGreyTimer` instance.
///
/// # Safety
///
/// The caller must ensure that no other driver instance is concurrently writing
/// to the timer hardware configuration. Reading the timer value is always safe.
pub const unsafe fn new() -> Self {
Self {
device: unsafe { RvTimer::new() },
}
}
/// Reads the current 64-bit timer ticks.
///
/// This method performs a safe double-read of the high 32-bit register
/// to handle potential carry-over/overflow while reading the low 32-bit register
/// on 32-bit CPU architectures.
pub fn read_ticks(&self) -> u64 {
let regs = self.device.regs();
loop {
let hi1 = regs.timer_v_upper0().read();
let low = regs.timer_v_lower0().read();
let hi2 = regs.timer_v_upper0().read();
if hi1 == hi2 {
return ((hi1 as u64) << 32) | (low as u64);
}
}
}
}