diff options
author | Linaro CI <ci_notify@linaro.org> | 2019-03-26 07:26:48 +0000 |
---|---|---|
committer | Linaro CI <ci_notify@linaro.org> | 2019-03-26 07:26:48 +0000 |
commit | 50296a93cfd27862a43b3f2c5e4243574d6e9903 (patch) | |
tree | a790fe0f09136841d8cde3383cb499ccbaa5c24d | |
parent | a2ffe555ceb595aacfb0a952152ff240f81f07fd (diff) | |
parent | 1245d2153a0afeb073a1eefd2ab28ab3e7e14090 (diff) |
Merge remote-tracking branch 'tsens-thermal/integration/thermal-automerge' into integration-linux-qcomlt
# Conflicts:
# arch/arm64/boot/dts/qcom/msm8996.dtsi
-rw-r--r-- | Documentation/devicetree/bindings/thermal/qcom-tsens.txt | 14 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/msm8916.dtsi | 41 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/msm8996.dtsi | 174 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/msm8998.dtsi | 242 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/pms405.dtsi | 20 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/qcs404.dtsi | 272 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/sdm845.dtsi | 205 | ||||
-rw-r--r-- | drivers/thermal/qcom/Makefile | 4 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-8916.c | 105 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-8960.c | 84 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-common.c | 159 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-v0_1.c (renamed from drivers/thermal/qcom/tsens-8974.c) | 166 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-v1.c | 193 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-v2.c | 111 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens.c | 100 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens.h | 291 |
16 files changed, 1768 insertions, 413 deletions
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt index 1d9e8cf61018..673cc1831ee9 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt @@ -6,11 +6,14 @@ Required properties: - "qcom,msm8916-tsens" (MSM8916) - "qcom,msm8974-tsens" (MSM8974) - "qcom,msm8996-tsens" (MSM8996) + - "qcom,qcs404-tsens", "qcom,tsens-v1" (QCS404) - "qcom,msm8998-tsens", "qcom,tsens-v2" (MSM8998) - "qcom,sdm845-tsens", "qcom,tsens-v2" (SDM845) The generic "qcom,tsens-v2" property must be used as a fallback for any SoC with version 2 of the TSENS IP. MSM8996 is the only exception because the generic property did not exist when support was added. + Similarly, the generic "qcom,tsens-v1" property must be used as a fallback for + any SoC with version 1 of the TSENS IP. - reg: Address range of the thermal registers. New platforms containing v2.x.y of the TSENS IP must specify the SROT and TM @@ -39,3 +42,14 @@ tsens0: thermal-sensor@c263000 { #qcom,sensors = <13>; #thermal-sensor-cells = <1>; }; + +Example 3 (for any platform containing v1 of the TSENS IP): +tsens: thermal-sensor@4a9000 { + compatible = "qcom,qcs404-tsens", "qcom,tsens-v1"; + reg = <0x004a9000 0x1000>, /* TM */ + <0x004a8000 0x1000>; /* SROT */ + nvmem-cells = <&tsens_caldata>; + nvmem-cell-names = "calib"; + #qcom,sensors = <10>; + #thermal-sensor-cells = <1>; + }; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 5da0024523dd..2ce03a47c690 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -181,19 +181,19 @@ }; thermal-zones { - cpu-thermal0 { + cpu0_1-thermal { polling-delay-passive = <250>; polling-delay = <1000>; thermal-sensors = <&tsens 4>; trips { - cpu_alert0: trip0 { + cpu0_1_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit0: trip1 { + cpu0_1_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -202,7 +202,7 @@ cooling-maps { map0 { - trip = <&cpu_alert0>; + trip = <&cpu0_1_alert0>; cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, @@ -211,19 +211,19 @@ }; }; - cpu-thermal1 { + cpu2_3-thermal { polling-delay-passive = <250>; polling-delay = <1000>; thermal-sensors = <&tsens 3>; trips { - cpu_alert1: trip0 { + cpu2_3_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit1: trip1 { + cpu2_3_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -232,7 +232,7 @@ cooling-maps { map0 { - trip = <&cpu_alert1>; + trip = <&cpu2_3_alert0>; cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, @@ -248,12 +248,12 @@ thermal-sensors = <&tsens 2>; trips { - gpu_alert: trip0 { + gpu_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - gpu_crit: trip1 { + gpu_crit: gpu_crit { temperature = <95000>; hysteresis = <2000>; type = "critical"; @@ -268,18 +268,27 @@ thermal-sensors = <&tsens 1>; trips { - cam_alert: trip0 { + cam_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; - type = "passive"; + type = "hot"; }; - cam_crit: trip1 { - temperature = <95000>; + }; + }; + + modem-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 0>; + + trips { + modem_alert0: trip-point@0 { + temperature = <75000>; hysteresis = <2000>; - type = "critical"; + type = "hot"; }; }; - }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index f0adfd5062c2..ef7e3c5e375c 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -598,14 +598,14 @@ }; thermal-zones { - cpu-thermal0 { + cpu0-thermal { polling-delay-passive = <250>; polling-delay = <1000>; thermal-sensors = <&tsens0 3>; trips { - cpu_alert0: cpu_alert0 { + cpu0_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "active"; @@ -616,7 +616,7 @@ type = "passive"; }; - cpu_crit0: cpu_crit0 { + cpu0_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -635,14 +635,14 @@ }; }; - cpu-thermal1 { + cpu1-thermal { polling-delay-passive = <250>; polling-delay = <1000>; thermal-sensors = <&tsens0 5>; trips { - cpu_alert1: cpu_alert1 { + cpu1_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "active"; @@ -653,7 +653,7 @@ type = "passive"; }; - cpu_crit1: cpu_crit1 { + cpu1_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -672,14 +672,14 @@ }; }; - cpu-thermal2 { + cpu2-thermal { polling-delay-passive = <250>; polling-delay = <1000>; thermal-sensors = <&tsens0 8>; trips { - cpu_alert2: cpu_alert2 { + cpu2_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "active"; @@ -690,7 +690,7 @@ type = "passive"; }; - cpu_crit2: cpu_crit2 { + cpu2_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -708,14 +708,14 @@ }; }; - cpu-thermal3 { + cpu3-thermal { polling-delay-passive = <250>; polling-delay = <1000>; thermal-sensors = <&tsens0 10>; trips { - cpu_alert3: cpu_alert3 { + cpu3_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "active"; @@ -726,7 +726,7 @@ type = "passive"; }; - cpu_crit3: trip1 { + cpu3_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -743,6 +743,156 @@ }; }; }; + + gpu-thermal-top { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 6>; + + trips { + gpu1_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + gpu-thermal-bottom { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 7>; + + trips { + gpu2_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + m4m-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 1>; + + trips { + m4m_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + l3-or-venus-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 2>; + + trips { + l3_or_venus_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + cluster0-l2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 7>; + + trips { + cluster0_l2_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + cluster1-l2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 12>; + + trips { + cluster1_l2_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + camera-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 1>; + + trips { + camera_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + q6-dsp-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 2>; + + trips { + q6_dsp_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + mem-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 3>; + + trips { + mem_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + modemtx-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 4>; + + trips { + modemtx_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; }; timer { diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi index 3fd0769fe648..998017d4d847 100644 --- a/arch/arm64/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi @@ -78,7 +78,6 @@ compatible = "arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; - efficiency = <1024>; next-level-cache = <&L2_0>; L2_0: l2-cache { compatible = "arm,arch-cache"; @@ -97,7 +96,6 @@ compatible = "arm,armv8"; reg = <0x0 0x1>; enable-method = "psci"; - efficiency = <1024>; next-level-cache = <&L2_0>; L1_I_1: l1-icache { compatible = "arm,arch-cache"; @@ -112,7 +110,6 @@ compatible = "arm,armv8"; reg = <0x0 0x2>; enable-method = "psci"; - efficiency = <1024>; next-level-cache = <&L2_0>; L1_I_2: l1-icache { compatible = "arm,arch-cache"; @@ -127,7 +124,6 @@ compatible = "arm,armv8"; reg = <0x0 0x3>; enable-method = "psci"; - efficiency = <1024>; next-level-cache = <&L2_0>; L1_I_3: l1-icache { compatible = "arm,arch-cache"; @@ -142,7 +138,6 @@ compatible = "arm,armv8"; reg = <0x0 0x100>; enable-method = "psci"; - efficiency = <1536>; next-level-cache = <&L2_1>; L2_1: l2-cache { compatible = "arm,arch-cache"; @@ -161,7 +156,6 @@ compatible = "arm,armv8"; reg = <0x0 0x101>; enable-method = "psci"; - efficiency = <1536>; next-level-cache = <&L2_1>; L1_I_101: l1-icache { compatible = "arm,arch-cache"; @@ -176,7 +170,6 @@ compatible = "arm,armv8"; reg = <0x0 0x102>; enable-method = "psci"; - efficiency = <1536>; next-level-cache = <&L2_1>; L1_I_102: l1-icache { compatible = "arm,arch-cache"; @@ -191,7 +184,6 @@ compatible = "arm,armv8"; reg = <0x0 0x103>; enable-method = "psci"; - efficiency = <1536>; next-level-cache = <&L2_1>; L1_I_103: l1-icache { compatible = "arm,arch-cache"; @@ -346,20 +338,20 @@ }; thermal-zones { - cpu-thermal0 { + cpu0-thermal { polling-delay-passive = <250>; polling-delay = <1000>; - thermal-sensors = <&tsens0 6>; + thermal-sensors = <&tsens0 1>; trips { - cpu_alert0: trip0 { + cpu0_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit0: trip1 { + cpu0_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -367,20 +359,20 @@ }; }; - cpu-thermal1 { + cpu1-thermal { polling-delay-passive = <250>; polling-delay = <1000>; - thermal-sensors = <&tsens0 7>; + thermal-sensors = <&tsens0 2>; trips { - cpu_alert1: trip0 { + cpu1_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit1: trip1 { + cpu1_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -388,20 +380,20 @@ }; }; - cpu-thermal2 { + cpu2-thermal { polling-delay-passive = <250>; polling-delay = <1000>; - thermal-sensors = <&tsens0 8>; + thermal-sensors = <&tsens0 3>; trips { - cpu_alert2: trip0 { + cpu2_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit2: trip1 { + cpu2_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -409,20 +401,20 @@ }; }; - cpu-thermal3 { + cpu3-thermal { polling-delay-passive = <250>; polling-delay = <1000>; - thermal-sensors = <&tsens0 9>; + thermal-sensors = <&tsens0 4>; trips { - cpu_alert3: trip0 { + cpu3_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit3: trip1 { + cpu3_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -430,20 +422,20 @@ }; }; - cpu-thermal4 { + cpu4-thermal { polling-delay-passive = <250>; polling-delay = <1000>; - thermal-sensors = <&tsens0 10>; + thermal-sensors = <&tsens0 7>; trips { - cpu_alert4: trip0 { + cpu4_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit4: trip1 { + cpu4_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -451,20 +443,20 @@ }; }; - cpu-thermal5 { + cpu5-thermal { polling-delay-passive = <250>; polling-delay = <1000>; - thermal-sensors = <&tsens0 11>; + thermal-sensors = <&tsens0 8>; trips { - cpu_alert5: trip0 { + cpu5_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit5: trip1 { + cpu5_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -472,20 +464,20 @@ }; }; - cpu-thermal6 { + cpu6-thermal { polling-delay-passive = <250>; polling-delay = <1000>; - thermal-sensors = <&tsens1 0>; + thermal-sensors = <&tsens0 9>; trips { - cpu_alert6: trip0 { + cpu6_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit6: trip1 { + cpu6_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -493,20 +485,20 @@ }; }; - cpu-thermal7 { + cpu7-thermal { polling-delay-passive = <250>; polling-delay = <1000>; - thermal-sensors = <&tsens1 1>; + thermal-sensors = <&tsens0 10>; trips { - cpu_alert7: trip0 { + cpu7_alert0: trip-point@0 { temperature = <75000>; hysteresis = <2000>; type = "passive"; }; - cpu_crit7: trip1 { + cpu7_crit: cpu_crit { temperature = <110000>; hysteresis = <2000>; type = "critical"; @@ -514,11 +506,169 @@ }; }; - gpu-thermal { + gpu-thermal-bottom { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 12>; + + trips { + gpu1_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + gpu-thermal-top { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 13>; + + trips { + gpu2_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + cluster0-mhm-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 5>; + + trips { + cluster0_mhm_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + cluster1-mhm-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 6>; + + trips { + cluster1_mhm_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + cluster1-l2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 11>; + + trips { + cluster1_l2_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + modem-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 1>; + + trips { + modem_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + mem-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 2>; + + trips { + mem_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + wlan-thermal { polling-delay-passive = <250>; polling-delay = <1000>; thermal-sensors = <&tsens1 3>; + + trips { + wlan_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + q6-dsp-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 4>; + + trips { + q6_dsp_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + camera-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 5>; + + trips { + camera_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + multimedia-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 6>; + + trips { + multimedia_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; }; }; @@ -590,17 +740,19 @@ cell-index = <0>; }; - tsens0: thermal@10aa000 { + tsens0: thermal@10ab000 { compatible = "qcom,msm8998-tsens", "qcom,tsens-v2"; - reg = <0x10aa000 0x2000>; + reg = <0x10ab000 0x1000>, /* TM */ + <0x10aa000 0x1000>; /* SROT */ #qcom,sensors = <12>; #thermal-sensor-cells = <1>; }; - tsens1: thermal@10ad000 { + tsens1: thermal@10ae000 { compatible = "qcom,msm8998-tsens", "qcom,tsens-v2"; - reg = <0x10ad000 0x2000>; + reg = <0x10ae000 0x1000>, /* TM */ + <0x10ad000 0x1000>; /* SROT */ #qcom,sensors = <8>; #thermal-sensor-cells = <1>; diff --git a/arch/arm64/boot/dts/qcom/pms405.dtsi b/arch/arm64/boot/dts/qcom/pms405.dtsi index 1bb836d1e8aa..37c8bea24796 100644 --- a/arch/arm64/boot/dts/qcom/pms405.dtsi +++ b/arch/arm64/boot/dts/qcom/pms405.dtsi @@ -98,7 +98,7 @@ qcom,pre-scaling = <1 1>; }; - vph_pwr { + pon_1: vph_pwr { reg = <ADC5_VPH_PWR>; qcom,pre-scaling = <1 3>; }; @@ -108,18 +108,24 @@ qcom,pre-scaling = <1 1>; }; - xo_therm_100k_pu { - reg = <ADC5_XO_THERM_100K_PU>; + pa_therm1: thermistor1 { + reg = <ADC5_AMUX_THM1_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time = <200>; qcom,pre-scaling = <1 1>; }; - amux_thm1_100k_pu { - reg = <ADC5_AMUX_THM1_100K_PU>; + pa_therm3: thermistor3 { + reg = <ADC5_AMUX_THM3_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time = <200>; qcom,pre-scaling = <1 1>; }; - amux_thm3_100k_pu { - reg = <ADC5_AMUX_THM3_100K_PU>; + xo_therm: xo_temp { + reg = <ADC5_XO_THERM_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time = <200>; qcom,pre-scaling = <1 1>; }; }; diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi index e8fd26633d57..2423c816b98d 100644 --- a/arch/arm64/boot/dts/qcom/qcs404.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi @@ -4,6 +4,7 @@ #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/clock/qcom,gcc-qcs404.h> #include <dt-bindings/clock/qcom,rpmcc.h> +#include <dt-bindings/thermal/thermal.h> / { interrupt-parent = <&intc>; @@ -31,6 +32,7 @@ reg = <0x100>; enable-method = "psci"; next-level-cache = <&L2_0>; + #cooling-cells= <2>; }; CPU1: cpu@101 { @@ -39,6 +41,7 @@ reg = <0x101>; enable-method = "psci"; next-level-cache = <&L2_0>; + #cooling-cells= <2>; }; CPU2: cpu@102 { @@ -47,6 +50,7 @@ reg = <0x102>; enable-method = "psci"; next-level-cache = <&L2_0>; + #cooling-cells= <2>; }; CPU3: cpu@103 { @@ -55,6 +59,7 @@ reg = <0x103>; enable-method = "psci"; next-level-cache = <&L2_0>; + #cooling-cells= <2>; }; L2_0: l2-cache { @@ -259,6 +264,16 @@ reg = <0x00060000 0x6000>; }; + qfprom: qfprom@a4000 { + compatible = "qcom,qfprom"; + reg = <0x000a4000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + tsens_caldata: caldata@d0 { + reg = <0x1f8 0x14>; + }; + }; + rng: rng@e3000 { compatible = "qcom,prng-ee"; reg = <0x000e3000 0x1000>; @@ -266,6 +281,16 @@ clock-names = "core"; }; + tsens: thermal-sensor@4a9000 { + compatible = "qcom,qcs404-tsens", "qcom,tsens-v1"; + reg = <0x004a9000 0x1000>, /* TM */ + <0x004a8000 0x1000>; /* SROT */ + nvmem-cells = <&tsens_caldata>; + nvmem-cell-names = "calib"; + #qcom,sensors = <10>; + #thermal-sensor-cells = <1>; + }; + tlmm: pinctrl@1000000 { compatible = "qcom,qcs404-pinctrl"; reg = <0x01000000 0x200000>, @@ -846,4 +871,251 @@ #interrupt-cells = <2>; }; }; + + thermal-zones { + aoss-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 0>; + + trips { + aoss_alert0: trip-point@0 { + temperature = <105000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + q6-hvx-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 1>; + + trips { + q6_hvx_alert0: trip-point@0 { + temperature = <105000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + lpass-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 2>; + + trips { + lpass_alert0: trip-point@0 { + temperature = <105000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + wlan-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 3>; + + trips { + wlan_alert0: trip-point@0 { + temperature = <105000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + cluster-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 4>; + + trips { + cluster_alert0: trip-point@0 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + cluster_alert1: trip-point@1 { + temperature = <105000>; + hysteresis = <2000>; + type = "passive"; + }; + cluster_crit: cluster_crit { + temperature = <120000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + cooling-maps { + map0 { + trip = <&cluster_alert1>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu0-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 5>; + + trips { + cpu0_alert0: trip-point@0 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + cpu0_alert1: trip-point@1 { + temperature = <105000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu0_crit: cpu_crit { + temperature = <120000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + cooling-maps { + map0 { + trip = <&cpu0_alert1>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 6>; + + trips { + cpu1_alert0: trip-point@0 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + cpu1_alert1: trip-point@1 { + temperature = <105000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu1_crit: cpu_crit { + temperature = <120000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + cooling-maps { + map0 { + trip = <&cpu1_alert1>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 7>; + + trips { + cpu2_alert0: trip-point@0 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + cpu2_alert1: trip-point@1 { + temperature = <105000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu2_crit: cpu_crit { + temperature = <120000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + cooling-maps { + map0 { + trip = <&cpu2_alert1>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 8>; + + trips { + cpu3_alert0: trip-point@0 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + cpu3_alert1: trip-point@1 { + temperature = <105000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu3_crit: cpu_crit { + temperature = <120000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + cooling-maps { + map0 { + trip = <&cpu3_alert1>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + gpu-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 9>; + + trips { + gpu_alert0: trip-point@0 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index c6689f1bd035..48605c194a32 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -3035,5 +3035,210 @@ }; }; }; + + aoss0-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 0>; + + trips { + aoss0_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + cluster0-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 5>; + + trips { + cluster0_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + cluster0_crit: cluster0_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cluster1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 6>; + + trips { + cluster1_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + cluster1_crit: cluster1_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + gpu-thermal-top { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 11>; + + trips { + gpu1_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + gpu-thermal-bottom { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 12>; + + trips { + gpu2_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + aoss1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 0>; + + trips { + aoss1_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + q6-modem-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 1>; + + trips { + q6_modem_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + mem-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 2>; + + trips { + mem_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + wlan-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 3>; + + trips { + wlan_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + q6-hvx-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 4>; + + trips { + q6_hvx_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + camera-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 5>; + + trips { + camera_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + video-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 6>; + + trips { + video_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + modem-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 7>; + + trips { + modem_alert0: trip-point@0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; }; }; diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile index 717a08600bb5..fc6fe50cdde4 100644 --- a/drivers/thermal/qcom/Makefile +++ b/drivers/thermal/qcom/Makefile @@ -1,3 +1,5 @@ obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o -qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o + +qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o \ + tsens-8960.o tsens-v2.o tsens-v1.o obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-8916.c deleted file mode 100644 index c6dd620ac029..000000000000 --- a/drivers/thermal/qcom/tsens-8916.c +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. - */ - -#include <linux/platform_device.h> -#include "tsens.h" - -/* eeprom layout data for 8916 */ -#define BASE0_MASK 0x0000007f -#define BASE1_MASK 0xfe000000 -#define BASE0_SHIFT 0 -#define BASE1_SHIFT 25 - -#define S0_P1_MASK 0x00000f80 -#define S1_P1_MASK 0x003e0000 -#define S2_P1_MASK 0xf8000000 -#define S3_P1_MASK 0x000003e0 -#define S4_P1_MASK 0x000f8000 - -#define S0_P2_MASK 0x0001f000 -#define S1_P2_MASK 0x07c00000 -#define S2_P2_MASK 0x0000001f -#define S3_P2_MASK 0x00007c00 -#define S4_P2_MASK 0x01f00000 - -#define S0_P1_SHIFT 7 -#define S1_P1_SHIFT 17 -#define S2_P1_SHIFT 27 -#define S3_P1_SHIFT 5 -#define S4_P1_SHIFT 15 - -#define S0_P2_SHIFT 12 -#define S1_P2_SHIFT 22 -#define S2_P2_SHIFT 0 -#define S3_P2_SHIFT 10 -#define S4_P2_SHIFT 20 - -#define CAL_SEL_MASK 0xe0000000 -#define CAL_SEL_SHIFT 29 - -static int calibrate_8916(struct tsens_device *tmdev) -{ - int base0 = 0, base1 = 0, i; - u32 p1[5], p2[5]; - int mode = 0; - u32 *qfprom_cdata, *qfprom_csel; - - qfprom_cdata = (u32 *)qfprom_read(tmdev->dev, "calib"); - if (IS_ERR(qfprom_cdata)) - return PTR_ERR(qfprom_cdata); - - qfprom_csel = (u32 *)qfprom_read(tmdev->dev, "calib_sel"); - if (IS_ERR(qfprom_csel)) - return PTR_ERR(qfprom_csel); - - mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT; - dev_dbg(tmdev->dev, "calibration mode is %d\n", mode); - - switch (mode) { - case TWO_PT_CALIB: - base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT; - p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT; - p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT; - p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT; - p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT; - p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT; - for (i = 0; i < tmdev->num_sensors; i++) - p2[i] = ((base1 + p2[i]) << 3); - /* Fall through */ - case ONE_PT_CALIB2: - base0 = (qfprom_cdata[0] & BASE0_MASK); - p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT; - p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT; - p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT; - p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT; - p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT; - for (i = 0; i < tmdev->num_sensors; i++) - p1[i] = (((base0) + p1[i]) << 3); - break; - default: - for (i = 0; i < tmdev->num_sensors; i++) { - p1[i] = 500; - p2[i] = 780; - } - break; - } - - compute_intercept_slope(tmdev, p1, p2, mode); - - return 0; -} - -static const struct tsens_ops ops_8916 = { - .init = init_common, - .calibrate = calibrate_8916, - .get_temp = get_temp_common, -}; - -const struct tsens_data data_8916 = { - .num_sensors = 5, - .ops = &ops_8916, - .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 }, - .hw_ids = (unsigned int []){0, 1, 2, 4, 5 }, -}; diff --git a/drivers/thermal/qcom/tsens-8960.c b/drivers/thermal/qcom/tsens-8960.c index 0f0adb302a7b..8d9b721dadb6 100644 --- a/drivers/thermal/qcom/tsens-8960.c +++ b/drivers/thermal/qcom/tsens-8960.c @@ -56,21 +56,21 @@ #define TRDY_MASK BIT(7) #define TIMEOUT_US 100 -static int suspend_8960(struct tsens_device *tmdev) +static int suspend_8960(struct tsens_priv *priv) { int ret; unsigned int mask; - struct regmap *map = tmdev->tm_map; + struct regmap *map = priv->tm_map; - ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold); + ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold); if (ret) return ret; - ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control); + ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control); if (ret) return ret; - if (tmdev->num_sensors > 1) + if (priv->num_sensors > 1) mask = SLP_CLK_ENA | EN; else mask = SLP_CLK_ENA_8660 | EN; @@ -82,10 +82,10 @@ static int suspend_8960(struct tsens_device *tmdev) return 0; } -static int resume_8960(struct tsens_device *tmdev) +static int resume_8960(struct tsens_priv *priv) { int ret; - struct regmap *map = tmdev->tm_map; + struct regmap *map = priv->tm_map; ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST); if (ret) @@ -95,80 +95,80 @@ static int resume_8960(struct tsens_device *tmdev) * Separate CONFIG restore is not needed only for 8660 as * config is part of CTRL Addr and its restored as such */ - if (tmdev->num_sensors > 1) { + if (priv->num_sensors > 1) { ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG); if (ret) return ret; } - ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold); + ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold); if (ret) return ret; - ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control); + ret = regmap_write(map, CNTL_ADDR, priv->ctx.control); if (ret) return ret; return 0; } -static int enable_8960(struct tsens_device *tmdev, int id) +static int enable_8960(struct tsens_priv *priv, int id) { int ret; u32 reg, mask; - ret = regmap_read(tmdev->tm_map, CNTL_ADDR, ®); + ret = regmap_read(priv->tm_map, CNTL_ADDR, ®); if (ret) return ret; mask = BIT(id + SENSOR0_SHIFT); - ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg | SW_RST); + ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST); if (ret) return ret; - if (tmdev->num_sensors > 1) + if (priv->num_sensors > 1) reg |= mask | SLP_CLK_ENA | EN; else reg |= mask | SLP_CLK_ENA_8660 | EN; - ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg); + ret = regmap_write(priv->tm_map, CNTL_ADDR, reg); if (ret) return ret; return 0; } -static void disable_8960(struct tsens_device *tmdev) +static void disable_8960(struct tsens_priv *priv) { int ret; u32 reg_cntl; u32 mask; - mask = GENMASK(tmdev->num_sensors - 1, 0); + mask = GENMASK(priv->num_sensors - 1, 0); mask <<= SENSOR0_SHIFT; mask |= EN; - ret = regmap_read(tmdev->tm_map, CNTL_ADDR, ®_cntl); + ret = regmap_read(priv->tm_map, CNTL_ADDR, ®_cntl); if (ret) return; reg_cntl &= ~mask; - if (tmdev->num_sensors > 1) + if (priv->num_sensors > 1) reg_cntl &= ~SLP_CLK_ENA; else reg_cntl &= ~SLP_CLK_ENA_8660; - regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl); + regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl); } -static int init_8960(struct tsens_device *tmdev) +static int init_8960(struct tsens_priv *priv) { int ret, i; u32 reg_cntl; - tmdev->tm_map = dev_get_regmap(tmdev->dev, NULL); - if (!tmdev->tm_map) + priv->tm_map = dev_get_regmap(priv->dev, NULL); + if (!priv->tm_map) return -ENODEV; /* @@ -177,21 +177,21 @@ static int init_8960(struct tsens_device *tmdev) * but the control registers stay in the same place, i.e * directly after the first 5 status registers. */ - for (i = 0; i < tmdev->num_sensors; i++) { + for (i = 0; i < priv->num_sensors; i++) { if (i >= 5) - tmdev->sensor[i].status = S0_STATUS_ADDR + 40; - tmdev->sensor[i].status += i * 4; + priv->sensor[i].status = S0_STATUS_ADDR + 40; + priv->sensor[i].status += i * 4; } reg_cntl = SW_RST; - ret = regmap_update_bits(tmdev->tm_map, CNTL_ADDR, SW_RST, reg_cntl); + ret = regmap_update_bits(priv->tm_map, CNTL_ADDR, SW_RST, reg_cntl); if (ret) return ret; - if (tmdev->num_sensors > 1) { + if (priv->num_sensors > 1) { reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18); reg_cntl &= ~SW_RST; - ret = regmap_update_bits(tmdev->tm_map, CONFIG_ADDR, + ret = regmap_update_bits(priv->tm_map, CONFIG_ADDR, CONFIG_MASK, CONFIG); } else { reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16); @@ -199,30 +199,30 @@ static int init_8960(struct tsens_device *tmdev) reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660; } - reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT; - ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl); + reg_cntl |= GENMASK(priv->num_sensors - 1, 0) << SENSOR0_SHIFT; + ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl); if (ret) return ret; reg_cntl |= EN; - ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl); + ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl); if (ret) return ret; return 0; } -static int calibrate_8960(struct tsens_device *tmdev) +static int calibrate_8960(struct tsens_priv *priv) { int i; char *data; - ssize_t num_read = tmdev->num_sensors; - struct tsens_sensor *s = tmdev->sensor; + ssize_t num_read = priv->num_sensors; + struct tsens_sensor *s = priv->sensor; - data = qfprom_read(tmdev->dev, "calib"); + data = qfprom_read(priv->dev, "calib"); if (IS_ERR(data)) - data = qfprom_read(tmdev->dev, "calib_backup"); + data = qfprom_read(priv->dev, "calib_backup"); if (IS_ERR(data)) return PTR_ERR(data); @@ -243,21 +243,21 @@ static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s) return adc_code * slope + offset; } -static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp) +static int get_temp_8960(struct tsens_priv *priv, int id, int *temp) { int ret; u32 code, trdy; - const struct tsens_sensor *s = &tmdev->sensor[id]; + const struct tsens_sensor *s = &priv->sensor[id]; unsigned long timeout; timeout = jiffies + usecs_to_jiffies(TIMEOUT_US); do { - ret = regmap_read(tmdev->tm_map, INT_STATUS_ADDR, &trdy); + ret = regmap_read(priv->tm_map, INT_STATUS_ADDR, &trdy); if (ret) return ret; if (!(trdy & TRDY_MASK)) continue; - ret = regmap_read(tmdev->tm_map, s->status, &code); + ret = regmap_read(priv->tm_map, s->status, &code); if (ret) return ret; *temp = code_to_mdegC(code, s); @@ -277,7 +277,7 @@ static const struct tsens_ops ops_8960 = { .resume = resume_8960, }; -const struct tsens_data data_8960 = { +const struct tsens_plat_data data_8960 = { .num_sensors = 11, .ops = &ops_8960, }; diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c index f80c73f11740..928e8e81ba69 100644 --- a/drivers/thermal/qcom/tsens-common.c +++ b/drivers/thermal/qcom/tsens-common.c @@ -12,18 +12,6 @@ #include <linux/regmap.h> #include "tsens.h" -/* SROT */ -#define TSENS_EN BIT(0) - -/* TM */ -#define STATUS_OFFSET 0x30 -#define SN_ADDR_OFFSET 0x4 -#define SN_ST_TEMP_MASK 0x3ff -#define CAL_DEGC_PT1 30 -#define CAL_DEGC_PT2 120 -#define SLOPE_FACTOR 1000 -#define SLOPE_DEFAULT 3200 - char *qfprom_read(struct device *dev, const char *cname) { struct nvmem_cell *cell; @@ -46,18 +34,18 @@ char *qfprom_read(struct device *dev, const char *cname) * and offset values are derived from tz->tzp->slope and tz->tzp->offset * resp. */ -void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1, +void compute_intercept_slope(struct tsens_priv *priv, u32 *p1, u32 *p2, u32 mode) { int i; int num, den; - for (i = 0; i < tmdev->num_sensors; i++) { - dev_dbg(tmdev->dev, + for (i = 0; i < priv->num_sensors; i++) { + dev_dbg(priv->dev, "sensor%d - data_point1:%#x data_point2:%#x\n", i, p1[i], p2[i]); - tmdev->sensor[i].slope = SLOPE_DEFAULT; + priv->sensor[i].slope = SLOPE_DEFAULT; if (mode == TWO_PT_CALIB) { /* * slope (m) = adc_code2 - adc_code1 (y2 - y1)/ @@ -66,16 +54,30 @@ void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1, num = p2[i] - p1[i]; num *= SLOPE_FACTOR; den = CAL_DEGC_PT2 - CAL_DEGC_PT1; - tmdev->sensor[i].slope = num / den; + priv->sensor[i].slope = num / den; } - tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) - + priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) - (CAL_DEGC_PT1 * - tmdev->sensor[i].slope); - dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset); + priv->sensor[i].slope); + dev_dbg(priv->dev, "offset:%d\n", priv->sensor[i].offset); } } +bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id) +{ + u32 val; + int ret; + + if ((hw_id > (priv->num_sensors - 1)) || (hw_id < 0)) + return -EINVAL; + ret = regmap_field_read(priv->rf[SENSOR_EN], &val); + if (ret) + return ret; + + return val & (1 << hw_id); +} + static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s) { int degc, num, den; @@ -95,18 +97,54 @@ static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s) return degc; } -int get_temp_common(struct tsens_device *tmdev, int id, int *temp) +int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp) { - struct tsens_sensor *s = &tmdev->sensor[id]; - u32 code; - unsigned int status_reg; + struct tsens_sensor *s = &priv->sensor[i]; + u32 temp_idx = LAST_TEMP_0 + s->hw_id; + u32 valid_idx = VALID_0 + s->hw_id; + u32 last_temp = 0, valid, mask; + int ret; + + ret = regmap_field_read(priv->rf[valid_idx], &valid); + if (ret) + return ret; + while (!valid) { + /* Valid bit is 0 for 6 AHB clock cycles. + * At 19.2MHz, 1 AHB clock is ~60ns. + * We should enter this loop very, very rarely. + */ + ndelay(400); + ret = regmap_field_read(priv->rf[valid_idx], &valid); + if (ret) + return ret; + } + + /* Valid bit is set, OK to read the temperature */ + ret = regmap_field_read(priv->rf[temp_idx], &last_temp); + if (ret) + return ret; + + if (priv->feat->adc) { + /* Convert temperature from ADC code to milliCelsius */ + *temp = code_to_degc(last_temp, s) * 1000; + } else { + mask = GENMASK(priv->fields[LAST_TEMP_0].msb, + priv->fields[LAST_TEMP_0].lsb); + /* Convert temperature from deciCelsius to milliCelsius */ + *temp = sign_extend32(last_temp, fls(mask) - 1) * 100; + } + + return 0; +} + +int get_temp_common(struct tsens_priv *priv, int i, int *temp) +{ + struct tsens_sensor *s = &priv->sensor[i]; int last_temp = 0, ret; - status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * SN_ADDR_OFFSET; - ret = regmap_read(tmdev->tm_map, status_reg, &code); + ret = regmap_field_read(priv->rf[LAST_TEMP_0 + s->hw_id], &last_temp); if (ret) return ret; - last_temp = code & SN_ST_TEMP_MASK; *temp = code_to_degc(last_temp, s) * 1000; @@ -127,21 +165,21 @@ static const struct regmap_config tsens_srot_config = { .reg_stride = 4, }; -int __init init_common(struct tsens_device *tmdev) +int __init init_common(struct tsens_priv *priv) { void __iomem *tm_base, *srot_base; + struct device *dev = priv->dev; struct resource *res; - u32 code; - int ret; - struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node); - u16 ctrl_offset = tmdev->reg_offsets[SROT_CTRL_OFFSET]; + u32 enabled; + int ret, i, j; + struct platform_device *op = of_find_device_by_node(priv->dev->of_node); if (!op) return -EINVAL; if (op->num_resources > 1) { /* DT with separate SROT and TM address space */ - tmdev->tm_offset = 0; + priv->tm_offset = 0; res = platform_get_resource(op, IORESOURCE_MEM, 1); srot_base = devm_ioremap_resource(&op->dev, res); if (IS_ERR(srot_base)) { @@ -149,16 +187,15 @@ int __init init_common(struct tsens_device *tmdev) goto err_put_device; } - tmdev->srot_map = devm_regmap_init_mmio(tmdev->dev, srot_base, + priv->srot_map = devm_regmap_init_mmio(dev, srot_base, &tsens_srot_config); - if (IS_ERR(tmdev->srot_map)) { - ret = PTR_ERR(tmdev->srot_map); + if (IS_ERR(priv->srot_map)) { + ret = PTR_ERR(priv->srot_map); goto err_put_device; } - } else { /* old DTs where SROT and TM were in a contiguous 2K block */ - tmdev->tm_offset = 0x1000; + priv->tm_offset = 0x1000; } res = platform_get_resource(op, IORESOURCE_MEM, 0); @@ -168,19 +205,47 @@ int __init init_common(struct tsens_device *tmdev) goto err_put_device; } - tmdev->tm_map = devm_regmap_init_mmio(tmdev->dev, tm_base, &tsens_config); - if (IS_ERR(tmdev->tm_map)) { - ret = PTR_ERR(tmdev->tm_map); + priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config); + if (IS_ERR(priv->tm_map)) { + ret = PTR_ERR(priv->tm_map); goto err_put_device; } - if (tmdev->srot_map) { - ret = regmap_read(tmdev->srot_map, ctrl_offset, &code); - if (ret) + priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map, + priv->fields[TSENS_EN]); + if (IS_ERR(priv->rf[TSENS_EN])) { + ret = PTR_ERR(priv->rf[TSENS_EN]); + goto err_put_device; + } + ret = regmap_field_read(priv->rf[TSENS_EN], &enabled); + if (ret) + goto err_put_device; + if (!enabled) { + dev_err(dev, "tsens device is not enabled\n"); + ret = -ENODEV; + goto err_put_device; + } + + priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map, + priv->fields[SENSOR_EN]); + if (IS_ERR(priv->rf[SENSOR_EN])) { + ret = PTR_ERR(priv->rf[SENSOR_EN]); + goto err_put_device; + } + /* now alloc regmap_fields in tm_map */ + for (i = 0, j = LAST_TEMP_0; i < priv->feat->max_sensors; i++, j++) { + priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map, + priv->fields[j]); + if (IS_ERR(priv->rf[j])) { + ret = PTR_ERR(priv->rf[j]); goto err_put_device; - if (!(code & TSENS_EN)) { - dev_err(tmdev->dev, "tsens device is not enabled\n"); - ret = -ENODEV; + } + } + for (i = 0, j = VALID_0; i < priv->feat->max_sensors; i++, j++) { + priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map, + priv->fields[j]); + if (IS_ERR(priv->rf[j])) { + ret = PTR_ERR(priv->rf[j]); goto err_put_device; } } diff --git a/drivers/thermal/qcom/tsens-8974.c b/drivers/thermal/qcom/tsens-v0_1.c index 3d3fda3d731b..b3a63d7b19ea 100644 --- a/drivers/thermal/qcom/tsens-8974.c +++ b/drivers/thermal/qcom/tsens-v0_1.c @@ -6,6 +6,48 @@ #include <linux/platform_device.h> #include "tsens.h" +/* ----- SROT ------ */ +#define SROT_CTRL_OFF 0x0000 + +/* ----- TM ------ */ +#define TM_INT_EN_OFF 0x0000 +#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004 +#define TM_Sn_STATUS_OFF 0x0030 +#define TM_TRDY_OFF 0x005c + +/* eeprom layout data for 8916 */ +#define MSM8916_BASE0_MASK 0x0000007f +#define MSM8916_BASE1_MASK 0xfe000000 +#define MSM8916_BASE0_SHIFT 0 +#define MSM8916_BASE1_SHIFT 25 + +#define MSM8916_S0_P1_MASK 0x00000f80 +#define MSM8916_S1_P1_MASK 0x003e0000 +#define MSM8916_S2_P1_MASK 0xf8000000 +#define MSM8916_S3_P1_MASK 0x000003e0 +#define MSM8916_S4_P1_MASK 0x000f8000 + +#define MSM8916_S0_P2_MASK 0x0001f000 +#define MSM8916_S1_P2_MASK 0x07c00000 +#define MSM8916_S2_P2_MASK 0x0000001f +#define MSM8916_S3_P2_MASK 0x00007c00 +#define MSM8916_S4_P2_MASK 0x01f00000 + +#define MSM8916_S0_P1_SHIFT 7 +#define MSM8916_S1_P1_SHIFT 17 +#define MSM8916_S2_P1_SHIFT 27 +#define MSM8916_S3_P1_SHIFT 5 +#define MSM8916_S4_P1_SHIFT 15 + +#define MSM8916_S0_P2_SHIFT 12 +#define MSM8916_S1_P2_SHIFT 22 +#define MSM8916_S2_P2_SHIFT 0 +#define MSM8916_S3_P2_SHIFT 10 +#define MSM8916_S4_P2_SHIFT 20 + +#define MSM8916_CAL_SEL_MASK 0xe0000000 +#define MSM8916_CAL_SEL_SHIFT 29 + /* eeprom layout data for 8974 */ #define BASE1_MASK 0xff #define S0_P1_MASK 0x3f00 @@ -91,7 +133,59 @@ #define BIT_APPEND 0x3 -static int calibrate_8974(struct tsens_device *tmdev) +static int calibrate_8916(struct tsens_priv *priv) +{ + int base0 = 0, base1 = 0, i; + u32 p1[5], p2[5]; + int mode = 0; + u32 *qfprom_cdata, *qfprom_csel; + + qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); + if (IS_ERR(qfprom_cdata)) + return PTR_ERR(qfprom_cdata); + + qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel"); + if (IS_ERR(qfprom_csel)) + return PTR_ERR(qfprom_csel); + + mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT; + dev_dbg(priv->dev, "calibration mode is %d\n", mode); + + switch (mode) { + case TWO_PT_CALIB: + base1 = (qfprom_cdata[1] & MSM8916_BASE1_MASK) >> MSM8916_BASE1_SHIFT; + p2[0] = (qfprom_cdata[0] & MSM8916_S0_P2_MASK) >> MSM8916_S0_P2_SHIFT; + p2[1] = (qfprom_cdata[0] & MSM8916_S1_P2_MASK) >> MSM8916_S1_P2_SHIFT; + p2[2] = (qfprom_cdata[1] & MSM8916_S2_P2_MASK) >> MSM8916_S2_P2_SHIFT; + p2[3] = (qfprom_cdata[1] & MSM8916_S3_P2_MASK) >> MSM8916_S3_P2_SHIFT; + p2[4] = (qfprom_cdata[1] & MSM8916_S4_P2_MASK) >> MSM8916_S4_P2_SHIFT; + for (i = 0; i < priv->num_sensors; i++) + p2[i] = ((base1 + p2[i]) << 3); + /* Fall through */ + case ONE_PT_CALIB2: + base0 = (qfprom_cdata[0] & MSM8916_BASE0_MASK); + p1[0] = (qfprom_cdata[0] & MSM8916_S0_P1_MASK) >> MSM8916_S0_P1_SHIFT; + p1[1] = (qfprom_cdata[0] & MSM8916_S1_P1_MASK) >> MSM8916_S1_P1_SHIFT; + p1[2] = (qfprom_cdata[0] & MSM8916_S2_P1_MASK) >> MSM8916_S2_P1_SHIFT; + p1[3] = (qfprom_cdata[1] & MSM8916_S3_P1_MASK) >> MSM8916_S3_P1_SHIFT; + p1[4] = (qfprom_cdata[1] & MSM8916_S4_P1_MASK) >> MSM8916_S4_P1_SHIFT; + for (i = 0; i < priv->num_sensors; i++) + p1[i] = (((base0) + p1[i]) << 3); + break; + default: + for (i = 0; i < priv->num_sensors; i++) { + p1[i] = 500; + p2[i] = 780; + } + break; + } + + compute_intercept_slope(priv, p1, p2, mode); + + return 0; +} + +static int calibrate_8974(struct tsens_priv *priv) { int base1 = 0, base2 = 0, i; u32 p1[11], p2[11]; @@ -99,11 +193,11 @@ static int calibrate_8974(struct tsens_device *tmdev) u32 *calib, *bkp; u32 calib_redun_sel; - calib = (u32 *)qfprom_read(tmdev->dev, "calib"); + calib = (u32 *)qfprom_read(priv->dev, "calib"); if (IS_ERR(calib)) return PTR_ERR(calib); - bkp = (u32 *)qfprom_read(tmdev->dev, "calib_backup"); + bkp = (u32 *)qfprom_read(priv->dev, "calib_backup"); if (IS_ERR(bkp)) return PTR_ERR(bkp); @@ -184,25 +278,25 @@ static int calibrate_8974(struct tsens_device *tmdev) switch (mode) { case ONE_PT_CALIB: - for (i = 0; i < tmdev->num_sensors; i++) + for (i = 0; i < priv->num_sensors; i++) p1[i] += (base1 << 2) | BIT_APPEND; break; case TWO_PT_CALIB: - for (i = 0; i < tmdev->num_sensors; i++) { + for (i = 0; i < priv->num_sensors; i++) { p2[i] += base2; p2[i] <<= 2; p2[i] |= BIT_APPEND; } /* Fall through */ case ONE_PT_CALIB2: - for (i = 0; i < tmdev->num_sensors; i++) { + for (i = 0; i < priv->num_sensors; i++) { p1[i] += base1; p1[i] <<= 2; p1[i] |= BIT_APPEND; } break; default: - for (i = 0; i < tmdev->num_sensors; i++) + for (i = 0; i < priv->num_sensors; i++) p2[i] = 780; p1[0] = 502; p1[1] = 509; @@ -218,19 +312,71 @@ static int calibrate_8974(struct tsens_device *tmdev) break; } - compute_intercept_slope(tmdev, p1, p2, mode); + compute_intercept_slope(priv, p1, p2, mode); return 0; } +/* v0.1: 8916, 8974 */ + +const struct tsens_features tsens_v0_1_feat = { + .ver_major = VER_0_1, + .crit_int = 0, + .adc = 1, + .srot_split = 1, + .max_sensors = 11, +}; + +const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = { + /* ----- SROT ------ */ + /* No VERSION information */ + + /* CTRL_OFFSET */ + [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0), + [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1), + [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13), + + /* ----- TM ------ */ + /* INTERRUPT ENABLE */ + [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0), + + /* Sn_STATUS */ + REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9), + /* No VALID field on v0.1 */ + REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10), + REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11), + REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12), + /* No CRITICAL field on v0.1 */ + REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13), + + /* TRDY: 1=ready, 0=in progress */ + [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), +}; + +static const struct tsens_ops ops_8916 = { + .init = init_common, + .calibrate = calibrate_8916, + .get_temp = get_temp_common, +}; + +const struct tsens_plat_data data_8916 = { + .num_sensors = 5, + .ops = &ops_8916, + .hw_ids = (unsigned int []){0, 1, 2, 4, 5 }, + + .feat = &tsens_v0_1_feat, + .fields = tsens_v0_1_regfields, +}; + static const struct tsens_ops ops_8974 = { .init = init_common, .calibrate = calibrate_8974, .get_temp = get_temp_common, }; -const struct tsens_data data_8974 = { +const struct tsens_plat_data data_8974 = { .num_sensors = 11, .ops = &ops_8974, - .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 }, + .feat = &tsens_v0_1_feat, + .fields = tsens_v0_1_regfields, }; diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c new file mode 100644 index 000000000000..a1221efd1ddc --- /dev/null +++ b/drivers/thermal/qcom/tsens-v1.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include <linux/bitops.h> +#include <linux/regmap.h> +#include <linux/delay.h> +#include "tsens.h" + +/* ----- SROT ------ */ +#define SROT_HW_VER_OFF 0x0000 +#define SROT_CTRL_OFF 0x0004 + +/* ----- TM ------ */ +#define TM_INT_EN_OFF 0x0000 +#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004 +#define TM_Sn_STATUS_OFF 0x0044 +#define TM_TRDY_OFF 0x0084 + +/* eeprom layout data for qcs404/405 (v1) */ +#define BASE0_MASK 0x000007f8 +#define BASE1_MASK 0x0007f800 +#define BASE0_SHIFT 3 +#define BASE1_SHIFT 11 + +#define S0_P1_MASK 0x0000003f +#define S1_P1_MASK 0x0003f000 +#define S2_P1_MASK 0x3f000000 +#define S3_P1_MASK 0x000003f0 +#define S4_P1_MASK 0x003f0000 +#define S5_P1_MASK 0x0000003f +#define S6_P1_MASK 0x0003f000 +#define S7_P1_MASK 0x3f000000 +#define S8_P1_MASK 0x000003f0 +#define S9_P1_MASK 0x003f0000 + +#define S0_P2_MASK 0x00000fc0 +#define S1_P2_MASK 0x00fc0000 +#define S2_P2_MASK_1_0 0xc0000000 +#define S2_P2_MASK_5_2 0x0000000f +#define S3_P2_MASK 0x0000fc00 +#define S4_P2_MASK 0x0fc00000 +#define S5_P2_MASK 0x00000fc0 +#define S6_P2_MASK 0x00fc0000 +#define S7_P2_MASK_1_0 0xc0000000 +#define S7_P2_MASK_5_2 0x0000000f +#define S8_P2_MASK 0x0000fc00 +#define S9_P2_MASK 0x0fc00000 + +#define S0_P1_SHIFT 0 +#define S0_P2_SHIFT 6 +#define S1_P1_SHIFT 12 +#define S1_P2_SHIFT 18 +#define S2_P1_SHIFT 24 +#define S2_P2_SHIFT_1_0 30 + +#define S2_P2_SHIFT_5_2 0 +#define S3_P1_SHIFT 4 +#define S3_P2_SHIFT 10 +#define S4_P1_SHIFT 16 +#define S4_P2_SHIFT 22 + +#define S5_P1_SHIFT 0 +#define S5_P2_SHIFT 6 +#define S6_P1_SHIFT 12 +#define S6_P2_SHIFT 18 +#define S7_P1_SHIFT 24 +#define S7_P2_SHIFT_1_0 30 + +#define S7_P2_SHIFT_5_2 0 +#define S8_P1_SHIFT 4 +#define S8_P2_SHIFT 10 +#define S9_P1_SHIFT 16 +#define S9_P2_SHIFT 22 + +#define CAL_SEL_MASK 7 +#define CAL_SEL_SHIFT 0 + +static int calibrate_v1(struct tsens_priv *priv) +{ + u32 base0 = 0, base1 = 0; + u32 p1[10], p2[10]; + u32 mode = 0, lsb = 0, msb = 0; + u32 *qfprom_cdata; + int i; + + qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); + if (IS_ERR(qfprom_cdata)) + return PTR_ERR(qfprom_cdata); + + mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT; + dev_dbg(priv->dev, "calibration mode is %d\n", mode); + + switch (mode) { + case TWO_PT_CALIB: + base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT; + p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT; + p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT; + /* This value is split over two registers, 2 bits and 4 bits */ + lsb = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0; + msb = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2; + p2[2] = msb << 2 | lsb; + p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT; + p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT; + p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT; + p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT; + /* This value is split over two registers, 2 bits and 4 bits */ + lsb = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0; + msb = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2; + p2[7] = msb << 2 | lsb; + p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT; + p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT; + for (i = 0; i < priv->num_sensors; i++) + p2[i] = ((base1 + p2[i]) << 2); + /* Fall through */ + case ONE_PT_CALIB2: + base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT; + p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT; + p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT; + p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT; + p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT; + p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT; + p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT; + p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT; + p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT; + p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT; + p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT; + for (i = 0; i < priv->num_sensors; i++) + p1[i] = (((base0) + p1[i]) << 2); + break; + default: + for (i = 0; i < priv->num_sensors; i++) { + p1[i] = 500; + p2[i] = 780; + } + break; + } + + compute_intercept_slope(priv, p1, p2, mode); + + return 0; +} + +/* v1.x: qcs404,405 */ + +const struct tsens_features tsens_v1_feat = { + .ver_major = VER_1_X, + .crit_int = 0, + .adc = 1, + .srot_split = 1, + .max_sensors = 11, +}; + +const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = { + /* ----- SROT ------ */ + /* VERSION */ + [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31), + [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27), + [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15), + /* CTRL_OFFSET */ + [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0), + [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1), + [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13), + + /* ----- TM ------ */ + /* INTERRUPT ENABLE */ + [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0), + + /* Sn_STATUS */ + REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9), + REG_FIELD_FOR_EACH_SENSOR11(VALID, TM_Sn_STATUS_OFF, 14, 14), + REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10), + REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11), + REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12), + /* No CRITICAL field on v1.x */ + REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13), + + /* TRDY: 1=ready, 0=in progress */ + [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), +}; + +static const struct tsens_ops ops_generic_v1 = { + .init = init_common, + .calibrate = calibrate_v1, + .get_temp = get_temp_tsens_valid, +}; + +const struct tsens_plat_data data_tsens_v1 = { + .ops = &ops_generic_v1, + .feat = &tsens_v1_feat, + .fields = tsens_v1_regfields, +}; diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c index 381a212872bf..36fbfa6a471e 100644 --- a/drivers/thermal/qcom/tsens-v2.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -4,76 +4,81 @@ * Copyright (c) 2018, Linaro Limited */ -#include <linux/regmap.h> #include <linux/bitops.h> +#include <linux/regmap.h> #include "tsens.h" -#define STATUS_OFFSET 0xa0 -#define LAST_TEMP_MASK 0xfff -#define STATUS_VALID_BIT BIT(21) +/* ----- SROT ------ */ +#define SROT_HW_VER_OFF 0x0000 +#define SROT_CTRL_OFF 0x0004 + +/* ----- TM ------ */ +#define TM_INT_EN_OFF 0x0004 +#define TM_UPPER_LOWER_INT_STATUS_OFF 0x0008 +#define TM_UPPER_LOWER_INT_CLEAR_OFF 0x000c +#define TM_UPPER_LOWER_INT_MASK_OFF 0x0010 +#define TM_CRITICAL_INT_STATUS_OFF 0x0014 +#define TM_CRITICAL_INT_CLEAR_OFF 0x0018 +#define TM_CRITICAL_INT_MASK_OFF 0x001c +#define TM_Sn_UPPER_LOWER_THRESHOLD_OFF 0x0020 +#define TM_Sn_CRITICAL_THRESHOLD_OFF 0x0060 +#define TM_Sn_STATUS_OFF 0x00a0 +#define TM_TRDY_OFF 0x00e4 -static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp) -{ - struct tsens_sensor *s = &tmdev->sensor[id]; - u32 code; - unsigned int status_reg; - u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0; - int ret; +/* v2.x: 8996, 8998, sdm845 */ - status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4; - ret = regmap_read(tmdev->tm_map, status_reg, &code); - if (ret) - return ret; - last_temp = code & LAST_TEMP_MASK; - if (code & STATUS_VALID_BIT) - goto done; +const struct tsens_features tsens_v2_feat = { + .ver_major = VER_2_X, + .crit_int = 1, + .adc = 0, + .srot_split = 1, + .max_sensors = 16, +}; - /* Try a second time */ - ret = regmap_read(tmdev->tm_map, status_reg, &code); - if (ret) - return ret; - if (code & STATUS_VALID_BIT) { - last_temp = code & LAST_TEMP_MASK; - goto done; - } else { - last_temp2 = code & LAST_TEMP_MASK; - } +const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = { + /* ----- SROT ------ */ + /* VERSION */ + [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31), + [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27), + [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15), + /* CTRL_OFF */ + [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0), + [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1), + [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 18), - /* Try a third/last time */ - ret = regmap_read(tmdev->tm_map, status_reg, &code); - if (ret) - return ret; - if (code & STATUS_VALID_BIT) { - last_temp = code & LAST_TEMP_MASK; - goto done; - } else { - last_temp3 = code & LAST_TEMP_MASK; - } + /* ----- TM ------ */ + /* INTERRUPT ENABLE */ + /* v2 has separate enables for UPPER/LOWER/CRITICAL interrupts */ + [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 2), - if (last_temp == last_temp2) - last_temp = last_temp2; - else if (last_temp2 == last_temp3) - last_temp = last_temp3; -done: - /* Convert temperature from deciCelsius to milliCelsius */ - *temp = sign_extend32(last_temp, fls(LAST_TEMP_MASK) - 1) * 100; + /* Sn_STATUS */ + REG_FIELD_FOR_EACH_SENSOR16(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 11), + REG_FIELD_FOR_EACH_SENSOR16(VALID, TM_Sn_STATUS_OFF, 21, 21), + REG_FIELD_FOR_EACH_SENSOR16(MIN_STATUS, TM_Sn_STATUS_OFF, 16, 16), + REG_FIELD_FOR_EACH_SENSOR16(LOWER_STATUS, TM_Sn_STATUS_OFF, 17, 17), + REG_FIELD_FOR_EACH_SENSOR16(UPPER_STATUS, TM_Sn_STATUS_OFF, 18, 18), + REG_FIELD_FOR_EACH_SENSOR16(CRITICAL_STATUS, TM_Sn_STATUS_OFF, 19, 19), + REG_FIELD_FOR_EACH_SENSOR16(MAX_STATUS, TM_Sn_STATUS_OFF, 20, 20), - return 0; -} + /* TRDY: 1=ready, 0=in progress */ + [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), +}; static const struct tsens_ops ops_generic_v2 = { .init = init_common, - .get_temp = get_temp_tsens_v2, + .get_temp = get_temp_tsens_valid, }; -const struct tsens_data data_tsens_v2 = { - .ops = &ops_generic_v2, - .reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 }, +const struct tsens_plat_data data_tsens_v2 = { + .ops = &ops_generic_v2, + .feat = &tsens_v2_feat, + .fields = tsens_v2_regfields, }; /* Kept around for backward compatibility with old msm8996.dtsi */ -const struct tsens_data data_8996 = { +const struct tsens_plat_data data_8996 = { .num_sensors = 13, .ops = &ops_generic_v2, - .reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 }, + .feat = &tsens_v2_feat, + .fields = tsens_v2_regfields, }; diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index f1ec9bbe4717..36b0b52db524 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -15,38 +15,38 @@ static int tsens_get_temp(void *data, int *temp) { const struct tsens_sensor *s = data; - struct tsens_device *tmdev = s->tmdev; + struct tsens_priv *priv = s->priv; - return tmdev->ops->get_temp(tmdev, s->id, temp); + return priv->ops->get_temp(priv, s->id, temp); } -static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend) +static int tsens_get_trend(void *data, int trip, enum thermal_trend *trend) { - const struct tsens_sensor *s = p; - struct tsens_device *tmdev = s->tmdev; + const struct tsens_sensor *s = data; + struct tsens_priv *priv = s->priv; - if (tmdev->ops->get_trend) - return tmdev->ops->get_trend(tmdev, s->id, trend); + if (priv->ops->get_trend) + return priv->ops->get_trend(priv, s->id, trend); return -ENOTSUPP; } static int __maybe_unused tsens_suspend(struct device *dev) { - struct tsens_device *tmdev = dev_get_drvdata(dev); + struct tsens_priv *priv = dev_get_drvdata(dev); - if (tmdev->ops && tmdev->ops->suspend) - return tmdev->ops->suspend(tmdev); + if (priv->ops && priv->ops->suspend) + return priv->ops->suspend(priv); return 0; } static int __maybe_unused tsens_resume(struct device *dev) { - struct tsens_device *tmdev = dev_get_drvdata(dev); + struct tsens_priv *priv = dev_get_drvdata(dev); - if (tmdev->ops && tmdev->ops->resume) - return tmdev->ops->resume(tmdev); + if (priv->ops && priv->ops->resume) + return priv->ops->resume(priv); return 0; } @@ -64,6 +64,9 @@ static const struct of_device_id tsens_table[] = { .compatible = "qcom,msm8996-tsens", .data = &data_8996, }, { + .compatible = "qcom,tsens-v1", + .data = &data_tsens_v1, + }, { .compatible = "qcom,tsens-v2", .data = &data_tsens_v2, }, @@ -76,22 +79,27 @@ static const struct thermal_zone_of_device_ops tsens_of_ops = { .get_trend = tsens_get_trend, }; -static int tsens_register(struct tsens_device *tmdev) +static int tsens_register(struct tsens_priv *priv) { int i; struct thermal_zone_device *tzd; - for (i = 0; i < tmdev->num_sensors; i++) { - tmdev->sensor[i].tmdev = tmdev; - tmdev->sensor[i].id = i; - tzd = devm_thermal_zone_of_sensor_register(tmdev->dev, i, - &tmdev->sensor[i], + for (i = 0; i < priv->num_sensors; i++) { + if (!is_sensor_enabled(priv, priv->sensor[i].hw_id)) { + dev_err(priv->dev, "sensor %d: disabled\n", + priv->sensor[i].hw_id); + continue; + } + priv->sensor[i].priv = priv; + priv->sensor[i].id = i; + tzd = devm_thermal_zone_of_sensor_register(priv->dev, i, + &priv->sensor[i], &tsens_of_ops); if (IS_ERR(tzd)) continue; - tmdev->sensor[i].tzd = tzd; - if (tmdev->ops->enable) - tmdev->ops->enable(tmdev, i); + priv->sensor[i].tzd = tzd; + if (priv->ops->enable) + priv->ops->enable(priv, i); } return 0; } @@ -101,8 +109,8 @@ static int tsens_probe(struct platform_device *pdev) int ret, i; struct device *dev; struct device_node *np; - struct tsens_device *tmdev; - const struct tsens_data *data; + struct tsens_priv *priv; + const struct tsens_plat_data *data; const struct of_device_id *id; u32 num_sensors; @@ -129,55 +137,55 @@ static int tsens_probe(struct platform_device *pdev) return -EINVAL; } - tmdev = devm_kzalloc(dev, - struct_size(tmdev, sensor, num_sensors), + priv = devm_kzalloc(dev, + struct_size(priv, sensor, num_sensors), GFP_KERNEL); - if (!tmdev) + if (!priv) return -ENOMEM; - tmdev->dev = dev; - tmdev->num_sensors = num_sensors; - tmdev->ops = data->ops; - for (i = 0; i < tmdev->num_sensors; i++) { + priv->dev = dev; + priv->num_sensors = num_sensors; + priv->ops = data->ops; + for (i = 0; i < priv->num_sensors; i++) { if (data->hw_ids) - tmdev->sensor[i].hw_id = data->hw_ids[i]; + priv->sensor[i].hw_id = data->hw_ids[i]; else - tmdev->sensor[i].hw_id = i; - } - for (i = 0; i < REG_ARRAY_SIZE; i++) { - tmdev->reg_offsets[i] = data->reg_offsets[i]; + priv->sensor[i].hw_id = i; } + priv->feat = data->feat; + priv->fields = data->fields; - if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->get_temp) + if (!priv->ops || !priv->ops->init || !priv->ops->get_temp) return -EINVAL; - ret = tmdev->ops->init(tmdev); + ret = priv->ops->init(priv); if (ret < 0) { dev_err(dev, "tsens init failed\n"); return ret; } - if (tmdev->ops->calibrate) { - ret = tmdev->ops->calibrate(tmdev); + if (priv->ops->calibrate) { + ret = priv->ops->calibrate(priv); if (ret < 0) { - dev_err(dev, "tsens calibration failed\n"); + if (ret != -EPROBE_DEFER) + dev_err(dev, "tsens calibration failed\n"); return ret; } } - ret = tsens_register(tmdev); + ret = tsens_register(priv); - platform_set_drvdata(pdev, tmdev); + platform_set_drvdata(pdev, priv); return ret; } static int tsens_remove(struct platform_device *pdev) { - struct tsens_device *tmdev = platform_get_drvdata(pdev); + struct tsens_priv *priv = platform_get_drvdata(pdev); - if (tmdev->ops->disable) - tmdev->ops->disable(tmdev); + if (priv->ops->disable) + priv->ops->disable(priv); return 0; } diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 7b7feee5dc46..eefe3844fb4e 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -9,17 +9,39 @@ #define ONE_PT_CALIB 0x1 #define ONE_PT_CALIB2 0x2 #define TWO_PT_CALIB 0x3 +#define CAL_DEGC_PT1 30 +#define CAL_DEGC_PT2 120 +#define SLOPE_FACTOR 1000 +#define SLOPE_DEFAULT 3200 + #include <linux/thermal.h> +#include <linux/regmap.h> + +struct tsens_priv; -struct tsens_device; +enum tsens_ver { + VER_0_1 = 0, + VER_1_X, + VER_2_X, +}; +/** + * struct tsens_sensor - data for each sensor connected to the tsens device + * @priv: tsens device instance that this sensor is connected to + * @tzd: pointer to the thermal zone that this sensor is in + * @offset: offset of temperature adjustment curve + * @id: Sensor ID + * @hw_id: HW ID can be used in case of platform-specific IDs + * @slope: slope of temperature adjustment curve + * @status: 8960-specific variable to track 8960 and 8660 status register offset + */ struct tsens_sensor { - struct tsens_device *tmdev; + struct tsens_priv *priv; struct thermal_zone_device *tzd; int offset; - int id; - int hw_id; + unsigned int id; + unsigned int hw_id; int slope; u32 status; }; @@ -37,63 +59,274 @@ struct tsens_sensor { */ struct tsens_ops { /* mandatory callbacks */ - int (*init)(struct tsens_device *); - int (*calibrate)(struct tsens_device *); - int (*get_temp)(struct tsens_device *, int, int *); + int (*init)(struct tsens_priv *priv); + int (*calibrate)(struct tsens_priv *priv); + int (*get_temp)(struct tsens_priv *priv, int i, int *temp); /* optional callbacks */ - int (*enable)(struct tsens_device *, int); - void (*disable)(struct tsens_device *); - int (*suspend)(struct tsens_device *); - int (*resume)(struct tsens_device *); - int (*get_trend)(struct tsens_device *, int, enum thermal_trend *); + int (*enable)(struct tsens_priv *priv, int i); + void (*disable)(struct tsens_priv *priv); + int (*suspend)(struct tsens_priv *priv); + int (*resume)(struct tsens_priv *priv); + int (*get_trend)(struct tsens_priv *priv, int i, enum thermal_trend *trend); }; -enum reg_list { - SROT_CTRL_OFFSET, +#define REG_FIELD_FOR_EACH_SENSOR11(_name, _offset, _startbit, _stopbit) \ + [_name##_##0] = REG_FIELD(_offset, _startbit, _stopbit), \ + [_name##_##1] = REG_FIELD(_offset + 4, _startbit, _stopbit), \ + [_name##_##2] = REG_FIELD(_offset + 8, _startbit, _stopbit), \ + [_name##_##3] = REG_FIELD(_offset + 12, _startbit, _stopbit), \ + [_name##_##4] = REG_FIELD(_offset + 16, _startbit, _stopbit), \ + [_name##_##5] = REG_FIELD(_offset + 20, _startbit, _stopbit), \ + [_name##_##6] = REG_FIELD(_offset + 24, _startbit, _stopbit), \ + [_name##_##7] = REG_FIELD(_offset + 28, _startbit, _stopbit), \ + [_name##_##8] = REG_FIELD(_offset + 32, _startbit, _stopbit), \ + [_name##_##9] = REG_FIELD(_offset + 36, _startbit, _stopbit), \ + [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit) - REG_ARRAY_SIZE, +#define REG_FIELD_FOR_EACH_SENSOR16(_name, _offset, _startbit, _stopbit) \ + [_name##_##0] = REG_FIELD(_offset, _startbit, _stopbit), \ + [_name##_##1] = REG_FIELD(_offset + 4, _startbit, _stopbit), \ + [_name##_##2] = REG_FIELD(_offset + 8, _startbit, _stopbit), \ + [_name##_##3] = REG_FIELD(_offset + 12, _startbit, _stopbit), \ + [_name##_##4] = REG_FIELD(_offset + 16, _startbit, _stopbit), \ + [_name##_##5] = REG_FIELD(_offset + 20, _startbit, _stopbit), \ + [_name##_##6] = REG_FIELD(_offset + 24, _startbit, _stopbit), \ + [_name##_##7] = REG_FIELD(_offset + 28, _startbit, _stopbit), \ + [_name##_##8] = REG_FIELD(_offset + 32, _startbit, _stopbit), \ + [_name##_##9] = REG_FIELD(_offset + 36, _startbit, _stopbit), \ + [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit), \ + [_name##_##11] = REG_FIELD(_offset + 44, _startbit, _stopbit), \ + [_name##_##12] = REG_FIELD(_offset + 48, _startbit, _stopbit), \ + [_name##_##13] = REG_FIELD(_offset + 52, _startbit, _stopbit), \ + [_name##_##14] = REG_FIELD(_offset + 56, _startbit, _stopbit), \ + [_name##_##15] = REG_FIELD(_offset + 60, _startbit, _stopbit) + +/* reg_field IDs to use as an index into an array */ +enum regfield_ids { + /* ----- SROT ------ */ + /* HW_VER */ + VER_MAJOR = 0, + VER_MINOR, + VER_STEP, + /* CTRL_OFFSET */ + TSENS_EN = 3, + TSENS_SW_RST, + SENSOR_EN, + CODE_OR_TEMP, + + /* ----- TM ------ */ + /* STATUS */ + LAST_TEMP_0 = 7, /* Last temperature reading */ + LAST_TEMP_1, + LAST_TEMP_2, + LAST_TEMP_3, + LAST_TEMP_4, + LAST_TEMP_5, + LAST_TEMP_6, + LAST_TEMP_7, + LAST_TEMP_8, + LAST_TEMP_9, + LAST_TEMP_10, + LAST_TEMP_11, + LAST_TEMP_12, + LAST_TEMP_13, + LAST_TEMP_14, + LAST_TEMP_15, + VALID_0 = 23, /* VALID reading or not */ + VALID_1, + VALID_2, + VALID_3, + VALID_4, + VALID_5, + VALID_6, + VALID_7, + VALID_8, + VALID_9, + VALID_10, + VALID_11, + VALID_12, + VALID_13, + VALID_14, + VALID_15, + MIN_STATUS_0, /* MIN threshold violated */ + MIN_STATUS_1, + MIN_STATUS_2, + MIN_STATUS_3, + MIN_STATUS_4, + MIN_STATUS_5, + MIN_STATUS_6, + MIN_STATUS_7, + MIN_STATUS_8, + MIN_STATUS_9, + MIN_STATUS_10, + MIN_STATUS_11, + MIN_STATUS_12, + MIN_STATUS_13, + MIN_STATUS_14, + MIN_STATUS_15, + MAX_STATUS_0, /* MAX threshold violated */ + MAX_STATUS_1, + MAX_STATUS_2, + MAX_STATUS_3, + MAX_STATUS_4, + MAX_STATUS_5, + MAX_STATUS_6, + MAX_STATUS_7, + MAX_STATUS_8, + MAX_STATUS_9, + MAX_STATUS_10, + MAX_STATUS_11, + MAX_STATUS_12, + MAX_STATUS_13, + MAX_STATUS_14, + MAX_STATUS_15, + LOWER_STATUS_0, /* LOWER threshold violated */ + LOWER_STATUS_1, + LOWER_STATUS_2, + LOWER_STATUS_3, + LOWER_STATUS_4, + LOWER_STATUS_5, + LOWER_STATUS_6, + LOWER_STATUS_7, + LOWER_STATUS_8, + LOWER_STATUS_9, + LOWER_STATUS_10, + LOWER_STATUS_11, + LOWER_STATUS_12, + LOWER_STATUS_13, + LOWER_STATUS_14, + LOWER_STATUS_15, + UPPER_STATUS_0, /* UPPER threshold violated */ + UPPER_STATUS_1, + UPPER_STATUS_2, + UPPER_STATUS_3, + UPPER_STATUS_4, + UPPER_STATUS_5, + UPPER_STATUS_6, + UPPER_STATUS_7, + UPPER_STATUS_8, + UPPER_STATUS_9, + UPPER_STATUS_10, + UPPER_STATUS_11, + UPPER_STATUS_12, + UPPER_STATUS_13, + UPPER_STATUS_14, + UPPER_STATUS_15, + CRITICAL_STATUS_0, /* CRITICAL threshold violated */ + CRITICAL_STATUS_1, + CRITICAL_STATUS_2, + CRITICAL_STATUS_3, + CRITICAL_STATUS_4, + CRITICAL_STATUS_5, + CRITICAL_STATUS_6, + CRITICAL_STATUS_7, + CRITICAL_STATUS_8, + CRITICAL_STATUS_9, + CRITICAL_STATUS_10, + CRITICAL_STATUS_11, + CRITICAL_STATUS_12, + CRITICAL_STATUS_13, + CRITICAL_STATUS_14, + CRITICAL_STATUS_15, + /* TRDY */ + TRDY, + /* INTERRUPT ENABLE */ + INT_EN, /* Pre-V1, V1.x */ + LOW_INT_EN, /* V2.x */ + UP_INT_EN, /* V2.x */ + CRIT_INT_EN, /* V2.x */ + + /* Keep last */ + MAX_REGFIELDS }; /** - * struct tsens_data - tsens instance specific data - * @num_sensors: Max number of sensors supported by platform + * struct tsens_features - Features supported by the IP + * @ver_major: Major number of IP version + * @crit_int: does the IP support critical interrupts? + * @adc: do the sensors only output adc code (instead of temperature)? + * @srot_split: does the IP neatly splits the register space into SROT and TM, + * with SROT only being available to secure boot firmware? + * @max_sensors: maximum sensors supported by this version of the IP + */ +struct tsens_features { + unsigned int ver_major; + unsigned int crit_int:1; + unsigned int adc:1; + unsigned int srot_split:1; + unsigned int max_sensors; +}; + +/** + * struct tsens_plat_data - tsens compile-time platform data + * @num_sensors: Number of sensors supported by platform * @ops: operations the tsens instance supports * @hw_ids: Subset of sensors ids supported by platform, if not the first n - * @reg_offsets: Register offsets for commonly used registers + * @feat: features of the IP + * @fields: bitfield locations */ -struct tsens_data { +struct tsens_plat_data { const u32 num_sensors; const struct tsens_ops *ops; - const u16 reg_offsets[REG_ARRAY_SIZE]; unsigned int *hw_ids; + const struct tsens_features *feat; + const struct reg_field *fields; }; -/* Registers to be saved/restored across a context loss */ +/** + * struct tsens_context - Registers to be saved/restored across a context loss + */ struct tsens_context { int threshold; int control; }; -struct tsens_device { +/** + * struct tsens_priv - private data for each instance of the tsens IP + * @dev: pointer to struct device + * @num_sensors: number of sensors enabled on this device + * @tm_map: pointer to TM register address space + * @srot_map: pointer to SROT register address space + * @tm_offset: deal with old device trees that don't address TM and SROT + * address space separately + * @rf: array of regmap_fields used to store value of the field + * @ctx: registers to be saved and restored during suspend/resume + * @feat: features of the IP + * @fields: bitfield locations + * @ops: pointer to list of callbacks supported by this device + * @sensor: list of sensors attached to this device + */ +struct tsens_priv { struct device *dev; u32 num_sensors; struct regmap *tm_map; struct regmap *srot_map; u32 tm_offset; - u16 reg_offsets[REG_ARRAY_SIZE]; + struct regmap_field *rf[MAX_REGFIELDS]; struct tsens_context ctx; + const struct tsens_features *feat; + const struct reg_field *fields; const struct tsens_ops *ops; struct tsens_sensor sensor[0]; }; -char *qfprom_read(struct device *, const char *); -void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32); -int init_common(struct tsens_device *); -int get_temp_common(struct tsens_device *, int, int *); +char *qfprom_read(struct device *dev, const char *cname); +void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode); +int init_common(struct tsens_priv *priv); +int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp); +int get_temp_common(struct tsens_priv *priv, int i, int *temp); +bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id); + +/* TSENS target */ +extern const struct tsens_plat_data data_8960; + +/* TSENS v0.1 targets */ +extern const struct tsens_plat_data data_8916, data_8974; /* TSENS v1 targets */ -extern const struct tsens_data data_8916, data_8974, data_8960; +extern const struct tsens_plat_data data_tsens_v1; + /* TSENS v2 targets */ -extern const struct tsens_data data_8996, data_tsens_v2; +extern const struct tsens_plat_data data_8996, data_tsens_v2; #endif /* __QCOM_TSENS_H__ */ |