Skip to main content

esp_hal/rtc_cntl/rtc/
esp32c6.rs

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