pm: device_runtime: suspend device on enable
The pm_device_runtime_enable did not suspend devices, so it assumed that the device was in a physically suspended state. This change makes sure that device is left in a suspended state if the device is initially active. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
parent
d6ebab55f3
commit
91b8abfb4d
4 changed files with 34 additions and 7 deletions
|
@ -142,23 +142,28 @@ special synchronization is required.
|
|||
|
||||
To enable device runtime power management on a device, the driver needs to call
|
||||
:c:func:`pm_device_runtime_enable` at initialization time. Note that this
|
||||
function will put the device into the :c:enumerator:`PM_DEVICE_STATE_SUSPENDED`
|
||||
state. In case this does not reflect the actual device state, the init function
|
||||
must perform the necessary operations to suspend the device.
|
||||
function will suspend the device if its state is
|
||||
:c:enumerator:`PM_DEVICE_STATE_ACTIVE`. In case the device is physically
|
||||
suspended, the init function should call
|
||||
:c:func:`pm_device_runtime_init_suspended` before calling
|
||||
:c:func:`pm_device_runtime_enable`.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* device driver initialization function */
|
||||
static int mydev_init(const struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
...
|
||||
/* make sure the device physically is suspended */
|
||||
|
||||
/* OPTIONAL: mark device as suspended if it is physically suspended */
|
||||
pm_device_runtime_init_suspended(dev);
|
||||
|
||||
/* enable device runtime power management */
|
||||
ret = pm_device_runtime_enable(dev);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
if ((ret < 0) && (ret != -ENOSYS)) {
|
||||
return ret;
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
Assuming an example device driver that implements an ``operation`` API call, the
|
||||
|
|
|
@ -25,6 +25,9 @@ extern "C" {
|
|||
/**
|
||||
* @brief Enable device runtime PM
|
||||
*
|
||||
* This function will enable runtime PM on the given device. If the device is
|
||||
* in #PM_DEVICE_STATE_ACTIVE state, the device will be suspended.
|
||||
*
|
||||
* @funcprops \pre_kernel_ok
|
||||
*
|
||||
* @param dev Device instance.
|
||||
|
@ -32,6 +35,9 @@ extern "C" {
|
|||
* @retval 0 If the device runtime PM is enabled successfully.
|
||||
* @retval -EPERM If device has power state locked.
|
||||
* @retval -ENOSYS If the functionality is not available.
|
||||
* @retval -errno Other negative errno, result of suspending the device.
|
||||
*
|
||||
* @see pm_device_runtime_init_suspended()
|
||||
*/
|
||||
int pm_device_runtime_enable(const struct device *dev);
|
||||
|
||||
|
|
|
@ -188,6 +188,14 @@ int pm_device_runtime_enable(const struct device *dev)
|
|||
pm->dev = dev;
|
||||
k_work_init_delayable(&pm->work, runtime_suspend_work);
|
||||
}
|
||||
|
||||
if (pm->state == PM_DEVICE_STATE_ACTIVE) {
|
||||
ret = pm->action_cb(pm->dev, PM_DEVICE_ACTION_SUSPEND);
|
||||
if (ret < 0) {
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
pm->state = PM_DEVICE_STATE_SUSPENDED;
|
||||
pm->usage = 0U;
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ static void get_runner(void *arg1, void *arg2, void *arg3)
|
|||
static void test_api_setup(void)
|
||||
{
|
||||
int ret;
|
||||
enum pm_device_state state;
|
||||
|
||||
/* check API always returns 0 when runtime PM is disabled */
|
||||
ret = pm_device_runtime_get(dev);
|
||||
|
@ -47,6 +48,13 @@ static void test_api_setup(void)
|
|||
/* enable runtime PM */
|
||||
ret = pm_device_runtime_enable(dev);
|
||||
zassert_equal(ret, 0, NULL);
|
||||
|
||||
(void)pm_device_state_get(dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED, NULL);
|
||||
|
||||
/* enabling again should succeed (no-op) */
|
||||
ret = pm_device_runtime_enable(dev);
|
||||
zassert_equal(ret, 0, NULL);
|
||||
}
|
||||
|
||||
static void test_api_teardown(void)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue