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::{SleepKind, pmu_common::SleepTimeConfig},
10 },
11 soc::{
12 clocks::{self, ClockTree, CpuClkConfig, HpRootClkConfig, LpSlowClkConfig},
13 xtal32k,
14 },
15};
16
17#[derive(Clone, Copy)]
19pub struct AnalogSleepConfig {
24 pub regulator_xpd: bool,
26}
27
28impl AnalogSleepConfig {
29 fn defaults_deep_sleep() -> Self {
30 Self {
31 regulator_xpd: false,
33 }
34 }
35
36 fn defaults_light_sleep() -> Self {
37 Self {
38 regulator_xpd: true,
40 }
41 }
42
43 fn apply(&self) {
44 PMU::regs().hp_sleep_hp_regulator0().modify(|_, w| {
46 w.hp_sleep_hp_regulator_xpd() .bit(self.regulator_xpd)
48 });
49 }
50}
51
52#[derive(Clone, Copy)]
55pub struct DigitalSleepConfig {
57 pub syscntl: HpSysCntlReg,
59 pub icg_func: u32,
61 pub deep_sleep: bool,
63}
64
65impl DigitalSleepConfig {
66 fn defaults_light_sleep(pd_flags: PowerDownFlags) -> Self {
67 Self {
68 syscntl: {
70 let mut cfg = HpSysCntlReg::default();
71
72 cfg.set_dig_pad_slp_sel(pd_flags.pd_top().not());
73
74 cfg
75 },
76 icg_func: 0xffff_ffff, deep_sleep: false,
78 }
79 }
80
81 fn defaults_deep_sleep() -> Self {
82 Self {
83 syscntl: HpSysCntlReg::default(),
85 icg_func: 0,
86 deep_sleep: true,
87 }
88 }
89
90 fn apply(&self) {
91 PMU::regs().hp_sleep_sysclk().modify(|_, w| {
93 w.hp_sleep_icg_sys_clock_en().bit(self.icg_func != 0) });
95 PMU::regs().hp_sleep_icg_hp_func().modify(|_, w| unsafe {
96 w.hp_sleep_dig_icg_func_en().bits(self.icg_func) });
98 if !self.deep_sleep {
99 PMU::regs().hp_sleep_hp_sys_cntl().modify(|_, w| {
100 w.hp_sleep_dig_pad_slp_sel()
101 .bit(self.syscntl.dig_pad_slp_sel()) });
103 }
104 }
105}
106
107#[derive(Clone, Copy)]
110pub struct PowerSleepConfig {
112 pub hp_sys: HpSysPower,
114 pub lp_sys_active: LpSysPower,
116 pub lp_sys_sleep: LpSysPower,
118}
119
120impl PowerSleepConfig {
121 fn defaults(pd_flags: PowerDownFlags) -> Self {
122 let mut this = Self {
123 hp_sys: HpSysPower::default(),
124 lp_sys_active: LpSysPower::default(),
125 lp_sys_sleep: LpSysPower::default(),
126 };
127 this.apply_flags(pd_flags);
128 this
129 }
130
131 fn apply_flags(&mut self, pd_flags: PowerDownFlags) {
132 self.hp_sys
134 .dig_power
135 .set_vdd_spi_pd_en(pd_flags.pd_vddsdio());
136 self.hp_sys.dig_power.set_modem_pd_en(pd_flags.pd_modem());
137 self.hp_sys.dig_power.set_cpu_pd_en(pd_flags.pd_cpu());
138 self.hp_sys.dig_power.set_top_pd_en(pd_flags.pd_top());
139
140 self.hp_sys.clk.set_xpd_bbpll(false);
141
142 self.hp_sys.xtal.set_xpd_xtal(pd_flags.pd_xtal().not());
143
144 self.lp_sys_active
145 .clk_power
146 .set_xpd_xtal32k(xtal32k::use_xtal32k());
147 self.lp_sys_active.clk_power.set_xpd_fosc(true);
148
149 self.lp_sys_sleep.dig_power.set_mem_dslp(true);
150 self.lp_sys_sleep.dig_power.set_vddbat_mode(0);
151 self.lp_sys_sleep.dig_power.set_bod_source_sel(true);
152
153 self.lp_sys_sleep
154 .clk_power
155 .set_xpd_xtal32k(pd_flags.pd_xtal32k().not());
156 self.lp_sys_sleep
157 .clk_power
158 .set_xpd_fosc(pd_flags.pd_rc_fast().not());
159
160 self.lp_sys_sleep
161 .xtal
162 .set_xpd_xtal(pd_flags.pd_xtal().not());
163 }
164
165 fn apply(&self) {
166 PMU::regs()
169 .hp_sleep_dig_power()
170 .modify(|_, w| unsafe { w.bits(self.hp_sys.dig_power.0) });
171 PMU::regs()
172 .hp_sleep_hp_ck_power()
173 .modify(|_, w| unsafe { w.bits(self.hp_sys.clk.0) });
174 PMU::regs()
175 .hp_sleep_xtal()
176 .modify(|_, w| w.hp_sleep_xpd_xtal().bit(self.hp_sys.xtal.xpd_xtal()));
177
178 PMU::regs()
180 .hp_sleep_lp_dig_power()
181 .modify(|_, w| unsafe { w.bits(self.lp_sys_active.dig_power.0) });
182 PMU::regs()
183 .hp_sleep_lp_ck_power()
184 .modify(|_, w| unsafe { w.bits(self.lp_sys_active.clk_power.0) });
185
186 PMU::regs()
188 .lp_sleep_lp_dig_power()
189 .modify(|_, w| unsafe { w.bits(self.lp_sys_sleep.dig_power.0) });
190 PMU::regs()
191 .lp_sleep_lp_ck_power()
192 .modify(|_, w| unsafe { w.bits(self.lp_sys_sleep.clk_power.0) });
193 PMU::regs()
194 .lp_sleep_xtal()
195 .modify(|_, w| w.lp_sleep_xpd_xtal().bit(self.lp_sys_sleep.xtal.xpd_xtal()));
196 }
197}
198
199#[derive(Clone, Copy)]
201pub struct HpParam {
203 pub modem_wakeup_wait_cycle: u32,
205 pub analog_wait_target_cycle: u16,
207 pub digital_power_down_wait_cycle: u16,
209 pub digital_power_supply_wait_cycle: u16,
211 pub digital_power_up_wait_cycle: u16,
213 pub pll_stable_wait_cycle: u16,
215 pub modify_icg_cntl_wait_cycle: u8,
217 pub switch_icg_cntl_wait_cycle: u8,
219 pub min_slp_slow_clk_cycle: u8,
221}
222
223#[derive(Clone, Copy)]
225pub struct LpParam {
227 pub digital_power_supply_wait_cycle: u16,
229 pub min_slp_slow_clk_cycle: u8,
231 pub analog_wait_target_cycle: u8,
233 pub digital_power_down_wait_cycle: u8,
235 pub digital_power_up_wait_cycle: u8,
237}
238
239#[derive(Clone, Copy)]
242pub struct HpLpParam {
244 pub xtal_stable_wait_cycle: u16,
246}
247
248#[derive(Clone, Copy)]
250pub struct ParamSleepConfig {
252 pub hp_sys: HpParam,
254 pub lp_sys: LpParam,
256 pub hp_lp: HpLpParam,
258}
259impl ParamSleepConfig {
260 const PMU_SLEEP_PARAM_CONFIG_DEFAULT: Self = Self {
261 hp_sys: HpParam {
262 min_slp_slow_clk_cycle: 10,
263 analog_wait_target_cycle: 1700,
264 digital_power_supply_wait_cycle: 32,
265 digital_power_up_wait_cycle: 32,
266 modem_wakeup_wait_cycle: 0,
267 pll_stable_wait_cycle: 2,
268
269 digital_power_down_wait_cycle: 0,
270 modify_icg_cntl_wait_cycle: 0,
271 switch_icg_cntl_wait_cycle: 0,
272 },
273 lp_sys: LpParam {
274 min_slp_slow_clk_cycle: 10,
275 analog_wait_target_cycle: 15,
276 digital_power_supply_wait_cycle: 32,
277 digital_power_up_wait_cycle: 32,
278
279 digital_power_down_wait_cycle: 0,
280 },
281 hp_lp: HpLpParam {
282 xtal_stable_wait_cycle: 30,
283 },
284 };
285
286 fn apply(&self) {
287 unsafe {
289 PMU::regs().slp_wakeup_cntl3().modify(|_, w| {
290 w.hp_min_slp_val().bits(self.hp_sys.min_slp_slow_clk_cycle);
292 w.lp_min_slp_val().bits(self.lp_sys.min_slp_slow_clk_cycle)
294 });
295
296 PMU::regs().slp_wakeup_cntl7().modify(|_, w| {
297 w.ana_wait_target() .bits(self.hp_sys.analog_wait_target_cycle)
299 });
300
301 PMU::regs().slp_wakeup_cntl5().modify(|_, w| {
302 w.lp_ana_wait_target() .bits(self.lp_sys.analog_wait_target_cycle)
304 });
305
306 PMU::regs().power_wait_timer0().modify(|_, w| {
307 w.dg_hp_wait_timer()
309 .bits(self.hp_sys.digital_power_supply_wait_cycle);
310 w.dg_hp_powerup_timer()
312 .bits(self.hp_sys.digital_power_up_wait_cycle)
313 });
314
315 PMU::regs().power_wait_timer1().modify(|_, w| {
316 w.dg_lp_wait_timer()
318 .bits(self.lp_sys.digital_power_supply_wait_cycle);
319 w.dg_lp_powerup_timer()
321 .bits(self.lp_sys.digital_power_up_wait_cycle)
322 });
323
324 PMU::regs().power_ck_wait_cntl().modify(|_, w| {
325 w.wait_xtl_stable().bits(self.hp_lp.xtal_stable_wait_cycle);
327 w.wait_pll_stable().bits(self.hp_sys.pll_stable_wait_cycle)
329 });
330 }
331 }
332
333 fn defaults(config: SleepTimeConfig, pd_xtal: bool) -> Self {
334 let mut param = Self::PMU_SLEEP_PARAM_CONFIG_DEFAULT;
335
336 param.hp_sys.min_slp_slow_clk_cycle =
338 config.us_to_slowclk(machine_constants::HP_MIN_SLP_TIME_US) as u8;
339 param.hp_sys.analog_wait_target_cycle =
340 config.us_to_fastclk(machine_constants::HP_ANALOG_WAIT_TIME_US) as u16;
341 param.hp_sys.digital_power_supply_wait_cycle =
342 config.us_to_fastclk(machine_constants::HP_POWER_SUPPLY_WAIT_TIME_US) as u16;
343 param.hp_sys.digital_power_up_wait_cycle =
344 config.us_to_fastclk(machine_constants::HP_POWER_UP_WAIT_TIME_US) as u16;
345 param.hp_sys.pll_stable_wait_cycle =
346 config.us_to_fastclk(machine_constants::HP_PLL_WAIT_STABLE_TIME_US) as u16;
347
348 param.lp_sys.min_slp_slow_clk_cycle =
349 config.us_to_slowclk(machine_constants::LP_MIN_SLP_TIME_US) as u8;
350 param.lp_sys.analog_wait_target_cycle =
351 config.us_to_slowclk(machine_constants::LP_ANALOG_WAIT_TIME_US) as u8;
352 param.lp_sys.digital_power_supply_wait_cycle =
353 config.us_to_fastclk(machine_constants::LP_POWER_SUPPLY_WAIT_TIME_US) as u16;
354 param.lp_sys.digital_power_up_wait_cycle =
355 config.us_to_fastclk(machine_constants::LP_POWER_UP_WAIT_TIME_US) as u8;
356
357 param.hp_lp.xtal_stable_wait_cycle = if pd_xtal {
361 config.us_to_slowclk(machine_constants::LP_XTAL_WAIT_STABLE_TIME_US) as u16
362 } else {
363 config.us_to_fastclk(machine_constants::HP_XTAL_WAIT_STABLE_TIME_US) as u16
364 };
365
366 param
367 }
368}
369
370impl SleepTimeConfig {
371 pub(crate) const CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ: u32 = 96;
372 pub(crate) const LIGHT_SLEEP_TIME_OVERHEAD_US: u32 = 9;
373
374 pub(crate) fn pmu_sleep_calculate_hw_wait_time(&self, pd_flags: PowerDownFlags) -> u32 {
375 let lp_clk_switch_time_us = self.slowclk_to_us(machine_constants::LP_CLK_SWITCH_CYCLE);
376 let lp_clk_power_on_wait_time_us = if pd_flags.pd_xtal() {
377 machine_constants::LP_XTAL_WAIT_STABLE_TIME_US
378 } else {
379 self.slowclk_to_us(machine_constants::LP_CLK_POWER_ON_WAIT_CYCLE)
380 };
381
382 let lp_hw_wait_time_us = machine_constants::LP_MIN_SLP_TIME_US
383 + machine_constants::LP_ANALOG_WAIT_TIME_US
384 + lp_clk_power_on_wait_time_us
385 + lp_clk_switch_time_us
386 + machine_constants::LP_POWER_SUPPLY_WAIT_TIME_US
387 + machine_constants::LP_POWER_UP_WAIT_TIME_US;
388
389 let hp_digital_power_up_wait_time_us = machine_constants::HP_POWER_SUPPLY_WAIT_TIME_US
390 + machine_constants::HP_POWER_UP_WAIT_TIME_US;
391 let hp_regdma_wait_time_us = if pd_flags.pd_top() {
392 machine_constants::HP_REGDMA_S2A_WORK_TIME_PD_TOP_US
393 } else {
394 machine_constants::HP_REGDMA_S2A_WORK_TIME_PU_TOP_US
395 };
396 let hp_clock_wait_time_us = machine_constants::HP_XTAL_WAIT_STABLE_TIME_US
397 + machine_constants::HP_PLL_WAIT_STABLE_TIME_US;
398
399 let hp_hw_wait_time_us = machine_constants::HP_ANALOG_WAIT_TIME_US
400 + hp_digital_power_up_wait_time_us
401 + hp_regdma_wait_time_us
402 + hp_clock_wait_time_us;
403
404 lp_hw_wait_time_us + hp_hw_wait_time_us
405 }
406}
407
408#[derive(Clone, Copy)]
410pub struct RtcSleepConfig {
411 pub deep: bool,
413 pub pd_flags: PowerDownFlags,
415 need_pd_top: bool,
417}
418
419impl Default for RtcSleepConfig {
420 fn default() -> Self {
421 Self {
425 deep: false,
426 pd_flags: PowerDownFlags(0),
427 need_pd_top: false,
428 }
429 }
430}
431
432bitfield::bitfield! {
433 #[derive(Clone, Copy)]
434 pub struct PowerDownFlags(u32);
436
437 pub u32, pd_top , set_pd_top : 0;
439 pub u32, pd_vddsdio , set_pd_vddsdio : 1;
441 pub u32, pd_modem , set_pd_modem : 2;
443 pub u32, pd_cpu , set_pd_cpu : 3;
445 pub u32, pd_xtal , set_pd_xtal : 4;
447 pub u32, pd_rc_fast , set_pd_rc_fast : 5;
449 pub u32, pd_xtal32k , set_pd_xtal32k : 6;
451}
452
453mod machine_constants {
455 pub const LP_MIN_SLP_TIME_US: u32 = 450;
456 pub const LP_ANALOG_WAIT_TIME_US: u32 = 154;
457 pub const LP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
458 pub const LP_CLK_SWITCH_CYCLE: u32 = 1;
459 pub const LP_CLK_POWER_ON_WAIT_CYCLE: u32 = 1;
460 pub const LP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
461 pub const LP_POWER_UP_WAIT_TIME_US: u32 = 2;
462
463 pub const HP_MIN_SLP_TIME_US: u32 = 450;
464 pub const HP_ANALOG_WAIT_TIME_US: u32 = 154;
465 pub const HP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
466 pub const HP_POWER_UP_WAIT_TIME_US: u32 = 2;
467 pub const HP_REGDMA_S2A_WORK_TIME_PD_TOP_US: u32 = 480;
468 pub const HP_REGDMA_S2A_WORK_TIME_PU_TOP_US: u32 = 390;
469 pub const HP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
470 pub const HP_PLL_WAIT_STABLE_TIME_US: u32 = 50;
471}
472
473impl RtcSleepConfig {
474 pub fn deep_slp(&self) -> bool {
476 self.deep
477 }
478
479 pub fn deep() -> Self {
481 Self {
483 deep: true,
484 ..Self::default()
485 }
486 }
487
488 pub(crate) fn is_deep_sleep(&self) -> bool {
489 self.deep
490 }
491
492 pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
493 self.deep = kind == SleepKind::Deep;
494 }
495
496 pub(crate) fn base_settings(_rtc: &Rtc<'_>) {}
497
498 pub(crate) fn apply(&mut self) {
500 let lp_slow_uses_xtal32k = ClockTree::with(|clocks| {
501 matches!(
502 clocks::lp_slow_clk_config(clocks),
503 Some(LpSlowClkConfig::Xtal32k)
504 )
505 });
506
507 if self.deep {
508 self.pd_flags.set_pd_top(self.need_pd_top.not());
510 self.pd_flags.set_pd_vddsdio(true);
511 self.pd_flags.set_pd_modem(true);
512 self.pd_flags.set_pd_cpu(true);
513 self.pd_flags.set_pd_xtal(true);
514 self.pd_flags.set_pd_rc_fast(true);
515 self.pd_flags.set_pd_xtal32k(!lp_slow_uses_xtal32k);
516 } else {
517 self.pd_flags.set_pd_xtal(true);
524 self.pd_flags.set_pd_rc_fast(true);
525 self.pd_flags.set_pd_xtal32k(!lp_slow_uses_xtal32k);
526 }
527 }
528
529 pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) -> impl Sized {
534 let restore_clock_config = ClockTree::with(|clocks| {
535 let old_hp_root_clk = clocks.hp_root_clk();
536 let old_cpu_divider = clocks.cpu_clk();
537
538 clocks::configure_hp_root_clk(clocks, HpRootClkConfig::Xtal);
539 clocks::configure_cpu_clk(clocks, CpuClkConfig::new(0));
540
541 DropGuard::new((), move |_| {
543 ClockTree::with(|clocks| {
544 if let Some(old_hp_root_clk) = old_hp_root_clk {
545 clocks::configure_hp_root_clk(clocks, old_hp_root_clk);
546 }
547 if let Some(old_cpu_divider) = old_cpu_divider {
548 clocks::configure_cpu_clk(clocks, old_cpu_divider);
549 }
550 });
551 })
552 });
553
554 let power = PowerSleepConfig::defaults(self.pd_flags);
559 power.apply();
560
561 let config = if self.deep {
563 SleepTimeConfig::deep_sleep()
564 } else {
565 SleepTimeConfig::light_sleep(self.pd_flags)
566 };
567
568 let param = ParamSleepConfig::defaults(config, power.hp_sys.xtal.xpd_xtal());
569
570 if self.deep {
571 DigitalSleepConfig::defaults_deep_sleep().apply();
572 AnalogSleepConfig::defaults_deep_sleep().apply();
573 } else {
574 DigitalSleepConfig::defaults_light_sleep(self.pd_flags).apply();
575 AnalogSleepConfig::defaults_light_sleep().apply();
576 }
577
578 param.apply();
579
580 LP_AON::regs()
584 .store9()
585 .modify(|r, w| unsafe { w.bits(r.bits() & !0x01 | self.deep as u32) });
586
587 PMU::regs()
589 .slp_wakeup_cntl2()
590 .write(|w| unsafe { w.bits(wakeup_mask) });
591
592 PMU::regs().slp_wakeup_cntl1().modify(|_, w| unsafe {
594 w.slp_reject_en().bit(reject_mask != 0);
595 w.sleep_reject_ena().bits(reject_mask)
596 });
597
598 PMU::regs().int_clr().write(|w| {
599 w.soc_wakeup().clear_bit_by_one();
601 w.soc_sleep_reject().clear_bit_by_one()
603 });
604
605 PMU::regs()
607 .slp_wakeup_cntl4()
608 .write(|w| w.slp_reject_cause_clr().bit(true));
609
610 PMU::regs()
614 .slp_wakeup_cntl0()
615 .write(|w| w.sleep_req().bit(true));
616
617 restore_clock_config
618 }
619
620 pub(crate) fn finish_sleep(&self) {
622 }
625}