Table of Contents |
---|
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/.
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
None
zynq:
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
Devicetree
/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#
Summary:
ca1cf28 cpufreq: dt: Add zynqmp to the cpufreq dt platdev
c0b91f5 dts: zynqmp: Update the OPPs for cpu freq
2017.2
None
2017.3
None
2017.4
None
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 driverCONFIG_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
Code Block | ||
---|---|---|
| ||
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] |
Code Block | ||
---|---|---|
| ||
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
2017.1Summary:
- Added device tree node
- Added cpufreq driver support
ca1cf28 cpufreq: dt: Add zynqmp to the cpufreq dt platdev
c0b91f5 dts: zynqmp: Update the OPPs for cpu freq
2017.2
None
2017.3
None
2017.4
None
...
2019.2
None
None
2020.1
None
None
2020.2
None
None
2021.1
None
None
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>; | |
}; | |
}; | |