Linux电源管理之Regular系统
前言
本文简单介绍了Linux电源管理中较为简单的Regular子系统,regular系统使用简单广泛,在各种外设中只要需要电源都可以使用,以减少产品功耗。
一、概念
Regulator指的是稳定器,有电压稳定器及电流稳定器两种,能够自动维持恒定电流或者电压。其中,电压稳定器voltage regulator在电路中比较常见。从设备驱动的角度来看,regulator的控制比较简单,主要有enable/disable/输出电压或电流大小的控制。Linux利用regulator framework对regulator进行管理和控制。
Regulator : 电源芯片, 比如电压转换芯片
Consumer : 消费者,使用电源的部件, Regulator是给Consumer供电的
machine : 单板,上面焊接有Regulator和Consumer
Constraints : 约束, 比如某个电源管理芯片输出的电压范围
Supply : 提供电源的部件, Regulator就是一个Supply; Regulator A可以给Regulator B供电, 那么Regulator B的Supply就是A
二、框架
1、machine
machin使用struct regulator_init_data,静态的描述regulator在板级的硬件连接情况,这些限制通过驱动或dts配置,涉及到系统供电安全,因此必须小心,这些配置主要包括:
1)用于描述regulator在板级的级联关系:前级regulator(即该regulator的输出是另一个regulator的输入,简称supply regulator)和后级regulator(即该regulator的输入是其它regulator的输出,简称consumer regulator)。
2)利用struct regulation_constraints 描述regulator的物理限制,比如:
- 输出电压的最大值和最小值(voltage regulator);
- 输出电流的最大值和最小值(current regulator);
- 允许的操作(修改电压值、修改电流限制、enable、disable等);
- 输入电压是多少(当输入是另一个regulator时);
- 是否不允许关闭(always_on);
- 是否启动时就要打开(always_on);
2、regulator driver
regulator driver指的是regulator设备的驱动,主要包含如下结构:
1)使用struct regulator_desc,描述regulator的静态信息,包括:名字、supply regulator的名字、中断号、操作函数集(struct regulator_ops)、使用regmap时相应的寄存器即bitmap等。
2)使用struct regulator_config,描述regulator的动态信息(所谓的动态信息,体现在struct regulator_config变量都是局部变量,因此不会永久保存),包括struct regulator_init_data指针、设备指针、enable gpio等。
3)提供regulator的注册接口(regulator_register/devm_regulator_register),该接口接受描述该regulator的两个变量的指针:struct regulator_desc和struct regulator_config,并分配一个新的数据结构(struct regulator_dev,从设备的角度描述regulator),并把静态指针(struct regulator_desc)和动态指针(struct regulator_config)提供的信息保存在其中。
4)regulator driver以struct regulator_dev(代表设备)指针为对象,对regulator进行后续的操作。
2、regulator consumer
regulator consumer抽象出regulator设备(struct regulator),并提供regulator操作相关的接口。包括:regulator_get/regulator_put/regulator_enable/regulator_disable/ regulator_set_voltage/regulator_get_voltage等。
2、regulator core
regulator core负责上述regulator driver/consumer/machine逻辑的具体实现,对底层的硬件进行封装,并提供接口给内核中其他的consumer(使用当前regulator设备的驱动)提供操作接口,并以sysfs的形式,向用户空间提供接口。
三、驱动程序编写思路
- regulator:
注册一个platform_driver: 在它的probe函数里分配、设置、注册一个regulator
"设置"里要做的事情: 实现regulator的操作, 比如enable, disable, set_voltage - machine:
注册一个platform_device: 在它的私有数据里指定regulator和consume的对应关系(这个电源芯片给哪一个部件供电)
指定约束条件(比如电压范围) - consumer: 使用即可: regulator_get, regulator_enable, regulator_disable, regulator_set_voltage…
四、设备树regular节点
- regular主节点(/Linux-5.4/arch/arm/boot/dts/stm32mp15xx-edx.dtsi +163)
regulators {
164 compatible = "st,stpmic1-regulators";
165 buck1-supply = <&vin>;
166 buck2-supply = <&vin>;
167 buck3-supply = <&vin>;
168 buck4-supply = <&vin>;
169 ldo1-supply = <&v3v3>;
170 ldo2-supply = <&v3v3>;
171 ldo3-supply = <&vdd_ddr>;
172 ldo4-supply = <&vin>;
173 ldo5-supply = <&v3v3>;
174 ldo6-supply = <&v3v3>;
175 vref_ddr-supply = <&vin>;
176 boost-supply = <&vin>;
177 pwr_sw1-supply = <&bst_out>;
178 pwr_sw2-supply = <&bst_out>;
179
180 vddcore: buck1 {
181 regulator-name = "vddcore";
182 regulator-min-microvolt = <1200000>;
183 regulator-max-microvolt = <1350000>;
184 regulator-always-on;
185 regulator-initial-mode = <0>;
186 regulator-over-current-protection;
187 };
188
189 vdd_ddr: buck2 {
190 regulator-name = "vdd_ddr";
191 regulator-min-microvolt = <1350000>;
192 regulator-max-microvolt = <1350000>;
193 regulator-always-on;
194 regulator-initial-mode = <0>;
195 regulator-over-current-protection;
196 };
197
198 vdd: buck3 {
199 regulator-name = "vdd";
200 regulator-min-microvolt = <3300000>;
201 regulator-max-microvolt = <3300000>;
202 regulator-always-on;
203 st,mask-reset;
204 regulator-initial-mode = <0>;
205 regulator-over-current-protection;
206 };
207
208 v3v3: buck4 {
209 regulator-name = "v3v3";
210 regulator-min-microvolt = <3300000>;
211 regulator-max-microvolt = <3300000>;
212 regulator-always-on;
213 regulator-over-current-protection;
214 regulator-initial-mode = <0>;
215 };
216
217 vdda: ldo1 {
218 regulator-name = "vdda";
219 regulator-min-microvolt = <2900000>;
220 regulator-max-microvolt = <2900000>;
221 interrupts = <IT_CURLIM_LDO1 0>;
222 };
223
224 v2v8: ldo2 {
225 regulator-name = "v2v8";
225 regulator-name = "v2v8";
226 regulator-min-microvolt = <2800000>;
227 regulator-max-microvolt = <2800000>;
228 interrupts = <IT_CURLIM_LDO2 0>;
229 };
230
231 vtt_ddr: ldo3 {
232 regulator-name = "vtt_ddr";
233 regulator-min-microvolt = <500000>;
234 regulator-max-microvolt = <750000>;
235 regulator-always-on;
236 regulator-over-current-protection;
237 };
238
239 vdd_usb: ldo4 {
240 regulator-name = "vdd_usb";
241 regulator-min-microvolt = <3300000>;
242 regulator-max-microvolt = <3300000>;
243 interrupts = <IT_CURLIM_LDO4 0>;
244 regulator-always-on;
245 };
246
247 vdd_sd: ldo5 {
248 regulator-name = "vdd_sd";
249 regulator-min-microvolt = <2900000>;
250 regulator-max-microvolt = <2900000>;
251 interrupts = <IT_CURLIM_LDO5 0>;
252 regulator-boot-on;
253 };
254
255 v1v8: ldo6 {
256 regulator-name = "v1v8";
257 regulator-min-microvolt = <1800000>;
258 regulator-max-microvolt = <1800000>;
259 interrupts = <IT_CURLIM_LDO6 0>;
260 };
261
262 vref_ddr: vref_ddr {
263 regulator-name = "vref_ddr";
264 regulator-always-on;
265 regulator-over-current-protection;
266 };
267
68 bst_out: boost {
269 regulator-name = "bst_out";
270 interrupts = <IT_OCP_BOOST 0>;
271 };
272
273 vbus_otg: pwr_sw1 {
274 regulator-name = "vbus_otg";
275 interrupts = <IT_OCP_OTG 0>;
276 };
277
278 vbus_sw: pwr_sw2 {
279 regulator-name = "vbus_sw";
280 interrupts = <IT_OCP_SWOUT 0>;
281 regulator-active-discharge = <1>;
282 };
283 };
284
- sd卡开关电源管理节点(/Linux-5.4/arch/arm/boot/dts/stm32mp15xx-edx.dtsi 67)
68 sd_switch: regulator-sd_switch {
69 compatible = "regulator-gpio";
70 regulator-name = "sd_switch";
71 regulator-min-microvolt = <1800000>;
72 regulator-max-microvolt = <2900000>;
73 regulator-type = "voltage";
74 regulator-always-on;
75
76 gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>;
77 gpios-states = <0>;
78 states = <1800000 0x1 2900000 0x0>;
79 };
- 输入电源节点
81 vin: vin {
82 compatible = "regulator-fixed";
83 regulator-name = "vin";
84 regulator-min-microvolt = <5000000>;
85 regulator-max-microvolt = <5000000>;
86 regulator-always-on;
87 };