Skip to main content

esp_hal/rtc_cntl/sleep/
esp32s3.rs

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