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:
Anke Xiao 2024-07-29 14:53:45 +08:00 committed by Anas Nashif
commit df2858944a
4 changed files with 74 additions and 0 deletions

View file

@ -8,6 +8,11 @@ zephyr_sources(
soc.c 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 "") set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "")
zephyr_include_directories(.) zephyr_include_directories(.)

View file

@ -12,3 +12,4 @@ config SOC_SERIES_KE1XZ
select CLOCK_CONTROL select CLOCK_CONTROL
select HAS_MCUX select HAS_MCUX
select PLATFORM_SPECIFIC_INIT select PLATFORM_SPECIFIC_INIT
select HAS_PM

View file

@ -6,8 +6,15 @@
if SOC_SERIES_KE1XZ 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 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,/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 config NUM_IRQS
default 32 default 32

View 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);
}