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