1use strum::FromRepr;
6
7use crate::{
8 clock::{
9 Clock,
10 XtalClock,
11 clocks_ll::{
12 esp32c6_bbpll_get_freq_mhz,
13 esp32c6_cpu_get_hs_divider,
14 esp32c6_cpu_get_ls_divider,
15 esp32c6_rtc_bbpll_configure_raw,
16 esp32c6_rtc_freq_to_pll_mhz_raw,
17 esp32c6_rtc_update_to_8m,
18 esp32c6_rtc_update_to_xtal_raw,
19 },
20 },
21 peripherals::TIMG0,
22 rtc_cntl::RtcClock,
23 soc::{efuse::Efuse, regi2c},
24 time::Rate,
25};
26
27unsafe fn pmu<'a>() -> &'a esp32c6::pmu::RegisterBlock {
28 unsafe { &*esp32c6::PMU::ptr() }
29}
30
31unsafe fn modem_lpcon<'a>() -> &'a esp32c6::modem_lpcon::RegisterBlock {
32 unsafe { &*esp32c6::MODEM_LPCON::ptr() }
33}
34
35unsafe fn modem_syscon<'a>() -> &'a esp32c6::modem_syscon::RegisterBlock {
36 unsafe { &*esp32c6::MODEM_SYSCON::ptr() }
37}
38
39unsafe fn lp_clkrst<'a>() -> &'a esp32c6::lp_clkrst::RegisterBlock {
40 unsafe { &*esp32c6::LP_CLKRST::ptr() }
41}
42
43unsafe fn pcr<'a>() -> &'a esp32c6::pcr::RegisterBlock {
44 unsafe { &*esp32c6::PCR::ptr() }
45}
46
47unsafe fn lp_aon<'a>() -> &'a esp32c6::lp_aon::RegisterBlock {
48 unsafe { &*esp32c6::LP_AON::ptr() }
49}
50
51fn pmu_power_domain_force_default() {
52 unsafe {
53 pmu().power_pd_top_cntl().modify(|_, w| {
57 w.force_top_reset() .bit(false)
59 .force_top_iso() .bit(false)
61 .force_top_pu() .bit(false)
63 .force_top_no_reset() .bit(false)
65 .force_top_no_iso() .bit(false)
67 .force_top_pd() .bit(false)
69 });
70
71 pmu().power_pd_hpaon_cntl().modify(|_, w| {
73 w.force_hp_aon_reset() .bit(false)
75 .force_hp_aon_iso() .bit(false)
77 .force_hp_aon_pu() .bit(false)
79 .force_hp_aon_no_reset() .bit(false)
81 .force_hp_aon_no_iso() .bit(false)
83 .force_hp_aon_pd() .bit(false)
85 });
86
87 pmu().power_pd_hpcpu_cntl().modify(|_, w| {
89 w.force_hp_cpu_reset() .bit(false)
91 .force_hp_cpu_iso() .bit(false)
93 .force_hp_cpu_pu() .bit(false)
95 .force_hp_cpu_no_reset() .bit(false)
97 .force_hp_cpu_no_iso() .bit(false)
99 .force_hp_cpu_pd() .bit(false)
101 });
102
103 pmu().power_pd_hpwifi_cntl().modify(|_, w| {
105 w.force_hp_wifi_reset() .bit(false)
107 .force_hp_wifi_iso() .bit(false)
109 .force_hp_wifi_pu() .bit(false)
111 .force_hp_wifi_no_reset() .bit(false)
113 .force_hp_wifi_no_iso() .bit(false)
115 .force_hp_wifi_pd() .bit(false)
117 });
118
119 pmu().power_pd_mem_cntl().modify(|_, w| {
122 w.force_hp_mem_no_iso() .bits(0)
124 });
125
126 pmu().power_pd_lpperi_cntl().modify(|_, w| {
127 w.force_lp_peri_reset() .bit(false)
129 .force_lp_peri_iso() .bit(false)
131 .force_lp_peri_pu() .bit(false)
133 .force_lp_peri_no_reset() .bit(false)
135 .force_lp_peri_no_iso() .bit(false)
137 .force_lp_peri_pd() .bit(false)
139 });
140 };
141}
142
143fn modem_clock_domain_power_state_icg_map_init() {
144 const ICG_NOGATING_MODEM: u8 = 1 << 1;
148 const ICG_NOGATING_ACTIVE: u8 = 1 << 2;
149
150 unsafe {
153 modem_syscon().clk_conf_power_st().modify(|_, w| {
154 w.clk_modem_apb_st_map() .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
156 .clk_modem_peri_st_map() .bits(ICG_NOGATING_ACTIVE)
158 .clk_wifi_st_map() .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
160 .clk_bt_st_map() .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
162 .clk_fe_st_map() .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
164 .clk_zb_st_map() .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
166 });
167
168 modem_lpcon().clk_conf_power_st().modify(|_, w| {
169 w.clk_lp_apb_st_map() .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
171 .clk_i2c_mst_st_map() .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
173 .clk_coex_st_map() .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
175 .clk_wifipwr_st_map() .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
177 });
178 }
179}
180
181enum RtcSlowClockSource {
182 RcSlow = 0,
184
185 XTAL32K = 1,
187
188 RC32K = 2,
190
191 OscSlow = 3,
193
194 Invalid,
196}
197
198impl RtcSlowClockSource {
199 fn current() -> Self {
200 let lp_clkrst = unsafe { lp_clkrst() };
202 match lp_clkrst.lp_clk_conf().read().slow_clk_sel().bits() {
203 0 => Self::RcSlow,
204 1 => Self::XTAL32K,
205 2 => Self::RC32K,
206 3 => Self::OscSlow,
207 _ => Self::Invalid,
208 }
209 }
210}
211
212#[allow(unused)]
213enum ModemClockLpclkSource {
214 RcSlow = 0,
215 RcFast,
216 MainXtal,
217 RC32K,
218 XTAL32K,
219 EXT32K,
220}
221
222impl From<RtcSlowClockSource> for ModemClockLpclkSource {
223 fn from(src: RtcSlowClockSource) -> Self {
224 match src {
225 RtcSlowClockSource::RcSlow => Self::RcSlow,
226 RtcSlowClockSource::XTAL32K => Self::XTAL32K,
227 RtcSlowClockSource::RC32K => Self::RC32K,
228 RtcSlowClockSource::OscSlow => Self::EXT32K,
229 _ => Self::RcSlow,
230 }
231 }
232}
233
234fn modem_clock_hal_deselect_all_wifi_lpclk_source() {
235 unsafe {
236 modem_lpcon().wifi_lp_clk_conf().modify(|_, w| {
237 w.clk_wifipwr_lp_sel_osc_slow()
238 .clear_bit()
239 .clk_wifipwr_lp_sel_osc_fast()
240 .clear_bit()
241 .clk_wifipwr_lp_sel_xtal32k()
242 .clear_bit()
243 .clk_wifipwr_lp_sel_xtal()
244 .clear_bit()
245 });
246 }
247}
248
249fn modem_clock_hal_select_wifi_lpclk_source(src: ModemClockLpclkSource) {
250 unsafe {
251 modem_lpcon().wifi_lp_clk_conf().modify(|_, w| match src {
252 ModemClockLpclkSource::RcSlow => w.clk_wifipwr_lp_sel_osc_slow().set_bit(),
253 ModemClockLpclkSource::RcFast => w.clk_wifipwr_lp_sel_osc_fast().set_bit(),
254 ModemClockLpclkSource::MainXtal => w.clk_wifipwr_lp_sel_xtal().set_bit(),
255
256 ModemClockLpclkSource::RC32K
257 | ModemClockLpclkSource::XTAL32K
258 | ModemClockLpclkSource::EXT32K => w.clk_wifipwr_lp_sel_xtal32k().set_bit(),
259 });
260
261 modem_lpcon().modem_32k_clk_conf().modify(|_, w| match src {
262 ModemClockLpclkSource::RcSlow
263 | ModemClockLpclkSource::RcFast
264 | ModemClockLpclkSource::MainXtal => w,
265
266 ModemClockLpclkSource::RC32K => w.clk_modem_32k_sel().bits(1),
267 ModemClockLpclkSource::XTAL32K => w.clk_modem_32k_sel().bits(0),
268 ModemClockLpclkSource::EXT32K => w.clk_modem_32k_sel().bits(2),
269 });
270 }
271}
272
273fn modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider: u16) {
274 unsafe {
275 modem_lpcon()
276 .wifi_lp_clk_conf()
277 .modify(|_, w| w.clk_wifipwr_lp_div_num().bits(divider));
278 }
279}
280
281fn modem_clock_hal_enable_wifipwr_clock(enable: bool) {
282 unsafe {
283 modem_lpcon()
284 .clk_conf()
285 .modify(|_, w| w.clk_wifipwr_en().bit(enable));
286 }
287}
288
289fn modem_clock_select_lp_clock_source_wifi(src: ModemClockLpclkSource, divider: u16) {
291 modem_clock_hal_deselect_all_wifi_lpclk_source();
292 modem_clock_hal_select_wifi_lpclk_source(src);
293 modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider);
294 modem_clock_hal_enable_wifipwr_clock(true);
295}
296
297const fn hp_retention_regdma_config(dir: u8, entry: u8) -> u8 {
298 (((dir) << 2) | (entry & 0x3)) & 0x7
299}
300
301const HP_CALI_DBIAS: u8 = 25;
302const LP_CALI_DBIAS: u8 = 26;
303
304const ICG_MODEM_CODE_SLEEP: u8 = 0;
305const ICG_MODEM_CODE_MODEM: u8 = 1;
306const ICG_MODEM_CODE_ACTIVE: u8 = 2;
307
308const HP_SYSCLK_XTAL: u8 = 0;
309const HP_SYSCLK_PLL: u8 = 1;
310
311bitfield::bitfield! {
312 #[derive(Clone, Copy, Default)]
313 pub struct HpDigPower(u32);
315
316 pub bool, vdd_spi_pd_en, set_vdd_spi_pd_en: 21;
317 pub bool, mem_dslp , set_mem_dslp : 22;
318 pub u8, mem_pd_en , set_mem_pd_en : 26, 23;
319 pub bool, wifi_pd_en , set_wifi_pd_en : 27;
320 pub bool, cpu_pd_en , set_cpu_pd_en : 29;
321 pub bool, aon_pd_en , set_aon_pd_en : 30;
322 pub bool, top_pd_en , set_top_pd_en : 31;
323}
324
325bitfield::bitfield! {
326 #[derive(Clone, Copy, Default)]
327 pub struct HpClkPower(u32);
329
330 pub bool, i2c_iso_en , set_i2c_iso_en : 26;
331 pub bool, i2c_retention, set_i2c_retention: 27;
332 pub bool, xpd_bb_i2c , set_xpd_bb_i2c : 28;
333 pub bool, xpd_bbpll_i2c, set_xpd_bbpll_i2c: 29;
334 pub bool, xpd_bbpll , set_xpd_bbpll : 30;
335}
336
337bitfield::bitfield! {
338 #[derive(Clone, Copy, Default)]
339 pub struct HpXtalPower(u32);
341
342 pub bool, xpd_xtal , set_xpd_xtal : 31;
343}
344
345#[derive(Clone, Copy, Default)]
346pub struct HpSysPower {
348 pub dig_power: HpDigPower,
351 pub clk: HpClkPower,
352 pub xtal: HpXtalPower,
353}
354
355bitfield::bitfield! {
356 #[derive(Clone, Copy, Default)]
357 pub struct HpSysCntlReg(u32);
359
360 pub bool, uart_wakeup_en , set_uart_wakeup_en : 24;
361 pub bool, lp_pad_hold_all, set_lp_pad_hold_all: 25;
362 pub bool, hp_pad_hold_all, set_hp_pad_hold_all: 26;
363 pub bool, dig_pad_slp_sel, set_dig_pad_slp_sel: 27;
364 pub bool, dig_pause_wdt , set_dig_pause_wdt : 28;
365 pub bool, dig_cpu_stall , set_dig_cpu_stall : 29;
366}
367
368bitfield::bitfield! {
369 #[derive(Clone, Copy, Default)]
370 pub struct HpIcgModem(u32);
372
373 pub u8, code, set_code: 31, 30;
374}
375
376bitfield::bitfield! {
377 #[derive(Clone, Copy, Default)]
378 pub struct HpSysclk(u32);
380
381 pub bool, dig_sysclk_nodiv , set_dig_sysclk_nodiv : 26;
382 pub bool, icg_sysclk_en , set_icg_sysclk_en : 27;
383 pub bool, sysclk_slp_sel , set_sysclk_slp_sel : 28;
384 pub bool, icg_slp_sel , set_icg_slp_sel : 29;
385 pub u8, dig_sysclk_sel , set_dig_sysclk_sel : 31, 30;
386}
387
388#[derive(Clone, Copy, Default)]
390struct SystemClockParam {
391 icg_func: u32,
392 icg_apb: u32,
393 icg_modem: HpIcgModem,
394 sysclk: HpSysclk,
395}
396
397bitfield::bitfield! {
398 #[derive(Clone, Copy, Default)]
399 pub struct HpAnalogBias(u32);
401
402 pub bool, xpd_bias , set_xpd_bias : 25;
403 pub u8, dbg_atten , set_dbg_atten : 29, 26;
404 pub bool, pd_cur , set_pd_cur : 30;
405 pub bool, bias_sleep, set_bias_sleep: 31;
406}
407
408bitfield::bitfield! {
409 #[derive(Clone, Copy, Default)]
410 pub struct HpAnalogRegulator0(u32);
412
413 pub u8, lp_dbias_vol , set_lp_dbias_vol : 8, 4;
415 pub u8, hp_dbias_vol , set_hp_dbias_vol : 13, 9;
417 pub bool, dbias_sel , set_dbias_sel : 14;
419 pub bool, dbias_init , set_dbias_init : 15;
421
422 pub bool, slp_mem_xpd , set_slp_mem_xpd : 16;
423 pub bool, slp_logic_xpd , set_slp_logic_xpd : 17;
424 pub bool, xpd , set_xpd : 18;
425 pub u8, slp_mem_dbias , set_slp_mem_dbias : 22, 19;
426 pub u8, slp_logic_dbias, set_slp_logic_dbias: 26, 23;
427 pub u8, dbias , set_dbias : 31, 27;
428}
429
430bitfield::bitfield! {
431 #[derive(Clone, Copy, Default)]
432 pub struct HpAnalogRegulator1(u32);
434
435 pub u32, drv_b , set_drv_b : 31, 8;
436}
437
438#[derive(Clone, Copy, Default)]
439pub struct HpAnalog {
441 pub bias: HpAnalogBias,
442 pub regulator0: HpAnalogRegulator0,
443 pub regulator1: HpAnalogRegulator1,
444}
445
446bitfield::bitfield! {
447 #[derive(Clone, Copy, Default)]
448 pub struct HpActiveBackup(u32);
450
451 pub u8, hp_sleep2active_backup_modem_clk_code, set_hp_sleep2active_backup_modem_clk_code: 5, 4;
452 pub u8, hp_modem2active_backup_modem_clk_code, set_hp_modem2active_backup_modem_clk_code: 7, 6;
453 pub bool, hp_active_retention_mode , set_hp_active_retention_mode : 10;
454 pub bool, hp_sleep2active_retention_en , set_hp_sleep2active_retention_en : 11;
455 pub bool, hp_modem2active_retention_en , set_hp_modem2active_retention_en : 12;
456 pub u8, hp_sleep2active_backup_clk_sel , set_hp_sleep2active_backup_clk_sel : 15, 14;
457 pub u8, hp_modem2active_backup_clk_sel , set_hp_modem2active_backup_clk_sel : 17, 16;
458 pub u8, hp_sleep2active_backup_mode , set_hp_sleep2active_backup_mode : 22, 20;
459 pub u8, hp_modem2active_backup_mode , set_hp_modem2active_backup_mode : 25, 23;
460 pub bool, hp_sleep2active_backup_en , set_hp_sleep2active_backup_en : 29;
461 pub bool, hp_modem2active_backup_en , set_hp_modem2active_backup_en : 30;
462}
463
464bitfield::bitfield! {
465 #[derive(Clone, Copy, Default)]
466 pub struct HpModemBackup(u32);
468
469 pub u8, hp_sleep2modem_backup_modem_clk_code , set_hp_sleep2modem_backup_modem_clk_code : 5, 4;
470 pub bool, hp_modem_retention_mode , set_hp_modem_retention_mode : 10;
471 pub bool, hp_sleep2modem_retention_en , set_hp_sleep2modem_retention_en : 11;
472 pub u8, hp_sleep2modem_backup_clk_sel , set_hp_sleep2modem_backup_clk_sel : 15, 14;
473 pub u8, hp_sleep2modem_backup_mode , set_hp_sleep2modem_backup_mode : 22, 20;
474 pub bool, hp_sleep2modem_backup_en , set_hp_sleep2modem_backup_en : 29;
475}
476
477bitfield::bitfield! {
478 #[derive(Clone, Copy, Default)]
479 pub struct HpSleepBackup(u32);
481
482 pub u8, hp_modem2sleep_backup_modem_clk_code , set_hp_modem2sleep_backup_modem_clk_code : 7, 6;
483 pub u8, hp_active2sleep_backup_modem_clk_code, set_hp_active2sleep_backup_modem_clk_code: 9, 8;
484 pub bool, hp_sleep_retention_mode , set_hp_sleep_retention_mode : 10;
485 pub bool, hp_modem2sleep_retention_en , set_hp_modem2sleep_retention_en : 12;
486 pub bool, hp_active2sleep_retention_en , set_hp_active2sleep_retention_en : 13;
487 pub u8, hp_modem2sleep_backup_clk_sel , set_hp_modem2sleep_backup_clk_sel : 17, 16;
488 pub u8, hp_active2sleep_backup_clk_sel , set_hp_active2sleep_backup_clk_sel : 19, 18;
489 pub u8, hp_modem2sleep_backup_mode , set_hp_modem2sleep_backup_mode : 25, 23;
490 pub u8, hp_active2sleep_backup_mode , set_hp_active2sleep_backup_mode : 28, 26;
491 pub bool, hp_modem2sleep_backup_en , set_hp_modem2sleep_backup_en : 30;
492 pub bool, hp_active2sleep_backup_en , set_hp_active2sleep_backup_en : 31;
493}
494
495bitfield::bitfield! {
496 #[derive(Clone, Copy, Default)]
497 pub struct HpBackupClk(u32);
499
500 pub bool, gdma , set_gdma : 0;
501 pub bool, spi2 , set_spi2 : 1;
502 pub bool, i2s_rx , set_i2s_rx : 2;
503 pub bool, uart0 , set_uart0 : 3;
504 pub bool, uart1 , set_uart1 : 4;
505 pub bool, uhci , set_uhci : 5;
506 pub bool, usb_device , set_usb_device : 6;
507 pub bool, i2s_tx , set_i2s_tx : 7;
508 pub bool, regdma , set_regdma : 8;
509 pub bool, retention , set_retention : 9;
510 pub bool, mem_monitor , set_mem_monitor : 10;
511 pub bool, sdio_slave , set_sdio_slave : 11;
512 pub bool, tsens , set_tsens : 12;
513 pub bool, tg1 , set_tg1 : 13;
514 pub bool, tg0 , set_tg0 : 14;
515 pub bool, hpbus , set_hpbus : 15;
516 pub bool, soc_etm , set_soc_etm : 16;
517 pub bool, hpcore , set_hpcore : 17;
518 pub bool, systimer , set_systimer : 18;
519 pub bool, sec , set_sec : 19;
520 pub bool, saradc , set_saradc : 20;
521 pub bool, rmt , set_rmt : 21;
522 pub bool, pwm , set_pwm : 22;
523 pub bool, pvt_monitor , set_pvt_monitor : 23;
524 pub bool, parl_tx , set_parl_tx : 24;
525 pub bool, parl_rx , set_parl_rx : 25;
526 pub bool, mspi , set_mspi : 26;
527 pub bool, ledc , set_ledc : 27;
528 pub bool, iomux , set_iomux : 28;
529 pub bool, i2c , set_i2c : 29;
530 pub bool, can1 , set_can1 : 30;
531 pub bool, can0 , set_can0 : 31;
532}
533
534macro_rules! hp_system_init {
535 ($state:ident => $s:ident) => {
536 paste::paste! {
537 unsafe {
538 pmu().[<$state _dig_power >]().modify(|_, w| w.bits($s.power.dig_power.0));
540 pmu().[<$state _hp_ck_power >]().modify(|_, w| w.bits($s.power.clk.0));
541 pmu().[<$state _xtal >]().modify(|_, w| w
542 .[<$state _xpd_xtal >]().bit($s.power.xtal.xpd_xtal())
543 );
544
545 pmu().[<$state _icg_hp_func >]().write(|w| w.bits($s.clock.icg_func));
547 pmu().[<$state _icg_hp_apb >]().write(|w| w.bits($s.clock.icg_apb));
548 pmu().[<$state _icg_modem >]().write(|w| w
549 .[<$state _dig_icg_modem_code >]().bits($s.clock.icg_modem.code())
550 );
551 pmu().[<$state _sysclk >]().modify(|_, w| w
552 .[<$state _dig_sys_clk_no_div >]().bit($s.clock.sysclk.dig_sysclk_nodiv())
553 .[<$state _icg_sys_clock_en >]().bit($s.clock.sysclk.icg_sysclk_en())
554 .[<$state _sys_clk_slp_sel >]().bit($s.clock.sysclk.sysclk_slp_sel())
555 .[<$state _icg_slp_sel >]().bit($s.clock.sysclk.icg_slp_sel())
556 .[<$state _dig_sys_clk_sel >]().bits($s.clock.sysclk.dig_sysclk_sel())
557 );
558
559 pmu().[<$state _hp_sys_cntl >]().modify(|_, w| w
562 .[<$state _uart_wakeup_en >]().bit($s.syscntl.uart_wakeup_en())
563 .[<$state _lp_pad_hold_all >]().bit($s.syscntl.lp_pad_hold_all())
564 .[<$state _hp_pad_hold_all >]().bit($s.syscntl.hp_pad_hold_all())
565 .[<$state _dig_pad_slp_sel >]().bit($s.syscntl.dig_pad_slp_sel())
566 .[<$state _dig_pause_wdt >]().bit($s.syscntl.dig_pause_wdt())
567 .[<$state _dig_cpu_stall >]().bit($s.syscntl.dig_cpu_stall())
568 );
569
570 pmu().[<$state _bias >]().modify(|_, w| w
573 .[<$state _xpd_bias >]().bit($s.anlg.bias.xpd_bias())
574 .[<$state _dbg_atten >]().bits($s.anlg.bias.dbg_atten())
575 .[<$state _pd_cur >]().bit($s.anlg.bias.pd_cur())
576 .sleep().bit($s.anlg.bias.bias_sleep())
577 );
578
579 pmu().[<$state _hp_regulator0 >]().modify(|_, w| w
580 .[<$state _hp_regulator_slp_mem_xpd >]().bit($s.anlg.regulator0.slp_mem_xpd())
581 .[<$state _hp_regulator_slp_logic_xpd >]().bit($s.anlg.regulator0.slp_logic_xpd())
582 .[<$state _hp_regulator_xpd >]().bit($s.anlg.regulator0.xpd())
583 .[<$state _hp_regulator_slp_mem_dbias >]().bits($s.anlg.regulator0.slp_mem_dbias())
584 .[<$state _hp_regulator_slp_logic_dbias >]().bits($s.anlg.regulator0.slp_logic_dbias())
585 .[<$state _hp_regulator_dbias >]().bits($s.anlg.regulator0.dbias())
586 );
587
588 pmu().[<$state _hp_regulator1 >]().modify(|_, w| w
589 .[<$state _hp_regulator_drv_b >]().bits($s.anlg.regulator1.drv_b())
590 );
591
592 pmu().[<$state _backup >]().write(|w| w.bits($s.retention));
595 pmu().[<$state _backup_clk >]().write(|w| w.bits($s.backup_clk));
596 }
597 }
598 };
599}
600
601struct HpSystemInit {
602 power: HpSysPower,
603 clock: SystemClockParam,
604 syscntl: HpSysCntlReg,
605 anlg: HpAnalog,
606 retention: u32,
607 backup_clk: u32,
608}
609impl HpSystemInit {
610 fn active() -> Self {
611 let mut power = HpSysPower::default();
614 power.dig_power.set_vdd_spi_pd_en(false);
615 power.dig_power.set_wifi_pd_en(false);
616 power.dig_power.set_cpu_pd_en(false);
617 power.dig_power.set_aon_pd_en(false);
618 power.dig_power.set_top_pd_en(false);
619 power.dig_power.set_mem_pd_en(0);
620 power.dig_power.set_mem_dslp(false);
621
622 power.clk.set_i2c_iso_en(false);
623 power.clk.set_i2c_retention(false);
624 power.clk.set_xpd_bb_i2c(true);
625 power.clk.set_xpd_bbpll_i2c(true);
626 power.clk.set_xpd_bbpll(true);
627
628 power.xtal.set_xpd_xtal(true);
629
630 let mut clock = SystemClockParam {
631 icg_func: 0xffffffff,
632 icg_apb: 0xffffffff,
633 ..SystemClockParam::default()
634 };
635 clock.icg_modem.set_code(ICG_MODEM_CODE_ACTIVE);
636 clock.sysclk.set_dig_sysclk_nodiv(false);
637 clock.sysclk.set_icg_sysclk_en(true);
638 clock.sysclk.set_sysclk_slp_sel(false);
639 clock.sysclk.set_icg_slp_sel(false);
640 clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
641
642 let mut syscntl = HpSysCntlReg::default();
643 syscntl.set_uart_wakeup_en(false);
644 syscntl.set_lp_pad_hold_all(false);
645 syscntl.set_hp_pad_hold_all(false);
646 syscntl.set_dig_pad_slp_sel(false);
647 syscntl.set_dig_pause_wdt(false);
648 syscntl.set_dig_cpu_stall(false);
649
650 let mut anlg = HpAnalog::default();
652 anlg.bias.set_xpd_bias(true);
653 anlg.bias.set_dbg_atten(0x0);
654 anlg.bias.set_pd_cur(false);
655 anlg.bias.set_bias_sleep(false);
656
657 anlg.regulator0.set_lp_dbias_vol(0xD);
659 anlg.regulator0.set_hp_dbias_vol(0x1C);
660 anlg.regulator0.set_dbias_sel(true);
661 anlg.regulator0.set_dbias_init(true);
662
663 anlg.regulator0.set_slp_mem_xpd(false);
664 anlg.regulator0.set_slp_logic_xpd(false);
665 anlg.regulator0.set_xpd(true);
666 anlg.regulator0.set_slp_mem_dbias(0);
667 anlg.regulator0.set_slp_logic_dbias(0);
668 anlg.regulator0.set_dbias(HP_CALI_DBIAS);
669
670 anlg.regulator1.set_drv_b(0);
671
672 let mut retention = HpActiveBackup::default();
673 retention.set_hp_sleep2active_backup_modem_clk_code(2);
674 retention.set_hp_modem2active_backup_modem_clk_code(2);
675 retention.set_hp_active_retention_mode(false);
676 retention.set_hp_sleep2active_retention_en(false);
677 retention.set_hp_modem2active_retention_en(false);
678 retention.set_hp_sleep2active_backup_clk_sel(0);
679 retention.set_hp_modem2active_backup_clk_sel(1);
680 retention.set_hp_sleep2active_backup_mode(hp_retention_regdma_config(0, 0));
681 retention.set_hp_modem2active_backup_mode(hp_retention_regdma_config(0, 2));
682 retention.set_hp_sleep2active_backup_en(false);
683 retention.set_hp_modem2active_backup_en(false);
684
685 let mut backup_clk = HpBackupClk::default();
686 backup_clk.set_regdma(true);
687 backup_clk.set_tg0(true);
688 backup_clk.set_tg1(true);
689 backup_clk.set_hpbus(true);
690 backup_clk.set_mspi(true);
691 backup_clk.set_iomux(true);
692 backup_clk.set_spi2(true);
693 backup_clk.set_uart0(true);
694 backup_clk.set_systimer(true);
695
696 Self {
697 power,
698 clock,
699 syscntl,
700 anlg,
701 retention: retention.0,
702 backup_clk: backup_clk.0,
703 }
704 }
705
706 fn modem() -> Self {
707 let mut power = HpSysPower::default();
708 power.dig_power.set_vdd_spi_pd_en(false);
709 power.dig_power.set_wifi_pd_en(false);
710 power.dig_power.set_cpu_pd_en(true);
711 power.dig_power.set_aon_pd_en(false);
712 power.dig_power.set_top_pd_en(false);
713 power.dig_power.set_mem_pd_en(0);
714 power.dig_power.set_mem_dslp(false);
715
716 power.clk.set_xpd_bb_i2c(true);
717 power.clk.set_xpd_bbpll_i2c(true);
718 power.clk.set_xpd_bbpll(true);
719 power.clk.set_i2c_iso_en(false);
720 power.clk.set_i2c_retention(false);
721
722 power.xtal.set_xpd_xtal(true);
723
724 let mut clock = SystemClockParam {
725 icg_func: 0,
726 icg_apb: 0,
727 ..SystemClockParam::default()
728 };
729 clock.icg_modem.set_code(ICG_MODEM_CODE_MODEM);
730 clock.sysclk.set_dig_sysclk_nodiv(false);
731 clock.sysclk.set_icg_sysclk_en(true);
732 clock.sysclk.set_sysclk_slp_sel(true);
733 clock.sysclk.set_icg_slp_sel(true);
734 clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_PLL);
735
736 let mut syscntl = HpSysCntlReg::default();
737 syscntl.set_uart_wakeup_en(true);
738 syscntl.set_lp_pad_hold_all(false);
739 syscntl.set_hp_pad_hold_all(false);
740 syscntl.set_dig_pad_slp_sel(false);
741 syscntl.set_dig_pause_wdt(true);
742 syscntl.set_dig_cpu_stall(true);
743
744 let mut anlg = HpAnalog::default();
745 anlg.bias.set_xpd_bias(false);
746 anlg.bias.set_dbg_atten(0x0);
747 anlg.bias.set_pd_cur(false);
748 anlg.bias.set_bias_sleep(false);
749
750 anlg.regulator0.set_slp_mem_xpd(false);
751 anlg.regulator0.set_slp_logic_xpd(false);
752 anlg.regulator0.set_xpd(true);
753 anlg.regulator0.set_slp_mem_dbias(0);
754 anlg.regulator0.set_slp_logic_dbias(0);
755 anlg.regulator0.set_dbias(HP_CALI_DBIAS);
756
757 anlg.regulator1.set_drv_b(0);
758
759 let mut retention = HpModemBackup::default();
760 retention.set_hp_sleep2modem_backup_modem_clk_code(1);
761 retention.set_hp_modem_retention_mode(false);
762 retention.set_hp_sleep2modem_retention_en(false);
763 retention.set_hp_sleep2modem_backup_clk_sel(0);
764 retention.set_hp_sleep2modem_backup_mode(hp_retention_regdma_config(0, 1));
765 retention.set_hp_sleep2modem_backup_en(false);
766
767 let mut backup_clk = HpBackupClk::default();
768 backup_clk.set_regdma(true);
769 backup_clk.set_tg0(true);
770 backup_clk.set_tg1(true);
771 backup_clk.set_hpbus(true);
772 backup_clk.set_mspi(true);
773 backup_clk.set_iomux(true);
774 backup_clk.set_spi2(true);
775 backup_clk.set_uart0(true);
776 backup_clk.set_systimer(true);
777
778 Self {
779 power,
780 clock,
781 syscntl,
782 anlg,
783 retention: retention.0,
784 backup_clk: backup_clk.0,
785 }
786 }
787
788 fn sleep() -> Self {
789 let mut power = HpSysPower::default();
790 power.dig_power.set_vdd_spi_pd_en(true);
791 power.dig_power.set_mem_dslp(false);
792 power.dig_power.set_mem_pd_en(0);
793 power.dig_power.set_wifi_pd_en(true);
794 power.dig_power.set_cpu_pd_en(false);
795 power.dig_power.set_aon_pd_en(false);
796 power.dig_power.set_top_pd_en(false);
797
798 power.clk.set_i2c_iso_en(true);
799 power.clk.set_i2c_retention(true);
800 power.clk.set_xpd_bb_i2c(true);
801 power.clk.set_xpd_bbpll_i2c(false);
802 power.clk.set_xpd_bbpll(false);
803
804 power.xtal.set_xpd_xtal(false);
805
806 let mut clock = SystemClockParam {
807 icg_func: 0,
808 icg_apb: 0,
809 ..SystemClockParam::default()
810 };
811 clock.icg_modem.set_code(ICG_MODEM_CODE_SLEEP);
812 clock.sysclk.set_dig_sysclk_nodiv(false);
813 clock.sysclk.set_icg_sysclk_en(false);
814 clock.sysclk.set_sysclk_slp_sel(true);
815 clock.sysclk.set_icg_slp_sel(true);
816 clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
817
818 let mut anlg = HpAnalog::default();
819 anlg.bias.set_xpd_bias(false);
820 anlg.bias.set_dbg_atten(0x0);
821 anlg.bias.set_pd_cur(false);
822 anlg.bias.set_bias_sleep(false);
823
824 anlg.regulator0.set_slp_mem_xpd(false);
825 anlg.regulator0.set_slp_logic_xpd(false);
826 anlg.regulator0.set_xpd(true);
827 anlg.regulator0.set_slp_mem_dbias(0);
828 anlg.regulator0.set_slp_logic_dbias(0);
829 anlg.regulator0.set_dbias(1);
830
831 anlg.regulator1.set_drv_b(0);
832
833 let mut retention = HpSleepBackup::default();
834 retention.set_hp_modem2sleep_backup_modem_clk_code(0);
835 retention.set_hp_active2sleep_backup_modem_clk_code(2);
836 retention.set_hp_sleep_retention_mode(false);
837 retention.set_hp_modem2sleep_retention_en(false);
838 retention.set_hp_active2sleep_retention_en(false);
839 retention.set_hp_modem2sleep_backup_clk_sel(0);
840 retention.set_hp_active2sleep_backup_clk_sel(0);
841 retention.set_hp_modem2sleep_backup_mode(hp_retention_regdma_config(1, 1));
842 retention.set_hp_active2sleep_backup_mode(hp_retention_regdma_config(1, 0));
843 retention.set_hp_modem2sleep_backup_en(false);
844 retention.set_hp_active2sleep_backup_en(false);
845
846 let mut backup_clk = HpBackupClk::default();
847 backup_clk.set_regdma(true);
848 backup_clk.set_tg0(true);
849 backup_clk.set_tg1(true);
850 backup_clk.set_hpbus(true);
851 backup_clk.set_mspi(true);
852 backup_clk.set_iomux(true);
853 backup_clk.set_spi2(true);
854 backup_clk.set_uart0(true);
855 backup_clk.set_systimer(true);
856
857 let mut syscntl = HpSysCntlReg::default();
858 syscntl.set_uart_wakeup_en(true);
859 syscntl.set_lp_pad_hold_all(false);
860 syscntl.set_hp_pad_hold_all(false);
861 syscntl.set_dig_pad_slp_sel(true);
862 syscntl.set_dig_pause_wdt(true);
863 syscntl.set_dig_cpu_stall(true);
864
865 Self {
866 power,
867 clock,
868 syscntl,
869 anlg,
870 retention: retention.0,
871 backup_clk: backup_clk.0,
872 }
873 }
874
875 fn init_default() {
876 let active = Self::active();
877 let modem = Self::modem();
878 let sleep = Self::sleep();
879
880 hp_system_init!(hp_active => active);
881 hp_system_init!(hp_modem => modem);
882 hp_system_init!(hp_sleep => sleep);
883
884 unsafe {
885 pmu()
887 .imm_modem_icg()
888 .write(|w| w.update_dig_icg_modem_en().bit(true));
889 pmu()
890 .imm_sleep_sysclk()
891 .write(|w| w.update_dig_icg_switch().bit(true));
892
893 const PMU_SLEEP_PROTECT_HP_LP_SLEEP: u8 = 2;
894 pmu()
895 .slp_wakeup_cntl3()
896 .modify(|_, w| w.sleep_prt_sel().bits(PMU_SLEEP_PROTECT_HP_LP_SLEEP));
897 }
898 }
899}
900
901bitfield::bitfield! {
902 #[derive(Clone, Copy, Default)]
903 pub struct LpDigPower(u32);
905
906 pub u32, mem_dslp , set_mem_dslp : 30;
907 pub u32, peri_pd_en, set_peri_pd_en: 31;
908
909}
910
911bitfield::bitfield! {
912 #[derive(Clone, Copy, Default)]
913 pub struct LpClkPower(u32);
915
916 pub u32, xpd_xtal32k, set_xpd_xtal32k: 28;
917 pub u32, xpd_rc32k , set_xpd_rc32k : 29;
918 pub u32, xpd_fosc , set_xpd_fosc : 30;
919 pub u32, pd_osc , set_pd_osc : 31;
920}
921
922bitfield::bitfield! {
923 #[derive(Clone, Copy, Default)]
924 pub struct LpXtalPower(u32);
926
927 pub bool, xpd_xtal , set_xpd_xtal : 31;
928}
929
930#[derive(Clone, Copy, Default)]
931pub struct LpSysPower {
933 pub dig_power: LpDigPower,
936 pub clk_power: LpClkPower,
937 pub xtal: LpXtalPower,
938}
939
940bitfield::bitfield! {
941 #[derive(Clone, Copy, Default)]
942 pub struct LpAnalogBias(u32);
944
945 pub bool, xpd_bias , set_xpd_bias : 25;
946 pub u8, dbg_atten , set_dbg_atten : 29, 26;
947 pub bool, pd_cur , set_pd_cur : 30;
948 pub bool, bias_sleep, set_bias_sleep: 31;
949}
950
951bitfield::bitfield! {
952 #[derive(Clone, Copy, Default)]
953 pub struct LpAnalogRegulator0(u32);
955
956 pub bool, slp_xpd , set_slp_xpd : 21;
957 pub bool, xpd , set_xpd : 22;
958 pub u8, slp_dbias, set_slp_dbias: 26, 23;
959 pub u8, dbias , set_dbias : 31, 27;
960}
961
962bitfield::bitfield! {
963 #[derive(Clone, Copy, Default)]
964 pub struct LpAnalogRegulator1(u32);
966
967 pub u8, drv_b , set_drv_b : 31, 28;
968}
969
970#[derive(Clone, Copy, Default)]
971pub struct LpAnalog {
973 pub bias: LpAnalogBias,
974 pub regulator0: LpAnalogRegulator0,
975 pub regulator1: LpAnalogRegulator1,
976}
977
978macro_rules! lp_system_init {
979 ($state:ident => $s:ident) => {
980 paste::paste! {
981 unsafe {
982 pmu().[< $state _dig_power >]().modify(|_, w| w.bits($s.dig_power.0));
984 pmu().[< $state _ck_power >]().modify(|_, w| w.bits($s.clk_power.0));
985
986 pmu().[< $state _regulator0 >]().modify(|_, w| w
988 .[< $state _regulator_slp_xpd >]().bit($s.analog_regulator0.slp_xpd())
989 .[< $state _regulator_xpd >]().bit($s.analog_regulator0.xpd())
990 .[< $state _regulator_slp_dbias >]().bits($s.analog_regulator0.slp_dbias())
991 .[< $state _regulator_dbias >]().bits($s.analog_regulator0.dbias())
992 );
993
994 pmu().[< $state _regulator1 >]().modify(|_, w| w
995 .[< $state _regulator_drv_b >]().bits($s.analog_regulator1.drv_b())
996 );
997 }
998 }
999 };
1000}
1001
1002struct LpSystemInit {
1003 dig_power: LpDigPower,
1004 clk_power: LpClkPower,
1005 xtal: LpXtalPower,
1006 bias: LpAnalogBias,
1007 analog_regulator0: LpAnalogRegulator0,
1008 analog_regulator1: LpAnalogRegulator1,
1009}
1010impl LpSystemInit {
1011 fn active() -> Self {
1012 let mut dig_power = LpDigPower::default();
1013 dig_power.set_peri_pd_en(false);
1014 dig_power.set_mem_dslp(false);
1015
1016 let mut clk_power = LpClkPower::default();
1017 clk_power.set_xpd_xtal32k(true);
1018 clk_power.set_xpd_rc32k(true);
1019 clk_power.set_xpd_fosc(true);
1020
1021 let mut analog_regulator0 = LpAnalogRegulator0::default();
1022 analog_regulator0.set_slp_xpd(false);
1023 analog_regulator0.set_xpd(true);
1024 analog_regulator0.set_slp_dbias(0);
1025 analog_regulator0.set_dbias(26);
1026
1027 let mut analog_regulator1 = LpAnalogRegulator1::default();
1028 analog_regulator1.set_drv_b(0);
1029
1030 Self {
1031 dig_power,
1032 clk_power,
1033 xtal: LpXtalPower::default(),
1034 bias: LpAnalogBias::default(),
1035 analog_regulator0,
1036 analog_regulator1,
1037 }
1038 }
1039
1040 fn sleep() -> Self {
1041 let mut dig_power = LpDigPower::default();
1042 dig_power.set_mem_dslp(true);
1043 dig_power.set_peri_pd_en(false);
1044
1045 let mut clk_power = LpClkPower::default();
1046 clk_power.set_xpd_xtal32k(false);
1047 clk_power.set_xpd_rc32k(false);
1048 clk_power.set_xpd_fosc(false);
1049 clk_power.set_pd_osc(false);
1050
1051 let mut xtal = LpXtalPower::default();
1052 xtal.set_xpd_xtal(false);
1053
1054 let mut analog_bias = LpAnalogBias::default();
1055 analog_bias.set_xpd_bias(false);
1056 analog_bias.set_dbg_atten(0);
1057 analog_bias.set_pd_cur(true);
1058 analog_bias.set_bias_sleep(true);
1059
1060 let mut analog_regulator0 = LpAnalogRegulator0::default();
1061 analog_regulator0.set_slp_xpd(false);
1062 analog_regulator0.set_xpd(true);
1063 analog_regulator0.set_slp_dbias(0);
1064 analog_regulator0.set_dbias(12);
1065
1066 let mut analog_regulator1 = LpAnalogRegulator1::default();
1067 analog_regulator1.set_drv_b(0);
1068
1069 Self {
1070 dig_power,
1071 clk_power,
1072 xtal,
1073 bias: analog_bias,
1074 analog_regulator0,
1075 analog_regulator1,
1076 }
1077 }
1078
1079 fn init_default() {
1080 let active = Self::active();
1081 let sleep = Self::sleep();
1082
1083 lp_system_init!(hp_sleep_lp => active);
1084 lp_system_init!(lp_sleep_lp => sleep);
1085
1086 unsafe {
1087 pmu()
1088 .lp_sleep_xtal()
1089 .modify(|_, w| w.lp_sleep_xpd_xtal().bit(sleep.xtal.xpd_xtal()));
1090
1091 pmu().lp_sleep_bias().modify(|_, w| {
1092 w.lp_sleep_xpd_bias() .bit(sleep.bias.xpd_bias())
1094 .lp_sleep_dbg_atten() .bits(sleep.bias.dbg_atten())
1096 .lp_sleep_pd_cur() .bit(sleep.bias.pd_cur())
1098 .sleep() .bit(sleep.bias.bias_sleep())
1100 });
1101 }
1102 }
1103}
1104
1105pub(crate) fn init() {
1106 let pmu = unsafe { pmu() };
1108
1109 pmu.rf_pwc()
1110 .modify(|_, w| w.perif_i2c_rstb().set_bit().xpd_perif_i2c().set_bit());
1111
1112 regi2c::I2C_DIG_REG_ENIF_RTC_DREG.write_field(1);
1113 regi2c::I2C_DIG_REG_ENIF_DIG_DREG.write_field(1);
1114 regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
1115 regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
1116
1117 HpSystemInit::init_default();
1118 LpSystemInit::init_default();
1119
1120 pmu_power_domain_force_default();
1121
1122 modem_clock_domain_power_state_icg_map_init();
1124
1125 let modem_lpclk_src = ModemClockLpclkSource::from(RtcSlowClockSource::current());
1134
1135 modem_clock_select_lp_clock_source_wifi(modem_lpclk_src, 0);
1136}
1137
1138pub(crate) fn configure_clock() {
1139 assert!(matches!(RtcClock::xtal_freq(), XtalClock::_40M));
1140
1141 RtcClock::set_fast_freq(RtcFastClock::RtcFastClockRcFast);
1142
1143 let cal_val = loop {
1144 RtcClock::set_slow_freq(RtcSlowClock::RtcSlowClockRcSlow);
1145
1146 let res = RtcClock::calibrate(RtcCalSel::RtcCalRtcMux, 1024);
1147 if res != 0 {
1148 break res;
1149 }
1150 };
1151
1152 unsafe {
1153 lp_aon().store1().modify(|_, w| w.bits(cal_val));
1154 }
1155
1156 modem_clk_domain_active_state_icg_map_preinit();
1157}
1158
1159fn modem_clk_domain_active_state_icg_map_preinit() {
1160 unsafe {
1161 pmu()
1163 .hp_active_icg_modem()
1164 .modify(|_, w| w.hp_active_dig_icg_modem_code().bits(ICG_MODEM_CODE_ACTIVE));
1165
1166 modem_syscon()
1169 .clk_conf_power_st()
1170 .modify(|_, w| w.clk_modem_apb_st_map().bits(1 << ICG_MODEM_CODE_ACTIVE));
1171 modem_lpcon().clk_conf_power_st().modify(|_, w| {
1172 w.clk_i2c_mst_st_map()
1173 .bits(1 << ICG_MODEM_CODE_ACTIVE)
1174 .clk_lp_apb_st_map()
1175 .bits(1 << ICG_MODEM_CODE_ACTIVE)
1176 });
1177
1178 pmu()
1180 .imm_modem_icg()
1181 .write(|w| w.update_dig_icg_modem_en().set_bit());
1182 pmu()
1183 .imm_sleep_sysclk()
1184 .write(|w| w.update_dig_icg_switch().set_bit());
1185
1186 lp_clkrst()
1189 .fosc_cntl()
1190 .modify(|_, w| w.fosc_dfreq().bits(100));
1191
1192 regi2c::I2C_DIG_REG_SCK_DCAP.write_reg(128);
1193
1194 lp_clkrst()
1195 .rc32k_cntl()
1196 .modify(|_, w| w.rc32k_dfreq().bits(700));
1197
1198 regi2c::I2C_DIG_REG_ENIF_RTC_DREG.write_field(1);
1199 regi2c::I2C_DIG_REG_ENIF_DIG_DREG.write_field(1);
1200
1201 pmu()
1202 .hp_active_hp_regulator0()
1203 .modify(|_, w| w.hp_active_hp_regulator_dbias().bits(HP_CALI_DBIAS));
1204 pmu()
1205 .hp_sleep_lp_regulator0()
1206 .modify(|_, w| w.hp_sleep_lp_regulator_dbias().bits(LP_CALI_DBIAS));
1207
1208 pcr()
1210 .ctrl_tick_conf()
1211 .modify(|_, w| w.fosc_tick_num().bits(255));
1212 }
1213}
1214
1215#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
1225pub enum SocResetReason {
1226 ChipPowerOn = 0x01,
1232 CoreSw = 0x03,
1234 CoreDeepSleep = 0x05,
1236 CoreSDIO = 0x06,
1238 CoreMwdt0 = 0x07,
1240 CoreMwdt1 = 0x08,
1242 CoreRtcWdt = 0x09,
1244 Cpu0Mwdt0 = 0x0B,
1246 Cpu0Sw = 0x0C,
1248 Cpu0RtcWdt = 0x0D,
1250 SysBrownOut = 0x0F,
1252 SysRtcWdt = 0x10,
1254 Cpu0Mwdt1 = 0x11,
1256 SysSuperWdt = 0x12,
1258 CoreEfuseCrc = 0x14,
1260 CoreUsbUart = 0x15,
1262 CoreUsbJtag = 0x16,
1264 Cpu0JtagCpu = 0x18,
1266}
1267
1268#[allow(unused)]
1269#[derive(Debug, Clone, Copy)]
1270pub(crate) enum RtcFastClock {
1272 RtcFastClockRcFast = 0,
1274 RtcFastClockXtalD2 = 1,
1276}
1277
1278impl Clock for RtcFastClock {
1279 fn frequency(&self) -> Rate {
1280 match self {
1281 RtcFastClock::RtcFastClockXtalD2 => {
1282 Rate::from_hz(40_000_000 / 2)
1284 }
1285 RtcFastClock::RtcFastClockRcFast => Rate::from_hz(17_500_000),
1286 }
1287 }
1288}
1289
1290#[allow(clippy::enum_variant_names)]
1291#[derive(Debug, Clone, Copy, PartialEq)]
1292pub enum RtcSlowClock {
1294 RtcSlowClockRcSlow = 0,
1296 RtcSlowClock32kXtal = 1,
1298 RtcSlowClock32kRc = 2,
1300 RtcSlowOscSlow = 3,
1302}
1303
1304impl Clock for RtcSlowClock {
1305 fn frequency(&self) -> Rate {
1306 match self {
1307 RtcSlowClock::RtcSlowClockRcSlow => Rate::from_hz(136_000),
1308 RtcSlowClock::RtcSlowClock32kXtal => Rate::from_hz(32_768),
1309 RtcSlowClock::RtcSlowClock32kRc => Rate::from_hz(32_768),
1310 RtcSlowClock::RtcSlowOscSlow => Rate::from_hz(32_768),
1311 }
1312 }
1313}
1314
1315#[derive(Debug, Clone, Copy, PartialEq)]
1316pub(crate) enum RtcCalSel {
1318 RtcCalRtcMux = -1,
1320 RtcCalRcSlow = 0,
1322 RtcCal32kXtal = 1,
1324 RtcCal32kRc = 2,
1326 RtcCal32kOscSlow = 3,
1329 RtcCalRcFast,
1331}
1332
1333#[derive(Clone)]
1334pub(crate) enum RtcCaliClkSel {
1335 CaliClkRcSlow = 0,
1336 CaliClkRcFast = 1,
1337 CaliClk32k = 2,
1338}
1339
1340impl RtcClock {
1342 pub(crate) fn xtal_freq_mhz() -> u32 {
1344 Self::read_xtal_freq_mhz().unwrap_or(40)
1345 }
1346
1347 pub fn xtal_freq() -> XtalClock {
1351 match Self::xtal_freq_mhz() {
1352 40 => XtalClock::_40M,
1353 other => XtalClock::Other(other),
1354 }
1355 }
1356
1357 pub fn slow_freq() -> RtcSlowClock {
1359 let lp_clrst = unsafe { lp_clkrst() };
1360
1361 let slow_freq = lp_clrst.lp_clk_conf().read().slow_clk_sel().bits();
1362 match slow_freq {
1363 0 => RtcSlowClock::RtcSlowClockRcSlow,
1364 1 => RtcSlowClock::RtcSlowClock32kXtal,
1365 2 => RtcSlowClock::RtcSlowClock32kRc,
1366 3 => RtcSlowClock::RtcSlowOscSlow,
1367 _ => unreachable!(),
1368 }
1369 }
1370
1371 fn set_slow_freq(slow_freq: RtcSlowClock) {
1372 unsafe {
1373 lp_clkrst()
1374 .lp_clk_conf()
1375 .modify(|_, w| w.slow_clk_sel().bits(slow_freq as u8));
1376
1377 lp_clkrst().clk_to_hp().modify(|_, w| {
1378 w.icg_hp_xtal32k()
1379 .bit(matches!(slow_freq, RtcSlowClock::RtcSlowClock32kXtal))
1380 .icg_hp_xtal32k()
1381 .bit(matches!(slow_freq, RtcSlowClock::RtcSlowClock32kXtal))
1382 });
1383 }
1384 }
1385
1386 fn set_fast_freq(fast_freq: RtcFastClock) {
1390 unsafe {
1391 lp_clkrst().lp_clk_conf().modify(|_, w| {
1392 w.fast_clk_sel().bit(match fast_freq {
1393 RtcFastClock::RtcFastClockRcFast => false,
1394 RtcFastClock::RtcFastClockXtalD2 => true,
1395 })
1396 });
1397 }
1398
1399 crate::rom::ets_delay_us(3);
1400 }
1401
1402 pub(crate) fn calibrate_internal(mut cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 {
1406 const SOC_CLK_RC_FAST_FREQ_APPROX: u32 = 17_500_000;
1407 const SOC_CLK_RC_SLOW_FREQ_APPROX: u32 = 136_000;
1408 const SOC_CLK_XTAL32K_FREQ_APPROX: u32 = 32768;
1409
1410 if cal_clk == RtcCalSel::RtcCalRtcMux {
1411 cal_clk = match cal_clk {
1412 RtcCalSel::RtcCalRtcMux => match RtcClock::slow_freq() {
1413 RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal,
1414 RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc,
1415 _ => cal_clk,
1416 },
1417 RtcCalSel::RtcCal32kOscSlow => RtcCalSel::RtcCalRtcMux,
1418 _ => cal_clk,
1419 };
1420 }
1421
1422 let lp_clkrst = unsafe { lp_clkrst() };
1423 let pcr = unsafe { pcr() };
1424 let pmu = unsafe { pmu() };
1425
1426 let clk_src = RtcClock::slow_freq();
1427
1428 if cal_clk == RtcCalSel::RtcCalRtcMux {
1429 cal_clk = match clk_src {
1430 RtcSlowClock::RtcSlowClockRcSlow => RtcCalSel::RtcCalRcSlow,
1431 RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal,
1432 RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc,
1433 RtcSlowClock::RtcSlowOscSlow => RtcCalSel::RtcCal32kOscSlow,
1434 };
1435 }
1436
1437 let cali_clk_sel;
1438 if cal_clk == RtcCalSel::RtcCalRtcMux {
1439 cal_clk = match clk_src {
1440 RtcSlowClock::RtcSlowClockRcSlow => RtcCalSel::RtcCalRcSlow,
1441 RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal,
1442 RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc,
1443 RtcSlowClock::RtcSlowOscSlow => RtcCalSel::RtcCalRcSlow,
1444 }
1445 }
1446
1447 if cal_clk == RtcCalSel::RtcCalRcFast {
1448 cali_clk_sel = RtcCaliClkSel::CaliClkRcFast;
1449 } else if cal_clk == RtcCalSel::RtcCalRcSlow {
1450 cali_clk_sel = RtcCaliClkSel::CaliClkRcSlow;
1451 } else {
1452 cali_clk_sel = RtcCaliClkSel::CaliClk32k;
1453 match cal_clk {
1454 RtcCalSel::RtcCalRtcMux | RtcCalSel::RtcCalRcSlow | RtcCalSel::RtcCalRcFast => {}
1455 RtcCalSel::RtcCal32kRc => {
1456 pcr.ctrl_32k_conf()
1457 .modify(|_, w| unsafe { w.clk_32k_sel().bits(0) });
1458 }
1459 RtcCalSel::RtcCal32kXtal => {
1460 pcr.ctrl_32k_conf()
1461 .modify(|_, w| unsafe { w.clk_32k_sel().bits(1) });
1462 }
1463 RtcCalSel::RtcCal32kOscSlow => {
1464 pcr.ctrl_32k_conf()
1465 .modify(|_, w| unsafe { w.clk_32k_sel().bits(2) });
1466 }
1467 }
1468 }
1469
1470 let dig_32k_xtal_enabled = lp_clkrst.clk_to_hp().read().icg_hp_xtal32k().bit_is_set();
1476
1477 if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled {
1478 lp_clkrst
1479 .clk_to_hp()
1480 .modify(|_, w| w.icg_hp_xtal32k().set_bit());
1481 }
1482
1483 lp_clkrst
1486 .clk_to_hp()
1487 .modify(|_, w| w.icg_hp_xtal32k().set_bit());
1488 pmu.hp_sleep_lp_ck_power().modify(|_, w| {
1489 w.hp_sleep_xpd_xtal32k().set_bit();
1490 w.hp_sleep_xpd_rc32k().set_bit()
1491 });
1492
1493 let rc_fast_enabled = pmu
1494 .hp_sleep_lp_ck_power()
1495 .read()
1496 .hp_sleep_xpd_fosc_clk()
1497 .bit_is_set();
1498 let dig_rc_fast_enabled = lp_clkrst.clk_to_hp().read().icg_hp_fosc().bit_is_set();
1499
1500 if cal_clk == RtcCalSel::RtcCalRcFast {
1501 if !rc_fast_enabled {
1502 pmu.hp_sleep_lp_ck_power()
1503 .modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit());
1504 crate::rom::ets_delay_us(50);
1505 }
1506
1507 if !dig_rc_fast_enabled {
1508 lp_clkrst
1509 .clk_to_hp()
1510 .modify(|_, w| w.icg_hp_fosc().set_bit());
1511 crate::rom::ets_delay_us(5);
1512 }
1513 }
1514
1515 let rc32k_enabled = pmu
1516 .hp_sleep_lp_ck_power()
1517 .read()
1518 .hp_sleep_xpd_rc32k()
1519 .bit_is_set();
1520 let dig_rc32k_enabled = lp_clkrst.clk_to_hp().read().icg_hp_osc32k().bit_is_set();
1521
1522 if cal_clk == RtcCalSel::RtcCal32kRc {
1523 if !rc32k_enabled {
1524 pmu.hp_sleep_lp_ck_power()
1525 .modify(|_, w| w.hp_sleep_xpd_rc32k().set_bit());
1526 crate::rom::ets_delay_us(300);
1527 }
1528
1529 if !dig_rc32k_enabled {
1530 lp_clkrst
1531 .clk_to_hp()
1532 .modify(|_, w| w.icg_hp_osc32k().set_bit());
1533 }
1534 }
1535
1536 let timg0 = TIMG0::regs();
1539
1540 if timg0
1541 .rtccalicfg()
1542 .read()
1543 .rtc_cali_start_cycling()
1544 .bit_is_set()
1545 {
1546 timg0
1547 .rtccalicfg2()
1548 .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(1) });
1549
1550 while !timg0.rtccalicfg().read().rtc_cali_rdy().bit_is_set()
1554 && !timg0.rtccalicfg2().read().rtc_cali_timeout().bit_is_set()
1555 {}
1556 }
1557
1558 timg0
1560 .rtccalicfg()
1561 .modify(|_, w| unsafe { w.rtc_cali_clk_sel().bits(cali_clk_sel.clone() as u8) });
1562 timg0
1563 .rtccalicfg()
1564 .modify(|_, w| w.rtc_cali_start_cycling().clear_bit());
1565 timg0
1566 .rtccalicfg()
1567 .modify(|_, w| unsafe { w.rtc_cali_max().bits(slowclk_cycles as u16) });
1568
1569 let expected_freq = match cali_clk_sel {
1570 RtcCaliClkSel::CaliClk32k => {
1571 timg0.rtccalicfg2().modify(|_, w| unsafe {
1572 w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)
1573 });
1574 SOC_CLK_XTAL32K_FREQ_APPROX
1575 }
1576 RtcCaliClkSel::CaliClkRcFast => {
1577 timg0
1578 .rtccalicfg2()
1579 .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(0x01FFFFFF) });
1580 SOC_CLK_RC_FAST_FREQ_APPROX
1581 }
1582 _ => {
1583 timg0.rtccalicfg2().modify(|_, w| unsafe {
1584 w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)
1585 });
1586 SOC_CLK_RC_SLOW_FREQ_APPROX
1587 }
1588 };
1589
1590 let us_time_estimate = (Rate::from_mhz(slowclk_cycles) / expected_freq).as_hz();
1591
1592 timg0
1594 .rtccalicfg()
1595 .modify(|_, w| w.rtc_cali_start().clear_bit());
1596 timg0
1597 .rtccalicfg()
1598 .modify(|_, w| w.rtc_cali_start().set_bit());
1599
1600 crate::rom::ets_delay_us(us_time_estimate);
1602
1603 let cal_val = loop {
1604 if timg0.rtccalicfg().read().rtc_cali_rdy().bit_is_set() {
1605 if Efuse::chip_revision() > 0 {
1611 if cal_clk == RtcCalSel::RtcCalRcFast {
1612 break timg0.rtccalicfg1().read().rtc_cali_value().bits() >> 5;
1613 }
1614 break timg0.rtccalicfg1().read().rtc_cali_value().bits();
1615 } else {
1616 break timg0.rtccalicfg1().read().rtc_cali_value().bits();
1617 }
1618 }
1619
1620 if timg0.rtccalicfg2().read().rtc_cali_timeout().bit_is_set() {
1621 break 0;
1623 }
1624 };
1625
1626 timg0
1627 .rtccalicfg()
1628 .modify(|_, w| w.rtc_cali_start().clear_bit());
1629
1630 if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled {
1631 lp_clkrst
1632 .clk_to_hp()
1633 .modify(|_, w| w.icg_hp_xtal32k().clear_bit());
1634 }
1635
1636 if cal_clk == RtcCalSel::RtcCalRcFast {
1637 if rc_fast_enabled {
1638 pmu.hp_sleep_lp_ck_power()
1639 .modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit());
1640 crate::rom::ets_delay_us(50);
1641 }
1642
1643 if dig_rc_fast_enabled {
1644 lp_clkrst
1645 .clk_to_hp()
1646 .modify(|_, w| w.icg_hp_fosc().set_bit());
1647 crate::rom::ets_delay_us(5);
1648 }
1649 }
1650
1651 if cal_clk == RtcCalSel::RtcCal32kRc {
1652 if rc32k_enabled {
1653 pmu.hp_sleep_lp_ck_power()
1654 .modify(|_, w| w.hp_sleep_xpd_rc32k().set_bit());
1655 crate::rom::ets_delay_us(300);
1656 }
1657 if dig_rc32k_enabled {
1658 lp_clkrst
1659 .clk_to_hp()
1660 .modify(|_, w| w.icg_hp_osc32k().set_bit());
1661 }
1662 }
1663
1664 cal_val
1665 }
1666
1667 fn calibrate(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 {
1675 let xtal_freq = RtcClock::xtal_freq();
1676
1677 let mut slowclk_cycles = slowclk_cycles;
1678
1679 if Efuse::chip_revision() > 0 && cal_clk == RtcCalSel::RtcCalRcFast {
1683 slowclk_cycles >>= 5;
1684 }
1685
1686 let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64;
1687 let divider = xtal_freq.mhz() as u64 * slowclk_cycles as u64;
1688 let period_64 = ((xtal_cycles << RtcClock::CAL_FRACT) + divider / 2u64 - 1u64) / divider;
1689
1690 (period_64 & u32::MAX as u64) as u32
1691 }
1692
1693 pub(crate) fn cycles_to_1ms() -> u16 {
1695 let period_13q19 = RtcClock::calibrate(
1696 match RtcClock::slow_freq() {
1697 RtcSlowClock::RtcSlowClockRcSlow => RtcCalSel::RtcCalRtcMux,
1698 RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal,
1699 RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc,
1700 RtcSlowClock::RtcSlowOscSlow => RtcCalSel::RtcCal32kOscSlow,
1701 },
1703 1024,
1704 );
1705
1706 let period = (100_000_000 * period_13q19 as u64) / (1 << RtcClock::CAL_FRACT);
1708
1709 (100_000_000 * 1000 / period) as u16
1710 }
1711
1712 pub(crate) fn estimate_xtal_frequency() -> u32 {
1713 let timg0 = TIMG0::regs();
1714 while timg0.rtccalicfg().read().rtc_cali_rdy().bit_is_clear() {}
1715
1716 timg0.rtccalicfg().modify(|_, w| unsafe {
1717 w.rtc_cali_clk_sel()
1718 .bits(0) .rtc_cali_max()
1720 .bits(100)
1721 .rtc_cali_start_cycling()
1722 .clear_bit()
1723 .rtc_cali_start()
1724 .set_bit()
1725 });
1726 timg0
1727 .rtccalicfg()
1728 .modify(|_, w| w.rtc_cali_start().set_bit());
1729
1730 while timg0.rtccalicfg().read().rtc_cali_rdy().bit_is_clear() {}
1731
1732 (timg0.rtccalicfg1().read().rtc_cali_value().bits()
1733 * (RtcSlowClock::RtcSlowClockRcSlow.frequency().as_hz() / 100))
1734 / 1_000_000
1735 }
1736}
1737
1738pub(crate) fn rtc_clk_cpu_freq_set_xtal() {
1739 let freq = RtcClock::xtal_freq_mhz();
1741
1742 esp32c6_rtc_update_to_xtal_raw(freq, 1);
1743
1744 rtc_clk_bbpll_disable();
1747 }
1749
1750#[derive(Clone, Copy, PartialEq, Debug)]
1751#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1752pub(crate) struct UnsupportedClockSource;
1753
1754#[derive(Clone, Copy, PartialEq, Debug)]
1755#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1756pub(crate) enum CpuClockSource {
1757 Xtal,
1758 Pll,
1759 RcFast,
1760}
1761
1762impl CpuClockSource {
1763 pub(crate) fn current() -> Result<Self, UnsupportedClockSource> {
1764 let source = match unsafe { pcr().sysclk_conf().read().soc_clk_sel().bits() } {
1765 0 => CpuClockSource::Xtal,
1766 1 => CpuClockSource::Pll,
1767 2 => CpuClockSource::RcFast,
1768 _ => return Err(UnsupportedClockSource),
1769 };
1770
1771 Ok(source)
1772 }
1773
1774 pub(crate) fn select(self) {
1775 unsafe {
1776 pcr().sysclk_conf().modify(|_, w| {
1777 w.soc_clk_sel().bits(match self {
1778 CpuClockSource::Xtal => 0,
1779 CpuClockSource::Pll => 1,
1780 CpuClockSource::RcFast => 2,
1781 })
1782 });
1783 }
1784 }
1785}
1786
1787#[derive(Clone, Copy)]
1788pub(crate) struct SavedClockConfig {
1789 pub source: CpuClockSource,
1791
1792 pub source_freq_mhz: u32,
1794
1795 pub div: u8,
1797}
1798
1799impl SavedClockConfig {
1800 pub(crate) fn save() -> Self {
1801 let source = unwrap!(CpuClockSource::current());
1802
1803 let div;
1804 let source_freq_mhz;
1805 match source {
1806 CpuClockSource::Xtal => {
1807 div = esp32c6_cpu_get_ls_divider();
1808 source_freq_mhz = RtcClock::xtal_freq_mhz();
1809 }
1810 CpuClockSource::Pll => {
1811 div = esp32c6_cpu_get_hs_divider();
1812 source_freq_mhz = esp32c6_bbpll_get_freq_mhz();
1813 }
1814 CpuClockSource::RcFast => {
1815 div = esp32c6_cpu_get_ls_divider();
1816 source_freq_mhz = 20;
1817 }
1818 }
1819
1820 SavedClockConfig {
1821 source,
1822 source_freq_mhz,
1823 div,
1824 }
1825 }
1826
1827 fn freq_mhz(&self) -> u32 {
1828 self.source_freq_mhz / self.div as u32
1829 }
1830
1831 pub(crate) fn restore(self) {
1833 let old_source = unwrap!(CpuClockSource::current());
1834
1835 match self.source {
1836 CpuClockSource::Xtal => esp32c6_rtc_update_to_xtal_raw(self.freq_mhz(), self.div),
1837 CpuClockSource::RcFast => esp32c6_rtc_update_to_8m(),
1838 CpuClockSource::Pll => {
1839 if old_source != CpuClockSource::Pll {
1840 rtc_clk_bbpll_enable();
1841 esp32c6_rtc_bbpll_configure_raw(
1842 RtcClock::xtal_freq_mhz(),
1843 self.source_freq_mhz,
1844 );
1845 }
1846 esp32c6_rtc_freq_to_pll_mhz_raw(self.freq_mhz());
1847 }
1848 }
1849
1850 if old_source == CpuClockSource::Pll && self.source != CpuClockSource::Pll
1851 {
1853 rtc_clk_bbpll_disable();
1855 }
1856 }
1857}
1858
1859fn rtc_clk_bbpll_enable() {
1860 unsafe {
1861 pmu().imm_hp_ck_power().modify(|_, w| {
1862 w.tie_high_xpd_bb_i2c()
1863 .set_bit()
1864 .tie_high_xpd_bbpll()
1865 .set_bit()
1866 .tie_high_xpd_bbpll_i2c()
1867 .set_bit()
1868 });
1869 pmu()
1870 .imm_hp_ck_power()
1871 .modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
1872 }
1873}
1874
1875fn rtc_clk_bbpll_disable() {
1876 unsafe {
1877 pmu()
1878 .imm_hp_ck_power()
1879 .modify(|_, w| w.tie_low_global_bbpll_icg().set_bit());
1880
1881 pmu().imm_hp_ck_power().modify(|_, w| {
1882 w.tie_low_xpd_bbpll()
1883 .set_bit()
1884 .tie_low_xpd_bbpll_i2c()
1885 .set_bit()
1886 });
1887 }
1888}