1use core::ops::Not;
2
3use crate::{
4 peripherals::{LP_AON, PMU},
5 private::DropGuard,
6 rtc_cntl::{
7 Rtc,
8 rtc::{HpSysCntlReg, HpSysPower, LpSysPower},
9 sleep::{
10 SleepKind,
11 pmu_common::{SleepTimeConfig, request_sleep},
12 },
13 },
14 soc::{
15 clocks::{self, ClockTree, CpuClkConfig, HpRootClkConfig},
16 xtal32k,
17 },
18};
19
20#[derive(Clone, Copy)]
22pub struct AnalogSleepConfig {
27 pub regulator_xpd: bool,
29}
30
31impl AnalogSleepConfig {
32 fn defaults_deep_sleep() -> Self {
33 Self {
34 regulator_xpd: false,
36 }
37 }
38
39 fn defaults_light_sleep() -> Self {
40 Self {
41 regulator_xpd: true,
43 }
44 }
45
46 fn apply(&self) {
47 PMU::regs().hp_sleep_hp_regulator0().modify(|_, w| {
49 w.hp_sleep_hp_regulator_xpd() .bit(self.regulator_xpd)
51 });
52 }
53}
54
55#[derive(Clone, Copy)]
58pub struct DigitalSleepConfig {
60 pub syscntl: HpSysCntlReg,
62 pub icg_func: u32,
64 pub deep_sleep: bool,
66}
67
68impl DigitalSleepConfig {
69 fn defaults_light_sleep(pd_flags: PowerDownFlags) -> Self {
70 Self {
71 syscntl: {
73 let mut cfg = HpSysCntlReg::default();
74
75 cfg.set_dig_pad_slp_sel(pd_flags.pd_top().not());
76
77 cfg
78 },
79 icg_func: 0,
82 deep_sleep: false,
83 }
84 }
85
86 fn defaults_deep_sleep() -> Self {
87 Self {
88 syscntl: HpSysCntlReg::default(),
90 icg_func: 0,
91 deep_sleep: true,
92 }
93 }
94
95 fn apply(&self) {
96 PMU::regs().hp_sleep_sysclk().modify(|_, w| {
98 w.hp_sleep_icg_sys_clock_en().bit(self.icg_func != 0) });
100 PMU::regs().hp_sleep_icg_hp_func().modify(|_, w| unsafe {
101 w.hp_sleep_dig_icg_func_en().bits(self.icg_func) });
103 if !self.deep_sleep {
104 PMU::regs().hp_sleep_hp_sys_cntl().modify(|_, w| {
105 w.hp_sleep_dig_pad_slp_sel()
106 .bit(self.syscntl.dig_pad_slp_sel()) });
108 }
109 }
110}
111
112#[derive(Clone, Copy)]
115pub struct PowerSleepConfig {
117 pub hp_sys: HpSysPower,
119 pub lp_sys_active: LpSysPower,
121 pub lp_sys_sleep: LpSysPower,
123}
124
125impl PowerSleepConfig {
126 fn defaults(pd_flags: PowerDownFlags) -> Self {
127 let mut this = Self {
128 hp_sys: HpSysPower::default(),
129 lp_sys_active: LpSysPower::default(),
130 lp_sys_sleep: LpSysPower::default(),
131 };
132 this.apply_flags(pd_flags);
133 this
134 }
135
136 fn apply_flags(&mut self, pd_flags: PowerDownFlags) {
137 self.hp_sys
139 .dig_power
140 .set_vdd_spi_pd_en(pd_flags.pd_vddsdio());
141 self.hp_sys.dig_power.set_modem_pd_en(pd_flags.pd_modem());
142 self.hp_sys.dig_power.set_cpu_pd_en(pd_flags.pd_cpu());
143 self.hp_sys.dig_power.set_top_pd_en(pd_flags.pd_top());
144
145 self.hp_sys.clk.set_xpd_bbpll(false);
146
147 self.hp_sys.xtal.set_xpd_xtal(pd_flags.pd_xtal().not());
148
149 self.lp_sys_active
150 .clk_power
151 .set_xpd_xtal32k(xtal32k::use_xtal32k());
152 self.lp_sys_active.clk_power.set_xpd_fosc(true);
153
154 self.lp_sys_sleep.dig_power.set_mem_dslp(true);
155 self.lp_sys_sleep.dig_power.set_vddbat_mode(0);
156 self.lp_sys_sleep.dig_power.set_bod_source_sel(true);
157
158 self.lp_sys_sleep
159 .clk_power
160 .set_xpd_xtal32k(pd_flags.pd_xtal32k().not());
161 self.lp_sys_sleep
162 .clk_power
163 .set_xpd_fosc(pd_flags.pd_rc_fast().not());
164
165 self.lp_sys_sleep
166 .xtal
167 .set_xpd_xtal(pd_flags.pd_xtal().not());
168 }
169
170 fn apply(&self) {
171 PMU::regs()
174 .hp_sleep_dig_power()
175 .modify(|_, w| unsafe { w.bits(self.hp_sys.dig_power.0) });
176 PMU::regs()
177 .hp_sleep_hp_ck_power()
178 .modify(|_, w| unsafe { w.bits(self.hp_sys.clk.0) });
179 PMU::regs()
180 .hp_sleep_xtal()
181 .modify(|_, w| w.hp_sleep_xpd_xtal().bit(self.hp_sys.xtal.xpd_xtal()));
182
183 PMU::regs()
185 .hp_sleep_lp_dig_power()
186 .modify(|_, w| unsafe { w.bits(self.lp_sys_active.dig_power.0) });
187 PMU::regs()
188 .hp_sleep_lp_ck_power()
189 .modify(|_, w| unsafe { w.bits(self.lp_sys_active.clk_power.0) });
190
191 PMU::regs()
193 .lp_sleep_lp_dig_power()
194 .modify(|_, w| unsafe { w.bits(self.lp_sys_sleep.dig_power.0) });
195 PMU::regs()
196 .lp_sleep_lp_ck_power()
197 .modify(|_, w| unsafe { w.bits(self.lp_sys_sleep.clk_power.0) });
198 PMU::regs()
199 .lp_sleep_xtal()
200 .modify(|_, w| w.lp_sleep_xpd_xtal().bit(self.lp_sys_sleep.xtal.xpd_xtal()));
201 }
202}
203
204#[derive(Clone, Copy)]
206pub struct HpParam {
208 pub modem_wakeup_wait_cycle: u32,
210 pub analog_wait_target_cycle: u16,
212 pub digital_power_down_wait_cycle: u16,
214 pub digital_power_supply_wait_cycle: u16,
216 pub digital_power_up_wait_cycle: u16,
218 pub pll_stable_wait_cycle: u16,
220 pub modify_icg_cntl_wait_cycle: u8,
222 pub switch_icg_cntl_wait_cycle: u8,
224 pub min_slp_slow_clk_cycle: u8,
226}
227
228#[derive(Clone, Copy)]
230pub struct LpParam {
232 pub digital_power_supply_wait_cycle: u16,
234 pub min_slp_slow_clk_cycle: u8,
236 pub analog_wait_target_cycle: u8,
238 pub digital_power_down_wait_cycle: u8,
240 pub digital_power_up_wait_cycle: u8,
242}
243
244#[derive(Clone, Copy)]
247pub struct HpLpParam {
249 pub xtal_stable_wait_cycle: u16,
251}
252
253#[derive(Clone, Copy)]
255pub struct ParamSleepConfig {
257 pub hp_sys: HpParam,
259 pub lp_sys: LpParam,
261 pub hp_lp: HpLpParam,
263}
264impl ParamSleepConfig {
265 const PMU_SLEEP_PARAM_CONFIG_DEFAULT: Self = Self {
266 hp_sys: HpParam {
267 min_slp_slow_clk_cycle: 10,
268 analog_wait_target_cycle: 1700,
269 digital_power_supply_wait_cycle: 32,
270 digital_power_up_wait_cycle: 32,
271 modem_wakeup_wait_cycle: 0,
272 pll_stable_wait_cycle: 2,
273
274 digital_power_down_wait_cycle: 0,
275 modify_icg_cntl_wait_cycle: 0,
276 switch_icg_cntl_wait_cycle: 0,
277 },
278 lp_sys: LpParam {
279 min_slp_slow_clk_cycle: 10,
280 analog_wait_target_cycle: 15,
281 digital_power_supply_wait_cycle: 32,
282 digital_power_up_wait_cycle: 32,
283
284 digital_power_down_wait_cycle: 0,
285 },
286 hp_lp: HpLpParam {
287 xtal_stable_wait_cycle: 30,
288 },
289 };
290
291 fn apply(&self) {
292 unsafe {
294 PMU::regs().slp_wakeup_cntl3().modify(|_, w| {
295 w.hp_min_slp_val().bits(self.hp_sys.min_slp_slow_clk_cycle);
297 w.lp_min_slp_val().bits(self.lp_sys.min_slp_slow_clk_cycle)
299 });
300
301 PMU::regs().slp_wakeup_cntl7().modify(|_, w| {
302 w.ana_wait_target() .bits(self.hp_sys.analog_wait_target_cycle)
304 });
305
306 PMU::regs().slp_wakeup_cntl5().modify(|_, w| {
307 w.lp_ana_wait_target() .bits(self.lp_sys.analog_wait_target_cycle)
309 });
310
311 PMU::regs().power_wait_timer0().modify(|_, w| {
312 w.dg_hp_wait_timer()
314 .bits(self.hp_sys.digital_power_supply_wait_cycle);
315 w.dg_hp_powerup_timer()
317 .bits(self.hp_sys.digital_power_up_wait_cycle)
318 });
319
320 PMU::regs().power_wait_timer1().modify(|_, w| {
321 w.dg_lp_wait_timer()
323 .bits(self.lp_sys.digital_power_supply_wait_cycle);
324 w.dg_lp_powerup_timer()
326 .bits(self.lp_sys.digital_power_up_wait_cycle)
327 });
328
329 PMU::regs().power_ck_wait_cntl().modify(|_, w| {
330 w.wait_xtl_stable().bits(self.hp_lp.xtal_stable_wait_cycle);
332 w.wait_pll_stable().bits(self.hp_sys.pll_stable_wait_cycle)
334 });
335 }
336 }
337
338 fn defaults(config: SleepTimeConfig, pd_xtal: bool) -> Self {
339 let mut param = Self::PMU_SLEEP_PARAM_CONFIG_DEFAULT;
340
341 param.hp_sys.min_slp_slow_clk_cycle =
343 config.us_to_slowclk(machine_constants::HP_MIN_SLP_TIME_US) as u8;
344 param.hp_sys.analog_wait_target_cycle =
345 config.us_to_fastclk(machine_constants::HP_ANALOG_WAIT_TIME_US) as u16;
346 param.hp_sys.digital_power_supply_wait_cycle =
347 config.us_to_fastclk(machine_constants::HP_POWER_SUPPLY_WAIT_TIME_US) as u16;
348 param.hp_sys.digital_power_up_wait_cycle =
349 config.us_to_fastclk(machine_constants::HP_POWER_UP_WAIT_TIME_US) as u16;
350 param.hp_sys.pll_stable_wait_cycle =
351 config.us_to_fastclk(machine_constants::HP_PLL_WAIT_STABLE_TIME_US) as u16;
352
353 param.lp_sys.min_slp_slow_clk_cycle =
354 config.us_to_slowclk(machine_constants::LP_MIN_SLP_TIME_US) as u8;
355 param.lp_sys.analog_wait_target_cycle =
356 config.us_to_slowclk(machine_constants::LP_ANALOG_WAIT_TIME_US) as u8;
357 param.lp_sys.digital_power_supply_wait_cycle =
358 config.us_to_fastclk(machine_constants::LP_POWER_SUPPLY_WAIT_TIME_US) as u16;
359 param.lp_sys.digital_power_up_wait_cycle =
360 config.us_to_fastclk(machine_constants::LP_POWER_UP_WAIT_TIME_US) as u8;
361
362 param.hp_lp.xtal_stable_wait_cycle = if pd_xtal {
366 config.us_to_slowclk(machine_constants::LP_XTAL_WAIT_STABLE_TIME_US) as u16
367 } else {
368 config.us_to_fastclk(machine_constants::HP_XTAL_WAIT_STABLE_TIME_US) as u16
369 };
370
371 param
372 }
373}
374
375impl SleepTimeConfig {
376 pub(crate) const CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ: u32 = 96;
377 pub(crate) const LIGHT_SLEEP_TIME_OVERHEAD_US: u32 = 9;
378
379 pub(crate) fn pmu_sleep_calculate_hw_wait_time(&self, pd_flags: PowerDownFlags) -> u32 {
380 let lp_clk_switch_time_us = self.slowclk_to_us(machine_constants::LP_CLK_SWITCH_CYCLE);
381 let lp_clk_power_on_wait_time_us = if pd_flags.pd_xtal() {
382 machine_constants::LP_XTAL_WAIT_STABLE_TIME_US
383 } else {
384 self.slowclk_to_us(machine_constants::LP_CLK_POWER_ON_WAIT_CYCLE)
385 };
386
387 let lp_hw_wait_time_us = machine_constants::LP_MIN_SLP_TIME_US
388 + machine_constants::LP_ANALOG_WAIT_TIME_US
389 + lp_clk_power_on_wait_time_us
390 + lp_clk_switch_time_us
391 + machine_constants::LP_POWER_SUPPLY_WAIT_TIME_US
392 + machine_constants::LP_POWER_UP_WAIT_TIME_US;
393
394 let hp_digital_power_up_wait_time_us = machine_constants::HP_POWER_SUPPLY_WAIT_TIME_US
395 + machine_constants::HP_POWER_UP_WAIT_TIME_US;
396 let hp_regdma_wait_time_us = if pd_flags.pd_top() {
397 machine_constants::HP_REGDMA_S2A_WORK_TIME_PD_TOP_US
398 } else {
399 machine_constants::HP_REGDMA_S2A_WORK_TIME_PU_TOP_US
400 };
401 let hp_clock_wait_time_us = machine_constants::HP_XTAL_WAIT_STABLE_TIME_US
402 + machine_constants::HP_PLL_WAIT_STABLE_TIME_US;
403
404 let hp_hw_wait_time_us = machine_constants::HP_ANALOG_WAIT_TIME_US
405 + hp_digital_power_up_wait_time_us
406 + hp_regdma_wait_time_us
407 + hp_clock_wait_time_us;
408
409 lp_hw_wait_time_us + hp_hw_wait_time_us
410 }
411}
412
413#[derive(Clone, Copy)]
415pub struct RtcSleepConfig {
416 pub deep: bool,
418 pub pd_flags: PowerDownFlags,
420 need_pd_top: bool,
422}
423
424impl Default for RtcSleepConfig {
425 fn default() -> Self {
426 Self {
430 deep: false,
431 pd_flags: PowerDownFlags(0),
432 need_pd_top: false,
433 }
434 }
435}
436
437bitfield::bitfield! {
438 #[derive(Clone, Copy)]
439 pub struct PowerDownFlags(u32);
441
442 pub u32, pd_top , set_pd_top : 0;
444 pub u32, pd_vddsdio , set_pd_vddsdio : 1;
446 pub u32, pd_modem , set_pd_modem : 2;
448 pub(crate) u32, pd_cpu, set_pd_cpu: 3;
453 pub u32, pd_xtal , set_pd_xtal : 4;
455 pub u32, pd_rc_fast , set_pd_rc_fast : 5;
457 pub u32, pd_xtal32k , set_pd_xtal32k : 6;
459}
460
461mod machine_constants {
463 pub const LP_MIN_SLP_TIME_US: u32 = 450;
464 pub const LP_ANALOG_WAIT_TIME_US: u32 = 154;
465 pub const LP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
466 pub const LP_CLK_SWITCH_CYCLE: u32 = 1;
467 pub const LP_CLK_POWER_ON_WAIT_CYCLE: u32 = 1;
468 pub const LP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
469 pub const LP_POWER_UP_WAIT_TIME_US: u32 = 2;
470
471 pub const HP_MIN_SLP_TIME_US: u32 = 450;
472 pub const HP_ANALOG_WAIT_TIME_US: u32 = 154;
473 pub const HP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
474 pub const HP_POWER_UP_WAIT_TIME_US: u32 = 2;
475 pub const HP_REGDMA_S2A_WORK_TIME_PD_TOP_US: u32 = 480;
476 pub const HP_REGDMA_S2A_WORK_TIME_PU_TOP_US: u32 = 390;
477 pub const HP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
478 pub const HP_PLL_WAIT_STABLE_TIME_US: u32 = 50;
479}
480
481impl RtcSleepConfig {
482 pub fn deep_slp(&self) -> bool {
484 self.deep
485 }
486
487 pub fn deep() -> Self {
489 Self {
491 deep: true,
492 ..Self::default()
493 }
494 }
495
496 pub(crate) fn is_deep_sleep(&self) -> bool {
497 self.deep
498 }
499
500 pub(crate) fn base_settings(_rtc: &Rtc<'_>) {}
501
502 pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
507 self.deep = kind == SleepKind::Deep;
508
509 let lp_slow_uses_xtal32k = cfg_select! {
510 use_xtal32k => ClockTree::with(|clocks| {
511 matches!(
512 clocks::lp_slow_clk_config(clocks),
513 Some(clocks::LpSlowClkConfig::Xtal32k)
514 )
515 }),
516 _ => false,
517 };
518
519 if self.deep {
520 self.pd_flags.set_pd_top(self.need_pd_top.not());
522 self.pd_flags.set_pd_vddsdio(true);
523 self.pd_flags.set_pd_modem(true);
524 self.pd_flags.set_pd_cpu(true);
525 self.pd_flags.set_pd_xtal(true);
526 self.pd_flags.set_pd_rc_fast(true);
527 self.pd_flags.set_pd_xtal32k(!lp_slow_uses_xtal32k);
528 } else {
529 self.pd_flags.set_pd_xtal(true);
536 self.pd_flags.set_pd_rc_fast(true);
537 self.pd_flags.set_pd_xtal32k(!lp_slow_uses_xtal32k);
538 }
539 }
540
541 #[crate::ram]
547 pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) -> impl Sized {
548 let restore_clock_config = ClockTree::with(|clocks| {
549 let old_hp_root_clk = clocks.hp_root_clk();
550 let old_cpu_divider = clocks.cpu_clk();
551
552 clocks::configure_hp_root_clk(clocks, HpRootClkConfig::Xtal);
553 clocks::configure_cpu_clk(clocks, CpuClkConfig::new(0));
554
555 DropGuard::new((), move |_| {
557 ClockTree::with(|clocks| {
558 if let Some(old_hp_root_clk) = old_hp_root_clk {
559 clocks::configure_hp_root_clk(clocks, old_hp_root_clk);
560 }
561 if let Some(old_cpu_divider) = old_cpu_divider {
562 clocks::configure_cpu_clk(clocks, old_cpu_divider);
563 }
564 });
565 })
566 });
567
568 let power = PowerSleepConfig::defaults(self.pd_flags);
573 power.apply();
574
575 let config = if self.deep {
577 SleepTimeConfig::deep_sleep()
578 } else {
579 SleepTimeConfig::light_sleep(self.pd_flags)
580 };
581
582 let param = ParamSleepConfig::defaults(config, power.hp_sys.xtal.xpd_xtal());
583
584 if self.deep {
585 DigitalSleepConfig::defaults_deep_sleep().apply();
586 AnalogSleepConfig::defaults_deep_sleep().apply();
587 } else {
588 DigitalSleepConfig::defaults_light_sleep(self.pd_flags).apply();
589 AnalogSleepConfig::defaults_light_sleep().apply();
590 }
591
592 param.apply();
593
594 LP_AON::regs()
598 .store9()
599 .modify(|r, w| unsafe { w.bits(r.bits() & !0x01 | self.deep as u32) });
600
601 PMU::regs()
603 .slp_wakeup_cntl2()
604 .write(|w| unsafe { w.bits(wakeup_mask) });
605
606 PMU::regs().slp_wakeup_cntl1().modify(|_, w| unsafe {
608 w.slp_reject_en().bit(reject_mask != 0);
609 w.sleep_reject_ena().bits(reject_mask)
610 });
611
612 PMU::regs().int_clr().write(|w| {
613 w.soc_wakeup().clear_bit_by_one();
615 w.soc_sleep_reject().clear_bit_by_one()
617 });
618
619 PMU::regs()
621 .slp_wakeup_cntl4()
622 .write(|w| w.slp_reject_cause_clr().bit(true));
623
624 restore_clock_config
627 }
628
629 #[inline(always)]
633 pub(crate) fn enter_sleep(&self) -> bool {
634 request_sleep()
635 }
636
637 #[inline(always)]
639 pub(crate) fn finish_sleep(&self) {
640 }
643}