1use strum::FromRepr;
6
7use crate::{
8 clock::{
9 Clock,
10 RtcClock,
11 RtcFastClock,
12 RtcSlowClock,
13 clocks_ll::{
14 esp32c6_bbpll_get_freq_mhz,
15 esp32c6_cpu_get_hs_divider,
16 esp32c6_cpu_get_ls_divider,
17 esp32c6_rtc_bbpll_configure_raw,
18 esp32c6_rtc_freq_to_pll_mhz_raw,
19 esp32c6_rtc_update_to_8m,
20 esp32c6_rtc_update_to_xtal_raw,
21 },
22 },
23 peripherals::{LP_AON, LP_CLKRST, MODEM_LPCON, MODEM_SYSCON, PCR, PMU},
24 rtc_cntl::RtcCalSel,
25 soc::regi2c,
26};
27
28fn pmu_power_domain_force_default() {
29 PMU::regs().power_pd_top_cntl().modify(|_, w| {
33 w.force_top_reset().bit(false); w.force_top_iso().bit(false); w.force_top_pu().bit(false); w.force_top_no_reset().bit(false); w.force_top_no_iso().bit(false); w.force_top_pd().bit(false) });
40
41 PMU::regs().power_pd_hpaon_cntl().modify(|_, w| {
43 w.force_hp_aon_reset().bit(false); w.force_hp_aon_iso().bit(false); w.force_hp_aon_pu().bit(false); w.force_hp_aon_no_reset().bit(false); w.force_hp_aon_no_iso().bit(false); w.force_hp_aon_pd().bit(false) });
50
51 PMU::regs().power_pd_hpcpu_cntl().modify(|_, w| {
53 w.force_hp_cpu_reset().bit(false); w.force_hp_cpu_iso().bit(false); w.force_hp_cpu_pu().bit(false); w.force_hp_cpu_no_reset().bit(false); w.force_hp_cpu_no_iso().bit(false); w.force_hp_cpu_pd().bit(false) });
60
61 PMU::regs().power_pd_hpwifi_cntl().modify(|_, w| {
63 w.force_hp_wifi_reset().bit(false); w.force_hp_wifi_iso().bit(false); w.force_hp_wifi_pu().bit(false); w.force_hp_wifi_no_reset().bit(false); w.force_hp_wifi_no_iso().bit(false); w.force_hp_wifi_pd().bit(false) });
70
71 PMU::regs().power_pd_mem_cntl().modify(|_, w| unsafe {
74 w.force_hp_mem_no_iso().bits(0) });
76
77 PMU::regs().power_pd_lpperi_cntl().modify(|_, w| {
78 w.force_lp_peri_reset().bit(false); w.force_lp_peri_iso().bit(false); w.force_lp_peri_pu().bit(false); w.force_lp_peri_no_reset().bit(false); w.force_lp_peri_no_iso().bit(false); w.force_lp_peri_pd().bit(false) });
85}
86
87fn modem_clock_domain_power_state_icg_map_init() {
88 const ICG_NOGATING_MODEM: u8 = 1 << 1;
92 const ICG_NOGATING_ACTIVE: u8 = 1 << 2;
93
94 const ICG_NOGATING_ACTIVE_MODEM: u8 = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM;
95
96 MODEM_SYSCON::regs()
99 .clk_conf_power_st()
100 .modify(|_, w| unsafe {
101 w.clk_modem_apb_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_modem_peri_st_map().bits(ICG_NOGATING_ACTIVE); w.clk_wifi_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_bt_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_fe_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_zb_st_map().bits(ICG_NOGATING_ACTIVE_MODEM) });
108
109 MODEM_LPCON::regs()
110 .clk_conf_power_st()
111 .modify(|_, w| unsafe {
112 w.clk_lp_apb_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_i2c_mst_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_coex_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_wifipwr_st_map().bits(ICG_NOGATING_ACTIVE_MODEM) });
117}
118
119enum RtcSlowClockSource {
120 RcSlow = 0,
122
123 XTAL32K = 1,
125
126 RC32K = 2,
128
129 OscSlow = 3,
131
132 Invalid,
134}
135
136impl RtcSlowClockSource {
137 fn current() -> Self {
138 match LP_CLKRST::regs().lp_clk_conf().read().slow_clk_sel().bits() {
140 0 => Self::RcSlow,
141 1 => Self::XTAL32K,
142 2 => Self::RC32K,
143 3 => Self::OscSlow,
144 _ => Self::Invalid,
145 }
146 }
147}
148
149#[allow(unused)]
150enum ModemClockLpclkSource {
151 RcSlow = 0,
152 RcFast,
153 MainXtal,
154 RC32K,
155 XTAL32K,
156 EXT32K,
157}
158
159impl From<RtcSlowClockSource> for ModemClockLpclkSource {
160 fn from(src: RtcSlowClockSource) -> Self {
161 match src {
162 RtcSlowClockSource::RcSlow => Self::RcSlow,
163 RtcSlowClockSource::XTAL32K => Self::XTAL32K,
164 RtcSlowClockSource::RC32K => Self::RC32K,
165 RtcSlowClockSource::OscSlow => Self::EXT32K,
166 _ => Self::RcSlow,
167 }
168 }
169}
170
171fn modem_clock_hal_deselect_all_wifi_lpclk_source() {
172 MODEM_LPCON::regs().wifi_lp_clk_conf().modify(|_, w| {
173 w.clk_wifipwr_lp_sel_osc_slow().clear_bit();
174 w.clk_wifipwr_lp_sel_osc_fast().clear_bit();
175 w.clk_wifipwr_lp_sel_xtal32k().clear_bit();
176 w.clk_wifipwr_lp_sel_xtal().clear_bit()
177 });
178}
179
180fn modem_clock_hal_select_wifi_lpclk_source(src: ModemClockLpclkSource) {
181 MODEM_LPCON::regs()
182 .wifi_lp_clk_conf()
183 .modify(|_, w| match src {
184 ModemClockLpclkSource::RcSlow => w.clk_wifipwr_lp_sel_osc_slow().set_bit(),
185 ModemClockLpclkSource::RcFast => w.clk_wifipwr_lp_sel_osc_fast().set_bit(),
186 ModemClockLpclkSource::MainXtal => w.clk_wifipwr_lp_sel_xtal().set_bit(),
187
188 ModemClockLpclkSource::RC32K
189 | ModemClockLpclkSource::XTAL32K
190 | ModemClockLpclkSource::EXT32K => w.clk_wifipwr_lp_sel_xtal32k().set_bit(),
191 });
192
193 MODEM_LPCON::regs()
194 .modem_32k_clk_conf()
195 .modify(|_, w| unsafe {
196 match src {
197 ModemClockLpclkSource::RcSlow
198 | ModemClockLpclkSource::RcFast
199 | ModemClockLpclkSource::MainXtal => w,
200
201 ModemClockLpclkSource::RC32K => w.clk_modem_32k_sel().bits(1),
202 ModemClockLpclkSource::XTAL32K => w.clk_modem_32k_sel().bits(0),
203 ModemClockLpclkSource::EXT32K => w.clk_modem_32k_sel().bits(2),
204 }
205 });
206}
207
208fn modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider: u16) {
209 MODEM_LPCON::regs()
210 .wifi_lp_clk_conf()
211 .modify(|_, w| unsafe { w.clk_wifipwr_lp_div_num().bits(divider) });
212}
213
214fn modem_clock_hal_enable_wifipwr_clock(enable: bool) {
215 MODEM_LPCON::regs()
216 .clk_conf()
217 .modify(|_, w| w.clk_wifipwr_en().bit(enable));
218}
219
220fn modem_clock_select_lp_clock_source_wifi(src: ModemClockLpclkSource, divider: u16) {
222 modem_clock_hal_deselect_all_wifi_lpclk_source();
223 modem_clock_hal_select_wifi_lpclk_source(src);
224 modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider);
225 modem_clock_hal_enable_wifipwr_clock(true);
226}
227
228const fn hp_retention_regdma_config(dir: u8, entry: u8) -> u8 {
229 (((dir) << 2) | (entry & 0x3)) & 0x7
230}
231
232const HP_CALI_DBIAS: u8 = 25;
233const LP_CALI_DBIAS: u8 = 26;
234
235const ICG_MODEM_CODE_SLEEP: u8 = 0;
236const ICG_MODEM_CODE_MODEM: u8 = 1;
237const ICG_MODEM_CODE_ACTIVE: u8 = 2;
238
239const HP_SYSCLK_XTAL: u8 = 0;
240const HP_SYSCLK_PLL: u8 = 1;
241
242bitfield::bitfield! {
243 #[derive(Clone, Copy, Default)]
244 pub struct HpDigPower(u32);
246
247 pub bool, vdd_spi_pd_en, set_vdd_spi_pd_en: 21;
248 pub bool, mem_dslp , set_mem_dslp : 22;
249 pub u8, mem_pd_en , set_mem_pd_en : 26, 23;
250 pub bool, wifi_pd_en , set_wifi_pd_en : 27;
251 pub bool, cpu_pd_en , set_cpu_pd_en : 29;
252 pub bool, aon_pd_en , set_aon_pd_en : 30;
253 pub bool, top_pd_en , set_top_pd_en : 31;
254}
255
256bitfield::bitfield! {
257 #[derive(Clone, Copy, Default)]
258 pub struct HpClkPower(u32);
260
261 pub bool, i2c_iso_en , set_i2c_iso_en : 26;
262 pub bool, i2c_retention, set_i2c_retention: 27;
263 pub bool, xpd_bb_i2c , set_xpd_bb_i2c : 28;
264 pub bool, xpd_bbpll_i2c, set_xpd_bbpll_i2c: 29;
265 pub bool, xpd_bbpll , set_xpd_bbpll : 30;
266}
267
268bitfield::bitfield! {
269 #[derive(Clone, Copy, Default)]
270 pub struct HpXtalPower(u32);
272
273 pub bool, xpd_xtal , set_xpd_xtal : 31;
274}
275
276#[derive(Clone, Copy, Default)]
277pub struct HpSysPower {
279 pub dig_power: HpDigPower,
282 pub clk: HpClkPower,
283 pub xtal: HpXtalPower,
284}
285
286bitfield::bitfield! {
287 #[derive(Clone, Copy, Default)]
288 pub struct HpSysCntlReg(u32);
290
291 pub bool, uart_wakeup_en , set_uart_wakeup_en : 24;
292 pub bool, lp_pad_hold_all, set_lp_pad_hold_all: 25;
293 pub bool, hp_pad_hold_all, set_hp_pad_hold_all: 26;
294 pub bool, dig_pad_slp_sel, set_dig_pad_slp_sel: 27;
295 pub bool, dig_pause_wdt , set_dig_pause_wdt : 28;
296 pub bool, dig_cpu_stall , set_dig_cpu_stall : 29;
297}
298
299bitfield::bitfield! {
300 #[derive(Clone, Copy, Default)]
301 pub struct HpIcgModem(u32);
303
304 pub u8, code, set_code: 31, 30;
305}
306
307bitfield::bitfield! {
308 #[derive(Clone, Copy, Default)]
309 pub struct HpSysclk(u32);
311
312 pub bool, dig_sysclk_nodiv , set_dig_sysclk_nodiv : 26;
313 pub bool, icg_sysclk_en , set_icg_sysclk_en : 27;
314 pub bool, sysclk_slp_sel , set_sysclk_slp_sel : 28;
315 pub bool, icg_slp_sel , set_icg_slp_sel : 29;
316 pub u8, dig_sysclk_sel , set_dig_sysclk_sel : 31, 30;
317}
318
319#[derive(Clone, Copy, Default)]
321struct SystemClockParam {
322 icg_func: u32,
323 icg_apb: u32,
324 icg_modem: HpIcgModem,
325 sysclk: HpSysclk,
326}
327
328bitfield::bitfield! {
329 #[derive(Clone, Copy, Default)]
330 pub struct HpAnalogBias(u32);
332
333 pub bool, xpd_bias , set_xpd_bias : 25;
334 pub u8, dbg_atten , set_dbg_atten : 29, 26;
335 pub bool, pd_cur , set_pd_cur : 30;
336 pub bool, bias_sleep, set_bias_sleep: 31;
337}
338
339bitfield::bitfield! {
340 #[derive(Clone, Copy, Default)]
341 pub struct HpAnalogRegulator0(u32);
343
344 pub u8, lp_dbias_vol , set_lp_dbias_vol : 8, 4;
346 pub u8, hp_dbias_vol , set_hp_dbias_vol : 13, 9;
348 pub bool, dbias_sel , set_dbias_sel : 14;
350 pub bool, dbias_init , set_dbias_init : 15;
352
353 pub bool, slp_mem_xpd , set_slp_mem_xpd : 16;
354 pub bool, slp_logic_xpd , set_slp_logic_xpd : 17;
355 pub bool, xpd , set_xpd : 18;
356 pub u8, slp_mem_dbias , set_slp_mem_dbias : 22, 19;
357 pub u8, slp_logic_dbias, set_slp_logic_dbias: 26, 23;
358 pub u8, dbias , set_dbias : 31, 27;
359}
360
361bitfield::bitfield! {
362 #[derive(Clone, Copy, Default)]
363 pub struct HpAnalogRegulator1(u32);
365
366 pub u32, drv_b , set_drv_b : 31, 8;
367}
368
369#[derive(Clone, Copy, Default)]
370pub struct HpAnalog {
372 pub bias: HpAnalogBias,
373 pub regulator0: HpAnalogRegulator0,
374 pub regulator1: HpAnalogRegulator1,
375}
376
377bitfield::bitfield! {
378 #[derive(Clone, Copy, Default)]
379 pub struct HpActiveBackup(u32);
381
382 pub u8, hp_sleep2active_backup_modem_clk_code, set_hp_sleep2active_backup_modem_clk_code: 5, 4;
383 pub u8, hp_modem2active_backup_modem_clk_code, set_hp_modem2active_backup_modem_clk_code: 7, 6;
384 pub bool, hp_active_retention_mode , set_hp_active_retention_mode : 10;
385 pub bool, hp_sleep2active_retention_en , set_hp_sleep2active_retention_en : 11;
386 pub bool, hp_modem2active_retention_en , set_hp_modem2active_retention_en : 12;
387 pub u8, hp_sleep2active_backup_clk_sel , set_hp_sleep2active_backup_clk_sel : 15, 14;
388 pub u8, hp_modem2active_backup_clk_sel , set_hp_modem2active_backup_clk_sel : 17, 16;
389 pub u8, hp_sleep2active_backup_mode , set_hp_sleep2active_backup_mode : 22, 20;
390 pub u8, hp_modem2active_backup_mode , set_hp_modem2active_backup_mode : 25, 23;
391 pub bool, hp_sleep2active_backup_en , set_hp_sleep2active_backup_en : 29;
392 pub bool, hp_modem2active_backup_en , set_hp_modem2active_backup_en : 30;
393}
394
395bitfield::bitfield! {
396 #[derive(Clone, Copy, Default)]
397 pub struct HpModemBackup(u32);
399
400 pub u8, hp_sleep2modem_backup_modem_clk_code , set_hp_sleep2modem_backup_modem_clk_code : 5, 4;
401 pub bool, hp_modem_retention_mode , set_hp_modem_retention_mode : 10;
402 pub bool, hp_sleep2modem_retention_en , set_hp_sleep2modem_retention_en : 11;
403 pub u8, hp_sleep2modem_backup_clk_sel , set_hp_sleep2modem_backup_clk_sel : 15, 14;
404 pub u8, hp_sleep2modem_backup_mode , set_hp_sleep2modem_backup_mode : 22, 20;
405 pub bool, hp_sleep2modem_backup_en , set_hp_sleep2modem_backup_en : 29;
406}
407
408bitfield::bitfield! {
409 #[derive(Clone, Copy, Default)]
410 pub struct HpSleepBackup(u32);
412
413 pub u8, hp_modem2sleep_backup_modem_clk_code , set_hp_modem2sleep_backup_modem_clk_code : 7, 6;
414 pub u8, hp_active2sleep_backup_modem_clk_code, set_hp_active2sleep_backup_modem_clk_code: 9, 8;
415 pub bool, hp_sleep_retention_mode , set_hp_sleep_retention_mode : 10;
416 pub bool, hp_modem2sleep_retention_en , set_hp_modem2sleep_retention_en : 12;
417 pub bool, hp_active2sleep_retention_en , set_hp_active2sleep_retention_en : 13;
418 pub u8, hp_modem2sleep_backup_clk_sel , set_hp_modem2sleep_backup_clk_sel : 17, 16;
419 pub u8, hp_active2sleep_backup_clk_sel , set_hp_active2sleep_backup_clk_sel : 19, 18;
420 pub u8, hp_modem2sleep_backup_mode , set_hp_modem2sleep_backup_mode : 25, 23;
421 pub u8, hp_active2sleep_backup_mode , set_hp_active2sleep_backup_mode : 28, 26;
422 pub bool, hp_modem2sleep_backup_en , set_hp_modem2sleep_backup_en : 30;
423 pub bool, hp_active2sleep_backup_en , set_hp_active2sleep_backup_en : 31;
424}
425
426bitfield::bitfield! {
427 #[derive(Clone, Copy, Default)]
428 pub struct HpBackupClk(u32);
430
431 pub bool, gdma , set_gdma : 0;
432 pub bool, spi2 , set_spi2 : 1;
433 pub bool, i2s_rx , set_i2s_rx : 2;
434 pub bool, uart0 , set_uart0 : 3;
435 pub bool, uart1 , set_uart1 : 4;
436 pub bool, uhci , set_uhci : 5;
437 pub bool, usb_device , set_usb_device : 6;
438 pub bool, i2s_tx , set_i2s_tx : 7;
439 pub bool, regdma , set_regdma : 8;
440 pub bool, retention , set_retention : 9;
441 pub bool, mem_monitor , set_mem_monitor : 10;
442 pub bool, sdio_slave , set_sdio_slave : 11;
443 pub bool, tsens , set_tsens : 12;
444 pub bool, tg1 , set_tg1 : 13;
445 pub bool, tg0 , set_tg0 : 14;
446 pub bool, hpbus , set_hpbus : 15;
447 pub bool, soc_etm , set_soc_etm : 16;
448 pub bool, hpcore , set_hpcore : 17;
449 pub bool, systimer , set_systimer : 18;
450 pub bool, sec , set_sec : 19;
451 pub bool, saradc , set_saradc : 20;
452 pub bool, rmt , set_rmt : 21;
453 pub bool, pwm , set_pwm : 22;
454 pub bool, pvt_monitor , set_pvt_monitor : 23;
455 pub bool, parl_tx , set_parl_tx : 24;
456 pub bool, parl_rx , set_parl_rx : 25;
457 pub bool, mspi , set_mspi : 26;
458 pub bool, ledc , set_ledc : 27;
459 pub bool, iomux , set_iomux : 28;
460 pub bool, i2c , set_i2c : 29;
461 pub bool, can1 , set_can1 : 30;
462 pub bool, can0 , set_can0 : 31;
463}
464
465macro_rules! hp_system_init {
466 ($state:ident => $s:ident) => {
467 paste::paste! {
468 unsafe {
469 PMU::regs().[<$state _dig_power >]().modify(|_, w| w.bits($s.power.dig_power.0));
471 PMU::regs().[<$state _hp_ck_power >]().modify(|_, w| w.bits($s.power.clk.0));
472 PMU::regs().[<$state _xtal >]().modify(|_, w| w
473 .[<$state _xpd_xtal >]().bit($s.power.xtal.xpd_xtal())
474 );
475
476 PMU::regs().[<$state _icg_hp_func >]().write(|w| w.bits($s.clock.icg_func));
478 PMU::regs().[<$state _icg_hp_apb >]().write(|w| w.bits($s.clock.icg_apb));
479 PMU::regs().[<$state _icg_modem >]().write(|w| w
480 .[<$state _dig_icg_modem_code >]().bits($s.clock.icg_modem.code())
481 );
482 PMU::regs().[<$state _sysclk >]().modify(|_, w| w
483 .[<$state _dig_sys_clk_no_div >]().bit($s.clock.sysclk.dig_sysclk_nodiv())
484 .[<$state _icg_sys_clock_en >]().bit($s.clock.sysclk.icg_sysclk_en())
485 .[<$state _sys_clk_slp_sel >]().bit($s.clock.sysclk.sysclk_slp_sel())
486 .[<$state _icg_slp_sel >]().bit($s.clock.sysclk.icg_slp_sel())
487 .[<$state _dig_sys_clk_sel >]().bits($s.clock.sysclk.dig_sysclk_sel())
488 );
489
490 PMU::regs().[<$state _hp_sys_cntl >]().modify(|_, w| w
493 .[<$state _uart_wakeup_en >]().bit($s.syscntl.uart_wakeup_en())
494 .[<$state _lp_pad_hold_all >]().bit($s.syscntl.lp_pad_hold_all())
495 .[<$state _hp_pad_hold_all >]().bit($s.syscntl.hp_pad_hold_all())
496 .[<$state _dig_pad_slp_sel >]().bit($s.syscntl.dig_pad_slp_sel())
497 .[<$state _dig_pause_wdt >]().bit($s.syscntl.dig_pause_wdt())
498 .[<$state _dig_cpu_stall >]().bit($s.syscntl.dig_cpu_stall())
499 );
500
501 PMU::regs().[<$state _bias >]().modify(|_, w| w
504 .[<$state _xpd_bias >]().bit($s.anlg.bias.xpd_bias())
505 .[<$state _dbg_atten >]().bits($s.anlg.bias.dbg_atten())
506 .[<$state _pd_cur >]().bit($s.anlg.bias.pd_cur())
507 .sleep().bit($s.anlg.bias.bias_sleep())
508 );
509
510 PMU::regs().[<$state _hp_regulator0 >]().modify(|_, w| w
511 .[<$state _hp_regulator_slp_mem_xpd >]().bit($s.anlg.regulator0.slp_mem_xpd())
512 .[<$state _hp_regulator_slp_logic_xpd >]().bit($s.anlg.regulator0.slp_logic_xpd())
513 .[<$state _hp_regulator_xpd >]().bit($s.anlg.regulator0.xpd())
514 .[<$state _hp_regulator_slp_mem_dbias >]().bits($s.anlg.regulator0.slp_mem_dbias())
515 .[<$state _hp_regulator_slp_logic_dbias >]().bits($s.anlg.regulator0.slp_logic_dbias())
516 .[<$state _hp_regulator_dbias >]().bits($s.anlg.regulator0.dbias())
517 );
518
519 PMU::regs().[<$state _hp_regulator1 >]().modify(|_, w| w
520 .[<$state _hp_regulator_drv_b >]().bits($s.anlg.regulator1.drv_b())
521 );
522
523 PMU::regs().[<$state _backup >]().write(|w| w.bits($s.retention));
526 PMU::regs().[<$state _backup_clk >]().write(|w| w.bits($s.backup_clk));
527 }
528 }
529 };
530}
531
532struct HpSystemInit {
533 power: HpSysPower,
534 clock: SystemClockParam,
535 syscntl: HpSysCntlReg,
536 anlg: HpAnalog,
537 retention: u32,
538 backup_clk: u32,
539}
540impl HpSystemInit {
541 fn active() -> Self {
542 let mut power = HpSysPower::default();
545 power.dig_power.set_vdd_spi_pd_en(false);
546 power.dig_power.set_wifi_pd_en(false);
547 power.dig_power.set_cpu_pd_en(false);
548 power.dig_power.set_aon_pd_en(false);
549 power.dig_power.set_top_pd_en(false);
550 power.dig_power.set_mem_pd_en(0);
551 power.dig_power.set_mem_dslp(false);
552
553 power.clk.set_i2c_iso_en(false);
554 power.clk.set_i2c_retention(false);
555 power.clk.set_xpd_bb_i2c(true);
556 power.clk.set_xpd_bbpll_i2c(true);
557 power.clk.set_xpd_bbpll(true);
558
559 power.xtal.set_xpd_xtal(true);
560
561 let mut clock = SystemClockParam {
562 icg_func: 0xffffffff,
563 icg_apb: 0xffffffff,
564 ..SystemClockParam::default()
565 };
566 clock.icg_modem.set_code(ICG_MODEM_CODE_ACTIVE);
567 clock.sysclk.set_dig_sysclk_nodiv(false);
568 clock.sysclk.set_icg_sysclk_en(true);
569 clock.sysclk.set_sysclk_slp_sel(false);
570 clock.sysclk.set_icg_slp_sel(false);
571 clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
572
573 let mut syscntl = HpSysCntlReg::default();
574 syscntl.set_uart_wakeup_en(false);
575 syscntl.set_lp_pad_hold_all(false);
576 syscntl.set_hp_pad_hold_all(false);
577 syscntl.set_dig_pad_slp_sel(false);
578 syscntl.set_dig_pause_wdt(false);
579 syscntl.set_dig_cpu_stall(false);
580
581 let mut anlg = HpAnalog::default();
583 anlg.bias.set_xpd_bias(true);
584 anlg.bias.set_dbg_atten(0x0);
585 anlg.bias.set_pd_cur(false);
586 anlg.bias.set_bias_sleep(false);
587
588 anlg.regulator0.set_lp_dbias_vol(0xD);
590 anlg.regulator0.set_hp_dbias_vol(0x1C);
591 anlg.regulator0.set_dbias_sel(true);
592 anlg.regulator0.set_dbias_init(true);
593
594 anlg.regulator0.set_slp_mem_xpd(false);
595 anlg.regulator0.set_slp_logic_xpd(false);
596 anlg.regulator0.set_xpd(true);
597 anlg.regulator0.set_slp_mem_dbias(0);
598 anlg.regulator0.set_slp_logic_dbias(0);
599 anlg.regulator0.set_dbias(HP_CALI_DBIAS);
600
601 anlg.regulator1.set_drv_b(0);
602
603 let mut retention = HpActiveBackup::default();
604 retention.set_hp_sleep2active_backup_modem_clk_code(2);
605 retention.set_hp_modem2active_backup_modem_clk_code(2);
606 retention.set_hp_active_retention_mode(false);
607 retention.set_hp_sleep2active_retention_en(false);
608 retention.set_hp_modem2active_retention_en(false);
609 retention.set_hp_sleep2active_backup_clk_sel(0);
610 retention.set_hp_modem2active_backup_clk_sel(1);
611 retention.set_hp_sleep2active_backup_mode(hp_retention_regdma_config(0, 0));
612 retention.set_hp_modem2active_backup_mode(hp_retention_regdma_config(0, 2));
613 retention.set_hp_sleep2active_backup_en(false);
614 retention.set_hp_modem2active_backup_en(false);
615
616 let mut backup_clk = HpBackupClk::default();
617 backup_clk.set_regdma(true);
618 backup_clk.set_tg0(true);
619 backup_clk.set_tg1(true);
620 backup_clk.set_hpbus(true);
621 backup_clk.set_mspi(true);
622 backup_clk.set_iomux(true);
623 backup_clk.set_spi2(true);
624 backup_clk.set_uart0(true);
625 backup_clk.set_systimer(true);
626
627 Self {
628 power,
629 clock,
630 syscntl,
631 anlg,
632 retention: retention.0,
633 backup_clk: backup_clk.0,
634 }
635 }
636
637 fn modem() -> Self {
638 let mut power = HpSysPower::default();
639 power.dig_power.set_vdd_spi_pd_en(false);
640 power.dig_power.set_wifi_pd_en(false);
641 power.dig_power.set_cpu_pd_en(true);
642 power.dig_power.set_aon_pd_en(false);
643 power.dig_power.set_top_pd_en(false);
644 power.dig_power.set_mem_pd_en(0);
645 power.dig_power.set_mem_dslp(false);
646
647 power.clk.set_xpd_bb_i2c(true);
648 power.clk.set_xpd_bbpll_i2c(true);
649 power.clk.set_xpd_bbpll(true);
650 power.clk.set_i2c_iso_en(false);
651 power.clk.set_i2c_retention(false);
652
653 power.xtal.set_xpd_xtal(true);
654
655 let mut clock = SystemClockParam {
656 icg_func: 0,
657 icg_apb: 0,
658 ..SystemClockParam::default()
659 };
660 clock.icg_modem.set_code(ICG_MODEM_CODE_MODEM);
661 clock.sysclk.set_dig_sysclk_nodiv(false);
662 clock.sysclk.set_icg_sysclk_en(true);
663 clock.sysclk.set_sysclk_slp_sel(true);
664 clock.sysclk.set_icg_slp_sel(true);
665 clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_PLL);
666
667 let mut syscntl = HpSysCntlReg::default();
668 syscntl.set_uart_wakeup_en(true);
669 syscntl.set_lp_pad_hold_all(false);
670 syscntl.set_hp_pad_hold_all(false);
671 syscntl.set_dig_pad_slp_sel(false);
672 syscntl.set_dig_pause_wdt(true);
673 syscntl.set_dig_cpu_stall(true);
674
675 let mut anlg = HpAnalog::default();
676 anlg.bias.set_xpd_bias(false);
677 anlg.bias.set_dbg_atten(0x0);
678 anlg.bias.set_pd_cur(false);
679 anlg.bias.set_bias_sleep(false);
680
681 anlg.regulator0.set_slp_mem_xpd(false);
682 anlg.regulator0.set_slp_logic_xpd(false);
683 anlg.regulator0.set_xpd(true);
684 anlg.regulator0.set_slp_mem_dbias(0);
685 anlg.regulator0.set_slp_logic_dbias(0);
686 anlg.regulator0.set_dbias(HP_CALI_DBIAS);
687
688 anlg.regulator1.set_drv_b(0);
689
690 let mut retention = HpModemBackup::default();
691 retention.set_hp_sleep2modem_backup_modem_clk_code(1);
692 retention.set_hp_modem_retention_mode(false);
693 retention.set_hp_sleep2modem_retention_en(false);
694 retention.set_hp_sleep2modem_backup_clk_sel(0);
695 retention.set_hp_sleep2modem_backup_mode(hp_retention_regdma_config(0, 1));
696 retention.set_hp_sleep2modem_backup_en(false);
697
698 let mut backup_clk = HpBackupClk::default();
699 backup_clk.set_regdma(true);
700 backup_clk.set_tg0(true);
701 backup_clk.set_tg1(true);
702 backup_clk.set_hpbus(true);
703 backup_clk.set_mspi(true);
704 backup_clk.set_iomux(true);
705 backup_clk.set_spi2(true);
706 backup_clk.set_uart0(true);
707 backup_clk.set_systimer(true);
708
709 Self {
710 power,
711 clock,
712 syscntl,
713 anlg,
714 retention: retention.0,
715 backup_clk: backup_clk.0,
716 }
717 }
718
719 fn sleep() -> Self {
720 let mut power = HpSysPower::default();
721 power.dig_power.set_vdd_spi_pd_en(true);
722 power.dig_power.set_mem_dslp(false);
723 power.dig_power.set_mem_pd_en(0);
724 power.dig_power.set_wifi_pd_en(true);
725 power.dig_power.set_cpu_pd_en(false);
726 power.dig_power.set_aon_pd_en(false);
727 power.dig_power.set_top_pd_en(false);
728
729 power.clk.set_i2c_iso_en(true);
730 power.clk.set_i2c_retention(true);
731 power.clk.set_xpd_bb_i2c(true);
732 power.clk.set_xpd_bbpll_i2c(false);
733 power.clk.set_xpd_bbpll(false);
734
735 power.xtal.set_xpd_xtal(false);
736
737 let mut clock = SystemClockParam {
738 icg_func: 0,
739 icg_apb: 0,
740 ..SystemClockParam::default()
741 };
742 clock.icg_modem.set_code(ICG_MODEM_CODE_SLEEP);
743 clock.sysclk.set_dig_sysclk_nodiv(false);
744 clock.sysclk.set_icg_sysclk_en(false);
745 clock.sysclk.set_sysclk_slp_sel(true);
746 clock.sysclk.set_icg_slp_sel(true);
747 clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
748
749 let mut anlg = HpAnalog::default();
750 anlg.bias.set_xpd_bias(false);
751 anlg.bias.set_dbg_atten(0x0);
752 anlg.bias.set_pd_cur(false);
753 anlg.bias.set_bias_sleep(false);
754
755 anlg.regulator0.set_slp_mem_xpd(false);
756 anlg.regulator0.set_slp_logic_xpd(false);
757 anlg.regulator0.set_xpd(true);
758 anlg.regulator0.set_slp_mem_dbias(0);
759 anlg.regulator0.set_slp_logic_dbias(0);
760 anlg.regulator0.set_dbias(1);
761
762 anlg.regulator1.set_drv_b(0);
763
764 let mut retention = HpSleepBackup::default();
765 retention.set_hp_modem2sleep_backup_modem_clk_code(0);
766 retention.set_hp_active2sleep_backup_modem_clk_code(2);
767 retention.set_hp_sleep_retention_mode(false);
768 retention.set_hp_modem2sleep_retention_en(false);
769 retention.set_hp_active2sleep_retention_en(false);
770 retention.set_hp_modem2sleep_backup_clk_sel(0);
771 retention.set_hp_active2sleep_backup_clk_sel(0);
772 retention.set_hp_modem2sleep_backup_mode(hp_retention_regdma_config(1, 1));
773 retention.set_hp_active2sleep_backup_mode(hp_retention_regdma_config(1, 0));
774 retention.set_hp_modem2sleep_backup_en(false);
775 retention.set_hp_active2sleep_backup_en(false);
776
777 let mut backup_clk = HpBackupClk::default();
778 backup_clk.set_regdma(true);
779 backup_clk.set_tg0(true);
780 backup_clk.set_tg1(true);
781 backup_clk.set_hpbus(true);
782 backup_clk.set_mspi(true);
783 backup_clk.set_iomux(true);
784 backup_clk.set_spi2(true);
785 backup_clk.set_uart0(true);
786 backup_clk.set_systimer(true);
787
788 let mut syscntl = HpSysCntlReg::default();
789 syscntl.set_uart_wakeup_en(true);
790 syscntl.set_lp_pad_hold_all(false);
791 syscntl.set_hp_pad_hold_all(false);
792 syscntl.set_dig_pad_slp_sel(true);
793 syscntl.set_dig_pause_wdt(true);
794 syscntl.set_dig_cpu_stall(true);
795
796 Self {
797 power,
798 clock,
799 syscntl,
800 anlg,
801 retention: retention.0,
802 backup_clk: backup_clk.0,
803 }
804 }
805
806 fn init_default() {
807 let active = Self::active();
808 let modem = Self::modem();
809 let sleep = Self::sleep();
810
811 hp_system_init!(hp_active => active);
812 hp_system_init!(hp_modem => modem);
813 hp_system_init!(hp_sleep => sleep);
814
815 unsafe {
816 PMU::regs()
818 .imm_modem_icg()
819 .write(|w| w.update_dig_icg_modem_en().bit(true));
820 PMU::regs()
821 .imm_sleep_sysclk()
822 .write(|w| w.update_dig_icg_switch().bit(true));
823
824 const PMU_SLEEP_PROTECT_HP_LP_SLEEP: u8 = 2;
825 PMU::regs()
826 .slp_wakeup_cntl3()
827 .modify(|_, w| w.sleep_prt_sel().bits(PMU_SLEEP_PROTECT_HP_LP_SLEEP));
828 }
829 }
830}
831
832bitfield::bitfield! {
833 #[derive(Clone, Copy, Default)]
834 pub struct LpDigPower(u32);
836
837 pub u32, mem_dslp , set_mem_dslp : 30;
838 pub u32, peri_pd_en, set_peri_pd_en: 31;
839
840}
841
842bitfield::bitfield! {
843 #[derive(Clone, Copy, Default)]
844 pub struct LpClkPower(u32);
846
847 pub u32, xpd_xtal32k, set_xpd_xtal32k: 28;
848 pub u32, xpd_rc32k , set_xpd_rc32k : 29;
849 pub u32, xpd_fosc , set_xpd_fosc : 30;
850 pub u32, pd_osc , set_pd_osc : 31;
851}
852
853bitfield::bitfield! {
854 #[derive(Clone, Copy, Default)]
855 pub struct LpXtalPower(u32);
857
858 pub bool, xpd_xtal , set_xpd_xtal : 31;
859}
860
861#[derive(Clone, Copy, Default)]
862pub struct LpSysPower {
864 pub dig_power: LpDigPower,
867 pub clk_power: LpClkPower,
868 pub xtal: LpXtalPower,
869}
870
871bitfield::bitfield! {
872 #[derive(Clone, Copy, Default)]
873 pub struct LpAnalogBias(u32);
875
876 pub bool, xpd_bias , set_xpd_bias : 25;
877 pub u8, dbg_atten , set_dbg_atten : 29, 26;
878 pub bool, pd_cur , set_pd_cur : 30;
879 pub bool, bias_sleep, set_bias_sleep: 31;
880}
881
882bitfield::bitfield! {
883 #[derive(Clone, Copy, Default)]
884 pub struct LpAnalogRegulator0(u32);
886
887 pub bool, slp_xpd , set_slp_xpd : 21;
888 pub bool, xpd , set_xpd : 22;
889 pub u8, slp_dbias, set_slp_dbias: 26, 23;
890 pub u8, dbias , set_dbias : 31, 27;
891}
892
893bitfield::bitfield! {
894 #[derive(Clone, Copy, Default)]
895 pub struct LpAnalogRegulator1(u32);
897
898 pub u8, drv_b , set_drv_b : 31, 28;
899}
900
901#[derive(Clone, Copy, Default)]
902pub struct LpAnalog {
904 pub bias: LpAnalogBias,
905 pub regulator0: LpAnalogRegulator0,
906 pub regulator1: LpAnalogRegulator1,
907}
908
909macro_rules! lp_system_init {
910 ($state:ident => $s:ident) => {
911 paste::paste! {
912 unsafe {
913 PMU::regs().[< $state _dig_power >]().modify(|_, w| w.bits($s.dig_power.0));
915 PMU::regs().[< $state _ck_power >]().modify(|_, w| w.bits($s.clk_power.0));
916
917 PMU::regs().[< $state _regulator0 >]().modify(|_, w| w
919 .[< $state _regulator_slp_xpd >]().bit($s.analog_regulator0.slp_xpd())
920 .[< $state _regulator_xpd >]().bit($s.analog_regulator0.xpd())
921 .[< $state _regulator_slp_dbias >]().bits($s.analog_regulator0.slp_dbias())
922 .[< $state _regulator_dbias >]().bits($s.analog_regulator0.dbias())
923 );
924
925 PMU::regs().[< $state _regulator1 >]().modify(|_, w| w
926 .[< $state _regulator_drv_b >]().bits($s.analog_regulator1.drv_b())
927 );
928 }
929 }
930 };
931}
932
933struct LpSystemInit {
934 dig_power: LpDigPower,
935 clk_power: LpClkPower,
936 xtal: LpXtalPower,
937 bias: LpAnalogBias,
938 analog_regulator0: LpAnalogRegulator0,
939 analog_regulator1: LpAnalogRegulator1,
940}
941impl LpSystemInit {
942 fn active() -> Self {
943 let mut dig_power = LpDigPower::default();
944 dig_power.set_peri_pd_en(false);
945 dig_power.set_mem_dslp(false);
946
947 let mut clk_power = LpClkPower::default();
948 clk_power.set_xpd_xtal32k(true);
949 clk_power.set_xpd_rc32k(true);
950 clk_power.set_xpd_fosc(true);
951
952 let mut analog_regulator0 = LpAnalogRegulator0::default();
953 analog_regulator0.set_slp_xpd(false);
954 analog_regulator0.set_xpd(true);
955 analog_regulator0.set_slp_dbias(0);
956 analog_regulator0.set_dbias(26);
957
958 let mut analog_regulator1 = LpAnalogRegulator1::default();
959 analog_regulator1.set_drv_b(0);
960
961 Self {
962 dig_power,
963 clk_power,
964 xtal: LpXtalPower::default(),
965 bias: LpAnalogBias::default(),
966 analog_regulator0,
967 analog_regulator1,
968 }
969 }
970
971 fn sleep() -> Self {
972 let mut dig_power = LpDigPower::default();
973 dig_power.set_mem_dslp(true);
974 dig_power.set_peri_pd_en(false);
975
976 let mut clk_power = LpClkPower::default();
977 clk_power.set_xpd_xtal32k(false);
978 clk_power.set_xpd_rc32k(false);
979 clk_power.set_xpd_fosc(false);
980 clk_power.set_pd_osc(false);
981
982 let mut xtal = LpXtalPower::default();
983 xtal.set_xpd_xtal(false);
984
985 let mut analog_bias = LpAnalogBias::default();
986 analog_bias.set_xpd_bias(false);
987 analog_bias.set_dbg_atten(0);
988 analog_bias.set_pd_cur(true);
989 analog_bias.set_bias_sleep(true);
990
991 let mut analog_regulator0 = LpAnalogRegulator0::default();
992 analog_regulator0.set_slp_xpd(false);
993 analog_regulator0.set_xpd(true);
994 analog_regulator0.set_slp_dbias(0);
995 analog_regulator0.set_dbias(12);
996
997 let mut analog_regulator1 = LpAnalogRegulator1::default();
998 analog_regulator1.set_drv_b(0);
999
1000 Self {
1001 dig_power,
1002 clk_power,
1003 xtal,
1004 bias: analog_bias,
1005 analog_regulator0,
1006 analog_regulator1,
1007 }
1008 }
1009
1010 fn init_default() {
1011 let active = Self::active();
1012 let sleep = Self::sleep();
1013
1014 lp_system_init!(hp_sleep_lp => active);
1015 lp_system_init!(lp_sleep_lp => sleep);
1016
1017 PMU::regs()
1018 .lp_sleep_xtal()
1019 .modify(|_, w| w.lp_sleep_xpd_xtal().bit(sleep.xtal.xpd_xtal()));
1020
1021 PMU::regs().lp_sleep_bias().modify(|_, w| unsafe {
1022 w.lp_sleep_xpd_bias().bit(sleep.bias.xpd_bias()); w.lp_sleep_dbg_atten().bits(sleep.bias.dbg_atten()); w.lp_sleep_pd_cur().bit(sleep.bias.pd_cur()); w.sleep().bit(sleep.bias.bias_sleep()) });
1027 }
1028}
1029
1030pub(crate) fn init() {
1031 PMU::regs()
1033 .rf_pwc()
1034 .modify(|_, w| w.perif_i2c_rstb().set_bit().xpd_perif_i2c().set_bit());
1035
1036 regi2c::I2C_DIG_REG_ENIF_RTC_DREG.write_field(1);
1037 regi2c::I2C_DIG_REG_ENIF_DIG_DREG.write_field(1);
1038 regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
1039 regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
1040
1041 HpSystemInit::init_default();
1042 LpSystemInit::init_default();
1043
1044 pmu_power_domain_force_default();
1045
1046 modem_clock_domain_power_state_icg_map_init();
1048
1049 let modem_lpclk_src = ModemClockLpclkSource::from(RtcSlowClockSource::current());
1058
1059 modem_clock_select_lp_clock_source_wifi(modem_lpclk_src, 0);
1060
1061 RtcClock::set_fast_freq(RtcFastClock::RcFast);
1062 RtcClock::set_slow_freq(RtcSlowClock::RcSlow);
1063}
1064
1065pub(crate) fn configure_clock() {
1066 let cal_val = loop {
1067 let res = RtcClock::calibrate(RtcCalSel::RtcMux, 1024);
1068 if res != 0 {
1069 break res;
1070 }
1071 };
1072
1073 LP_AON::regs()
1074 .store1()
1075 .modify(|_, w| unsafe { w.bits(cal_val) });
1076
1077 modem_clk_domain_active_state_icg_map_preinit();
1078}
1079
1080fn modem_clk_domain_active_state_icg_map_preinit() {
1081 unsafe {
1082 PMU::regs()
1084 .hp_active_icg_modem()
1085 .modify(|_, w| w.hp_active_dig_icg_modem_code().bits(ICG_MODEM_CODE_ACTIVE));
1086
1087 MODEM_SYSCON::regs()
1090 .clk_conf_power_st()
1091 .modify(|_, w| w.clk_modem_apb_st_map().bits(1 << ICG_MODEM_CODE_ACTIVE));
1092 MODEM_LPCON::regs().clk_conf_power_st().modify(|_, w| {
1093 w.clk_i2c_mst_st_map()
1094 .bits(1 << ICG_MODEM_CODE_ACTIVE)
1095 .clk_lp_apb_st_map()
1096 .bits(1 << ICG_MODEM_CODE_ACTIVE)
1097 });
1098
1099 PMU::regs()
1101 .imm_modem_icg()
1102 .write(|w| w.update_dig_icg_modem_en().set_bit());
1103 PMU::regs()
1104 .imm_sleep_sysclk()
1105 .write(|w| w.update_dig_icg_switch().set_bit());
1106
1107 LP_CLKRST::regs()
1110 .fosc_cntl()
1111 .modify(|_, w| w.fosc_dfreq().bits(100));
1112
1113 regi2c::I2C_DIG_REG_SCK_DCAP.write_reg(128);
1114
1115 LP_CLKRST::regs()
1116 .rc32k_cntl()
1117 .modify(|_, w| w.rc32k_dfreq().bits(700));
1118
1119 regi2c::I2C_DIG_REG_ENIF_RTC_DREG.write_field(1);
1120 regi2c::I2C_DIG_REG_ENIF_DIG_DREG.write_field(1);
1121
1122 PMU::regs()
1123 .hp_active_hp_regulator0()
1124 .modify(|_, w| w.hp_active_hp_regulator_dbias().bits(HP_CALI_DBIAS));
1125 PMU::regs()
1126 .hp_sleep_lp_regulator0()
1127 .modify(|_, w| w.hp_sleep_lp_regulator_dbias().bits(LP_CALI_DBIAS));
1128
1129 PCR::regs()
1131 .ctrl_tick_conf()
1132 .modify(|_, w| w.fosc_tick_num().bits(255));
1133 }
1134}
1135
1136#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
1146pub enum SocResetReason {
1147 ChipPowerOn = 0x01,
1153 CoreSw = 0x03,
1155 CoreDeepSleep = 0x05,
1157 CoreSDIO = 0x06,
1159 CoreMwdt0 = 0x07,
1161 CoreMwdt1 = 0x08,
1163 CoreRtcWdt = 0x09,
1165 Cpu0Mwdt0 = 0x0B,
1167 Cpu0Sw = 0x0C,
1169 Cpu0RtcWdt = 0x0D,
1171 SysBrownOut = 0x0F,
1173 SysRtcWdt = 0x10,
1175 Cpu0Mwdt1 = 0x11,
1177 SysSuperWdt = 0x12,
1179 CoreEfuseCrc = 0x14,
1181 CoreUsbUart = 0x15,
1183 CoreUsbJtag = 0x16,
1185 Cpu0JtagCpu = 0x18,
1187}
1188
1189pub(crate) fn rtc_clk_cpu_freq_set_xtal() {
1190 let freq = RtcClock::xtal_freq().mhz();
1192
1193 esp32c6_rtc_update_to_xtal_raw(freq, 1);
1194
1195 rtc_clk_bbpll_disable();
1198 }
1200
1201#[derive(Clone, Copy, PartialEq, Debug)]
1202#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1203pub(crate) struct UnsupportedClockSource;
1204
1205#[derive(Clone, Copy, PartialEq, Debug)]
1206#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1207pub(crate) enum CpuClockSource {
1208 Xtal,
1209 Pll,
1210 RcFast,
1211}
1212
1213impl CpuClockSource {
1214 pub(crate) fn current() -> Result<Self, UnsupportedClockSource> {
1215 let source = match PCR::regs().sysclk_conf().read().soc_clk_sel().bits() {
1216 0 => CpuClockSource::Xtal,
1217 1 => CpuClockSource::Pll,
1218 2 => CpuClockSource::RcFast,
1219 _ => return Err(UnsupportedClockSource),
1220 };
1221
1222 Ok(source)
1223 }
1224
1225 pub(crate) fn select(self) {
1226 PCR::regs().sysclk_conf().modify(|_, w| unsafe {
1227 w.soc_clk_sel().bits(match self {
1228 CpuClockSource::Xtal => 0,
1229 CpuClockSource::Pll => 1,
1230 CpuClockSource::RcFast => 2,
1231 })
1232 });
1233 }
1234}
1235
1236#[derive(Clone, Copy)]
1237pub(crate) struct SavedClockConfig {
1238 pub source: CpuClockSource,
1240
1241 pub source_freq_mhz: u32,
1243
1244 pub div: u8,
1246}
1247
1248impl SavedClockConfig {
1249 pub(crate) fn save() -> Self {
1250 let source = unwrap!(CpuClockSource::current());
1251
1252 let div;
1253 let source_freq_mhz;
1254 match source {
1255 CpuClockSource::Xtal => {
1256 div = esp32c6_cpu_get_ls_divider();
1257 source_freq_mhz = RtcClock::xtal_freq().mhz();
1258 }
1259 CpuClockSource::Pll => {
1260 div = esp32c6_cpu_get_hs_divider();
1261 source_freq_mhz = esp32c6_bbpll_get_freq_mhz();
1262 }
1263 CpuClockSource::RcFast => {
1264 div = esp32c6_cpu_get_ls_divider();
1265 source_freq_mhz = 20;
1266 }
1267 }
1268
1269 SavedClockConfig {
1270 source,
1271 source_freq_mhz,
1272 div,
1273 }
1274 }
1275
1276 fn freq_mhz(&self) -> u32 {
1277 self.source_freq_mhz / self.div as u32
1278 }
1279
1280 pub(crate) fn restore(self) {
1282 let old_source = unwrap!(CpuClockSource::current());
1283
1284 match self.source {
1285 CpuClockSource::Xtal => esp32c6_rtc_update_to_xtal_raw(self.freq_mhz(), self.div),
1286 CpuClockSource::RcFast => esp32c6_rtc_update_to_8m(),
1287 CpuClockSource::Pll => {
1288 if old_source != CpuClockSource::Pll {
1289 rtc_clk_bbpll_enable();
1290 esp32c6_rtc_bbpll_configure_raw(
1291 RtcClock::xtal_freq().mhz(),
1292 self.source_freq_mhz,
1293 );
1294 }
1295 esp32c6_rtc_freq_to_pll_mhz_raw(self.freq_mhz());
1296 }
1297 }
1298
1299 if old_source == CpuClockSource::Pll && self.source != CpuClockSource::Pll
1300 {
1302 rtc_clk_bbpll_disable();
1304 }
1305 }
1306}
1307
1308fn rtc_clk_bbpll_enable() {
1309 PMU::regs().imm_hp_ck_power().modify(|_, w| {
1310 w.tie_high_xpd_bb_i2c().set_bit();
1311 w.tie_high_xpd_bbpll().set_bit();
1312 w.tie_high_xpd_bbpll_i2c().set_bit()
1313 });
1314 PMU::regs()
1315 .imm_hp_ck_power()
1316 .modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
1317}
1318
1319fn rtc_clk_bbpll_disable() {
1320 PMU::regs()
1321 .imm_hp_ck_power()
1322 .modify(|_, w| w.tie_low_global_bbpll_icg().set_bit());
1323
1324 PMU::regs().imm_hp_ck_power().modify(|_, w| {
1325 w.tie_low_xpd_bbpll().set_bit();
1326 w.tie_low_xpd_bbpll_i2c().set_bit()
1327 });
1328}