Registered User m (→OPP table) |
Registered User m (→OPP table) Tag: 2017 source edit |
||
(10 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{ApplicableFor | {{ApplicableFor | ||
|MPUs list=STM32MP13x, STM32MP15x | |MPUs list=STM32MP13x, STM32MP15x, STM32MP25x | ||
|MPUs checklist=STM32MP13x, STM32MP15x | |MPUs checklist=STM32MP13x, STM32MP15x, STM32MP25x | ||
}} | }} | ||
==Purpose== | ==Purpose== | ||
This article explains how to change the CPU '''operating point''' (also known as OPP). An operating point corresponds to the '''frequency''' of the processor and the '''voltage''' that needs to be supplied to sustain it. | This article explains how to change the CPU '''operating point''' (also known as OPP). An operating point corresponds to the '''frequency''' of the processor and the '''voltage''' that needs to be supplied to sustain it. | ||
It also shows how it is possible to define multiple operating points, allowing the system to jump among them at run time: this is the '''dynamic voltage and frequency scaling (DVFS)'''. Some cautions are given at the end of the article, to help the user in its DVFS deployment. | It also shows how it is possible to define multiple operating points, allowing the system to jump among them at run time: this is the '''dynamic voltage and frequency scaling (DVFS)'''. Some cautions are given at the end of the article, to help the user in its DVFS deployment. | ||
==Hardware side== | ==Hardware side== | ||
On {{MicroprocessorDevice | device= | On {{MicroprocessorDevice | device=Class}} products, the Cortex-A core: | ||
* | * is clocked by PLL1 from the [[RCC internal peripheral]] in OpenSTLinux:<br/>the PLL1 output '''frequency''' can be directly propagated to the core, or it can go through an intermediate MPUDIV divider | ||
* is supplied with | * is supplied with | ||
:* VDDCPU '''voltage''' on {{MicroprocessorDevice | device=13}} | :* VDDCPU '''voltage''' on {{MicroprocessorDevice | device=13}} and {{MicroprocessorDevice | device=25}} | ||
:* VDDCORE '''voltage''' on {{MicroprocessorDevice | device=15}} | :* VDDCORE '''voltage''' on {{MicroprocessorDevice | device=15}} | ||
The '''part number''' tells the device maximum supported frequency | |||
The '''part number''' tells the device maximum supported frequency with associated usage conditions | |||
* up to 1 GHz for the [[STM32MP13_microprocessor#Part_number_codification|STM32MP13]] | |||
* up to 800 MHz for the [[STM32MP15_microprocessor#Part_number_codification|STM32MP15]] | |||
* up to 1.5 GHz for the [[STM32MP25_microprocessor#Part_number_codification|STM32MP25]] | |||
Otherwise, the frequency must be kept below the '''nominal frequency''': | |||
* 650 MHz for {{MicroprocessorDevice | device=1}} | |||
* 1.2 GHz for {{MicroprocessorDevice | device=2}}. | |||
==Software side== | ==Software side== | ||
=== Boot time === | === Boot time === | ||
In OpenSTLinux distribution, TF-A BL2 sets the CPU frequency | In OpenSTLinux distribution, TF-A BL2 sets the CPU '''nominal frequency''', that is the maximum frequency sustainable with the nominal voltage. | ||
Notice that the processor must receive the nominal voltage during TF-A BL2 execution, whether configuring the [[PMIC_hardware_components#STPMIC1|STPMIC1]] from TF-A BL2 itself or getting it from a discrete power supply, depending on the hardware board configuration. | Notice that the processor must receive the nominal voltage during TF-A BL2 execution, whether configuring the [[PMIC_hardware_components#STPMIC1|STPMIC1]] from TF-A BL2 itself or getting it from a discrete power supply, depending on the hardware board configuration. | ||
Line 25: | Line 34: | ||
The example below sets STPMIC1 BUCK1 minimal voltage to 1.25 V, allowing to provide the expected nominal voltage on VDDCPU for the CPU: | The example below sets STPMIC1 BUCK1 minimal voltage to 1.25 V, allowing to provide the expected nominal voltage on VDDCPU for the CPU: | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
&cpu0 { | |||
cpu-supply = <&vddcpu>; | |||
}; | |||
... | |||
pmic: stpmic@33 { | |||
vddcpu: buck1 { | vddcpu: buck1 { | ||
regulator-name = "vddcpu"; | regulator-name = "vddcpu"; | ||
Line 38: | Line 52: | ||
===== VDDCORE voltage configuration ===== | ===== VDDCORE voltage configuration ===== | ||
The example below sets STPMIC1 BUCK1 minimal voltage to 1.2 V, allowing to provide the expected nominal voltage on VDDCORE for the CPU: | The example below sets STPMIC1 BUCK1 minimal voltage to 1.2 V, allowing to provide the expected nominal voltage on VDDCORE for the CPU: | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
&cpu0 { | |||
cpu-supply = <&vddcore>; | |||
}; | |||
... | |||
pmic: stpmic@33 { | |||
vddcore: buck1 { | vddcore: buck1 { | ||
regulator-name = "vddcore"; | regulator-name = "vddcore"; | ||
Line 45: | Line 65: | ||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===== CPU frequency configuration ===== | ===== CPU frequency configuration ===== | ||
TF-A is using an algorithm to calculate the PLL1 settings in {{CodeSource | TF-A | drivers/st/clk/stm32mp1_clk.c}}. | TF-A is using an algorithm to calculate the PLL1 settings in {{CodeSource | TF-A | drivers/st/clk/stm32mp1_clk.c}}. | ||
==== On {{MicroprocessorDevice | device=25}} ==== | |||
===== VDDCPU voltage configuration ===== | |||
The example below sets STPMIC25 BUCK1 minimal voltage to 0.8 V, allowing to provide the expected nominal voltage on VDDCPU for the CPU: | |||
<syntaxhighlight lang="c"> | |||
&cpu0 { | |||
cpu-supply = <&vddcpu>; | |||
}; | |||
... | |||
pmic2: stpmic2@33 { | |||
vddcpu: buck1 { | |||
regulator-name = "vddcpu"; | |||
regulator-min-microvolt = <800000>; | |||
... | |||
}; | |||
</syntaxhighlight> | |||
===== CPU frequency configuration ===== | |||
TF-A is using an algorithm to calculate the PLL1 settings in {{CodeSource | TF-A | drivers/st/clk/clk-stm32mp2.c}}. | |||
=== Runtime === | === Runtime === | ||
==== On {{MicroprocessorDevice | device=13}} ==== | ==== On {{MicroprocessorDevice | device=13}} ==== | ||
===== Overview ===== | ===== Overview ===== | ||
By default, in OpenSTLinux distribution, the OP-TEE [[STM32 MPU device tree|"soc | By default, in OpenSTLinux distribution, the OP-TEE [[STM32 MPU device tree|"soc" device tree]] file defines an '''OPP table''' that contains one or several frequency / voltage pair(s). | ||
{{Info | Whatever the implementation is, if your [[STM32MP13_microprocessor#Part_number_codification|part number]] supports up to 1 GHz, ensure that the VDDCPU minimum '''voltage''' is increased from 1.25 V to 1.35 V while running above 650 MHz}} | {{Info | Whatever the implementation is, if your [[STM32MP13_microprocessor#Part_number_codification|part number]] supports up to 1 GHz, ensure that the VDDCPU minimum '''voltage''' is increased from 1.25 V to 1.35 V while running above 650 MHz}} | ||
===== OPP table ===== | ===== OPP table ===== | ||
At runtime, Linux will automatically request to [[SCMI overview|OP-TEE SCMI]] interface to switch between the available operating points according to the CPU load and thanks to Linux cpufreq framework, configured with "ondemand" governor policy (see {{ | At runtime, Linux will automatically request to [[SCMI overview|OP-TEE SCMI]] interface to switch between the available operating points according to the CPU load and thanks to Linux cpufreq framework, configured with "ondemand" governor policy (see {{DocSource | domain=Linux kernel | path=admin-guide/pm/cpufreq.html}}). This feature is called dynamic voltage and frequency scaling (DVFS).<br> | ||
In {{CodeSource | OP-TEE_OS | core/arch/arm/dts/stm32mp131.dtsi}}, two operating points ([1 GHz ; 1.35 V]; [650 MHz ; 1.25 V]) are defined and the supported OPP are defined with the bitfield <code>opp-supported-hw</code> | |||
* bit 0: 650 MHz capable part number = STM32MP13xA / STM32MP13xC | |||
* bit 1: 1 GHz capable part number = STM32MP13xD / STM32MP13xF | |||
<syntaxhighlight lang="c"> | |||
cpu0_opp_table: cpu0-opp-table { | |||
compatible = "operating-points-v2"; | |||
opp-650000000 { | |||
opp-hz = /bits/ 64 <650000000>; | |||
opp-microvolt = <1250000>; | |||
opp-supported-hw = <0x3>; | |||
st,opp-default; | |||
}; | |||
opp-1000000000 { | |||
opp-hz = /bits/ 64 <1000000000>; | |||
opp-microvolt = <1350000>; | |||
opp-supported-hw = <0x2>; | |||
st,opp-default; | |||
}; | |||
}; | }; | ||
</ | </syntaxhighlight> | ||
The PLL1 configurations needed to reach the above frequencies must be described via the {{highlight|st,clk_opp}}, {{highlight|st,pll@0}} and {{highlight|st,pll_vco}} property in 'rcc' device tree node on OP-TEE device tree. | The PLL1 configurations needed to reach the above frequencies must be described via the {{highlight|st,clk_opp}}, {{highlight|st,pll@0}} and {{highlight|st,pll_vco}} property in 'rcc' device tree node on OP-TEE device tree. | ||
Line 144: | Line 176: | ||
Notes: | Notes: | ||
* OP-TEE selects the highest '''st,opp-default''' supported OPP during the cold boot | |||
* OP-TEE | |||
* This description is valid for cold boot, but also when coming back from [[Power overview|Standby]] low power mode. | * This description is valid for cold boot, but also when coming back from [[Power overview|Standby]] low power mode. | ||
==== On {{MicroprocessorDevice | device=15}} ==== | ==== On {{MicroprocessorDevice | device=15}} ==== | ||
===== Overview ===== | ===== Overview ===== | ||
By default, in OpenSTLinux distribution, the Linux kernel [[STM32 MPU device tree|"soc | By default, in OpenSTLinux distribution, the OP-TEE OS and Linux kernel [[STM32 MPU device tree|"soc" device tree]] file defines an '''OPP table''' that contains one or several frequency / voltage pair(s). | ||
{{Info | Whatever the implementation is, if your [[STM32MP15_microprocessor#Part_number_codification|part number]] supports up to 800 MHz, ensure that the VDDCORE minimum '''voltage''' is increased from 1.2 V to 1.35 V while running above 650 MHz}} | {{Info | Whatever the implementation is, if your [[STM32MP15_microprocessor#Part_number_codification|part number]] supports up to 800 MHz, ensure that the VDDCORE minimum '''voltage''' is increased from 1.2 V to 1.35 V while running above 650 MHz}} | ||
===== OPP table ===== | ===== OPP table ===== | ||
At runtime, the Linux kernel will automatically switch between the available operating points according to the CPU load and thanks to Linux cpufreq framework, configured with "ondemand" governor policy (see {{ | At runtime, the Linux kernel will automatically switch between the available operating points according to the CPU load and thanks to Linux cpufreq framework, configured with "ondemand" governor policy (see {{DocSource | domain=Linux kernel | path=admin-guide/pm/cpufreq.html}}). This feature is called dynamic voltage and frequency scaling (DVFS). | ||
In {Linux device tree {{CodeSource | Linux kernel | arch/arm/boot/dts/stm32mp151.dtsi}} and in OP-TEE device tree {{CodeSource | OP-TEE_OS | core/arch/arm/dts/stm32mp151.dtsi}} , two operating points ([800 MHz ; 1.35 V] and [400 MHz ; 1.2 V]) are defined for a 800 MHz capable part number (opp-supported-hw = <0x2>), one operating points ([400 MHz ; 1.2 V]) are defined for a 650 MHz capable part number (opp-supported-hw = <0x1>): | |||
<syntaxhighlight lang="c"> | |||
cpu0_opp_table: cpu0-opp-table { | |||
compatible = "operating-points-v2"; | |||
opp-shared; | |||
opp-400000000 { | opp-400000000 { | ||
opp-hz = /bits/ 64 <400000000>; | opp-hz = /bits/ 64 <400000000>; | ||
Line 171: | Line 200: | ||
opp-suspend; | opp-suspend; | ||
}; | }; | ||
opp-650000000 { | opp-650000000 { | ||
opp-hz = /bits/ 64 <650000000>; | opp-hz = /bits/ 64 <650000000>; | ||
opp-microvolt = <1200000>; | opp-microvolt = <1200000>; | ||
opp-supported-hw = <0x1>; | opp-supported-hw = <0x1>; | ||
}; | }; | ||
}; | |||
</ | opp-800000000 { | ||
opp-hz = /bits/ 64 <800000000>; | |||
opp-microvolt = <1350000>; | |||
opp-supported-hw = <0x2>; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
OP-TEE is using an algorithm to calculate the PLL1 settings in {{CodeSource | OP-TEE_OS | core/drivers/clk/clk-stm32mp15.c}}, pll1_config_from_opp_khz(). | OP-TEE is using an algorithm to calculate the PLL1 settings in {{CodeSource | OP-TEE_OS | core/drivers/clk/clk-stm32mp15.c}}, pll1_config_from_opp_khz(). | ||
Notes: | Notes: | ||
* This same OPP table must be present in both the BL32 (OP-TEE) and Linux device tree | * This same OPP table must be present in both the BL32 (OP-TEE) and Linux device tree | ||
* OP-TEE configure the OPP selected by '''st,opp-default''' during the cold boot | * OP-TEE configure the OPP selected by supported OPP with '''st,opp-default''' and with the higher frequency during the cold boot | ||
* This description is valid for cold boot, but also when coming back from [[Power overview|Standby]] low power mode. | |||
* During cold boot, BL32 (OP-TEE computes and saves the PLL1 settings for all operating points available in the device tree in compliance with the hardware capabilities. These saved parameters are used later to increase the performance of the system-state transitions. | |||
* Selecting OPP frequencies that can be reached with [[RCC internal peripheral|RCC]] MPUDIV divider and without configuring again the PLL1 is recommended in order to get the fastest switch time between the OPP. | |||
==== On {{MicroprocessorDevice | device=25}} ==== | |||
===== Overview ===== | |||
By default, in OpenSTLinux distribution, the OP-TEE [[STM32 MPU device tree|"soc" device tree]] file defines an '''OPP table''' that contains one or several frequency / voltage pair(s). | |||
{{Info | Whatever the implementation is, if your [[STM32MP25_microprocessor#Part_number_codification|part number]] supports up to 1.5 GHz, ensure that the VDDCPU minimum '''voltage''' is increased from 0.8V to 0.91V while running above 1.2 GHz}} | |||
===== OPP table ===== | |||
At runtime, Linux will automatically request to [[SCMI overview|OP-TEE SCMI]] interface to switch between the available operating points according to the CPU load and thanks to Linux cpufreq framework, configured with "schedutil" governor policy (default in {{CodeSource | Linux kernel | drivers/cpufreq/Kconfig}} for ARM64 see {{DocSource | domain=Linux kernel | path=admin-guide/pm/cpufreq.html}}). This feature is called dynamic voltage and frequency scaling (DVFS).<br> | |||
In {{CodeSource | OP-TEE_OS | core/arch/arm/dts/stm32mp251.dtsi}}, the two operating points [1.5GHz ; 0.9.1V] and [1.2GHz ; 0.8V] are defined with the associated bit-field <code>opp-supported-hw</code> | |||
* bit 0: supported by 1.2 GHz part number = STM32MP25xA / STM32MP25xC | |||
* bit 1: supported by 1.5 GHz part number = STM32MP25xD / STM32MP25xF | |||
<syntaxhighlight lang="c"> | |||
cpu0_opp_table: cpu0-opp-table { | |||
compatible = "operating-points-v2"; | |||
opp-1200000000 { | |||
opp-hz = /bits/ 64 <1200000000>; | |||
opp-microvolt = <800000>; | |||
opp-supported-hw = <0x3>; | |||
st,opp-default; | |||
}; | |||
opp-1500000000 { | |||
opp-hz = /bits/ 64 <1500000000>; | |||
opp-microvolt = <910000>; | |||
opp-supported-hw = <0x2>; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
The PLL1 configurations needed to reach the above frequencies must be described via the {{highlight|st,clk_opp}}, {{highlight|st,pll-1}} and {{highlight|st,pll_vco}} property in 'rcc' device tree node on OP-TEE device tree. | |||
For example in {{CodeSource | OP-TEE_OS | core/arch/arm/dts/stm32mp257f-dk-ca35tdcid-rcc.dtsi}}, generated by [[STM32MP25 clock tree]]: | |||
&rcc { | |||
{{highlight|pll1: st,pll-1}} { | |||
st,pll = <&pll1_cfg_1200Mhz>; | |||
{{HighlightParam|pll1_cfg_1200Mhz}}: pll1-cfg-1200Mhz { | |||
cfg = <30 1 1 1>; | |||
src = <MUX_CFG(MUX_MUXSEL5, MUXSEL_HSE)>; | |||
}; | |||
{{HighlightParam|pll1_cfg_1500Mhz}}: pll1-cfg-1500Mhz { | |||
cfg = <75 2 1 1>; | |||
src = <MUX_CFG(MUX_MUXSEL5, MUXSEL_HSE)>; | |||
}; | |||
}; | |||
And in {{CodeSource | OP-TEE_OS | core/arch/arm/dts/stm32mp257f-dk.dts}}: | |||
&rcc { | |||
st,c1msrd = <2>; | |||
{{highlight|st,clk_opp}} { | |||
st,ck_cpu1 { | |||
cfg_1 { | |||
hz = <1500000000>; | |||
st,clksrc = <0>; | |||
st,pll = <{{HighlightParam|&pll1_cfg_1500Mhz}}>; | |||
}; | |||
cfg_2 { | |||
hz = <1200000000>; | |||
st,clksrc = <0>; | |||
st,pll = <{{HighlightParam|&pll1_cfg_1200Mhz}}>; | |||
}; | |||
}; | |||
}; | |||
}; | |||
Notes: | |||
* OP-TEE selects the highest '''st,opp-default''' supported OPP during the cold boot | |||
* This description is valid for cold boot, but also when coming back from [[Power overview|Standby]] low power mode. | * This description is valid for cold boot, but also when coming back from [[Power overview|Standby]] low power mode. | ||
==Dynamic voltage and frequency scaling (DVFS) caution== | ==Dynamic voltage and frequency scaling (DVFS) caution== | ||
As stated above, as soon as at least two operating points are defined in the OPP table, Linux kernel will automatically switch between them at runtime thanks to Linux cpufreq framework, configured with "ondemand" governor policy (see {{ | As stated above, as soon as at least two operating points are defined in the OPP table, Linux kernel will automatically switch between them at runtime thanks to Linux cpufreq framework, configured with "ondemand" (for ARM, {{MicroprocessorDevice | device=1}}) or "schedutil" (for ARM64, {{MicroprocessorDevice | device=2}}) governor policy (see {{DocSource | domain=Linux kernel | path=admin-guide/pm/cpufreq.html}}). It is important to notice that cpufreq framework is only monitoring the CPU load to select the OPP because this can lead to some limitation during use cases where the CPU is not loaded a lot but high reactivity is needed to respect some real time constraints, like interrupt management. If you face some system issue where the CPU reactivity may be the root cause whereas DVFS is enabled, consider doing a trial with "performance" governor (see {{DocSource | domain=Linux kernel | path=admin-guide/pm/cpufreq.html}}). | ||
{{Board$}} echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor | |||
{{Board$}} cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq | |||
==How to go further== | |||
* {{DocSource | domain=Linux kernel | path=admin-guide/pm/cpufreq.html}} | |||
* {{DocSource | domain=Linux kernel | path=cpu-freq/cpufreq-stats.html}} | |||
* Guidelines for Lifetime Usage Estimates: [[STM32_MPU_resources#AN5438|AN5438]] and [[STM32_MPU_resources#AN5729|AN5729]] | |||
* [[Clock device tree configuration]] and "how to build a clock tree". | |||
<noinclude> | <noinclude> | ||
[[Category:How to customize software]] | [[Category:How to customize software]] | ||
{{PublicationRequestId | 14900 | 2020-02-11 | AnneJ}} | {{PublicationRequestId | 14900 | 2020-02-11 | AnneJ}} | ||
</noinclude> | </noinclude> |
Latest revision as of 12:19, 4 June 2024
1. Purpose
This article explains how to change the CPU operating point (also known as OPP). An operating point corresponds to the frequency of the processor and the voltage that needs to be supplied to sustain it.
It also shows how it is possible to define multiple operating points, allowing the system to jump among them at run time: this is the dynamic voltage and frequency scaling (DVFS). Some cautions are given at the end of the article, to help the user in its DVFS deployment.
2. Hardware side
On STM32 Arm® Cortex® MPUs products, the Cortex-A core:
- is clocked by PLL1 from the RCC internal peripheral in OpenSTLinux:
the PLL1 output frequency can be directly propagated to the core, or it can go through an intermediate MPUDIV divider - is supplied with
The part number tells the device maximum supported frequency with associated usage conditions
Otherwise, the frequency must be kept below the nominal frequency:
- 650 MHz for STM32MP1 Series
- 1.2 GHz for STM32MP2 unknown microprocessor device.
3. Software side
3.1. Boot time
In OpenSTLinux distribution, TF-A BL2 sets the CPU nominal frequency, that is the maximum frequency sustainable with the nominal voltage.
Notice that the processor must receive the nominal voltage during TF-A BL2 execution, whether configuring the STPMIC1 from TF-A BL2 itself or getting it from a discrete power supply, depending on the hardware board configuration.
3.1.1. On STM32MP13x lines 
3.1.1.1. VDDCPU voltage configuration
The example below sets STPMIC1 BUCK1 minimal voltage to 1.25 V, allowing to provide the expected nominal voltage on VDDCPU for the CPU:
&cpu0 {
cpu-supply = <&vddcpu>;
};
...
pmic: stpmic@33 {
vddcpu: buck1 {
regulator-name = "vddcpu";
regulator-min-microvolt = <1250000>;
...
};
3.1.1.2. CPU frequency configuration
TF-A is using an algorithm to calculate the PLL1 settings in drivers/st/clk/clk-stm32mp13.c .
3.1.2. On STM32MP15x lines 
3.1.2.1. VDDCORE voltage configuration
The example below sets STPMIC1 BUCK1 minimal voltage to 1.2 V, allowing to provide the expected nominal voltage on VDDCORE for the CPU:
&cpu0 {
cpu-supply = <&vddcore>;
};
...
pmic: stpmic@33 {
vddcore: buck1 {
regulator-name = "vddcore";
regulator-min-microvolt = <1200000>;
...
};
3.1.2.2. CPU frequency configuration
TF-A is using an algorithm to calculate the PLL1 settings in drivers/st/clk/stm32mp1_clk.c .
3.1.3. On STM32MP25 unknown microprocessor device
3.1.3.1. VDDCPU voltage configuration
The example below sets STPMIC25 BUCK1 minimal voltage to 0.8 V, allowing to provide the expected nominal voltage on VDDCPU for the CPU:
&cpu0 {
cpu-supply = <&vddcpu>;
};
...
pmic2: stpmic2@33 {
vddcpu: buck1 {
regulator-name = "vddcpu";
regulator-min-microvolt = <800000>;
...
};
3.1.3.2. CPU frequency configuration
TF-A is using an algorithm to calculate the PLL1 settings in drivers/st/clk/clk-stm32mp2.c .
3.2. Runtime
3.2.1. On STM32MP13x lines 
3.2.1.1. Overview
By default, in OpenSTLinux distribution, the OP-TEE "soc" device tree file defines an OPP table that contains one or several frequency / voltage pair(s).
3.2.1.2. OPP table
At runtime, Linux will automatically request to OP-TEE SCMI interface to switch between the available operating points according to the CPU load and thanks to Linux cpufreq framework, configured with "ondemand" governor policy (see admin-guide/pm/cpufreq.html). This feature is called dynamic voltage and frequency scaling (DVFS).
In core/arch/arm/dts/stm32mp131.dtsi , two operating points ([1 GHz ; 1.35 V]; [650 MHz ; 1.25 V]) are defined and the supported OPP are defined with the bitfield opp-supported-hw
- bit 0: 650 MHz capable part number = STM32MP13xA / STM32MP13xC
- bit 1: 1 GHz capable part number = STM32MP13xD / STM32MP13xF
cpu0_opp_table: cpu0-opp-table {
compatible = "operating-points-v2";
opp-650000000 {
opp-hz = /bits/ 64 <650000000>;
opp-microvolt = <1250000>;
opp-supported-hw = <0x3>;
st,opp-default;
};
opp-1000000000 {
opp-hz = /bits/ 64 <1000000000>;
opp-microvolt = <1350000>;
opp-supported-hw = <0x2>;
st,opp-default;
};
};
The PLL1 configurations needed to reach the above frequencies must be described via the st,clk_opp, st,pll@0 and st,pll_vco property in 'rcc' device tree node on OP-TEE device tree.
For example in core/arch/arm/dts/stm32mp135f-dk.dts :
st,pll_vco { pll1_vco_2000Mhz: pll1-vco-2000Mhz { src = <CLK_PLL12_HSE>; divmn = <1 82>; frac = <0xAAA>; }; pll1_vco_1300Mhz: pll1-vco-1300Mhz { src = <CLK_PLL12_HSE>; divmn = <2 80>; frac = <0x800>; }; ... }; /* VCO = 1300.0 MHz => P = 650 (CPU) */ pll1: st,pll@0 { compatible = "st,stm32mp1-pll"; reg = <0>; st,pll = <&pll1_cfg1>; pll1_cfg1: pll1_cfg1 { st,pll_vco = <&pll1_vco_1300Mhz>; st,pll_div_pqr = <0 1 1>; }; pll1_cfg2: pll1_cfg2 { st,pll_vco = <&pll1_vco_2000Mhz>; st,pll_div_pqr = <0 1 1>; }; }; .... st,clk_opp { st,ck_mpu { cfg_1 { hz = < 1000000000 >; st,clksrc = < CLK_MPU_PLL1P >; st,pll = < &pll1_cfg2 >; }; cfg_2 { hz = < 650000000 >; st,clksrc = < CLK_MPU_PLL1P >; st,pll = < &pll1_cfg1 >; }; }; }; };&rcc {
Notes:
- OP-TEE selects the highest st,opp-default supported OPP during the cold boot
- This description is valid for cold boot, but also when coming back from Standby low power mode.
3.2.2. On STM32MP15x lines 
3.2.2.1. Overview
By default, in OpenSTLinux distribution, the OP-TEE OS and Linux kernel "soc" device tree file defines an OPP table that contains one or several frequency / voltage pair(s).
3.2.2.2. OPP table
At runtime, the Linux kernel will automatically switch between the available operating points according to the CPU load and thanks to Linux cpufreq framework, configured with "ondemand" governor policy (see admin-guide/pm/cpufreq.html). This feature is called dynamic voltage and frequency scaling (DVFS).
In {Linux device tree arch/arm/boot/dts/stm32mp151.dtsi and in OP-TEE device tree core/arch/arm/dts/stm32mp151.dtsi , two operating points ([800 MHz ; 1.35 V] and [400 MHz ; 1.2 V]) are defined for a 800 MHz capable part number (opp-supported-hw = <0x2>), one operating points ([400 MHz ; 1.2 V]) are defined for a 650 MHz capable part number (opp-supported-hw = <0x1>):
cpu0_opp_table: cpu0-opp-table {
compatible = "operating-points-v2";
opp-shared;
opp-400000000 {
opp-hz = /bits/ 64 <400000000>;
opp-microvolt = <1200000>;
opp-supported-hw = <0x2>;
opp-suspend;
};
opp-650000000 {
opp-hz = /bits/ 64 <650000000>;
opp-microvolt = <1200000>;
opp-supported-hw = <0x1>;
};
opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
opp-microvolt = <1350000>;
opp-supported-hw = <0x2>;
};
};
OP-TEE is using an algorithm to calculate the PLL1 settings in core/drivers/clk/clk-stm32mp15.c , pll1_config_from_opp_khz().
Notes:
- This same OPP table must be present in both the BL32 (OP-TEE) and Linux device tree
- OP-TEE configure the OPP selected by supported OPP with st,opp-default and with the higher frequency during the cold boot
- This description is valid for cold boot, but also when coming back from Standby low power mode.
- During cold boot, BL32 (OP-TEE computes and saves the PLL1 settings for all operating points available in the device tree in compliance with the hardware capabilities. These saved parameters are used later to increase the performance of the system-state transitions.
- Selecting OPP frequencies that can be reached with RCC MPUDIV divider and without configuring again the PLL1 is recommended in order to get the fastest switch time between the OPP.
3.2.3. On STM32MP25 unknown microprocessor device
3.2.3.1. Overview
By default, in OpenSTLinux distribution, the OP-TEE "soc" device tree file defines an OPP table that contains one or several frequency / voltage pair(s).
3.2.3.2. OPP table
At runtime, Linux will automatically request to OP-TEE SCMI interface to switch between the available operating points according to the CPU load and thanks to Linux cpufreq framework, configured with "schedutil" governor policy (default in drivers/cpufreq/Kconfig for ARM64 see admin-guide/pm/cpufreq.html). This feature is called dynamic voltage and frequency scaling (DVFS).
In core/arch/arm/dts/stm32mp251.dtsi , the two operating points [1.5GHz ; 0.9.1V] and [1.2GHz ; 0.8V] are defined with the associated bit-field opp-supported-hw
- bit 0: supported by 1.2 GHz part number = STM32MP25xA / STM32MP25xC
- bit 1: supported by 1.5 GHz part number = STM32MP25xD / STM32MP25xF
cpu0_opp_table: cpu0-opp-table {
compatible = "operating-points-v2";
opp-1200000000 {
opp-hz = /bits/ 64 <1200000000>;
opp-microvolt = <800000>;
opp-supported-hw = <0x3>;
st,opp-default;
};
opp-1500000000 {
opp-hz = /bits/ 64 <1500000000>;
opp-microvolt = <910000>;
opp-supported-hw = <0x2>;
};
};
The PLL1 configurations needed to reach the above frequencies must be described via the st,clk_opp, st,pll-1 and st,pll_vco property in 'rcc' device tree node on OP-TEE device tree.
For example in core/arch/arm/dts/stm32mp257f-dk-ca35tdcid-rcc.dtsi , generated by STM32MP25 clock tree:
pll1: st,pll-1 { st,pll = <&pll1_cfg_1200Mhz>; pll1_cfg_1200Mhz: pll1-cfg-1200Mhz { cfg = <30 1 1 1>; src = <MUX_CFG(MUX_MUXSEL5, MUXSEL_HSE)>; }; pll1_cfg_1500Mhz: pll1-cfg-1500Mhz { cfg = <75 2 1 1>; src = <MUX_CFG(MUX_MUXSEL5, MUXSEL_HSE)>; }; };&rcc {
And in core/arch/arm/dts/stm32mp257f-dk.dts :
st,clk_opp { st,ck_cpu1 { cfg_1 { hz = <1500000000>; st,clksrc = <0>; st,pll = <&pll1_cfg_1500Mhz>; }; cfg_2 { hz = <1200000000>; st,clksrc = <0>; st,pll = <&pll1_cfg_1200Mhz>; }; }; }; };&rcc { st,c1msrd = <2>;
Notes:
- OP-TEE selects the highest st,opp-default supported OPP during the cold boot
- This description is valid for cold boot, but also when coming back from Standby low power mode.
4. Dynamic voltage and frequency scaling (DVFS) caution
As stated above, as soon as at least two operating points are defined in the OPP table, Linux kernel will automatically switch between them at runtime thanks to Linux cpufreq framework, configured with "ondemand" (for ARM, STM32MP1 Series) or "schedutil" (for ARM64, STM32MP2 unknown microprocessor device) governor policy (see admin-guide/pm/cpufreq.html). It is important to notice that cpufreq framework is only monitoring the CPU load to select the OPP because this can lead to some limitation during use cases where the CPU is not loaded a lot but high reactivity is needed to respect some real time constraints, like interrupt management. If you face some system issue where the CPU reactivity may be the root cause whereas DVFS is enabled, consider doing a trial with "performance" governor (see admin-guide/pm/cpufreq.html).
echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq
5. How to go further
- admin-guide/pm/cpufreq.html
- cpu-freq/cpufreq-stats.html
- Guidelines for Lifetime Usage Estimates: AN5438 and AN5729
- Clock device tree configuration and "how to build a clock tree".