esp_hal/rtc_cntl/sleep/
esp32c3.rs

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