Linux电源管理-Linux regulator framework概述

前言 1.什么是regulator? regulator翻译为"调节器",分为voltage regulator(电压调节器)和current(电流调节器)。一般电源管理芯片(Power Management IC)中会包含一个甚至多个regulator。
2.regulator有什么作用? 通常的作用是给电子设备供电。大多数regulator可以启用(enable)和禁用(disable)其输出,同时也可以控制其输出电压(voltage)和电流(current)。 Linux电源管理-Linux regulator framework概述
文章图片

从上图可以看出,input power会经过 regulator 转化为output power,regulator会做如下的约束: -Voltage control:输入5V输出1.8V -Current limiting:电流的输出最大为20MA -Power switch:可以控制电压enable/disable 问题 1.如果一个系统只有一个regulator,而且只对一个设备控制的话,完全没必要使用linux regulator framework机制。但是如果一个系统几个甚至十几个regulator,每个regulator之间还存在级连关系,这时候就需要Linux regulator framework。 2.如果一个regulator控制多个设备,而每个设备的电压或电流需求方式不同,linuxregulator framework会怎么管理这些设备? 3.有些设备只需要enable/disable电源即可,而有些设备在运行的过程中需要动态的改变voltage或者current,Linux regulator Framework会如何处理这些问题? 4.regulator的错误配置可能也会对硬件有非常严重的后果,所以需要小心设计regulaor,同时也要规范的使用regulator。 Linux Regulator Framework 1.Linux Regulator Framework设计出主要是提供一个标准的内核接口来控制电压和电流调节器。目的是允许系统动态控制regulator power输出以节省能源延长电池寿命。这适用于voltage regulator和current regulator(其中电压和电流都是可控的)。 2.Linux Regulator Framework分为四个部分,分别是machine,regulator,consumer,sys-class-regulator。 machine
machine可以理解为regulator在板级的硬件配置,使用regulator_init_data结构体代表regulator板级的配置。

struct regulator_init_data { const char *supply_regulator; /* or NULL for system supply */ struct regulation_constraints constraints; int num_consumer_supplies; struct regulator_consumer_supply *consumer_supplies; /* optional regulator machine specific init */ int (*regulator_init)(void *driver_data); void *driver_data; /* core does not touch this */ };

.supply_regulator:regulator的parent。用于级联regulator使用。 .constraints:此regulator的约束,比如输出电压范围,输出电流范围等。 .num_consumer_supplies:此regulator提供的consumer的个数,也就是控制外设的个数。 .consumer_supplies:使用此结构确定regulator和consumer之间的联系。 .regulator_init:regulator注册时候的回调函数。 .driver_data:regulator_init回调函数的参数。
而regulator板级的配置,也可以称为约束,定义在regulation_constraints结构中。
struct regulation_constraints { const char *name; /* voltage output range (inclusive) - for voltage control */ int min_uV; int max_uV; int uV_offset; /* current output range (inclusive) - for current control */ int min_uA; int max_uA; /* valid regulator operating modes for this machine */ unsigned int valid_modes_mask; /* valid operations for regulator on this machine */ unsigned int valid_ops_mask; /* regulator input voltage - only if supply is another regulator */ int input_uV; /* regulator suspend states for global PMIC STANDBY/HIBERNATE */ struct regulator_state state_disk; struct regulator_state state_mem; struct regulator_state state_standby; suspend_state_t initial_state; /* suspend state to set at init */ /* mode to set on startup */ unsigned int initial_mode; unsigned int ramp_delay; unsigned int enable_time; /* constraint flags */ unsigned always_on:1; /* regulator never off when system is on */ unsigned boot_on:1; /* bootloader/firmware enabled regulator */ unsigned apply_uV:1; /* apply uV constraint if min == max */ unsigned ramp_disable:1; /* disable ramp delay */ };

.name:描述该约束的名字。 .min_uV/max_uV:最小/最大的输出电压。 .uV_offset:consumer看到的电源和实际电源之间的偏移值,用于电源补偿。 .min_uA/max_uA:最小/最大的输出电流。 .valid_modes_mask:该regulator支持的操作模式。 #define REGULATOR_MODE_FAST 0x1//快速改变模式
#define REGULATOR_MODE_NORMAL 0x2//正常模式,大多数驱动都使用这种模式
#define REGULATOR_MODE_IDLE 0x4//设备在idle状态,regulator给设备提供服务
#define REGULATOR_MODE_STANDBY 0x8//设备在standby状态,regulator给设备提供服务 .valid_ops_mask: 该regulator支持的操作。 #define REGULATOR_CHANGE_VOLTAGE 0x1//该regulator可以改变电压
#define REGULATOR_CHANGE_CURRENT 0x2//该regulator可以改变电流
#define REGULATOR_CHANGE_MODE 0x4//该regulator可以改变mode
#define REGULATOR_CHANGE_STATUS 0x8//该regulator可以改变状态,也就是enable/disable power
#define REGULATOR_CHANGE_DRMS 0x10//该regulator可以动态该变mode
#define REGULATOR_CHANGE_BYPASS 0x20//该regulator支持bypass mode
.input_uV:表示该regulator的input是另一个regulator。 .state_disk/state_mem/state_standby:代表该regulator的各种suspend状态。 .always_on:是否在系统启动后一直使能。 .boot_on:是否在boot阶段使能。
.apply_uV: 当min_uV=max_uV的时候时使用。 .ramp_delay: 改变电压到电源稳定后时间。因为硬件原因,改变电源后不能立刻就成功,其中需要有一定的延迟。 .enable_time:regulator的使能时间。
举例说明:参考内核中s5pv210-goni.dts片段
buck3_reg: BUCK3 { regulator-name = "VCC_1.8V"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; regulator-boot-on; };

regulator-name对应struct regulation_constraints中的name regulator-min-microvolt对应struct regulation_constraints中的min_uV regulator-max-microvolt对应struct regulation_constraints中的max_uV regulator-always-on对应struct regulation_constraints中的always_on regulator-boot-on对应struct regulation_constraints中的boot_on
regulator
regulator可以理解为regulator driver。主要作用有注册自己的regulator服务到regulator core framework中,给consumer提供服务。regulator driver通过regulator_register函数注册regulator operation到regulator core。其中第一个参数struct regulator_desc代表静态的regulator配置,所谓静态就是不再会改变的配置。第二个参数代表regulator的动态配置信息。
struct regulator_desc { const char *name; const char *supply_name; const char *of_match; const char *regulators_node; int id; bool continuous_voltage_range; unsigned n_voltages; const struct regulator_ops *ops; int irq; enum regulator_type type; struct module *owner; unsigned int min_uV; unsigned int uV_step; unsigned int linear_min_sel; int fixed_uV; unsigned int ramp_delay; const struct regulator_linear_range *linear_ranges; int n_linear_ranges; const unsigned int *volt_table; unsigned int vsel_reg; unsigned int vsel_mask; unsigned int apply_reg; unsigned int apply_bit; unsigned int enable_reg; unsigned int enable_mask; unsigned int enable_val; unsigned int disable_val; bool enable_is_inverted; unsigned int bypass_reg; unsigned int bypass_mask; unsigned int bypass_val_on; unsigned int bypass_val_off; unsigned int enable_time; unsigned int off_on_delay; };

.name:该regulator的名字。 .supply_name:该regulator parent的name,在级联时使用。 .of_match:在dt中指定的name。 .regulators_node:定义在dt中的regulator name. .id:用于标识该regulator,也可以标识系统有多少个regulator. .continuous_voltage_range:表示regulator是否可以在电压约束范围内连续输出电压。 .n_voltages:通过ops.list_voltage函数获取可用的电压数量。
.ops:regulator的操作函数集合。 .irq: 该regulator的中断号。 .type: 代表当前regulator的类型。
.min_uV:如果是线性mapp的话,使用最低的selector获取的电压。 .uV_step:每个selector下电压增加step。 .linear_min_sel: 线性mapp下最小的selector。 .fixed_uV: 固定电压。 .ramp_delay: 电压改变之后需要多久时间稳定下来。 .linear_rangs: 电压的可能范围的常数表。 .n_linear_rangs: 电压范围常数表的个数。 .volt_table: 电压的mapp表。 .enable_time: regulator初始化所需要的时间。 .off_on_delay:重新使能regulator的保护时间。
其中struct regulator_ops代表了regulator提供的函数操作集合。
struct regulator_ops { /* enumerate supported voltages */ int (*list_voltage) (struct regulator_dev *, unsigned selector); /* get/set regulator voltage */ int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV, unsigned *selector); int (*map_voltage)(struct regulator_dev *, int min_uV, int max_uV); int (*set_voltage_sel) (struct regulator_dev *, unsigned selector); int (*get_voltage) (struct regulator_dev *); int (*get_voltage_sel) (struct regulator_dev *); /* get/set regulator current*/ int (*set_current_limit) (struct regulator_dev *, int min_uA, int max_uA); int (*get_current_limit) (struct regulator_dev *); /* enable/disable regulator */ int (*enable) (struct regulator_dev *); int (*disable) (struct regulator_dev *); int (*is_enabled) (struct regulator_dev *); /* get/set regulator operating mode (defined in consumer.h) */ int (*set_mode) (struct regulator_dev *, unsigned int mode); unsigned int (*get_mode) (struct regulator_dev *); /* Time taken to enable or set voltage on the regulator */ int (*enable_time) (struct regulator_dev *); int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay); int (*set_voltage_time_sel) (struct regulator_dev *, unsigned int old_selector, unsigned int new_selector); /* report regulator status ... most other accessors report * control inputs, this reports results of combining inputs * from Linux (and other sources) with the actual load. * returns REGULATOR_STATUS_* or negative errno. */ int (*get_status)(struct regulator_dev *); /* get most efficient regulator operating mode for load */ unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV, int output_uV, int load_uA); /* control and report on bypass mode */ int (*set_bypass)(struct regulator_dev *dev, bool enable); int (*get_bypass)(struct regulator_dev *dev, bool *enable); /* the operations below are for configuration of regulator state when * its parent PMIC enters a global STANDBY/HIBERNATE state */ /* set regulator suspend voltage */ int (*set_suspend_voltage) (struct regulator_dev *, int uV); /* enable/disable regulator in suspend state */ int (*set_suspend_enable) (struct regulator_dev *); int (*set_suspend_disable) (struct regulator_dev *); /* set regulator suspend operating mode (defined in consumer.h) */ int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode); };

此结构体的注释写的非常清楚,这里就不做详细的解释。 struct regulator_config代表regulator的动态配置信息。此结构体如下:
struct regulator_config { struct device *dev; const struct regulator_init_data *init_data; void *driver_data; struct device_node *of_node; struct regmap *regmap; int ena_gpio; unsigned int ena_gpio_invert:1; unsigned int ena_gpio_flags; };

.dev:struct device指针。 .init_data: 板级的相关初始化信息,通过解析DT,保存在此。 .dirver_data:私有数据。 .of_node:dt相关的node。 .regmap:regulator register map。
当调用regulator_register函数之后,传入静态和动态参数之后,就会返回一个regulator_dev结构。此结构可以认为是regulator设备的一个抽象描述。
struct regulator_dev { const struct regulator_desc *desc; int exclusive; u32 use_count; u32 open_count; u32 bypass_count; /* lists we belong to */ struct list_head list; /* list of all regulators */ /* lists we own */ struct list_head consumer_list; /* consumers we supply */ struct blocking_notifier_head notifier; struct mutex mutex; /* consumer lock */ struct module *owner; struct device dev; struct regulation_constraints *constraints; struct regulator *supply; /* for tree */ struct regmap *regmap; struct delayed_work disable_work; int deferred_disables; void *reg_data; /* regulator_dev data */ struct dentry *debugfs; struct regulator_enable_gpio *ena_pin; unsigned int ena_gpio_state:1; /* time when this regulator was disabled last time */ unsigned long last_off_jiffy; };

.list:所有的regulator链表。 .consumer:此regulator下所有的consumer。 .notifier:此regulator的通知链,用于给consumer通知event。 .supply: 该regulator的supply,级联时候使用。 .disable_work: 该regulator的延迟工作,用于延迟disable regulator。 .use_count/open_count:代表该regulator的使用计数。 .exclusive: 该regulator是否是唯一的标志。 consumer
consumer可以理解为regulator提供服务的对象。比如LCD使用regulator管理自己,就必须使用regulator core提供的regulator相关接口函数。regulator_get()/regulator_put()函数。 详细可以看Documentation/power/regulator/consumer.txt文档。 sysfs-class-regulator
regulator core framework通过sysfs文件系统导出了一些"voltage/current/opmode"相关的信息,此将很有帮忙监控设备的功耗使用情况。 详细信息可以看Documentation/ABI/testing/sysfs-class-regulator文档。 常见的API regulator consumer interface 获取regulator/释放regulator
regulator = regulator_get(dev, "Vcc"); regulator_put(regulator);

Enable and disable
int regulator_enable(regulator); int regulator_disable(regulator); int regulator_force_disable(regulator);

设置regulator的电压,获得regulator的电压状态
int regulator_set_voltage(regulator, min_uV, max_uV); int regulator_get_voltage(regulator);

设置regulator的电流,获得regulator的电流状态
int regulator_set_current_limit(regulator, min_uA, max_uA); int regulator_get_current_limit(regulator);

regulator的模式设置,间接(通过负载),直接设置
int regulator_set_optimum_mode(struct regulator *regulator, int load_uA); int regulator_set_mode(struct regulator *regulator, unsigned int mode); unsigned int regulator_get_mode(struct regulator *regulator);

Regulator Driver interface
注册/反注册一个regulator
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, const struct regulator_config *config); void regulator_unregister(struct regulator_dev *rdev);

regulator事件通知
int regulator_notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data);


本小节就先到这里,下节通过一个实际的例子对regulator再有一个更深的认识。

    推荐阅读