Lines
38.89 %
Functions
100 %
use super::SleepKind;
use crate::{
peripherals::{APB_CTRL, BB, EXTMEM, FE, FE2, LPWR, NRX, SPI0, SPI1, SYSTEM},
rtc_cntl::Rtc,
soc::regi2c,
};
// Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP,
// RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values.
// Valid if RTC_CNTL_DBG_ATTEN is 0.
/// Digital bias voltage level of 0.90V.
pub const RTC_CNTL_DBIAS_0V90: u8 = 13;
/// Digital bias voltage level of 0.95V.
pub const RTC_CNTL_DBIAS_0V95: u8 = 16;
/// Digital bias voltage level of 1.00V.
pub const RTC_CNTL_DBIAS_1V00: u8 = 18;
/// Digital bias voltage level of 1.05V.
pub const RTC_CNTL_DBIAS_1V05: u8 = 20;
/// Digital bias voltage level of 1.10V.
pub const RTC_CNTL_DBIAS_1V10: u8 = 23;
/// Digital bias voltage level of 1.15V.
pub const RTC_CNTL_DBIAS_1V15: u8 = 25;
/// Digital bias voltage level of 1.20V.
pub const RTC_CNTL_DBIAS_1V20: u8 = 28;
/// Digital bias voltage level of 1.25V.
pub const RTC_CNTL_DBIAS_1V25: u8 = 30;
/// Digital bias voltage level of approximately 1.34V.
pub const RTC_CNTL_DBIAS_1V30: u8 = 31;
/// Default attenuation setting during light sleep, with a voltage drop.
pub const RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT: u8 = 5;
/// No attenuation (no voltage drop) during light sleep.
pub const RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP: u8 = 0;
/// Default attenuation setting during deep sleep, with maximum voltage drop.
pub const RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT: u8 = 15;
/// No attenuation (no voltage drop) during deep sleep.
pub const RTC_CNTL_DBG_ATTEN_DEEPSLEEP_NODROP: u8 = 0;
/// Default bias setting during sleep mode.
pub const RTC_CNTL_BIASSLP_SLEEP_DEFAULT: u8 = 1;
/// Keeps the bias for ultra-low power sleep mode always on.
pub const RTC_CNTL_BIASSLP_SLEEP_ON: u8 = 0;
/// Default power-down current setting during sleep mode.
pub const RTC_CNTL_PD_CUR_SLEEP_DEFAULT: u8 = 1;
/// Keeps the power-down current setting for sleep mode always on.
pub const RTC_CNTL_PD_CUR_SLEEP_ON: u8 = 0;
/// Default driver bias setting for the digital domain during sleep mode.
pub const RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT: u8 = 254;
/// Default debug attenuation setting for the monitor mode.
pub const RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT: u8 = 0;
/// Default bias setting for sleep mode in the monitor mode.
pub const RTC_CNTL_BIASSLP_MONITOR_DEFAULT: bool = false;
/// Default power-down current setting for the monitor mode.
pub const RTC_CNTL_PD_CUR_MONITOR_DEFAULT: bool = false;
/// Default number of cycles to wait for the PLL buffer to stabilize.
pub const RTC_CNTL_PLL_BUF_WAIT_DEFAULT: u8 = 20;
/// Default number of cycles to wait for the XTL buffer to stabilize.
pub const RTC_CNTL_XTL_BUF_WAIT_DEFAULT: u8 = 100;
/// Default number of cycles to wait for the internal 8 MHz clock to stabilize.
pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
/// Default number of cycles required to enable the internal 8 MHz clock.
pub const RTC_CK8M_ENABLE_WAIT_DEFAULT: u8 = 5;
/// Minimum number of cycles for sleep duration.
pub const RTC_CNTL_MIN_SLP_VAL_MIN: u8 = 2;
/// Power-up cycles for other hardware blocks.
pub const OTHER_BLOCKS_POWERUP: u8 = 1;
/// Waits cycles for other hardware blocks to stabilize.
pub const OTHER_BLOCKS_WAIT: u16 = 1;
/// Disables GPIO interrupt.
pub const GPIO_INTR_DISABLE: u8 = 0;
/// Sets GPIO interrupt to trigger on a low level signal.
pub const GPIO_INTR_LOW_LEVEL: u8 = 4;
/// Sets GPIO interrupt to trigger on a high level signal.
pub const GPIO_INTR_HIGH_LEVEL: u8 = 5;
/// Specifies the function configuration for GPIO pins.
pub const PIN_FUNC_GPIO: u8 = 1;
/// Index for signaling GPIO output.
pub const SIG_GPIO_OUT_IDX: u32 = 128;
/// Maximum number of GPIO pins supported.
pub const GPIO_NUM_MAX: usize = 22;
bitfield::bitfield! {
#[derive(Clone, Copy)]
/// RTC Configuration.
pub struct RtcConfig(u32);
impl Debug;
/// Number of rtc_fast_clk cycles to wait for 8M clock to be ready
pub u8, ck8m_wait, set_ck8m_wait: 7, 0;
/// Number of rtc_fast_clk cycles to wait for XTAL clock to be ready
pub u8, xtal_wait, set_xtal_wait: 15, 8;
/// Number of rtc_fast_clk cycles to wait for PLL clock to be ready
pub u8, pll_wait, set_pll_wait: 23, 16;
/// Performs clock control related initialization.
pub clkctl_init, set_clkctl_init: 24;
/// Performs power control related initialization.
pub pwrctl_init, set_pwrctl_init: 25;
/// Forces power-down of `RTC_DBOOST`.
pub rtc_dboost_fpd, set_rtc_dboost_fpd: 26;
/// Keeps the XTAL oscillator powered up in sleep.
pub xtal_fpu, set_xtal_fpu: 27;
/// Keeps the BBPLL oscillator powered up in sleep.
pub bbpll_fpu, set_bbpll_fpu: 28;
/// Enables clock gating when the CPU is in wait-for-interrupt state.
pub cpu_waiti_clk_gate, set_cpu_waiti_clk_gate: 29;
/// Calibrates Ocode to make bandgap voltage more precise.
pub cali_ocode, set_cali_ocode: 30;
}
impl Default for RtcConfig {
fn default() -> Self {
let mut cfg = Self(Default::default());
cfg.set_ck8m_wait(RTC_CNTL_CK8M_WAIT_DEFAULT);
cfg.set_xtal_wait(RTC_CNTL_XTL_BUF_WAIT_DEFAULT);
cfg.set_pll_wait(RTC_CNTL_PLL_BUF_WAIT_DEFAULT);
cfg.set_clkctl_init(true);
cfg.set_pwrctl_init(true);
cfg.set_rtc_dboost_fpd(true);
cfg.set_cpu_waiti_clk_gate(true);
cfg
/// Configuration for RTC initialization.
pub struct RtcInitConfig(u128);
/// Number of cycles required to power up WiFi
pub u8, wifi_powerup_cycles, set_wifi_powerup_cycles: 6, 0;
/// Number of wait cycles for WiFi to stabilize
pub u16, wifi_wait_cycles, set_wifi_wait_cycles: 15, 7;
/// Number of cycles required to power up Bluetooth
pub u8, bt_powerup_cycles, set_bt_powerup_cycles: 22, 16;
/// Number of wait cycles for Bluetooth to stabilize
pub u16, bt_wait_cycles, set_bt_wait_cycles: 31, 23;
/// Number of cycles required to power up the top CPU
pub u8, cpu_top_powerup_cycles, set_cpu_top_powerup_cycles: 38, 32;
/// Number of wait cycles for the top CPU to stabilize
pub u16, cpu_top_wait_cycles, set_cpu_top_wait_cycles: 47, 39;
/// Number of cycles required to power up the digital wrapper
pub u8, dg_wrap_powerup_cycles, set_dg_wrap_powerup_cycles: 54, 48;
/// Number of wait cycles for the digital wrapper to stabilize
pub u16, dg_wrap_wait_cycles, set_dg_wrap_wait_cycles: 63, 55;
/// Number of cycles required to power up the digital peripherals
pub u8, dg_peri_powerup_cycles, set_dg_peri_powerup_cycles: 70, 64;
/// Number of wait cycles for the digital peripherals to stabilize
pub u16, dg_peri_wait_cycles, set_dg_peri_wait_cycles: 79, 71;
impl Default for RtcInitConfig {
cfg.set_wifi_powerup_cycles(OTHER_BLOCKS_POWERUP);
cfg.set_bt_powerup_cycles(OTHER_BLOCKS_POWERUP);
cfg.set_cpu_top_powerup_cycles(OTHER_BLOCKS_POWERUP);
cfg.set_dg_wrap_powerup_cycles(OTHER_BLOCKS_POWERUP);
cfg.set_dg_peri_powerup_cycles(OTHER_BLOCKS_POWERUP);
cfg.set_wifi_wait_cycles(OTHER_BLOCKS_WAIT);
cfg.set_bt_wait_cycles(OTHER_BLOCKS_WAIT);
cfg.set_cpu_top_wait_cycles(OTHER_BLOCKS_WAIT);
cfg.set_dg_wrap_wait_cycles(OTHER_BLOCKS_WAIT);
cfg.set_dg_peri_wait_cycles(OTHER_BLOCKS_WAIT);
/// Configuration for RTC sleep mode.
pub struct RtcSleepConfig(u64);
/// force normal voltage in sleep mode (digital domain memory)
pub lslp_mem_inf_fpu, set_lslp_mem_inf_fpu: 0;
/// keep low voltage in sleep mode (even if ULP/touch is used)
pub rtc_mem_inf_follow_cpu, set_rtc_mem_inf_follow_cpu: 1;
/// power down RTC fast memory
pub rtc_fastmem_pd_en, set_rtc_fastmem_pd_en: 2;
/// power down RTC slow memory
pub rtc_slowmem_pd_en, set_rtc_slowmem_pd_en: 3;
/// power down RTC peripherals
pub rtc_peri_pd_en, set_rtc_peri_pd_en: 4;
/// power down WiFi
pub wifi_pd_en, set_wifi_pd_en: 5;
/// power down BT
pub bt_pd_en, set_bt_pd_en: 6;
/// power down CPU, but not restart when lightsleep.
///
/// Crate-private, because a light sleep derives this from the installed retention memory. A
/// CPU power-down without retention loses the CPU state.
pub(crate) cpu_pd_en, set_cpu_pd_en: 7;
/// Powers down Internal 8M oscillator.
pub int_8m_pd_en, set_int_8m_pd_en: 8;
/// power down digital peripherals
pub dig_peri_pd_en, set_dig_peri_pd_en: 9;
/// power down digital domain
pub deep_slp, set_deep_slp: 10;
/// enable WDT flashboot mode
pub wdt_flashboot_mod_en, set_wdt_flashboot_mod_en: 11;
/// set bias for digital domain, in sleep mode
pub u8, dig_dbias_slp, set_dig_dbias_slp: 16, 12;
/// set bias for RTC domain, in sleep mode
pub u8, rtc_dbias_slp, set_rtc_dbias_slp: 21, 17;
/// voltage parameter, in sleep mode
pub u8, dbg_atten_slp, set_dbg_atten_slp: 25, 22;
/// circuit control parameter, in monitor mode
pub bias_sleep_monitor, set_bias_sleep_monitor: 26;
/// circuit control parameter, in sleep mode
pub bias_sleep_slp, set_bias_sleep_slp: 27;
pub pd_cur_slp, set_pd_cur_slp: 28;
/// power down VDDSDIO regulator
pub vddsdio_pd_en, set_vddsdio_pd_en: 29;
/// keep main XTAL powered up in sleep
pub xtal_fpu, set_xtal_fpu: 30;
/// keep rtc regulator powered up in sleep
pub rtc_regulator_fpu, set_rtc_regulator_fpu: 31;
/// enable deep sleep reject
pub deep_slp_reject, set_deep_slp_reject: 32;
/// enable light sleep reject
pub light_slp_reject, set_light_slp_reject: 33;
impl Default for RtcSleepConfig {
cfg.set_deep_slp_reject(true);
cfg.set_light_slp_reject(true);
cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_1V10);
// This is the light-sleep config. The main XTAL is powered down in sleep
// (`xtal_fpu` stays false), so the analog regulator/bias must use the
// same XTAL-down settings that `deep()` applies "because of xtal_fpu".
cfg.set_rtc_regulator_fpu(true);
cfg.set_bias_sleep_monitor(true);
cfg.set_bias_sleep_slp(true);
cfg.set_pd_cur_slp(true);
const SYSCON_SRAM_POWER_UP: u8 = 0x0000000F;
const SYSCON_ROM_POWER_UP: u8 = 0x00000003;
fn rtc_sleep_pu(val: bool) {
LPWR::regs()
.dig_pwc()
.modify(|_, w| w.lslp_mem_force_pu().bit(val).fastmem_force_lpu().bit(val));
APB_CTRL::regs().front_end_mem_pd().modify(|_r, w| {
w.dc_mem_force_pu().bit(val);
w.pbus_mem_force_pu().bit(val);
w.agc_mem_force_pu().bit(val)
});
BB::regs()
.bbpd_ctrl()
.modify(|_r, w| w.fft_force_pu().bit(val).dc_est_force_pu().bit(val));
NRX::regs().nrxpd_ctrl().modify(|_, w| {
w.rx_rot_force_pu().bit(val);
w.vit_force_pu().bit(val);
w.demap_force_pu().bit(val)
FE::regs()
.gen_ctrl()
.modify(|_, w| w.iq_est_force_pu().bit(val));
FE2::regs()
.tx_interp_ctrl()
.modify(|_, w| w.tx_inf_force_pu().bit(val));
APB_CTRL::regs().mem_power_up().modify(|_r, w| unsafe {
w.sram_power_up()
.bits(if val { SYSCON_SRAM_POWER_UP } else { 0 });
w.rom_power_up()
.bits(if val { SYSCON_ROM_POWER_UP } else { 0 })
impl RtcSleepConfig {
/// Configures the RTC for deep sleep mode.
pub fn deep() -> Self {
// Set up for ultra-low power sleep. Wakeup sources may modify these settings.
let mut cfg = Self::default();
cfg.set_lslp_mem_inf_fpu(false);
cfg.set_rtc_mem_inf_follow_cpu(true); // ?
cfg.set_rtc_fastmem_pd_en(true);
cfg.set_rtc_slowmem_pd_en(true);
cfg.set_rtc_peri_pd_en(true);
cfg.set_wifi_pd_en(true);
cfg.set_bt_pd_en(true);
cfg.set_cpu_pd_en(true);
cfg.set_int_8m_pd_en(true);
cfg.set_dig_peri_pd_en(true);
cfg.set_dig_dbias_slp(0); // because of dig_peri_pd_en
cfg.set_deep_slp(true);
cfg.set_wdt_flashboot_mod_en(false);
cfg.set_vddsdio_pd_en(true);
cfg.set_xtal_fpu(false);
// because of dig_peri_pd_en
cfg.set_rtc_regulator_fpu(false);
cfg.set_dbg_atten_slp(RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT);
// because of xtal_fpu
pub(crate) fn is_deep_sleep(&self) -> bool {
self.deep_slp()
pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
self.set_deep_slp(kind == SleepKind::Deep);
pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
let cfg = RtcConfig::default();
// settings derived from esp_clk_init -> rtc_init
let rtc_cntl = LPWR::regs();
let extmem = EXTMEM::regs();
let system = SYSTEM::regs();
unsafe {
rtc_cntl
.modify(|_, w| w.wifi_force_pd().clear_bit());
regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
rtc_cntl.ana_conf().modify(|_, w| w.pvtmon_pu().clear_bit());
rtc_cntl.timer1().modify(|_, w| {
w.pll_buf_wait().bits(cfg.pll_wait());
w.ck8m_wait().bits(cfg.ck8m_wait())
// Moved from rtc sleep to rtc init to save sleep function running time
// set shortest possible sleep time limit
.timer5()
.modify(|_, w| w.min_slp_val().bits(RTC_CNTL_MIN_SLP_VAL_MIN));
let init_cfg = RtcInitConfig::default();
rtc_cntl.timer3().modify(|_, w| {
// set wifi timer
w.wifi_powerup_timer().bits(init_cfg.wifi_powerup_cycles());
w.wifi_wait_timer().bits(init_cfg.wifi_wait_cycles());
// set bt timer
w.bt_powerup_timer().bits(init_cfg.bt_powerup_cycles());
w.bt_wait_timer().bits(init_cfg.bt_wait_cycles())
rtc_cntl.timer4().modify(|_, w| {
w.cpu_top_powerup_timer()
.bits(init_cfg.cpu_top_powerup_cycles());
w.cpu_top_wait_timer().bits(init_cfg.cpu_top_wait_cycles());
// set digital wrap timer
w.dg_wrap_powerup_timer()
.bits(init_cfg.dg_wrap_powerup_cycles());
w.dg_wrap_wait_timer().bits(init_cfg.dg_wrap_wait_cycles())
rtc_cntl.timer6().modify(|_, w| {
w.dg_peri_powerup_timer()
.bits(init_cfg.dg_peri_powerup_cycles());
w.dg_peri_wait_timer().bits(init_cfg.dg_peri_wait_cycles())
// TODO: something about cali_ocode
// Reset RTC bias to default value (needed if waking up from deep sleep)
regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(RTC_CNTL_DBIAS_1V10);
// LDO dbias initialization
// TODO: this modifies g_rtc_dbias_pvt_non_240m and g_dig_dbias_pvt_non_240m.
// We're using a high enough default but we should read from the efuse.
// set_rtc_dig_dbias();
regi2c::I2C_DIG_REG_EXT_RTC_DREG.write_field(RTC_CNTL_DBIAS_1V25);
regi2c::I2C_DIG_REG_EXT_DIG_DREG.write_field(RTC_CNTL_DBIAS_1V25);
if cfg.clkctl_init() {
// clear CMMU clock force on
extmem
.cache_mmu_power_ctrl()
.modify(|_, w| w.cache_mmu_mem_force_on().clear_bit());
// clear tag clock force on
.icache_tag_power_ctrl()
.modify(|_, w| w.icache_tag_mem_force_on().clear_bit());
// clear register clock force on
SPI0::regs()
.clock_gate()
.modify(|_, w| w.clk_en().clear_bit());
SPI1::regs()
if cfg.pwrctl_init() {
.clk_conf()
.modify(|_, w| w.ck8m_force_pu().clear_bit());
.options0()
.modify(|_, w| w.xtl_force_pu().bit(cfg.xtal_fpu() || cfg.bbpll_fpu()));
// force pd APLL
.ana_conf()
.modify(|_, w| w.plla_force_pu().clear_bit().plla_force_pd().set_bit());
rtc_cntl.ana_conf().modify(|_, w| {
w
// open sar_i2c protect function to avoid sar_i2c reset when rtc_ldo is low.
.reset_por_force_pd()
.clear_bit()
// cancel bbpll force pu if setting no force power up
rtc_cntl.options0().modify(|_, w| {
w.bbpll_force_pu().bit(cfg.bbpll_fpu());
w.bbpll_i2c_force_pu().bit(cfg.bbpll_fpu());
w.bb_i2c_force_pu().bit(cfg.bbpll_fpu())
rtc_cntl.rtc_cntl().modify(|_, w| {
w.regulator_force_pu().clear_bit();
w.dboost_force_pu().clear_bit();
w.dboost_force_pd().bit(cfg.rtc_dboost_fpd())
// If this mask is enabled, all soc memories cannot enter power down mode
// We should control soc memory power down mode from RTC, so we will not touch
// this register any more
system
.mem_pd_mask()
.modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
// If this pd_cfg is set to 1, all memory won't enter low power mode during
// light sleep If this pd_cfg is set to 0, all memory will enter low
// power mode during light sleep
rtc_sleep_pu(false);
rtc_cntl.dig_pwc().modify(|_, w| {
w.dg_wrap_force_pu().clear_bit();
w.wifi_force_pu().clear_bit();
w.bt_force_pu().clear_bit();
w.cpu_top_force_pu().clear_bit();
w.dg_peri_force_pu().clear_bit()
rtc_cntl.dig_iso().modify(|_, w| {
w.dg_wrap_force_noiso().clear_bit();
w.wifi_force_noiso().clear_bit();
w.bt_force_noiso().clear_bit();
w.cpu_top_force_noiso().clear_bit();
w.dg_peri_force_noiso().clear_bit()
// if SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0 , the cpu clk will be closed when cpu
// enter WAITI mode
.cpu_per_conf()
.modify(|_, w| w.cpu_wait_mode_force_on().bit(!cfg.cpu_waiti_clk_gate()));
// cancel digital PADS force no iso
w.dg_pad_force_unhold().clear_bit();
w.dg_pad_force_noiso().clear_bit()
// force power down modem(wifi and ble) power domain
.dig_iso()
.modify(|_, w| w.wifi_force_iso().set_bit().bt_force_iso().set_bit());
.modify(|_, w| w.wifi_force_pd().set_bit().bt_force_pd().set_bit());
rtc_cntl.int_ena().write(|w| w.bits(0));
rtc_cntl.int_clr().write(|w| w.bits(u32::MAX));
regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(1);
pub(crate) fn apply(&self) {
// like esp-idf rtc_sleep_init()
if self.lslp_mem_inf_fpu() {
rtc_sleep_pu(true);
if self.wifi_pd_en() {
w.wifi_force_iso().clear_bit()
w.wifi_pd_en().set_bit()
} else {
rtc_cntl.dig_pwc().modify(|_, w| w.wifi_pd_en().clear_bit());
if self.bt_pd_en() {
w.bt_force_iso().clear_bit()
w.bt_pd_en().set_bit()
rtc_cntl.dig_pwc().modify(|_, w| w.bt_pd_en().clear_bit());
w.cpu_top_pd_en().bit(self.cpu_pd_en());
w.dg_peri_pd_en().bit(self.dig_peri_pd_en())
rtc_cntl.bias_conf().modify(|_, w| {
w.dbg_atten_monitor()
.bits(RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT);
// We have config values for this in self, so I don't know why we're setting
// hardcoded defaults for these next two. It's what IDF does...
w.bias_sleep_monitor().bit(RTC_CNTL_BIASSLP_MONITOR_DEFAULT);
w.pd_cur_monitor().bit(RTC_CNTL_PD_CUR_MONITOR_DEFAULT)
// Like `rtc_sleep_get_default_config`: a crystal that stays on through a light sleep
// needs the bias current and the voltage of the active mode.
let xtal_on = self.xtal_fpu() && !self.deep_slp();
let bias_sleep_slp = self.bias_sleep_slp() && !xtal_on;
let pd_cur_slp = self.pd_cur_slp() && !xtal_on;
let dbg_atten_slp = if xtal_on {
RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP
self.dbg_atten_slp()
assert!(!pd_cur_slp || bias_sleep_slp);
regi2c::I2C_DIG_REG_EXT_RTC_DREG_SLEEP.write_field(self.rtc_dbias_slp());
regi2c::I2C_DIG_REG_EXT_DIG_DREG_SLEEP.write_field(self.dig_dbias_slp());
w.dbg_atten_deep_slp().bits(dbg_atten_slp);
w.bias_sleep_deep_slp().bit(bias_sleep_slp);
w.pd_cur_deep_slp().bit(pd_cur_slp)
if self.deep_slp() {
regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(0);
.modify(|_, w| w.dg_wrap_pd_en().set_bit());
w.ckgen_i2c_pu().clear_bit();
w.pll_i2c_pu().clear_bit();
w.rfrx_pbus_pu().clear_bit();
w.txrf_i2c_pu().clear_bit()
.modify(|_, w| w.bb_i2c_force_pu().clear_bit());
w.dg_vdd_drv_b_slp_en().set_bit();
w.dg_vdd_drv_b_slp().bits(RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT)
.modify(|_, w| w.dg_wrap_pd_en().clear_bit());
// mem force pu
.modify(|_, w| w.lslp_mem_force_pu().set_bit());
.rtc_cntl()
.modify(|_, w| w.regulator_force_pu().bit(self.rtc_regulator_fpu()));
rtc_cntl.clk_conf().modify(|_, w| {
w.ck8m_force_pu().bit(!self.int_8m_pd_en());
w.ck8m_force_nogating().bit(!self.int_8m_pd_en())
// enable VDDSDIO control by state machine
rtc_cntl.sdio_conf().modify(|_, w| {
w.sdio_force().clear_bit();
w.sdio_reg_pd_en().bit(self.vddsdio_pd_en())
rtc_cntl.slp_reject_conf().modify(|_, w| {
w.deep_slp_reject_en().bit(self.deep_slp_reject());
w.light_slp_reject_en().bit(self.light_slp_reject())
.modify(|_, w| w.xtl_force_pu().bit(self.xtal_fpu()));
.modify(|_, w| w.xtal_global_force_nogating().bit(self.xtal_fpu()));
/// Configures the wakeup and reject sources of the sleep.
/// [`Self::enter_sleep`] requests the sleep after this call.
pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) {
// set bits for what can wake us up
.wakeup_state()
.modify(|_, w| unsafe { w.wakeup_ena().bits(wakeup_mask) });
// Set the bits of the sources that reject the sleep. The reject enables that `apply` wrote
// arm those sources.
.slp_reject_conf()
.modify(|_, w| unsafe { w.sleep_reject_ena().bits(reject_mask) });
/// Requests the sleep.
/// The caller waits for the result of the request.
#[inline(always)]
pub(crate) fn enter_sleep(&self) -> bool {
LPWR::regs().state0().modify(|_, w| w.sleep_en().set_bit());
super::wait_for_sleep_result()
pub(crate) fn finish_sleep(&self) {
// In deep sleep mode, we never get here
LPWR::regs().int_clr().write(|w| {
w.slp_reject().clear_bit_by_one();
w.slp_wakeup().clear_bit_by_one()
// restore config if it is a light sleep