diff --git a/doc/reference/power_management/index.rst b/doc/reference/power_management/index.rst index b7d41f2d99f..7807e846283 100644 --- a/doc/reference/power_management/index.rst +++ b/doc/reference/power_management/index.rst @@ -253,16 +253,6 @@ The four device power states: Most device context is lost by the hardware. Device drivers must save and restore or reinitialize any context lost by the hardware. -:code:`PM_DEVICE_STATE_SUSPENDING` - - Device is currently transitioning from :c:macro:`PM_DEVICE_STATE_ACTIVE` to - :c:macro:`PM_DEVICE_STATE_SUSPENDED`. - -:code:`PM_DEVICE_STATE_RESUMING` - - Device is currently transitioning from :c:macro:`PM_DEVICE_STATE_SUSPENDED` - to :c:macro:`PM_DEVICE_STATE_ACTIVE`. - :code:`PM_DEVICE_STATE_OFF` Power has been fully removed from the device. The device context is lost diff --git a/include/pm/device.h b/include/pm/device.h index cc38fd4e718..5a5c52c17ae 100644 --- a/include/pm/device.h +++ b/include/pm/device.h @@ -48,11 +48,7 @@ enum pm_device_state { * @note * Device context is lost. */ - PM_DEVICE_STATE_OFF, - /** Device is being resumed. */ - PM_DEVICE_STATE_RESUMING, - /** Device is being suspended. */ - PM_DEVICE_STATE_SUSPENDING, + PM_DEVICE_STATE_OFF }; /** @brief Device PM flags. */ @@ -66,6 +62,8 @@ enum pm_device_flag { PM_DEVICE_FLAGS_WS_CAPABLE, /** Indicates if the device is being used as wakeup source. */ PM_DEVICE_FLAGS_WS_ENABLED, + /** Indicates that the device is changing its state */ + PM_DEVICE_FLAG_TRANSITIONING, /** Number of flags (internal use only). */ PM_DEVICE_FLAG_COUNT }; @@ -161,8 +159,9 @@ const char *pm_device_state_str(enum pm_device_state state); * * @retval 0 If successful. * @retval -ENOTSUP If requested state is not supported. - * @retval -EALREADY If device is already at (or transitioning to) the requested - * state. + * @retval -EALREADY If device is already at the requested state. + * @retval -EBUSY If device is changing its state. + * @retval Errno Other negative errno on failure. */ int pm_device_state_set(const struct device *dev, diff --git a/subsys/pm/device.c b/subsys/pm/device.c index 9e5baea7b6a..ec8f273accd 100644 --- a/subsys/pm/device.c +++ b/subsys/pm/device.c @@ -103,10 +103,13 @@ int pm_device_state_set(const struct device *dev, return -ENOSYS; } + if (atomic_test_bit(&dev->pm->flags, PM_DEVICE_FLAG_TRANSITIONING)) { + return -EBUSY; + } + switch (state) { case PM_DEVICE_STATE_SUSPENDED: - if ((dev->pm->state == PM_DEVICE_STATE_SUSPENDED) || - (dev->pm->state == PM_DEVICE_STATE_SUSPENDING)) { + if (dev->pm->state == PM_DEVICE_STATE_SUSPENDED) { return -EALREADY; } else if (dev->pm->state == PM_DEVICE_STATE_OFF) { return -ENOTSUP; @@ -115,8 +118,7 @@ int pm_device_state_set(const struct device *dev, action = PM_DEVICE_ACTION_SUSPEND; break; case PM_DEVICE_STATE_ACTIVE: - if ((dev->pm->state == PM_DEVICE_STATE_ACTIVE) || - (dev->pm->state == PM_DEVICE_STATE_RESUMING)) { + if (dev->pm->state == PM_DEVICE_STATE_ACTIVE) { return -EALREADY; } diff --git a/subsys/pm/device_runtime.c b/subsys/pm/device_runtime.c index 6c74be02e73..b99a7d8c673 100644 --- a/subsys/pm/device_runtime.c +++ b/subsys/pm/device_runtime.c @@ -24,6 +24,9 @@ static void pm_device_runtime_state_set(struct pm_device *pm) const struct device *dev = pm->dev; int ret = 0; + /* Clear transitioning flags */ + atomic_clear_bit(&dev->pm->flags, PM_DEVICE_FLAG_TRANSITIONING); + switch (dev->pm->state) { case PM_DEVICE_STATE_ACTIVE: if ((dev->pm->usage == 0) && dev->pm->enable) { @@ -35,11 +38,6 @@ static void pm_device_runtime_state_set(struct pm_device *pm) ret = pm_device_state_set(dev, PM_DEVICE_STATE_ACTIVE); } break; - case PM_DEVICE_STATE_SUSPENDING: - __fallthrough; - case PM_DEVICE_STATE_RESUMING: - /* Do nothing: We are waiting for resume/suspend to finish */ - break; default: LOG_ERR("Invalid state!!\n"); } @@ -127,13 +125,13 @@ static int pm_device_request(const struct device *dev, /* Return in case of Async request */ if (pm_flags & PM_DEVICE_ASYNC) { + atomic_set_bit(&dev->pm->flags, PM_DEVICE_FLAG_TRANSITIONING); (void)k_work_schedule(&dev->pm->work, K_NO_WAIT); goto out_unlock; } while ((k_work_delayable_is_pending(&dev->pm->work)) || - (dev->pm->state == PM_DEVICE_STATE_SUSPENDING) || - (dev->pm->state == PM_DEVICE_STATE_RESUMING)) { + atomic_test_bit(&dev->pm->flags, PM_DEVICE_FLAG_TRANSITIONING)) { ret = k_condvar_wait(&dev->pm->condvar, &dev->pm->lock, K_FOREVER); if (ret != 0) { @@ -238,8 +236,7 @@ int pm_device_wait(const struct device *dev, k_timeout_t timeout) k_mutex_lock(&dev->pm->lock, K_FOREVER); while ((k_work_delayable_is_pending(&dev->pm->work)) || - (dev->pm->state == PM_DEVICE_STATE_SUSPENDING) || - (dev->pm->state == PM_DEVICE_STATE_RESUMING)) { + atomic_test_bit(&dev->pm->flags, PM_DEVICE_FLAG_TRANSITIONING)) { ret = k_condvar_wait(&dev->pm->condvar, &dev->pm->lock, timeout); if (ret != 0) {