简介

设备运行时电源管理框架是一种主动电源管理机制,它通过挂起空闲未使用的设备来降低整体系统功耗。可以通过设置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()函数可用于指示不再需要该设备。此功能将减少设备使用计数,并在必要时挂起设备。值得注意的是,在这两种情况下,操作是同步执行的。
26.设备运行时电源管理 - 图1
同步模型非常简单。但是,它可能会引入不必要的延迟,因为在设备挂起之前,应用程序将无法获得操作结果。如果操作速度很快,例如寄存器切换,则可能不会有问题。但是,如果挂起涉及通过慢速总线发送数据包,则情况将不同。因此,设备驱动程序还可以利用pm_device_put_async()函数。如果设备不再使用,此功能将再次计划挂起操作。然后,当系统工作队列有机会运行时,将执行暂停。
26.设备运行时电源管理 - 图2

示例

电源管理的驱动函数实现:

  1. static int mydev_pm_action(const struct device *dev,
  2. enum pm_device_action *action)
  3. {
  4. switch (action) {
  5. case PM_DEVICE_ACTION_SUSPEND:
  6. /* suspend the device */
  7. ...
  8. break;
  9. case PM_DEVICE_ACTION_RESUME:
  10. /* resume the device */
  11. ...
  12. break;
  13. default:
  14. return -ENOTSUP;
  15. }
  16. return 0;
  17. }

若要在设备上启用设备运行时电源管理驱动程序需要在初始化时调用pm_device_enable()。请注意,如果设备的状态为PM_DEVICE_STATE_ACTIVE,则此功能将挂起设备。如果设备在物理上挂起,init函数应在调用pm_device_enable()之前调用pm_device_runtime_init_suspended()

  1. /* device driver initialization function */
  2. static int mydev_init(const struct device *dev)
  3. {
  4. int ret;
  5. ...
  6. /* OPTIONAL: mark device as suspended if it is physically suspended */
  7. pm_device_runtime_init_suspended(dev);
  8. /* enable device runtime power management */
  9. ret = pm_device_enable(dev);
  10. if ((ret < 0) && (ret != -ENOSYS)) {
  11. return ret;
  12. }
  13. }

在操作设备时,以同步的方式进行电源管理:

  1. static int mydev_operation(const struct device *dev)
  2. {
  3. int ret;
  4. /* "get" device (increases usage count, resumes device if suspended) */
  5. ret = pm_device_runtime_get(dev);
  6. if (ret < 0) {
  7. return ret;
  8. }
  9. /* do something with the device */
  10. ...
  11. /* "put" device (decreases usage count, suspends device if no more users) */
  12. return pm_device_runtime_put(dev);
  13. }

在设备操作时以异步的方式进行电源管理:

  1. static int mydev_operation(const struct device *dev)
  2. {
  3. int ret;
  4. /* "get" device (increases usage count, resumes device if suspended) */
  5. ret = pm_device_runtime_get(dev);
  6. if (ret < 0) {
  7. return ret;
  8. }
  9. /* do something with the device */
  10. ...
  11. /* "put" device (decreases usage count, schedule suspend if no more users) */
  12. return pm_device_runtime_put_async(dev);
  13. }