1#![allow(dead_code, reason = "Some of this is bound to be unused")]
14#![allow(missing_docs, reason = "Experimental")]
15
16use esp_rom_sys::rom::{ets_delay_us, ets_update_cpu_frequency_rom};
19
20use crate::{
21 clock::Clocks,
22 peripherals::{I2C_ANA_MST, LPWR, SYSTEM, TIMG0, UART0, UART1},
23 rtc_cntl::Rtc,
24 soc::regi2c,
25 time::Rate,
26};
27
28define_clock_tree_types!();
29
30#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
33#[allow(
34 clippy::enum_variant_names,
35 reason = "MHz suffix indicates physical unit."
36)]
37#[non_exhaustive]
38pub enum CpuClock {
39 #[default]
41 _80MHz = 80,
42
43 _120MHz = 120,
45}
46
47impl CpuClock {
48 const PRESET_80: ClockConfig = ClockConfig {
49 xtal_clk: None,
50 system_pre_div: None,
51 cpu_pll_div: Some(CpuPllDivConfig::new(CpuPllDivDivisor::_6)),
52 cpu_clk: Some(CpuClkConfig::Pll),
53 rc_fast_clk_div_n: Some(RcFastClkDivNConfig::new(0)),
54 rtc_slow_clk: Some(RtcSlowClkConfig::RcSlow),
55 rtc_fast_clk: Some(RtcFastClkConfig::Rc),
56 low_power_clk: Some(LowPowerClkConfig::RtcSlow),
57 timg_calibration_clock: None,
58 };
59 const PRESET_120: ClockConfig = ClockConfig {
60 xtal_clk: None,
61 system_pre_div: None,
62 cpu_pll_div: Some(CpuPllDivConfig::new(CpuPllDivDivisor::_4)),
63 cpu_clk: Some(CpuClkConfig::Pll),
64 rc_fast_clk_div_n: Some(RcFastClkDivNConfig::new(0)),
65 rtc_slow_clk: Some(RtcSlowClkConfig::RcSlow),
66 rtc_fast_clk: Some(RtcFastClkConfig::Rc),
67 low_power_clk: Some(LowPowerClkConfig::RtcSlow),
68 timg_calibration_clock: None,
69 };
70}
71
72impl From<CpuClock> for ClockConfig {
73 fn from(value: CpuClock) -> ClockConfig {
74 match value {
75 CpuClock::_80MHz => CpuClock::PRESET_80,
76 CpuClock::_120MHz => CpuClock::PRESET_120,
77 }
78 }
79}
80
81impl Default for ClockConfig {
82 fn default() -> Self {
83 Self::from(CpuClock::default())
84 }
85}
86
87impl ClockConfig {
88 pub(crate) fn try_get_preset(self) -> Option<CpuClock> {
89 match self {
90 v if v == CpuClock::PRESET_80 => Some(CpuClock::_80MHz),
91 v if v == CpuClock::PRESET_120 => Some(CpuClock::_120MHz),
92 _ => None,
93 }
94 }
95
96 pub(crate) fn configure(mut self) {
97 ClockTree::with(|clocks| {
99 configure_xtal_clk(clocks, XtalClkConfig::_40);
100 configure_system_pre_div(clocks, SystemPreDivConfig::new(0));
101 configure_cpu_clk(clocks, CpuClkConfig::Xtal);
102 });
103
104 if self.xtal_clk.is_none() {
108 let xtal = ClockTree::with(detect_xtal_freq);
112 debug!("Auto-detected XTAL frequency: {}", xtal.value());
113 self.xtal_clk = Some(xtal);
114 }
115
116 self.apply();
117 }
118}
119
120fn detect_xtal_freq(clocks: &mut ClockTree) -> XtalClkConfig {
121 const CALIBRATION_CYCLES: u32 = 10;
124
125 LPWR::regs()
127 .clk_conf()
128 .modify(|_, w| w.dig_clk8m_d256_en().set_bit());
129
130 let (xtal_cycles, calibration_clock_frequency) = Clocks::measure_rtc_clock(
131 clocks,
132 TimgCalibrationClockConfig::RcFastDivClk,
133 TimgFunctionClockConfig::XtalClk,
134 CALIBRATION_CYCLES,
135 );
136
137 LPWR::regs()
138 .clk_conf()
139 .modify(|_, w| w.dig_clk8m_d256_en().clear_bit());
140
141 let mhz = (calibration_clock_frequency * xtal_cycles / CALIBRATION_CYCLES).as_mhz();
142
143 if mhz.abs_diff(40) < mhz.abs_diff(26) {
144 XtalClkConfig::_40
145 } else {
146 XtalClkConfig::_26
147 }
148}
149
150fn configure_xtal_clk_impl(
153 _clocks: &mut ClockTree,
154 _old_config: Option<XtalClkConfig>,
155 config: XtalClkConfig,
156) {
157 let freq_mhz = config.value() / 1_000_000;
163 LPWR::regs().store4().modify(|r, w| unsafe {
164 let disable_rom_log_bit = r.bits() & Rtc::RTC_DISABLE_ROM_LOG;
169 let half = (freq_mhz & (0xFFFF & !Rtc::RTC_DISABLE_ROM_LOG)) | disable_rom_log_bit;
170 w.data().bits(half | (half << 16))
171 });
172}
173
174fn enable_pll_clk_impl(clocks: &mut ClockTree, en: bool) {
177 const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4;
178 const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4;
179 const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
180
181 I2C_ANA_MST::regs()
183 .ana_config()
184 .modify(|_, w| w.bbpll_pd().bit(!en));
185
186 LPWR::regs().options0().modify(|_, w| {
187 let power_down = !en;
188 w.bb_i2c_force_pd().bit(power_down);
189 w.bbpll_force_pd().bit(power_down);
190 w.bbpll_i2c_force_pd().bit(power_down)
191 });
192
193 if !en {
194 return;
195 }
196
197 SYSTEM::regs()
200 .cpu_per_conf()
201 .modify(|_, w| w.pll_freq_sel().set_bit()); I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
207 w.bbpll_stop_force_high().clear_bit();
208 w.bbpll_stop_force_low().set_bit()
209 });
210
211 let div_ref: u8;
212 let div7_0: u8;
213 let dr1: u8;
214 let dr3: u8;
215 let dchgp: u8;
216 let dcur: u8;
217 let dbias: u8;
218 match unwrap!(clocks.xtal_clk) {
220 XtalClkConfig::_26 => {
221 div_ref = 12;
223 div7_0 = 236;
225 dr1 = 4;
226 dr3 = 4;
227 dchgp = 0;
228 dcur = 0;
229 dbias = 2;
230 }
231 XtalClkConfig::_40 => {
232 div_ref = 0;
234 div7_0 = 8;
236 dr1 = 0;
237 dr3 = 0;
238 dchgp = 5;
239 dcur = 3;
240 dbias = 2;
241 }
242 }
243
244 regi2c::I2C_BBPLL_REG4.write_reg(0x6b);
245
246 let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref;
247 let i2c_bbpll_dcur =
248 (1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
249
250 regi2c::I2C_BBPLL_OC_REF.write_reg(i2c_bbpll_lref);
251 regi2c::I2C_BBPLL_OC_DIV_REG.write_reg(div7_0);
252 regi2c::I2C_BBPLL_OC_DR1.write_field(dr1);
253 regi2c::I2C_BBPLL_OC_DR3.write_field(dr3);
254 regi2c::I2C_BBPLL_REG6.write_reg(i2c_bbpll_dcur);
255 regi2c::I2C_BBPLL_OC_VCO_DBIAS.write_field(dbias);
256
257 while I2C_ANA_MST::regs()
258 .ana_conf0()
259 .read()
260 .bbpll_cal_done()
261 .bit_is_clear()
262 {}
263
264 ets_delay_us(10);
265
266 I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
268 w.bbpll_stop_force_high().set_bit();
269 w.bbpll_stop_force_low().clear_bit()
270 });
271}
272
273fn enable_rc_fast_clk_impl(_clocks: &mut ClockTree, en: bool) {
276 const RTC_CNTL_FOSC_DFREQ_DEFAULT: u8 = 172;
278 LPWR::regs().clk_conf().modify(|_, w| {
279 unsafe { w.ck8m_dfreq().bits(RTC_CNTL_FOSC_DFREQ_DEFAULT) };
283
284 w.enb_ck8m().bit(!en);
285 w.dig_clk8m_en().bit(en); w.ck8m_force_pd().clear_bit();
288 w.ck8m_force_pu().clear_bit()
289 });
290 LPWR::regs()
291 .timer1()
292 .modify(|_, w| unsafe { w.ck8m_wait().bits(if en { 5 } else { 20 }) });
293}
294
295fn enable_osc_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) {
298 }
300
301fn enable_rc_slow_clk_impl(_clocks: &mut ClockTree, en: bool) {
304 if !en {
305 return;
306 }
307
308 const RTC_CNTL_SCK_DCAP_DEFAULT: u8 = 255;
311 LPWR::regs()
312 .rtc_cntl()
313 .modify(|_, w| unsafe { w.sck_dcap().bits(RTC_CNTL_SCK_DCAP_DEFAULT) });
314
315 let slow_clk_conf = LPWR::regs().slow_clk_conf();
319 let new_value = slow_clk_conf.modify(|_, w| w.ana_clk_div_vld().clear_bit());
321 let new_value = slow_clk_conf.write(|w| unsafe {
323 w.bits(new_value);
324 w.ana_clk_div().bits(0)
325 });
326 slow_clk_conf.write(|w| {
328 unsafe { w.bits(new_value) };
329 w.ana_clk_div_vld().set_bit()
330 });
331}
332
333fn enable_rc_fast_div_clk_impl(_clocks: &mut ClockTree, en: bool) {
336 LPWR::regs()
337 .clk_conf()
338 .modify(|_, w| w.enb_ck8m_div().bit(!en));
339}
340
341fn enable_system_pre_div_in_impl(_clocks: &mut ClockTree, _en: bool) {
346 }
348
349fn configure_system_pre_div_in_impl(
350 _clocks: &mut ClockTree,
351 _old_config: Option<SystemPreDivInConfig>,
352 _new_config: SystemPreDivInConfig,
353) {
354 }
356
357fn enable_system_pre_div_impl(_clocks: &mut ClockTree, _en: bool) {
360 }
362
363fn configure_system_pre_div_impl(
364 _clocks: &mut ClockTree,
365 _old_config: Option<SystemPreDivConfig>,
366 new_config: SystemPreDivConfig,
367) {
368 SYSTEM::regs()
369 .sysclk_conf()
370 .modify(|_, w| unsafe { w.pre_div_cnt().bits(new_config.divisor() as u16 & 0x3FF) });
371}
372
373fn enable_cpu_pll_div_impl(_clocks: &mut ClockTree, _en: bool) {
376 }
378
379fn configure_cpu_pll_div_impl(
380 _clocks: &mut ClockTree,
381 _old_config: Option<CpuPllDivConfig>,
382 _new_config: CpuPllDivConfig,
383) {
384 }
386
387fn enable_apb_clk_impl(_clocks: &mut ClockTree, _en: bool) {
390 }
392
393fn configure_apb_clk_impl(
394 _clocks: &mut ClockTree,
395 _old_config: Option<ApbClkConfig>,
396 _new_config: ApbClkConfig,
397) {
398 }
400
401fn enable_crypto_clk_impl(_clocks: &mut ClockTree, _en: bool) {
404 }
406
407fn configure_crypto_clk_impl(
408 _clocks: &mut ClockTree,
409 _old_config: Option<CryptoClkConfig>,
410 _new_config: CryptoClkConfig,
411) {
412 }
414
415fn enable_mspi_clk_impl(_clocks: &mut ClockTree, _en: bool) {
418 }
420
421fn configure_mspi_clk_impl(
422 _clocks: &mut ClockTree,
423 _old_config: Option<MspiClkConfig>,
424 _new_config: MspiClkConfig,
425) {
426 }
428
429fn configure_cpu_clk_impl(
432 clocks: &mut ClockTree,
433 _old_config: Option<CpuClkConfig>,
434 new_config: CpuClkConfig,
435) {
436 if new_config == CpuClkConfig::Pll {
438 SYSTEM::regs().cpu_per_conf().modify(|_, w| unsafe {
439 w.cpuperiod_sel()
440 .bits(match unwrap!(clocks.cpu_pll_div).divisor {
441 CpuPllDivDivisor::_4 => 1,
442 CpuPllDivDivisor::_6 => 0,
443 })
444 });
445 }
446
447 SYSTEM::regs().sysclk_conf().modify(|_, w| unsafe {
448 w.soc_clk_sel().bits(match new_config {
449 CpuClkConfig::Xtal => 0,
450 CpuClkConfig::RcFast => 2,
451 CpuClkConfig::Pll => 1,
452 })
453 });
454
455 let apb_freq = Rate::from_hz(apb_clk_frequency(clocks));
456 update_apb_frequency(apb_freq);
457
458 let cpu_freq = Rate::from_hz(cpu_clk_frequency(clocks));
459 ets_update_cpu_frequency_rom(cpu_freq.as_mhz());
460}
461
462fn update_apb_frequency(freq: Rate) {
463 let freq_shifted = (freq.as_hz() >> 12) & 0xFFFF;
464 let value = freq_shifted | (freq_shifted << 16);
465 LPWR::regs()
466 .store5()
467 .modify(|_, w| unsafe { w.data().bits(value) });
468}
469
470fn enable_pll_40m_impl(_clocks: &mut ClockTree, _en: bool) {
473 }
475
476fn enable_pll_60m_impl(_clocks: &mut ClockTree, _en: bool) {
479 }
481
482fn enable_pll_80m_impl(_clocks: &mut ClockTree, _en: bool) {
485 }
487
488fn enable_cpu_div2_impl(_clocks: &mut ClockTree, _en: bool) {
491 }
493
494fn enable_rc_fast_clk_div_n_impl(_clocks: &mut ClockTree, _en: bool) {
497 }
499
500fn configure_rc_fast_clk_div_n_impl(
501 _clocks: &mut ClockTree,
502 _old_config: Option<RcFastClkDivNConfig>,
503 new_config: RcFastClkDivNConfig,
504) {
505 let clk_conf = LPWR::regs().clk_conf();
506 let new_value = clk_conf.modify(|_, w| w.ck8m_div_sel_vld().clear_bit());
508 let new_value = clk_conf.write(|w| unsafe {
510 w.bits(new_value);
511 w.ck8m_div_sel().bits(new_config.divisor() as u8)
512 });
513 clk_conf.write(|w| {
515 unsafe { w.bits(new_value) };
516 w.ck8m_div_sel_vld().set_bit()
517 });
518}
519
520fn enable_xtal_div_clk_impl(_clocks: &mut ClockTree, _en: bool) {
523 }
525
526fn enable_rtc_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) {
529 }
531
532fn configure_rtc_slow_clk_impl(
533 _clocks: &mut ClockTree,
534 _old_config: Option<RtcSlowClkConfig>,
535 new_config: RtcSlowClkConfig,
536) {
537 LPWR::regs().clk_conf().modify(|_, w| unsafe {
538 w.ana_clk_rtc_sel().bits(match new_config {
540 RtcSlowClkConfig::OscSlow => 1,
541 RtcSlowClkConfig::RcSlow => 0,
542 RtcSlowClkConfig::RcFast => 2,
543 })
544 });
545
546 ets_delay_us(300);
547}
548
549fn enable_rtc_fast_clk_impl(_clocks: &mut ClockTree, _en: bool) {
552 }
554
555fn configure_rtc_fast_clk_impl(
556 _clocks: &mut ClockTree,
557 _old_config: Option<RtcFastClkConfig>,
558 new_config: RtcFastClkConfig,
559) {
560 LPWR::regs().clk_conf().modify(|_, w| match new_config {
562 RtcFastClkConfig::Xtal => w.fast_clk_rtc_sel().clear_bit(),
563 RtcFastClkConfig::Rc => w.fast_clk_rtc_sel().set_bit(),
564 });
565 ets_delay_us(3);
566}
567
568fn enable_low_power_clk_impl(_clocks: &mut ClockTree, _en: bool) {
571 }
576
577fn configure_low_power_clk_impl(
578 _clocks: &mut ClockTree,
579 _old_config: Option<LowPowerClkConfig>,
580 new_config: LowPowerClkConfig,
581) {
582 SYSTEM::regs().bt_lpck_div_frac().modify(|_, w| {
583 w.lpclk_sel_8m()
584 .bit(new_config == LowPowerClkConfig::RcFast);
585 w.lpclk_sel_rtc_slow()
586 .bit(new_config == LowPowerClkConfig::RtcSlow);
587 w.lpclk_sel_xtal()
588 .bit(new_config == LowPowerClkConfig::Xtal);
589 w.lpclk_sel_xtal32k()
590 .bit(new_config == LowPowerClkConfig::OscSlow)
591 });
592}
593
594fn enable_uart_mem_clk_impl(_clocks: &mut ClockTree, en: bool) {
597 let regs = SYSTEM::regs();
601
602 if en {
603 regs.perip_rst_en0()
604 .modify(|_, w| w.uart_mem_rst().bit(true));
605 regs.perip_rst_en0()
606 .modify(|_, w| w.uart_mem_rst().bit(false));
607 }
608
609 regs.perip_clk_en0()
610 .modify(|_, w| w.uart_mem_clk_en().bit(en));
611}
612
613fn enable_timg_calibration_clock_impl(_clocks: &mut ClockTree, _en: bool) {
616 }
619
620fn configure_timg_calibration_clock_impl(
621 _clocks: &mut ClockTree,
622 _old_config: Option<TimgCalibrationClockConfig>,
623 new_config: TimgCalibrationClockConfig,
624) {
625 TIMG0::regs().rtccalicfg().modify(|_, w| unsafe {
626 w.rtc_cali_clk_sel().bits(match new_config {
627 TimgCalibrationClockConfig::RcSlowClk => 0,
628 TimgCalibrationClockConfig::RcFastDivClk => 1,
629 TimgCalibrationClockConfig::Osc32kClk => 2,
630 })
631 });
632}
633
634impl TimgInstance {
635 fn enable_function_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
638 TIMG0::regs()
640 .regclk()
641 .modify(|_, w| w.timer_clk_is_active().bit(en));
642 }
643
644 fn configure_function_clock_impl(
645 self,
646 _clocks: &mut ClockTree,
647 _old_config: Option<TimgFunctionClockConfig>,
648 new_config: TimgFunctionClockConfig,
649 ) {
650 TIMG0::regs().t(0).config().modify(|_, w| {
651 w.use_xtal()
652 .bit(new_config == TimgFunctionClockConfig::XtalClk)
653 });
654 }
655
656 fn enable_wdt_clock_impl(self, _clocks: &mut ClockTree, _en: bool) {
659 }
661
662 fn configure_wdt_clock_impl(
663 self,
664 _clocks: &mut ClockTree,
665 _old_config: Option<TimgWdtClockConfig>,
666 new_config: TimgWdtClockConfig,
667 ) {
668 TIMG0::regs().wdtconfig0().modify(|_, w| {
669 w.wdt_use_xtal()
670 .bit(new_config == TimgWdtClockConfig::XtalClk)
671 });
672 }
673}
674
675impl UartInstance {
676 fn enable_function_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
679 let regs = match self {
680 UartInstance::Uart0 => UART0::regs(),
681 UartInstance::Uart1 => UART1::regs(),
682 };
683 regs.clk_conf().modify(|_, w| w.sclk_en().bit(en));
684 }
685
686 fn configure_function_clock_impl(
687 self,
688 _clocks: &mut ClockTree,
689 _old_config: Option<UartFunctionClockConfig>,
690 new_config: UartFunctionClockConfig,
691 ) {
692 let regs = match self {
693 UartInstance::Uart0 => UART0::regs(),
694 UartInstance::Uart1 => UART1::regs(),
695 };
696 regs.clk_conf().modify(|_, w| unsafe {
697 w.sclk_sel().bits(match new_config.sclk {
698 UartFunctionClockSclk::PllF40m => 1,
699 UartFunctionClockSclk::RcFast => 2,
700 UartFunctionClockSclk::Xtal => 3,
701 });
702 w.sclk_div_num().bits(new_config.div_num as _)
703 });
704 }
705
706 fn enable_mem_clock_impl(self, _clocks: &mut ClockTree, _en: bool) {
709 }
711
712 fn configure_mem_clock_impl(
713 self,
714 _clocks: &mut ClockTree,
715 _old_config: Option<UartMemClockConfig>,
716 _new_config: UartMemClockConfig,
717 ) {
718 }
720
721 fn enable_baud_rate_generator_impl(self, _clocks: &mut ClockTree, _en: bool) {
724 }
726
727 fn configure_baud_rate_generator_impl(
728 self,
729 _clocks: &mut ClockTree,
730 _old_config: Option<UartBaudRateGeneratorConfig>,
731 new_config: UartBaudRateGeneratorConfig,
732 ) {
733 let regs = match self {
734 UartInstance::Uart0 => UART0::regs(),
735 UartInstance::Uart1 => UART1::regs(),
736 };
737 regs.clkdiv().write(|w| unsafe {
738 w.clkdiv().bits(new_config.integral as _);
739 w.frag().bits(new_config.fractional as _)
740 });
741 }
742}