CPU frequency scaling

CPU frequency scaling

Introduction

This page gives an overview of the CPU freq driver which is available as part of the ZynqMP Linux distribution.
Paths, files, links and documentation on this page are given relative to the Linux kernel source tree.

It is documented in Documentation/cpu-freq/.

Cpufreq often uses the Operating Performance Point library, which is explained in Documentation/power/opp.txt. The cpufreq framework comes with different frequency scaling governors, which scale the CPU frequency according to system load (for details please refer to the documentation).
The driver exposes a control interface through sysFS in /sys/devices/system/cpu/cpu0/cpufreq/.


HW IP features

Dynamic frequency scaling for Zynqmp Ultrascale+ MPSoc APU.


Features supported in driver

Dynamic frequency scaling for Zynqmp Ultrascale+ MPSoc APU.


Frequencies supported in Zynq Ultrascale+ MPSoC

We do not support changing the parent pll rates (pllfreq). We support only integral divisors of pllfreq.


In the above example the acpu frequencies are limited to pllfreq/x where x is integral numbers 1, 2 , 3 .. etc
pllfreq = osc_frequency * PLL_multiplier

Lets take the example of zcu102
In zcu102 the osc frequency is 33.33
The default hdf has PLL multiplier of 72.
pllfreq = 33.33*72 = 2399.76

the possible frequencies are integral divisors of 2399.76M
1199.88 M
799.92 M
599.94 M
479.95M
399.96M
342.82M
etc


Missing Features, Known Issues and Limitations

zynqmp Ultrascale+:
None

zynq:

  • When running at a too low frequency, USB breaks. The lowest tested and working frequency is 222.222 MHz. Highest frequency where it is known broken is 111.111 MHz

  • Suspend breaks on reduced frequencies

  • Due to dependencies between the CPU frequency and timers, the range of valid frequencies is limited/frequency changes may fail (see: https://github.com/Xilinx/linux-xlnx/commit/356cbded4131b067ec5fa4430c15c2fac867fa2b)

  • cpufreq statistics don't work

  • System clock runs slower proportionately to the difference between the default clock rate and that set by cpufreq if a timer other than the TTC (e.g. arm_global_timer) is used as clocksource




Kernel Configuration

The following config options should be enabled in order to build the cpufreq driver

CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPUFREQ_DT=y
CONFIG_CPUFREQ_DT_PLATDEV=y

Symbol: CPU_FREQ [=y] Type : boolean Prompt: CPU Frequency scaling Location: -> CPU Power Management -> CPU Frequency scaling Defined at drivers/cpufreq/Kconfig:3 Selects: SRCU [=y]

Devicetree

cpus { #address-cells = <1>; #size-cells = <0>; cpu0: cpu@0 { compatible = "arm,cortex-a53", "arm,armv8"; device_type = "cpu"; enable-method = "psci"; operating-points-v2 = <&cpu_opp_table>; reg = <0x0>; cpu-idle-states = <&CPU_SLEEP_0>; }; cpu1: cpu@1 { compatible = "arm,cortex-a53", "arm,armv8"; device_type = "cpu"; enable-method = "psci"; reg = <0x1>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP_0>; }; cpu2: cpu@2 { compatible = "arm,cortex-a53", "arm,armv8"; device_type = "cpu"; enable-method = "psci"; reg = <0x2>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP_0>; }; cpu3: cpu@3 { compatible = "arm,cortex-a53", "arm,armv8"; device_type = "cpu"; enable-method = "psci"; reg = <0x3>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP_0>; }; cpu_opp_table: cpu_opp_table { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <1199999988>; opp-microvolt = <1000000>; clock-latency-ns = <500000>; }; opp01 { opp-hz = /bits/ 64 <599999994>; opp-microvolt = <1000000>; clock-latency-ns = <500000>; }; opp02 { opp-hz = /bits/ 64 <399999996>; opp-microvolt = <1000000>; clock-latency-ns = <500000>; }; opp03 { opp-hz = /bits/ 64 <299999997>; opp-microvolt = <1000000>; clock-latency-ns = <500000>; }; };

Test Procedure

/sys/devices/system/cpu/cpufreq/policy0/stats/ti 275000 0 366666 0 550000 0 1100000 18170 roott@Xilinx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0# cat affected_cpu 0 1 2 3 root@Xilinx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0# ilable_frequenciesREMUS:/sys/devices/system/cpu/cpufreq/policy0# cat scaling_ava 275000 366666 550000 1100000 root@Xilinx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0# root@Xilinx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0# ilable_governors REMUS:/sys/devices/system/cpu/cpufreq/policy0# cat scaling_avai conservative ondemand userspace powersave performance root@Xilinx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0# root@Xilinx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0# scaling_setspeed -REMUS:/sys/devices/system/cpu/cpufreq/policy0# echo 275000 > PMUFW: PmMmioRead: (NODE_APU) addr=0xFD1A0060, value=0x3000200 PMUFW: PmMmioWrite: (NODE_APU) addr=0xFD1A0060, mask=0xFFFFFFFF, value=0x3000500 PMUFW: PmMmioRead: (NODE_APU) addr=0xFD1A0060, value=0x3000500 root@Xilinx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0# _freq ilinx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0# cat scaling_cur 275000 in_state nx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0# cat stats/time_i 275000 3275 366666 0 550000 0 1100000 32448 root@Xilinx-EP108-REMUS:/sys/devices/system/cpu/cpufreq/policy0#







Mainline status

The driver is currently in sync with the mainline.


Change Log

2024.2
None

2024.1
None

2023.2
None

2023.1
None

2022.2
None

2022.1
None

2021.2
None

2021.1
None

2021.1
None

2020.2
None

2019.1
None

2019.2
None

2018.3
None

2018.2
None

2018.1
None

2017.4
None

2017.3
None

2017.2
None



2017.1
Summary:

  • Added device tree node

  • Added cpufreq driver support

Commits:
ca1cf28 cpufreq: dt: Add zynqmp to the cpufreq dt platdev
c0b91f5 dts: zynqmp: Update the OPPs for cpu freq

Related Links


||

cpus {



#address-cells = <1>;



#size-cells = <0>;







cpu0: cpu@0 {



compatible = "arm,cortex-a53", "arm,armv8";



device_type = "cpu";



enable-method = "psci";



operating-points-v2 = <&cpu_opp_table>;



reg = <0x0>;



cpu-idle-states = <&CPU_SLEEP_0>;



};







cpu1: cpu@1 {



compatible = "arm,cortex-a53", "arm,armv8";



device_type = "cpu";



enable-method = "psci";



reg = <0x1>;



operating-points-v2 = <&cpu_opp_table>;



cpu-idle-states = <&CPU_SLEEP_0>;



};







cpu2: cpu@2 {



compatible = "arm,cortex-a53", "arm,armv8";



device_type = "cpu";



enable-method = "psci";



reg = <0x2>;



operating-points-v2 = <&cpu_opp_table>;



cpu-idle-states = <&CPU_SLEEP_0>;



};







cpu3: cpu@3 {



compatible = "arm,cortex-a53", "arm,armv8";



device_type = "cpu";



enable-method = "psci";



reg = <0x3>;



operating-points-v2 = <&cpu_opp_table>;



cpu-idle-states = <&CPU_SLEEP_0>;



};







idle-states {



entry-method = "arm,psci";







CPU_SLEEP_0: cpu-sleep-0 {



compatible = "arm,idle-state";



arm,psci-suspend-param = <0x40000000>;



local-timer-stop;



entry-latency-us = <300>;



exit-latency-us = <600>;



min-residency-us = <100000>;



};



};



};







cpu_opp_table: cpu_opp_table {



compatible = "operating-points-v2";



opp-shared;



opp00 {



opp-hz = /bits/ 64 <1199999988>;



opp-microvolt = <1000000>;



clock-latency-ns = <500000>;



};



opp01 {



opp-hz = /bits/ 64 <599999994>;



opp-microvolt = <1000000>;



clock-latency-ns = <500000>;



};



opp02 {



opp-hz = /bits/ 64 <399999996>;



opp-microvolt = <1000000>;



clock-latency-ns = <500000>;



};



opp03 {



opp-hz = /bits/ 64 <299999997>;



opp-microvolt = <1000000>;



clock-latency-ns = <500000>;



};



};



© 2025 Advanced Micro Devices, Inc. Privacy Policy