Skip to main content

esp_hal/rtc_cntl/sleep/
esp32c2.rs

1use super::{TimerWakeupSource, WakeSource, WakeTriggers, WakeupLevel};
2use crate::{
3    gpio::{RtcFunction, RtcPinWithResistors},
4    peripherals::{APB_CTRL, BB, EXTMEM, GPIO, IO_MUX, LPWR, SPI0, SPI1, SYSTEM},
5    rtc_cntl::{Rtc, 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 rtc_cntl = LPWR::regs();
100        // TODO: maybe add check to prevent overflow?
101        let ticks = crate::clock::us_to_rtc_ticks(self.duration.as_micros() as u64);
102        // "alarm" time in slow rtc ticks
103        let now = rtc.time_since_boot_raw();
104        let time_in_ticks = now + ticks;
105        unsafe {
106            rtc_cntl
107                .slp_timer0()
108                .write(|w| w.slp_val_lo().bits((time_in_ticks & 0xffffffff) as u32));
109
110            rtc_cntl
111                .int_clr()
112                .write(|w| w.main_timer().clear_bit_by_one());
113
114            rtc_cntl.slp_timer1().write(|w| {
115                w.slp_val_hi().bits(((time_in_ticks >> 32) & 0xffff) as u16);
116                w.main_timer_alarm_en().set_bit()
117            });
118        }
119    }
120}
121
122impl RtcioWakeupSource<'_, '_> {
123    fn apply_pin(&self, pin: &mut dyn RtcPinWithResistors, level: WakeupLevel) {
124        // The pullup/pulldown part is like in gpio_deep_sleep_wakeup_prepare
125        let level = match level {
126            WakeupLevel::High => {
127                pin.rtcio_pullup(false);
128                pin.rtcio_pulldown(true);
129                GPIO_INTR_HIGH_LEVEL
130            }
131            WakeupLevel::Low => {
132                pin.rtcio_pullup(true);
133                pin.rtcio_pulldown(false);
134                GPIO_INTR_LOW_LEVEL
135            }
136        };
137        pin.rtcio_pad_hold(true);
138
139        // apply_wakeup does the same as idf's esp_deep_sleep_enable_gpio_wakeup
140        unsafe {
141            pin.apply_wakeup(true, level);
142        }
143    }
144}
145
146fn isolate_digital_gpio() {
147    // like esp_sleep_isolate_digital_gpio
148    let rtc_cntl = LPWR::regs();
149    let io_mux = IO_MUX::regs();
150    let gpio = GPIO::regs();
151
152    let dig_iso = &rtc_cntl.dig_iso().read();
153    let deep_sleep_hold_is_en =
154        !dig_iso.dg_pad_force_unhold().bit() && dig_iso.dg_pad_autohold_en().bit();
155    if !deep_sleep_hold_is_en {
156        return;
157    }
158
159    // TODO: assert that the task stack is not in external ram
160
161    for pin_num in 0..GPIO_NUM_MAX {
162        let pin_hold = rtc_cntl.dig_pad_hold().read().bits() & (1 << pin_num) != 0;
163        if !pin_hold {
164            // input disable, like gpio_ll_input_disable
165            io_mux.gpio(pin_num).modify(|_, w| w.fun_ie().clear_bit());
166            // output disable, like gpio_ll_output_disable
167            unsafe {
168                gpio.func_out_sel_cfg(pin_num)
169                    .modify(|_, w| w.bits(SIG_GPIO_OUT_IDX));
170            }
171
172            // disable pull-up and pull-down
173            io_mux.gpio(pin_num).modify(|_, w| w.fun_wpu().clear_bit());
174            io_mux.gpio(pin_num).modify(|_, w| w.fun_wpd().clear_bit());
175
176            // make pad work as gpio (otherwise, deep_sleep bottom current will rise)
177            io_mux
178                .gpio(pin_num)
179                .modify(|_, w| unsafe { w.mcu_sel().bits(RtcFunction::Digital as u8) });
180        }
181    }
182}
183
184impl WakeSource for RtcioWakeupSource<'_, '_> {
185    fn apply(
186        &self,
187        _rtc: &Rtc<'_>,
188        triggers: &mut WakeTriggers,
189        sleep_config: &mut RtcSleepConfig,
190    ) {
191        let mut pins = self.pins.borrow_mut();
192
193        if pins.is_empty() {
194            return;
195        }
196
197        triggers.set_gpio(true);
198
199        // If deep sleep is enabled, esp_start_sleep calls
200        // gpio_deep_sleep_wakeup_prepare which sets these pullup and
201        // pulldown values. But later in esp_start_sleep it calls
202        // esp_sleep_isolate_digital_gpio, which disables the pullup and pulldown (but
203        // only if it isn't held).
204        // But it looks like gpio_deep_sleep_wakeup_prepare enables hold for all pins
205        // in the wakeup mask.
206        //
207        // So: all pins in the wake mask should get this treatment here, and all pins
208        // not in the wake mask should get
209        // - pullup and pulldowns disabled
210        // - input and output disabled, and
211        // - their func should get set to GPIO.
212        // But this last block of things gets skipped if hold is disabled globally (see
213        // gpio_ll_deep_sleep_hold_is_en)
214
215        LPWR::regs()
216            .cntl_gpio_wakeup()
217            .modify(|_, w| w.gpio_pin_clk_gate().set_bit());
218
219        LPWR::regs()
220            .ext_wakeup_conf()
221            .modify(|_, w| w.gpio_wakeup_filter().set_bit());
222
223        if sleep_config.deep_slp() {
224            for (pin, level) in pins.iter_mut() {
225                self.apply_pin(*pin, *level);
226            }
227
228            isolate_digital_gpio();
229        }
230
231        // like rtc_cntl_ll_gpio_clear_wakeup_status, as called from
232        // gpio_deep_sleep_wakeup_prepare
233        LPWR::regs()
234            .cntl_gpio_wakeup()
235            .modify(|_, w| w.gpio_wakeup_status_clr().set_bit());
236        LPWR::regs()
237            .cntl_gpio_wakeup()
238            .modify(|_, w| w.gpio_wakeup_status_clr().clear_bit());
239    }
240}
241
242// impl Drop for RtcioWakeupSource<'_, '_> {
243// fn drop(&mut self) {
244// should we have saved the pin configuration first?
245// set pin back to IO_MUX (input_enable and func have no effect when pin is sent
246// to IO_MUX)
247// let mut pins = self.pins.borrow_mut();
248// for (pin, _level) in pins.iter_mut() {
249// pin.rtc_set_config(true, false, RtcFunction::Rtc);
250// }
251// }
252// }
253
254bitfield::bitfield! {
255    #[derive(Clone, Copy)]
256    /// RTC Configuration.
257    pub struct RtcConfig(u32);
258    impl Debug;
259    /// Number of rtc_fast_clk cycles to wait for 8M clock to be ready
260    pub u8, ck8m_wait, set_ck8m_wait: 7, 0;
261    /// Number of rtc_fast_clk cycles to wait for XTAL clock to be ready
262    pub u8, xtal_wait, set_xtal_wait: 15, 8;
263    /// Number of rtc_fast_clk cycles to wait for PLL clock to be ready
264    pub u8, pll_wait, set_pll_wait: 23, 16;
265    /// Perform clock control related initialization.
266    pub clkctl_init, set_clkctl_init: 24;
267    /// Perform power control related initialization.
268    pub pwrctl_init, set_pwrctl_init: 25;
269    /// Force power down RTC_DBOOST
270    pub rtc_dboost_fpd, set_rtc_dboost_fpd: 26;
271    /// Keep the XTAL oscillator powered up in sleep.
272    pub xtal_fpu, set_xtal_fpu: 27;
273    /// Keep the BBPLL oscillator powered up in sleep.
274    pub bbpll_fpu, set_bbpll_fpu: 28;
275    /// Enable clock gating when the CPU is in wait-for-interrupt state.
276    pub cpu_waiti_clk_gate, set_cpu_waiti_clk_gate: 29;
277    /// Calibrate Ocode to make bandgap voltage more precise.
278    pub cali_ocode, set_cali_ocode: 30;
279}
280
281impl Default for RtcConfig {
282    fn default() -> Self {
283        let mut cfg = Self(Default::default());
284        cfg.set_ck8m_wait(RTC_CNTL_CK8M_WAIT_DEFAULT);
285        cfg.set_xtal_wait(RTC_CNTL_XTL_BUF_WAIT_DEFAULT);
286        cfg.set_pll_wait(RTC_CNTL_PLL_BUF_WAIT_DEFAULT);
287        cfg.set_clkctl_init(true);
288        cfg.set_pwrctl_init(true);
289        cfg.set_rtc_dboost_fpd(true);
290        cfg.set_cpu_waiti_clk_gate(true);
291        cfg.set_bbpll_fpu(true);
292        cfg
293    }
294}
295
296bitfield::bitfield! {
297    #[derive(Clone, Copy)]
298    /// Configuration for RTC initialization.
299    pub struct RtcInitConfig(u128);
300    impl Debug;
301    /// Number of cycles required to power up WiFi
302    pub u8, wifi_powerup_cycles, set_wifi_powerup_cycles: 6, 0;
303    /// Number of wait cycles for WiFi to stabilize
304    pub u16, wifi_wait_cycles, set_wifi_wait_cycles: 15, 7;
305    /// Number of cycles required to power up Bluetooth
306    pub u8, bt_powerup_cycles, set_bt_powerup_cycles: 22, 16;
307    /// Number of wait cycles for Bluetooth to stabilize
308    pub u16, bt_wait_cycles, set_bt_wait_cycles: 31, 23;
309    /// Number of cycles required to power up the top CPU
310    pub u8, cpu_top_powerup_cycles, set_cpu_top_powerup_cycles: 38, 32;
311    /// Number of wait cycles for the top CPU to stabilize
312    pub u16, cpu_top_wait_cycles, set_cpu_top_wait_cycles: 47, 39;
313    /// Number of cycles required to power up the digital wrapper
314    pub u8, dg_wrap_powerup_cycles, set_dg_wrap_powerup_cycles: 54, 48;
315    /// Number of wait cycles for the digital wrapper to stabilize
316    pub u16, dg_wrap_wait_cycles, set_dg_wrap_wait_cycles: 63, 55;
317    /// Number of cycles required to power up the digital peripherals
318    pub u8, dg_peri_powerup_cycles, set_dg_peri_powerup_cycles: 70, 64;
319    /// Number of wait cycles for the digital peripherals to stabilize
320    pub u16, dg_peri_wait_cycles, set_dg_peri_wait_cycles: 79, 71;
321}
322
323impl Default for RtcInitConfig {
324    fn default() -> Self {
325        let mut cfg = Self(Default::default());
326        cfg.set_wifi_powerup_cycles(OTHER_BLOCKS_POWERUP);
327        cfg.set_bt_powerup_cycles(OTHER_BLOCKS_POWERUP);
328        cfg.set_cpu_top_powerup_cycles(OTHER_BLOCKS_POWERUP);
329        cfg.set_dg_wrap_powerup_cycles(OTHER_BLOCKS_POWERUP);
330        cfg.set_dg_peri_powerup_cycles(OTHER_BLOCKS_POWERUP);
331        cfg.set_wifi_wait_cycles(OTHER_BLOCKS_WAIT);
332        cfg.set_bt_wait_cycles(OTHER_BLOCKS_WAIT);
333        cfg.set_cpu_top_wait_cycles(OTHER_BLOCKS_WAIT);
334        cfg.set_dg_wrap_wait_cycles(OTHER_BLOCKS_WAIT);
335        cfg.set_dg_peri_wait_cycles(OTHER_BLOCKS_WAIT);
336        cfg
337    }
338}
339
340bitfield::bitfield! {
341    #[derive(Clone, Copy)]
342    /// Configuration for RTC sleep mode.
343    pub struct RtcSleepConfig(u64);
344    impl Debug;
345    /// force normal voltage in sleep mode (digital domain memory)
346    pub lslp_mem_inf_fpu, set_lslp_mem_inf_fpu: 0;
347    /// keep low voltage in sleep mode (even if ULP/touch is used)
348    pub rtc_mem_inf_follow_cpu, set_rtc_mem_inf_follow_cpu: 1;
349    /// power down RTC fast memory
350    pub rtc_fastmem_pd_en, set_rtc_fastmem_pd_en: 2;
351    /// power down RTC slow memory
352    pub rtc_slowmem_pd_en, set_rtc_slowmem_pd_en: 3;
353    /// power down RTC peripherals
354    pub rtc_peri_pd_en, set_rtc_peri_pd_en: 4;
355    /// power down WiFi
356    pub wifi_pd_en, set_wifi_pd_en: 5;
357    /// power down BT
358    pub bt_pd_en, set_bt_pd_en: 6;
359    /// power down CPU, but not restart when lightsleep.
360    pub cpu_pd_en, set_cpu_pd_en: 7;
361    /// Power down Internal 8M oscillator
362    pub int_8m_pd_en, set_int_8m_pd_en: 8;
363    /// power down digital peripherals
364    pub dig_peri_pd_en, set_dig_peri_pd_en: 9;
365    /// power down digital domain
366    pub deep_slp, set_deep_slp: 10;
367    /// enable WDT flashboot mode
368    pub wdt_flashboot_mod_en, set_wdt_flashboot_mod_en: 11;
369    /// set bias for digital domain, in sleep mode
370    pub u8, dig_dbias_slp, set_dig_dbias_slp: 16, 12;
371    /// set bias for RTC domain, in sleep mode
372    pub u8, rtc_dbias_slp, set_rtc_dbias_slp: 21, 17;
373    /// voltage parameter, in sleep mode
374    pub u8, dbg_atten_slp, set_dbg_atten_slp: 25, 22;
375    /// circuit control parameter, in monitor mode
376    pub bias_sleep_monitor, set_bias_sleep_monitor: 26;
377    /// circuit control parameter, in sleep mode
378    pub bias_sleep_slp, set_bias_sleep_slp: 27;
379    /// circuit control parameter, in monitor mode
380    pub pd_cur_slp, set_pd_cur_slp: 28;
381    /// power down VDDSDIO regulator
382    pub vddsdio_pd_en, set_vddsdio_pd_en: 29;
383    /// keep main XTAL powered up in sleep
384    pub xtal_fpu, set_xtal_fpu: 30;
385    /// keep rtc regulator powered up in sleep
386    pub rtc_regulator_fpu, set_rtc_regulator_fpu: 31;
387    /// enable deep sleep reject
388    pub deep_slp_reject, set_deep_slp_reject: 32;
389    /// enable light sleep reject
390    pub light_slp_reject, set_light_slp_reject: 33;
391}
392
393impl Default for RtcSleepConfig {
394    fn default() -> Self {
395        let mut cfg = Self(Default::default());
396        cfg.set_deep_slp_reject(true);
397        cfg.set_light_slp_reject(true);
398        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
399        cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_1V10);
400        cfg
401    }
402}
403
404const DR_REG_NRX_BASE: u32 = 0x6001CC00;
405const DR_REG_FE_BASE: u32 = 0x60006000;
406const DR_REG_FE2_BASE: u32 = 0x60005000;
407
408const NRXPD_CTRL: u32 = DR_REG_NRX_BASE + 0x00d4;
409const FE_GEN_CTRL: u32 = DR_REG_FE_BASE + 0x0090;
410const FE2_TX_INTERP_CTRL: u32 = DR_REG_FE2_BASE + 0x00f0;
411
412const SYSCON_SRAM_POWER_UP: u8 = 0x0000000F;
413const SYSCON_ROM_POWER_UP: u8 = 0x00000003;
414
415const NRX_RX_ROT_FORCE_PU: u32 = 1 << 5;
416const NRX_VIT_FORCE_PU: u32 = 1 << 3;
417const NRX_DEMAP_FORCE_PU: u32 = 1 << 1;
418
419const FE_IQ_EST_FORCE_PU: u32 = 1 << 5;
420const FE2_TX_INF_FORCE_PU: u32 = 1 << 10;
421
422fn modify_register(reg: u32, mask: u32, value: u32) {
423    let reg = reg as *mut u32;
424
425    unsafe { reg.write_volatile((reg.read_volatile() & !mask) | value) };
426}
427
428fn register_modify_bits(reg: u32, bits: u32, set: bool) {
429    if set {
430        modify_register(reg, bits, bits);
431    } else {
432        modify_register(reg, bits, 0);
433    }
434}
435
436fn rtc_sleep_pu(val: bool) {
437    LPWR::regs()
438        .dig_pwc()
439        .modify(|_, w| w.lslp_mem_force_pu().bit(val));
440
441    APB_CTRL::regs().front_end_mem_pd().modify(|_r, w| {
442        w.dc_mem_force_pu()
443            .bit(val)
444            .pbus_mem_force_pu()
445            .bit(val)
446            .agc_mem_force_pu()
447            .bit(val)
448    });
449
450    BB::regs()
451        .bbpd_ctrl()
452        .modify(|_r, w| w.fft_force_pu().bit(val).dc_est_force_pu().bit(val));
453
454    register_modify_bits(
455        NRXPD_CTRL,
456        NRX_RX_ROT_FORCE_PU | NRX_VIT_FORCE_PU | NRX_DEMAP_FORCE_PU,
457        val,
458    );
459
460    register_modify_bits(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, val);
461
462    register_modify_bits(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, val);
463
464    APB_CTRL::regs().mem_power_up().modify(|_r, w| unsafe {
465        w.sram_power_up()
466            .bits(if val { SYSCON_SRAM_POWER_UP } else { 0 });
467        w.rom_power_up()
468            .bits(if val { SYSCON_ROM_POWER_UP } else { 0 })
469    });
470}
471
472impl RtcSleepConfig {
473    /// Configures the RTC for deep sleep mode.
474    pub fn deep() -> Self {
475        // Set up for ultra-low power sleep. Wakeup sources may modify these settings.
476        let mut cfg = Self::default();
477
478        cfg.set_lslp_mem_inf_fpu(false);
479        cfg.set_rtc_mem_inf_follow_cpu(true); // ?
480        cfg.set_rtc_fastmem_pd_en(true);
481        cfg.set_rtc_slowmem_pd_en(true);
482        cfg.set_rtc_peri_pd_en(true);
483        cfg.set_wifi_pd_en(true);
484        cfg.set_bt_pd_en(true);
485        cfg.set_cpu_pd_en(true);
486        cfg.set_int_8m_pd_en(true);
487
488        cfg.set_dig_peri_pd_en(true);
489        cfg.set_dig_dbias_slp(0); // because of dig_peri_pd_en
490
491        cfg.set_deep_slp(true);
492        cfg.set_wdt_flashboot_mod_en(false);
493        cfg.set_vddsdio_pd_en(true);
494        cfg.set_xtal_fpu(false);
495        cfg.set_deep_slp_reject(true);
496        cfg.set_light_slp_reject(true);
497        cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
498
499        // because of dig_peri_pd_en
500        cfg.set_rtc_regulator_fpu(false);
501        cfg.set_dbg_atten_slp(RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT);
502
503        // because of xtal_fpu
504        cfg.set_bias_sleep_monitor(true);
505        cfg.set_bias_sleep_slp(true);
506        cfg.set_pd_cur_slp(true);
507
508        cfg
509    }
510
511    pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
512        let cfg = RtcConfig::default();
513
514        // settings derived from esp_clk_init -> rtc_init
515        let rtc_cntl = LPWR::regs();
516        let extmem = EXTMEM::regs();
517        let system = SYSTEM::regs();
518
519        regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
520        regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
521
522        unsafe {
523            rtc_cntl.timer1().modify(|_, w| {
524                w.pll_buf_wait().bits(cfg.pll_wait());
525                w.ck8m_wait().bits(cfg.ck8m_wait())
526            });
527
528            // Moved from rtc sleep to rtc init to save sleep function running time
529            // set shortest possible sleep time limit
530
531            rtc_cntl
532                .timer5()
533                .modify(|_, w| w.min_slp_val().bits(RTC_CNTL_MIN_SLP_VAL_MIN));
534
535            // TODO: something about cali_ocode
536
537            // Reset RTC bias to default value (needed if waking up from deep sleep)
538            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(RTC_CNTL_DBIAS_1V10);
539
540            // LDO dbias initialization
541            // TODO: this modifies g_rtc_dbias_pvt_non_240m and g_dig_dbias_pvt_non_240m.
542            //       We're using a high enough default but we should read from the efuse.
543            // set_rtc_dig_dbias();
544
545            regi2c::I2C_DIG_REG_EXT_RTC_DREG.write_field(RTC_CNTL_DBIAS_1V25);
546            regi2c::I2C_DIG_REG_EXT_DIG_DREG.write_field(RTC_CNTL_DBIAS_1V25);
547
548            if cfg.clkctl_init() {
549                // clear CMMU clock force on
550
551                extmem
552                    .cache_mmu_power_ctrl()
553                    .modify(|_, w| w.cache_mmu_mem_force_on().clear_bit());
554                // clear tag clock force on
555
556                extmem
557                    .icache_tag_power_ctrl()
558                    .modify(|_, w| w.icache_tag_mem_force_on().clear_bit());
559
560                // clear register clock force on
561                SPI0::regs()
562                    .clock_gate()
563                    .modify(|_, w| w.clk_en().clear_bit());
564                SPI1::regs()
565                    .clock_gate()
566                    .modify(|_, w| w.clk_en().clear_bit());
567            }
568
569            if cfg.pwrctl_init() {
570                rtc_cntl
571                    .clk_conf()
572                    .modify(|_, w| w.ck8m_force_pu().clear_bit());
573
574                rtc_cntl
575                    .options0()
576                    .modify(|_, w| w.xtl_force_pu().bit(cfg.xtal_fpu() || cfg.bbpll_fpu()));
577
578                // cancel bbpll force pu if setting no force power up
579
580                rtc_cntl.options0().modify(|_, w| {
581                    w.bbpll_force_pu().bit(cfg.bbpll_fpu());
582                    w.bbpll_i2c_force_pu().bit(cfg.bbpll_fpu());
583                    w.bb_i2c_force_pu().bit(cfg.bbpll_fpu())
584                });
585
586                rtc_cntl
587                    .rtc_cntl()
588                    .modify(|_, w| w.regulator_force_pu().clear_bit());
589
590                // If this mask is enabled, all soc memories cannot enter power down mode
591                // We should control soc memory power down mode from RTC, so we will not touch
592                // this register any more
593
594                system
595                    .mem_pd_mask()
596                    .modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
597
598                // If this pd_cfg is set to 1, all memory won't enter low power mode during
599                // light sleep If this pd_cfg is set to 0, all memory will enter low
600                // power mode during light sleep
601                rtc_sleep_pu(false);
602
603                rtc_cntl
604                    .dig_pwc()
605                    .modify(|_, w| w.dg_wrap_force_pu().clear_bit());
606
607                rtc_cntl
608                    .dig_iso()
609                    .modify(|_, w| w.dg_wrap_force_noiso().clear_bit());
610
611                // if SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0 , the cpu clk will be closed when cpu
612                // enter WAITI mode
613
614                system
615                    .cpu_per_conf()
616                    .modify(|_, w| w.cpu_wait_mode_force_on().bit(!cfg.cpu_waiti_clk_gate()));
617
618                // cancel digital PADS force no iso
619
620                rtc_cntl.dig_iso().modify(|_, w| {
621                    w.dg_pad_force_unhold().clear_bit();
622                    w.dg_pad_force_noiso().clear_bit()
623                });
624            }
625
626            rtc_cntl.int_ena().write(|w| w.bits(0));
627            rtc_cntl.int_clr().write(|w| w.bits(u32::MAX));
628
629            regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(1);
630        }
631    }
632
633    pub(crate) fn apply(&self) {
634        // like esp-idf rtc_sleep_init()
635        let rtc_cntl = LPWR::regs();
636
637        if self.lslp_mem_inf_fpu() {
638            rtc_sleep_pu(true);
639        }
640
641        unsafe {
642            assert!(!self.pd_cur_slp() || self.bias_sleep_slp());
643
644            regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(self.rtc_dbias_slp());
645            regi2c::I2C_DIG_REG_EXT_DIG_DREG_SLEEP.write_field(self.dig_dbias_slp());
646
647            rtc_cntl.bias_conf().modify(|_, w| {
648                w.dbg_atten_monitor()
649                    .bits(RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT);
650                // We have config values for this in self, so I don't know why we're setting
651                // hardcoded defaults for these next two. It's what IDF does...
652                w.bias_sleep_monitor().bit(RTC_CNTL_BIASSLP_MONITOR_DEFAULT);
653                w.pd_cur_monitor().bit(RTC_CNTL_PD_CUR_MONITOR_DEFAULT)
654            });
655
656            rtc_cntl.bias_conf().modify(|_, w| {
657                w.dbg_atten_deep_slp().bits(self.dbg_atten_slp());
658                w.bias_sleep_deep_slp().bit(self.bias_sleep_slp());
659                w.pd_cur_deep_slp().bit(self.pd_cur_slp())
660            });
661
662            if self.deep_slp() {
663                regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(0);
664
665                rtc_cntl
666                    .dig_pwc()
667                    .modify(|_, w| w.dg_wrap_pd_en().set_bit());
668
669                rtc_cntl.ana_conf().modify(|_, w| {
670                    w.ckgen_i2c_pu().clear_bit();
671                    w.pll_i2c_pu().clear_bit();
672                    w.rfrx_pbus_pu().clear_bit();
673                    w.txrf_i2c_pu().clear_bit()
674                });
675
676                rtc_cntl
677                    .options0()
678                    .modify(|_, w| w.bb_i2c_force_pu().clear_bit());
679            } else {
680                rtc_cntl.bias_conf().modify(|_, w| {
681                    w.dg_vdd_drv_b_slp_en().set_bit();
682                    w.dg_vdd_drv_b_slp().bits(RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT)
683                });
684
685                rtc_cntl
686                    .dig_pwc()
687                    .modify(|_, w| w.dg_wrap_pd_en().clear_bit());
688            }
689
690            rtc_cntl
691                .rtc_cntl()
692                .modify(|_, w| w.regulator_force_pu().bit(self.rtc_regulator_fpu()));
693
694            rtc_cntl.clk_conf().modify(|_, w| {
695                w.ck8m_force_pu().bit(!self.int_8m_pd_en());
696                w.ck8m_force_nogating().bit(!self.int_8m_pd_en())
697            });
698
699            // enable VDDSDIO control by state machine
700
701            rtc_cntl.dig_pwc().modify(|_, w| {
702                w.vdd_spi_pwr_force().clear_bit();
703                w.vdd_spi_pd_en().bit(self.vddsdio_pd_en())
704            });
705
706            rtc_cntl.slp_reject_conf().modify(|_, w| {
707                w.deep_slp_reject_en().bit(self.deep_slp_reject());
708                w.light_slp_reject_en().bit(self.light_slp_reject())
709            });
710
711            rtc_cntl
712                .options0()
713                .modify(|_, w| w.xtl_force_pu().bit(self.xtal_fpu()));
714
715            rtc_cntl
716                .clk_conf()
717                .modify(|_, w| w.xtal_global_force_nogating().bit(self.xtal_fpu()));
718        }
719    }
720
721    pub(crate) fn start_sleep(&self, wakeup_triggers: WakeTriggers) {
722        // set bits for what can wake us up
723        LPWR::regs()
724            .wakeup_state()
725            .modify(|_, w| unsafe { w.wakeup_ena().bits(wakeup_triggers.0.into()) });
726
727        LPWR::regs()
728            .state0()
729            .write(|w| w.sleep_en().set_bit().slp_wakeup().set_bit());
730    }
731
732    pub(crate) fn finish_sleep(&self) {
733        // In deep sleep mode, we never get here
734
735        LPWR::regs().int_clr().write(|w| {
736            w.slp_reject().clear_bit_by_one();
737            w.slp_wakeup().clear_bit_by_one()
738        });
739
740        // restore config if it is a light sleep
741        if self.lslp_mem_inf_fpu() {
742            rtc_sleep_pu(true);
743        }
744    }
745}