I have been wondering why no proper CPU frequency scaling driver has been implemented for WRT3200ACM (and WRT1900ACS etc.) and the other mvebu devices.
Apparently no such driver has been accepted upstream in Linux, but luckily there is one RFC version of a driver, which has been published in 2015. I noticed that the driver has recently been implemented for Turris Omnia (running an Openwrt derivative with kernel 4.4 for mvebu), so I decided to test if the driver could be modified to work with kernel 4.9.
I succeeded in modifying the driver. So far it has worked ok in my WRT3200ACM with kernel 4.9, 4.14, 4.19 and currently with 5.4.
Based on my experience, it scales ok, and running the CPU at half of the max frequency when idle (most of the time) lowers CPU temperature by some 2 degrees.
Ps. does anybody know it the processor can be run with other clock speeds? The upstream authors have implemented only 100% and 50% operating points, but other devices scale with more granular steps (like R7800 IPQ8065 with 6 steps from 384 to 1700). So I wonder if the Marvell mvebu has stricter limitations in clock speeds, or if there could be found other operating points (like 1/4 etc.)...
commit for kernel 5.4
https://github.com/hnyman/openwrt/commit/90113cd70f33449a68827e63501dcc688c14d007
as a patch:
https://github.com/hnyman/openwrt/commit/90113cd70f33449a68827e63501dcc688c14d007.patch
Add CPU frequency scaling driver for mvebu Armada XP/380/385.
The driver supports only the 100% and 50% operating points for the CPU. Linux scales the CPU frequency automatically according to the CPU load.
Both CPU cores are scaled simultaneously in 380/385.
Armada XP may have independent clocks, but I can't verify that.
The driver has been originally published by Gregory Clement in Linux kernel mailing list in July 2015 as RFC, but no final version of the driver has been published.
Reference to messages starting at:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/353871.html
Note: upstream messages mention possible instability under heavy I/O.
The driver has been adapted for Turris Omnia running kernel 4.4, as shown in commit:
https://gitlab.labs.nic.cz/turris/openwrt/commit/a249596367dde0f02fca750d19d13a14695e3fa3
I have adapted the driver first for kernel 4.9, then for 4.14, 4.19 and 5.4. The necessary changes were mainly minor context changes, with the exception of:
- the driver initialiation routine has been moved from pmsu.c to cpufreq.c so use include/linux/mvebu-pmsu.h to pass variables and functions between pmsu.c and cpufreq.c
- data structure for cpufreq-dt has been simplified upstream, so drop the unused independent clocks argument and simplify driver registration according to upstream changes.
I haven't really compared this to the upstream changes in between, but the code runs ok with kernel 5.4.
Run-tested with WRT3200ACM (Armada 385) at master r14966-7330348f2d
Note:
Upstream WIP code can be found at
https://github.com/MISL-EBU-System-SW/mainline-public/commits/cpufreq-Armada38x-4.4-WIP
Based on that it is possible that Armada XP (original WRT1900AC, mamba) requires two additional commits to be stable.
root@LEDE:~# cat /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq
1866000
1866000
root@LEDE:~# kill 6166
root@LEDE:~# cat /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq
933000
933000
root@LEDE:~# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
ondemand performance
root@LEDE:~# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
ondemand