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