Skip to main content

esp_hal/rtc_cntl/rtc/
esp32h4.rs

1use strum::FromRepr;
2
3use crate::{
4    peripherals::{LP_AON, LP_CLKRST, PMU},
5    soc::{clocks::ClockConfig, regi2c, xtal32k},
6};
7
8// IDF sourced values.
9const CK8M_DFREQ: u16 = 100;
10const SCK_DCAP: u16 = 28;
11pub(crate) const HP_CALI_DRVB: u32 = 6;
12pub(crate) const LP_CALI_DBIAS: u8 = 0;
13
14const ICG_MODEM_CODE_SLEEP: u8 = 0;
15const ICG_MODEM_CODE_MODEM: u8 = 1;
16const ICG_MODEM_CODE_ACTIVE: u8 = 2;
17
18// `PMU_CLK_SRC_VAL` of esp-idf `pmu_param.c`, used by `dig_sysclk_sel` and `backup_clk_sel`.
19const PMU_CLK_SRC_XTAL: u8 = 0;
20const PMU_CLK_SRC_XTAL_X2: u8 = 2;
21const PMU_CLK_SRC_PLL: u8 = 3;
22
23// `PMU_ICG_FUNC_ENA_HPBUS` of esp-idf `pmu_icg_mapping.h`.
24const ICG_FUNC_ENA_HPBUS: u32 = 1 << 15;
25
26const fn hp_retention_regdma_config(dir: u8, entry: u8) -> u8 {
27    (((dir) << 4) | (entry & 0xf)) & 0x1f
28}
29
30/// Clears the force bits of the power domains.
31fn pmu_power_domain_force_default() {
32    // PMU_HP_PD_TOP
33    PMU::regs().power_pd_top_cntl().modify(|_, w| {
34        w.force_top_reset().bit(false); // pmu_ll_hp_set_power_force_reset
35        w.force_top_iso().bit(false); // pmu_ll_hp_set_power_force_isolate
36        w.force_top_pu().bit(false); // pmu_ll_hp_set_power_force_power_up
37        w.force_top_no_reset().bit(false); // pmu_ll_hp_set_power_force_no_reset
38        w.force_top_no_iso().bit(false); // pmu_ll_hp_set_power_force_no_isolate
39        w.force_top_pd().bit(false) // pmu_ll_hp_set_power_force_power_down
40    });
41
42    // PMU_HP_PD_HP_AON
43    PMU::regs().power_pd_hpaon_cntl().modify(|_, w| {
44        w.force_hp_aon_reset().bit(false);
45        w.force_hp_aon_iso().bit(false);
46        w.force_hp_aon_pu().bit(false);
47        w.force_hp_aon_no_reset().bit(false);
48        w.force_hp_aon_no_iso().bit(false);
49        w.force_hp_aon_pd().bit(false)
50    });
51
52    // PMU_HP_PD_CPU
53    PMU::regs().power_pd_hpcpu_cntl().modify(|_, w| {
54        w.force_hp_cpu_reset().bit(false);
55        w.force_hp_cpu_iso().bit(false);
56        w.force_hp_cpu_pu().bit(false);
57        w.force_hp_cpu_no_reset().bit(false);
58        w.force_hp_cpu_no_iso().bit(false);
59        w.force_hp_cpu_pd().bit(false)
60    });
61
62    // PMU_HP_PD_BT_154
63    PMU::regs().power_pd_hpwifi_cntl().modify(|_, w| {
64        w.force_hp_wifi_reset().bit(false);
65        w.force_hp_wifi_iso().bit(false);
66        w.force_hp_wifi_pu().bit(false);
67        w.force_hp_wifi_no_reset().bit(false);
68        w.force_hp_wifi_no_iso().bit(false);
69        w.force_hp_wifi_pd().bit(false)
70    });
71
72    PMU::regs().power_pd_mem_cntl().modify(|_, w| unsafe {
73        // Isolate all memory banks while sleeping, avoid memory leakage current
74        w.force_hp_mem_no_iso().bits(0); // pmu_ll_hp_set_memory_no_isolate
75        // Disable memory force pu for memory pd during deep sleep
76        w.force_hp_mem_pu().bits(0) // pmu_ll_hp_set_memory_power_up
77    });
78
79    // pmu_ll_hp_set_vdd_flash_tiel_enable
80    PMU::regs().power_vdd_flash().modify(|_, w| {
81        w.flash_ldo_tiel_en().set_bit();
82        w.flash_ldo_tiel().set_bit()
83    });
84
85    PMU::regs().power_pd_lpperi_cntl().modify(|_, w| {
86        w.force_lp_peri_reset().bit(false); // pmu_ll_lp_set_power_force_reset
87        w.force_lp_peri_iso().bit(false); // pmu_ll_lp_set_power_force_isolate
88        w.force_lp_peri_pu().bit(false); // pmu_ll_lp_set_power_force_power_up
89        w.force_lp_peri_no_reset().bit(false); // pmu_ll_lp_set_power_force_no_reset
90        w.force_lp_peri_no_iso().bit(false); // pmu_ll_lp_set_power_force_no_isolate
91        w.force_lp_peri_pd().bit(false) // pmu_ll_lp_set_power_force_power_down
92    });
93}
94
95bitfield::bitfield! {
96    #[derive(Clone, Copy, Default)]
97    // pmu_hp_power_t.0
98    pub struct HpDigPower(u32);
99
100    pub u8,   vdd_flash_mode, set_vdd_flash_mode: 21, 18;
101    pub bool, mem_dslp      , set_mem_dslp      : 22;
102    pub u8,   mem_pd_en     , set_mem_pd_en     : 26, 23;
103    pub bool, wifi_pd_en    , set_wifi_pd_en    : 27;
104    pub bool, peri_pd_en    , set_peri_pd_en    : 28;
105    pub bool, cpu_pd_en     , set_cpu_pd_en     : 29;
106    pub bool, aon_pd_en     , set_aon_pd_en     : 30;
107    pub bool, top_pd_en     , set_top_pd_en     : 31;
108}
109
110bitfield::bitfield! {
111    #[derive(Clone, Copy, Default)]
112    // pmu_hp_power_t.1
113    pub struct HpClkPower(u32);
114
115    pub bool, i2c_iso_en   , set_i2c_iso_en   : 26;
116    pub bool, i2c_retention, set_i2c_retention: 27;
117    pub bool, xpd_bb_i2c   , set_xpd_bb_i2c   : 28;
118    pub bool, xpd_bbpll_i2c, set_xpd_bbpll_i2c: 29;
119    pub bool, xpd_bbpll    , set_xpd_bbpll    : 30;
120}
121
122bitfield::bitfield! {
123    #[derive(Clone, Copy, Default)]
124    // pmu_hp_power_t.2
125    pub struct XtalPower(u32);
126
127    pub bool, xpd_xtalx2, set_xpd_xtalx2: 30;
128    pub bool, xpd_xtal  , set_xpd_xtal  : 31;
129}
130
131#[derive(Clone, Copy, Default)]
132// pmu_sleep_power_config_t.hp_sys
133pub struct HpSysPower {
134    pub dig_power: HpDigPower,
135    pub clk: HpClkPower,
136    pub xtal: XtalPower,
137}
138
139bitfield::bitfield! {
140    #[derive(Clone, Copy, Default)]
141    // pmu_hp_sys_cntl_reg_t
142    pub struct HpSysCntlReg(u32);
143
144    pub bool, uart_wakeup_en , set_uart_wakeup_en : 24;
145    pub bool, lp_pad_hold_all, set_lp_pad_hold_all: 25;
146    pub bool, hp_pad_hold_all, set_hp_pad_hold_all: 26;
147    pub bool, dig_pad_slp_sel, set_dig_pad_slp_sel: 27;
148    pub bool, dig_pause_wdt  , set_dig_pause_wdt  : 28;
149    pub bool, dig_cpu_stall  , set_dig_cpu_stall  : 29;
150}
151
152bitfield::bitfield! {
153    #[derive(Clone, Copy, Default)]
154    // pmu_hp_sysclk_reg_t
155    pub struct HpSysclk(u32);
156
157    pub bool, dig_sysclk_nodiv, set_dig_sysclk_nodiv: 26;
158    pub bool, icg_sysclk_en   , set_icg_sysclk_en   : 27;
159    pub bool, sysclk_slp_sel  , set_sysclk_slp_sel  : 28;
160    pub bool, icg_slp_sel     , set_icg_slp_sel     : 29;
161    pub u8,   dig_sysclk_sel  , set_dig_sysclk_sel  : 31, 30;
162}
163
164// pmu_hp_system_clock_param_t
165#[derive(Clone, Copy, Default)]
166struct SystemClockParam {
167    icg_func: u32,
168    icg_apb: u32,
169    icg_modem_code: u8,
170    sysclk: HpSysclk,
171}
172
173bitfield::bitfield! {
174    #[derive(Clone, Copy, Default)]
175    // pmu_hp_analog_t.0, which is also pmu_lp_analog_t.0 without `xpd_trx`
176    pub struct AnalogBias(u32);
177
178    pub bool, dcdc_ccm_enb      , set_dcdc_ccm_enb      : 9;
179    pub bool, dcdc_clear_rdy    , set_dcdc_clear_rdy    : 10;
180    pub u8,   dig_reg_dpcur_bias, set_dig_reg_dpcur_bias: 12, 11;
181    pub u8,   dig_reg_dsfmos    , set_dig_reg_dsfmos    : 16, 13;
182    pub u8,   dcm_vset          , set_dcm_vset          : 21, 17;
183    pub u8,   dcm_mode          , set_dcm_mode          : 23, 22;
184    pub bool, xpd_trx           , set_xpd_trx           : 24;
185    pub bool, xpd_bias          , set_xpd_bias          : 25;
186    pub bool, discnnt_dig_rtc   , set_discnnt_dig_rtc   : 29;
187    pub bool, pd_cur            , set_pd_cur            : 30;
188    pub bool, bias_sleep        , set_bias_sleep        : 31;
189}
190
191bitfield::bitfield! {
192    #[derive(Clone, Copy, Default)]
193    // pmu_hp_analog_t.1
194    pub struct HpAnalogRegulator0(u32);
195
196    pub bool, power_det_bypass, set_power_det_bypass: 0;
197    // Only the HP_ACTIVE mode has these two fields.
198    pub bool, dbias_sel       , set_dbias_sel       : 14;
199    pub bool, dbias_init      , set_dbias_init      : 15;
200    pub bool, slp_mem_xpd     , set_slp_mem_xpd     : 16;
201    pub bool, slp_logic_xpd   , set_slp_logic_xpd   : 17;
202    pub bool, xpd             , set_xpd             : 18;
203    pub u8,   slp_mem_dbias   , set_slp_mem_dbias   : 22, 19;
204    pub u8,   slp_logic_dbias , set_slp_logic_dbias : 26, 23;
205    pub u8,   dbias           , set_dbias           : 31, 27;
206}
207
208bitfield::bitfield! {
209    #[derive(Clone, Copy, Default)]
210    // pmu_hp_analog_t.2
211    pub struct HpAnalogRegulator1(u32);
212
213    pub u32, drv_b, set_drv_b: 31, 8;
214}
215
216#[derive(Clone, Copy, Default)]
217// pmu_hp_analog_t
218pub struct HpAnalog {
219    pub bias: AnalogBias,
220    pub regulator0: HpAnalogRegulator0,
221    pub regulator1: HpAnalogRegulator1,
222}
223
224bitfield::bitfield! {
225    #[derive(Clone, Copy, Default)]
226    // pmu_hp_backup_reg_t/active
227    struct HpActiveBackup(u32);
228
229    pub u8,   hp_sleep2active_backup_modem_clk_code, set_hp_sleep2active_backup_modem_clk_code: 5, 4;
230    pub u8,   hp_modem2active_backup_modem_clk_code, set_hp_modem2active_backup_modem_clk_code: 7, 6;
231    pub u8,   hp_sleep2active_backup_clk_sel       , set_hp_sleep2active_backup_clk_sel       : 15, 14;
232    pub u8,   hp_modem2active_backup_clk_sel       , set_hp_modem2active_backup_clk_sel       : 17, 16;
233    pub u8,   hp_sleep2active_backup_mode          , set_hp_sleep2active_backup_mode          : 22, 18;
234    pub u8,   hp_modem2active_backup_mode          , set_hp_modem2active_backup_mode          : 27, 23;
235    pub bool, hp_sleep2active_backup_en            , set_hp_sleep2active_backup_en            : 29;
236    pub bool, hp_modem2active_backup_en            , set_hp_modem2active_backup_en            : 30;
237}
238
239bitfield::bitfield! {
240    #[derive(Clone, Copy, Default)]
241    // pmu_hp_backup_reg_t/modem
242    struct HpModemBackup(u32);
243
244    pub u8,   hp_sleep2modem_backup_modem_clk_code, set_hp_sleep2modem_backup_modem_clk_code: 5, 4;
245    pub u8,   hp_sleep2modem_backup_clk_sel       , set_hp_sleep2modem_backup_clk_sel       : 15, 14;
246    pub u8,   hp_sleep2modem_backup_mode          , set_hp_sleep2modem_backup_mode          : 24, 20;
247    pub bool, hp_sleep2modem_backup_en            , set_hp_sleep2modem_backup_en            : 29;
248}
249
250bitfield::bitfield! {
251    #[derive(Clone, Copy, Default)]
252    // pmu_hp_backup_reg_t/sleep
253    struct HpSleepBackup(u32);
254
255    pub u8,   hp_modem2sleep_backup_modem_clk_code , set_hp_modem2sleep_backup_modem_clk_code : 7, 6;
256    pub u8,   hp_active2sleep_backup_modem_clk_code, set_hp_active2sleep_backup_modem_clk_code: 9, 8;
257    pub u8,   hp_modem2sleep_backup_clk_sel        , set_hp_modem2sleep_backup_clk_sel        : 17, 16;
258    pub u8,   hp_active2sleep_backup_clk_sel       , set_hp_active2sleep_backup_clk_sel       : 19, 18;
259    pub u8,   hp_modem2sleep_backup_mode           , set_hp_modem2sleep_backup_mode           : 24, 20;
260    pub u8,   hp_active2sleep_backup_mode          , set_hp_active2sleep_backup_mode          : 29, 25;
261    pub bool, hp_modem2sleep_backup_en             , set_hp_modem2sleep_backup_en             : 30;
262    pub bool, hp_active2sleep_backup_en            , set_hp_active2sleep_backup_en            : 31;
263}
264
265/// Writes the parts of `pmu_hp_system_init` that are the same in every HP mode.
266macro_rules! hp_system_init {
267    ($state:ident => $s:ident) => {
268        paste::paste! {
269            unsafe {
270                PMU::regs().[<$state _dig_power >]().write(|w| w.bits($s.power.dig_power.0));
271                PMU::regs().[<$state _xtal >]().modify(|_, w| w
272                    .[<$state _xpd_xtal >]().bit($s.power.xtal.xpd_xtal())
273                );
274
275                PMU::regs().[<$state _icg_hp_func >]().write(|w| w.bits($s.clock.icg_func));
276                PMU::regs().[<$state _icg_hp_apb >]().write(|w| w.bits($s.clock.icg_apb));
277                PMU::regs().[<$state _icg_modem >]().write(|w| w
278                    .[<$state _dig_icg_modem_code >]().bits($s.clock.icg_modem_code)
279                );
280                PMU::regs().[<$state _sysclk >]().modify(|_, w| w
281                    .[<$state _dig_sys_clk_no_div >]().bit($s.clock.sysclk.dig_sysclk_nodiv())
282                    .[<$state _icg_sys_clock_en >]().bit($s.clock.sysclk.icg_sysclk_en())
283                    .[<$state _sys_clk_slp_sel >]().bit($s.clock.sysclk.sysclk_slp_sel())
284                    .[<$state _icg_slp_sel >]().bit($s.clock.sysclk.icg_slp_sel())
285                    .[<$state _dig_sys_clk_sel >]().bits($s.clock.sysclk.dig_sysclk_sel())
286                );
287
288                PMU::regs().[<$state _hp_sys_cntl >]().modify(|_, w| w
289                    .[<$state _uart_wakeup_en >]().bit($s.syscntl.uart_wakeup_en())
290                    .[<$state _lp_pad_hold_all >]().bit($s.syscntl.lp_pad_hold_all())
291                    .[<$state _hp_pad_hold_all >]().bit($s.syscntl.hp_pad_hold_all())
292                    .[<$state _dig_pad_slp_sel >]().bit($s.syscntl.dig_pad_slp_sel())
293                    .[<$state _dig_pause_wdt >]().bit($s.syscntl.dig_pause_wdt())
294                    .[<$state _dig_cpu_stall >]().bit($s.syscntl.dig_cpu_stall())
295                );
296
297                PMU::regs().[<$state _bias >]().modify(|_, w| w
298                    .[<$state _dcdc_ccm_enb >]().bit($s.anlg.bias.dcdc_ccm_enb())
299                    .[<$state _dcdc_clear_rdy >]().bit($s.anlg.bias.dcdc_clear_rdy())
300                    .[<$state _dig_pmu_dpcur_bias >]().bits($s.anlg.bias.dig_reg_dpcur_bias())
301                    .[<$state _dig_pmu_dsfmos >]().bits($s.anlg.bias.dig_reg_dsfmos())
302                    .[<$state _dcm_vset >]().bits($s.anlg.bias.dcm_vset())
303                    .[<$state _dcm_mode >]().bits($s.anlg.bias.dcm_mode())
304                    .[<$state _xpd_bias >]().bit($s.anlg.bias.xpd_bias())
305                    .[<$state _xpd_trx >]().bit($s.anlg.bias.xpd_trx())
306                    .[<$state _discnnt_dig_rtc >]().bit($s.anlg.bias.discnnt_dig_rtc())
307                    .[<$state _pd_cur >]().bit($s.anlg.bias.pd_cur())
308                    .sleep().bit($s.anlg.bias.bias_sleep())
309                );
310
311                PMU::regs().[<$state _hp_regulator0 >]().modify(|_, w| w
312                    .[<$state _hp_power_det_bypass >]().bit($s.anlg.regulator0.power_det_bypass())
313                    .[<$state _hp_regulator_slp_mem_xpd >]().bit($s.anlg.regulator0.slp_mem_xpd())
314                    .[<$state _hp_regulator_slp_logic_xpd >]().bit($s.anlg.regulator0.slp_logic_xpd())
315                    .[<$state _hp_regulator_xpd >]().bit($s.anlg.regulator0.xpd())
316                    .[<$state _hp_regulator_slp_mem_dbias >]().bits($s.anlg.regulator0.slp_mem_dbias())
317                    .[<$state _hp_regulator_slp_logic_dbias >]().bits($s.anlg.regulator0.slp_logic_dbias())
318                    .[<$state _hp_regulator_dbias >]().bits($s.anlg.regulator0.dbias())
319                );
320
321                PMU::regs().[<$state _hp_regulator1 >]().modify(|_, w| w
322                    .[<$state _hp_regulator_drv_b >]().bits($s.anlg.regulator1.drv_b())
323                );
324
325                PMU::regs().[<$state _backup >]().write(|w| w.bits($s.retention));
326                PMU::regs().[<$state _backup_clk >]().write(|w| w.bits($s.backup_clk));
327            }
328        }
329    };
330}
331
332// pmu_hp_system_param_t
333struct HpSystemInit {
334    power: HpSysPower,
335    clock: SystemClockParam,
336    syscntl: HpSysCntlReg,
337    anlg: HpAnalog,
338    retention: u32,
339    backup_clk: u32,
340}
341
342impl HpSystemInit {
343    /// The active-mode analog configuration, which the modem mode shares.
344    ///
345    /// PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT, PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT
346    fn active_analog() -> HpAnalog {
347        let mut anlg = HpAnalog::default();
348        anlg.bias.set_dcdc_ccm_enb(false);
349        anlg.bias.set_dcdc_clear_rdy(false);
350        anlg.bias.set_dig_reg_dpcur_bias(3);
351        anlg.bias.set_dig_reg_dsfmos(15);
352        anlg.bias.set_dcm_mode(3);
353        anlg.bias.set_dcm_vset(24);
354        anlg.bias.set_xpd_trx(true);
355        anlg.bias.set_xpd_bias(true);
356        anlg.bias.set_discnnt_dig_rtc(false);
357        anlg.bias.set_pd_cur(false);
358        anlg.bias.set_bias_sleep(false);
359
360        anlg.regulator0.set_power_det_bypass(false);
361        anlg.regulator0.set_dbias_sel(true);
362        anlg.regulator0.set_dbias_init(true);
363        anlg.regulator0.set_slp_mem_xpd(false);
364        anlg.regulator0.set_slp_logic_xpd(false);
365        anlg.regulator0.set_xpd(true);
366        anlg.regulator0.set_slp_mem_dbias(0);
367        anlg.regulator0.set_slp_logic_dbias(0);
368        anlg.regulator0.set_dbias(0);
369
370        // get_act_hp_drvb
371        anlg.regulator1.set_drv_b(HP_CALI_DRVB);
372
373        anlg
374    }
375
376    fn active() -> Self {
377        // PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT
378        let mut power = HpSysPower::default();
379        power.clk.set_i2c_iso_en(false);
380        power.clk.set_i2c_retention(false);
381        power.clk.set_xpd_bb_i2c(true);
382        power.xtal.set_xpd_xtal(true);
383
384        // PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT
385        let mut clock = SystemClockParam {
386            icg_func: 0xffff_ffff,
387            icg_apb: 0xffff_ffff,
388            icg_modem_code: ICG_MODEM_CODE_ACTIVE,
389            ..Default::default()
390        };
391        clock.sysclk.set_icg_sysclk_en(true);
392        clock.sysclk.set_dig_sysclk_sel(PMU_CLK_SRC_XTAL);
393
394        // PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT
395        let syscntl = HpSysCntlReg::default();
396
397        // PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT
398        let mut retention = HpActiveBackup::default();
399        retention.set_hp_sleep2active_backup_modem_clk_code(2);
400        retention.set_hp_modem2active_backup_modem_clk_code(2);
401        retention.set_hp_sleep2active_backup_clk_sel(PMU_CLK_SRC_XTAL_X2);
402        retention.set_hp_modem2active_backup_clk_sel(PMU_CLK_SRC_XTAL);
403        retention.set_hp_sleep2active_backup_mode(hp_retention_regdma_config(0, 0));
404        retention.set_hp_modem2active_backup_mode(hp_retention_regdma_config(0, 2));
405        retention.set_hp_sleep2active_backup_en(false);
406        retention.set_hp_modem2active_backup_en(false);
407
408        Self {
409            power,
410            clock,
411            syscntl,
412            anlg: Self::active_analog(),
413            retention: retention.0,
414            backup_clk: 0xffff_ffff,
415        }
416    }
417
418    fn modem() -> Self {
419        // PMU_HP_MODEM_POWER_CONFIG_DEFAULT
420        let mut power = HpSysPower::default();
421        power.dig_power.set_cpu_pd_en(true);
422        power.clk.set_xpd_bb_i2c(true);
423        power.xtal.set_xpd_xtal(true);
424
425        // PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT
426        let mut clock = SystemClockParam {
427            icg_func: ICG_FUNC_ENA_HPBUS,
428            icg_apb: 0,
429            icg_modem_code: ICG_MODEM_CODE_MODEM,
430            ..Default::default()
431        };
432        clock.sysclk.set_icg_sysclk_en(true);
433        clock.sysclk.set_sysclk_slp_sel(true);
434        clock.sysclk.set_icg_slp_sel(true);
435        clock.sysclk.set_dig_sysclk_sel(PMU_CLK_SRC_PLL);
436
437        // PMU_HP_MODEM_DIGITAL_CONFIG_DEFAULT
438        let mut syscntl = HpSysCntlReg::default();
439        syscntl.set_uart_wakeup_en(true);
440        syscntl.set_dig_pause_wdt(true);
441        syscntl.set_dig_cpu_stall(true);
442
443        // PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT
444        let mut retention = HpModemBackup::default();
445        retention.set_hp_sleep2modem_backup_modem_clk_code(1);
446        retention.set_hp_sleep2modem_backup_clk_sel(PMU_CLK_SRC_XTAL);
447        retention.set_hp_sleep2modem_backup_mode(hp_retention_regdma_config(0, 1));
448        retention.set_hp_sleep2modem_backup_en(false);
449
450        Self {
451            power,
452            clock,
453            syscntl,
454            anlg: Self::active_analog(),
455            retention: retention.0,
456            backup_clk: 0xffff_ffff,
457        }
458    }
459
460    fn sleep() -> Self {
461        // PMU_HP_SLEEP_POWER_CONFIG_DEFAULT
462        let mut power = HpSysPower::default();
463        power.dig_power.set_vdd_flash_mode(3);
464        power.clk.set_i2c_iso_en(true);
465        power.clk.set_i2c_retention(true);
466
467        // PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT
468        let mut clock = SystemClockParam {
469            icg_func: 0,
470            icg_apb: 0,
471            icg_modem_code: ICG_MODEM_CODE_SLEEP,
472            ..Default::default()
473        };
474        clock.sysclk.set_sysclk_slp_sel(true);
475        clock.sysclk.set_icg_slp_sel(true);
476        clock.sysclk.set_dig_sysclk_sel(PMU_CLK_SRC_XTAL);
477
478        // PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT
479        let mut syscntl = HpSysCntlReg::default();
480        syscntl.set_uart_wakeup_en(true);
481        syscntl.set_dig_pad_slp_sel(true);
482        syscntl.set_dig_pause_wdt(true);
483        syscntl.set_dig_cpu_stall(true);
484
485        // PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT
486        let mut anlg = HpAnalog::default();
487        anlg.bias.set_dcdc_ccm_enb(true);
488        anlg.bias.set_dcdc_clear_rdy(false);
489        anlg.bias.set_dig_reg_dpcur_bias(1);
490        anlg.bias.set_dig_reg_dsfmos(4);
491        anlg.bias.set_dcm_mode(3);
492        anlg.bias.set_dcm_vset(20);
493        anlg.bias.set_xpd_trx(false);
494        anlg.bias.set_xpd_bias(false);
495        anlg.bias.set_discnnt_dig_rtc(false);
496        anlg.bias.set_pd_cur(true);
497        anlg.bias.set_bias_sleep(true);
498        anlg.regulator0.set_xpd(true);
499        anlg.regulator0.set_dbias(0);
500        anlg.regulator1.set_drv_b(25);
501
502        // PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT
503        let mut retention = HpSleepBackup::default();
504        retention.set_hp_modem2sleep_backup_modem_clk_code(0);
505        retention.set_hp_active2sleep_backup_modem_clk_code(2);
506        retention.set_hp_modem2sleep_backup_clk_sel(PMU_CLK_SRC_XTAL);
507        retention.set_hp_active2sleep_backup_clk_sel(PMU_CLK_SRC_XTAL_X2);
508        retention.set_hp_modem2sleep_backup_mode(hp_retention_regdma_config(1, 1));
509        retention.set_hp_active2sleep_backup_mode(hp_retention_regdma_config(1, 0));
510        retention.set_hp_modem2sleep_backup_en(false);
511        retention.set_hp_active2sleep_backup_en(false);
512
513        Self {
514            power,
515            clock,
516            syscntl,
517            anlg,
518            retention: retention.0,
519            backup_clk: 0xffff_ffff,
520        }
521    }
522
523    fn init_default() {
524        let active = Self::active();
525        let modem = Self::modem();
526        let sleep = Self::sleep();
527
528        hp_system_init!(hp_active => active);
529        hp_system_init!(hp_modem => modem);
530        hp_system_init!(hp_sleep => sleep);
531
532        // The clock tree owns the power of the root clock circuits (BBPLL, XTAL_X2) in the active
533        // mode, so only the analog I2C master is configured there.
534        PMU::regs().hp_active_hp_ck_power().modify(|_, w| {
535            w.hp_active_xpd_bb_i2c().bit(active.power.clk.xpd_bb_i2c());
536            w.hp_active_i2c_iso_en().bit(active.power.clk.i2c_iso_en());
537            w.hp_active_i2c_retention()
538                .bit(active.power.clk.i2c_retention())
539        });
540        PMU::regs()
541            .hp_modem_hp_ck_power()
542            .write(|w| unsafe { w.bits(modem.power.clk.0) });
543        PMU::regs()
544            .hp_modem_xtal()
545            .modify(|_, w| w.hp_modem_xpd_xtalx2().bit(modem.power.xtal.xpd_xtalx2()));
546        PMU::regs()
547            .hp_sleep_hp_ck_power()
548            .write(|w| unsafe { w.bits(sleep.power.clk.0) });
549        PMU::regs()
550            .hp_sleep_xtal()
551            .modify(|_, w| w.hp_sleep_xpd_xtalx2().bit(sleep.power.xtal.xpd_xtalx2()));
552
553        // Only the HP_ACTIVE mode has the regulator select bits.
554        PMU::regs().hp_active_hp_regulator0().modify(|_, w| {
555            w.dig_regulator0_dbias_sel()
556                .bit(active.anlg.regulator0.dbias_sel());
557            w.dig_dbias_init().bit(active.anlg.regulator0.dbias_init())
558        });
559
560        // Some PMU initial parameter configuration
561        PMU::regs()
562            .imm_modem_icg()
563            .write(|w| w.update_dig_icg_modem_en().set_bit());
564        PMU::regs()
565            .imm_sleep_sysclk()
566            .write(|w| w.update_dig_icg_switch().set_bit());
567
568        const PMU_SLEEP_PROTECT_HP_LP_SLEEP: u8 = 2;
569        PMU::regs()
570            .slp_wakeup_cntl3()
571            .modify(|_, w| unsafe { w.sleep_prt_sel().bits(PMU_SLEEP_PROTECT_HP_LP_SLEEP) });
572
573        // pmu_ll_set_dcdc_ccm_sw_en
574        PMU::regs()
575            .dcm_ctrl()
576            .modify(|_, w| w.dcdc_ccm_sw_en().set_bit());
577
578        // lp_aon_ll_set_ldo_sw: the DC-DC LDO mode for a VDD below about 2.6 V.
579        const DREG_LDO_HW: u32 = 1 << 5;
580        const DREG_LDO_SW_SHIFT: u32 = 11;
581        const DREG_LDO_SW_MASK: u32 = 0xf << DREG_LDO_SW_SHIFT;
582        LP_AON::regs().date().modify(|r, w| unsafe {
583            w.bits((r.bits() & !(DREG_LDO_HW | DREG_LDO_SW_MASK)) | (15 << DREG_LDO_SW_SHIFT))
584        });
585
586        // The BLE bandgap uses the calibrated ocode.
587        let ulp_ocode = if regi2c::I2C_ULP_IR_FORCE_CODE.read() != 0 {
588            regi2c::I2C_ULP_EXT_CODE.read()
589        } else {
590            regi2c::I2C_ULP_OCODE.read()
591        };
592        PMU::regs().ble_bandgap_ctrl().modify(|_, w| unsafe {
593            w.ext_ocode().bits(ulp_ocode);
594            w.ext_force_ocode().set_bit()
595        });
596    }
597}
598
599bitfield::bitfield! {
600    #[derive(Clone, Copy, Default)]
601    // pmu_lp_power_t.0
602    pub struct LpDigPower(u32);
603
604    pub u8,   vdd_io_mode   , set_vdd_io_mode   : 26, 23;
605    pub bool, bod_source_sel, set_bod_source_sel: 27;
606    pub u8,   vddbat_mode   , set_vddbat_mode   : 29, 28;
607    pub bool, mem_dslp      , set_mem_dslp      : 30;
608    pub bool, peri_pd_en    , set_peri_pd_en    : 31;
609}
610
611bitfield::bitfield! {
612    #[derive(Clone, Copy, Default)]
613    // pmu_lp_power_t.1
614    pub struct LpClkPower(u32);
615
616    pub bool, xpd_lppll  , set_xpd_lppll  : 27;
617    pub bool, xpd_xtal32k, set_xpd_xtal32k: 28;
618    pub bool, xpd_rc32k  , set_xpd_rc32k  : 29;
619    pub bool, xpd_fosc   , set_xpd_fosc   : 30;
620    pub bool, pd_osc     , set_pd_osc     : 31;
621}
622
623#[derive(Clone, Copy, Default)]
624// pmu_sleep_power_config_t.lp_sys
625pub struct LpSysPower {
626    pub dig_power: LpDigPower,
627    pub clk_power: LpClkPower,
628    // Only the LP_SLEEP mode has this register.
629    pub xtal: XtalPower,
630}
631
632bitfield::bitfield! {
633    #[derive(Clone, Copy, Default)]
634    // pmu_lp_analog_t.1
635    pub struct LpAnalogRegulator0(u32);
636
637    pub bool, slp_xpd  , set_slp_xpd  : 21;
638    pub bool, xpd      , set_xpd      : 22;
639    pub u8,   slp_dbias, set_slp_dbias: 26, 23;
640    pub u8,   dbias    , set_dbias    : 31, 27;
641}
642
643bitfield::bitfield! {
644    #[derive(Clone, Copy, Default)]
645    // pmu_lp_analog_t.2
646    pub struct LpAnalogRegulator1(u32);
647
648    pub u8, drv_b, set_drv_b: 31, 28;
649}
650
651#[derive(Clone, Copy, Default)]
652// pmu_lp_analog_t
653pub struct LpAnalog {
654    // Only the LP_SLEEP mode has this register.
655    pub bias: AnalogBias,
656    pub regulator0: LpAnalogRegulator0,
657    pub regulator1: LpAnalogRegulator1,
658}
659
660/// Writes the parts of `pmu_lp_system_init` that are the same in every LP mode.
661macro_rules! lp_system_init {
662    ($state:ident => $s:ident) => {
663        paste::paste! {
664            unsafe {
665                PMU::regs().[< $state _dig_power >]().write(|w| w.bits($s.power.dig_power.0));
666                PMU::regs().[< $state _ck_power >]().write(|w| w.bits($s.power.clk_power.0));
667
668                PMU::regs().[< $state _regulator0 >]().modify(|_, w| w
669                    .[< $state _regulator_slp_xpd >]().bit($s.anlg.regulator0.slp_xpd())
670                    .[< $state _regulator_xpd >]().bit($s.anlg.regulator0.xpd())
671                    .[< $state _regulator_slp_dbias >]().bits($s.anlg.regulator0.slp_dbias())
672                    .[< $state _regulator_dbias >]().bits($s.anlg.regulator0.dbias())
673                );
674
675                PMU::regs().[< $state _regulator1 >]().modify(|_, w| w
676                    .[< $state _regulator_drv_b >]().bits($s.anlg.regulator1.drv_b())
677                );
678            }
679        }
680    };
681}
682
683// pmu_lp_system_param_t
684struct LpSystemInit {
685    power: LpSysPower,
686    anlg: LpAnalog,
687}
688
689impl LpSystemInit {
690    fn active() -> Self {
691        // PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT
692        let mut power = LpSysPower::default();
693        power.clk_power.set_xpd_xtal32k(xtal32k::use_xtal32k());
694        power.clk_power.set_xpd_fosc(true);
695
696        // PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT
697        let mut anlg = LpAnalog::default();
698        anlg.regulator0.set_xpd(true);
699        anlg.regulator0.set_dbias(LP_CALI_DBIAS);
700
701        Self { power, anlg }
702    }
703
704    fn sleep() -> Self {
705        // PMU_LP_SLEEP_POWER_CONFIG_DEFAULT
706        let power = LpSysPower::default();
707
708        // PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT
709        let mut anlg = LpAnalog::default();
710        anlg.bias.set_dcdc_ccm_enb(true);
711        anlg.bias.set_dcdc_clear_rdy(false);
712        anlg.bias.set_dig_reg_dpcur_bias(1);
713        anlg.bias.set_dig_reg_dsfmos(4);
714        anlg.bias.set_dcm_mode(3);
715        anlg.bias.set_dcm_vset(20);
716        anlg.bias.set_xpd_bias(false);
717        anlg.bias.set_discnnt_dig_rtc(true);
718        anlg.bias.set_pd_cur(true);
719        anlg.bias.set_bias_sleep(true);
720        anlg.regulator0.set_xpd(true);
721        anlg.regulator0.set_dbias(3);
722
723        Self { power, anlg }
724    }
725
726    fn init_default() {
727        let active = Self::active();
728        let sleep = Self::sleep();
729
730        // The LP_ACTIVE registers are the ones named after HP_SLEEP.
731        lp_system_init!(hp_sleep_lp => active);
732        lp_system_init!(lp_sleep_lp => sleep);
733
734        PMU::regs().lp_sleep_xtal().modify(|_, w| {
735            w.lp_sleep_xpd_xtal().bit(sleep.power.xtal.xpd_xtal());
736            w.lp_sleep_xpd_xtalx2().bit(sleep.power.xtal.xpd_xtalx2())
737        });
738
739        let bias = sleep.anlg.bias;
740        PMU::regs().lp_sleep_bias().modify(|_, w| unsafe {
741            w.lp_sleep_dcdc_ccm_enb().bit(bias.dcdc_ccm_enb());
742            w.lp_sleep_dcdc_clear_rdy().bit(bias.dcdc_clear_rdy());
743            w.lp_sleep_dig_pmu_dpcur_bias()
744                .bits(bias.dig_reg_dpcur_bias());
745            w.lp_sleep_dig_pmu_dsfmos().bits(bias.dig_reg_dsfmos());
746            w.lp_sleep_dcm_vset().bits(bias.dcm_vset());
747            w.lp_sleep_dcm_mode().bits(bias.dcm_mode());
748            w.lp_sleep_xpd_bias().bit(bias.xpd_bias());
749            w.lp_sleep_discnnt_dig_rtc().bit(bias.discnnt_dig_rtc());
750            w.lp_sleep_pd_cur().bit(bias.pd_cur());
751            w.sleep().bit(bias.bias_sleep())
752        });
753    }
754}
755
756pub(crate) fn init(_config: &ClockConfig) {
757    // pmu_init()
758
759    // Peripheral reg i2c power up
760    PMU::regs().rf_pwc().modify(|_, w| {
761        w.xpd_perif_i2c().set_bit();
762        w.xpd_rftx_i2c().set_bit();
763        w.xpd_rfrx_i2c().set_bit()
764    });
765
766    HpSystemInit::init_default();
767    LpSystemInit::init_default();
768
769    pmu_power_domain_force_default();
770
771    // This is the part of esp-idf's `rtc_clk_init` that has to run before the CPU can be switched
772    // to the BBPLL.
773
774    // Tuning of the internal oscillators. Unlike on the other chips, RC_SLOW is tuned through the
775    // RC32K register (see the comment in esp-idf's rtc_clk_init.c).
776    LP_CLKRST::regs()
777        .fosc_cntl()
778        .modify(|_, w| unsafe { w.fosc_dfreq().bits(CK8M_DFREQ) });
779    LP_CLKRST::regs()
780        .rc32k_cntl()
781        .modify(|_, w| unsafe { w.rc32k_dfreq().bits(SCK_DCAP) });
782
783    // Switch the DC-DC converter to CCM mode and apply its defaults.
784    PMU::regs()
785        .dcm_ctrl()
786        .modify(|_, w| w.dcdc_ccm_sw_en().set_bit());
787    PMU::regs()
788        .hp_active_bias()
789        .modify(|_, w| w.hp_active_dcdc_ccm_enb().clear_bit());
790
791    regi2c::I2C_DCDC_CCM_DREG0.write_field(24);
792    regi2c::I2C_DCDC_CCM_PCUR_LIMIT0.write_field(4);
793    regi2c::I2C_DCDC_VCM_DREG0.write_field(24);
794    regi2c::I2C_DCDC_VCM_PCUR_LIMIT0.write_field(2);
795    regi2c::I2C_DCDC_XPD_TRX.write_field(0);
796
797    // Power down the RF PLL.
798    PMU::regs()
799        .date()
800        .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << 25)) });
801
802    // Regulator settings for the active modes.
803    PMU::regs()
804        .hp_active_hp_regulator0()
805        .modify(|_, w| w.hp_active_hp_regulator_xpd().set_bit());
806    PMU::regs()
807        .hp_active_hp_regulator1()
808        .modify(|_, w| unsafe { w.hp_active_hp_regulator_drv_b().bits(HP_CALI_DRVB) });
809    // The LP active mode registers are the ones named after HP sleep.
810    PMU::regs()
811        .hp_sleep_lp_regulator0()
812        .modify(|_, w| unsafe { w.hp_sleep_lp_regulator_dbias().bits(LP_CALI_DBIAS) });
813}
814
815/// SOC Reset Reason.
816#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
817pub enum SocResetReason {
818    /// Powers on reset.
819    ///
820    /// In ESP-IDF this value (0x01) can *also* be `ChipBrownOut`
821    ChipPowerOn   = 0x01,
822    /// Software resets the digital core by LP_AON_HPSYS_SW_RESET
823    CoreSw        = 0x03,
824    /// Deep sleep reset the digital core
825    CoreDeepSleep = 0x05,
826    /// Main watch dog 0 resets digital core
827    CoreMwdt0     = 0x07,
828    /// Main watch dog 1 resets digital core
829    CoreMwdt1     = 0x08,
830    /// RTC watch dog resets digital core
831    CoreRtcWdt    = 0x09,
832    /// Main watch dog 0 resets CPU 0
833    Cpu0Mwdt0     = 0x0B,
834    /// Software resets CPU 0 by LP_AON_CPU_CORE0_SW_RESET
835    Cpu0Sw        = 0x0C,
836    /// RTC watch dog resets CPU 0
837    Cpu0RtcWdt    = 0x0D,
838    /// VDD voltage is not stable and resets the digital core
839    SysBrownOut   = 0x0F,
840    /// RTC watch dog resets digital core and rtc module
841    SysRtcWdt     = 0x10,
842    /// Main watch dog 1 resets CPU 0
843    Cpu0Mwdt1     = 0x11,
844    /// Super watch dog resets the digital core and rtc module
845    SysSuperWdt   = 0x12,
846    /// Glitch on power resets the digital core and rtc module
847    CorePwrGlitch = 0x13,
848    /// eFuse CRC error resets the digital core
849    CoreEfuseCrc  = 0x14,
850    /// USB UART resets the digital core
851    CoreUsbUart   = 0x15,
852    /// USB JTAG resets the digital core
853    CoreUsbJtag   = 0x16,
854    /// JTAG resets CPU 0
855    Cpu0JtagCpu   = 0x18,
856    /// CPU lockup reset
857    CpuLockup     = 0x1A,
858}