Skip to main content
 首页 » 操作系统

Linux Regeultor内核文档翻译_学习笔记

2022年07月19日75mengfanrong

一、Documentation\power\regulator\overview.txt

1.命名规则

(1) Regulator - 为其他设备供电的电子设备。大多数调节器可以启用和禁用其输出,而某些调节器可以控制其输出电压和/或电流。
Input Voltage -> Regulator -> Output Voltage

(2) PMIC - 电源管理IC。一个pmic里面包含大量regulator且通常包含其他子系统的IC。

(3) Consumer -由调节器供电的电子设备,Consumers可分为两类:

静态:消费者不更改其电源电压或电流限制。它只需要启用或禁用电源即可。它的电源电压由硬件,启动程序,固件或内核板初始化代码设置。

动态:消费者需要更改其电源电压或电流限制,以满足操作需求。

(4) Power Domain - 由调节器、开关或其他电源域的输出功率提供其输入功率的电子电路。电源调节器可能在开关后面。即:

Regulator -+-> Switch-1 -+-> Switch-2 --> [Consumer A] 
           |             | 
           |             +-> [Consumer B], [Consumer C] 
           | 
           +-> [Consumer D], [Consumer E]

这是一个调节器和三个电源域:

域1:Switch-1,消费者D和E。
域2:Switch-2,消费者B和C。
域3:消费者A。

这表示一种“供应”关系:

Domain-1 --> Domain-2 --> Domain-3.

电源域可能具有由其他调节器供电的调节器。即:

Regulator-1 -+-> Regulator-2 -+-> [Consumer A] 
             | 
             +-> [Consumer B]

这为我们提供了两个调节器和两个电源域:
Domain 1: Regulator-2, Consumer B.
Domain 2: Consumer A.
和“供应”关系:
Domain-1 --> Domain-2

(5) Constraints - 约束用于定义功耗性能和硬件保护的功率级别。 约束存在三个层次:

a. 调节器级别:这由调节器硬件操作参数定义,并在调节器数据表中指定。 即:
-电压输出范围为800mV-> 3500mV。
-电流输出限制为20mA@5V,但为10mA@10V。

b. 电源域级别:这是在软件中由内核级板初始化代码定义的。 它用于将电源域限制为特定的范围内。即:
-域1电压为3300mV
-域2电压为1400mV->1600mV
-域3的电流限制为0mA->20mA。

c. 消费者级别:由Consumer的驱动程序动态设置电压或电流的限制水平的定义。

例如,消费者背光驱动器要求电流从5mA增加到10mA以增加LCD照明,通过以下级别:

消费者:需要增加LCD的亮度。在亮度表中查找并请求下一个电流mA值(基于相同的参考设备,用户驱动程序可以用于几种不同的方式)。
电源域:是对此域和系统状态(例如电池电源,USB电源)进行限制的一种新的电流限制方式。
调节器域:是在调节器工作参数中调节输入/输出电压的一种新的电流限制方式。

如果对调节器的请求通过了所有约束测试,则将应用新的调节器值。

2. 设计

该框架旨在针对基于SoC的设备而设计的,但也可能与非SoC设备相关,并且分为以下四个接口:

(1) 消费者驱动接口(Consumer driver interface)。

这使用了与内核时钟接口类似的API,因为消费者驱动程序可以获取和释放一个调节器(就像使用atm时钟一样)并获取/设置电压电流限制,模式,启用和禁用。 这应该使消费者驱动能够完全控制其电源电压和电流限制。 如果不使用,这也可以不编译进去,因此驱动程序可以在不基于调节器的电源控制的系统中重用。

请看 Documentation/power/regulator/consumer.txt

(2) 调节器驱动程序接口(Regulator driver interface)。
这使调节器驱动程序可以注册其调节器并向内核提供操作。 它还具有一个通知链,用于将调节事件传播给客户(clients)。

请看 Documentation/power/regulator/regulator.txt

(3) 机器接口(Machine interface)

该接口特定用于机器的代码,并允许为每个调节器创建电压/电流域(带有约束)。它可以提供调节器约束,以防止由于错误的客户端驱动器引起的过电压或过电流而损坏设备。它还允许创建一个调节器树,其中一些调节器由其他调节器供电(类似于时钟树)。

请看 /power/regulator/machine.txt

(4) 用户空间ABI。

该框架还通过sysfs将大量有用的电压/电流/opmode数据导出到用户空间。 这可用于帮助监视设备的功耗和状态。

请看 Documentation/ABI/testing/sysfs-class-regulator

二、Documentation\power\regulator\consumer.txt

稳压器消费者驱动程序接口
==================================

本文介绍了消费类设备驱动程序的调节器接口。请参阅overview.txt以获取本文中所用术语的描述。

1.消费者驱动获取调节器(静态和动态驱动程序)
=======================================================

(1) 消费者驱动程序可以通过以下方式访问为其供电的调节器:

regulator = regulator_get(dev, "Vcc"); //Vcc-supply = <&XXX>

使用者传递其dev结构设备指针和supplyID。 然后,内核通过查询机器特定的查找表来找到正确的调节器。如果查找成功,则此调用将返回一个指针,该指针指向此使用者的调节器结构。

(2) 要释放调节器,消费者驱动程序可以调用:

regulator_put(regulator);

消费者可能存在同时由多个调节器供电的情况,例如,具有需要进行模拟供电和数字供电的编解码器:

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

通常在消费者驱动的probe()中调用regulator_get(),在消费者驱动的remove()中调用regulator_put()。

2.调节器输出的使能和禁止(静态和动态驱动)
=======================================================

(1) 消费者可以通过以下方式启用电源:

int regulator_enable(regulator);

注意:在调用regulator_enabled()之前,电源可能已经启用。如果使用者共享调节器,或者先前已通过引导加载程序或内核板初始化代码启用了调节器,则可能会发生这种情况。

(2) 消费者驱动可以通过以下方式确定是否已经使能了调节器:

int regulator_is_enabled(regulator); //若调节器是使能的,返回0

(3) 消费者驱动可以通过以下方式禁用不再需要的电源:

int regulator_disable(regulator);

注意:如果与其他使用者共享电源,则可能不会禁用电源。仅当启用的引用计数为零时,才会真正禁用此调节器。

(4) 在紧急情况下,可以强制禁用调节器:

int regulator_force_disable(regulator);

注意:这将立即强制关闭调节器输出。所有使用此调节器的消费者都会下电。

3.调节器的电压控制和状态(动态驱动)
======================================================

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

(1) 消费者驱动可以通过以下方式控制其电源电压:

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

注意:可以在启用或禁用调节器时调用此函数。如果在启用时调用,则电压会立即改变,否则电压配置会改变,并且在下次使能调节器时会实际设置电压。

(2) 调节器配置的电压输出值可通过以下方法查到:

int regulator_get_voltage(regulator);

注意:无论是启用还是禁用调节器的状态,get_voltage()都将返回配置的输出电压,因此不应将其用于确定调节器的输出状态。但是,可以将其与is_enabled()结合使用以确定调节器的物理输出电压。

4.调节器电流限制控制和状态(动态驱动)
======================================================

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

(1) 消费者可以通过以下方式控制其电源电流限制:

int regulator_set_current_limit(regulator, min_uA, max_uA); //其中min_uA和max_uA是微安的最小和最大可接受电流限制。

注意:在启用或禁用调节器的状态下都可以调用此函数。如果在启用时调用,则电流限制会立即生效,否则电流限制配置会更改,并且在下次启用调节器时会实际设置电流限制。

(3) 可以通过以下方法查询调节器的电流限制:

int regulator_get_current_limit(regulator);

注意:无论是启用还是禁用调节器的状态,get_current_limit()都将返回电流限制,因此不应将其用于确定调节器实际电流值。

5. 调节器操作模式控制和状态(动态驱动器)
======================================================

一些使用者可以通过更改其电源调节器的工作模式来进一步节省系统功率,从而在使用者工作状态发生变化时更加高效。 例如 消费者驱动程序处于空闲状态,因此消耗的电流更少

调节器的运行模式可以间接或直接更改。

(1) 间接操作模式控制。
--------------------------------
消费者驱动可以通过调用这个函数更改其供应调节器的运行模式

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

这将导致内核重新计算调节器上的总负载(基于其所有consumers),并更改运行模式(如果需要并允许)以最佳地匹配当前的运行负载。

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

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

(2) 直接操作模式控制。
------------------------------
定制或紧密耦合的驱动器可能希望根据其工作点直接控制调节器的工作模式。 这可以通过调用这个函数实现:

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

直接模式将仅由“了解”调节器并且不与其他使用者共享调节器的使用者使用。

6.调节器事件
===================
Regulators可以将外部事件通知消费者。 消费者可以在调节器压力或故障条件下接收事件。

消费者可以通过以下方式注册对调节器事件的监听:

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

消费者可以通过以下方式取消对调节器事件的监听:

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

调机器使用内核通知链框架将事件发送给感兴趣的使用者(Consumers)。

7. Regulator直接寄存器访问
==================================
某些电源管理硬件或固件经过设计,因此它们需要对调节器进行低级硬件访问,而无需内核参与。 此类设备的示例是:

-具有压控振荡器和控制逻辑的时钟源,用于改变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);

三、Documentation\power\regulator\regulator.txt

调节器驱动程序接口
=========================

调节器驱动程序界面相对简单,旨在允许调节器驱动程序在核心框架中注册其服务。

1.注册
============

驱动可以通过以下方式注册一个regulator:

struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, const struct regulator_config *config);

这会将调节器的功能和操作注册到调节器核心。

2. 可以通过以下方式取消调节器的注册:

void regulator_unregister(struct regulator_dev *rdev);

3. 调节器事件
================
调节器可以通过以下方式将事件(例如,过热,欠压等)发送给消费者驱动器:

int regulator_notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data);

四、Documentation\power\regulator\machine.txt

1. 调节器Machine端驱动程序接口
==================================

调节器Machine驱动程序接口旨在用于主板/机器专用的初始化代码,以配置调节器子系统。

考虑以下机器:

  Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V] 
               | 
               +-> [Consumer B @ 3.3V]

消费者A和B的驱动必须映射到正确的调节器,以控制其电源。 通过为每个调节器创建一个struct regulator_consumer_supply结构,可以在机器初始化代码中实现此映射。

struct regulator_consumer_supply { 
    const char *dev_name;    /* consumer dev_name() */ 
    const char *supply;    /* consumer supply - e.g. "vcc" */ 
};

例如 对于上面的机器

static struct regulator_consumer_supply regulator1_consumers[] = { 
    REGULATOR_SUPPLY("Vcc", "consumer B"), 
}; 
 
static struct regulator_consumer_supply regulator2_consumers[] = { 
    REGULATOR_SUPPLY("Vcc", "consumer A"), 
};

这将调节器1映射到消费者B的“Vcc”电源,并将调节器2映射到消费者A的“Vcc”电源。

现在可以通过为每个调节器电源域定义一个struct regulator_init_data 来注册约束。 这种结构还将消费者映射到他们的供应调节器中:

static struct regulator_init_data regulator1_data = { 
    .constraints = { 
        .name = "Regulator-1", 
        .min_uV = 3300000, 
        .max_uV = 3300000, 
        .valid_modes_mask = REGULATOR_MODE_NORMAL, 
    }, 
    .num_consumer_supplies = ARRAY_SIZE(regulator1_consumers), 
    .consumer_supplies = regulator1_consumers, 
};

名称字段应设置为对板有用的描述,用于配置其他调节器的电源以及用于日志记录和其他诊断输出。 通常,示意图中用于供电轨的名称是一个不错的选择。 如果未提供名称,则子系统将选择一个。

调节器1为调节器2供电。 此关系必须在内核中注册,以便在消费者A启用其电源(Regulator-2)时也启用Regulator-1。 电源调节器由下面的supply_regulator字段和co设置:

static struct regulator_init_data regulator2_data = { 
    .supply_regulator = "Regulator-1", 
    .constraints = { 
        .min_uV = 1800000, 
        .max_uV = 2000000, 
        .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, 
        .valid_modes_mask = REGULATOR_MODE_NORMAL, 
    }, 
    .num_consumer_supplies = ARRAY_SIZE(regulator2_consumers), 
    .consumer_supplies = regulator2_consumers, 
};

最后,必须以常规方式注册调节器设备。

static struct platform_device regulator_devices[] = { 
    { 
        .name = "regulator", 
        .id = DCDC_1, 
        .dev = { 
            .platform_data = &regulator1_data, 
        }, 
    }, 
    { 
        .name = "regulator", 
        .id = DCDC_2, 
        .dev = { 
            .platform_data = &regulator2_data, 
        }, 
    }, 
}; 
/* register regulator 1 device */ 
platform_device_register(&regulator_devices[0]); 
 
/* register regulator 2 device */ 
platform_device_register(&regulator_devices[1]);

五、Documentation\ABI\testing\sysfs-class-regulator

(1) /sys/class/regulator/.../state

一些调节器目录将包含一个称为state的字段。 这报告了调节器启用控制,用于可以报告该输入值的调节器。

这将是以下字符串之一:
'enabled'
'disabled'
'unknown'

“enabled”表示调节器输出为ON,并且正在为系统供电(假设没有错误可防止调节器输出)。
“disabled”表示调节器输出为OFF,并且不为系统供电(除非某些非Linux控件已启用它)。
“unknown”表示软件无法确定状态,或报告的状态无效。
注意:此字段可与微伏或微安一起使用,以确定已配置的调节器输出电平。

(2) /sys/class/regulator/.../status

某些调节器目录将包含一个称为“status”的字段。 对于可以报告该输出值的调节器,此报告当前的调节器状态。

这将是以下字符串之一:
off
on
error
fast
normal
idle
standby

“off”表示调节器没有为系统供电。

“on”表示调节器正在为系统供电,并且调节器无法报告详细的操作模式。

“error”表示失调状态,例如由于热关机而被禁用,或者由于输入电源的问题而导致电压不稳定。

“fast”,“normal”,“idle”和“standby”都是详细的调节器操作模式(在其他地方介绍)。 它们暗示“on”,但提供更多细节。

请注意,调节器状态是许多输入的函数,而不仅限于Linux的控制输入。 例如,显示的实际负载可能会触发“error”状态。 或其他用户可能启用了调节器,即使Linux没有启用它也是如此。

(3) /sys/class/regulator/.../type

每个调节器目录将包含一个称为type的字段。 这保存调节器类型。

这将是以下字符串之一:
'voltage'
'current'
'unknown'

“voltage”表示调节器的输出电压可以通过软件控制。
“current”表示调节器输出电流极限可以通过软件控制
“unknown”表示软件无法控制电压或电流限制。

(4) /sys/class/regulator/.../microvolts

一些调节器目录将包含一个称为microvolts(微伏)的字段。 对于可报告电压控制输入的调节器,它保持以微伏(即E-6伏)为单位的调节器输出电压设置。
注意:该值不应用于确定调节器输出电压电平,因为无论调节器是启用还是禁用,该值都相同。

(5) /sys/class/regulator/.../microamps

一些调节器目录将包含一个称为microamps(微安)的字段。 对于可报告电流限制的控制输入的调节器,这将保持以微安(即E-6安培)为单位的调节器输出电流限制设置。
注意:此值不应用于确定egulator的输出电流水平,因为无论调节器是启用还是禁用,此值都相同。

(6) /sys/class/regulator/.../opmode

一些调节器目录将包含一个名为opmode的字段。 对于可以报告该控制输入值的调节器,它保持当前的调节器操作模式。

opmode值可以是以下字符串之一:
'fast'
'normal'
'idle'
'standby'
'unknown'

模式在include/linux/regulator/consumer.h中描述
注意:此值不应用于确定调节器输出操作模式,因为无论调节器是启用还是禁用,此值都相同。 “status”属性可能可用于确定实际模式。

(7) /sys/class/regulator/.../min_microvolts

一些调节器目录将包含一个名为min_microvolts的字段。 对于支持电压约束的调节器,此保存该域的最小安全工作调节器输出电压设置(以微伏为单位)。

注意:如果电源域没有平台代码定义的最小微伏特约束,则它将返回字符串“constraint not defined”。

(8) /sys/class/regulator/.../max_microvolts

一些调节器目录将包含一个名为max_microvolts的字段。 对于支持电压限制的调节器,此保持该域的最大安全工作调节器输出电压设置(以微伏为单位)。

注意:如果电源域没有平台代码定义的最大微伏约束,则将返回字符串“ constraint not defined”。

(9) /sys/class/regulator/.../min_microamps

一些调节器目录将包含一个名为min_microamps的字段。 对于支持电流限制的调节器,这保持了该域的最小安全工作调节器输出电流限制设置(以微安为单位)。
注意:如果电源域没有平台代码定义的最小微安约束,则它将返回字符串“ constraint not defined”。

(9) /sys/class/regulator/.../max_microamps

一些调节器目录将包含一个名为max_microamps的字段。 对于支持电流限制的调节器,此保持该域的最大安全工作调节器输出电流限制设置(以微安为单位)。
注意:如果电源域没有平台代码定义的最大微安约束,则它将返回字符串“ constraint not defined”。

(10) /sys/class/regulator/.../name

每个调节器目录将包含一个名为name的字段。 它包含一个字符串,用于标识用于显示的调节器。
注意:如果平台或调节器驱动程序未提供合适的名称,则此字段为空。

(11) /sys/class/regulator/.../num_users

每个调节器目录将包含一个名为num_users的字段。 这保留了在此调节器上调用了regulator_enable()的消费类设备的数量。

(12) /sys/class/regulator/.../requested_microamps

一些调节器目录将包含一个名为requested_microamps的字段。 这将保持其所有消费类设备为该稳压器提供的总要求负载电流(以微安为单位)。

(13) /sys/class/regulator/.../parent

一些调节器目录将包含一个称为parent的链接。 如果存在,则指向上级或供应regulator。

(14) /sys/class/regulator/.../suspend_mem_microvolts

一些调节器目录将包含一个名为suspend_mem_microvolts的字段。 当系统挂起至存储器时,这将保持该域的调节器输出电压设置(以微伏为单位),用于实现挂起电压配置约束的电压调节器。

(15) /sys/class/regulator/.../suspend_disk_microvolts

一些调节器目录将包含一个名为suspend_disk_microvolts的字段。 当系统悬挂到磁盘上时,这将保持该域的调节器输出电压设置(以微伏为单位),以实现实现suspend电压配置约束的电压调节器。

(16) /sys/class/regulator/.../suspend_standby_microvolts

一些调节器目录将包含一个称为suspend_standby_microvolts的字段。 当系统挂起到待机状态时,这将保持该域的调节器输出电压设置(以微伏为单位),
用于实现了suspend电压配置约束的电压调节器。

(17) /sys/class/regulator/.../suspend_mem_mode

一些调节器目录将包含一个称为suspend_mem_mode的字段。 当系统挂起到内存时,这将保留该域的调节器操作模式设置,以用于实现挂起模式配置约束的调节器。

(18) /sys/class/regulator/.../suspend_disk_mode

一些调节器目录将包含一个称为suspend_disk_mode的字段。 当系统挂起到磁盘时,这将保留该域的调节器操作模式设置,以用于实现挂起模式配置约束的调节器。

(19) /sys/class/regulator/.../suspend_standby_mode

一些调节器目录将包含一个称为suspend_standby_mode的字段。 当系统挂起到standby状态时,这将保留该域的调节器操作模式设置,以用于实现挂起模式配置约束的调节器。

(20) /sys/class/regulator/.../suspend_mem_state

一些调节器目录将包含一个称为suspend_mem_state的字段。 当调节器实施到挂起配置约束时,这将保持调节器在suspend到内存中时的工作状态。
这将是“ state”属性报告的相同字符串之一。

(21) /sys/class/regulator/.../suspend_disk_state

一些调节器目录将包含一个名为suspend_disk_state的字段。 当调节器实施到挂起配置约束时,它会在挂起到磁盘时保持调节器的工作状态。这将是“ state”属性报告的相同字符串之一。

(22) /sys/class/regulator/.../suspend_standby_state

一些调节器目录将包含一个称为suspend_standby_state的字段。 当调节器实现暂停配置约束时,它会在暂停到待机状态时保持调节器的工作状态。这将是“ state”属性报告的相同字符串之一。

(22) /sys/class/regulator/.../bypass

一些调节器目录将包含一个称为bypass(旁路)的字段。 这表明设备是否处于旁路模式。
这将是以下字符串之一:
'enabled'
'disabled'
'unknown'
“enabled”表示调节器处于旁路模式。
“disabled”表示调节器正在监管。
“unknown”表示软件无法确定状态,或报告的状态无效。

五、补充

1.dump /d/regulator下的内容可以看到设备树中供电配置的差异。


本文参考链接:https://www.cnblogs.com/hellokitty2/p/14165334.html