Skip to content

NXP imx95 add basic pm support #91410

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

yongxu-wang15
Copy link
Contributor

added basic pm support for imx95 evk m7 board, verified it in power_mgmt_soc test case, based on this case, M7 can enter/exit wait/suspend mode as we expected.

@yongxu-wang15 yongxu-wang15 force-pushed the nxp-imx95-add-basic-pm-support branch 2 times, most recently from 9ab89c6 to 44fd99b Compare June 12, 2025 01:29
@yongxu-wang15 yongxu-wang15 changed the title Nxp imx95 add basic pm support NXP imx95 add basic pm support Jun 12, 2025
@yongxu-wang15
Copy link
Contributor Author

yongxu-wang15 commented Jun 18, 2025

hi @ceolin @bjarki-andreasen @yangbolu1991, @JiafeiPan , can you help review this pr when you time free? its basic pm support for imx95 m7 core, thanks

{
struct k_thread *current = k_current_get();

return strcmp(k_thread_name_get(current), "idle") == 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

use z_is_idle_thread_object(current) ?

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 internal to kernel, but yep, this is better than check the name that depends on CONFIG_THREAD_NAME

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks, have updated

@@ -158,6 +158,13 @@ static int scmi_send_message_post_kernel(struct scmi_protocol *proto,
return ret;
}

bool scmi_is_current_thread_idle(void)
Copy link
Contributor

Choose a reason for hiding this comment

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

static ?

* the sm interrupt should be disabled in the soc low power phase.
* In this case, the pre kernel is used instead of the post kernel.
*/
use_pre_kernel_path = use_pre_kernel_path || scmi_is_current_thread_idle();
Copy link
Contributor

Choose a reason for hiding this comment

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

use_pre_kernel_path |= scmi_is_current_thread_idle();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks, updated

irq_unlock(0);

/* disabled system manager irq */
irq_disable(DT_IRQN(DT_NODELABEL(mu5)));
Copy link
Contributor

Choose a reason for hiding this comment

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

Would you please help me to understand why still need to disable SM irq as you have already called __disable_irq(); which should have disable all interrupt?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the above code only mask irq to don't give reaction to interrupt, the capacity of wakeup Mcore from wfi is reserved, and the sm protocol use interrupt from scmi notification logic even though use scmi pre_kernel logic, so we need disabled mu5 now.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree @JiafeiPan i still don't get why mu5 irq needs to be disabled if IRQ's are disabled already.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. the system manager will reply message in currently mechanism, so we need keep mu5 is be disabled to not wakeup m7 core from wfi after run scmi interface api.
  2. the _disable_irq is to set PRIMASK register, it will mask all regular peripheral interrupt responce for cpu(such as m7 core), it mean that m7 can't enter nvic irq handler in this side, but this will not shield the triggering of interrupts, which will cause the CPU to be awakened from WFI. So in low power use case, although we have already set _disable_irq, but the cpu still have recognize this MU interrupt and thus leave WFI.

Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't then the system design of system manager flawed? And needs reconsideration?

I think Linux uses the same mechanism using SCMI for PM does that work well then?

Copy link
Contributor Author

@yongxu-wang15 yongxu-wang15 Jun 25, 2025

Choose a reason for hiding this comment

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

in linux side, the low power flow is in atf side, the atf use another mu, the atf mu use polling mode and set non-interrupt in there, but it have not this distinguish in zephyr now, and this way is hard to dela with in zephyr as it need another MU hardware resource, I think we can set mu hardware interface into non-interrupt mode in per kernel send scmi message side, in this it can fix this issue from my understand.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes putting SCMI into non-interrupt mode for PM makes sense. Then poll response after wake up, this doesn't do busy waiting. Then after wakeup put SCMI MU into interrupt mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, have updated it, now in pre kernel process(include idle task pm case), it will disable shem completion interrupt and mu side interrupt, and resume it after send message done. please help review it again

scmi_cpu_sleep_mode_set(&cpu_cfg);
__DSB();
__WFI();
__ISB();
Copy link
Contributor

Choose a reason for hiding this comment

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

whether need ISB after WFI

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated. thanks

Copy link
Contributor

@bjarki-andreasen bjarki-andreasen left a comment

Choose a reason for hiding this comment

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

Don't know anything about SCMI, but at least some irq_disable() may be superfluous :)

Comment on lines 95 to 136
/* Set PRIMASK, Shield the CPU from responding to interrupts,
* the CPU will not jump to the interrupt service routine (ISR).
*/
__disable_irq();
/* Set BASEPRI to 0 */
irq_unlock(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

when we get here, irqs are already disabled by PM, see

(void) arch_irq_lock();

Copy link
Member

Choose a reason for hiding this comment

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

Maybe because this arch using BASEPRI instead of masking interruptions globally ? This is still confusing for me too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hi @ceolin @bjarki-andreasen , this is as imx95 m7 is based on ARMv7-M architecture, For this architecture, the current implementation of arch_irq_lock of zephyr is based on BASEPRI, which will only retain abnormal interrupts such as NMI,
and all other interrupts from the CPU(including systemtick) will be masked, which makes the CORE unable to be woken up from WFI. so we used primask rather than defaultly basepri in there

Copy link
Contributor

@bjarki-andreasen bjarki-andreasen Jun 20, 2025

Choose a reason for hiding this comment

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

is that a bug in the implementation of arch_irq_lock() for this arch? arch_irq_lock() is only supposed to block ISRs from being executed, not the CPU from waking up. Maybe a fix at arch level would be more fitting, or?

Copy link
Contributor Author

@yongxu-wang15 yongxu-wang15 Jun 20, 2025

Choose a reason for hiding this comment

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

if we want keep arch_irq_lock keep wakeup source capacity for all arch, it have some issue from my understand, its best to fix in top arch level, https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/arch/arm/cortex_m/exception.h#L53
image

{
struct k_thread *current = k_current_get();

return strcmp(k_thread_name_get(current), "idle") == 0;
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 internal to kernel, but yep, this is better than check the name that depends on CONFIG_THREAD_NAME

};

power-states {
active: power-state-active {
Copy link
Member

Choose a reason for hiding this comment

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

What this state means ? Power states are used by the power management subsystem and are used only by the idle thread.

Since you don't have any special treatment for this state in pm_state_set you can remove it. This way the power subsystem won't find a suitable state and will just sit idle (wfi or wfe).

If you keep it the idle thread will continuously loop issuing pm_state_set and pm_state_exit_post_ops

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks reminder, have deleted it

Comment on lines 95 to 136
/* Set PRIMASK, Shield the CPU from responding to interrupts,
* the CPU will not jump to the interrupt service routine (ISR).
*/
__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.

Maybe because this arch using BASEPRI instead of masking interruptions globally ? This is still confusing for me too.

Copy link
Contributor

@PetervdPerk-NXP PetervdPerk-NXP left a comment

Choose a reason for hiding this comment

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

Could you verify if the systick is actually capable of waking up the core when doing wfi?
We've seen some issues with this, that other interrupts can wake the m7 but the systisck doesn't thus giving big delays.

@yongxu-wang15 yongxu-wang15 force-pushed the nxp-imx95-add-basic-pm-support branch from 44fd99b to d9fc857 Compare June 20, 2025 03:20
@yongxu-wang15
Copy link
Contributor Author

hi @PetervdPerk-NXP , in my side, the system tick work fine on this patch

Copy link
Contributor

@bjarki-andreasen bjarki-andreasen left a comment

Choose a reason for hiding this comment

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

Regarding __disable_irq(), its soc dependent, so if it works, its fine. Regarding using internal kernel apis to check for idle thread context, that seems like a clear layering violation, and I have proposed a solution which seems to be more appropriate :)

@yongxu-wang15 yongxu-wang15 force-pushed the nxp-imx95-add-basic-pm-support branch from 4708bc7 to c966036 Compare June 26, 2025 09:40
added wait/stop/suspend pm node for imx95 m7

Signed-off-by: Yongxu Wang <[email protected]>
add basic pm_state_set and pm_state_exit_post_ops

Signed-off-by: Yongxu Wang <[email protected]>
enable imx95_evk m7 for this power_mgmt_soc test case

Signed-off-by: Yongxu Wang <[email protected]>
@yongxu-wang15 yongxu-wang15 force-pushed the nxp-imx95-add-basic-pm-support branch from c966036 to fe2807b Compare July 3, 2025 08:26
@yongxu-wang15
Copy link
Contributor Author

yongxu-wang15 commented Jul 3, 2025

update this patch to re-name cpu into cpu0: cpu@0 in order to align pm test case, please help review this pr when time free, thanks a lot

SCMI now supports both polling and interrupt modes to determine
message completion. By default, polling is used during
the pre-kernel phase, while interrupts are used post-kernel.

However, for certain SCMI APIs related to power management (PM),
although they are invoked post-kernel, using interrupt mode
may cause unintended CPU wakeups. To prevent this,
polling mode should be used instead.

This patch extends the scmi_send_message() interface by
adding a 'pre_kernel' parameter, allowing callers to explicitly
indicate the desired behavior based on context,
rather than relying on internal kernel state detection.

Signed-off-by: Yongxu Wang <[email protected]>
in pre kernel scmi send message process, it should use poll to receive
system manager core notification, add disable and re-enable
completion interrupt in this flow.

Signed-off-by: Yongxu Wang <[email protected]>
@yongxu-wang15 yongxu-wang15 force-pushed the nxp-imx95-add-basic-pm-support branch from fe2807b to 866dd58 Compare July 22, 2025 07:10
@zephyrbot zephyrbot added the platform: NXP Drivers NXP Semiconductors, drivers label Jul 22, 2025
add scmi_cpu_pd_lpm_set api for nxp imx scmi interface

Signed-off-by: Yongxu Wang <[email protected]>
wakeupmix keep power on state is essential for system
suspend mode, because of console uart locate in it.

temporarily set the M7 mix to power on,
further optimization will be carried out later

Signed-off-by: Yongxu Wang <[email protected]>
@yongxu-wang15 yongxu-wang15 force-pushed the nxp-imx95-add-basic-pm-support branch from 866dd58 to 138eef8 Compare July 22, 2025 08:07
@yongxu-wang15
Copy link
Contributor Author

yongxu-wang15 commented Jul 22, 2025

newly update:

  1. from @bjarki-andreasen suggestion, add pre_kernel variable into scmi_send_message api, and do kernel state judge in scmi higher level api
  2. add scmi nxp cpu lpm interface, and set M7/wakeup mix to keep power on state when m7 cpu enter suspend mode

Copy link

Copy link
Contributor

@bjarki-andreasen bjarki-andreasen left a comment

Choose a reason for hiding this comment

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

Nice work! looks clean :)

@bjarki-andreasen
Copy link
Contributor

ping @ceolin

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

Successfully merging this pull request may close these issues.

6 participants