power_mgmt: Update Power Management device driver API
Have one function that can be used for all possible device purposes using a control code instead of the suspend resume functions, makes it generic for device control. Added device power states. The older replaced APIs will be deprecated in a future patch Jira: ZEP-954 Change-Id: I6dd3ebfd0fde3546b2d8397f19842f5758fda0c4 Signed-off-by: Amir Kaplan <amir.kaplan@intel.com>
This commit is contained in:
parent
035ec8249d
commit
d305da61e9
3 changed files with 152 additions and 10 deletions
150
include/device.h
150
include/device.h
|
@ -29,6 +29,9 @@
|
||||||
* @defgroup device_model Device Model APIs
|
* @defgroup device_model Device Model APIs
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -119,6 +122,11 @@ extern "C" {
|
||||||
data, cfg_info, level, prio, api) \
|
data, cfg_info, level, prio, api) \
|
||||||
DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
|
DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
|
||||||
level, prio, api)
|
level, prio, api)
|
||||||
|
|
||||||
|
#define DEVICE_DEFINE(dev_name, drv_name, init_fn, control_fn, \
|
||||||
|
data, cfg_info, level, prio, api) \
|
||||||
|
DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
|
||||||
|
level, prio, api)
|
||||||
#else
|
#else
|
||||||
/**
|
/**
|
||||||
* @def DEVICE_INIT_PM
|
* @def DEVICE_INIT_PM
|
||||||
|
@ -142,7 +150,7 @@ extern "C" {
|
||||||
* @details The driver api is also set here, eliminating the need to do that
|
* @details The driver api is also set here, eliminating the need to do that
|
||||||
* during initialization.
|
* during initialization.
|
||||||
*/
|
*/
|
||||||
|
/* deprecated */
|
||||||
#define DEVICE_AND_API_INIT_PM(dev_name, drv_name, init_fn, device_pm_ops, \
|
#define DEVICE_AND_API_INIT_PM(dev_name, drv_name, init_fn, device_pm_ops, \
|
||||||
data, cfg_info, level, prio, api) \
|
data, cfg_info, level, prio, api) \
|
||||||
\
|
\
|
||||||
|
@ -160,19 +168,48 @@ extern "C" {
|
||||||
.driver_data = data \
|
.driver_data = data \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Create a default device_pm_ops for devices that do not call the
|
* @def DEVICE_DEFINE
|
||||||
* DEVICE_INIT_PM macro so that caller of hook functions
|
*
|
||||||
* need not check dev_pm_ops != NULL.
|
* @brief Create device object and set it up for boot time initialization,
|
||||||
|
* with the option to device_control.
|
||||||
|
*
|
||||||
|
* @copydetails DEVICE_AND_API_INIT
|
||||||
|
* @param control_fn Provides an initial pointer to the API function
|
||||||
|
* used by App to send control command to the driver.
|
||||||
|
* Can be empty function (device_control_nop) for not implementing.
|
||||||
*/
|
*/
|
||||||
extern struct device_pm_ops device_pm_ops_nop;
|
extern struct device_pm_ops device_pm_ops_nop;
|
||||||
|
#define DEVICE_DEFINE(dev_name, drv_name, init_fn, control_fn, \
|
||||||
|
data, cfg_info, level, prio, api) \
|
||||||
|
\
|
||||||
|
static struct device_config __config_##dev_name __used \
|
||||||
|
__attribute__((__section__(".devconfig.init"))) = { \
|
||||||
|
.name = drv_name, .init = (init_fn), \
|
||||||
|
.device_control = (control_fn), \
|
||||||
|
.dev_pm_ops = (&device_pm_ops_nop), \
|
||||||
|
.config_info = (cfg_info) \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
static struct device (__device_##dev_name) __used \
|
||||||
|
__attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \
|
||||||
|
.config = &(__config_##dev_name), \
|
||||||
|
.driver_api = api, \
|
||||||
|
.driver_data = data \
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Use the default device_control for devices that do not call the
|
||||||
|
* DEVICE_DEFINE macro so that caller of hook functions
|
||||||
|
* need not check device_control != NULL.
|
||||||
|
*/
|
||||||
#define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
|
#define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
|
||||||
level, prio, api) \
|
level, prio, api) \
|
||||||
DEVICE_AND_API_INIT_PM(dev_name, drv_name, init_fn, \
|
DEVICE_DEFINE(dev_name, drv_name, init_fn, \
|
||||||
&device_pm_ops_nop, data, cfg_info, \
|
device_control_nop, data, cfg_info, level, \
|
||||||
level, prio, api)
|
prio, api)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* deprecated */
|
||||||
#define DEVICE_INIT_PM(dev_name, drv_name, init_fn, device_pm_ops, \
|
#define DEVICE_INIT_PM(dev_name, drv_name, init_fn, device_pm_ops, \
|
||||||
data, cfg_info, level, prio) \
|
data, cfg_info, level, prio) \
|
||||||
DEVICE_AND_API_INIT_PM(dev_name, drv_name, init_fn, device_pm_ops, \
|
DEVICE_AND_API_INIT_PM(dev_name, drv_name, init_fn, device_pm_ops, \
|
||||||
|
@ -244,6 +281,7 @@ struct device;
|
||||||
* @param suspend Pointer to the handler for suspend operations
|
* @param suspend Pointer to the handler for suspend operations
|
||||||
* @param resume Pointer to the handler for resume operations
|
* @param resume Pointer to the handler for resume operations
|
||||||
*/
|
*/
|
||||||
|
/* deprecated */
|
||||||
struct device_pm_ops {
|
struct device_pm_ops {
|
||||||
int (*suspend)(struct device *device, int pm_policy);
|
int (*suspend)(struct device *device, int pm_policy);
|
||||||
int (*resume)(struct device *device, int pm_policy);
|
int (*resume)(struct device *device, int pm_policy);
|
||||||
|
@ -277,6 +315,47 @@ struct device_pm_ops {
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** @def DEVICE_PM_ACTIVE_STATE
|
||||||
|
*
|
||||||
|
* @brief device is in ACTIVE power state
|
||||||
|
*
|
||||||
|
* @details Normal operation of the device. All device context is retained.
|
||||||
|
*/
|
||||||
|
#define DEVICE_PM_ACTIVE_STATE 1
|
||||||
|
|
||||||
|
/** @def DEVICE_PM_LOW_POWER_STATE
|
||||||
|
*
|
||||||
|
* @brief device is in LOW power state
|
||||||
|
*
|
||||||
|
* @details Device context is preserved by the HW and need not be
|
||||||
|
* restored by the driver.
|
||||||
|
*/
|
||||||
|
#define DEVICE_PM_LOW_POWER_STATE 2
|
||||||
|
|
||||||
|
/** @def DEVICE_PM_SUSPEND_STATE
|
||||||
|
*
|
||||||
|
* @brief device is in SUSPEND power state
|
||||||
|
*
|
||||||
|
* @details Most device context is lost by the hardware.
|
||||||
|
* Device drivers must save and restore or reinitialize any context
|
||||||
|
* lost by the hardware
|
||||||
|
*/
|
||||||
|
#define DEVICE_PM_SUSPEND_STATE 3
|
||||||
|
|
||||||
|
/** @def DEVICE_PM_OFF_STATE
|
||||||
|
*
|
||||||
|
* @brief device is in OFF power state
|
||||||
|
*
|
||||||
|
* @details - Power has been fully removed from the device.
|
||||||
|
* The device context is lost when this state is entered, so the OS
|
||||||
|
* software will reinitialize the device when powering it back on
|
||||||
|
*/
|
||||||
|
#define DEVICE_PM_OFF_STATE 4
|
||||||
|
|
||||||
|
/* Constants defining support device power commands */
|
||||||
|
#define DEVICE_PM_SET_POWER_STATE 1
|
||||||
|
#define DEVICE_PM_GET_POWER_STATE 2
|
||||||
#else
|
#else
|
||||||
#define DEFINE_DEVICE_PM_OPS(_name, _suspend, _resume)
|
#define DEFINE_DEVICE_PM_OPS(_name, _suspend, _resume)
|
||||||
#define DEVICE_PM_OPS_GET(_name) NULL
|
#define DEVICE_PM_OPS_GET(_name) NULL
|
||||||
|
@ -293,6 +372,8 @@ struct device_config {
|
||||||
int (*init)(struct device *device);
|
int (*init)(struct device *device);
|
||||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||||
struct device_pm_ops *dev_pm_ops;
|
struct device_pm_ops *dev_pm_ops;
|
||||||
|
int (*device_control)(struct device *device, uint32_t command,
|
||||||
|
void *context);
|
||||||
#endif
|
#endif
|
||||||
void *config_info;
|
void *config_info;
|
||||||
};
|
};
|
||||||
|
@ -404,6 +485,59 @@ static inline int device_resume(struct device *device, int pm_policy)
|
||||||
return device->config->dev_pm_ops->resume(device, pm_policy);
|
return device->config->dev_pm_ops->resume(device, pm_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief No-op function to initialize unimplemented hook
|
||||||
|
*
|
||||||
|
* This function should be used to initialize device hook
|
||||||
|
* for which a device has no operation.
|
||||||
|
*
|
||||||
|
* @param unused_device Unused
|
||||||
|
* @param unused_ctrl_command Unused
|
||||||
|
* @param unused_context Unused
|
||||||
|
*
|
||||||
|
* @retval 0 Always returns 0
|
||||||
|
*/
|
||||||
|
int device_control_nop(struct device *unused_device,
|
||||||
|
uint32_t unused_ctrl_command, void *unused_context);
|
||||||
|
/**
|
||||||
|
* @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 device Pointer to device structure of the driver instance.
|
||||||
|
* @param device_power_state Device power state to be set
|
||||||
|
*
|
||||||
|
* @retval 0 If successful.
|
||||||
|
* @retval Errno Negative errno code if failure.
|
||||||
|
*/
|
||||||
|
static inline int device_set_power_state(struct device *device,
|
||||||
|
uint32_t device_power_state)
|
||||||
|
{
|
||||||
|
return device->config->device_control(device,
|
||||||
|
DEVICE_PM_SET_POWER_STATE, &device_power_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Call the get power state function of a device
|
||||||
|
*
|
||||||
|
* This function lets the caller know the current device
|
||||||
|
* power state at any time. This state will be one of the defined
|
||||||
|
* power states allowed for the devices in that system
|
||||||
|
*
|
||||||
|
* @param device pointer to device structure of the driver instance.
|
||||||
|
* @param device_power_state Device power state to be filled by the device
|
||||||
|
*
|
||||||
|
* @retval 0 If successful.
|
||||||
|
* @retval Errno Negative errno code if failure.
|
||||||
|
*/
|
||||||
|
static inline int device_get_power_state(struct device *device,
|
||||||
|
uint32_t *device_power_state)
|
||||||
|
{
|
||||||
|
return device->config->device_control(device,
|
||||||
|
DEVICE_PM_GET_POWER_STATE, device_power_state);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the device structure list array and device count
|
* @brief Gets the device structure list array and device count
|
||||||
*
|
*
|
||||||
|
|
|
@ -75,6 +75,10 @@ extern "C" {
|
||||||
DEVICE_INIT(sys_init_##init_fn, "", init_fn, NULL, NULL, level, prio)
|
DEVICE_INIT(sys_init_##init_fn, "", init_fn, NULL, NULL, level, prio)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SYS_DEVICE_DEFINE(drv_name, init_fn, control_fn, level, prio) \
|
||||||
|
DEVICE_DEFINE(sys_init_##init_fn, drv_name, init_fn, control_fn, \
|
||||||
|
NULL, NULL, level, prio, NULL)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -84,7 +84,11 @@ int device_pm_nop(struct device *unused_device, int unused_policy)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int device_control_nop(struct device *unused_device,
|
||||||
|
uint32_t unused_ctrl_command, void *unused_context)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
void device_list_get(struct device **device_list, int *device_count)
|
void device_list_get(struct device **device_list, int *device_count)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue