首页 > 系统相关 >Linux电源管理-Linux regulator framework概述

Linux电源管理-Linux regulator framework概述

时间:2023-05-17 12:33:09浏览次数:40  
标签:struct int uV unsigned dev regulator framework Linux

一、前言

1. 什么是regulator?

regulator翻译为"调节器",分为voltage regulator(电压调节器)和current(电流调节器)。一般电源管理芯片(Power Management IC)中会包含一个甚至多个regulator。

2. regulator有什么作用?

通常的作用是给电子设备供电。大多数regulator可以启用(enable)和禁用(disable)其输出,同时也可以控制其输出电压(voltage)和电流(current)。

从上图可以看出,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控制多个设备,而每个设备的电压或电流需求方式不同,linux regulator 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。

(1)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

(2)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文档。

(3)sysfs-class-regulator

regulator core framework通过sysfs文件系统导出了一些"voltage/current/opmode"相关的信息,此将很有帮忙监控设备的功耗使用情况。

详细信息可以看Documentation/ABI/testing/sysfs-class-regulator文档。

四、常见的API

1、regulator consumer interface

(1)获取regulator/释放regulator
regulator = regulator_get(dev, "Vcc");
regulator_put(regulator);
(2)Enable and disable
int regulator_enable(regulator);
int regulator_disable(regulator);
int regulator_force_disable(regulator);
(3)设置regulator的电压,获得regulator的电压状态
int regulator_set_voltage(regulator, min_uV, max_uV);
int regulator_get_voltage(regulator);
(4)设置regulator的电流,获得regulator的电流状态
int regulator_set_current_limit(regulator, min_uA, max_uA);
int regulator_get_current_limit(regulator);
(5)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);

2、Regulator Driver interface

(1)注册/反注册一个regulator
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
					 const struct regulator_config *config);
void regulator_unregister(struct regulator_dev *rdev);
(2)regulator事件通知
int regulator_notifier_call_chain(struct regulator_dev *rdev,
				  unsigned long event, void *data);

  

标签:struct,int,uV,unsigned,dev,regulator,framework,Linux
From: https://www.cnblogs.com/yuanqiangfei/p/17408267.html

相关文章

  • Linux - Centos操作系统iso文件下载
    CENTOS VERSIONDOWNLOADLINKCentOS8.5(2111)DownloadCentOS8.4(2105)DownloadCentOS8.3(2011)DownloadCentOS8.2(2004)DownloadCentOS8.1(1911)DownloadCentOS8.0(1905)DownloadCentOS7.9(2009)NewDownloadCentOS7.8(2003)Downlo......
  • Kali Linux使用 airmon-ng 等相关命令爆破 Wifi 密码
    首先我是在淘宝上买的免驱动的无线网卡,插上一般可以直接使用,不过买回来发现无法连接一些wifi,是wifi除了满格信号,就是没有信号黑色的。我还以为这个wifi信号怎么这么差,联系客服发现是最新的kali需要安装一个软件包realtek-rtl8188eus-dkms淘宝客服的教程:kali单频无线网卡驱动更......
  • Linux 文件系统inode号
    目录一、inodeinode只有一个,唯一的,一个文件必须占用一个inode号,但是至少占用一个数据块(数据不足一个数据块,也是占用一个数据块)inode记录:元信息,权限,字节数,所有组,所有组,时间 二、时间类型atime:使用都会修改时间mtime:修改数据内容,空文件修改内容并且保存内容......
  • linux 定时任务只保留7天内的文件和目录
    shell脚本#!/bin/bash##########################删除7天之前的文件##########################tmp_path=/tmp/test/*find${tmp_path}-maxdepth0-typed-ctime+7|xargsrm-rvf定时任务:crontab-e[root@test~]#crontab-e10***/root/test/......
  • linux grep 查找文件中关键字
    grep[选项]{关键字}文件名选项:-i:忽略大小写-n:输出关键字行号-v:取反,不输出包含关键字内容-r:递归查找,用于查找多个文件是否包含某个关键字-E:使用正则表达式查找file.txt文件中匹配关键字的-所有行grep"关键字1"file.txt查找file.txt文件中匹配多个关键字......
  • linux 新增swap交换空间
    关闭所有交换分区命令如下:swapoff-a通过swap分区文件增加swap空间创建swap分区的文件ddif=/dev/zeroof=swapfilebs=1Mcount=1024其中bs是每块的大小,count是块的数量;bscount,就是swap文件的大小:这里1M1024=1G。可以根据需要自行调整。此外,swapfile是swap文件的路径,可......
  • Linux开发
    shell命令概述Shell作用:命令解释器介于操作系统内核与用户之间,负责解释命令行获得命令帮助内部命令help命令的“--help”选项使用man命令阅读手册页命令行编辑的几个辅助操作Tab键:自动补齐反斜杠“\”:强制换行快捷键Ctrl+U:清空至行首快捷键Ctrl+K:清空至行尾快捷键Ctr......
  • Linux系统中软件简单License的实现
    Linux系统中软件简单License的实现概述       目前,很多商用应用系统是运行在Linux系统之上的,为了维护开发者利益,有必要为软件添加license功能,防止软件被盗用和挪用。本文探讨如何在Linux软件中添加license功能,用到的算法是MD5算法。 关键字:MD5 一目的和思路  ......
  • Linux-用户和权限管理
    用户管理命令命令作用useradd创建用户usermod修改用户信息userdel删除用户及配置文件passwd修改用户密码chpasswd批量更新用户密码change修改用户密码属性id查看用户UID,GID,组信息su切换用户sudo用root身份执行命令visudo编辑sudoe......
  • Linux下文本格式异常:with CRLF line terminators
    linux下在处理文本时,有时会遇到列打印或者显示异常:这是因为有些命令输出重写向到文本,会带入默认Windows文本格式,正常的linux文本中每行是以换行符(\n)结束,windows文本中每行是以回车+换行符(\r\n)结束,可以通过dos2unix工具进行转换:通过file文件名命令可以查看输出:linux文本格式为:A......