Regulator子系统
基本介绍
Regulator指的是稳定器,有电压稳定器及电流稳定器两种,能够自动维持恒定电流或者电压。其中,电压稳定器voltage regulator在电路中比较常见。从设备驱动的角度来看,regulator的控制比较简单,主要有enable/disable/输出电压或电流大小的控制。Linux利用regulator framework对regulator进行管理和控制。
Linux regulator framework的主要目的:提供标准的内核接口,控制系统的voltage/current regulators,并提供相应的开关、大小设置的机制。在系统运行的过程中,根据具体的需要动态改变regulators的输出,从而达到省电的目的。在系统中如果配错regulator是比较危险的,可能会造成硬件器件的损坏。因此,需要在regulator framework中对电流或者电压的大小做限定,并且不能被ragulator的consumer或者provider更改。
框架说明
regulator属于电源管理部分,主要实现电压、电流的输出操作,本篇文章主要介绍regulator子系统的代码实现,因此我们先熟悉一些regulator子系统的相关概念。对于regulator子系统,我们可以讲其分为三部分
- 供电端的regulator, 负责电源芯片本身的驱动程序,比如enable/disable函数,使能或者禁止电源芯片,有一些强悍的电源芯片,是可以动态的调整电压或电流的
- 耗电端的consumer: 比如声卡,网卡, lcd==, 在这些驱动程序里,只是去引用regulator的函数,不关心电源函数如何实现,想使能就调用enable函数
- 不同类型的单板,regulator和consumer的对应关系是不一致的。
- regulator和consumer的对应关系,哪一个regulator对哪一个consumer供电
- 约束条件,在模块单板里可以输出xxx的电压或者电流,在其他的单板里可能就输出xxx的电压或者电流,单板相关的条件,比如电压范围
machine(表示一个单板)
machin使用struct regulator_init_data,静态的描述regulator在板级的硬件连接情况,这些限制通过驱动或dts配置,涉及到系统供电安全,因此必须小心,这些配置主要包括:
1)用于描述regulator在板级的级联关系:前级regulator(即该regulator的输出是另一个regulator的输入,简称supply regulator)和后级regulator(即该regulator的输入是其它regulator的输出,简称consumer regulator)。
2)利用struct regulation_constraints 描述regulator的物理限制,比如:
- 输出电压的最大值和最小值(voltage regulator);
- 输出电流的最大值和最小值(current regulator);
- 允许的操作(修改电压值、修改电流限制、enable、disable等);
- 输入电压是多少(当输入是另一个regulator时);
- 是否不允许关闭(always_on);
- 是否启动时就要打开(always_on);
machin使用struct regulator_init_data,静态的描述regulator在板级的硬件连接情况,这些限制通过驱动或dts配置,涉及到系统供电安全,因此必须小心,这些配置主要包括:
1)用于描述regulator在板级的级联关系:前级regulator(即该regulator的输出是另一个regulator的输入,简称supply regulator)和后级regulator(即该regulator的输入是其它regulator的输出,简称consumer regulator)。
2)利用struct regulation_constraints 描述regulator的物理限制,比如:
- 输出电压的最大值和最小值(voltage regulator);
- 输出电流的最大值和最小值(current regulator);
- 允许的操作(修改电压值、修改电流限制、enable、disable等);
- 输入电压是多少(当输入是另一个regulator时);
- 是否不允许关闭(always_on);
- 是否启动时就要打开(always_on);
regulator driver
regulator driver指的是regulator设备的驱动,主要包含如下结构:
1)使用struct regulator_desc,描述regulator的静态信息,包括:名字、supply regulator的名字、中断号、操作函数集(struct regulator_ops)、使用regmap时相应的寄存器即bitmap等。
2)使用struct regulator_config,描述regulator的动态信息(所谓的动态信息,体现在struct regulator_config变量都是局部变量,因此不会永久保存),包括struct regulator_init_data指针、设备指针、enable gpio等。
3)提供regulator的注册接口(regulator_register/devm_regulator_register),该接口接受描述该regulator的两个变量的指针:struct regulator_desc和struct regulator_config,并分配一个新的数据结构(struct regulator_dev,从设备的角度描述regulator),并把静态指针(struct regulator_desc)和动态指针(struct regulator_config)提供的信息保存在其中。
4)regulator driver以struct regulator_dev(代表设备)指针为对象,对regulator进行后续的操作。
PMIC
电源管理芯片,一个电源管理芯片可包含多个regulator;
Consumer
表示一个regulator使用者,regulator是电源的提供者,而consumer则是电源的消费者(比如LCD),一个regulator可供多个consumer使用;
regulator consumer抽象出regulator设备(struct regulator),并提供regulator操作相关的接口。包括:regulator_get/regulator_put/regulator_enable/regulator_disable/ regulator_set_voltage/regulator_get_voltage等。
regulator core
regulator core负责上述regulator driver/consumer/machine逻辑的具体实现,对底层的硬件进行封装,并提供接口给内核中其他的consumer(使用当前regulator设备的驱动)提供操作接口,并以sysfs的形式,向用户空间提供接口。
Power Domain
电源域,regulator可以级联,不同的regulator的使用者属于相同的电源域。如下图的regulator,则包含三个电源域:
Domain1: switch-1、consumer D、Consumer E;
Domain2:switch-2、consumer B、consumer C;
Domain3:consumer A;
这三个电源域的关系如下:
Domain-1 --> Domain-2 --> Domain-3,在使用时domain-3下consumer相关的电压、电流设置需要满足这三级电源域的电压、电流约束。
Constraints
表示regulator的约束,而针对regulator约束也包含三部分:
该regulator自身的约束信息:这属于regulator相关的约束信息,可通过regulator的datasheet中获取该regulator的约束信息;
Power domain级别的约束信息:这属于该regulator下不同电源域的约束信息,这些约束信息时regulator自身约束信息的子集(如regulator的电压输出约束为1v-3.5v;而domain1的约束信息为2v-3v;domain2的约束信息为2.5v等);
consumer级别的约束信息,可动态设置该consumer所需的输入电压或电流约束等。
针对regulator子系统基本上就是这几个主要的概念,而linux regulator子系统的实现也是围绕着这几个概念进行子系统的框架设计的。
regulator的简单使用(参考内核tps6105x-regulator.c)
regulator driver’
- 注册一个platform driver, 在它的probe函数里面分配,设置,注册一个regulator
- 设置里面要做的事情: 实现regulator的操作,比如enable, disable, set_voltage’
static struct regulator_ops tps6105x_regulator_ops = {.enable = regulator_enable_regmap, //将对应引脚设置输入/输出电平.disable = regulator_disable_regmap, //将对应引脚设置输入/输出电平.is_enabled = regulator_is_enabled_regmap,.get_voltage_sel = regulator_get_voltage_sel_regmap,.set_voltage_sel = regulator_set_voltage_sel_regmap,.list_voltage = regulator_list_voltage_table, };static const struct regulator_desc tps6105x_regulator_desc = {.name = "tps6105x-boost",.ops = &tps6105x_regulator_ops, //包含regulator的操作函数.type = REGULATOR_VOLTAGE,.id = 0,.owner = THIS_MODULE,.n_voltages = ARRAY_SIZE(tps6105x_voltages),.volt_table = tps6105x_voltages,.vsel_reg = TPS6105X_REG_0,.vsel_mask = TPS6105X_REG0_VOLTAGE_MASK,.enable_reg = TPS6105X_REG_0,.enable_mask = TPS6105X_REG0_MODE_MASK,.enable_val = TPS6105X_REG0_MODE_VOLTAGE <<TPS6105X_REG0_MODE_SHIFT, };static int tps6105x_regulator_probe(struct platform_device *pdev) {struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);struct tps6105x_platform_data *pdata = tps6105x->pdata;struct regulator_config config = { };int ret;config.dev = &tps6105x->client->dev;config.init_data = pdata->regulator_data; // 这个init_data就是单板中regulator的对应关系,约束条件==, 这个从pdev中的私有数据获取config.driver_data = tps6105x;config.regmap = tps6105x->regmap;/* Register regulator with framework */tps6105x->regulator = devm_regulator_register(&pdev->dev,&tps6105x_regulator_desc,&config); }static struct platform_driver tps6105x_regulator_driver = {.driver = {.name = "tps6105x-regulator",},.probe = tps6105x_regulator_probe, };
machine: 构造一个regulator的platform_device, 然后填充对应关系和约束条件
- 注册一个platfrom_device, 在他的私有数据里指定regulator和consumer的对应关系(这个电源芯片给哪一些设备供电)
- 指定约束条件, 比如电压范围
- 填充regulator_init_data(在内核搜索)
consumer
- 使用regulator core提供的接口使用,比如regulator_get获取一个regulator, regulator_enable使能regulator
regulator注册流程
static const struct regulator_desc dummy_desc = {.name = "regulator-dummy",.id = -1,.type = REGULATOR_VOLTAGE,.owner = THIS_MODULE,.ops = &dummy_ops,
};
static struct regulator_init_data dummy_initdata = {.constraints = {.always_on = 1,},
};config.dev = &pdev->dev;
config.init_data = &dummy_initdata;regulator_register(&dummy_desc, &config);kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); //申请一个regulator devconfig = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); //把config取出来regulator_of_get_init_data(dev, regulator_desc, config,&rdev->dev.of_node); //从中取出config配置INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);初始化一个工作队列rdev->dev.class = ®ulator_class; register with sysfsset_machine_constraints(rdev, constraints); //设置对应关系//add consumers devices 在regulator_map_list链表里生成一项regulator map它里面有dev->name(consumer的名字,还有supply(consumer的电源引脚名字)device_register(&rdev->dev);struct regulator *regulator_get(struct device *dev, const char *id) // 第一个参数就是consumer的名字,第二个参数就是supply电源引脚的名字
Regulator子系统相关推荐
- Linux 电源管理子系统
Linux 在消费电子领域的应用已经相当普遍,而对于消费电子产品而言,省电是一个重要的议题. Linux 电源管理非常复杂,牵扯到系统级的待机.频率电压变换.系统空闲时的处理以及每个设备驱动对系统待机 ...
- linux内核驱动子系统,linux内核中的MFD子系统
分析用的内核版本为5.1.3 1.MFD全称 Multi-function Device,多功能设备 2. 为何会出现MFD子系统 由于出现了一类具有多种功能的外围设备或cpu内部集成的硬件模块 3. ...
- linux-- input子系统分析
二 设备驱动层 本节将讲述一个简单的输入设备驱动实例. 这个输入设备只有一个按键,按键被连接到一条中断线上,当按键被按下时,将产生一个中断,内核将检测到这个中 断,并对其进行处理.该实例的代码如下: ...
- ⑭tiny4412 Linux驱动开发之cpufreq子系统驱动程序
本次我们来说一下CPU动态调频子系统. 首先来看一下三星Exynos 4412的datasheet,如下: 上图就是Exynos 4412的时钟分布图,可以看到CPU的频率可以在1.4GHz~200M ...
- SCSI子系统基础学习笔记 (之UFS子系统) - 2.1UFS子系统初始化之ufs_qcom_probe
目录 1. 前言 2.ufs_qcom_probe |- -ufshcd_alloc_host |- -ufshcd_init 参考文档 1. 前言 本专题我们开始学习SCSI子系统的相关内容.本专题 ...
- PINCTRL子系统
转载地址:http://www.360doc.com/content/14/0914/22/426085_409500256.shtml PINCTRL子系统用于处理: - 枚举和命名控制引脚 - 复 ...
- ㉕AW-A33 Linux驱动开发之audio子系统驱动程序
在Linux源码里,Aduio这一部分现在是一个独立文件夹叫sound,在2.x的版本时,sound这个目录是在drivers里的,后来从这个里面剥离出来了,很多人不知道其中的原因,我也不知道,我们先 ...
- input子系统与tp驱动
1.层级结构 jiang-pc:~/build_projects2/build/60_ali/kernel-3.18/drivers/input$ ls apm-power.c ff-core.c g ...
- Linux驱动分析之MMC子系统框架
前言 上一篇<一文搞懂SDIO>简单介绍了SDIO接口及相关的协议.接下来来看一下Linux提供的驱动框架. MMC子系统介绍 Linux内核中,MMC不仅是一个驱动,而是一个子系统.内核 ...
最新文章
- 每个年龄段,都有每个年龄段的“好”
- c语言编程存航线,C语言编程飞机订票系统如何设计?
- 无线信标功能调试-2021-3-9-HALL检测与主控接口
- Message Loop 原理及应用
- ViceDinoSpecCtrl.cpp
- 在vmware虚拟机器上安装1000gwall(原创)
- PHP表单提交后页面跳转,PHP在表单提交后重定向到另一个页面
- 列举python的数据类型_Python的数据类型
- Codeforces Round #375 (Div. 2) F. st-Spanning Tree 生成树
- hadoop05---进程线程
- 32.从1到n整数中1出现的次数
- NIS 病毒库 更新 地址
- 孔浩javaScript原型的内存分析
- GitHub上整理的一些工具
- 关于更换PC版浏览器推荐
- 使用小丸工具箱进行极限视频压缩
- android体脂代码,该减肥了吗?教你用手机App测量体脂率
- .Net5使用Sqlsugar操作加密Sqlite数据库
- Sun jdk, Openjdk, Icedtea jdk关系
- winform 显示分隔控件_Winform分页控件之纯分页显示处理
热门文章
- windows下载Android系统源码
- Fedora 9.0 官方下载
- MATLAB 声音文件处理
- 强化学习Q-Learning解决FrozenLake例子(Python)
- PINN深度学习求解微分方程系列一:求解框架
- 2014ACM亚洲区域北京邀请赛总结
- 【蓝桥杯】python进制转换16进制转8进制。16进制转10进制。10进制转16进制。
- base64转16进制
- debian源(Debian源代码)
- ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed问题解决