axplat_aarch64_peripherals/
generic_timer.rs1use aarch64_cpu::registers::{CNTFRQ_EL0, CNTP_TVAL_EL0, CNTPCT_EL0};
4use aarch64_cpu::registers::{Readable, Writeable};
5use int_ratio::Ratio;
6
7static mut CNTPCT_TO_NANOS_RATIO: Ratio = Ratio::zero();
8static mut NANOS_TO_CNTPCT_RATIO: Ratio = Ratio::zero();
9
10#[inline]
12pub fn current_ticks() -> u64 {
13 CNTPCT_EL0.get()
14}
15
16#[inline]
18pub fn ticks_to_nanos(ticks: u64) -> u64 {
19 unsafe { CNTPCT_TO_NANOS_RATIO.mul_trunc(ticks) }
20}
21
22#[inline]
24pub fn nanos_to_ticks(nanos: u64) -> u64 {
25 unsafe { NANOS_TO_CNTPCT_RATIO.mul_trunc(nanos) }
26}
27
28pub fn set_oneshot_timer(deadline_ns: u64) {
32 let cnptct = CNTPCT_EL0.get();
33 let cnptct_deadline = nanos_to_ticks(deadline_ns);
34 if cnptct < cnptct_deadline {
35 let interval = cnptct_deadline - cnptct;
36 debug_assert!(interval <= u32::MAX as u64);
37 CNTP_TVAL_EL0.set(interval);
38 } else {
39 CNTP_TVAL_EL0.set(0);
40 }
41}
42
43pub fn init_early() {
45 let freq = CNTFRQ_EL0.get();
46 unsafe {
47 CNTPCT_TO_NANOS_RATIO = Ratio::new(axplat::time::NANOS_PER_SEC as u32, freq as u32);
48 NANOS_TO_CNTPCT_RATIO = CNTPCT_TO_NANOS_RATIO.inverse();
49 }
50}
51
52#[cfg(feature = "irq")]
57pub fn enable_irqs(timer_irq_num: usize) {
58 use aarch64_cpu::registers::CNTP_CTL_EL0;
59 CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET);
60 CNTP_TVAL_EL0.set(0);
61 axplat::irq::set_enable(timer_irq_num, true);
62}
63
64#[macro_export]
67macro_rules! time_if_impl {
68 ($name:ident) => {
69 struct $name;
70
71 #[impl_plat_interface]
72 impl axplat::time::TimeIf for $name {
73 fn current_ticks() -> u64 {
75 $crate::generic_timer::current_ticks()
76 }
77
78 fn ticks_to_nanos(ticks: u64) -> u64 {
80 $crate::generic_timer::ticks_to_nanos(ticks)
81 }
82
83 fn nanos_to_ticks(nanos: u64) -> u64 {
85 $crate::generic_timer::nanos_to_ticks(nanos)
86 }
87
88 fn epochoffset_nanos() -> u64 {
91 $crate::pl031::epochoffset_nanos()
92 }
93
94 #[cfg(feature = "irq")]
99 fn set_oneshot_timer(deadline_ns: u64) {
100 $crate::generic_timer::set_oneshot_timer(deadline_ns)
101 }
102 }
103 };
104}