soc: nxp: ke1xz: Add power management support

Implement power management with IDLE, STOP, PSTOP1, and PSTOP2 modes.

- Add power state definitions with timing parameters
- Implement pm_state_set() with proper SLEEPDEEP handling
- Add XIP-safe WFI execution from RAM
- Enable SMC driver and power mode protection
- Remove forced timer Kconfig defaults

Signed-off-by: Holt Sun <holt.sun@nxp.com>
This commit is contained in:
Holt Sun
2026-01-09 15:21:03 +08:00
committed by Fabio Baltieri
parent e59a65386e
commit 8260974216
5 changed files with 56 additions and 20 deletions

View File

@@ -26,31 +26,40 @@
compatible = "arm,cortex-m0+";
clock-frequency = <DT_FREQ_M(48)>;
reg = <0>;
cpu-power-states = <&idle &stop &pstop1 &pstop2>;
cpu-power-states = <&idle &pstop2 &pstop1 &stop>;
};
power-states {
idle: idle {
compatible = "zephyr,power-state";
power-state-name = "runtime-idle";
min-residency-us = <10>;
/* 0.7 µs rounded */
exit-latency-us = <1>;
};
stop: stop {
compatible = "zephyr,power-state";
power-state-name = "suspend-to-idle";
substate-id = <0>;
min-residency-us = <14>;
exit-latency-us = <140>;
};
pstop1: pstop1 {
compatible = "zephyr,power-state";
power-state-name = "suspend-to-idle";
substate-id = <1>;
min-residency-us = <13>;
exit-latency-us = <130>;
};
pstop2: pstop2 {
compatible = "zephyr,power-state";
power-state-name = "suspend-to-idle";
substate-id = <2>;
min-residency-us = <12>;
exit-latency-us = <120>;
};
};
};

View File

@@ -69,6 +69,7 @@ set_variable_ifdef(CONFIG_ENTROPY_MCUX_TRNG CONFIG_MCUX_COMPONENT_driver.trn
set_variable_ifdef(CONFIG_ENTROPY_MCUX_CAAM CONFIG_MCUX_COMPONENT_driver.caam)
set_variable_ifdef(CONFIG_ETH_NXP_ENET CONFIG_MCUX_COMPONENT_driver.enet)
set_variable_ifdef(CONFIG_SOC_SERIES_KINETIS_K2X CONFIG_MCUX_COMPONENT_driver.smc)
set_variable_ifdef(CONFIG_SOC_SERIES_KE1XZ CONFIG_MCUX_COMPONENT_driver.smc)
set_variable_ifdef(CONFIG_I2C_MCUX CONFIG_MCUX_COMPONENT_driver.i2c)
set_variable_ifdef(CONFIG_I2C_NXP_II2C CONFIG_MCUX_COMPONENT_driver.ii2c)
set_variable_ifdef(CONFIG_I3C_MCUX CONFIG_MCUX_COMPONENT_driver.i3c)

View File

@@ -1,17 +1,11 @@
# Kinetis KE1xZ series configuration options
# Copyright (c) 2019-2021 Vestas Wind Systems A/S
# Copyright 2024 NXP
# Copyright 2024-2025 NXP
# SPDX-License-Identifier: Apache-2.0
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

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2021 Vestas Wind Systems A/S
* Copyright 2021, 2024 NXP
* Copyright 2021, 2024-2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,7 +12,8 @@
LOG_MODULE_DECLARE(power, CONFIG_PM_LOG_LEVEL);
__ramfunc static void wait_for_flash_prefetch_and_idle(void)
#ifdef CONFIG_XIP
__ramfunc static void wait_for_flash_prefetch_and_wfi(void)
{
uint32_t i;
@@ -20,27 +21,54 @@ __ramfunc static void wait_for_flash_prefetch_and_idle(void)
arch_nop();
}
k_cpu_idle();
/*
* Must execute WFI directly from RAM when XIP is enabled.
* Calling k_cpu_idle() may jump back into flash.
*/
__DSB();
__ISB();
__WFI();
}
#endif /* CONFIG_XIP */
void pm_state_set(enum pm_state state, uint8_t substate_id)
{
switch (state) {
case PM_STATE_RUNTIME_IDLE:
k_cpu_idle();
/* Normal WAIT: WFI with SLEEPDEEP cleared. */
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__ISB();
__WFI();
irq_unlock(0);
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 (substate_id > 2U) {
LOG_WRN("Unsupported substate-id %u, using 0", substate_id);
substate_id = 0U;
}
/* Ensure STOPM is set to normal STOP (not VLPS/VLLS families), if present. */
SMC->PMCTRL &= ~SMC_PMCTRL_STOPM_MASK;
#if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO)
SMC->STOPCTRL = (SMC->STOPCTRL & ~SMC_STOPCTRL_PSTOPO_MASK) |
SMC_STOPCTRL_PSTOPO(substate_id);
#endif
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
/* readback to complete bus writes */
(void)SMC->PMCTRL;
__DSB();
__ISB();
#ifdef CONFIG_XIP
wait_for_flash_prefetch_and_wfi();
#else
__WFI();
#endif
if (SMC->PMCTRL & SMC_PMCTRL_STOPA_MASK) {
LOG_DBG("partial stop aborted");
}
irq_unlock(0);
break;
default:
LOG_WRN("Unsupported power state %u", state);
@@ -54,7 +82,7 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
if (state == PM_STATE_SUSPEND_TO_IDLE) {
/* Disable deep sleep upon exit */
SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
}
irq_unlock(0);

View File

@@ -14,6 +14,7 @@
#include <zephyr/init.h>
#include <fsl_clock.h>
#include <cmsis_core.h>
#include "fsl_smc.h"
#define ASSERT_WITHIN_RANGE(val, min, max, str) BUILD_ASSERT(val >= min && val <= max, str)
@@ -186,6 +187,9 @@ void soc_early_init_hook(void)
{
/* Initialize system clocks and PLL */
clk_init();
#ifdef CONFIG_PM
SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll);
#endif /* CONFIG_PM */
}
#ifdef CONFIG_SOC_RESET_HOOK