soc: silabs: Fix the PRIMASK for Silabs S2 SoCs
sl_power_manager_sleep() doesn't expect the PRIMASK to be set when called. Setting BASEPRI to 0 was moved to sl_power_manager_is_ok_to_sleep(), this function is called after sl_power_manager_sleep() has set the PRIMASK. Added sli_power_manager_on_wakeup() to force a clock restore before the interrupt are handled. Added a call to retrieve the startup measurements, reducing the early wakeup time. Signed-off-by: Bastien Beauchamp <bastien.beauchamp@silabs.com>
This commit is contained in:
parent
19756be822
commit
ec1a2c6f47
1 changed files with 29 additions and 15 deletions
|
@ -8,6 +8,8 @@
|
|||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/pm/pm.h>
|
||||
#include <sl_power_manager.h>
|
||||
#include <sl_hfxo_manager.h>
|
||||
#include <sli_hfxo_manager.h>
|
||||
|
||||
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
|
||||
|
||||
|
@ -46,18 +48,6 @@ void pm_state_set(enum pm_state state, uint8_t substate_id)
|
|||
break;
|
||||
}
|
||||
|
||||
/* FIXME: When this function is entered the Kernel has disabled
|
||||
* interrupts using BASEPRI register. This is incorrect as it prevents
|
||||
* waking up from any interrupt which priority is not 0. Work around the
|
||||
* issue and disable interrupts using PRIMASK register as recommended
|
||||
* by ARM.
|
||||
*/
|
||||
|
||||
/* Set PRIMASK */
|
||||
__disable_irq();
|
||||
/* Set BASEPRI to 0 */
|
||||
irq_unlock(0);
|
||||
|
||||
LOG_DBG("Entry to energy mode %d", energy_mode);
|
||||
|
||||
if (energy_mode == SL_POWER_MANAGER_EM4) {
|
||||
|
@ -77,9 +67,6 @@ void pm_state_set(enum pm_state state, uint8_t substate_id)
|
|||
}
|
||||
|
||||
LOG_DBG("Exit from energy mode %d", energy_mode);
|
||||
|
||||
/* Clear PRIMASK */
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
|
||||
|
@ -88,6 +75,33 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
|
|||
ARG_UNUSED(substate_id);
|
||||
}
|
||||
|
||||
/* This function is called by sl_power_manager_sleep() after it has set the PRIMASK. */
|
||||
bool sl_power_manager_is_ok_to_sleep(void)
|
||||
{
|
||||
/* FIXME: When this function is entered the Kernel has disabled
|
||||
* interrupts using BASEPRI register. This is incorrect as it prevents
|
||||
* waking up from any interrupt which priority is not 0. Work around the
|
||||
* issue and disable interrupts using PRIMASK register as recommended
|
||||
* by ARM.
|
||||
*/
|
||||
/* Set BASEPRI to 0. */
|
||||
irq_unlock(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This function is called by sl_power_manager_sleep() right after it was woken up from WFI. */
|
||||
void sli_power_manager_on_wakeup(void)
|
||||
{
|
||||
#if defined(HFXO_MANAGER_SLEEPTIMER_SYSRTC_INTEGRATION_ON)
|
||||
/* Handle the HFXO IRQ as soon as possible to retrieve the startup time. */
|
||||
sl_hfxo_manager_irq_handler();
|
||||
#endif
|
||||
/* Forces a clock restore before handling interrupts. */
|
||||
sl_power_manager_add_em_requirement(SL_POWER_MANAGER_EM1);
|
||||
sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some SiLabs blobs, such as RAIL, call directly into sl_power_manager, and
|
||||
* for that they had to include sl_power_manager.h during build. Some of those
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue