1use core::ops::Not;
2
3use crate::{
4 clock::RtcClock,
5 gpio::RtcFunction,
6 rtc_cntl::{
7 Rtc,
8 rtc::{HpAnalog, HpSysCntlReg, HpSysPower, LpAnalog, LpSysPower, SavedClockConfig},
9 sleep::{
10 Ext1WakeupSource,
11 TimerWakeupSource,
12 WakeFromLpCoreWakeupSource,
13 WakeSource,
14 WakeTriggers,
15 WakeupLevel,
16 },
17 },
18 soc::clocks::{ClockTree, TimgCalibrationClockConfig},
19};
20
21impl WakeSource for TimerWakeupSource {
22 fn apply(
23 &self,
24 rtc: &Rtc<'_>,
25 triggers: &mut WakeTriggers,
26 _sleep_config: &mut RtcSleepConfig,
27 ) {
28 triggers.set_timer(true);
29
30 let lp_timer = unsafe { &*esp32c6::LP_TIMER::ptr() };
31 let ticks = crate::clock::us_to_rtc_ticks(self.duration.as_micros() as u64);
33 let now = rtc.time_since_boot_raw();
35 let time_in_ticks = now + ticks;
36 unsafe {
37 lp_timer.tar0_high().write(|w| {
38 w.main_timer_tar_high0()
39 .bits(((time_in_ticks >> 32) & 0xffff) as u16)
40 });
41 lp_timer.tar0_low().write(|w| {
42 w.main_timer_tar_low0()
43 .bits((time_in_ticks & 0xffffffff) as u32)
44 });
45 lp_timer
46 .int_clr()
47 .write(|w| w.soc_wakeup().clear_bit_by_one());
48 lp_timer
49 .tar0_high()
50 .modify(|_, w| w.main_timer_tar_en0().set_bit());
51 }
52 }
53}
54
55impl Ext1WakeupSource<'_, '_> {
56 fn wakeup_pins() -> u8 {
58 unsafe { lp_aon().ext_wakeup_cntl().read().ext_wakeup_sel().bits() }
59 }
60
61 fn wake_io_reset() {
62 use crate::gpio::RtcPin;
63
64 fn uninit_pin(pin: impl RtcPin, wakeup_pins: u8) {
65 if wakeup_pins & (1 << pin.number()) != 0 {
66 pin.rtcio_pad_hold(false);
67 pin.rtc_set_config(false, false, RtcFunction::Rtc);
68 }
69 }
70
71 let wakeup_pins = Ext1WakeupSource::wakeup_pins();
72 uninit_pin(unsafe { crate::peripherals::GPIO0::steal() }, wakeup_pins);
73 uninit_pin(unsafe { crate::peripherals::GPIO1::steal() }, wakeup_pins);
74 uninit_pin(unsafe { crate::peripherals::GPIO2::steal() }, wakeup_pins);
75 uninit_pin(unsafe { crate::peripherals::GPIO3::steal() }, wakeup_pins);
76 uninit_pin(unsafe { crate::peripherals::GPIO4::steal() }, wakeup_pins);
77 uninit_pin(unsafe { crate::peripherals::GPIO5::steal() }, wakeup_pins);
78 uninit_pin(unsafe { crate::peripherals::GPIO6::steal() }, wakeup_pins);
79 uninit_pin(unsafe { crate::peripherals::GPIO7::steal() }, wakeup_pins);
80 }
81}
82
83impl WakeSource for Ext1WakeupSource<'_, '_> {
84 fn apply(
85 &self,
86 _rtc: &Rtc<'_>,
87 triggers: &mut WakeTriggers,
88 _sleep_config: &mut RtcSleepConfig,
89 ) {
90 triggers.set_ext1(true);
92
93 let mut pins = self.pins.borrow_mut();
95 let mut pin_mask = 0u8;
96 let mut level_mask = 0u8;
97 for (pin, level) in pins.iter_mut() {
98 pin_mask |= 1 << pin.number();
99 level_mask |= match level {
100 WakeupLevel::High => 1 << pin.number(),
101 WakeupLevel::Low => 0,
102 };
103
104 pin.rtc_set_config(true, true, RtcFunction::Rtc);
105 pin.rtcio_pad_hold(true);
106 }
107
108 unsafe {
109 lp_aon()
111 .ext_wakeup_cntl()
112 .modify(|_, w| w.ext_wakeup_status_clr().set_bit());
113
114 lp_aon().ext_wakeup_cntl().modify(|r, w| {
116 w.ext_wakeup_sel()
117 .bits(r.ext_wakeup_sel().bits() | pin_mask)
118 .ext_wakeup_lv()
119 .bits(r.ext_wakeup_lv().bits() & !pin_mask | level_mask)
120 });
121 }
122 }
123}
124
125impl Drop for Ext1WakeupSource<'_, '_> {
126 fn drop(&mut self) {
127 let mut pins = self.pins.borrow_mut();
131 for (pin, _level) in pins.iter_mut() {
132 pin.rtc_set_config(true, false, RtcFunction::Rtc);
133 }
134 }
135}
136
137impl WakeSource for WakeFromLpCoreWakeupSource {
138 fn apply(
139 &self,
140 _rtc: &Rtc<'_>,
141 triggers: &mut WakeTriggers,
142 _sleep_config: &mut RtcSleepConfig,
143 ) {
144 triggers.set_lp_core(true);
145 }
146}
147
148#[derive(Clone, Copy)]
150pub struct AnalogSleepConfig {
152 pub hp_sys: HpAnalog,
154 pub lp_sys_sleep: LpAnalog,
157}
158
159impl AnalogSleepConfig {
160 fn defaults_deep_sleep() -> Self {
161 Self {
162 hp_sys: {
164 let mut cfg = HpAnalog::default();
165
166 cfg.bias.set_pd_cur(false);
167 cfg.bias.set_bias_sleep(false);
168 cfg.regulator0.set_xpd(false);
169 cfg.bias.set_dbg_atten(0);
170
171 cfg
172 },
173 lp_sys_sleep: {
175 let mut cfg = LpAnalog::default();
176
177 cfg.regulator1.set_drv_b(0);
178 cfg.bias.set_pd_cur(true);
179 cfg.bias.set_bias_sleep(true);
180 cfg.regulator0.set_slp_xpd(false);
181 cfg.regulator0.set_slp_dbias(0);
182 cfg.regulator0.set_xpd(true);
183 cfg.bias.set_dbg_atten(12);
184 cfg.regulator0.set_dbias(23); cfg
187 },
188 }
189 }
190
191 fn defaults_light_sleep(pd_flags: PowerDownFlags) -> Self {
192 let mut this = Self {
193 hp_sys: {
195 let mut cfg = HpAnalog::default();
196
197 cfg.regulator1.set_drv_b(0);
198 cfg.bias.set_pd_cur(true);
199 cfg.bias.set_bias_sleep(true);
200 cfg.regulator0.set_xpd(true);
201 cfg.bias.set_dbg_atten(0);
202 cfg.regulator0.set_dbias(1); cfg
205 },
206 lp_sys_sleep: {
208 let mut cfg = LpAnalog::default();
209
210 cfg.regulator1.set_drv_b(0);
211 cfg.bias.set_pd_cur(true);
212 cfg.bias.set_bias_sleep(true);
213 cfg.regulator0.set_slp_xpd(false);
214 cfg.regulator0.set_slp_dbias(0);
215 cfg.regulator0.set_xpd(true);
216 cfg.bias.set_dbg_atten(0);
217 cfg.regulator0.set_dbias(12); cfg
220 },
221 };
222
223 if !pd_flags.pd_xtal() {
224 this.hp_sys.bias.set_pd_cur(false);
225 this.hp_sys.bias.set_bias_sleep(false);
226 this.hp_sys.regulator0.set_dbias(25);
227
228 this.lp_sys_sleep.bias.set_pd_cur(false);
229 this.lp_sys_sleep.bias.set_bias_sleep(false);
230 this.lp_sys_sleep.regulator0.set_dbias(26);
231 }
232
233 this
234 }
235
236 fn apply(&self) {
237 unsafe {
240 pmu().hp_sleep_bias().modify(|_, w| {
242 w.hp_sleep_dbg_atten() .bits(self.hp_sys.bias.dbg_atten())
244 .hp_sleep_pd_cur() .bit(self.hp_sys.bias.pd_cur())
246 .sleep() .bit(self.hp_sys.bias.bias_sleep())
248 });
249 pmu().hp_sleep_hp_regulator0().modify(|_, w| {
250 w.hp_sleep_hp_regulator_xpd() .bit(self.hp_sys.regulator0.xpd())
252 .hp_sleep_hp_regulator_dbias() .bits(self.hp_sys.regulator0.dbias())
254 });
255 pmu().hp_sleep_hp_regulator1().modify(|_, w| {
256 w.hp_sleep_hp_regulator_drv_b() .bits(self.hp_sys.regulator1.drv_b())
258 });
259
260 pmu().lp_sleep_bias().modify(|_, w| {
262 w.lp_sleep_dbg_atten() .bits(self.lp_sys_sleep.bias.dbg_atten())
264 .lp_sleep_pd_cur() .bit(self.lp_sys_sleep.bias.pd_cur())
266 .sleep() .bit(self.lp_sys_sleep.bias.bias_sleep())
268 });
269
270 pmu().lp_sleep_lp_regulator0().modify(|_, w| {
271 w.lp_sleep_lp_regulator_slp_xpd() .bit(self.lp_sys_sleep.regulator0.slp_xpd())
273 .lp_sleep_lp_regulator_xpd() .bit(self.lp_sys_sleep.regulator0.xpd())
275 .lp_sleep_lp_regulator_slp_dbias() .bits(self.lp_sys_sleep.regulator0.slp_dbias())
277 .lp_sleep_lp_regulator_dbias() .bits(self.lp_sys_sleep.regulator0.dbias())
279 });
280
281 pmu().lp_sleep_lp_regulator1().modify(|_, w| {
282 w.lp_sleep_lp_regulator_drv_b() .bits(self.lp_sys_sleep.regulator1.drv_b())
284 });
285 }
286 }
287}
288
289#[derive(Clone, Copy)]
292pub struct DigitalSleepConfig {
294 pub syscntl: HpSysCntlReg,
296}
297
298impl DigitalSleepConfig {
299 fn defaults_light_sleep(pd_flags: PowerDownFlags) -> Self {
300 Self {
301 syscntl: {
303 let mut cfg = HpSysCntlReg::default();
304
305 cfg.set_dig_pad_slp_sel(pd_flags.pd_top().not());
306
307 cfg
308 },
309 }
310 }
311
312 fn apply(&self) {
313 unsafe {
315 pmu().hp_sleep_hp_sys_cntl().modify(|_, w| {
316 w.hp_sleep_dig_pad_slp_sel()
317 .bit(self.syscntl.dig_pad_slp_sel())
318 })
319 };
320 }
321}
322
323#[derive(Clone, Copy)]
326pub struct PowerSleepConfig {
328 pub hp_sys: HpSysPower,
330 pub lp_sys_active: LpSysPower,
332 pub lp_sys_sleep: LpSysPower,
334}
335
336impl PowerSleepConfig {
337 fn defaults(pd_flags: PowerDownFlags) -> Self {
338 let mut this = Self {
339 hp_sys: HpSysPower::default(),
340 lp_sys_active: LpSysPower::default(),
341 lp_sys_sleep: LpSysPower::default(),
342 };
343 this.apply_flags(pd_flags);
344 this
345 }
346
347 fn apply_flags(&mut self, pd_flags: PowerDownFlags) {
348 self.hp_sys
350 .dig_power
351 .set_vdd_spi_pd_en(pd_flags.pd_vddsdio());
352 self.hp_sys.dig_power.set_wifi_pd_en(pd_flags.pd_modem());
353 self.hp_sys.dig_power.set_cpu_pd_en(pd_flags.pd_cpu());
354 self.hp_sys.dig_power.set_aon_pd_en(pd_flags.pd_hp_aon());
355 self.hp_sys.dig_power.set_top_pd_en(pd_flags.pd_top());
356
357 self.hp_sys.clk.set_i2c_iso_en(true);
358 self.hp_sys.clk.set_i2c_retention(true);
359
360 self.hp_sys.xtal.set_xpd_xtal(pd_flags.pd_xtal().not());
361
362 self.lp_sys_active.clk_power.set_xpd_xtal32k(true);
363 self.lp_sys_active.clk_power.set_xpd_rc32k(true);
364 self.lp_sys_active.clk_power.set_xpd_fosc(true);
365
366 self.lp_sys_sleep
367 .dig_power
368 .set_peri_pd_en(pd_flags.pd_lp_periph());
369 self.lp_sys_sleep.dig_power.set_mem_dslp(true);
370
371 self.lp_sys_sleep
372 .clk_power
373 .set_xpd_xtal32k(pd_flags.pd_xtal32k().not());
374 self.lp_sys_sleep
375 .clk_power
376 .set_xpd_rc32k(pd_flags.pd_rc32k().not());
377 self.lp_sys_sleep
378 .clk_power
379 .set_xpd_fosc(pd_flags.pd_rc_fast().not());
380
381 self.lp_sys_sleep
382 .xtal
383 .set_xpd_xtal(pd_flags.pd_xtal().not());
384 }
385
386 fn apply(&self) {
387 unsafe {
390 pmu()
392 .hp_sleep_dig_power()
393 .modify(|_, w| w.bits(self.hp_sys.dig_power.0));
394 pmu()
395 .hp_sleep_hp_ck_power()
396 .modify(|_, w| w.bits(self.hp_sys.clk.0));
397 pmu()
398 .hp_sleep_xtal()
399 .modify(|_, w| w.hp_sleep_xpd_xtal().bit(self.hp_sys.xtal.xpd_xtal()));
400
401 pmu()
403 .hp_sleep_lp_dig_power()
404 .modify(|_, w| w.bits(self.lp_sys_active.dig_power.0));
405 pmu()
406 .hp_sleep_lp_ck_power()
407 .modify(|_, w| w.bits(self.lp_sys_active.clk_power.0));
408
409 pmu()
411 .lp_sleep_lp_dig_power()
412 .modify(|_, w| w.bits(self.lp_sys_sleep.dig_power.0));
413 pmu()
414 .lp_sleep_lp_ck_power()
415 .modify(|_, w| w.bits(self.lp_sys_sleep.clk_power.0));
416 pmu()
417 .lp_sleep_xtal()
418 .modify(|_, w| w.lp_sleep_xpd_xtal().bit(self.lp_sys_sleep.xtal.xpd_xtal()));
419 }
420 }
421}
422
423#[derive(Clone, Copy)]
425pub struct HpParam {
427 pub modem_wakeup_wait_cycle: u32,
429 pub analog_wait_target_cycle: u16,
431 pub digital_power_down_wait_cycle: u16,
433 pub digital_power_supply_wait_cycle: u16,
435 pub digital_power_up_wait_cycle: u16,
437 pub pll_stable_wait_cycle: u16,
439 pub modify_icg_cntl_wait_cycle: u8,
441 pub switch_icg_cntl_wait_cycle: u8,
443 pub min_slp_slow_clk_cycle: u8,
445}
446
447#[derive(Clone, Copy)]
449pub struct LpParam {
451 pub digital_power_supply_wait_cycle: u16,
453 pub min_slp_slow_clk_cycle: u8,
455 pub analog_wait_target_cycle: u8,
457 pub digital_power_down_wait_cycle: u8,
459 pub digital_power_up_wait_cycle: u8,
461}
462
463#[derive(Clone, Copy)]
466pub struct HpLpParam {
468 pub xtal_stable_wait_cycle: u16,
470}
471
472#[derive(Clone, Copy)]
474pub struct ParamSleepConfig {
476 pub hp_sys: HpParam,
478 pub lp_sys: LpParam,
480 pub hp_lp: HpLpParam,
482}
483impl ParamSleepConfig {
484 const PMU_SLEEP_PARAM_CONFIG_DEFAULT: Self = Self {
485 hp_sys: HpParam {
486 min_slp_slow_clk_cycle: 10,
487 analog_wait_target_cycle: 2419,
488 digital_power_supply_wait_cycle: 32,
489 digital_power_up_wait_cycle: 32,
490 modem_wakeup_wait_cycle: 20700,
491 pll_stable_wait_cycle: 2,
492
493 digital_power_down_wait_cycle: 0,
494 modify_icg_cntl_wait_cycle: 0,
495 switch_icg_cntl_wait_cycle: 0,
496 },
497 lp_sys: LpParam {
498 min_slp_slow_clk_cycle: 10,
499 analog_wait_target_cycle: 23,
500 digital_power_supply_wait_cycle: 32,
501 digital_power_up_wait_cycle: 32,
502
503 digital_power_down_wait_cycle: 0,
504 },
505 hp_lp: HpLpParam {
506 xtal_stable_wait_cycle: 30,
507 },
508 };
509
510 fn apply(&self) {
511 unsafe {
514 pmu().slp_wakeup_cntl3().modify(|_, w| {
515 w.hp_min_slp_val() .bits(self.hp_sys.min_slp_slow_clk_cycle)
517 .lp_min_slp_val() .bits(self.lp_sys.min_slp_slow_clk_cycle)
519 });
520
521 pmu().slp_wakeup_cntl7().modify(|_, w| {
522 w.ana_wait_target() .bits(self.hp_sys.analog_wait_target_cycle)
524 });
525
526 pmu().power_wait_timer0().modify(|_, w| {
527 w.dg_hp_wait_timer() .bits(self.hp_sys.digital_power_supply_wait_cycle)
529 .dg_hp_powerup_timer() .bits(self.hp_sys.digital_power_up_wait_cycle)
531 });
532
533 pmu().power_wait_timer1().modify(|_, w| {
534 w.dg_lp_wait_timer() .bits(self.lp_sys.digital_power_supply_wait_cycle)
536 .dg_lp_powerup_timer() .bits(self.lp_sys.digital_power_up_wait_cycle)
538 });
539
540 pmu().slp_wakeup_cntl5().modify(|_, w| {
541 w.lp_ana_wait_target() .bits(self.lp_sys.analog_wait_target_cycle)
543 .modem_wait_target() .bits(self.hp_sys.modem_wakeup_wait_cycle)
545 });
546 pmu().power_ck_wait_cntl().modify(|_, w| {
547 w.wait_xtl_stable() .bits(self.hp_lp.xtal_stable_wait_cycle)
549 .wait_pll_stable() .bits(self.hp_sys.pll_stable_wait_cycle)
551 });
552 }
553 }
554
555 fn defaults(config: SleepTimeConfig, pd_flags: PowerDownFlags, pd_xtal: bool) -> Self {
556 let mut param = Self::PMU_SLEEP_PARAM_CONFIG_DEFAULT;
557
558 param.hp_sys.min_slp_slow_clk_cycle =
560 config.us_to_slowclk(MachineConstants::HP_MIN_SLP_TIME_US) as u8;
561 param.hp_sys.analog_wait_target_cycle =
562 config.us_to_fastclk(MachineConstants::HP_ANALOG_WAIT_TIME_US) as u16;
563 param.hp_sys.digital_power_supply_wait_cycle =
564 config.us_to_fastclk(MachineConstants::HP_POWER_SUPPLY_WAIT_TIME_US) as u16;
565 param.hp_sys.digital_power_up_wait_cycle =
566 config.us_to_fastclk(MachineConstants::HP_POWER_UP_WAIT_TIME_US) as u16;
567 param.hp_sys.pll_stable_wait_cycle =
568 config.us_to_fastclk(MachineConstants::HP_PLL_WAIT_STABLE_TIME_US) as u16;
569
570 let hw_wait_time_us = config.pmu_sleep_calculate_hw_wait_time(pd_flags);
571
572 let modem_wakeup_wait_time_us = (config.sleep_time_adjustment
573 + MachineConstants::MODEM_STATE_SKIP_TIME_US
574 + MachineConstants::HP_REGDMA_RF_ON_WORK_TIME_US)
575 .saturating_sub(hw_wait_time_us);
576 param.hp_sys.modem_wakeup_wait_cycle = config.us_to_fastclk(modem_wakeup_wait_time_us);
577
578 param.lp_sys.min_slp_slow_clk_cycle =
579 config.us_to_slowclk(MachineConstants::LP_MIN_SLP_TIME_US) as u8;
580 param.lp_sys.analog_wait_target_cycle =
581 config.us_to_slowclk(MachineConstants::LP_ANALOG_WAIT_TIME_US) as u8;
582 param.lp_sys.digital_power_supply_wait_cycle =
583 config.us_to_fastclk(MachineConstants::LP_POWER_SUPPLY_WAIT_TIME_US) as u16;
584 param.lp_sys.digital_power_up_wait_cycle =
585 config.us_to_fastclk(MachineConstants::LP_POWER_UP_WAIT_TIME_US) as u8;
586
587 param.hp_lp.xtal_stable_wait_cycle = if pd_xtal {
591 config.us_to_slowclk(MachineConstants::LP_XTAL_WAIT_STABLE_TIME_US) as u16
592 } else {
593 config.us_to_fastclk(MachineConstants::HP_XTAL_WAIT_STABLE_TIME_US) as u16
594 };
595
596 param
597 }
598}
599
600#[derive(Clone, Copy)]
601struct SleepTimeConfig {
602 sleep_time_adjustment: u32,
603 slowclk_period: u32,
605 fastclk_period: u32,
606}
607
608const CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ: u32 = 160;
609
610impl SleepTimeConfig {
611 const RTC_CLK_CAL_FRACT: u32 = 19;
612
613 fn rtc_clk_cal_fast(slowclk_cycles: u32) -> u32 {
614 RtcClock::calibrate(TimgCalibrationClockConfig::RcFastDivClk, slowclk_cycles)
615 }
616
617 fn new(_deep: bool) -> Self {
618 let slowclk_period = unsafe { lp_aon().store1().read().data().bits() };
623
624 const FAST_CLK_SRC_CAL_CYCLES: u32 = 2048;
626 let fastclk_period = Self::rtc_clk_cal_fast(FAST_CLK_SRC_CAL_CYCLES);
627
628 Self {
629 sleep_time_adjustment: 0,
630 slowclk_period,
631 fastclk_period,
632 }
633 }
634
635 fn light_sleep(pd_flags: PowerDownFlags) -> Self {
636 const LIGHT_SLEEP_TIME_OVERHEAD_US: u32 = 56;
637
638 let mut this = Self::new(false);
639
640 let sw = LIGHT_SLEEP_TIME_OVERHEAD_US; let hw = this.pmu_sleep_calculate_hw_wait_time(pd_flags);
642
643 this.sleep_time_adjustment = sw + hw;
644
645 this
646 }
647
648 fn deep_sleep() -> Self {
649 let mut this = Self::new(true);
650
651 this.sleep_time_adjustment = 250 + 100 * 240 / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
652
653 this
654 }
655
656 fn us_to_slowclk(&self, us: u32) -> u32 {
657 (us << Self::RTC_CLK_CAL_FRACT) / self.slowclk_period
658 }
659
660 fn slowclk_to_us(&self, rtc_cycles: u32) -> u32 {
661 (rtc_cycles * self.slowclk_period) >> Self::RTC_CLK_CAL_FRACT
662 }
663
664 fn us_to_fastclk(&self, us: u32) -> u32 {
665 (us << Self::RTC_CLK_CAL_FRACT) / self.fastclk_period
666 }
667
668 fn pmu_sleep_calculate_hw_wait_time(&self, pd_flags: PowerDownFlags) -> u32 {
669 let lp_wakeup_wait_time_us = self.slowclk_to_us(MachineConstants::LP_WAKEUP_WAIT_CYCLE);
671 let lp_clk_switch_time_us = self.slowclk_to_us(MachineConstants::LP_CLK_SWITCH_CYCLE);
672 let lp_clk_power_on_wait_time_us = if pd_flags.pd_xtal() {
673 MachineConstants::LP_XTAL_WAIT_STABLE_TIME_US
674 } else {
675 self.slowclk_to_us(MachineConstants::LP_CLK_POWER_ON_WAIT_CYCLE)
676 };
677
678 let lp_hw_wait_time_us = MachineConstants::LP_MIN_SLP_TIME_US
679 + MachineConstants::LP_ANALOG_WAIT_TIME_US
680 + lp_clk_power_on_wait_time_us
681 + lp_wakeup_wait_time_us
682 + lp_clk_switch_time_us
683 + MachineConstants::LP_POWER_SUPPLY_WAIT_TIME_US
684 + MachineConstants::LP_POWER_UP_WAIT_TIME_US;
685
686 let hp_digital_power_up_wait_time_us = MachineConstants::HP_POWER_SUPPLY_WAIT_TIME_US
688 + MachineConstants::HP_POWER_UP_WAIT_TIME_US;
689 let hp_regdma_wait_time_us = u32::max(
690 MachineConstants::HP_REGDMA_S2M_WORK_TIME_US
691 + MachineConstants::HP_REGDMA_M2A_WORK_TIME_US,
692 MachineConstants::HP_REGDMA_S2A_WORK_TIME_US,
693 );
694 let hp_clock_wait_time_us = MachineConstants::HP_XTAL_WAIT_STABLE_TIME_US
695 + MachineConstants::HP_PLL_WAIT_STABLE_TIME_US;
696
697 let hp_hw_wait_time_us = MachineConstants::HP_ANALOG_WAIT_TIME_US
698 + u32::max(
699 hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us,
700 hp_clock_wait_time_us,
701 );
702
703 #[rustfmt::skip] const CONFIG_ESP_RADIO_ENHANCED_LIGHT_SLEEP: bool = true;
722
723 let (rf_on_protect_time_us, sync_time_us) = if CONFIG_ESP_RADIO_ENHANCED_LIGHT_SLEEP {
724 (
725 MachineConstants::HP_REGDMA_RF_ON_WORK_TIME_US,
726 MachineConstants::HP_CLOCK_DOMAIN_SYNC_TIME_US,
727 )
728 } else {
729 (0, 0)
730 };
731
732 lp_hw_wait_time_us + hp_hw_wait_time_us + sync_time_us + rf_on_protect_time_us
733 }
734}
735
736#[derive(Clone, Copy)]
738pub struct RtcSleepConfig {
740 pub deep: bool,
742 pub pd_flags: PowerDownFlags,
744}
745
746impl Default for RtcSleepConfig {
747 fn default() -> Self {
748 Self {
752 deep: false,
753 pd_flags: PowerDownFlags(0),
754 }
755 }
756}
757
758unsafe fn pmu<'a>() -> &'a esp32c6::pmu::RegisterBlock {
759 unsafe { &*esp32c6::PMU::ptr() }
760}
761
762unsafe fn lp_aon<'a>() -> &'a esp32c6::lp_aon::RegisterBlock {
763 unsafe { &*esp32c6::LP_AON::ptr() }
764}
765
766bitfield::bitfield! {
767 #[derive(Clone, Copy)]
768 pub struct PowerDownFlags(u32);
770
771 pub u32, pd_top , set_pd_top : 0;
773 pub u32, pd_vddsdio , set_pd_vddsdio : 1;
775 pub u32, pd_modem , set_pd_modem : 2;
777 pub u32, pd_hp_periph, set_pd_hp_periph: 3;
779 pub u32, pd_cpu , set_pd_cpu : 4;
781 pub u32, pd_hp_aon , set_pd_hp_aon : 5;
783 pub u32, pd_mem_g0 , set_pd_mem_g0 : 6;
785 pub u32, pd_mem_g1 , set_pd_mem_g1 : 7;
787 pub u32, pd_mem_g2 , set_pd_mem_g2 : 8;
789 pub u32, pd_mem_g3 , set_pd_mem_g3 : 9;
791 pub u32, pd_xtal , set_pd_xtal : 10;
793 pub u32, pd_rc_fast , set_pd_rc_fast : 11;
795 pub u32, pd_xtal32k , set_pd_xtal32k : 12;
797 pub u32, pd_rc32k , set_pd_rc32k : 13;
799 pub u32, pd_lp_periph, set_pd_lp_periph: 14;
801}
802
803impl PowerDownFlags {
804 pub fn pd_mem(self) -> bool {
806 self.pd_mem_g0() && self.pd_mem_g1() && self.pd_mem_g2() && self.pd_mem_g3()
807 }
808
809 pub fn set_pd_mem(&mut self, value: bool) {
812 self.set_pd_mem_g0(value);
813 self.set_pd_mem_g1(value);
814 self.set_pd_mem_g2(value);
815 self.set_pd_mem_g3(value);
816 }
817}
818
819struct MachineConstants;
821impl MachineConstants {
822 const LP_MIN_SLP_TIME_US: u32 = 450;
823 const LP_WAKEUP_WAIT_CYCLE: u32 = 4;
824 const LP_ANALOG_WAIT_TIME_US: u32 = 154;
825 const LP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
826 const LP_CLK_SWITCH_CYCLE: u32 = 1;
827 const LP_CLK_POWER_ON_WAIT_CYCLE: u32 = 1;
828 const LP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
829 const LP_POWER_UP_WAIT_TIME_US: u32 = 2;
830
831 const HP_MIN_SLP_TIME_US: u32 = 450;
832 const HP_CLOCK_DOMAIN_SYNC_TIME_US: u32 = 150;
833 const HP_SYSTEM_DFS_UP_WORK_TIME_US: u32 = 124;
834 const HP_ANALOG_WAIT_TIME_US: u32 = 154;
835 const HP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
836 const HP_POWER_UP_WAIT_TIME_US: u32 = 2;
837 const HP_REGDMA_S2M_WORK_TIME_US: u32 = 172;
838 const HP_REGDMA_S2A_WORK_TIME_US: u32 = 480;
839 const HP_REGDMA_M2A_WORK_TIME_US: u32 = 278;
840 const HP_REGDMA_RF_ON_WORK_TIME_US: u32 = 70;
843 const HP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
846 const HP_PLL_WAIT_STABLE_TIME_US: u32 = 1;
847
848 const MODEM_STATE_SKIP_TIME_US: u32 = Self::HP_REGDMA_M2A_WORK_TIME_US
849 + Self::HP_SYSTEM_DFS_UP_WORK_TIME_US
850 + Self::LP_MIN_SLP_TIME_US;
851}
852
853impl RtcSleepConfig {
854 pub fn deep_slp(&self) -> bool {
856 self.deep
857 }
858
859 pub fn deep() -> Self {
861 Self {
863 deep: true,
864 ..Self::default()
865 }
866 }
867
868 pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
869 Self::wake_io_reset();
870 }
871
872 fn wake_io_reset() {
873 Ext1WakeupSource::wake_io_reset();
875 }
876
877 pub(crate) fn apply(&mut self) {
879 if self.deep {
880 self.pd_flags.set_pd_top(true);
882 self.pd_flags.set_pd_vddsdio(true);
883 self.pd_flags.set_pd_modem(true);
884 self.pd_flags.set_pd_hp_periph(true);
885 self.pd_flags.set_pd_cpu(true);
886 self.pd_flags.set_pd_mem(true);
887 self.pd_flags.set_pd_xtal(true);
888 self.pd_flags.set_pd_hp_aon(true);
889 self.pd_flags.set_pd_lp_periph(true);
890 self.pd_flags.set_pd_xtal32k(true);
891 self.pd_flags.set_pd_rc32k(true);
892 self.pd_flags.set_pd_rc_fast(true);
893 }
894 }
895
896 pub(crate) fn start_sleep(&self, wakeup_triggers: WakeTriggers) {
900 const PMU_EXT0_WAKEUP_EN: u32 = 1 << 0;
901 const PMU_EXT1_WAKEUP_EN: u32 = 1 << 1;
902 const PMU_GPIO_WAKEUP_EN: u32 = 1 << 2;
903 const PMU_LP_TIMER_WAKEUP_EN: u32 = 1 << 4;
904 const PMU_WIFI_SOC_WAKEUP_EN: u32 = 1 << 5;
905 const PMU_UART0_WAKEUP_EN: u32 = 1 << 6;
906 const PMU_UART1_WAKEUP_EN: u32 = 1 << 7;
907 const PMU_SDIO_WAKEUP_EN: u32 = 1 << 8;
908 const PMU_BLE_SOC_WAKEUP_EN: u32 = 1 << 10;
909 const PMU_LP_CORE_WAKEUP_EN: u32 = 1 << 11;
910 const PMU_USB_WAKEUP_EN: u32 = 1 << 14;
911 const MODEM_REJECT: u32 = 1 << 16;
912
913 const RTC_SLEEP_REJECT_MASK: u32 = PMU_EXT0_WAKEUP_EN
914 | PMU_EXT1_WAKEUP_EN
915 | PMU_GPIO_WAKEUP_EN
916 | PMU_LP_TIMER_WAKEUP_EN
917 | PMU_WIFI_SOC_WAKEUP_EN
918 | PMU_UART0_WAKEUP_EN
919 | PMU_UART1_WAKEUP_EN
920 | PMU_SDIO_WAKEUP_EN
921 | PMU_BLE_SOC_WAKEUP_EN
922 | PMU_LP_CORE_WAKEUP_EN
923 | PMU_USB_WAKEUP_EN;
924
925 let wakeup_mask = wakeup_triggers.0 as u32;
926 let reject_mask = if self.deep {
927 0
928 } else {
929 let reject_mask = RTC_SLEEP_REJECT_MASK | MODEM_REJECT;
931 wakeup_mask & reject_mask
932 };
933
934 let cpu_freq_config = ClockTree::with(|clocks| {
935 let cpu_freq_config = SavedClockConfig::save(clocks);
936 crate::soc::clocks::configure_soc_root_clk(
937 clocks,
938 crate::soc::clocks::SocRootClkConfig::Xtal,
939 );
940 cpu_freq_config
941 });
942
943 let power = PowerSleepConfig::defaults(self.pd_flags);
946 power.apply();
947
948 let config = if self.deep {
950 SleepTimeConfig::deep_sleep()
951 } else {
952 SleepTimeConfig::light_sleep(self.pd_flags)
953 };
954
955 let mut param =
956 ParamSleepConfig::defaults(config, self.pd_flags, power.hp_sys.xtal.xpd_xtal());
957
958 if self.deep {
959 const PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US: u32 = 500;
960 param.lp_sys.analog_wait_target_cycle =
961 config.us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US) as u8;
962
963 AnalogSleepConfig::defaults_deep_sleep().apply();
964 } else {
965 AnalogSleepConfig::defaults_light_sleep(self.pd_flags).apply();
966 DigitalSleepConfig::defaults_light_sleep(self.pd_flags).apply();
967 }
968
969 param.apply();
970
971 unsafe {
974 lp_aon()
976 .store9()
977 .modify(|r, w| w.bits(r.bits() & !0x01 | self.deep as u32));
978
979 pmu().slp_wakeup_cntl2().write(|w| w.bits(wakeup_mask));
981
982 pmu().slp_wakeup_cntl1().modify(|_, w| {
984 w.slp_reject_en()
985 .bit(true)
986 .sleep_reject_ena()
987 .bits(reject_mask)
988 });
989
990 pmu()
992 .slp_wakeup_cntl4()
993 .write(|w| w.slp_reject_cause_clr().bit(true));
994
995 pmu().int_clr().write(|w| {
996 w.sw() .clear_bit_by_one()
998 .soc_sleep_reject() .clear_bit_by_one()
1000 .soc_wakeup() .clear_bit_by_one()
1002 });
1003
1004 #[cfg(not(soc_has_pmu))]
1008 if !(self.deep && wakeup_triggers.touch) {
1009 APB_SARADC::regs()
1010 .ctrl()
1011 .modify(|_, w| w.saradc2_pwdet_drv().bit(false));
1012 }
1013
1014 pmu().slp_wakeup_cntl0().write(|w| w.sleep_req().bit(true));
1018
1019 loop {
1021 let int_raw = pmu().int_raw().read();
1022 if int_raw.soc_wakeup().bit_is_set() || int_raw.soc_sleep_reject().bit_is_set() {
1023 break;
1024 }
1025 }
1026 }
1027
1028 ClockTree::with(|clocks| {
1031 cpu_freq_config.restore(clocks);
1032 });
1033 }
1034
1035 pub(crate) fn finish_sleep(&self) {
1037 Self::wake_io_reset();
1044 }
1045}