Skip to content

Conversation

mmahadevan108
Copy link
Contributor

Add support for power management states

Signed-off-by: Mahesh Mahadevan [email protected]

Comment on lines 46 to 82
/* This is corresponding to entering the "sleep" mode
* of the MCXW without any futher configurations. This is most simple
* state and is just entered by doing WFI mostly.
*/
sleep: sleep {
compatible = "zephyr,power-state";
power-state-name = "runtime-idle";
min-residency-us = <100>;
exit-latency-us = <0>;
};
/* This is corresponding to "sleep mode" with extra
* optimization by gating the clocks of certain peripherals,
* also the subdomains voltage levels could be configured differently
* Note it is "suspend-to-idle" for zephyr due to some peripherals may
* lose operation if their clock is gated, even though it is same
* hardware power mode.
*/
sleep_optimized: sleep-optimized {
compatible = "zephyr,power-state";
power-state-name = "suspend-to-idle";
substate-id = <0>;
min-residency-us = <500>;
exit-latency-us = <10>;
};
/* It is possible to do more configuring of the hardware in addition
* to just enter deep sleep, the peripherals in core domain
* can be power gated instead of just low power retention,
* and different peripheral in wakeup domain can be put in low power
* instead of remaining operational. So this is "standby" due to
* allowing configure of power gating peripherals which could lose state
*/
deep_sleep_optimized: deep-sleep-optimized {
compatible = "zephyr,power-state";
power-state-name = "standby";
min-residency-us = <1000>;
exit-latency-us = <11>;
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to align about these states, the comments i provided you internally that you seem to have kept here were just brainstorms, this "optimized" state idea , is not complete yet without domains and device runtime PM enablement of the device on this platform, the idea was about system configuration per app, to show that a zephyr PM state doesnt need to map 1:1 with hardware SOC modes

Comment on lines 13 to 16
zephyr_sources_ifdef(CONFIG_PM
power.c
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, do on one line

Comment on lines 12 to +17
default 96000000 if CORTEX_M_SYSTICK
default $(dt_node_int_prop_int,$(DT_LPTMR_PATH),clock-frequency) if MCUX_LPTMR_TIMER
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure it's getting set right, I thought the first value will take precedence here, and I don't see wheere would "CORTEX_M_SYSTICK" be unset

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CORTEX_M_SYSTICK is disabled when LPTMR is enabled.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does that happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 25 to 29
#ifdef CONFIG_DEBUG
CMC_EnableDebugOperation(CMC0, true);
#else
CMC_EnableDebugOperation(CMC0, false);
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#ifdef CONFIG_DEBUG
CMC_EnableDebugOperation(CMC0, true);
#else
CMC_EnableDebugOperation(CMC0, false);
#endif
CMC_EnableDebugOperation(CMC0, IS_ENABLED(CONFIG_DEBUG));


#if CONFIG_PM
nxp_mcxw7x_power_init();
set_spc_configuration();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function i dont see why it wouldnt just be called or even just put inline in the power init function, don't know why it is going in soc.c

Comment on lines 136 to 202
void nxp_mcxw7x_power_init(void)
{
/* Enable LPTMR0 as wakeup source */
NXP_ENABLE_WAKEUP_SIGNAL(0);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like the SPC code can just go in here

}
#endif

extern void nxp_mcxw7x_power_init(void);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be declared in soc.h with a mock ie #else #define nxp_mcxw7x_power_init(...) #endif

Comment on lines 11 to 19
#include <fsl_wuu.h>

#define PORT_MUX_GPIO kPORT_MuxAsGpio

#define nbu_handler RF_IMU0_IRQHandler

#undef NXP_ENABLE_WAKEUP_SIGNAL
#define NXP_ENABLE_WAKEUP_SIGNAL(sig) WUU_SetInternalWakeUpModulesConfig(WUU0,\
sig, kWUU_InternalModuleInterrupt);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed previously, we should not be adding hal headers into soc.h anymore, instead this macro should evaluate to a wrapper function declared in this file and defined in power.c

Comment on lines +52 to +53
/* Set PRIMASK */
__disable_irq();
/* Set BASEPRI to 0 */
irq_unlock(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should not be necessary, already done by arch code last time I checked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is needed. We can discuss where you see this implemented.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(void) arch_irq_lock();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


#undef NXP_ENABLE_WAKEUP_SIGNAL
#define NXP_ENABLE_WAKEUP_SIGNAL(sig) WUU_SetInternalWakeUpModulesConfig(WUU0,\
sig, kWUU_InternalModuleInterrupt);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @bjarki-andreasen, it seems that the management of wakeup sources in zephyr is currently quite fragmented? Some wakeup sources are managed through device drivers, while others are managed at the SoC level (soc.c/.h). I would like to ask the power management maintainer if there are any plans to introduce a standardized/systematized wakeup source management system. Thanks.

Copy link
Member

@decsny decsny Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ZhaoxiangJin it was a discussion a lot the last few years. but what you should know here is in our case that we intend to manage all of them by device driver. this soc.h define idea is to have a common api across all nxp platform that the nxp driver can call. but yes, this approach is just how nxp does it, but I think it will work for us, and is not exposed actually to client code. issue only would arise if NXP platform for some reason used some non-nxp driver for an soc peripheral or vice versa (which, is not impossible, since some IP can come from third party designer that is on many different vendor SOC, but usually still there are changes and they write their own driver pretending it's not third party is what I have noticed)

the way that is common in all of zephyr to declare/configure if something is a wakeup is by putting the wakeup-source property on it's node in DT.

void nxp_mcxw7x_power_init(void)
{
/* Enable LPTMR0 as wakeup source */
NXP_ENABLE_WAKEUP_SIGNAL(0);
Copy link
Contributor

@ZhaoxiangJin ZhaoxiangJin Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mcxw7x has many wakeup sources. Users may need GPIO wake up, RTC wake up, or LPTMR wake up. However, based on the current approach, users cannot configure them. They can only refer to the SDK implementation or the SoC RM to know how to enable the wakeup sources they need here. Does this go against the Zephyr concept of configure hardware features based on the devicetree?

Currently, Zephyr does not have a wakeup source management subsystem. My view is that we need to describe the WUU information in the wakup source peripheral node, and then configure the WUU in the driver based on the information in the device tree.
As a SoC vendor, we need to enable all these wakeup sources in SoC.dts and driver. The user can use /delete-property/ is-wakeup-source; to remove wakeup sources they don't need in the board.dts or application.dts.

Copy link
Member

@decsny decsny Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mcxw7x has many wakeup sources. Users may need GPIO wake up, RTC wake up, or LPTMR wake up. However, based on the current approach, users cannot configure them. They can only refer to the SDK implementation or the SoC RM to know how to enable the wakeup sources they need here. Does this go against the Zephyr concept of configure hardware features based on the devicetree?

I think the reason mahesh put this here is because the lptmr in this case is chosen as the kernel timer when CONFIG_PM=y (hence building this function), so it is a system requirement that it should be a wakeup source, otherwise the system doesn't function. So it should not be left up to user configurability in this case. The LPTMR though can also be used just as a normal counter (not system timer) and in that case the wakeup-source property for configuration would be relevant and the counter driver should be responsible to call this macro to configure the wakeup source conditionally. But for system timer, it is not conditional, it is mandatory.

But, speaking of this line, @mmahadevan108 , this 0 is a magic number, is there not some identifier from the SDK that can mean LPTMR0 wakeup signal?

Currently, Zephyr does not have a wakeup source management subsystem. My view is that we need to describe the WUU information in the wakup source peripheral node, and then configure the WUU in the driver based on the information in the device tree. As a SoC vendor, we need to enable all these wakeup sources in SoC.dts and driver. The user can use /delete-property/ is-wakeup-source; to remove wakeup sources they don't need in the board.dts or application.dts.

No, I don't agree to this approach, nothing should be a wakeup by default, except the system timer. User should be explicit about what causes wakeup for their system, not try to figure out all the ones they need to disable, that is just annoying.

As for the discussion about how to do generic wakeup sources in zephyr, I think the current paradigm is well understood enough and sufficient , and we should avoid over architecting and causing churn across the whole project unless we really decide its actually needed, not just for pedantic reasons. But in an ideal world, probably each node would be putting some controller+data style info using phandle arrays in DT similar to the resets and interrupts and clocks property, about how to configure the wakeups, especially if one device can have different wakeup sources. But I think we should cross that bridge when we come to it, not just for the sake of it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can move this to the driver level. I have created PR #96996 for such cases where the wakeup signal is not mapped to the interrupt number.

@mmahadevan108 mmahadevan108 force-pushed the Power_MCXW71 branch 2 times, most recently from 5ea2df0 to 1c69397 Compare October 3, 2025 22:24
Comment on lines +23 to +27
void mcxw7xx_set_wakeup(int32_t sig)
{
WUU_SetInternalWakeUpModulesConfig(WUU0, sig, kWUU_InternalModuleInterrupt);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should go in power.c

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Power.c gets compiled only when PM is enabled. This could get called without PM enabled as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you be configuring wake up from low power modes if you don't enter them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some drivers may not have CONFIG_PM wrapper added. I don't see a negative to putting this in soc.c

Comment on lines +20 to +22
#if CONFIG_PM
extern void nxp_mcxw7x_power_init(void);
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not what extern is for, remove that, and declare a mock

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats wrong with having an extern?

#define nbu_handler RF_IMU0_IRQHandler

#undef NXP_ENABLE_WAKEUP_SIGNAL
extern void mcxw7xx_set_wakeup(int32_t sig);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extern is redundant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was seeing warning without it, so seems needed.

Comment on lines +243 to +245
#if CONFIG_PM
nxp_mcxw7x_power_init();
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove #if

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had a discussion with @DerekSnell about this and we felt it best we make the changes to power only for PM as we want some of the voltage detects to stay enabled and the low voltage config is needed only for low power modes.

Comment on lines 12 to +17
default 96000000 if CORTEX_M_SYSTICK
default $(dt_node_int_prop_int,$(DT_LPTMR_PATH),clock-frequency) if MCUX_LPTMR_TIMER
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does that happen?

Comment on lines +52 to +53
/* Set PRIMASK */
__disable_irq();
/* Set BASEPRI to 0 */
irq_unlock(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(void) arch_irq_lock();

Comment on lines +74 to +78
/* Set MAIN_CORE and MAIN_WAKE power domain into sleep mode. */
config.clock_mode = kCMC_GateAllSystemClocksEnterLowPowerMode;
config.main_domain = kCMC_SleepMode;
config.wake_domain = kCMC_SleepMode;
CMC_EnterLowPowerMode(CMC0, &config);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not be setting domain states in the SOC power driver, this is backwards. the state of the domains should be handled by domain drivers and the result will affect what actual SOC state is selected in the first place based on device runtime PM constraints. cc @bjarki-andreasen

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optimally the devicetree would contain the power domains which manage the main and wake domains, if anything needs them to be resumed, the power domains would be resumed directly (thus not in sleep mode) and the sleep mode which can only be entered if they are suspended, would have been blocked by the drivers/power domains with pm_policy_state_lock_get() or similar.

That said, some hardware is just quirky, it may make no sense to manage these power domains independently, which is maybe hinted at by the CMC_EnterLowPowerMode(CMC0, &config); taking one config which configures all of them together, so this may just be the way to enter one particular sleep mode.

Add support for power management states

Signed-off-by: Mahesh Mahadevan <[email protected]>
Add bindings for the power related modules. Use the bindings
Kconfig to pull in SDK drivers for cmc, spc, vbat and wuu.

Signed-off-by: Mahesh Mahadevan <[email protected]>
Add PM support for MCXW SoC's

Signed-off-by: Mahesh Mahadevan <[email protected]>
Copy link

sonarqubecloud bot commented Oct 6, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants