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,