Linux regulator分析 .

本文深入探讨了嵌入式系统中Regulator模块的作用,如何通过Regulator控制设备的电压/电流供应以优化能耗,并详细介绍了Regulator的注册、使用及关键功能。同时,解释了Regulator与设备之间的树状关系及其内部结构,提供了Regulator框架的使用指南。

Regulator模块用于控制系统中某些设备的电压/电流供应。在嵌入式系统(尤其是手机)中,控制耗电量很重要,直接影响到电池的续航时间。所以,如果系统中某一个模块暂时不需要使用,就可以通过regulator关闭其电源供应;或者降低提供给该模块的电压、电流大小。

Regulator的文档在KERNEL/Documentation/Power/Regulator中。

Regulator与模块之间是树状关系。父regulator可以给设备供电,也可以给子regulator供电:

父Regulator -+->子Regulator --> [Consumer A @ 1.8 - 2.0V] |

+-> [Consumer B @ 3.3V]

具体细节可参考内核文档machine.txt。

regulator_dev

regulator_dev代表一个regulator设备。

struct regulator_dev {

struct regulator_desc *desc;// 描述符,包括regulator的名称、ID、regulator_ops等

int use_count;// 使用计数

/* lists we belong to */

struct list_head list;// regulator通过此结构挂到regulator_list链表中

struct list_head slist;// 如果有父regulator,通过此域挂到父regulator的链表

/* lists we own */

struct list_head consumer_list;// 此regulator负责供电的设备列表

struct list_head supply_list;//此regulator负责供电的子regulator

struct blocking_notifier_head notifier;// notifier,具体的值在consumer.h中,比如REGULATOR_EVENT_FAIL

struct mutex mutex;

struct module *owner;

struct device dev;// device结构,属于class regulator_class

struct regulation_constraints *constraints; //限制,比如最大电压/电流、最小电压/电流

struct regulator_dev *supply;// 父regulator的指针

void *reg_data;/* regulator_dev data */

};

regulator_init_data

regulator_init_data在初始化时使用,用来建立父子regulator、受电模块之间的树状结构,以及一些regulator的基本参数。

struct regulator_init_data {

struct device *supply_regulator_dev;// 父regulator的指针

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 */

};

Regulator的注册

Regulator的注册由regulator_register完成。

一般来说,为了添加regulator_dev,需要实现一个设备驱动程序,以及在板子的设备列表中增加一个该驱动对应的设备(比如platform_device)。在这个设备的struct device->platform_data域,需要设置regulator_init结构,填写该regulator的相关信息。另外,还需要定义一个regulator_desc结构。这样,在这个物理设备的驱动程序中,就可以通过regulator_register函数登记生成一个regulator_dev。

struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, void *driver_data)

struct regulator_init_data *init_data = dev->platform_data;//得到init_data

//完整性检查

//分配regulator_dev结构

struct regulator_dev *rdev = kzalloc (sizeof(struct regulator_dev), GFP_KERNEL);

//初始化regulator_dev结构

//执行regulator_init,该函数中实现regulator代表的硬件设备的初始化

if (init_data->regulator_init)

ret = init_data->regulator_init(rdev->reg_data);

rdev->dev.class = &regulator_class;// 指定class为regulator_class

rdev->dev.parent = dev;

device_register(&rdev->dev);// 注册设备

//设置constraints,其中可能会包括供电状态的初始化(设置初始电压,enable/disable等等)

set_machine_constraints(rdev, &init_data->constraints);

add_regulator_attributes (rdev);

//如果此regulator有父regulator,设置父regulator

if (init_data->supply_regulator_dev) {

ret = set_supply(rdev,

dev_get_drvdata(init_data->supply_regulator_dev));

if (ret < 0)

goto scrub;

}

//设置此regulator与其负责供电的设备之间的联系

for (i = 0; i < init_data->num_consumer_supplies; i++)

ret = set_consumer_device_supply(rdev, init_data->consumer_supplies[i].dev,

init_data->consumer_supplies[i].supply);

//将regulator加入一个链表,该链表包含所有regulator

list_add(&rdev->list, &regulator_list);

set_consumer_device_supply函数用于登记regulator_dev与comsumer_dev(regulator负责供电的设备)之间的对应关系。对于每一个regulator_dev—comsumer_dev的配对,都会有一个regulator_map结构,这些结构会被加入到全局链表regulator_map_list中。

Regulator的使用

在设备驱动使用regulator对其驱动的设备供电时,需要首先保证设备与对应regulator之间的匹配关系已经被登记到regulator框架中。这可通过填写regulator_init_data结构实现。(具体可参考内核文档machine.txt)

之后,设备驱动通过regulator_get函数得到regulator结构,此函数通过前文所述regulator_map_list找到对应regulator_dev,再生成regulator结构给用户使用。

通过regulator_enable / regulator_disable打开、关闭regulator,这两个函数最终都是调用struct regulator_ops里的对应成员。

除此之外,还有regualtor_set_voltage / regulator_get_voltage等等。

Regulator能够支持的所有功能列表都在struct regulator_ops中定义,具体可参考代码中的注释。

struct regulator_ops {

/* get/set regulator voltage */

int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV);

int (*get_voltage) (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 regulator.h) */

int (*set_mode) (struct regulator_dev *, unsigned int mode);

unsigned int (*get_mode) (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);

/* 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 regulator.h) */

int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode);

};

 

 

 

http://blog.youkuaiyun.com/walkingman321/article/details/6987769

### Linux 内核中的 Regulator 子系统 Regulator 子系统是 Linux 内核中用于管理电源调节器的一个模块化框架。它的设计目标是为了简化驱动程序开发者的工作,同时提供一种统一的方式来控制硬件上的电压和电流调节器。 #### 1. Regulator 子系统的架构概述 Regulator 子系统的核心概念包括以下几个部分: - **Consumer API**: 提供给设备驱动使用的接口,允许它们请求特定的电压或电流设置。 - **Core Framework**: 实现了 regulator 的核心逻辑,负责协调 consumer 和 regulator 驱动之间的交互。 - **Driver Implementations**: 各种具体的 regulator 驱动实现了底层硬件的操作细节[^1]。 这些组件共同协作,使得设备可以动态调整其供电需求,从而优化功耗并提高效率。 #### 2. Consumer API 使用方法 为了使某个设备能够利用 regulator 功能,通常需要遵循以下模式: ```c #include <linux/regulator/consumer.h> struct regulator *reg; // 获取指定名称的 regulator reg = devm_regulator_get(dev, "vdd-core"); if (IS_ERR(reg)) { pr_err("Failed to get regulator\n"); } // 设置最小最大电压范围 int ret; ret = regulator_set_voltage(reg, 800000, 1200000); if (ret < 0) { pr_err("Failed to set voltage range\n"); } // 开启 regulator 输出 ret = regulator_enable(reg); if (ret < 0) { pr_err("Failed to enable regulator\n"); } ``` 上述代码片段展示了如何获取一个名为 `vdd-core` 的 regulator 并配置其工作参数[^3]。 #### 3. 反汇编定位错误地址的应用场景 当遇到与 regulator 相关的运行时崩溃或者异常行为时,可以通过反汇编 vmlinux 文件找到具体发生问题的位置。例如,在高通平台 MSM 芯片上升级内核版本期间可能会引入新的 bug 或者不兼容性问题[^2]。此时借助 objdump 工具生成详细的指令列表可以帮助分析根本原因所在。 #### 4. 编译环境准备注意事项 对于不同版本的 Linux 内核以及对应的硬件平台来说,构建合适的交叉编译链至关重要。比如在 Ubuntu 系统下安装 GCC 版本号为 7.5.0 的工具链就可以满足大多数 ARM 架构的需求。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值