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 8MHz clock to stabilize.
64pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
65/// Default number of cycles required to enable the internal 8MHz 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/// Wait 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    /// Perform clock control related initialization.
102    pub clkctl_init, set_clkctl_init: 24;
103    /// Perform power control related initialization.
104    pub pwrctl_init, set_pwrctl_init: 25;
105    /// Force power down `RTC_DBOOST`.
106    pub rtc_dboost_fpd, set_rtc_dboost_fpd: 26;
107    /// Keep the XTAL oscillator powered up in sleep.
108    pub xtal_fpu, set_xtal_fpu: 27;
109    /// Keep the BBPLL oscillator powered up in sleep.
110    pub bbpll_fpu, set_bbpll_fpu: 28;
111    /// Enable clock gating when the CPU is in wait-for-interrupt state.
112    pub cpu_waiti_clk_gate, set_cpu_waiti_clk_gate: 29;
113    /// Calibrate 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    pub cpu_pd_en, set_cpu_pd_en: 7;
196    /// Power down Internal 8M oscillator
197    pub int_8m_pd_en, set_int_8m_pd_en: 8;
198    /// power down digital peripherals
199    pub dig_peri_pd_en, set_dig_peri_pd_en: 9;
200    /// power down digital domain
201    pub deep_slp, set_deep_slp: 10;
202    /// enable WDT flashboot mode
203    pub wdt_flashboot_mod_en, set_wdt_flashboot_mod_en: 11;
204    /// set bias for digital domain, in sleep mode
205    pub u8, dig_dbias_slp, set_dig_dbias_slp: 16, 12;
206    /// set bias for RTC domain, in sleep mode
207    pub u8, rtc_dbias_slp, set_rtc_dbias_slp: 21, 17;
208    /// voltage parameter, in sleep mode
209    pub u8, dbg_atten_slp, set_dbg_atten_slp: 25, 22;
210    /// circuit control parameter, in monitor mode
211    pub bias_sleep_monitor, set_bias_sleep_monitor: 26;
212    /// circuit control parameter, in sleep mode
213    pub bias_sleep_slp, set_bias_sleep_slp: 27;
214    /// circuit control parameter, in monitor mode
215    pub pd_cur_slp, set_pd_cur_slp: 28;
216    /// power down VDDSDIO regulator
217    pub vddsdio_pd_en, set_vddsdio_pd_en: 29;
218    /// keep main XTAL powered up in sleep
219    pub xtal_fpu, set_xtal_fpu: 30;
220    /// keep rtc regulator powered up in sleep
221    pub rtc_regulator_fpu, set_rtc_regulator_fpu: 31;
222    /// enable deep sleep reject
223    pub deep_slp_reject, set_deep_slp_reject: 32;
224    /// enable light sleep reject
225    pub light_slp_reject, set_light_slp_reject: 33;
226}
227
228impl Default for RtcSleepConfig {
229    fn default() -> Self {
230        let mut cfg = Self(Default::default());
231        cfg.set_deep_slp_reject(true);
232        cfg.set_light_slp_reject(true);
233        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
234        cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_1V10);
235
236        // This is the light-sleep config. The main XTAL is powered down in sleep
237        // (`xtal_fpu` stays false), so the analog regulator/bias must use the
238        // same XTAL-down settings that `deep()` applies "because of xtal_fpu".
239        cfg.set_rtc_regulator_fpu(true);
240        cfg.set_bias_sleep_monitor(true);
241        cfg.set_bias_sleep_slp(true);
242        cfg.set_pd_cur_slp(true);
243        cfg
244    }
245}
246
247const SYSCON_SRAM_POWER_UP: u8 = 0x0000000F;
248const SYSCON_ROM_POWER_UP: u8 = 0x00000003;
249
250fn rtc_sleep_pu(val: bool) {
251    LPWR::regs()
252        .dig_pwc()
253        .modify(|_, w| w.lslp_mem_force_pu().bit(val).fastmem_force_lpu().bit(val));
254
255    APB_CTRL::regs().front_end_mem_pd().modify(|_r, w| {
256        w.dc_mem_force_pu().bit(val);
257        w.pbus_mem_force_pu().bit(val);
258        w.agc_mem_force_pu().bit(val)
259    });
260
261    BB::regs()
262        .bbpd_ctrl()
263        .modify(|_r, w| w.fft_force_pu().bit(val).dc_est_force_pu().bit(val));
264
265    NRX::regs().nrxpd_ctrl().modify(|_, w| {
266        w.rx_rot_force_pu().bit(val);
267        w.vit_force_pu().bit(val);
268        w.demap_force_pu().bit(val)
269    });
270
271    FE::regs()
272        .gen_ctrl()
273        .modify(|_, w| w.iq_est_force_pu().bit(val));
274
275    FE2::regs()
276        .tx_interp_ctrl()
277        .modify(|_, w| w.tx_inf_force_pu().bit(val));
278
279    APB_CTRL::regs().mem_power_up().modify(|_r, w| unsafe {
280        w.sram_power_up()
281            .bits(if val { SYSCON_SRAM_POWER_UP } else { 0 })
282            .rom_power_up()
283            .bits(if val { SYSCON_ROM_POWER_UP } else { 0 })
284    });
285}
286
287impl RtcSleepConfig {
288    /// Configures the RTC for deep sleep mode.
289    pub fn deep() -> Self {
290        // Set up for ultra-low power sleep. Wakeup sources may modify these settings.
291        let mut cfg = Self::default();
292
293        cfg.set_lslp_mem_inf_fpu(false);
294        cfg.set_rtc_mem_inf_follow_cpu(true); // ?
295        cfg.set_rtc_fastmem_pd_en(true);
296        cfg.set_rtc_slowmem_pd_en(true);
297        cfg.set_rtc_peri_pd_en(true);
298        cfg.set_wifi_pd_en(true);
299        cfg.set_bt_pd_en(true);
300        cfg.set_cpu_pd_en(true);
301        cfg.set_int_8m_pd_en(true);
302
303        cfg.set_dig_peri_pd_en(true);
304        cfg.set_dig_dbias_slp(0); // because of dig_peri_pd_en
305
306        cfg.set_deep_slp(true);
307        cfg.set_wdt_flashboot_mod_en(false);
308        cfg.set_vddsdio_pd_en(true);
309        cfg.set_xtal_fpu(false);
310        cfg.set_deep_slp_reject(true);
311        cfg.set_light_slp_reject(true);
312        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
313
314        // because of dig_peri_pd_en
315        cfg.set_rtc_regulator_fpu(false);
316        cfg.set_dbg_atten_slp(RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT);
317
318        // because of xtal_fpu
319        cfg.set_bias_sleep_monitor(true);
320        cfg.set_bias_sleep_slp(true);
321        cfg.set_pd_cur_slp(true);
322
323        cfg
324    }
325
326    pub(crate) fn is_deep_sleep(&self) -> bool {
327        self.deep_slp()
328    }
329
330    pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
331        self.set_deep_slp(kind == SleepKind::Deep);
332    }
333
334    pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
335        let cfg = RtcConfig::default();
336
337        // settings derived from esp_clk_init -> rtc_init
338        let rtc_cntl = LPWR::regs();
339        let extmem = EXTMEM::regs();
340        let system = SYSTEM::regs();
341
342        unsafe {
343            rtc_cntl
344                .dig_pwc()
345                .modify(|_, w| w.wifi_force_pd().clear_bit());
346
347            regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
348            regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
349
350            rtc_cntl.ana_conf().modify(|_, w| w.pvtmon_pu().clear_bit());
351
352            rtc_cntl.timer1().modify(|_, w| {
353                w.pll_buf_wait().bits(cfg.pll_wait());
354                w.ck8m_wait().bits(cfg.ck8m_wait())
355            });
356
357            // Moved from rtc sleep to rtc init to save sleep function running time
358            // set shortest possible sleep time limit
359
360            rtc_cntl
361                .timer5()
362                .modify(|_, w| w.min_slp_val().bits(RTC_CNTL_MIN_SLP_VAL_MIN));
363
364            let init_cfg = RtcInitConfig::default();
365
366            rtc_cntl.timer3().modify(|_, w| {
367                w
368                    // set wifi timer
369                    .wifi_powerup_timer()
370                    .bits(init_cfg.wifi_powerup_cycles())
371                    .wifi_wait_timer()
372                    .bits(init_cfg.wifi_wait_cycles())
373                    // set bt timer
374                    .bt_powerup_timer()
375                    .bits(init_cfg.bt_powerup_cycles())
376                    .bt_wait_timer()
377                    .bits(init_cfg.bt_wait_cycles())
378            });
379
380            rtc_cntl.timer4().modify(|_, w| {
381                w.cpu_top_powerup_timer()
382                    .bits(init_cfg.cpu_top_powerup_cycles())
383                    .cpu_top_wait_timer()
384                    .bits(init_cfg.cpu_top_wait_cycles())
385                    // set digital wrap timer
386                    .dg_wrap_powerup_timer()
387                    .bits(init_cfg.dg_wrap_powerup_cycles())
388                    .dg_wrap_wait_timer()
389                    .bits(init_cfg.dg_wrap_wait_cycles())
390            });
391
392            rtc_cntl.timer6().modify(|_, w| {
393                w.dg_peri_powerup_timer()
394                    .bits(init_cfg.dg_peri_powerup_cycles())
395                    .dg_peri_wait_timer()
396                    .bits(init_cfg.dg_peri_wait_cycles())
397            });
398
399            // TODO: something about cali_ocode
400
401            // Reset RTC bias to default value (needed if waking up from deep sleep)
402            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(RTC_CNTL_DBIAS_1V10);
403
404            // LDO dbias initialization
405            // TODO: this modifies g_rtc_dbias_pvt_non_240m and g_dig_dbias_pvt_non_240m.
406            //       We're using a high enough default but we should read from the efuse.
407            // set_rtc_dig_dbias();
408
409            regi2c::I2C_DIG_REG_EXT_RTC_DREG.write_field(RTC_CNTL_DBIAS_1V25);
410            regi2c::I2C_DIG_REG_EXT_DIG_DREG.write_field(RTC_CNTL_DBIAS_1V25);
411
412            if cfg.clkctl_init() {
413                // clear CMMU clock force on
414
415                extmem
416                    .cache_mmu_power_ctrl()
417                    .modify(|_, w| w.cache_mmu_mem_force_on().clear_bit());
418                // clear tag clock force on
419
420                extmem
421                    .icache_tag_power_ctrl()
422                    .modify(|_, w| w.icache_tag_mem_force_on().clear_bit());
423                // clear register clock force on
424                SPI0::regs()
425                    .clock_gate()
426                    .modify(|_, w| w.clk_en().clear_bit());
427                SPI1::regs()
428                    .clock_gate()
429                    .modify(|_, w| w.clk_en().clear_bit());
430            }
431
432            if cfg.pwrctl_init() {
433                rtc_cntl
434                    .clk_conf()
435                    .modify(|_, w| w.ck8m_force_pu().clear_bit());
436
437                rtc_cntl
438                    .options0()
439                    .modify(|_, w| w.xtl_force_pu().bit(cfg.xtal_fpu() || cfg.bbpll_fpu()));
440
441                // force pd APLL
442
443                rtc_cntl
444                    .ana_conf()
445                    .modify(|_, w| w.plla_force_pu().clear_bit().plla_force_pd().set_bit());
446
447                rtc_cntl.ana_conf().modify(|_, w| {
448                    w
449                        // open sar_i2c protect function to avoid sar_i2c reset when rtc_ldo is low.
450                        .reset_por_force_pd()
451                        .clear_bit()
452                });
453
454                // cancel bbpll force pu if setting no force power up
455
456                rtc_cntl.options0().modify(|_, w| {
457                    w.bbpll_force_pu()
458                        .bit(cfg.bbpll_fpu())
459                        .bbpll_i2c_force_pu()
460                        .bit(cfg.bbpll_fpu())
461                        .bb_i2c_force_pu()
462                        .bit(cfg.bbpll_fpu())
463                });
464
465                rtc_cntl.rtc_cntl().modify(|_, w| {
466                    w.regulator_force_pu()
467                        .clear_bit()
468                        .dboost_force_pu()
469                        .clear_bit()
470                        .dboost_force_pd()
471                        .bit(cfg.rtc_dboost_fpd())
472                });
473
474                // If this mask is enabled, all soc memories cannot enter power down mode
475                // We should control soc memory power down mode from RTC, so we will not touch
476                // this register any more
477
478                system
479                    .mem_pd_mask()
480                    .modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
481
482                // If this pd_cfg is set to 1, all memory won't enter low power mode during
483                // light sleep If this pd_cfg is set to 0, all memory will enter low
484                // power mode during light sleep
485                rtc_sleep_pu(false);
486
487                rtc_cntl.dig_pwc().modify(|_, w| {
488                    w.dg_wrap_force_pu()
489                        .clear_bit()
490                        .wifi_force_pu()
491                        .clear_bit()
492                        .bt_force_pu()
493                        .clear_bit()
494                        .cpu_top_force_pu()
495                        .clear_bit()
496                        .dg_peri_force_pu()
497                        .clear_bit()
498                });
499
500                rtc_cntl.dig_iso().modify(|_, w| {
501                    w.dg_wrap_force_noiso()
502                        .clear_bit()
503                        .wifi_force_noiso()
504                        .clear_bit()
505                        .bt_force_noiso()
506                        .clear_bit()
507                        .cpu_top_force_noiso()
508                        .clear_bit()
509                        .dg_peri_force_noiso()
510                        .clear_bit()
511                });
512
513                // if SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0 , the cpu clk will be closed when cpu
514                // enter WAITI mode
515
516                system
517                    .cpu_per_conf()
518                    .modify(|_, w| w.cpu_wait_mode_force_on().bit(!cfg.cpu_waiti_clk_gate()));
519
520                // cancel digital PADS force no iso
521
522                rtc_cntl.dig_iso().modify(|_, w| {
523                    w.dg_pad_force_unhold()
524                        .clear_bit()
525                        .dg_pad_force_noiso()
526                        .clear_bit()
527                });
528            }
529
530            // force power down modem(wifi and ble) power domain
531
532            rtc_cntl
533                .dig_iso()
534                .modify(|_, w| w.wifi_force_iso().set_bit().bt_force_iso().set_bit());
535
536            rtc_cntl
537                .dig_pwc()
538                .modify(|_, w| w.wifi_force_pd().set_bit().bt_force_pd().set_bit());
539
540            rtc_cntl.int_ena().write(|w| w.bits(0));
541            rtc_cntl.int_clr().write(|w| w.bits(u32::MAX));
542
543            regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(1);
544        }
545    }
546
547    pub(crate) fn apply(&self) {
548        // like esp-idf rtc_sleep_init()
549        let rtc_cntl = LPWR::regs();
550
551        if self.lslp_mem_inf_fpu() {
552            rtc_sleep_pu(true);
553        }
554
555        if self.wifi_pd_en() {
556            rtc_cntl.dig_iso().modify(|_, w| {
557                w.wifi_force_noiso().clear_bit();
558                w.wifi_force_iso().clear_bit()
559            });
560
561            rtc_cntl.dig_pwc().modify(|_, w| {
562                w.wifi_force_pu().clear_bit();
563                w.wifi_pd_en().set_bit()
564            });
565        } else {
566            rtc_cntl.dig_pwc().modify(|_, w| w.wifi_pd_en().clear_bit());
567        }
568        if self.bt_pd_en() {
569            rtc_cntl.dig_iso().modify(|_, w| {
570                w.bt_force_noiso().clear_bit();
571                w.bt_force_iso().clear_bit()
572            });
573
574            rtc_cntl.dig_pwc().modify(|_, w| {
575                w.bt_force_pu().clear_bit();
576                w.bt_pd_en().set_bit()
577            });
578        } else {
579            rtc_cntl.dig_pwc().modify(|_, w| w.bt_pd_en().clear_bit());
580        }
581
582        rtc_cntl.dig_pwc().modify(|_, w| {
583            w.cpu_top_pd_en().bit(self.cpu_pd_en());
584            w.dg_peri_pd_en().bit(self.dig_peri_pd_en())
585        });
586
587        unsafe {
588            rtc_cntl.bias_conf().modify(|_, w| {
589                w.dbg_atten_monitor()
590                    .bits(RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT);
591
592                // We have config values for this in self, so I don't know why we're setting
593                // hardcoded defaults for these next two. It's what IDF does...
594
595                w.bias_sleep_monitor().bit(RTC_CNTL_BIASSLP_MONITOR_DEFAULT);
596                w.pd_cur_monitor().bit(RTC_CNTL_PD_CUR_MONITOR_DEFAULT)
597            });
598
599            assert!(!self.pd_cur_slp() || self.bias_sleep_slp());
600
601            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(self.rtc_dbias_slp());
602            regi2c::I2C_DIG_REG_EXT_DIG_DREG_SLEEP.write_field(self.dig_dbias_slp());
603
604            rtc_cntl.bias_conf().modify(|_, w| {
605                w.dbg_atten_deep_slp().bits(self.dbg_atten_slp());
606                w.bias_sleep_deep_slp().bit(self.bias_sleep_slp());
607                w.pd_cur_deep_slp().bit(self.pd_cur_slp())
608            });
609
610            if self.deep_slp() {
611                regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(0);
612
613                rtc_cntl
614                    .dig_pwc()
615                    .modify(|_, w| w.dg_wrap_pd_en().set_bit());
616
617                rtc_cntl.ana_conf().modify(|_, w| {
618                    w.ckgen_i2c_pu().clear_bit();
619                    w.pll_i2c_pu().clear_bit();
620                    w.rfrx_pbus_pu().clear_bit();
621                    w.txrf_i2c_pu().clear_bit()
622                });
623
624                rtc_cntl
625                    .options0()
626                    .modify(|_, w| w.bb_i2c_force_pu().clear_bit());
627            } else {
628                rtc_cntl.bias_conf().modify(|_, w| {
629                    w.dg_vdd_drv_b_slp_en().set_bit();
630                    w.dg_vdd_drv_b_slp().bits(RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT)
631                });
632
633                rtc_cntl
634                    .dig_pwc()
635                    .modify(|_, w| w.dg_wrap_pd_en().clear_bit());
636            }
637
638            // mem force pu
639
640            rtc_cntl
641                .dig_pwc()
642                .modify(|_, w| w.lslp_mem_force_pu().set_bit());
643
644            rtc_cntl
645                .rtc_cntl()
646                .modify(|_, w| w.regulator_force_pu().bit(self.rtc_regulator_fpu()));
647
648            rtc_cntl.clk_conf().modify(|_, w| {
649                w.ck8m_force_pu().bit(!self.int_8m_pd_en());
650                w.ck8m_force_nogating().bit(!self.int_8m_pd_en())
651            });
652
653            // enable VDDSDIO control by state machine
654
655            rtc_cntl.sdio_conf().modify(|_, w| {
656                w.sdio_force().clear_bit();
657                w.sdio_reg_pd_en().bit(self.vddsdio_pd_en())
658            });
659
660            rtc_cntl.slp_reject_conf().modify(|_, w| {
661                w.deep_slp_reject_en().bit(self.deep_slp_reject());
662                w.light_slp_reject_en().bit(self.light_slp_reject())
663            });
664
665            rtc_cntl
666                .options0()
667                .modify(|_, w| w.xtl_force_pu().bit(self.xtal_fpu()));
668
669            rtc_cntl
670                .clk_conf()
671                .modify(|_, w| w.xtal_global_force_nogating().bit(self.xtal_fpu()));
672        }
673    }
674
675    /// Configures the wakeup options and requests the sleep.
676    ///
677    /// The caller waits for the result of the request.
678    pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) {
679        // set bits for what can wake us up
680        LPWR::regs()
681            .wakeup_state()
682            .modify(|_, w| unsafe { w.wakeup_ena().bits(wakeup_mask) });
683
684        // Set the bits of the sources that reject the sleep. The reject enables that `apply` wrote
685        // arm those sources.
686        LPWR::regs()
687            .slp_reject_conf()
688            .modify(|_, w| unsafe { w.sleep_reject_ena().bits(reject_mask) });
689
690        LPWR::regs().state0().modify(|_, w| w.sleep_en().set_bit());
691    }
692
693    pub(crate) fn finish_sleep(&self) {
694        // In deep sleep mode, we never get here
695        LPWR::regs().int_clr().write(|w| {
696            w.slp_reject().clear_bit_by_one();
697            w.slp_wakeup().clear_bit_by_one()
698        });
699
700        // restore config if it is a light sleep
701        if self.lslp_mem_inf_fpu() {
702            rtc_sleep_pu(true);
703        }
704    }
705}