基本介绍

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 = &regulator_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子系统相关推荐

  1. Linux 电源管理子系统

    Linux 在消费电子领域的应用已经相当普遍,而对于消费电子产品而言,省电是一个重要的议题. Linux 电源管理非常复杂,牵扯到系统级的待机.频率电压变换.系统空闲时的处理以及每个设备驱动对系统待机 ...

  2. linux内核驱动子系统,linux内核中的MFD子系统

    分析用的内核版本为5.1.3 1.MFD全称 Multi-function Device,多功能设备 2. 为何会出现MFD子系统 由于出现了一类具有多种功能的外围设备或cpu内部集成的硬件模块 3. ...

  3. linux-- input子系统分析

    二 设备驱动层 本节将讲述一个简单的输入设备驱动实例. 这个输入设备只有一个按键,按键被连接到一条中断线上,当按键被按下时,将产生一个中断,内核将检测到这个中 断,并对其进行处理.该实例的代码如下: ...

  4. ⑭tiny4412 Linux驱动开发之cpufreq子系统驱动程序

    本次我们来说一下CPU动态调频子系统. 首先来看一下三星Exynos 4412的datasheet,如下: 上图就是Exynos 4412的时钟分布图,可以看到CPU的频率可以在1.4GHz~200M ...

  5. SCSI子系统基础学习笔记 (之UFS子系统) - 2.1UFS子系统初始化之ufs_qcom_probe

    目录 1. 前言 2.ufs_qcom_probe |- -ufshcd_alloc_host |- -ufshcd_init 参考文档 1. 前言 本专题我们开始学习SCSI子系统的相关内容.本专题 ...

  6. PINCTRL子系统

    转载地址:http://www.360doc.com/content/14/0914/22/426085_409500256.shtml PINCTRL子系统用于处理: - 枚举和命名控制引脚 - 复 ...

  7. ㉕AW-A33 Linux驱动开发之audio子系统驱动程序

    在Linux源码里,Aduio这一部分现在是一个独立文件夹叫sound,在2.x的版本时,sound这个目录是在drivers里的,后来从这个里面剥离出来了,很多人不知道其中的原因,我也不知道,我们先 ...

  8. input子系统与tp驱动

    1.层级结构 jiang-pc:~/build_projects2/build/60_ali/kernel-3.18/drivers/input$ ls apm-power.c ff-core.c g ...

  9. Linux驱动分析之MMC子系统框架

    前言 上一篇<一文搞懂SDIO>简单介绍了SDIO接口及相关的协议.接下来来看一下Linux提供的驱动框架. MMC子系统介绍 Linux内核中,MMC不仅是一个驱动,而是一个子系统.内核 ...

最新文章

  1. 每个年龄段,都有每个年龄段的“好”
  2. c语言编程存航线,C语言编程飞机订票系统如何设计?
  3. 无线信标功能调试-2021-3-9-HALL检测与主控接口
  4. Message Loop 原理及应用
  5. ViceDinoSpecCtrl.cpp
  6. 在vmware虚拟机器上安装1000gwall(原创)
  7. PHP表单提交后页面跳转,PHP在表单提交后重定向到另一个页面
  8. 列举python的数据类型_Python的数据类型
  9. Codeforces Round #375 (Div. 2) F. st-Spanning Tree 生成树
  10. hadoop05---进程线程
  11. 32.从1到n整数中1出现的次数
  12. NIS 病毒库 更新 地址
  13. 孔浩javaScript原型的内存分析
  14. GitHub上整理的一些工具
  15. 关于更换PC版浏览器推荐
  16. 使用小丸工具箱进行极限视频压缩
  17. android体脂代码,该减肥了吗?教你用手机App测量体脂率
  18. .Net5使用Sqlsugar操作加密Sqlite数据库
  19. Sun jdk, Openjdk, Icedtea jdk关系
  20. winform 显示分隔控件_Winform分页控件之纯分页显示处理

热门文章

  1. windows下载Android系统源码
  2. Fedora 9.0 官方下载
  3. MATLAB 声音文件处理
  4. 强化学习Q-Learning解决FrozenLake例子(Python)
  5. PINN深度学习求解微分方程系列一:求解框架
  6. 2014ACM亚洲区域北京邀请赛总结
  7. 【蓝桥杯】python进制转换16进制转8进制。16进制转10进制。10进制转16进制。
  8. base64转16进制
  9. debian源(Debian源代码)
  10. ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed问题解决