use strum::FromRepr;
use crate::{
peripherals::PMU,
soc::{clocks::ClockConfig, regi2c},
};
const HP_SYSCLK_XTAL: u8 = 0;
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
#[repr(usize)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SocResetReason {
ChipPowerOn = 0x01,
CoreSw = 0x03,
CoreDeepSleep = 0x05,
CoreSDIO = 0x06,
CoreMwdt0 = 0x07,
CoreMwdt1 = 0x08,
CoreRtcWdt = 0x09,
Cpu0Mwdt0 = 0x0B,
Cpu0Sw = 0x0C,
Cpu0RtcWdt = 0x0D,
SysBrownOut = 0x0F,
SysRtcWdt = 0x10,
Cpu0Mwdt1 = 0x11,
SysSuperWdt = 0x12,
CoreEfuseCrc = 0x14,
CoreUsbUart = 0x15,
CoreUsbJtag = 0x16,
Cpu0JtagCpu = 0x18,
}
fn pmu_power_domain_force_default() {
let pmu = PMU::regs();
pmu.power_pd_top_cntl().modify(|_, w| {
w.force_top_reset().bit(false);
w.force_top_iso().bit(false);
w.force_top_pu().bit(false);
w.force_top_no_reset().bit(false);
w.force_top_no_iso().bit(false);
w.force_top_pd().bit(false)
});
pmu.power_pd_cnnt_cntl().modify(|_, w| {
w.force_cnnt_reset().bit(false);
w.force_cnnt_iso().bit(false);
w.force_cnnt_pu().bit(false);
w.force_cnnt_no_reset().bit(false);
w.force_cnnt_no_iso().bit(false);
w.force_cnnt_pd().bit(false)
});
pmu.power_pd_hpmem_cntl().modify(|_, w| {
w.force_hp_mem_reset().bit(false);
w.force_hp_mem_iso().bit(false);
w.force_hp_mem_pu().bit(false);
w.force_hp_mem_no_reset().bit(false);
w.force_hp_mem_no_iso().bit(false);
w.force_hp_mem_pd().bit(false)
});
pmu.power_pd_lpperi_cntl().modify(|_, w| {
w.force_lp_peri_reset().bit(false);
w.force_lp_peri_iso().bit(false);
w.force_lp_peri_pu().bit(false);
w.force_lp_peri_no_reset().bit(false);
w.force_lp_peri_no_iso().bit(false);
w.force_lp_peri_pd().bit(false)
});
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct HpDigPower(u32);
pub bool, dcdc_switch_pd_en, set_dcdc_switch_pd_en: 21;
pub bool, mem_dslp , set_mem_dslp : 22;
pub bool, mem_pd_en , set_mem_pd_en : 23;
pub bool, cpu_pd_en , set_cpu_pd_en : 29;
pub bool, cnnt_pd_en , set_cnnt_pd_en : 30;
pub bool, top_pd_en , set_top_pd_en : 31;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct HpClkPower(u32);
pub bool, i2c_iso_en , set_i2c_iso_en : 21;
pub bool, i2c_retention, set_i2c_retention: 22;
pub u8, xpd_pll_i2c , set_xpd_pll_i2c : 26, 23;
pub u8, xpd_pll , set_xpd_pll : 30, 27;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct HpXtalPower(u32);
pub bool, xpd_xtal, set_xpd_xtal: 31;
}
#[derive(Clone, Copy, Default)]
pub struct HpSysPower {
pub dig_power: HpDigPower,
pub clk: HpClkPower,
pub xtal: HpXtalPower,
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct HpSysCntlReg(u32);
pub bool, uart_wakeup_en , set_uart_wakeup_en : 24;
pub bool, lp_pad_hold_all, set_lp_pad_hold_all: 25;
pub bool, hp_pad_hold_all, set_hp_pad_hold_all: 26;
pub bool, dig_pad_slp_sel, set_dig_pad_slp_sel: 27;
pub bool, dig_pause_wdt , set_dig_pause_wdt : 28;
pub bool, dig_cpu_stall , set_dig_cpu_stall : 29;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct HpSysclk(u32);
pub bool, dig_sysclk_nodiv, set_dig_sysclk_nodiv: 26;
pub bool, icg_sysclk_en , set_icg_sysclk_en : 27;
pub bool, sysclk_slp_sel , set_sysclk_slp_sel : 28;
pub bool, icg_slp_sel , set_icg_slp_sel : 29;
pub u8, dig_sysclk_sel , set_dig_sysclk_sel : 31, 30;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct HpAnalogBias(u32);
pub u8, dcm_vset , set_dcm_vset : 22, 18;
pub u8, dcm_mode , set_dcm_mode : 24, 23;
pub bool, xpd_bias , set_xpd_bias : 25;
pub u8, dbg_atten , set_dbg_atten : 29, 26;
pub bool, pd_cur , set_pd_cur : 30;
pub bool, bias_sleep, set_bias_sleep: 31;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct HpAnalogRegulator0(u32);
pub bool, slp_mem_xpd , set_slp_mem_xpd : 16;
pub bool, slp_logic_xpd , set_slp_logic_xpd : 17;
pub bool, xpd , set_xpd : 18;
pub u8, slp_mem_dbias , set_slp_mem_dbias : 22, 19;
pub u8, slp_logic_dbias, set_slp_logic_dbias: 26, 23;
pub u8, dbias , set_dbias : 31, 27;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct HpAnalogRegulator1(u32);
pub u8, drv_b, set_drv_b: 31, 26;
}
#[derive(Clone, Copy, Default)]
pub struct HpAnalog {
pub bias: HpAnalogBias,
pub regulator0: HpAnalogRegulator0,
pub regulator1: HpAnalogRegulator1,
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct LpDigPower(u32);
pub bool, lp_pad_slp_sel, set_lp_pad_slp_sel: 26;
pub bool, bod_source_sel, set_bod_source_sel: 27;
pub u8, vddbat_mode , set_vddbat_mode : 29, 28;
pub bool, mem_dslp , set_mem_dslp : 30;
pub bool, peri_pd_en , set_peri_pd_en : 31;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct LpClkPower(u32);
pub bool, xpd_lppll , set_xpd_lppll : 27;
pub bool, xpd_xtal32k, set_xpd_xtal32k: 28;
pub bool, xpd_rc32k , set_xpd_rc32k : 29;
pub bool, xpd_fosc , set_xpd_fosc : 30;
pub bool, pd_osc , set_pd_osc : 31;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct LpXtalPower(u32);
pub bool, xpd_xtal, set_xpd_xtal: 31;
}
#[derive(Clone, Copy, Default)]
pub struct LpSysPower {
pub dig_power: LpDigPower,
pub clk_power: LpClkPower,
pub xtal: LpXtalPower,
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct LpAnalogBias(u32);
pub bool, xpd_bias , set_xpd_bias : 25;
pub u8, dbg_atten , set_dbg_atten : 29, 26;
pub bool, pd_cur , set_pd_cur : 30;
pub bool, bias_sleep, set_bias_sleep: 31;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct LpAnalogRegulator0(u32);
pub bool, slp_xpd , set_slp_xpd : 21;
pub bool, xpd , set_xpd : 22;
pub u8, slp_dbias, set_slp_dbias: 26, 23;
pub u8, dbias , set_dbias : 31, 27;
}
bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
pub struct LpAnalogRegulator1(u32);
pub u8, drv_b, set_drv_b: 31, 26;
}
#[derive(Clone, Copy, Default)]
pub struct LpAnalog {
pub bias: LpAnalogBias,
pub regulator0: LpAnalogRegulator0,
pub regulator1: LpAnalogRegulator1,
}
fn pmu_hp_system_init() {
let pmu = PMU::regs();
pmu.hp_active_dig_power().write(|w| unsafe { w.bits(0) });
pmu.hp_active_hp_ck_power().write(|w| unsafe {
w.hp_active_i2c_iso_en().bit(false);
w.hp_active_i2c_retention().bit(false);
w.hp_active_xpd_pll_i2c().bits(0xf);
w.hp_active_xpd_pll().bits(0xf)
});
pmu.hp_active_xtal()
.modify(|_, w| w.hp_active_xpd_xtal().bit(true));
pmu.hp_active_icg_hp_func()
.write(|w| unsafe { w.bits(0xffff_ffff) });
pmu.hp_active_icg_hp_apb()
.write(|w| unsafe { w.bits(0xffff_ffff) });
pmu.hp_active_icg_modem()
.write(|w| unsafe { w.hp_active_dig_icg_modem_code().bits(0) });
pmu.hp_active_sysclk().modify(|_, w| unsafe {
w.hp_active_dig_sys_clk_no_div().bit(false);
w.hp_active_icg_sys_clock_en().bit(true);
w.hp_active_sys_clk_slp_sel().bit(false);
w.hp_active_icg_slp_sel().bit(false);
w.hp_active_dig_sys_clk_sel().bits(HP_SYSCLK_XTAL)
});
pmu.hp_active_hp_sys_cntl().modify(|_, w| {
w.hp_active_uart_wakeup_en().bit(false);
w.hp_active_lp_pad_hold_all().bit(false);
w.hp_active_hp_pad_hold_all().bit(false);
w.hp_active_dig_pad_slp_sel().bit(false);
w.hp_active_dig_pause_wdt().bit(false);
w.hp_active_dig_cpu_stall().bit(false)
});
pmu.hp_active_bias().modify(|_, w| unsafe {
w.hp_active_dcm_vset().bits(27);
w.hp_active_dcm_mode().bits(1);
w.hp_active_xpd_bias().bit(true);
w.hp_active_dbg_atten().bits(0);
w.hp_active_pd_cur().bit(false);
w.sleep().bit(false)
});
pmu.hp_active_hp_regulator0().modify(|_, w| unsafe {
w.hp_active_hp_regulator_slp_mem_xpd().bit(false);
w.hp_active_hp_regulator_slp_logic_xpd().bit(false);
w.hp_active_hp_regulator_slp_logic_dbias().bits(0)
});
pmu.hp_active_backup().write(|w| unsafe { w.bits(0) });
pmu.hp_active_backup_clk()
.write(|w| unsafe { w.bits(0xffff_ffff) });
pmu.hp_sleep_dig_power()
.write(|w| w.hp_sleep_dcdc_switch_pd_en().bit(true));
pmu.hp_sleep_hp_ck_power().write(|w| unsafe {
w.hp_sleep_i2c_iso_en().bit(true);
w.hp_sleep_i2c_retention().bit(true);
w.hp_sleep_xpd_pll_i2c().bits(1);
w.hp_sleep_xpd_pll().bits(0)
});
pmu.hp_sleep_xtal()
.modify(|_, w| w.hp_sleep_xpd_xtal().bit(false));
pmu.hp_sleep_icg_hp_func().write(|w| unsafe { w.bits(0) });
pmu.hp_sleep_icg_hp_apb().write(|w| unsafe { w.bits(0) });
pmu.hp_sleep_icg_modem()
.write(|w| unsafe { w.hp_sleep_dig_icg_modem_code().bits(0) });
pmu.hp_sleep_sysclk().modify(|_, w| unsafe {
w.hp_sleep_dig_sys_clk_no_div().bit(false);
w.hp_sleep_icg_sys_clock_en().bit(false);
w.hp_sleep_sys_clk_slp_sel().bit(true);
w.hp_sleep_icg_slp_sel().bit(true);
w.hp_sleep_dig_sys_clk_sel().bits(HP_SYSCLK_XTAL)
});
pmu.hp_sleep_hp_sys_cntl().modify(|_, w| {
w.hp_sleep_uart_wakeup_en().bit(true);
w.hp_sleep_lp_pad_hold_all().bit(false);
w.hp_sleep_hp_pad_hold_all().bit(false);
w.hp_sleep_dig_pad_slp_sel().bit(false);
w.hp_sleep_dig_pause_wdt().bit(true);
w.hp_sleep_dig_cpu_stall().bit(true)
});
pmu.hp_sleep_bias().modify(|_, w| unsafe {
w.hp_sleep_dcm_vset().bits(0);
w.hp_sleep_dcm_mode().bits(1);
w.hp_sleep_xpd_bias().bit(false);
w.hp_sleep_dbg_atten().bits(0);
w.hp_sleep_pd_cur().bit(true);
w.sleep().bit(true)
});
pmu.hp_sleep_hp_regulator0().modify(|_, w| unsafe {
w.hp_sleep_hp_regulator_slp_mem_xpd().bit(false);
w.hp_sleep_hp_regulator_slp_logic_xpd().bit(false);
w.hp_sleep_hp_regulator_xpd().bit(true);
w.hp_sleep_hp_regulator_slp_mem_dbias().bits(1);
w.hp_sleep_hp_regulator_slp_logic_dbias().bits(0)
});
pmu.hp_sleep_backup().write(|w| unsafe { w.bits(0) });
pmu.hp_sleep_backup_clk()
.write(|w| unsafe { w.bits(0xffff_ffff) });
pmu.imm_modem_icg()
.write(|w| w.update_dig_icg_modem_en().bit(true));
pmu.imm_sleep_sysclk()
.write(|w| w.update_dig_icg_switch().bit(true));
const PMU_SLEEP_PROTECT_HP_LP_SLEEP: u8 = 2;
pmu.slp_wakeup_cntl3()
.modify(|_, w| unsafe { w.sleep_prt_sel().bits(PMU_SLEEP_PROTECT_HP_LP_SLEEP) });
}
fn pmu_lp_system_init() {
let pmu = PMU::regs();
pmu.hp_sleep_lp_dig_power().write(|w| unsafe { w.bits(0) });
pmu.hp_sleep_lp_ck_power().write(|w| {
w.hp_sleep_xpd_lppll().bit(false);
w.hp_sleep_xpd_xtal32k().bit(true);
w.hp_sleep_xpd_rc32k().bit(true);
w.hp_sleep_xpd_fosc_clk().bit(true);
w.hp_sleep_pd_osc_clk().bit(false)
});
pmu.hp_sleep_lp_regulator0().modify(|_, w| unsafe {
w.hp_sleep_lp_regulator_slp_xpd().bit(false);
w.hp_sleep_lp_regulator_slp_dbias().bits(0)
});
pmu.hp_sleep_lp_regulator1()
.modify(|_, w| unsafe { w.hp_sleep_lp_regulator_drv_b().bits(0) });
pmu.lp_sleep_lp_dig_power().write(|w| unsafe { w.bits(0) });
pmu.lp_sleep_lp_ck_power().write(|w| unsafe { w.bits(0) });
pmu.lp_sleep_xtal()
.modify(|_, w| w.lp_sleep_xpd_xtal().bit(false));
pmu.lp_sleep_bias().modify(|_, w| unsafe {
w.lp_sleep_xpd_bias().bit(false);
w.lp_sleep_dbg_atten().bits(0);
w.lp_sleep_pd_cur().bit(true);
w.sleep().bit(true)
});
pmu.lp_sleep_lp_regulator0().modify(|_, w| unsafe {
w.lp_sleep_lp_regulator_slp_xpd().bit(false);
w.lp_sleep_lp_regulator_xpd().bit(true);
w.lp_sleep_lp_regulator_slp_dbias().bits(0);
w.lp_sleep_lp_regulator_dbias().bits(12)
});
pmu.lp_sleep_lp_regulator1()
.modify(|_, w| unsafe { w.lp_sleep_lp_regulator_drv_b().bits(0) });
}
pub(crate) fn init(_config: &ClockConfig) {
pmu_power_domain_force_default();
regi2c::I2C_DIG_REG_FORCE_RTC_DREG.write_field(1);
regi2c::I2C_DIG_REG_FORCE_DIG_DREG.write_field(1);
regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
pmu_hp_system_init();
pmu_lp_system_init();
PMU::regs().power_dcdc_switch().modify(|_, w| {
w.force_dcdc_switch_pu().bit(false);
w.force_dcdc_switch_pd().bit(false)
});
PMU::regs().imm_hp_ck_power().write(|w| unsafe {
w.tie_high_xpd_pll().bits(0xF);
w.tie_high_xpd_pll_i2c().bits(0xF)
});
}