简介
设备运行时电源管理框架
是一种主动电源管理机制
,它通过挂起空闲
或未使用
的设备来降低整体系统功耗。可以通过设置CONFIG_PM_DEVICE_RUNTIME
来启用它。在此模型中,设备驱动程序负责指示何时需要设备,何时不需要设备
。此信息用于根据使用情况计数
确定何时挂起
或恢复
设备。
启用设备运行时电源管理
后,其状态最初将设置为PM_DEVICE_STATE_SUSPENDED
指示未使用
它。在第一个设备请求时,它将恢复
,因此将其置于PM_DEVICE_STATE_ACTIVE
状态。设备将保持此状态,直到不再使用。如果同步
执行挂起,则设备将立即进入PM_DEVICE_STATE_SUSPENDED
状态,而如果以异步方式执行,则将首先将其置于PM_DEVICE_STATE_SUSPENDING
状态,然后在操作运行时进入PM_DEVICE_STATE_SUSPENDED
状态。
同步和异步操作
设备驱动程序可以使用pm_device_get()
函数来指示它需要设备处于活动状态或可操作。此功能将增加设备使用计数,并在必要时恢复设备。同样,pm_device_put()
函数可用于指示不再需要该设备。此功能将减少设备使用计数,并在必要时挂起设备。值得注意的是,在这两种情况下,操作是同步执行的。同步模型
非常简单。但是,它可能会引入不必要的延迟
,因为在设备挂起
之前,应用程序将无法获得操作结果。如果操作速度
很快,例如寄存器
切换,则可能不会有问题。但是,如果挂起
涉及通过慢速总线发送数据包,则情况将不同。因此,设备驱动程序还可以利用pm_device_put_async()
函数。如果设备不再使用,此功能将再次计划挂起操作。然后,当系统工作队列
有机会运行时,将执行暂停。
示例
电源管理的驱动函数实现:
static int mydev_pm_action(const struct device *dev,
enum pm_device_action *action)
{
switch (action) {
case PM_DEVICE_ACTION_SUSPEND:
/* suspend the device */
...
break;
case PM_DEVICE_ACTION_RESUME:
/* resume the device */
...
break;
default:
return -ENOTSUP;
}
return 0;
}
若要在设备
上启用设备运行时电源管理
,驱动程序
需要在初始化
时调用pm_device_enable()
。请注意,如果设备的状态为PM_DEVICE_STATE_ACTIVE
,则此功能将挂起设备。如果设备在物理上挂起,init函数
应在调用pm_device_enable()
之前调用pm_device_runtime_init_suspended()
。
/* device driver initialization function */
static int mydev_init(const struct device *dev)
{
int ret;
...
/* OPTIONAL: mark device as suspended if it is physically suspended */
pm_device_runtime_init_suspended(dev);
/* enable device runtime power management */
ret = pm_device_enable(dev);
if ((ret < 0) && (ret != -ENOSYS)) {
return ret;
}
}
在操作设备时,以同步的方式进行电源管理:
static int mydev_operation(const struct device *dev)
{
int ret;
/* "get" device (increases usage count, resumes device if suspended) */
ret = pm_device_runtime_get(dev);
if (ret < 0) {
return ret;
}
/* do something with the device */
...
/* "put" device (decreases usage count, suspends device if no more users) */
return pm_device_runtime_put(dev);
}
在设备操作时以异步的方式进行电源管理:
static int mydev_operation(const struct device *dev)
{
int ret;
/* "get" device (increases usage count, resumes device if suspended) */
ret = pm_device_runtime_get(dev);
if (ret < 0) {
return ret;
}
/* do something with the device */
...
/* "put" device (decreases usage count, schedule suspend if no more users) */
return pm_device_runtime_put_async(dev);
}