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