1#![allow(dead_code, reason = "Some of this is bound to be unused")]
14#![allow(missing_docs, reason = "Experimental")]
15
16use crate::{
19 peripherals::{I2C_ANA_MST, LP_CLKRST, PCR, PMU, UART0, UART1},
20 soc::regi2c,
21};
22
23define_clock_tree_types!();
24
25#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
27#[cfg_attr(feature = "defmt", derive(defmt::Format))]
28#[allow(
29 clippy::enum_variant_names,
30 reason = "MHz suffix indicates physical unit."
31)]
32#[non_exhaustive]
33pub enum CpuClock {
34 #[default]
36 _80MHz = 80,
37
38 _160MHz = 160,
40
41 _240MHz = 240,
43}
44
45impl CpuClock {
46 const PRESET_80: ClockConfig = ClockConfig {
47 xtal_clk: None,
48 hp_root_clk: Some(HpRootClkConfig::PllF160m),
49 cpu_clk: Some(CpuClkConfig::new(1)),
50 ahb_clk: Some(AhbClkConfig::new(3)), apb_clk: Some(ApbClkConfig::new(0)),
52 lp_fast_clk: Some(LpFastClkConfig::RcFast),
53 lp_slow_clk: Some(LpSlowClkConfig::RcSlow),
54 crypto_clk: Some(CryptoClkConfig::PllF480m),
55 timg_calibration_clock: None,
56 };
57 const PRESET_160: ClockConfig = ClockConfig {
58 xtal_clk: None,
59 hp_root_clk: Some(HpRootClkConfig::PllF160m),
60 cpu_clk: Some(CpuClkConfig::new(0)),
61 ahb_clk: Some(AhbClkConfig::new(3)), apb_clk: Some(ApbClkConfig::new(0)),
63 lp_fast_clk: Some(LpFastClkConfig::RcFast),
64 lp_slow_clk: Some(LpSlowClkConfig::RcSlow),
65 crypto_clk: Some(CryptoClkConfig::PllF480m),
66 timg_calibration_clock: None,
67 };
68 const PRESET_240: ClockConfig = ClockConfig {
69 xtal_clk: None,
70 hp_root_clk: Some(HpRootClkConfig::PllF240m),
71 cpu_clk: Some(CpuClkConfig::new(0)),
72 ahb_clk: Some(AhbClkConfig::new(5)), apb_clk: Some(ApbClkConfig::new(0)),
74 lp_fast_clk: Some(LpFastClkConfig::RcFast),
75 lp_slow_clk: Some(LpSlowClkConfig::RcSlow),
76 crypto_clk: Some(CryptoClkConfig::PllF480m),
77 timg_calibration_clock: None,
78 };
79}
80
81impl From<CpuClock> for ClockConfig {
82 fn from(value: CpuClock) -> ClockConfig {
83 match value {
84 CpuClock::_80MHz => CpuClock::PRESET_80,
85 CpuClock::_160MHz => CpuClock::PRESET_160,
86 CpuClock::_240MHz => CpuClock::PRESET_240,
87 }
88 }
89}
90
91impl Default for ClockConfig {
92 fn default() -> Self {
93 Self::from(CpuClock::default())
94 }
95}
96
97impl ClockConfig {
98 pub(crate) fn try_get_preset(self) -> Option<CpuClock> {
99 match self {
100 v if v == CpuClock::PRESET_80 => Some(CpuClock::_80MHz),
101 v if v == CpuClock::PRESET_160 => Some(CpuClock::_160MHz),
102 v if v == CpuClock::PRESET_240 => Some(CpuClock::_240MHz),
103 _ => None,
104 }
105 }
106
107 pub(crate) fn configure(mut self) {
108 self.xtal_clk = if PCR::regs().sysclk_conf().read().clk_xtal_freq().bits() == 40 {
111 Some(XtalClkConfig::_40)
112 } else {
113 Some(XtalClkConfig::_48)
114 };
115
116 self.apply();
117 }
118}
119
120fn configure_xtal_clk_impl(
123 _clocks: &mut ClockTree,
124 _old_config: Option<XtalClkConfig>,
125 _config: XtalClkConfig,
126) {
127 }
129
130fn enable_pll_clk_impl(clocks: &mut ClockTree, en: bool) {
133 if en {
134 PMU::regs().imm_hp_ck_power().write(|w| {
135 w.tie_high_xpd_bb_i2c().set_bit();
136 w.tie_high_xpd_bbpll().set_bit();
137 w.tie_high_xpd_bbpll_i2c().set_bit()
138 });
139 PMU::regs()
140 .imm_hp_ck_power()
141 .write(|w| w.tie_high_global_bbpll_icg().set_bit());
142 } else {
143 PMU::regs()
144 .imm_hp_ck_power()
145 .write(|w| w.tie_low_global_bbpll_icg().set_bit());
146 PMU::regs().imm_hp_ck_power().write(|w| {
147 w.tie_low_xpd_bb_i2c().set_bit();
148 w.tie_low_xpd_bbpll().set_bit();
149 w.tie_low_xpd_bbpll_i2c().set_bit()
150 });
151
152 return;
153 }
154
155 I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
161 w.bbpll_stop_force_high().clear_bit();
162 w.bbpll_stop_force_low().set_bit()
163 });
164
165 let div7_0: u8;
166 let dr1: u8;
167 let dr3: u8;
168 match unwrap!(clocks.xtal_clk()) {
169 XtalClkConfig::_40 => {
170 div7_0 = 12;
171 dr1 = 0;
172 dr3 = 0;
173 }
174 XtalClkConfig::_48 => {
175 div7_0 = 10;
176 dr1 = 1;
177 dr3 = 1;
178 }
179 }
180
181 const DIV_REF: u8 = 1; const DCHGP: u8 = 5;
183 const DBIAS: u8 = 3;
184 const HREF: u8 = 3;
185 const LREF: u8 = 1;
186
187 const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4;
188 const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4;
189 const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
190
191 const I2C_BBPLL_LREF: u8 = (DCHGP << I2C_BBPLL_OC_DCHGP_LSB) | DIV_REF;
192
193 regi2c::I2C_BBPLL_OC_REF.write_reg(I2C_BBPLL_LREF);
194 regi2c::I2C_BBPLL_OC_DIV_REG.write_reg(div7_0);
195 regi2c::I2C_BBPLL_OC_DR1.write_field(dr1);
196 regi2c::I2C_BBPLL_OC_DR3.write_field(dr3);
197 regi2c::I2C_BBPLL_OC_DLREF_SEL.write_field(LREF);
198 regi2c::I2C_BBPLL_OC_DHREF_SEL.write_field(HREF);
199 regi2c::I2C_BBPLL_OC_VCO_DBIAS.write_field(DBIAS);
200
201 while I2C_ANA_MST::regs()
203 .ana_conf0()
204 .read()
205 .cal_done()
206 .bit_is_clear()
207 {}
208 crate::rom::ets_delay_us(10);
209
210 I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
212 w.bbpll_stop_force_high().set_bit();
213 w.bbpll_stop_force_low().clear_bit()
214 });
215}
216
217fn enable_rc_fast_clk_impl(_clocks: &mut ClockTree, en: bool) {
220 LP_CLKRST::regs()
221 .clk_to_hp()
222 .modify(|_, w| w.icg_hp_fosc().bit(en));
223}
224
225fn enable_xtal32k_clk_impl(_clocks: &mut ClockTree, en: bool) {
228 LP_CLKRST::regs()
229 .clk_to_hp()
230 .modify(|_, w| w.icg_hp_xtal32k().bit(en));
231}
232
233fn enable_osc_slow_clk_impl(_clocks: &mut ClockTree, en: bool) {
236 LP_CLKRST::regs()
237 .clk_to_hp()
238 .modify(|_, w| w.icg_hp_osc32k().bit(en));
239}
240
241fn enable_rc_slow_clk_impl(_clocks: &mut ClockTree, en: bool) {
244 LP_CLKRST::regs()
245 .clk_to_hp()
246 .modify(|_, w| w.icg_hp_sosc().bit(en));
247}
248
249fn enable_pll_f12m_impl(_clocks: &mut ClockTree, en: bool) {
252 PCR::regs()
253 .pll_div_clk_en()
254 .modify(|_, w| w.pll_12m_clk_en().bit(en));
255}
256
257fn enable_pll_f20m_impl(_clocks: &mut ClockTree, en: bool) {
260 PCR::regs()
261 .pll_div_clk_en()
262 .modify(|_, w| w.pll_20m_clk_en().bit(en));
263}
264
265fn enable_pll_f40m_impl(_clocks: &mut ClockTree, en: bool) {
268 PCR::regs()
269 .pll_div_clk_en()
270 .modify(|_, w| w.pll_40m_clk_en().bit(en));
271}
272
273fn enable_pll_f48m_impl(_clocks: &mut ClockTree, en: bool) {
276 PCR::regs()
277 .pll_div_clk_en()
278 .modify(|_, w| w.pll_48m_clk_en().bit(en));
279}
280
281fn enable_pll_f60m_impl(_clocks: &mut ClockTree, en: bool) {
284 PCR::regs()
285 .pll_div_clk_en()
286 .modify(|_, w| w.pll_60m_clk_en().bit(en));
287}
288
289fn enable_pll_f80m_impl(_clocks: &mut ClockTree, en: bool) {
292 PCR::regs()
293 .pll_div_clk_en()
294 .modify(|_, w| w.pll_80m_clk_en().bit(en));
295}
296
297fn enable_pll_f120m_impl(_clocks: &mut ClockTree, en: bool) {
300 PCR::regs()
301 .pll_div_clk_en()
302 .modify(|_, w| w.pll_120m_clk_en().bit(en));
303}
304
305fn enable_pll_f160m_impl(_clocks: &mut ClockTree, en: bool) {
308 PCR::regs()
309 .pll_div_clk_en()
310 .modify(|_, w| w.pll_160m_clk_en().bit(en));
311}
312
313fn enable_pll_f240m_impl(_clocks: &mut ClockTree, en: bool) {
316 PCR::regs()
317 .pll_div_clk_en()
318 .modify(|_, w| w.pll_240m_clk_en().bit(en));
319}
320
321fn enable_hp_root_clk_impl(_clocks: &mut ClockTree, _en: bool) {
324 }
326
327fn configure_hp_root_clk_impl(
328 _clocks: &mut ClockTree,
329 _old_config: Option<HpRootClkConfig>,
330 new_config: HpRootClkConfig,
331) {
332 PCR::regs().sysclk_conf().modify(|_, w| unsafe {
335 w.soc_clk_sel().bits(match new_config {
336 HpRootClkConfig::Xtal => 0,
337 HpRootClkConfig::RcFast => 1,
338 HpRootClkConfig::PllF160m => 2,
339 HpRootClkConfig::PllF240m => 3,
340 })
341 });
342}
343
344fn enable_cpu_clk_impl(_clocks: &mut ClockTree, _en: bool) {
347 }
349
350fn configure_cpu_clk_impl(
351 _clocks: &mut ClockTree,
352 _old_config: Option<CpuClkConfig>,
353 new_config: CpuClkConfig,
354) {
355 PCR::regs()
356 .cpu_freq_conf()
357 .modify(|_, w| unsafe { w.cpu_div_num().bits(new_config.divisor() as u8) });
358
359 PCR::regs()
360 .bus_clk_update()
361 .write(|w| w.bus_clock_update().set_bit());
362}
363
364fn enable_ahb_clk_impl(_clocks: &mut ClockTree, _en: bool) {
367 }
369
370fn configure_ahb_clk_impl(
371 _clocks: &mut ClockTree,
372 _old_config: Option<AhbClkConfig>,
373 new_config: AhbClkConfig,
374) {
375 PCR::regs()
376 .ahb_freq_conf()
377 .modify(|_, w| unsafe { w.ahb_div_num().bits(new_config.divisor() as u8) });
378
379 PCR::regs()
380 .bus_clk_update()
381 .write(|w| w.bus_clock_update().set_bit());
382}
383
384fn enable_apb_clk_impl(_clocks: &mut ClockTree, _en: bool) {
387 }
389
390fn configure_apb_clk_impl(
391 _clocks: &mut ClockTree,
392 _old_config: Option<ApbClkConfig>,
393 new_config: ApbClkConfig,
394) {
395 PCR::regs()
396 .apb_freq_conf()
397 .modify(|_, w| unsafe { w.apb_div_num().bits(new_config.divisor() as u8) });
398}
399
400fn enable_xtal_d2_clk_impl(_clocks: &mut ClockTree, _en: bool) {
403 }
405
406fn enable_lp_fast_clk_impl(_clocks: &mut ClockTree, _en: bool) {
409 }
411
412fn configure_lp_fast_clk_impl(
413 _clocks: &mut ClockTree,
414 _old_config: Option<LpFastClkConfig>,
415 new_config: LpFastClkConfig,
416) {
417 LP_CLKRST::regs().lp_clk_conf().modify(|_, w| unsafe {
418 w.fast_clk_sel().bits(match new_config {
419 LpFastClkConfig::RcFast => 0,
420 LpFastClkConfig::XtalD2 => 1,
421 LpFastClkConfig::Xtal => 2,
422 })
423 });
424}
425
426fn enable_lp_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) {
429 }
431
432fn configure_lp_slow_clk_impl(
433 _clocks: &mut ClockTree,
434 _old_config: Option<LpSlowClkConfig>,
435 new_config: LpSlowClkConfig,
436) {
437 LP_CLKRST::regs().lp_clk_conf().modify(|_, w| unsafe {
438 w.slow_clk_sel().bits(match new_config {
439 LpSlowClkConfig::RcSlow => 0,
440 LpSlowClkConfig::Xtal32k => 1,
441 LpSlowClkConfig::OscSlow => 3,
443 })
444 });
445}
446
447fn enable_crypto_clk_impl(_clocks: &mut ClockTree, _en: bool) {
450 }
452
453fn configure_crypto_clk_impl(
454 _clocks: &mut ClockTree,
455 _old_config: Option<CryptoClkConfig>,
456 new_config: CryptoClkConfig,
457) {
458 PCR::regs().sec_conf().modify(|_, w| unsafe {
459 w.sec_clk_sel().bits(match new_config {
460 CryptoClkConfig::Xtal => 0,
461 CryptoClkConfig::Fosc => 1,
462 CryptoClkConfig::PllF480m => 2,
463 })
464 });
465}
466
467fn enable_timg_calibration_clock_impl(_clocks: &mut ClockTree, _en: bool) {
470 }
472
473fn configure_timg_calibration_clock_impl(
474 _clocks: &mut ClockTree,
475 _old_config: Option<TimgCalibrationClockConfig>,
476 new_config: TimgCalibrationClockConfig,
477) {
478 PCR::regs().ctrl_32k_conf().modify(|_, w| unsafe {
479 w._32k_sel().bits(match new_config {
480 TimgCalibrationClockConfig::OscSlowClk => 0,
481 TimgCalibrationClockConfig::Xtal32kClk => 1,
482 TimgCalibrationClockConfig::RcSlowClk => 3,
484 TimgCalibrationClockConfig::RcFastDivClk => 4,
485 })
486 });
487}
488
489impl ParlIoInstance {
490 fn enable_rx_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
493 PCR::regs()
494 .parl_clk_rx_conf()
495 .modify(|_, w| w.parl_clk_rx_en().bit(en));
496 }
497
498 fn configure_rx_clock_impl(
499 self,
500 _clocks: &mut ClockTree,
501 _old_config: Option<ParlIoRxClockConfig>,
502 new_config: ParlIoRxClockConfig,
503 ) {
504 PCR::regs().parl_clk_rx_conf().modify(|_, w| unsafe {
505 w.parl_clk_rx_sel().bits(match new_config {
506 ParlIoRxClockConfig::XtalClk => 0,
507 ParlIoRxClockConfig::RcFastClk => 1,
508 ParlIoRxClockConfig::PllF240m => 2,
509 })
510 });
511 }
512
513 fn enable_tx_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
516 PCR::regs()
517 .parl_clk_tx_conf()
518 .modify(|_, w| w.parl_clk_tx_en().bit(en));
519 }
520
521 fn configure_tx_clock_impl(
522 self,
523 _clocks: &mut ClockTree,
524 _old_config: Option<ParlIoTxClockConfig>,
525 new_config: ParlIoTxClockConfig,
526 ) {
527 PCR::regs().parl_clk_tx_conf().modify(|_, w| unsafe {
528 w.parl_clk_tx_sel().bits(match new_config {
529 ParlIoTxClockConfig::XtalClk => 0,
530 ParlIoTxClockConfig::RcFastClk => 1,
531 ParlIoTxClockConfig::PllF240m => 2,
532 })
533 });
534 }
535}
536
537impl RmtInstance {
538 fn enable_sclk_impl(self, _clocks: &mut ClockTree, en: bool) {
541 PCR::regs().rmt_pd_ctrl().modify(|_, w| {
542 w.rmt_mem_force_pu().bit(en);
543 w.rmt_mem_force_pd().bit(!en)
544 });
545
546 PCR::regs()
547 .rmt_sclk_conf()
548 .modify(|_, w| w.sclk_en().bit(en));
549 }
550
551 fn configure_sclk_impl(
552 self,
553 _clocks: &mut ClockTree,
554 _old_config: Option<RmtSclkConfig>,
555 new_config: RmtSclkConfig,
556 ) {
557 PCR::regs().rmt_sclk_conf().modify(|_, w| unsafe {
558 w.sclk_sel().bits(match new_config {
559 RmtSclkConfig::XtalClk => 0,
560 RmtSclkConfig::RcFastClk => 1,
561 RmtSclkConfig::PllF80m => 2,
562 })
563 });
564 }
565}
566
567impl TimgInstance {
568 fn enable_function_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
573 let timg = match self {
574 TimgInstance::Timg0 => 0,
575 TimgInstance::Timg1 => 1,
576 };
577 PCR::regs()
578 .timergroup(timg)
579 .timer_clk_conf()
580 .modify(|_, w| w.timer_clk_en().bit(en));
581 }
582
583 fn configure_function_clock_impl(
584 self,
585 _clocks: &mut ClockTree,
586 _old_config: Option<TimgFunctionClockConfig>,
587 new_config: TimgFunctionClockConfig,
588 ) {
589 let timg = match self {
591 TimgInstance::Timg0 => 0,
592 TimgInstance::Timg1 => 1,
593 };
594 PCR::regs()
595 .timergroup(timg)
596 .timer_clk_conf()
597 .modify(|_, w| unsafe {
598 w.timer_clk_sel().bits(match new_config {
599 TimgFunctionClockConfig::XtalClk => 0,
600 TimgFunctionClockConfig::RcFastClk => 1,
601 TimgFunctionClockConfig::PllF80m => 2,
602 })
603 });
604 }
605
606 fn enable_wdt_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
609 let timg = match self {
610 TimgInstance::Timg0 => 0,
611 TimgInstance::Timg1 => 1,
612 };
613 PCR::regs()
614 .timergroup(timg)
615 .wdt_clk_conf()
616 .modify(|_, w| w.wdt_clk_en().bit(en));
617 }
618
619 fn configure_wdt_clock_impl(
620 self,
621 _clocks: &mut ClockTree,
622 _old_config: Option<TimgWdtClockConfig>,
623 new_config: TimgWdtClockConfig,
624 ) {
625 let timg = match self {
626 TimgInstance::Timg0 => 0,
627 TimgInstance::Timg1 => 1,
628 };
629 PCR::regs()
630 .timergroup(timg)
631 .wdt_clk_conf()
632 .modify(|_, w| unsafe {
633 w.wdt_clk_sel().bits(match new_config {
634 TimgWdtClockConfig::XtalClk => 0,
635 TimgWdtClockConfig::RcFastClk => 1,
636 TimgWdtClockConfig::PllF80m => 2,
637 })
638 });
639 }
640}
641
642impl UartInstance {
643 fn enable_function_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
646 let uart = match self {
647 UartInstance::Uart0 => {
648 return;
651 }
652 UartInstance::Uart1 => 1,
653 };
654 PCR::regs()
655 .uart(uart)
656 .clk_conf()
657 .modify(|_, w| w.sclk_en().bit(en));
658 }
659
660 fn configure_function_clock_impl(
661 self,
662 _clocks: &mut ClockTree,
663 _old_config: Option<UartFunctionClockConfig>,
664 new_config: UartFunctionClockConfig,
665 ) {
666 PCR::regs()
667 .uart(match self {
668 UartInstance::Uart0 => 0,
669 UartInstance::Uart1 => 1,
670 })
671 .clk_conf()
672 .modify(|_, w| unsafe {
673 w.sclk_sel().bits(match new_config.sclk {
674 UartFunctionClockSclk::Xtal => 0,
675 UartFunctionClockSclk::RcFast => 1,
676 UartFunctionClockSclk::PllF80m => 2,
677 });
678 w.sclk_div_a().bits(0);
679 w.sclk_div_b().bits(0);
680 w.sclk_div_num().bits(new_config.div_num as _);
681 w
682 });
683 }
684
685 fn enable_baud_rate_generator_impl(self, _clocks: &mut ClockTree, _en: bool) {
688 }
690
691 fn configure_baud_rate_generator_impl(
692 self,
693 _clocks: &mut ClockTree,
694 _old_config: Option<UartBaudRateGeneratorConfig>,
695 new_config: UartBaudRateGeneratorConfig,
696 ) {
697 let regs = match self {
698 UartInstance::Uart0 => UART0::regs(),
699 UartInstance::Uart1 => UART1::regs(),
700 };
701 regs.clkdiv().write(|w| unsafe {
702 w.clkdiv().bits(new_config.integral as _);
703 w.frag().bits(new_config.fractional as _)
704 });
705 }
706}