esp_hal/rtc_cntl/rtc/
esp32c6.rs

1// Note: the PMU setup is based on esp-idf v5.1.2. Related code should be based
2// on the same version until documentation is released and the code can be
3// reasoned about.
4
5use 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        // for bypass reserved power domain
54
55        // PMU_HP_PD_TOP
56        pmu().power_pd_top_cntl().modify(|_, w| {
57            w.force_top_reset() // pmu_ll_hp_set_power_force_reset
58                .bit(false)
59                .force_top_iso() // pmu_ll_hp_set_power_force_isolate
60                .bit(false)
61                .force_top_pu() // pmu_ll_hp_set_power_force_power_up
62                .bit(false)
63                .force_top_no_reset() // pmu_ll_hp_set_power_force_no_reset
64                .bit(false)
65                .force_top_no_iso() // pmu_ll_hp_set_power_force_no_isolate
66                .bit(false)
67                .force_top_pd() // pmu_ll_hp_set_power_force_power_down
68                .bit(false)
69        });
70
71        // PMU_HP_PD_HP_AON
72        pmu().power_pd_hpaon_cntl().modify(|_, w| {
73            w.force_hp_aon_reset() // pmu_ll_hp_set_power_force_reset
74                .bit(false)
75                .force_hp_aon_iso() // pmu_ll_hp_set_power_force_isolate
76                .bit(false)
77                .force_hp_aon_pu() // pmu_ll_hp_set_power_force_power_up
78                .bit(false)
79                .force_hp_aon_no_reset() // pmu_ll_hp_set_power_force_no_reset
80                .bit(false)
81                .force_hp_aon_no_iso() // pmu_ll_hp_set_power_force_no_isolate
82                .bit(false)
83                .force_hp_aon_pd() // pmu_ll_hp_set_power_force_power_down
84                .bit(false)
85        });
86
87        // PMU_HP_PD_CPU
88        pmu().power_pd_hpcpu_cntl().modify(|_, w| {
89            w.force_hp_cpu_reset() // pmu_ll_hp_set_power_force_reset
90                .bit(false)
91                .force_hp_cpu_iso() // pmu_ll_hp_set_power_force_isolate
92                .bit(false)
93                .force_hp_cpu_pu() // pmu_ll_hp_set_power_force_power_up
94                .bit(false)
95                .force_hp_cpu_no_reset() // pmu_ll_hp_set_power_force_no_reset
96                .bit(false)
97                .force_hp_cpu_no_iso() // pmu_ll_hp_set_power_force_no_isolate
98                .bit(false)
99                .force_hp_cpu_pd() // pmu_ll_hp_set_power_force_power_down
100                .bit(false)
101        });
102
103        // PMU_HP_PD_WIFI
104        pmu().power_pd_hpwifi_cntl().modify(|_, w| {
105            w.force_hp_wifi_reset() // pmu_ll_hp_set_power_force_reset
106                .bit(false)
107                .force_hp_wifi_iso() // pmu_ll_hp_set_power_force_isolate
108                .bit(false)
109                .force_hp_wifi_pu() // pmu_ll_hp_set_power_force_power_up
110                .bit(false)
111                .force_hp_wifi_no_reset() // pmu_ll_hp_set_power_force_no_reset
112                .bit(false)
113                .force_hp_wifi_no_iso() // pmu_ll_hp_set_power_force_no_isolate
114                .bit(false)
115                .force_hp_wifi_pd() // pmu_ll_hp_set_power_force_power_down
116                .bit(false)
117        });
118
119        // Isolate all memory banks while sleeping, avoid memory leakage current
120
121        pmu().power_pd_mem_cntl().modify(|_, w| {
122            w.force_hp_mem_no_iso() // pmu_ll_hp_set_memory_no_isolate
123                .bits(0)
124        });
125
126        pmu().power_pd_lpperi_cntl().modify(|_, w| {
127            w.force_lp_peri_reset() // pmu_ll_lp_set_power_force_reset
128                .bit(false)
129                .force_lp_peri_iso() // pmu_ll_lp_set_power_force_isolate
130                .bit(false)
131                .force_lp_peri_pu() // pmu_ll_lp_set_power_force_power_up
132                .bit(false)
133                .force_lp_peri_no_reset() // pmu_ll_lp_set_power_force_no_reset
134                .bit(false)
135                .force_lp_peri_no_iso() // pmu_ll_lp_set_power_force_no_isolate
136                .bit(false)
137                .force_lp_peri_pd() // pmu_ll_lp_set_power_force_power_down
138                .bit(false)
139        });
140    };
141}
142
143fn modem_clock_domain_power_state_icg_map_init() {
144    // C6 has SOC_PM_SUPPORT_PMU_MODEM_STATE defined
145
146    // const ICG_NOGATING_SLEEP: u8 = 1 << 0; // unused
147    const ICG_NOGATING_MODEM: u8 = 1 << 1;
148    const ICG_NOGATING_ACTIVE: u8 = 1 << 2;
149
150    // the ICG code's bit 0, 1 and 2 indicates the ICG state
151    // of pmu SLEEP, MODEM and ACTIVE mode respectively
152    unsafe {
153        modem_syscon().clk_conf_power_st().modify(|_, w| {
154            w.clk_modem_apb_st_map() // modem_syscon_ll_set_modem_apb_icg_bitmap
155                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
156                .clk_modem_peri_st_map() // modem_syscon_ll_set_modem_periph_icg_bitmap
157                .bits(ICG_NOGATING_ACTIVE)
158                .clk_wifi_st_map() // modem_syscon_ll_set_wifi_icg_bitmap
159                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
160                .clk_bt_st_map() // modem_syscon_ll_set_bt_icg_bitmap
161                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
162                .clk_fe_st_map() // modem_syscon_ll_set_fe_icg_bitmap
163                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
164                .clk_zb_st_map() // modem_syscon_ll_set_ieee802154_icg_bitmap
165                .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() // modem_lpcon_ll_set_lp_apb_icg_bitmap
170                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
171                .clk_i2c_mst_st_map() // modem_lpcon_ll_set_i2c_master_icg_bitmap
172                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
173                .clk_coex_st_map() // modem_lpcon_ll_set_coex_icg_bitmap
174                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
175                .clk_wifipwr_st_map() // modem_lpcon_ll_set_wifipwr_icg_bitmap
176                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
177        });
178    }
179}
180
181enum RtcSlowClockSource {
182    /// Select RC_SLOW_CLK as RTC_SLOW_CLK source
183    RcSlow  = 0,
184
185    /// Select XTAL32K_CLK as RTC_SLOW_CLK source
186    XTAL32K = 1,
187
188    /// Select RC32K_CLK as RTC_SLOW_CLK source
189    RC32K   = 2,
190
191    /// Select OSC_SLOW_CLK (external slow clock) as RTC_SLOW_CLK source
192    OscSlow = 3,
193
194    /// Invalid RTC_SLOW_CLK source
195    Invalid,
196}
197
198impl RtcSlowClockSource {
199    fn current() -> Self {
200        // clk_ll_rtc_slow_get_src()
201        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
289// PHY, BT, IEEE802154 are not used by the init code so they are unimplemented
290fn 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    // pmu_hp_power_t.0
314    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    // pmu_hp_power_t.1
328    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    // pmu_hp_power_t.2
340    pub struct HpXtalPower(u32);
341
342    pub bool, xpd_xtal     , set_xpd_xtal     : 31;
343}
344
345#[derive(Clone, Copy, Default)]
346// pmu_sleep_power_config_t.0
347pub struct HpSysPower {
348    // This is a best-guess assignment of the variants in the union `pmu_hp_power_t` union
349    // In esp-idf, all three fields are `pmu_hp_power_t`
350    pub dig_power: HpDigPower,
351    pub clk: HpClkPower,
352    pub xtal: HpXtalPower,
353}
354
355bitfield::bitfield! {
356    #[derive(Clone, Copy, Default)]
357    // pmu_hp_sys_cntl_reg_t
358    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    // pmu_hp_icg_modem_reg_t
371    pub struct HpIcgModem(u32);
372
373    pub u8, code, set_code: 31, 30;
374}
375
376bitfield::bitfield! {
377    #[derive(Clone, Copy, Default)]
378    // pmu_hp_sysclk_reg_t
379    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// pmu_hp_system_clock_param_t
389#[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    // pmu_hp_analog_t.0
400    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    // pmu_hp_analog_t.1
411    pub struct HpAnalogRegulator0(u32);
412
413    // Only HP_ACTIVE modem under hp system is valid
414    pub u8,   lp_dbias_vol   , set_lp_dbias_vol   : 8, 4;
415    // Only HP_ACTIVE modem under hp system is valid
416    pub u8,   hp_dbias_vol   , set_hp_dbias_vol   : 13, 9;
417    // Only HP_ACTIVE modem under hp system is valid
418    pub bool, dbias_sel      , set_dbias_sel      : 14;
419    // Only HP_ACTIVE modem under hp system is valid
420    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    // pmu_hp_analog_t.2
433    pub struct HpAnalogRegulator1(u32);
434
435    pub u32, drv_b          , set_drv_b          : 31, 8;
436}
437
438#[derive(Clone, Copy, Default)]
439// pmu_hp_analog_t
440pub struct HpAnalog {
441    pub bias: HpAnalogBias,
442    pub regulator0: HpAnalogRegulator0,
443    pub regulator1: HpAnalogRegulator1,
444}
445
446bitfield::bitfield! {
447    #[derive(Clone, Copy, Default)]
448    // pmu_hp_backup_reg_t/active
449    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    // pmu_hp_backup_reg_t/modem
467    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    // pmu_hp_backup_reg_t/sleep
480    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    // custom based on `PMU_ICG_FUNC_ENA_*` bitflag constants
498    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                // Default configuration of hp-system power in active, modem and sleep modes
539                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                // Default configuration of hp-system clock in active, modem and sleep modes
546                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                // Default configuration of hp-system digital sub-system in active, modem
560                // and sleep modes
561                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                // Default configuration of hp-system analog sub-system in active, modem and
571                // sleep modes
572                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                // Default configuration of hp-system retention sub-system in active, modem
593                // and sleep modes
594                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        // pmu_hp_system_init_default
612
613        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        // PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT
651        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        // TODO: These 4 aren't applied currently?
658        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            // Some PMU initial parameter configuration
886            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    // pmu_lp_power_t.0
904    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    // pmu_lp_power_t.1
914    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    // pmu_lp_power_t.2
925    pub struct LpXtalPower(u32);
926
927    pub bool, xpd_xtal     , set_xpd_xtal     : 31;
928}
929
930#[derive(Clone, Copy, Default)]
931// pmu_sleep_power_config_t.1
932pub struct LpSysPower {
933    // This is a best-guess assignment of the variants in the union `pmu_lp_power_t` union
934    // In esp-idf, all three fields are `pmu_lp_power_t`
935    pub dig_power: LpDigPower,
936    pub clk_power: LpClkPower,
937    pub xtal: LpXtalPower,
938}
939
940bitfield::bitfield! {
941    #[derive(Clone, Copy, Default)]
942    // pmu_lp_analog_t.0
943    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    // pmu_lp_analog_t.1
954    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    // pmu_lp_analog_t.2
965    pub struct LpAnalogRegulator1(u32);
966
967    pub u8, drv_b    , set_drv_b    : 31, 28;
968}
969
970#[derive(Clone, Copy, Default)]
971// pmu_lp_analog_t
972pub 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                // Default configuration of lp-system power in active and sleep modes
983                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                // Default configuration of lp-system analog sub-system in active and sleep modes
987                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() // pmu_ll_lp_set_bias_xpd
1093                    .bit(sleep.bias.xpd_bias())
1094                    .lp_sleep_dbg_atten() // pmu_ll_lp_set_bias_dbg_atten
1095                    .bits(sleep.bias.dbg_atten())
1096                    .lp_sleep_pd_cur() // pmu_ll_lp_set_bias_pd_cur
1097                    .bit(sleep.bias.pd_cur())
1098                    .sleep() // pmu_ll_lp_set_bias_sleep
1099                    .bit(sleep.bias.bias_sleep())
1100            });
1101        }
1102    }
1103}
1104
1105pub(crate) fn init() {
1106    // pmu_init()
1107    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    // esp_perip_clk_init()
1123    modem_clock_domain_power_state_icg_map_init();
1124
1125    //  During system initialization, the low-power clock source of the modem
1126    //  (WiFi, BLE or Coexist) follows the configuration of the slow clock source
1127    //  of the system. If the WiFi, BLE or Coexist module needs a higher
1128    //  precision sleep clock (for example, the BLE needs to use the main XTAL
1129    //  oscillator (40 MHz) to provide the clock during the sleep process in some
1130    //  scenarios), the module needs to switch to the required clock source by
1131    //  itself.
1132    // TODO - WIFI-5233
1133    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        // Configure modem ICG code in PMU_ACTIVE state
1162        pmu()
1163            .hp_active_icg_modem()
1164            .modify(|_, w| w.hp_active_dig_icg_modem_code().bits(ICG_MODEM_CODE_ACTIVE));
1165
1166        // Disable clock gating for MODEM_APB, I2C_MST and LP_APB clock domains in
1167        // PMU_ACTIVE state
1168        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        // Software trigger force update modem ICG code and ICG switch
1179        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        // The following is part of rtc_clk_init
1187
1188        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        // clk_ll_rc_fast_tick_conf
1209        pcr()
1210            .ctrl_tick_conf()
1211            .modify(|_, w| w.fosc_tick_num().bits(255));
1212    }
1213}
1214
1215// Terminology:
1216//
1217// CPU Reset:    Reset CPU core only, once reset done, CPU will execute from
1218//               reset vector
1219// Core Reset:   Reset the whole digital system except RTC sub-system
1220// System Reset: Reset the whole digital system, including RTC sub-system
1221// Chip Reset:   Reset the whole chip, including the analog part
1222
1223/// SOC Reset Reason.
1224#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
1225pub enum SocResetReason {
1226    /// Power on reset
1227    ///
1228    /// In ESP-IDF this value (0x01) can *also* be `ChipBrownOut` or
1229    /// `ChipSuperWdt`, however that is not really compatible with Rust-style
1230    /// enums.
1231    ChipPowerOn   = 0x01,
1232    /// Software resets the digital core by RTC_CNTL_SW_SYS_RST
1233    CoreSw        = 0x03,
1234    /// Deep sleep reset the digital core
1235    CoreDeepSleep = 0x05,
1236    /// SDIO Core reset
1237    CoreSDIO      = 0x06,
1238    /// Main watch dog 0 resets digital core
1239    CoreMwdt0     = 0x07,
1240    /// Main watch dog 1 resets digital core
1241    CoreMwdt1     = 0x08,
1242    /// RTC watch dog resets digital core
1243    CoreRtcWdt    = 0x09,
1244    /// Main watch dog 0 resets CPU 0
1245    Cpu0Mwdt0     = 0x0B,
1246    /// Software resets CPU 0 by RTC_CNTL_SW_PROCPU_RST
1247    Cpu0Sw        = 0x0C,
1248    /// RTC watch dog resets CPU 0
1249    Cpu0RtcWdt    = 0x0D,
1250    /// VDD voltage is not stable and resets the digital core
1251    SysBrownOut   = 0x0F,
1252    /// RTC watch dog resets digital core and rtc module
1253    SysRtcWdt     = 0x10,
1254    /// Main watch dog 1 resets CPU 0
1255    Cpu0Mwdt1     = 0x11,
1256    /// Super watch dog resets the digital core and rtc module
1257    SysSuperWdt   = 0x12,
1258    /// eFuse CRC error resets the digital core
1259    CoreEfuseCrc  = 0x14,
1260    /// USB UART resets the digital core
1261    CoreUsbUart   = 0x15,
1262    /// USB JTAG resets the digital core
1263    CoreUsbJtag   = 0x16,
1264    /// JTAG resets CPU
1265    Cpu0JtagCpu   = 0x18,
1266}
1267
1268#[allow(unused)]
1269#[derive(Debug, Clone, Copy)]
1270/// RTC SLOW_CLK frequency values
1271pub(crate) enum RtcFastClock {
1272    /// Select RC_FAST_CLK as RTC_FAST_CLK source
1273    RtcFastClockRcFast = 0,
1274    /// Select XTAL_D2_CLK as RTC_FAST_CLK source
1275    RtcFastClockXtalD2 = 1,
1276}
1277
1278impl Clock for RtcFastClock {
1279    fn frequency(&self) -> Rate {
1280        match self {
1281            RtcFastClock::RtcFastClockXtalD2 => {
1282                // TODO: Is the value correct?
1283                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)]
1292/// RTC SLOW_CLK frequency values
1293pub enum RtcSlowClock {
1294    /// Select RC_SLOW_CLK as RTC_SLOW_CLK source
1295    RtcSlowClockRcSlow  = 0,
1296    /// Select XTAL32K_CLK as RTC_SLOW_CLK source
1297    RtcSlowClock32kXtal = 1,
1298    /// Select RC32K_CLK as RTC_SLOW_CLK source
1299    RtcSlowClock32kRc   = 2,
1300    /// Select OSC_SLOW_CLK (external slow clock) as RTC_SLOW_CLK source
1301    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)]
1316/// Clock source to be calibrated using rtc_clk_cal function
1317pub(crate) enum RtcCalSel {
1318    /// Currently selected RTC SLOW_CLK
1319    RtcCalRtcMux     = -1,
1320    /// Internal 150kHz RC oscillator
1321    RtcCalRcSlow     = 0,
1322    /// External 32kHz XTAL, as one type of 32k clock
1323    RtcCal32kXtal    = 1,
1324    /// Internal 32kHz RC oscillator, as one type of 32k clock
1325    RtcCal32kRc      = 2,
1326    /// External slow clock signal input by lp_pad_gpio0, as one type of 32k
1327    /// clock
1328    RtcCal32kOscSlow = 3,
1329    /// Internal 20MHz RC oscillator
1330    RtcCalRcFast,
1331}
1332
1333#[derive(Clone)]
1334pub(crate) enum RtcCaliClkSel {
1335    CaliClkRcSlow = 0,
1336    CaliClkRcFast = 1,
1337    CaliClk32k    = 2,
1338}
1339
1340/// RTC Watchdog Timer driver
1341impl RtcClock {
1342    // rtc_clk_xtal_freq_get
1343    pub(crate) fn xtal_freq_mhz() -> u32 {
1344        Self::read_xtal_freq_mhz().unwrap_or(40)
1345    }
1346
1347    /// Get main XTAL frequency
1348    /// This is the value stored in RTC register RTC_XTAL_FREQ_REG by the
1349    /// bootloader, as passed to rtc_clk_init function.
1350    pub fn xtal_freq() -> XtalClock {
1351        match Self::xtal_freq_mhz() {
1352            40 => XtalClock::_40M,
1353            other => XtalClock::Other(other),
1354        }
1355    }
1356
1357    /// Get the RTC_SLOW_CLK source
1358    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    // TODO: IDF-5781 Some of esp32c6 SOC_RTC_FAST_CLK_SRC_XTAL_D2 rtc_fast clock
1387    // has timing issue Force to use SOC_RTC_FAST_CLK_SRC_RC_FAST since 2nd
1388    // stage bootloader https://github.com/espressif/esp-idf/blob/master/components/bootloader_support/src/bootloader_clock_init.c#L65-L67
1389    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    /// Calibration of RTC_SLOW_CLK is performed using a special feature of
1403    /// TIMG0. This feature counts the number of XTAL clock cycles within a
1404    /// given number of RTC_SLOW_CLK cycles.
1405    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        // Enable requested clock (150k is always on)
1471        // Some delay is required before the time is stable
1472        // Only enable if originaly was disabled
1473        // If clock is already on, do nothing
1474
1475        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        // TODO: very hacky - icg_hp_xtal32k is already set in the above condition?
1484        // in ESP-IDF these are not called in this function but the fields are set
1485        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        // Check if there is already running calibration process
1537        // TODO: &mut TIMG0 for calibration
1538        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            // Set small timeout threshold to accelerate the generation of timeot
1551            // Internal circuit will be reset when timeout occurs and will not affect the
1552            // next calibration
1553            while !timg0.rtccalicfg().read().rtc_cali_rdy().bit_is_set()
1554                && !timg0.rtccalicfg2().read().rtc_cali_timeout().bit_is_set()
1555            {}
1556        }
1557
1558        // Prepare calibration
1559        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        // Start calibration
1593        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        // Wait for calibration to finish up to another us_time_estimate
1601        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                // The Fosc CLK of calibration circuit is divided by 32 for ECO1.
1606                // So we need to multiply the frequency of the Fosc for ECO1 and above chips by
1607                // 32 times. And ensure that this modification will not affect
1608                // ECO0.
1609                // https://github.com/espressif/esp-idf/commit/e3148369f32fdc6de62c35a67f7adb6f4faef4e3
1610                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                // Timed out waiting for calibration
1622                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    /// Measure RTC slow clock's period, based on main XTAL frequency
1668    ///
1669    /// This function will time out and return 0 if the time for the given
1670    /// number of cycles to be counted exceeds the expected time twice. This
1671    /// may happen if 32k XTAL is being calibrated, but the oscillator has
1672    /// not started up (due to incorrect loading capacitance, board design
1673    /// issue, or lack of 32 XTAL on board).
1674    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        // The Fosc CLK of calibration circuit is divided by 32 for ECO1.
1680        // So we need to divide the calibrate cycles of the FOSC for ECO1 and above
1681        // chips by 32 to avoid excessive calibration time.
1682        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    /// Calculate the necessary RTC_SLOW_CLK cycles to complete 1 millisecond.
1694    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                // RtcSlowClock::RtcCalRcFast => RtcCalSel::RtcCalRcFast,
1702            },
1703            1024,
1704        );
1705
1706        // 100_000_000 is used to get rid of `float` calculations
1707        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_SLOW_CLK
1719                .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    // rtc_clk_cpu_set_to_default_config
1740    let freq = RtcClock::xtal_freq_mhz();
1741
1742    esp32c6_rtc_update_to_xtal_raw(freq, 1);
1743
1744    // TODO: don't turn off the bbpll if some consumers depend on bbpll
1745    // if !s_bbpll_digi_consumers_ref_count {
1746    rtc_clk_bbpll_disable();
1747    //}
1748}
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    /// The clock from which CPU clock is derived
1790    pub source: CpuClockSource,
1791
1792    /// Source clock frequency
1793    pub source_freq_mhz: u32,
1794
1795    /// Divider, freq_mhz = SOC_ROOT_CLK freq_mhz / div
1796    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    // rtc_clk_cpu_freq_set_config
1832    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        // && !s_bbpll_digi_consumers_ref_count
1852        {
1853            // We don't turn off the bbpll if some consumers depend on bbpll
1854            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}