Skip to main content

esp_hal/rtc_cntl/sleep/
esp32c3.rs

1use super::SleepKind;
2use crate::{
3    peripherals::{APB_CTRL, BB, EXTMEM, FE, FE2, LPWR, NRX, SPI0, SPI1, SYSTEM},
4    rtc_cntl::Rtc,
5    soc::regi2c,
6};
7
8// Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP,
9// RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values.
10// Valid if RTC_CNTL_DBG_ATTEN is 0.
11/// Digital bias voltage level of 0.90V.
12pub const RTC_CNTL_DBIAS_0V90: u8 = 13;
13/// Digital bias voltage level of 0.95V.
14pub const RTC_CNTL_DBIAS_0V95: u8 = 16;
15/// Digital bias voltage level of 1.00V.
16pub const RTC_CNTL_DBIAS_1V00: u8 = 18;
17/// Digital bias voltage level of 1.05V.
18pub const RTC_CNTL_DBIAS_1V05: u8 = 20;
19/// Digital bias voltage level of 1.10V.
20pub const RTC_CNTL_DBIAS_1V10: u8 = 23;
21/// Digital bias voltage level of 1.15V.
22pub const RTC_CNTL_DBIAS_1V15: u8 = 25;
23/// Digital bias voltage level of 1.20V.
24pub const RTC_CNTL_DBIAS_1V20: u8 = 28;
25/// Digital bias voltage level of 1.25V.
26pub const RTC_CNTL_DBIAS_1V25: u8 = 30;
27/// Digital bias voltage level of approximately 1.34V.
28pub const RTC_CNTL_DBIAS_1V30: u8 = 31;
29
30/// Default attenuation setting during light sleep, with a voltage drop.
31pub const RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT: u8 = 5;
32/// No attenuation (no voltage drop) during light sleep.
33pub const RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP: u8 = 0;
34/// Default attenuation setting during deep sleep, with maximum voltage drop.
35pub const RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT: u8 = 15;
36/// No attenuation (no voltage drop) during deep sleep.
37pub const RTC_CNTL_DBG_ATTEN_DEEPSLEEP_NODROP: u8 = 0;
38
39/// Default bias setting during sleep mode.
40pub const RTC_CNTL_BIASSLP_SLEEP_DEFAULT: u8 = 1;
41/// Keeps the bias for ultra-low power sleep mode always on.
42pub const RTC_CNTL_BIASSLP_SLEEP_ON: u8 = 0;
43
44/// Default power-down current setting during sleep mode.
45pub const RTC_CNTL_PD_CUR_SLEEP_DEFAULT: u8 = 1;
46/// Keeps the power-down current setting for sleep mode always on.
47pub const RTC_CNTL_PD_CUR_SLEEP_ON: u8 = 0;
48
49/// Default driver bias setting for the digital domain during sleep mode.
50pub const RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT: u8 = 254;
51
52/// Default debug attenuation setting for the monitor mode.
53pub const RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT: u8 = 0;
54/// Default bias setting for sleep mode in the monitor mode.
55pub const RTC_CNTL_BIASSLP_MONITOR_DEFAULT: bool = false;
56/// Default power-down current setting for the monitor mode.
57pub const RTC_CNTL_PD_CUR_MONITOR_DEFAULT: bool = false;
58
59/// Default number of cycles to wait for the PLL buffer to stabilize.
60pub const RTC_CNTL_PLL_BUF_WAIT_DEFAULT: u8 = 20;
61/// Default number of cycles to wait for the XTL buffer to stabilize.
62pub const RTC_CNTL_XTL_BUF_WAIT_DEFAULT: u8 = 100;
63/// Default number of cycles to wait for the internal 8 MHz clock to stabilize.
64pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
65/// Default number of cycles required to enable the internal 8 MHz clock.
66pub const RTC_CK8M_ENABLE_WAIT_DEFAULT: u8 = 5;
67
68/// Minimum number of cycles for sleep duration.
69pub const RTC_CNTL_MIN_SLP_VAL_MIN: u8 = 2;
70
71/// Power-up cycles for other hardware blocks.
72pub const OTHER_BLOCKS_POWERUP: u8 = 1;
73/// Waits cycles for other hardware blocks to stabilize.
74pub const OTHER_BLOCKS_WAIT: u16 = 1;
75
76/// Disables GPIO interrupt.
77pub const GPIO_INTR_DISABLE: u8 = 0;
78/// Sets GPIO interrupt to trigger on a low level signal.
79pub const GPIO_INTR_LOW_LEVEL: u8 = 4;
80/// Sets GPIO interrupt to trigger on a high level signal.
81pub const GPIO_INTR_HIGH_LEVEL: u8 = 5;
82
83/// Specifies the function configuration for GPIO pins.
84pub const PIN_FUNC_GPIO: u8 = 1;
85/// Index for signaling GPIO output.
86pub const SIG_GPIO_OUT_IDX: u32 = 128;
87/// Maximum number of GPIO pins supported.
88pub const GPIO_NUM_MAX: usize = 22;
89
90bitfield::bitfield! {
91    #[derive(Clone, Copy)]
92    /// RTC Configuration.
93    pub struct RtcConfig(u32);
94    impl Debug;
95    /// Number of rtc_fast_clk cycles to wait for 8M clock to be ready
96    pub u8, ck8m_wait, set_ck8m_wait: 7, 0;
97    /// Number of rtc_fast_clk cycles to wait for XTAL clock to be ready
98    pub u8, xtal_wait, set_xtal_wait: 15, 8;
99    /// Number of rtc_fast_clk cycles to wait for PLL clock to be ready
100    pub u8, pll_wait, set_pll_wait: 23, 16;
101    /// Performs clock control related initialization.
102    pub clkctl_init, set_clkctl_init: 24;
103    /// Performs power control related initialization.
104    pub pwrctl_init, set_pwrctl_init: 25;
105    /// Forces power-down of `RTC_DBOOST`.
106    pub rtc_dboost_fpd, set_rtc_dboost_fpd: 26;
107    /// Keeps the XTAL oscillator powered up in sleep.
108    pub xtal_fpu, set_xtal_fpu: 27;
109    /// Keeps the BBPLL oscillator powered up in sleep.
110    pub bbpll_fpu, set_bbpll_fpu: 28;
111    /// Enables clock gating when the CPU is in wait-for-interrupt state.
112    pub cpu_waiti_clk_gate, set_cpu_waiti_clk_gate: 29;
113    /// Calibrates Ocode to make bandgap voltage more precise.
114    pub cali_ocode, set_cali_ocode: 30;
115}
116
117impl Default for RtcConfig {
118    fn default() -> Self {
119        let mut cfg = Self(Default::default());
120        cfg.set_ck8m_wait(RTC_CNTL_CK8M_WAIT_DEFAULT);
121        cfg.set_xtal_wait(RTC_CNTL_XTL_BUF_WAIT_DEFAULT);
122        cfg.set_pll_wait(RTC_CNTL_PLL_BUF_WAIT_DEFAULT);
123        cfg.set_clkctl_init(true);
124        cfg.set_pwrctl_init(true);
125        cfg.set_rtc_dboost_fpd(true);
126        cfg.set_cpu_waiti_clk_gate(true);
127        cfg
128    }
129}
130
131bitfield::bitfield! {
132    #[derive(Clone, Copy)]
133    /// Configuration for RTC initialization.
134    pub struct RtcInitConfig(u128);
135    impl Debug;
136    /// Number of cycles required to power up WiFi
137    pub u8, wifi_powerup_cycles, set_wifi_powerup_cycles: 6, 0;
138    /// Number of wait cycles for WiFi to stabilize
139    pub u16, wifi_wait_cycles, set_wifi_wait_cycles: 15, 7;
140    /// Number of cycles required to power up Bluetooth
141    pub u8, bt_powerup_cycles, set_bt_powerup_cycles: 22, 16;
142    /// Number of wait cycles for Bluetooth to stabilize
143    pub u16, bt_wait_cycles, set_bt_wait_cycles: 31, 23;
144    /// Number of cycles required to power up the top CPU
145    pub u8, cpu_top_powerup_cycles, set_cpu_top_powerup_cycles: 38, 32;
146    /// Number of wait cycles for the top CPU to stabilize
147    pub u16, cpu_top_wait_cycles, set_cpu_top_wait_cycles: 47, 39;
148    /// Number of cycles required to power up the digital wrapper
149    pub u8, dg_wrap_powerup_cycles, set_dg_wrap_powerup_cycles: 54, 48;
150    /// Number of wait cycles for the digital wrapper to stabilize
151    pub u16, dg_wrap_wait_cycles, set_dg_wrap_wait_cycles: 63, 55;
152    /// Number of cycles required to power up the digital peripherals
153    pub u8, dg_peri_powerup_cycles, set_dg_peri_powerup_cycles: 70, 64;
154    /// Number of wait cycles for the digital peripherals to stabilize
155    pub u16, dg_peri_wait_cycles, set_dg_peri_wait_cycles: 79, 71;
156}
157
158impl Default for RtcInitConfig {
159    fn default() -> Self {
160        let mut cfg = Self(Default::default());
161        cfg.set_wifi_powerup_cycles(OTHER_BLOCKS_POWERUP);
162        cfg.set_bt_powerup_cycles(OTHER_BLOCKS_POWERUP);
163        cfg.set_cpu_top_powerup_cycles(OTHER_BLOCKS_POWERUP);
164        cfg.set_dg_wrap_powerup_cycles(OTHER_BLOCKS_POWERUP);
165        cfg.set_dg_peri_powerup_cycles(OTHER_BLOCKS_POWERUP);
166        cfg.set_wifi_wait_cycles(OTHER_BLOCKS_WAIT);
167        cfg.set_bt_wait_cycles(OTHER_BLOCKS_WAIT);
168        cfg.set_cpu_top_wait_cycles(OTHER_BLOCKS_WAIT);
169        cfg.set_dg_wrap_wait_cycles(OTHER_BLOCKS_WAIT);
170        cfg.set_dg_peri_wait_cycles(OTHER_BLOCKS_WAIT);
171        cfg
172    }
173}
174
175bitfield::bitfield! {
176    #[derive(Clone, Copy)]
177    /// Configuration for RTC sleep mode.
178    pub struct RtcSleepConfig(u64);
179    impl Debug;
180    /// force normal voltage in sleep mode (digital domain memory)
181    pub lslp_mem_inf_fpu, set_lslp_mem_inf_fpu: 0;
182    /// keep low voltage in sleep mode (even if ULP/touch is used)
183    pub rtc_mem_inf_follow_cpu, set_rtc_mem_inf_follow_cpu: 1;
184    /// power down RTC fast memory
185    pub rtc_fastmem_pd_en, set_rtc_fastmem_pd_en: 2;
186    /// power down RTC slow memory
187    pub rtc_slowmem_pd_en, set_rtc_slowmem_pd_en: 3;
188    /// power down RTC peripherals
189    pub rtc_peri_pd_en, set_rtc_peri_pd_en: 4;
190    /// power down WiFi
191    pub wifi_pd_en, set_wifi_pd_en: 5;
192    /// power down BT
193    pub bt_pd_en, set_bt_pd_en: 6;
194    /// power down CPU, but not restart when lightsleep.
195    ///
196    /// Crate-private, because a light sleep derives this from the installed retention memory. A
197    /// CPU power-down without retention loses the CPU state.
198    pub(crate) cpu_pd_en, set_cpu_pd_en: 7;
199    /// Powers down Internal 8M oscillator.
200    pub int_8m_pd_en, set_int_8m_pd_en: 8;
201    /// power down digital peripherals
202    pub dig_peri_pd_en, set_dig_peri_pd_en: 9;
203    /// power down digital domain
204    pub deep_slp, set_deep_slp: 10;
205    /// enable WDT flashboot mode
206    pub wdt_flashboot_mod_en, set_wdt_flashboot_mod_en: 11;
207    /// set bias for digital domain, in sleep mode
208    pub u8, dig_dbias_slp, set_dig_dbias_slp: 16, 12;
209    /// set bias for RTC domain, in sleep mode
210    pub u8, rtc_dbias_slp, set_rtc_dbias_slp: 21, 17;
211    /// voltage parameter, in sleep mode
212    pub u8, dbg_atten_slp, set_dbg_atten_slp: 25, 22;
213    /// circuit control parameter, in monitor mode
214    pub bias_sleep_monitor, set_bias_sleep_monitor: 26;
215    /// circuit control parameter, in sleep mode
216    pub bias_sleep_slp, set_bias_sleep_slp: 27;
217    /// circuit control parameter, in monitor mode
218    pub pd_cur_slp, set_pd_cur_slp: 28;
219    /// power down VDDSDIO regulator
220    pub vddsdio_pd_en, set_vddsdio_pd_en: 29;
221    /// keep main XTAL powered up in sleep
222    pub xtal_fpu, set_xtal_fpu: 30;
223    /// keep rtc regulator powered up in sleep
224    pub rtc_regulator_fpu, set_rtc_regulator_fpu: 31;
225    /// enable deep sleep reject
226    pub deep_slp_reject, set_deep_slp_reject: 32;
227    /// enable light sleep reject
228    pub light_slp_reject, set_light_slp_reject: 33;
229}
230
231impl Default for RtcSleepConfig {
232    fn default() -> Self {
233        let mut cfg = Self(Default::default());
234        cfg.set_deep_slp_reject(true);
235        cfg.set_light_slp_reject(true);
236        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
237        cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_1V10);
238
239        // This is the light-sleep config. The main XTAL is powered down in sleep
240        // (`xtal_fpu` stays false), so the analog regulator/bias must use the
241        // same XTAL-down settings that `deep()` applies "because of xtal_fpu".
242        cfg.set_rtc_regulator_fpu(true);
243        cfg.set_bias_sleep_monitor(true);
244        cfg.set_bias_sleep_slp(true);
245        cfg.set_pd_cur_slp(true);
246        cfg
247    }
248}
249
250const SYSCON_SRAM_POWER_UP: u8 = 0x0000000F;
251const SYSCON_ROM_POWER_UP: u8 = 0x00000003;
252
253fn rtc_sleep_pu(val: bool) {
254    LPWR::regs()
255        .dig_pwc()
256        .modify(|_, w| w.lslp_mem_force_pu().bit(val).fastmem_force_lpu().bit(val));
257
258    APB_CTRL::regs().front_end_mem_pd().modify(|_r, w| {
259        w.dc_mem_force_pu().bit(val);
260        w.pbus_mem_force_pu().bit(val);
261        w.agc_mem_force_pu().bit(val)
262    });
263
264    BB::regs()
265        .bbpd_ctrl()
266        .modify(|_r, w| w.fft_force_pu().bit(val).dc_est_force_pu().bit(val));
267
268    NRX::regs().nrxpd_ctrl().modify(|_, w| {
269        w.rx_rot_force_pu().bit(val);
270        w.vit_force_pu().bit(val);
271        w.demap_force_pu().bit(val)
272    });
273
274    FE::regs()
275        .gen_ctrl()
276        .modify(|_, w| w.iq_est_force_pu().bit(val));
277
278    FE2::regs()
279        .tx_interp_ctrl()
280        .modify(|_, w| w.tx_inf_force_pu().bit(val));
281
282    APB_CTRL::regs().mem_power_up().modify(|_r, w| unsafe {
283        w.sram_power_up()
284            .bits(if val { SYSCON_SRAM_POWER_UP } else { 0 });
285        w.rom_power_up()
286            .bits(if val { SYSCON_ROM_POWER_UP } else { 0 })
287    });
288}
289
290impl RtcSleepConfig {
291    /// Configures the RTC for deep sleep mode.
292    pub fn deep() -> Self {
293        // Set up for ultra-low power sleep. Wakeup sources may modify these settings.
294        let mut cfg = Self::default();
295
296        cfg.set_lslp_mem_inf_fpu(false);
297        cfg.set_rtc_mem_inf_follow_cpu(true); // ?
298        cfg.set_rtc_fastmem_pd_en(true);
299        cfg.set_rtc_slowmem_pd_en(true);
300        cfg.set_rtc_peri_pd_en(true);
301        cfg.set_wifi_pd_en(true);
302        cfg.set_bt_pd_en(true);
303        cfg.set_cpu_pd_en(true);
304        cfg.set_int_8m_pd_en(true);
305
306        cfg.set_dig_peri_pd_en(true);
307        cfg.set_dig_dbias_slp(0); // because of dig_peri_pd_en
308
309        cfg.set_deep_slp(true);
310        cfg.set_wdt_flashboot_mod_en(false);
311        cfg.set_vddsdio_pd_en(true);
312        cfg.set_xtal_fpu(false);
313        cfg.set_deep_slp_reject(true);
314        cfg.set_light_slp_reject(true);
315        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
316
317        // because of dig_peri_pd_en
318        cfg.set_rtc_regulator_fpu(false);
319        cfg.set_dbg_atten_slp(RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT);
320
321        // because of xtal_fpu
322        cfg.set_bias_sleep_monitor(true);
323        cfg.set_bias_sleep_slp(true);
324        cfg.set_pd_cur_slp(true);
325
326        cfg
327    }
328
329    pub(crate) fn is_deep_sleep(&self) -> bool {
330        self.deep_slp()
331    }
332
333    pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
334        self.set_deep_slp(kind == SleepKind::Deep);
335    }
336
337    pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
338        let cfg = RtcConfig::default();
339
340        // settings derived from esp_clk_init -> rtc_init
341        let rtc_cntl = LPWR::regs();
342        let extmem = EXTMEM::regs();
343        let system = SYSTEM::regs();
344
345        unsafe {
346            rtc_cntl
347                .dig_pwc()
348                .modify(|_, w| w.wifi_force_pd().clear_bit());
349
350            regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
351            regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
352
353            rtc_cntl.ana_conf().modify(|_, w| w.pvtmon_pu().clear_bit());
354
355            rtc_cntl.timer1().modify(|_, w| {
356                w.pll_buf_wait().bits(cfg.pll_wait());
357                w.ck8m_wait().bits(cfg.ck8m_wait())
358            });
359
360            // Moved from rtc sleep to rtc init to save sleep function running time
361            // set shortest possible sleep time limit
362
363            rtc_cntl
364                .timer5()
365                .modify(|_, w| w.min_slp_val().bits(RTC_CNTL_MIN_SLP_VAL_MIN));
366
367            let init_cfg = RtcInitConfig::default();
368
369            rtc_cntl.timer3().modify(|_, w| {
370                // set wifi timer
371                w.wifi_powerup_timer().bits(init_cfg.wifi_powerup_cycles());
372                w.wifi_wait_timer().bits(init_cfg.wifi_wait_cycles());
373                // set bt timer
374                w.bt_powerup_timer().bits(init_cfg.bt_powerup_cycles());
375                w.bt_wait_timer().bits(init_cfg.bt_wait_cycles())
376            });
377
378            rtc_cntl.timer4().modify(|_, w| {
379                w.cpu_top_powerup_timer()
380                    .bits(init_cfg.cpu_top_powerup_cycles());
381                w.cpu_top_wait_timer().bits(init_cfg.cpu_top_wait_cycles());
382                // set digital wrap timer
383                w.dg_wrap_powerup_timer()
384                    .bits(init_cfg.dg_wrap_powerup_cycles());
385                w.dg_wrap_wait_timer().bits(init_cfg.dg_wrap_wait_cycles())
386            });
387
388            rtc_cntl.timer6().modify(|_, w| {
389                w.dg_peri_powerup_timer()
390                    .bits(init_cfg.dg_peri_powerup_cycles());
391                w.dg_peri_wait_timer().bits(init_cfg.dg_peri_wait_cycles())
392            });
393
394            // TODO: something about cali_ocode
395
396            // Reset RTC bias to default value (needed if waking up from deep sleep)
397            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(RTC_CNTL_DBIAS_1V10);
398
399            // LDO dbias initialization
400            // TODO: this modifies g_rtc_dbias_pvt_non_240m and g_dig_dbias_pvt_non_240m.
401            //       We're using a high enough default but we should read from the efuse.
402            // set_rtc_dig_dbias();
403
404            regi2c::I2C_DIG_REG_EXT_RTC_DREG.write_field(RTC_CNTL_DBIAS_1V25);
405            regi2c::I2C_DIG_REG_EXT_DIG_DREG.write_field(RTC_CNTL_DBIAS_1V25);
406
407            if cfg.clkctl_init() {
408                // clear CMMU clock force on
409
410                extmem
411                    .cache_mmu_power_ctrl()
412                    .modify(|_, w| w.cache_mmu_mem_force_on().clear_bit());
413                // clear tag clock force on
414
415                extmem
416                    .icache_tag_power_ctrl()
417                    .modify(|_, w| w.icache_tag_mem_force_on().clear_bit());
418                // clear register clock force on
419                SPI0::regs()
420                    .clock_gate()
421                    .modify(|_, w| w.clk_en().clear_bit());
422                SPI1::regs()
423                    .clock_gate()
424                    .modify(|_, w| w.clk_en().clear_bit());
425            }
426
427            if cfg.pwrctl_init() {
428                rtc_cntl
429                    .clk_conf()
430                    .modify(|_, w| w.ck8m_force_pu().clear_bit());
431
432                rtc_cntl
433                    .options0()
434                    .modify(|_, w| w.xtl_force_pu().bit(cfg.xtal_fpu() || cfg.bbpll_fpu()));
435
436                // force pd APLL
437
438                rtc_cntl
439                    .ana_conf()
440                    .modify(|_, w| w.plla_force_pu().clear_bit().plla_force_pd().set_bit());
441
442                rtc_cntl.ana_conf().modify(|_, w| {
443                    w
444                        // open sar_i2c protect function to avoid sar_i2c reset when rtc_ldo is low.
445                        .reset_por_force_pd()
446                        .clear_bit()
447                });
448
449                // cancel bbpll force pu if setting no force power up
450
451                rtc_cntl.options0().modify(|_, w| {
452                    w.bbpll_force_pu().bit(cfg.bbpll_fpu());
453                    w.bbpll_i2c_force_pu().bit(cfg.bbpll_fpu());
454                    w.bb_i2c_force_pu().bit(cfg.bbpll_fpu())
455                });
456
457                rtc_cntl.rtc_cntl().modify(|_, w| {
458                    w.regulator_force_pu().clear_bit();
459                    w.dboost_force_pu().clear_bit();
460                    w.dboost_force_pd().bit(cfg.rtc_dboost_fpd())
461                });
462
463                // If this mask is enabled, all soc memories cannot enter power down mode
464                // We should control soc memory power down mode from RTC, so we will not touch
465                // this register any more
466
467                system
468                    .mem_pd_mask()
469                    .modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
470
471                // If this pd_cfg is set to 1, all memory won't enter low power mode during
472                // light sleep If this pd_cfg is set to 0, all memory will enter low
473                // power mode during light sleep
474                rtc_sleep_pu(false);
475
476                rtc_cntl.dig_pwc().modify(|_, w| {
477                    w.dg_wrap_force_pu().clear_bit();
478                    w.wifi_force_pu().clear_bit();
479                    w.bt_force_pu().clear_bit();
480                    w.cpu_top_force_pu().clear_bit();
481                    w.dg_peri_force_pu().clear_bit()
482                });
483
484                rtc_cntl.dig_iso().modify(|_, w| {
485                    w.dg_wrap_force_noiso().clear_bit();
486                    w.wifi_force_noiso().clear_bit();
487                    w.bt_force_noiso().clear_bit();
488                    w.cpu_top_force_noiso().clear_bit();
489                    w.dg_peri_force_noiso().clear_bit()
490                });
491
492                // if SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0 , the cpu clk will be closed when cpu
493                // enter WAITI mode
494
495                system
496                    .cpu_per_conf()
497                    .modify(|_, w| w.cpu_wait_mode_force_on().bit(!cfg.cpu_waiti_clk_gate()));
498
499                // cancel digital PADS force no iso
500
501                rtc_cntl.dig_iso().modify(|_, w| {
502                    w.dg_pad_force_unhold().clear_bit();
503                    w.dg_pad_force_noiso().clear_bit()
504                });
505            }
506
507            // force power down modem(wifi and ble) power domain
508
509            rtc_cntl
510                .dig_iso()
511                .modify(|_, w| w.wifi_force_iso().set_bit().bt_force_iso().set_bit());
512
513            rtc_cntl
514                .dig_pwc()
515                .modify(|_, w| w.wifi_force_pd().set_bit().bt_force_pd().set_bit());
516
517            rtc_cntl.int_ena().write(|w| w.bits(0));
518            rtc_cntl.int_clr().write(|w| w.bits(u32::MAX));
519
520            regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(1);
521        }
522    }
523
524    pub(crate) fn apply(&self) {
525        // like esp-idf rtc_sleep_init()
526        let rtc_cntl = LPWR::regs();
527
528        if self.lslp_mem_inf_fpu() {
529            rtc_sleep_pu(true);
530        }
531
532        if self.wifi_pd_en() {
533            rtc_cntl.dig_iso().modify(|_, w| {
534                w.wifi_force_noiso().clear_bit();
535                w.wifi_force_iso().clear_bit()
536            });
537
538            rtc_cntl.dig_pwc().modify(|_, w| {
539                w.wifi_force_pu().clear_bit();
540                w.wifi_pd_en().set_bit()
541            });
542        } else {
543            rtc_cntl.dig_pwc().modify(|_, w| w.wifi_pd_en().clear_bit());
544        }
545        if self.bt_pd_en() {
546            rtc_cntl.dig_iso().modify(|_, w| {
547                w.bt_force_noiso().clear_bit();
548                w.bt_force_iso().clear_bit()
549            });
550
551            rtc_cntl.dig_pwc().modify(|_, w| {
552                w.bt_force_pu().clear_bit();
553                w.bt_pd_en().set_bit()
554            });
555        } else {
556            rtc_cntl.dig_pwc().modify(|_, w| w.bt_pd_en().clear_bit());
557        }
558
559        rtc_cntl.dig_pwc().modify(|_, w| {
560            w.cpu_top_pd_en().bit(self.cpu_pd_en());
561            w.dg_peri_pd_en().bit(self.dig_peri_pd_en())
562        });
563
564        unsafe {
565            rtc_cntl.bias_conf().modify(|_, w| {
566                w.dbg_atten_monitor()
567                    .bits(RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT);
568
569                // We have config values for this in self, so I don't know why we're setting
570                // hardcoded defaults for these next two. It's what IDF does...
571
572                w.bias_sleep_monitor().bit(RTC_CNTL_BIASSLP_MONITOR_DEFAULT);
573                w.pd_cur_monitor().bit(RTC_CNTL_PD_CUR_MONITOR_DEFAULT)
574            });
575
576            // Like `rtc_sleep_get_default_config`: a crystal that stays on through a light sleep
577            // needs the bias current and the voltage of the active mode.
578            let xtal_on = self.xtal_fpu() && !self.deep_slp();
579            let bias_sleep_slp = self.bias_sleep_slp() && !xtal_on;
580            let pd_cur_slp = self.pd_cur_slp() && !xtal_on;
581            let dbg_atten_slp = if xtal_on {
582                RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP
583            } else {
584                self.dbg_atten_slp()
585            };
586
587            assert!(!pd_cur_slp || bias_sleep_slp);
588
589            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(self.rtc_dbias_slp());
590            regi2c::I2C_DIG_REG_EXT_DIG_DREG_SLEEP.write_field(self.dig_dbias_slp());
591
592            rtc_cntl.bias_conf().modify(|_, w| {
593                w.dbg_atten_deep_slp().bits(dbg_atten_slp);
594                w.bias_sleep_deep_slp().bit(bias_sleep_slp);
595                w.pd_cur_deep_slp().bit(pd_cur_slp)
596            });
597
598            if self.deep_slp() {
599                regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(0);
600
601                rtc_cntl
602                    .dig_pwc()
603                    .modify(|_, w| w.dg_wrap_pd_en().set_bit());
604
605                rtc_cntl.ana_conf().modify(|_, w| {
606                    w.ckgen_i2c_pu().clear_bit();
607                    w.pll_i2c_pu().clear_bit();
608                    w.rfrx_pbus_pu().clear_bit();
609                    w.txrf_i2c_pu().clear_bit()
610                });
611
612                rtc_cntl
613                    .options0()
614                    .modify(|_, w| w.bb_i2c_force_pu().clear_bit());
615            } else {
616                rtc_cntl.bias_conf().modify(|_, w| {
617                    w.dg_vdd_drv_b_slp_en().set_bit();
618                    w.dg_vdd_drv_b_slp().bits(RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT)
619                });
620
621                rtc_cntl
622                    .dig_pwc()
623                    .modify(|_, w| w.dg_wrap_pd_en().clear_bit());
624            }
625
626            // mem force pu
627
628            rtc_cntl
629                .dig_pwc()
630                .modify(|_, w| w.lslp_mem_force_pu().set_bit());
631
632            rtc_cntl
633                .rtc_cntl()
634                .modify(|_, w| w.regulator_force_pu().bit(self.rtc_regulator_fpu()));
635
636            rtc_cntl.clk_conf().modify(|_, w| {
637                w.ck8m_force_pu().bit(!self.int_8m_pd_en());
638                w.ck8m_force_nogating().bit(!self.int_8m_pd_en())
639            });
640
641            // enable VDDSDIO control by state machine
642
643            rtc_cntl.sdio_conf().modify(|_, w| {
644                w.sdio_force().clear_bit();
645                w.sdio_reg_pd_en().bit(self.vddsdio_pd_en())
646            });
647
648            rtc_cntl.slp_reject_conf().modify(|_, w| {
649                w.deep_slp_reject_en().bit(self.deep_slp_reject());
650                w.light_slp_reject_en().bit(self.light_slp_reject())
651            });
652
653            rtc_cntl
654                .options0()
655                .modify(|_, w| w.xtl_force_pu().bit(self.xtal_fpu()));
656
657            rtc_cntl
658                .clk_conf()
659                .modify(|_, w| w.xtal_global_force_nogating().bit(self.xtal_fpu()));
660        }
661    }
662
663    /// Configures the wakeup and reject sources of the sleep.
664    ///
665    /// [`Self::enter_sleep`] requests the sleep after this call.
666    pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) {
667        // set bits for what can wake us up
668        LPWR::regs()
669            .wakeup_state()
670            .modify(|_, w| unsafe { w.wakeup_ena().bits(wakeup_mask) });
671
672        // Set the bits of the sources that reject the sleep. The reject enables that `apply` wrote
673        // arm those sources.
674        LPWR::regs()
675            .slp_reject_conf()
676            .modify(|_, w| unsafe { w.sleep_reject_ena().bits(reject_mask) });
677    }
678
679    /// Requests the sleep.
680    ///
681    /// The caller waits for the result of the request.
682    #[inline(always)]
683    pub(crate) fn enter_sleep(&self) -> bool {
684        LPWR::regs().state0().modify(|_, w| w.sleep_en().set_bit());
685        super::wait_for_sleep_result()
686    }
687
688    pub(crate) fn finish_sleep(&self) {
689        // In deep sleep mode, we never get here
690        LPWR::regs().int_clr().write(|w| {
691            w.slp_reject().clear_bit_by_one();
692            w.slp_wakeup().clear_bit_by_one()
693        });
694
695        // restore config if it is a light sleep
696        if self.lslp_mem_inf_fpu() {
697            rtc_sleep_pu(true);
698        }
699    }
700}