From 9adffd620a4f4fb4d393fe399adaa7ea2dd0d4d5 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 22 Nov 2021 15:32:17 -0800 Subject: [PATCH] pm: device: Add pm_device_action_run Devices PM callback receive an action and not a state. Add a new API that receives an action instead of a state. Signed-off-by: Flavio Ceolin --- include/pm/device.h | 19 +++++++++++++++++ subsys/pm/device.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/include/pm/device.h b/include/pm/device.h index 68826eadc41..bd512c234b7 100644 --- a/include/pm/device.h +++ b/include/pm/device.h @@ -293,6 +293,25 @@ int pm_device_state_set(const struct device *dev, int pm_device_state_get(const struct device *dev, enum pm_device_state *state); +/** + * @brief Run a pm action on a device. + * + * This function calls the device PM control callback so that the device does + * the necessary operations to execute the given action. + * + * @param dev Device instance. + * @param action Device pm action. + * + * @retval 0 If successful. + * @retval -ENOTSUP If requested state is not supported. + * @retval -EALREADY If device is already at the requested state. + * @retval -EBUSY If device is changing its state. + * @retval -ENOSYS If device does not support PM. + * @retval Errno Other negative errno on failure. + */ +int pm_device_action_run(const struct device *dev, + enum pm_device_action action); + #if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__) /** * @brief Mark a device as busy. diff --git a/subsys/pm/device.c b/subsys/pm/device.c index 54757b740e2..1df1d65ca5b 100644 --- a/subsys/pm/device.c +++ b/subsys/pm/device.c @@ -73,6 +73,57 @@ int pm_device_state_set(const struct device *dev, return 0; } +int pm_device_action_run(const struct device *dev, + enum pm_device_action action) +{ + int ret; + enum pm_device_state state; + struct pm_device *pm = dev->pm; + + if (pm == NULL) { + return -ENOSYS; + } + + switch (action) { + case PM_DEVICE_ACTION_FORCE_SUSPEND: + __fallthrough; + case PM_DEVICE_ACTION_SUSPEND: + if (pm->state == PM_DEVICE_STATE_SUSPENDED) { + return -EALREADY; + } else if (pm->state == PM_DEVICE_STATE_OFF) { + return -ENOTSUP; + } + + state = PM_DEVICE_STATE_SUSPENDED; + break; + case PM_DEVICE_ACTION_RESUME: + if (pm->state == PM_DEVICE_STATE_ACTIVE) { + return -EALREADY; + } + + state = PM_DEVICE_STATE_ACTIVE; + break; + case PM_DEVICE_ACTION_TURN_OFF: + if (pm->state == PM_DEVICE_STATE_OFF) { + return -EALREADY; + } + + state = PM_DEVICE_STATE_OFF; + break; + default: + return -ENOTSUP; + } + + ret = pm->action_cb(dev, action); + if (ret < 0) { + return ret; + } + + pm->state = state; + + return 0; +} + int pm_device_state_get(const struct device *dev, enum pm_device_state *state) {