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