Skip to main content

esp_hal/rtc_cntl/rtc/
esp32c5.rs

1use strum::FromRepr;
2
3use crate::{
4    peripherals::{LP_CLKRST, MODEM_LPCON, MODEM_SYSCON, PCR, PMU},
5    soc::{
6        clocks::{ClockConfig, LpSlowClkConfig},
7        regi2c,
8        xtal32k,
9    },
10};
11
12// Trims the RTC bandgap using eFuse calibration data.
13//
14// See `esp_ocode_calib_init` in
15// <https://github.com/espressif/esp-idf/blob/v6.1/components/esp_hw_support/port/esp32c5/ocode_init.c>
16fn calibrate_ocode() {
17    super::calibrate_ocode(|| {
18        let chip = crate::efuse::chip_revision().combined();
19        let (major, minor) = crate::efuse::block_version();
20        let blk = u16::from(major) * 100 + u16::from(minor);
21
22        // v0.1 chips and v1.0+ chips got the ocode in different block versions.
23        ((chip == 1 && blk >= 1) || (chip >= 100 && blk >= 2))
24            .then(|| crate::efuse::read_field_le::<u8>(crate::efuse::OCODE))
25    });
26}
27
28fn pmu_power_domain_force_default() {
29    // for bypass reserved power domain
30
31    // PMU_HP_PD_TOP
32    PMU::regs().power_pd_top_cntl().modify(|_, w| {
33        w.force_top_reset().bit(false); // pmu_ll_hp_set_power_force_reset
34        w.force_top_iso().bit(false); // pmu_ll_hp_set_power_force_isolate
35        w.force_top_pu().bit(false); // pmu_ll_hp_set_power_force_power_up
36        w.force_top_no_reset().bit(false); // pmu_ll_hp_set_power_force_no_reset
37        w.force_top_no_iso().bit(false); // pmu_ll_hp_set_power_force_no_isolate
38        w.force_top_pd().bit(false) // pmu_ll_hp_set_power_force_power_down
39    });
40
41    // PMU_HP_PD_HP_AON
42    PMU::regs().power_pd_hpaon_cntl().modify(|_, w| {
43        w.force_hp_aon_reset().bit(false); // pmu_ll_hp_set_power_force_reset
44        w.force_hp_aon_iso().bit(false); // pmu_ll_hp_set_power_force_isolate
45        w.force_hp_aon_pu().bit(false); // pmu_ll_hp_set_power_force_power_up
46        w.force_hp_aon_no_reset().bit(false); // pmu_ll_hp_set_power_force_no_reset
47        w.force_hp_aon_no_iso().bit(false); // pmu_ll_hp_set_power_force_no_isolate
48        w.force_hp_aon_pd().bit(false) // pmu_ll_hp_set_power_force_power_down
49    });
50
51    // PMU_HP_PD_CPU
52    PMU::regs().power_pd_hpcpu_cntl().modify(|_, w| {
53        w.force_hp_cpu_reset().bit(false); // pmu_ll_hp_set_power_force_reset
54        w.force_hp_cpu_iso().bit(false); // pmu_ll_hp_set_power_force_isolate
55        w.force_hp_cpu_pu().bit(false); // pmu_ll_hp_set_power_force_power_up
56        w.force_hp_cpu_no_reset().bit(false); // pmu_ll_hp_set_power_force_no_reset
57        w.force_hp_cpu_no_iso().bit(false); // pmu_ll_hp_set_power_force_no_isolate
58        w.force_hp_cpu_pd().bit(false) // pmu_ll_hp_set_power_force_power_down
59    });
60
61    // PMU_HP_PD_WIFI
62    PMU::regs().power_pd_hpwifi_cntl().modify(|_, w| {
63        w.force_hp_wifi_reset().bit(false); // pmu_ll_hp_set_power_force_reset
64        w.force_hp_wifi_iso().bit(false); // pmu_ll_hp_set_power_force_isolate
65        w.force_hp_wifi_pu().bit(false); // pmu_ll_hp_set_power_force_power_up
66        w.force_hp_wifi_no_reset().bit(false); // pmu_ll_hp_set_power_force_no_reset
67        w.force_hp_wifi_no_iso().bit(false); // pmu_ll_hp_set_power_force_no_isolate
68        w.force_hp_wifi_pd().bit(false) // pmu_ll_hp_set_power_force_power_down
69    });
70
71    // Isolate all memory banks while sleeping, avoid memory leakage current
72
73    PMU::regs().power_pd_mem_cntl().modify(|_, w| unsafe {
74        w.force_hp_mem_no_iso().bits(0) // pmu_ll_hp_set_memory_no_isolate
75    });
76
77    PMU::regs().power_pd_lpperi_cntl().modify(|_, w| {
78        w.force_lp_peri_reset().bit(false); // pmu_ll_lp_set_power_force_reset
79        w.force_lp_peri_iso().bit(false); // pmu_ll_lp_set_power_force_isolate
80        w.force_lp_peri_pu().bit(false); // pmu_ll_lp_set_power_force_power_up
81        w.force_lp_peri_no_reset().bit(false); // pmu_ll_lp_set_power_force_no_reset
82        w.force_lp_peri_no_iso().bit(false); // pmu_ll_lp_set_power_force_no_isolate
83        w.force_lp_peri_pd().bit(false) // pmu_ll_lp_set_power_force_power_down
84    });
85}
86
87fn modem_clock_domain_power_state_icg_map_init() {
88    // C6 has SOC_PM_SUPPORT_PMU_MODEM_STATE defined
89
90    // const ICG_NOGATING_SLEEP: u8 = 1 << 0; // unused
91    const ICG_NOGATING_MODEM: u8 = 1 << 1;
92    const ICG_NOGATING_ACTIVE: u8 = 1 << 2;
93
94    const ICG_NOGATING_ACTIVE_MODEM: u8 = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM;
95
96    // the ICG code's bit 0, 1 and 2 indicates the ICG state
97    // of pmu SLEEP, MODEM and ACTIVE mode respectively
98    MODEM_SYSCON::regs()
99        .clk_conf_power_st()
100        .modify(|_, w| unsafe {
101            w.clk_modem_apb_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); // modem_syscon_ll_set_modem_apb_icg_bitmap
102            w.clk_modem_peri_st_map().bits(ICG_NOGATING_ACTIVE); // modem_syscon_ll_set_modem_periph_icg_bitmap
103            w.clk_wifi_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); // modem_syscon_ll_set_wifi_icg_bitmap
104            w.clk_bt_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); // modem_syscon_ll_set_bt_icg_bitmap
105            w.clk_fe_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); // modem_syscon_ll_set_fe_icg_bitmap
106            w.clk_zb_st_map().bits(ICG_NOGATING_ACTIVE_MODEM) // modem_syscon_ll_set_ieee802154_icg_bitmap
107        });
108
109    MODEM_LPCON::regs()
110        .clk_conf_power_st()
111        .modify(|_, w| unsafe {
112            w.clk_lp_apb_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); // modem_lpcon_ll_set_lp_apb_icg_bitmap
113            w.clk_i2c_mst_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); // modem_lpcon_ll_set_i2c_master_icg_bitmap
114            w.clk_coex_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); // modem_lpcon_ll_set_coex_icg_bitmap
115            w.clk_wifipwr_st_map().bits(ICG_NOGATING_ACTIVE_MODEM) // modem_lpcon_ll_set_wifipwr_icg_bitmap
116        });
117}
118
119#[allow(unused)]
120enum ModemClockLpclkSource {
121    RcSlow = 0,
122    RcFast,
123    MainXtal,
124    RC32K,
125    XTAL32K,
126    EXT32K,
127}
128
129impl From<LpSlowClkConfig> for ModemClockLpclkSource {
130    fn from(src: LpSlowClkConfig) -> Self {
131        match src {
132            LpSlowClkConfig::RcSlow => Self::RcSlow,
133            #[cfg(use_xtal32k)]
134            LpSlowClkConfig::Xtal32k => Self::XTAL32K,
135            LpSlowClkConfig::OscSlow => Self::EXT32K,
136        }
137    }
138}
139
140fn modem_clock_hal_deselect_all_wifi_lpclk_source() {
141    MODEM_LPCON::regs().wifi_lp_clk_conf().modify(|_, w| {
142        w.clk_wifipwr_lp_sel_osc_slow().clear_bit();
143        w.clk_wifipwr_lp_sel_osc_fast().clear_bit();
144        w.clk_wifipwr_lp_sel_xtal32k().clear_bit();
145        w.clk_wifipwr_lp_sel_xtal().clear_bit()
146    });
147}
148
149fn modem_clock_hal_select_wifi_lpclk_source(src: ModemClockLpclkSource) {
150    MODEM_LPCON::regs()
151        .wifi_lp_clk_conf()
152        .modify(|_, w| match src {
153            ModemClockLpclkSource::RcSlow => w.clk_wifipwr_lp_sel_osc_slow().set_bit(),
154            ModemClockLpclkSource::RcFast => w.clk_wifipwr_lp_sel_osc_fast().set_bit(),
155            ModemClockLpclkSource::MainXtal => w.clk_wifipwr_lp_sel_xtal().set_bit(),
156
157            ModemClockLpclkSource::RC32K
158            | ModemClockLpclkSource::XTAL32K
159            | ModemClockLpclkSource::EXT32K => w.clk_wifipwr_lp_sel_xtal32k().set_bit(),
160        });
161
162    MODEM_LPCON::regs()
163        .modem_32k_clk_conf()
164        .modify(|_, w| unsafe {
165            match src {
166                ModemClockLpclkSource::RcSlow
167                | ModemClockLpclkSource::RcFast
168                | ModemClockLpclkSource::MainXtal => w,
169
170                ModemClockLpclkSource::RC32K => w.clk_modem_32k_sel().bits(1),
171                ModemClockLpclkSource::XTAL32K => w.clk_modem_32k_sel().bits(0),
172                ModemClockLpclkSource::EXT32K => w.clk_modem_32k_sel().bits(2),
173            }
174        });
175}
176
177fn modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider: u16) {
178    MODEM_LPCON::regs()
179        .wifi_lp_clk_conf()
180        .modify(|_, w| unsafe { w.clk_wifipwr_lp_div_num().bits(divider) });
181}
182
183fn modem_clock_hal_enable_wifipwr_clock(enable: bool) {
184    MODEM_LPCON::regs()
185        .clk_conf()
186        .modify(|_, w| w.clk_wifipwr_en().bit(enable));
187}
188
189// PHY, BT, IEEE802154 are not used by the init code so they are unimplemented
190fn modem_clock_select_lp_clock_source_wifi(src: ModemClockLpclkSource, divider: u16) {
191    modem_clock_hal_deselect_all_wifi_lpclk_source();
192    modem_clock_hal_select_wifi_lpclk_source(src);
193    modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider);
194    modem_clock_hal_enable_wifipwr_clock(true);
195}
196
197const fn hp_retention_regdma_config(dir: u8, entry: u8) -> u8 {
198    // ESP32-C5 widens the backup mode field: `PMU_HP_RETENTION_REGDMA_CONFIG`
199    // becomes `(((dir) << 4) | (entry & 0xf)) & 0x1f`.
200    (((dir) << 4) | (entry & 0xf)) & 0x1f
201}
202
203const HP_CALI_DBIAS: u8 = 28;
204const LP_CALI_DBIAS: u8 = 28;
205
206const ICG_MODEM_CODE_SLEEP: u8 = 0;
207const ICG_MODEM_CODE_MODEM: u8 = 1;
208const ICG_MODEM_CODE_ACTIVE: u8 = 2;
209
210// ESP32-C5 `dig_sysclk_sel`/`backup_clk_sel` use `PMU_CLK_SRC_VAL`:
211// XTAL = 0, RC_FAST = 1, PLL_F160M = 2, PLL_F240M = 3.
212const HP_SYSCLK_XTAL: u8 = 0;
213const HP_SYSCLK_PLL: u8 = 2;
214
215bitfield::bitfield! {
216    #[derive(Clone, Copy, Default)]
217    // pmu_hp_power_t.0
218    pub struct HpDigPower(u32);
219
220    pub bool, vdd_spi_pd_en, set_vdd_spi_pd_en: 21;
221    pub bool, mem_dslp     , set_mem_dslp     : 22;
222    pub u8,   mem_pd_en    , set_mem_pd_en    : 26, 23;
223    pub bool, wifi_pd_en   , set_wifi_pd_en   : 27;
224    pub bool, cpu_pd_en    , set_cpu_pd_en    : 29;
225    pub bool, aon_pd_en    , set_aon_pd_en    : 30;
226    pub bool, top_pd_en    , set_top_pd_en    : 31;
227}
228
229bitfield::bitfield! {
230    #[derive(Clone, Copy, Default)]
231    // pmu_hp_power_t.1
232    pub struct HpClkPower(u32);
233
234    pub bool, i2c_iso_en   , set_i2c_iso_en   : 26;
235    pub bool, i2c_retention, set_i2c_retention: 27;
236    pub bool, xpd_bb_i2c   , set_xpd_bb_i2c   : 28;
237    pub bool, xpd_bbpll_i2c, set_xpd_bbpll_i2c: 29;
238    pub bool, xpd_bbpll    , set_xpd_bbpll    : 30;
239}
240
241bitfield::bitfield! {
242    #[derive(Clone, Copy, Default)]
243    // pmu_hp_power_t.2
244    pub struct HpXtalPower(u32);
245
246    pub bool, xpd_xtal     , set_xpd_xtal     : 31;
247}
248
249#[derive(Clone, Copy, Default)]
250// pmu_sleep_power_config_t.0
251pub struct HpSysPower {
252    // This is a best-guess assignment of the variants in the union `pmu_hp_power_t` union
253    // In esp-idf, all three fields are `pmu_hp_power_t`
254    pub dig_power: HpDigPower,
255    pub clk: HpClkPower,
256    pub xtal: HpXtalPower,
257}
258
259bitfield::bitfield! {
260    #[derive(Clone, Copy, Default)]
261    // pmu_hp_sys_cntl_reg_t
262    pub struct HpSysCntlReg(u32);
263
264    pub bool, uart_wakeup_en , set_uart_wakeup_en : 24;
265    pub bool, lp_pad_hold_all, set_lp_pad_hold_all: 25;
266    pub bool, hp_pad_hold_all, set_hp_pad_hold_all: 26;
267    pub bool, dig_pad_slp_sel, set_dig_pad_slp_sel: 27;
268    pub bool, dig_pause_wdt  , set_dig_pause_wdt  : 28;
269    pub bool, dig_cpu_stall  , set_dig_cpu_stall  : 29;
270}
271
272bitfield::bitfield! {
273    #[derive(Clone, Copy, Default)]
274    // pmu_hp_icg_modem_reg_t
275    pub struct HpIcgModem(u32);
276
277    pub u8, code, set_code: 31, 30;
278}
279
280bitfield::bitfield! {
281    #[derive(Clone, Copy, Default)]
282    // pmu_hp_sysclk_reg_t
283    pub struct HpSysclk(u32);
284
285    pub bool, dig_sysclk_nodiv , set_dig_sysclk_nodiv : 26;
286    pub bool, icg_sysclk_en    , set_icg_sysclk_en    : 27;
287    pub bool, sysclk_slp_sel   , set_sysclk_slp_sel   : 28;
288    pub bool, icg_slp_sel      , set_icg_slp_sel      : 29;
289    pub u8,   dig_sysclk_sel   , set_dig_sysclk_sel   : 31, 30;
290}
291
292// pmu_hp_system_clock_param_t
293#[derive(Clone, Copy, Default)]
294struct SystemClockParam {
295    icg_func: u32,
296    icg_apb: u32,
297    icg_modem: HpIcgModem,
298    sysclk: HpSysclk,
299}
300
301bitfield::bitfield! {
302    #[derive(Clone, Copy, Default)]
303    // pmu_hp_analog_t.0
304    pub struct HpAnalogBias(u32);
305
306    pub bool, xpd_bias  , set_xpd_bias  : 25;
307    pub u8,   dbg_atten , set_dbg_atten : 29, 26;
308    pub bool, pd_cur    , set_pd_cur    : 30;
309    pub bool, bias_sleep, set_bias_sleep: 31;
310}
311
312bitfield::bitfield! {
313    #[derive(Clone, Copy, Default)]
314    // pmu_hp_analog_t.1
315    pub struct HpAnalogRegulator0(u32);
316
317    // Only HP_ACTIVE modem under hp system is valid
318    pub u8,   lp_dbias_vol   , set_lp_dbias_vol   : 8, 4;
319    // Only HP_ACTIVE modem under hp system is valid
320    pub u8,   hp_dbias_vol   , set_hp_dbias_vol   : 13, 9;
321    // Only HP_ACTIVE modem under hp system is valid
322    pub bool, dbias_sel      , set_dbias_sel      : 14;
323    // Only HP_ACTIVE modem under hp system is valid
324    pub bool, dbias_init     , set_dbias_init     : 15;
325
326    pub bool, slp_mem_xpd    , set_slp_mem_xpd    : 16;
327    pub bool, slp_logic_xpd  , set_slp_logic_xpd  : 17;
328    pub bool, xpd            , set_xpd            : 18;
329    pub u8,   slp_mem_dbias  , set_slp_mem_dbias  : 22, 19;
330    pub u8,   slp_logic_dbias, set_slp_logic_dbias: 26, 23;
331    pub u8,   dbias          , set_dbias          : 31, 27;
332}
333
334bitfield::bitfield! {
335    #[derive(Clone, Copy, Default)]
336    // pmu_hp_analog_t.2
337    pub struct HpAnalogRegulator1(u32);
338
339    pub u32, drv_b          , set_drv_b          : 31, 8;
340}
341
342#[derive(Clone, Copy, Default)]
343// pmu_hp_analog_t
344pub struct HpAnalog {
345    pub bias: HpAnalogBias,
346    pub regulator0: HpAnalogRegulator0,
347    pub regulator1: HpAnalogRegulator1,
348}
349
350bitfield::bitfield! {
351    #[derive(Clone, Copy, Default)]
352    // pmu_hp_backup_reg_t/active
353    pub struct HpActiveBackup(u32);
354
355    pub u8,   hp_sleep2active_backup_modem_clk_code, set_hp_sleep2active_backup_modem_clk_code: 5, 4;
356    pub u8,   hp_modem2active_backup_modem_clk_code, set_hp_modem2active_backup_modem_clk_code: 7, 6;
357    pub bool, hp_active_retention_mode             , set_hp_active_retention_mode             : 10;
358    pub bool, hp_sleep2active_retention_en         , set_hp_sleep2active_retention_en         : 11;
359    pub bool, hp_modem2active_retention_en         , set_hp_modem2active_retention_en         : 12;
360    pub u8,   hp_sleep2active_backup_clk_sel       , set_hp_sleep2active_backup_clk_sel       : 15, 14;
361    pub u8,   hp_modem2active_backup_clk_sel       , set_hp_modem2active_backup_clk_sel       : 17, 16;
362    pub u8,   hp_sleep2active_backup_mode          , set_hp_sleep2active_backup_mode          : 22, 18;
363    pub u8,   hp_modem2active_backup_mode          , set_hp_modem2active_backup_mode          : 27, 23;
364    pub bool, hp_sleep2active_backup_en            , set_hp_sleep2active_backup_en            : 29;
365    pub bool, hp_modem2active_backup_en            , set_hp_modem2active_backup_en            : 30;
366}
367
368bitfield::bitfield! {
369    #[derive(Clone, Copy, Default)]
370    // pmu_hp_backup_reg_t/modem
371    pub struct HpModemBackup(u32);
372
373    pub u8,   hp_sleep2modem_backup_modem_clk_code , set_hp_sleep2modem_backup_modem_clk_code : 5, 4;
374    pub bool, hp_modem_retention_mode              , set_hp_modem_retention_mode              : 10;
375    pub bool, hp_sleep2modem_retention_en          , set_hp_sleep2modem_retention_en          : 11;
376    pub u8,   hp_sleep2modem_backup_clk_sel        , set_hp_sleep2modem_backup_clk_sel        : 15, 14;
377    pub u8,   hp_sleep2modem_backup_mode           , set_hp_sleep2modem_backup_mode           : 24, 20;
378    pub bool, hp_sleep2modem_backup_en             , set_hp_sleep2modem_backup_en             : 29;
379}
380
381bitfield::bitfield! {
382    #[derive(Clone, Copy, Default)]
383    // pmu_hp_backup_reg_t/sleep
384    pub struct HpSleepBackup(u32);
385
386    pub u8,   hp_modem2sleep_backup_modem_clk_code , set_hp_modem2sleep_backup_modem_clk_code : 7, 6;
387    pub u8,   hp_active2sleep_backup_modem_clk_code, set_hp_active2sleep_backup_modem_clk_code: 9, 8;
388    pub bool, hp_sleep_retention_mode              , set_hp_sleep_retention_mode              : 10;
389    pub bool, hp_modem2sleep_retention_en          , set_hp_modem2sleep_retention_en          : 12;
390    pub bool, hp_active2sleep_retention_en         , set_hp_active2sleep_retention_en         : 13;
391    pub u8,   hp_modem2sleep_backup_clk_sel        , set_hp_modem2sleep_backup_clk_sel        : 17, 16;
392    pub u8,   hp_active2sleep_backup_clk_sel       , set_hp_active2sleep_backup_clk_sel       : 19, 18;
393    pub u8,   hp_modem2sleep_backup_mode           , set_hp_modem2sleep_backup_mode           : 24, 20;
394    pub u8,   hp_active2sleep_backup_mode          , set_hp_active2sleep_backup_mode          : 29, 25;
395    pub bool, hp_modem2sleep_backup_en             , set_hp_modem2sleep_backup_en             : 30;
396    pub bool, hp_active2sleep_backup_en            , set_hp_active2sleep_backup_en            : 31;
397}
398
399bitfield::bitfield! {
400    #[derive(Clone, Copy, Default)]
401    // custom based on `PMU_ICG_FUNC_ENA_*` bitflag constants
402    pub struct HpBackupClk(u32);
403
404    pub bool, gdma        , set_gdma         : 0;
405    pub bool, spi2        , set_spi2         : 1;
406    pub bool, i2s_rx      , set_i2s_rx       : 2;
407    pub bool, uart0       , set_uart0        : 3;
408    pub bool, uart1       , set_uart1        : 4;
409    pub bool, uhci        , set_uhci         : 5;
410    pub bool, usb_device  , set_usb_device   : 6;
411    pub bool, i2s_tx      , set_i2s_tx       : 7;
412    pub bool, regdma      , set_regdma       : 8;
413    pub bool, retention   , set_retention    : 9;
414    pub bool, mem_monitor , set_mem_monitor  : 10;
415    pub bool, sdio_slave  , set_sdio_slave   : 11;
416    pub bool, tsens       , set_tsens        : 12;
417    pub bool, tg1         , set_tg1          : 13;
418    pub bool, tg0         , set_tg0          : 14;
419    pub bool, hpbus       , set_hpbus        : 15;
420    pub bool, soc_etm     , set_soc_etm      : 16;
421    pub bool, hpcore      , set_hpcore       : 17;
422    pub bool, systimer    , set_systimer     : 18;
423    pub bool, sec         , set_sec          : 19;
424    pub bool, saradc      , set_saradc       : 20;
425    pub bool, rmt         , set_rmt          : 21;
426    pub bool, pwm         , set_pwm          : 22;
427    pub bool, pvt_monitor , set_pvt_monitor  : 23;
428    pub bool, parl_tx     , set_parl_tx      : 24;
429    pub bool, parl_rx     , set_parl_rx      : 25;
430    pub bool, mspi        , set_mspi         : 26;
431    pub bool, ledc        , set_ledc         : 27;
432    pub bool, iomux       , set_iomux        : 28;
433    pub bool, i2c         , set_i2c          : 29;
434    pub bool, can1        , set_can1         : 30;
435    pub bool, can0        , set_can0         : 31;
436}
437
438macro_rules! hp_system_init {
439    ($state:ident => $s:ident) => {
440        paste::paste! {
441            unsafe {
442                // Default configuration of hp-system power in active, modem and sleep modes
443                PMU::regs().[<$state _dig_power >]().modify(|_, w| w.bits($s.power.dig_power.0));
444                PMU::regs().[<$state _hp_ck_power >]().modify(|_, w| w.bits($s.power.clk.0));
445                PMU::regs().[<$state _xtal >]().modify(|_, w| w
446                    .[<$state _xpd_xtal >]().bit($s.power.xtal.xpd_xtal())
447                );
448
449                // Default configuration of hp-system clock in active, modem and sleep modes
450                PMU::regs().[<$state _icg_hp_func >]().write(|w| w.bits($s.clock.icg_func));
451                PMU::regs().[<$state _icg_hp_apb >]().write(|w| w.bits($s.clock.icg_apb));
452                PMU::regs().[<$state _icg_modem >]().write(|w| w
453                    .[<$state _dig_icg_modem_code >]().bits($s.clock.icg_modem.code())
454                );
455                PMU::regs().[<$state _sysclk >]().modify(|_, w| w
456                    .[<$state _dig_sys_clk_no_div >]().bit($s.clock.sysclk.dig_sysclk_nodiv())
457                    .[<$state _icg_sys_clock_en >]().bit($s.clock.sysclk.icg_sysclk_en())
458                    .[<$state _sys_clk_slp_sel >]().bit($s.clock.sysclk.sysclk_slp_sel())
459                    .[<$state _icg_slp_sel >]().bit($s.clock.sysclk.icg_slp_sel())
460                    .[<$state _dig_sys_clk_sel >]().bits($s.clock.sysclk.dig_sysclk_sel())
461                );
462
463                // Default configuration of hp-system digital sub-system in active, modem
464                // and sleep modes
465                PMU::regs().[<$state _hp_sys_cntl >]().modify(|_, w| w
466                    .[<$state _uart_wakeup_en >]().bit($s.syscntl.uart_wakeup_en())
467                    .[<$state _lp_pad_hold_all >]().bit($s.syscntl.lp_pad_hold_all())
468                    .[<$state _hp_pad_hold_all >]().bit($s.syscntl.hp_pad_hold_all())
469                    .[<$state _dig_pad_slp_sel >]().bit($s.syscntl.dig_pad_slp_sel())
470                    .[<$state _dig_pause_wdt >]().bit($s.syscntl.dig_pause_wdt())
471                    .[<$state _dig_cpu_stall >]().bit($s.syscntl.dig_cpu_stall())
472                );
473
474                // Default configuration of hp-system analog sub-system in active, modem and
475                // sleep modes
476                PMU::regs().[<$state _bias >]().modify(|_, w| w
477                    .[<$state _xpd_bias >]().bit($s.anlg.bias.xpd_bias())
478                    .[<$state _dbg_atten >]().bits($s.anlg.bias.dbg_atten())
479                    .[<$state _pd_cur >]().bit($s.anlg.bias.pd_cur())
480                    .sleep().bit($s.anlg.bias.bias_sleep())
481                );
482
483                PMU::regs().[<$state _hp_regulator0 >]().modify(|_, w| w
484                    .[<$state _hp_regulator_slp_mem_xpd >]().bit($s.anlg.regulator0.slp_mem_xpd())
485                    .[<$state _hp_regulator_slp_logic_xpd >]().bit($s.anlg.regulator0.slp_logic_xpd())
486                    .[<$state _hp_regulator_xpd >]().bit($s.anlg.regulator0.xpd())
487                    .[<$state _hp_regulator_slp_mem_dbias >]().bits($s.anlg.regulator0.slp_mem_dbias())
488                    .[<$state _hp_regulator_slp_logic_dbias >]().bits($s.anlg.regulator0.slp_logic_dbias())
489                    .[<$state _hp_regulator_dbias >]().bits($s.anlg.regulator0.dbias())
490                );
491
492                PMU::regs().[<$state _hp_regulator1 >]().modify(|_, w| w
493                    .[<$state _hp_regulator_drv_b >]().bits($s.anlg.regulator1.drv_b())
494                );
495
496                // Default configuration of hp-system retention sub-system in active, modem
497                // and sleep modes
498                PMU::regs().[<$state _backup >]().write(|w| w.bits($s.retention));
499                PMU::regs().[<$state _backup_clk >]().write(|w| w.bits($s.backup_clk));
500            }
501        }
502    };
503}
504
505struct HpSystemInit {
506    power: HpSysPower,
507    clock: SystemClockParam,
508    syscntl: HpSysCntlReg,
509    anlg: HpAnalog,
510    retention: u32,
511    backup_clk: u32,
512}
513impl HpSystemInit {
514    fn active() -> Self {
515        // pmu_hp_system_init_default
516
517        let mut power = HpSysPower::default();
518        power.dig_power.set_vdd_spi_pd_en(false);
519        power.dig_power.set_wifi_pd_en(false);
520        power.dig_power.set_cpu_pd_en(false);
521        power.dig_power.set_aon_pd_en(false);
522        power.dig_power.set_top_pd_en(false);
523        power.dig_power.set_mem_pd_en(0);
524        power.dig_power.set_mem_dslp(false);
525
526        power.clk.set_i2c_iso_en(false);
527        power.clk.set_i2c_retention(false);
528        power.clk.set_xpd_bb_i2c(true);
529        power.clk.set_xpd_bbpll_i2c(true);
530        power.clk.set_xpd_bbpll(true);
531
532        power.xtal.set_xpd_xtal(true);
533
534        let mut clock = SystemClockParam {
535            icg_func: 0xffffffff,
536            icg_apb: 0xffffffff,
537            ..SystemClockParam::default()
538        };
539        clock.icg_modem.set_code(ICG_MODEM_CODE_ACTIVE);
540        clock.sysclk.set_dig_sysclk_nodiv(false);
541        clock.sysclk.set_icg_sysclk_en(true);
542        clock.sysclk.set_sysclk_slp_sel(false);
543        clock.sysclk.set_icg_slp_sel(false);
544        clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
545
546        let mut syscntl = HpSysCntlReg::default();
547        syscntl.set_uart_wakeup_en(false);
548        syscntl.set_lp_pad_hold_all(false);
549        syscntl.set_hp_pad_hold_all(false);
550        syscntl.set_dig_pad_slp_sel(false);
551        syscntl.set_dig_pause_wdt(false);
552        syscntl.set_dig_cpu_stall(false);
553
554        // PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT
555        let mut anlg = HpAnalog::default();
556        anlg.bias.set_xpd_bias(true);
557        anlg.bias.set_dbg_atten(0x0);
558        anlg.bias.set_pd_cur(false);
559        anlg.bias.set_bias_sleep(false);
560
561        // TODO: These 4 aren't applied currently?
562        anlg.regulator0.set_lp_dbias_vol(0xD);
563        anlg.regulator0.set_hp_dbias_vol(0x1C);
564        anlg.regulator0.set_dbias_sel(true);
565        anlg.regulator0.set_dbias_init(true);
566
567        anlg.regulator0.set_slp_mem_xpd(false);
568        anlg.regulator0.set_slp_logic_xpd(false);
569        anlg.regulator0.set_xpd(true);
570        anlg.regulator0.set_slp_mem_dbias(0);
571        anlg.regulator0.set_slp_logic_dbias(0);
572        anlg.regulator0.set_dbias(HP_CALI_DBIAS);
573
574        anlg.regulator1.set_drv_b(0);
575
576        let mut retention = HpActiveBackup::default();
577        retention.set_hp_sleep2active_backup_modem_clk_code(2);
578        retention.set_hp_modem2active_backup_modem_clk_code(2);
579        retention.set_hp_active_retention_mode(false);
580        retention.set_hp_sleep2active_retention_en(false);
581        retention.set_hp_modem2active_retention_en(false);
582        retention.set_hp_sleep2active_backup_clk_sel(HP_SYSCLK_XTAL);
583        retention.set_hp_modem2active_backup_clk_sel(HP_SYSCLK_PLL);
584        retention.set_hp_sleep2active_backup_mode(hp_retention_regdma_config(0, 0));
585        retention.set_hp_modem2active_backup_mode(hp_retention_regdma_config(0, 2));
586        retention.set_hp_sleep2active_backup_en(false);
587        retention.set_hp_modem2active_backup_en(false);
588
589        let mut backup_clk = HpBackupClk::default();
590        backup_clk.set_regdma(true);
591        backup_clk.set_tg0(true);
592        backup_clk.set_tg1(true);
593        backup_clk.set_hpbus(true);
594        backup_clk.set_mspi(true);
595        backup_clk.set_iomux(true);
596        backup_clk.set_spi2(true);
597        backup_clk.set_uart0(true);
598        backup_clk.set_systimer(true);
599
600        Self {
601            power,
602            clock,
603            syscntl,
604            anlg,
605            retention: retention.0,
606            backup_clk: backup_clk.0,
607        }
608    }
609
610    fn modem() -> Self {
611        let mut power = HpSysPower::default();
612        power.dig_power.set_vdd_spi_pd_en(false);
613        power.dig_power.set_wifi_pd_en(false);
614        power.dig_power.set_cpu_pd_en(true);
615        power.dig_power.set_aon_pd_en(false);
616        power.dig_power.set_top_pd_en(false);
617        power.dig_power.set_mem_pd_en(0);
618        power.dig_power.set_mem_dslp(false);
619
620        power.clk.set_xpd_bb_i2c(true);
621        power.clk.set_xpd_bbpll_i2c(true);
622        power.clk.set_xpd_bbpll(true);
623        power.clk.set_i2c_iso_en(false);
624        power.clk.set_i2c_retention(false);
625
626        power.xtal.set_xpd_xtal(true);
627
628        let mut clock = SystemClockParam {
629            icg_func: 0,
630            icg_apb: 0,
631            ..SystemClockParam::default()
632        };
633        clock.icg_modem.set_code(ICG_MODEM_CODE_MODEM);
634        clock.sysclk.set_dig_sysclk_nodiv(false);
635        clock.sysclk.set_icg_sysclk_en(true);
636        clock.sysclk.set_sysclk_slp_sel(true);
637        clock.sysclk.set_icg_slp_sel(true);
638        clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_PLL);
639
640        let mut syscntl = HpSysCntlReg::default();
641        syscntl.set_uart_wakeup_en(true);
642        syscntl.set_lp_pad_hold_all(false);
643        syscntl.set_hp_pad_hold_all(false);
644        syscntl.set_dig_pad_slp_sel(false);
645        syscntl.set_dig_pause_wdt(true);
646        syscntl.set_dig_cpu_stall(true);
647
648        let mut anlg = HpAnalog::default();
649        anlg.bias.set_xpd_bias(false);
650        anlg.bias.set_dbg_atten(0x0);
651        anlg.bias.set_pd_cur(false);
652        anlg.bias.set_bias_sleep(false);
653
654        anlg.regulator0.set_slp_mem_xpd(false);
655        anlg.regulator0.set_slp_logic_xpd(false);
656        anlg.regulator0.set_xpd(true);
657        anlg.regulator0.set_slp_mem_dbias(0);
658        anlg.regulator0.set_slp_logic_dbias(0);
659        anlg.regulator0.set_dbias(HP_CALI_DBIAS);
660
661        anlg.regulator1.set_drv_b(0);
662
663        let mut retention = HpModemBackup::default();
664        retention.set_hp_sleep2modem_backup_modem_clk_code(1);
665        retention.set_hp_modem_retention_mode(false);
666        retention.set_hp_sleep2modem_retention_en(false);
667        retention.set_hp_sleep2modem_backup_clk_sel(0);
668        retention.set_hp_sleep2modem_backup_mode(hp_retention_regdma_config(0, 1));
669        retention.set_hp_sleep2modem_backup_en(false);
670
671        let mut backup_clk = HpBackupClk::default();
672        backup_clk.set_regdma(true);
673        backup_clk.set_tg0(true);
674        backup_clk.set_tg1(true);
675        backup_clk.set_hpbus(true);
676        backup_clk.set_mspi(true);
677        backup_clk.set_iomux(true);
678        backup_clk.set_spi2(true);
679        backup_clk.set_uart0(true);
680        backup_clk.set_systimer(true);
681
682        Self {
683            power,
684            clock,
685            syscntl,
686            anlg,
687            retention: retention.0,
688            backup_clk: backup_clk.0,
689        }
690    }
691
692    fn sleep() -> Self {
693        let mut power = HpSysPower::default();
694        power.dig_power.set_vdd_spi_pd_en(true);
695        power.dig_power.set_mem_dslp(false);
696        power.dig_power.set_mem_pd_en(0);
697        power.dig_power.set_wifi_pd_en(true);
698        power.dig_power.set_cpu_pd_en(false);
699        power.dig_power.set_aon_pd_en(false);
700        power.dig_power.set_top_pd_en(false);
701
702        power.clk.set_i2c_iso_en(true);
703        power.clk.set_i2c_retention(true);
704        power.clk.set_xpd_bb_i2c(true);
705        power.clk.set_xpd_bbpll_i2c(false);
706        power.clk.set_xpd_bbpll(false);
707
708        power.xtal.set_xpd_xtal(false);
709
710        let mut clock = SystemClockParam {
711            icg_func: 0,
712            icg_apb: 0,
713            ..SystemClockParam::default()
714        };
715        clock.icg_modem.set_code(ICG_MODEM_CODE_SLEEP);
716        clock.sysclk.set_dig_sysclk_nodiv(false);
717        clock.sysclk.set_icg_sysclk_en(false);
718        clock.sysclk.set_sysclk_slp_sel(true);
719        clock.sysclk.set_icg_slp_sel(true);
720        clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
721
722        let mut anlg = HpAnalog::default();
723        anlg.bias.set_xpd_bias(false);
724        anlg.bias.set_dbg_atten(0x0);
725        anlg.bias.set_pd_cur(false);
726        anlg.bias.set_bias_sleep(false);
727
728        anlg.regulator0.set_slp_mem_xpd(false);
729        anlg.regulator0.set_slp_logic_xpd(false);
730        anlg.regulator0.set_xpd(true);
731        anlg.regulator0.set_slp_mem_dbias(0);
732        anlg.regulator0.set_slp_logic_dbias(0);
733        anlg.regulator0.set_dbias(1);
734
735        anlg.regulator1.set_drv_b(0);
736
737        let mut retention = HpSleepBackup::default();
738        retention.set_hp_modem2sleep_backup_modem_clk_code(0);
739        retention.set_hp_active2sleep_backup_modem_clk_code(2);
740        retention.set_hp_sleep_retention_mode(false);
741        retention.set_hp_modem2sleep_retention_en(false);
742        retention.set_hp_active2sleep_retention_en(false);
743        retention.set_hp_modem2sleep_backup_clk_sel(0);
744        retention.set_hp_active2sleep_backup_clk_sel(0);
745        retention.set_hp_modem2sleep_backup_mode(hp_retention_regdma_config(1, 1));
746        retention.set_hp_active2sleep_backup_mode(hp_retention_regdma_config(1, 0));
747        retention.set_hp_modem2sleep_backup_en(false);
748        retention.set_hp_active2sleep_backup_en(false);
749
750        let mut backup_clk = HpBackupClk::default();
751        backup_clk.set_regdma(true);
752        backup_clk.set_tg0(true);
753        backup_clk.set_tg1(true);
754        backup_clk.set_hpbus(true);
755        backup_clk.set_mspi(true);
756        backup_clk.set_iomux(true);
757        backup_clk.set_spi2(true);
758        backup_clk.set_uart0(true);
759        backup_clk.set_systimer(true);
760
761        let mut syscntl = HpSysCntlReg::default();
762        syscntl.set_uart_wakeup_en(true);
763        syscntl.set_lp_pad_hold_all(false);
764        syscntl.set_hp_pad_hold_all(false);
765        syscntl.set_dig_pad_slp_sel(true);
766        syscntl.set_dig_pause_wdt(true);
767        syscntl.set_dig_cpu_stall(true);
768
769        Self {
770            power,
771            clock,
772            syscntl,
773            anlg,
774            retention: retention.0,
775            backup_clk: backup_clk.0,
776        }
777    }
778
779    fn init_default() {
780        let active = Self::active();
781        let modem = Self::modem();
782        let sleep = Self::sleep();
783
784        hp_system_init!(hp_active => active);
785        hp_system_init!(hp_modem => modem);
786        hp_system_init!(hp_sleep => sleep);
787
788        unsafe {
789            // Some PMU initial parameter configuration
790            PMU::regs()
791                .imm_modem_icg()
792                .write(|w| w.update_dig_icg_modem_en().bit(true));
793            PMU::regs()
794                .imm_sleep_sysclk()
795                .write(|w| w.update_dig_icg_switch().bit(true));
796
797            const PMU_SLEEP_PROTECT_HP_LP_SLEEP: u8 = 2;
798            PMU::regs()
799                .slp_wakeup_cntl3()
800                .modify(|_, w| w.sleep_prt_sel().bits(PMU_SLEEP_PROTECT_HP_LP_SLEEP));
801        }
802    }
803}
804
805bitfield::bitfield! {
806    #[derive(Clone, Copy, Default)]
807    // pmu_lp_power_t.0
808    pub struct LpDigPower(u32);
809
810    pub u32, mem_dslp  , set_mem_dslp  : 30;
811    pub u32, peri_pd_en, set_peri_pd_en: 31;
812
813}
814
815bitfield::bitfield! {
816    #[derive(Clone, Copy, Default)]
817    // pmu_lp_power_t.1
818    pub struct LpClkPower(u32);
819
820    pub u32, xpd_xtal32k, set_xpd_xtal32k: 28;
821    pub u32, xpd_rc32k  , set_xpd_rc32k  : 29;
822    pub u32, xpd_fosc   , set_xpd_fosc   : 30;
823    pub u32, pd_osc     , set_pd_osc     : 31;
824}
825
826bitfield::bitfield! {
827    #[derive(Clone, Copy, Default)]
828    // pmu_lp_power_t.2
829    pub struct LpXtalPower(u32);
830
831    pub bool, xpd_xtal     , set_xpd_xtal     : 31;
832}
833
834#[derive(Clone, Copy, Default)]
835// pmu_sleep_power_config_t.1
836pub struct LpSysPower {
837    // This is a best-guess assignment of the variants in the union `pmu_lp_power_t` union
838    // In esp-idf, all three fields are `pmu_lp_power_t`
839    pub dig_power: LpDigPower,
840    pub clk_power: LpClkPower,
841    pub xtal: LpXtalPower,
842}
843
844bitfield::bitfield! {
845    #[derive(Clone, Copy, Default)]
846    // pmu_lp_analog_t.0
847    pub struct LpAnalogBias(u32);
848
849    pub bool, xpd_bias  , set_xpd_bias  : 25;
850    pub u8,   dbg_atten , set_dbg_atten : 29, 26;
851    pub bool, pd_cur    , set_pd_cur    : 30;
852    pub bool, bias_sleep, set_bias_sleep: 31;
853}
854
855bitfield::bitfield! {
856    #[derive(Clone, Copy, Default)]
857    // pmu_lp_analog_t.1
858    pub struct LpAnalogRegulator0(u32);
859
860    pub bool, slp_xpd  , set_slp_xpd  : 21;
861    pub bool, xpd      , set_xpd      : 22;
862    pub u8,   slp_dbias, set_slp_dbias: 26, 23;
863    pub u8,   dbias    , set_dbias    : 31, 27;
864}
865
866bitfield::bitfield! {
867    #[derive(Clone, Copy, Default)]
868    // pmu_lp_analog_t.2
869    pub struct LpAnalogRegulator1(u32);
870
871    pub u8, drv_b    , set_drv_b    : 31, 28;
872}
873
874#[derive(Clone, Copy, Default)]
875// pmu_lp_analog_t
876pub struct LpAnalog {
877    pub bias: LpAnalogBias,
878    pub regulator0: LpAnalogRegulator0,
879    pub regulator1: LpAnalogRegulator1,
880}
881
882macro_rules! lp_system_init {
883    ($state:ident => $s:ident) => {
884        paste::paste! {
885            unsafe {
886                // Default configuration of lp-system power in active and sleep modes
887                PMU::regs().[< $state _dig_power >]().modify(|_, w| w.bits($s.dig_power.0));
888                PMU::regs().[< $state _ck_power >]().modify(|_, w| w.bits($s.clk_power.0));
889
890                // Default configuration of lp-system analog sub-system in active and sleep modes
891                PMU::regs().[< $state _regulator0 >]().modify(|_, w| w
892                    .[< $state _regulator_slp_xpd >]().bit($s.analog_regulator0.slp_xpd())
893                    .[< $state _regulator_xpd >]().bit($s.analog_regulator0.xpd())
894                    .[< $state _regulator_slp_dbias >]().bits($s.analog_regulator0.slp_dbias())
895                    .[< $state _regulator_dbias >]().bits($s.analog_regulator0.dbias())
896                );
897
898                PMU::regs().[< $state _regulator1 >]().modify(|_, w| w
899                    .[< $state _regulator_drv_b >]().bits($s.analog_regulator1.drv_b())
900                );
901            }
902        }
903    };
904}
905
906struct LpSystemInit {
907    dig_power: LpDigPower,
908    clk_power: LpClkPower,
909    xtal: LpXtalPower,
910    bias: LpAnalogBias,
911    analog_regulator0: LpAnalogRegulator0,
912    analog_regulator1: LpAnalogRegulator1,
913}
914impl LpSystemInit {
915    fn active() -> Self {
916        let mut dig_power = LpDigPower::default();
917        dig_power.set_peri_pd_en(false);
918        dig_power.set_mem_dslp(false);
919
920        let mut clk_power = LpClkPower::default();
921        clk_power.set_xpd_xtal32k(xtal32k::use_xtal32k());
922        // ESP32-C5 disables RC32K in LP active by default.
923        clk_power.set_xpd_rc32k(false);
924        clk_power.set_xpd_fosc(true);
925
926        let mut analog_regulator0 = LpAnalogRegulator0::default();
927        analog_regulator0.set_slp_xpd(false);
928        analog_regulator0.set_xpd(true);
929        analog_regulator0.set_slp_dbias(0);
930        analog_regulator0.set_dbias(LP_CALI_DBIAS);
931
932        let mut analog_regulator1 = LpAnalogRegulator1::default();
933        analog_regulator1.set_drv_b(0);
934
935        Self {
936            dig_power,
937            clk_power,
938            xtal: LpXtalPower::default(),
939            bias: LpAnalogBias::default(),
940            analog_regulator0,
941            analog_regulator1,
942        }
943    }
944
945    fn sleep() -> Self {
946        let mut dig_power = LpDigPower::default();
947        dig_power.set_mem_dslp(true);
948        dig_power.set_peri_pd_en(false);
949
950        let mut clk_power = LpClkPower::default();
951        clk_power.set_xpd_xtal32k(false);
952        clk_power.set_xpd_rc32k(false);
953        clk_power.set_xpd_fosc(false);
954        clk_power.set_pd_osc(false);
955
956        let mut xtal = LpXtalPower::default();
957        xtal.set_xpd_xtal(false);
958
959        let mut analog_bias = LpAnalogBias::default();
960        analog_bias.set_xpd_bias(false);
961        analog_bias.set_dbg_atten(0);
962        analog_bias.set_pd_cur(true);
963        analog_bias.set_bias_sleep(true);
964
965        let mut analog_regulator0 = LpAnalogRegulator0::default();
966        analog_regulator0.set_slp_xpd(false);
967        analog_regulator0.set_xpd(true);
968        analog_regulator0.set_slp_dbias(0);
969        analog_regulator0.set_dbias(12);
970
971        let mut analog_regulator1 = LpAnalogRegulator1::default();
972        analog_regulator1.set_drv_b(0);
973
974        Self {
975            dig_power,
976            clk_power,
977            xtal,
978            bias: analog_bias,
979            analog_regulator0,
980            analog_regulator1,
981        }
982    }
983
984    fn init_default() {
985        let active = Self::active();
986        let sleep = Self::sleep();
987
988        lp_system_init!(hp_sleep_lp => active);
989        lp_system_init!(lp_sleep_lp => sleep);
990
991        PMU::regs()
992            .lp_sleep_xtal()
993            .modify(|_, w| w.lp_sleep_xpd_xtal().bit(sleep.xtal.xpd_xtal()));
994
995        PMU::regs().lp_sleep_bias().modify(|_, w| unsafe {
996            w.lp_sleep_xpd_bias().bit(sleep.bias.xpd_bias()); // pmu_ll_lp_set_bias_xpd
997            w.lp_sleep_dbg_atten().bits(sleep.bias.dbg_atten()); // pmu_ll_lp_set_bias_dbg_atten
998            w.lp_sleep_pd_cur().bit(sleep.bias.pd_cur()); // pmu_ll_lp_set_bias_pd_cur
999            w.sleep().bit(sleep.bias.bias_sleep()) // pmu_ll_lp_set_bias_sleep
1000        });
1001    }
1002}
1003
1004pub(crate) fn init(config: &ClockConfig) {
1005    // pmu_init()
1006    PMU::regs().rf_pwc().modify(|_, w| {
1007        w.perif_i2c_rstb().set_bit();
1008        w.xpd_perif_i2c().set_bit()
1009    });
1010
1011    regi2c::I2C_DIG_REG_ENIF_RTC_DREG.write_field(1);
1012    regi2c::I2C_DIG_REG_ENIF_DIG_DREG.write_field(1);
1013    regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
1014    regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
1015
1016    HpSystemInit::init_default();
1017    LpSystemInit::init_default();
1018
1019    pmu_power_domain_force_default();
1020
1021    calibrate_ocode();
1022
1023    // esp_perip_clk_init()
1024    modem_clock_domain_power_state_icg_map_init();
1025
1026    //  During system initialization, the low-power clock source of the modem
1027    //  (WiFi, BLE or Coexist) follows the configuration of the slow clock source
1028    //  of the system. If the WiFi, BLE or Coexist module needs a higher
1029    //  precision sleep clock (for example, the BLE needs to use the main XTAL
1030    //  oscillator (40 MHz) to provide the clock during the sleep process in some
1031    //  scenarios), the module needs to switch to the required clock source by
1032    //  itself.
1033    let lpclk_src = config.lp_slow_clk.unwrap_or(LpSlowClkConfig::RcSlow);
1034
1035    modem_clock_select_lp_clock_source_wifi(ModemClockLpclkSource::from(lpclk_src), 0);
1036    modem_clk_domain_active_state_icg_map_preinit();
1037
1038    PCR::regs()
1039        .ctrl_32k_conf()
1040        .modify(|_, w| unsafe { w.fosc_tick_num().bits(31) });
1041}
1042
1043fn modem_clk_domain_active_state_icg_map_preinit() {
1044    unsafe {
1045        // Configure modem ICG code in PMU_ACTIVE state
1046        PMU::regs()
1047            .hp_active_icg_modem()
1048            .modify(|_, w| w.hp_active_dig_icg_modem_code().bits(ICG_MODEM_CODE_ACTIVE));
1049
1050        // Disable clock gating for MODEM_APB, I2C_MST and LP_APB clock domains in
1051        // PMU_ACTIVE state
1052        MODEM_SYSCON::regs()
1053            .clk_conf_power_st()
1054            .modify(|_, w| w.clk_modem_apb_st_map().bits(1 << ICG_MODEM_CODE_ACTIVE));
1055        MODEM_LPCON::regs().clk_conf_power_st().modify(|_, w| {
1056            w.clk_i2c_mst_st_map().bits(1 << ICG_MODEM_CODE_ACTIVE);
1057            w.clk_lp_apb_st_map().bits(1 << ICG_MODEM_CODE_ACTIVE)
1058        });
1059
1060        // Software trigger force update modem ICG code and ICG switch
1061        PMU::regs()
1062            .imm_modem_icg()
1063            .write(|w| w.update_dig_icg_modem_en().set_bit());
1064        PMU::regs()
1065            .imm_sleep_sysclk()
1066            .write(|w| w.update_dig_icg_switch().set_bit());
1067
1068        // The following is part of rtc_clk_init
1069
1070        LP_CLKRST::regs()
1071            .fosc_cntl()
1072            .modify(|_, w| w.fosc_dfreq().bits(100));
1073
1074        regi2c::I2C_DIG_REG_SCK_DCAP.write_reg(128);
1075
1076        LP_CLKRST::regs()
1077            .rc32k_cntl()
1078            .modify(|_, w| w.rc32k_dfreq().bits(700));
1079
1080        regi2c::I2C_DIG_REG_ENIF_RTC_DREG.write_field(1);
1081        regi2c::I2C_DIG_REG_ENIF_DIG_DREG.write_field(1);
1082
1083        PMU::regs()
1084            .hp_active_hp_regulator0()
1085            .modify(|_, w| w.hp_active_hp_regulator_dbias().bits(HP_CALI_DBIAS));
1086        PMU::regs()
1087            .hp_sleep_lp_regulator0()
1088            .modify(|_, w| w.hp_sleep_lp_regulator_dbias().bits(LP_CALI_DBIAS));
1089
1090        // clk_ll_rc_fast_tick_conf
1091        PCR::regs()
1092            .ctrl_32k_conf()
1093            .modify(|_, w| w.fosc_tick_num().bits(255));
1094    }
1095}
1096
1097// Terminology:
1098//
1099// CPU Reset:    Reset CPU core only, once reset done, CPU will execute from
1100//               reset vector
1101// Core Reset:   Reset the whole digital system except RTC sub-system
1102// System Reset: Reset the whole digital system, including RTC sub-system
1103// Chip Reset:   Reset the whole chip, including the analog part
1104
1105/// SOC Reset Reason.
1106#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
1107pub enum SocResetReason {
1108    /// Powers on reset.
1109    ///
1110    /// In ESP-IDF this value (0x01) can *also* be `ChipBrownOut` or
1111    /// `ChipSuperWdt`, however that is not really compatible with Rust-style
1112    /// enums.
1113    ChipPowerOn   = 0x01,
1114    /// Software resets the digital core by RTC_CNTL_SW_SYS_RST
1115    CoreSw        = 0x03,
1116    /// Deep sleep reset the digital core
1117    CoreDeepSleep = 0x05,
1118    /// Main watch dog 0 resets digital core
1119    CoreMwdt0     = 0x07,
1120    /// Main watch dog 1 resets digital core
1121    CoreMwdt1     = 0x08,
1122    /// RTC watch dog resets digital core
1123    CoreRtcWdt    = 0x09,
1124    /// Main watch dog 0 resets CPU 0
1125    Cpu0Mwdt0     = 0x0B,
1126    /// Software resets CPU 0 by RTC_CNTL_SW_PROCPU_RST
1127    Cpu0Sw        = 0x0C,
1128    /// RTC watch dog resets CPU 0
1129    Cpu0RtcWdt    = 0x0D,
1130    /// VDD voltage is not stable and resets the digital core.
1131    SysBrownOut   = 0x0F,
1132    /// RTC watch dog resets digital core and rtc module
1133    SysRtcWdt     = 0x10,
1134    /// Main watch dog 1 resets CPU 0
1135    Cpu0Mwdt1     = 0x11,
1136    /// Super watch dog resets the digital core and rtc module
1137    SysSuperWdt   = 0x12,
1138    /// eFuse CRC error resets the digital core
1139    CoreEfuseCrc  = 0x14,
1140    /// USB UART resets the digital core
1141    CoreUsbUart   = 0x15,
1142    /// USB JTAG resets the digital core
1143    CoreUsbJtag   = 0x16,
1144    /// JTAG resets CPU
1145    Cpu0JtagCpu   = 0x18,
1146    /// Powers glitch resets CPU.
1147    PowerGlitch   = 0x19,
1148    /// CPU lockup reset
1149    CpuLockup     = 0x1A,
1150}