Re: [PATCH 3/3] ARM: dts: qcom: msm8960: Add CPU frequency scaling support
From: Antony Kurniawan Soemardi
Date: Fri May 15 2026 - 04:18:29 EST
On 5/14/2026 2:04 PM, Rudraksha Gupta wrote:
Enable Krait DVFS on MSM8960 by adding the required device tree nodes:
- OPP table with 12 operating points from 384 MHz to 1.512 GHz, with
per-PVS voltages for slow, nominal, and fast silicon bins.
- Krait clock controller (krait-cc-v1) driving the CPU muxes from
PLL9/PLL10, ACC aux outputs, and PXO.
- PVS efuse nvmem cell in qfprom for the cpufreq-nvmem driver to
read the speed-bin and process voltage class.
- CPU idle state for Standalone Power Collapse (SPC).
- operating-points-v2, clocks, cpu-supply, and cpu-idle-states wired
into both CPU nodes.
Link: https://github.com/CyanogenMod/android_kernel_samsung_d2/blob/0dbe2b56847b304d30b809dfd08ba3b4a61d9af8/arch/arm/mach-msm/acpuclock-8960.c#L120-L235
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Rudraksha Gupta <guptarud@xxxxxxxxx>
---
arch/arm/boot/dts/qcom/qcom-msm8960.dtsi | 133 ++++++++++++++++++++++++++++++-
1 file changed, 131 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi
index a427f0f41cd1..b5b9239c7aa0 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi
@@ -54,6 +54,10 @@ cpu@0 {
reg = <0>;
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&kraitcc 0>;
+ cpu-supply = <&saw0_vreg>;
+ cpu-idle-states = <&cpu_spc>;
next-level-cache = <&l2>;
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
@@ -64,6 +68,10 @@ cpu@1 {
reg = <1>;
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&kraitcc 1>;
+ cpu-supply = <&saw1_vreg>;
+ cpu-idle-states = <&cpu_spc>;
next-level-cache = <&l2>;
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
@@ -74,6 +82,116 @@ l2: l2-cache {
cache-level = <2>;
cache-unified;
};
+
+ idle-states {
+ cpu_spc: cpu-spc {
+ compatible = "qcom,idle-state-spc", "arm,idle-state";
+ entry-latency-us = <400>;
+ exit-latency-us = <900>;
+ min-residency-us = <3000>;
+ };
+ };
+ };
+
+ cpu_opp_table: opp-table-cpu {
+ compatible = "operating-points-v2-krait-cpu";
+ nvmem-cells = <&pvs_efuse>;
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ opp-microvolt-speed0-pvs0-v0 = <950000>;
+ opp-microvolt-speed0-pvs1-v0 = <900000>;
+ opp-microvolt-speed0-pvs3-v0 = <850000>;
The Sashiko bot comment about the binding schema is valid, I encountered the following warnings:
/mnt/linux/.output/arch/arm/boot/dts/qcom/qcom-msm8960-sony-huashan.dtb: / (sony,huashan): opp-table-cpu:opp-384000000: 'opp-microvolt-speed0-pvs0-v0', 'opp-microvolt-speed0-pvs1-v0', 'opp-microvolt-speed0-pvs3-v0' do not match any of the regexes: '^opp-microvolt-speed[0-9]+-pvs[0-9]+$', '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/cpufreq/qcom-cpufreq-nvmem.yaml
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-486000000 {
+ opp-hz = /bits/ 64 <486000000>;
+ opp-microvolt-speed0-pvs0-v0 = <975000>;
+ opp-microvolt-speed0-pvs1-v0 = <925000>;
+ opp-microvolt-speed0-pvs3-v0 = <875000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-594000000 {
+ opp-hz = /bits/ 64 <594000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1000000>;
+ opp-microvolt-speed0-pvs1-v0 = <950000>;
+ opp-microvolt-speed0-pvs3-v0 = <900000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-702000000 {
+ opp-hz = /bits/ 64 <702000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1025000>;
+ opp-microvolt-speed0-pvs1-v0 = <975000>;
+ opp-microvolt-speed0-pvs3-v0 = <925000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-810000000 {
+ opp-hz = /bits/ 64 <810000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1075000>;
+ opp-microvolt-speed0-pvs1-v0 = <1025000>;
+ opp-microvolt-speed0-pvs3-v0 = <975000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-918000000 {
+ opp-hz = /bits/ 64 <918000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1100000>;
+ opp-microvolt-speed0-pvs1-v0 = <1050000>;
+ opp-microvolt-speed0-pvs3-v0 = <1000000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-1026000000 {
+ opp-hz = /bits/ 64 <1026000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1125000>;
+ opp-microvolt-speed0-pvs1-v0 = <1075000>;
+ opp-microvolt-speed0-pvs3-v0 = <1025000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-1134000000 {
+ opp-hz = /bits/ 64 <1134000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1175000>;
+ opp-microvolt-speed0-pvs1-v0 = <1125000>;
+ opp-microvolt-speed0-pvs3-v0 = <1075000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-1242000000 {
+ opp-hz = /bits/ 64 <1242000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1200000>;
+ opp-microvolt-speed0-pvs1-v0 = <1150000>;
+ opp-microvolt-speed0-pvs3-v0 = <1100000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-1350000000 {
+ opp-hz = /bits/ 64 <1350000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1225000>;
+ opp-microvolt-speed0-pvs1-v0 = <1175000>;
+ opp-microvolt-speed0-pvs3-v0 = <1125000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-1458000000 {
+ opp-hz = /bits/ 64 <1458000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1237500>;
+ opp-microvolt-speed0-pvs1-v0 = <1187500>;
+ opp-microvolt-speed0-pvs3-v0 = <1137500>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
+
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1250000>;
+ opp-microvolt-speed0-pvs1-v0 = <1200000>;
+ opp-microvolt-speed0-pvs3-v0 = <1150000>;
+ opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF>;
+ };
};
memory@80000000 {
@@ -81,6 +199,13 @@ memory@80000000 {
reg = <0x80000000 0>;
};
+ kraitcc: clock-controller {
+ compatible = "qcom,krait-cc-v1";
+ clocks = <&gcc PLL9>, <&gcc PLL10>, <&acc0>, <&acc1>, <&pxo_board>;
+ clock-names = "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb";
+ #clock-cells = <1>;
+ };
+
I think the kraitcc node should be placed before the memory node so that it's sorted alphabetically.
soc: soc {
compatible = "simple-bus";
ranges;
@@ -112,6 +237,10 @@ qfprom: efuse@700000 {
#address-cells = <1>;
#size-cells = <1>;
+ pvs_efuse: pvs@c0 {
+ reg = <0xc0 0x04>;
+ };
+
tsens_calib: calib@404 {
reg = <0x404 0x10>;
};
@@ -348,7 +477,7 @@ acc0: clock-controller@2088000 {
};
saw0: power-manager@2089000 {
- compatible = "qcom,msm8960-saw2-cpu", "qcom,saw2";
+ compatible = "qcom,msm8960-saw2-v1.1-cpu", "qcom,saw2";
reg = <0x02089000 0x1000>, <0x02009000 0x1000>;
saw0_vreg: regulator {
@@ -367,7 +496,7 @@ acc1: clock-controller@2098000 {
};
saw1: power-manager@2099000 {
- compatible = "qcom,msm8960-saw2-cpu", "qcom,saw2";
+ compatible = "qcom,msm8960-saw2-v1.1-cpu", "qcom,saw2";
reg = <0x02099000 0x1000>, <0x02009000 0x1000>;
saw1_vreg: regulator {
Tested on the Sony Xperia SP (msm8960t), and it works as expected.
# echo performance | tee /sys/devices/system/cpu/cpufreq/policy*/scaling_governor
# echo 1512000 | tee /sys/devices/system/cpu/cpufreq/policy*/scaling_max_freq
# 7z b
7-Zip (z) 26.00 (armt) : Copyright (c) 1999-2026 Igor Pavlov : 2026-02-12
32-bit arm_v:7-A thumb:2 locale=C.UTF-8 Threads:2 OPEN_MAX:1024
Compiler: ver:15.2.0 GCC 15.2.0 : FP SIMD32 UNALIGNED
Linux : 7.0.0 : #247 SMP Thu May 14 20:32:48 UTC 2026 : armv7l
PageSize:4KB hwcap:FB8D6:NEON hwcap2:0
armt
1T CPU Freq (MHz): 717 814 815 815 817 799 816
1T CPU Freq (MHz): 100% 815 100% 816
2T CPU Freq (MHz): 196% 800 191% 777
RAM size: 974 MB, # CPU hardware threads: 2
RAM usage: 444 MB, # Benchmark threads: 2
Compressing | Decompressing
Dict Speed Usage R/U Rating | Speed Usage R/U Rating
KiB/s % MIPS MIPS | KiB/s % MIPS MIPS
22: 806 174 451 784 | 24894 193 1102 2126
23: 772 173 456 787 | 24344 194 1084 2107
24: 760 176 464 817 | 23257 194 1051 2042
25: 743 179 475 849 | 22233 193 1025 1979
---------------------------------- | ------------------------------
Avr: 770 175 462 809 | 23682 194 1066 2063
Tot: 184 764 1436
# echo 384000| tee /sys/devices/system/cpu/cpufreq/policy*/scaling_max_freq
# 7z b
7-Zip (z) 26.00 (armt) : Copyright (c) 1999-2026 Igor Pavlov : 2026-02-12
32-bit arm_v:7-A thumb:2 locale=C.UTF-8 Threads:2 OPEN_MAX:1024
Compiler: ver:15.2.0 GCC 15.2.0 : FP SIMD32 UNALIGNED
Linux : 7.0.0 : #247 SMP Thu May 14 20:32:48 UTC 2026 : armv7l
PageSize:4KB hwcap:FB8D6:NEON hwcap2:0
armt
1T CPU Freq (MHz): 210 209 210 210 209 210 210
1T CPU Freq (MHz): 99% 209 100% 210
2T CPU Freq (MHz): 191% 202 190% 200
RAM size: 974 MB, # CPU hardware threads: 2
RAM usage: 444 MB, # Benchmark threads: 2
Compressing | Decompressing
Dict Speed Usage R/U Rating | Speed Usage R/U Rating
KiB/s % MIPS MIPS | KiB/s % MIPS MIPS
22: 295 146 196 287 | 7444 188 337 636
23: 286 148 197 292 | 7302 188 337 632
24: 285 150 205 307 | 7255 191 333 637
25: 282 151 214 322 | 7105 192 330 632
---------------------------------- | ------------------------------
Avr: 287 149 203 302 | 7276 190 334 634
Tot: 169 269 468
Tested-by: Antony Kurniawan Soemardi <linux@xxxxxxxxxxxxxx>
--
Thanks,
Antony K. S.