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