From 1608c8adba51092eaf8b566cb377ea817b15994d Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Wed, 15 Jun 2022 11:36:53 +0200 Subject: [PATCH] pm: Introduce CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE Sometimes we want to entirely decouple the system PM from the device PM, leaving the devices to manage its own power states using the runtime PM. This is currently not possible because the suspend / resume code path is triggering the device PM hooks even when the runtime PM is enabled. Introduce a new PM_DEVICE_RUNTIME_EXCLUSIVE symbol to allow the platform to skip the device PM triggers on suspend / resume. Signed-off-by: Carlo Caione --- subsys/pm/Kconfig | 8 ++++++++ subsys/pm/pm.c | 8 +++++--- tests/subsys/pm/power_mgmt/prj.conf | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index 9cc972922f6..5b968c2756e 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -103,6 +103,14 @@ config PM_DEVICE_RUNTIME enabled, devices can be suspended or resumed based on the device usage even while the CPU or system is running. +config PM_DEVICE_RUNTIME_EXCLUSIVE + depends on PM_DEVICE_RUNTIME + bool "Use only on Runtime Power Management on system suspend / resume" + default y + help + On system suspend / resume do not trigger the Device PM hooks but + only rely on Runtime PM to manage the devices power states. + endif # PM_DEVICE endmenu diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index 5c3537f4f23..85b2820f6f5 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -43,7 +43,7 @@ static struct pm_state_info z_cpus_pm_forced_state[] = { static struct k_spinlock pm_forced_state_lock; -#ifdef CONFIG_PM_DEVICE +#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) static atomic_t z_cpus_active = ATOMIC_INIT(CONFIG_MP_NUM_CPUS); #endif static struct k_spinlock pm_notifier_lock; @@ -52,6 +52,7 @@ static struct k_spinlock pm_notifier_lock; #ifdef CONFIG_PM_DEVICE extern const struct device *__pm_device_slots_start[]; +#if !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) /* Number of devices successfully suspended. */ static size_t num_susp; @@ -105,6 +106,7 @@ static void pm_resume_devices(void) num_susp = 0; } +#endif /* !CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE */ #endif /* CONFIG_PM_DEVICE */ static inline void pm_exit_pos_ops(struct pm_state_info *info) @@ -238,7 +240,7 @@ bool pm_system_suspend(int32_t ticks) true); } -#if CONFIG_PM_DEVICE +#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) if ((z_cpus_pm_state[id].state != PM_STATE_RUNTIME_IDLE) && (atomic_sub(&z_cpus_active, 1) == 1)) { if (pm_suspend_devices()) { @@ -269,7 +271,7 @@ bool pm_system_suspend(int32_t ticks) pm_stats_stop(); /* Wake up sequence starts here */ -#if CONFIG_PM_DEVICE +#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) if (atomic_add(&z_cpus_active, 1) == 0) { pm_resume_devices(); } diff --git a/tests/subsys/pm/power_mgmt/prj.conf b/tests/subsys/pm/power_mgmt/prj.conf index 2401fe109dd..7e9c0b8b7a1 100644 --- a/tests/subsys/pm/power_mgmt/prj.conf +++ b/tests/subsys/pm/power_mgmt/prj.conf @@ -4,3 +4,4 @@ CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y CONFIG_PM_POLICY_CUSTOM=y CONFIG_MP_NUM_CPUS=1 +CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n