Skip to main content

esp_hal/rtc_cntl/rtc/
esp32c6.rs

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