1use core::sync::atomic::{AtomicU32, Ordering};
6use cortexm7::support::atomic;
7use kernel::hil;
8use kernel::hil::time::{Ticks, Ticks32, Time};
9use kernel::platform::chip::ClockInterface;
10use kernel::utilities::cells::OptionalCell;
11use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
12use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
13use kernel::utilities::StaticRef;
14use kernel::ErrorCode;
15
16use crate::ccm;
17use crate::nvic;
18
19#[repr(C)]
21struct GptRegisters {
22 cr: ReadWrite<u32, CR::Register>,
24 pr: ReadWrite<u32, PR::Register>,
26 sr: ReadWrite<u32, SR::Register>,
28 ir: ReadWrite<u32, IR::Register>,
30 ocr1: ReadWrite<u32, OCR1::Register>,
32 ocr2: ReadWrite<u32, OCR2::Register>,
34 ocr3: ReadWrite<u32, OCR3::Register>,
36 icr1: ReadOnly<u32, ICR1::Register>,
38 icr2: ReadOnly<u32, ICR2::Register>,
40 cnt: ReadOnly<u32, CNT::Register>,
42}
43
44register_bitfields![u32,
45 CR [
46 FO3 OFFSET(31) NUMBITS(1) [],
48 FO2 OFFSET(30) NUMBITS(1) [],
50 FO1 OFFSET(29) NUMBITS(1) [],
52 OM3 OFFSET(26) NUMBITS(3) [],
54 OM2 OFFSET(23) NUMBITS(3) [],
56 OM1 OFFSET(20) NUMBITS(3) [],
58 IM2 OFFSET(18) NUMBITS(2) [],
60 IM1 OFFSET(16) NUMBITS(2) [],
62 SWR OFFSET(15) NUMBITS(1) [],
64 EN_24M OFFSET(10) NUMBITS(1) [],
66 FRR OFFSET(9) NUMBITS(1) [],
68 CLKSRC OFFSET(6) NUMBITS(3) [
70 NoClock = 0,
72 PeripheralClock = 1,
74 HighFrequencyReferenceClock = 2,
76 ExternalClock = 3,
78 LowFrequencyReferenceClock = 4,
80 CrystalOscillator = 5
82 ],
83 STOPEN OFFSET(5) NUMBITS(1) [],
85 DOZEEN OFFSET(4) NUMBITS(1) [],
87 WAITEN OFFSET(3) NUMBITS(1) [],
89 DBGEN OFFSET(2) NUMBITS(1) [],
91 ENMOD OFFSET(1) NUMBITS(1) [],
93 EN OFFSET(0) NUMBITS(1) []
95 ],
96
97 PR [
98 PRESCALER24M OFFSET(12) NUMBITS(4),
100 PRESCALER OFFSET(0) NUMBITS(12)
102 ],
103
104 SR [
105 ROV OFFSET(5) NUMBITS(1),
107 IF2 OFFSET(4) NUMBITS(1),
109 IF1 OFFSET(3) NUMBITS(1),
111 OF3 OFFSET(2) NUMBITS(1),
113 OF2 OFFSET(1) NUMBITS(1),
115 OF1 OFFSET(0) NUMBITS(1)
117 ],
118
119 IR [
120 ROVIE OFFSET(5) NUMBITS(1),
122 IF2IE OFFSET(4) NUMBITS(1),
124 IF1IE OFFSET(3) NUMBITS(1),
126 OF3IE OFFSET(2) NUMBITS(1),
128 OF2IE OFFSET(1) NUMBITS(1),
130 OF1IE OFFSET(0) NUMBITS(1)
132 ],
133
134 OCR1 [
135 COMP OFFSET(0) NUMBITS(32)
136 ],
137
138 OCR2 [
139 COMP OFFSET(0) NUMBITS(32)
140 ],
141
142 OCR3 [
143 COMP OFFSET(0) NUMBITS(32)
144 ],
145
146 ICR1 [
147 CAPT OFFSET(0) NUMBITS(32)
148 ],
149
150 ICR2 [
151 CAPT OFFSET(0) NUMBITS(32)
152 ],
153
154 CNT [
155 COUNT OFFSET(0) NUMBITS(32)
156 ]
157];
158
159const GPT1_BASE: StaticRef<GptRegisters> =
160 unsafe { StaticRef::new(0x401EC000 as *const GptRegisters) };
161const GPT2_BASE: StaticRef<GptRegisters> =
162 unsafe { StaticRef::new(0x401F0000 as *const GptRegisters) };
163
164pub struct Gpt<'a, S> {
165 registers: StaticRef<GptRegisters>,
166 clock: GptClock<'a>,
167 client: OptionalCell<&'a dyn hil::time::AlarmClient>,
168 irqn: u32,
169 _selection: core::marker::PhantomData<S>,
170}
171
172pub type Gpt1<'a> = Gpt<'a, _1>;
173pub type Gpt2<'a> = Gpt<'a, _2>;
174
175impl<'a> Gpt1<'a> {
176 pub const fn new_gpt1(ccm: &'a crate::ccm::Ccm) -> Self {
177 Gpt::new(
178 GPT1_BASE,
179 nvic::GPT1,
180 ccm::PeripheralClock::ccgr1(ccm, ccm::HCLK1::GPT1),
181 )
182 }
183}
184
185impl<'a> Gpt2<'a> {
186 pub const fn new_gpt2(ccm: &'a crate::ccm::Ccm) -> Self {
187 Gpt::new(
188 GPT2_BASE,
189 nvic::GPT2,
190 ccm::PeripheralClock::ccgr0(ccm, ccm::HCLK0::GPT2),
191 )
192 }
193}
194
195impl<'a, S> Gpt<'a, S> {
196 const fn new(
197 registers: StaticRef<GptRegisters>,
198 irqn: u32,
199 clock_gate: ccm::PeripheralClock<'a>,
200 ) -> Self {
201 Gpt {
202 registers,
203 clock: GptClock(clock_gate),
204 client: OptionalCell::empty(),
205 irqn,
206 _selection: core::marker::PhantomData,
207 }
208 }
209
210 pub fn is_enabled_clock(&self) -> bool {
211 self.clock.is_enabled()
212 }
213
214 pub fn enable_clock(&self) {
215 self.clock.enable();
216 }
217
218 pub fn disable_clock(&self) {
219 self.clock.disable();
220 }
221
222 pub fn handle_interrupt(&self) {
223 self.registers.sr.modify(SR::OF1::SET);
224 self.registers.ir.modify(IR::OF1IE::CLEAR);
225
226 self.client.map(|client| client.alarm());
227 }
228
229 pub fn start(&self, selection: ccm::PerclkClockSel, divider: u8) {
236 self.registers.cr.modify(CR::EN::CLEAR);
238
239 self.registers.ir.modify(IR::ROVIE::CLEAR);
240 self.registers.ir.modify(IR::IF1IE::CLEAR);
241 self.registers.ir.modify(IR::IF2IE::CLEAR);
242 self.registers.ir.modify(IR::OF1IE::CLEAR);
243 self.registers.ir.modify(IR::OF2IE::CLEAR);
244 self.registers.ir.modify(IR::OF3IE::CLEAR);
245
246 self.registers.cr.modify(CR::OM1::CLEAR);
248 self.registers.cr.modify(CR::OM2::CLEAR);
249 self.registers.cr.modify(CR::OM3::CLEAR);
250
251 self.registers.cr.modify(CR::IM1::CLEAR);
253 self.registers.cr.modify(CR::IM2::CLEAR);
254
255 self.registers.cr.modify(CR::SWR::SET);
258
259 while self.registers.cr.is_set(CR::SWR) {}
261
262 self.registers.sr.set(31_u32);
264
265 self.registers.cr.modify(CR::FRR::SET);
267
268 self.registers.cr.modify(CR::WAITEN::SET);
270
271 self.registers.cr.modify(CR::STOPEN::SET);
273
274 self.registers.cr.modify(CR::ENMOD::SET);
276
277 self.registers.ocr1.set(0xFFFF_FFFF - 1);
279
280 match selection {
281 ccm::PerclkClockSel::IPG => {
282 self.registers.cr.modify(CR::EN_24M::CLEAR);
284
285 self.registers.cr.modify(CR::CLKSRC.val(0x2_u32));
289
290 self.registers.pr.modify(PR::PRESCALER.val(0_u32));
293
294 self.set_frequency(IMXRT1050_IPG_CLOCK_HZ / divider as u32);
295 }
296 ccm::PerclkClockSel::Oscillator => {
297 self.registers
299 .cr
300 .modify(CR::EN_24M::SET + CR::CLKSRC::CrystalOscillator);
301
302 const DEFAULT_PRESCALER: u32 = 3;
310 self.registers
311 .pr
312 .write(PR::PRESCALER24M.val(DEFAULT_PRESCALER - 1));
313 self.set_frequency(OSCILLATOR_HZ / DEFAULT_PRESCALER / divider as u32);
314 }
315 }
316
317 self.registers.cr.modify(CR::EN::SET);
319
320 self.registers.ir.modify(IR::OF1IE::SET);
322 }
323
324 fn set_frequency(&self, hz: u32) {
325 let idx = match self.irqn {
326 nvic::GPT1 => 0,
327 nvic::GPT2 => 1,
328 _ => unreachable!(),
329 };
330 GPT_FREQUENCIES[idx].store(hz, Ordering::Release);
331 }
332}
333
334const IMXRT1050_IPG_CLOCK_HZ: u32 = 24_750_000;
339const OSCILLATOR_HZ: u32 = 24_000_000;
341
342pub enum _1 {}
344pub enum _2 {}
345
346static GPT_FREQUENCIES: [AtomicU32; 2] = [AtomicU32::new(0), AtomicU32::new(0)];
347
348impl hil::time::Frequency for _1 {
349 fn frequency() -> u32 {
350 GPT_FREQUENCIES[0].load(Ordering::Acquire)
351 }
352}
353
354impl hil::time::Frequency for _2 {
355 fn frequency() -> u32 {
356 GPT_FREQUENCIES[1].load(Ordering::Acquire)
357 }
358}
359
360impl<F: hil::time::Frequency> hil::time::Time for Gpt<'_, F> {
361 type Frequency = F;
362 type Ticks = Ticks32;
363
364 fn now(&self) -> Ticks32 {
365 Ticks32::from(self.registers.cnt.get())
366 }
367}
368
369impl<'a, F: hil::time::Frequency> hil::time::Alarm<'a> for Gpt<'a, F> {
370 fn set_alarm_client(&self, client: &'a dyn hil::time::AlarmClient) {
371 self.client.set(client);
372 }
373
374 fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
375 let mut expire = reference.wrapping_add(dt);
376 let now = self.now();
377 if !now.within_range(reference, expire) {
378 expire = now;
379 }
380
381 if expire.wrapping_sub(now) < self.minimum_dt() {
382 expire = now.wrapping_add(self.minimum_dt());
383 }
384
385 let _ = self.disarm();
386 self.registers.ocr1.set(expire.into_u32());
387 self.registers.ir.modify(IR::OF1IE::SET);
388 }
389
390 fn get_alarm(&self) -> Self::Ticks {
391 Self::Ticks::from(self.registers.ocr1.get())
392 }
393
394 fn disarm(&self) -> Result<(), ErrorCode> {
395 unsafe {
396 atomic(|| {
397 self.registers.ir.modify(IR::OF1IE::CLEAR);
399 cortexm7::nvic::Nvic::new(self.irqn).clear_pending();
400 });
401 }
402 Ok(())
403 }
404
405 fn is_armed(&self) -> bool {
406 self.registers.ir.is_set(IR::OF1IE)
408 }
409
410 fn minimum_dt(&self) -> Self::Ticks {
411 Self::Ticks::from(1)
412 }
413}
414
415struct GptClock<'a>(ccm::PeripheralClock<'a>);
416
417impl ClockInterface for GptClock<'_> {
418 fn is_enabled(&self) -> bool {
419 self.0.is_enabled()
420 }
421
422 fn enable(&self) {
423 self.0.enable();
424 }
425
426 fn disable(&self) {
427 self.0.disable();
428 }
429}