Skip to main content

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