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