Linux电源管理
Posted 四季帆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux电源管理相关的知识,希望对你有一定的参考价值。
1. 设备电源管理的两种模型
在一个系统中,数量最多的是设备,耗电最多的也是设备,因此设备的电源管理是Linux电源管理的核心内容,驱动程序可以使用其中一种模型来使设备进入低功耗状态。
1.1 系统睡眠模型
驱动程序作为一部分,跟随系统级别的低功耗状态,比如"suspend"(也叫做"suspend-to-RAM"),或者对于有硬盘的系统,可以进入"hibernation"(也叫做"suspend-to-disk")。
有些驱动程序可以管理硬件的唤醒事件,这些事件可以让系统离开低功耗状态。这一特性可以通过相应的/sys/devices/.../power/wakeup文件来开启和关闭。
系统休眠模型给我的感觉是以整机角度进行省电。
在Linux中,通过cat /sys/power/state可以得知当前设备支持的节能模式,一般情况有如下选项:
standby: CPU处于浅睡眠模式,主要针对CPU功耗;
mem: Suspend to RAM;
disk: Suspend to Disk;
需要设置以上模式,只需echo mem > /sys/power/state即可。
1.2 Runtime 电源管理模型
这种模型允许设备在系统运行阶段进入低功耗状态,原则上,他可以独立于其他的电源管理活动。不过,通常设备之间不能单独进行控制(例如,父设备不能进入suspend,除非他的所有子设备已经进入suspend状态)。如果设备在系统运行阶段进入了低功耗状态,在系统级别的电源状态迁移时(suspend或hibernation)就必须做出特别的处理。
如果在系统运行状态,足够多的设备进入了低功耗状态,这时的效果其实和进入了系统级别的低功耗状态非常相像。这样一些驱动程序可以利用rumtime电源管理让系统进入一种类似深度省电的状态。
大多数进入suspend状态的设备会停止所有的I/O操作:不会有DMA或者IRQ请求(需要唤醒系统的除外),不会有数据的读写,不再接受上层驱动的请求。
Runtime电源管理模型给我的感觉是以模块角度进行省电。
Runtime电源管理模型的原理比较简单,就是计数,当该设备驱动被使用时就加1,放弃使用时就减1,计数大于1时,就打开该设备的电源,等于0时就关闭电源。
1.3 设备电源管理操作
设备电源管理最核心的操作就是:在合适的时机(如不再使用,如暂停使用),将设备置为合理的状态(如关闭,如睡眠),这就是device PM callbacks的目的:定义一套统一的方式,让设备在特定的时机,步调一致的进入类似的状态。
在旧版本的内核中,这些PM callbacks分布在设备模型的大型数据结构中,如struct bus_type中的suspend、suspend_late、resume、resume_late,如struct device_driver/struct class/struct device_type中的suspend、resume。很显然这样不具备良好的封装特性,因为随着设备复杂度的增加,简单的suspend、resume已经不能满足电源管理的需求,就需要扩充PM callbacks,就会不可避免的改动这些数据结构。
于是新版本的内核,就将这些Callbacks统一封装为一个数据结构struct dev_pm_ops,上层的数据结构只需要包含这个结构即可。这样如果需要增加或者修改PM callbacks,就不用改动上层结构了。当然,内核为了兼容旧的设计,也保留了上述的suspend/resume类型的callbacks,只是已不建议使用。
//include/linux/pm.h
//子系统和驱动程序的设备电源管理操作,都定义在dev_pm_ops结构中
struct dev_pm_ops
int (*prepare)(struct device *dev);
void (*complete)(struct device *dev);
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
int (*freeze)(struct device *dev);
int (*thaw)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*restore)(struct device *dev);
int (*suspend_late)(struct device *dev);
int (*resume_early)(struct device *dev);
int (*freeze_late)(struct device *dev);
int (*thaw_early)(struct device *dev);
int (*poweroff_late)(struct device *dev);
int (*restore_early)(struct device *dev);
int (*suspend_noirq)(struct device *dev);
int (*resume_noirq)(struct device *dev);
int (*freeze_noirq)(struct device *dev);
int (*thaw_noirq)(struct device *dev);
int (*poweroff_noirq)(struct device *dev);
int (*restore_noirq)(struct device *dev);
/* 最后三个方法是专门用于rumtime pm的,其他的则用于系统级别的电源状态迁移。 */
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);
;
1.4 设置唤醒源
唤醒源最常见的就是按键中断,就如同手机进入锁屏状态下,按下电源键唤醒一样。
2. regulator系统
系统睡眠模型和runtime电源管理模型偏“软”,regulator系统偏“硬”,在复杂的单板中,有专门的电源管理芯片控制各个模块电源,regulator系统就是为这个电源芯片编写驱动,实现电源管理。
如果使用 系统睡眠模型 或 Runtime电源模型 进行休眠操作,就会调用到regulator系统的操作函数,实现电源管理芯片的关闭。
Regulator分为voltage regulator和current。一般PMIC(Power Management IC)中会包含一个或者多个regulator。通常的作用是给电子设备供电,大多数regulator可以启用(enable)和禁用(disable)其输出,同时也可以控制其输出电压(voltage)和电流(current)。
cpu内部会集成一些regulator,通常cpu还会通过I2C controller外接多个regulator。比如,通过i2c controller外接pfuze100这个型号的电源IC,其对应的驱动程序在drivers/regulator/pfuze100-regulator.c。
2.1 regulator framework
调用注册接口regulator_register/devm_regulator_register进行注册regulator。
regulator的主要功能,是输出电压/电流的调整(或改变)。由于模拟器件的特性,电压/电流的改变,是需要一定的时间的。对有些regulator而言,可以工作在不同的模式,这些模式有不同的改变速度,较快的速度,有较大的功耗。模式如下所示:
include/linux/regulator/consumer.h
/*
* Regulator operating modes.
*
* Regulators can run in a variety of different operating modes depending on
* output load. This allows further system power savings by selecting the
* best (and most efficient) regulator mode for a desired load.
*
* Most drivers will only care about NORMAL. The modes below are generic and
* will probably not match the naming convention of your regulator data sheet
* but should match the use cases in the datasheet.
*
* In order of power efficiency (least efficient at top).
*
* Mode Description
* FAST Regulator can handle fast changes in it's load.
* e.g. useful in CPU voltage & frequency scaling where
* load can quickly increase with CPU frequency increases.
*
* NORMAL Normal regulator power supply mode. Most drivers will
* use this mode.
*
* IDLE Regulator runs in a more efficient mode for light
* loads. Can be used for devices that have a low power
* requirement during periods of inactivity. This mode
* may be more noisy than NORMAL and may not be able
* to handle fast load switching.
*
* STANDBY Regulator runs in the most efficient mode for very
* light loads. Can be used by devices when they are
* in a sleep/standby state. This mode is likely to be
* the most noisy and may not be able to handle fast load
* switching.
*
* NOTE: Most regulators will only support a subset of these modes. Some
* will only just support NORMAL.
*
* These modes can be OR'ed together to make up a mask of valid register modes.
*/
#define REGULATOR_MODE_FAST 0x1
#define REGULATOR_MODE_NORMAL 0x2
#define REGULATOR_MODE_IDLE 0x4
#define REGULATOR_MODE_STANDBY 0x8
kernel抽象出直接操作电压的方法:对应struct regulator_ops中的如下回调函数:
/* get/set regulator voltage */
int (*list_voltage) (struct regulator_dev *, unsigned selector);
int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV, unsigned *selector);
int (*get_voltage) (struct regulator_dev *);
3. 小结
不是所有的设备都需要专门的电源IC的,所以有的设备另外配置了电源管理IC,那么就需要通过regulator系统来注册电源管理IC对应的驱动,所以当系统睡眠或该设备睡眠时,这种设备的dev_pm_ops回调接口在实现时,需要调用电源管理IC驱动的接口来设置电压/电流的大小/关闭等状态,也就是说可能不仅仅是实现ON和OFF两个状态,还需要实现IC输出不同大小的状态,比如输出1A、2A、3A三种不同电流的状态。
还有一些简单的设备是不需要配置电源管理IC的,所以当系统睡眠或该设备睡眠时,这种设备的dev_pm_ops回调接口在实现时,实现ON和OFF两个状态就可以了。
3.1 进入和退出睡眠
系统睡眠模型一般是通过按键(即外部中断)的方式来进入和退出睡眠,runtime电源管理模型一般是自动进入睡眠(软件计数、定时等方式),按键(即外部中断)的方式退出睡眠。
以上是关于Linux电源管理的主要内容,如果未能解决你的问题,请参考以下文章