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