Regulator overview
目录
Article Purpose
This article aims to explain how to use regulators:
- how to configure a regulator on a Linux BSP
- how to access a regulator from a kernel space
This article is applicable for the Linux kernel version 4.10 and later.
System overview
Some documentation on the Linux regulator framework is provided with the kernel source code:overview.txt [1]
Overview
The power supplies can be provided by various blocks:
- External single regulators:
- Low-dropout regulators (LDO)
- BUCKs (DC-to-DC power converter)
- Switches
- A Power Management Integrated Circuit (PMIC) that integrates several LDO and BUCKS
- Internal regulators from the microprocessor device internal blocks:
All the regulators are implemented and controlled under the standard Linux regulator framework.
Components Description
External devices: external regulators, PMIC
This corresponds to physical components that provide the various power supplies on the board.
Microprocessor device internal regulators
This corresponds to the regulators integrated to the microprocessor device. Those regulators supply mainly the USB and ADC peripherals.
Regulator drivers
A regulator that can be controlled (enable/disable, adjust voltage...) needs a driver to operate. This is the role of the regulator driver.
A driver can also send notifications like over current or over temperature.
Notes:
- The kernel contains generic drivers for GPIO controlled regulators.
- The PMIC uses a specific driver.
- The internal regulators of the microprocessor device are implemented in the STM32 machine.
- kernel Documentation regulator.txt [4]
Regulator framework core
The core manages all the regulators. A consumer request is not handled directly by a regulator driver. It is handled by the core that can arbitrate requests between consumers in order to save power.
Regulator consumers
The devices correspond to internal or external peripherals of the microprocessor device ( ADC, SDCARD, USB, ETHERNET... )
Each peripheral that needs a power supply to operate must enable it. When a regulator is not used, it is disabled by the core.
The consumer interface allows to control a regulator (enable/disable, set voltage...), and to register to a notification service.
- kernel Documentation consumer.txt [5]
Sysfs interface
The regulator framework offers a sysfs interface that can be used for monitoring. It is not possible to control a regulator via the sysfs.
Configfs interface
Most of the regulator configurations are described in the device-tree (configfs)
How to find the source code
Everything is part of the kernel source code:
- The regulator framework core and drivers code are located in drivers/regulator | |}} regulator
- Driver interface: include/linux/regulator/driver.h | |}} driver.h
- Consumer interface: include/linux/regulator/consumer.h | |}} consumer.h
Regulator configuration
Kernel configuration
The configuration is done using the standard menuconfig. Most configurations are available under Device Drivers / Voltage and Current Regulator Support
Device tree configuration
The device tree describes regulators and consumers:
- A regulator provides a supply.
- A consumer uses a supply.
When possible, the supply name comes from the electrical schematics of the board.
Some regulator drivers
Binding Doc:Documentation/devicetree/bindings/regulator/regulator.txt | |}} regulator.txt
Gpio controlled regulator
usb otg vbus:
vbus_otg: regulator-vbus_otg { compatible = "regulator-fixed"; regulator-name = "vbus_otg"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; gpio = <&gpioz 4 0>; enable-active-high; };
Binding Doc:Documentation/devicetree/bindings/regulator/fixed-regulator.txt | |}} fixed-regulator.txt
sdcard level shifter:
sd_switch: regulator-sd_switch { compatible = "regulator-gpio"; regulator-name = "sd_switch"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <2900000>; regulator-type = "voltage"; regulator-always-on; gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; gpios-states = <0>; states = <1800000 0x1 2900000 0x0>; };
Binding Doc:Documentation/devicetree/bindings/regulator/gpio-regulator.txt | |}} gpio-regulator.txt
PMIC
pmic: stpmu1@33 { compatible = "st,stpmu1"; reg = <0x33>; interrupts = <0 2>; interrupt-parent = <&gpioa>; interrupt-controller; #interrupt-cells = <2>; status = "okay"; st,main_control_register = <0x04>; st,vin_control_register = <0xc0>; st,usb_control_register = <0x30>; regulators { compatible = "st,stpmu1-regulators"; vddcore: buck1 { regulator-compatible = "buck1"; regulator-name = "vddcore"; regulator-min-microvolt = <800000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <2>; regulator-state-standby { regulator-on-in-suspend; regulator-suspend-microvolt = <900000>; regulator-mode = <8>; }; regulator-state-mem { regulator-off-in-suspend; }; regulator-state-disk { regulator-off-in-suspend; }; }; vdd_ddr: buck2 { regulator-compatible = "buck2"; regulator-name = "vdd_ddr"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <2>; regulator-state-standby { regulator-suspend-microvolt = <1350000>; regulator-on-in-suspend; regulator-mode = <8>; }; regulator-state-mem { regulator-suspend-microvolt = <1350000>; regulator-on-in-suspend; regulator-mode = <8>; }; regulator-state-disk { regulator-off-in-suspend; }; }; ... };
NOTE: The PMIC features allow to achieve more advanced suspend states: for each state, it is possible to define whether the regulator is enabled/disabled and to define a specific voltage.
Microcontroller device internal regulator
VREFBUF[3] regulator:
vrefbuf: vrefbuf@50025000 { compatible = "st,stm32-vrefbuf"; reg = <0x50025000 0x8>; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <2500000>; clocks = <&rcc_clk VREF>; status = "disabled"; };
Binding Doc:Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.txt | |}} st,stm32-vrefbuf.txt
Consumers
See below some examples of consumers.
The SDMMC needs 2 power supply:
&sdmmc1 { vmmc-supply = <&vdd_sd>; vqmmc-supply = <&sd_switch>; };
The name before "-supply" is not free. vmmc and vqmmc are imposed by the consumer driver. They should be aligned with the name used in the data sheet of the driven component.
The USBPHY is supplied by vdd_usb:
&usbphyc { vdd-supply = <&vdd_usb>; };
The DAC is supplied by vdda:
&dac { pinctrl-names = "default"; pinctrl-0 = <&dac_ch1_pins &dac_ch2_pins>; vref-supply = <&vdda>; status = "okay"; ... };
The regulators can be consumers. This is used to define power domains:
pmic: stpmu1@33 { compatible = "st,stpmu1"; ... regulators { compatible = "st,stpmu1-regulators"; ldo1-supply = <&v3v3>; ldo2-supply = <&v3v3>; ldo5-supply = <&v3v3>; ldo6-supply = <&v3v3>; vref_ddr-supply = <&vdd_ddr>; vbus_otg-supply = <&bst_out>; sw_out-supply = <&bst_out>; ... }; };
Enabling ldo1 will enable v3v3 automatically.
Power management
The regulator framework handles the power management at runtime and during suspend.
Runtime
- The consumers should disable the regulators that are not needed.
- The core disables a regulator as soon as it is not requested by any consumer.
This can be avoided by the usage of "regulator-always-on" property in the device-tree.
Suspend
The regulator framework offers the possibility to define suspend states for regulators. This is only possible if the driver allows it.
regulator-state-standby, regulator-state-mem, regulator-state-disk are used to define the state of the regulators during suspend.
regulator-state-standby { regulator-on-in-suspend; regulator-suspend-microvolt = <900000>; regulator-mode = <8>; }; regulator-state-mem { regulator-off-in-suspend; };
- The regulator runtime strategy does not apply to suspend. With "regulator-on-in-suspend", the regulator is enabled in suspend even if no consumer uses it.
- "regulator-always-on" does not apply to suspend states.
How to trace and debug the framework
How to trace
The regulator framework provides 调试文件系统(debugfs) tools. The most important one is regulator/regulator_summary:
Board $> cat /sys/kernel/debug/regulator/regulator_summary regulator use open bypass voltage current min max ------------------------------------------------------------------------------- regulator-dummy 0 6 0 0mV 0mA 0mV 0mV vddcore 0 0 0 1200mV 0mA 800mV 1350mV vdd_ddr 0 1 0 1350mV 0mA 1350mV 1350mV vtt_ddr 0 0 0 675mV 0mA 675mV 675mV vdd 0 1 0 3300mV 0mA 3300mV 3300mV 58007000.sdmmc 3300mV 3300mV v3v3 1 5 0 3300mV 0mA 3300mV 3300mV 58007000.sdmmc 3300mV 3300mV vdda 0 2 0 2900mV 0mA 2900mV 2900mV 40017000.dac 0mV 0mV 48003000.adc 0mV 0mV v2v8 0 0 0 2800mV 0mA 2800mV 2800mV vdd_sd 0 1 0 2900mV 0mA 2900mV 2900mV 58005000.sdmmc 2900mV 2900mV v1v8 0 0 0 1800mV 0mA 1800mV 1800mV vdd_usb 0 0 0 3300mV 0mA 3300mV 3300mV bst_out 0 2 0 5000mV 0mA 0mV 0mV vbus_otg 0 0 0 5000mV 0mA 0mV 0mV vbus_sw 0 0 0 5000mV 0mA 0mV 0mV sd_switch 0 1 0 2900mV 0mA 1800mV 2900mV 58005000.sdmmc 2700mV 2900mV reg11 0 0 0 1100mV 0mA 1100mV 1100mV reg18 0 0 0 1800mV 0mA 1800mV 1800mV usb33 0 0 0 3300mV 0mA 3300mV 3300mV vref_ddr 0 0 0 675mV 0mA 0mV 0mV
Notes:
- use: counts the "enable" calls made by the consumers
- open: is the number of consumers that get the regulator
- vdd_sd is a consumer for v3v3
- 58005000.sdmmc is a consumer for v3v3, vdd_sd, sd_switch
- when regulator_always_on property is set, use is equal to ZERO (but the regulator is enabled...)
References
<securetransclude src="ProtectedTemplate:PublicationRequestId" params="7961 | 2018-07-03 | AlainF"></securetransclude> <securetransclude src="ProtectedTemplate:ArticleBasedOnModel" params="Framework overview article model"></securetransclude> <securetransclude src="ProtectedTemplate:ReviewsComments" params="JCT 1840: alignment needed with the last version of the model<br>"></securetransclude>{{#set:Has reviews comments=true}}