2021-04-29 13:32:28 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015 Intel Corporation.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef ZEPHYR_INCLUDE_PM_DEVICE_H_
|
|
|
|
#define ZEPHYR_INCLUDE_PM_DEVICE_H_
|
|
|
|
|
|
|
|
#include <kernel.h>
|
|
|
|
#include <sys/atomic.h>
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Device Power Management API
|
|
|
|
*
|
|
|
|
* @defgroup device_power_management_api Device Power Management API
|
|
|
|
* @ingroup power_management_api
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct device;
|
|
|
|
|
2021-06-03 19:06:53 +02:00
|
|
|
/** @brief Device power states. */
|
|
|
|
enum pm_device_state {
|
|
|
|
/** Device is in active or regular state. */
|
|
|
|
PM_DEVICE_STATE_ACTIVE,
|
|
|
|
/**
|
|
|
|
* Device is in low power state.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* Device context is preserved.
|
|
|
|
*/
|
|
|
|
PM_DEVICE_STATE_LOW_POWER,
|
|
|
|
/**
|
|
|
|
* Device is suspended.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* Device context may be lost.
|
|
|
|
*/
|
|
|
|
PM_DEVICE_STATE_SUSPEND,
|
|
|
|
/**
|
|
|
|
* Device is suspended (forced).
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* Device context may be lost.
|
|
|
|
*/
|
|
|
|
PM_DEVICE_STATE_FORCE_SUSPEND,
|
|
|
|
/**
|
|
|
|
* Device is turned off (power removed).
|
|
|
|
*
|
|
|
|
* @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,
|
|
|
|
};
|
2021-04-28 09:48:52 -07:00
|
|
|
|
2021-07-14 11:05:34 +02:00
|
|
|
/** @brief Device PM flags. */
|
|
|
|
enum pm_device_flag {
|
|
|
|
/** Indicate if the device is busy or not. */
|
|
|
|
PM_DEVICE_FLAG_BUSY,
|
|
|
|
/** Number of flags (internal use only). */
|
|
|
|
PM_DEVICE_FLAG_COUNT
|
|
|
|
};
|
|
|
|
|
2021-04-29 13:32:28 +02:00
|
|
|
/**
|
|
|
|
* @brief Device PM info
|
|
|
|
*/
|
2021-05-03 17:42:31 +02:00
|
|
|
struct pm_device {
|
2021-04-29 13:32:28 +02:00
|
|
|
/** Pointer to the device */
|
|
|
|
const struct device *dev;
|
|
|
|
/** Lock to synchronize the get/put operations */
|
2021-05-20 14:47:04 -07:00
|
|
|
struct k_mutex lock;
|
2021-04-29 13:32:28 +02:00
|
|
|
/* Following are packed fields protected by #lock. */
|
|
|
|
/** Device pm enable flag */
|
|
|
|
bool enable : 1;
|
2021-07-14 11:05:34 +02:00
|
|
|
/* Device PM status flags. */
|
|
|
|
ATOMIC_DEFINE(flags, PM_DEVICE_FLAG_COUNT);
|
2021-04-29 13:32:28 +02:00
|
|
|
/** Device usage count */
|
2021-05-14 16:50:23 -07:00
|
|
|
uint32_t usage;
|
2021-06-03 19:06:53 +02:00
|
|
|
/** Device power state */
|
|
|
|
enum pm_device_state state;
|
2021-04-29 13:32:28 +02:00
|
|
|
/** Work object for asynchronous calls */
|
2021-04-26 22:37:42 -07:00
|
|
|
struct k_work_delayable work;
|
|
|
|
/** Event conditional var to listen to the sync request events */
|
|
|
|
struct k_condvar condvar;
|
2021-04-29 13:32:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get name of device PM state
|
|
|
|
*
|
|
|
|
* @param state State id which name should be returned
|
|
|
|
*/
|
2021-06-03 19:06:53 +02:00
|
|
|
const char *pm_device_state_str(enum pm_device_state state);
|
2021-04-29 13:32:28 +02:00
|
|
|
|
2021-05-03 18:12:17 +02:00
|
|
|
/**
|
|
|
|
* @brief Call the set power state function of a device
|
|
|
|
*
|
|
|
|
* Called by the application or power management service to let the device do
|
|
|
|
* required operations when moving to the required power state
|
|
|
|
* Note that devices may support just some of the device power states
|
|
|
|
* @param dev Pointer to device structure of the driver instance.
|
|
|
|
* @param device_power_state Device power state to be set
|
|
|
|
*
|
|
|
|
* @retval 0 If successful in queuing the request or changing the state.
|
2021-06-04 12:30:35 +02:00
|
|
|
* @retval Errno Negative errno code if failure.
|
2021-05-03 18:12:17 +02:00
|
|
|
*/
|
2021-06-03 19:06:53 +02:00
|
|
|
int pm_device_state_set(const struct device *dev,
|
2021-06-04 12:30:35 +02:00
|
|
|
enum pm_device_state device_power_state);
|
2021-05-03 18:12:17 +02:00
|
|
|
|
|
|
|
/**
|
2021-06-04 17:41:39 +02:00
|
|
|
* @brief Obtain the power state of a device.
|
2021-05-03 18:12:17 +02:00
|
|
|
*
|
2021-06-04 17:41:39 +02:00
|
|
|
* @param dev Device instance.
|
|
|
|
* @param state Pointer where device power state will be stored.
|
2021-05-03 18:12:17 +02:00
|
|
|
*
|
|
|
|
* @retval 0 If successful.
|
2021-06-04 17:41:39 +02:00
|
|
|
* @retval -ENOSYS If device does not implement power management.
|
2021-05-03 18:12:17 +02:00
|
|
|
*/
|
2021-06-03 19:06:53 +02:00
|
|
|
int pm_device_state_get(const struct device *dev,
|
2021-06-04 17:41:39 +02:00
|
|
|
enum pm_device_state *state);
|
2021-05-03 18:12:17 +02:00
|
|
|
|
2021-05-31 15:24:34 +02:00
|
|
|
#ifdef CONFIG_PM_DEVICE
|
|
|
|
/**
|
|
|
|
* @brief Indicate that the device is in the middle of a transaction
|
|
|
|
*
|
|
|
|
* Called by a device driver to indicate that it is in the middle of a
|
|
|
|
* transaction.
|
|
|
|
*
|
|
|
|
* @param dev Pointer to device structure of the driver instance.
|
|
|
|
*/
|
|
|
|
void pm_device_busy_set(const struct device *dev);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Indicate that the device has completed its transaction
|
|
|
|
*
|
|
|
|
* Called by a device driver to indicate the end of a transaction.
|
|
|
|
*
|
|
|
|
* @param dev Pointer to device structure of the driver instance.
|
|
|
|
*/
|
|
|
|
void pm_device_busy_clear(const struct device *dev);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Check if any device is in the middle of a transaction
|
|
|
|
*
|
|
|
|
* Called by an application to see if any device is in the middle
|
|
|
|
* of a critical transaction that cannot be interrupted.
|
|
|
|
*
|
2021-07-29 11:07:27 +02:00
|
|
|
* @retval false if no device is busy
|
|
|
|
* @retval true if any device is busy
|
2021-05-31 15:24:34 +02:00
|
|
|
*/
|
2021-07-29 11:07:27 +02:00
|
|
|
bool pm_device_is_any_busy(void);
|
2021-05-31 15:24:34 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Check if a specific device is in the middle of a transaction
|
|
|
|
*
|
|
|
|
* Called by an application to see if a particular device is in the
|
|
|
|
* middle of a critical transaction that cannot be interrupted.
|
|
|
|
*
|
2021-07-29 17:02:49 +02:00
|
|
|
* @param dev Pointer to device structure of the specific device driver
|
2021-05-31 15:24:34 +02:00
|
|
|
* the caller is interested in.
|
2021-07-29 11:07:27 +02:00
|
|
|
* @retval false if the device is not busy
|
|
|
|
* @retval true if the device is busy
|
2021-05-31 15:24:34 +02:00
|
|
|
*/
|
2021-07-29 17:02:49 +02:00
|
|
|
bool pm_device_is_busy(const struct device *dev);
|
2021-05-31 15:24:34 +02:00
|
|
|
#else
|
|
|
|
static inline void pm_device_busy_set(const struct device *dev) {}
|
|
|
|
static inline void pm_device_busy_clear(const struct device *dev) {}
|
2021-07-29 11:07:27 +02:00
|
|
|
static inline bool pm_device_is_any_busy(void) { return false; }
|
2021-07-29 17:02:49 +02:00
|
|
|
static inline bool pm_device_is_busy(const struct device *dev) { return false; }
|
2021-05-31 15:24:34 +02:00
|
|
|
#endif
|
|
|
|
|
2021-07-30 13:17:08 +02:00
|
|
|
__deprecated static inline void device_busy_set(const struct device *dev)
|
|
|
|
{
|
|
|
|
pm_device_busy_set(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
__deprecated static inline void device_busy_clear(const struct device *dev)
|
|
|
|
{
|
|
|
|
pm_device_busy_clear(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
__deprecated static inline int device_any_busy_check(void)
|
|
|
|
{
|
|
|
|
return pm_device_is_any_busy() ? -EBUSY : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
__deprecated static inline int device_busy_check(const struct device *dev)
|
|
|
|
{
|
|
|
|
return pm_device_is_busy(dev) ? -EBUSY : 0;
|
|
|
|
}
|
|
|
|
|
2021-04-29 13:32:28 +02:00
|
|
|
/** Alias for legacy use of device_pm_control_nop */
|
|
|
|
#define device_pm_control_nop __DEPRECATED_MACRO NULL
|
|
|
|
|
|
|
|
/** @} */
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|