diff --git a/soc/arm/microchip_mec/mec1501/device_power.c b/soc/arm/microchip_mec/mec1501/device_power.c index 11f321123f4..37df97c65f3 100644 --- a/soc/arm/microchip_mec/mec1501/device_power.c +++ b/soc/arm/microchip_mec/mec1501/device_power.c @@ -53,8 +53,15 @@ void soc_deep_sleep_enable(void) PCR_REGS->SYS_SLP_CTRL = MCHP_PCR_SYS_SLP_HEAVY; } +/* + * Clear PCR Sleep control sleep all causing HW to de-assert all peripheral + * SLP_EN signals. HW will does this automatically only if it vectors to an + * ISR after wake. We are masking ISR's from running until we restore + * peripheral state therefore we force HW to de-assert the SLP_EN signals. + */ void soc_deep_sleep_disable(void) { + PCR_REGS->SYS_SLP_CTRL = 0U; SCB->SCR &= ~(1ul << 2); /* disable Cortex-M4 SLEEPDEEP */ } diff --git a/soc/arm/microchip_mec/mec1501/power.c b/soc/arm/microchip_mec/mec1501/power.c index 7902a64ba53..af4f2abf01c 100644 --- a/soc/arm/microchip_mec/mec1501/power.c +++ b/soc/arm/microchip_mec/mec1501/power.c @@ -115,16 +115,25 @@ void pm_power_state_set(struct pm_state_info info) } } +/* + * Zephyr PM code expects us to enabled interrupts at post op exit. Zephyr used + * arch_irq_lock() which sets BASEPRI to a non-zero value masking all interrupts + * preventing wake. MCHP z_power_soc_(deep)_sleep sets PRIMASK=1 and BASEPRI=0 + * allowing wake from any enabled interrupt and prevents the CPU from entering + * an ISR on wake except for faults. We re-enable interrupts by setting PRIMASK + * to 0. + */ void pm_power_state_exit_post_ops(struct pm_state_info info) { switch (info.state) { case PM_STATE_SUSPEND_TO_IDLE: - __enable_irq(); - break; case PM_STATE_SUSPEND_TO_RAM: - __enable_irq(); + __set_PRIMASK(0); + __ISB(); break; + default: + irq_unlock(0); break; } }