Skip to main content

esp_hal/rtc_cntl/sleep/
esp32s2.rs

1use super::SleepKind;
2use crate::{
3    peripherals::{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 setting for 0.90V.
12pub const RTC_CNTL_DBIAS_0V90: u8 = 0;
13/// Digital bias setting for 0.95V.
14pub const RTC_CNTL_DBIAS_0V95: u8 = 1;
15/// Digital bias setting for 1.00V.
16pub const RTC_CNTL_DBIAS_1V00: u8 = 2;
17/// Digital bias setting for 1.05V.
18pub const RTC_CNTL_DBIAS_1V05: u8 = 3;
19/// Digital bias setting for 1.10V.
20pub const RTC_CNTL_DBIAS_1V10: u8 = 4;
21/// Digital bias setting for 1.15V.
22pub const RTC_CNTL_DBIAS_1V15: u8 = 5;
23/// Digital bias setting for 1.20V.
24pub const RTC_CNTL_DBIAS_1V20: u8 = 6;
25/// Digital bias setting for 1.25V.
26pub const RTC_CNTL_DBIAS_1V25: u8 = 7;
27/// Default monitor debug attenuation value.
28pub const RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT: u8 = 0;
29/// ULP co-processor touch start wait time during sleep, set to maximum.
30pub const RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP: u16 = 0xFF;
31/// ULP co-processor touch start wait time default value.
32pub const RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT: u16 = 0x10;
33/// Default wait time for PLL buffer during startup.
34pub const RTC_CNTL_PLL_BUF_WAIT_DEFAULT: u8 = 20;
35/// Default wait time for CK8M during startup.
36pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
37/// Default wait time for XTL buffer during startup.
38pub const RTC_CNTL_XTL_BUF_WAIT_DEFAULT: u8 = 100;
39/// Minimum sleep value.
40pub const RTC_CNTL_MIN_SLP_VAL_MIN: u8 = 2;
41/// Deep sleep debug attenuation setting for ultra-low power mode.
42pub const RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT: u8 = 15;
43/// Power-up setting for other blocks.
44pub const OTHER_BLOCKS_POWERUP: u8 = 1;
45/// Wait cycles for other blocks.
46pub const OTHER_BLOCKS_WAIT: u16 = 1;
47/// WiFi power-up cycles.
48pub const WIFI_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
49/// WiFi wait cycles.
50pub const WIFI_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
51/// RTC power-up cycles.
52pub const RTC_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
53/// RTC wait cycles.
54pub const RTC_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
55/// DG wrap power-up cycles.
56pub const DG_WRAP_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
57/// DG wrap wait cycles.
58pub const DG_WRAP_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
59/// DG peripheral power-up cycles.
60pub const DG_PERI_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
61/// DG peripheral wait cycles.
62pub const DG_PERI_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
63/// RTC memory power-up cycles.
64pub const RTC_MEM_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
65/// RTC memory wait cycles.
66pub const RTC_MEM_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
67
68bitfield::bitfield! {
69    /// Configuration for the RTC sleep behavior.
70    #[derive(Clone, Copy)]
71    pub struct RtcSleepConfig(u64);
72    impl Debug;
73    /// force normal voltage in sleep mode (digital domain memory)
74    pub lslp_mem_inf_fpu, set_lslp_mem_inf_fpu: 0;
75    /// keep low voltage in sleep mode (even if ULP/touch is used)
76    pub rtc_mem_inf_follow_cpu, set_rtc_mem_inf_follow_cpu: 1;
77    /// power down RTC fast memory
78    pub rtc_fastmem_pd_en, set_rtc_fastmem_pd_en: 2;
79    /// power down RTC slow memory
80    pub rtc_slowmem_pd_en, set_rtc_slowmem_pd_en: 3;
81    /// power down RTC peripherals
82    pub rtc_peri_pd_en, set_rtc_peri_pd_en: 4;
83    /// power down Wifi
84    pub wifi_pd_en, set_wifi_pd_en: 5;
85    /// Power down Internal 8M oscillator
86    pub int_8m_pd_en, set_int_8m_pd_en: 6;
87    /// power down digital domain
88    pub deep_slp, set_deep_slp: 8;
89    /// enable WDT flashboot mode
90    pub wdt_flashboot_mod_en, set_wdt_flashboot_mod_en: 9;
91    /// set bias for digital domain, in sleep mode
92    pub u8, dig_dbias_slp, set_dig_dbias_slp: 12, 10;
93    /// set bias for RTC domain, in sleep mode
94    pub u8, rtc_dbias_slp, set_rtc_dbias_slp: 16, 13;
95    /// circuit control parameter, in monitor mode
96    pub bias_sleep_monitor, set_bias_sleep_monitor: 17;
97    /// voltage parameter, in sleep mode
98    pub u8, dbg_atten_slp, set_dbg_atten_slp: 22, 18;
99    /// circuit control parameter, in sleep mode
100    pub bias_sleep_slp, set_bias_sleep_slp: 23;
101    /// circuit control parameter, in monitor mode
102    pub pd_cur_monitor, set_pd_cur_monitor: 24;
103    /// circuit control parameter, in sleep mode
104    pub pd_cur_slp, set_pd_cur_slp: 25;
105    /// power down VDDSDIO regulator
106    pub vddsdio_pd_en, set_vddsdio_pd_en: 26;
107    /// keep main XTAL powered up in sleep
108    pub xtal_fpu, set_xtal_fpu: 27;
109    /// keep rtc regulator powered up in sleep
110    pub rtc_regulator_fpu, set_rtc_regulator_fpu: 28;
111    /// enable deep sleep reject
112    pub deep_slp_reject, set_deep_slp_reject: 29;
113    /// enable light sleep reject
114    pub light_slp_reject, set_light_slp_reject: 30;
115}
116
117impl Default for RtcSleepConfig {
118    fn default() -> Self {
119        let mut cfg = Self(Default::default());
120        cfg.set_deep_slp_reject(true);
121        cfg.set_light_slp_reject(true);
122        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
123        cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_1V10);
124
125        // This is the light-sleep config. The main XTAL is powered down in sleep
126        // (`xtal_fpu` stays false), so the analog regulator/bias must use the
127        // same XTAL-down settings that `deep()` applies "because of xtal_fpu".
128        cfg.set_rtc_regulator_fpu(true);
129        cfg.set_bias_sleep_monitor(true);
130        cfg.set_pd_cur_monitor(true);
131        cfg.set_bias_sleep_slp(true);
132        cfg.set_pd_cur_slp(true);
133        cfg
134    }
135}
136
137fn rtc_sleep_pu(val: bool) {
138    // Note: Called rtc_sleep_pd in idf, but makes more sense like this with the
139    // single boolean argument
140    let rtc_cntl = LPWR::regs();
141    let syscon = unsafe { &*esp32s2::SYSCON::ptr() };
142    let bb = unsafe { &*esp32s2::BB::ptr() };
143    let i2s = unsafe { &*esp32s2::I2S0::ptr() };
144    let nrx = unsafe { &*esp32s2::NRX::ptr() };
145    let fe = unsafe { &*esp32s2::FE::ptr() };
146    let fe2 = unsafe { &*esp32s2::FE2::ptr() };
147
148    rtc_cntl
149        .dig_pwc()
150        .modify(|_, w| w.lslp_mem_force_pu().bit(val));
151
152    rtc_cntl
153        .pwc()
154        .modify(|_, w| w.slowmem_force_lpu().bit(val).fastmem_force_lpu().bit(val));
155
156    i2s.pd_conf()
157        .write(|w| w.plc_mem_force_pu().bit(val).fifo_force_pu().bit(val));
158
159    syscon.front_end_mem_pd().modify(|_r, w| {
160        w.dc_mem_force_pu()
161            .bit(val)
162            .pbus_mem_force_pu()
163            .bit(val)
164            .agc_mem_force_pu()
165            .bit(val)
166    });
167
168    bb.bbpd_ctrl()
169        .modify(|_r, w| w.fft_force_pu().bit(val).dc_est_force_pu().bit(val));
170
171    nrx.nrxpd_ctrl().modify(|_, w| {
172        w.rx_rot_force_pu()
173            .bit(val)
174            .vit_force_pu()
175            .bit(val)
176            .demap_force_pu()
177            .bit(val)
178    });
179
180    fe.gen_ctrl().modify(|_, w| w.iq_est_force_pu().bit(val));
181
182    fe2.tx_interp_ctrl()
183        .modify(|_, w| w.tx_inf_force_pu().bit(val));
184}
185
186impl RtcSleepConfig {
187    /// Configures the RTC for deep sleep mode.
188    pub fn deep() -> Self {
189        // Set up for ultra-low power sleep. Wakeup sources may modify these settings.
190        let mut cfg = Self::default();
191
192        cfg.set_lslp_mem_inf_fpu(false);
193        cfg.set_rtc_mem_inf_follow_cpu(true); // ?
194        cfg.set_rtc_fastmem_pd_en(true);
195        cfg.set_rtc_slowmem_pd_en(true);
196        cfg.set_rtc_peri_pd_en(true);
197        cfg.set_wifi_pd_en(true);
198        cfg.set_int_8m_pd_en(true);
199
200        // Because of force_flags
201        cfg.set_vddsdio_pd_en(true);
202
203        // because of dig_peri_pd_en
204        cfg.set_dig_dbias_slp(0);
205
206        cfg.set_deep_slp(true);
207        cfg.set_wdt_flashboot_mod_en(false);
208        cfg.set_vddsdio_pd_en(true);
209        cfg.set_xtal_fpu(false);
210        cfg.set_deep_slp_reject(true);
211        cfg.set_light_slp_reject(true);
212
213        // because of RTC_SLEEP_PD_DIG
214        // NOTE: Might be the a different case for RTC_SLEEP_PD_DIG in
215        // rtc_sleep_get_default_config
216        cfg.set_rtc_regulator_fpu(false);
217        cfg.set_dbg_atten_slp(RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT);
218        cfg.set_rtc_dbias_slp(0);
219
220        // because of xtal_fpu
221        cfg.set_xtal_fpu(false);
222        cfg.set_bias_sleep_monitor(true);
223        cfg.set_pd_cur_monitor(true);
224        cfg.set_bias_sleep_slp(true);
225        cfg.set_pd_cur_slp(true);
226
227        cfg
228    }
229
230    pub(crate) fn is_deep_sleep(&self) -> bool {
231        self.deep_slp()
232    }
233
234    pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
235        self.set_deep_slp(kind == SleepKind::Deep);
236    }
237
238    pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
239        // settings derived from esp_clk_init -> rtc_init
240        unsafe {
241            let rtc_cntl = LPWR::regs();
242            let extmem = EXTMEM::regs();
243            let system = SYSTEM::regs();
244
245            rtc_cntl
246                .dig_pwc()
247                .modify(|_, w| w.wifi_force_pd().clear_bit());
248            rtc_cntl
249                .dig_iso()
250                .modify(|_, w| w.wifi_force_iso().clear_bit());
251
252            rtc_cntl.ana_conf().modify(|_, w| w.pvtmon_pu().clear_bit());
253
254            rtc_cntl.timer1().modify(|_, w| {
255                w.pll_buf_wait().bits(RTC_CNTL_PLL_BUF_WAIT_DEFAULT);
256                w.ck8m_wait().bits(RTC_CNTL_CK8M_WAIT_DEFAULT)
257            });
258
259            // idf: "Moved from rtc sleep to rtc init to save sleep function running time
260            // set shortest possible sleep time limit"
261
262            rtc_cntl
263                .timer5()
264                .modify(|_, w| w.min_slp_val().bits(RTC_CNTL_MIN_SLP_VAL_MIN));
265
266            rtc_cntl.timer3().modify(|_, w| {
267                // set wifi timer
268                w.wifi_powerup_timer().bits(WIFI_POWERUP_CYCLES);
269                w.wifi_wait_timer().bits(WIFI_WAIT_CYCLES)
270            });
271
272            rtc_cntl.timer4().modify(|_, w| {
273                // set rtc peri timer
274                w.powerup_timer().bits(RTC_POWERUP_CYCLES);
275                w.wait_timer().bits(RTC_WAIT_CYCLES);
276                // set digital wrap timer
277                w.dg_wrap_powerup_timer().bits(DG_WRAP_POWERUP_CYCLES);
278                w.dg_wrap_wait_timer().bits(DG_WRAP_WAIT_CYCLES)
279            });
280
281            rtc_cntl.timer5().modify(|_, w| {
282                w.rtcmem_powerup_timer().bits(RTC_MEM_POWERUP_CYCLES);
283                w.rtcmem_wait_timer().bits(RTC_MEM_WAIT_CYCLES)
284            });
285
286            rtc_cntl.bias_conf().modify(|_, w| {
287                w.dec_heartbeat_width().set_bit();
288                w.inc_heartbeat_period().set_bit()
289            });
290
291            // Reset RTC bias to default value (needed if waking up from deep sleep)
292            rtc_cntl.reg().modify(|_, w| {
293                w.dbias_wak().bits(RTC_CNTL_DBIAS_1V10);
294                w.dbias_slp().bits(RTC_CNTL_DBIAS_1V10)
295            });
296
297            // Set the wait time to the default value.
298            rtc_cntl.timer2().modify(|_, w| {
299                w.ulpcp_touch_start_wait()
300                    .bits(RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT)
301            });
302
303            // clkctl_init
304            {
305                // clear CMMU clock force on
306                extmem
307                    .pro_cache_mmu_power_ctrl()
308                    .modify(|_, w| w.pro_cache_mmu_mem_force_on().clear_bit());
309
310                // clear tag clock force on
311                extmem
312                    .pro_dcache_tag_power_ctrl()
313                    .modify(|_, w| w.pro_dcache_tag_mem_force_on().clear_bit());
314
315                extmem
316                    .pro_icache_tag_power_ctrl()
317                    .modify(|_, w| w.pro_icache_tag_mem_force_on().clear_bit());
318
319                system.rom_ctrl_0().modify(|_, w| w.rom_fo().bits(0));
320                system.sram_ctrl_0().modify(|_, w| w.sram_fo().bits(0));
321
322                // clear register clock force on
323                SPI0::regs()
324                    .clock_gate()
325                    .modify(|_, w| w.clk_en().clear_bit());
326                SPI1::regs()
327                    .clock_gate()
328                    .modify(|_, w| w.clk_en().clear_bit());
329            }
330
331            // pwrctl_init
332            {
333                rtc_cntl
334                    .clk_conf()
335                    .modify(|_, w| w.ck8m_force_pu().clear_bit());
336
337                rtc_cntl
338                    .options0()
339                    .modify(|_, w| w.xtl_force_pu().clear_bit());
340
341                // CLEAR APLL close
342                rtc_cntl.ana_conf().modify(|_, w| {
343                    w.plla_force_pu().clear_bit();
344                    w.plla_force_pd().set_bit()
345                });
346
347                // cancel bbpll force pu if setting no force power up
348                rtc_cntl.options0().modify(|_, w| {
349                    w.bbpll_force_pu().clear_bit();
350                    w.bbpll_i2c_force_pu().clear_bit();
351                    w.bb_i2c_force_pu().clear_bit()
352                });
353
354                // cancel RTC REG force PU
355
356                rtc_cntl.pwc().modify(|_, w| w.force_pu().clear_bit());
357                rtc_cntl.reg().modify(|_, w| {
358                    w.regulator_force_pu().clear_bit();
359                    w.dboost_force_pu().clear_bit()
360                });
361
362                rtc_cntl.pwc().modify(|_, w| {
363                    w.slowmem_force_pu().clear_bit();
364                    w.fastmem_force_pu().clear_bit();
365                    w.slowmem_force_noiso().clear_bit();
366                    w.fastmem_force_noiso().clear_bit()
367                });
368
369                rtc_cntl.reg().modify(|_, w| w.dboost_force_pd().set_bit());
370
371                // cancel sar i2c pd force
372                rtc_cntl
373                    .ana_conf()
374                    .modify(|_, w| w.sar_i2c_force_pd().clear_bit());
375                // cancel digital pu force
376                // NOTE: duplicate from idf
377                rtc_cntl.pwc().modify(|_, w| {
378                    w.slowmem_force_pu().clear_bit();
379                    w.fastmem_force_pu().clear_bit()
380                });
381
382                // If this mask is enabled, all soc memories cannot enter power down mode
383                // We should control soc memory power down mode from RTC, so we will not touch
384                // this register any more
385
386                system
387                    .mem_pd_mask()
388                    .modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
389
390                // If this pd_cfg is set to 1, all memory won't enter low power mode during
391                // light sleep If this pd_cfg is set to 0, all memory will enter low
392                // power mode during light sleep
393                rtc_sleep_pu(false);
394
395                rtc_cntl.dig_pwc().modify(|_, w| {
396                    w.dg_wrap_force_pu().clear_bit();
397                    w.wifi_force_pu().clear_bit()
398                });
399
400                rtc_cntl.dig_iso().modify(|_, w| {
401                    w.dg_wrap_force_noiso().clear_bit();
402                    // NOTE: not present in idf.
403                    w.dg_wrap_force_iso().clear_bit()
404                });
405
406                rtc_cntl.dig_iso().modify(|_, w| {
407                    w.wifi_force_noiso().clear_bit();
408                    // NOTE: not present in idf.
409                    w.wifi_force_iso().clear_bit()
410                });
411
412                rtc_cntl.pwc().modify(|_, w| w.force_noiso().clear_bit());
413
414                // cancel digital PADS force no iso
415                system
416                    .cpu_per_conf()
417                    .modify(|_, w| w.cpu_wait_mode_force_on().clear_bit());
418
419                // if DPORT_CPU_WAIT_MODE_FORCE_ON == 0,
420                // the cpu clk will be closed when cpu enter WAITI mode
421                rtc_cntl.dig_iso().modify(|_, w| {
422                    w.dg_pad_force_unhold().clear_bit();
423                    w.dg_pad_force_noiso().clear_bit()
424                });
425            }
426
427            // force power down wifi and bt power domain
428            rtc_cntl
429                .dig_iso()
430                .modify(|_, w| w.wifi_force_iso().set_bit());
431
432            rtc_cntl
433                .dig_pwc()
434                .modify(|_, w| w.wifi_force_pd().set_bit());
435
436            rtc_cntl.int_ena().write(|w| w.bits(0));
437            rtc_cntl.int_clr().write(|w| w.bits(u32::MAX));
438        }
439    }
440
441    pub(crate) fn apply(&self) {
442        // like esp-idf rtc_sleep_init() and deep_sleep_start()
443        let rtc_cntl = LPWR::regs();
444
445        if self.deep_slp() {
446            // "Due to hardware limitations, on S2 the brownout detector
447            // sometimes trigger during deep sleep to circumvent
448            // this we disable the brownout detector before sleeping' - from
449            // idf's deep_sleep_start()
450            unsafe {
451                // brownout_hal_config(brownlout_hal_config_t{0})
452                rtc_cntl.brown_out().modify(|_, w| {
453                    w.int_wait().bits(2);
454                    w.close_flash_ena().clear_bit();
455                    w.pd_rf_ena().clear_bit();
456                    w.cnt_clr().set_bit()
457                });
458                rtc_cntl.brown_out().modify(|_, w| {
459                    // Set followed by clear in idf
460                    w.cnt_clr().clear_bit();
461                    w.rst_wait().bits(0x3fff);
462                    w.rst_ena().clear_bit();
463                    w.brown_out2_ena().set_bit();
464                    w.rst_sel().set_bit()
465                });
466                regi2c::I2C_BOD_REG_THRESHOLD.write_field(0);
467                rtc_cntl.brown_out().modify(|_, w| w.ena().clear_bit());
468                rtc_cntl.int_ena().modify(|_, w| w.brown_out().clear_bit());
469                // NOTE: rtc_isr_deregister?
470            }
471        }
472
473        if self.lslp_mem_inf_fpu() {
474            rtc_sleep_pu(true);
475        }
476
477        let mem_folw_cpu = self.rtc_mem_inf_follow_cpu();
478        rtc_cntl.pwc().modify(|_, w| {
479            w.slowmem_folw_cpu().bit(mem_folw_cpu);
480            w.fastmem_folw_cpu().bit(mem_folw_cpu)
481        });
482
483        let rtc_fastmem_pd_en = self.rtc_fastmem_pd_en();
484        rtc_cntl.pwc().modify(|_, w| {
485            w.fastmem_pd_en().bit(rtc_fastmem_pd_en);
486            w.fastmem_force_pu().bit(!rtc_fastmem_pd_en);
487            w.fastmem_force_noiso().bit(!rtc_fastmem_pd_en)
488        });
489
490        let rtc_slowmem_pd_en = self.rtc_slowmem_pd_en();
491        rtc_cntl.pwc().modify(|_, w| {
492            w.slowmem_pd_en().bit(rtc_slowmem_pd_en);
493            w.slowmem_force_pu().bit(!rtc_slowmem_pd_en);
494            w.slowmem_force_noiso().bit(!rtc_slowmem_pd_en)
495        });
496
497        let rtc_peri_pd_en = self.rtc_peri_pd_en();
498        rtc_cntl.pwc().modify(|_, w| w.pd_en().bit(rtc_peri_pd_en));
499
500        if self.wifi_pd_en() {
501            rtc_cntl
502                .dig_iso()
503                .modify(|_, w| w.wifi_force_noiso().clear_bit());
504
505            rtc_cntl.dig_pwc().modify(|_, w| {
506                w.wifi_force_pu().clear_bit();
507                w.wifi_pd_en().set_bit()
508            });
509        } else {
510            rtc_cntl.dig_pwc().modify(|_, w| w.wifi_pd_en().clear_bit());
511        }
512
513        unsafe {
514            rtc_cntl.reg().modify(|_, w| {
515                w.dbias_slp().bits(self.rtc_dbias_slp());
516                w.dig_reg_dbias_slp().bits(self.dig_dbias_slp())
517            });
518
519            rtc_cntl.bias_conf().modify(|_, w| {
520                w.dbg_atten_monitor()
521                    .bits(RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT);
522                w.bias_sleep_monitor().bit(self.bias_sleep_monitor());
523                w.bias_sleep_deep_slp().bit(self.bias_sleep_slp());
524                w.pd_cur_monitor().bit(self.pd_cur_monitor());
525                w.pd_cur_deep_slp().bit(self.pd_cur_slp());
526                w.dbg_atten_deep_slp().bits(self.dbg_atten_slp())
527            });
528
529            if self.deep_slp() {
530                rtc_cntl
531                    .dig_pwc()
532                    .modify(|_, w| w.dg_wrap_pd_en().set_bit());
533
534                rtc_cntl.ana_conf().modify(|_, w| {
535                    w.ckgen_i2c_pu().clear_bit();
536                    w.pll_i2c_pu().clear_bit();
537                    w.rfrx_pbus_pu().clear_bit();
538                    w.txrf_i2c_pu().clear_bit()
539                });
540
541                rtc_cntl
542                    .options0()
543                    .modify(|_, w| w.bb_i2c_force_pu().clear_bit());
544            } else {
545                rtc_cntl
546                    .dig_pwc()
547                    .modify(|_, w| w.dg_wrap_pd_en().clear_bit());
548            }
549
550            let rtc_regulator_fpu = self.rtc_regulator_fpu();
551            rtc_cntl
552                .reg()
553                .modify(|_, w| w.regulator_force_pu().bit(rtc_regulator_fpu));
554
555            let int_8m_pd_en = self.int_8m_pd_en();
556            rtc_cntl
557                .clk_conf()
558                .modify(|_, w| w.ck8m_force_pu().bit(!int_8m_pd_en));
559
560            // enable VDDSDIO control by state machine
561            rtc_cntl.sdio_conf().modify(|_, w| {
562                w.sdio_force().clear_bit();
563                w.sdio_reg_pd_en().bit(self.vddsdio_pd_en())
564            });
565
566            rtc_cntl.slp_reject_conf().modify(|_, w| {
567                w.deep_slp_reject_en().bit(self.deep_slp_reject());
568                w.light_slp_reject_en().bit(self.light_slp_reject())
569            });
570
571            // Set wait cycle for touch or COCPU after deep sleep and light
572            // sleep.
573
574            rtc_cntl.timer2().modify(|_, w| {
575                w.ulpcp_touch_start_wait()
576                    .bits(RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP)
577            });
578
579            rtc_cntl
580                .options0()
581                .modify(|_, w| w.xtl_force_pu().bit(self.xtal_fpu()));
582        }
583    }
584
585    /// Configures the wakeup options and requests the sleep.
586    ///
587    /// The caller waits for the result of the request.
588    pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) {
589        unsafe {
590            LPWR::regs()
591                .reset_state()
592                .modify(|_, w| w.procpu_stat_vector_sel().set_bit());
593
594            // set bits for what can wake us up
595            LPWR::regs()
596                .wakeup_state()
597                .modify(|_, w| w.wakeup_ena().bits(wakeup_mask));
598
599            // Set the bits of the sources that reject the sleep. The reject enables that `apply`
600            // wrote arm those sources.
601            LPWR::regs()
602                .slp_reject_conf()
603                .modify(|_, w| w.sleep_reject_ena().bits(reject_mask));
604
605            LPWR::regs().state0().modify(|_, w| w.sleep_en().set_bit());
606        }
607    }
608
609    pub(crate) fn finish_sleep(&self) {
610        // In deep sleep mode, we never get here
611        unsafe {
612            LPWR::regs().int_clr().write(|w| {
613                w.slp_reject()
614                    .clear_bit_by_one()
615                    .slp_wakeup()
616                    .clear_bit_by_one()
617            });
618
619            // restore config if it is a light sleep
620            if self.lslp_mem_inf_fpu() {
621                rtc_sleep_pu(true);
622            }
623
624            // Recover default wait cycle for touch or COCPU after wakeup.
625
626            LPWR::regs().timer2().modify(|_, w| {
627                w.ulpcp_touch_start_wait()
628                    .bits(RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT)
629            });
630        }
631    }
632}