aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinaro CI <ci_notify@linaro.org>2019-01-15 11:56:41 +0000
committerLinaro CI <ci_notify@linaro.org>2019-01-15 11:56:41 +0000
commit48e01452e7d2a55f58ed9cde7a62045c95e8d2f4 (patch)
treef5a23ff325a6ac3e597cd9309a5e13100a82d10c
parentefd69074cd4f4b93b266611d12ff15dc6f0ec8b2 (diff)
parent9bde3651f3585ec358dfff6e5bc824413e59c524 (diff)
Merge remote-tracking branch 'apq8064-cpufreq/qcomlt-apq8064-cpufreq' into integration-linux-qcomlt
-rw-r--r--Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt (renamed from Documentation/devicetree/bindings/opp/kryo-cpufreq.txt)7
-rw-r--r--arch/arm/boot/dts/qcom-apq8064.dtsi630
-rw-r--r--drivers/cpufreq/Kconfig.arm6
-rw-r--r--drivers/cpufreq/Makefile2
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c5
-rw-r--r--drivers/cpufreq/qcom-cpufreq-kryo.c233
-rw-r--r--drivers/cpufreq/qcom-cpufreq-nvmem.c388
7 files changed, 1023 insertions, 248 deletions
diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
index c2127b96805a..7bc0f1a23ac5 100644
--- a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
+++ b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
@@ -19,7 +19,8 @@ In 'cpus' nodes:
In 'operating-points-v2' table:
- compatible: Should be
- - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+ - 'operating-points-v2-qcom-cpu' for apq8096, msm8996, msm8974,
+ apq8064, msm8960 and ipq8074.
- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
efuse registers that has information about the
speedbin that is used to select the right frequency/voltage
@@ -127,7 +128,7 @@ Example 1:
};
cluster0_opp: opp_table0 {
- compatible = "operating-points-v2-kryo-cpu";
+ compatible = "operating-points-v2-qcom-cpu";
nvmem-cells = <&speedbin_efuse>;
opp-shared;
@@ -338,7 +339,7 @@ Example 1:
};
cluster1_opp: opp_table1 {
- compatible = "operating-points-v2-kryo-cpu";
+ compatible = "operating-points-v2-qcom-cpu";
nvmem-cells = <&speedbin_efuse>;
opp-shared;
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 48c3cf427610..b2ba1cf4ade2 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -9,6 +9,8 @@
#include <dt-bindings/soc/qcom,gsbi.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
+
/ {
model = "Qualcomm APQ8064";
compatible = "qcom,apq8064";
@@ -43,6 +45,14 @@
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
cpu-idle-states = <&CPU_SPC>;
+ clocks = <&kraitcc 0>, <&kraitcc 4>;
+ clock-names = "cpu", "l2";
+ clock-latency = <100000>;
+ cpu-supply = <&saw0_regulator>;
+ cooling-min-level = <0>;
+ cooling-max-level = <7>;
+ #cooling-cells = <2>;
+ operating-points-v2 = <&cpu_opp_table>;
};
CPU1: cpu@1 {
@@ -54,6 +64,14 @@
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
cpu-idle-states = <&CPU_SPC>;
+ clocks = <&kraitcc 1>, <&kraitcc 4>;
+ clock-names = "cpu", "l2";
+ clock-latency = <100000>;
+ cpu-supply = <&saw1_regulator>;
+ cooling-min-level = <0>;
+ cooling-max-level = <7>;
+ #cooling-cells = <2>;
+ operating-points-v2 = <&cpu_opp_table>;
};
CPU2: cpu@2 {
@@ -65,6 +83,14 @@
qcom,acc = <&acc2>;
qcom,saw = <&saw2>;
cpu-idle-states = <&CPU_SPC>;
+ clocks = <&kraitcc 2>, <&kraitcc 4>;
+ clock-names = "cpu", "l2";
+ clock-latency = <100000>;
+ cpu-supply = <&saw2_regulator>;
+ cooling-min-level = <0>;
+ cooling-max-level = <7>;
+ #cooling-cells = <2>;
+ operating-points-v2 = <&cpu_opp_table>;
};
CPU3: cpu@3 {
@@ -76,6 +102,14 @@
qcom,acc = <&acc3>;
qcom,saw = <&saw3>;
cpu-idle-states = <&CPU_SPC>;
+ clocks = <&kraitcc 3>, <&kraitcc 4>;
+ clock-names = "cpu", "l2";
+ clock-latency = <100000>;
+ cpu-supply = <&saw3_regulator>;
+ cooling-min-level = <0>;
+ cooling-max-level = <7>;
+ #cooling-cells = <2>;
+ operating-points-v2 = <&cpu_opp_table>;
};
L2: l2-cache {
@@ -83,6 +117,10 @@
cache-level = <2>;
};
+ l2-clock {
+ l2-rates = <384000000 972000000 1188000000>;
+ };
+
idle-states {
CPU_SPC: spc {
compatible = "qcom,idle-state-spc",
@@ -114,6 +152,13 @@
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert0>;
+ cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
cpu-thermal1 {
@@ -135,6 +180,13 @@
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert1>;
+ cooling-device = <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
cpu-thermal2 {
@@ -156,6 +208,13 @@
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert2>;
+ cooling-device = <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
cpu-thermal3 {
@@ -177,6 +236,13 @@
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert3>;
+ cooling-device = <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
};
@@ -185,6 +251,11 @@
interrupts = <1 10 0x304>;
};
+ kraitcc: clock-controller {
+ compatible = "qcom,krait-cc-v1";
+ #clock-cells = <1>;
+ };
+
clocks {
cxo_board: cxo_board {
compatible = "fixed-clock";
@@ -333,6 +404,514 @@
<&xoadc 0x00 0x0e>; /* Charger temperature */
};
+ cpu_opp_table: opp-table {
+ compatible = "operating-points-v2-krait-cpu";
+ nvmem-cells = <&pvs_efuse>;
+
+ /*
+ * Missing opp-shared property means CPUs switch DVFS states
+ * independently.
+ */
+
+ opp-391500000 {
+ opp-hz = /bits/ 64 <391500000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <950000>;
+ opp-microvolt-speed0-pvs1-v0 = <900000>;
+ opp-microvolt-speed0-pvs3-v0 = <850000>;
+ opp-microvolt-speed0-pvs4-v0 = <850000>;
+ opp-microvolt-speed1-pvs0-v0 = <950000>;
+ opp-microvolt-speed1-pvs1-v0 = <950000>;
+ opp-microvolt-speed1-pvs2-v0 = <925000>;
+ opp-microvolt-speed1-pvs3-v0 = <900000>;
+ opp-microvolt-speed1-pvs4-v0 = <875000>;
+ opp-microvolt-speed1-pvs5-v0 = <875000>;
+ opp-microvolt-speed1-pvs6-v0 = <875000>;
+ opp-microvolt-speed2-pvs0-v0 = <950000>;
+ opp-microvolt-speed2-pvs1-v0 = <950000>;
+ opp-microvolt-speed2-pvs2-v0 = <925000>;
+ opp-microvolt-speed2-pvs3-v0 = <900000>;
+ opp-microvolt-speed2-pvs4-v0 = <875000>;
+ opp-microvolt-speed2-pvs5-v0 = <875000>;
+ opp-microvolt-speed2-pvs6-v0 = <875000>;
+ opp-microvolt-speed7-pvs0-v0 = <950000>;
+ opp-microvolt-speed7-pvs1-v0 = <925000>;
+ opp-microvolt-speed7-pvs2-v0 = <900000>;
+ opp-microvolt-speed7-pvs3-v0 = <900000>;
+ opp-microvolt-speed7-pvs4-v0 = <875000>;
+ opp-microvolt-speed7-pvs5-v0 = <875000>;
+ opp-microvolt-speed7-pvs6-v0 = <875000>;
+ };
+
+ opp-432000000 {
+ opp-hz = /bits/ 64 <432000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <975000>;
+ opp-microvolt-speed0-pvs1-v0 = <925000>;
+ opp-microvolt-speed0-pvs3-v0 = <875000>;
+ opp-microvolt-speed0-pvs4-v0 = <875000>;
+ };
+
+ opp-486000000 {
+ opp-hz = /bits/ 64 <486000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <975000>;
+ opp-microvolt-speed0-pvs1-v0 = <925000>;
+ opp-microvolt-speed0-pvs3-v0 = <875000>;
+ opp-microvolt-speed0-pvs4-v0 = <875000>;
+ opp-microvolt-speed1-pvs0-v0 = <950000>;
+ opp-microvolt-speed1-pvs1-v0 = <950000>;
+ opp-microvolt-speed1-pvs2-v0 = <925000>;
+ opp-microvolt-speed1-pvs3-v0 = <900000>;
+ opp-microvolt-speed1-pvs4-v0 = <875000>;
+ opp-microvolt-speed1-pvs5-v0 = <875000>;
+ opp-microvolt-speed1-pvs6-v0 = <875000>;
+ opp-microvolt-speed2-pvs0-v0 = <950000>;
+ opp-microvolt-speed2-pvs1-v0 = <950000>;
+ opp-microvolt-speed2-pvs2-v0 = <925000>;
+ opp-microvolt-speed2-pvs3-v0 = <900000>;
+ opp-microvolt-speed2-pvs4-v0 = <875000>;
+ opp-microvolt-speed2-pvs5-v0 = <875000>;
+ opp-microvolt-speed2-pvs6-v0 = <875000>;
+ opp-microvolt-speed7-pvs0-v0 = <950000>;
+ opp-microvolt-speed7-pvs1-v0 = <925000>;
+ opp-microvolt-speed7-pvs2-v0 = <900000>;
+ opp-microvolt-speed7-pvs3-v0 = <900000>;
+ opp-microvolt-speed7-pvs4-v0 = <875000>;
+ opp-microvolt-speed7-pvs5-v0 = <875000>;
+ opp-microvolt-speed7-pvs6-v0 = <875000>;
+ };
+
+ opp-540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <1000000>;
+ opp-microvolt-speed0-pvs1-v0 = <950000>;
+ opp-microvolt-speed0-pvs3-v0 = <900000>;
+ opp-microvolt-speed0-pvs4-v0 = <900000>;
+ };
+
+ opp-594000000 {
+ opp-hz = /bits/ 64 <594000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <1000000>;
+ opp-microvolt-speed0-pvs1-v0 = <950000>;
+ opp-microvolt-speed0-pvs3-v0 = <900000>;
+ opp-microvolt-speed0-pvs4-v0 = <900000>;
+ opp-microvolt-speed1-pvs0-v0 = <950000>;
+ opp-microvolt-speed1-pvs1-v0 = <950000>;
+ opp-microvolt-speed1-pvs2-v0 = <925000>;
+ opp-microvolt-speed1-pvs3-v0 = <900000>;
+ opp-microvolt-speed1-pvs4-v0 = <875000>;
+ opp-microvolt-speed1-pvs5-v0 = <875000>;
+ opp-microvolt-speed1-pvs6-v0 = <875000>;
+ opp-microvolt-speed2-pvs0-v0 = <950000>;
+ opp-microvolt-speed2-pvs1-v0 = <950000>;
+ opp-microvolt-speed2-pvs2-v0 = <925000>;
+ opp-microvolt-speed2-pvs3-v0 = <900000>;
+ opp-microvolt-speed2-pvs4-v0 = <875000>;
+ opp-microvolt-speed2-pvs5-v0 = <875000>;
+ opp-microvolt-speed2-pvs6-v0 = <875000>;
+ opp-microvolt-speed7-pvs0-v0 = <950000>;
+ opp-microvolt-speed7-pvs1-v0 = <925000>;
+ opp-microvolt-speed7-pvs2-v0 = <900000>;
+ opp-microvolt-speed7-pvs3-v0 = <900000>;
+ opp-microvolt-speed7-pvs4-v0 = <875000>;
+ opp-microvolt-speed7-pvs5-v0 = <875000>;
+ opp-microvolt-speed7-pvs6-v0 = <875000>;
+ };
+
+ opp-648000000 {
+ opp-hz = /bits/ 64 <648000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <1025000>;
+ opp-microvolt-speed0-pvs1-v0 = <975000>;
+ opp-microvolt-speed0-pvs3-v0 = <925000>;
+ opp-microvolt-speed0-pvs4-v0 = <925000>;
+ };
+
+ opp-702000000 {
+ opp-hz = /bits/ 64 <702000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <1025000>;
+ opp-microvolt-speed0-pvs1-v0 = <975000>;
+ opp-microvolt-speed0-pvs3-v0 = <925000>;
+ opp-microvolt-speed0-pvs4-v0 = <925000>;
+ opp-microvolt-speed1-pvs0-v0 = <962500>;
+ opp-microvolt-speed1-pvs1-v0 = <962500>;
+ opp-microvolt-speed1-pvs2-v0 = <925000>;
+ opp-microvolt-speed1-pvs3-v0 = <900000>;
+ opp-microvolt-speed1-pvs4-v0 = <875000>;
+ opp-microvolt-speed1-pvs5-v0 = <875000>;
+ opp-microvolt-speed1-pvs6-v0 = <875000>;
+ opp-microvolt-speed2-pvs0-v0 = <962500>;
+ opp-microvolt-speed2-pvs1-v0 = <962500>;
+ opp-microvolt-speed2-pvs2-v0 = <925000>;
+ opp-microvolt-speed2-pvs3-v0 = <900000>;
+ opp-microvolt-speed2-pvs4-v0 = <875000>;
+ opp-microvolt-speed2-pvs5-v0 = <875000>;
+ opp-microvolt-speed2-pvs6-v0 = <875000>;
+ opp-microvolt-speed7-pvs0-v0 = <950000>;
+ opp-microvolt-speed7-pvs1-v0 = <925000>;
+ opp-microvolt-speed7-pvs2-v0 = <900000>;
+ opp-microvolt-speed7-pvs3-v0 = <900000>;
+ opp-microvolt-speed7-pvs4-v0 = <875000>;
+ opp-microvolt-speed7-pvs5-v0 = <875000>;
+ opp-microvolt-speed7-pvs6-v0 = <875000>;
+ };
+
+ opp-756000000 {
+ opp-hz = /bits/ 64 <756000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <1075000>;
+ opp-microvolt-speed0-pvs1-v0 = <1025000>;
+ opp-microvolt-speed0-pvs3-v0 = <975000>;
+ opp-microvolt-speed0-pvs4-v0 = <962500>;
+ };
+
+ opp-810000000 {
+ opp-hz = /bits/ 64 <810000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <1075000>;
+ opp-microvolt-speed0-pvs1-v0 = <1025000>;
+ opp-microvolt-speed0-pvs3-v0 = <975000>;
+ opp-microvolt-speed0-pvs4-v0 = <962500>;
+ opp-microvolt-speed1-pvs0-v0 = <1000000>;
+ opp-microvolt-speed1-pvs1-v0 = <975000>;
+ opp-microvolt-speed1-pvs2-v0 = <937500>;
+ opp-microvolt-speed1-pvs3-v0 = <900000>;
+ opp-microvolt-speed1-pvs4-v0 = <887500>;
+ opp-microvolt-speed1-pvs5-v0 = <887500>;
+ opp-microvolt-speed1-pvs6-v0 = <887500>;
+ opp-microvolt-speed2-pvs0-v0 = <1000000>;
+ opp-microvolt-speed2-pvs1-v0 = <975000>;
+ opp-microvolt-speed2-pvs2-v0 = <937500>;
+ opp-microvolt-speed2-pvs3-v0 = <900000>;
+ opp-microvolt-speed2-pvs4-v0 = <887500>;
+ opp-microvolt-speed2-pvs5-v0 = <887500>;
+ opp-microvolt-speed2-pvs6-v0 = <887500>;
+ opp-microvolt-speed7-pvs0-v0 = <962500>;
+ opp-microvolt-speed7-pvs1-v0 = <937500>;
+ opp-microvolt-speed7-pvs2-v0 = <912500>;
+ opp-microvolt-speed7-pvs3-v0 = <900000>;
+ opp-microvolt-speed7-pvs4-v0 = <887500>;
+ opp-microvolt-speed7-pvs5-v0 = <887500>;
+ opp-microvolt-speed7-pvs6-v0 = <887500>;
+ };
+
+ opp-864000000 {
+ opp-hz = /bits/ 64 <864000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <1100000>;
+ opp-microvolt-speed0-pvs1-v0 = <1050000>;
+ opp-microvolt-speed0-pvs3-v0 = <1000000>;
+ opp-microvolt-speed0-pvs4-v0 = <975000>;
+ };
+
+ opp-918000000 {
+ opp-hz = /bits/ 64 <918000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <1100000>;
+ opp-microvolt-speed0-pvs1-v0 = <1050000>;
+ opp-microvolt-speed0-pvs3-v0 = <1000000>;
+ opp-microvolt-speed0-pvs4-v0 = <975000>;
+ opp-microvolt-speed1-pvs0-v0 = <1025000>;
+ opp-microvolt-speed1-pvs1-v0 = <1000000>;
+ opp-microvolt-speed1-pvs2-v0 = <950000>;
+ opp-microvolt-speed1-pvs3-v0 = <925000>;
+ opp-microvolt-speed1-pvs4-v0 = <900000>;
+ opp-microvolt-speed1-pvs5-v0 = <900000>;
+ opp-microvolt-speed1-pvs6-v0 = <900000>;
+ opp-microvolt-speed2-pvs0-v0 = <1025000>;
+ opp-microvolt-speed2-pvs1-v0 = <1000000>;
+ opp-microvolt-speed2-pvs2-v0 = <950000>;
+ opp-microvolt-speed2-pvs3-v0 = <925000>;
+ opp-microvolt-speed2-pvs4-v0 = <900000>;
+ opp-microvolt-speed2-pvs5-v0 = <900000>;
+ opp-microvolt-speed2-pvs6-v0 = <900000>;
+ opp-microvolt-speed7-pvs0-v0 = <975000>;
+ opp-microvolt-speed7-pvs1-v0 = <950000>;
+ opp-microvolt-speed7-pvs2-v0 = <925000>;
+ opp-microvolt-speed7-pvs3-v0 = <912500>;
+ opp-microvolt-speed7-pvs4-v0 = <900000>;
+ opp-microvolt-speed7-pvs5-v0 = <900000>;
+ opp-microvolt-speed7-pvs6-v0 = <900000>;
+ };
+
+ opp-972000000 {
+ opp-hz = /bits/ 64 <972000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <1125000>;
+ opp-microvolt-speed0-pvs1-v0 = <1075000>;
+ opp-microvolt-speed0-pvs3-v0 = <1025000>;
+ opp-microvolt-speed0-pvs4-v0 = <1000000>;
+ };
+
+ opp-1026000000 {
+ opp-hz = /bits/ 64 <1026000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <1125000>;
+ opp-microvolt-speed0-pvs1-v0 = <1075000>;
+ opp-microvolt-speed0-pvs3-v0 = <1025000>;
+ opp-microvolt-speed0-pvs4-v0 = <1000000>;
+ opp-microvolt-speed1-pvs0-v0 = <1037500>;
+ opp-microvolt-speed1-pvs1-v0 = <1012500>;
+ opp-microvolt-speed1-pvs2-v0 = <975000>;
+ opp-microvolt-speed1-pvs3-v0 = <950000>;
+ opp-microvolt-speed1-pvs4-v0 = <925000>;
+ opp-microvolt-speed1-pvs5-v0 = <925000>;
+ opp-microvolt-speed1-pvs6-v0 = <925000>;
+ opp-microvolt-speed2-pvs0-v0 = <1037500>;
+ opp-microvolt-speed2-pvs1-v0 = <1012500>;
+ opp-microvolt-speed2-pvs2-v0 = <975000>;
+ opp-microvolt-speed2-pvs3-v0 = <950000>;
+ opp-microvolt-speed2-pvs4-v0 = <925000>;
+ opp-microvolt-speed2-pvs5-v0 = <925000>;
+ opp-microvolt-speed2-pvs6-v0 = <925000>;
+ opp-microvolt-speed7-pvs0-v0 = <1000000>;
+ opp-microvolt-speed7-pvs1-v0 = <975000>;
+ opp-microvolt-speed7-pvs2-v0 = <950000>;
+ opp-microvolt-speed7-pvs3-v0 = <937500>;
+ opp-microvolt-speed7-pvs4-v0 = <925000>;
+ opp-microvolt-speed7-pvs5-v0 = <925000>;
+ opp-microvolt-speed7-pvs6-v0 = <925000>;
+ };
+
+ opp-1080000000 {
+ opp-hz = /bits/ 64 <1080000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <1175000>;
+ opp-microvolt-speed0-pvs1-v0 = <1125000>;
+ opp-microvolt-speed0-pvs3-v0 = <1075000>;
+ opp-microvolt-speed0-pvs4-v0 = <1050000>;
+ };
+
+ opp-1134000000 {
+ opp-hz = /bits/ 64 <1134000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <1175000>;
+ opp-microvolt-speed0-pvs1-v0 = <1125000>;
+ opp-microvolt-speed0-pvs3-v0 = <1075000>;
+ opp-microvolt-speed0-pvs4-v0 = <1050000>;
+ opp-microvolt-speed1-pvs0-v0 = <1075000>;
+ opp-microvolt-speed1-pvs1-v0 = <1037500>;
+ opp-microvolt-speed1-pvs2-v0 = <1000000>;
+ opp-microvolt-speed1-pvs3-v0 = <975000>;
+ opp-microvolt-speed1-pvs4-v0 = <950000>;
+ opp-microvolt-speed1-pvs5-v0 = <937500>;
+ opp-microvolt-speed1-pvs6-v0 = <937500>;
+ opp-microvolt-speed2-pvs0-v0 = <1075000>;
+ opp-microvolt-speed2-pvs1-v0 = <1037500>;
+ opp-microvolt-speed2-pvs2-v0 = <1000000>;
+ opp-microvolt-speed2-pvs3-v0 = <975000>;
+ opp-microvolt-speed2-pvs4-v0 = <950000>;
+ opp-microvolt-speed2-pvs5-v0 = <937500>;
+ opp-microvolt-speed2-pvs6-v0 = <937500>;
+ opp-microvolt-speed7-pvs0-v0 = <1025000>;
+ opp-microvolt-speed7-pvs1-v0 = <1000000>;
+ opp-microvolt-speed7-pvs2-v0 = <975000>;
+ opp-microvolt-speed7-pvs3-v0 = <962500>;
+ opp-microvolt-speed7-pvs4-v0 = <950000>;
+ opp-microvolt-speed7-pvs5-v0 = <937500>;
+ opp-microvolt-speed7-pvs6-v0 = <937500>;
+ };
+
+ opp-1188000000 {
+ opp-hz = /bits/ 64 <1188000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <1200000>;
+ opp-microvolt-speed0-pvs1-v0 = <1150000>;
+ opp-microvolt-speed0-pvs3-v0 = <1100000>;
+ opp-microvolt-speed0-pvs4-v0 = <1075000>;
+ };
+
+ opp-1242000000 {
+ opp-hz = /bits/ 64 <1242000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <1200000>;
+ opp-microvolt-speed0-pvs1-v0 = <1150000>;
+ opp-microvolt-speed0-pvs3-v0 = <1100000>;
+ opp-microvolt-speed0-pvs4-v0 = <1075000>;
+ opp-microvolt-speed1-pvs0-v0 = <1087500>;
+ opp-microvolt-speed1-pvs1-v0 = <1050000>;
+ opp-microvolt-speed1-pvs2-v0 = <1012500>;
+ opp-microvolt-speed1-pvs3-v0 = <987500>;
+ opp-microvolt-speed1-pvs4-v0 = <962500>;
+ opp-microvolt-speed1-pvs5-v0 = <950000>;
+ opp-microvolt-speed1-pvs6-v0 = <950000>;
+ opp-microvolt-speed2-pvs0-v0 = <1087500>;
+ opp-microvolt-speed2-pvs1-v0 = <1050000>;
+ opp-microvolt-speed2-pvs2-v0 = <1012500>;
+ opp-microvolt-speed2-pvs3-v0 = <987500>;
+ opp-microvolt-speed2-pvs4-v0 = <962500>;
+ opp-microvolt-speed2-pvs5-v0 = <950000>;
+ opp-microvolt-speed2-pvs6-v0 = <950000>;
+ opp-microvolt-speed7-pvs0-v0 = <1037500>;
+ opp-microvolt-speed7-pvs1-v0 = <1012500>;
+ opp-microvolt-speed7-pvs2-v0 = <987500>;
+ opp-microvolt-speed7-pvs3-v0 = <975000>;
+ opp-microvolt-speed7-pvs4-v0 = <962500>;
+ opp-microvolt-speed7-pvs5-v0 = <950000>;
+ opp-microvolt-speed7-pvs6-v0 = <950000>;
+ };
+
+ opp-1296000000 {
+ opp-hz = /bits/ 64 <1296000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <1225000>;
+ opp-microvolt-speed0-pvs1-v0 = <1175000>;
+ opp-microvolt-speed0-pvs3-v0 = <1125000>;
+ opp-microvolt-speed0-pvs4-v0 = <1100000>;
+ };
+
+ opp-1350000000 {
+ opp-hz = /bits/ 64 <1350000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <1225000>;
+ opp-microvolt-speed0-pvs1-v0 = <1175000>;
+ opp-microvolt-speed0-pvs3-v0 = <1125000>;
+ opp-microvolt-speed0-pvs4-v0 = <1100000>;
+ opp-microvolt-speed1-pvs0-v0 = <1125000>;
+ opp-microvolt-speed1-pvs1-v0 = <1087500>;
+ opp-microvolt-speed1-pvs2-v0 = <1037500>;
+ opp-microvolt-speed1-pvs3-v0 = <1000000>;
+ opp-microvolt-speed1-pvs4-v0 = <975000>;
+ opp-microvolt-speed1-pvs5-v0 = <962500>;
+ opp-microvolt-speed1-pvs6-v0 = <962500>;
+ opp-microvolt-speed2-pvs0-v0 = <1125000>;
+ opp-microvolt-speed2-pvs1-v0 = <1087500>;
+ opp-microvolt-speed2-pvs2-v0 = <1037500>;
+ opp-microvolt-speed2-pvs3-v0 = <1000000>;
+ opp-microvolt-speed2-pvs4-v0 = <975000>;
+ opp-microvolt-speed2-pvs5-v0 = <962500>;
+ opp-microvolt-speed2-pvs6-v0 = <962500>;
+ opp-microvolt-speed7-pvs0-v0 = <1062500>;
+ opp-microvolt-speed7-pvs1-v0 = <1037500>;
+ opp-microvolt-speed7-pvs2-v0 = <1012500>;
+ opp-microvolt-speed7-pvs3-v0 = <1000000>;
+ opp-microvolt-speed7-pvs4-v0 = <975000>;
+ opp-microvolt-speed7-pvs5-v0 = <962500>;
+ opp-microvolt-speed7-pvs6-v0 = <962500>;
+ };
+
+ opp-1404000000 {
+ opp-hz = /bits/ 64 <1404000000>;
+ opp-supported-hw = <0x01>;
+ opp-microvolt-speed0-pvs0-v0 = <1237500>;
+ opp-microvolt-speed0-pvs1-v0 = <1187500>;
+ opp-microvolt-speed0-pvs3-v0 = <1137500>;
+ opp-microvolt-speed0-pvs4-v0 = <1112500>;
+ };
+
+ opp-1458000000 {
+ opp-hz = /bits/ 64 <1458000000>;
+ opp-supported-hw = <0x87>;
+ opp-microvolt-speed0-pvs0-v0 = <1237500>;
+ opp-microvolt-speed0-pvs1-v0 = <1187500>;
+ opp-microvolt-speed0-pvs3-v0 = <1137500>;
+ opp-microvolt-speed0-pvs4-v0 = <1112500>;
+ opp-microvolt-speed1-pvs0-v0 = <1150000>;
+ opp-microvolt-speed1-pvs1-v0 = <1112500>;
+ opp-microvolt-speed1-pvs2-v0 = <1075000>;
+ opp-microvolt-speed1-pvs3-v0 = <1037500>;
+ opp-microvolt-speed1-pvs4-v0 = <1000000>;
+ opp-microvolt-speed1-pvs5-v0 = <987500>;
+ opp-microvolt-speed1-pvs6-v0 = <975000>;
+ opp-microvolt-speed2-pvs0-v0 = <1150000>;
+ opp-microvolt-speed2-pvs1-v0 = <1112500>;
+ opp-microvolt-speed2-pvs2-v0 = <1075000>;
+ opp-microvolt-speed2-pvs3-v0 = <1037500>;
+ opp-microvolt-speed2-pvs4-v0 = <1000000>;
+ opp-microvolt-speed2-pvs5-v0 = <987500>;
+ opp-microvolt-speed2-pvs6-v0 = <975000>;
+ opp-microvolt-speed7-pvs0-v0 = <1110000>;
+ opp-microvolt-speed7-pvs1-v0 = <1075000>;
+ opp-microvolt-speed7-pvs2-v0 = <1050000>;
+ opp-microvolt-speed7-pvs3-v0 = <1025000>;
+ opp-microvolt-speed7-pvs4-v0 = <1000000>;
+ opp-microvolt-speed7-pvs5-v0 = <987500>;
+ opp-microvolt-speed7-pvs6-v0 = <975000>;
+ };
+
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-supported-hw = <0x03>;
+ opp-microvolt-speed0-pvs0-v0 = <1250000>;
+ opp-microvolt-speed0-pvs1-v0 = <1200000>;
+ opp-microvolt-speed0-pvs3-v0 = <1150000>;
+ opp-microvolt-speed0-pvs4-v0 = <1125000>;
+ opp-microvolt-speed1-pvs0-v0 = <1162500>;
+ opp-microvolt-speed1-pvs1-v0 = <1125000>;
+ opp-microvolt-speed1-pvs2-v0 = <1087500>;
+ opp-microvolt-speed1-pvs3-v0 = <1050000>;
+ opp-microvolt-speed1-pvs4-v0 = <1012500>;
+ opp-microvolt-speed1-pvs5-v0 = <1000000>;
+ opp-microvolt-speed1-pvs6-v0 = <987500>;
+ };
+
+ opp-1566000000 {
+ opp-hz = /bits/ 64 <1566000000>;
+ opp-supported-hw = <0x84>;
+ opp-microvolt-speed2-pvs0-v0 = <1175000>;
+ opp-microvolt-speed2-pvs1-v0 = <1150000>;
+ opp-microvolt-speed2-pvs2-v0 = <1100000>;
+ opp-microvolt-speed2-pvs3-v0 = <1062500>;
+ opp-microvolt-speed2-pvs4-v0 = <1037500>;
+ opp-microvolt-speed2-pvs5-v0 = <1012500>;
+ opp-microvolt-speed2-pvs6-v0 = <1000000>;
+ opp-microvolt-speed7-pvs0-v0 = <1125000>;
+ opp-microvolt-speed7-pvs1-v0 = <1100000>;
+ opp-microvolt-speed7-pvs2-v0 = <1075000>;
+ opp-microvolt-speed7-pvs3-v0 = <1050000>;
+ opp-microvolt-speed7-pvs4-v0 = <1037500>;
+ opp-microvolt-speed7-pvs5-v0 = <1012500>;
+ opp-microvolt-speed7-pvs6-v0 = <1000000>;
+ };
+
+ opp-1674000000 {
+ opp-hz = /bits/ 64 <1674000000>;
+ opp-supported-hw = <0x84>;
+ opp-microvolt-speed2-pvs0-v0 = <1225000>;
+ opp-microvolt-speed2-pvs1-v0 = <1187500>;
+ opp-microvolt-speed2-pvs2-v0 = <1137500>;
+ opp-microvolt-speed2-pvs3-v0 = <1100000>;
+ opp-microvolt-speed2-pvs4-v0 = <1075000>;
+ opp-microvolt-speed2-pvs5-v0 = <1050000>;
+ opp-microvolt-speed2-pvs6-v0 = <1025000>;
+ opp-microvolt-speed7-pvs0-v0 = <1175000>;
+ opp-microvolt-speed7-pvs1-v0 = <1137500>;
+ opp-microvolt-speed7-pvs2-v0 = <1112500>;
+ opp-microvolt-speed7-pvs3-v0 = <1087500>;
+ opp-microvolt-speed7-pvs4-v0 = <1075000>;
+ opp-microvolt-speed7-pvs5-v0 = <1050000>;
+ opp-microvolt-speed7-pvs6-v0 = <1025000>;
+ };
+
+ opp-1728000000 {
+ opp-hz = /bits/ 64 <1728000000>;
+ opp-supported-hw = <0x04>;
+ opp-microvolt-speed2-pvs0-v0 = <1250000>;
+ opp-microvolt-speed2-pvs1-v0 = <1200000>;
+ opp-microvolt-speed2-pvs2-v0 = <1162500>;
+ opp-microvolt-speed2-pvs3-v0 = <1125000>;
+ opp-microvolt-speed2-pvs4-v0 = <1100000>;
+ opp-microvolt-speed2-pvs5-v0 = <1075000>;
+ opp-microvolt-speed2-pvs6-v0 = <1050000>;
+ };
+
+ opp-1782000000 {
+ opp-hz = /bits/ 64 <1782000000>;
+ opp-supported-hw = <0x80>;
+ opp-microvolt-speed7-pvs0-v0 = <1225000>;
+ opp-microvolt-speed7-pvs1-v0 = <1187500>;
+ opp-microvolt-speed7-pvs2-v0 = <1162500>;
+ opp-microvolt-speed7-pvs3-v0 = <1137500>;
+ opp-microvolt-speed7-pvs4-v0 = <1112500>;
+ opp-microvolt-speed7-pvs5-v0 = <1087500>;
+ opp-microvolt-speed7-pvs6-v0 = <1062500>;
+ };
+ };
+
soc: soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -399,27 +978,59 @@
};
saw0: power-controller@2089000 {
- compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2";
+ compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2", "syscon", "simple-mfd";
reg = <0x02089000 0x1000>, <0x02009000 0x1000>;
- regulator;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ saw0_regulator: regulator@2089000 {
+ compatible = "qcom,apq8064-saw2-v1.1-regulator";
+ regulator-always-on;
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <1250000>;
+ };
};
saw1: power-controller@2099000 {
- compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2";
+ compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2", "syscon", "simple-mfd";
reg = <0x02099000 0x1000>, <0x02009000 0x1000>;
- regulator;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ saw1_regulator: regulator@2099000 {
+ compatible = "qcom,apq8064-saw2-v1.1-regulator";
+ regulator-always-on;
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <1250000>;
+ };
};
saw2: power-controller@20a9000 {
- compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2";
+ compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2", "syscon", "simple-mfd";
reg = <0x020a9000 0x1000>, <0x02009000 0x1000>;
- regulator;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ saw2_regulator: regulator@20a9000 {
+ compatible = "qcom,apq8064-saw2-v1.1-regulator";
+ regulator-always-on;
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <1250000>;
+ };
};
saw3: power-controller@20b9000 {
- compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2";
+ compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2", "syscon", "simple-mfd";
reg = <0x020b9000 0x1000>, <0x02009000 0x1000>;
- regulator;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ saw3_regulator: regulator@20b9000 {
+ compatible = "qcom,apq8064-saw2-v1.1-regulator";
+ regulator-always-on;
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <1250000>;
+ };
};
sps_sic_non_secure: sps-sic-non-secure@12100000 {
@@ -852,6 +1463,9 @@
tsens_backup: backup_calib {
reg = <0x414 0x10>;
};
+ pvs_efuse: pvs {
+ reg = <0xc0 0x4>;
+ };
};
gcc: clock-controller@900000 {
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 688f10227793..a55db1015078 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -103,9 +103,9 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
-config ARM_QCOM_CPUFREQ_KRYO
- tristate "Qualcomm Kryo based CPUFreq"
- depends on ARM64
+config ARM_QCOM_CPUFREQ_NVMEM
+ tristate "Qualcomm nvmem based CPUFreq"
+ depends on ARCH_QCOM
depends on QCOM_QFPROM
depends on QCOM_SMEM
select PM_OPP
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 08c071be2491..e127a5c36cf3 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -62,7 +62,7 @@ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o
obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o
obj-$(CONFIG_ARM_QCOM_CPUFREQ_HW) += qcom-cpufreq-hw.o
-obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO) += qcom-cpufreq-kryo.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_NVMEM) += qcom-cpufreq-nvmem.o
obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o
obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o
obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index b1c5468dca16..272141eed647 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -132,6 +132,11 @@ static const struct of_device_id blacklist[] __initconst = {
{ .compatible = "ti,am43", },
{ .compatible = "ti,dra7", },
+ { .compatible = "qcom,ipq8064", },
+ { .compatible = "qcom,apq8064", },
+ { .compatible = "qcom,msm8974", },
+ { .compatible = "qcom,msm8960", },
+
{ }
};
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c b/drivers/cpufreq/qcom-cpufreq-kryo.c
deleted file mode 100644
index 2a3675c24032..000000000000
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ /dev/null
@@ -1,233 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
- */
-
-/*
- * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
- * the CPU frequency subset and voltage value of each OPP varies
- * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
- * defines the voltage and frequency value based on the msm-id in SMEM
- * and speedbin blown in the efuse combination.
- * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
- * to provide the OPP framework with required information.
- * This is used to determine the voltage and frequency value for each OPP of
- * operating-points-v2 table when it is parsed by the OPP framework.
- */
-
-#include <linux/cpu.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/nvmem-consumer.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_opp.h>
-#include <linux/slab.h>
-#include <linux/soc/qcom/smem.h>
-
-#define MSM_ID_SMEM 137
-
-enum _msm_id {
- MSM8996V3 = 0xF6ul,
- APQ8096V3 = 0x123ul,
- MSM8996SG = 0x131ul,
- APQ8096SG = 0x138ul,
-};
-
-enum _msm8996_version {
- MSM8996_V3,
- MSM8996_SG,
- NUM_OF_MSM8996_VERSIONS,
-};
-
-struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
-
-static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void)
-{
- size_t len;
- u32 *msm_id;
- enum _msm8996_version version;
-
- msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
- if (IS_ERR(msm_id))
- return NUM_OF_MSM8996_VERSIONS;
-
- /* The first 4 bytes are format, next to them is the actual msm-id */
- msm_id++;
-
- switch ((enum _msm_id)*msm_id) {
- case MSM8996V3:
- case APQ8096V3:
- version = MSM8996_V3;
- break;
- case MSM8996SG:
- case APQ8096SG:
- version = MSM8996_SG;
- break;
- default:
- version = NUM_OF_MSM8996_VERSIONS;
- }
-
- return version;
-}
-
-static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
-{
- struct opp_table *opp_tables[NR_CPUS] = {0};
- enum _msm8996_version msm8996_version;
- struct nvmem_cell *speedbin_nvmem;
- struct device_node *np;
- struct device *cpu_dev;
- unsigned cpu;
- u8 *speedbin;
- u32 versions;
- size_t len;
- int ret;
-
- cpu_dev = get_cpu_device(0);
- if (!cpu_dev)
- return -ENODEV;
-
- msm8996_version = qcom_cpufreq_kryo_get_msm_id();
- if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
- dev_err(cpu_dev, "Not Snapdragon 820/821!");
- return -ENODEV;
- }
-
- np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
- if (!np)
- return -ENOENT;
-
- ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu");
- if (!ret) {
- of_node_put(np);
- return -ENOENT;
- }
-
- speedbin_nvmem = of_nvmem_cell_get(np, NULL);
- of_node_put(np);
- if (IS_ERR(speedbin_nvmem)) {
- if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER)
- dev_err(cpu_dev, "Could not get nvmem cell: %ld\n",
- PTR_ERR(speedbin_nvmem));
- return PTR_ERR(speedbin_nvmem);
- }
-
- speedbin = nvmem_cell_read(speedbin_nvmem, &len);
- nvmem_cell_put(speedbin_nvmem);
- if (IS_ERR(speedbin))
- return PTR_ERR(speedbin);
-
- switch (msm8996_version) {
- case MSM8996_V3:
- versions = 1 << (unsigned int)(*speedbin);
- break;
- case MSM8996_SG:
- versions = 1 << ((unsigned int)(*speedbin) + 4);
- break;
- default:
- BUG();
- break;
- }
- kfree(speedbin);
-
- for_each_possible_cpu(cpu) {
- cpu_dev = get_cpu_device(cpu);
- if (NULL == cpu_dev) {
- ret = -ENODEV;
- goto free_opp;
- }
-
- opp_tables[cpu] = dev_pm_opp_set_supported_hw(cpu_dev,
- &versions, 1);
- if (IS_ERR(opp_tables[cpu])) {
- ret = PTR_ERR(opp_tables[cpu]);
- dev_err(cpu_dev, "Failed to set supported hardware\n");
- goto free_opp;
- }
- }
-
- cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
- NULL, 0);
- if (!IS_ERR(cpufreq_dt_pdev))
- return 0;
-
- ret = PTR_ERR(cpufreq_dt_pdev);
- dev_err(cpu_dev, "Failed to register platform device\n");
-
-free_opp:
- for_each_possible_cpu(cpu) {
- if (IS_ERR_OR_NULL(opp_tables[cpu]))
- break;
- dev_pm_opp_put_supported_hw(opp_tables[cpu]);
- }
-
- return ret;
-}
-
-static int qcom_cpufreq_kryo_remove(struct platform_device *pdev)
-{
- platform_device_unregister(cpufreq_dt_pdev);
- return 0;
-}
-
-static struct platform_driver qcom_cpufreq_kryo_driver = {
- .probe = qcom_cpufreq_kryo_probe,
- .remove = qcom_cpufreq_kryo_remove,
- .driver = {
- .name = "qcom-cpufreq-kryo",
- },
-};
-
-static const struct of_device_id qcom_cpufreq_kryo_match_list[] __initconst = {
- { .compatible = "qcom,apq8096", },
- { .compatible = "qcom,msm8996", },
- {}
-};
-
-/*
- * Since the driver depends on smem and nvmem drivers, which may
- * return EPROBE_DEFER, all the real activity is done in the probe,
- * which may be defered as well. The init here is only registering
- * the driver and the platform device.
- */
-static int __init qcom_cpufreq_kryo_init(void)
-{
- struct device_node *np = of_find_node_by_path("/");
- const struct of_device_id *match;
- int ret;
-
- if (!np)
- return -ENODEV;
-
- match = of_match_node(qcom_cpufreq_kryo_match_list, np);
- of_node_put(np);
- if (!match)
- return -ENODEV;
-
- ret = platform_driver_register(&qcom_cpufreq_kryo_driver);
- if (unlikely(ret < 0))
- return ret;
-
- kryo_cpufreq_pdev = platform_device_register_simple(
- "qcom-cpufreq-kryo", -1, NULL, 0);
- ret = PTR_ERR_OR_ZERO(kryo_cpufreq_pdev);
- if (0 == ret)
- return 0;
-
- platform_driver_unregister(&qcom_cpufreq_kryo_driver);
- return ret;
-}
-module_init(qcom_cpufreq_kryo_init);
-
-static void __exit qcom_cpufreq_kryo_exit(void)
-{
- platform_device_unregister(kryo_cpufreq_pdev);
- platform_driver_unregister(&qcom_cpufreq_kryo_driver);
-}
-module_exit(qcom_cpufreq_kryo_exit);
-
-MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
new file mode 100644
index 000000000000..fa7e1c6c6a85
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -0,0 +1,388 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/smem.h>
+
+#define MSM_ID_SMEM 137
+
+enum _msm_id {
+ MSM8996V3 = 0xF6ul,
+ APQ8096V3 = 0x123ul,
+ MSM8996SG = 0x131ul,
+ APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+ MSM8996_V3,
+ MSM8996_SG,
+ NUM_OF_MSM8996_VERSIONS,
+};
+
+static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
+
+static void __init get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver,
+ struct nvmem_cell *pvs_nvmem, u8 *buf)
+{
+ u32 pte_efuse;
+
+ pte_efuse = *((u32 *)buf);
+
+ *speed = pte_efuse & 0xf;
+ if (*speed == 0xf)
+ *speed = (pte_efuse >> 4) & 0xf;
+
+ if (*speed == 0xf) {
+ *speed = 0;
+ pr_warn("Speed bin: Defaulting to %d\n", *speed);
+ } else {
+ pr_info("Speed bin: %d\n", *speed);
+ }
+
+ *pvs = (pte_efuse >> 10) & 0x7;
+ if (*pvs == 0x7)
+ *pvs = (pte_efuse >> 13) & 0x7;
+
+ if (*pvs == 0x7) {
+ *pvs = 0;
+ pr_warn("PVS bin: Defaulting to %d\n", *pvs);
+ } else {
+ pr_info("PVS bin: %d\n", *pvs);
+ }
+
+ kfree(buf);
+}
+
+static void __init get_krait_bin_format_b(int *speed, int *pvs, int *pvs_ver,
+ struct nvmem_cell *pvs_nvmem, u8 *buf)
+{
+ u32 pte_efuse, redundant_sel;
+
+ pte_efuse = *((u32 *)buf);
+ redundant_sel = (pte_efuse >> 24) & 0x7;
+ *speed = pte_efuse & 0x7;
+
+ /* 4 bits of PVS are in efuse register bits 31, 8-6. */
+ *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
+ *pvs_ver = (pte_efuse >> 4) & 0x3;
+
+ switch (redundant_sel) {
+ case 1:
+ *speed = (pte_efuse >> 27) & 0xf;
+ break;
+ case 2:
+ *pvs = (pte_efuse >> 27) & 0xf;
+ break;
+ }
+
+ /* Check SPEED_BIN_BLOW_STATUS */
+ if (pte_efuse & BIT(3)) {
+ pr_info("Speed bin: %d\n", *speed);
+ } else {
+ pr_warn("Speed bin not set. Defaulting to 0!\n");
+ *speed = 0;
+ }
+
+ /* Check PVS_BLOW_STATUS */
+ pte_efuse = *(((u32 *)buf) + 4);
+ pte_efuse &= BIT(21);
+ if (pte_efuse) {
+ pr_info("PVS bin: %d\n", *pvs);
+ } else {
+ pr_warn("PVS bin not set. Defaulting to 0!\n");
+ *pvs = 0;
+ }
+
+ pr_info("PVS version: %d\n", *pvs_ver);
+ kfree(buf);
+}
+
+static enum _msm8996_version qcom_cpufreq_get_msm_id(void)
+{
+ size_t len;
+ u32 *msm_id;
+ enum _msm8996_version version;
+
+ msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+ if (IS_ERR(msm_id))
+ return NUM_OF_MSM8996_VERSIONS;
+
+ /* The first 4 bytes are format, next to them is the actual msm-id */
+ msm_id++;
+
+ switch ((enum _msm_id)*msm_id) {
+ case MSM8996V3:
+ case APQ8096V3:
+ version = MSM8996_V3;
+ break;
+ case MSM8996SG:
+ case APQ8096SG:
+ version = MSM8996_SG;
+ break;
+ default:
+ version = NUM_OF_MSM8996_VERSIONS;
+ }
+
+ return version;
+}
+
+static int qcom_cpufreq_krait_name_version(struct device *cpu_dev,
+ struct nvmem_cell *speedbin_nvmem,
+ char **name,
+ u32 *versions)
+{
+ int speed = 0, pvs = 0, pvs_ver = 0;
+ u8 *buf;
+ size_t len;
+
+ buf = nvmem_cell_read(speedbin_nvmem, &len);
+ if (len == 4) {
+ get_krait_bin_format_a(&speed, &pvs, &pvs_ver,
+ speedbin_nvmem, buf);
+ } else if (len == 8) {
+ get_krait_bin_format_b(&speed, &pvs, &pvs_ver,
+ speedbin_nvmem, buf);
+ } else {
+ dev_err(cpu_dev, "Unable to read nvmem data. Defaulting to 0!\n");
+ return -ENODEV;
+ }
+
+ snprintf(*name, sizeof("speedXX-pvsXX-vXX"), "speed%d-pvs%d-v%d",
+ speed, pvs, pvs_ver);
+
+ *versions = (1 << speed);
+
+ return 0;
+}
+
+static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
+ struct nvmem_cell *speedbin_nvmem,
+ char **pvs_name,
+ u32 *versions)
+{
+ size_t len;
+ u8 *speedbin;
+ enum _msm8996_version msm8996_version;
+
+ *pvs_name = NULL;
+ msm8996_version = qcom_cpufreq_get_msm_id();
+ if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
+ dev_err(cpu_dev, "Not Snapdragon 820/821!");
+ return -ENODEV;
+ }
+
+ speedbin = nvmem_cell_read(speedbin_nvmem, &len);
+ if (IS_ERR(speedbin))
+ return PTR_ERR(speedbin);
+
+ switch (msm8996_version) {
+ case MSM8996_V3:
+ *versions = 1 << (unsigned int)(*speedbin);
+ break;
+ case MSM8996_SG:
+ *versions = 1 << ((unsigned int)(*speedbin) + 4);
+ break;
+ default:
+ BUG();
+ break;
+ }
+
+ kfree(speedbin);
+ return 0;
+}
+
+static int qcom_cpufreq_probe(struct platform_device *pdev)
+{
+ struct opp_table *tbl1[NR_CPUS] = { NULL }, *tbl2[NR_CPUS] = { NULL };
+ int (*get_version)(struct device *cpu_dev,
+ struct nvmem_cell *speedbin_nvmem,
+ char **name, int *versions);
+ struct nvmem_cell *speedbin_nvmem;
+ struct device_node *np;
+ struct device *cpu_dev;
+ unsigned cpu;
+ u32 versions;
+ const struct of_device_id *match;
+ char *pvs_name = "speedXX-pvsXX-vXX";
+ int ret;
+
+ cpu_dev = get_cpu_device(0);
+ if (!cpu_dev)
+ return -ENODEV;
+
+ match = pdev->dev.platform_data;
+ get_version = match->data;
+ if (!get_version)
+ return -ENODEV;
+
+ np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
+ if (!np)
+ return -ENOENT;
+
+ ret = of_device_is_compatible(np, "operating-points-v2-qcom-cpu");
+ if (!ret) {
+ of_node_put(np);
+ return -ENOENT;
+ }
+
+ speedbin_nvmem = of_nvmem_cell_get(np, NULL);
+ of_node_put(np);
+ if (IS_ERR(speedbin_nvmem)) {
+ if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER)
+ dev_err(cpu_dev, "Could not get nvmem cell: %ld\n",
+ PTR_ERR(speedbin_nvmem));
+ return PTR_ERR(speedbin_nvmem);
+ }
+
+ ret = get_version(cpu_dev, speedbin_nvmem, &pvs_name, &versions);
+ nvmem_cell_put(speedbin_nvmem);
+ if (ret)
+ return ret;
+
+ for_each_possible_cpu(cpu) {
+ cpu_dev = get_cpu_device(cpu);
+ if (NULL == cpu_dev) {
+ ret = -ENODEV;
+ goto free_opp;
+ }
+
+ if (pvs_name) {
+ tbl1[cpu] = dev_pm_opp_set_prop_name(cpu_dev, pvs_name);
+ if (IS_ERR(tbl1[cpu])) {
+ ret = PTR_ERR(tbl1[cpu]);
+ dev_err(cpu_dev, "Failed to add OPP name %s\n",
+ pvs_name);
+ goto free_opp;
+ }
+ }
+
+ tbl2[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, &versions, 1);
+ if (IS_ERR(tbl2[cpu])) {
+ ret = PTR_ERR(tbl2[cpu]);
+ dev_err(cpu_dev, "Failed to set supported hardware\n");
+ goto free_opp;
+ }
+ }
+
+ cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
+ NULL, 0);
+ if (!IS_ERR(cpufreq_dt_pdev))
+ return 0;
+
+ ret = PTR_ERR(cpufreq_dt_pdev);
+ dev_err(cpu_dev, "Failed to register platform device\n");
+
+free_opp:
+ for_each_possible_cpu(cpu) {
+ if (IS_ERR_OR_NULL(tbl1[cpu]))
+ break;
+ dev_pm_opp_put_prop_name(tbl1[cpu]);
+ }
+
+ for_each_possible_cpu(cpu) {
+ if (IS_ERR_OR_NULL(tbl2[cpu]))
+ break;
+ dev_pm_opp_put_supported_hw(tbl2[cpu]);
+ }
+
+ return ret;
+}
+
+static int qcom_cpufreq_remove(struct platform_device *pdev)
+{
+ platform_device_unregister(cpufreq_dt_pdev);
+ return 0;
+}
+
+static struct platform_driver qcom_cpufreq_driver = {
+ .probe = qcom_cpufreq_probe,
+ .remove = qcom_cpufreq_remove,
+ .driver = {
+ .name = "qcom-cpufreq",
+ },
+};
+
+static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
+ { .compatible = "qcom,apq8096",
+ .data = qcom_cpufreq_kryo_name_version},
+ { .compatible = "qcom,msm8996",
+ .data = qcom_cpufreq_kryo_name_version},
+ { .compatible = "qcom,ipq8064",
+ .data = qcom_cpufreq_krait_name_version },
+ { .compatible = "qcom,apq8064",
+ .data = qcom_cpufreq_krait_name_version },
+ { .compatible = "qcom,msm8974",
+ .data = qcom_cpufreq_krait_name_version },
+ { .compatible = "qcom,msm8960",
+ .data = qcom_cpufreq_krait_name_version },
+ {},
+};
+
+/*
+ * Since the driver depends on smem and nvmem drivers, which may
+ * return EPROBE_DEFER, all the real activity is done in the probe,
+ * which may be defered as well. The init here is only registering
+ * the driver and the platform device.
+ */
+static int __init qcom_cpufreq_init(void)
+{
+ struct device_node *np = of_find_node_by_path("/");
+ const struct of_device_id *match;
+ int ret;
+
+ if (!np)
+ return -ENODEV;
+
+ match = of_match_node(qcom_cpufreq_match_list, np);
+ of_node_put(np);
+ if (!match)
+ return -ENODEV;
+
+ ret = platform_driver_register(&qcom_cpufreq_driver);
+ if (unlikely(ret < 0))
+ return ret;
+
+ cpufreq_pdev = platform_device_register_data(NULL, "qcom-cpufreq",
+ -1, match, sizeof(*match));
+ ret = PTR_ERR_OR_ZERO(cpufreq_pdev);
+ if (0 == ret)
+ return 0;
+
+ platform_driver_unregister(&qcom_cpufreq_driver);
+ return ret;
+}
+module_init(qcom_cpufreq_init);
+
+static void __exit qcom_cpufreq_exit(void)
+{
+ platform_device_unregister(cpufreq_pdev);
+ platform_driver_unregister(&qcom_cpufreq_driver);
+}
+module_exit(qcom_cpufreq_exit);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. CPUfreq driver");
+MODULE_LICENSE("GPL v2");