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/logging/log.h>
|
||||||
#include <zephyr/pm/pm.h>
|
#include <zephyr/pm/pm.h>
|
||||||
#include <sl_power_manager.h>
|
#include <sl_power_manager.h>
|
||||||
|
#include <sl_hfxo_manager.h>
|
||||||
|
#include <sli_hfxo_manager.h>
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
|
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;
|
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);
|
LOG_DBG("Entry to energy mode %d", energy_mode);
|
||||||
|
|
||||||
if (energy_mode == SL_POWER_MANAGER_EM4) {
|
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);
|
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)
|
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);
|
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
|
* 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
|
* 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