Skip to main content

arm_generic_timer/
sysreg.rs

1// SPDX-FileCopyrightText: Copyright The arm-generic-timer Contributors.
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use crate::TimerInterface;
5#[cfg(feature = "el2")]
6use arm_sysregs::{
7    CnthpCtlEl2, CnthpsCtlEl2, CnthvCtlEl2, CnthvsCtlEl2, read_cnthp_ctl_el2, read_cnthp_tval_el2,
8    read_cnthps_ctl_el2, read_cnthps_tval_el2, read_cnthv_ctl_el2, read_cnthv_tval_el2,
9    read_cnthvs_ctl_el2, read_cnthvs_tval_el2, write_cnthp_ctl_el2, write_cnthps_ctl_el2,
10    write_cnthv_ctl_el2, write_cnthvs_ctl_el2,
11};
12use arm_sysregs::{
13    CntpCtlEl0, CntvCtlEl0, read_cntfrq_el0, read_cntp_ctl_el0, read_cntp_tval_el0,
14    read_cntv_ctl_el0, read_cntv_tval_el0, write_cntp_ctl_el0, write_cntv_ctl_el0,
15};
16#[cfg(feature = "el1")]
17use arm_sysregs::{CntpsCtlEl1, read_cntps_ctl_el1, read_cntps_tval_el1, write_cntps_ctl_el1};
18
19/// Physical Secure Timer
20///
21/// Uses `CNTPS_*` system registers.
22#[cfg(feature = "el1")]
23pub struct PhysicalSecureTimer;
24
25#[cfg(feature = "el1")]
26impl TimerInterface for PhysicalSecureTimer {
27    fn enable(&mut self) {
28        let control = read_cntps_ctl_el1();
29        write_cntps_ctl_el1(control | CntpsCtlEl1::ENABLE);
30    }
31
32    fn frequency(&self) -> u32 {
33        read_cntfrq_el0().clockfreq()
34    }
35
36    fn timer_value(&self) -> u32 {
37        read_cntps_tval_el1().timervalue()
38    }
39}
40
41/// Hypervisor Physical Timer
42///
43/// Uses `CNTHP_*` system registers.
44#[cfg(feature = "el2")]
45pub struct HypervisorPhysicalTimer;
46
47#[cfg(feature = "el2")]
48impl TimerInterface for HypervisorPhysicalTimer {
49    fn enable(&mut self) {
50        let control = read_cnthp_ctl_el2();
51        write_cnthp_ctl_el2(control | CnthpCtlEl2::ENABLE);
52    }
53
54    fn frequency(&self) -> u32 {
55        read_cntfrq_el0().clockfreq()
56    }
57
58    fn timer_value(&self) -> u32 {
59        read_cnthp_tval_el2().timervalue()
60    }
61}
62
63/// Secure EL2 Physical Timer
64///
65/// Uses `CNTHPS_*` system registers.
66#[cfg(feature = "el2")]
67pub struct SecureEl2PhysicalTimer;
68
69#[cfg(feature = "el2")]
70impl TimerInterface for SecureEl2PhysicalTimer {
71    fn enable(&mut self) {
72        let control = read_cnthps_ctl_el2();
73        write_cnthps_ctl_el2(control | CnthpsCtlEl2::ENABLE);
74    }
75
76    fn frequency(&self) -> u32 {
77        read_cntfrq_el0().clockfreq()
78    }
79
80    fn timer_value(&self) -> u32 {
81        read_cnthps_tval_el2().timervalue()
82    }
83}
84
85/// EL2 Virtual Timer
86///
87/// Uses `CNTHV_*` system registers
88#[cfg(feature = "el2")]
89pub struct El2VirtualTimer;
90
91#[cfg(feature = "el2")]
92impl TimerInterface for El2VirtualTimer {
93    fn enable(&mut self) {
94        let control = read_cnthv_ctl_el2();
95        write_cnthv_ctl_el2(control | CnthvCtlEl2::ENABLE);
96    }
97
98    fn frequency(&self) -> u32 {
99        read_cntfrq_el0().clockfreq()
100    }
101
102    fn timer_value(&self) -> u32 {
103        read_cnthv_tval_el2().timervalue()
104    }
105}
106
107/// Secure EL2 Virtual Timer
108///
109/// Uses `CNTHVS_*` system registers
110#[cfg(feature = "el2")]
111pub struct SecureEl2VirtualTimer;
112
113#[cfg(feature = "el2")]
114impl TimerInterface for SecureEl2VirtualTimer {
115    fn enable(&mut self) {
116        let control = read_cnthvs_ctl_el2();
117        write_cnthvs_ctl_el2(control | CnthvsCtlEl2::ENABLE);
118    }
119
120    fn frequency(&self) -> u32 {
121        read_cntfrq_el0().clockfreq()
122    }
123
124    fn timer_value(&self) -> u32 {
125        read_cnthvs_tval_el2().timervalue()
126    }
127}
128
129/// Physical Timer
130///
131/// Uses `CNTP_*` system registers.
132pub struct PhysicalTimer;
133
134impl TimerInterface for PhysicalTimer {
135    fn enable(&mut self) {
136        let control = read_cntp_ctl_el0();
137        write_cntp_ctl_el0(control | CntpCtlEl0::ENABLE);
138    }
139
140    fn frequency(&self) -> u32 {
141        read_cntfrq_el0().clockfreq()
142    }
143
144    fn timer_value(&self) -> u32 {
145        read_cntp_tval_el0().timervalue()
146    }
147}
148
149/// Virtual Timer
150///
151/// Uses `CNTV_*` system registers.
152pub struct VirtualTimer;
153
154impl TimerInterface for VirtualTimer {
155    fn enable(&mut self) {
156        let control = read_cntv_ctl_el0();
157        write_cntv_ctl_el0(control | CntvCtlEl0::ENABLE);
158    }
159
160    fn frequency(&self) -> u32 {
161        read_cntfrq_el0().clockfreq()
162    }
163
164    fn timer_value(&self) -> u32 {
165        read_cntv_tval_el0().timervalue()
166    }
167}