use crate::peripherals::{LP_AON, LP_CORE, LP_PERI, LPWR, PMU};
#[derive(Debug, Clone, Copy)]
pub enum LpCoreWakeupSource {
HpCpu,
}
#[derive(Debug, Clone, Copy)]
pub enum LpCoreClockSource {
RcFastClk,
XtalD2Clk,
}
pub struct LpCore<'d> {
_lp_core: LP_CORE<'d>,
}
impl<'d> LpCore<'d> {
pub fn new(lp_core: LP_CORE<'d>) -> Self {
LpCore::new_with_clock(lp_core, LpCoreClockSource::RcFastClk)
}
pub fn new_with_clock(lp_core: LP_CORE<'d>, clk_src: LpCoreClockSource) -> Self {
match clk_src {
LpCoreClockSource::RcFastClk => LPWR::regs()
.lp_clk_conf()
.modify(|_, w| w.fast_clk_sel().clear_bit()),
LpCoreClockSource::XtalD2Clk => LPWR::regs()
.lp_clk_conf()
.modify(|_, w| w.fast_clk_sel().set_bit()),
};
let mut this = Self { _lp_core: lp_core };
this.stop();
let lp_ram =
unsafe { core::slice::from_raw_parts_mut(0x5000_0000 as *mut u32, 16 * 1024 / 4) };
lp_ram.fill(0u32);
this
}
pub fn stop(&mut self) {
ulp_lp_core_stop();
}
pub fn run(&mut self, wakeup_src: LpCoreWakeupSource) {
ulp_lp_core_run(wakeup_src);
}
}
fn ulp_lp_core_stop() {
PMU::regs()
.lp_cpu_pwr1()
.modify(|_, w| unsafe { w.lp_cpu_wakeup_en().bits(0) });
PMU::regs()
.lp_cpu_pwr1()
.modify(|_, w| w.lp_cpu_sleep_req().set_bit());
}
fn ulp_lp_core_run(wakeup_src: LpCoreWakeupSource) {
let lp_aon = LP_AON::regs();
let pmu = PMU::regs();
let lp_peri = LP_PERI::regs();
lp_aon.lpcore().modify(|_, w| w.disable().clear_bit());
lp_aon
.lpbus()
.modify(|_, w| w.fast_mem_mux_sel().clear_bit());
lp_aon
.lpbus()
.modify(|_, w| w.fast_mem_mux_sel_update().set_bit());
pmu.lp_cpu_pwr0()
.modify(|_, w| w.lp_cpu_slp_stall_en().set_bit());
pmu.lp_cpu_pwr0()
.modify(|_, w| w.lp_cpu_slp_reset_en().set_bit());
let src = match wakeup_src {
LpCoreWakeupSource::HpCpu => 0x01,
};
pmu.lp_cpu_pwr1()
.modify(|_, w| unsafe { w.lp_cpu_wakeup_en().bits(src) });
lp_peri
.cpu()
.modify(|_, w| w.lpcore_dbgm_unavaliable().clear_bit());
match wakeup_src {
LpCoreWakeupSource::HpCpu => {
pmu.hp_lp_cpu_comm().write(|w| w.hp_trigger_lp().set_bit());
}
}
}