Reducing CPU frequency in iMX8M processors
From SomLabs Wiki
Reducing CPU frequency in iMX8M processors
In iMX8M processors a number of core operating frequencies can be defined in order to minimize the power consumption. This tutorial presents how to add additional frequencies to the default list and force the kernel driver to use the required one. It was prepared for the Yocto Scarthgap version with meta-somlabs layer.
The default available frequencies defined in dts files are:
- 1200000000
- 1600000000
- 1800000000
Linux uses those values according to the computing power requirements and the currently used governor. The CPU frequency governors policies are described in the kernel docummentation:
https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt
By default the ondemand governor is used, which automatically chooses the required CPU frequency. It may be verified by reading the sysfs driver file.
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
Adding supported frequencies
In order to add more supported core frequencies the PLL driver needs to be modified, as well as the dts entries for the device. The following patch adds more available frequencies to the system configuration for iMX8Mmini and iMX8MPlus processors:
diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index abd144c2ea7d..b1a285c41afe 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -156,6 +156,38 @@ a53_opp_table: opp-table { compatible = "operating-points-v2"; opp-shared; + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0xe>, <0x7>; + clock-latency-ns = <150000>; + opp-suspend; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0xe>, <0x7>; + clock-latency-ns = <150000>; + opp-suspend; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0xe>, <0x7>; + clock-latency-ns = <150000>; + opp-suspend; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0xe>, <0x7>; + clock-latency-ns = <150000>; + opp-suspend; + }; + opp-1200000000 { opp-hz = /bits/ 64 <1200000000>; opp-microvolt = <850000>; diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index 9335f1713ce6..2b0f57418e66 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -166,6 +166,38 @@ a53_opp_table: opp-table { compatible = "operating-points-v2"; opp-shared; + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0x8a0>, <0x7>; + clock-latency-ns = <150000>; + opp-suspend; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0x8a0>, <0x7>; + clock-latency-ns = <150000>; + opp-suspend; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0x8a0>, <0x7>; + clock-latency-ns = <150000>; + opp-suspend; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0x8a0>, <0x7>; + clock-latency-ns = <150000>; + opp-suspend; + }; + opp-1200000000 { opp-hz = /bits/ 64 <1200000000>; opp-microvolt = <850000>; diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index 6c17786ecb9f..7701e6e2f4cc 100644 --- a/drivers/clk/imx/clk-pll14xx.c +++ b/drivers/clk/imx/clk-pll14xx.c @@ -56,7 +56,10 @@ static const struct imx_pll14xx_rate_table imx_pll1416x_tbl[] = { PLL_1416X_RATE(700000000U, 350, 3, 2), PLL_1416X_RATE(640000000U, 320, 3, 2), PLL_1416X_RATE(600000000U, 300, 3, 2), + PLL_1416X_RATE(400000000U, 200, 3, 2), PLL_1416X_RATE(320000000U, 160, 3, 2), + PLL_1416X_RATE(200000000U, 200, 3, 3), + PLL_1416X_RATE(100000000U, 200, 3, 4), }; static const struct imx_pll14xx_rate_table imx_pll1443x_tbl[] = {
Note that 800MHz frequency is already defined in the PLL driver. This driver sets the PLL parameters according to the defined macro:
PLL_1416X_RATE(Fout, M, P, S)
The Fout is calculated as follows:
Fout = 32MHz * M / (P * 2^S)
This patch can be added to meta-somlabs layer in order to build it together with the default system image. The created patch file should be placed in meta-somlabs/recipes-kernel/linux/linux-imx directory and the following line should be added to the the kernel recipe meta-somlabs/recipes-kernel/linux//linux-imx_6.6.bbappend:
SRC_URI += "file://frequency.patch"
The frequency.patch file should be changed according to the added patch file in linux-imx directory.
Verifying core frequency
Setting the core frequency can be easily tested using userspace governor which allows for manual configuration. The frequency is set in kHz. For example the following lines set the CPU frequency to 100MHz:
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor echo 100000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
The execution time can be then measured using simple script:
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor echo 100000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed time bash -c "for i in {1..1000000}; do :; done" real 2m39.501s user 2m32.015s sys 0m3.861s
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor echo 1600000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed time bash -c "for i in {1..1000000}; do :; done" real 0m11.525s user 0m11.154s sys 0m0.330s