Skip to main content

esp_hal/rtc_cntl/rtc/
esp32s31.rs

1use strum::FromRepr;
2
3use crate::{
4    peripherals::{MODEM_LPCON, MODEM_SYSCON, PMU},
5    soc::{
6        clocks::{ClockConfig, LpSlowClkConfig},
7        regi2c,
8    },
9};
10
11const HP_CALI_DBIAS: u32 = 26;
12const LP_CALI_DBIAS: u32 = 26;
13
14const ICG_NOGATING_MODEM: u8 = 1 << 1;
15const ICG_NOGATING_ACTIVE: u8 = 1 << 2;
16const ICG_NOGATING_ACTIVE_MODEM: u8 = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM;
17
18const fn hp_retention_regdma_config(dir: u32, entry: u32) -> u32 {
19    ((dir << 4) | (entry & 0xf)) & 0x1f
20}
21
22bitfield::bitfield! {
23    #[derive(Clone, Copy, Default)]
24    pub struct HpDigPower(u32);
25
26    pub bool, vdd_spi_pd_en, set_vdd_spi_pd_en: 20;
27    pub bool, hp_alive_pd_en, set_hp_alive_pd_en: 21;
28    pub bool, hp_mem_dslp, set_hp_mem_dslp: 22;
29    pub u8, hp_mem_pd_en, set_hp_mem_pd_en: 26, 23;
30    pub bool, modem_top_pd_en, set_modem_top_pd_en: 27;
31    pub bool, hp_cnnt_pd_en, set_hp_cnnt_pd_en: 28;
32    pub bool, hp_cpu_pd_en, set_hp_cpu_pd_en: 29;
33    pub bool, modem_pwr_pd_en, set_modem_pwr_pd_en: 30;
34    pub bool, top_pd_en, set_top_pd_en: 31;
35}
36
37bitfield::bitfield! {
38    #[derive(Clone, Copy, Default)]
39    pub struct HpClkPower(u32);
40
41    pub bool, xpd_xtalx2, set_xpd_xtalx2: 19;
42    pub bool, i2c_iso_en, set_i2c_iso_en: 20;
43    pub bool, i2c_retention, set_i2c_retention: 21;
44    pub bool, xpd_bb_i2c, set_xpd_bb_i2c: 22;
45    pub bool, xpd_cpll_i2c, set_xpd_cpll_i2c: 23;
46    pub bool, xpd_bbpll_i2c, set_xpd_bbpll_i2c: 24;
47    pub bool, xpd_apll_i2c, set_xpd_apll_i2c: 25;
48    pub bool, xpd_mpll_i2c, set_xpd_mpll_i2c: 26;
49    pub bool, xpd_cpll, set_xpd_cpll: 27;
50    pub bool, xpd_bbpll, set_xpd_bbpll: 28;
51    pub bool, xpd_apll, set_xpd_apll: 29;
52    pub bool, xpd_mpll, set_xpd_mpll: 30;
53}
54
55bitfield::bitfield! {
56    #[derive(Clone, Copy, Default)]
57    pub struct XtalPower(u32);
58
59    pub bool, xpd_xtal, set_xpd_xtal: 31;
60}
61
62bitfield::bitfield! {
63    #[derive(Clone, Copy, Default)]
64    pub struct HpIcgModem(u32);
65
66    pub u8, code, set_code: 31, 30;
67}
68
69bitfield::bitfield! {
70    #[derive(Clone, Copy, Default)]
71    pub struct HpSysclk(u32);
72
73    pub bool, dig_sysclk_nodiv, set_dig_sysclk_nodiv: 26;
74    pub bool, icg_sysclk_en, set_icg_sysclk_en: 27;
75    pub bool, sysclk_slp_sel, set_sysclk_slp_sel: 28;
76    pub bool, icg_slp_sel, set_icg_slp_sel: 29;
77    pub u8, dig_sysclk_sel, set_dig_sysclk_sel: 31, 30;
78}
79
80bitfield::bitfield! {
81    #[derive(Clone, Copy, Default)]
82    pub struct HpSysCntl(u32);
83
84    pub bool, c_channel, set_c_channel: 23;
85    pub bool, uart_wakeup_en, set_uart_wakeup_en: 24;
86    pub bool, lp_pad_hold_all, set_lp_pad_hold_all: 25;
87    pub bool, hp_pad_hold_all, set_hp_pad_hold_all: 26;
88    pub bool, dig_pad_slp_sel, set_dig_pad_slp_sel: 27;
89    pub bool, dig_pause_wdt, set_dig_pause_wdt: 28;
90    pub bool, dig_cpu_stall, set_dig_cpu_stall: 29;
91}
92
93bitfield::bitfield! {
94    #[derive(Clone, Copy, Default)]
95    pub struct AnalogBias(u32);
96
97    pub bool, xpd_bias, set_xpd_bias: 25;
98    pub u8, dbg_atten, set_dbg_atten: 29, 26;
99    pub bool, pd_cur, set_pd_cur: 30;
100    pub bool, bias_sleep, set_bias_sleep: 31;
101}
102
103bitfield::bitfield! {
104    #[derive(Clone, Copy, Default)]
105    pub struct HpRegulator0(u32);
106
107    pub bool, dig_dbias_init, set_dig_dbias_init: 3;
108    pub u8, lp_dbias_vol, set_lp_dbias_vol: 8, 4;
109    pub u8, hp_dbias_vol, set_hp_dbias_vol: 13, 9;
110    pub bool, dbias_sel, set_dbias_sel: 14;
111    pub bool, slp_connect_en, set_slp_connect_en: 15;
112    pub bool, slp_mem_xpd, set_slp_mem_xpd: 16;
113    pub bool, slp_logic_xpd, set_slp_logic_xpd: 17;
114    pub bool, xpd, set_xpd: 18;
115    pub u8, slp_mem_dbias, set_slp_mem_dbias: 22, 19;
116    pub u8, slp_logic_dbias, set_slp_logic_dbias: 26, 23;
117    pub u8, dbias, set_dbias: 31, 27;
118}
119
120bitfield::bitfield! {
121    #[derive(Clone, Copy, Default)]
122    pub struct HpRegulator1(u32);
123
124    pub u32, drv_b, set_drv_b: 31, 8;
125}
126
127bitfield::bitfield! {
128    #[derive(Clone, Copy, Default)]
129    pub struct HpBackup(u32);
130
131    pub u8, sleep2active_modem_clk_code, set_sleep2active_modem_clk_code: 5, 4;
132    pub u8, modem2active_modem_clk_code, set_modem2active_modem_clk_code: 7, 6;
133    pub bool, active_retention_mode, set_active_retention_mode: 10;
134    pub bool, sleep2active_retention_en, set_sleep2active_retention_en: 11;
135    pub bool, modem2active_retention_en, set_modem2active_retention_en: 12;
136    pub u8, sleep2active_backup_clk_sel, set_sleep2active_backup_clk_sel: 15, 14;
137    pub u8, modem2active_backup_clk_sel, set_modem2active_backup_clk_sel: 17, 16;
138    pub u8, sleep2active_backup_mode, set_sleep2active_backup_mode: 22, 18;
139    pub u8, modem2active_backup_mode, set_modem2active_backup_mode: 27, 23;
140    pub bool, sleep2active_backup_en, set_sleep2active_backup_en: 29;
141    pub bool, modem2active_backup_en, set_modem2active_backup_en: 30;
142
143    pub u8, sleep2modem_modem_clk_code, set_sleep2modem_modem_clk_code: 5, 4;
144    pub bool, modem_retention_mode, set_modem_retention_mode: 10;
145    pub bool, sleep2modem_retention_en, set_sleep2modem_retention_en: 11;
146    pub u8, sleep2modem_backup_clk_sel, set_sleep2modem_backup_clk_sel: 15, 14;
147    pub u8, sleep2modem_backup_mode, set_sleep2modem_backup_mode: 24, 20;
148    pub bool, sleep2modem_backup_en, set_sleep2modem_backup_en: 29;
149
150    pub u8, modem2sleep_modem_clk_code, set_modem2sleep_modem_clk_code: 7, 6;
151    pub u8, active2sleep_modem_clk_code, set_active2sleep_modem_clk_code: 9, 8;
152    pub bool, sleep_retention_mode, set_sleep_retention_mode: 10;
153    pub bool, modem2sleep_retention_en, set_modem2sleep_retention_en: 12;
154    pub bool, active2sleep_retention_en, set_active2sleep_retention_en: 13;
155    pub u8, modem2sleep_backup_clk_sel, set_modem2sleep_backup_clk_sel: 17, 16;
156    pub u8, active2sleep_backup_clk_sel, set_active2sleep_backup_clk_sel: 19, 18;
157    pub u8, modem2sleep_backup_mode, set_modem2sleep_backup_mode: 24, 20;
158    pub u8, active2sleep_backup_mode, set_active2sleep_backup_mode: 29, 25;
159    pub bool, modem2sleep_backup_en, set_modem2sleep_backup_en: 30;
160    pub bool, active2sleep_backup_en, set_active2sleep_backup_en: 31;
161}
162
163#[derive(Clone, Copy, Default)]
164struct HpSystemPower {
165    dig_power: HpDigPower,
166    clk_power: HpClkPower,
167    xtal: XtalPower,
168}
169
170#[derive(Clone, Copy)]
171struct HpSystemClock {
172    icg_func: [u32; 2],
173    icg_apb: [u32; 2],
174    icg_modem: HpIcgModem,
175    sysclk: HpSysclk,
176}
177
178#[derive(Clone, Copy)]
179struct HpSystemDigital {
180    syscntl: HpSysCntl,
181}
182
183#[derive(Clone, Copy)]
184struct HpSystemAnalog {
185    bias: AnalogBias,
186    regulator0: HpRegulator0,
187    regulator1: HpRegulator1,
188}
189
190#[derive(Clone, Copy)]
191struct HpSystemRetention {
192    retention: HpBackup,
193    backup_clk: [u32; 2],
194}
195
196#[derive(Clone, Copy)]
197struct HpSystemInit {
198    power: HpSystemPower,
199    clock: HpSystemClock,
200    digital: HpSystemDigital,
201    analog: HpSystemAnalog,
202    retention: HpSystemRetention,
203}
204
205impl HpSystemInit {
206    // PMU_HP_ACTIVE_*_CONFIG_DEFAULT
207    fn active() -> Self {
208        let mut power = HpSystemPower::default();
209        power.clk_power.set_xpd_bb_i2c(true);
210        power.clk_power.set_xpd_cpll_i2c(true);
211        power.clk_power.set_xpd_bbpll_i2c(true);
212        power.clk_power.set_xpd_mpll_i2c(true);
213        power.clk_power.set_xpd_cpll(true);
214        power.clk_power.set_xpd_bbpll(true);
215        power.clk_power.set_xpd_mpll(true);
216        power.xtal.set_xpd_xtal(true);
217
218        let mut icg_modem = HpIcgModem::default();
219        icg_modem.set_code(2);
220        let mut sysclk = HpSysclk::default();
221        sysclk.set_icg_sysclk_en(true);
222        let mut syscntl = HpSysCntl::default();
223        syscntl.set_c_channel(true);
224
225        let mut bias = AnalogBias::default();
226        bias.set_xpd_bias(true);
227        let mut regulator0 = HpRegulator0::default();
228        regulator0.set_dig_dbias_init(true);
229        regulator0.set_lp_dbias_vol(0xd);
230        regulator0.set_hp_dbias_vol(0x1c);
231        regulator0.set_dbias_sel(true);
232        regulator0.set_xpd(true);
233        regulator0.set_dbias(HP_CALI_DBIAS as u8);
234
235        let mut retention = HpBackup::default();
236        retention.set_sleep2active_modem_clk_code(2);
237        retention.set_modem2active_modem_clk_code(2);
238        retention.set_sleep2active_backup_mode(hp_retention_regdma_config(0, 0) as u8);
239        retention.set_modem2active_backup_mode(hp_retention_regdma_config(0, 2) as u8);
240
241        Self {
242            power,
243            clock: HpSystemClock {
244                icg_func: [u32::MAX; 2],
245                icg_apb: [u32::MAX; 2],
246                icg_modem,
247                sysclk,
248            },
249            digital: HpSystemDigital { syscntl },
250            analog: HpSystemAnalog {
251                bias,
252                regulator0,
253                regulator1: HpRegulator1::default(),
254            },
255            retention: HpSystemRetention {
256                retention,
257                backup_clk: [u32::MAX; 2],
258            },
259        }
260    }
261
262    // PMU_HP_MODEM_*_CONFIG_DEFAULT
263    fn modem() -> Self {
264        let mut power = HpSystemPower::default();
265        power.clk_power.set_i2c_iso_en(true);
266        power.clk_power.set_i2c_retention(true);
267        power.clk_power.set_xpd_bb_i2c(true);
268        power.clk_power.set_xpd_cpll_i2c(true);
269        power.clk_power.set_xpd_bbpll_i2c(true);
270        power.clk_power.set_xpd_cpll(true);
271        power.clk_power.set_xpd_bbpll(true);
272        power.xtal.set_xpd_xtal(true);
273
274        let mut icg_modem = HpIcgModem::default();
275        icg_modem.set_code(1);
276        let mut sysclk = HpSysclk::default();
277        sysclk.set_icg_sysclk_en(true);
278        sysclk.set_sysclk_slp_sel(true);
279        sysclk.set_icg_slp_sel(true);
280        let mut syscntl = HpSysCntl::default();
281        syscntl.set_c_channel(true);
282        syscntl.set_lp_pad_hold_all(true);
283        syscntl.set_hp_pad_hold_all(true);
284        syscntl.set_dig_pause_wdt(true);
285        syscntl.set_dig_cpu_stall(true);
286
287        let mut regulator0 = HpRegulator0::default();
288        regulator0.set_xpd(true);
289        regulator0.set_dbias(HP_CALI_DBIAS as u8);
290
291        let mut retention = HpBackup::default();
292        retention.set_sleep2modem_modem_clk_code(1);
293        retention.set_sleep2modem_backup_mode(hp_retention_regdma_config(0, 1) as u8);
294
295        Self {
296            power,
297            clock: HpSystemClock {
298                // PMU_ICG_FUNC_ENA_ETM=40 and PMU_ICG_FUNC_ENA_BUS=47.
299                icg_func: [0, (1 << (40 - 32)) | (1 << (47 - 32))],
300                icg_apb: [0; 2],
301                icg_modem,
302                // The S31 IDF deliberately keeps the modem-state system clock on XTAL.
303                sysclk,
304            },
305            digital: HpSystemDigital { syscntl },
306            analog: HpSystemAnalog {
307                bias: AnalogBias::default(),
308                regulator0,
309                regulator1: HpRegulator1::default(),
310            },
311            retention: HpSystemRetention {
312                retention,
313                backup_clk: [u32::MAX; 2],
314            },
315        }
316    }
317
318    // PMU_HP_SLEEP_*_CONFIG_DEFAULT
319    fn sleep() -> Self {
320        let mut power = HpSystemPower::default();
321        power.clk_power.set_i2c_iso_en(true);
322        power.clk_power.set_i2c_retention(true);
323
324        let mut sysclk = HpSysclk::default();
325        sysclk.set_sysclk_slp_sel(true);
326        sysclk.set_icg_slp_sel(true);
327        let mut syscntl = HpSysCntl::default();
328        syscntl.set_uart_wakeup_en(true);
329        syscntl.set_lp_pad_hold_all(true);
330        syscntl.set_hp_pad_hold_all(true);
331        syscntl.set_dig_pause_wdt(true);
332        syscntl.set_dig_cpu_stall(true);
333
334        let mut bias = AnalogBias::default();
335        bias.set_pd_cur(true);
336        bias.set_bias_sleep(true);
337        let mut regulator0 = HpRegulator0::default();
338        regulator0.set_xpd(true);
339
340        let mut retention = HpBackup::default();
341        retention.set_active2sleep_modem_clk_code(2);
342        retention.set_modem2sleep_backup_mode(hp_retention_regdma_config(1, 1) as u8);
343        retention.set_active2sleep_backup_mode(hp_retention_regdma_config(1, 0) as u8);
344
345        Self {
346            power,
347            clock: HpSystemClock {
348                icg_func: [0; 2],
349                icg_apb: [0; 2],
350                icg_modem: HpIcgModem::default(),
351                sysclk,
352            },
353            digital: HpSystemDigital { syscntl },
354            analog: HpSystemAnalog {
355                bias,
356                regulator0,
357                regulator1: HpRegulator1::default(),
358            },
359            retention: HpSystemRetention {
360                retention,
361                backup_clk: [u32::MAX; 2],
362            },
363        }
364    }
365}
366
367macro_rules! hp_system_init {
368    ($state:ident, $param:expr) => {{
369        let param = $param;
370        let pmu = PMU::regs();
371        paste::paste! {
372            unsafe {
373                pmu.[<$state _dig_power>]().write(|w| w.bits(param.power.dig_power.0));
374                pmu.[<$state _hp_ck_power>]().write(|w| w.bits(param.power.clk_power.0));
375                pmu.[<$state _xtal>]().write(|w| w.bits(param.power.xtal.0));
376
377                pmu.[<$state _icg_hp_func>]().write(|w| w.bits(param.clock.icg_func[0]));
378                pmu.[<$state _icg_hp_apb>]().write(|w| w.bits(param.clock.icg_apb[0]));
379                pmu.[<$state _icg_hp_func1>]().write(|w| w.bits(param.clock.icg_func[1]));
380                pmu.[<$state _icg_hp_apb1>]().write(|w| w.bits(param.clock.icg_apb[1]));
381                pmu.[<$state _icg_modem>]().write(|w| w.bits(param.clock.icg_modem.0));
382                pmu.[<$state _sysclk>]().write(|w| w.bits(param.clock.sysclk.0));
383
384                pmu.[<$state _hp_sys_cntl>]().write(|w| w.bits(param.digital.syscntl.0));
385
386                pmu.[<$state _bias>]().write(|w| w.bits(param.analog.bias.0));
387                pmu.[<$state _hp_regulator0>]().write(|w| w.bits(param.analog.regulator0.0));
388                pmu.[<$state _hp_regulator1>]().write(|w| w.bits(param.analog.regulator1.0));
389
390                pmu.[<$state _backup>]().write(|w| w.bits(param.retention.retention.0));
391                pmu.[<$state _backup_clk>]().write(|w| w.bits(param.retention.backup_clk[0]));
392                pmu.[<$state _backup1_clk>]().write(|w| w.bits(param.retention.backup_clk[1]));
393            }
394        }
395    }};
396}
397
398fn update_hp_system_config() {
399    PMU::regs()
400        .imm_modem_icg()
401        .write(|w| w.update_dig_icg_modem_en().set_bit());
402    PMU::regs()
403        .imm_sleep_sysclk()
404        .write(|w| w.update_dig_icg_switch().set_bit());
405}
406
407impl HpSystemInit {
408    fn init_default() {
409        hp_system_init!(hp_active, Self::active());
410        update_hp_system_config();
411        hp_system_init!(hp_modem, Self::modem());
412        update_hp_system_config();
413        hp_system_init!(hp_sleep, Self::sleep());
414        update_hp_system_config();
415        PMU::regs()
416            .slp_wakeup_cntl3()
417            .modify(|_, w| unsafe { w.sleep_prt_sel().bits(2) });
418    }
419}
420
421bitfield::bitfield! {
422    #[derive(Clone, Copy, Default)]
423    pub struct LpDigPower(u32);
424
425    pub bool, mem_dslp, set_mem_dslp: 30;
426    pub bool, peri_pd_en, set_peri_pd_en: 31;
427}
428
429bitfield::bitfield! {
430    #[derive(Clone, Copy, Default)]
431    pub struct LpClkPower(u32);
432
433    pub bool, xpd_xtal32k, set_xpd_xtal32k: 28;
434    pub bool, xpd_rc32k, set_xpd_rc32k: 29;
435    pub bool, xpd_fosc, set_xpd_fosc: 30;
436    pub bool, pd_osc, set_pd_osc: 31;
437}
438
439bitfield::bitfield! {
440    #[derive(Clone, Copy, Default)]
441    pub struct LpRegulator0(u32);
442
443    pub bool, slp_xpd, set_slp_xpd: 21;
444    pub bool, xpd, set_xpd: 22;
445    pub u8, slp_dbias, set_slp_dbias: 26, 23;
446    pub u8, dbias, set_dbias: 31, 27;
447}
448
449bitfield::bitfield! {
450    #[derive(Clone, Copy, Default)]
451    pub struct LpRegulator1(u32);
452
453    pub u8, drv_b, set_drv_b: 31, 28;
454}
455
456#[derive(Clone, Copy, Default)]
457struct LpSystemPower {
458    dig_power: LpDigPower,
459    clk_power: LpClkPower,
460    xtal: XtalPower,
461}
462
463#[derive(Clone, Copy, Default)]
464struct LpSystemAnalog {
465    bias: AnalogBias,
466    regulator0: LpRegulator0,
467    regulator1: LpRegulator1,
468}
469
470#[derive(Clone, Copy)]
471struct LpSystemInit {
472    power: LpSystemPower,
473    analog: LpSystemAnalog,
474}
475
476impl LpSystemInit {
477    // PMU_LP_ACTIVE_*_CONFIG_DEFAULT
478    fn active() -> Self {
479        let mut clk_power = LpClkPower::default();
480        clk_power.set_xpd_fosc(true);
481        let mut regulator0 = LpRegulator0::default();
482        regulator0.set_xpd(true);
483        regulator0.set_dbias(LP_CALI_DBIAS as u8);
484
485        Self {
486            power: LpSystemPower {
487                dig_power: LpDigPower::default(),
488                clk_power,
489                xtal: XtalPower::default(),
490            },
491            analog: LpSystemAnalog {
492                bias: AnalogBias::default(),
493                regulator0,
494                regulator1: LpRegulator1::default(),
495            },
496        }
497    }
498
499    // PMU_LP_SLEEP_*_CONFIG_DEFAULT
500    fn sleep() -> Self {
501        let mut bias = AnalogBias::default();
502        bias.set_pd_cur(true);
503        bias.set_bias_sleep(true);
504        let mut regulator0 = LpRegulator0::default();
505        regulator0.set_xpd(true);
506
507        Self {
508            power: LpSystemPower::default(),
509            analog: LpSystemAnalog {
510                bias,
511                regulator0,
512                regulator1: LpRegulator1::default(),
513            },
514        }
515    }
516}
517
518impl LpSystemInit {
519    fn init_default() {
520        let active = Self::active();
521        let sleep = Self::sleep();
522        let pmu = PMU::regs();
523
524        unsafe {
525            // PMU_MODE_LP_ACTIVE is represented by the HP-sleep LP register group.
526            pmu.hp_sleep_lp_dig_power()
527                .write(|w| w.bits(active.power.dig_power.0));
528            pmu.hp_sleep_lp_ck_power()
529                .write(|w| w.bits(active.power.clk_power.0));
530            pmu.hp_sleep_lp_regulator0()
531                .write(|w| w.bits(active.analog.regulator0.0));
532            pmu.hp_sleep_lp_regulator1()
533                .write(|w| w.bits(active.analog.regulator1.0));
534
535            pmu.lp_sleep_lp_dig_power()
536                .write(|w| w.bits(sleep.power.dig_power.0));
537            pmu.lp_sleep_lp_ck_power()
538                .write(|w| w.bits(sleep.power.clk_power.0));
539            pmu.lp_sleep_bias().write(|w| w.bits(sleep.analog.bias.0));
540            pmu.lp_sleep_lp_regulator0()
541                .write(|w| w.bits(sleep.analog.regulator0.0));
542            pmu.lp_sleep_lp_regulator1()
543                .write(|w| w.bits(sleep.analog.regulator1.0));
544            pmu.lp_sleep_xtal().write(|w| w.bits(sleep.power.xtal.0));
545        }
546    }
547}
548
549fn power_domain_force_default() {
550    let pmu = PMU::regs();
551
552    // Clear the six force-control bits for every S31 HP power domain while
553    // preserving the domain mask fields.
554    macro_rules! clear_force_control {
555        ($reg:expr) => {
556            $reg.modify(|r, w| unsafe { w.bits(r.bits() & !0x3f) })
557        };
558    }
559    clear_force_control!(pmu.power_pd_top_cntl());
560    clear_force_control!(pmu.power_pd_hp_alive_cntl());
561    clear_force_control!(pmu.power_pd_modem_pwr_cntl());
562    clear_force_control!(pmu.power_pd_hpcpu_cntl());
563    clear_force_control!(pmu.power_pd_hpcnnt_cntl());
564    clear_force_control!(pmu.power_pd_modem_top_cntl());
565
566    // Isolate all HP memory banks in sleep and disable force-power-up.
567    pmu.power_pd_mem_cntl()
568        .modify(|r, w| unsafe { w.bits(r.bits() & !0xff00_0000) });
569    pmu.power_pd_lpperi_cntl()
570        .modify(|r, w| unsafe { w.bits(r.bits() & !0x3f) });
571}
572
573fn modem_clock_domain_power_state_icg_map_init() {
574    // OR in the defaults from esp32s31/modem_clock_impl.c. Other users may
575    // already own additional state-map bits, so do not replace whole fields.
576    MODEM_SYSCON::regs()
577        .clk_conf_power_st()
578        .modify(|r, w| unsafe {
579            w.clk_modem_apb_st_map()
580                .bits(r.clk_modem_apb_st_map().bits() | ICG_NOGATING_ACTIVE_MODEM);
581            w.clk_modem_peri_st_map()
582                .bits(r.clk_modem_peri_st_map().bits() | ICG_NOGATING_ACTIVE);
583            w.clk_wifi_st_map()
584                .bits(r.clk_wifi_st_map().bits() | ICG_NOGATING_ACTIVE_MODEM);
585            w.clk_bt_st_map()
586                .bits(r.clk_bt_st_map().bits() | ICG_NOGATING_ACTIVE);
587            w.clk_fe_st_map()
588                .bits(r.clk_fe_st_map().bits() | ICG_NOGATING_ACTIVE_MODEM);
589            w.clk_zb_st_map()
590                .bits(r.clk_zb_st_map().bits() | ICG_NOGATING_ACTIVE)
591        });
592    MODEM_LPCON::regs()
593        .clk_conf_power_st()
594        .modify(|r, w| unsafe {
595            w.clk_lp_apb_st_map()
596                .bits(r.clk_lp_apb_st_map().bits() | ICG_NOGATING_ACTIVE_MODEM);
597            w.clk_i2c_mst_st_map()
598                .bits(r.clk_i2c_mst_st_map().bits() | ICG_NOGATING_ACTIVE_MODEM);
599            w.clk_coex_st_map()
600                .bits(r.clk_coex_st_map().bits() | ICG_NOGATING_ACTIVE_MODEM);
601            w.clk_wifipwr_st_map()
602                .bits(r.clk_wifipwr_st_map().bits() | ICG_NOGATING_ACTIVE_MODEM)
603        });
604}
605
606/// Select the WiFi LP clock after `ClockConfig::configure` has applied and
607/// acquired the configured LP clock source.
608pub(crate) fn configure_wifi_lp_clock(config: &ClockConfig) {
609    let lpcon = MODEM_LPCON::regs();
610    let source = config.lp_slow_clk.unwrap_or(LpSlowClkConfig::RcSlow);
611
612    lpcon.wifi_lp_clk_conf().modify(|_, w| {
613        w.clk_wifipwr_lp_sel_osc_slow().clear_bit();
614        w.clk_wifipwr_lp_sel_osc_fast().clear_bit();
615        w.clk_wifipwr_lp_sel_xtal().clear_bit();
616        w.clk_wifipwr_lp_sel_xtal32k().clear_bit();
617        match source {
618            LpSlowClkConfig::RcSlow => w.clk_wifipwr_lp_sel_osc_slow().set_bit(),
619            LpSlowClkConfig::Xtal32k => w.clk_wifipwr_lp_sel_xtal32k().set_bit(),
620        }
621    });
622    if source == LpSlowClkConfig::Xtal32k {
623        // The WiFi 32 kHz selector feeds from the shared modem 32 kHz mux.
624        // MODEM_CLOCK_XTAL32K_CODE is 0 on S31.
625        lpcon
626            .modem_32k_clk_conf()
627            .modify(|_, w| unsafe { w.clk_modem_32k_sel().bits(0) });
628    }
629    lpcon
630        .wifi_lp_clk_conf()
631        .modify(|_, w| unsafe { w.clk_wifipwr_lp_div_num().bits(0) });
632    lpcon.clk_conf().modify(|_, w| w.clk_wifipwr_en().set_bit());
633}
634
635pub(crate) fn init(_config: &ClockConfig) {
636    // pmu_init: power up and release reset for the analog peripheral I2C.
637    PMU::regs()
638        .ana_peri_pwr_ctrl()
639        .modify(|_, w| w.rstb_perif_i2c().clear_bit());
640    crate::rom::ets_delay_us(1);
641    PMU::regs().ana_peri_pwr_ctrl().modify(|_, w| {
642        w.xpd_perif_i2c().set_bit();
643        w.rstb_perif_i2c().set_bit()
644    });
645
646    HpSystemInit::init_default();
647    LpSystemInit::init_default();
648    power_domain_force_default();
649
650    // rtc_clk_init: S31 only applies RC_SLOW tuning and regulator force bits
651    // here, it has no PCR/FOSC/RC32K tuning sequence.
652    regi2c::I2C_DIG_REG_SCK_DCAP.write_field(128);
653    regi2c::I2C_DIG_REG_ENIF_RTC_DREG.write_field(1);
654    regi2c::I2C_DIG_REG_ENIF_DIG_DREG.write_field(1);
655    regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
656    regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
657
658    modem_clock_domain_power_state_icg_map_init();
659}
660
661/// SOC Reset Reason.
662#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
663pub enum SocResetReason {
664    /// Power on reset
665    ///
666    /// In ESP-IDF this value (0x01) can *also* be `ChipBrownOut` or
667    /// `ChipSuperWdt`, however that is not really compatible with Rust-style
668    /// enums.
669    ChipPowerOn   = 0x01,
670    /// Software resets the digital core
671    CoreSw        = 0x03,
672    /// Deep sleep reset the digital core (also: PMU HP power down core reset)
673    CoreDeepSleep = 0x05,
674    /// PMU HP CPU power down reset
675    CpuPmuPwrDown = 0x06,
676    /// Main watch dog 0 resets digital core
677    CoreMwdt0     = 0x07,
678    /// Main watch dog 1 resets digital core
679    CoreMwdt1     = 0x08,
680    /// RWDT core reset
681    CoreRwdt      = 0x09,
682    /// MWDT HP CPU reset
683    CpuMwdt       = 0x0B,
684    /// Software resets HP CPU
685    CpuSw         = 0x0C,
686    /// RWDT resets digital core
687    CpuRwdt       = 0x0D,
688    /// VDD voltage is not stable and resets the digital core
689    SysBrownOut   = 0x0F,
690    /// RWDT system reset
691    SysRwdt       = 0x10,
692    /// Super watch dog resets the digital core and rtc module
693    SysSuperWdt   = 0x12,
694    /// Glitch on power resets the digital core and rtc module
695    CorePwrGlitch = 0x13,
696    /// eFuse CRC error resets the digital core
697    CoreEfuseCrc  = 0x14,
698    /// USB Serial/JTAG controller's JTAG resets the digital core
699    CoreUsbJtag   = 0x16,
700    /// USB Serial/JTAG controller's UART resets the digital core
701    CoreUsbUart   = 0x17,
702    /// JTAG resets the CPU
703    CpuJtag       = 0x18,
704    /// CPU lockup (exception inside exception handler)
705    CpuLockup     = 0x1A,
706}