平台 | 内核版本 | 安卓版本 |
---|---|---|
RK3399 | Linux4.4 | Android7.1 |
沉淀、分享、成长,让自己和他人都能有所收获!😄
📢本篇将讲解调节器消费者接口。
消费者接口只需要驱动程序包含一个头文件:
#include
消费者可以是静态的或动态的。静态消费者只需要固定电源,而动态消费者则需要在运行时对调节器进行主动管理。从消费者角度来看,调节器设备在内核中表示为struct regulator
的实例,该结构在drivers/regulator/internal.h
中定义,如下所示:
/*
* 结构调节器
*
* 每个消费设备有一个
*/
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_get()
函数请求内核,也可以使用托管版本devm_regulator_get()
函数:
struct regulator *regulator_get(struct device *dev,
const char *id)
使用该函数的例子如下:
reg = regulator_get(dev, "Vcc");
消费者传入struct device
指针和电源ID
。核心通过查询DT
或机器特定的查找表尝试找到正确的调节器。如果只关注设备树,则* id
应该匹配设备树中调节器电源的
模式。如果查找成功,则此调用将返回指向为此消费者提供的struct regulator
的指针。
要释放调节器,消费者驱动程序应该调用:
void regulator_put(struct regulator *regulator)
在调用此函数之前,驱动程序应确保在该调节器源上的所有regulator_enable()
调用都通过regulator_disable()
调用进行平衡。
可以有多个调节器为消费者供电,例如,编解码器消费者具有模拟和数字供电:
digital = regulator_get(dev, "Vcc"); /* 数字*/
analog = regulator_get(dev, "Avdd"); /* 模拟 */
消费者probe()
和remove()
函数是获取和释放调节器的合适位置。
调节器控制包括启用、禁用和设置调节器的输出值。
消费者可以调用以下函数启用其电源:
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));
对于共享调节器,仅当启用的引用计数为
0
时,regulator_disable()
才会实际禁用调节器。而调用regulator_force_disable()
则可以强制禁用,例如在紧急情况下:
int regulator_force_disable(regulator);
对于需要根据自己的操作模式调整电源的消费者,内核提供以下函数:
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()
使内核执行一些后台工作,以确定哪种运行模式最适合于所请求的电流。这称作间接模式。