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.