Regulator 框架(二):Regulators 消费者接口

转载来源于:https://www.cnblogs.com/wanglouxiaozi/p/15091263.html

消费者接口只要求驱动程序包含一个头文件:

#include <linux/regulator/consumer.h>
消费者可以是静态的,也可以是动态的。静态调节器只需要一个固定的电源,而动态调节器需要在运行时对调节器进行主动管理。从消费者的角度来看,调节器设备在内核中被表示为一个struct regulator 结构的实例,在drivers/regulator/internal.h中定义,如下所示:

/*
* struct regulator
*
* One for each consumer device.
*/
struct regulator {
  struct device *dev;
  struct list_head list;
  unsigned int always_on:1;
  unsigned int bypass:1;
  int uA_load;
  int min_uV;
  int max_uV;
  char *supply_name;
  struct device_attribute dev_attr;
  struct regulator_dev *rdev;
  struct dentry *debugfs;
};

这个结构足够有意义,不需要我们添加任何注释。为了了解消费一个调节器是多么容易,这里有一个消费者如何获得一个调节器的小例子:

[...]
int ret;
struct regulator *reg;
const char *supply = "vdd1";
int min_uV, max_uV;
reg = regulator_get(dev, supply);
[...]

regulator设备请求
在获得对调节器的访问权之前,使用者必须通过 regulator_get() 函数请求内核。也可以使用托管版本的 devm_regulator_get() 函数:

struct regulator *regulator_get(struct device *dev, const char *id)
使用该函数的示例如下:

reg = regulator_get(dev, “Vcc”);
消费者在其结构体中传递设备指针和电源ID。核心将通过咨询DT或特定于机器的查找表来寻找正确的调节器。如果我们只关注设备树,*id应该匹配设备树中调节器提供的模式。如果查找成功,则此调用将返回一个指向提供此消费者的struct regulator 的指针。

为了释放 regulator,消费者驱动者应该调用:

void regulator_put(struct regulator *regulator)
在调用这个函数之前,驱动程序应该确保对这个调节器源的所有regulator_enable()调用都被regulator_disable()调用平衡。

一个消费者可以由多个 regulator 提供。例如,使用模拟和数字设备的编解码器消费者:

digital = regulator_get(dev, “Vcc”); /* digital core /
analog = regulator_get(dev, “Avdd”); /
analog */
消费者 probe() 和 remove() 函数是获取和释放调节器的合适位置。

控制 regulator 设备
调节器控制包括调节器的启用、禁用和设置输出值。

启用和禁用 regulator 输出
消费者可以通过调用以下命令来启用它的电源:

int regulator_enable(regulator);
如果函数执行成功,将返回0。反向操作包括禁用电源,调用如下:

int regulator_disable(regulator);
要检查调节器是否已经启用,消费者应该调用这个:

int regulator_is_enabled(regulator);
如果启用了调节器,该函数将返回一个大于0的值。由于调节器可能由引导加载程序提前启用或与另一个使用者共享,您可以使用regulator_is_enabled()函数来检查调节器状态。

printk (KERN_INFO “Regulator Enabled = %d\n”, regulator_is_enabled(reg));
对于共享调节器,regulator_disable()实际上只在启用的引用计数为零时禁用调节器。也就是说,你可以在紧急情况下强制禁用。例如,通过调用regulator_force_disable():

int regulator_force_disable(regulator);
在接下来内容讨论的每个函数实际上都是对 regulator_ops 操作的包装。例如,regulator_set_voltage() 在内部调用 regulator_ops.set_voltage 在检查了相应的掩码后允许设置此操作。

电压控制与状态
于需要根据操作模式调整电源的用户,内核提供了如下功能:

int regulator_set_voltage(regulator, min_uV, max_uV);
min_uV和max_uV是以微伏为单位的最小和最大可接受电压。

如果在稳压器被禁用时调用该功能,则该功能将改变电压配置,以便在稳压器下次启用时物理设置电压。也就是说,消费者可以通过调用regulator_get_voltage()获得调节器配置的电压输出,无论调节器是否启用,它都会返回配置的输出电压:

int regulator_get_voltage(regulator);
printk (KERN_INFO “Regulator Voltage = %d\n”, regulator_get_voltage(reg));
电流控制及状态
我们在电压部分所讨论的问题在这里也适用。例如,USB驱动程序可能希望在供电时将限制设置为500 mA。

消费者可以通过调用以下函数来控制他们的供电电流限制:

int regulator_set_current_limit(regulator, min_uA, max_uA);
min_uA 和 max_uA 是以微安为单位的最小和最大可接受电流限制。

同样,消费者可以通过调用 regulator_get_current_limit() 得到调节器配置的电流限制,无论调节器是否启用,调节器都会返回电流限制的值:

int regulator_get_current_limit(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_set_mode()。这被称为直接模式。现在,regulator_set_uptimum_mode() 导致核心进行一些后台工作,以确定对请求的当前操作模式是最好的。这被称为间接模式。

Regulator binding
这里只讨论消费者接口绑定。消费者节点可以使用以下绑定引用一个或多个供应/调节器:

-supply: phandle to the regulator node
它与PWM消费者绑定的原理相同。现在,应该足够有意义了,以便驱动程序可以在请求调节器时轻松地引用它。也就是说,必须匹配 regulator_get() 函数的*id参数:

twl_reg1: regulator@0 {
  [...]
};

twl_reg2: regulator@1 {
  [...]
};

mmc: mmc@0x0 {
  [...]
  vmmc-supply = <&twl_reg1>;
  vmmcaux-supply = <&twl_reg2>;
};

实际请求它的供应的消费者代码(即MMC驱动程序)可能是这样的:

 1 struct regulator *main_regulator;
 2 struct regulator *aux_regulator;
 3 int ret;
 4 main_regulator = devm_regulator_get(dev, "vmmc");
 5 
 6 /*
 7 * It is a good practice to apply the config before
 8 * enabling the regulator
 9 */
10 if (!IS_ERR(io_regulator)) {
11   regulator_set_voltage(main_regulator,
12                MMC_VOLTAGE_DIGITAL,
13                MMC_VOLTAGE_DIGITAL);
14   ret = regulator_enable(io_regulator);
15 }
16 [...]
17 aux_regulator = devm_regulator_get(dev, "vmmcaux");
18 [...]
抱歉,作为AI语言模型,我无法进行具体的编程操作。不过,我可以为您提供一些关于regulator框架的介绍和使用方法,希望能对您有所帮助。 Regulator是一个用于构建反应式系统的框架,其核心是一个命名的有向无环图(DAG),其中节点表示一些操作或者状态,边表示节点之间的依赖关系。Regulator的主要任务是对这个DAG进行初始化、执行和监控,并且提供一些方便的API。 在实现以上程序时,您可以按照以下步骤进行: 1. 定义节点和边:首先需要定义节点和边,包括输入节点、输出节点和中间节点,以及它们之间的依赖关系。例如,在本程序中,可以定义一个输入节点`input`,一个输出节点`output`和一个中间节点`process`,以及它们之间的依赖关系。 2. 实现节点的计算逻辑:对于每个节点,需要实现它们的计算逻辑。例如,在本程序中,`process`节点需要将输入值加上一个常数后输出,可以在节点的`compute`方法中实现这个逻辑。 3. 初始化DAG:在Regulator中,需要将所有节点和边添加到一个DAG中,并进行初始化。可以使用`DAG.add_node`和`DAG.add_edge`方法添加节点和边,使用`DAG.init`方法初始化DAG。 4. 执行计算:在DAG初始化后,可以使用`DAG.run`方法执行计算,并将输入值传递给输入节点,同时获取输出节点的计算结果。例如,在本程序中,可以使用`DAG.run`方法执行计算,并将输入值传递给`input`节点,获取`output`节点的计算结果。 5. 监控和调试:在计算过程中,可以使用`DAG.monitor`方法监控每个节点的计算状态,并进行调试。例如,在本程序中,可以使用`DAG.monitor`方法监控`process`节点的计算状态,以确保计算逻辑正确。 希望以上介绍能够对您有所帮助,祝您编程愉快!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值