blob: b7dd21f35f3d83bf442b48cd232b60588aaa9e41 [file] [log] [blame]
Austin Applebyfe18d192021-10-27 18:22:56 -07001//! Timer driver.
2
Austin Applebyfe18d192021-10-27 18:22:56 -07003use kernel::common::cells::OptionalCell;
4use kernel::common::registers::{register_bitfields, register_structs, ReadWrite, WriteOnly};
5use kernel::common::StaticRef;
6use kernel::hil::time;
7use kernel::hil::time::{Ticks, Ticks64, Time};
8use kernel::ReturnCode;
9
Austin Applebycac7a5d2021-11-09 18:21:23 -080010const PRESCALE: u16 = ((crate::chip::CHIP_CPU_FREQ / 10_000) - 1) as u16; // 10Khz
Austin Applebyfe18d192021-10-27 18:22:56 -070011
12/// 10KHz `Frequency`
13#[derive(Debug)]
14pub struct Freq10KHz;
15impl time::Frequency for Freq10KHz {
16 fn frequency() -> u32 {
17 10_000
18 }
19}
20
21register_structs! {
22 pub TimerRegisters {
Austin Applebybad2b0e2022-01-20 15:26:20 -080023 // There's a bug in register_structs! - if the register map is
24 // non-contiguous, you have to put a read-only register at the end of
25 // each chunk or the addresses in the generated code are wrong. :/
26 (0x000 => alert_test: ReadWrite<u32>),
27 (0x004 => ctrl: ReadWrite<u32, ctrl::Register>),
28 (0x008 => _fake_register_to_fix_bug),
Austin Applebyfe18d192021-10-27 18:22:56 -070029
30 (0x100 => config: ReadWrite<u32, config::Register>),
31
32 (0x104 => value_low: ReadWrite<u32>),
33 (0x108 => value_high: ReadWrite<u32>),
34
35 (0x10c => compare_low: ReadWrite<u32>),
36 (0x110 => compare_high: ReadWrite<u32>),
37
38 (0x114 => intr_enable: ReadWrite<u32, intr::Register>),
39 (0x118 => intr_state: ReadWrite<u32, intr::Register>),
40 (0x11c => intr_test: WriteOnly<u32, intr::Register>),
41 (0x120 => @END),
42 }
43}
44
45register_bitfields![u32,
46 ctrl [
47 enable OFFSET(0) NUMBITS(1) []
48 ],
49 config [
50 prescale OFFSET(0) NUMBITS(12) [],
51 step OFFSET(16) NUMBITS(8) []
52 ],
53 intr [
54 timer0 OFFSET(0) NUMBITS(1) []
55 ]
56];
57
58pub struct RvTimer<'a> {
59 registers: StaticRef<TimerRegisters>,
60 alarm_client: OptionalCell<&'a dyn time::AlarmClient>,
61 overflow_client: OptionalCell<&'a dyn time::OverflowClient>,
62}
63
64impl<'a> RvTimer<'a> {
65 const fn new(base: StaticRef<TimerRegisters>) -> RvTimer<'a> {
66 RvTimer {
67 registers: base,
68 alarm_client: OptionalCell::empty(),
69 overflow_client: OptionalCell::empty(),
70 }
71 }
72
73 pub fn setup(&self) {
74 let regs = self.registers;
75 // Set proper prescaler and the like
76 regs.config
77 .write(config::prescale.val(PRESCALE as u32) + config::step.val(1u32));
78 regs.compare_high.set(0);
79 regs.value_low.set(0xFFFF_0000);
80 regs.intr_enable.write(intr::timer0::CLEAR);
Austin Applebybad2b0e2022-01-20 15:26:20 -080081 regs.ctrl.set(1);
Austin Applebyfe18d192021-10-27 18:22:56 -070082 }
83
84 pub fn service_interrupt(&self) {
85 let regs = self.registers;
86 regs.intr_enable.write(intr::timer0::CLEAR);
87 regs.intr_state.write(intr::timer0::SET);
88 self.alarm_client.map(|client| {
89 client.alarm();
90 });
91 }
92}
93
94impl time::Time for RvTimer<'_> {
95 type Frequency = Freq10KHz;
96 type Ticks = Ticks64;
97
98 fn now(&self) -> Ticks64 {
99 // RISC-V has a 64-bit counter but you can only read 32 bits
100 // at once, which creates a race condition if the lower register
101 // wraps between the reads. So the recommended approach is to read
102 // low, read high, read low, and if the second low is lower, re-read
103 // high. -pal 8/6/20
104 let first_low: u32 = self.registers.value_low.get();
105 let mut high: u32 = self.registers.value_high.get();
106 let second_low: u32 = self.registers.value_low.get();
107 if second_low < first_low {
108 // Wraparound
109 high = self.registers.value_high.get();
110 }
111 Ticks64::from(((high as u64) << 32) | second_low as u64)
112 }
113}
114
115impl<'a> time::Counter<'a> for RvTimer<'a> {
116 fn set_overflow_client(&'a self, client: &'a dyn time::OverflowClient) {
117 self.overflow_client.set(client);
118 }
119
120 fn start(&self) -> ReturnCode {
121 ReturnCode::SUCCESS
122 }
123
124 fn stop(&self) -> ReturnCode {
125 // RISCV counter can't be stopped...
126 ReturnCode::EBUSY
127 }
128
129 fn reset(&self) -> ReturnCode {
130 // RISCV counter can't be reset
131 ReturnCode::FAIL
132 }
133
134 fn is_running(&self) -> bool {
135 true
136 }
137}
138
139impl<'a> time::Alarm<'a> for RvTimer<'a> {
140 fn set_alarm_client(&self, client: &'a dyn time::AlarmClient) {
141 self.alarm_client.set(client);
142 }
143
144 fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
145 // This does not handle the 64-bit wraparound case.
146 // Because mtimer fires if the counter is >= the compare,
147 // handling wraparound requires setting compare to the
148 // maximum value, issuing a callback on the overflow client
149 // if there is one, spinning until it wraps around to 0, then
150 // setting the compare to the correct value.
151 let regs = self.registers;
152 let now = self.now();
153 let mut expire = reference.wrapping_add(dt);
154
155 if !now.within_range(reference, expire) {
156 expire = now;
157 }
158
159 let val = expire.into_u64();
160 let high = (val >> 32) as u32;
161 let low = (val & 0xffffffff) as u32;
162
163 // Recommended approach for setting the two compare registers
164 // (RISC-V Privileged Architectures 3.1.15) -pal 8/6/20
165 regs.compare_low.set(0xffffffff);
166 regs.compare_high.set(high);
167 regs.compare_low.set(low);
168 //debug!("TIMER: set to {}", expire.into_u64());
169 self.registers.intr_enable.write(intr::timer0::SET);
170 }
171
172 fn get_alarm(&self) -> Self::Ticks {
173 let mut val: u64 = (self.registers.compare_high.get() as u64) << 32;
174 val |= self.registers.compare_low.get() as u64;
175 Ticks64::from(val)
176 }
177
178 fn disarm(&self) -> ReturnCode {
179 // You clear the RISCV mtime interrupt by writing to the compare
180 // registers. Since the only way to do so is to set a new alarm,
181 // and this is also the only way to re-enable the interrupt, disabling
182 // the interrupt is sufficient. Calling set_alarm will clear the
183 // pending interrupt before re-enabling. -pal 8/6/20
184 self.registers.intr_enable.write(intr::timer0::CLEAR);
185 ReturnCode::SUCCESS
186 }
187
188 fn is_armed(&self) -> bool {
189 self.registers.intr_enable.is_set(intr::timer0)
190 }
191
192 fn minimum_dt(&self) -> Self::Ticks {
193 Self::Ticks::from(1 as u64)
194 }
195}
196
197const TIMER_BASE: StaticRef<TimerRegisters> =
198 unsafe { StaticRef::new(0x4010_0000 as *const TimerRegisters) };
199
200pub static mut TIMER: RvTimer = RvTimer::new(TIMER_BASE);