1#![allow(clippy::from_over_into)]
9
10use atsamd_hal_macros::hal_macro_helper;
11
12use fugit::RateExtU32;
13
14use crate::clock::v2::pclk::{Pclk, PclkSourceId, ids::*};
15use crate::pac::gclk::genctrl::Srcselect::*;
16use crate::pac::gclk::pchctrl::Genselect::*;
17use crate::pac::{self, Gclk, Mclk, Nvmctrl, Osc32kctrl, Oscctrl};
18use crate::sercom::*;
19use crate::time::Hertz;
20
21pub type ClockGenId = pac::gclk::pchctrl::Genselect;
22pub type ClockSource = pac::gclk::genctrl::Srcselect;
23
24#[allow(non_camel_case_types)]
25pub enum ClockId {
26 DFLL48 = 0,
27 FDPLL0,
28 FDPLL1,
29 SLOW_32K,
30 EIC,
31 FREQM_MSR,
32 FREQM_REF,
33 SERCOM0_CORE,
34 SERCOM1_CORE,
35 TC0_TC1,
36 USB,
37 EVSYS0,
38 EVSYS1,
39 EVSYS2,
40 EVSYS3,
41 EVSYS4,
42 EVSYS5,
43 EVSYS6,
44 EVSYS7,
45 EVSYS8,
46 EVSYS9,
47 EVSYS10,
48 EVSYS11,
49 SERCOM2_CORE,
50 SERCOM3_CORE,
51 TCC0_TCC1,
52 TC2_TC3,
53 CAN0,
54 CAN1,
55 TCC2_TCC3,
56 TC4_TC5,
57 PDEC,
58 AC,
59 CCL,
60 SERCOM4_CORE,
61 SERCOM5_CORE,
62 SERCOM6_CORE,
63 SERCOM7_CORE,
64 TCC4,
65 TC6_TC7,
66 ADC0,
67 ADC1,
68 DAC,
69 I2S0,
70 I2S1,
71 SDHC0,
72 SDHC1,
73 CM4_TRACE,
74}
75
76impl From<ClockId> for u8 {
77 fn from(clock: ClockId) -> u8 {
78 clock as u8
79 }
80}
81
82pub struct GClock {
90 gclk: ClockGenId,
91 freq: Hertz,
92}
93
94impl Into<Hertz> for GClock {
95 fn into(self) -> Hertz {
96 self.freq
97 }
98}
99
100struct State {
101 gclk: Gclk,
102}
103
104impl State {
105 fn reset_gclk(&mut self) {
106 self.gclk.ctrla().write(|w| w.swrst().set_bit());
107 while self.gclk.ctrla().read().swrst().bit_is_set()
108 || self.gclk.syncbusy().read().bits() != 0
109 {}
110 }
111
112 fn wait_for_sync(&mut self) {
113 while self.gclk.syncbusy().read().bits() != 0 {}
114 }
115
116 fn set_gclk_divider_and_source(
117 &mut self,
118 gclk: ClockGenId,
119 divider: u16,
120 src: ClockSource,
121 improve_duty_cycle: bool,
122 ) {
123 let mut divisor_invalid = false;
125 if gclk == Gclk1 {
126 if divider as u32 >= 2_u32.pow(16) {
127 divisor_invalid = true;
128 }
129 } else if divider >= 2_u16.pow(8) {
130 divisor_invalid = true;
131 }
132 if divisor_invalid {
133 panic!("invalid divisor {} for Gclk {}", divider, gclk as u8);
134 }
135
136 self.gclk
137 .genctrl(u8::from(gclk) as usize)
138 .write(|w| unsafe {
139 w.src().variant(src);
140 w.div().bits(divider);
141 w.divsel().clear_bit();
143 w.idc().bit(improve_duty_cycle);
144 w.genen().set_bit();
145 w.oe().set_bit()
146 });
147
148 self.wait_for_sync();
149 }
150
151 fn enable_clock_generator(&mut self, clock: ClockId, generator: ClockGenId) {
152 self.gclk
153 .pchctrl(u8::from(clock) as usize)
154 .write(|w| unsafe {
155 w.r#gen().bits(generator.into());
156 w.chen().set_bit()
157 });
158 self.wait_for_sync();
159 }
160
161 fn configure_standby(&mut self, gclk: ClockGenId, enable: bool) {
162 self.gclk
163 .genctrl(u8::from(gclk) as usize)
164 .modify(|_, w| w.runstdby().bit(enable));
165 self.wait_for_sync();
166 }
167}
168
169pub struct GenericClockController {
177 state: State,
178 gclks: [Hertz; 12],
179 used_clocks: u64,
180}
181
182impl GenericClockController {
183 pub fn with_internal_32kosc(
186 gclk: Gclk,
187 mclk: &mut Mclk,
188 osc32kctrl: &mut Osc32kctrl,
189 oscctrl: &mut Oscctrl,
190 nvmctrl: &mut Nvmctrl,
191 ) -> Self {
192 Self::new(gclk, mclk, osc32kctrl, oscctrl, nvmctrl, false)
193 }
194
195 pub fn with_external_32kosc(
198 gclk: Gclk,
199 mclk: &mut Mclk,
200 osc32kctrl: &mut Osc32kctrl,
201 oscctrl: &mut Oscctrl,
202 nvmctrl: &mut Nvmctrl,
203 ) -> Self {
204 Self::new(gclk, mclk, osc32kctrl, oscctrl, nvmctrl, true)
205 }
206
207 fn new(
208 gclk: Gclk,
209 mclk: &mut Mclk,
210 osc32kctrl: &mut Osc32kctrl,
211 oscctrl: &mut Oscctrl,
212 nvmctrl: &mut Nvmctrl,
213 use_external_crystal: bool,
214 ) -> Self {
215 let mut state = State { gclk };
216
217 set_flash_to_half_auto_wait_state(nvmctrl);
218 enable_gclk_apb(mclk);
219
220 if use_external_crystal {
221 enable_external_32kosc(osc32kctrl);
222 state.reset_gclk();
223 state.set_gclk_divider_and_source(Gclk1, 1, Xosc32k, false);
224 } else {
225 enable_internal_32kosc(osc32kctrl);
226 state.reset_gclk();
227 state.set_gclk_divider_and_source(Gclk1, 1, Osculp32k, false);
228 }
229
230 while state.gclk.syncbusy().read().genctrl().is_gclk0() {}
231
232 #[cfg(feature = "usb")]
233 configure_usb_correction(oscctrl);
234
235 unsafe {
237 state.gclk.genctrl(5).write(|w| {
238 w.src().dfll();
239 w.genen().set_bit();
240 w.div().bits(24)
241 });
242 }
243
244 while state.gclk.syncbusy().read().genctrl().is_gclk5() {}
245
246 configure_and_enable_dpll0(oscctrl, &mut state.gclk);
247 wait_for_dpllrdy(oscctrl);
248
249 unsafe {
250 state.gclk.genctrl(0).write(|w| {
252 w.src().dpll0();
253 w.div().bits(1);
254 w.oe().set_bit();
255 w.genen().set_bit()
256 });
257 }
258
259 while state.gclk.syncbusy().read().genctrl().is_gclk0() {}
260
261 mclk.cpudiv().write(|w| w.div().div1());
262
263 Self {
264 state,
265 gclks: [
266 OSC120M_FREQ,
267 OSC32K_FREQ,
268 0.Hz(),
269 0.Hz(),
270 0.Hz(),
271 2.MHz(),
272 0.Hz(),
273 0.Hz(),
274 0.Hz(),
275 0.Hz(),
276 0.Hz(),
277 0.Hz(),
278 ],
279 used_clocks: 1u64 << u8::from(ClockId::FDPLL0),
280 }
281 }
282
283 pub fn gclk0(&mut self) -> GClock {
285 GClock {
286 gclk: Gclk0,
287 freq: self.gclks[0],
288 }
289 }
290
291 pub fn gclk1(&mut self) -> GClock {
293 GClock {
294 gclk: Gclk1,
295 freq: self.gclks[1],
296 }
297 }
298
299 pub fn get_gclk(&mut self, gclk: ClockGenId) -> Option<GClock> {
303 let idx = u8::from(gclk) as usize;
304 if self.gclks[idx].to_Hz() == 0 {
305 None
306 } else {
307 Some(GClock {
308 gclk,
309 freq: self.gclks[idx],
310 })
311 }
312 }
313
314 pub fn configure_gclk_divider_and_source(
324 &mut self,
325 gclk: ClockGenId,
326 divider: u16,
327 src: ClockSource,
328 improve_duty_cycle: bool,
329 ) -> Option<GClock> {
330 let idx = u8::from(gclk) as usize;
331 if self.gclks[idx].to_Hz() != 0 {
332 return None;
333 }
334 self.state
335 .set_gclk_divider_and_source(gclk, divider, src, improve_duty_cycle);
336 let freq: Hertz = match src {
337 Xosc32k | Osculp32k => OSC32K_FREQ,
338 Gclkgen1 => self.gclks[1],
339 Dfll => OSC48M_FREQ,
340 Dpll0 => OSC120M_FREQ,
341 Xosc0 | Xosc1 | Gclkin | Dpll1 => unimplemented!(),
342 };
343 self.gclks[idx] = freq / divider as u32;
344 Some(GClock { gclk, freq })
345 }
346
347 pub fn configure_standby(&mut self, gclk: ClockGenId, enable: bool) {
349 self.state.configure_standby(gclk, enable)
350 }
351}
352
353macro_rules! clock_generator {
354 (
355 $(
356 $(#[$attr:meta])*
357 ($id:ident, $Type:ident, $clock:ident, $PclkId:ident),
358 )+
359 ) => {
360
361$(
362
363$(#[$attr])*
372#[derive(Debug)]
373pub struct $Type {
374 freq: Hertz,
375}
376
377$(#[$attr])*
378impl $Type {
379 pub fn freq(&self) -> Hertz {
381 self.freq
382 }
383}
384$(#[$attr])*
385impl Into<Hertz> for $Type {
386 fn into(self) -> Hertz {
387 self.freq
388 }
389}
390
391$(#[$attr])*
395impl<I: PclkSourceId> core::convert::From<Pclk<$PclkId, I>> for $Type {
396 fn from(pclk: Pclk<$PclkId, I>) -> Self {
397 $Type {
398 freq: pclk.freq()
399 }
400 }
401}
402
403
404)+
405
406impl GenericClockController {
407 $(
408 $(#[$attr])*
421 pub fn $id(&mut self, generator: &GClock) -> Option<$Type> {
422 let bits: u64 = 1 << u8::from(ClockId::$clock) as u64;
423 if (self.used_clocks & bits) != 0 {
424 return None;
425 }
426 self.used_clocks |= bits;
427
428 self.state.enable_clock_generator(ClockId::$clock, generator.gclk);
429 let freq = self.gclks[u8::from(generator.gclk) as usize];
430 Some($Type{freq})
431 }
432 )+
433}
434 }
435}
436
437#[hal_macro_helper]
438clock_generator!(
439 (tc0_tc1, Tc0Tc1Clock, TC0_TC1, Tc0Tc1),
440 (tcc0_tcc1, Tcc0Tcc1Clock, TCC0_TCC1, Tcc0Tcc1),
441 (tc2_tc3, Tc2Tc3Clock, TC2_TC3, Tc2Tc3),
442 (tcc2_tcc3, Tcc2Tcc3Clock, TCC2_TCC3, Tcc2Tcc3),
443 #[hal_cfg(all("tc4", "tc5"))]
444 (tc4_tc5, Tc4Tc5Clock, TC4_TC5, Tc4Tc5),
445 #[hal_cfg("tcc4")]
446 (tcc4, Tcc4Clock, TCC4, Tcc4),
447 #[hal_cfg(all("tc6", "tc7"))]
448 (tc6_tc7, Tc6Tc7Clock, TC6_TC7, Tc6Tc7),
449 (sercom0_core, Sercom0CoreClock, SERCOM0_CORE, Sercom0),
450 (sercom1_core, Sercom1CoreClock, SERCOM1_CORE, Sercom1),
451 (sercom2_core, Sercom2CoreClock, SERCOM2_CORE, Sercom2),
452 (sercom3_core, Sercom3CoreClock, SERCOM3_CORE, Sercom3),
453 (sercom4_core, Sercom4CoreClock, SERCOM4_CORE, Sercom4),
454 (sercom5_core, Sercom5CoreClock, SERCOM5_CORE, Sercom5),
455 #[hal_cfg("sercom6")]
456 (sercom6_core, Sercom6CoreClock, SERCOM6_CORE, Sercom6),
457 #[hal_cfg("sercom7")]
458 (sercom7_core, Sercom7CoreClock, SERCOM7_CORE, Sercom7),
459 (usb, UsbClock, USB, Usb),
460 (adc0, Adc0Clock, ADC0, Adc0),
461 (adc1, Adc1Clock, ADC1, Adc1),
462 (eic, EicClock, EIC, Eic),
463 (freq_m_msr, FreqmMsrClock, FREQM_MSR, FreqMMeasure),
464 (freq_m_ref, FreqmRefClock, FREQM_REF, FreqMReference),
465 (evsys0, Evsys0Clock, EVSYS0, EvSys0),
466 (evsys1, Evsys1Clock, EVSYS1, EvSys1),
467 (evsys2, Evsys2Clock, EVSYS2, EvSys2),
468 (evsys3, Evsys3Clock, EVSYS3, EvSys3),
469 (evsys4, Evsys4Clock, EVSYS4, EvSys4),
470 (evsys5, Evsys5Clock, EVSYS5, EvSys5),
471 (evsys6, Evsys6Clock, EVSYS6, EvSys6),
472 (evsys7, Evsys7Clock, EVSYS7, EvSys7),
473 (evsys8, Evsys8Clock, EVSYS8, EvSys8),
474 (evsys9, Evsys9Clock, EVSYS9, EvSys9),
475 (evsys10, Evsys10Clock, EVSYS10, EvSys10),
476 (evsys11, Evsys11Clock, EVSYS11, EvSys11),
477 #[hal_cfg("can0")]
478 (can0, Can0Clock, CAN0, Can0),
479 #[hal_cfg("can1")]
480 (can1, Can1Clock, CAN1, Can1),
481 (pdec, PdecClock, PDEC, PDec),
482 (ac, AcClock, AC, Ac),
483 (ccl, CclClock, CCL, Ccl),
484 (dac, DacClock, DAC, Dac),
485 #[hal_cfg("i2s")]
486 (i2s0, I2S0Clock, I2S0, I2S0),
487 #[hal_cfg("i2s")]
488 (i2s1, I2S1Clock, I2S1, I2S1),
489 (sdhc0, Sdhc0Clock, SDHC0, Sdhc0),
490 #[hal_cfg("sdhc1")]
491 (sdhc1, Sdhc1Clock, SDHC1, Sdhc1),
492 (cm4_trace, Cm4TraceClock, CM4_TRACE, CM4Trace),
493);
494
495pub const OSC48M_FREQ: Hertz = Hertz::Hz(48_000_000);
497pub const OSC32K_FREQ: Hertz = Hertz::Hz(32_768);
499pub const OSC120M_FREQ: Hertz = Hertz::Hz(120_000_000);
501
502fn set_flash_to_half_auto_wait_state(nvmctrl: &mut Nvmctrl) {
503 nvmctrl
506 .ctrla()
507 .modify(|_, w| unsafe { w.rws().bits(0b0111) });
508}
509
510fn enable_gclk_apb(mclk: &mut Mclk) {
511 mclk.apbamask().modify(|_, w| w.gclk_().set_bit());
512}
513
514fn enable_internal_32kosc(osc32kctrl: &mut Osc32kctrl) {
516 osc32kctrl.osculp32k().modify(|_, w| {
517 w.en32k().set_bit();
518 w.en1k().set_bit()
519 });
520 osc32kctrl.rtcctrl().write(|w| w.rtcsel().ulp1k());
521}
522
523fn enable_external_32kosc(osc32kctrl: &mut Osc32kctrl) {
525 osc32kctrl.xosc32k().modify(|_, w| {
526 w.ondemand().clear_bit();
527 w.en32k().set_bit();
529 w.en1k().set_bit();
530 w.xtalen().set_bit();
532 w.enable().set_bit();
533 w.cgm().xt();
534 w.runstdby().set_bit()
535 });
536
537 osc32kctrl.rtcctrl().write(|w| w.rtcsel().xosc1k());
538
539 while osc32kctrl.status().read().xosc32krdy().bit_is_clear() {}
541}
542
543fn wait_for_dpllrdy(oscctrl: &mut Oscctrl) {
544 while oscctrl.dpll(0).dpllstatus().read().lock().bit_is_clear()
545 || oscctrl.dpll(0).dpllstatus().read().clkrdy().bit_is_clear()
546 {}
547}
548
549fn configure_and_enable_dpll0(oscctrl: &mut Oscctrl, gclk: &mut Gclk) {
551 gclk.pchctrl(ClockId::FDPLL0 as usize).write(|w| {
552 w.chen().set_bit();
553 w.r#gen().gclk5()
554 });
555 unsafe {
556 oscctrl.dpll(0).dpllratio().write(|w| {
557 w.ldr().bits(59);
558 w.ldrfrac().bits(0)
559 });
560 }
561 oscctrl.dpll(0).dpllctrlb().write(|w| w.refclk().gclk());
562 oscctrl.dpll(0).dpllctrla().write(|w| {
563 w.enable().set_bit();
564 w.ondemand().clear_bit()
565 });
566}
567
568#[cfg(feature = "usb")]
569fn configure_usb_correction(oscctrl: &mut Oscctrl) {
571 oscctrl.dfllmul().write(|w| unsafe {
572 w.cstep().bits(0x1)
573 .fstep().bits(0x1)
574 .mul().bits((48_000_000u32 / 1000) as u16)
576 });
577 while oscctrl.dfllsync().read().dfllmul().bit_is_set() {}
578
579 oscctrl.dfllctrlb().write(|w| {
580 w.mode().set_bit()
582 .ccdis().set_bit()
584 .usbcrm().set_bit()
586 });
587 while oscctrl.dfllsync().read().dfllctrlb().bit_is_set() {}
588}