From 2f99ff51ccd49c4baa6790f3bf2e27f359d643c1 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 28 Jul 2023 13:39:52 -0700 Subject: [PATCH] pm: Disable device pm per power state Make it possible to disble device power management individually per power state. This allows targets tuning which states should (and which should not) trigger device power management. Signed-off-by: Flavio Ceolin --- dts/bindings/power/zephyr,power-state.yaml | 6 ++++++ include/zephyr/pm/state.h | 12 ++++++++++++ subsys/pm/pm.c | 3 ++- tests/subsys/pm/device_wakeup_api/src/main.c | 2 +- tests/subsys/pm/power_states_api/src/main.c | 4 ++-- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/dts/bindings/power/zephyr,power-state.yaml b/dts/bindings/power/zephyr,power-state.yaml index 5c645306b58..4fe22d1c5db 100644 --- a/dts/bindings/power/zephyr,power-state.yaml +++ b/dts/bindings/power/zephyr,power-state.yaml @@ -31,3 +31,9 @@ properties: type: int description: | Worst case latency in microseconds required to exit the idle state. + zephyr,pm-device-disabled: + type: boolean + description: | + Disable system managed device power management for this state. When set, + the power management subsystem will not suspend devices before entering + this state. diff --git a/include/zephyr/pm/state.h b/include/zephyr/pm/state.h index cc387879411..e5866953f37 100644 --- a/include/zephyr/pm/state.h +++ b/include/zephyr/pm/state.h @@ -134,12 +134,22 @@ struct pm_state_info { * substate-id = <2>; * min-residency-us = <20000>; * exit-latency-us = <200>; + * zephyr,pm-device-disabled; * }; * }; * @endcode */ uint8_t substate_id; + /** + * Whether or not this state triggers device power management. + * + * When this property is false the power management subsystem + * will suspend devices before entering this state and will + * properly resume them when leaving it. + */ + bool pm_device_disabled; + /** * Minimum residency duration in microseconds. It is the minimum * time for a given idle state to be worthwhile energywise. @@ -209,6 +219,7 @@ struct pm_state_info { .substate_id = DT_PROP_OR(node_id, substate_id, 0), \ .min_residency_us = DT_PROP_OR(node_id, min_residency_us, 0), \ .exit_latency_us = DT_PROP_OR(node_id, exit_latency_us, 0), \ + .pm_device_disabled = DT_PROP(node_id, zephyr_pm_device_disabled), \ } /** @@ -260,6 +271,7 @@ struct pm_state_info { * power-state-name = "suspend-to-ram"; * min-residency-us = <50000>; * exit-latency-us = <500>; + * zephyr,pm-device-disabled; * }; * }; * }; diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index 96ca35cdbe9..6f5cca1452f 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -205,7 +205,8 @@ bool pm_system_suspend(int32_t ticks) #if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) if (atomic_sub(&_cpus_active, 1) == 1) { - if (z_cpus_pm_state[id].state != PM_STATE_RUNTIME_IDLE) { + if ((z_cpus_pm_state[id].state != PM_STATE_RUNTIME_IDLE) && + !z_cpus_pm_state[id].pm_device_disabled) { if (pm_suspend_devices()) { pm_resume_devices(); z_cpus_pm_state[id].state = PM_STATE_ACTIVE; diff --git a/tests/subsys/pm/device_wakeup_api/src/main.c b/tests/subsys/pm/device_wakeup_api/src/main.c index cf8d7e2f3c3..6a45f3ffe79 100644 --- a/tests/subsys/pm/device_wakeup_api/src/main.c +++ b/tests/subsys/pm/device_wakeup_api/src/main.c @@ -61,7 +61,7 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) { static const struct pm_state_info state = { - .state = PM_STATE_SUSPEND_TO_RAM + .state = PM_STATE_SUSPEND_TO_RAM, }; ARG_UNUSED(cpu); diff --git a/tests/subsys/pm/power_states_api/src/main.c b/tests/subsys/pm/power_states_api/src/main.c index 3699bc0d3ff..dac96e9e299 100644 --- a/tests/subsys/pm/power_states_api/src/main.c +++ b/tests/subsys/pm/power_states_api/src/main.c @@ -11,8 +11,8 @@ /* Last state has not declared a minimum residency, so it should be * set the default 0 value */ -static struct pm_state_info infos[] = {{PM_STATE_SUSPEND_TO_IDLE, 0, 10000, 100}, - {PM_STATE_SUSPEND_TO_RAM, 0, 50000, 500}, {PM_STATE_STANDBY, 0, 0}}; +static struct pm_state_info infos[] = {{PM_STATE_SUSPEND_TO_IDLE, 0, false, 10000, 100}, + {PM_STATE_SUSPEND_TO_RAM, 0, false, 50000, 500}, {PM_STATE_STANDBY, 0, false, 0}}; static enum pm_state states[] = {PM_STATE_SUSPEND_TO_IDLE, PM_STATE_SUSPEND_TO_RAM, PM_STATE_STANDBY}; static enum pm_state wrong_states[] = {PM_STATE_SUSPEND_TO_DISK,