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        clocks_ll::{
10            esp32c6_bbpll_get_freq_mhz,
11            esp32c6_cpu_get_hs_divider,
12            esp32c6_cpu_get_ls_divider,
13            esp32c6_rtc_bbpll_configure_raw,
14            esp32c6_rtc_freq_to_pll_mhz_raw,
15            esp32c6_rtc_update_to_8m,
16            esp32c6_rtc_update_to_xtal_raw,
17            regi2c_write_mask,
18        },
19        Clock,
20        XtalClock,
21    },
22    peripherals::TIMG0,
23    rtc_cntl::RtcClock,
24    soc::efuse::Efuse,
25    time::Rate,
26};
27
28const I2C_DIG_REG: u8 = 0x6d;
29const I2C_DIG_REG_HOSTID: u8 = 0;
30
31const I2C_DIG_REG_XPD_RTC_REG: u8 = 13;
32const I2C_DIG_REG_XPD_RTC_REG_MSB: u8 = 2;
33const I2C_DIG_REG_XPD_RTC_REG_LSB: u8 = 2;
34
35const I2C_DIG_REG_XPD_DIG_REG: u8 = 13;
36const I2C_DIG_REG_XPD_DIG_REG_MSB: u8 = 3;
37const I2C_DIG_REG_XPD_DIG_REG_LSB: u8 = 3;
38
39const I2C_DIG_REG_ENIF_RTC_DREG: u8 = 5;
40const I2C_DIG_REG_ENIF_RTC_DREG_MSB: u8 = 7;
41const I2C_DIG_REG_ENIF_RTC_DREG_LSB: u8 = 7;
42
43const I2C_DIG_REG_ENIF_DIG_DREG: u8 = 7;
44const I2C_DIG_REG_ENIF_DIG_DREG_MSB: u8 = 7;
45const I2C_DIG_REG_ENIF_DIG_DREG_LSB: u8 = 7;
46
47const I2C_DIG_REG_SCK_DCAP: u8 = 14;
48const I2C_DIG_REG_SCK_DCAP_MSB: u8 = 7;
49const I2C_DIG_REG_SCK_DCAP_LSB: u8 = 0;
50
51unsafe fn pmu<'a>() -> &'a esp32c6::pmu::RegisterBlock {
52    &*esp32c6::PMU::ptr()
53}
54
55unsafe fn modem_lpcon<'a>() -> &'a esp32c6::modem_lpcon::RegisterBlock {
56    &*esp32c6::MODEM_LPCON::ptr()
57}
58
59unsafe fn modem_syscon<'a>() -> &'a esp32c6::modem_syscon::RegisterBlock {
60    &*esp32c6::MODEM_SYSCON::ptr()
61}
62
63unsafe fn lp_clkrst<'a>() -> &'a esp32c6::lp_clkrst::RegisterBlock {
64    &*esp32c6::LP_CLKRST::ptr()
65}
66
67unsafe fn pcr<'a>() -> &'a esp32c6::pcr::RegisterBlock {
68    &*esp32c6::PCR::ptr()
69}
70
71unsafe fn lp_aon<'a>() -> &'a esp32c6::lp_aon::RegisterBlock {
72    &*esp32c6::LP_AON::ptr()
73}
74
75fn pmu_power_domain_force_default() {
76    unsafe {
77        // for bypass reserved power domain
78
79        // PMU_HP_PD_TOP
80        pmu().power_pd_top_cntl().modify(|_, w| {
81            w.force_top_reset() // pmu_ll_hp_set_power_force_reset
82                .bit(false)
83                .force_top_iso() // pmu_ll_hp_set_power_force_isolate
84                .bit(false)
85                .force_top_pu() // pmu_ll_hp_set_power_force_power_up
86                .bit(false)
87                .force_top_no_reset() // pmu_ll_hp_set_power_force_no_reset
88                .bit(false)
89                .force_top_no_iso() // pmu_ll_hp_set_power_force_no_isolate
90                .bit(false)
91                .force_top_pd() // pmu_ll_hp_set_power_force_power_down
92                .bit(false)
93        });
94
95        // PMU_HP_PD_HP_AON
96        pmu().power_pd_hpaon_cntl().modify(|_, w| {
97            w.force_hp_aon_reset() // pmu_ll_hp_set_power_force_reset
98                .bit(false)
99                .force_hp_aon_iso() // pmu_ll_hp_set_power_force_isolate
100                .bit(false)
101                .force_hp_aon_pu() // pmu_ll_hp_set_power_force_power_up
102                .bit(false)
103                .force_hp_aon_no_reset() // pmu_ll_hp_set_power_force_no_reset
104                .bit(false)
105                .force_hp_aon_no_iso() // pmu_ll_hp_set_power_force_no_isolate
106                .bit(false)
107                .force_hp_aon_pd() // pmu_ll_hp_set_power_force_power_down
108                .bit(false)
109        });
110
111        // PMU_HP_PD_CPU
112        pmu().power_pd_hpcpu_cntl().modify(|_, w| {
113            w.force_hp_cpu_reset() // pmu_ll_hp_set_power_force_reset
114                .bit(false)
115                .force_hp_cpu_iso() // pmu_ll_hp_set_power_force_isolate
116                .bit(false)
117                .force_hp_cpu_pu() // pmu_ll_hp_set_power_force_power_up
118                .bit(false)
119                .force_hp_cpu_no_reset() // pmu_ll_hp_set_power_force_no_reset
120                .bit(false)
121                .force_hp_cpu_no_iso() // pmu_ll_hp_set_power_force_no_isolate
122                .bit(false)
123                .force_hp_cpu_pd() // pmu_ll_hp_set_power_force_power_down
124                .bit(false)
125        });
126
127        // PMU_HP_PD_WIFI
128        pmu().power_pd_hpwifi_cntl().modify(|_, w| {
129            w.force_hp_wifi_reset() // pmu_ll_hp_set_power_force_reset
130                .bit(false)
131                .force_hp_wifi_iso() // pmu_ll_hp_set_power_force_isolate
132                .bit(false)
133                .force_hp_wifi_pu() // pmu_ll_hp_set_power_force_power_up
134                .bit(false)
135                .force_hp_wifi_no_reset() // pmu_ll_hp_set_power_force_no_reset
136                .bit(false)
137                .force_hp_wifi_no_iso() // pmu_ll_hp_set_power_force_no_isolate
138                .bit(false)
139                .force_hp_wifi_pd() // pmu_ll_hp_set_power_force_power_down
140                .bit(false)
141        });
142
143        // Isolate all memory banks while sleeping, avoid memory leakage current
144
145        pmu().power_pd_mem_cntl().modify(|_, w| {
146            w.force_hp_mem_no_iso() // pmu_ll_hp_set_memory_no_isolate
147                .bits(0)
148        });
149
150        pmu().power_pd_lpperi_cntl().modify(|_, w| {
151            w.force_lp_peri_reset() // pmu_ll_lp_set_power_force_reset
152                .bit(false)
153                .force_lp_peri_iso() // pmu_ll_lp_set_power_force_isolate
154                .bit(false)
155                .force_lp_peri_pu() // pmu_ll_lp_set_power_force_power_up
156                .bit(false)
157                .force_lp_peri_no_reset() // pmu_ll_lp_set_power_force_no_reset
158                .bit(false)
159                .force_lp_peri_no_iso() // pmu_ll_lp_set_power_force_no_isolate
160                .bit(false)
161                .force_lp_peri_pd() // pmu_ll_lp_set_power_force_power_down
162                .bit(false)
163        });
164    };
165}
166
167fn modem_clock_domain_power_state_icg_map_init() {
168    // C6 has SOC_PM_SUPPORT_PMU_MODEM_STATE defined
169
170    // const ICG_NOGATING_SLEEP: u8 = 1 << 0; // unused
171    const ICG_NOGATING_MODEM: u8 = 1 << 1;
172    const ICG_NOGATING_ACTIVE: u8 = 1 << 2;
173
174    // the ICG code's bit 0, 1 and 2 indicates the ICG state
175    // of pmu SLEEP, MODEM and ACTIVE mode respectively
176    unsafe {
177        modem_syscon().clk_conf_power_st().modify(|_, w| {
178            w.clk_modem_apb_st_map() // modem_syscon_ll_set_modem_apb_icg_bitmap
179                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
180                .clk_modem_peri_st_map() // modem_syscon_ll_set_modem_periph_icg_bitmap
181                .bits(ICG_NOGATING_ACTIVE)
182                .clk_wifi_st_map() // modem_syscon_ll_set_wifi_icg_bitmap
183                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
184                .clk_bt_st_map() // modem_syscon_ll_set_bt_icg_bitmap
185                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
186                .clk_fe_st_map() // modem_syscon_ll_set_fe_icg_bitmap
187                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
188                .clk_zb_st_map() // modem_syscon_ll_set_ieee802154_icg_bitmap
189                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
190        });
191
192        modem_lpcon().clk_conf_power_st().modify(|_, w| {
193            w.clk_lp_apb_st_map() // modem_lpcon_ll_set_lp_apb_icg_bitmap
194                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
195                .clk_i2c_mst_st_map() // modem_lpcon_ll_set_i2c_master_icg_bitmap
196                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
197                .clk_coex_st_map() // modem_lpcon_ll_set_coex_icg_bitmap
198                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
199                .clk_wifipwr_st_map() // modem_lpcon_ll_set_wifipwr_icg_bitmap
200                .bits(ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM)
201        });
202    }
203}
204
205enum RtcSlowClockSource {
206    /// Select RC_SLOW_CLK as RTC_SLOW_CLK source
207    RcSlow  = 0,
208
209    /// Select XTAL32K_CLK as RTC_SLOW_CLK source
210    XTAL32K = 1,
211
212    /// Select RC32K_CLK as RTC_SLOW_CLK source
213    RC32K   = 2,
214
215    /// Select OSC_SLOW_CLK (external slow clock) as RTC_SLOW_CLK source
216    OscSlow = 3,
217
218    /// Invalid RTC_SLOW_CLK source
219    Invalid,
220}
221
222impl RtcSlowClockSource {
223    fn current() -> Self {
224        // clk_ll_rtc_slow_get_src()
225        let lp_clkrst = unsafe { lp_clkrst() };
226        match lp_clkrst.lp_clk_conf().read().slow_clk_sel().bits() {
227            0 => Self::RcSlow,
228            1 => Self::XTAL32K,
229            2 => Self::RC32K,
230            3 => Self::OscSlow,
231            _ => Self::Invalid,
232        }
233    }
234}
235
236#[allow(unused)]
237enum ModemClockLpclkSource {
238    RcSlow = 0,
239    RcFast,
240    MainXtal,
241    RC32K,
242    XTAL32K,
243    EXT32K,
244}
245
246impl From<RtcSlowClockSource> for ModemClockLpclkSource {
247    fn from(src: RtcSlowClockSource) -> Self {
248        match src {
249            RtcSlowClockSource::RcSlow => Self::RcSlow,
250            RtcSlowClockSource::XTAL32K => Self::XTAL32K,
251            RtcSlowClockSource::RC32K => Self::RC32K,
252            RtcSlowClockSource::OscSlow => Self::EXT32K,
253            _ => Self::RcSlow,
254        }
255    }
256}
257
258fn modem_clock_hal_deselect_all_wifi_lpclk_source() {
259    unsafe {
260        modem_lpcon().wifi_lp_clk_conf().modify(|_, w| {
261            w.clk_wifipwr_lp_sel_osc_slow()
262                .clear_bit()
263                .clk_wifipwr_lp_sel_osc_fast()
264                .clear_bit()
265                .clk_wifipwr_lp_sel_xtal32k()
266                .clear_bit()
267                .clk_wifipwr_lp_sel_xtal()
268                .clear_bit()
269        });
270    }
271}
272
273fn modem_clock_hal_select_wifi_lpclk_source(src: ModemClockLpclkSource) {
274    unsafe {
275        modem_lpcon().wifi_lp_clk_conf().modify(|_, w| match src {
276            ModemClockLpclkSource::RcSlow => w.clk_wifipwr_lp_sel_osc_slow().set_bit(),
277            ModemClockLpclkSource::RcFast => w.clk_wifipwr_lp_sel_osc_fast().set_bit(),
278            ModemClockLpclkSource::MainXtal => w.clk_wifipwr_lp_sel_xtal().set_bit(),
279
280            ModemClockLpclkSource::RC32K
281            | ModemClockLpclkSource::XTAL32K
282            | ModemClockLpclkSource::EXT32K => w.clk_wifipwr_lp_sel_xtal32k().set_bit(),
283        });
284
285        modem_lpcon().modem_32k_clk_conf().modify(|_, w| match src {
286            ModemClockLpclkSource::RcSlow
287            | ModemClockLpclkSource::RcFast
288            | ModemClockLpclkSource::MainXtal => w,
289
290            ModemClockLpclkSource::RC32K => w.clk_modem_32k_sel().bits(1),
291            ModemClockLpclkSource::XTAL32K => w.clk_modem_32k_sel().bits(0),
292            ModemClockLpclkSource::EXT32K => w.clk_modem_32k_sel().bits(2),
293        });
294    }
295}
296
297fn modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider: u16) {
298    unsafe {
299        modem_lpcon()
300            .wifi_lp_clk_conf()
301            .modify(|_, w| w.clk_wifipwr_lp_div_num().bits(divider));
302    }
303}
304
305fn modem_clock_hal_enable_wifipwr_clock(enable: bool) {
306    unsafe {
307        modem_lpcon()
308            .clk_conf()
309            .modify(|_, w| w.clk_wifipwr_en().bit(enable));
310    }
311}
312
313// PHY, BT, IEEE802154 are not used by the init code so they are unimplemented
314fn modem_clock_select_lp_clock_source_wifi(src: ModemClockLpclkSource, divider: u16) {
315    modem_clock_hal_deselect_all_wifi_lpclk_source();
316    modem_clock_hal_select_wifi_lpclk_source(src);
317    modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider);
318    modem_clock_hal_enable_wifipwr_clock(true);
319}
320
321const fn hp_retention_regdma_config(dir: u8, entry: u8) -> u8 {
322    (((dir) << 2) | (entry & 0x3)) & 0x7
323}
324
325const HP_CALI_DBIAS: u8 = 25;
326const LP_CALI_DBIAS: u8 = 26;
327
328const ICG_MODEM_CODE_SLEEP: u8 = 0;
329const ICG_MODEM_CODE_MODEM: u8 = 1;
330const ICG_MODEM_CODE_ACTIVE: u8 = 2;
331
332const HP_SYSCLK_XTAL: u8 = 0;
333const HP_SYSCLK_PLL: u8 = 1;
334
335bitfield::bitfield! {
336    #[derive(Clone, Copy, Default)]
337    // pmu_hp_power_t.0
338    pub struct HpDigPower(u32);
339
340    pub bool, vdd_spi_pd_en, set_vdd_spi_pd_en: 21;
341    pub bool, mem_dslp     , set_mem_dslp     : 22;
342    pub u8,   mem_pd_en    , set_mem_pd_en    : 26, 23;
343    pub bool, wifi_pd_en   , set_wifi_pd_en   : 27;
344    pub bool, cpu_pd_en    , set_cpu_pd_en    : 29;
345    pub bool, aon_pd_en    , set_aon_pd_en    : 30;
346    pub bool, top_pd_en    , set_top_pd_en    : 31;
347}
348
349bitfield::bitfield! {
350    #[derive(Clone, Copy, Default)]
351    // pmu_hp_power_t.1
352    pub struct HpClkPower(u32);
353
354    pub bool, i2c_iso_en   , set_i2c_iso_en   : 26;
355    pub bool, i2c_retention, set_i2c_retention: 27;
356    pub bool, xpd_bb_i2c   , set_xpd_bb_i2c   : 28;
357    pub bool, xpd_bbpll_i2c, set_xpd_bbpll_i2c: 29;
358    pub bool, xpd_bbpll    , set_xpd_bbpll    : 30;
359}
360
361bitfield::bitfield! {
362    #[derive(Clone, Copy, Default)]
363    // pmu_hp_power_t.2
364    pub struct HpXtalPower(u32);
365
366    pub bool, xpd_xtal     , set_xpd_xtal     : 31;
367}
368
369#[derive(Clone, Copy, Default)]
370// pmu_sleep_power_config_t.0
371pub struct HpSysPower {
372    // This is a best-guess assignment of the variants in the union `pmu_hp_power_t` union
373    // In esp-idf, all three fields are `pmu_hp_power_t`
374    pub dig_power: HpDigPower,
375    pub clk: HpClkPower,
376    pub xtal: HpXtalPower,
377}
378
379bitfield::bitfield! {
380    #[derive(Clone, Copy, Default)]
381    // pmu_hp_sys_cntl_reg_t
382    pub struct HpSysCntlReg(u32);
383
384    pub bool, uart_wakeup_en , set_uart_wakeup_en : 24;
385    pub bool, lp_pad_hold_all, set_lp_pad_hold_all: 25;
386    pub bool, hp_pad_hold_all, set_hp_pad_hold_all: 26;
387    pub bool, dig_pad_slp_sel, set_dig_pad_slp_sel: 27;
388    pub bool, dig_pause_wdt  , set_dig_pause_wdt  : 28;
389    pub bool, dig_cpu_stall  , set_dig_cpu_stall  : 29;
390}
391
392bitfield::bitfield! {
393    #[derive(Clone, Copy, Default)]
394    // pmu_hp_icg_modem_reg_t
395    pub struct HpIcgModem(u32);
396
397    pub u8, code, set_code: 31, 30;
398}
399
400bitfield::bitfield! {
401    #[derive(Clone, Copy, Default)]
402    // pmu_hp_sysclk_reg_t
403    pub struct HpSysclk(u32);
404
405    pub bool, dig_sysclk_nodiv , set_dig_sysclk_nodiv : 26;
406    pub bool, icg_sysclk_en    , set_icg_sysclk_en    : 27;
407    pub bool, sysclk_slp_sel   , set_sysclk_slp_sel   : 28;
408    pub bool, icg_slp_sel      , set_icg_slp_sel      : 29;
409    pub u8,   dig_sysclk_sel   , set_dig_sysclk_sel   : 31, 30;
410}
411
412// pmu_hp_system_clock_param_t
413#[derive(Clone, Copy, Default)]
414struct SystemClockParam {
415    icg_func: u32,
416    icg_apb: u32,
417    icg_modem: HpIcgModem,
418    sysclk: HpSysclk,
419}
420
421bitfield::bitfield! {
422    #[derive(Clone, Copy, Default)]
423    // pmu_hp_analog_t.0
424    pub struct HpAnalogBias(u32);
425
426    pub bool, xpd_bias  , set_xpd_bias  : 25;
427    pub u8,   dbg_atten , set_dbg_atten : 29, 26;
428    pub bool, pd_cur    , set_pd_cur    : 30;
429    pub bool, bias_sleep, set_bias_sleep: 31;
430}
431
432bitfield::bitfield! {
433    #[derive(Clone, Copy, Default)]
434    // pmu_hp_analog_t.1
435    pub struct HpAnalogRegulator0(u32);
436
437    // Only HP_ACTIVE modem under hp system is valid
438    pub u8,   lp_dbias_vol   , set_lp_dbias_vol   : 8, 4;
439    // Only HP_ACTIVE modem under hp system is valid
440    pub u8,   hp_dbias_vol   , set_hp_dbias_vol   : 13, 9;
441    // Only HP_ACTIVE modem under hp system is valid
442    pub bool, dbias_sel      , set_dbias_sel      : 14;
443    // Only HP_ACTIVE modem under hp system is valid
444    pub bool, dbias_init     , set_dbias_init     : 15;
445
446    pub bool, slp_mem_xpd    , set_slp_mem_xpd    : 16;
447    pub bool, slp_logic_xpd  , set_slp_logic_xpd  : 17;
448    pub bool, xpd            , set_xpd            : 18;
449    pub u8,   slp_mem_dbias  , set_slp_mem_dbias  : 22, 19;
450    pub u8,   slp_logic_dbias, set_slp_logic_dbias: 26, 23;
451    pub u8,   dbias          , set_dbias          : 31, 27;
452}
453
454bitfield::bitfield! {
455    #[derive(Clone, Copy, Default)]
456    // pmu_hp_analog_t.2
457    pub struct HpAnalogRegulator1(u32);
458
459    pub u32, drv_b          , set_drv_b          : 31, 8;
460}
461
462#[derive(Clone, Copy, Default)]
463// pmu_hp_analog_t
464pub struct HpAnalog {
465    pub bias: HpAnalogBias,
466    pub regulator0: HpAnalogRegulator0,
467    pub regulator1: HpAnalogRegulator1,
468}
469
470bitfield::bitfield! {
471    #[derive(Clone, Copy, Default)]
472    // pmu_hp_backup_reg_t/active
473    pub struct HpActiveBackup(u32);
474
475    pub u8,   hp_sleep2active_backup_modem_clk_code, set_hp_sleep2active_backup_modem_clk_code: 5, 4;
476    pub u8,   hp_modem2active_backup_modem_clk_code, set_hp_modem2active_backup_modem_clk_code: 7, 6;
477    pub bool, hp_active_retention_mode             , set_hp_active_retention_mode             : 10;
478    pub bool, hp_sleep2active_retention_en         , set_hp_sleep2active_retention_en         : 11;
479    pub bool, hp_modem2active_retention_en         , set_hp_modem2active_retention_en         : 12;
480    pub u8,   hp_sleep2active_backup_clk_sel       , set_hp_sleep2active_backup_clk_sel       : 15, 14;
481    pub u8,   hp_modem2active_backup_clk_sel       , set_hp_modem2active_backup_clk_sel       : 17, 16;
482    pub u8,   hp_sleep2active_backup_mode          , set_hp_sleep2active_backup_mode          : 22, 20;
483    pub u8,   hp_modem2active_backup_mode          , set_hp_modem2active_backup_mode          : 25, 23;
484    pub bool, hp_sleep2active_backup_en            , set_hp_sleep2active_backup_en            : 29;
485    pub bool, hp_modem2active_backup_en            , set_hp_modem2active_backup_en            : 30;
486}
487
488bitfield::bitfield! {
489    #[derive(Clone, Copy, Default)]
490    // pmu_hp_backup_reg_t/modem
491    pub struct HpModemBackup(u32);
492
493    pub u8,   hp_sleep2modem_backup_modem_clk_code , set_hp_sleep2modem_backup_modem_clk_code : 5, 4;
494    pub bool, hp_modem_retention_mode              , set_hp_modem_retention_mode              : 10;
495    pub bool, hp_sleep2modem_retention_en          , set_hp_sleep2modem_retention_en          : 11;
496    pub u8,   hp_sleep2modem_backup_clk_sel        , set_hp_sleep2modem_backup_clk_sel        : 15, 14;
497    pub u8,   hp_sleep2modem_backup_mode           , set_hp_sleep2modem_backup_mode           : 22, 20;
498    pub bool, hp_sleep2modem_backup_en             , set_hp_sleep2modem_backup_en             : 29;
499}
500
501bitfield::bitfield! {
502    #[derive(Clone, Copy, Default)]
503    // pmu_hp_backup_reg_t/sleep
504    pub struct HpSleepBackup(u32);
505
506    pub u8,   hp_modem2sleep_backup_modem_clk_code , set_hp_modem2sleep_backup_modem_clk_code : 7, 6;
507    pub u8,   hp_active2sleep_backup_modem_clk_code, set_hp_active2sleep_backup_modem_clk_code: 9, 8;
508    pub bool, hp_sleep_retention_mode              , set_hp_sleep_retention_mode              : 10;
509    pub bool, hp_modem2sleep_retention_en          , set_hp_modem2sleep_retention_en          : 12;
510    pub bool, hp_active2sleep_retention_en         , set_hp_active2sleep_retention_en         : 13;
511    pub u8,   hp_modem2sleep_backup_clk_sel        , set_hp_modem2sleep_backup_clk_sel        : 17, 16;
512    pub u8,   hp_active2sleep_backup_clk_sel       , set_hp_active2sleep_backup_clk_sel       : 19, 18;
513    pub u8,   hp_modem2sleep_backup_mode           , set_hp_modem2sleep_backup_mode           : 25, 23;
514    pub u8,   hp_active2sleep_backup_mode          , set_hp_active2sleep_backup_mode          : 28, 26;
515    pub bool, hp_modem2sleep_backup_en             , set_hp_modem2sleep_backup_en             : 30;
516    pub bool, hp_active2sleep_backup_en            , set_hp_active2sleep_backup_en            : 31;
517}
518
519bitfield::bitfield! {
520    #[derive(Clone, Copy, Default)]
521    // custom based on `PMU_ICG_FUNC_ENA_*` bitflag constants
522    pub struct HpBackupClk(u32);
523
524    pub bool, gdma        , set_gdma         : 0;
525    pub bool, spi2        , set_spi2         : 1;
526    pub bool, i2s_rx      , set_i2s_rx       : 2;
527    pub bool, uart0       , set_uart0        : 3;
528    pub bool, uart1       , set_uart1        : 4;
529    pub bool, uhci        , set_uhci         : 5;
530    pub bool, usb_device  , set_usb_device   : 6;
531    pub bool, i2s_tx      , set_i2s_tx       : 7;
532    pub bool, regdma      , set_regdma       : 8;
533    pub bool, retention   , set_retention    : 9;
534    pub bool, mem_monitor , set_mem_monitor  : 10;
535    pub bool, sdio_slave  , set_sdio_slave   : 11;
536    pub bool, tsens       , set_tsens        : 12;
537    pub bool, tg1         , set_tg1          : 13;
538    pub bool, tg0         , set_tg0          : 14;
539    pub bool, hpbus       , set_hpbus        : 15;
540    pub bool, soc_etm     , set_soc_etm      : 16;
541    pub bool, hpcore      , set_hpcore       : 17;
542    pub bool, systimer    , set_systimer     : 18;
543    pub bool, sec         , set_sec          : 19;
544    pub bool, saradc      , set_saradc       : 20;
545    pub bool, rmt         , set_rmt          : 21;
546    pub bool, pwm         , set_pwm          : 22;
547    pub bool, pvt_monitor , set_pvt_monitor  : 23;
548    pub bool, parl_tx     , set_parl_tx      : 24;
549    pub bool, parl_rx     , set_parl_rx      : 25;
550    pub bool, mspi        , set_mspi         : 26;
551    pub bool, ledc        , set_ledc         : 27;
552    pub bool, iomux       , set_iomux        : 28;
553    pub bool, i2c         , set_i2c          : 29;
554    pub bool, can1        , set_can1         : 30;
555    pub bool, can0        , set_can0         : 31;
556}
557
558macro_rules! hp_system_init {
559    ($state:ident => $s:ident) => {
560        paste::paste! {
561            unsafe {
562                // Default configuration of hp-system power in active, modem and sleep modes
563                pmu().[<$state _dig_power >]().modify(|_, w| w.bits($s.power.dig_power.0));
564                pmu().[<$state _hp_ck_power >]().modify(|_, w| w.bits($s.power.clk.0));
565                pmu().[<$state _xtal >]().modify(|_, w| w
566                    .[<$state _xpd_xtal >]().bit($s.power.xtal.xpd_xtal())
567                );
568
569                // Default configuration of hp-system clock in active, modem and sleep modes
570                pmu().[<$state _icg_hp_func >]().write(|w| w.bits($s.clock.icg_func));
571                pmu().[<$state _icg_hp_apb >]().write(|w| w.bits($s.clock.icg_apb));
572                pmu().[<$state _icg_modem >]().write(|w| w
573                    .[<$state _dig_icg_modem_code >]().bits($s.clock.icg_modem.code())
574                );
575                pmu().[<$state _sysclk >]().modify(|_, w| w
576                    .[<$state _dig_sys_clk_no_div >]().bit($s.clock.sysclk.dig_sysclk_nodiv())
577                    .[<$state _icg_sys_clock_en >]().bit($s.clock.sysclk.icg_sysclk_en())
578                    .[<$state _sys_clk_slp_sel >]().bit($s.clock.sysclk.sysclk_slp_sel())
579                    .[<$state _icg_slp_sel >]().bit($s.clock.sysclk.icg_slp_sel())
580                    .[<$state _dig_sys_clk_sel >]().bits($s.clock.sysclk.dig_sysclk_sel())
581                );
582
583                // Default configuration of hp-system digital sub-system in active, modem
584                // and sleep modes
585                pmu().[<$state _hp_sys_cntl >]().modify(|_, w| w
586                    .[<$state _uart_wakeup_en >]().bit($s.syscntl.uart_wakeup_en())
587                    .[<$state _lp_pad_hold_all >]().bit($s.syscntl.lp_pad_hold_all())
588                    .[<$state _hp_pad_hold_all >]().bit($s.syscntl.hp_pad_hold_all())
589                    .[<$state _dig_pad_slp_sel >]().bit($s.syscntl.dig_pad_slp_sel())
590                    .[<$state _dig_pause_wdt >]().bit($s.syscntl.dig_pause_wdt())
591                    .[<$state _dig_cpu_stall >]().bit($s.syscntl.dig_cpu_stall())
592                );
593
594                // Default configuration of hp-system analog sub-system in active, modem and
595                // sleep modes
596                pmu().[<$state _bias >]().modify(|_, w| w
597                    .[<$state _xpd_bias >]().bit($s.anlg.bias.xpd_bias())
598                    .[<$state _dbg_atten >]().bits($s.anlg.bias.dbg_atten())
599                    .[<$state _pd_cur >]().bit($s.anlg.bias.pd_cur())
600                    .sleep().bit($s.anlg.bias.bias_sleep())
601                );
602
603                pmu().[<$state _hp_regulator0 >]().modify(|_, w| w
604                    .[<$state _hp_regulator_slp_mem_xpd >]().bit($s.anlg.regulator0.slp_mem_xpd())
605                    .[<$state _hp_regulator_slp_logic_xpd >]().bit($s.anlg.regulator0.slp_logic_xpd())
606                    .[<$state _hp_regulator_xpd >]().bit($s.anlg.regulator0.xpd())
607                    .[<$state _hp_regulator_slp_mem_dbias >]().bits($s.anlg.regulator0.slp_mem_dbias())
608                    .[<$state _hp_regulator_slp_logic_dbias >]().bits($s.anlg.regulator0.slp_logic_dbias())
609                    .[<$state _hp_regulator_dbias >]().bits($s.anlg.regulator0.dbias())
610                );
611
612                pmu().[<$state _hp_regulator1 >]().modify(|_, w| w
613                    .[<$state _hp_regulator_drv_b >]().bits($s.anlg.regulator1.drv_b())
614                );
615
616                // Default configuration of hp-system retention sub-system in active, modem
617                // and sleep modes
618                pmu().[<$state _backup >]().write(|w| w.bits($s.retention));
619                pmu().[<$state _backup_clk >]().write(|w| w.bits($s.backup_clk));
620            }
621        }
622    };
623}
624
625struct HpSystemInit {
626    power: HpSysPower,
627    clock: SystemClockParam,
628    syscntl: HpSysCntlReg,
629    anlg: HpAnalog,
630    retention: u32,
631    backup_clk: u32,
632}
633impl HpSystemInit {
634    fn active() -> Self {
635        // pmu_hp_system_init_default
636
637        let mut power = HpSysPower::default();
638        power.dig_power.set_vdd_spi_pd_en(false);
639        power.dig_power.set_wifi_pd_en(false);
640        power.dig_power.set_cpu_pd_en(false);
641        power.dig_power.set_aon_pd_en(false);
642        power.dig_power.set_top_pd_en(false);
643        power.dig_power.set_mem_pd_en(0);
644        power.dig_power.set_mem_dslp(false);
645
646        power.clk.set_i2c_iso_en(false);
647        power.clk.set_i2c_retention(false);
648        power.clk.set_xpd_bb_i2c(true);
649        power.clk.set_xpd_bbpll_i2c(true);
650        power.clk.set_xpd_bbpll(true);
651
652        power.xtal.set_xpd_xtal(true);
653
654        let mut clock = SystemClockParam {
655            icg_func: 0xffffffff,
656            icg_apb: 0xffffffff,
657            ..SystemClockParam::default()
658        };
659        clock.icg_modem.set_code(ICG_MODEM_CODE_ACTIVE);
660        clock.sysclk.set_dig_sysclk_nodiv(false);
661        clock.sysclk.set_icg_sysclk_en(true);
662        clock.sysclk.set_sysclk_slp_sel(false);
663        clock.sysclk.set_icg_slp_sel(false);
664        clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
665
666        let mut syscntl = HpSysCntlReg::default();
667        syscntl.set_uart_wakeup_en(false);
668        syscntl.set_lp_pad_hold_all(false);
669        syscntl.set_hp_pad_hold_all(false);
670        syscntl.set_dig_pad_slp_sel(false);
671        syscntl.set_dig_pause_wdt(false);
672        syscntl.set_dig_cpu_stall(false);
673
674        // PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT
675        let mut anlg = HpAnalog::default();
676        anlg.bias.set_xpd_bias(true);
677        anlg.bias.set_dbg_atten(0x0);
678        anlg.bias.set_pd_cur(false);
679        anlg.bias.set_bias_sleep(false);
680
681        // TODO: These 4 aren't applied currently?
682        anlg.regulator0.set_lp_dbias_vol(0xD);
683        anlg.regulator0.set_hp_dbias_vol(0x1C);
684        anlg.regulator0.set_dbias_sel(true);
685        anlg.regulator0.set_dbias_init(true);
686
687        anlg.regulator0.set_slp_mem_xpd(false);
688        anlg.regulator0.set_slp_logic_xpd(false);
689        anlg.regulator0.set_xpd(true);
690        anlg.regulator0.set_slp_mem_dbias(0);
691        anlg.regulator0.set_slp_logic_dbias(0);
692        anlg.regulator0.set_dbias(HP_CALI_DBIAS);
693
694        anlg.regulator1.set_drv_b(0);
695
696        let mut retention = HpActiveBackup::default();
697        retention.set_hp_sleep2active_backup_modem_clk_code(2);
698        retention.set_hp_modem2active_backup_modem_clk_code(2);
699        retention.set_hp_active_retention_mode(false);
700        retention.set_hp_sleep2active_retention_en(false);
701        retention.set_hp_modem2active_retention_en(false);
702        retention.set_hp_sleep2active_backup_clk_sel(0);
703        retention.set_hp_modem2active_backup_clk_sel(1);
704        retention.set_hp_sleep2active_backup_mode(hp_retention_regdma_config(0, 0));
705        retention.set_hp_modem2active_backup_mode(hp_retention_regdma_config(0, 2));
706        retention.set_hp_sleep2active_backup_en(false);
707        retention.set_hp_modem2active_backup_en(false);
708
709        let mut backup_clk = HpBackupClk::default();
710        backup_clk.set_regdma(true);
711        backup_clk.set_tg0(true);
712        backup_clk.set_tg1(true);
713        backup_clk.set_hpbus(true);
714        backup_clk.set_mspi(true);
715        backup_clk.set_iomux(true);
716        backup_clk.set_spi2(true);
717        backup_clk.set_uart0(true);
718        backup_clk.set_systimer(true);
719
720        Self {
721            power,
722            clock,
723            syscntl,
724            anlg,
725            retention: retention.0,
726            backup_clk: backup_clk.0,
727        }
728    }
729
730    fn modem() -> Self {
731        let mut power = HpSysPower::default();
732        power.dig_power.set_vdd_spi_pd_en(false);
733        power.dig_power.set_wifi_pd_en(false);
734        power.dig_power.set_cpu_pd_en(true);
735        power.dig_power.set_aon_pd_en(false);
736        power.dig_power.set_top_pd_en(false);
737        power.dig_power.set_mem_pd_en(0);
738        power.dig_power.set_mem_dslp(false);
739
740        power.clk.set_xpd_bb_i2c(true);
741        power.clk.set_xpd_bbpll_i2c(true);
742        power.clk.set_xpd_bbpll(true);
743        power.clk.set_i2c_iso_en(false);
744        power.clk.set_i2c_retention(false);
745
746        power.xtal.set_xpd_xtal(true);
747
748        let mut clock = SystemClockParam {
749            icg_func: 0,
750            icg_apb: 0,
751            ..SystemClockParam::default()
752        };
753        clock.icg_modem.set_code(ICG_MODEM_CODE_MODEM);
754        clock.sysclk.set_dig_sysclk_nodiv(false);
755        clock.sysclk.set_icg_sysclk_en(true);
756        clock.sysclk.set_sysclk_slp_sel(true);
757        clock.sysclk.set_icg_slp_sel(true);
758        clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_PLL);
759
760        let mut syscntl = HpSysCntlReg::default();
761        syscntl.set_uart_wakeup_en(true);
762        syscntl.set_lp_pad_hold_all(false);
763        syscntl.set_hp_pad_hold_all(false);
764        syscntl.set_dig_pad_slp_sel(false);
765        syscntl.set_dig_pause_wdt(true);
766        syscntl.set_dig_cpu_stall(true);
767
768        let mut anlg = HpAnalog::default();
769        anlg.bias.set_xpd_bias(false);
770        anlg.bias.set_dbg_atten(0x0);
771        anlg.bias.set_pd_cur(false);
772        anlg.bias.set_bias_sleep(false);
773
774        anlg.regulator0.set_slp_mem_xpd(false);
775        anlg.regulator0.set_slp_logic_xpd(false);
776        anlg.regulator0.set_xpd(true);
777        anlg.regulator0.set_slp_mem_dbias(0);
778        anlg.regulator0.set_slp_logic_dbias(0);
779        anlg.regulator0.set_dbias(HP_CALI_DBIAS);
780
781        anlg.regulator1.set_drv_b(0);
782
783        let mut retention = HpModemBackup::default();
784        retention.set_hp_sleep2modem_backup_modem_clk_code(1);
785        retention.set_hp_modem_retention_mode(false);
786        retention.set_hp_sleep2modem_retention_en(false);
787        retention.set_hp_sleep2modem_backup_clk_sel(0);
788        retention.set_hp_sleep2modem_backup_mode(hp_retention_regdma_config(0, 1));
789        retention.set_hp_sleep2modem_backup_en(false);
790
791        let mut backup_clk = HpBackupClk::default();
792        backup_clk.set_regdma(true);
793        backup_clk.set_tg0(true);
794        backup_clk.set_tg1(true);
795        backup_clk.set_hpbus(true);
796        backup_clk.set_mspi(true);
797        backup_clk.set_iomux(true);
798        backup_clk.set_spi2(true);
799        backup_clk.set_uart0(true);
800        backup_clk.set_systimer(true);
801
802        Self {
803            power,
804            clock,
805            syscntl,
806            anlg,
807            retention: retention.0,
808            backup_clk: backup_clk.0,
809        }
810    }
811
812    fn sleep() -> Self {
813        let mut power = HpSysPower::default();
814        power.dig_power.set_vdd_spi_pd_en(true);
815        power.dig_power.set_mem_dslp(false);
816        power.dig_power.set_mem_pd_en(0);
817        power.dig_power.set_wifi_pd_en(true);
818        power.dig_power.set_cpu_pd_en(false);
819        power.dig_power.set_aon_pd_en(false);
820        power.dig_power.set_top_pd_en(false);
821
822        power.clk.set_i2c_iso_en(true);
823        power.clk.set_i2c_retention(true);
824        power.clk.set_xpd_bb_i2c(true);
825        power.clk.set_xpd_bbpll_i2c(false);
826        power.clk.set_xpd_bbpll(false);
827
828        power.xtal.set_xpd_xtal(false);
829
830        let mut clock = SystemClockParam {
831            icg_func: 0,
832            icg_apb: 0,
833            ..SystemClockParam::default()
834        };
835        clock.icg_modem.set_code(ICG_MODEM_CODE_SLEEP);
836        clock.sysclk.set_dig_sysclk_nodiv(false);
837        clock.sysclk.set_icg_sysclk_en(false);
838        clock.sysclk.set_sysclk_slp_sel(true);
839        clock.sysclk.set_icg_slp_sel(true);
840        clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
841
842        let mut anlg = HpAnalog::default();
843        anlg.bias.set_xpd_bias(false);
844        anlg.bias.set_dbg_atten(0x0);
845        anlg.bias.set_pd_cur(false);
846        anlg.bias.set_bias_sleep(false);
847
848        anlg.regulator0.set_slp_mem_xpd(false);
849        anlg.regulator0.set_slp_logic_xpd(false);
850        anlg.regulator0.set_xpd(true);
851        anlg.regulator0.set_slp_mem_dbias(0);
852        anlg.regulator0.set_slp_logic_dbias(0);
853        anlg.regulator0.set_dbias(1);
854
855        anlg.regulator1.set_drv_b(0);
856
857        let mut retention = HpSleepBackup::default();
858        retention.set_hp_modem2sleep_backup_modem_clk_code(0);
859        retention.set_hp_active2sleep_backup_modem_clk_code(2);
860        retention.set_hp_sleep_retention_mode(false);
861        retention.set_hp_modem2sleep_retention_en(false);
862        retention.set_hp_active2sleep_retention_en(false);
863        retention.set_hp_modem2sleep_backup_clk_sel(0);
864        retention.set_hp_active2sleep_backup_clk_sel(0);
865        retention.set_hp_modem2sleep_backup_mode(hp_retention_regdma_config(1, 1));
866        retention.set_hp_active2sleep_backup_mode(hp_retention_regdma_config(1, 0));
867        retention.set_hp_modem2sleep_backup_en(false);
868        retention.set_hp_active2sleep_backup_en(false);
869
870        let mut backup_clk = HpBackupClk::default();
871        backup_clk.set_regdma(true);
872        backup_clk.set_tg0(true);
873        backup_clk.set_tg1(true);
874        backup_clk.set_hpbus(true);
875        backup_clk.set_mspi(true);
876        backup_clk.set_iomux(true);
877        backup_clk.set_spi2(true);
878        backup_clk.set_uart0(true);
879        backup_clk.set_systimer(true);
880
881        let mut syscntl = HpSysCntlReg::default();
882        syscntl.set_uart_wakeup_en(true);
883        syscntl.set_lp_pad_hold_all(false);
884        syscntl.set_hp_pad_hold_all(false);
885        syscntl.set_dig_pad_slp_sel(true);
886        syscntl.set_dig_pause_wdt(true);
887        syscntl.set_dig_cpu_stall(true);
888
889        Self {
890            power,
891            clock,
892            syscntl,
893            anlg,
894            retention: retention.0,
895            backup_clk: backup_clk.0,
896        }
897    }
898
899    fn init_default() {
900        let active = Self::active();
901        let modem = Self::modem();
902        let sleep = Self::sleep();
903
904        hp_system_init!(hp_active => active);
905        hp_system_init!(hp_modem => modem);
906        hp_system_init!(hp_sleep => sleep);
907
908        unsafe {
909            // Some PMU initial parameter configuration
910            pmu()
911                .imm_modem_icg()
912                .write(|w| w.update_dig_icg_modem_en().bit(true));
913            pmu()
914                .imm_sleep_sysclk()
915                .write(|w| w.update_dig_icg_switch().bit(true));
916
917            const PMU_SLEEP_PROTECT_HP_LP_SLEEP: u8 = 2;
918            pmu()
919                .slp_wakeup_cntl3()
920                .modify(|_, w| w.sleep_prt_sel().bits(PMU_SLEEP_PROTECT_HP_LP_SLEEP));
921        }
922    }
923}
924
925bitfield::bitfield! {
926    #[derive(Clone, Copy, Default)]
927    // pmu_lp_power_t.0
928    pub struct LpDigPower(u32);
929
930    pub u32, mem_dslp  , set_mem_dslp  : 30;
931    pub u32, peri_pd_en, set_peri_pd_en: 31;
932
933}
934
935bitfield::bitfield! {
936    #[derive(Clone, Copy, Default)]
937    // pmu_lp_power_t.1
938    pub struct LpClkPower(u32);
939
940    pub u32, xpd_xtal32k, set_xpd_xtal32k: 28;
941    pub u32, xpd_rc32k  , set_xpd_rc32k  : 29;
942    pub u32, xpd_fosc   , set_xpd_fosc   : 30;
943    pub u32, pd_osc     , set_pd_osc     : 31;
944}
945
946bitfield::bitfield! {
947    #[derive(Clone, Copy, Default)]
948    // pmu_lp_power_t.2
949    pub struct LpXtalPower(u32);
950
951    pub bool, xpd_xtal     , set_xpd_xtal     : 31;
952}
953
954#[derive(Clone, Copy, Default)]
955// pmu_sleep_power_config_t.1
956pub struct LpSysPower {
957    // This is a best-guess assignment of the variants in the union `pmu_lp_power_t` union
958    // In esp-idf, all three fields are `pmu_lp_power_t`
959    pub dig_power: LpDigPower,
960    pub clk_power: LpClkPower,
961    pub xtal: LpXtalPower,
962}
963
964bitfield::bitfield! {
965    #[derive(Clone, Copy, Default)]
966    // pmu_lp_analog_t.0
967    pub struct LpAnalogBias(u32);
968
969    pub bool, xpd_bias  , set_xpd_bias  : 25;
970    pub u8,   dbg_atten , set_dbg_atten : 29, 26;
971    pub bool, pd_cur    , set_pd_cur    : 30;
972    pub bool, bias_sleep, set_bias_sleep: 31;
973}
974
975bitfield::bitfield! {
976    #[derive(Clone, Copy, Default)]
977    // pmu_lp_analog_t.1
978    pub struct LpAnalogRegulator0(u32);
979
980    pub bool, slp_xpd  , set_slp_xpd  : 21;
981    pub bool, xpd      , set_xpd      : 22;
982    pub u8,   slp_dbias, set_slp_dbias: 26, 23;
983    pub u8,   dbias    , set_dbias    : 31, 27;
984}
985
986bitfield::bitfield! {
987    #[derive(Clone, Copy, Default)]
988    // pmu_lp_analog_t.2
989    pub struct LpAnalogRegulator1(u32);
990
991    pub u8, drv_b    , set_drv_b    : 31, 28;
992}
993
994#[derive(Clone, Copy, Default)]
995// pmu_lp_analog_t
996pub struct LpAnalog {
997    pub bias: LpAnalogBias,
998    pub regulator0: LpAnalogRegulator0,
999    pub regulator1: LpAnalogRegulator1,
1000}
1001
1002macro_rules! lp_system_init {
1003    ($state:ident => $s:ident) => {
1004        paste::paste! {
1005            unsafe {
1006                // Default configuration of lp-system power in active and sleep modes
1007                pmu().[< $state _dig_power >]().modify(|_, w| w.bits($s.dig_power.0));
1008                pmu().[< $state _ck_power >]().modify(|_, w| w.bits($s.clk_power.0));
1009
1010                // Default configuration of lp-system analog sub-system in active and sleep modes
1011                pmu().[< $state _regulator0 >]().modify(|_, w| w
1012                    .[< $state _regulator_slp_xpd >]().bit($s.analog_regulator0.slp_xpd())
1013                    .[< $state _regulator_xpd >]().bit($s.analog_regulator0.xpd())
1014                    .[< $state _regulator_slp_dbias >]().bits($s.analog_regulator0.slp_dbias())
1015                    .[< $state _regulator_dbias >]().bits($s.analog_regulator0.dbias())
1016                );
1017
1018                pmu().[< $state _regulator1 >]().modify(|_, w| w
1019                    .[< $state _regulator_drv_b >]().bits($s.analog_regulator1.drv_b())
1020                );
1021            }
1022        }
1023    };
1024}
1025
1026struct LpSystemInit {
1027    dig_power: LpDigPower,
1028    clk_power: LpClkPower,
1029    xtal: LpXtalPower,
1030    bias: LpAnalogBias,
1031    analog_regulator0: LpAnalogRegulator0,
1032    analog_regulator1: LpAnalogRegulator1,
1033}
1034impl LpSystemInit {
1035    fn active() -> Self {
1036        let mut dig_power = LpDigPower::default();
1037        dig_power.set_peri_pd_en(false);
1038        dig_power.set_mem_dslp(false);
1039
1040        let mut clk_power = LpClkPower::default();
1041        clk_power.set_xpd_xtal32k(true);
1042        clk_power.set_xpd_rc32k(true);
1043        clk_power.set_xpd_fosc(true);
1044
1045        let mut analog_regulator0 = LpAnalogRegulator0::default();
1046        analog_regulator0.set_slp_xpd(false);
1047        analog_regulator0.set_xpd(true);
1048        analog_regulator0.set_slp_dbias(0);
1049        analog_regulator0.set_dbias(26);
1050
1051        let mut analog_regulator1 = LpAnalogRegulator1::default();
1052        analog_regulator1.set_drv_b(0);
1053
1054        Self {
1055            dig_power,
1056            clk_power,
1057            xtal: LpXtalPower::default(),
1058            bias: LpAnalogBias::default(),
1059            analog_regulator0,
1060            analog_regulator1,
1061        }
1062    }
1063
1064    fn sleep() -> Self {
1065        let mut dig_power = LpDigPower::default();
1066        dig_power.set_mem_dslp(true);
1067        dig_power.set_peri_pd_en(false);
1068
1069        let mut clk_power = LpClkPower::default();
1070        clk_power.set_xpd_xtal32k(false);
1071        clk_power.set_xpd_rc32k(false);
1072        clk_power.set_xpd_fosc(false);
1073        clk_power.set_pd_osc(false);
1074
1075        let mut xtal = LpXtalPower::default();
1076        xtal.set_xpd_xtal(false);
1077
1078        let mut analog_bias = LpAnalogBias::default();
1079        analog_bias.set_xpd_bias(false);
1080        analog_bias.set_dbg_atten(0);
1081        analog_bias.set_pd_cur(true);
1082        analog_bias.set_bias_sleep(true);
1083
1084        let mut analog_regulator0 = LpAnalogRegulator0::default();
1085        analog_regulator0.set_slp_xpd(false);
1086        analog_regulator0.set_xpd(true);
1087        analog_regulator0.set_slp_dbias(0);
1088        analog_regulator0.set_dbias(12);
1089
1090        let mut analog_regulator1 = LpAnalogRegulator1::default();
1091        analog_regulator1.set_drv_b(0);
1092
1093        Self {
1094            dig_power,
1095            clk_power,
1096            xtal,
1097            bias: analog_bias,
1098            analog_regulator0,
1099            analog_regulator1,
1100        }
1101    }
1102
1103    fn init_default() {
1104        let active = Self::active();
1105        let sleep = Self::sleep();
1106
1107        lp_system_init!(hp_sleep_lp => active);
1108        lp_system_init!(lp_sleep_lp => sleep);
1109
1110        unsafe {
1111            pmu()
1112                .lp_sleep_xtal()
1113                .modify(|_, w| w.lp_sleep_xpd_xtal().bit(sleep.xtal.xpd_xtal()));
1114
1115            pmu().lp_sleep_bias().modify(|_, w| {
1116                w.lp_sleep_xpd_bias() // pmu_ll_lp_set_bias_xpd
1117                    .bit(sleep.bias.xpd_bias())
1118                    .lp_sleep_dbg_atten() // pmu_ll_lp_set_bias_dbg_atten
1119                    .bits(sleep.bias.dbg_atten())
1120                    .lp_sleep_pd_cur() // pmu_ll_lp_set_bias_pd_cur
1121                    .bit(sleep.bias.pd_cur())
1122                    .sleep() // pmu_ll_lp_set_bias_sleep
1123                    .bit(sleep.bias.bias_sleep())
1124            });
1125        }
1126    }
1127}
1128
1129pub(crate) fn init() {
1130    // pmu_init()
1131    let pmu = unsafe { pmu() };
1132
1133    pmu.rf_pwc()
1134        .modify(|_, w| w.perif_i2c_rstb().set_bit().xpd_perif_i2c().set_bit());
1135
1136    regi2c_write_mask(
1137        I2C_DIG_REG,
1138        I2C_DIG_REG_HOSTID,
1139        I2C_DIG_REG_ENIF_RTC_DREG,
1140        I2C_DIG_REG_ENIF_RTC_DREG_MSB,
1141        I2C_DIG_REG_ENIF_RTC_DREG_LSB,
1142        1,
1143    );
1144    regi2c_write_mask(
1145        I2C_DIG_REG,
1146        I2C_DIG_REG_HOSTID,
1147        I2C_DIG_REG_ENIF_DIG_DREG,
1148        I2C_DIG_REG_ENIF_DIG_DREG_MSB,
1149        I2C_DIG_REG_ENIF_DIG_DREG_LSB,
1150        1,
1151    );
1152
1153    regi2c_write_mask(
1154        I2C_DIG_REG,
1155        I2C_DIG_REG_HOSTID,
1156        I2C_DIG_REG_XPD_RTC_REG,
1157        I2C_DIG_REG_XPD_RTC_REG_MSB,
1158        I2C_DIG_REG_XPD_RTC_REG_LSB,
1159        0,
1160    );
1161    regi2c_write_mask(
1162        I2C_DIG_REG,
1163        I2C_DIG_REG_HOSTID,
1164        I2C_DIG_REG_XPD_DIG_REG,
1165        I2C_DIG_REG_XPD_DIG_REG_MSB,
1166        I2C_DIG_REG_XPD_DIG_REG_LSB,
1167        0,
1168    );
1169
1170    HpSystemInit::init_default();
1171    LpSystemInit::init_default();
1172
1173    pmu_power_domain_force_default();
1174
1175    // esp_perip_clk_init()
1176    modem_clock_domain_power_state_icg_map_init();
1177
1178    //  During system initialization, the low-power clock source of the modem
1179    //  (WiFi, BLE or Coexist) follows the configuration of the slow clock source
1180    //  of the system. If the WiFi, BLE or Coexist module needs a higher
1181    //  precision sleep clock (for example, the BLE needs to use the main XTAL
1182    //  oscillator (40 MHz) to provide the clock during the sleep process in some
1183    //  scenarios), the module needs to switch to the required clock source by
1184    //  itself.
1185    // TODO - WIFI-5233
1186    let modem_lpclk_src = ModemClockLpclkSource::from(RtcSlowClockSource::current());
1187
1188    modem_clock_select_lp_clock_source_wifi(modem_lpclk_src, 0);
1189}
1190
1191pub(crate) fn configure_clock() {
1192    assert!(matches!(RtcClock::xtal_freq(), XtalClock::_40M));
1193
1194    RtcClock::set_fast_freq(RtcFastClock::RtcFastClockRcFast);
1195
1196    let cal_val = loop {
1197        RtcClock::set_slow_freq(RtcSlowClock::RtcSlowClockRcSlow);
1198
1199        let res = RtcClock::calibrate(RtcCalSel::RtcCalRtcMux, 1024);
1200        if res != 0 {
1201            break res;
1202        }
1203    };
1204
1205    unsafe {
1206        lp_aon().store1().modify(|_, w| w.bits(cal_val));
1207    }
1208
1209    modem_clk_domain_active_state_icg_map_preinit();
1210}
1211
1212fn modem_clk_domain_active_state_icg_map_preinit() {
1213    unsafe {
1214        // Configure modem ICG code in PMU_ACTIVE state
1215        pmu()
1216            .hp_active_icg_modem()
1217            .modify(|_, w| w.hp_active_dig_icg_modem_code().bits(ICG_MODEM_CODE_ACTIVE));
1218
1219        // Disable clock gating for MODEM_APB, I2C_MST and LP_APB clock domains in
1220        // PMU_ACTIVE state
1221        modem_syscon()
1222            .clk_conf_power_st()
1223            .modify(|_, w| w.clk_modem_apb_st_map().bits(1 << ICG_MODEM_CODE_ACTIVE));
1224        modem_lpcon().clk_conf_power_st().modify(|_, w| {
1225            w.clk_i2c_mst_st_map()
1226                .bits(1 << ICG_MODEM_CODE_ACTIVE)
1227                .clk_lp_apb_st_map()
1228                .bits(1 << ICG_MODEM_CODE_ACTIVE)
1229        });
1230
1231        // Software trigger force update modem ICG code and ICG switch
1232        pmu()
1233            .imm_modem_icg()
1234            .write(|w| w.update_dig_icg_modem_en().set_bit());
1235        pmu()
1236            .imm_sleep_sysclk()
1237            .write(|w| w.update_dig_icg_switch().set_bit());
1238
1239        // The following is part of rtc_clk_init
1240
1241        lp_clkrst()
1242            .fosc_cntl()
1243            .modify(|_, w| w.fosc_dfreq().bits(100));
1244        regi2c_write_mask(
1245            I2C_DIG_REG,
1246            I2C_DIG_REG_HOSTID,
1247            I2C_DIG_REG_SCK_DCAP,
1248            I2C_DIG_REG_SCK_DCAP_MSB,
1249            I2C_DIG_REG_SCK_DCAP_LSB,
1250            128,
1251        );
1252        lp_clkrst()
1253            .rc32k_cntl()
1254            .modify(|_, w| w.rc32k_dfreq().bits(700));
1255
1256        regi2c_write_mask(
1257            I2C_DIG_REG,
1258            I2C_DIG_REG_HOSTID,
1259            I2C_DIG_REG_ENIF_RTC_DREG,
1260            I2C_DIG_REG_ENIF_RTC_DREG_MSB,
1261            I2C_DIG_REG_ENIF_RTC_DREG_LSB,
1262            1,
1263        );
1264        regi2c_write_mask(
1265            I2C_DIG_REG,
1266            I2C_DIG_REG_HOSTID,
1267            I2C_DIG_REG_ENIF_DIG_DREG,
1268            I2C_DIG_REG_ENIF_DIG_DREG_MSB,
1269            I2C_DIG_REG_ENIF_DIG_DREG_LSB,
1270            1,
1271        );
1272
1273        pmu()
1274            .hp_active_hp_regulator0()
1275            .modify(|_, w| w.hp_active_hp_regulator_dbias().bits(HP_CALI_DBIAS));
1276        pmu()
1277            .hp_sleep_lp_regulator0()
1278            .modify(|_, w| w.hp_sleep_lp_regulator_dbias().bits(LP_CALI_DBIAS));
1279
1280        // clk_ll_rc_fast_tick_conf
1281        pcr()
1282            .ctrl_tick_conf()
1283            .modify(|_, w| w.fosc_tick_num().bits(255));
1284    }
1285}
1286
1287// Terminology:
1288//
1289// CPU Reset:    Reset CPU core only, once reset done, CPU will execute from
1290//               reset vector
1291// Core Reset:   Reset the whole digital system except RTC sub-system
1292// System Reset: Reset the whole digital system, including RTC sub-system
1293// Chip Reset:   Reset the whole chip, including the analog part
1294
1295/// SOC Reset Reason.
1296#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
1297pub enum SocResetReason {
1298    /// Power on reset
1299    ///
1300    /// In ESP-IDF this value (0x01) can *also* be `ChipBrownOut` or
1301    /// `ChipSuperWdt`, however that is not really compatible with Rust-style
1302    /// enums.
1303    ChipPowerOn   = 0x01,
1304    /// Software resets the digital core by RTC_CNTL_SW_SYS_RST
1305    CoreSw        = 0x03,
1306    /// Deep sleep reset the digital core
1307    CoreDeepSleep = 0x05,
1308    /// SDIO Core reset
1309    CoreSDIO      = 0x06,
1310    /// Main watch dog 0 resets digital core
1311    CoreMwdt0     = 0x07,
1312    /// Main watch dog 1 resets digital core
1313    CoreMwdt1     = 0x08,
1314    /// RTC watch dog resets digital core
1315    CoreRtcWdt    = 0x09,
1316    /// Main watch dog 0 resets CPU 0
1317    Cpu0Mwdt0     = 0x0B,
1318    /// Software resets CPU 0 by RTC_CNTL_SW_PROCPU_RST
1319    Cpu0Sw        = 0x0C,
1320    /// RTC watch dog resets CPU 0
1321    Cpu0RtcWdt    = 0x0D,
1322    /// VDD voltage is not stable and resets the digital core
1323    SysBrownOut   = 0x0F,
1324    /// RTC watch dog resets digital core and rtc module
1325    SysRtcWdt     = 0x10,
1326    /// Main watch dog 1 resets CPU 0
1327    Cpu0Mwdt1     = 0x11,
1328    /// Super watch dog resets the digital core and rtc module
1329    SysSuperWdt   = 0x12,
1330    /// eFuse CRC error resets the digital core
1331    CoreEfuseCrc  = 0x14,
1332    /// USB UART resets the digital core
1333    CoreUsbUart   = 0x15,
1334    /// USB JTAG resets the digital core
1335    CoreUsbJtag   = 0x16,
1336    /// JTAG resets CPU
1337    Cpu0JtagCpu   = 0x18,
1338}
1339
1340#[allow(unused)]
1341#[derive(Debug, Clone, Copy)]
1342/// RTC SLOW_CLK frequency values
1343pub(crate) enum RtcFastClock {
1344    /// Select RC_FAST_CLK as RTC_FAST_CLK source
1345    RtcFastClockRcFast = 0,
1346    /// Select XTAL_D2_CLK as RTC_FAST_CLK source
1347    RtcFastClockXtalD2 = 1,
1348}
1349
1350impl Clock for RtcFastClock {
1351    fn frequency(&self) -> Rate {
1352        match self {
1353            RtcFastClock::RtcFastClockXtalD2 => {
1354                // TODO: Is the value correct?
1355                Rate::from_hz(40_000_000 / 2)
1356            }
1357            RtcFastClock::RtcFastClockRcFast => Rate::from_hz(17_500_000),
1358        }
1359    }
1360}
1361
1362#[allow(clippy::enum_variant_names)]
1363#[derive(Debug, Clone, Copy, PartialEq)]
1364/// RTC SLOW_CLK frequency values
1365pub enum RtcSlowClock {
1366    /// Select RC_SLOW_CLK as RTC_SLOW_CLK source
1367    RtcSlowClockRcSlow  = 0,
1368    /// Select XTAL32K_CLK as RTC_SLOW_CLK source
1369    RtcSlowClock32kXtal = 1,
1370    /// Select RC32K_CLK as RTC_SLOW_CLK source
1371    RtcSlowClock32kRc   = 2,
1372    /// Select OSC_SLOW_CLK (external slow clock) as RTC_SLOW_CLK source
1373    RtcSlowOscSlow      = 3,
1374}
1375
1376impl Clock for RtcSlowClock {
1377    fn frequency(&self) -> Rate {
1378        match self {
1379            RtcSlowClock::RtcSlowClockRcSlow => Rate::from_hz(136_000),
1380            RtcSlowClock::RtcSlowClock32kXtal => Rate::from_hz(32_768),
1381            RtcSlowClock::RtcSlowClock32kRc => Rate::from_hz(32_768),
1382            RtcSlowClock::RtcSlowOscSlow => Rate::from_hz(32_768),
1383        }
1384    }
1385}
1386
1387#[derive(Debug, Clone, Copy, PartialEq)]
1388/// Clock source to be calibrated using rtc_clk_cal function
1389pub(crate) enum RtcCalSel {
1390    /// Currently selected RTC SLOW_CLK
1391    RtcCalRtcMux     = -1,
1392    /// Internal 150kHz RC oscillator
1393    RtcCalRcSlow     = 0,
1394    /// External 32kHz XTAL, as one type of 32k clock
1395    RtcCal32kXtal    = 1,
1396    /// Internal 32kHz RC oscillator, as one type of 32k clock
1397    RtcCal32kRc      = 2,
1398    /// External slow clock signal input by lp_pad_gpio0, as one type of 32k
1399    /// clock
1400    RtcCal32kOscSlow = 3,
1401    /// Internal 20MHz RC oscillator
1402    RtcCalRcFast,
1403}
1404
1405#[derive(Clone)]
1406pub(crate) enum RtcCaliClkSel {
1407    CaliClkRcSlow = 0,
1408    CaliClkRcFast = 1,
1409    CaliClk32k    = 2,
1410}
1411
1412/// RTC Watchdog Timer driver
1413impl RtcClock {
1414    // rtc_clk_xtal_freq_get
1415    pub(crate) fn xtal_freq_mhz() -> u32 {
1416        Self::read_xtal_freq_mhz().unwrap_or(40)
1417    }
1418
1419    /// Get main XTAL frequency
1420    /// This is the value stored in RTC register RTC_XTAL_FREQ_REG by the
1421    /// bootloader, as passed to rtc_clk_init function.
1422    pub fn xtal_freq() -> XtalClock {
1423        match Self::xtal_freq_mhz() {
1424            40 => XtalClock::_40M,
1425            other => XtalClock::Other(other),
1426        }
1427    }
1428
1429    /// Get the RTC_SLOW_CLK source
1430    pub fn slow_freq() -> RtcSlowClock {
1431        let lp_clrst = unsafe { lp_clkrst() };
1432
1433        let slow_freq = lp_clrst.lp_clk_conf().read().slow_clk_sel().bits();
1434        match slow_freq {
1435            0 => RtcSlowClock::RtcSlowClockRcSlow,
1436            1 => RtcSlowClock::RtcSlowClock32kXtal,
1437            2 => RtcSlowClock::RtcSlowClock32kRc,
1438            3 => RtcSlowClock::RtcSlowOscSlow,
1439            _ => unreachable!(),
1440        }
1441    }
1442
1443    fn set_slow_freq(slow_freq: RtcSlowClock) {
1444        unsafe {
1445            lp_clkrst()
1446                .lp_clk_conf()
1447                .modify(|_, w| w.slow_clk_sel().bits(slow_freq as u8));
1448
1449            lp_clkrst().clk_to_hp().modify(|_, w| {
1450                w.icg_hp_xtal32k()
1451                    .bit(matches!(slow_freq, RtcSlowClock::RtcSlowClock32kXtal))
1452                    .icg_hp_xtal32k()
1453                    .bit(matches!(slow_freq, RtcSlowClock::RtcSlowClock32kXtal))
1454            });
1455        }
1456    }
1457
1458    // TODO: IDF-5781 Some of esp32c6 SOC_RTC_FAST_CLK_SRC_XTAL_D2 rtc_fast clock
1459    // has timing issue Force to use SOC_RTC_FAST_CLK_SRC_RC_FAST since 2nd
1460    // stage bootloader https://github.com/espressif/esp-idf/blob/master/components/bootloader_support/src/bootloader_clock_init.c#L65-L67
1461    fn set_fast_freq(fast_freq: RtcFastClock) {
1462        unsafe {
1463            lp_clkrst().lp_clk_conf().modify(|_, w| {
1464                w.fast_clk_sel().bit(match fast_freq {
1465                    RtcFastClock::RtcFastClockRcFast => false,
1466                    RtcFastClock::RtcFastClockXtalD2 => true,
1467                })
1468            });
1469        }
1470
1471        crate::rom::ets_delay_us(3);
1472    }
1473
1474    /// Calibration of RTC_SLOW_CLK is performed using a special feature of
1475    /// TIMG0. This feature counts the number of XTAL clock cycles within a
1476    /// given number of RTC_SLOW_CLK cycles.
1477    pub(crate) fn calibrate_internal(mut cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 {
1478        const SOC_CLK_RC_FAST_FREQ_APPROX: u32 = 17_500_000;
1479        const SOC_CLK_RC_SLOW_FREQ_APPROX: u32 = 136_000;
1480        const SOC_CLK_XTAL32K_FREQ_APPROX: u32 = 32768;
1481
1482        if cal_clk == RtcCalSel::RtcCalRtcMux {
1483            cal_clk = match cal_clk {
1484                RtcCalSel::RtcCalRtcMux => match RtcClock::slow_freq() {
1485                    RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal,
1486                    RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc,
1487                    _ => cal_clk,
1488                },
1489                RtcCalSel::RtcCal32kOscSlow => RtcCalSel::RtcCalRtcMux,
1490                _ => cal_clk,
1491            };
1492        }
1493
1494        let lp_clkrst = unsafe { lp_clkrst() };
1495        let pcr = unsafe { pcr() };
1496        let pmu = unsafe { pmu() };
1497
1498        let clk_src = RtcClock::slow_freq();
1499
1500        if cal_clk == RtcCalSel::RtcCalRtcMux {
1501            cal_clk = match clk_src {
1502                RtcSlowClock::RtcSlowClockRcSlow => RtcCalSel::RtcCalRcSlow,
1503                RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal,
1504                RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc,
1505                RtcSlowClock::RtcSlowOscSlow => RtcCalSel::RtcCal32kOscSlow,
1506            };
1507        }
1508
1509        let cali_clk_sel;
1510        if cal_clk == RtcCalSel::RtcCalRtcMux {
1511            cal_clk = match clk_src {
1512                RtcSlowClock::RtcSlowClockRcSlow => RtcCalSel::RtcCalRcSlow,
1513                RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal,
1514                RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc,
1515                RtcSlowClock::RtcSlowOscSlow => RtcCalSel::RtcCalRcSlow,
1516            }
1517        }
1518
1519        if cal_clk == RtcCalSel::RtcCalRcFast {
1520            cali_clk_sel = RtcCaliClkSel::CaliClkRcFast;
1521        } else if cal_clk == RtcCalSel::RtcCalRcSlow {
1522            cali_clk_sel = RtcCaliClkSel::CaliClkRcSlow;
1523        } else {
1524            cali_clk_sel = RtcCaliClkSel::CaliClk32k;
1525            match cal_clk {
1526                RtcCalSel::RtcCalRtcMux | RtcCalSel::RtcCalRcSlow | RtcCalSel::RtcCalRcFast => {}
1527                RtcCalSel::RtcCal32kRc => {
1528                    pcr.ctrl_32k_conf()
1529                        .modify(|_, w| unsafe { w.clk_32k_sel().bits(0) });
1530                }
1531                RtcCalSel::RtcCal32kXtal => {
1532                    pcr.ctrl_32k_conf()
1533                        .modify(|_, w| unsafe { w.clk_32k_sel().bits(1) });
1534                }
1535                RtcCalSel::RtcCal32kOscSlow => {
1536                    pcr.ctrl_32k_conf()
1537                        .modify(|_, w| unsafe { w.clk_32k_sel().bits(2) });
1538                }
1539            }
1540        }
1541
1542        // Enable requested clock (150k is always on)
1543        // Some delay is required before the time is stable
1544        // Only enable if originaly was disabled
1545        // If clock is already on, do nothing
1546
1547        let dig_32k_xtal_enabled = lp_clkrst.clk_to_hp().read().icg_hp_xtal32k().bit_is_set();
1548
1549        if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled {
1550            lp_clkrst
1551                .clk_to_hp()
1552                .modify(|_, w| w.icg_hp_xtal32k().set_bit());
1553        }
1554
1555        // TODO: very hacky
1556        // in ESP-IDF these are not called in this function but the fields are set
1557        lp_clkrst
1558            .clk_to_hp()
1559            .modify(|_, w| w.icg_hp_xtal32k().set_bit());
1560        pmu.hp_sleep_lp_ck_power()
1561            .modify(|_, w| w.hp_sleep_xpd_xtal32k().set_bit());
1562
1563        pmu.hp_sleep_lp_ck_power()
1564            .modify(|_, w| w.hp_sleep_xpd_rc32k().set_bit());
1565
1566        let rc_fast_enabled = pmu
1567            .hp_sleep_lp_ck_power()
1568            .read()
1569            .hp_sleep_xpd_fosc_clk()
1570            .bit_is_set();
1571        let dig_rc_fast_enabled = lp_clkrst.clk_to_hp().read().icg_hp_fosc().bit_is_set();
1572
1573        if cal_clk == RtcCalSel::RtcCalRcFast {
1574            if !rc_fast_enabled {
1575                pmu.hp_sleep_lp_ck_power()
1576                    .modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit());
1577                crate::rom::ets_delay_us(50);
1578            }
1579
1580            if !dig_rc_fast_enabled {
1581                lp_clkrst
1582                    .clk_to_hp()
1583                    .modify(|_, w| w.icg_hp_fosc().set_bit());
1584                crate::rom::ets_delay_us(5);
1585            }
1586        }
1587
1588        let rc32k_enabled = pmu
1589            .hp_sleep_lp_ck_power()
1590            .read()
1591            .hp_sleep_xpd_rc32k()
1592            .bit_is_set();
1593        let dig_rc32k_enabled = lp_clkrst.clk_to_hp().read().icg_hp_osc32k().bit_is_set();
1594
1595        if cal_clk == RtcCalSel::RtcCal32kRc {
1596            if !rc32k_enabled {
1597                pmu.hp_sleep_lp_ck_power()
1598                    .modify(|_, w| w.hp_sleep_xpd_rc32k().set_bit());
1599                crate::rom::ets_delay_us(300);
1600            }
1601
1602            if !dig_rc32k_enabled {
1603                lp_clkrst
1604                    .clk_to_hp()
1605                    .modify(|_, w| w.icg_hp_osc32k().set_bit());
1606            }
1607        }
1608
1609        // Check if there is already running calibration process
1610        // TODO: &mut TIMG0 for calibration
1611        let timg0 = TIMG0::regs();
1612
1613        if timg0
1614            .rtccalicfg()
1615            .read()
1616            .rtc_cali_start_cycling()
1617            .bit_is_set()
1618        {
1619            timg0
1620                .rtccalicfg2()
1621                .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(1) });
1622
1623            // Set small timeout threshold to accelerate the generation of timeot
1624            // Internal circuit will be reset when timeout occurs and will not affect the
1625            // next calibration
1626            while !timg0.rtccalicfg().read().rtc_cali_rdy().bit_is_set()
1627                && !timg0.rtccalicfg2().read().rtc_cali_timeout().bit_is_set()
1628            {}
1629        }
1630
1631        // Prepare calibration
1632        timg0
1633            .rtccalicfg()
1634            .modify(|_, w| unsafe { w.rtc_cali_clk_sel().bits(cali_clk_sel.clone() as u8) });
1635        timg0
1636            .rtccalicfg()
1637            .modify(|_, w| w.rtc_cali_start_cycling().clear_bit());
1638        timg0
1639            .rtccalicfg()
1640            .modify(|_, w| unsafe { w.rtc_cali_max().bits(slowclk_cycles as u16) });
1641
1642        let expected_freq = match cali_clk_sel {
1643            RtcCaliClkSel::CaliClk32k => {
1644                timg0.rtccalicfg2().modify(|_, w| unsafe {
1645                    w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)
1646                });
1647                SOC_CLK_XTAL32K_FREQ_APPROX
1648            }
1649            RtcCaliClkSel::CaliClkRcFast => {
1650                timg0
1651                    .rtccalicfg2()
1652                    .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(0x01FFFFFF) });
1653                SOC_CLK_RC_FAST_FREQ_APPROX
1654            }
1655            _ => {
1656                timg0.rtccalicfg2().modify(|_, w| unsafe {
1657                    w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)
1658                });
1659                SOC_CLK_RC_SLOW_FREQ_APPROX
1660            }
1661        };
1662
1663        let us_time_estimate = (Rate::from_mhz(slowclk_cycles) / expected_freq).as_hz();
1664
1665        // Start calibration
1666        timg0
1667            .rtccalicfg()
1668            .modify(|_, w| w.rtc_cali_start().clear_bit());
1669        timg0
1670            .rtccalicfg()
1671            .modify(|_, w| w.rtc_cali_start().set_bit());
1672
1673        // Wait for calibration to finish up to another us_time_estimate
1674        crate::rom::ets_delay_us(us_time_estimate);
1675
1676        let cal_val = loop {
1677            if timg0.rtccalicfg().read().rtc_cali_rdy().bit_is_set() {
1678                // The Fosc CLK of calibration circuit is divided by 32 for ECO1.
1679                // So we need to multiply the frequency of the Fosc for ECO1 and above chips by
1680                // 32 times. And ensure that this modification will not affect
1681                // ECO0.
1682                // https://github.com/espressif/esp-idf/commit/e3148369f32fdc6de62c35a67f7adb6f4faef4e3
1683                if Efuse::chip_revision() > 0 {
1684                    if cal_clk == RtcCalSel::RtcCalRcFast {
1685                        break timg0.rtccalicfg1().read().rtc_cali_value().bits() >> 5;
1686                    }
1687                    break timg0.rtccalicfg1().read().rtc_cali_value().bits();
1688                } else {
1689                    break timg0.rtccalicfg1().read().rtc_cali_value().bits();
1690                }
1691            }
1692
1693            if timg0.rtccalicfg2().read().rtc_cali_timeout().bit_is_set() {
1694                // Timed out waiting for calibration
1695                break 0;
1696            }
1697        };
1698
1699        timg0
1700            .rtccalicfg()
1701            .modify(|_, w| w.rtc_cali_start().clear_bit());
1702
1703        if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled {
1704            lp_clkrst
1705                .clk_to_hp()
1706                .modify(|_, w| w.icg_hp_xtal32k().clear_bit());
1707        }
1708
1709        if cal_clk == RtcCalSel::RtcCalRcFast {
1710            if rc_fast_enabled {
1711                pmu.hp_sleep_lp_ck_power()
1712                    .modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit());
1713                crate::rom::ets_delay_us(50);
1714            }
1715
1716            if dig_rc_fast_enabled {
1717                lp_clkrst
1718                    .clk_to_hp()
1719                    .modify(|_, w| w.icg_hp_fosc().set_bit());
1720                crate::rom::ets_delay_us(5);
1721            }
1722        }
1723
1724        if cal_clk == RtcCalSel::RtcCal32kRc {
1725            if rc32k_enabled {
1726                pmu.hp_sleep_lp_ck_power()
1727                    .modify(|_, w| w.hp_sleep_xpd_rc32k().set_bit());
1728                crate::rom::ets_delay_us(300);
1729            }
1730            if dig_rc32k_enabled {
1731                lp_clkrst
1732                    .clk_to_hp()
1733                    .modify(|_, w| w.icg_hp_osc32k().set_bit());
1734            }
1735        }
1736
1737        cal_val
1738    }
1739
1740    /// Measure RTC slow clock's period, based on main XTAL frequency
1741    ///
1742    /// This function will time out and return 0 if the time for the given
1743    /// number of cycles to be counted exceeds the expected time twice. This
1744    /// may happen if 32k XTAL is being calibrated, but the oscillator has
1745    /// not started up (due to incorrect loading capacitance, board design
1746    /// issue, or lack of 32 XTAL on board).
1747    fn calibrate(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 {
1748        let xtal_freq = RtcClock::xtal_freq();
1749
1750        let mut slowclk_cycles = slowclk_cycles;
1751
1752        // The Fosc CLK of calibration circuit is divided by 32 for ECO1.
1753        // So we need to divide the calibrate cycles of the FOSC for ECO1 and above
1754        // chips by 32 to avoid excessive calibration time.
1755        if Efuse::chip_revision() > 0 && cal_clk == RtcCalSel::RtcCalRcFast {
1756            slowclk_cycles >>= 5;
1757        }
1758
1759        let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64;
1760        let divider = xtal_freq.mhz() as u64 * slowclk_cycles as u64;
1761        let period_64 = ((xtal_cycles << RtcClock::CAL_FRACT) + divider / 2u64 - 1u64) / divider;
1762
1763        (period_64 & u32::MAX as u64) as u32
1764    }
1765
1766    /// Calculate the necessary RTC_SLOW_CLK cycles to complete 1 millisecond.
1767    pub(crate) fn cycles_to_1ms() -> u16 {
1768        let period_13q19 = RtcClock::calibrate(
1769            match RtcClock::slow_freq() {
1770                RtcSlowClock::RtcSlowClockRcSlow => RtcCalSel::RtcCalRtcMux,
1771                RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal,
1772                RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc,
1773                RtcSlowClock::RtcSlowOscSlow => RtcCalSel::RtcCal32kOscSlow,
1774                // RtcSlowClock::RtcCalRcFast => RtcCalSel::RtcCalRcFast,
1775            },
1776            1024,
1777        );
1778
1779        // 100_000_000 is used to get rid of `float` calculations
1780        let period = (100_000_000 * period_13q19 as u64) / (1 << RtcClock::CAL_FRACT);
1781
1782        (100_000_000 * 1000 / period) as u16
1783    }
1784
1785    pub(crate) fn estimate_xtal_frequency() -> u32 {
1786        let timg0 = TIMG0::regs();
1787        while timg0.rtccalicfg().read().rtc_cali_rdy().bit_is_clear() {}
1788
1789        timg0.rtccalicfg().modify(|_, w| unsafe {
1790            w.rtc_cali_clk_sel()
1791                .bits(0) // RTC_SLOW_CLK
1792                .rtc_cali_max()
1793                .bits(100)
1794                .rtc_cali_start_cycling()
1795                .clear_bit()
1796                .rtc_cali_start()
1797                .set_bit()
1798        });
1799        timg0
1800            .rtccalicfg()
1801            .modify(|_, w| w.rtc_cali_start().set_bit());
1802
1803        while timg0.rtccalicfg().read().rtc_cali_rdy().bit_is_clear() {}
1804
1805        (timg0.rtccalicfg1().read().rtc_cali_value().bits()
1806            * (RtcSlowClock::RtcSlowClockRcSlow.frequency().as_hz() / 100))
1807            / 1_000_000
1808    }
1809}
1810
1811pub(crate) fn rtc_clk_cpu_freq_set_xtal() {
1812    // rtc_clk_cpu_set_to_default_config
1813    let freq = RtcClock::xtal_freq_mhz();
1814
1815    esp32c6_rtc_update_to_xtal_raw(freq, 1);
1816
1817    // TODO: don't turn off the bbpll if some consumers depend on bbpll
1818    // if !s_bbpll_digi_consumers_ref_count {
1819    rtc_clk_bbpll_disable();
1820    //}
1821}
1822
1823#[derive(Clone, Copy, PartialEq, Debug)]
1824#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1825pub(crate) struct UnsupportedClockSource;
1826
1827#[derive(Clone, Copy, PartialEq, Debug)]
1828#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1829pub(crate) enum CpuClockSource {
1830    Xtal,
1831    Pll,
1832    RcFast,
1833}
1834
1835impl CpuClockSource {
1836    pub(crate) fn current() -> Result<Self, UnsupportedClockSource> {
1837        let source = match unsafe { pcr().sysclk_conf().read().soc_clk_sel().bits() } {
1838            0 => CpuClockSource::Xtal,
1839            1 => CpuClockSource::Pll,
1840            2 => CpuClockSource::RcFast,
1841            _ => return Err(UnsupportedClockSource),
1842        };
1843
1844        Ok(source)
1845    }
1846
1847    pub(crate) fn select(self) {
1848        unsafe {
1849            pcr().sysclk_conf().modify(|_, w| {
1850                w.soc_clk_sel().bits(match self {
1851                    CpuClockSource::Xtal => 0,
1852                    CpuClockSource::Pll => 1,
1853                    CpuClockSource::RcFast => 2,
1854                })
1855            });
1856        }
1857    }
1858}
1859
1860#[derive(Clone, Copy)]
1861pub(crate) struct SavedClockConfig {
1862    /// The clock from which CPU clock is derived
1863    pub source: CpuClockSource,
1864
1865    /// Source clock frequency
1866    pub source_freq_mhz: u32,
1867
1868    /// Divider, freq_mhz = SOC_ROOT_CLK freq_mhz / div
1869    pub div: u8,
1870}
1871
1872impl SavedClockConfig {
1873    pub(crate) fn save() -> Self {
1874        let source = unwrap!(CpuClockSource::current());
1875
1876        let div;
1877        let source_freq_mhz;
1878        match source {
1879            CpuClockSource::Xtal => {
1880                div = esp32c6_cpu_get_ls_divider();
1881                source_freq_mhz = RtcClock::xtal_freq_mhz();
1882            }
1883            CpuClockSource::Pll => {
1884                div = esp32c6_cpu_get_hs_divider();
1885                source_freq_mhz = esp32c6_bbpll_get_freq_mhz();
1886            }
1887            CpuClockSource::RcFast => {
1888                div = esp32c6_cpu_get_ls_divider();
1889                source_freq_mhz = 20;
1890            }
1891        }
1892
1893        SavedClockConfig {
1894            source,
1895            source_freq_mhz,
1896            div,
1897        }
1898    }
1899
1900    fn freq_mhz(&self) -> u32 {
1901        self.source_freq_mhz / self.div as u32
1902    }
1903
1904    // rtc_clk_cpu_freq_set_config
1905    pub(crate) fn restore(self) {
1906        let old_source = unwrap!(CpuClockSource::current());
1907
1908        match self.source {
1909            CpuClockSource::Xtal => esp32c6_rtc_update_to_xtal_raw(self.freq_mhz(), self.div),
1910            CpuClockSource::RcFast => esp32c6_rtc_update_to_8m(),
1911            CpuClockSource::Pll => {
1912                if old_source != CpuClockSource::Pll {
1913                    rtc_clk_bbpll_enable();
1914                    esp32c6_rtc_bbpll_configure_raw(
1915                        RtcClock::xtal_freq_mhz(),
1916                        self.source_freq_mhz,
1917                    );
1918                }
1919                esp32c6_rtc_freq_to_pll_mhz_raw(self.freq_mhz());
1920            }
1921        }
1922
1923        if old_source == CpuClockSource::Pll && self.source != CpuClockSource::Pll
1924        // && !s_bbpll_digi_consumers_ref_count
1925        {
1926            // We don't turn off the bbpll if some consumers depend on bbpll
1927            rtc_clk_bbpll_disable();
1928        }
1929    }
1930}
1931
1932fn rtc_clk_bbpll_enable() {
1933    unsafe {
1934        pmu().imm_hp_ck_power().modify(|_, w| {
1935            w.tie_high_xpd_bb_i2c()
1936                .set_bit()
1937                .tie_high_xpd_bbpll()
1938                .set_bit()
1939                .tie_high_xpd_bbpll_i2c()
1940                .set_bit()
1941        });
1942        pmu()
1943            .imm_hp_ck_power()
1944            .modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
1945    }
1946}
1947
1948fn rtc_clk_bbpll_disable() {
1949    unsafe {
1950        pmu()
1951            .imm_hp_ck_power()
1952            .modify(|_, w| w.tie_low_global_bbpll_icg().set_bit());
1953
1954        pmu().imm_hp_ck_power().modify(|_, w| {
1955            w.tie_low_xpd_bbpll()
1956                .set_bit()
1957                .tie_low_xpd_bbpll_i2c()
1958                .set_bit()
1959        });
1960    }
1961}