稳压器消费者驱动接口

本文档描述了消费者设备驱动程序的稳压器接口。 有关本文档中使用的术语的描述,请参阅Linux 电压和电流稳压器框架

1. 消费者稳压器访问(静态和动态驱动)

消费者驱动程序可以通过调用以下方式访问其电源稳压器

regulator = regulator_get(dev, "Vcc");

消费者传入其struct device指针和电源ID。 然后,核心通过查阅机器特定的查找表来找到正确的稳压器。 如果查找成功,则此调用将返回指向为该消费者供电的struct regulator的指针。

要释放稳压器,消费者驱动程序应调用

regulator_put(regulator);

消费者可以由多个稳压器供电,例如,具有模拟和数字电源的编解码器消费者

digital = regulator_get(dev, "Vcc");  /* digital core */
analog = regulator_get(dev, "Avdd");  /* analog */

稳压器访问函数regulator_get()regulator_put()通常会在您的设备驱动程序的probe()和remove()中分别调用。

2. 稳压器输出使能和禁用(静态和动态驱动)

消费者可以通过调用以下方式启用其电源

int regulator_enable(regulator);
注意

在调用regulator_enable()之前,电源可能已经被启用。 如果消费者共享稳压器,或者稳压器先前已由引导加载程序或内核板初始化代码启用,则可能会发生这种情况。

消费者可以通过调用以下方式确定稳压器是否已启用

int regulator_is_enabled(regulator);

当稳压器启用时,这将返回>零。

当不再需要时,消费者可以通过调用以下方式禁用其电源

int regulator_disable(regulator);
注意

如果它与其他消费者共享,则这可能不会禁用电源。 只有在启用引用计数为零时,稳压器才会被禁用。

最后,在紧急情况下,可以强制禁用稳压器

int regulator_force_disable(regulator);
注意

这将立即并强制关闭稳压器输出。 所有消费者都将被断电。

3. 稳压器电压控制和状态(动态驱动)

一些消费者驱动程序需要能够动态更改其电源电压以匹配系统运行点。 例如,CPUfreq驱动程序可以根据频率缩放电压以节省功率,SD驱动程序可能需要选择正确的卡电压等。

消费者可以通过调用以下方式控制其电源电压

int regulator_set_voltage(regulator, min_uV, max_uV);

其中min_uV和max_uV是以微伏为单位的最小和最大可接受电压。

注意:这可以在启用或禁用稳压器时调用。 如果在启用时调用,则电压会立即改变,否则电压配置会改变,并且电压会在下次启用稳压器时物理设置。

可以通过调用以下方式找到稳压器配置的电压输出

int regulator_get_voltage(regulator);
注意

get_voltage()将返回配置的输出电压,无论稳压器是启用还是禁用,并且不应用于确定稳压器输出状态。 但是,它可以与is_enabled()结合使用以确定稳压器物理输出电压。

4. 稳压器电流限制控制和状态(动态驱动)

一些消费者驱动程序需要能够动态更改其电源电流限制以匹配系统运行点。 例如,LCD背光驱动程序可以更改电流限制以改变背光亮度,USB驱动程序可能希望在供电时将限制设置为500mA。

消费者可以通过调用以下方式控制其电源电流限制

int regulator_set_current_limit(regulator, min_uA, max_uA);

其中min_uA和max_uA是以微安为单位的最小和最大可接受电流限制。

注意

这可以在启用或禁用稳压器时调用。 如果在启用时调用,则电流限制会立即改变,否则电流限制配置会改变,并且电流限制会在下次启用稳压器时物理设置。

可以通过调用以下方式找到稳压器电流限制

int regulator_get_current_limit(regulator);
注意

get_current_limit()将返回电流限制,无论稳压器是启用还是禁用,并且不应用于确定稳压器电流负载。

5. 稳压器运行模式控制和状态(动态驱动)

一些消费者可以通过更改其电源稳压器的运行模式来进一步节省系统功耗,以便在消费者运行状态改变时更有效。 例如,消费者驱动程序空闲并且随后消耗更少的电流

稳压器运行模式可以间接或直接更改。

间接运行模式控制。

消费者驱动程序可以通过调用以下方式请求更改其电源稳压器运行模式

int regulator_set_load(struct regulator *regulator, int load_uA);

这将导致核心重新计算稳压器上的总负载(基于其所有消费者),并更改运行模式(如果必要和允许)以最佳匹配当前运行负载。

load_uA值可以从消费者的数据表中确定。 例如,大多数数据表都有表格显示在某些情况下消耗的最大电流。

大多数消费者将使用间接运行模式控制,因为他们不了解稳压器或稳压器是否与其他消费者共享。

直接运行模式控制。

定制或紧密耦合的驱动程序可能希望根据其运行点直接控制稳压器运行模式。 这可以通过调用以下方式实现

int regulator_set_mode(struct regulator *regulator, unsigned int mode);
unsigned int regulator_get_mode(struct regulator *regulator);

只有 *知道* 稳压器且不与其他消费者共享稳压器的消费者才会使用直接模式。

6. 稳压器事件

稳压器可以通知消费者外部事件。 消费者可能会在稳压器压力或故障情况下收到事件。

消费者可以通过调用以下方式注册对稳压器事件的兴趣

int regulator_register_notifier(struct regulator *regulator,
                                struct notifier_block *nb);

消费者可以通过调用以下方式取消注册兴趣

int regulator_unregister_notifier(struct regulator *regulator,
                                  struct notifier_block *nb);

稳压器使用内核通知程序框架将事件发送给他们感兴趣的消费者。

7. 稳压器直接寄存器访问

某些类型的电源管理硬件或固件的设计方式使得它们需要对稳压器进行低级硬件访问,而无需内核的参与。 此类设备的示例有

  • 具有压控振荡器的时钟源和控制逻辑,可以通过I2C改变电源电压以实现所需的输出时钟频率

  • 可以在过温条件下发出任意I2C事务以执行系统断电的热管理固件

要设置此类设备/固件,需要为其配置各种参数,例如稳压器的I2C地址、各种稳压器寄存器的地址等。 稳压器框架提供了以下辅助函数来查询这些详细信息。

特定于总线的详细信息,例如I2C地址或传输速率由regmap框架处理。 要获取稳压器的regmap(如果支持),请使用

struct regmap *regulator_get_regmap(struct regulator *regulator);

要获取稳压器电压选择器寄存器的硬件寄存器偏移量和位掩码,请使用

int regulator_get_hardware_vsel_register(struct regulator *regulator,
                                         unsigned *vsel_reg,
                                         unsigned *vsel_mask);

要将稳压器框架电压选择器代码(由regulator_list_voltage使用)转换为可以直接写入电压选择器寄存器的特定于硬件的电压选择器,请使用

int regulator_list_hardware_vsel(struct regulator *regulator,
                                 unsigned selector);

要访问用于启用/禁用稳压器的硬件,消费者必须使用regulator_get_exclusive(),因为如果存在多个消费者则无法工作。 要启用/禁用稳压器,请使用

int regulator_hardware_enable(struct regulator *regulator, bool enable);