Skip to main content

esp_hal/rtc_cntl/sleep/
esp32c2.rs

1use super::SleepKind;
2use crate::{
3    peripherals::{APB_CTRL, BB, EXTMEM, LPWR, 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.set_bbpll_fpu(true);
128        cfg
129    }
130}
131
132bitfield::bitfield! {
133    #[derive(Clone, Copy)]
134    /// Configuration for RTC initialization.
135    pub struct RtcInitConfig(u128);
136    impl Debug;
137    /// Number of cycles required to power up WiFi
138    pub u8, wifi_powerup_cycles, set_wifi_powerup_cycles: 6, 0;
139    /// Number of wait cycles for WiFi to stabilize
140    pub u16, wifi_wait_cycles, set_wifi_wait_cycles: 15, 7;
141    /// Number of cycles required to power up Bluetooth
142    pub u8, bt_powerup_cycles, set_bt_powerup_cycles: 22, 16;
143    /// Number of wait cycles for Bluetooth to stabilize
144    pub u16, bt_wait_cycles, set_bt_wait_cycles: 31, 23;
145    /// Number of cycles required to power up the top CPU
146    pub u8, cpu_top_powerup_cycles, set_cpu_top_powerup_cycles: 38, 32;
147    /// Number of wait cycles for the top CPU to stabilize
148    pub u16, cpu_top_wait_cycles, set_cpu_top_wait_cycles: 47, 39;
149    /// Number of cycles required to power up the digital wrapper
150    pub u8, dg_wrap_powerup_cycles, set_dg_wrap_powerup_cycles: 54, 48;
151    /// Number of wait cycles for the digital wrapper to stabilize
152    pub u16, dg_wrap_wait_cycles, set_dg_wrap_wait_cycles: 63, 55;
153    /// Number of cycles required to power up the digital peripherals
154    pub u8, dg_peri_powerup_cycles, set_dg_peri_powerup_cycles: 70, 64;
155    /// Number of wait cycles for the digital peripherals to stabilize
156    pub u16, dg_peri_wait_cycles, set_dg_peri_wait_cycles: 79, 71;
157}
158
159impl Default for RtcInitConfig {
160    fn default() -> Self {
161        let mut cfg = Self(Default::default());
162        cfg.set_wifi_powerup_cycles(OTHER_BLOCKS_POWERUP);
163        cfg.set_bt_powerup_cycles(OTHER_BLOCKS_POWERUP);
164        cfg.set_cpu_top_powerup_cycles(OTHER_BLOCKS_POWERUP);
165        cfg.set_dg_wrap_powerup_cycles(OTHER_BLOCKS_POWERUP);
166        cfg.set_dg_peri_powerup_cycles(OTHER_BLOCKS_POWERUP);
167        cfg.set_wifi_wait_cycles(OTHER_BLOCKS_WAIT);
168        cfg.set_bt_wait_cycles(OTHER_BLOCKS_WAIT);
169        cfg.set_cpu_top_wait_cycles(OTHER_BLOCKS_WAIT);
170        cfg.set_dg_wrap_wait_cycles(OTHER_BLOCKS_WAIT);
171        cfg.set_dg_peri_wait_cycles(OTHER_BLOCKS_WAIT);
172        cfg
173    }
174}
175
176bitfield::bitfield! {
177    #[derive(Clone, Copy)]
178    /// Configuration for RTC sleep mode.
179    pub struct RtcSleepConfig(u64);
180    impl Debug;
181    /// force normal voltage in sleep mode (digital domain memory)
182    pub lslp_mem_inf_fpu, set_lslp_mem_inf_fpu: 0;
183    /// keep low voltage in sleep mode (even if ULP/touch is used)
184    pub rtc_mem_inf_follow_cpu, set_rtc_mem_inf_follow_cpu: 1;
185    /// power down RTC fast memory
186    pub rtc_fastmem_pd_en, set_rtc_fastmem_pd_en: 2;
187    /// power down RTC slow memory
188    pub rtc_slowmem_pd_en, set_rtc_slowmem_pd_en: 3;
189    /// power down RTC peripherals
190    pub rtc_peri_pd_en, set_rtc_peri_pd_en: 4;
191    /// power down WiFi
192    pub wifi_pd_en, set_wifi_pd_en: 5;
193    /// power down BT
194    pub bt_pd_en, set_bt_pd_en: 6;
195    /// power down CPU, but not restart when lightsleep.
196    pub cpu_pd_en, set_cpu_pd_en: 7;
197    /// Power down Internal 8M oscillator
198    pub int_8m_pd_en, set_int_8m_pd_en: 8;
199    /// power down digital peripherals
200    pub dig_peri_pd_en, set_dig_peri_pd_en: 9;
201    /// power down digital domain
202    pub deep_slp, set_deep_slp: 10;
203    /// enable WDT flashboot mode
204    pub wdt_flashboot_mod_en, set_wdt_flashboot_mod_en: 11;
205    /// set bias for digital domain, in sleep mode
206    pub u8, dig_dbias_slp, set_dig_dbias_slp: 16, 12;
207    /// set bias for RTC domain, in sleep mode
208    pub u8, rtc_dbias_slp, set_rtc_dbias_slp: 21, 17;
209    /// voltage parameter, in sleep mode
210    pub u8, dbg_atten_slp, set_dbg_atten_slp: 25, 22;
211    /// circuit control parameter, in monitor mode
212    pub bias_sleep_monitor, set_bias_sleep_monitor: 26;
213    /// circuit control parameter, in sleep mode
214    pub bias_sleep_slp, set_bias_sleep_slp: 27;
215    /// circuit control parameter, in monitor mode
216    pub pd_cur_slp, set_pd_cur_slp: 28;
217    /// power down VDDSDIO regulator
218    pub vddsdio_pd_en, set_vddsdio_pd_en: 29;
219    /// keep main XTAL powered up in sleep
220    pub xtal_fpu, set_xtal_fpu: 30;
221    /// keep rtc regulator powered up in sleep
222    pub rtc_regulator_fpu, set_rtc_regulator_fpu: 31;
223    /// enable deep sleep reject
224    pub deep_slp_reject, set_deep_slp_reject: 32;
225    /// enable light sleep reject
226    pub light_slp_reject, set_light_slp_reject: 33;
227}
228
229impl Default for RtcSleepConfig {
230    fn default() -> Self {
231        let mut cfg = Self(Default::default());
232        cfg.set_deep_slp_reject(true);
233        cfg.set_light_slp_reject(true);
234        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
235        cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_1V10);
236
237        // This is the light-sleep config. The main XTAL is powered down in sleep
238        // (`xtal_fpu` stays false), so the analog regulator/bias must use the
239        // same XTAL-down settings that `deep()` applies "because of xtal_fpu".
240        cfg.set_rtc_regulator_fpu(true);
241        cfg.set_bias_sleep_monitor(true);
242        cfg.set_bias_sleep_slp(true);
243        cfg.set_pd_cur_slp(true);
244        cfg
245    }
246}
247
248const DR_REG_NRX_BASE: u32 = 0x6001CC00;
249const DR_REG_FE_BASE: u32 = 0x60006000;
250const DR_REG_FE2_BASE: u32 = 0x60005000;
251
252const NRXPD_CTRL: u32 = DR_REG_NRX_BASE + 0x00d4;
253const FE_GEN_CTRL: u32 = DR_REG_FE_BASE + 0x0090;
254const FE2_TX_INTERP_CTRL: u32 = DR_REG_FE2_BASE + 0x00f0;
255
256const SYSCON_SRAM_POWER_UP: u8 = 0x0000000F;
257const SYSCON_ROM_POWER_UP: u8 = 0x00000003;
258
259const NRX_RX_ROT_FORCE_PU: u32 = 1 << 5;
260const NRX_VIT_FORCE_PU: u32 = 1 << 3;
261const NRX_DEMAP_FORCE_PU: u32 = 1 << 1;
262
263const FE_IQ_EST_FORCE_PU: u32 = 1 << 5;
264const FE2_TX_INF_FORCE_PU: u32 = 1 << 10;
265
266fn modify_register(reg: u32, mask: u32, value: u32) {
267    let reg = reg as *mut u32;
268
269    unsafe { reg.write_volatile((reg.read_volatile() & !mask) | value) };
270}
271
272fn register_modify_bits(reg: u32, bits: u32, set: bool) {
273    if set {
274        modify_register(reg, bits, bits);
275    } else {
276        modify_register(reg, bits, 0);
277    }
278}
279
280fn rtc_sleep_pu(val: bool) {
281    LPWR::regs()
282        .dig_pwc()
283        .modify(|_, w| w.lslp_mem_force_pu().bit(val));
284
285    APB_CTRL::regs().front_end_mem_pd().modify(|_r, w| {
286        w.dc_mem_force_pu().bit(val);
287        w.pbus_mem_force_pu().bit(val);
288        w.agc_mem_force_pu().bit(val)
289    });
290
291    BB::regs()
292        .bbpd_ctrl()
293        .modify(|_r, w| w.fft_force_pu().bit(val).dc_est_force_pu().bit(val));
294
295    register_modify_bits(
296        NRXPD_CTRL,
297        NRX_RX_ROT_FORCE_PU | NRX_VIT_FORCE_PU | NRX_DEMAP_FORCE_PU,
298        val,
299    );
300
301    register_modify_bits(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, val);
302
303    register_modify_bits(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, val);
304
305    APB_CTRL::regs().mem_power_up().modify(|_r, w| unsafe {
306        w.sram_power_up()
307            .bits(if val { SYSCON_SRAM_POWER_UP } else { 0 });
308        w.rom_power_up()
309            .bits(if val { SYSCON_ROM_POWER_UP } else { 0 })
310    });
311}
312
313impl RtcSleepConfig {
314    /// Configures the RTC for deep sleep mode.
315    pub fn deep() -> Self {
316        // Set up for ultra-low power sleep. Wakeup sources may modify these settings.
317        let mut cfg = Self::default();
318
319        cfg.set_lslp_mem_inf_fpu(false);
320        cfg.set_rtc_mem_inf_follow_cpu(true); // ?
321        cfg.set_rtc_fastmem_pd_en(true);
322        cfg.set_rtc_slowmem_pd_en(true);
323        cfg.set_rtc_peri_pd_en(true);
324        cfg.set_wifi_pd_en(true);
325        cfg.set_bt_pd_en(true);
326        cfg.set_cpu_pd_en(true);
327        cfg.set_int_8m_pd_en(true);
328
329        cfg.set_dig_peri_pd_en(true);
330        cfg.set_dig_dbias_slp(0); // because of dig_peri_pd_en
331
332        cfg.set_deep_slp(true);
333        cfg.set_wdt_flashboot_mod_en(false);
334        cfg.set_vddsdio_pd_en(true);
335        cfg.set_xtal_fpu(false);
336        cfg.set_deep_slp_reject(true);
337        cfg.set_light_slp_reject(true);
338        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
339
340        // because of dig_peri_pd_en
341        cfg.set_rtc_regulator_fpu(false);
342        cfg.set_dbg_atten_slp(RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT);
343
344        // because of xtal_fpu
345        cfg.set_bias_sleep_monitor(true);
346        cfg.set_bias_sleep_slp(true);
347        cfg.set_pd_cur_slp(true);
348
349        cfg
350    }
351
352    pub(crate) fn is_deep_sleep(&self) -> bool {
353        self.deep_slp()
354    }
355
356    pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
357        self.set_deep_slp(kind == SleepKind::Deep);
358    }
359
360    pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
361        let cfg = RtcConfig::default();
362
363        // settings derived from esp_clk_init -> rtc_init
364        let rtc_cntl = LPWR::regs();
365        let extmem = EXTMEM::regs();
366        let system = SYSTEM::regs();
367
368        regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
369        regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
370
371        unsafe {
372            rtc_cntl.timer1().modify(|_, w| {
373                w.pll_buf_wait().bits(cfg.pll_wait());
374                w.ck8m_wait().bits(cfg.ck8m_wait())
375            });
376
377            // Moved from rtc sleep to rtc init to save sleep function running time
378            // set shortest possible sleep time limit
379
380            rtc_cntl
381                .timer5()
382                .modify(|_, w| w.min_slp_val().bits(RTC_CNTL_MIN_SLP_VAL_MIN));
383
384            // TODO: something about cali_ocode
385
386            // Reset RTC bias to default value (needed if waking up from deep sleep)
387            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(RTC_CNTL_DBIAS_1V10);
388
389            // LDO dbias initialization
390            // TODO: this modifies g_rtc_dbias_pvt_non_240m and g_dig_dbias_pvt_non_240m.
391            //       We're using a high enough default but we should read from the efuse.
392            // set_rtc_dig_dbias();
393
394            regi2c::I2C_DIG_REG_EXT_RTC_DREG.write_field(RTC_CNTL_DBIAS_1V25);
395            regi2c::I2C_DIG_REG_EXT_DIG_DREG.write_field(RTC_CNTL_DBIAS_1V25);
396
397            if cfg.clkctl_init() {
398                // clear CMMU clock force on
399
400                extmem
401                    .cache_mmu_power_ctrl()
402                    .modify(|_, w| w.cache_mmu_mem_force_on().clear_bit());
403                // clear tag clock force on
404
405                extmem
406                    .icache_tag_power_ctrl()
407                    .modify(|_, w| w.icache_tag_mem_force_on().clear_bit());
408
409                // clear register clock force on
410                SPI0::regs()
411                    .clock_gate()
412                    .modify(|_, w| w.clk_en().clear_bit());
413                SPI1::regs()
414                    .clock_gate()
415                    .modify(|_, w| w.clk_en().clear_bit());
416            }
417
418            if cfg.pwrctl_init() {
419                rtc_cntl
420                    .clk_conf()
421                    .modify(|_, w| w.ck8m_force_pu().clear_bit());
422
423                rtc_cntl
424                    .options0()
425                    .modify(|_, w| w.xtl_force_pu().bit(cfg.xtal_fpu() || cfg.bbpll_fpu()));
426
427                // cancel bbpll force pu if setting no force power up
428
429                rtc_cntl.options0().modify(|_, w| {
430                    w.bbpll_force_pu().bit(cfg.bbpll_fpu());
431                    w.bbpll_i2c_force_pu().bit(cfg.bbpll_fpu());
432                    w.bb_i2c_force_pu().bit(cfg.bbpll_fpu())
433                });
434
435                rtc_cntl
436                    .rtc_cntl()
437                    .modify(|_, w| w.regulator_force_pu().clear_bit());
438
439                // If this mask is enabled, all soc memories cannot enter power down mode
440                // We should control soc memory power down mode from RTC, so we will not touch
441                // this register any more
442
443                system
444                    .mem_pd_mask()
445                    .modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
446
447                // If this pd_cfg is set to 1, all memory won't enter low power mode during
448                // light sleep If this pd_cfg is set to 0, all memory will enter low
449                // power mode during light sleep
450                rtc_sleep_pu(false);
451
452                rtc_cntl
453                    .dig_pwc()
454                    .modify(|_, w| w.dg_wrap_force_pu().clear_bit());
455
456                rtc_cntl
457                    .dig_iso()
458                    .modify(|_, w| w.dg_wrap_force_noiso().clear_bit());
459
460                // if SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0 , the cpu clk will be closed when cpu
461                // enter WAITI mode
462
463                system
464                    .cpu_per_conf()
465                    .modify(|_, w| w.cpu_wait_mode_force_on().bit(!cfg.cpu_waiti_clk_gate()));
466
467                // cancel digital PADS force no iso
468
469                rtc_cntl.dig_iso().modify(|_, w| {
470                    w.dg_pad_force_unhold().clear_bit();
471                    w.dg_pad_force_noiso().clear_bit()
472                });
473            }
474
475            rtc_cntl.int_ena().write(|w| w.bits(0));
476            rtc_cntl.int_clr().write(|w| w.bits(u32::MAX));
477
478            regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(1);
479        }
480    }
481
482    pub(crate) fn apply(&self) {
483        // like esp-idf rtc_sleep_init()
484        let rtc_cntl = LPWR::regs();
485
486        if self.lslp_mem_inf_fpu() {
487            rtc_sleep_pu(true);
488        }
489
490        unsafe {
491            assert!(!self.pd_cur_slp() || self.bias_sleep_slp());
492
493            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(self.rtc_dbias_slp());
494            regi2c::I2C_DIG_REG_EXT_DIG_DREG_SLEEP.write_field(self.dig_dbias_slp());
495
496            rtc_cntl.bias_conf().modify(|_, w| {
497                w.dbg_atten_monitor()
498                    .bits(RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT);
499                // We have config values for this in self, so I don't know why we're setting
500                // hardcoded defaults for these next two. It's what IDF does...
501                w.bias_sleep_monitor().bit(RTC_CNTL_BIASSLP_MONITOR_DEFAULT);
502                w.pd_cur_monitor().bit(RTC_CNTL_PD_CUR_MONITOR_DEFAULT)
503            });
504
505            rtc_cntl.bias_conf().modify(|_, w| {
506                w.dbg_atten_deep_slp().bits(self.dbg_atten_slp());
507                w.bias_sleep_deep_slp().bit(self.bias_sleep_slp());
508                w.pd_cur_deep_slp().bit(self.pd_cur_slp())
509            });
510
511            if self.deep_slp() {
512                regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(0);
513
514                rtc_cntl
515                    .dig_pwc()
516                    .modify(|_, w| w.dg_wrap_pd_en().set_bit());
517
518                rtc_cntl.ana_conf().modify(|_, w| {
519                    w.ckgen_i2c_pu().clear_bit();
520                    w.pll_i2c_pu().clear_bit();
521                    w.rfrx_pbus_pu().clear_bit();
522                    w.txrf_i2c_pu().clear_bit()
523                });
524
525                rtc_cntl
526                    .options0()
527                    .modify(|_, w| w.bb_i2c_force_pu().clear_bit());
528            } else {
529                rtc_cntl.bias_conf().modify(|_, w| {
530                    w.dg_vdd_drv_b_slp_en().set_bit();
531                    w.dg_vdd_drv_b_slp().bits(RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT)
532                });
533
534                rtc_cntl
535                    .dig_pwc()
536                    .modify(|_, w| w.dg_wrap_pd_en().clear_bit());
537            }
538
539            rtc_cntl
540                .rtc_cntl()
541                .modify(|_, w| w.regulator_force_pu().bit(self.rtc_regulator_fpu()));
542
543            rtc_cntl.clk_conf().modify(|_, w| {
544                w.ck8m_force_pu().bit(!self.int_8m_pd_en());
545                w.ck8m_force_nogating().bit(!self.int_8m_pd_en())
546            });
547
548            // enable VDDSDIO control by state machine
549
550            rtc_cntl.dig_pwc().modify(|_, w| {
551                w.vdd_spi_pwr_force().clear_bit();
552                w.vdd_spi_pd_en().bit(self.vddsdio_pd_en())
553            });
554
555            rtc_cntl.slp_reject_conf().modify(|_, w| {
556                w.deep_slp_reject_en().bit(self.deep_slp_reject());
557                w.light_slp_reject_en().bit(self.light_slp_reject())
558            });
559
560            rtc_cntl
561                .options0()
562                .modify(|_, w| w.xtl_force_pu().bit(self.xtal_fpu()));
563
564            rtc_cntl
565                .clk_conf()
566                .modify(|_, w| w.xtal_global_force_nogating().bit(self.xtal_fpu()));
567        }
568    }
569
570    /// Configures the wakeup options and requests the sleep.
571    ///
572    /// The caller waits for the result of the request.
573    pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) {
574        // set bits for what can wake us up
575        LPWR::regs()
576            .wakeup_state()
577            .modify(|_, w| unsafe { w.wakeup_ena().bits(wakeup_mask) });
578
579        // Set the bits of the sources that reject the sleep. The reject enables that `apply` wrote
580        // arm those sources.
581        LPWR::regs()
582            .slp_reject_conf()
583            .modify(|_, w| unsafe { w.sleep_reject_ena().bits(reject_mask) });
584
585        LPWR::regs().state0().modify(|_, w| w.sleep_en().set_bit());
586    }
587
588    pub(crate) fn finish_sleep(&self) {
589        // In deep sleep mode, we never get here
590
591        LPWR::regs().int_clr().write(|w| {
592            w.slp_reject().clear_bit_by_one();
593            w.slp_wakeup().clear_bit_by_one()
594        });
595
596        // restore config if it is a light sleep
597        if self.lslp_mem_inf_fpu() {
598            rtc_sleep_pu(true);
599        }
600    }
601}