1use core::{
8 ops::Not,
9 sync::atomic::{AtomicBool, Ordering},
10};
11
12use crate::{
13 peripherals::{HP_SYS_CLKRST, LP_AON_CLKRST, PMU, USB_DEVICE},
14 private::DropGuard,
15 rtc_cntl::{
16 Rtc,
17 rtc::{HpAnalog, HpSysCntlReg, HpSysPower, LpAnalog, LpSysPower},
18 sleep::{SleepKind, pmu_common::SleepTimeConfig},
19 },
20 soc::clocks::{self, ClockTree, CpuRootClkConfig, LpSlowClkConfig},
21};
22
23static USJ_CLOCK_WAS_ENABLED: AtomicBool = AtomicBool::new(false);
36static USJ_PAD_WAS_ENABLED: AtomicBool = AtomicBool::new(false);
37
38fn usj_module_is_enabled() -> bool {
39 let clkrst = HP_SYS_CLKRST::regs();
40 let aon = LP_AON_CLKRST::regs();
41 clkrst
42 .soc_clk_ctrl2()
43 .read()
44 .usb_device_apb_clk_en()
45 .bit_is_set()
46 && aon
47 .lp_aonclkrst_hp_usb_clkrst_ctrl1()
48 .read()
49 .lp_aonclkrst_rst_en_usb_device()
50 .bit_is_clear()
51}
52
53fn usj_enable_bus_clock(enable: bool) {
54 HP_SYS_CLKRST::regs()
55 .soc_clk_ctrl2()
56 .modify(|_, w| w.usb_device_apb_clk_en().bit(enable));
57 LP_AON_CLKRST::regs()
59 .lp_aonclkrst_hp_usb_clkrst_ctrl0()
60 .modify(|_, w| w.lp_aonclkrst_usb_device_48m_clk_en().bit(enable));
61}
62
63fn usj_reset_register() {
64 let aon = LP_AON_CLKRST::regs();
65 aon.lp_aonclkrst_hp_usb_clkrst_ctrl1()
66 .modify(|_, w| w.lp_aonclkrst_rst_en_usb_device().set_bit());
67 aon.lp_aonclkrst_hp_usb_clkrst_ctrl1()
68 .modify(|_, w| w.lp_aonclkrst_rst_en_usb_device().clear_bit());
69}
70
71fn usj_set_pad_enable(enable: bool) {
72 USB_DEVICE::regs()
73 .conf0()
74 .modify(|_, w| w.usb_pad_enable().bit(enable));
75}
76
77fn usj_pad_is_enabled() -> bool {
78 USB_DEVICE::regs()
79 .conf0()
80 .read()
81 .usb_pad_enable()
82 .bit_is_set()
83}
84
85fn usj_pad_backup_and_disable() {
88 let clock_enabled = usj_module_is_enabled();
89 let pad_enabled = if clock_enabled {
90 usj_pad_is_enabled()
91 } else {
92 usj_enable_bus_clock(true);
94 usj_reset_register();
95 false
96 };
97 usj_set_pad_enable(false);
98 usj_enable_bus_clock(false);
99
100 USJ_CLOCK_WAS_ENABLED.store(clock_enabled, Ordering::Relaxed);
101 USJ_PAD_WAS_ENABLED.store(pad_enabled, Ordering::Relaxed);
102}
103
104fn usj_pad_restore() {
106 usj_enable_bus_clock(true);
107 usj_set_pad_enable(USJ_PAD_WAS_ENABLED.load(Ordering::Relaxed));
108 if !USJ_CLOCK_WAS_ENABLED.load(Ordering::Relaxed) {
109 usj_enable_bus_clock(false);
110 }
111}
112
113const P4_LP_RAM_BOOT_ADDR: usize = 0x5010_8000;
116
117fn is_rev3_mspi_workaround_needed() -> bool {
121 crate::efuse::chip_revision() == crate::efuse::ChipRevision::from_combined(300)
122}
123
124core::arch::global_asm!(
134 ".pushsection .rodata.p4_rev3_mspi_wa, \"a\"",
135 ".option push",
136 ".option norelax",
137 ".option norvc",
138 ".balign 4",
139 ".global _p4_rev3_mspi_wa_start",
140 ".global _p4_rev3_mspi_wa_end",
141 "_p4_rev3_mspi_wa_start:",
142 "li a0, 0x50111014",
144 "li a1, 0x8000",
145 "lw a2, 0(a0)",
146 "or a2, a2, a1",
147 "sw a2, 0(a0)",
148 "li a0, 0x5008C03C",
150 "li a1, 0x80000000",
151 "not a1, a1",
152 "lw a2, 0(a0)",
153 "and a2, a2, a1",
154 "sw a2, 0(a0)",
155 "li a1, 0x1",
157 "lw a2, 0(a0)",
158 "or a2, a2, a1",
159 "sw a2, 0(a0)",
160 "li a0, 0x5008C380", "sw zero, 0(a0)",
163 "li a0, 0x5008C37C", "li a1, 0x1000",
165 "sw a1, 0(a0)",
166 "li a0, 0x500E51A4",
168 "li a1, 0x7",
169 "sw a1, 0(a0)",
170 "li a0, 0x80000000",
172 "lw a1, 0(a0)",
173 "li a0, 0x80000080",
174 "lw a1, 0(a0)",
175 "li t3, 40",
177 "csrr t0, cycle",
178 "add t1, t0, t3",
179 "100:",
180 "csrr t2, cycle",
181 "blt t2, t1, 100b",
182 "li a0, 0x500E51A4",
184 "sw zero, 0(a0)",
185 "li a0, 0x500E60C0",
187 "li a1, 0x400000", "lw a2, 0(a0)",
189 "or a2, a2, a1",
190 "sw a2, 0(a0)",
191 "li a1, 0x1000000", "lw a2, 0(a0)",
193 "or a2, a2, a1",
194 "sw a2, 0(a0)",
195 "li a1, 0x400000",
196 "not a1, a1",
197 "lw a2, 0(a0)",
198 "and a2, a2, a1",
199 "sw a2, 0(a0)",
200 "li a1, 0x1000000",
201 "not a1, a1",
202 "lw a2, 0(a0)",
203 "and a2, a2, a1",
204 "sw a2, 0(a0)",
205 "li a5, 0x4FC00000",
207 "jr a5",
208 "_p4_rev3_mspi_wa_end:",
209 ".option pop",
210 ".popsection",
211);
212
213fn install_mspi_workaround_stub() {
218 unsafe extern "C" {
219 static _p4_rev3_mspi_wa_start: u8;
220 static _p4_rev3_mspi_wa_end: u8;
221 }
222
223 let src = &raw const _p4_rev3_mspi_wa_start;
224 let end = &raw const _p4_rev3_mspi_wa_end;
225 let len = end as usize - src as usize;
226 let words = len.div_ceil(4);
227
228 let src = src as *const u32;
229 let dst = P4_LP_RAM_BOOT_ADDR as *mut u32;
230 for i in 0..words {
231 unsafe { dst.add(i).write_volatile(src.add(i).read_volatile()) };
232 }
233}
234
235fn set_boot_from_lp_ram(boot_from_lp_ram: bool) {
240 LP_AON_CLKRST::regs()
241 .lp_aonclkrst_hpcpu_reset_ctrl0()
242 .modify(|_, w| {
243 w.lp_aonclkrst_hpcore0_stat_vector_sel()
244 .bit(!boot_from_lp_ram)
245 });
246}
247
248fn pmu_sleep_dcdc_to_ldo_handover() {
260 const LDO_TAKEOVER_PREPARATION_TIME_US: u32 = 185;
262 const HP_CALI_ACTIVE_DBIAS: u8 = 24;
264 const LDO_TAKEOVER_DBIAS: u8 = 30;
266 const LDO_TAKEOVER_DCM_VSET: u8 = 24;
267
268 PMU::regs()
271 .hp_active_hp_regulator0()
272 .modify(|_, w| unsafe { w.hp_active_hp_regulator_dbias().bits(LDO_TAKEOVER_DBIAS) });
273 PMU::regs()
274 .hp_active_hp_regulator0()
275 .modify(|_, w| w.hp_active_hp_regulator_xpd().set_bit());
276 PMU::regs()
277 .hp_active_bias()
278 .modify(|_, w| unsafe { w.hp_active_dcm_vset().bits(LDO_TAKEOVER_DCM_VSET) });
279
280 crate::rom::ets_delay_us(LDO_TAKEOVER_PREPARATION_TIME_US);
281
282 PMU::regs().dcm_ctrl().modify(|_, w| {
286 w.dcdc_off_req().set_bit();
287 w.dcdc_done_force().set_bit()
288 });
289 PMU::regs()
290 .hp_active_hp_regulator0()
291 .modify(|_, w| unsafe { w.hp_active_hp_regulator_dbias().bits(HP_CALI_ACTIVE_DBIAS) });
292}
293
294#[derive(Clone, Copy)]
296pub struct AnalogSleepConfig {
298 pub hp_sys: HpAnalog,
300 pub lp_sys_sleep: LpAnalog,
302}
303
304impl AnalogSleepConfig {
305 fn defaults_deep_sleep() -> Self {
306 Self {
308 hp_sys: {
309 let mut cfg = HpAnalog::default();
310 cfg.bias.set_dcm_mode(0);
311 cfg.bias.set_pd_cur(true); cfg.bias.set_bias_sleep(true); cfg.regulator0.set_xpd(false); cfg.bias.set_dbg_atten(0); cfg
316 },
317 lp_sys_sleep: {
318 let mut cfg = LpAnalog::default();
319 cfg.regulator1.set_drv_b(0);
320 cfg.bias.set_pd_cur(true);
321 cfg.bias.set_bias_sleep(true);
322 cfg.regulator0.set_slp_xpd(false);
323 cfg.regulator0.set_slp_dbias(0);
324 cfg.regulator0.set_xpd(true);
325 cfg.bias.set_dbg_atten(12); cfg.regulator0.set_dbias(23); cfg
328 },
329 }
330 }
331
332 fn defaults_light_sleep(pd_flags: PowerDownFlags) -> Self {
333 let mut this = Self {
335 hp_sys: {
336 let mut cfg = HpAnalog::default();
337 cfg.bias.set_dcm_mode(1);
338 cfg.bias.set_dcm_vset(DCM_VSET_IN_SLEEP);
339 cfg.regulator1.set_drv_b(0); cfg.bias.set_pd_cur(true); cfg.bias.set_bias_sleep(true); cfg.regulator0.set_xpd(false); cfg.bias.set_dbg_atten(0); cfg.regulator0.set_dbias(1); cfg
346 },
347 lp_sys_sleep: {
348 let mut cfg = LpAnalog::default();
349 cfg.regulator1.set_drv_b(0);
350 cfg.bias.set_pd_cur(true);
351 cfg.bias.set_bias_sleep(true);
352 cfg.regulator0.set_slp_xpd(false);
353 cfg.regulator0.set_slp_dbias(0);
354 cfg.regulator0.set_xpd(true);
355 cfg.bias.set_dbg_atten(0);
356 cfg.regulator0.set_dbias(12); cfg
358 },
359 };
360
361 if !pd_flags.pd_xtal() {
364 this.hp_sys.bias.set_pd_cur(false);
365 this.hp_sys.bias.set_bias_sleep(false);
366 this.hp_sys.bias.set_dbg_atten(0);
367 this.hp_sys.regulator0.set_dbias(HP_CALI_ACTIVE_DBIAS);
368
369 this.lp_sys_sleep.bias.set_pd_cur(false);
370 this.lp_sys_sleep.bias.set_bias_sleep(false);
371 this.lp_sys_sleep.bias.set_dbg_atten(0);
372 }
373
374 this
375 }
376
377 fn apply(&self, dslp: bool) {
378 PMU::regs()
382 .hp_active_bias()
383 .modify(|_, w| unsafe { w.hp_active_dcm_mode().bits(if dslp { 0 } else { 1 }) });
384
385 PMU::regs().hp_sleep_bias().modify(|_, w| unsafe {
386 w.hp_sleep_dcm_mode().bits(self.hp_sys.bias.dcm_mode());
387 w.hp_sleep_dcm_vset().bits(self.hp_sys.bias.dcm_vset());
388 w.hp_sleep_dbg_atten().bits(self.hp_sys.bias.dbg_atten());
389 w.hp_sleep_pd_cur().bit(self.hp_sys.bias.pd_cur());
390 w.sleep().bit(self.hp_sys.bias.bias_sleep())
391 });
392 PMU::regs().hp_sleep_hp_regulator0().modify(|_, w| unsafe {
393 w.hp_sleep_hp_regulator_slp_mem_xpd()
394 .bit(self.hp_sys.regulator0.slp_mem_xpd());
395 w.hp_sleep_hp_regulator_slp_logic_xpd()
396 .bit(self.hp_sys.regulator0.slp_logic_xpd());
397 w.hp_sleep_hp_regulator_xpd()
398 .bit(self.hp_sys.regulator0.xpd());
399 w.hp_sleep_hp_regulator_slp_logic_dbias()
400 .bits(self.hp_sys.regulator0.slp_logic_dbias());
401 w.hp_sleep_hp_regulator_dbias()
402 .bits(self.hp_sys.regulator0.dbias())
403 });
404 PMU::regs().hp_sleep_hp_regulator1().modify(|_, w| unsafe {
405 w.hp_sleep_hp_regulator_drv_b()
406 .bits(self.hp_sys.regulator1.drv_b())
407 });
408
409 PMU::regs().lp_sleep_bias().modify(|_, w| unsafe {
411 w.lp_sleep_dbg_atten()
412 .bits(self.lp_sys_sleep.bias.dbg_atten());
413 w.lp_sleep_pd_cur().bit(self.lp_sys_sleep.bias.pd_cur());
414 w.sleep().bit(self.lp_sys_sleep.bias.bias_sleep())
415 });
416 PMU::regs().lp_sleep_lp_regulator0().modify(|_, w| unsafe {
417 w.lp_sleep_lp_regulator_slp_xpd()
418 .bit(self.lp_sys_sleep.regulator0.slp_xpd());
419 w.lp_sleep_lp_regulator_xpd()
420 .bit(self.lp_sys_sleep.regulator0.xpd());
421 w.lp_sleep_lp_regulator_slp_dbias()
422 .bits(self.lp_sys_sleep.regulator0.slp_dbias());
423 w.lp_sleep_lp_regulator_dbias()
424 .bits(self.lp_sys_sleep.regulator0.dbias())
425 });
426 PMU::regs().lp_sleep_lp_regulator1().modify(|_, w| unsafe {
427 w.lp_sleep_lp_regulator_drv_b()
428 .bits(self.lp_sys_sleep.regulator1.drv_b())
429 });
430 }
431}
432
433#[derive(Clone, Copy)]
435pub struct DigitalSleepConfig {
437 pub syscntl: HpSysCntlReg,
439}
440
441impl DigitalSleepConfig {
442 fn defaults_deep_sleep(pd_flags: PowerDownFlags) -> Self {
443 let mut syscntl = HpSysCntlReg::default();
444 syscntl.set_dig_pad_slp_sel(false);
445 syscntl.set_lp_pad_hold_all(pd_flags.pd_lp_periph());
446
447 Self { syscntl }
448 }
449
450 fn defaults_light_sleep(pd_flags: PowerDownFlags) -> Self {
451 Self {
453 syscntl: {
454 let mut cfg = HpSysCntlReg::default();
455 cfg.set_dig_pad_slp_sel(false);
456 cfg.set_lp_pad_hold_all(pd_flags.pd_lp_periph());
458 cfg.set_dig_pause_wdt(true);
459 cfg
460 },
461 }
462 }
463
464 fn apply(&self) {
465 PMU::regs().hp_sleep_hp_sys_cntl().modify(|_, w| {
468 w.hp_sleep_dig_pad_slp_sel()
469 .bit(self.syscntl.dig_pad_slp_sel());
470 w.hp_sleep_lp_pad_hold_all()
471 .bit(self.syscntl.lp_pad_hold_all());
472 w.hp_sleep_dig_pause_wdt().bit(self.syscntl.dig_pause_wdt());
473 w.hp_sleep_dig_cpu_stall().bit(true)
474 });
475 }
476}
477
478#[derive(Clone, Copy)]
481pub struct PowerSleepConfig {
483 pub hp_sys: HpSysPower,
485 pub lp_sys_active: LpSysPower,
487 pub lp_sys_sleep: LpSysPower,
489}
490
491impl PowerSleepConfig {
492 fn defaults(pd_flags: PowerDownFlags) -> Self {
493 let mut this = Self {
494 hp_sys: HpSysPower::default(),
495 lp_sys_active: LpSysPower::default(),
496 lp_sys_sleep: LpSysPower::default(),
497 };
498 this.apply_flags(pd_flags);
499 this
500 }
501
502 fn apply_flags(&mut self, pd_flags: PowerDownFlags) {
503 self.hp_sys
508 .dig_power
509 .set_dcdc_switch_pd_en(pd_flags.pd_vddsdio());
510 self.hp_sys.dig_power.set_cnnt_pd_en(pd_flags.pd_modem());
511 self.hp_sys.dig_power.set_cpu_pd_en(pd_flags.pd_cpu());
512 self.hp_sys.dig_power.set_top_pd_en(pd_flags.pd_top());
513 self.hp_sys.dig_power.set_mem_pd_en(pd_flags.pd_mem());
514
515 self.hp_sys.clk.set_i2c_iso_en(true);
516 self.hp_sys.clk.set_i2c_retention(true);
517 self.hp_sys.clk.set_xpd_pll_i2c(0);
518 self.hp_sys.clk.set_xpd_pll(0);
519
520 self.hp_sys.xtal.set_xpd_xtal(pd_flags.pd_xtal().not());
521
522 self.lp_sys_active.clk_power.set_xpd_lppll(true);
523 self.lp_sys_active.clk_power.set_xpd_xtal32k(true);
524 self.lp_sys_active.clk_power.set_xpd_rc32k(true);
525 self.lp_sys_active.clk_power.set_xpd_fosc(true);
526
527 self.lp_sys_sleep
528 .dig_power
529 .set_peri_pd_en(pd_flags.pd_lp_periph());
530
531 self.lp_sys_sleep
532 .clk_power
533 .set_xpd_xtal32k(pd_flags.pd_xtal32k().not());
534 self.lp_sys_sleep
535 .clk_power
536 .set_xpd_rc32k(pd_flags.pd_rc32k().not());
537 self.lp_sys_sleep
538 .clk_power
539 .set_xpd_fosc(pd_flags.pd_rc_fast().not());
540
541 self.lp_sys_sleep
542 .xtal
543 .set_xpd_xtal(pd_flags.pd_xtal().not());
544 }
545
546 fn apply(&self) {
547 PMU::regs()
551 .hp_sleep_dig_power()
552 .modify(|_, w| unsafe { w.bits(self.hp_sys.dig_power.0) });
553 PMU::regs()
554 .hp_sleep_hp_ck_power()
555 .modify(|_, w| unsafe { w.bits(self.hp_sys.clk.0) });
556 PMU::regs()
557 .hp_sleep_xtal()
558 .modify(|_, w| w.hp_sleep_xpd_xtal().bit(self.hp_sys.xtal.xpd_xtal()));
559
560 PMU::regs()
562 .hp_sleep_lp_dig_power()
563 .modify(|_, w| unsafe { w.bits(self.lp_sys_active.dig_power.0) });
564 PMU::regs()
565 .hp_sleep_lp_ck_power()
566 .modify(|_, w| unsafe { w.bits(self.lp_sys_active.clk_power.0) });
567
568 PMU::regs()
570 .lp_sleep_lp_dig_power()
571 .modify(|_, w| unsafe { w.bits(self.lp_sys_sleep.dig_power.0) });
572 PMU::regs()
573 .lp_sleep_lp_ck_power()
574 .modify(|_, w| unsafe { w.bits(self.lp_sys_sleep.clk_power.0) });
575 PMU::regs()
576 .lp_sleep_xtal()
577 .modify(|_, w| w.lp_sleep_xpd_xtal().bit(self.lp_sys_sleep.xtal.xpd_xtal()));
578 }
579}
580
581#[derive(Clone, Copy, Default)]
583pub struct HpParam {
584 analog_wait_target_cycle: u16,
585 digital_power_supply_wait_cycle: u16,
586 digital_power_up_wait_cycle: u16,
587 pll_stable_wait_cycle: u16,
588 min_slp_slow_clk_cycle: u8,
589}
590
591#[derive(Clone, Copy, Default)]
593pub struct LpParam {
594 digital_power_supply_wait_cycle: u16,
595 min_slp_slow_clk_cycle: u8,
596 analog_wait_target_cycle: u8,
597 digital_power_up_wait_cycle: u16,
598}
599
600#[derive(Clone, Copy, Default)]
602pub struct HpLpParam {
603 xtal_stable_wait_cycle: u16,
604}
605
606#[derive(Clone, Copy)]
608pub struct ParamSleepConfig {
609 hp_sys: HpParam,
610 lp_sys: LpParam,
611 hp_lp: HpLpParam,
612}
613
614impl ParamSleepConfig {
615 fn apply(&self) {
616 PMU::regs().slp_wakeup_cntl3().modify(|_, w| unsafe {
618 w.hp_min_slp_val().bits(self.hp_sys.min_slp_slow_clk_cycle);
619 w.lp_min_slp_val().bits(self.lp_sys.min_slp_slow_clk_cycle)
620 });
621
622 PMU::regs().slp_wakeup_cntl7().modify(|_, w| unsafe {
623 w.ana_wait_target()
624 .bits(self.hp_sys.analog_wait_target_cycle)
625 });
626
627 PMU::regs().power_wait_timer0().modify(|_, w| unsafe {
628 w.dg_hp_wait_timer()
629 .bits(self.hp_sys.digital_power_supply_wait_cycle);
630 w.dg_hp_powerup_timer()
631 .bits(self.hp_sys.digital_power_up_wait_cycle)
632 });
633
634 PMU::regs().power_wait_timer1().modify(|_, w| unsafe {
635 w.dg_lp_wait_timer()
636 .bits(self.lp_sys.digital_power_supply_wait_cycle);
637 w.dg_lp_powerup_timer()
638 .bits(self.lp_sys.digital_power_up_wait_cycle)
639 });
640
641 PMU::regs().slp_wakeup_cntl5().modify(|_, w| unsafe {
642 w.lp_ana_wait_target()
643 .bits(self.lp_sys.analog_wait_target_cycle)
644 });
645
646 PMU::regs().power_ck_wait_cntl().modify(|_, w| unsafe {
647 w.pmu_wait_xtl_stable()
648 .bits(self.hp_lp.xtal_stable_wait_cycle);
649 w.pmu_wait_pll_stable()
650 .bits(self.hp_sys.pll_stable_wait_cycle)
651 });
652 }
653
654 fn defaults(config: SleepTimeConfig, pd_flags: PowerDownFlags, pd_xtal: bool) -> Self {
655 let hp_analog_wait_time_us = if pd_flags.pd_top() {
657 MachineConstants::HP_ANA_WAIT_TIME_PD_TOP_US
658 } else {
659 MachineConstants::HP_ANA_WAIT_TIME_PU_TOP_US
660 };
661
662 let hp_sys = HpParam {
663 min_slp_slow_clk_cycle: config.us_to_slowclk(MachineConstants::HP_MIN_SLP_TIME_US)
664 as u8,
665 analog_wait_target_cycle: config.us_to_slowclk(hp_analog_wait_time_us) as u16,
666 digital_power_supply_wait_cycle: config
667 .us_to_fastclk(MachineConstants::HP_POWER_SUPPLY_WAIT_TIME_US)
668 as u16,
669 digital_power_up_wait_cycle: config
670 .us_to_fastclk(MachineConstants::HP_POWER_UP_WAIT_TIME_US)
671 as u16,
672 pll_stable_wait_cycle: config
673 .us_to_fastclk(MachineConstants::HP_PLL_WAIT_STABLE_TIME_US)
674 as u16,
675 };
676
677 let lp_sys = LpParam {
678 min_slp_slow_clk_cycle: config.us_to_slowclk(MachineConstants::LP_MIN_SLP_TIME_US)
679 as u8,
680 analog_wait_target_cycle: config.us_to_slowclk(MachineConstants::LP_ANALOG_WAIT_TIME_US)
681 as u8,
682 digital_power_supply_wait_cycle: config
683 .us_to_fastclk(MachineConstants::LP_POWER_SUPPLY_WAIT_TIME_US)
684 as u16,
685 digital_power_up_wait_cycle: config
686 .us_to_fastclk(MachineConstants::LP_POWER_UP_WAIT_TIME_US)
687 as u16,
688 };
689
690 let xtal_stable_wait_cycle = if pd_xtal {
691 config.us_to_slowclk(MachineConstants::LP_XTAL_WAIT_STABLE_TIME_US) as u16
692 } else {
693 config.us_to_fastclk(MachineConstants::HP_XTAL_WAIT_STABLE_TIME_US) as u16
694 };
695
696 Self {
697 hp_sys,
698 lp_sys,
699 hp_lp: HpLpParam {
700 xtal_stable_wait_cycle,
701 },
702 }
703 }
704}
705
706impl SleepTimeConfig {
707 pub(crate) const CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ: u32 = 360;
708 pub(crate) const LIGHT_SLEEP_TIME_OVERHEAD_US: u32 = 56;
709
710 pub(crate) fn pmu_sleep_calculate_hw_wait_time(&self, pd_flags: PowerDownFlags) -> u32 {
711 let lp_wakeup_wait_time_us = self.slowclk_to_us(MachineConstants::LP_WAKEUP_WAIT_CYCLE);
713 let lp_clk_switch_time_us = self.slowclk_to_us(MachineConstants::LP_CLK_SWITCH_CYCLE);
714 let lp_clk_power_on_wait_time_us =
717 self.slowclk_to_us(MachineConstants::LP_CLK_POWER_ON_WAIT_CYCLE);
718
719 let lp_hw_wait_time_us = MachineConstants::LP_MIN_SLP_TIME_US
720 + MachineConstants::LP_ANALOG_WAIT_TIME_US
721 + lp_clk_power_on_wait_time_us
722 + lp_wakeup_wait_time_us
723 + lp_clk_switch_time_us
724 + MachineConstants::LP_POWER_SUPPLY_WAIT_TIME_US
725 + MachineConstants::LP_POWER_UP_WAIT_TIME_US;
726
727 let hp_analog_wait_time_us = if pd_flags.pd_top() {
729 MachineConstants::HP_ANA_WAIT_TIME_PD_TOP_US
730 } else {
731 MachineConstants::HP_ANA_WAIT_TIME_PU_TOP_US
732 };
733 let hp_digital_power_up_wait_time_us = MachineConstants::HP_POWER_SUPPLY_WAIT_TIME_US
734 + MachineConstants::HP_POWER_UP_WAIT_TIME_US;
735 let hp_regdma_wait_time_us = 0;
737 let hp_clock_wait_time_us = if pd_flags.pd_xtal() {
740 MachineConstants::HP_XTAL_WAIT_STABLE_TIME_US
741 + MachineConstants::HP_PLL_WAIT_STABLE_TIME_US
742 } else {
743 MachineConstants::HP_PLL_WAIT_STABLE_TIME_US
744 };
745
746 let hp_hw_wait_time_us = hp_analog_wait_time_us
747 + hp_digital_power_up_wait_time_us
748 + hp_regdma_wait_time_us
749 + hp_clock_wait_time_us;
750
751 lp_hw_wait_time_us + hp_hw_wait_time_us
752 }
753}
754
755#[derive(Clone, Copy)]
757pub struct RtcSleepConfig {
758 pub deep: bool,
760 pub pd_flags: PowerDownFlags,
762}
763
764impl Default for RtcSleepConfig {
765 fn default() -> Self {
766 Self {
767 deep: false,
768 pd_flags: PowerDownFlags(0),
769 }
770 }
771}
772
773bitfield::bitfield! {
774 #[derive(Clone, Copy)]
775 pub struct PowerDownFlags(u32);
777
778 pub u32, pd_top , set_pd_top : 0;
780 pub u32, pd_vddsdio , set_pd_vddsdio : 1;
782 pub u32, pd_modem , set_pd_modem : 2;
784 pub u32, pd_hp_periph, set_pd_hp_periph: 3;
786 pub u32, pd_cpu , set_pd_cpu : 4;
788 pub u32, pd_hp_aon , set_pd_hp_aon : 5;
790 pub u32, pd_mem_g0 , set_pd_mem_g0 : 6;
792 pub u32, pd_mem_g1 , set_pd_mem_g1 : 7;
794 pub u32, pd_mem_g2 , set_pd_mem_g2 : 8;
796 pub u32, pd_mem_g3 , set_pd_mem_g3 : 9;
798 pub u32, pd_xtal , set_pd_xtal : 10;
800 pub u32, pd_rc_fast , set_pd_rc_fast : 11;
802 pub u32, pd_xtal32k , set_pd_xtal32k : 12;
804 pub u32, pd_rc32k , set_pd_rc32k : 13;
806 pub u32, pd_lp_periph, set_pd_lp_periph: 14;
808}
809
810impl PowerDownFlags {
811 pub fn pd_mem(self) -> bool {
813 self.pd_mem_g0() && self.pd_mem_g1() && self.pd_mem_g2() && self.pd_mem_g3()
814 }
815
816 pub fn set_pd_mem(&mut self, value: bool) {
818 self.set_pd_mem_g0(value);
819 self.set_pd_mem_g1(value);
820 self.set_pd_mem_g2(value);
821 self.set_pd_mem_g3(value);
822 }
823}
824
825const DCM_VSET_IN_SLEEP: u8 = 14;
828const HP_CALI_ACTIVE_DBIAS: u8 = 24;
830
831struct MachineConstants;
833impl MachineConstants {
834 const LP_MIN_SLP_TIME_US: u32 = 450;
835 const LP_WAKEUP_WAIT_CYCLE: u32 = 4;
836 const LP_ANALOG_WAIT_TIME_US: u32 = 154;
837 const LP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
838 const LP_CLK_SWITCH_CYCLE: u32 = 1;
839 const LP_CLK_POWER_ON_WAIT_CYCLE: u32 = 1;
840 const LP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
841 const LP_POWER_UP_WAIT_TIME_US: u32 = 2;
842
843 const HP_MIN_SLP_TIME_US: u32 = 450;
844 const HP_ANA_WAIT_TIME_PD_TOP_US: u32 = 260;
846 const HP_REGDMA_S2A_WORK_TIME_US: u32 = 685;
847 const HP_ANA_WAIT_TIME_PU_TOP_US: u32 =
848 Self::HP_ANA_WAIT_TIME_PD_TOP_US + Self::HP_REGDMA_S2A_WORK_TIME_US;
849 const HP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
850 const HP_POWER_UP_WAIT_TIME_US: u32 = 26;
851 const HP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
852 const HP_PLL_WAIT_STABLE_TIME_US: u32 = 50;
853}
854
855impl RtcSleepConfig {
856 pub fn deep_slp(&self) -> bool {
858 self.deep
859 }
860
861 pub fn deep() -> Self {
863 Self {
864 deep: true,
865 ..Self::default()
866 }
867 }
868
869 pub(crate) fn is_deep_sleep(&self) -> bool {
870 self.deep_slp()
871 }
872
873 pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
874 self.deep = kind == SleepKind::Deep;
875 }
876
877 pub(crate) fn base_settings(_rtc: &Rtc<'_>) {}
878
879 pub(crate) fn apply(&mut self) {
881 let lp_slow_uses_xtal32k = ClockTree::with(|clocks| {
882 matches!(
883 clocks::lp_slow_clk_config(clocks),
884 Some(LpSlowClkConfig::Xtal32k)
885 )
886 });
887
888 if self.deep {
889 self.pd_flags.set_pd_top(true);
890 self.pd_flags.set_pd_vddsdio(true);
891 self.pd_flags.set_pd_modem(true);
892 self.pd_flags.set_pd_hp_periph(true);
893 self.pd_flags.set_pd_cpu(true);
894 self.pd_flags.set_pd_mem(true);
895 self.pd_flags.set_pd_xtal(true);
896 self.pd_flags.set_pd_hp_aon(true);
897 self.pd_flags.set_pd_lp_periph(true);
898 self.pd_flags.set_pd_xtal32k(!lp_slow_uses_xtal32k);
899 self.pd_flags.set_pd_rc32k(true);
900 self.pd_flags.set_pd_rc_fast(true);
901 } else {
902 self.pd_flags.set_pd_xtal(true);
908 self.pd_flags.set_pd_rc_fast(true);
909 self.pd_flags.set_pd_xtal32k(!lp_slow_uses_xtal32k);
910 }
911 }
912
913 #[crate::ram]
918 pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) -> impl Sized {
919 let restore_clock_config = ClockTree::with(|clocks| {
921 let old_cpu_root_clk = clocks.cpu_root_clk();
922
923 clocks::configure_cpu_root_clk(clocks, CpuRootClkConfig::Xtal);
924
925 DropGuard::new((), move |_| {
927 ClockTree::with(|clocks| {
928 if let Some(old) = old_cpu_root_clk {
929 clocks::configure_cpu_root_clk(clocks, old);
930 }
931 });
932 })
933 });
934
935 let power = PowerSleepConfig::defaults(self.pd_flags);
936 power.apply();
937
938 let config = if self.deep {
939 SleepTimeConfig::deep_sleep()
940 } else {
941 SleepTimeConfig::light_sleep(self.pd_flags)
942 };
943
944 let mut param = ParamSleepConfig::defaults(config, self.pd_flags, self.pd_flags.pd_xtal());
949
950 if self.deep {
951 const PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US: u32 = 500;
952 param.lp_sys.analog_wait_target_cycle =
953 config.us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US) as u8;
954
955 DigitalSleepConfig::defaults_deep_sleep(self.pd_flags).apply();
956 AnalogSleepConfig::defaults_deep_sleep().apply(true);
957 } else {
958 AnalogSleepConfig::defaults_light_sleep(self.pd_flags).apply(false);
959 DigitalSleepConfig::defaults_light_sleep(self.pd_flags).apply();
960 }
961
962 param.apply();
963
964 let mspi_workaround = self.deep && is_rev3_mspi_workaround_needed();
968 if mspi_workaround {
969 install_mspi_workaround_stub();
970 set_boot_from_lp_ram(true);
971 }
972
973 let restore_boot_vector = DropGuard::new((), move |_| {
977 if mspi_workaround {
978 set_boot_from_lp_ram(false);
979 }
980 });
981
982 crate::peripherals::LP_AON::regs()
988 .lp_store8()
989 .modify(|r, w| unsafe { w.bits(r.bits() & !0x01 | self.deep as u32) });
990
991 PMU::regs()
995 .slp_wakeup_cntl2()
996 .write(|w| unsafe { w.bits(wakeup_mask) });
997
998 PMU::regs().slp_wakeup_cntl1().modify(|_, w| unsafe {
999 w.slp_reject_en().bit(reject_mask != 0);
1000 w.sleep_reject_ena().bits(reject_mask)
1001 });
1002
1003 PMU::regs()
1004 .slp_wakeup_cntl4()
1005 .write(|w| w.slp_reject_cause_clr().bit(true));
1006
1007 PMU::regs().int_clr().write(|w| {
1008 w.sw().clear_bit_by_one();
1009 w.soc_sleep_reject().clear_bit_by_one();
1010 w.soc_wakeup().clear_bit_by_one()
1011 });
1012
1013 if self.deep {
1022 pmu_sleep_dcdc_to_ldo_handover();
1023 }
1024
1025 if !self.deep {
1029 usj_pad_backup_and_disable();
1030 }
1031
1032 PMU::regs()
1037 .imm_pad_hold_all()
1038 .write(|w| w.tie_high_pad_slp_sel().set_bit());
1039
1040 PMU::regs()
1045 .slp_wakeup_cntl0()
1046 .write(|w| w.sleep_req().bit(true));
1047
1048 (restore_clock_config, restore_boot_vector)
1049 }
1050
1051 #[crate::ram]
1053 pub(crate) fn finish_sleep(&self) {
1054 PMU::regs()
1058 .imm_pad_hold_all()
1059 .write(|w| w.tie_low_pad_slp_sel().set_bit());
1060
1061 if !self.deep {
1067 usj_pad_restore();
1068 }
1069 }
1070}