Skip to content

Commit c992e1a

Browse files
yongxu-wang15kartben
authored andcommitted
soc: nxp: imx943: implement basic PM flow for Cortex-M cores
Add initial power management support for i.MX943 M-core (M33/M7) This lays the foundation for multi-core PM handling on i.MX943 Signed-off-by: Yongxu Wang <[email protected]>
1 parent bf71281 commit c992e1a

File tree

8 files changed

+237
-0
lines changed

8 files changed

+237
-0
lines changed

soc/nxp/imx/imx9/imx943/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ elseif(CONFIG_SOC_MIMX94398_M7_0)
1212
elseif(CONFIG_SOC_MIMX94398_M7_1)
1313
add_subdirectory(m7_1)
1414
endif()
15+
16+
zephyr_library_sources_ifdef(CONFIG_SOC_IMX943_PM_MCORE pm_mcore.c)

soc/nxp/imx/imx9/imx943/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ config SOC_MIMX94398_M33
2222
select HAS_MCUX_XCACHE
2323
select INIT_ARCH_HW_AT_BOOT
2424
select SOC_EARLY_INIT_HOOK
25+
select HAS_PM
2526

2627
config SOC_MIMX94398_M7_0
2728
select ARM
@@ -35,6 +36,7 @@ config SOC_MIMX94398_M7_0
3536
select SOC_EARLY_INIT_HOOK
3637
select HAS_MCUX
3738
select HAS_MCUX_CACHE
39+
select HAS_PM
3840

3941
config SOC_MIMX94398_M7_1
4042
select ARM
@@ -48,3 +50,12 @@ config SOC_MIMX94398_M7_1
4850
select SOC_EARLY_INIT_HOOK
4951
select HAS_MCUX
5052
select HAS_MCUX_CACHE
53+
select HAS_PM
54+
55+
config SOC_IMX943_PM_MCORE
56+
bool "i.MX943 multi-core PM shared logic"
57+
default y
58+
depends on PM
59+
depends on SOC_MIMX94398_M33 || SOC_MIMX94398_M7_0 || SOC_MIMX94398_M7_1
60+
help
61+
Common PM flow for Cortex-M cores (M33/M7) on i.MX943

soc/nxp/imx/imx9/imx943/Kconfig.defconfig.mimx94398.m33

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,11 @@ config ETH_NXP_IMX_MSGINTR
3030
config CACHE_MANAGEMENT
3131
default y
3232

33+
if PM
34+
35+
config IDLE_STACK_SIZE
36+
default 640
37+
38+
endif
39+
3340
endif # SOC_MIMX94398_M33

soc/nxp/imx/imx9/imx943/Kconfig.defconfig.mimx94398.m7_0

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,11 @@ config ETH_NXP_IMX_MSGINTR
2626
config CACHE_MANAGEMENT
2727
default n
2828

29+
if PM
30+
31+
config IDLE_STACK_SIZE
32+
default 640
33+
34+
endif
35+
2936
endif # SOC_MIMX94398_M7_0

soc/nxp/imx/imx9/imx943/Kconfig.defconfig.mimx94398.m7_1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,11 @@ config ETH_NXP_IMX_MSGINTR
2626
config CACHE_MANAGEMENT
2727
default n
2828

29+
if PM
30+
31+
config IDLE_STACK_SIZE
32+
default 640
33+
34+
endif
35+
2936
endif # SOC_MIMX94398_M7_1

soc/nxp/imx/imx9/imx943/pm_mcore.c

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#include <zephyr/kernel.h>
7+
#include <zephyr/device.h>
8+
#include <zephyr/drivers/firmware/scmi/nxp/cpu.h>
9+
#include <zephyr/dt-bindings/power/imx943_power.h>
10+
#include <pm_mcore.h>
11+
12+
static void pm_state_before(void)
13+
{
14+
struct scmi_cpu_pd_lpm_config cpu_pd_lpm_cfg;
15+
struct scmi_cpu_irq_mask_config cpu_irq_mask_cfg;
16+
17+
/*
18+
* 1. Set CPU mix as power on state in suspend mode
19+
* 2. Keep wakeupmix power on whatever low power mode, as lpuart(console) in there.
20+
*/
21+
22+
cpu_pd_lpm_cfg.cpu_id = cpu_idx;
23+
cpu_pd_lpm_cfg.num_cfg = 2;
24+
cpu_pd_lpm_cfg.cfgs[0].domain_id = pwr_mix_idx;
25+
cpu_pd_lpm_cfg.cfgs[0].lpm_setting = SCMI_CPU_LPM_SETTING_ON_ALWAYS;
26+
cpu_pd_lpm_cfg.cfgs[0].ret_mask = 1U << pwr_mem_idx;
27+
cpu_pd_lpm_cfg.cfgs[1].domain_id = PWR_MIX_SLICE_IDX_WAKEUP;
28+
cpu_pd_lpm_cfg.cfgs[1].lpm_setting = SCMI_CPU_LPM_SETTING_ON_ALWAYS;
29+
cpu_pd_lpm_cfg.cfgs[1].ret_mask = 0;
30+
31+
scmi_cpu_pd_lpm_set(&cpu_pd_lpm_cfg);
32+
33+
/* Set wakeup mask */
34+
uint32_t wake_mask[GPC_CPU_CTRL_CMC_IRQ_WAKEUP_MASK_COUNT] = {
35+
[0 ... GPC_CPU_CTRL_CMC_IRQ_WAKEUP_MASK_COUNT - 1] = 0xFFFFFFFFU
36+
};
37+
38+
/* IRQs enabled at NVIC level become GPC wake sources */
39+
for (uint32_t idx = 0; idx < nvic_iser_nb; idx++) {
40+
wake_mask[idx] = ~(NVIC->ISER[idx]);
41+
}
42+
43+
cpu_irq_mask_cfg.cpu_id = cpu_idx;
44+
cpu_irq_mask_cfg.mask_idx = 0;
45+
cpu_irq_mask_cfg.num_mask = GPC_CPU_CTRL_CMC_IRQ_WAKEUP_MASK_COUNT;
46+
47+
for (uint8_t val = 0; val < GPC_CPU_CTRL_CMC_IRQ_WAKEUP_MASK_COUNT; val++) {
48+
cpu_irq_mask_cfg.mask[val] = wake_mask[val];
49+
}
50+
51+
scmi_cpu_set_irq_mask(&cpu_irq_mask_cfg);
52+
}
53+
54+
static void pm_state_resume(void)
55+
{
56+
struct scmi_cpu_irq_mask_config cpu_irq_mask_cfg;
57+
58+
/* Restore scmi cpu wake mask */
59+
uint32_t wake_mask[GPC_CPU_CTRL_CMC_IRQ_WAKEUP_MASK_COUNT] = {
60+
[0 ... GPC_CPU_CTRL_CMC_IRQ_WAKEUP_MASK_COUNT - 1] = 0x0U
61+
};
62+
63+
cpu_irq_mask_cfg.cpu_id = cpu_idx;
64+
cpu_irq_mask_cfg.mask_idx = 0;
65+
cpu_irq_mask_cfg.num_mask = GPC_CPU_CTRL_CMC_IRQ_WAKEUP_MASK_COUNT;
66+
67+
for (uint8_t val = 0; val < GPC_CPU_CTRL_CMC_IRQ_WAKEUP_MASK_COUNT; val++) {
68+
cpu_irq_mask_cfg.mask[val] = wake_mask[val];
69+
}
70+
71+
scmi_cpu_set_irq_mask(&cpu_irq_mask_cfg);
72+
}
73+
74+
void pm_state_set(enum pm_state state, uint8_t substate_id)
75+
{
76+
struct scmi_cpu_sleep_mode_config cpu_cfg = {0};
77+
78+
pm_state_before();
79+
80+
__disable_irq();
81+
/* Set BASEPRI to 0 */
82+
irq_unlock(0);
83+
84+
switch (state) {
85+
case PM_STATE_RUNTIME_IDLE:
86+
cpu_cfg.cpu_id = cpu_idx;
87+
cpu_cfg.sleep_mode = CPU_SLEEP_MODE_WAIT;
88+
scmi_cpu_sleep_mode_set(&cpu_cfg);
89+
__DSB();
90+
__WFI();
91+
break;
92+
case PM_STATE_SUSPEND_TO_IDLE:
93+
cpu_cfg.cpu_id = cpu_idx;
94+
cpu_cfg.sleep_mode = CPU_SLEEP_MODE_STOP;
95+
scmi_cpu_sleep_mode_set(&cpu_cfg);
96+
__DSB();
97+
__WFI();
98+
break;
99+
case PM_STATE_STANDBY:
100+
cpu_cfg.cpu_id = cpu_idx;
101+
cpu_cfg.sleep_mode = CPU_SLEEP_MODE_SUSPEND;
102+
scmi_cpu_sleep_mode_set(&cpu_cfg);
103+
__DSB();
104+
__WFI();
105+
break;
106+
default:
107+
break;
108+
}
109+
}
110+
111+
/* Handle SOC specific activity after Low Power Mode Exit */
112+
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
113+
{
114+
struct scmi_cpu_sleep_mode_config cpu_cfg = {0};
115+
116+
pm_state_resume();
117+
118+
/* restore Mcore state into ACTIVE. */
119+
cpu_cfg.cpu_id = cpu_idx;
120+
cpu_cfg.sleep_mode = CPU_SLEEP_MODE_RUN;
121+
scmi_cpu_sleep_mode_set(&cpu_cfg);
122+
123+
/* Clear PRIMASK */
124+
__enable_irq();
125+
}

soc/nxp/imx/imx9/imx943/pm_mcore.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_NXP_IMX943_PM_MCORE_H_
8+
#define ZEPHYR_NXP_IMX943_PM_MCORE_H_
9+
10+
#ifdef CONFIG_SOC_MIMX94398_M33
11+
#define cpu_idx CPU_IDX_M33P_S
12+
#define pwr_mix_idx PWR_MIX_SLICE_IDX_NETC;
13+
#define pwr_mem_idx PWR_MEM_SLICE_IDX_NETC
14+
#define nvic_iser_nb 16
15+
#elif CONFIG_SOC_MIMX94398_M7_0
16+
#define cpu_idx CPU_IDX_M7P_0
17+
#define pwr_mix_idx PWR_MIX_SLICE_IDX_M7_0;
18+
#define pwr_mem_idx PWR_MEM_SLICE_IDX_M7_0
19+
#define nvic_iser_nb 8
20+
#else
21+
#define cpu_idx CPU_IDX_M7P_1
22+
#define pwr_mix_idx PWR_MIX_SLICE_IDX_M7_1;
23+
#define pwr_mem_idx PWR_MEM_SLICE_IDX_M7_1
24+
#define nvic_iser_nb 8
25+
#endif
26+
27+
#endif /* ZEPHYR_NXP_IMX943_PM_MCORE_H_ */

soc/nxp/imx/imx9/imx943/scmi_cpu_soc.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,55 @@
2222
#define CPU_SLEEP_MODE_STOP 2U
2323
#define CPU_SLEEP_MODE_SUSPEND 3U
2424

25+
/*!
26+
* @name SCMI CPU LPM settings
27+
*/
28+
#define SCMI_CPU_LPM_SETTING_ON_NEVER 0U
29+
#define SCMI_CPU_LPM_SETTING_ON_RUN 1U
30+
#define SCMI_CPU_LPM_SETTING_ON_RUN_WAIT 2U
31+
#define SCMI_CPU_LPM_SETTING_ON_RUN_WAIT_STOP 3U
32+
#define SCMI_CPU_LPM_SETTING_ON_ALWAYS 4U
33+
34+
#define PWR_NUM_MIX_SLICE 19U
35+
36+
#define PWR_MIX_SLICE_IDX_ANA 0U
37+
#define PWR_MIX_SLICE_IDX_AON 1U
38+
#define PWR_MIX_SLICE_IDX_BBSM 2U
39+
#define PWR_MIX_SLICE_IDX_M7_1 3U
40+
#define PWR_MIX_SLICE_IDX_CCMSRCGPC 4U
41+
#define PWR_MIX_SLICE_IDX_A55C0 5U
42+
#define PWR_MIX_SLICE_IDX_A55C1 6U
43+
#define PWR_MIX_SLICE_IDX_A55C2 7U
44+
#define PWR_MIX_SLICE_IDX_A55C3 8U
45+
#define PWR_MIX_SLICE_IDX_A55P 9U
46+
#define PWR_MIX_SLICE_IDX_DDR 10U
47+
#define PWR_MIX_SLICE_IDX_DISPLAY 11U
48+
#define PWR_MIX_SLICE_IDX_M7_0 12U
49+
#define PWR_MIX_SLICE_IDX_HSIO_TOP 13U
50+
#define PWR_MIX_SLICE_IDX_HSIO_WAON 14U
51+
#define PWR_MIX_SLICE_IDX_NETC 15U
52+
#define PWR_MIX_SLICE_IDX_NOC 16U
53+
#define PWR_MIX_SLICE_IDX_NPU 17U
54+
#define PWR_MIX_SLICE_IDX_WAKEUP 18U
55+
56+
#define PWR_NUM_MEM_SLICE 17U
57+
58+
#define PWR_MEM_SLICE_IDX_AON 0U
59+
#define PWR_MEM_SLICE_IDX_M7_1 1U
60+
#define PWR_MEM_SLICE_IDX_A55C0 2U
61+
#define PWR_MEM_SLICE_IDX_A55C1 3U
62+
#define PWR_MEM_SLICE_IDX_A55C2 4U
63+
#define PWR_MEM_SLICE_IDX_A55C3 5U
64+
#define PWR_MEM_SLICE_IDX_A55P 6U
65+
#define PWR_MEM_SLICE_IDX_A55L3 7U
66+
#define PWR_MEM_SLICE_IDX_DDR 8U
67+
#define PWR_MEM_SLICE_IDX_DISPLAY 9U
68+
#define PWR_MEM_SLICE_IDX_M7_0 10U
69+
#define PWR_MEM_SLICE_IDX_HSIO 11U
70+
#define PWR_MEM_SLICE_IDX_NETC 12U
71+
#define PWR_MEM_SLICE_IDX_NOC1 13U
72+
#define PWR_MEM_SLICE_IDX_NOC2 14U
73+
#define PWR_MEM_SLICE_IDX_NPU 15U
74+
#define PWR_MEM_SLICE_IDX_WAKEUP 16U
75+
2576
#endif /* ZEPHYR_NXP_IMX943_SCMI_CPU_SOC_H_ */

0 commit comments

Comments
 (0)