soc: mchp: Deep sleep exit sequence update
Zephyr kernel masks interrupts before calling the SoC PM sleep entry point. On the Cortex-Mx family this prevents wake from peripheral interrupts. The SoC PM layer requires interrupts to wake the SoC and must prevent the CPU from vectoring to an interrup until PM exit. The SoC does this by setting ARM NVIC PRIMASK to 1 and BASEPRI to 0. On return to the kernel SoC sets PRIMASK to 0 allowing ISR's to fire. In addition the MEC HW only clears its peripheral sleep enables if the CPU vectors to an ISR. On wake we clear the MEC PCR sleep control register which clears all the peripheral sleep enables so peripherals will be active before exiting the SoC PM layer. Signed-off-by: Scott Worley <scott.worley@microchip.com>
This commit is contained in:
parent
b07356dbce
commit
a10ce7561f
2 changed files with 19 additions and 3 deletions
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue