Difference between revisions of "Regulator overview"

[unchecked revision] [quality revision]
m (SCMI regulator)
m (Microcontroller device internal regulator)
 

This article gives information about the Linux® regulator framework.

1 Article Purpose[edit]

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.

2 System overview[edit]

Some documentation on the Linux regulator framework is provided with the kernel source code:overview.rst [1]


2.1 Overview[edit]

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:
    • PWR peripheral [2]
    • VREFBUF peripheral [3]

All the regulators are implemented and controlled under the standard Linux regulator framework.

2.2 Components Description[edit]

Regulators.png

2.2.1 External devices: external regulators, PMIC[edit]

This corresponds to physical components that provide the various power supplies on the board.

2.2.2 Microprocessor device internal regulators[edit]

This corresponds to the regulators integrated to the microprocessor device. Those regulators supply mainly the USB and ADC peripherals.

2.2.3 Regulator drivers[edit]

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]

2.2.4 Regulator framework core[edit]

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.

2.2.5 Regulator consumers[edit]

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]

2.2.6 Sysfs interface[edit]

The regulator framework offers a sysfs interface that can be used for monitoring. It is not possible to control a regulator via the sysfs.

2.2.7 Configfs interface[edit]

Most of the regulator configurations are described in the device-tree (configfs)

3 How to find the source code[edit]

Everything is part of the kernel source code:

  • The regulator framework core and drivers code are located in drivers/regulator directory

4 Regulator configuration[edit]

4.1 Kernel configuration[edit]

The configuration is done using the standard menuconfig. Most configurations are available under Device Drivers / Voltage and Current Regulator Support

4.2 Device tree configuration[edit]

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.

4.2.1 Some regulator drivers[edit]

Binding Doc:regulator.yaml

4.2.1.1 Gpio controlled regulator[edit]

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:fixed-regulator.yaml

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:gpio-regulator.yaml

4.2.1.2 PMIC[edit]
   pmic: stpmu1@33 {
       compatible = "st,stpmu1";
       reg = <0x33>;
       interrupts = <0 2>;
       interrupt-parent = <&gpioa>;
       interrupt-controller;
       #interrupt-cells = <2>;
       status = "okay";
   
       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>;
           };
   
           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>;
           };
           ...
       };
       
4.2.1.3 Microcontroller device internal regulator[edit]

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:st,stm32-vrefbuf.txt yaml

4.2.1.4 SCMI regulator[edit]

The SCMI protocol permits to drive a regulator handled by the secure monitor (OP-TEE). Linux scmi driver implements requests like get, set voltage, enable and disable. OP-TEE then receives and arbitrate the requests depending on internal constraints.

 scmi0_voltd: protocol@17 {
 	reg = <0x17>;
 
 	scmi0_regu: regulators {
 		scmi_reg11: voltd-reg11 {
 			voltd-name = "reg11";
 			regulator-name = "reg11";
 		};
 		scmi_reg18: voltd-reg18 {
 			voltd-name = "reg18";
 			regulator-name = "reg18";
 		};
 		...
 	};
 };

Binding Doc:arm,scmi.txt

4.2.2 Consumers[edit]

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.

5 Power management[edit]

The regulator framework handles the power management at runtime and during suspend.

5.1 Runtime[edit]

  • 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.

5.2 Suspend[edit]

The regulator framework offers the possibility to define suspend states for regulators. This is only possible if the driver allows it. The regulator suspend sate is no more handled by the linux kernel in OpenSTLinux distribution.

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.


6 How to trace and debug the framework[edit]

6.1 How to trace[edit]

The regulator framework provides debugfs tools. The most important one is regulator/regulator_summary:

 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...)

7 References[edit]



This article gives information about the Linux<sup>&reg;</sup> regulator framework.

== 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.rst <ref>{{CodeSource | Linux kernel | Documentation/power/regulator/overview.rst| kernel documentation overview}}</ref>


=== 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:
** PWR peripheral <ref>[[PWR internal peripheral]]</ref>

** VREFBUF peripheral <ref name="vrefbuf">[[VREFBUF internal peripheral]]</ref>


All the regulators are implemented and controlled under the standard Linux regulator framework.

=== Components Description ===

[[File:regulators.png|link=]]

==== 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 <ref>{{CodeSource | Linux kernel | Documentation/power/regulator/regulator.rst | Driver API documentation}}</ref>


==== 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 <ref>{{CodeSource | Linux kernel | Documentation/power/regulator/consumer.rst | Consumer API documentation}}</ref>


==== 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 directory
** Driver interface: {{CodeSource | Linux kernel | include/linux/regulator/driver.h | driver.h}}
** Consumer interface: {{CodeSource | Linux kernel | 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:{{CodeSource | Linux kernel | Documentation/devicetree/bindings/regulator/regulator.yaml | regulator.yaml}}

===== 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:{{CodeSource | Linux kernel | Documentation/devicetree/bindings/regulator/fixed-regulator.yaml | fixed-regulator.yaml}}

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:{{CodeSource | Linux kernel | Documentation/devicetree/bindings/regulator/gpio-regulator.yaml | gpio-regulator.yaml}}

===== PMIC ===== 

    pmic: stpmu1@33 {
        compatible = "st,stpmu1";
        reg = <0x33>;
        interrupts = <0 2>;
        interrupt-parent = <&gpioa>;
        interrupt-controller;
        #interrupt-cells = <2>;
        status = "okay";

        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>;
            };

            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>;
            };
            ...
        };

===== Microcontroller device internal regulator ===== 

VREFBUF<ref name="vrefbuf"/> 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:{{CodeSource | Linux kernel | Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.txtyaml | st,stm32-vrefbuf.txtyaml}}

===== SCMI regulator =====

The SCMI protocol permits to drive a regulator handled by the secure monitor (OP-TEE).
Linux scmi driver implements requests like get, set voltage, enable and disable.
OP-TEE then receives and arbitrate the requests depending on internal constraints.

  scmi0_voltd: protocol@17 {
  	reg = <0x17>;

  	scmi0_regu: regulators {
  		scmi_reg11: voltd-reg11 {
  			voltd-name = "reg11";
  			regulator-name = "reg11";
  		};
  		scmi_reg18: voltd-reg18 {
  			voltd-name = "reg18";
  			regulator-name = "reg18";
  		};
  		...
  	};
  };
Binding Doc:{{CodeSource | Linux kernel | Documentation/devicetree/bindings/arm/arm/arm,scmi.txt | arm,scmi.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.
The regulator suspend sate is no more handled by the linux kernel in OpenSTLinux distribution.

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|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==<references/>

<noinclude>

[[Category:Power and Thermal|1]]
{{PublicationRequestId | 7961 | 2018-07-03 | AlainF}}
{{ArticleBasedOnModel|Framework overview article model}}
{{ReviewsComments|JCT 1840: alignment needed with the last version of the model<br>

[[Category:ToBeAlignedWithModel]]
}}</noinclude>
Line 179: Line 179:
 
     };
 
     };
   
Binding Doc:{{CodeSource | Linux kernel | Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.txt | st,stm32-vrefbuf.txt}}
+
Binding Doc:{{CodeSource | Linux kernel | Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml | st,stm32-vrefbuf.yaml}}
   
 
===== SCMI regulator =====
 
===== SCMI regulator =====