RPM:在一个运行的系统中,对某个设备进行休眠和唤醒操作;每个设备(包括CPU)都处理好自身的电源管理工作,尽量在不需要工作的时候进入低功耗状态,尽量不和其它模块有过多耦合。
device driver(或者driver所在的bus、class等)需要提供3个回调函数,runtime_suspend、runtime_resume和runtime_idle,分别用于suspend device、resume device和idle device。
调用时机:
1)主动访问设备时,如写寄存器、发起数据传输等等,get,增加引用计数,告诉RPM core设备active;访问结束后,put,减小引用计数,告诉RPM core设备可能idle。
2)设备有事件通知时,get(可能在中断处理中);driver处理完事件后,put。
举例 bma150.c
bma150_register_polled_device —> input_allocate_device----> device_initialize(&dev->dev);
----> device_pm_init(dev) ----> pm_runtime_init(dev);
void pm_runtime_init(struct device *dev)
{
dev->power.runtime_status = RPM_SUSPENDED;
dev->power.idle_notification = false;
dev->power.disable_depth = 1; // disable_depth 的初值设定为 1
atomic_set(&dev->power.usage_count, 0); // dev->power.usage_count 的初值设定为 0
dev->power.runtime_error = 0;
atomic_set(&dev->power.child_count, 0);
pm_suspend_ignore_children(dev, false);
dev->power.runtime_auto = true;
dev->power.request_pending = false;
dev->power.request = RPM_REQ_NONE;
dev->power.deferred_resume = false;
dev->power.accounting_timestamp = jiffies;
INIT_WORK(&dev->power.work, pm_runtime_work); // 使workstruct结构体的func指向pm_runtime_work
dev->power.timer_expires = 0;
setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn,
(unsigned long)dev); // 初始化 timer_list结构体,并将其 function 指针指向pm_suspend_timer_fn,将其data指针指向 dev
init_waitqueue_head(&dev->power.wait_queue); // 双向链表初始化
}
在 bma150_probe中有
pm_runtime_enable(&client->dev); // 使能设备的runtime PM
void pm_runtime_enable(struct device *dev)
{
unsigned long flags;
spin_lock_irqsave(&dev->power.lock, flags);
if (dev->power.disable_depth > 0)
dev->power.disable_depth--; // 减少disable_depth的计数值,减为0
else
dev_warn(dev, "Unbalanced %s!\n", __func__);
spin_unlock_irqrestore(&dev->power.lock, flags);
}
在 bma150_remove中有
pm_runtime_disable(&client->dev);
void __pm_runtime_disable(struct device *dev, bool check_resume)