esp_hal/rtc_cntl/sleep/
esp32s3.rs

1use super::{
2    Ext0WakeupSource,
3    Ext1WakeupSource,
4    TimerWakeupSource,
5    WakeSource,
6    WakeTriggers,
7    WakeupLevel,
8};
9use crate::{
10    gpio::{RtcFunction, RtcPin},
11    peripherals::{APB_CTRL, EXTMEM, LPWR, RTC_IO, SPI0, SPI1, SYSTEM},
12    rtc_cntl::{Clock, Rtc, RtcClock, sleep::RtcioWakeupSource},
13    soc::regi2c,
14};
15
16// Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP,
17// RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values.
18// Valid if RTC_CNTL_DBG_ATTEN is 0.
19/// Digital bias setting for 0.90V.
20pub const RTC_CNTL_DBIAS_0V90: u8 = 13;
21/// Digital bias setting for 0.95V.
22pub const RTC_CNTL_DBIAS_0V95: u8 = 16;
23/// Digital bias setting for 1.00V.
24pub const RTC_CNTL_DBIAS_1V00: u8 = 18;
25/// Digital bias setting for 1.05V.
26pub const RTC_CNTL_DBIAS_1V05: u8 = 20;
27/// Digital bias setting for 1.10V.
28pub const RTC_CNTL_DBIAS_1V10: u8 = 23;
29/// Digital bias setting for 1.15V.
30pub const RTC_CNTL_DBIAS_1V15: u8 = 25;
31/// Digital bias setting for 1.20V.
32pub const RTC_CNTL_DBIAS_1V20: u8 = 28;
33/// Digital bias setting for 1.25V.
34pub const RTC_CNTL_DBIAS_1V25: u8 = 30;
35/// Digital bias setting for 1.30V. Voltage is approximately 1.34V in practice.
36pub const RTC_CNTL_DBIAS_1V30: u8 = 31;
37/// Default monitor debug attenuation value.
38pub const RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT: u8 = 0;
39/// ULP co-processor touch start wait time during sleep, set to maximum.
40pub const RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP: u16 = 0xFF;
41/// ULP co-processor touch start wait time default value.
42pub const RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT: u16 = 0x10;
43/// Default wait time for PLL buffer during startup.
44pub const RTC_CNTL_PLL_BUF_WAIT_DEFAULT: u8 = 20;
45/// Default wait time for CK8M during startup.
46pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
47/// Minimum sleep value.
48pub const RTC_CNTL_MIN_SLP_VAL_MIN: u8 = 2;
49/// Deep sleep debug attenuation setting for ultra-low power mode.
50pub const RTC_CNTL_DBG_ATTEN_DEEPSLEEP_ULTRA_LOW: u8 = 15;
51/// Power-up setting for other blocks.
52pub const OTHER_BLOCKS_POWERUP: u8 = 1;
53/// Wait cycles for other blocks.
54pub const OTHER_BLOCKS_WAIT: u16 = 1;
55/// WiFi power-up cycles.
56pub const WIFI_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
57/// WiFi wait cycles.
58pub const WIFI_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
59/// Bluetooth power-up cycles.
60pub const BT_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
61/// Bluetooth wait cycles.
62pub const BT_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
63/// RTC power-up cycles.
64pub const RTC_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
65/// RTC wait cycles.
66pub const RTC_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
67/// CPU top power-up cycles.
68pub const CPU_TOP_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
69/// CPU top wait cycles.
70pub const CPU_TOP_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
71/// DG wrap power-up cycles.
72pub const DG_WRAP_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
73/// DG wrap wait cycles.
74pub const DG_WRAP_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
75/// DG peripheral power-up cycles.
76pub const DG_PERI_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
77/// DG peripheral wait cycles.
78pub const DG_PERI_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
79/// RTC memory power-up cycles.
80pub const RTC_MEM_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
81/// RTC memory wait cycles.
82pub const RTC_MEM_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
83
84impl WakeSource for TimerWakeupSource {
85    fn apply(
86        &self,
87        rtc: &Rtc<'_>,
88        triggers: &mut WakeTriggers,
89        _sleep_config: &mut RtcSleepConfig,
90    ) {
91        triggers.set_timer(true);
92        let rtc_cntl = LPWR::regs();
93        let clock_freq = RtcClock::slow_freq();
94        // TODO: maybe add sleep time adjustlemnt like idf
95        // TODO: maybe add check to prevent overflow?
96        let clock_hz = clock_freq.frequency().as_hz() as u64;
97        let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64;
98        // "alarm" time in slow rtc ticks
99        let now = rtc.time_since_boot_raw();
100        let time_in_ticks = now + ticks;
101        unsafe {
102            rtc_cntl
103                .slp_timer0()
104                .write(|w| w.slp_val_lo().bits((time_in_ticks & 0xffffffff) as u32));
105
106            rtc_cntl
107                .int_clr()
108                .write(|w| w.main_timer().clear_bit_by_one());
109
110            rtc_cntl.slp_timer1().write(|w| {
111                w.slp_val_hi().bits(((time_in_ticks >> 32) & 0xffff) as u16);
112                w.main_timer_alarm_en().set_bit()
113            });
114        }
115    }
116}
117
118impl<P: RtcPin> WakeSource for Ext0WakeupSource<P> {
119    fn apply(
120        &self,
121        _rtc: &Rtc<'_>,
122        triggers: &mut WakeTriggers,
123        sleep_config: &mut RtcSleepConfig,
124    ) {
125        // don't power down RTC peripherals
126        sleep_config.set_rtc_peri_pd_en(false);
127        triggers.set_ext0(true);
128
129        // set pin to RTC function
130        self.pin
131            .borrow_mut()
132            .rtc_set_config(true, true, RtcFunction::Rtc);
133
134        unsafe {
135            let rtc_io = RTC_IO::regs();
136            // set pin register field
137            rtc_io
138                .ext_wakeup0()
139                .modify(|_, w| w.sel().bits(self.pin.borrow().rtc_number()));
140            // set level register field
141            let rtc_cntl = LPWR::regs();
142            rtc_cntl
143                .ext_wakeup_conf()
144                .modify(|_r, w| w.ext_wakeup0_lv().bit(self.level == WakeupLevel::High));
145        }
146    }
147}
148
149impl<P: RtcPin> Drop for Ext0WakeupSource<P> {
150    fn drop(&mut self) {
151        // should we have saved the pin configuration first?
152        // set pin back to IO_MUX (input_enable and func have no effect when pin is sent
153        // to IO_MUX)
154        self.pin
155            .borrow_mut()
156            .rtc_set_config(true, false, RtcFunction::Rtc);
157    }
158}
159
160impl WakeSource for Ext1WakeupSource<'_, '_> {
161    fn apply(
162        &self,
163        _rtc: &Rtc<'_>,
164        triggers: &mut WakeTriggers,
165        sleep_config: &mut RtcSleepConfig,
166    ) {
167        // don't power down RTC peripherals
168        sleep_config.set_rtc_peri_pd_en(false);
169        triggers.set_ext1(true);
170
171        // set pins to RTC function
172        let mut pins = self.pins.borrow_mut();
173        let mut bits = 0u32;
174        for pin in pins.iter_mut() {
175            pin.rtc_set_config(true, true, RtcFunction::Rtc);
176            bits |= 1 << pin.rtc_number();
177        }
178
179        unsafe {
180            let rtc_cntl = LPWR::regs();
181            // clear previous wakeup status
182            rtc_cntl
183                .ext_wakeup1()
184                .modify(|_, w| w.ext_wakeup1_status_clr().set_bit());
185            // set pin register field
186            rtc_cntl
187                .ext_wakeup1()
188                .modify(|_, w| w.ext_wakeup1_sel().bits(bits));
189            // set level register field
190            rtc_cntl
191                .ext_wakeup_conf()
192                .modify(|_r, w| w.ext_wakeup1_lv().bit(self.level == WakeupLevel::High));
193        }
194    }
195}
196
197impl Drop for Ext1WakeupSource<'_, '_> {
198    fn drop(&mut self) {
199        // should we have saved the pin configuration first?
200        // set pin back to IO_MUX (input_enable and func have no effect when pin is sent
201        // to IO_MUX)
202        let mut pins = self.pins.borrow_mut();
203        for pin in pins.iter_mut() {
204            pin.rtc_set_config(true, false, RtcFunction::Rtc);
205        }
206    }
207}
208
209impl RtcioWakeupSource<'_, '_> {
210    fn apply_pin(&self, pin: &mut dyn RtcPin, level: WakeupLevel) {
211        let rtcio = RTC_IO::regs();
212
213        pin.rtc_set_config(true, true, RtcFunction::Rtc);
214
215        rtcio.pin(pin.number() as usize).modify(|_, w| unsafe {
216            w.wakeup_enable().set_bit().int_type().bits(match level {
217                WakeupLevel::Low => 4,
218                WakeupLevel::High => 5,
219            })
220        });
221    }
222}
223
224impl WakeSource for RtcioWakeupSource<'_, '_> {
225    fn apply(
226        &self,
227        _rtc: &Rtc<'_>,
228        triggers: &mut WakeTriggers,
229        sleep_config: &mut RtcSleepConfig,
230    ) {
231        let mut pins = self.pins.borrow_mut();
232
233        if pins.is_empty() {
234            return;
235        }
236
237        // don't power down RTC peripherals
238        sleep_config.set_rtc_peri_pd_en(false);
239        triggers.set_gpio(true);
240
241        // Since we only use RTCIO pins, we can keep deep sleep enabled.
242        let sens = crate::peripherals::SENS::regs();
243
244        // TODO: disable clock when not in use
245        sens.sar_peri_clk_gate_conf()
246            .modify(|_, w| w.iomux_clk_en().set_bit());
247
248        for (pin, level) in pins.iter_mut() {
249            self.apply_pin(*pin, *level);
250        }
251    }
252}
253
254impl Drop for RtcioWakeupSource<'_, '_> {
255    fn drop(&mut self) {
256        // should we have saved the pin configuration first?
257        // set pin back to IO_MUX (input_enable and func have no effect when pin is sent
258        // to IO_MUX)
259        let mut pins = self.pins.borrow_mut();
260        for (pin, _level) in pins.iter_mut() {
261            pin.rtc_set_config(true, false, RtcFunction::Rtc);
262        }
263    }
264}
265
266bitfield::bitfield! {
267    /// Configuration for the RTC sleep behavior.
268    #[derive(Clone, Copy)]
269    pub struct RtcSleepConfig(u64);
270    impl Debug;
271    /// force normal voltage in sleep mode (digital domain memory)
272    pub lslp_mem_inf_fpu, set_lslp_mem_inf_fpu: 0;
273    /// keep low voltage in sleep mode (even if ULP/touch is used)
274    pub rtc_mem_inf_follow_cpu, set_rtc_mem_inf_follow_cpu: 1;
275    /// power down RTC fast memory
276    pub rtc_fastmem_pd_en, set_rtc_fastmem_pd_en: 2;
277    /// power down RTC slow memory
278    pub rtc_slowmem_pd_en, set_rtc_slowmem_pd_en: 3;
279    /// power down RTC peripherals
280    pub rtc_peri_pd_en, set_rtc_peri_pd_en: 4;
281    /// power down Modem(wifi and ble)
282    pub modem_pd_en, set_modem_pd_en: 5;
283    /// power down CPU, but not restart when lightsleep.
284    pub cpu_pd_en, set_cpu_pd_en: 6;
285    /// Power down Internal 8M oscillator
286    pub int_8m_pd_en, set_int_8m_pd_en: 7;
287    /// power down digital peripherals
288    pub dig_peri_pd_en, set_dig_peri_pd_en: 8;
289    /// power down digital domain
290    pub deep_slp, set_deep_slp: 9;
291    /// enable WDT flashboot mode
292    pub wdt_flashboot_mod_en, set_wdt_flashboot_mod_en: 10;
293    /// set bias for digital domain, in sleep mode
294    pub u8, dig_dbias_slp, set_dig_dbias_slp: 15, 11;
295    /// set bias for RTC domain, in sleep mode
296    pub u8, rtc_dbias_slp, set_rtc_dbias_slp: 20, 16;
297    /// circuit control parameter, in monitor mode
298    pub bias_sleep_monitor, set_bias_sleep_monitor: 21;
299    /// voltage parameter, in sleep mode
300    pub u8, dbg_atten_slp, set_dbg_atten_slp: 25, 22;
301    /// circuit control parameter, in sleep mode
302    pub bias_sleep_slp, set_bias_sleep_slp: 26;
303    /// circuit control parameter, in monitor mode
304    pub pd_cur_monitor, set_pd_cur_monitor: 27;
305    /// circuit control parameter, in sleep mode
306    pub pd_cur_slp, set_pd_cur_slp: 28;
307    /// power down VDDSDIO regulator
308    pub vddsdio_pd_en, set_vddsdio_pd_en: 29;
309    /// keep main XTAL powered up in sleep
310    pub xtal_fpu, set_xtal_fpu: 30;
311    /// keep rtc regulator powered up in sleep
312    pub rtc_regulator_fpu, set_rtc_regulator_fpu: 31;
313    /// enable deep sleep reject
314    pub deep_slp_reject, set_deep_slp_reject: 32;
315    /// enable light sleep reject
316    pub light_slp_reject, set_light_slp_reject: 33;
317}
318
319impl Default for RtcSleepConfig {
320    fn default() -> Self {
321        let mut cfg = Self(Default::default());
322        cfg.set_deep_slp_reject(true);
323        cfg.set_light_slp_reject(true);
324        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
325        cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_1V10);
326        cfg
327    }
328}
329
330const SYSCON_SRAM_POWER_UP: u16 = 0x7FF;
331const SYSCON_ROM_POWER_UP: u8 = 0x7;
332
333fn rtc_sleep_pu(val: bool) {
334    let rtc_cntl = LPWR::regs();
335    let syscon = unsafe { &*esp32s3::APB_CTRL::ptr() };
336    let bb = unsafe { &*esp32s3::BB::ptr() };
337    let nrx = unsafe { &*esp32s3::NRX::ptr() };
338    let fe = unsafe { &*esp32s3::FE::ptr() };
339    let fe2 = unsafe { &*esp32s3::FE2::ptr() };
340
341    rtc_cntl
342        .dig_pwc()
343        .modify(|_, w| w.lslp_mem_force_pu().bit(val));
344
345    rtc_cntl
346        .pwc()
347        .modify(|_, w| w.slowmem_force_lpu().bit(val).fastmem_force_lpu().bit(val));
348
349    syscon.front_end_mem_pd().modify(|_r, w| {
350        w.dc_mem_force_pu()
351            .bit(val)
352            .pbus_mem_force_pu()
353            .bit(val)
354            .agc_mem_force_pu()
355            .bit(val)
356    });
357
358    bb.bbpd_ctrl()
359        .modify(|_r, w| w.fft_force_pu().bit(val).dc_est_force_pu().bit(val));
360
361    nrx.nrxpd_ctrl().modify(|_, w| {
362        w.rx_rot_force_pu()
363            .bit(val)
364            .vit_force_pu()
365            .bit(val)
366            .demap_force_pu()
367            .bit(val)
368    });
369
370    fe.gen_ctrl().modify(|_, w| w.iq_est_force_pu().bit(val));
371
372    fe2.tx_interp_ctrl()
373        .modify(|_, w| w.tx_inf_force_pu().bit(val));
374
375    syscon.mem_power_up().modify(|_r, w| unsafe {
376        w.sram_power_up()
377            .bits(if val { SYSCON_SRAM_POWER_UP } else { 0 })
378            .rom_power_up()
379            .bits(if val { SYSCON_ROM_POWER_UP } else { 0 })
380    });
381}
382
383impl RtcSleepConfig {
384    /// Configures the RTC for deep sleep mode.
385    pub fn deep() -> Self {
386        // Set up for ultra-low power sleep. Wakeup sources may modify these settings.
387        let mut cfg = Self::default();
388
389        cfg.set_lslp_mem_inf_fpu(false);
390        cfg.set_rtc_mem_inf_follow_cpu(true); // ?
391        cfg.set_rtc_fastmem_pd_en(true);
392        cfg.set_rtc_slowmem_pd_en(true);
393        cfg.set_rtc_peri_pd_en(true);
394        cfg.set_modem_pd_en(true);
395        cfg.set_cpu_pd_en(true);
396        cfg.set_int_8m_pd_en(true);
397
398        cfg.set_dig_peri_pd_en(true);
399        cfg.set_dig_dbias_slp(0); // because of dig_peri_pd_en
400
401        cfg.set_deep_slp(true);
402        cfg.set_wdt_flashboot_mod_en(false);
403        cfg.set_vddsdio_pd_en(true);
404        cfg.set_xtal_fpu(false);
405        cfg.set_deep_slp_reject(true);
406        cfg.set_light_slp_reject(true);
407        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
408
409        // because of dig_peri_pd_en
410        cfg.set_rtc_regulator_fpu(false);
411        cfg.set_dbg_atten_slp(RTC_CNTL_DBG_ATTEN_DEEPSLEEP_ULTRA_LOW);
412
413        // because of xtal_fpu
414        cfg.set_bias_sleep_monitor(true);
415        cfg.set_pd_cur_monitor(true);
416        cfg.set_bias_sleep_slp(true);
417        cfg.set_pd_cur_slp(true);
418
419        cfg
420    }
421
422    pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
423        // settings derived from esp_clk_init -> rtc_init
424        unsafe {
425            let rtc_cntl = LPWR::regs();
426            let syscon = APB_CTRL::regs();
427            let extmem = EXTMEM::regs();
428            let system = SYSTEM::regs();
429
430            rtc_cntl
431                .dig_pwc()
432                .modify(|_, w| w.wifi_force_pd().clear_bit());
433
434            regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
435            regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
436
437            rtc_cntl.ana_conf().modify(|_, w| w.pvtmon_pu().clear_bit());
438
439            rtc_cntl.timer1().modify(|_, w| {
440                w.pll_buf_wait()
441                    .bits(RTC_CNTL_PLL_BUF_WAIT_DEFAULT)
442                    .ck8m_wait()
443                    .bits(RTC_CNTL_CK8M_WAIT_DEFAULT)
444            });
445
446            // Moved from rtc sleep to rtc init to save sleep function running time
447            // set shortest possible sleep time limit
448
449            rtc_cntl
450                .timer5()
451                .modify(|_, w| w.min_slp_val().bits(RTC_CNTL_MIN_SLP_VAL_MIN));
452
453            rtc_cntl.timer3().modify(|_, w| {
454                // set wifi timer
455                w.wifi_powerup_timer().bits(WIFI_POWERUP_CYCLES);
456                // set bt timer
457                w.wifi_wait_timer().bits(WIFI_WAIT_CYCLES);
458                w.bt_powerup_timer().bits(BT_POWERUP_CYCLES);
459                w.bt_wait_timer().bits(BT_WAIT_CYCLES)
460            });
461
462            rtc_cntl.timer6().modify(|_, w| {
463                w.cpu_top_powerup_timer().bits(CPU_TOP_POWERUP_CYCLES);
464                w.cpu_top_wait_timer().bits(CPU_TOP_WAIT_CYCLES)
465            });
466
467            rtc_cntl.timer4().modify(|_, w| {
468                // set rtc peri timer
469                w.powerup_timer().bits(RTC_POWERUP_CYCLES);
470                // set digital wrap timer
471                w.wait_timer().bits(RTC_WAIT_CYCLES);
472                w.dg_wrap_powerup_timer().bits(DG_WRAP_POWERUP_CYCLES);
473                w.dg_wrap_wait_timer().bits(DG_WRAP_WAIT_CYCLES)
474            });
475
476            rtc_cntl.timer6().modify(|_, w| {
477                w.dg_peri_powerup_timer().bits(DG_PERI_POWERUP_CYCLES);
478                w.dg_peri_wait_timer().bits(DG_PERI_WAIT_CYCLES)
479            });
480
481            // Reset RTC bias to default value (needed if waking up from deep sleep)
482            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(RTC_CNTL_DBIAS_1V10);
483            regi2c::I2C_DIG_REG_EXT_RTC_DREG.write_field(RTC_CNTL_DBIAS_1V10);
484
485            // Set the wait time to the default value.
486
487            rtc_cntl.timer2().modify(|_, w| {
488                w.ulpcp_touch_start_wait()
489                    .bits(RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT)
490            });
491
492            // LDO dbias initialization
493            // TODO: this modifies g_rtc_dbias_pvt_non_240m and g_dig_dbias_pvt_non_240m.
494            //       We're using a high enough default but we should read from the efuse.
495            // rtc_set_stored_dbias();
496
497            regi2c::I2C_DIG_REG_EXT_RTC_DREG.write_field(RTC_CNTL_DBIAS_1V25);
498            regi2c::I2C_DIG_REG_EXT_DIG_DREG.write_field(RTC_CNTL_DBIAS_1V25);
499
500            // clear CMMU clock force on
501
502            extmem
503                .cache_mmu_power_ctrl()
504                .modify(|_, w| w.cache_mmu_mem_force_on().clear_bit());
505
506            // clear clkgate force on
507            syscon.clkgate_force_on().write(|w| w.bits(0));
508
509            // clear tag clock force on
510
511            extmem
512                .dcache_tag_power_ctrl()
513                .modify(|_, w| w.dcache_tag_mem_force_on().clear_bit());
514
515            extmem
516                .icache_tag_power_ctrl()
517                .modify(|_, w| w.icache_tag_mem_force_on().clear_bit());
518
519            // clear register clock force on
520            SPI0::regs()
521                .clock_gate()
522                .modify(|_, w| w.clk_en().clear_bit());
523            SPI1::regs()
524                .clock_gate()
525                .modify(|_, w| w.clk_en().clear_bit());
526
527            rtc_cntl
528                .clk_conf()
529                .modify(|_, w| w.ck8m_force_pu().clear_bit());
530
531            rtc_cntl
532                .options0()
533                .modify(|_, w| w.xtl_force_pu().clear_bit());
534
535            rtc_cntl.ana_conf().modify(|_, w| {
536                w
537                    // open sar_i2c protect function to avoid sar_i2c reset when rtc_ldo is low.
538                    // clear i2c_reset_protect pd force, need tested in low temperature.
539                    // NOTE: this bit is written again in esp-idf, but it's not clear why.
540                    .i2c_reset_por_force_pd()
541                    .clear_bit()
542            });
543
544            // cancel bbpll force pu if setting no force power up
545
546            rtc_cntl.options0().modify(|_, w| {
547                w.bbpll_force_pu().clear_bit();
548                w.bbpll_i2c_force_pu().clear_bit();
549                w.bb_i2c_force_pu().clear_bit()
550            });
551
552            // cancel RTC REG force PU
553
554            rtc_cntl.pwc().modify(|_, w| w.force_pu().clear_bit());
555
556            rtc_cntl.rtc().modify(|_, w| {
557                w.regulator_force_pu().clear_bit();
558                w.dboost_force_pu().clear_bit()
559            });
560
561            rtc_cntl.pwc().modify(|_, w| {
562                w.slowmem_force_noiso().clear_bit();
563                w.fastmem_force_noiso().clear_bit()
564            });
565
566            rtc_cntl.rtc().modify(|_, w| w.dboost_force_pd().set_bit());
567
568            // If this mask is enabled, all soc memories cannot enter power down mode
569            // We should control soc memory power down mode from RTC, so we will not touch
570            // this register any more
571
572            system
573                .mem_pd_mask()
574                .modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
575
576            // If this pd_cfg is set to 1, all memory won't enter low power mode during
577            // light sleep If this pd_cfg is set to 0, all memory will enter low
578            // power mode during light sleep
579            rtc_sleep_pu(false);
580
581            rtc_cntl
582                .dig_pwc()
583                .modify(|_, w| w.dg_wrap_force_pu().clear_bit());
584
585            rtc_cntl.dig_iso().modify(|_, w| {
586                w.dg_wrap_force_noiso().clear_bit();
587                w.dg_wrap_force_iso().clear_bit()
588            });
589
590            rtc_cntl.dig_iso().modify(|_, w| {
591                w.wifi_force_noiso().clear_bit();
592                w.wifi_force_iso().clear_bit()
593            });
594
595            rtc_cntl
596                .dig_pwc()
597                .modify(|_, w| w.wifi_force_pu().clear_bit());
598
599            rtc_cntl
600                .dig_iso()
601                .modify(|_, w| w.bt_force_noiso().clear_bit().bt_force_iso().clear_bit());
602
603            rtc_cntl
604                .dig_pwc()
605                .modify(|_, w| w.bt_force_pu().clear_bit());
606
607            rtc_cntl.dig_iso().modify(|_, w| {
608                w.cpu_top_force_noiso().clear_bit();
609                w.cpu_top_force_iso().clear_bit()
610            });
611
612            rtc_cntl
613                .dig_pwc()
614                .modify(|_, w| w.cpu_top_force_pu().clear_bit());
615
616            rtc_cntl.dig_iso().modify(|_, w| {
617                w.dg_peri_force_noiso().clear_bit();
618                w.dg_peri_force_iso().clear_bit()
619            });
620
621            rtc_cntl
622                .dig_pwc()
623                .modify(|_, w| w.dg_peri_force_pu().clear_bit());
624
625            rtc_cntl.pwc().modify(|_, w| {
626                w.force_noiso().clear_bit();
627                w.force_iso().clear_bit();
628                w.force_pu().clear_bit()
629            });
630
631            // if SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0,
632            // the cpu clk will be closed when cpu enter WAITI mode
633
634            system
635                .cpu_per_conf()
636                .modify(|_, w| w.cpu_wait_mode_force_on().clear_bit());
637
638            // cancel digital PADS force no iso
639
640            rtc_cntl.dig_iso().modify(|_, w| {
641                w.dg_pad_force_unhold().clear_bit();
642                w.dg_pad_force_noiso().clear_bit()
643            });
644
645            // force power down modem(wifi and ble) power domain
646
647            rtc_cntl
648                .dig_iso()
649                .modify(|_, w| w.wifi_force_iso().set_bit());
650
651            rtc_cntl
652                .dig_pwc()
653                .modify(|_, w| w.wifi_force_pd().set_bit());
654
655            rtc_cntl.int_ena().write(|w| w.bits(0));
656            rtc_cntl.int_clr().write(|w| w.bits(u32::MAX));
657        }
658    }
659
660    pub(crate) fn apply(&self) {
661        // like esp-idf rtc_sleep_init()
662        let rtc_cntl = LPWR::regs();
663
664        if self.lslp_mem_inf_fpu() {
665            rtc_sleep_pu(true);
666        }
667
668        if self.modem_pd_en() {
669            rtc_cntl.dig_iso().modify(|_, w| {
670                w.wifi_force_noiso().clear_bit();
671                w.wifi_force_iso().clear_bit()
672            });
673
674            rtc_cntl
675                .dig_pwc()
676                .modify(|_, w| w.wifi_force_pu().clear_bit().wifi_pd_en().set_bit());
677        } else {
678            rtc_cntl.dig_pwc().modify(|_, w| w.wifi_pd_en().clear_bit());
679        }
680
681        if self.cpu_pd_en() {
682            rtc_cntl.dig_iso().modify(|_, w| {
683                w.cpu_top_force_noiso().clear_bit();
684                w.cpu_top_force_iso().clear_bit()
685            });
686
687            rtc_cntl
688                .dig_pwc()
689                .modify(|_, w| w.cpu_top_force_pu().clear_bit().cpu_top_pd_en().set_bit());
690        } else {
691            rtc_cntl
692                .dig_pwc()
693                .modify(|_, w| w.cpu_top_pd_en().clear_bit());
694        }
695
696        if self.dig_peri_pd_en() {
697            rtc_cntl.dig_iso().modify(|_, w| {
698                w.dg_peri_force_noiso().clear_bit();
699                w.dg_peri_force_iso().clear_bit()
700            });
701
702            rtc_cntl
703                .dig_pwc()
704                .modify(|_, w| w.dg_peri_force_pu().clear_bit().dg_peri_pd_en().set_bit());
705        } else {
706            rtc_cntl
707                .dig_pwc()
708                .modify(|_, w| w.dg_peri_pd_en().clear_bit());
709        }
710
711        if self.rtc_peri_pd_en() {
712            rtc_cntl.pwc().modify(|_, w| {
713                w.force_noiso().clear_bit();
714                w.force_iso().clear_bit();
715                w.force_pu().clear_bit();
716                w.pd_en().set_bit()
717            });
718        } else {
719            rtc_cntl.pwc().modify(|_, w| w.pd_en().clear_bit());
720        }
721
722        unsafe {
723            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(self.rtc_dbias_slp());
724            regi2c::I2C_DIG_REG_EXT_DIG_DREG_SLEEP.write_field(self.dig_dbias_slp());
725
726            rtc_cntl.bias_conf().modify(|_, w| {
727                w.dbg_atten_deep_slp().bits(self.dbg_atten_slp());
728                w.bias_sleep_deep_slp().bit(self.bias_sleep_slp());
729                w.pd_cur_deep_slp().bit(self.pd_cur_slp());
730                w.dbg_atten_monitor()
731                    .bits(RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT);
732                w.bias_sleep_monitor().bit(self.bias_sleep_monitor());
733                w.pd_cur_monitor().bit(self.pd_cur_monitor())
734            });
735
736            if self.deep_slp() {
737                rtc_cntl
738                    .dig_pwc()
739                    .modify(|_, w| w.dg_wrap_pd_en().set_bit());
740
741                rtc_cntl.ana_conf().modify(|_, w| {
742                    w.ckgen_i2c_pu().clear_bit();
743                    w.pll_i2c_pu().clear_bit();
744                    w.rfrx_pbus_pu().clear_bit();
745                    w.txrf_i2c_pu().clear_bit()
746                });
747
748                rtc_cntl
749                    .options0()
750                    .modify(|_, w| w.bb_i2c_force_pu().clear_bit());
751            } else {
752                rtc_cntl
753                    .regulator_drv_ctrl()
754                    .modify(|_, w| w.dg_vdd_drv_b_slp().bits(0xF));
755
756                rtc_cntl
757                    .dig_pwc()
758                    .modify(|_, w| w.dg_wrap_pd_en().clear_bit());
759            }
760
761            // mem force pu
762
763            rtc_cntl
764                .dig_pwc()
765                .modify(|_, w| w.lslp_mem_force_pu().set_bit());
766
767            rtc_cntl
768                .rtc()
769                .modify(|_, w| w.regulator_force_pu().bit(self.rtc_regulator_fpu()));
770
771            rtc_cntl
772                .clk_conf()
773                .modify(|_, w| w.ck8m_force_pu().bit(!self.int_8m_pd_en()));
774
775            // enable VDDSDIO control by state machine
776
777            rtc_cntl.sdio_conf().modify(|_, w| {
778                w.sdio_force().clear_bit();
779                w.sdio_reg_pd_en().bit(self.vddsdio_pd_en())
780            });
781
782            rtc_cntl.slp_reject_conf().modify(|_, w| {
783                w.deep_slp_reject_en().bit(self.deep_slp_reject());
784                w.light_slp_reject_en().bit(self.light_slp_reject())
785            });
786
787            // Set wait cycle for touch or COCPU after deep sleep and light
788            // sleep.
789
790            rtc_cntl.timer2().modify(|_, w| {
791                w.ulpcp_touch_start_wait()
792                    .bits(RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP)
793            });
794
795            rtc_cntl
796                .options0()
797                .modify(|_, w| w.xtl_force_pu().bit(self.xtal_fpu()));
798
799            rtc_cntl
800                .clk_conf()
801                .modify(|_, w| w.xtal_global_force_nogating().bit(self.xtal_fpu()));
802        }
803    }
804
805    pub(crate) fn start_sleep(&self, wakeup_triggers: WakeTriggers) {
806        unsafe {
807            LPWR::regs()
808                .reset_state()
809                .modify(|_, w| w.procpu_stat_vector_sel().set_bit());
810
811            // set bits for what can wake us up
812            LPWR::regs()
813                .wakeup_state()
814                .modify(|_, w| w.wakeup_ena().bits(wakeup_triggers.0.into()));
815
816            LPWR::regs()
817                .state0()
818                .write(|w| w.sleep_en().set_bit().slp_wakeup().set_bit());
819        }
820    }
821
822    pub(crate) fn finish_sleep(&self) {
823        // In deep sleep mode, we never get here
824        unsafe {
825            LPWR::regs().int_clr().write(|w| {
826                w.slp_reject()
827                    .clear_bit_by_one()
828                    .slp_wakeup()
829                    .clear_bit_by_one()
830            });
831
832            // restore config if it is a light sleep
833            if self.lslp_mem_inf_fpu() {
834                rtc_sleep_pu(true);
835            }
836
837            // Recover default wait cycle for touch or COCPU after wakeup.
838
839            LPWR::regs().timer2().modify(|_, w| {
840                w.ulpcp_touch_start_wait()
841                    .bits(RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT)
842            });
843        }
844    }
845}