1#![allow(clippy::from_over_into)]
8
9use atsamd_hal_macros::{hal_cfg, hal_macro_helper};
10
11use fugit::RateExtU32;
12
13use crate::pac::gclk::clkctrl::Genselect::*;
14use crate::pac::gclk::clkctrl::Idselect::*;
15use crate::pac::gclk::genctrl::Srcselect::*;
16use crate::pac::{self, Gclk, Nvmctrl, Pm, Sysctrl};
17use crate::time::Hertz;
18
19pub type ClockId = pac::gclk::clkctrl::Idselect;
20pub type ClockGenId = pac::gclk::clkctrl::Genselect;
21pub type ClockSource = pac::gclk::genctrl::Srcselect;
22
23#[derive(Clone, Copy)]
30pub struct GClock {
31 gclk: ClockGenId,
32 freq: Hertz,
33}
34
35impl Into<Hertz> for GClock {
36 fn into(self) -> Hertz {
37 self.freq
38 }
39}
40
41struct State {
42 gclk: Gclk,
43}
44
45impl State {
46 fn reset_gclk(&mut self) {
47 self.gclk.ctrl().write(|w| w.swrst().set_bit());
48 while self.gclk.ctrl().read().swrst().bit_is_set()
49 || self.gclk.status().read().syncbusy().bit_is_set()
50 {}
51 }
52
53 fn wait_for_sync(&mut self) {
54 while self.gclk.status().read().syncbusy().bit_is_set() {}
55 }
56
57 fn set_gclk_divider_and_source(
58 &mut self,
59 gclk: ClockGenId,
60 divider: u16,
61 src: ClockSource,
62 improve_duty_cycle: bool,
63 ) {
64 let mut divisor_invalid = false;
67 if gclk == Gclk1 {
68 if divider as u32 >= 2_u32.pow(16) {
69 divisor_invalid = true;
70 }
71 } else if gclk == Gclk2 {
72 if divider >= 2_u16.pow(5) {
73 divisor_invalid = true;
74 }
75 } else if divider >= 2_u16.pow(8) {
76 divisor_invalid = true;
77 }
78 if divisor_invalid {
79 panic!("invalid divisor {} for Gclk {}", divider, gclk as u8);
80 }
81
82 self.gclk.gendiv().write(|w| unsafe {
83 w.id().bits(u8::from(gclk));
84 w.div().bits(divider)
85 });
86 self.wait_for_sync();
87
88 self.gclk.genctrl().write(|w| unsafe {
89 w.id().bits(u8::from(gclk));
90 w.src().bits(u8::from(src));
91 w.divsel().clear_bit();
93 w.idc().bit(improve_duty_cycle);
94 w.genen().set_bit();
95 w.oe().set_bit()
96 });
97 self.wait_for_sync();
98 }
99
100 fn enable_clock_generator(&mut self, clock: ClockId, generator: ClockGenId) {
101 self.gclk.clkctrl().write(|w| unsafe {
102 w.id().bits(u8::from(clock));
103 w.gen().bits(u8::from(generator));
104 w.clken().set_bit()
105 });
106 self.wait_for_sync();
107 }
108
109 fn configure_standby(&mut self, gclk: ClockGenId, enable: bool) {
110 unsafe {
114 let genctrl_ptr_u8: *mut u8 = self.gclk.genctrl().as_ptr() as *mut u8;
115 *genctrl_ptr_u8 = u8::from(gclk);
116 }
117 self.wait_for_sync();
118
119 self.gclk.genctrl().modify(|_, w| w.runstdby().bit(enable));
121 self.wait_for_sync();
122 }
123}
124
125pub struct GenericClockController {
133 state: State,
134 gclks: [Hertz; 8],
135 used_clocks: u64,
136}
137
138impl GenericClockController {
139 pub fn with_internal_32kosc(
142 gclk: Gclk,
143 pm: &mut Pm,
144 sysctrl: &mut Sysctrl,
145 nvmctrl: &mut Nvmctrl,
146 ) -> Self {
147 Self::new_48mhz_from_32khz(gclk, pm, sysctrl, nvmctrl, false)
148 }
149
150 pub fn with_external_32kosc(
153 gclk: Gclk,
154 pm: &mut Pm,
155 sysctrl: &mut Sysctrl,
156 nvmctrl: &mut Nvmctrl,
157 ) -> Self {
158 Self::new_48mhz_from_32khz(gclk, pm, sysctrl, nvmctrl, true)
159 }
160
161 #[hal_macro_helper]
162 fn new_48mhz_from_32khz(
163 gclk: Gclk,
164 pm: &mut Pm,
165 sysctrl: &mut Sysctrl,
166 nvmctrl: &mut Nvmctrl,
167 use_external_crystal: bool,
168 ) -> Self {
169 let mut state = State { gclk };
170
171 set_flash_to_half_auto_wait_state(nvmctrl);
172 #[hal_cfg("clock-d21")]
173 set_flash_manual_write(nvmctrl);
174 enable_gclk_apb(pm);
175 if use_external_crystal {
176 enable_external_32kosc(sysctrl);
177 } else {
178 enable_internal_32kosc(sysctrl);
179 }
180
181 state.reset_gclk();
182
183 if use_external_crystal {
185 state.set_gclk_divider_and_source(Gclk1, 1, Xosc32k, false);
186 } else {
187 state.set_gclk_divider_and_source(Gclk1, 1, Osc32k, false);
188 }
189
190 state.enable_clock_generator(Dfll48, Gclk1);
192 configure_and_enable_dfll48m(sysctrl, use_external_crystal);
194 state.set_gclk_divider_and_source(Gclk0, 1, Dfll48m, true);
196 sysctrl.osc8m().modify(|_, w| {
200 w.presc()._0();
201 w.ondemand().clear_bit()
202 });
203 pm.cpusel().write(|w| w.cpudiv().div1());
204 pm.apbasel().write(|w| w.apbadiv().div1());
205 pm.apbbsel().write(|w| w.apbbdiv().div1());
206 pm.apbcsel().write(|w| w.apbcdiv().div1());
207
208 Self {
209 state,
210 gclks: [
211 OSC48M_FREQ,
212 OSC32K_FREQ,
213 0.Hz(),
214 0.Hz(),
215 0.Hz(),
216 0.Hz(),
217 0.Hz(),
218 0.Hz(),
219 ],
220 used_clocks: 1u64 << u8::from(ClockId::Dfll48),
221 }
222 }
223
224 #[hal_macro_helper]
227 pub fn with_internal_8mhz(
228 gclk: Gclk,
229 pm: &mut Pm,
230 sysctrl: &mut Sysctrl,
231 nvmctrl: &mut Nvmctrl,
232 ) -> Self {
233 let mut state = State { gclk };
234
235 #[hal_cfg("clock-d21")]
237 set_flash_manual_write(nvmctrl);
238
239 #[hal_cfg("clock-d11")]
241 let _ = nvmctrl;
242
243 enable_gclk_apb(pm);
244
245 state.reset_gclk();
246
247 state.set_gclk_divider_and_source(Gclk0, 1, Osc8m, false);
249
250 sysctrl.osc8m().modify(|_, w| {
252 w.presc()._0();
253 w.ondemand().clear_bit()
254 });
255 pm.cpusel().write(|w| w.cpudiv().div1());
256 pm.apbasel().write(|w| w.apbadiv().div1());
257 pm.apbbsel().write(|w| w.apbbdiv().div1());
258 pm.apbcsel().write(|w| w.apbcdiv().div1());
259
260 Self {
261 state,
262 gclks: [
263 OSC8M_FREQ,
264 0.Hz(),
265 0.Hz(),
266 0.Hz(),
267 0.Hz(),
268 0.Hz(),
269 0.Hz(),
270 0.Hz(),
271 ],
272 used_clocks: 0,
273 }
274 }
275
276 pub fn gclk0(&mut self) -> GClock {
278 GClock {
279 gclk: Gclk0,
280 freq: self.gclks[0],
281 }
282 }
283
284 pub fn gclk1(&mut self) -> GClock {
286 GClock {
287 gclk: Gclk1,
288 freq: self.gclks[1],
289 }
290 }
291
292 pub fn get_gclk(&mut self, gclk: ClockGenId) -> Option<GClock> {
296 let idx = u8::from(gclk) as usize;
297 if self.gclks[idx].to_Hz() == 0 {
298 None
299 } else {
300 Some(GClock {
301 gclk,
302 freq: self.gclks[idx],
303 })
304 }
305 }
306
307 pub fn configure_gclk_divider_and_source(
317 &mut self,
318 gclk: ClockGenId,
319 divider: u16,
320 src: ClockSource,
321 improve_duty_cycle: bool,
322 ) -> Option<GClock> {
323 let idx = u8::from(gclk) as usize;
324 if self.gclks[idx].to_Hz() != 0 {
325 return None;
326 }
327 self.state
328 .set_gclk_divider_and_source(gclk, divider, src, improve_duty_cycle);
329 let freq: Hertz = match src {
330 Xosc32k | Osc32k | Osculp32k => OSC32K_FREQ,
331 Gclkgen1 => self.gclks[1],
332 Osc8m => OSC8M_FREQ,
333 Dfll48m => OSC48M_FREQ,
334 Dpll96m => 96.MHz(),
335 Gclkin | Xosc => unimplemented!(),
336 };
337 self.gclks[idx] = freq / divider as u32;
338 Some(GClock { gclk, freq })
339 }
340
341 pub fn configure_standby(&mut self, gclk: ClockGenId, enable: bool) {
343 self.state.configure_standby(gclk, enable)
344 }
345}
346
347macro_rules! clock_generator {
348 ($(($id:ident, $Type:ident, $clock:ident),)+) => {
349
350$(
351#[derive(Debug)]
360pub struct $Type {
361 freq: Hertz,
362}
363
364impl $Type {
365 pub fn freq(&self) -> Hertz {
367 self.freq
368 }
369}
370impl Into<Hertz> for $Type {
371 fn into(self) -> Hertz {
372 self.freq
373 }
374}
375)+
376
377impl GenericClockController {
378 $(
379 pub fn $id(&mut self, generator: &GClock) -> Option<$Type> {
393 let bits: u64 = 1<<u8::from(ClockId::$clock) as u64;
394 if (self.used_clocks & bits) != 0 {
395 return None;
396 }
397 self.used_clocks |= bits;
398
399 self.state.enable_clock_generator(ClockId::$clock, generator.gclk);
400 let freq = self.gclks[u8::from(generator.gclk) as usize];
401 Some($Type{freq})
402 }
403 )+
404}
405 }
406}
407
408#[hal_cfg("clock-d11")]
410clock_generator!(
411 (tcc0, Tcc0Clock, Tcc0),
412 (tc1_tc2, Tc1Tc2Clock, Tc1Tc2),
413 (sercom0_core, Sercom0CoreClock, Sercom0Core),
414 (sercom1_core, Sercom1CoreClock, Sercom1Core),
415 (sercom2_core, Sercom2CoreClock, Sercom2Core),
416 (rtc, RtcClock, Rtc),
417 (adc, AdcClock, Adc),
418 (wdt, WdtClock, Wdt),
419 (eic, EicClock, Eic),
420 (usb, UsbClock, Usb),
421 (evsys0, Evsys0Clock, Evsys0),
422 (evsys1, Evsys1Clock, Evsys1),
423 (evsys2, Evsys2Clock, Evsys2),
424 (evsys3, Evsys3Clock, Evsys3),
425 (evsys4, Evsys4Clock, Evsys4),
426 (evsys5, Evsys5Clock, Evsys5),
427 (ac_ana, AcAnaClock, AcAna),
428 (ac_dig, AcDigClock, AcDig),
429 (dac, DacClock, Dac),
430);
431#[hal_cfg("clock-d21")]
433clock_generator!(
434 (tcc0_tcc1, Tcc0Tcc1Clock, Tcc0Tcc1),
435 (tcc2_tc3, Tcc2Tc3Clock, Tcc2Tc3),
436 (tc4_tc5, Tc4Tc5Clock, Tc4Tc5),
437 (tc6_tc7, Tc6Tc7Clock, Tc6Tc7),
438 (sercom0_core, Sercom0CoreClock, Sercom0Core),
439 (sercom1_core, Sercom1CoreClock, Sercom1Core),
440 (sercom2_core, Sercom2CoreClock, Sercom2Core),
441 (sercom3_core, Sercom3CoreClock, Sercom3Core),
442 (sercom4_core, Sercom4CoreClock, Sercom4Core),
443 (sercom5_core, Sercom5CoreClock, Sercom5Core),
444 (usb, UsbClock, Usb),
445 (rtc, RtcClock, Rtc),
446 (adc, AdcClock, Adc),
447 (wdt, WdtClock, Wdt),
448 (eic, EicClock, Eic),
449 (evsys0, Evsys0Clock, Evsys0),
450 (evsys1, Evsys1Clock, Evsys1),
451 (evsys2, Evsys2Clock, Evsys2),
452 (evsys3, Evsys3Clock, Evsys3),
453 (evsys4, Evsys4Clock, Evsys4),
454 (evsys5, Evsys5Clock, Evsys5),
455 (evsys6, Evsys6Clock, Evsys6),
456 (evsys7, Evsys7Clock, Evsys7),
457 (evsys8, Evsys8Clock, Evsys8),
458 (evsys9, Evsys9Clock, Evsys9),
459 (evsys10, Evsys10Clock, Evsys10),
460 (evsys11, Evsys11Clock, Evsys11),
461 (ac_ana, AcAnaClock, AcAna),
462 (ac_dig, AcDigClock, AcDig),
463 (dac, DacClock, Dac),
464 (i2s0, I2S0Clock, I2s0),
465 (i2s1, I2S1Clock, I2s1),
466);
467
468pub const OSC48M_FREQ: Hertz = Hertz::Hz(48_000_000);
470pub const OSC8M_FREQ: Hertz = Hertz::Hz(8_000_000);
472pub const OSC32K_FREQ: Hertz = Hertz::Hz(32_768);
474
475fn set_flash_to_half_auto_wait_state(nvmctrl: &mut Nvmctrl) {
476 nvmctrl.ctrlb().modify(|_, w| w.rws().half());
477}
478
479#[hal_cfg("clock-d21")]
481fn set_flash_manual_write(nvmctrl: &mut Nvmctrl) {
482 nvmctrl.ctrlb().modify(|_, w| w.manw().set_bit());
483}
484
485fn enable_gclk_apb(pm: &mut Pm) {
486 pm.apbamask().modify(|_, w| w.gclk_().set_bit());
487}
488
489pub fn enable_internal_32kosc(sysctrl: &mut Sysctrl) {
491 let calibration = super::calibration::osc32k_cal();
492 sysctrl.osc32k().write(|w| {
493 unsafe {
494 w.ondemand().clear_bit();
495 w.calib().bits(calibration);
496 w.startup().bits(6);
498 }
499 w.en32k().set_bit();
500 w.enable().set_bit();
501 w.runstdby().set_bit()
502 });
503 while sysctrl.pclksr().read().osc32krdy().bit_is_clear() {
504 }
506}
507
508pub fn enable_external_32kosc(sysctrl: &mut Sysctrl) {
510 sysctrl.xosc32k().modify(|_, w| {
511 unsafe {
512 w.startup().bits(6);
514 }
515 w.ondemand().clear_bit();
516 w.en32k().set_bit();
518 w.xtalen().set_bit();
520 w.runstdby().set_bit()
521 });
522 sysctrl.xosc32k().modify(|_, w| w.enable().set_bit());
523 while sysctrl.pclksr().read().xosc32krdy().bit_is_clear() {
524 }
526}
527
528fn wait_for_dfllrdy(sysctrl: &mut Sysctrl) {
529 while sysctrl.pclksr().read().dfllrdy().bit_is_clear() {}
530}
531
532#[hal_macro_helper]
534fn configure_and_enable_dfll48m(sysctrl: &mut Sysctrl, use_external_crystal: bool) {
535 sysctrl.dfllctrl().write(|w| w.ondemand().clear_bit());
540 wait_for_dfllrdy(sysctrl);
541
542 if use_external_crystal {
543 sysctrl.dfllmul().write(|w| unsafe {
544 w.cstep().bits(31);
545 w.fstep().bits(511);
546 w.mul().bits(((48_000_000u32 + 32768 / 2) / 32768) as u16)
548 });
549
550 sysctrl.dfllctrl().write(|w| {
552 w.ondemand().clear_bit();
554
555 w.mode().set_bit();
557
558 w.waitlock().set_bit();
559
560 w.qldis().set_bit()
562 });
563 } else {
564 let coarse = super::calibration::dfll48m_coarse_cal();
566 let fine = 0x1ff;
567
568 sysctrl.dfllval().write(|w| unsafe {
569 w.coarse().bits(coarse);
570 w.fine().bits(fine)
571 });
572
573 sysctrl.dfllmul().write(|w| unsafe {
574 w.cstep().bits(coarse / 4);
575 w.fstep().bits(10);
576 w.mul().bits((48_000_000u32 / 1000) as u16)
578 });
579
580 sysctrl.dfllctrl().write(|w| {
582 w.ondemand().clear_bit();
584
585 w.mode().set_bit();
587
588 w.ccdis().set_bit();
590
591 w.usbcrm().set_bit();
593
594 w.bplckc().set_bit()
596 });
597 }
598
599 wait_for_dfllrdy(sysctrl);
600
601 sysctrl.dfllctrl().modify(|_, w| w.enable().set_bit());
603
604 #[hal_cfg("clock-d21")]
605 if use_external_crystal {
606 while sysctrl.pclksr().read().dflllckc().bit_is_clear()
608 || sysctrl.pclksr().read().dflllckf().bit_is_clear()
609 {}
610 }
611
612 wait_for_dfllrdy(sysctrl);
613}