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电源管理的主要内容,如果未能解决你的问题,请参考以下文章

电源电源的参数

inux电源管理-Linux regulator framework概述

中港扬盛恒流电源与开关电源的区别

如何根据负载选择开关电源规格?

--电路的分析方法

HaaS Python 硬件积木INA219电压电流计