soc: nxp: kinetis: ke1xz: add support cpu power states
Enable the NXP Kinetis Low Power Timer (LPTMR) timer driver when power management is enabled. When the NXP KE1xZ SoC series is using the Arm SysTick as hardware timer, the cycles/second will always be equal to the CPU core clock frequency. Signed-off-by: Anke Xiao <anke.xiao@nxp.com>
This commit is contained in:
parent
8628fa26c7
commit
df2858944a
4 changed files with 74 additions and 0 deletions
|
@ -8,6 +8,11 @@ zephyr_sources(
|
|||
soc.c
|
||||
)
|
||||
|
||||
zephyr_sources_ifdef(
|
||||
CONFIG_PM
|
||||
power.c
|
||||
)
|
||||
|
||||
set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "")
|
||||
|
||||
zephyr_include_directories(.)
|
||||
|
|
|
@ -12,3 +12,4 @@ config SOC_SERIES_KE1XZ
|
|||
select CLOCK_CONTROL
|
||||
select HAS_MCUX
|
||||
select PLATFORM_SPECIFIC_INIT
|
||||
select HAS_PM
|
||||
|
|
|
@ -6,8 +6,15 @@
|
|||
|
||||
if SOC_SERIES_KE1XZ
|
||||
|
||||
config MCUX_LPTMR_TIMER
|
||||
default y if PM
|
||||
|
||||
config CORTEX_M_SYSTICK
|
||||
default n if MCUX_LPTMR_TIMER
|
||||
|
||||
config SYS_CLOCK_HW_CYCLES_PER_SEC
|
||||
default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) if CORTEX_M_SYSTICK
|
||||
default $(dt_node_int_prop_int,/soc/lptmr@40040000,clock-frequency) if MCUX_LPTMR_TIMER
|
||||
|
||||
config NUM_IRQS
|
||||
default 32
|
||||
|
|
61
soc/nxp/kinetis/ke1xz/power.c
Normal file
61
soc/nxp/kinetis/ke1xz/power.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Vestas Wind Systems A/S
|
||||
* Copyright 2021, 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/pm/pm.h>
|
||||
#include <soc.h>
|
||||
|
||||
LOG_MODULE_DECLARE(power, CONFIG_PM_LOG_LEVEL);
|
||||
|
||||
__ramfunc static void wait_for_flash_prefetch_and_idle(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
arch_nop();
|
||||
}
|
||||
|
||||
k_cpu_idle();
|
||||
}
|
||||
|
||||
void pm_state_set(enum pm_state state, uint8_t substate_id)
|
||||
{
|
||||
switch (state) {
|
||||
case PM_STATE_RUNTIME_IDLE:
|
||||
k_cpu_idle();
|
||||
break;
|
||||
case PM_STATE_SUSPEND_TO_IDLE:
|
||||
/* Set partial stop mode and enable deep sleep */
|
||||
SMC->STOPCTRL = SMC_STOPCTRL_PSTOPO(substate_id);
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
if (IS_ENABLED(CONFIG_XIP)) {
|
||||
wait_for_flash_prefetch_and_idle();
|
||||
} else {
|
||||
k_cpu_idle();
|
||||
}
|
||||
if (SMC->PMCTRL & SMC_PMCTRL_STOPA_MASK) {
|
||||
LOG_DBG("partial stop aborted");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_WRN("Unsupported power state %u", state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
|
||||
{
|
||||
ARG_UNUSED(substate_id);
|
||||
|
||||
if (state == PM_STATE_SUSPEND_TO_IDLE) {
|
||||
/* Disable deep sleep upon exit */
|
||||
SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
|
||||
}
|
||||
|
||||
irq_unlock(0);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue