Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'thermal-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control updates from Rafael Wysocki:
"The majority of changes here are related to the general switch-over to
using arrays of generic trip point structures registered along with a
thermal zone instead of trip point callbacks (this has been done
mostly by Daniel Lezcano with some help from yours truly on the Intel
drivers front).

Apart from that and the related reorganization of code, there are some
enhancements of the existing driver and a new Mediatek Low Voltage
Thermal Sensor (LVTS) driver. The Intel powerclamp undergoes a major
rework so it will use the generic idle_inject facility for CPU idle
time injection going forward and it will take additional module
parameters for specifying the subset of CPUs to be affected by it
(work done by Srinivas Pandruvada).

Also included are assorted fixes and a whole bunch of cleanups.

Specifics:

- Rework a large bunch of drivers to use the generic thermal trip
structure and use the opportunity to do more cleanups by removing
unused functions from the OF code (Daniel Lezcano)

- Remove core header inclusion from drivers (Daniel Lezcano)

- Fix some locking issues related to the generic thermal trip rework
(Johan Hovold)

- Fix a crash when requesting the critical temperature on tegra,
which is related to the generic trip point work (Jon Hunter)

- Clean up thermal device unregistration code (Viresh Kumar)

- Fix and clean up thermal control core initialization error code
paths (Daniel Lezcano)

- Relocate the trip points handling code into a separate file (Daniel
Lezcano)

- Make the thermal core fail registration of thermal zones and
cooling devices if the thermal class has not been registered
(Rafael Wysocki)

- Add trip point initialization helper functions for ACPI-defined
trip points and modify two thermal drivers to use them (Rafael
Wysocki, Daniel Lezcano)

- Make the core thermal control code use sysfs_emit_at() instead of
scnprintf() where applicable (ye xingchen)

- Consolidate code accessing the Intel TCC (Thermal Control
Circuitry) MSRs by introducing library functions for that and
making the TCC-related code in thermal drivers use them (Zhang Rui)

- Enhance the x86_pkg_temp_thermal driver to support dynamic tjmax
changes (Zhang Rui)

- Address an "unsigned expression compared with zero" warning in the
intel_soc_dts_iosf thermal driver (Yang Li)

- Update comments regarding two functions in the Intel Menlow thermal
driver (Deming Wang)

- Use sysfs_emit_at() instead of scnprintf() in the int340x thermal
driver (ye xingchen)

- Make the intel_pch thermal driver support the Wellsburg PCH (Tim
Zimmermann)

- Modify the intel_pch and processor_thermal_device_pci thermal
drivers use generic trip point tables instead of thermal zone trip
point callbacks (Daniel Lezcano)

- Add production mode attribute sysfs attribute to the int340x
thermal driver (Srinivas Pandruvada)

- Rework dynamic trip point updates handling and locking in the
int340x thermal driver (Rafael Wysocki)

- Make the int340x thermal driver use a generic trip points table
instead of thermal zone trip point callbacks (Rafael Wysocki,
Daniel Lezcano)

- Clean up and improve the int340x thermal driver (Rafael Wysocki)

- Simplify and clean up the intel_pch thermal driver (Rafael Wysocki)

- Fix the Intel powerclamp thermal driver and make it use the common
idle injection framework (Srinivas Pandruvada)

- Add two module parameters, cpumask and max_idle, to the Intel
powerclamp thermal driver to allow it to affect only a specific
subset of CPUs instead of all of them (Srinivas Pandruvada)

- Make the Intel quark_dts thermal driver Use generic trip point
objects instead of its own trip point representation (Daniel
Lezcano)

- Add toctree entry for thermal documents and fix two issues in the
Intel powerclamp driver documentation (Bagas Sanjaya)

- Use strscpy() to instead of strncpy() in the thermal core (Xu
Panda)

- Fix thermal_sampling_exit() (Vincent Guittot)

- Add Mediatek Low Voltage Thermal Sensor (LVTS) driver (Balsam
Chihi)

- Add r8a779g0 RCar support to the rcar_gen3 thermal driver (Geert
Uytterhoeven)

- Fix useless call to set_trips() when resuming in the rcar_gen3
thermal control driver and add interrupt support detection at init
time to it (Niklas Söderlund)

- Fix memory corruption in the hi3660 thermal driver (Yongqin Liu)

- Fix include path for libnl3 in pkg-config file for libthermal
(Vibhav Pant)

- Remove syscfg-based driver for st as the platform is not supported
any more (Alain Volmat)"

* tag 'thermal-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (135 commits)
thermal/drivers/st: Remove syscfg based driver
thermal: Remove core header inclusion from drivers
tools/lib/thermal: Fix include path for libnl3 in pkg-config file.
thermal/drivers/hisi: Drop second sensor hi3660
thermal/drivers/rcar_gen3_thermal: Fix device initialization
thermal/drivers/rcar_gen3_thermal: Create device local ops struct
thermal/drivers/rcar_gen3_thermal: Do not call set_trips() when resuming
thermal/drivers/rcar_gen3: Add support for R-Car V4H
dt-bindings: thermal: rcar-gen3-thermal: Add r8a779g0 support
thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver
dt-bindings: thermal: mediatek: Add LVTS thermal controllers
thermal/drivers/mediatek: Relocate driver to mediatek folder
tools/lib/thermal: Fix thermal_sampling_exit()
Documentation: powerclamp: Fix numbered lists formatting
Documentation: powerclamp: Escape wildcard in cpumask description
Documentation: admin-guide: Add toctree entry for thermal docs
thermal: intel: powerclamp: Add two module parameters
Documentation: admin-guide: Move intel_powerclamp documentation
thermal: core: Use sysfs_emit_at() instead of scnprintf()
thermal: intel: powerclamp: Fix duration module parameter
...

+4152 -3185
+1
Documentation/admin-guide/index.rst
··· 116 116 svga 117 117 syscall-user-dispatch 118 118 sysrq 119 + thermal/index 119 120 thunderbolt 120 121 ufs 121 122 unicode
+8
Documentation/admin-guide/thermal/index.rst
··· 1 + ================= 2 + Thermal Subsystem 3 + ================= 4 + 5 + .. toctree:: 6 + :maxdepth: 1 7 + 8 + intel_powerclamp
+142
Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/thermal/mediatek,lvts-thermal.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MediaTek SoC Low Voltage Thermal Sensor (LVTS) 8 + 9 + maintainers: 10 + - Balsam CHIHI <bchihi@baylibre.com> 11 + 12 + description: | 13 + LVTS is a thermal management architecture composed of three subsystems, 14 + a Sensing device - Thermal Sensing Micro Circuit Unit (TSMCU), 15 + a Converter - Low Voltage Thermal Sensor converter (LVTS), and 16 + a Digital controller (LVTS_CTRL). 17 + 18 + properties: 19 + compatible: 20 + enum: 21 + - mediatek,mt8192-lvts-ap 22 + - mediatek,mt8192-lvts-mcu 23 + - mediatek,mt8195-lvts-ap 24 + - mediatek,mt8195-lvts-mcu 25 + 26 + reg: 27 + maxItems: 1 28 + 29 + interrupts: 30 + maxItems: 1 31 + 32 + clocks: 33 + maxItems: 1 34 + 35 + resets: 36 + maxItems: 1 37 + description: LVTS reset for clearing temporary data on AP/MCU. 38 + 39 + nvmem-cells: 40 + minItems: 1 41 + items: 42 + - description: Calibration eFuse data 1 for LVTS 43 + - description: Calibration eFuse data 2 for LVTS 44 + 45 + nvmem-cell-names: 46 + minItems: 1 47 + items: 48 + - const: lvts-calib-data-1 49 + - const: lvts-calib-data-2 50 + 51 + "#thermal-sensor-cells": 52 + const: 1 53 + 54 + allOf: 55 + - $ref: thermal-sensor.yaml# 56 + 57 + - if: 58 + properties: 59 + compatible: 60 + contains: 61 + enum: 62 + - mediatek,mt8192-lvts-ap 63 + - mediatek,mt8192-lvts-mcu 64 + then: 65 + properties: 66 + nvmem-cells: 67 + maxItems: 1 68 + 69 + nvmem-cell-names: 70 + maxItems: 1 71 + 72 + - if: 73 + properties: 74 + compatible: 75 + contains: 76 + enum: 77 + - mediatek,mt8195-lvts-ap 78 + - mediatek,mt8195-lvts-mcu 79 + then: 80 + properties: 81 + nvmem-cells: 82 + minItems: 2 83 + 84 + nvmem-cell-names: 85 + minItems: 2 86 + 87 + required: 88 + - compatible 89 + - reg 90 + - interrupts 91 + - clocks 92 + - resets 93 + - nvmem-cells 94 + - nvmem-cell-names 95 + - "#thermal-sensor-cells" 96 + 97 + additionalProperties: false 98 + 99 + examples: 100 + - | 101 + #include <dt-bindings/interrupt-controller/arm-gic.h> 102 + #include <dt-bindings/clock/mt8195-clk.h> 103 + #include <dt-bindings/reset/mt8195-resets.h> 104 + #include <dt-bindings/thermal/mediatek,lvts-thermal.h> 105 + 106 + soc { 107 + #address-cells = <2>; 108 + #size-cells = <2>; 109 + 110 + lvts_mcu: thermal-sensor@11278000 { 111 + compatible = "mediatek,mt8195-lvts-mcu"; 112 + reg = <0 0x11278000 0 0x1000>; 113 + interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>; 114 + clocks = <&infracfg_ao CLK_INFRA_AO_THERM>; 115 + resets = <&infracfg_ao MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST>; 116 + nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>; 117 + nvmem-cell-names = "lvts-calib-data-1", "lvts-calib-data-2"; 118 + #thermal-sensor-cells = <1>; 119 + }; 120 + }; 121 + 122 + thermal_zones: thermal-zones { 123 + cpu0-thermal { 124 + polling-delay = <1000>; 125 + polling-delay-passive = <250>; 126 + thermal-sensors = <&lvts_mcu MT8195_MCU_LITTLE_CPU0>; 127 + 128 + trips { 129 + cpu0_alert: trip-alert { 130 + temperature = <85000>; 131 + hysteresis = <2000>; 132 + type = "passive"; 133 + }; 134 + 135 + cpu0_crit: trip-crit { 136 + temperature = <100000>; 137 + hysteresis = <2000>; 138 + type = "critical"; 139 + }; 140 + }; 141 + }; 142 + };
+1
Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml
··· 13 13 enum: 14 14 - qcom,spmi-adc-tm5 15 15 - qcom,spmi-adc-tm5-gen2 16 + - qcom,adc-tm7 # Incomplete / subject to change 16 17 17 18 reg: 18 19 maxItems: 1
+143 -10
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
··· 37 37 - description: v1 of TSENS 38 38 items: 39 39 - enum: 40 + - qcom,msm8956-tsens 40 41 - qcom,msm8976-tsens 41 42 - qcom,qcs404-tsens 42 43 - const: qcom,tsens-v1 ··· 81 80 maxItems: 2 82 81 83 82 nvmem-cells: 84 - minItems: 1 85 - maxItems: 2 86 - description: 87 - Reference to an nvmem node for the calibration data 83 + oneOf: 84 + - minItems: 1 85 + maxItems: 2 86 + description: 87 + Reference to an nvmem node for the calibration data 88 + - minItems: 5 89 + maxItems: 35 90 + description: | 91 + Reference to nvmem cells for the calibration mode, two calibration 92 + bases and two cells per each sensor 93 + # special case for msm8974 / apq8084 94 + - maxItems: 51 95 + description: | 96 + Reference to nvmem cells for the calibration mode, two calibration 97 + bases and two cells per each sensor, main and backup copies, plus use_backup cell 88 98 89 99 nvmem-cell-names: 90 - minItems: 1 91 - items: 92 - - const: calib 93 - - enum: 94 - - calib_backup 95 - - calib_sel 100 + oneOf: 101 + - minItems: 1 102 + items: 103 + - const: calib 104 + - enum: 105 + - calib_backup 106 + - calib_sel 107 + - minItems: 5 108 + items: 109 + - const: mode 110 + - const: base1 111 + - const: base2 112 + - pattern: '^s[0-9]+_p1$' 113 + - pattern: '^s[0-9]+_p2$' 114 + - pattern: '^s[0-9]+_p1$' 115 + - pattern: '^s[0-9]+_p2$' 116 + - pattern: '^s[0-9]+_p1$' 117 + - pattern: '^s[0-9]+_p2$' 118 + - pattern: '^s[0-9]+_p1$' 119 + - pattern: '^s[0-9]+_p2$' 120 + - pattern: '^s[0-9]+_p1$' 121 + - pattern: '^s[0-9]+_p2$' 122 + - pattern: '^s[0-9]+_p1$' 123 + - pattern: '^s[0-9]+_p2$' 124 + - pattern: '^s[0-9]+_p1$' 125 + - pattern: '^s[0-9]+_p2$' 126 + - pattern: '^s[0-9]+_p1$' 127 + - pattern: '^s[0-9]+_p2$' 128 + - pattern: '^s[0-9]+_p1$' 129 + - pattern: '^s[0-9]+_p2$' 130 + - pattern: '^s[0-9]+_p1$' 131 + - pattern: '^s[0-9]+_p2$' 132 + - pattern: '^s[0-9]+_p1$' 133 + - pattern: '^s[0-9]+_p2$' 134 + - pattern: '^s[0-9]+_p1$' 135 + - pattern: '^s[0-9]+_p2$' 136 + - pattern: '^s[0-9]+_p1$' 137 + - pattern: '^s[0-9]+_p2$' 138 + - pattern: '^s[0-9]+_p1$' 139 + - pattern: '^s[0-9]+_p2$' 140 + - pattern: '^s[0-9]+_p1$' 141 + - pattern: '^s[0-9]+_p2$' 142 + - pattern: '^s[0-9]+_p1$' 143 + - pattern: '^s[0-9]+_p2$' 144 + # special case for msm8974 / apq8084 145 + - items: 146 + - const: mode 147 + - const: base1 148 + - const: base2 149 + - const: use_backup 150 + - const: mode_backup 151 + - const: base1_backup 152 + - const: base2_backup 153 + - const: s0_p1 154 + - const: s0_p2 155 + - const: s1_p1 156 + - const: s1_p2 157 + - const: s2_p1 158 + - const: s2_p2 159 + - const: s3_p1 160 + - const: s3_p2 161 + - const: s4_p1 162 + - const: s4_p2 163 + - const: s5_p1 164 + - const: s5_p2 165 + - const: s6_p1 166 + - const: s6_p2 167 + - const: s7_p1 168 + - const: s7_p2 169 + - const: s8_p1 170 + - const: s8_p2 171 + - const: s9_p1 172 + - const: s9_p2 173 + - const: s10_p1 174 + - const: s10_p2 175 + - const: s0_p1_backup 176 + - const: s0_p2_backup 177 + - const: s1_p1_backup 178 + - const: s1_p2_backup 179 + - const: s2_p1_backup 180 + - const: s2_p2_backup 181 + - const: s3_p1_backup 182 + - const: s3_p2_backup 183 + - const: s4_p1_backup 184 + - const: s4_p2_backup 185 + - const: s5_p1_backup 186 + - const: s5_p2_backup 187 + - const: s6_p1_backup 188 + - const: s6_p2_backup 189 + - const: s7_p1_backup 190 + - const: s7_p2_backup 191 + - const: s8_p1_backup 192 + - const: s8_p2_backup 193 + - const: s9_p1_backup 194 + - const: s9_p2_backup 195 + - const: s10_p1_backup 196 + - const: s10_p2_backup 96 197 97 198 "#qcom,sensors": 98 199 description: ··· 321 218 #qcom,sensors = <11>; 322 219 #thermal-sensor-cells = <1>; 323 220 }; 221 + }; 222 + 223 + - | 224 + #include <dt-bindings/interrupt-controller/arm-gic.h> 225 + // Example 1 (new calbiration data: for pre v1 IP): 226 + thermal-sensor@900000 { 227 + compatible = "qcom,msm8916-tsens", "qcom,tsens-v0_1"; 228 + reg = <0x4a9000 0x1000>, /* TM */ 229 + <0x4a8000 0x1000>; /* SROT */ 230 + 231 + nvmem-cells = <&tsens_mode>, 232 + <&tsens_base1>, <&tsens_base2>, 233 + <&tsens_s0_p1>, <&tsens_s0_p2>, 234 + <&tsens_s1_p1>, <&tsens_s1_p2>, 235 + <&tsens_s2_p1>, <&tsens_s2_p2>, 236 + <&tsens_s4_p1>, <&tsens_s4_p2>, 237 + <&tsens_s5_p1>, <&tsens_s5_p2>; 238 + nvmem-cell-names = "mode", 239 + "base1", "base2", 240 + "s0_p1", "s0_p2", 241 + "s1_p1", "s1_p2", 242 + "s2_p1", "s2_p2", 243 + "s4_p1", "s4_p2", 244 + "s5_p1", "s5_p2"; 245 + 246 + interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; 247 + interrupt-names = "uplow"; 248 + 249 + #qcom,sensors = <5>; 250 + #thermal-sensor-cells = <1>; 324 251 }; 325 252 326 253 - |
+3
Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml
··· 28 28 - renesas,r8a77980-thermal # R-Car V3H 29 29 - renesas,r8a779a0-thermal # R-Car V3U 30 30 - renesas,r8a779f0-thermal # R-Car S4-8 31 + - renesas,r8a779g0-thermal # R-Car V4H 31 32 32 33 reg: true 33 34 ··· 81 80 - description: TSC1 registers 82 81 - description: TSC2 registers 83 82 - description: TSC3 registers 83 + - description: TSC4 registers 84 84 if: 85 85 not: 86 86 properties: ··· 89 87 contains: 90 88 enum: 91 89 - renesas,r8a779f0-thermal 90 + - renesas,r8a779g0-thermal 92 91 then: 93 92 required: 94 93 - interrupts
-1
Documentation/driver-api/thermal/index.rst
··· 14 14 15 15 exynos_thermal 16 16 exynos_thermal_emulation 17 - intel_powerclamp 18 17 nouveau_thermal 19 18 x86_pkg_temperature_thermal 20 19 intel_dptf
+3
Documentation/driver-api/thermal/intel_dptf.rst
··· 84 84 https:/github.com/intel/thermal_daemon for decoding 85 85 thermal table. 86 86 87 + ``production_mode`` (RO) 88 + When different from zero, manufacturer locked thermal configuration 89 + from further changes. 87 90 88 91 ACPI Thermal Relationship table interface 89 92 ------------------------------------------
+30 -5
Documentation/driver-api/thermal/intel_powerclamp.rst Documentation/admin-guide/thermal/intel_powerclamp.rst
··· 26 26 - Generic Thermal Layer (sysfs) 27 27 - Kernel APIs (TBD) 28 28 29 + (*) Module Parameters 30 + 29 31 INTRODUCTION 30 32 ============ 31 33 ··· 155 153 Compensation to each target ratio consists of two parts: 156 154 157 155 a) steady state error compensation 158 - This is to offset the error occurring when the system can 159 - enter idle without extra wakeups (such as external interrupts). 156 + 157 + This is to offset the error occurring when the system can 158 + enter idle without extra wakeups (such as external interrupts). 160 159 161 160 b) dynamic error compensation 162 - When an excessive amount of wakeups occurs during idle, an 163 - additional idle ratio can be added to quiet interrupts, by 164 - slowing down CPU activities. 161 + 162 + When an excessive amount of wakeups occurs during idle, an 163 + additional idle ratio can be added to quiet interrupts, by 164 + slowing down CPU activities. 165 165 166 166 A debugfs file is provided for the user to examine compensation 167 167 progress and results, such as on a Westmere system:: ··· 285 281 100% busy state with the disabled state. 286 282 287 283 Example usage: 284 + 288 285 - To inject 25% idle time:: 289 286 290 287 $ sudo sh -c "echo 25 > /sys/class/thermal/cooling_device80/cur_state ··· 323 318 control CPU temperature effectively, when no other thermal influence 324 319 is added. For example, a UltraBook user can compile the kernel under 325 320 certain temperature (below most active trip points). 321 + 322 + Module Parameters 323 + ================= 324 + 325 + ``cpumask`` (RW) 326 + A bit mask of CPUs to inject idle. The format of the bitmask is same as 327 + used in other subsystems like in /proc/irq/\*/smp_affinity. The mask is 328 + comma separated 32 bit groups. Each CPU is one bit. For example for a 256 329 + CPU system the full mask is: 330 + ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff 331 + 332 + The rightmost mask is for CPU 0-32. 333 + 334 + ``max_idle`` (RW) 335 + Maximum injected idle time to the total CPU time ratio in percent range 336 + from 1 to 100. Even if the cooling device max_state is always 100 (100%), 337 + this parameter allows to add a max idle percent limit. The default is 50, 338 + to match the current implementation of powerclamp driver. Also doesn't 339 + allow value more than 75, if the cpumask includes every CPU present in 340 + the system.
+1
MAINTAINERS
··· 20529 20529 Q: https://patchwork.kernel.org/project/linux-pm/list/ 20530 20530 T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git thermal 20531 20531 F: Documentation/ABI/testing/sysfs-class-thermal 20532 + F: Documentation/admin-guide/thermal/ 20532 20533 F: Documentation/devicetree/bindings/thermal/ 20533 20534 F: Documentation/driver-api/thermal/ 20534 20535 F: drivers/thermal/
-2
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
··· 1079 1079 #if IS_ENABLED(CONFIG_THERMAL) 1080 1080 struct ch_thermal { 1081 1081 struct thermal_zone_device *tzdev; 1082 - int trip_temp; 1083 - int trip_type; 1084 1082 }; 1085 1083 #endif 1086 1084
+7 -32
drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
··· 29 29 return 0; 30 30 } 31 31 32 - static int cxgb4_thermal_get_trip_type(struct thermal_zone_device *tzdev, 33 - int trip, enum thermal_trip_type *type) 34 - { 35 - struct adapter *adap = tzdev->devdata; 36 - 37 - if (!adap->ch_thermal.trip_temp) 38 - return -EINVAL; 39 - 40 - *type = adap->ch_thermal.trip_type; 41 - return 0; 42 - } 43 - 44 - static int cxgb4_thermal_get_trip_temp(struct thermal_zone_device *tzdev, 45 - int trip, int *temp) 46 - { 47 - struct adapter *adap = tzdev->devdata; 48 - 49 - if (!adap->ch_thermal.trip_temp) 50 - return -EINVAL; 51 - 52 - *temp = adap->ch_thermal.trip_temp; 53 - return 0; 54 - } 55 - 56 32 static struct thermal_zone_device_ops cxgb4_thermal_ops = { 57 33 .get_temp = cxgb4_thermal_get_temp, 58 - .get_trip_type = cxgb4_thermal_get_trip_type, 59 - .get_trip_temp = cxgb4_thermal_get_trip_temp, 60 34 }; 35 + 36 + static struct thermal_trip trip = { .type = THERMAL_TRIP_CRITICAL } ; 61 37 62 38 int cxgb4_thermal_init(struct adapter *adap) 63 39 { ··· 55 79 if (ret < 0) { 56 80 num_trip = 0; /* could not get trip temperature */ 57 81 } else { 58 - ch_thermal->trip_temp = val * 1000; 59 - ch_thermal->trip_type = THERMAL_TRIP_CRITICAL; 82 + trip.temperature = val * 1000; 60 83 } 61 84 62 85 snprintf(ch_tz_name, sizeof(ch_tz_name), "cxgb4_%s", adap->name); 63 - ch_thermal->tzdev = thermal_zone_device_register(ch_tz_name, num_trip, 64 - 0, adap, 65 - &cxgb4_thermal_ops, 66 - NULL, 0, 0); 86 + ch_thermal->tzdev = thermal_zone_device_register_with_trips(ch_tz_name, &trip, num_trip, 87 + 0, adap, 88 + &cxgb4_thermal_ops, 89 + NULL, 0, 0); 67 90 if (IS_ERR(ch_thermal->tzdev)) { 68 91 ret = PTR_ERR(ch_thermal->tzdev); 69 92 dev_err(adap->pdev_dev, "Failed to register thermal zone\n");
+48 -161
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
··· 36 36 MLXSW_THERMAL_TEMP_TRIP_HOT, 37 37 }; 38 38 39 - struct mlxsw_thermal_trip { 40 - int type; 41 - int temp; 42 - int hyst; 39 + struct mlxsw_cooling_states { 43 40 int min_state; 44 41 int max_state; 45 42 }; 46 43 47 - static const struct mlxsw_thermal_trip default_thermal_trips[] = { 44 + static const struct thermal_trip default_thermal_trips[] = { 48 45 { /* In range - 0-40% PWM */ 49 46 .type = THERMAL_TRIP_ACTIVE, 50 - .temp = MLXSW_THERMAL_ASIC_TEMP_NORM, 51 - .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, 52 - .min_state = 0, 53 - .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, 47 + .temperature = MLXSW_THERMAL_ASIC_TEMP_NORM, 48 + .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP, 54 49 }, 55 50 { 56 51 /* In range - 40-100% PWM */ 57 52 .type = THERMAL_TRIP_ACTIVE, 58 - .temp = MLXSW_THERMAL_ASIC_TEMP_HIGH, 59 - .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, 60 - .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, 61 - .max_state = MLXSW_THERMAL_MAX_STATE, 53 + .temperature = MLXSW_THERMAL_ASIC_TEMP_HIGH, 54 + .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP, 62 55 }, 63 56 { /* Warning */ 64 57 .type = THERMAL_TRIP_HOT, 65 - .temp = MLXSW_THERMAL_ASIC_TEMP_HOT, 58 + .temperature = MLXSW_THERMAL_ASIC_TEMP_HOT, 59 + }, 60 + }; 61 + 62 + static const struct mlxsw_cooling_states default_cooling_states[] = { 63 + { 64 + .min_state = 0, 65 + .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, 66 + }, 67 + { 68 + .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, 69 + .max_state = MLXSW_THERMAL_MAX_STATE, 70 + }, 71 + { 66 72 .min_state = MLXSW_THERMAL_MAX_STATE, 67 73 .max_state = MLXSW_THERMAL_MAX_STATE, 68 74 }, ··· 84 78 struct mlxsw_thermal_module { 85 79 struct mlxsw_thermal *parent; 86 80 struct thermal_zone_device *tzdev; 87 - struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; 81 + struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; 82 + struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS]; 88 83 int module; /* Module or gearbox number */ 89 84 u8 slot_index; 90 85 }; ··· 106 99 int polling_delay; 107 100 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; 108 101 u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; 109 - struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; 102 + struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; 103 + struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS]; 110 104 struct mlxsw_thermal_area line_cards[]; 111 105 }; 112 106 ··· 144 136 static void 145 137 mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz) 146 138 { 147 - tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0; 148 - tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0; 149 - tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0; 139 + tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = 0; 140 + tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temperature = 0; 141 + tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temperature = 0; 150 142 } 151 143 152 144 static int ··· 188 180 * by subtracting double hysteresis value. 189 181 */ 190 182 if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT) 191 - tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp - 183 + tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = crit_temp - 192 184 MLXSW_THERMAL_MODULE_TEMP_SHIFT; 193 185 else 194 - tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp; 195 - tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp; 196 - tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp; 186 + tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = crit_temp; 187 + tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temperature = crit_temp; 188 + tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temperature = emerg_temp; 197 189 198 190 return 0; 199 191 } ··· 210 202 return 0; 211 203 212 204 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) { 213 - const struct mlxsw_thermal_trip *trip = &thermal->trips[i]; 205 + const struct mlxsw_cooling_states *state = &thermal->cooling_states[i]; 214 206 215 207 err = thermal_zone_bind_cooling_device(tzdev, i, cdev, 216 - trip->max_state, 217 - trip->min_state, 208 + state->max_state, 209 + state->min_state, 218 210 THERMAL_WEIGHT_DEFAULT); 219 211 if (err < 0) { 220 212 dev_err(dev, "Failed to bind cooling device to trip %d\n", i); ··· 268 260 return 0; 269 261 } 270 262 271 - static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev, 272 - int trip, 273 - enum thermal_trip_type *p_type) 274 - { 275 - struct mlxsw_thermal *thermal = tzdev->devdata; 276 - 277 - if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) 278 - return -EINVAL; 279 - 280 - *p_type = thermal->trips[trip].type; 281 - return 0; 282 - } 283 - 284 - static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev, 285 - int trip, int *p_temp) 286 - { 287 - struct mlxsw_thermal *thermal = tzdev->devdata; 288 - 289 - if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) 290 - return -EINVAL; 291 - 292 - *p_temp = thermal->trips[trip].temp; 293 - return 0; 294 - } 295 - 296 - static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev, 297 - int trip, int temp) 298 - { 299 - struct mlxsw_thermal *thermal = tzdev->devdata; 300 - 301 - if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) 302 - return -EINVAL; 303 - 304 - thermal->trips[trip].temp = temp; 305 - return 0; 306 - } 307 - 308 - static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev, 309 - int trip, int *p_hyst) 310 - { 311 - struct mlxsw_thermal *thermal = tzdev->devdata; 312 - 313 - *p_hyst = thermal->trips[trip].hyst; 314 - return 0; 315 - } 316 - 317 - static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev, 318 - int trip, int hyst) 319 - { 320 - struct mlxsw_thermal *thermal = tzdev->devdata; 321 - 322 - thermal->trips[trip].hyst = hyst; 323 - return 0; 324 - } 325 - 326 263 static struct thermal_zone_params mlxsw_thermal_params = { 327 264 .no_hwmon = true, 328 265 }; ··· 276 323 .bind = mlxsw_thermal_bind, 277 324 .unbind = mlxsw_thermal_unbind, 278 325 .get_temp = mlxsw_thermal_get_temp, 279 - .get_trip_type = mlxsw_thermal_get_trip_type, 280 - .get_trip_temp = mlxsw_thermal_get_trip_temp, 281 - .set_trip_temp = mlxsw_thermal_set_trip_temp, 282 - .get_trip_hyst = mlxsw_thermal_get_trip_hyst, 283 - .set_trip_hyst = mlxsw_thermal_set_trip_hyst, 284 326 }; 285 327 286 328 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, ··· 290 342 return 0; 291 343 292 344 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) { 293 - const struct mlxsw_thermal_trip *trip = &tz->trips[i]; 345 + const struct mlxsw_cooling_states *state = &tz->cooling_states[i]; 294 346 295 347 err = thermal_zone_bind_cooling_device(tzdev, i, cdev, 296 - trip->max_state, 297 - trip->min_state, 348 + state->max_state, 349 + state->min_state, 298 350 THERMAL_WEIGHT_DEFAULT); 299 351 if (err < 0) 300 352 goto err_thermal_zone_bind_cooling_device; ··· 382 434 return 0; 383 435 } 384 436 385 - static int 386 - mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip, 387 - enum thermal_trip_type *p_type) 388 - { 389 - struct mlxsw_thermal_module *tz = tzdev->devdata; 390 - 391 - if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) 392 - return -EINVAL; 393 - 394 - *p_type = tz->trips[trip].type; 395 - return 0; 396 - } 397 - 398 - static int 399 - mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev, 400 - int trip, int *p_temp) 401 - { 402 - struct mlxsw_thermal_module *tz = tzdev->devdata; 403 - 404 - if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) 405 - return -EINVAL; 406 - 407 - *p_temp = tz->trips[trip].temp; 408 - return 0; 409 - } 410 - 411 - static int 412 - mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev, 413 - int trip, int temp) 414 - { 415 - struct mlxsw_thermal_module *tz = tzdev->devdata; 416 - 417 - if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) 418 - return -EINVAL; 419 - 420 - tz->trips[trip].temp = temp; 421 - return 0; 422 - } 423 - 424 - static int 425 - mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip, 426 - int *p_hyst) 427 - { 428 - struct mlxsw_thermal_module *tz = tzdev->devdata; 429 - 430 - *p_hyst = tz->trips[trip].hyst; 431 - return 0; 432 - } 433 - 434 - static int 435 - mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip, 436 - int hyst) 437 - { 438 - struct mlxsw_thermal_module *tz = tzdev->devdata; 439 - 440 - tz->trips[trip].hyst = hyst; 441 - return 0; 442 - } 443 - 444 437 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { 445 438 .bind = mlxsw_thermal_module_bind, 446 439 .unbind = mlxsw_thermal_module_unbind, 447 440 .get_temp = mlxsw_thermal_module_temp_get, 448 - .get_trip_type = mlxsw_thermal_module_trip_type_get, 449 - .get_trip_temp = mlxsw_thermal_module_trip_temp_get, 450 - .set_trip_temp = mlxsw_thermal_module_trip_temp_set, 451 - .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, 452 - .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, 453 441 }; 454 442 455 443 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, ··· 415 531 .bind = mlxsw_thermal_module_bind, 416 532 .unbind = mlxsw_thermal_module_unbind, 417 533 .get_temp = mlxsw_thermal_gearbox_temp_get, 418 - .get_trip_type = mlxsw_thermal_module_trip_type_get, 419 - .get_trip_temp = mlxsw_thermal_module_trip_temp_get, 420 - .set_trip_temp = mlxsw_thermal_module_trip_temp_set, 421 - .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, 422 - .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, 423 534 }; 424 535 425 536 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev, ··· 496 617 else 497 618 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d", 498 619 module_tz->module + 1); 499 - module_tz->tzdev = thermal_zone_device_register(tz_name, 620 + module_tz->tzdev = thermal_zone_device_register_with_trips(tz_name, 621 + module_tz->trips, 500 622 MLXSW_THERMAL_NUM_TRIPS, 501 623 MLXSW_THERMAL_TRIP_MASK, 502 624 module_tz, ··· 541 661 module_tz->parent = thermal; 542 662 memcpy(module_tz->trips, default_thermal_trips, 543 663 sizeof(thermal->trips)); 664 + memcpy(module_tz->cooling_states, default_cooling_states, 665 + sizeof(thermal->cooling_states)); 544 666 /* Initialize all trip point. */ 545 667 mlxsw_thermal_module_trips_reset(module_tz); 546 668 /* Read module temperature and thresholds. */ ··· 638 756 else 639 757 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d", 640 758 gearbox_tz->module + 1); 641 - gearbox_tz->tzdev = thermal_zone_device_register(tz_name, 759 + gearbox_tz->tzdev = thermal_zone_device_register_with_trips(tz_name, 760 + gearbox_tz->trips, 642 761 MLXSW_THERMAL_NUM_TRIPS, 643 762 MLXSW_THERMAL_TRIP_MASK, 644 763 gearbox_tz, ··· 696 813 gearbox_tz = &area->tz_gearbox_arr[i]; 697 814 memcpy(gearbox_tz->trips, default_thermal_trips, 698 815 sizeof(thermal->trips)); 816 + memcpy(gearbox_tz->cooling_states, default_cooling_states, 817 + sizeof(thermal->cooling_states)); 699 818 gearbox_tz->module = i; 700 819 gearbox_tz->parent = thermal; 701 820 gearbox_tz->slot_index = area->slot_index; ··· 813 928 thermal->core = core; 814 929 thermal->bus_info = bus_info; 815 930 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips)); 931 + memcpy(thermal->cooling_states, default_cooling_states, sizeof(thermal->cooling_states)); 816 932 thermal->line_cards[0].slot_index = 0; 817 933 818 934 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl); ··· 867 981 MLXSW_THERMAL_SLOW_POLL_INT : 868 982 MLXSW_THERMAL_POLL_INT; 869 983 870 - thermal->tzdev = thermal_zone_device_register("mlxsw", 984 + thermal->tzdev = thermal_zone_device_register_with_trips("mlxsw", 985 + thermal->trips, 871 986 MLXSW_THERMAL_NUM_TRIPS, 872 987 MLXSW_THERMAL_TRIP_MASK, 873 988 thermal,
+1 -1
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
··· 501 501 * @tzone: thermal zone device data 502 502 */ 503 503 struct iwl_mvm_thermal_device { 504 - s16 temp_trips[IWL_MAX_DTS_TRIPS]; 504 + struct thermal_trip trips[IWL_MAX_DTS_TRIPS]; 505 505 u8 fw_trips_index[IWL_MAX_DTS_TRIPS]; 506 506 struct thermal_zone_device *tzone; 507 507 };
+12 -59
drivers/net/wireless/intel/iwlwifi/mvm/tt.c
··· 573 573 * and uncompressed, the FW should get it compressed and sorted 574 574 */ 575 575 576 - /* compress temp_trips to cmd array, remove uninitialized values*/ 576 + /* compress trips to cmd array, remove uninitialized values*/ 577 577 for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) { 578 - if (mvm->tz_device.temp_trips[i] != S16_MIN) { 578 + if (mvm->tz_device.trips[i].temperature != INT_MIN) { 579 579 cmd.thresholds[idx++] = 580 - cpu_to_le16(mvm->tz_device.temp_trips[i]); 580 + cpu_to_le16((s16)(mvm->tz_device.trips[i].temperature / 1000)); 581 581 } 582 582 } 583 583 cmd.num_temps = cpu_to_le32(idx); ··· 593 593 */ 594 594 for (i = 0; i < idx; i++) { 595 595 for (j = 0; j < IWL_MAX_DTS_TRIPS; j++) { 596 - if (le16_to_cpu(cmd.thresholds[i]) == 597 - mvm->tz_device.temp_trips[j]) 596 + if ((int)(le16_to_cpu(cmd.thresholds[i]) * 1000) == 597 + mvm->tz_device.trips[j].temperature) 598 598 mvm->tz_device.fw_trips_index[i] = j; 599 599 } 600 600 } ··· 638 638 return ret; 639 639 } 640 640 641 - static int iwl_mvm_tzone_get_trip_temp(struct thermal_zone_device *device, 642 - int trip, int *temp) 643 - { 644 - struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata; 645 - 646 - if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) 647 - return -EINVAL; 648 - 649 - *temp = mvm->tz_device.temp_trips[trip] * 1000; 650 - 651 - return 0; 652 - } 653 - 654 - static int iwl_mvm_tzone_get_trip_type(struct thermal_zone_device *device, 655 - int trip, enum thermal_trip_type *type) 656 - { 657 - if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) 658 - return -EINVAL; 659 - 660 - *type = THERMAL_TRIP_PASSIVE; 661 - 662 - return 0; 663 - } 664 - 665 641 static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device, 666 642 int trip, int temp) 667 643 { 668 644 struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata; 669 645 struct iwl_mvm_thermal_device *tzone; 670 - int i, ret; 671 - s16 temperature; 646 + int ret; 672 647 673 648 mutex_lock(&mvm->mutex); 674 649 ··· 653 678 goto out; 654 679 } 655 680 656 - if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) { 657 - ret = -EINVAL; 658 - goto out; 659 - } 660 - 661 681 if ((temp / 1000) > S16_MAX) { 662 682 ret = -EINVAL; 663 683 goto out; 664 684 } 665 685 666 - temperature = (s16)(temp / 1000); 667 686 tzone = &mvm->tz_device; 668 - 669 687 if (!tzone) { 670 688 ret = -EIO; 671 689 goto out; 672 690 } 673 - 674 - /* no updates*/ 675 - if (tzone->temp_trips[trip] == temperature) { 676 - ret = 0; 677 - goto out; 678 - } 679 - 680 - /* already existing temperature */ 681 - for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) { 682 - if (tzone->temp_trips[i] == temperature) { 683 - ret = -EINVAL; 684 - goto out; 685 - } 686 - } 687 - 688 - tzone->temp_trips[trip] = temperature; 689 691 690 692 ret = iwl_mvm_send_temp_report_ths_cmd(mvm); 691 693 out: ··· 672 720 673 721 static struct thermal_zone_device_ops tzone_ops = { 674 722 .get_temp = iwl_mvm_tzone_get_temp, 675 - .get_trip_temp = iwl_mvm_tzone_get_trip_temp, 676 - .get_trip_type = iwl_mvm_tzone_get_trip_type, 677 723 .set_trip_temp = iwl_mvm_tzone_set_trip_temp, 678 724 }; 679 725 ··· 693 743 BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH); 694 744 695 745 sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF); 696 - mvm->tz_device.tzone = thermal_zone_device_register(name, 746 + mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name, 747 + mvm->tz_device.trips, 697 748 IWL_MAX_DTS_TRIPS, 698 749 IWL_WRITABLE_TRIPS_MSK, 699 750 mvm, &tzone_ops, ··· 717 766 /* 0 is a valid temperature, 718 767 * so initialize the array with S16_MIN which invalid temperature 719 768 */ 720 - for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) 721 - mvm->tz_device.temp_trips[i] = S16_MIN; 769 + for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) { 770 + mvm->tz_device.trips[i].temperature = INT_MIN; 771 + mvm->tz_device.trips[i].type = THERMAL_TRIP_PASSIVE; 772 + } 722 773 } 723 774 724 775 static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev,
+26 -47
drivers/platform/x86/acerhdf.c
··· 46 46 * measured by the on-die thermal monitor are within 0 <= Tj <= 90. So, 47 47 * assume 89°C is critical temperature. 48 48 */ 49 + #define ACERHDF_DEFAULT_TEMP_FANON 60000 50 + #define ACERHDF_DEFAULT_TEMP_FANOFF 53000 49 51 #define ACERHDF_TEMP_CRIT 89000 50 52 #define ACERHDF_FAN_OFF 0 51 53 #define ACERHDF_FAN_AUTO 1 ··· 72 70 #endif 73 71 74 72 static unsigned int interval = 10; 75 - static unsigned int fanon = 60000; 76 - static unsigned int fanoff = 53000; 73 + static unsigned int fanon = ACERHDF_DEFAULT_TEMP_FANON; 74 + static unsigned int fanoff = ACERHDF_DEFAULT_TEMP_FANOFF; 77 75 static unsigned int verbose; 78 76 static unsigned int list_supported; 79 77 static unsigned int fanstate = ACERHDF_FAN_AUTO; ··· 137 135 u8 tempreg; 138 136 struct fancmd cmd; 139 137 int mcmd_enable; 138 + }; 139 + 140 + static struct thermal_trip trips[] = { 141 + [0] = { .temperature = ACERHDF_DEFAULT_TEMP_FANON, 142 + .hysteresis = ACERHDF_DEFAULT_TEMP_FANON - ACERHDF_DEFAULT_TEMP_FANOFF, 143 + .type = THERMAL_TRIP_ACTIVE }, 144 + 145 + [1] = { .temperature = ACERHDF_TEMP_CRIT, 146 + .type = THERMAL_TRIP_CRITICAL } 140 147 }; 141 148 142 149 static struct ctrl_settings ctrl_cfg __read_mostly; ··· 337 326 fanon = ACERHDF_MAX_FANON; 338 327 } 339 328 329 + if (fanon < fanoff) { 330 + pr_err("fanoff temperature (%d) is above fanon temperature (%d), clamping to %d\n", 331 + fanoff, fanon, fanon); 332 + fanoff = fanon; 333 + }; 334 + 335 + trips[0].temperature = fanon; 336 + trips[0].hysteresis = fanon - fanoff; 337 + 340 338 if (kernelmode && prev_interval != interval) { 341 339 if (interval > ACERHDF_MAX_INTERVAL) { 342 340 pr_err("interval too high, set to %d\n", ··· 444 424 return 0; 445 425 } 446 426 447 - static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip, 448 - enum thermal_trip_type *type) 449 - { 450 - if (trip == 0) 451 - *type = THERMAL_TRIP_ACTIVE; 452 - else if (trip == 1) 453 - *type = THERMAL_TRIP_CRITICAL; 454 - else 455 - return -EINVAL; 456 - 457 - return 0; 458 - } 459 - 460 - static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip, 461 - int *temp) 462 - { 463 - if (trip != 0) 464 - return -EINVAL; 465 - 466 - *temp = fanon - fanoff; 467 - 468 - return 0; 469 - } 470 - 471 - static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip, 472 - int *temp) 473 - { 474 - if (trip == 0) 475 - *temp = fanon; 476 - else if (trip == 1) 477 - *temp = ACERHDF_TEMP_CRIT; 478 - else 479 - return -EINVAL; 480 - 481 - return 0; 482 - } 483 - 484 427 static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal, 485 428 int *temperature) 486 429 { ··· 457 474 .unbind = acerhdf_unbind, 458 475 .get_temp = acerhdf_get_ec_temp, 459 476 .change_mode = acerhdf_change_mode, 460 - .get_trip_type = acerhdf_get_trip_type, 461 - .get_trip_hyst = acerhdf_get_trip_hyst, 462 - .get_trip_temp = acerhdf_get_trip_temp, 463 477 .get_crit_temp = acerhdf_get_crit_temp, 464 478 }; 465 - 466 479 467 480 /* 468 481 * cooling device callback functions ··· 689 710 if (IS_ERR(cl_dev)) 690 711 return -EINVAL; 691 712 692 - thz_dev = thermal_zone_device_register("acerhdf", 2, 0, NULL, 693 - &acerhdf_dev_ops, 694 - &acerhdf_zone_params, 0, 695 - (kernelmode) ? interval*1000 : 0); 713 + thz_dev = thermal_zone_device_register_with_trips("acerhdf", trips, ARRAY_SIZE(trips), 714 + 0, NULL, &acerhdf_dev_ops, 715 + &acerhdf_zone_params, 0, 716 + (kernelmode) ? interval*1000 : 0); 696 717 if (IS_ERR(thz_dev)) 697 718 return -EINVAL; 698 719
+53 -6
drivers/powercap/idle_inject.c
··· 63 63 * @idle_duration_us: duration of CPU idle time to inject 64 64 * @run_duration_us: duration of CPU run time to allow 65 65 * @latency_us: max allowed latency 66 + * @update: Optional callback deciding whether or not to skip idle 67 + * injection in the given cycle. 66 68 * @cpumask: mask of CPUs affected by idle injection 69 + * 70 + * This structure is used to define per instance idle inject device data. Each 71 + * instance has an idle duration, a run duration and mask of CPUs to inject 72 + * idle. 73 + * 74 + * Actual CPU idle time is injected by calling kernel scheduler interface 75 + * play_idle_precise(). There is one optional callback that can be registered 76 + * by calling idle_inject_register_full(): 77 + * 78 + * update() - This callback is invoked just before waking up CPUs to inject 79 + * idle. If it returns false, CPUs are not woken up to inject idle in the given 80 + * cycle. It also allows the caller to readjust the idle and run duration by 81 + * calling idle_inject_set_duration() for the next cycle. 67 82 */ 68 83 struct idle_inject_device { 69 84 struct hrtimer timer; 70 85 unsigned int idle_duration_us; 71 86 unsigned int run_duration_us; 72 87 unsigned int latency_us; 88 + bool (*update)(void); 73 89 unsigned long cpumask[]; 74 90 }; 75 91 ··· 127 111 struct idle_inject_device *ii_dev = 128 112 container_of(timer, struct idle_inject_device, timer); 129 113 114 + if (!ii_dev->update || (ii_dev->update && ii_dev->update())) 115 + idle_inject_wakeup(ii_dev); 116 + 130 117 duration_us = READ_ONCE(ii_dev->run_duration_us); 131 118 duration_us += READ_ONCE(ii_dev->idle_duration_us); 132 - 133 - idle_inject_wakeup(ii_dev); 134 119 135 120 hrtimer_forward_now(timer, ns_to_ktime(duration_us * NSEC_PER_USEC)); 136 121 ··· 179 162 if (!run_duration_us) 180 163 pr_debug("CPU is forced to 100 percent idle\n"); 181 164 } 165 + EXPORT_SYMBOL_NS_GPL(idle_inject_set_duration, IDLE_INJECT); 182 166 183 167 /** 184 168 * idle_inject_get_duration - idle and run duration retrieval helper ··· 194 176 *run_duration_us = READ_ONCE(ii_dev->run_duration_us); 195 177 *idle_duration_us = READ_ONCE(ii_dev->idle_duration_us); 196 178 } 179 + EXPORT_SYMBOL_NS_GPL(idle_inject_get_duration, IDLE_INJECT); 197 180 198 181 /** 199 182 * idle_inject_set_latency - set the maximum latency allowed ··· 206 187 { 207 188 WRITE_ONCE(ii_dev->latency_us, latency_us); 208 189 } 190 + EXPORT_SYMBOL_NS_GPL(idle_inject_set_latency, IDLE_INJECT); 209 191 210 192 /** 211 193 * idle_inject_start - start idle injections ··· 238 218 239 219 return 0; 240 220 } 221 + EXPORT_SYMBOL_NS_GPL(idle_inject_start, IDLE_INJECT); 241 222 242 223 /** 243 224 * idle_inject_stop - stops idle injections ··· 285 264 286 265 cpu_hotplug_enable(); 287 266 } 267 + EXPORT_SYMBOL_NS_GPL(idle_inject_stop, IDLE_INJECT); 288 268 289 269 /** 290 270 * idle_inject_setup - prepare the current task for idle injection ··· 314 292 } 315 293 316 294 /** 317 - * idle_inject_register - initialize idle injection on a set of CPUs 295 + * idle_inject_register_full - initialize idle injection on a set of CPUs 318 296 * @cpumask: CPUs to be affected by idle injection 297 + * @update: This callback is called just before waking up CPUs to inject 298 + * idle 319 299 * 320 300 * This function creates an idle injection control device structure for the 321 - * given set of CPUs and initializes the timer associated with it. It does not 322 - * start any injection cycles. 301 + * given set of CPUs and initializes the timer associated with it. This 302 + * function also allows to register update()callback. 303 + * It does not start any injection cycles. 323 304 * 324 305 * Return: NULL if memory allocation fails, idle injection control device 325 306 * pointer on success. 326 307 */ 327 - struct idle_inject_device *idle_inject_register(struct cpumask *cpumask) 308 + 309 + struct idle_inject_device *idle_inject_register_full(struct cpumask *cpumask, 310 + bool (*update)(void)) 328 311 { 329 312 struct idle_inject_device *ii_dev; 330 313 int cpu, cpu_rb; ··· 342 315 hrtimer_init(&ii_dev->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 343 316 ii_dev->timer.function = idle_inject_timer_fn; 344 317 ii_dev->latency_us = UINT_MAX; 318 + ii_dev->update = update; 345 319 346 320 for_each_cpu(cpu, to_cpumask(ii_dev->cpumask)) { 347 321 ··· 367 339 368 340 return NULL; 369 341 } 342 + EXPORT_SYMBOL_NS_GPL(idle_inject_register_full, IDLE_INJECT); 343 + 344 + /** 345 + * idle_inject_register - initialize idle injection on a set of CPUs 346 + * @cpumask: CPUs to be affected by idle injection 347 + * 348 + * This function creates an idle injection control device structure for the 349 + * given set of CPUs and initializes the timer associated with it. It does not 350 + * start any injection cycles. 351 + * 352 + * Return: NULL if memory allocation fails, idle injection control device 353 + * pointer on success. 354 + */ 355 + struct idle_inject_device *idle_inject_register(struct cpumask *cpumask) 356 + { 357 + return idle_inject_register_full(cpumask, NULL); 358 + } 359 + EXPORT_SYMBOL_NS_GPL(idle_inject_register, IDLE_INJECT); 370 360 371 361 /** 372 362 * idle_inject_unregister - unregister idle injection control device ··· 405 359 406 360 kfree(ii_dev); 407 361 } 362 + EXPORT_SYMBOL_NS_GPL(idle_inject_unregister, IDLE_INJECT); 408 363 409 364 static struct smp_hotplug_thread idle_inject_threads = { 410 365 .store = &idle_inject_thread.tsk,
+8 -10
drivers/thermal/Kconfig
··· 76 76 Say 'Y' here if you need to build thermal infrastructure 77 77 based on device tree. 78 78 79 + config THERMAL_ACPI 80 + depends on ACPI 81 + bool 82 + 79 83 config THERMAL_WRITABLE_TRIPS 80 84 bool "Enable writable trip points" 81 85 help ··· 416 412 zone. 417 413 Compatible with the DA9062 and DA9061 PMICs. 418 414 419 - config MTK_THERMAL 420 - tristate "Temperature sensor driver for mediatek SoCs" 421 - depends on ARCH_MEDIATEK || COMPILE_TEST 422 - depends on HAS_IOMEM 423 - depends on NVMEM || NVMEM=n 424 - depends on RESET_CONTROLLER 425 - default y 426 - help 427 - Enable this option if you want to have support for thermal management 428 - controller present in Mediatek SoCs 415 + menu "Mediatek thermal drivers" 416 + depends on ARCH_MEDIATEK || COMPILE_TEST 417 + source "drivers/thermal/mediatek/Kconfig" 418 + endmenu 429 419 430 420 config AMLOGIC_THERMAL 431 421 tristate "Amlogic Thermal Support"
+4 -3
drivers/thermal/Makefile
··· 4 4 # 5 5 6 6 obj-$(CONFIG_THERMAL) += thermal_sys.o 7 - thermal_sys-y += thermal_core.o thermal_sysfs.o \ 8 - thermal_helpers.o 7 + thermal_sys-y += thermal_core.o thermal_sysfs.o 8 + thermal_sys-y += thermal_trip.o thermal_helpers.o 9 9 10 10 # netlink interface to manage the thermal framework 11 11 thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o ··· 13 13 # interface to/from other layers providing sensors 14 14 thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o 15 15 thermal_sys-$(CONFIG_THERMAL_OF) += thermal_of.o 16 + thermal_sys-$(CONFIG_THERMAL_ACPI) += thermal_acpi.o 16 17 17 18 # governors 18 19 thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += gov_fair_share.o ··· 56 55 obj-y += qcom/ 57 56 obj-y += tegra/ 58 57 obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o 59 - obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o 58 + obj-y += mediatek/ 60 59 obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o 61 60 obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o 62 61 obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o
-1
drivers/thermal/amlogic_thermal.c
··· 28 28 #include <linux/regmap.h> 29 29 #include <linux/thermal.h> 30 30 31 - #include "thermal_core.h" 32 31 #include "thermal_hwmon.h" 33 32 34 33 #define TSENSOR_CFG_REG1 0x4
+10 -22
drivers/thermal/armada_thermal.c
··· 19 19 #include <linux/regmap.h> 20 20 #include <linux/interrupt.h> 21 21 22 - #include "thermal_core.h" 23 - 24 22 /* Thermal Manager Control and Status Register */ 25 23 #define PMU_TDC0_SW_RST_MASK (0x1 << 1) 26 24 #define PMU_TM_DISABLE_OFFS 0 ··· 707 709 struct armada_thermal_priv *priv) 708 710 { 709 711 struct armada_thermal_data *data = priv->data; 710 - struct resource *res; 711 712 void __iomem *base; 712 713 713 714 /* First memory region points towards the status register */ 714 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 715 - base = devm_ioremap_resource(&pdev->dev, res); 715 + base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 716 716 if (IS_ERR(base)) 717 717 return PTR_ERR(base); 718 718 ··· 757 761 } 758 762 759 763 /* Save the name locally */ 760 - strncpy(priv->zone_name, name, THERMAL_NAME_LENGTH - 1); 761 - priv->zone_name[THERMAL_NAME_LENGTH - 1] = '\0'; 764 + strscpy(priv->zone_name, name, THERMAL_NAME_LENGTH); 762 765 763 766 /* Then check there are no '-' or hwmon core will complain */ 764 767 do { ··· 780 785 int sensor_id) 781 786 { 782 787 /* Retrieve the critical trip point to enable the overheat interrupt */ 783 - const struct thermal_trip *trips = of_thermal_get_trip_points(tz); 788 + int temperature; 784 789 int ret; 785 - int i; 786 790 787 - if (!trips) 788 - return -EINVAL; 789 - 790 - for (i = 0; i < of_thermal_get_ntrips(tz); i++) 791 - if (trips[i].type == THERMAL_TRIP_CRITICAL) 792 - break; 793 - 794 - if (i == of_thermal_get_ntrips(tz)) 795 - return -EINVAL; 791 + ret = thermal_zone_get_crit_temp(tz, &temperature); 792 + if (ret) 793 + return ret; 796 794 797 795 ret = armada_select_channel(priv, sensor_id); 798 796 if (ret) 799 797 return ret; 800 798 801 - armada_set_overheat_thresholds(priv, 802 - trips[i].temperature, 803 - trips[i].hysteresis); 799 + /* 800 + * A critical temperature does not have a hysteresis 801 + */ 802 + armada_set_overheat_thresholds(priv, temperature, 0); 804 803 priv->overheat_sensor = tz; 805 804 priv->interrupt_source = sensor_id; 806 - 807 805 armada_enable_overheat_interrupt(priv); 808 806 809 807 return 0;
+5 -6
drivers/thermal/broadcom/bcm2835_thermal.c
··· 166 166 const struct of_device_id *match; 167 167 struct thermal_zone_device *tz; 168 168 struct bcm2835_thermal_data *data; 169 - struct resource *res; 170 169 int err = 0; 171 170 u32 val; 172 171 unsigned long rate; ··· 179 180 if (!match) 180 181 return -EINVAL; 181 182 182 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 183 - data->regs = devm_ioremap_resource(&pdev->dev, res); 183 + data->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 184 184 if (IS_ERR(data->regs)) { 185 185 err = PTR_ERR(data->regs); 186 186 return err; ··· 222 224 */ 223 225 val = readl(data->regs + BCM2835_TS_TSENSCTL); 224 226 if (!(val & BCM2835_TS_TSENSCTL_RSTB)) { 225 - int trip_temp, offset, slope; 227 + struct thermal_trip trip; 228 + int offset, slope; 226 229 227 230 slope = thermal_zone_get_slope(tz); 228 231 offset = thermal_zone_get_offset(tz); ··· 231 232 * For now we deal only with critical, otherwise 232 233 * would need to iterate 233 234 */ 234 - err = tz->ops->get_trip_temp(tz, 0, &trip_temp); 235 + err = thermal_zone_get_trip(tz, 0, &trip); 235 236 if (err < 0) { 236 237 dev_err(&pdev->dev, 237 238 "Not able to read trip_temp: %d\n", ··· 248 249 val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT); 249 250 250 251 /* trip_adc value from info */ 251 - val |= bcm2835_thermal_temp2adc(trip_temp, 252 + val |= bcm2835_thermal_temp2adc(trip.temperature, 252 253 offset, 253 254 slope) 254 255 << BCM2835_TS_TSENSCTL_THOLD_SHIFT;
+1 -3
drivers/thermal/broadcom/brcmstb_thermal.c
··· 321 321 const struct thermal_zone_device_ops *of_ops; 322 322 struct thermal_zone_device *thermal; 323 323 struct brcmstb_thermal_priv *priv; 324 - struct resource *res; 325 324 int irq, ret; 326 325 327 326 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ··· 331 332 if (!priv->temp_params) 332 333 return -EINVAL; 333 334 334 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 335 - priv->tmon_base = devm_ioremap_resource(&pdev->dev, res); 335 + priv->tmon_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 336 336 if (IS_ERR(priv->tmon_base)) 337 337 return PTR_ERR(priv->tmon_base); 338 338
+8 -44
drivers/thermal/da9062-thermal.c
··· 120 120 return IRQ_HANDLED; 121 121 } 122 122 123 - static int da9062_thermal_get_trip_type(struct thermal_zone_device *z, 124 - int trip, 125 - enum thermal_trip_type *type) 126 - { 127 - struct da9062_thermal *thermal = z->devdata; 128 - 129 - switch (trip) { 130 - case 0: 131 - *type = THERMAL_TRIP_HOT; 132 - break; 133 - default: 134 - dev_err(thermal->dev, 135 - "Driver does not support more than 1 trip-wire\n"); 136 - return -EINVAL; 137 - } 138 - 139 - return 0; 140 - } 141 - 142 - static int da9062_thermal_get_trip_temp(struct thermal_zone_device *z, 143 - int trip, 144 - int *temp) 145 - { 146 - struct da9062_thermal *thermal = z->devdata; 147 - 148 - switch (trip) { 149 - case 0: 150 - *temp = DA9062_MILLI_CELSIUS(125); 151 - break; 152 - default: 153 - dev_err(thermal->dev, 154 - "Driver does not support more than 1 trip-wire\n"); 155 - return -EINVAL; 156 - } 157 - 158 - return 0; 159 - } 160 - 161 123 static int da9062_thermal_get_temp(struct thermal_zone_device *z, 162 124 int *temp) 163 125 { ··· 134 172 135 173 static struct thermal_zone_device_ops da9062_thermal_ops = { 136 174 .get_temp = da9062_thermal_get_temp, 137 - .get_trip_type = da9062_thermal_get_trip_type, 138 - .get_trip_temp = da9062_thermal_get_trip_temp, 175 + }; 176 + 177 + static struct thermal_trip trips[] = { 178 + { .temperature = DA9062_MILLI_CELSIUS(125), .type = THERMAL_TRIP_HOT }, 139 179 }; 140 180 141 181 static const struct da9062_thermal_config da9062_config = { ··· 192 228 INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on); 193 229 mutex_init(&thermal->lock); 194 230 195 - thermal->zone = thermal_zone_device_register(thermal->config->name, 196 - 1, 0, thermal, 197 - &da9062_thermal_ops, NULL, pp_tmp, 198 - 0); 231 + thermal->zone = thermal_zone_device_register_with_trips(thermal->config->name, 232 + trips, ARRAY_SIZE(trips), 0, thermal, 233 + &da9062_thermal_ops, NULL, pp_tmp, 234 + 0); 199 235 if (IS_ERR(thermal->zone)) { 200 236 dev_err(&pdev->dev, "Cannot register thermal zone device\n"); 201 237 ret = PTR_ERR(thermal->zone);
+2 -5
drivers/thermal/dove_thermal.c
··· 122 122 { 123 123 struct thermal_zone_device *thermal = NULL; 124 124 struct dove_thermal_priv *priv; 125 - struct resource *res; 126 125 int ret; 127 126 128 127 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 129 128 if (!priv) 130 129 return -ENOMEM; 131 130 132 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 133 - priv->sensor = devm_ioremap_resource(&pdev->dev, res); 131 + priv->sensor = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 134 132 if (IS_ERR(priv->sensor)) 135 133 return PTR_ERR(priv->sensor); 136 134 137 - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 138 - priv->control = devm_ioremap_resource(&pdev->dev, res); 135 + priv->control = devm_platform_get_and_ioremap_resource(pdev, 1, NULL); 139 136 if (IS_ERR(priv->control)) 140 137 return PTR_ERR(priv->control); 141 138
+22 -15
drivers/thermal/gov_bang_bang.c
··· 13 13 14 14 #include "thermal_core.h" 15 15 16 - static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) 16 + static int thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id) 17 17 { 18 - int trip_temp, trip_hyst; 18 + struct thermal_trip trip; 19 19 struct thermal_instance *instance; 20 + int ret; 20 21 21 - tz->ops->get_trip_temp(tz, trip, &trip_temp); 22 + ret = __thermal_zone_get_trip(tz, trip_id, &trip); 23 + if (ret) { 24 + pr_warn_once("Failed to retrieve trip point %d\n", trip_id); 25 + return ret; 26 + } 22 27 23 - if (!tz->ops->get_trip_hyst) { 24 - pr_warn_once("Undefined get_trip_hyst for thermal zone %s - " 25 - "running with default hysteresis zero\n", tz->type); 26 - trip_hyst = 0; 27 - } else 28 - tz->ops->get_trip_hyst(tz, trip, &trip_hyst); 28 + if (!trip.hysteresis) 29 + dev_info_once(&tz->device, 30 + "Zero hysteresis value for thermal zone %s\n", tz->type); 29 31 30 32 dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", 31 - trip, trip_temp, tz->temperature, 32 - trip_hyst); 33 + trip_id, trip.temperature, tz->temperature, 34 + trip.hysteresis); 33 35 34 36 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 35 - if (instance->trip != trip) 37 + if (instance->trip != trip_id) 36 38 continue; 37 39 38 40 /* in case fan is in initial state, switch the fan off */ ··· 52 50 * enable fan when temperature exceeds trip_temp and disable 53 51 * the fan in case it falls below trip_temp minus hysteresis 54 52 */ 55 - if (instance->target == 0 && tz->temperature >= trip_temp) 53 + if (instance->target == 0 && tz->temperature >= trip.temperature) 56 54 instance->target = 1; 57 55 else if (instance->target == 1 && 58 - tz->temperature <= trip_temp - trip_hyst) 56 + tz->temperature <= trip.temperature - trip.hysteresis) 59 57 instance->target = 0; 60 58 61 59 dev_dbg(&instance->cdev->device, "target=%d\n", ··· 65 63 instance->cdev->updated = false; /* cdev needs update */ 66 64 mutex_unlock(&instance->cdev->lock); 67 65 } 66 + 67 + return 0; 68 68 } 69 69 70 70 /** ··· 99 95 static int bang_bang_control(struct thermal_zone_device *tz, int trip) 100 96 { 101 97 struct thermal_instance *instance; 98 + int ret; 102 99 103 100 lockdep_assert_held(&tz->lock); 104 101 105 - thermal_zone_trip_update(tz, trip); 102 + ret = thermal_zone_trip_update(tz, trip); 103 + if (ret) 104 + return ret; 106 105 107 106 list_for_each_entry(instance, &tz->thermal_instances, tz_node) 108 107 thermal_cdev_update(instance->cdev);
+6 -12
drivers/thermal/gov_fair_share.c
··· 21 21 */ 22 22 static int get_trip_level(struct thermal_zone_device *tz) 23 23 { 24 - int count = 0; 25 - int trip_temp; 26 - enum thermal_trip_type trip_type; 27 - 28 - if (tz->num_trips == 0 || !tz->ops->get_trip_temp) 29 - return 0; 24 + struct thermal_trip trip; 25 + int count; 30 26 31 27 for (count = 0; count < tz->num_trips; count++) { 32 - tz->ops->get_trip_temp(tz, count, &trip_temp); 33 - if (tz->temperature < trip_temp) 28 + __thermal_zone_get_trip(tz, count, &trip); 29 + if (tz->temperature < trip.temperature) 34 30 break; 35 31 } 36 32 ··· 34 38 * count > 0 only if temperature is greater than first trip 35 39 * point, in which case, trip_point = count - 1 36 40 */ 37 - if (count > 0) { 38 - tz->ops->get_trip_type(tz, count - 1, &trip_type); 39 - trace_thermal_zone_trip(tz, count - 1, trip_type); 40 - } 41 + if (count > 0) 42 + trace_thermal_zone_trip(tz, count - 1, trip.type); 41 43 42 44 return count; 43 45 }
+23 -28
drivers/thermal/gov_power_allocator.c
··· 124 124 u32 sustainable_power, int trip_switch_on, 125 125 int control_temp) 126 126 { 127 + struct thermal_trip trip; 128 + u32 temperature_threshold = control_temp; 127 129 int ret; 128 - int switch_on_temp; 129 - u32 temperature_threshold; 130 130 s32 k_i; 131 131 132 - ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp); 133 - if (ret) 134 - switch_on_temp = 0; 132 + ret = __thermal_zone_get_trip(tz, trip_switch_on, &trip); 133 + if (!ret) 134 + temperature_threshold -= trip.temperature; 135 135 136 - temperature_threshold = control_temp - switch_on_temp; 137 136 /* 138 137 * estimate_pid_constants() tries to find appropriate default 139 138 * values for thermal zones that don't provide them. If a ··· 518 519 last_passive = INVALID_TRIP; 519 520 520 521 for (i = 0; i < tz->num_trips; i++) { 521 - enum thermal_trip_type type; 522 + struct thermal_trip trip; 522 523 int ret; 523 524 524 - ret = tz->ops->get_trip_type(tz, i, &type); 525 + ret = __thermal_zone_get_trip(tz, i, &trip); 525 526 if (ret) { 526 527 dev_warn(&tz->device, 527 528 "Failed to get trip point %d type: %d\n", i, ··· 529 530 continue; 530 531 } 531 532 532 - if (type == THERMAL_TRIP_PASSIVE) { 533 + if (trip.type == THERMAL_TRIP_PASSIVE) { 533 534 if (!found_first_passive) { 534 535 params->trip_switch_on = i; 535 536 found_first_passive = true; 536 537 } else { 537 538 last_passive = i; 538 539 } 539 - } else if (type == THERMAL_TRIP_ACTIVE) { 540 + } else if (trip.type == THERMAL_TRIP_ACTIVE) { 540 541 last_active = i; 541 542 } else { 542 543 break; ··· 631 632 { 632 633 int ret; 633 634 struct power_allocator_params *params; 634 - int control_temp; 635 + struct thermal_trip trip; 635 636 636 637 ret = check_power_actors(tz); 637 638 if (ret) ··· 657 658 get_governor_trips(tz, params); 658 659 659 660 if (tz->num_trips > 0) { 660 - ret = tz->ops->get_trip_temp(tz, 661 - params->trip_max_desired_temperature, 662 - &control_temp); 661 + ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature, 662 + &trip); 663 663 if (!ret) 664 664 estimate_pid_constants(tz, tz->tzp->sustainable_power, 665 665 params->trip_switch_on, 666 - control_temp); 666 + trip.temperature); 667 667 } 668 668 669 669 reset_pid_controller(params); ··· 692 694 tz->governor_data = NULL; 693 695 } 694 696 695 - static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) 697 + static int power_allocator_throttle(struct thermal_zone_device *tz, int trip_id) 696 698 { 697 - int ret; 698 - int switch_on_temp, control_temp; 699 699 struct power_allocator_params *params = tz->governor_data; 700 + struct thermal_trip trip; 701 + int ret; 700 702 bool update; 701 703 702 704 lockdep_assert_held(&tz->lock); ··· 705 707 * We get called for every trip point but we only need to do 706 708 * our calculations once 707 709 */ 708 - if (trip != params->trip_max_desired_temperature) 710 + if (trip_id != params->trip_max_desired_temperature) 709 711 return 0; 710 712 711 - ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, 712 - &switch_on_temp); 713 - if (!ret && (tz->temperature < switch_on_temp)) { 714 - update = (tz->last_temperature >= switch_on_temp); 713 + ret = __thermal_zone_get_trip(tz, params->trip_switch_on, &trip); 714 + if (!ret && (tz->temperature < trip.temperature)) { 715 + update = (tz->last_temperature >= trip.temperature); 715 716 tz->passive = 0; 716 717 reset_pid_controller(params); 717 718 allow_maximum_power(tz, update); ··· 719 722 720 723 tz->passive = 1; 721 724 722 - ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature, 723 - &control_temp); 725 + ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature, &trip); 724 726 if (ret) { 725 - dev_warn(&tz->device, 726 - "Failed to get the maximum desired temperature: %d\n", 727 + dev_warn(&tz->device, "Failed to get the maximum desired temperature: %d\n", 727 728 ret); 728 729 return ret; 729 730 } 730 731 731 - return allocate_power(tz, control_temp); 732 + return allocate_power(tz, trip.temperature); 732 733 } 733 734 734 735 static struct thermal_governor thermal_gov_power_allocator = {
+10 -12
drivers/thermal/gov_step_wise.c
··· 95 95 tz->passive += value; 96 96 } 97 97 98 - static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) 98 + static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id) 99 99 { 100 - int trip_temp; 101 - enum thermal_trip_type trip_type; 102 100 enum thermal_trend trend; 103 101 struct thermal_instance *instance; 102 + struct thermal_trip trip; 104 103 bool throttle = false; 105 104 int old_target; 106 105 107 - tz->ops->get_trip_temp(tz, trip, &trip_temp); 108 - tz->ops->get_trip_type(tz, trip, &trip_type); 106 + __thermal_zone_get_trip(tz, trip_id, &trip); 109 107 110 - trend = get_tz_trend(tz, trip); 108 + trend = get_tz_trend(tz, trip_id); 111 109 112 - if (tz->temperature >= trip_temp) { 110 + if (tz->temperature >= trip.temperature) { 113 111 throttle = true; 114 - trace_thermal_zone_trip(tz, trip, trip_type); 112 + trace_thermal_zone_trip(tz, trip_id, trip.type); 115 113 } 116 114 117 115 dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", 118 - trip, trip_type, trip_temp, trend, throttle); 116 + trip_id, trip.type, trip.temperature, trend, throttle); 119 117 120 118 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 121 - if (instance->trip != trip) 119 + if (instance->trip != trip_id) 122 120 continue; 123 121 124 122 old_target = instance->target; ··· 130 132 /* Activate a passive thermal instance */ 131 133 if (old_target == THERMAL_NO_TARGET && 132 134 instance->target != THERMAL_NO_TARGET) 133 - update_passive_instance(tz, trip_type, 1); 135 + update_passive_instance(tz, trip.type, 1); 134 136 /* Deactivate a passive thermal instance */ 135 137 else if (old_target != THERMAL_NO_TARGET && 136 138 instance->target == THERMAL_NO_TARGET) 137 - update_passive_instance(tz, trip_type, -1); 139 + update_passive_instance(tz, trip.type, -1); 138 140 139 141 instance->initialized = true; 140 142 mutex_lock(&instance->cdev->lock);
+7 -11
drivers/thermal/hisi_thermal.c
··· 16 16 #include <linux/platform_device.h> 17 17 #include <linux/io.h> 18 18 #include <linux/of_device.h> 19 - 20 - #include "thermal_core.h" 19 + #include <linux/thermal.h> 21 20 22 21 #define HI6220_TEMP0_LAG (0x0) 23 22 #define HI6220_TEMP0_TH (0x4) ··· 426 427 data->sensor[0].irq_name = "tsensor_a73"; 427 428 data->sensor[0].data = data; 428 429 429 - data->sensor[1].id = HI3660_LITTLE_SENSOR; 430 - data->sensor[1].irq_name = "tsensor_a53"; 431 - data->sensor[1].data = data; 432 - 433 430 return 0; 434 431 } 435 432 ··· 477 482 struct hisi_thermal_sensor *sensor) 478 483 { 479 484 int ret, i; 480 - const struct thermal_trip *trip; 485 + struct thermal_trip trip; 481 486 482 487 sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, 483 488 sensor->id, sensor, ··· 490 495 return ret; 491 496 } 492 497 493 - trip = of_thermal_get_trip_points(sensor->tzd); 498 + for (i = 0; i < thermal_zone_get_num_trips(sensor->tzd); i++) { 494 499 495 - for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { 496 - if (trip[i].type == THERMAL_TRIP_PASSIVE) { 497 - sensor->thres_temp = trip[i].temperature; 500 + thermal_zone_get_trip(sensor->tzd, i, &trip); 501 + 502 + if (trip.type == THERMAL_TRIP_PASSIVE) { 503 + sensor->thres_temp = trip.temperature; 498 504 break; 499 505 } 500 506 }
-1
drivers/thermal/imx8mm_thermal.c
··· 17 17 #include <linux/slab.h> 18 18 #include <linux/thermal.h> 19 19 20 - #include "thermal_core.h" 21 20 #include "thermal_hwmon.h" 22 21 23 22 #define TER 0x0 /* TMU enable */
+6 -3
drivers/thermal/imx_sc_thermal.c
··· 13 13 #include <linux/slab.h> 14 14 #include <linux/thermal.h> 15 15 16 - #include "thermal_core.h" 17 16 #include "thermal_hwmon.h" 18 17 19 18 #define IMX_SC_MISC_FUNC_GET_TEMP 13 ··· 87 88 if (!resource_id) 88 89 return -EINVAL; 89 90 90 - for (i = 0; resource_id[i] > 0; i++) { 91 + for (i = 0; resource_id[i] >= 0; i++) { 91 92 92 93 sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL); 93 94 if (!sensor) ··· 126 127 return 0; 127 128 } 128 129 129 - static int imx_sc_sensors[] = { IMX_SC_R_SYSTEM, IMX_SC_R_PMIC_0, -1 }; 130 + static const int imx_sc_sensors[] = { 131 + IMX_SC_R_SYSTEM, IMX_SC_R_PMIC_0, 132 + IMX_SC_R_AP_0, IMX_SC_R_AP_1, 133 + IMX_SC_R_GPU_0_PID0, IMX_SC_R_GPU_1_PID0, 134 + IMX_SC_R_DRC_0, -1 }; 130 135 131 136 static const struct of_device_id imx_sc_thermal_table[] = { 132 137 { .compatible = "fsl,imx-sc-thermal", .data = imx_sc_sensors },
+27 -45
drivers/thermal/imx_thermal.c
··· 76 76 enum imx_thermal_trip { 77 77 IMX_TRIP_PASSIVE, 78 78 IMX_TRIP_CRITICAL, 79 - IMX_TRIP_NUM, 80 79 }; 81 80 82 81 #define IMX_POLLING_DELAY 2000 /* millisecond */ ··· 112 113 u32 low_alarm_ctrl; 113 114 u32 low_alarm_mask; 114 115 u32 low_alarm_shift; 116 + }; 117 + 118 + static struct thermal_trip trips[] = { 119 + [IMX_TRIP_PASSIVE] = { .type = THERMAL_TRIP_PASSIVE }, 120 + [IMX_TRIP_CRITICAL] = { .type = THERMAL_TRIP_CRITICAL }, 115 121 }; 116 122 117 123 static struct thermal_soc_data thermal_imx6q_data = { ··· 205 201 struct thermal_cooling_device *cdev; 206 202 struct regmap *tempmon; 207 203 u32 c1, c2; /* See formula in imx_init_calib() */ 208 - int temp_passive; 209 - int temp_critical; 210 204 int temp_max; 211 205 int alarm_temp; 212 206 int last_temp; ··· 281 279 282 280 /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */ 283 281 if (data->socdata->version == TEMPMON_IMX6Q) { 284 - if (data->alarm_temp == data->temp_passive && 285 - *temp >= data->temp_passive) 286 - imx_set_alarm_temp(data, data->temp_critical); 287 - if (data->alarm_temp == data->temp_critical && 288 - *temp < data->temp_passive) { 289 - imx_set_alarm_temp(data, data->temp_passive); 282 + if (data->alarm_temp == trips[IMX_TRIP_PASSIVE].temperature && 283 + *temp >= trips[IMX_TRIP_PASSIVE].temperature) 284 + imx_set_alarm_temp(data, trips[IMX_TRIP_CRITICAL].temperature); 285 + if (data->alarm_temp == trips[IMX_TRIP_CRITICAL].temperature && 286 + *temp < trips[IMX_TRIP_PASSIVE].temperature) { 287 + imx_set_alarm_temp(data, trips[IMX_TRIP_PASSIVE].temperature); 290 288 dev_dbg(&tz->device, "thermal alarm off: T < %d\n", 291 289 data->alarm_temp / 1000); 292 290 } ··· 332 330 return 0; 333 331 } 334 332 335 - static int imx_get_trip_type(struct thermal_zone_device *tz, int trip, 336 - enum thermal_trip_type *type) 337 - { 338 - *type = (trip == IMX_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE : 339 - THERMAL_TRIP_CRITICAL; 340 - return 0; 341 - } 342 - 343 333 static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp) 344 334 { 345 - struct imx_thermal_data *data = tz->devdata; 335 + *temp = trips[IMX_TRIP_CRITICAL].temperature; 346 336 347 - *temp = data->temp_critical; 348 - return 0; 349 - } 350 - 351 - static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip, 352 - int *temp) 353 - { 354 - struct imx_thermal_data *data = tz->devdata; 355 - 356 - *temp = (trip == IMX_TRIP_PASSIVE) ? data->temp_passive : 357 - data->temp_critical; 358 337 return 0; 359 338 } 360 339 ··· 354 371 return -EPERM; 355 372 356 373 /* do not allow passive to be set higher than critical */ 357 - if (temp < 0 || temp > data->temp_critical) 374 + if (temp < 0 || temp > trips[IMX_TRIP_CRITICAL].temperature) 358 375 return -EINVAL; 359 376 360 - data->temp_passive = temp; 377 + trips[IMX_TRIP_PASSIVE].temperature = temp; 361 378 362 379 imx_set_alarm_temp(data, temp); 363 380 ··· 406 423 .unbind = imx_unbind, 407 424 .get_temp = imx_get_temp, 408 425 .change_mode = imx_change_mode, 409 - .get_trip_type = imx_get_trip_type, 410 - .get_trip_temp = imx_get_trip_temp, 411 426 .get_crit_temp = imx_get_crit_temp, 412 427 .set_trip_temp = imx_set_trip_temp, 413 428 }; ··· 488 507 * Set the critical trip point at 5 °C under max 489 508 * Set the passive trip point at 10 °C under max (changeable via sysfs) 490 509 */ 491 - data->temp_critical = data->temp_max - (1000 * 5); 492 - data->temp_passive = data->temp_max - (1000 * 10); 510 + trips[IMX_TRIP_PASSIVE].temperature = data->temp_max - (1000 * 10); 511 + trips[IMX_TRIP_CRITICAL].temperature = data->temp_max - (1000 * 5); 493 512 } 494 513 495 514 static int imx_init_from_tempmon_data(struct platform_device *pdev) ··· 724 743 goto legacy_cleanup; 725 744 } 726 745 727 - data->tz = thermal_zone_device_register("imx_thermal_zone", 728 - IMX_TRIP_NUM, 729 - BIT(IMX_TRIP_PASSIVE), data, 730 - &imx_tz_ops, NULL, 731 - IMX_PASSIVE_DELAY, 732 - IMX_POLLING_DELAY); 746 + data->tz = thermal_zone_device_register_with_trips("imx_thermal_zone", 747 + trips, 748 + ARRAY_SIZE(trips), 749 + BIT(IMX_TRIP_PASSIVE), data, 750 + &imx_tz_ops, NULL, 751 + IMX_PASSIVE_DELAY, 752 + IMX_POLLING_DELAY); 733 753 if (IS_ERR(data->tz)) { 734 754 ret = PTR_ERR(data->tz); 735 755 dev_err(&pdev->dev, ··· 740 758 741 759 dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC" 742 760 " critical:%dC passive:%dC\n", data->temp_grade, 743 - data->temp_max / 1000, data->temp_critical / 1000, 744 - data->temp_passive / 1000); 761 + data->temp_max / 1000, trips[IMX_TRIP_CRITICAL].temperature / 1000, 762 + trips[IMX_TRIP_PASSIVE].temperature / 1000); 745 763 746 764 /* Enable measurements at ~ 10 Hz */ 747 765 regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR, ··· 749 767 measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */ 750 768 regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET, 751 769 measure_freq << data->socdata->measure_freq_shift); 752 - imx_set_alarm_temp(data, data->temp_passive); 770 + imx_set_alarm_temp(data, trips[IMX_TRIP_PASSIVE].temperature); 753 771 754 772 if (data->socdata->version == TEMPMON_IMX6SX) 755 - imx_set_panic_temp(data, data->temp_critical); 773 + imx_set_panic_temp(data, trips[IMX_TRIP_CRITICAL].temperature); 756 774 757 775 regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, 758 776 data->socdata->power_down_mask);
+11
drivers/thermal/intel/Kconfig
··· 3 3 tristate "Intel PowerClamp idle injection driver" 4 4 depends on X86 5 5 depends on CPU_SUP_INTEL 6 + depends on CPU_IDLE 7 + select POWERCAP 8 + select IDLE_INJECT 6 9 help 7 10 Enable this to enable Intel PowerClamp idle injection driver. This 8 11 enforce idle time which results in more package C-state residency. The ··· 15 12 def_bool y 16 13 depends on X86 && CPU_SUP_INTEL && X86_LOCAL_APIC 17 14 15 + config INTEL_TCC 16 + bool 17 + depends on X86 18 + 18 19 config X86_PKG_TEMP_THERMAL 19 20 tristate "X86 package temperature thermal driver" 20 21 depends on X86_THERMAL_VECTOR 21 22 select THERMAL_GOV_USER_SPACE 22 23 select THERMAL_WRITABLE_TRIPS 24 + select INTEL_TCC 23 25 default m 24 26 help 25 27 Enable this to register CPU digital sensor for package temperature as ··· 36 28 tristate 37 29 depends on X86 && PCI 38 30 select IOSF_MBI 31 + select INTEL_TCC 39 32 help 40 33 This is becoming a common feature for Intel SoCs to expose the additional 41 34 digital temperature sensors (DTSs) using side band interface (IOSF). This ··· 84 75 config INTEL_PCH_THERMAL 85 76 tristate "Intel PCH Thermal Reporting Driver" 86 77 depends on X86 && PCI 78 + select THERMAL_ACPI if ACPI 87 79 help 88 80 Enable this to support thermal reporting on certain intel PCHs. 89 81 Thermal reporting device will provide temperature reading, ··· 93 83 config INTEL_TCC_COOLING 94 84 tristate "Intel TCC offset cooling Driver" 95 85 depends on X86 86 + select INTEL_TCC 96 87 help 97 88 Enable this to support system cooling by adjusting the effective TCC 98 89 activation temperature via the TCC Offset register, which is widely
+1
drivers/thermal/intel/Makefile
··· 2 2 # 3 3 # Makefile for various Intel thermal drivers. 4 4 5 + obj-$(CONFIG_INTEL_TCC) += intel_tcc.o 5 6 obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 6 7 obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o 7 8 obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
+2
drivers/thermal/intel/int340x_thermal/Kconfig
··· 9 9 select THERMAL_GOV_USER_SPACE 10 10 select ACPI_THERMAL_REL 11 11 select ACPI_FAN 12 + select THERMAL_ACPI 12 13 select INTEL_SOC_DTS_IOSF_CORE 14 + select INTEL_TCC 13 15 select PROC_THERMAL_MMIO_RAPL if POWERCAP 14 16 help 15 17 Newer laptops and tablets that use ACPI may have thermal sensors and
+50 -8
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
··· 60 60 int odvp_count; 61 61 int *odvp; 62 62 u32 os_uuid_mask; 63 + int production_mode; 63 64 struct odvp_attr *odvp_attrs; 64 65 }; 65 66 ··· 131 130 132 131 for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) { 133 132 if (priv->uuid_bitmap & (1 << i)) 134 - length += scnprintf(&buf[length], 135 - PAGE_SIZE - length, 136 - "%s\n", 137 - int3400_thermal_uuids[i]); 133 + length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]); 138 134 } 139 135 140 136 return length; ··· 149 151 150 152 for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) { 151 153 if (priv->os_uuid_mask & BIT(i)) 152 - length += scnprintf(&buf[length], 153 - PAGE_SIZE - length, 154 - "%s\n", 155 - int3400_thermal_uuids[i]); 154 + length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]); 156 155 } 157 156 158 157 if (length) ··· 308 313 end: 309 314 kfree(buf.pointer); 310 315 return result; 316 + } 317 + 318 + static ssize_t production_mode_show(struct device *dev, struct device_attribute *attr, 319 + char *buf) 320 + { 321 + struct int3400_thermal_priv *priv = dev_get_drvdata(dev); 322 + 323 + return sysfs_emit(buf, "%d\n", priv->production_mode); 324 + } 325 + 326 + static DEVICE_ATTR_RO(production_mode); 327 + 328 + static int production_mode_init(struct int3400_thermal_priv *priv) 329 + { 330 + unsigned long long mode; 331 + acpi_status status; 332 + int ret; 333 + 334 + priv->production_mode = -1; 335 + 336 + status = acpi_evaluate_integer(priv->adev->handle, "DCFG", NULL, &mode); 337 + /* If the method is not present, this is not an error */ 338 + if (ACPI_FAILURE(status)) 339 + return 0; 340 + 341 + ret = sysfs_create_file(&priv->pdev->dev.kobj, &dev_attr_production_mode.attr); 342 + if (ret) 343 + return ret; 344 + 345 + priv->production_mode = mode; 346 + 347 + return 0; 348 + } 349 + 350 + static void production_mode_exit(struct int3400_thermal_priv *priv) 351 + { 352 + if (priv->production_mode >= 0) 353 + sysfs_remove_file(&priv->pdev->dev.kobj, &dev_attr_production_mode.attr); 311 354 } 312 355 313 356 static ssize_t odvp_show(struct device *dev, struct device_attribute *attr, ··· 643 610 if (result) 644 611 goto free_sysfs; 645 612 613 + result = production_mode_init(priv); 614 + if (result) 615 + goto free_notify; 616 + 646 617 return 0; 647 618 619 + free_notify: 620 + acpi_remove_notify_handler(priv->adev->handle, ACPI_DEVICE_NOTIFY, 621 + int3400_notify); 648 622 free_sysfs: 649 623 cleanup_odvp(priv); 650 624 if (!ZERO_OR_NULL_PTR(priv->data_vault)) { ··· 677 637 static int int3400_thermal_remove(struct platform_device *pdev) 678 638 { 679 639 struct int3400_thermal_priv *priv = platform_get_drvdata(pdev); 640 + 641 + production_mode_exit(priv); 680 642 681 643 acpi_remove_notify_handler( 682 644 priv->adev->handle, ACPI_DEVICE_NOTIFY,
+1 -1
drivers/thermal/intel/int340x_thermal/int3403_thermal.c
··· 69 69 THERMAL_TRIP_VIOLATED); 70 70 break; 71 71 case INT3403_PERF_TRIP_POINT_CHANGED: 72 - int340x_thermal_read_trips(obj->int340x_zone); 72 + int340x_thermal_update_trips(obj->int340x_zone); 73 73 int340x_thermal_zone_device_update(obj->int340x_zone, 74 74 THERMAL_TRIP_CHANGED); 75 75 break;
+152 -210
drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
··· 18 18 unsigned long long tmp; 19 19 acpi_status status; 20 20 21 - if (d->override_ops && d->override_ops->get_temp) 22 - return d->override_ops->get_temp(zone, temp); 23 - 24 21 status = acpi_evaluate_integer(d->adev->handle, "_TMP", NULL, &tmp); 25 22 if (ACPI_FAILURE(status)) 26 23 return -EIO; ··· 29 32 if (conv_temp < 0) 30 33 return conv_temp; 31 34 32 - *temp = (unsigned long)conv_temp * 10; 33 - } else 35 + *temp = conv_temp * 10; 36 + } else { 34 37 /* _TMP returns the temperature in tenths of degrees Kelvin */ 35 38 *temp = deci_kelvin_to_millicelsius(tmp); 39 + } 36 40 37 41 return 0; 38 - } 39 - 40 - static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone, 41 - int trip, int *temp) 42 - { 43 - struct int34x_thermal_zone *d = zone->devdata; 44 - int i, ret = 0; 45 - 46 - if (d->override_ops && d->override_ops->get_trip_temp) 47 - return d->override_ops->get_trip_temp(zone, trip, temp); 48 - 49 - mutex_lock(&d->trip_mutex); 50 - 51 - if (trip < d->aux_trip_nr) 52 - *temp = d->aux_trips[trip]; 53 - else if (trip == d->crt_trip_id) 54 - *temp = d->crt_temp; 55 - else if (trip == d->psv_trip_id) 56 - *temp = d->psv_temp; 57 - else if (trip == d->hot_trip_id) 58 - *temp = d->hot_temp; 59 - else { 60 - for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) { 61 - if (d->act_trips[i].valid && 62 - d->act_trips[i].id == trip) { 63 - *temp = d->act_trips[i].temp; 64 - break; 65 - } 66 - } 67 - if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT) 68 - ret = -EINVAL; 69 - } 70 - 71 - mutex_unlock(&d->trip_mutex); 72 - 73 - return ret; 74 - } 75 - 76 - static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone, 77 - int trip, 78 - enum thermal_trip_type *type) 79 - { 80 - struct int34x_thermal_zone *d = zone->devdata; 81 - int i, ret = 0; 82 - 83 - if (d->override_ops && d->override_ops->get_trip_type) 84 - return d->override_ops->get_trip_type(zone, trip, type); 85 - 86 - mutex_lock(&d->trip_mutex); 87 - 88 - if (trip < d->aux_trip_nr) 89 - *type = THERMAL_TRIP_PASSIVE; 90 - else if (trip == d->crt_trip_id) 91 - *type = THERMAL_TRIP_CRITICAL; 92 - else if (trip == d->hot_trip_id) 93 - *type = THERMAL_TRIP_HOT; 94 - else if (trip == d->psv_trip_id) 95 - *type = THERMAL_TRIP_PASSIVE; 96 - else { 97 - for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) { 98 - if (d->act_trips[i].valid && 99 - d->act_trips[i].id == trip) { 100 - *type = THERMAL_TRIP_ACTIVE; 101 - break; 102 - } 103 - } 104 - if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT) 105 - ret = -EINVAL; 106 - } 107 - 108 - mutex_unlock(&d->trip_mutex); 109 - 110 - return ret; 111 42 } 112 43 113 44 static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone, 114 - int trip, int temp) 45 + int trip, int temp) 115 46 { 116 47 struct int34x_thermal_zone *d = zone->devdata; 48 + char name[] = {'P', 'A', 'T', '0' + trip, '\0'}; 117 49 acpi_status status; 118 - char name[10]; 119 50 120 - if (d->override_ops && d->override_ops->set_trip_temp) 121 - return d->override_ops->set_trip_temp(zone, trip, temp); 51 + if (trip > 9) 52 + return -EINVAL; 122 53 123 - snprintf(name, sizeof(name), "PAT%d", trip); 124 54 status = acpi_execute_simple_method(d->adev->handle, name, 125 - millicelsius_to_deci_kelvin(temp)); 55 + millicelsius_to_deci_kelvin(temp)); 126 56 if (ACPI_FAILURE(status)) 127 57 return -EIO; 128 - 129 - d->aux_trips[trip] = temp; 130 - 131 - return 0; 132 - } 133 - 134 - 135 - static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone, 136 - int trip, int *temp) 137 - { 138 - struct int34x_thermal_zone *d = zone->devdata; 139 - acpi_status status; 140 - unsigned long long hyst; 141 - 142 - if (d->override_ops && d->override_ops->get_trip_hyst) 143 - return d->override_ops->get_trip_hyst(zone, trip, temp); 144 - 145 - status = acpi_evaluate_integer(d->adev->handle, "GTSH", NULL, &hyst); 146 - if (ACPI_FAILURE(status)) 147 - *temp = 0; 148 - else 149 - *temp = hyst * 100; 150 58 151 59 return 0; 152 60 } ··· 63 161 64 162 static struct thermal_zone_device_ops int340x_thermal_zone_ops = { 65 163 .get_temp = int340x_thermal_get_zone_temp, 66 - .get_trip_temp = int340x_thermal_get_trip_temp, 67 - .get_trip_type = int340x_thermal_get_trip_type, 68 164 .set_trip_temp = int340x_thermal_set_trip_temp, 69 - .get_trip_hyst = int340x_thermal_get_trip_hyst, 70 165 .critical = int340x_thermal_critical, 71 166 }; 72 167 73 - static int int340x_thermal_get_trip_config(acpi_handle handle, char *name, 74 - int *temp) 168 + static int int340x_thermal_read_trips(struct acpi_device *zone_adev, 169 + struct thermal_trip *zone_trips, 170 + int trip_cnt) 75 171 { 76 - unsigned long long r; 77 - acpi_status status; 172 + int i, ret; 78 173 79 - status = acpi_evaluate_integer(handle, name, NULL, &r); 80 - if (ACPI_FAILURE(status)) 81 - return -EIO; 82 - 83 - *temp = deci_kelvin_to_millicelsius(r); 84 - 85 - return 0; 86 - } 87 - 88 - int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone) 89 - { 90 - int trip_cnt = int34x_zone->aux_trip_nr; 91 - int i; 92 - 93 - mutex_lock(&int34x_zone->trip_mutex); 94 - 95 - int34x_zone->crt_trip_id = -1; 96 - if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_CRT", 97 - &int34x_zone->crt_temp)) 98 - int34x_zone->crt_trip_id = trip_cnt++; 99 - 100 - int34x_zone->hot_trip_id = -1; 101 - if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_HOT", 102 - &int34x_zone->hot_temp)) 103 - int34x_zone->hot_trip_id = trip_cnt++; 104 - 105 - int34x_zone->psv_trip_id = -1; 106 - if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_PSV", 107 - &int34x_zone->psv_temp)) 108 - int34x_zone->psv_trip_id = trip_cnt++; 109 - 110 - for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) { 111 - char name[5] = { '_', 'A', 'C', '0' + i, '\0' }; 112 - 113 - if (int340x_thermal_get_trip_config(int34x_zone->adev->handle, 114 - name, 115 - &int34x_zone->act_trips[i].temp)) 116 - break; 117 - 118 - int34x_zone->act_trips[i].id = trip_cnt++; 119 - int34x_zone->act_trips[i].valid = true; 174 + ret = thermal_acpi_critical_trip_temp(zone_adev, 175 + &zone_trips[trip_cnt].temperature); 176 + if (!ret) { 177 + zone_trips[trip_cnt].type = THERMAL_TRIP_CRITICAL; 178 + trip_cnt++; 120 179 } 121 180 122 - mutex_unlock(&int34x_zone->trip_mutex); 181 + ret = thermal_acpi_hot_trip_temp(zone_adev, 182 + &zone_trips[trip_cnt].temperature); 183 + if (!ret) { 184 + zone_trips[trip_cnt].type = THERMAL_TRIP_HOT; 185 + trip_cnt++; 186 + } 187 + 188 + ret = thermal_acpi_passive_trip_temp(zone_adev, 189 + &zone_trips[trip_cnt].temperature); 190 + if (!ret) { 191 + zone_trips[trip_cnt].type = THERMAL_TRIP_PASSIVE; 192 + trip_cnt++; 193 + } 194 + 195 + for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) { 196 + ret = thermal_acpi_active_trip_temp(zone_adev, i, 197 + &zone_trips[trip_cnt].temperature); 198 + if (ret) 199 + break; 200 + 201 + zone_trips[trip_cnt].type = THERMAL_TRIP_ACTIVE; 202 + trip_cnt++; 203 + } 123 204 124 205 return trip_cnt; 125 206 } 126 - EXPORT_SYMBOL_GPL(int340x_thermal_read_trips); 127 207 128 208 static struct thermal_zone_params int340x_thermal_params = { 129 209 .governor_name = "user_space", ··· 113 229 }; 114 230 115 231 struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, 116 - struct thermal_zone_device_ops *override_ops) 232 + int (*get_temp) (struct thermal_zone_device *, int *)) 117 233 { 118 - struct int34x_thermal_zone *int34x_thermal_zone; 119 - acpi_status status; 120 - unsigned long long trip_cnt; 234 + struct int34x_thermal_zone *int34x_zone; 235 + struct thermal_trip *zone_trips; 236 + unsigned long long trip_cnt = 0; 237 + unsigned long long hyst; 121 238 int trip_mask = 0; 122 - int ret; 239 + acpi_status status; 240 + int i, ret; 123 241 124 - int34x_thermal_zone = kzalloc(sizeof(*int34x_thermal_zone), 125 - GFP_KERNEL); 126 - if (!int34x_thermal_zone) 242 + int34x_zone = kzalloc(sizeof(*int34x_zone), GFP_KERNEL); 243 + if (!int34x_zone) 127 244 return ERR_PTR(-ENOMEM); 128 245 129 - mutex_init(&int34x_thermal_zone->trip_mutex); 246 + int34x_zone->adev = adev; 130 247 131 - int34x_thermal_zone->adev = adev; 132 - int34x_thermal_zone->override_ops = override_ops; 248 + int34x_zone->ops = kmemdup(&int340x_thermal_zone_ops, 249 + sizeof(int340x_thermal_zone_ops), GFP_KERNEL); 250 + if (!int34x_zone->ops) { 251 + ret = -ENOMEM; 252 + goto err_ops_alloc; 253 + } 254 + 255 + if (get_temp) 256 + int34x_zone->ops->get_temp = get_temp; 133 257 134 258 status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt); 135 - if (ACPI_FAILURE(status)) 136 - trip_cnt = 0; 137 - else { 138 - int i; 139 - 140 - int34x_thermal_zone->aux_trips = 141 - kcalloc(trip_cnt, 142 - sizeof(*int34x_thermal_zone->aux_trips), 143 - GFP_KERNEL); 144 - if (!int34x_thermal_zone->aux_trips) { 145 - ret = -ENOMEM; 146 - goto err_trip_alloc; 147 - } 259 + if (ACPI_SUCCESS(status)) { 260 + int34x_zone->aux_trip_nr = trip_cnt; 148 261 trip_mask = BIT(trip_cnt) - 1; 149 - int34x_thermal_zone->aux_trip_nr = trip_cnt; 150 - for (i = 0; i < trip_cnt; ++i) 151 - int34x_thermal_zone->aux_trips[i] = THERMAL_TEMP_INVALID; 152 262 } 153 263 154 - trip_cnt = int340x_thermal_read_trips(int34x_thermal_zone); 264 + zone_trips = kzalloc(sizeof(*zone_trips) * (trip_cnt + INT340X_THERMAL_MAX_TRIP_COUNT), 265 + GFP_KERNEL); 266 + if (!zone_trips) { 267 + ret = -ENOMEM; 268 + goto err_trips_alloc; 269 + } 155 270 156 - int34x_thermal_zone->lpat_table = acpi_lpat_get_conversion_table( 157 - adev->handle); 271 + for (i = 0; i < trip_cnt; i++) { 272 + zone_trips[i].type = THERMAL_TRIP_PASSIVE; 273 + zone_trips[i].temperature = THERMAL_TEMP_INVALID; 274 + } 158 275 159 - int34x_thermal_zone->zone = thermal_zone_device_register( 160 - acpi_device_bid(adev), 161 - trip_cnt, 162 - trip_mask, int34x_thermal_zone, 163 - &int340x_thermal_zone_ops, 164 - &int340x_thermal_params, 165 - 0, 0); 166 - if (IS_ERR(int34x_thermal_zone->zone)) { 167 - ret = PTR_ERR(int34x_thermal_zone->zone); 276 + trip_cnt = int340x_thermal_read_trips(adev, zone_trips, trip_cnt); 277 + 278 + status = acpi_evaluate_integer(adev->handle, "GTSH", NULL, &hyst); 279 + if (ACPI_SUCCESS(status)) 280 + hyst *= 100; 281 + else 282 + hyst = 0; 283 + 284 + for (i = 0; i < trip_cnt; ++i) 285 + zone_trips[i].hysteresis = hyst; 286 + 287 + int34x_zone->trips = zone_trips; 288 + 289 + int34x_zone->lpat_table = acpi_lpat_get_conversion_table(adev->handle); 290 + 291 + int34x_zone->zone = thermal_zone_device_register_with_trips( 292 + acpi_device_bid(adev), 293 + zone_trips, trip_cnt, 294 + trip_mask, int34x_zone, 295 + int34x_zone->ops, 296 + &int340x_thermal_params, 297 + 0, 0); 298 + if (IS_ERR(int34x_zone->zone)) { 299 + ret = PTR_ERR(int34x_zone->zone); 168 300 goto err_thermal_zone; 169 301 } 170 - ret = thermal_zone_device_enable(int34x_thermal_zone->zone); 302 + ret = thermal_zone_device_enable(int34x_zone->zone); 171 303 if (ret) 172 304 goto err_enable; 173 305 174 - return int34x_thermal_zone; 306 + return int34x_zone; 175 307 176 308 err_enable: 177 - thermal_zone_device_unregister(int34x_thermal_zone->zone); 309 + thermal_zone_device_unregister(int34x_zone->zone); 178 310 err_thermal_zone: 179 - acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table); 180 - kfree(int34x_thermal_zone->aux_trips); 181 - err_trip_alloc: 182 - mutex_destroy(&int34x_thermal_zone->trip_mutex); 183 - kfree(int34x_thermal_zone); 311 + kfree(int34x_zone->trips); 312 + acpi_lpat_free_conversion_table(int34x_zone->lpat_table); 313 + err_trips_alloc: 314 + kfree(int34x_zone->ops); 315 + err_ops_alloc: 316 + kfree(int34x_zone); 184 317 return ERR_PTR(ret); 185 318 } 186 319 EXPORT_SYMBOL_GPL(int340x_thermal_zone_add); 187 320 188 - void int340x_thermal_zone_remove(struct int34x_thermal_zone 189 - *int34x_thermal_zone) 321 + void int340x_thermal_zone_remove(struct int34x_thermal_zone *int34x_zone) 190 322 { 191 - thermal_zone_device_unregister(int34x_thermal_zone->zone); 192 - acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table); 193 - kfree(int34x_thermal_zone->aux_trips); 194 - mutex_destroy(&int34x_thermal_zone->trip_mutex); 195 - kfree(int34x_thermal_zone); 323 + thermal_zone_device_unregister(int34x_zone->zone); 324 + acpi_lpat_free_conversion_table(int34x_zone->lpat_table); 325 + kfree(int34x_zone->trips); 326 + kfree(int34x_zone->ops); 327 + kfree(int34x_zone); 196 328 } 197 329 EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove); 330 + 331 + void int340x_thermal_update_trips(struct int34x_thermal_zone *int34x_zone) 332 + { 333 + struct acpi_device *zone_adev = int34x_zone->adev; 334 + struct thermal_trip *zone_trips = int34x_zone->trips; 335 + int trip_cnt = int34x_zone->zone->num_trips; 336 + int act_trip_nr = 0; 337 + int i; 338 + 339 + mutex_lock(&int34x_zone->zone->lock); 340 + 341 + for (i = int34x_zone->aux_trip_nr; i < trip_cnt; i++) { 342 + int temp, err; 343 + 344 + switch (zone_trips[i].type) { 345 + case THERMAL_TRIP_CRITICAL: 346 + err = thermal_acpi_critical_trip_temp(zone_adev, &temp); 347 + break; 348 + case THERMAL_TRIP_HOT: 349 + err = thermal_acpi_hot_trip_temp(zone_adev, &temp); 350 + break; 351 + case THERMAL_TRIP_PASSIVE: 352 + err = thermal_acpi_passive_trip_temp(zone_adev, &temp); 353 + break; 354 + case THERMAL_TRIP_ACTIVE: 355 + err = thermal_acpi_active_trip_temp(zone_adev, act_trip_nr++, 356 + &temp); 357 + break; 358 + default: 359 + err = -ENODEV; 360 + } 361 + if (err) { 362 + zone_trips[i].temperature = THERMAL_TEMP_INVALID; 363 + continue; 364 + } 365 + 366 + zone_trips[i].temperature = temp; 367 + } 368 + 369 + mutex_unlock(&int34x_zone->zone->lock); 370 + } 371 + EXPORT_SYMBOL_GPL(int340x_thermal_update_trips); 198 372 199 373 MODULE_AUTHOR("Aaron Lu <aaron.lu@intel.com>"); 200 374 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+5 -12
drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.h
··· 10 10 #include <acpi/acpi_lpat.h> 11 11 12 12 #define INT340X_THERMAL_MAX_ACT_TRIP_COUNT 10 13 + #define INT340X_THERMAL_MAX_TRIP_COUNT INT340X_THERMAL_MAX_ACT_TRIP_COUNT + 3 13 14 14 15 struct active_trip { 15 16 int temp; ··· 20 19 21 20 struct int34x_thermal_zone { 22 21 struct acpi_device *adev; 23 - struct active_trip act_trips[INT340X_THERMAL_MAX_ACT_TRIP_COUNT]; 24 - unsigned long *aux_trips; 22 + struct thermal_trip *trips; 25 23 int aux_trip_nr; 26 - int psv_temp; 27 - int psv_trip_id; 28 - int crt_temp; 29 - int crt_trip_id; 30 - int hot_temp; 31 - int hot_trip_id; 32 24 struct thermal_zone_device *zone; 33 - struct thermal_zone_device_ops *override_ops; 25 + struct thermal_zone_device_ops *ops; 34 26 void *priv_data; 35 27 struct acpi_lpat_conversion_table *lpat_table; 36 - struct mutex trip_mutex; 37 28 }; 38 29 39 30 struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *, 40 - struct thermal_zone_device_ops *override_ops); 31 + int (*get_temp) (struct thermal_zone_device *, int *)); 41 32 void int340x_thermal_zone_remove(struct int34x_thermal_zone *); 42 - int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone); 33 + void int340x_thermal_update_trips(struct int34x_thermal_zone *int34x_zone); 43 34 44 35 static inline void int340x_thermal_zone_set_priv_data( 45 36 struct int34x_thermal_zone *tzone, void *priv_data)
+24 -105
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
··· 4 4 * Copyright (c) 2014, Intel Corporation. 5 5 */ 6 6 #include <linux/acpi.h> 7 + #include <linux/intel_tcc.h> 7 8 #include <linux/kernel.h> 8 9 #include <linux/module.h> 9 10 #include <linux/pci.h> ··· 69 68 .name = "power_limits" 70 69 }; 71 70 72 - static int tcc_get_offset(void) 73 - { 74 - u64 val; 75 - int err; 76 - 77 - err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val); 78 - if (err) 79 - return err; 80 - 81 - return (val >> 24) & 0x3f; 82 - } 83 - 84 71 static ssize_t tcc_offset_degree_celsius_show(struct device *dev, 85 72 struct device_attribute *attr, 86 73 char *buf) 87 74 { 88 - int tcc; 75 + int offset; 89 76 90 - tcc = tcc_get_offset(); 91 - if (tcc < 0) 92 - return tcc; 77 + offset = intel_tcc_get_offset(-1); 78 + if (offset < 0) 79 + return offset; 93 80 94 - return sprintf(buf, "%d\n", tcc); 95 - } 96 - 97 - static int tcc_offset_update(unsigned int tcc) 98 - { 99 - u64 val; 100 - int err; 101 - 102 - if (tcc > 63) 103 - return -EINVAL; 104 - 105 - err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val); 106 - if (err) 107 - return err; 108 - 109 - if (val & BIT(31)) 110 - return -EPERM; 111 - 112 - val &= ~GENMASK_ULL(29, 24); 113 - val |= (tcc & 0x3f) << 24; 114 - 115 - err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val); 116 - if (err) 117 - return err; 118 - 119 - return 0; 81 + return sprintf(buf, "%d\n", offset); 120 82 } 121 83 122 84 static ssize_t tcc_offset_degree_celsius_store(struct device *dev, ··· 100 136 if (kstrtouint(buf, 0, &tcc)) 101 137 return -EINVAL; 102 138 103 - err = tcc_offset_update(tcc); 139 + err = intel_tcc_set_offset(-1, tcc); 104 140 if (err) 105 141 return err; 106 142 ··· 109 145 110 146 static DEVICE_ATTR_RW(tcc_offset_degree_celsius); 111 147 112 - static int stored_tjmax; /* since it is fixed, we can have local storage */ 113 - 114 - static int get_tjmax(void) 115 - { 116 - u32 eax, edx; 117 - u32 val; 118 - int err; 119 - 120 - err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); 121 - if (err) 122 - return err; 123 - 124 - val = (eax >> 16) & 0xff; 125 - if (val) 126 - return val; 127 - 128 - return -EINVAL; 129 - } 130 - 131 - static int read_temp_msr(int *temp) 148 + static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone, 149 + int *temp) 132 150 { 133 151 int cpu; 134 - u32 eax, edx; 135 - int err; 136 - unsigned long curr_temp_off = 0; 152 + int curr_temp; 137 153 138 154 *temp = 0; 139 155 140 156 for_each_online_cpu(cpu) { 141 - err = rdmsr_safe_on_cpu(cpu, MSR_IA32_THERM_STATUS, &eax, 142 - &edx); 143 - if (err) 144 - goto err_ret; 145 - else { 146 - if (eax & 0x80000000) { 147 - curr_temp_off = (eax >> 16) & 0x7f; 148 - if (!*temp || curr_temp_off < *temp) 149 - *temp = curr_temp_off; 150 - } else { 151 - err = -EINVAL; 152 - goto err_ret; 153 - } 154 - } 157 + curr_temp = intel_tcc_get_temp(cpu, false); 158 + if (curr_temp < 0) 159 + return curr_temp; 160 + if (!*temp || curr_temp > *temp) 161 + *temp = curr_temp; 155 162 } 156 163 164 + *temp *= 1000; 165 + 157 166 return 0; 158 - err_ret: 159 - return err; 160 167 } 161 - 162 - static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone, 163 - int *temp) 164 - { 165 - int ret; 166 - 167 - ret = read_temp_msr(temp); 168 - if (!ret) 169 - *temp = (stored_tjmax - *temp) * 1000; 170 - 171 - return ret; 172 - } 173 - 174 - static struct thermal_zone_device_ops proc_thermal_local_ops = { 175 - .get_temp = proc_thermal_get_zone_temp, 176 - }; 177 168 178 169 static int proc_thermal_read_ppcc(struct proc_thermal_device *proc_priv) 179 170 { ··· 204 285 struct acpi_device *adev; 205 286 acpi_status status; 206 287 unsigned long long tmp; 207 - struct thermal_zone_device_ops *ops = NULL; 288 + int (*get_temp) (struct thermal_zone_device *, int *) = NULL; 208 289 int ret; 209 290 210 291 adev = ACPI_COMPANION(dev); ··· 221 302 status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp); 222 303 if (ACPI_FAILURE(status)) { 223 304 /* there is no _TMP method, add local method */ 224 - stored_tjmax = get_tjmax(); 225 - if (stored_tjmax > 0) 226 - ops = &proc_thermal_local_ops; 305 + if (intel_tcc_get_tjmax(-1) > 0) 306 + get_temp = proc_thermal_get_zone_temp; 227 307 } 228 308 229 - proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops); 309 + proc_priv->int340x_zone = int340x_thermal_zone_add(adev, get_temp); 230 310 if (IS_ERR(proc_priv->int340x_zone)) { 231 311 return PTR_ERR(proc_priv->int340x_zone); 232 312 } else ··· 274 356 275 357 int proc_thermal_suspend(struct device *dev) 276 358 { 277 - tcc_offset_save = tcc_get_offset(); 359 + tcc_offset_save = intel_tcc_get_offset(-1); 278 360 if (tcc_offset_save < 0) 279 361 dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save); 280 362 ··· 291 373 292 374 /* Do not update if saving failed */ 293 375 if (tcc_offset_save >= 0) 294 - tcc_offset_update(tcc_offset_save); 376 + intel_tcc_set_offset(-1, tcc_offset_save); 295 377 296 378 return 0; 297 379 } ··· 378 460 } 379 461 EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); 380 462 463 + MODULE_IMPORT_NS(INTEL_TCC); 381 464 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 382 465 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); 383 466 MODULE_LICENSE("GPL v2");
+22 -31
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
··· 144 144 return 0; 145 145 } 146 146 147 - static int sys_get_trip_temp(struct thermal_zone_device *tzd, 148 - int trip, int *temp) 149 - { 150 - struct proc_thermal_pci *pci_info = tzd->devdata; 151 - u32 _temp; 152 - 153 - proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &_temp); 154 - if (!_temp) { 155 - *temp = THERMAL_TEMP_INVALID; 156 - } else { 157 - int tjmax; 158 - 159 - proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); 160 - _temp = tjmax - _temp; 161 - *temp = (unsigned long)_temp * 1000; 162 - } 163 - 164 - return 0; 165 - } 166 - 167 - static int sys_get_trip_type(struct thermal_zone_device *tzd, int trip, 168 - enum thermal_trip_type *type) 169 - { 170 - *type = THERMAL_TRIP_PASSIVE; 171 - 172 - return 0; 173 - } 174 - 175 147 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) 176 148 { 177 149 struct proc_thermal_pci *pci_info = tzd->devdata; ··· 172 200 return 0; 173 201 } 174 202 203 + static int get_trip_temp(struct proc_thermal_pci *pci_info) 204 + { 205 + int temp, tjmax; 206 + 207 + proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &temp); 208 + if (!temp) 209 + return THERMAL_TEMP_INVALID; 210 + 211 + proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); 212 + temp = (tjmax - temp) * 1000; 213 + 214 + return temp; 215 + } 216 + 217 + static struct thermal_trip psv_trip = { 218 + .type = THERMAL_TRIP_PASSIVE, 219 + }; 220 + 175 221 static struct thermal_zone_device_ops tzone_ops = { 176 222 .get_temp = sys_get_curr_temp, 177 - .get_trip_temp = sys_get_trip_temp, 178 - .get_trip_type = sys_get_trip_type, 179 223 .set_trip_temp = sys_set_trip_temp, 180 224 }; 181 225 ··· 239 251 if (ret) 240 252 goto err_ret_thermal; 241 253 242 - pci_info->tzone = thermal_zone_device_register("TCPU_PCI", 1, 1, pci_info, 254 + psv_trip.temperature = get_trip_temp(pci_info); 255 + 256 + pci_info->tzone = thermal_zone_device_register_with_trips("TCPU_PCI", &psv_trip, 257 + 1, 1, pci_info, 243 258 &tzone_ops, 244 259 &tzone_params, 0, 0); 245 260 if (IS_ERR(pci_info->tzone)) {
+2 -1
drivers/thermal/intel/intel_hfi.c
··· 40 40 41 41 #include <asm/msr.h> 42 42 43 - #include "../thermal_core.h" 44 43 #include "intel_hfi.h" 45 44 #include "thermal_interrupt.h" 45 + 46 + #include "../thermal_netlink.h" 46 47 47 48 /* Hardware Feedback Interface MSR configuration bits */ 48 49 #define HW_FEEDBACK_PTR_VALID_BIT BIT(0)
+6 -6
drivers/thermal/intel/intel_menlow.c
··· 232 232 233 233 /* 234 234 * sensor_get_auxtrip - get the current auxtrip value from sensor 235 - * @name: Thermalzone name 236 - * @auxtype : AUX0/AUX1 237 - * @buf: syfs buffer 235 + * @handle: Object handle 236 + * @index : GET_AUX1/GET_AUX0 237 + * @value : The address will be fill by the value 238 238 */ 239 239 static int sensor_get_auxtrip(acpi_handle handle, int index, 240 240 unsigned long long *value) ··· 254 254 255 255 /* 256 256 * sensor_set_auxtrip - set the new auxtrip value to sensor 257 - * @name: Thermalzone name 258 - * @auxtype : AUX0/AUX1 259 - * @buf: syfs buffer 257 + * @handle: Object handle 258 + * @index : GET_AUX1/GET_AUX0 259 + * @value : The value will be set 260 260 */ 261 261 static int sensor_set_auxtrip(acpi_handle handle, int index, int value) 262 262 {
+145 -263
drivers/thermal/intel/intel_pch_thermal.c
··· 29 29 #define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */ 30 30 #define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */ 31 31 #define PCH_THERMAL_DID_LWB 0xA1B1 /* Lewisburg PCH */ 32 + #define PCH_THERMAL_DID_WBG 0x8D24 /* Wellsburg PCH */ 32 33 33 34 /* Wildcat Point-LP PCH Thermal registers */ 34 35 #define WPT_TEMP 0x0000 /* Temperature */ ··· 66 65 #define WPT_TEMP_OFFSET (PCH_TEMP_OFFSET * MILLIDEGREE_PER_DEGREE) 67 66 #define GET_PCH_TEMP(x) (((x) / 2) + PCH_TEMP_OFFSET) 68 67 68 + #define PCH_MAX_TRIPS 3 /* critical, hot, passive */ 69 + 69 70 /* Amount of time for each cooling delay, 100ms by default for now */ 70 71 static unsigned int delay_timeout = 100; 71 72 module_param(delay_timeout, int, 0644); ··· 82 79 83 80 struct pch_thermal_device { 84 81 void __iomem *hw_base; 85 - const struct pch_dev_ops *ops; 86 82 struct pci_dev *pdev; 87 83 struct thermal_zone_device *tzd; 88 - int crt_trip_id; 89 - unsigned long crt_temp; 90 - int hot_trip_id; 91 - unsigned long hot_temp; 92 - int psv_trip_id; 93 - unsigned long psv_temp; 84 + struct thermal_trip trips[PCH_MAX_TRIPS]; 94 85 bool bios_enabled; 95 86 }; 96 87 97 88 #ifdef CONFIG_ACPI 98 - 99 89 /* 100 90 * On some platforms, there is a companion ACPI device, which adds 101 91 * passive trip temperature using _PSV method. There is no specific 102 92 * passive temperature setting in MMIO interface of this PCI device. 103 93 */ 104 - static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd, 105 - int *nr_trips) 94 + static int pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd, int trip) 106 95 { 107 96 struct acpi_device *adev; 108 - 109 - ptd->psv_trip_id = -1; 97 + int temp; 110 98 111 99 adev = ACPI_COMPANION(&ptd->pdev->dev); 112 - if (adev) { 113 - unsigned long long r; 114 - acpi_status status; 100 + if (!adev) 101 + return 0; 115 102 116 - status = acpi_evaluate_integer(adev->handle, "_PSV", NULL, 117 - &r); 118 - if (ACPI_SUCCESS(status)) { 119 - unsigned long trip_temp; 103 + if (thermal_acpi_passive_trip_temp(adev, &temp) || temp <= 0) 104 + return 0; 120 105 121 - trip_temp = deci_kelvin_to_millicelsius(r); 122 - if (trip_temp) { 123 - ptd->psv_temp = trip_temp; 124 - ptd->psv_trip_id = *nr_trips; 125 - ++(*nr_trips); 126 - } 127 - } 128 - } 106 + ptd->trips[trip].type = THERMAL_TRIP_PASSIVE; 107 + ptd->trips[trip].temperature = temp; 108 + return 1; 129 109 } 130 110 #else 131 - static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd, 132 - int *nr_trips) 111 + static int pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd, int trip) 133 112 { 134 - ptd->psv_trip_id = -1; 135 - 113 + return 0; 136 114 } 137 115 #endif 138 116 139 - static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips) 117 + static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp) 140 118 { 141 - u8 tsel; 142 - u16 trip_temp; 119 + struct pch_thermal_device *ptd = tzd->devdata; 143 120 144 - *nr_trips = 0; 121 + *temp = GET_WPT_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP)); 122 + return 0; 123 + } 124 + 125 + static void pch_critical(struct thermal_zone_device *tzd) 126 + { 127 + dev_dbg(&tzd->device, "%s: critical temperature reached\n", tzd->type); 128 + } 129 + 130 + static struct thermal_zone_device_ops tzd_ops = { 131 + .get_temp = pch_thermal_get_temp, 132 + .critical = pch_critical, 133 + }; 134 + 135 + enum pch_board_ids { 136 + PCH_BOARD_HSW = 0, 137 + PCH_BOARD_WPT, 138 + PCH_BOARD_SKL, 139 + PCH_BOARD_CNL, 140 + PCH_BOARD_CML, 141 + PCH_BOARD_LWB, 142 + PCH_BOARD_WBG, 143 + }; 144 + 145 + static const char *board_names[] = { 146 + [PCH_BOARD_HSW] = "pch_haswell", 147 + [PCH_BOARD_WPT] = "pch_wildcat_point", 148 + [PCH_BOARD_SKL] = "pch_skylake", 149 + [PCH_BOARD_CNL] = "pch_cannonlake", 150 + [PCH_BOARD_CML] = "pch_cometlake", 151 + [PCH_BOARD_LWB] = "pch_lewisburg", 152 + [PCH_BOARD_WBG] = "pch_wellsburg", 153 + }; 154 + 155 + static int intel_pch_thermal_probe(struct pci_dev *pdev, 156 + const struct pci_device_id *id) 157 + { 158 + enum pch_board_ids board_id = id->driver_data; 159 + struct pch_thermal_device *ptd; 160 + int nr_trips = 0; 161 + u16 trip_temp; 162 + u8 tsel; 163 + int err; 164 + 165 + ptd = devm_kzalloc(&pdev->dev, sizeof(*ptd), GFP_KERNEL); 166 + if (!ptd) 167 + return -ENOMEM; 168 + 169 + pci_set_drvdata(pdev, ptd); 170 + ptd->pdev = pdev; 171 + 172 + err = pci_enable_device(pdev); 173 + if (err) { 174 + dev_err(&pdev->dev, "failed to enable pci device\n"); 175 + return err; 176 + } 177 + 178 + err = pci_request_regions(pdev, driver_name); 179 + if (err) { 180 + dev_err(&pdev->dev, "failed to request pci region\n"); 181 + goto error_disable; 182 + } 183 + 184 + ptd->hw_base = pci_ioremap_bar(pdev, 0); 185 + if (!ptd->hw_base) { 186 + err = -ENOMEM; 187 + dev_err(&pdev->dev, "failed to map mem base\n"); 188 + goto error_release; 189 + } 145 190 146 191 /* Check if BIOS has already enabled thermal sensor */ 147 192 if (WPT_TSEL_ETS & readb(ptd->hw_base + WPT_TSEL)) { ··· 204 153 */ 205 154 if (tsel & WPT_TSEL_PLDB) { 206 155 dev_err(&ptd->pdev->dev, "Sensor can't be enabled\n"); 207 - return -ENODEV; 156 + err = -ENODEV; 157 + goto error_cleanup; 208 158 } 209 159 210 160 writeb(tsel|WPT_TSEL_ETS, ptd->hw_base + WPT_TSEL); 211 161 if (!(WPT_TSEL_ETS & readb(ptd->hw_base + WPT_TSEL))) { 212 162 dev_err(&ptd->pdev->dev, "Sensor can't be enabled\n"); 213 - return -ENODEV; 163 + err = -ENODEV; 164 + goto error_cleanup; 214 165 } 215 166 216 167 read_trips: 217 - ptd->crt_trip_id = -1; 218 168 trip_temp = readw(ptd->hw_base + WPT_CTT); 219 169 trip_temp &= 0x1FF; 220 170 if (trip_temp) { 221 - ptd->crt_temp = GET_WPT_TEMP(trip_temp); 222 - ptd->crt_trip_id = 0; 223 - ++(*nr_trips); 171 + ptd->trips[nr_trips].temperature = GET_WPT_TEMP(trip_temp); 172 + ptd->trips[nr_trips++].type = THERMAL_TRIP_CRITICAL; 224 173 } 225 174 226 - ptd->hot_trip_id = -1; 227 175 trip_temp = readw(ptd->hw_base + WPT_PHL); 228 176 trip_temp &= 0x1FF; 229 177 if (trip_temp) { 230 - ptd->hot_temp = GET_WPT_TEMP(trip_temp); 231 - ptd->hot_trip_id = *nr_trips; 232 - ++(*nr_trips); 178 + ptd->trips[nr_trips].temperature = GET_WPT_TEMP(trip_temp); 179 + ptd->trips[nr_trips++].type = THERMAL_TRIP_HOT; 233 180 } 234 181 235 - pch_wpt_add_acpi_psv_trip(ptd, nr_trips); 182 + nr_trips += pch_wpt_add_acpi_psv_trip(ptd, nr_trips); 183 + 184 + ptd->tzd = thermal_zone_device_register_with_trips(board_names[board_id], 185 + ptd->trips, nr_trips, 186 + 0, ptd, &tzd_ops, 187 + NULL, 0, 0); 188 + if (IS_ERR(ptd->tzd)) { 189 + dev_err(&pdev->dev, "Failed to register thermal zone %s\n", 190 + board_names[board_id]); 191 + err = PTR_ERR(ptd->tzd); 192 + goto error_cleanup; 193 + } 194 + err = thermal_zone_device_enable(ptd->tzd); 195 + if (err) 196 + goto err_unregister; 236 197 237 198 return 0; 199 + 200 + err_unregister: 201 + thermal_zone_device_unregister(ptd->tzd); 202 + error_cleanup: 203 + iounmap(ptd->hw_base); 204 + error_release: 205 + pci_release_regions(pdev); 206 + error_disable: 207 + pci_disable_device(pdev); 208 + dev_err(&pdev->dev, "pci device failed to probe\n"); 209 + return err; 238 210 } 239 211 240 - static int pch_wpt_get_temp(struct pch_thermal_device *ptd, int *temp) 212 + static void intel_pch_thermal_remove(struct pci_dev *pdev) 241 213 { 242 - *temp = GET_WPT_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP)); 214 + struct pch_thermal_device *ptd = pci_get_drvdata(pdev); 243 215 244 - return 0; 216 + thermal_zone_device_unregister(ptd->tzd); 217 + iounmap(ptd->hw_base); 218 + pci_set_drvdata(pdev, NULL); 219 + pci_release_regions(pdev); 220 + pci_disable_device(pdev); 245 221 } 246 222 247 - /* Cool the PCH when it's overheat in .suspend_noirq phase */ 248 - static int pch_wpt_suspend(struct pch_thermal_device *ptd) 223 + static int intel_pch_thermal_suspend_noirq(struct device *device) 249 224 { 250 - u8 tsel; 251 - int pch_delay_cnt = 0; 225 + struct pch_thermal_device *ptd = dev_get_drvdata(device); 252 226 u16 pch_thr_temp, pch_cur_temp; 227 + int pch_delay_cnt = 0; 228 + u8 tsel; 253 229 254 230 /* Shutdown the thermal sensor if it is not enabled by BIOS */ 255 231 if (!ptd->bios_enabled) { ··· 339 261 return 0; 340 262 } 341 263 342 - static int pch_wpt_resume(struct pch_thermal_device *ptd) 264 + static int intel_pch_thermal_resume(struct device *device) 343 265 { 266 + struct pch_thermal_device *ptd = dev_get_drvdata(device); 344 267 u8 tsel; 345 268 346 269 if (ptd->bios_enabled) ··· 354 275 return 0; 355 276 } 356 277 357 - struct pch_dev_ops { 358 - int (*hw_init)(struct pch_thermal_device *ptd, int *nr_trips); 359 - int (*get_temp)(struct pch_thermal_device *ptd, int *temp); 360 - int (*suspend)(struct pch_thermal_device *ptd); 361 - int (*resume)(struct pch_thermal_device *ptd); 362 - }; 363 - 364 - 365 - /* dev ops for Wildcat Point */ 366 - static const struct pch_dev_ops pch_dev_ops_wpt = { 367 - .hw_init = pch_wpt_init, 368 - .get_temp = pch_wpt_get_temp, 369 - .suspend = pch_wpt_suspend, 370 - .resume = pch_wpt_resume, 371 - }; 372 - 373 - static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp) 374 - { 375 - struct pch_thermal_device *ptd = tzd->devdata; 376 - 377 - return ptd->ops->get_temp(ptd, temp); 378 - } 379 - 380 - static int pch_get_trip_type(struct thermal_zone_device *tzd, int trip, 381 - enum thermal_trip_type *type) 382 - { 383 - struct pch_thermal_device *ptd = tzd->devdata; 384 - 385 - if (ptd->crt_trip_id == trip) 386 - *type = THERMAL_TRIP_CRITICAL; 387 - else if (ptd->hot_trip_id == trip) 388 - *type = THERMAL_TRIP_HOT; 389 - else if (ptd->psv_trip_id == trip) 390 - *type = THERMAL_TRIP_PASSIVE; 391 - else 392 - return -EINVAL; 393 - 394 - return 0; 395 - } 396 - 397 - static int pch_get_trip_temp(struct thermal_zone_device *tzd, int trip, int *temp) 398 - { 399 - struct pch_thermal_device *ptd = tzd->devdata; 400 - 401 - if (ptd->crt_trip_id == trip) 402 - *temp = ptd->crt_temp; 403 - else if (ptd->hot_trip_id == trip) 404 - *temp = ptd->hot_temp; 405 - else if (ptd->psv_trip_id == trip) 406 - *temp = ptd->psv_temp; 407 - else 408 - return -EINVAL; 409 - 410 - return 0; 411 - } 412 - 413 - static void pch_critical(struct thermal_zone_device *tzd) 414 - { 415 - dev_dbg(&tzd->device, "%s: critical temperature reached\n", tzd->type); 416 - } 417 - 418 - static struct thermal_zone_device_ops tzd_ops = { 419 - .get_temp = pch_thermal_get_temp, 420 - .get_trip_type = pch_get_trip_type, 421 - .get_trip_temp = pch_get_trip_temp, 422 - .critical = pch_critical, 423 - }; 424 - 425 - enum board_ids { 426 - board_hsw, 427 - board_wpt, 428 - board_skl, 429 - board_cnl, 430 - board_cml, 431 - board_lwb, 432 - }; 433 - 434 - static const struct board_info { 435 - const char *name; 436 - const struct pch_dev_ops *ops; 437 - } board_info[] = { 438 - [board_hsw] = { 439 - .name = "pch_haswell", 440 - .ops = &pch_dev_ops_wpt, 441 - }, 442 - [board_wpt] = { 443 - .name = "pch_wildcat_point", 444 - .ops = &pch_dev_ops_wpt, 445 - }, 446 - [board_skl] = { 447 - .name = "pch_skylake", 448 - .ops = &pch_dev_ops_wpt, 449 - }, 450 - [board_cnl] = { 451 - .name = "pch_cannonlake", 452 - .ops = &pch_dev_ops_wpt, 453 - }, 454 - [board_cml] = { 455 - .name = "pch_cometlake", 456 - .ops = &pch_dev_ops_wpt, 457 - }, 458 - [board_lwb] = { 459 - .name = "pch_lewisburg", 460 - .ops = &pch_dev_ops_wpt, 461 - }, 462 - }; 463 - 464 - static int intel_pch_thermal_probe(struct pci_dev *pdev, 465 - const struct pci_device_id *id) 466 - { 467 - enum board_ids board_id = id->driver_data; 468 - const struct board_info *bi = &board_info[board_id]; 469 - struct pch_thermal_device *ptd; 470 - int err; 471 - int nr_trips; 472 - 473 - ptd = devm_kzalloc(&pdev->dev, sizeof(*ptd), GFP_KERNEL); 474 - if (!ptd) 475 - return -ENOMEM; 476 - 477 - ptd->ops = bi->ops; 478 - 479 - pci_set_drvdata(pdev, ptd); 480 - ptd->pdev = pdev; 481 - 482 - err = pci_enable_device(pdev); 483 - if (err) { 484 - dev_err(&pdev->dev, "failed to enable pci device\n"); 485 - return err; 486 - } 487 - 488 - err = pci_request_regions(pdev, driver_name); 489 - if (err) { 490 - dev_err(&pdev->dev, "failed to request pci region\n"); 491 - goto error_disable; 492 - } 493 - 494 - ptd->hw_base = pci_ioremap_bar(pdev, 0); 495 - if (!ptd->hw_base) { 496 - err = -ENOMEM; 497 - dev_err(&pdev->dev, "failed to map mem base\n"); 498 - goto error_release; 499 - } 500 - 501 - err = ptd->ops->hw_init(ptd, &nr_trips); 502 - if (err) 503 - goto error_cleanup; 504 - 505 - ptd->tzd = thermal_zone_device_register(bi->name, nr_trips, 0, ptd, 506 - &tzd_ops, NULL, 0, 0); 507 - if (IS_ERR(ptd->tzd)) { 508 - dev_err(&pdev->dev, "Failed to register thermal zone %s\n", 509 - bi->name); 510 - err = PTR_ERR(ptd->tzd); 511 - goto error_cleanup; 512 - } 513 - err = thermal_zone_device_enable(ptd->tzd); 514 - if (err) 515 - goto err_unregister; 516 - 517 - return 0; 518 - 519 - err_unregister: 520 - thermal_zone_device_unregister(ptd->tzd); 521 - error_cleanup: 522 - iounmap(ptd->hw_base); 523 - error_release: 524 - pci_release_regions(pdev); 525 - error_disable: 526 - pci_disable_device(pdev); 527 - dev_err(&pdev->dev, "pci device failed to probe\n"); 528 - return err; 529 - } 530 - 531 - static void intel_pch_thermal_remove(struct pci_dev *pdev) 532 - { 533 - struct pch_thermal_device *ptd = pci_get_drvdata(pdev); 534 - 535 - thermal_zone_device_unregister(ptd->tzd); 536 - iounmap(ptd->hw_base); 537 - pci_set_drvdata(pdev, NULL); 538 - pci_release_regions(pdev); 539 - pci_disable_device(pdev); 540 - } 541 - 542 - static int intel_pch_thermal_suspend_noirq(struct device *device) 543 - { 544 - struct pch_thermal_device *ptd = dev_get_drvdata(device); 545 - 546 - return ptd->ops->suspend(ptd); 547 - } 548 - 549 - static int intel_pch_thermal_resume(struct device *device) 550 - { 551 - struct pch_thermal_device *ptd = dev_get_drvdata(device); 552 - 553 - return ptd->ops->resume(ptd); 554 - } 555 - 556 278 static const struct pci_device_id intel_pch_thermal_id[] = { 557 279 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_1), 558 - .driver_data = board_hsw, }, 280 + .driver_data = PCH_BOARD_HSW, }, 559 281 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_2), 560 - .driver_data = board_hsw, }, 282 + .driver_data = PCH_BOARD_HSW, }, 561 283 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT), 562 - .driver_data = board_wpt, }, 284 + .driver_data = PCH_BOARD_WPT, }, 563 285 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL), 564 - .driver_data = board_skl, }, 286 + .driver_data = PCH_BOARD_SKL, }, 565 287 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL_H), 566 - .driver_data = board_skl, }, 288 + .driver_data = PCH_BOARD_SKL, }, 567 289 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL), 568 - .driver_data = board_cnl, }, 290 + .driver_data = PCH_BOARD_CNL, }, 569 291 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H), 570 - .driver_data = board_cnl, }, 292 + .driver_data = PCH_BOARD_CNL, }, 571 293 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_LP), 572 - .driver_data = board_cnl, }, 294 + .driver_data = PCH_BOARD_CNL, }, 573 295 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CML_H), 574 - .driver_data = board_cml, }, 296 + .driver_data = PCH_BOARD_CML, }, 575 297 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_LWB), 576 - .driver_data = board_lwb, }, 298 + .driver_data = PCH_BOARD_LWB, }, 299 + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WBG), 300 + .driver_data = PCH_BOARD_WBG, }, 577 301 { 0, }, 578 302 }; 579 303 MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id);
+327 -244
drivers/thermal/intel/intel_powerclamp.c
··· 2 2 /* 3 3 * intel_powerclamp.c - package c-state idle injection 4 4 * 5 - * Copyright (c) 2012, Intel Corporation. 5 + * Copyright (c) 2012-2023, Intel Corporation. 6 6 * 7 7 * Authors: 8 8 * Arjan van de Ven <arjan@linux.intel.com> ··· 27 27 #include <linux/module.h> 28 28 #include <linux/kernel.h> 29 29 #include <linux/delay.h> 30 - #include <linux/kthread.h> 31 30 #include <linux/cpu.h> 32 31 #include <linux/thermal.h> 33 - #include <linux/slab.h> 34 - #include <linux/tick.h> 35 32 #include <linux/debugfs.h> 36 33 #include <linux/seq_file.h> 37 - #include <linux/sched/rt.h> 38 - #include <uapi/linux/sched/types.h> 34 + #include <linux/idle_inject.h> 39 35 40 - #include <asm/nmi.h> 41 36 #include <asm/msr.h> 42 37 #include <asm/mwait.h> 43 38 #include <asm/cpu_device_id.h> 44 - #include <asm/hardirq.h> 45 39 46 - #define MAX_TARGET_RATIO (50U) 40 + #define MAX_TARGET_RATIO (100U) 47 41 /* For each undisturbed clamping period (no extra wake ups during idle time), 48 42 * we increment the confidence counter for the given target ratio. 49 43 * CONFIDENCE_OK defines the level where runtime calibration results are ··· 51 57 52 58 static unsigned int target_mwait; 53 59 static struct dentry *debug_dir; 60 + static bool poll_pkg_cstate_enable; 54 61 55 - /* user selected target */ 56 - static unsigned int set_target_ratio; 62 + /* Idle ratio observed using package C-state counters */ 57 63 static unsigned int current_ratio; 64 + 65 + /* Skip the idle injection till set to true */ 58 66 static bool should_skip; 59 67 60 - static unsigned int control_cpu; /* The cpu assigned to collect stat and update 61 - * control parameters. default to BSP but BSP 62 - * can be offlined. 63 - */ 64 - static bool clamping; 65 - 66 - struct powerclamp_worker_data { 67 - struct kthread_worker *worker; 68 - struct kthread_work balancing_work; 69 - struct kthread_delayed_work idle_injection_work; 68 + struct powerclamp_data { 70 69 unsigned int cpu; 71 70 unsigned int count; 72 71 unsigned int guard; 73 72 unsigned int window_size_now; 74 73 unsigned int target_ratio; 75 - unsigned int duration_jiffies; 76 74 bool clamping; 77 75 }; 78 76 79 - static struct powerclamp_worker_data __percpu *worker_data; 80 - static struct thermal_cooling_device *cooling_dev; 81 - static unsigned long *cpu_clamping_mask; /* bit map for tracking per cpu 82 - * clamping kthread worker 83 - */ 77 + static struct powerclamp_data powerclamp_data; 84 78 79 + static struct thermal_cooling_device *cooling_dev; 80 + 81 + static DEFINE_MUTEX(powerclamp_lock); 82 + 83 + /* This duration is in microseconds */ 85 84 static unsigned int duration; 86 85 static unsigned int pkg_cstate_ratio_cur; 87 86 static unsigned int window_size; ··· 91 104 pr_err("Out of recommended range %lu, between 6-25ms\n", 92 105 new_duration); 93 106 ret = -EINVAL; 107 + goto exit; 94 108 } 95 109 96 - duration = clamp(new_duration, 6ul, 25ul); 97 - smp_mb(); 98 - 110 + mutex_lock(&powerclamp_lock); 111 + duration = clamp(new_duration, 6ul, 25ul) * 1000; 112 + mutex_unlock(&powerclamp_lock); 99 113 exit: 114 + 115 + return ret; 116 + } 117 + 118 + static int duration_get(char *buf, const struct kernel_param *kp) 119 + { 120 + int ret; 121 + 122 + mutex_lock(&powerclamp_lock); 123 + ret = sysfs_emit(buf, "%d\n", duration / 1000); 124 + mutex_unlock(&powerclamp_lock); 100 125 101 126 return ret; 102 127 } 103 128 104 129 static const struct kernel_param_ops duration_ops = { 105 130 .set = duration_set, 131 + .get = duration_get, 132 + }; 133 + 134 + module_param_cb(duration, &duration_ops, NULL, 0644); 135 + MODULE_PARM_DESC(duration, "forced idle time for each attempt in msec."); 136 + 137 + #define DEFAULT_MAX_IDLE 50 138 + #define MAX_ALL_CPU_IDLE 75 139 + 140 + static u8 max_idle = DEFAULT_MAX_IDLE; 141 + 142 + static cpumask_var_t idle_injection_cpu_mask; 143 + 144 + static int allocate_copy_idle_injection_mask(const struct cpumask *copy_mask) 145 + { 146 + if (cpumask_available(idle_injection_cpu_mask)) 147 + goto copy_mask; 148 + 149 + /* This mask is allocated only one time and freed during module exit */ 150 + if (!alloc_cpumask_var(&idle_injection_cpu_mask, GFP_KERNEL)) 151 + return -ENOMEM; 152 + 153 + copy_mask: 154 + cpumask_copy(idle_injection_cpu_mask, copy_mask); 155 + 156 + return 0; 157 + } 158 + 159 + /* Return true if the cpumask and idle percent combination is invalid */ 160 + static bool check_invalid(cpumask_var_t mask, u8 idle) 161 + { 162 + if (cpumask_equal(cpu_present_mask, mask) && idle > MAX_ALL_CPU_IDLE) 163 + return true; 164 + 165 + return false; 166 + } 167 + 168 + static int cpumask_set(const char *arg, const struct kernel_param *kp) 169 + { 170 + cpumask_var_t new_mask; 171 + int ret; 172 + 173 + mutex_lock(&powerclamp_lock); 174 + 175 + /* Can't set mask when cooling device is in use */ 176 + if (powerclamp_data.clamping) { 177 + ret = -EAGAIN; 178 + goto skip_cpumask_set; 179 + } 180 + 181 + ret = alloc_cpumask_var(&new_mask, GFP_KERNEL); 182 + if (!ret) 183 + goto skip_cpumask_set; 184 + 185 + ret = bitmap_parse(arg, strlen(arg), cpumask_bits(new_mask), 186 + nr_cpumask_bits); 187 + if (ret) 188 + goto free_cpumask_set; 189 + 190 + if (cpumask_empty(new_mask) || check_invalid(new_mask, max_idle)) { 191 + ret = -EINVAL; 192 + goto free_cpumask_set; 193 + } 194 + 195 + /* 196 + * When module parameters are passed from kernel command line 197 + * during insmod, the module parameter callback is called 198 + * before powerclamp_init(), so we can't assume that some 199 + * cpumask can be allocated and copied before here. Also 200 + * in this case this cpumask is used as the default mask. 201 + */ 202 + ret = allocate_copy_idle_injection_mask(new_mask); 203 + 204 + free_cpumask_set: 205 + free_cpumask_var(new_mask); 206 + skip_cpumask_set: 207 + mutex_unlock(&powerclamp_lock); 208 + 209 + return ret; 210 + } 211 + 212 + static int cpumask_get(char *buf, const struct kernel_param *kp) 213 + { 214 + if (!cpumask_available(idle_injection_cpu_mask)) 215 + return -ENODEV; 216 + 217 + return bitmap_print_to_pagebuf(false, buf, cpumask_bits(idle_injection_cpu_mask), 218 + nr_cpumask_bits); 219 + } 220 + 221 + static const struct kernel_param_ops cpumask_ops = { 222 + .set = cpumask_set, 223 + .get = cpumask_get, 224 + }; 225 + 226 + module_param_cb(cpumask, &cpumask_ops, NULL, 0644); 227 + MODULE_PARM_DESC(cpumask, "Mask of CPUs to use for idle injection."); 228 + 229 + static int max_idle_set(const char *arg, const struct kernel_param *kp) 230 + { 231 + u8 new_max_idle; 232 + int ret = 0; 233 + 234 + mutex_lock(&powerclamp_lock); 235 + 236 + /* Can't set mask when cooling device is in use */ 237 + if (powerclamp_data.clamping) { 238 + ret = -EAGAIN; 239 + goto skip_limit_set; 240 + } 241 + 242 + ret = kstrtou8(arg, 10, &new_max_idle); 243 + if (ret) 244 + goto skip_limit_set; 245 + 246 + if (new_max_idle > MAX_TARGET_RATIO) { 247 + ret = -EINVAL; 248 + goto skip_limit_set; 249 + } 250 + 251 + if (check_invalid(idle_injection_cpu_mask, new_max_idle)) { 252 + ret = -EINVAL; 253 + goto skip_limit_set; 254 + } 255 + 256 + max_idle = new_max_idle; 257 + 258 + skip_limit_set: 259 + mutex_unlock(&powerclamp_lock); 260 + 261 + return ret; 262 + } 263 + 264 + static const struct kernel_param_ops max_idle_ops = { 265 + .set = max_idle_set, 106 266 .get = param_get_int, 107 267 }; 108 268 109 - 110 - module_param_cb(duration, &duration_ops, &duration, 0644); 111 - MODULE_PARM_DESC(duration, "forced idle time for each attempt in msec."); 269 + module_param_cb(max_idle, &max_idle_ops, &max_idle, 0644); 270 + MODULE_PARM_DESC(max_idle, "maximum injected idle time to the total CPU time ratio in percent range:1-100"); 112 271 113 272 struct powerclamp_calibration_data { 114 273 unsigned long confidence; /* used for calibration, basically a counter ··· 394 261 { 395 262 unsigned int comp = 0; 396 263 264 + if (!poll_pkg_cstate_enable) 265 + return 0; 266 + 397 267 /* we only use compensation if all adjacent ones are good */ 398 268 if (ratio == 1 && 399 269 cal_data[ratio].confidence >= CONFIDENCE_OK && ··· 438 302 if (d->confidence >= CONFIDENCE_OK) 439 303 return; 440 304 441 - delta = set_target_ratio - current_ratio; 305 + delta = powerclamp_data.target_ratio - current_ratio; 442 306 /* filter out bad data */ 443 307 if (delta >= 0 && delta <= (1+target_ratio/10)) { 444 308 if (d->steady_comp) ··· 477 341 adjust_compensation(target_ratio, win); 478 342 479 343 /* if we are above target+guard, skip */ 480 - return set_target_ratio + guard <= current_ratio; 344 + return powerclamp_data.target_ratio + guard <= current_ratio; 481 345 } 482 346 483 - static void clamp_balancing_func(struct kthread_work *work) 347 + /* 348 + * This function calculates runtime from the current target ratio. 349 + * This function gets called under powerclamp_lock. 350 + */ 351 + static unsigned int get_run_time(void) 484 352 { 485 - struct powerclamp_worker_data *w_data; 486 - int sleeptime; 487 - unsigned long target_jiffies; 488 353 unsigned int compensated_ratio; 489 - int interval; /* jiffies to sleep for each attempt */ 490 - 491 - w_data = container_of(work, struct powerclamp_worker_data, 492 - balancing_work); 354 + unsigned int runtime; 493 355 494 356 /* 495 357 * make sure user selected ratio does not take effect until 496 358 * the next round. adjust target_ratio if user has changed 497 359 * target such that we can converge quickly. 498 360 */ 499 - w_data->target_ratio = READ_ONCE(set_target_ratio); 500 - w_data->guard = 1 + w_data->target_ratio / 20; 501 - w_data->window_size_now = window_size; 502 - w_data->duration_jiffies = msecs_to_jiffies(duration); 503 - w_data->count++; 361 + powerclamp_data.guard = 1 + powerclamp_data.target_ratio / 20; 362 + powerclamp_data.window_size_now = window_size; 504 363 505 364 /* 506 365 * systems may have different ability to enter package level 507 366 * c-states, thus we need to compensate the injected idle ratio 508 367 * to achieve the actual target reported by the HW. 509 368 */ 510 - compensated_ratio = w_data->target_ratio + 511 - get_compensation(w_data->target_ratio); 369 + compensated_ratio = powerclamp_data.target_ratio + 370 + get_compensation(powerclamp_data.target_ratio); 512 371 if (compensated_ratio <= 0) 513 372 compensated_ratio = 1; 514 - interval = w_data->duration_jiffies * 100 / compensated_ratio; 515 373 516 - /* align idle time */ 517 - target_jiffies = roundup(jiffies, interval); 518 - sleeptime = target_jiffies - jiffies; 519 - if (sleeptime <= 0) 520 - sleeptime = 1; 374 + runtime = duration * 100 / compensated_ratio - duration; 521 375 522 - if (clamping && w_data->clamping && cpu_online(w_data->cpu)) 523 - kthread_queue_delayed_work(w_data->worker, 524 - &w_data->idle_injection_work, 525 - sleeptime); 526 - } 527 - 528 - static void clamp_idle_injection_func(struct kthread_work *work) 529 - { 530 - struct powerclamp_worker_data *w_data; 531 - 532 - w_data = container_of(work, struct powerclamp_worker_data, 533 - idle_injection_work.work); 534 - 535 - /* 536 - * only elected controlling cpu can collect stats and update 537 - * control parameters. 538 - */ 539 - if (w_data->cpu == control_cpu && 540 - !(w_data->count % w_data->window_size_now)) { 541 - should_skip = 542 - powerclamp_adjust_controls(w_data->target_ratio, 543 - w_data->guard, 544 - w_data->window_size_now); 545 - smp_mb(); 546 - } 547 - 548 - if (should_skip) 549 - goto balance; 550 - 551 - play_idle(jiffies_to_usecs(w_data->duration_jiffies)); 552 - 553 - balance: 554 - if (clamping && w_data->clamping && cpu_online(w_data->cpu)) 555 - kthread_queue_work(w_data->worker, &w_data->balancing_work); 376 + return runtime; 556 377 } 557 378 558 379 /* ··· 545 452 msr_last = msr_now; 546 453 tsc_last = tsc_now; 547 454 548 - if (true == clamping) 455 + mutex_lock(&powerclamp_lock); 456 + if (powerclamp_data.clamping) 549 457 schedule_delayed_work(&poll_pkg_cstate_work, HZ); 458 + mutex_unlock(&powerclamp_lock); 550 459 } 551 460 552 - static void start_power_clamp_worker(unsigned long cpu) 553 - { 554 - struct powerclamp_worker_data *w_data = per_cpu_ptr(worker_data, cpu); 555 - struct kthread_worker *worker; 461 + static struct idle_inject_device *ii_dev; 556 462 557 - worker = kthread_create_worker_on_cpu(cpu, 0, "kidle_inj/%ld", cpu); 558 - if (IS_ERR(worker)) 463 + /* 464 + * This function is called from idle injection core on timer expiry 465 + * for the run duration. This allows powerclamp to readjust or skip 466 + * injecting idle for this cycle. 467 + */ 468 + static bool idle_inject_update(void) 469 + { 470 + bool update = false; 471 + 472 + /* We can't sleep in this callback */ 473 + if (!mutex_trylock(&powerclamp_lock)) 474 + return true; 475 + 476 + if (!(powerclamp_data.count % powerclamp_data.window_size_now)) { 477 + 478 + should_skip = powerclamp_adjust_controls(powerclamp_data.target_ratio, 479 + powerclamp_data.guard, 480 + powerclamp_data.window_size_now); 481 + update = true; 482 + } 483 + 484 + if (update) { 485 + unsigned int runtime = get_run_time(); 486 + 487 + idle_inject_set_duration(ii_dev, runtime, duration); 488 + } 489 + 490 + powerclamp_data.count++; 491 + 492 + mutex_unlock(&powerclamp_lock); 493 + 494 + if (should_skip) 495 + return false; 496 + 497 + return true; 498 + } 499 + 500 + /* This function starts idle injection by calling idle_inject_start() */ 501 + static void trigger_idle_injection(void) 502 + { 503 + unsigned int runtime = get_run_time(); 504 + 505 + idle_inject_set_duration(ii_dev, runtime, duration); 506 + idle_inject_start(ii_dev); 507 + powerclamp_data.clamping = true; 508 + } 509 + 510 + /* 511 + * This function is called from start_power_clamp() to register 512 + * CPUS with powercap idle injection register and set default 513 + * idle duration and latency. 514 + */ 515 + static int powerclamp_idle_injection_register(void) 516 + { 517 + poll_pkg_cstate_enable = false; 518 + if (cpumask_equal(cpu_present_mask, idle_injection_cpu_mask)) { 519 + ii_dev = idle_inject_register_full(idle_injection_cpu_mask, idle_inject_update); 520 + if (topology_max_packages() == 1 && topology_max_die_per_package() == 1) 521 + poll_pkg_cstate_enable = true; 522 + } else { 523 + ii_dev = idle_inject_register(idle_injection_cpu_mask); 524 + } 525 + 526 + if (!ii_dev) { 527 + pr_err("powerclamp: idle_inject_register failed\n"); 528 + return -EAGAIN; 529 + } 530 + 531 + idle_inject_set_duration(ii_dev, TICK_USEC, duration); 532 + idle_inject_set_latency(ii_dev, UINT_MAX); 533 + 534 + return 0; 535 + } 536 + 537 + /* 538 + * This function is called from end_power_clamp() to stop idle injection 539 + * and unregister CPUS from powercap idle injection core. 540 + */ 541 + static void remove_idle_injection(void) 542 + { 543 + if (!powerclamp_data.clamping) 559 544 return; 560 545 561 - w_data->worker = worker; 562 - w_data->count = 0; 563 - w_data->cpu = cpu; 564 - w_data->clamping = true; 565 - set_bit(cpu, cpu_clamping_mask); 566 - sched_set_fifo(worker->task); 567 - kthread_init_work(&w_data->balancing_work, clamp_balancing_func); 568 - kthread_init_delayed_work(&w_data->idle_injection_work, 569 - clamp_idle_injection_func); 570 - kthread_queue_work(w_data->worker, &w_data->balancing_work); 546 + powerclamp_data.clamping = false; 547 + idle_inject_stop(ii_dev); 571 548 } 572 549 573 - static void stop_power_clamp_worker(unsigned long cpu) 574 - { 575 - struct powerclamp_worker_data *w_data = per_cpu_ptr(worker_data, cpu); 576 - 577 - if (!w_data->worker) 578 - return; 579 - 580 - w_data->clamping = false; 581 - /* 582 - * Make sure that all works that get queued after this point see 583 - * the clamping disabled. The counter part is not needed because 584 - * there is an implicit memory barrier when the queued work 585 - * is proceed. 586 - */ 587 - smp_wmb(); 588 - kthread_cancel_work_sync(&w_data->balancing_work); 589 - kthread_cancel_delayed_work_sync(&w_data->idle_injection_work); 590 - /* 591 - * The balancing work still might be queued here because 592 - * the handling of the "clapming" variable, cancel, and queue 593 - * operations are not synchronized via a lock. But it is not 594 - * a big deal. The balancing work is fast and destroy kthread 595 - * will wait for it. 596 - */ 597 - clear_bit(w_data->cpu, cpu_clamping_mask); 598 - kthread_destroy_worker(w_data->worker); 599 - 600 - w_data->worker = NULL; 601 - } 602 - 550 + /* 551 + * This function is called when user change the cooling device 552 + * state from zero to some other value. 553 + */ 603 554 static int start_power_clamp(void) 604 555 { 605 - unsigned long cpu; 556 + int ret; 606 557 607 - set_target_ratio = clamp(set_target_ratio, 0U, MAX_TARGET_RATIO - 1); 608 - /* prevent cpu hotplug */ 609 - cpus_read_lock(); 610 - 611 - /* prefer BSP */ 612 - control_cpu = cpumask_first(cpu_online_mask); 613 - 614 - clamping = true; 615 - schedule_delayed_work(&poll_pkg_cstate_work, 0); 616 - 617 - /* start one kthread worker per online cpu */ 618 - for_each_online_cpu(cpu) { 619 - start_power_clamp_worker(cpu); 558 + ret = powerclamp_idle_injection_register(); 559 + if (!ret) { 560 + trigger_idle_injection(); 561 + if (poll_pkg_cstate_enable) 562 + schedule_delayed_work(&poll_pkg_cstate_work, 0); 620 563 } 621 - cpus_read_unlock(); 622 564 623 - return 0; 565 + return ret; 624 566 } 625 567 568 + /* 569 + * This function is called when user change the cooling device 570 + * state from non zero value zero. 571 + */ 626 572 static void end_power_clamp(void) 627 573 { 628 - int i; 629 - 630 - /* 631 - * Block requeuing in all the kthread workers. They will flush and 632 - * stop faster. 633 - */ 634 - clamping = false; 635 - for_each_set_bit(i, cpu_clamping_mask, num_possible_cpus()) { 636 - pr_debug("clamping worker for cpu %d alive, destroy\n", i); 637 - stop_power_clamp_worker(i); 574 + if (powerclamp_data.clamping) { 575 + remove_idle_injection(); 576 + idle_inject_unregister(ii_dev); 638 577 } 639 - } 640 - 641 - static int powerclamp_cpu_online(unsigned int cpu) 642 - { 643 - if (clamping == false) 644 - return 0; 645 - start_power_clamp_worker(cpu); 646 - /* prefer BSP as controlling CPU */ 647 - if (cpu == 0) { 648 - control_cpu = 0; 649 - smp_mb(); 650 - } 651 - return 0; 652 - } 653 - 654 - static int powerclamp_cpu_predown(unsigned int cpu) 655 - { 656 - if (clamping == false) 657 - return 0; 658 - 659 - stop_power_clamp_worker(cpu); 660 - if (cpu != control_cpu) 661 - return 0; 662 - 663 - control_cpu = cpumask_first(cpu_online_mask); 664 - if (control_cpu == cpu) 665 - control_cpu = cpumask_next(cpu, cpu_online_mask); 666 - smp_mb(); 667 - return 0; 668 578 } 669 579 670 580 static int powerclamp_get_max_state(struct thermal_cooling_device *cdev, ··· 681 585 static int powerclamp_get_cur_state(struct thermal_cooling_device *cdev, 682 586 unsigned long *state) 683 587 { 684 - if (true == clamping) 685 - *state = pkg_cstate_ratio_cur; 686 - else 687 - /* to save power, do not poll idle ratio while not clamping */ 688 - *state = -1; /* indicates invalid state */ 588 + mutex_lock(&powerclamp_lock); 589 + *state = powerclamp_data.target_ratio; 590 + mutex_unlock(&powerclamp_lock); 689 591 690 592 return 0; 691 593 } ··· 693 599 { 694 600 int ret = 0; 695 601 602 + mutex_lock(&powerclamp_lock); 603 + 696 604 new_target_ratio = clamp(new_target_ratio, 0UL, 697 - (unsigned long) (MAX_TARGET_RATIO-1)); 698 - if (set_target_ratio == 0 && new_target_ratio > 0) { 605 + (unsigned long) (max_idle - 1)); 606 + if (!powerclamp_data.target_ratio && new_target_ratio > 0) { 699 607 pr_info("Start idle injection to reduce power\n"); 700 - set_target_ratio = new_target_ratio; 608 + powerclamp_data.target_ratio = new_target_ratio; 701 609 ret = start_power_clamp(); 610 + if (ret) 611 + powerclamp_data.target_ratio = 0; 702 612 goto exit_set; 703 - } else if (set_target_ratio > 0 && new_target_ratio == 0) { 613 + } else if (powerclamp_data.target_ratio > 0 && new_target_ratio == 0) { 704 614 pr_info("Stop forced idle injection\n"); 705 615 end_power_clamp(); 706 - set_target_ratio = 0; 616 + powerclamp_data.target_ratio = 0; 707 617 } else /* adjust currently running */ { 708 - set_target_ratio = new_target_ratio; 709 - /* make new set_target_ratio visible to other cpus */ 710 - smp_mb(); 618 + unsigned int runtime; 619 + 620 + powerclamp_data.target_ratio = new_target_ratio; 621 + runtime = get_run_time(); 622 + idle_inject_set_duration(ii_dev, runtime, duration); 711 623 } 712 624 713 625 exit_set: 626 + mutex_unlock(&powerclamp_lock); 627 + 714 628 return ret; 715 629 } 716 630 ··· 759 657 { 760 658 int i = 0; 761 659 762 - seq_printf(m, "controlling cpu: %d\n", control_cpu); 763 660 seq_printf(m, "pct confidence steady dynamic (compensation)\n"); 764 661 for (i = 0; i < MAX_TARGET_RATIO; i++) { 765 662 seq_printf(m, "%d\t%lu\t%lu\t%lu\n", ··· 781 680 &powerclamp_debug_fops); 782 681 } 783 682 784 - static enum cpuhp_state hp_state; 785 - 786 683 static int __init powerclamp_init(void) 787 684 { 788 685 int retval; 789 686 790 - cpu_clamping_mask = bitmap_zalloc(num_possible_cpus(), GFP_KERNEL); 791 - if (!cpu_clamping_mask) 792 - return -ENOMEM; 793 - 794 687 /* probe cpu features and ids here */ 795 688 retval = powerclamp_probe(); 796 689 if (retval) 797 - goto exit_free; 690 + return retval; 691 + 692 + mutex_lock(&powerclamp_lock); 693 + retval = allocate_copy_idle_injection_mask(cpu_present_mask); 694 + mutex_unlock(&powerclamp_lock); 695 + 696 + if (retval) 697 + return retval; 798 698 799 699 /* set default limit, maybe adjusted during runtime based on feedback */ 800 700 window_size = 2; 801 - retval = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, 802 - "thermal/intel_powerclamp:online", 803 - powerclamp_cpu_online, 804 - powerclamp_cpu_predown); 805 - if (retval < 0) 806 - goto exit_free; 807 - 808 - hp_state = retval; 809 - 810 - worker_data = alloc_percpu(struct powerclamp_worker_data); 811 - if (!worker_data) { 812 - retval = -ENOMEM; 813 - goto exit_unregister; 814 - } 815 701 816 702 cooling_dev = thermal_cooling_device_register("intel_powerclamp", NULL, 817 - &powerclamp_cooling_ops); 818 - if (IS_ERR(cooling_dev)) { 819 - retval = -ENODEV; 820 - goto exit_free_thread; 821 - } 703 + &powerclamp_cooling_ops); 704 + if (IS_ERR(cooling_dev)) 705 + return -ENODEV; 822 706 823 707 if (!duration) 824 - duration = jiffies_to_msecs(DEFAULT_DURATION_JIFFIES); 708 + duration = jiffies_to_usecs(DEFAULT_DURATION_JIFFIES); 825 709 826 710 powerclamp_create_debug_files(); 827 711 828 712 return 0; 829 - 830 - exit_free_thread: 831 - free_percpu(worker_data); 832 - exit_unregister: 833 - cpuhp_remove_state_nocalls(hp_state); 834 - exit_free: 835 - bitmap_free(cpu_clamping_mask); 836 - return retval; 837 713 } 838 714 module_init(powerclamp_init); 839 715 840 716 static void __exit powerclamp_exit(void) 841 717 { 718 + mutex_lock(&powerclamp_lock); 842 719 end_power_clamp(); 843 - cpuhp_remove_state_nocalls(hp_state); 844 - free_percpu(worker_data); 720 + mutex_unlock(&powerclamp_lock); 721 + 845 722 thermal_cooling_device_unregister(cooling_dev); 846 - bitmap_free(cpu_clamping_mask); 847 723 848 724 cancel_delayed_work_sync(&poll_pkg_cstate_work); 849 725 debugfs_remove_recursive(debug_dir); 726 + 727 + if (cpumask_available(idle_injection_cpu_mask)) 728 + free_cpumask_var(idle_injection_cpu_mask); 850 729 } 851 730 module_exit(powerclamp_exit); 731 + 732 + MODULE_IMPORT_NS(IDLE_INJECT); 852 733 853 734 MODULE_LICENSE("GPL"); 854 735 MODULE_AUTHOR("Arjan van de Ven <arjan@linux.intel.com>");
+20 -35
drivers/thermal/intel/intel_quark_dts_thermal.c
··· 84 84 #define QRK_DTS_MASK_TP_THRES 0xFF 85 85 #define QRK_DTS_SHIFT_TP 8 86 86 #define QRK_DTS_ID_TP_CRITICAL 0 87 + #define QRK_DTS_ID_TP_HOT 1 87 88 #define QRK_DTS_SAFE_TP_THRES 105 88 89 89 90 /* Thermal Sensor Register Lock */ ··· 105 104 u32 store_ptps; 106 105 u32 store_dts_enable; 107 106 struct thermal_zone_device *tzone; 107 + struct thermal_trip trips[QRK_MAX_DTS_TRIPS]; 108 108 }; 109 109 110 110 static struct soc_sensor_entry *soc_dts; ··· 174 172 return ret; 175 173 } 176 174 177 - static int _get_trip_temp(int trip, int *temp) 175 + static int get_trip_temp(int trip) 178 176 { 179 - int status; 177 + int status, temp; 180 178 u32 out; 181 179 182 180 mutex_lock(&dts_update_mutex); ··· 185 183 mutex_unlock(&dts_update_mutex); 186 184 187 185 if (status) 188 - return status; 186 + return THERMAL_TEMP_INVALID; 189 187 190 188 /* 191 189 * Thermal Sensor Programmable Trip Point Register has 8-bit ··· 193 191 * thresholds. The threshold value is always offset by its 194 192 * temperature base (50 degree Celsius). 195 193 */ 196 - *temp = (out >> (trip * QRK_DTS_SHIFT_TP)) & QRK_DTS_MASK_TP_THRES; 197 - *temp -= QRK_DTS_TEMP_BASE; 194 + temp = (out >> (trip * QRK_DTS_SHIFT_TP)) & QRK_DTS_MASK_TP_THRES; 195 + temp -= QRK_DTS_TEMP_BASE; 198 196 199 - return 0; 200 - } 201 - 202 - static inline int sys_get_trip_temp(struct thermal_zone_device *tzd, 203 - int trip, int *temp) 204 - { 205 - return _get_trip_temp(trip, temp); 206 - } 207 - 208 - static inline int sys_get_crit_temp(struct thermal_zone_device *tzd, int *temp) 209 - { 210 - return _get_trip_temp(QRK_DTS_ID_TP_CRITICAL, temp); 197 + return temp; 211 198 } 212 199 213 200 static int update_trip_temp(struct soc_sensor_entry *aux_entry, ··· 253 262 return update_trip_temp(tzd->devdata, trip, temp); 254 263 } 255 264 256 - static int sys_get_trip_type(struct thermal_zone_device *thermal, 257 - int trip, enum thermal_trip_type *type) 258 - { 259 - if (trip) 260 - *type = THERMAL_TRIP_HOT; 261 - else 262 - *type = THERMAL_TRIP_CRITICAL; 263 - 264 - return 0; 265 - } 266 - 267 265 static int sys_get_curr_temp(struct thermal_zone_device *tzd, 268 266 int *temp) 269 267 { ··· 295 315 296 316 static struct thermal_zone_device_ops tzone_ops = { 297 317 .get_temp = sys_get_curr_temp, 298 - .get_trip_temp = sys_get_trip_temp, 299 - .get_trip_type = sys_get_trip_type, 300 318 .set_trip_temp = sys_set_trip_temp, 301 - .get_crit_temp = sys_get_crit_temp, 302 319 .change_mode = sys_change_mode, 303 320 }; 304 321 ··· 362 385 goto err_ret; 363 386 } 364 387 365 - aux_entry->tzone = thermal_zone_device_register("quark_dts", 366 - QRK_MAX_DTS_TRIPS, 367 - wr_mask, 368 - aux_entry, &tzone_ops, NULL, 0, polling_delay); 388 + aux_entry->trips[QRK_DTS_ID_TP_CRITICAL].temperature = get_trip_temp(QRK_DTS_ID_TP_CRITICAL); 389 + aux_entry->trips[QRK_DTS_ID_TP_CRITICAL].type = THERMAL_TRIP_CRITICAL; 390 + 391 + aux_entry->trips[QRK_DTS_ID_TP_HOT].temperature = get_trip_temp(QRK_DTS_ID_TP_HOT); 392 + aux_entry->trips[QRK_DTS_ID_TP_HOT].type = THERMAL_TRIP_HOT; 393 + 394 + aux_entry->tzone = thermal_zone_device_register_with_trips("quark_dts", 395 + aux_entry->trips, 396 + QRK_MAX_DTS_TRIPS, 397 + wr_mask, 398 + aux_entry, &tzone_ops, 399 + NULL, 0, polling_delay); 369 400 if (IS_ERR(aux_entry->tzone)) { 370 401 err = PTR_ERR(aux_entry->tzone); 371 402 goto err_ret;
+6 -29
drivers/thermal/intel/intel_soc_dts_iosf.c
··· 7 7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 8 9 9 #include <linux/bitops.h> 10 + #include <linux/intel_tcc.h> 10 11 #include <linux/module.h> 11 12 #include <linux/slab.h> 12 13 #include <linux/interrupt.h> ··· 45 44 46 45 /* DTS0 and DTS 1 */ 47 46 #define SOC_MAX_DTS_SENSORS 2 48 - 49 - static int get_tj_max(u32 *tj_max) 50 - { 51 - u32 eax, edx; 52 - u32 val; 53 - int err; 54 - 55 - err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); 56 - if (err) 57 - goto err_ret; 58 - else { 59 - val = (eax >> 16) & 0xff; 60 - if (val) 61 - *tj_max = val * 1000; 62 - else { 63 - err = -EINVAL; 64 - goto err_ret; 65 - } 66 - } 67 - 68 - return 0; 69 - err_ret: 70 - *tj_max = 0; 71 - 72 - return err; 73 - } 74 47 75 48 static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip, 76 49 int *temp) ··· 380 405 { 381 406 struct intel_soc_dts_sensors *sensors; 382 407 bool notification; 383 - u32 tj_max; 408 + int tj_max; 384 409 int ret; 385 410 int i; 386 411 ··· 390 415 if (!trip_count || read_only_trip_count > trip_count) 391 416 return ERR_PTR(-EINVAL); 392 417 393 - if (get_tj_max(&tj_max)) 394 - return ERR_PTR(-EINVAL); 418 + tj_max = intel_tcc_get_tjmax(-1); 419 + if (tj_max < 0) 420 + return ERR_PTR(tj_max); 395 421 396 422 sensors = kzalloc(sizeof(*sensors), GFP_KERNEL); 397 423 if (!sensors) ··· 451 475 } 452 476 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit); 453 477 478 + MODULE_IMPORT_NS(INTEL_TCC); 454 479 MODULE_LICENSE("GPL v2");
+139
drivers/thermal/intel/intel_tcc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * intel_tcc.c - Library for Intel TCC (thermal control circuitry) MSR access 4 + * Copyright (c) 2022, Intel Corporation. 5 + */ 6 + 7 + #include <linux/errno.h> 8 + #include <linux/intel_tcc.h> 9 + #include <asm/msr.h> 10 + 11 + /** 12 + * intel_tcc_get_tjmax() - returns the default TCC activation Temperature 13 + * @cpu: cpu that the MSR should be run on, nagative value means any cpu. 14 + * 15 + * Get the TjMax value, which is the default thermal throttling or TCC 16 + * activation temperature in degrees C. 17 + * 18 + * Return: Tjmax value in degrees C on success, negative error code otherwise. 19 + */ 20 + int intel_tcc_get_tjmax(int cpu) 21 + { 22 + u32 low, high; 23 + int val, err; 24 + 25 + if (cpu < 0) 26 + err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high); 27 + else 28 + err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high); 29 + if (err) 30 + return err; 31 + 32 + val = (low >> 16) & 0xff; 33 + 34 + return val ? val : -ENODATA; 35 + } 36 + EXPORT_SYMBOL_NS_GPL(intel_tcc_get_tjmax, INTEL_TCC); 37 + 38 + /** 39 + * intel_tcc_get_offset() - returns the TCC Offset value to Tjmax 40 + * @cpu: cpu that the MSR should be run on, nagative value means any cpu. 41 + * 42 + * Get the TCC offset value to Tjmax. The effective thermal throttling or TCC 43 + * activation temperature equals "Tjmax" - "TCC Offset", in degrees C. 44 + * 45 + * Return: Tcc offset value in degrees C on success, negative error code otherwise. 46 + */ 47 + int intel_tcc_get_offset(int cpu) 48 + { 49 + u32 low, high; 50 + int err; 51 + 52 + if (cpu < 0) 53 + err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high); 54 + else 55 + err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high); 56 + if (err) 57 + return err; 58 + 59 + return (low >> 24) & 0x3f; 60 + } 61 + EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, INTEL_TCC); 62 + 63 + /** 64 + * intel_tcc_set_offset() - set the TCC offset value to Tjmax 65 + * @cpu: cpu that the MSR should be run on, nagative value means any cpu. 66 + * @offset: TCC offset value in degree C 67 + * 68 + * Set the TCC Offset value to Tjmax. The effective thermal throttling or TCC 69 + * activation temperature equals "Tjmax" - "TCC Offset", in degree C. 70 + * 71 + * Return: On success returns 0, negative error code otherwise. 72 + */ 73 + 74 + int intel_tcc_set_offset(int cpu, int offset) 75 + { 76 + u32 low, high; 77 + int err; 78 + 79 + if (offset < 0 || offset > 0x3f) 80 + return -EINVAL; 81 + 82 + if (cpu < 0) 83 + err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high); 84 + else 85 + err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high); 86 + if (err) 87 + return err; 88 + 89 + /* MSR Locked */ 90 + if (low & BIT(31)) 91 + return -EPERM; 92 + 93 + low &= ~(0x3f << 24); 94 + low |= offset << 24; 95 + 96 + if (cpu < 0) 97 + return wrmsr_safe(MSR_IA32_TEMPERATURE_TARGET, low, high); 98 + else 99 + return wrmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, low, high); 100 + } 101 + EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC); 102 + 103 + /** 104 + * intel_tcc_get_temp() - returns the current temperature 105 + * @cpu: cpu that the MSR should be run on, nagative value means any cpu. 106 + * @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor. 107 + * 108 + * Get the current temperature returned by the CPU core/package level 109 + * thermal sensor, in degrees C. 110 + * 111 + * Return: Temperature in degrees C on success, negative error code otherwise. 112 + */ 113 + int intel_tcc_get_temp(int cpu, bool pkg) 114 + { 115 + u32 low, high; 116 + u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS; 117 + int tjmax, temp, err; 118 + 119 + tjmax = intel_tcc_get_tjmax(cpu); 120 + if (tjmax < 0) 121 + return tjmax; 122 + 123 + if (cpu < 0) 124 + err = rdmsr_safe(msr, &low, &high); 125 + else 126 + err = rdmsr_safe_on_cpu(cpu, msr, &low, &high); 127 + if (err) 128 + return err; 129 + 130 + /* Temperature is beyond the valid thermal sensor range */ 131 + if (!(low & BIT(31))) 132 + return -ENODATA; 133 + 134 + temp = tjmax - ((low >> 16) & 0x7f); 135 + 136 + /* Do not allow negative CPU temperature */ 137 + return temp >= 0 ? temp : -ENODATA; 138 + } 139 + EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC);
+8 -29
drivers/thermal/intel/intel_tcc_cooling.c
··· 7 7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 8 9 9 #include <linux/device.h> 10 + #include <linux/intel_tcc.h> 10 11 #include <linux/module.h> 11 12 #include <linux/thermal.h> 12 13 #include <asm/cpu_device_id.h> 13 14 14 - #define TCC_SHIFT 24 15 - #define TCC_MASK (0x3fULL<<24) 16 15 #define TCC_PROGRAMMABLE BIT(30) 17 16 #define TCC_LOCKED BIT(31) 18 17 ··· 20 21 static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long 21 22 *state) 22 23 { 23 - *state = TCC_MASK >> TCC_SHIFT; 24 - return 0; 25 - } 26 - 27 - static int tcc_offset_update(int tcc) 28 - { 29 - u64 val; 30 - int err; 31 - 32 - err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val); 33 - if (err) 34 - return err; 35 - 36 - val &= ~TCC_MASK; 37 - val |= tcc << TCC_SHIFT; 38 - 39 - err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val); 40 - if (err) 41 - return err; 42 - 24 + *state = 0x3f; 43 25 return 0; 44 26 } 45 27 46 28 static int tcc_get_cur_state(struct thermal_cooling_device *cdev, unsigned long 47 29 *state) 48 30 { 49 - u64 val; 50 - int err; 31 + int offset = intel_tcc_get_offset(-1); 51 32 52 - err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val); 53 - if (err) 54 - return err; 33 + if (offset < 0) 34 + return offset; 55 35 56 - *state = (val & TCC_MASK) >> TCC_SHIFT; 36 + *state = offset; 57 37 return 0; 58 38 } 59 39 60 40 static int tcc_set_cur_state(struct thermal_cooling_device *cdev, unsigned long 61 41 state) 62 42 { 63 - return tcc_offset_update(state); 43 + return intel_tcc_set_offset(-1, (int)state); 64 44 } 65 45 66 46 static const struct thermal_cooling_device_ops tcc_cooling_ops = { ··· 118 140 119 141 module_exit(tcc_cooling_exit) 120 142 143 + MODULE_IMPORT_NS(INTEL_TCC); 121 144 MODULE_DESCRIPTION("TCC offset cooling device Driver"); 122 145 MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>"); 123 146 MODULE_LICENSE("GPL v2");
+88 -88
drivers/thermal/intel/x86_pkg_temp_thermal.c
··· 7 7 8 8 #include <linux/module.h> 9 9 #include <linux/init.h> 10 + #include <linux/intel_tcc.h> 10 11 #include <linux/err.h> 11 12 #include <linux/param.h> 12 13 #include <linux/device.h> ··· 49 48 struct zone_device { 50 49 int cpu; 51 50 bool work_scheduled; 52 - u32 tj_max; 53 51 u32 msr_pkg_therm_low; 54 52 u32 msr_pkg_therm_high; 55 53 struct delayed_work work; 56 54 struct thermal_zone_device *tzone; 55 + struct thermal_trip *trips; 57 56 struct cpumask cpumask; 58 57 }; 59 58 ··· 105 104 return NULL; 106 105 } 107 106 108 - /* 109 - * tj-max is interesting because threshold is set relative to this 110 - * temperature. 111 - */ 112 - static int get_tj_max(int cpu, u32 *tj_max) 113 - { 114 - u32 eax, edx, val; 115 - int err; 116 - 117 - err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); 118 - if (err) 119 - return err; 120 - 121 - val = (eax >> 16) & 0xff; 122 - *tj_max = val * 1000; 123 - 124 - return val ? 0 : -EINVAL; 125 - } 126 - 127 107 static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) 128 108 { 129 109 struct zone_device *zonedev = tzd->devdata; 130 - u32 eax, edx; 110 + int val; 131 111 132 - rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_STATUS, 133 - &eax, &edx); 134 - if (eax & 0x80000000) { 135 - *temp = zonedev->tj_max - ((eax >> 16) & 0x7f) * 1000; 136 - pr_debug("sys_get_curr_temp %d\n", *temp); 137 - return 0; 138 - } 139 - return -EINVAL; 140 - } 112 + val = intel_tcc_get_temp(zonedev->cpu, true); 113 + if (val < 0) 114 + return val; 141 115 142 - static int sys_get_trip_temp(struct thermal_zone_device *tzd, 143 - int trip, int *temp) 144 - { 145 - struct zone_device *zonedev = tzd->devdata; 146 - unsigned long thres_reg_value; 147 - u32 mask, shift, eax, edx; 148 - int ret; 149 - 150 - if (trip >= MAX_NUMBER_OF_TRIPS) 151 - return -EINVAL; 152 - 153 - if (trip) { 154 - mask = THERM_MASK_THRESHOLD1; 155 - shift = THERM_SHIFT_THRESHOLD1; 156 - } else { 157 - mask = THERM_MASK_THRESHOLD0; 158 - shift = THERM_SHIFT_THRESHOLD0; 159 - } 160 - 161 - ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, 162 - &eax, &edx); 163 - if (ret < 0) 164 - return ret; 165 - 166 - thres_reg_value = (eax & mask) >> shift; 167 - if (thres_reg_value) 168 - *temp = zonedev->tj_max - thres_reg_value * 1000; 169 - else 170 - *temp = THERMAL_TEMP_INVALID; 171 - pr_debug("sys_get_trip_temp %d\n", *temp); 172 - 116 + *temp = val * 1000; 117 + pr_debug("sys_get_curr_temp %d\n", *temp); 173 118 return 0; 174 119 } 175 120 ··· 124 177 { 125 178 struct zone_device *zonedev = tzd->devdata; 126 179 u32 l, h, mask, shift, intr; 127 - int ret; 180 + int tj_max, ret; 128 181 129 - if (trip >= MAX_NUMBER_OF_TRIPS || temp >= zonedev->tj_max) 182 + tj_max = intel_tcc_get_tjmax(zonedev->cpu); 183 + if (tj_max < 0) 184 + return tj_max; 185 + tj_max *= 1000; 186 + 187 + if (trip >= MAX_NUMBER_OF_TRIPS || temp >= tj_max) 130 188 return -EINVAL; 131 189 132 190 ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, ··· 156 204 if (!temp) { 157 205 l &= ~intr; 158 206 } else { 159 - l |= (zonedev->tj_max - temp)/1000 << shift; 207 + l |= (tj_max - temp)/1000 << shift; 160 208 l |= intr; 161 209 } 162 210 ··· 164 212 l, h); 165 213 } 166 214 167 - static int sys_get_trip_type(struct thermal_zone_device *thermal, int trip, 168 - enum thermal_trip_type *type) 169 - { 170 - *type = THERMAL_TRIP_PASSIVE; 171 - return 0; 172 - } 173 - 174 215 /* Thermal zone callback registry */ 175 216 static struct thermal_zone_device_ops tzone_ops = { 176 217 .get_temp = sys_get_curr_temp, 177 - .get_trip_temp = sys_get_trip_temp, 178 - .get_trip_type = sys_get_trip_type, 179 218 .set_trip_temp = sys_set_trip_temp, 180 219 }; 181 220 ··· 266 323 return 0; 267 324 } 268 325 326 + static struct thermal_trip *pkg_temp_thermal_trips_init(int cpu, int tj_max, int num_trips) 327 + { 328 + struct thermal_trip *trips; 329 + unsigned long thres_reg_value; 330 + u32 mask, shift, eax, edx; 331 + int ret, i; 332 + 333 + trips = kzalloc(sizeof(*trips) * num_trips, GFP_KERNEL); 334 + if (!trips) 335 + return ERR_PTR(-ENOMEM); 336 + 337 + for (i = 0; i < num_trips; i++) { 338 + 339 + if (i) { 340 + mask = THERM_MASK_THRESHOLD1; 341 + shift = THERM_SHIFT_THRESHOLD1; 342 + } else { 343 + mask = THERM_MASK_THRESHOLD0; 344 + shift = THERM_SHIFT_THRESHOLD0; 345 + } 346 + 347 + ret = rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, 348 + &eax, &edx); 349 + if (ret < 0) { 350 + kfree(trips); 351 + return ERR_PTR(ret); 352 + } 353 + 354 + thres_reg_value = (eax & mask) >> shift; 355 + 356 + trips[i].temperature = thres_reg_value ? 357 + tj_max - thres_reg_value * 1000 : THERMAL_TEMP_INVALID; 358 + 359 + trips[i].type = THERMAL_TRIP_PASSIVE; 360 + 361 + pr_debug("%s: cpu=%d, trip=%d, temp=%d\n", 362 + __func__, cpu, i, trips[i].temperature); 363 + } 364 + 365 + return trips; 366 + } 367 + 269 368 static int pkg_temp_thermal_device_add(unsigned int cpu) 270 369 { 271 370 int id = topology_logical_die_id(cpu); 272 - u32 tj_max, eax, ebx, ecx, edx; 371 + u32 eax, ebx, ecx, edx; 273 372 struct zone_device *zonedev; 274 373 int thres_count, err; 374 + int tj_max; 275 375 276 376 if (id >= max_id) 277 377 return -ENOMEM; ··· 326 340 327 341 thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS); 328 342 329 - err = get_tj_max(cpu, &tj_max); 330 - if (err) 331 - return err; 343 + tj_max = intel_tcc_get_tjmax(cpu); 344 + if (tj_max < 0) 345 + return tj_max; 332 346 333 347 zonedev = kzalloc(sizeof(*zonedev), GFP_KERNEL); 334 348 if (!zonedev) 335 349 return -ENOMEM; 336 350 351 + zonedev->trips = pkg_temp_thermal_trips_init(cpu, tj_max, thres_count); 352 + if (IS_ERR(zonedev->trips)) { 353 + err = PTR_ERR(zonedev->trips); 354 + goto out_kfree_zonedev; 355 + } 356 + 337 357 INIT_DELAYED_WORK(&zonedev->work, pkg_temp_thermal_threshold_work_fn); 338 358 zonedev->cpu = cpu; 339 - zonedev->tj_max = tj_max; 340 - zonedev->tzone = thermal_zone_device_register("x86_pkg_temp", 341 - thres_count, 359 + zonedev->tzone = thermal_zone_device_register_with_trips("x86_pkg_temp", 360 + zonedev->trips, thres_count, 342 361 (thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01, 343 362 zonedev, &tzone_ops, &pkg_temp_tz_params, 0, 0); 344 363 if (IS_ERR(zonedev->tzone)) { 345 364 err = PTR_ERR(zonedev->tzone); 346 - kfree(zonedev); 347 - return err; 365 + goto out_kfree_trips; 348 366 } 349 367 err = thermal_zone_device_enable(zonedev->tzone); 350 - if (err) { 351 - thermal_zone_device_unregister(zonedev->tzone); 352 - kfree(zonedev); 353 - return err; 354 - } 368 + if (err) 369 + goto out_unregister_tz; 370 + 355 371 /* Store MSR value for package thermal interrupt, to restore at exit */ 356 372 rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low, 357 373 zonedev->msr_pkg_therm_high); ··· 362 374 raw_spin_lock_irq(&pkg_temp_lock); 363 375 zones[id] = zonedev; 364 376 raw_spin_unlock_irq(&pkg_temp_lock); 377 + 365 378 return 0; 379 + 380 + out_unregister_tz: 381 + thermal_zone_device_unregister(zonedev->tzone); 382 + out_kfree_trips: 383 + kfree(zonedev->trips); 384 + out_kfree_zonedev: 385 + kfree(zonedev); 386 + return err; 366 387 } 367 388 368 389 static int pkg_thermal_cpu_offline(unsigned int cpu) ··· 455 458 raw_spin_unlock_irq(&pkg_temp_lock); 456 459 457 460 /* Final cleanup if this is the last cpu */ 458 - if (lastcpu) 461 + if (lastcpu) { 462 + kfree(zonedev->trips); 459 463 kfree(zonedev); 464 + } 460 465 return 0; 461 466 } 462 467 ··· 530 531 } 531 532 module_exit(pkg_temp_thermal_exit) 532 533 534 + MODULE_IMPORT_NS(INTEL_TCC); 533 535 MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver"); 534 536 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 535 537 MODULE_LICENSE("GPL v2");
+1 -3
drivers/thermal/kirkwood_thermal.c
··· 64 64 { 65 65 struct thermal_zone_device *thermal = NULL; 66 66 struct kirkwood_thermal_priv *priv; 67 - struct resource *res; 68 67 int ret; 69 68 70 69 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 71 70 if (!priv) 72 71 return -ENOMEM; 73 72 74 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 75 - priv->sensor = devm_ioremap_resource(&pdev->dev, res); 73 + priv->sensor = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 76 74 if (IS_ERR(priv->sensor)) 77 75 return PTR_ERR(priv->sensor); 78 76
+37
drivers/thermal/mediatek/Kconfig
··· 1 + config MTK_THERMAL 2 + tristate "MediaTek thermal drivers" 3 + depends on THERMAL_OF 4 + help 5 + This is the option for MediaTek thermal software solutions. 6 + Please enable corresponding options to get temperature 7 + information from thermal sensors or turn on throttle 8 + mechaisms for thermal mitigation. 9 + 10 + if MTK_THERMAL 11 + 12 + config MTK_SOC_THERMAL 13 + tristate "AUXADC temperature sensor driver for MediaTek SoCs" 14 + depends on HAS_IOMEM 15 + help 16 + Enable this option if you want to get SoC temperature 17 + information for MediaTek platforms. 18 + This driver configures thermal controllers to collect 19 + temperature via AUXADC interface. 20 + 21 + config MTK_LVTS_THERMAL 22 + tristate "LVTS Thermal Driver for MediaTek SoCs" 23 + depends on HAS_IOMEM 24 + help 25 + Enable this option if you want to get SoC temperature 26 + information for supported MediaTek platforms. 27 + This driver configures LVTS (Low Voltage Thermal Sensor) 28 + thermal controllers to collect temperatures via ASIF 29 + (Analog Serial Interface). 30 + 31 + config MTK_LVTS_THERMAL_DEBUGFS 32 + bool "LVTS thermal debugfs" 33 + depends on MTK_LVTS_THERMAL && DEBUG_FS 34 + help 35 + Enable this option to debug the internals of the device driver. 36 + 37 + endif
+2
drivers/thermal/mediatek/Makefile
··· 1 + obj-$(CONFIG_MTK_SOC_THERMAL) += auxadc_thermal.o 2 + obj-$(CONFIG_MTK_LVTS_THERMAL) += lvts_thermal.o
+1224
drivers/thermal/mediatek/lvts_thermal.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2023 MediaTek Inc. 4 + * Author: Balsam CHIHI <bchihi@baylibre.com> 5 + */ 6 + 7 + #include <linux/clk.h> 8 + #include <linux/clk-provider.h> 9 + #include <linux/delay.h> 10 + #include <linux/debugfs.h> 11 + #include <linux/init.h> 12 + #include <linux/interrupt.h> 13 + #include <linux/iopoll.h> 14 + #include <linux/kernel.h> 15 + #include <linux/nvmem-consumer.h> 16 + #include <linux/of_device.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/reset.h> 19 + #include <linux/thermal.h> 20 + #include <dt-bindings/thermal/mediatek,lvts-thermal.h> 21 + 22 + #define LVTS_MONCTL0(__base) (__base + 0x0000) 23 + #define LVTS_MONCTL1(__base) (__base + 0x0004) 24 + #define LVTS_MONCTL2(__base) (__base + 0x0008) 25 + #define LVTS_MONINT(__base) (__base + 0x000C) 26 + #define LVTS_MONINTSTS(__base) (__base + 0x0010) 27 + #define LVTS_MONIDET0(__base) (__base + 0x0014) 28 + #define LVTS_MONIDET1(__base) (__base + 0x0018) 29 + #define LVTS_MONIDET2(__base) (__base + 0x001C) 30 + #define LVTS_MONIDET3(__base) (__base + 0x0020) 31 + #define LVTS_H2NTHRE(__base) (__base + 0x0024) 32 + #define LVTS_HTHRE(__base) (__base + 0x0028) 33 + #define LVTS_OFFSETH(__base) (__base + 0x0030) 34 + #define LVTS_OFFSETL(__base) (__base + 0x0034) 35 + #define LVTS_MSRCTL0(__base) (__base + 0x0038) 36 + #define LVTS_MSRCTL1(__base) (__base + 0x003C) 37 + #define LVTS_TSSEL(__base) (__base + 0x0040) 38 + #define LVTS_CALSCALE(__base) (__base + 0x0048) 39 + #define LVTS_ID(__base) (__base + 0x004C) 40 + #define LVTS_CONFIG(__base) (__base + 0x0050) 41 + #define LVTS_EDATA00(__base) (__base + 0x0054) 42 + #define LVTS_EDATA01(__base) (__base + 0x0058) 43 + #define LVTS_EDATA02(__base) (__base + 0x005C) 44 + #define LVTS_EDATA03(__base) (__base + 0x0060) 45 + #define LVTS_MSR0(__base) (__base + 0x0090) 46 + #define LVTS_MSR1(__base) (__base + 0x0094) 47 + #define LVTS_MSR2(__base) (__base + 0x0098) 48 + #define LVTS_MSR3(__base) (__base + 0x009C) 49 + #define LVTS_IMMD0(__base) (__base + 0x00A0) 50 + #define LVTS_IMMD1(__base) (__base + 0x00A4) 51 + #define LVTS_IMMD2(__base) (__base + 0x00A8) 52 + #define LVTS_IMMD3(__base) (__base + 0x00AC) 53 + #define LVTS_PROTCTL(__base) (__base + 0x00C0) 54 + #define LVTS_PROTTA(__base) (__base + 0x00C4) 55 + #define LVTS_PROTTB(__base) (__base + 0x00C8) 56 + #define LVTS_PROTTC(__base) (__base + 0x00CC) 57 + #define LVTS_CLKEN(__base) (__base + 0x00E4) 58 + 59 + #define LVTS_PERIOD_UNIT ((118 * 1000) / (256 * 38)) 60 + #define LVTS_GROUP_INTERVAL 1 61 + #define LVTS_FILTER_INTERVAL 1 62 + #define LVTS_SENSOR_INTERVAL 1 63 + #define LVTS_HW_FILTER 0x2 64 + #define LVTS_TSSEL_CONF 0x13121110 65 + #define LVTS_CALSCALE_CONF 0x300 66 + #define LVTS_MONINT_CONF 0x9FBF7BDE 67 + 68 + #define LVTS_INT_SENSOR0 0x0009001F 69 + #define LVTS_INT_SENSOR1 0X000881F0 70 + #define LVTS_INT_SENSOR2 0x00247C00 71 + #define LVTS_INT_SENSOR3 0x1FC00000 72 + 73 + #define LVTS_SENSOR_MAX 4 74 + #define LVTS_GOLDEN_TEMP_MAX 62 75 + #define LVTS_GOLDEN_TEMP_DEFAULT 50 76 + #define LVTS_COEFF_A -250460 77 + #define LVTS_COEFF_B 250460 78 + 79 + #define LVTS_MSR_IMMEDIATE_MODE 0 80 + #define LVTS_MSR_FILTERED_MODE 1 81 + 82 + #define LVTS_HW_SHUTDOWN_MT8195 105000 83 + 84 + static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; 85 + static int coeff_b = LVTS_COEFF_B; 86 + 87 + struct lvts_sensor_data { 88 + int dt_id; 89 + }; 90 + 91 + struct lvts_ctrl_data { 92 + struct lvts_sensor_data lvts_sensor[LVTS_SENSOR_MAX]; 93 + int cal_offset[LVTS_SENSOR_MAX]; 94 + int hw_tshut_temp; 95 + int num_lvts_sensor; 96 + int offset; 97 + int mode; 98 + }; 99 + 100 + struct lvts_data { 101 + const struct lvts_ctrl_data *lvts_ctrl; 102 + int num_lvts_ctrl; 103 + }; 104 + 105 + struct lvts_sensor { 106 + struct thermal_zone_device *tz; 107 + void __iomem *msr; 108 + void __iomem *base; 109 + int id; 110 + int dt_id; 111 + }; 112 + 113 + struct lvts_ctrl { 114 + struct lvts_sensor sensors[LVTS_SENSOR_MAX]; 115 + u32 calibration[LVTS_SENSOR_MAX]; 116 + u32 hw_tshut_raw_temp; 117 + int num_lvts_sensor; 118 + int mode; 119 + void __iomem *base; 120 + }; 121 + 122 + struct lvts_domain { 123 + struct lvts_ctrl *lvts_ctrl; 124 + struct reset_control *reset; 125 + struct clk *clk; 126 + int num_lvts_ctrl; 127 + void __iomem *base; 128 + size_t calib_len; 129 + u8 *calib; 130 + #ifdef CONFIG_DEBUG_FS 131 + struct dentry *dom_dentry; 132 + #endif 133 + }; 134 + 135 + #ifdef CONFIG_MTK_LVTS_THERMAL_DEBUGFS 136 + 137 + #define LVTS_DEBUG_FS_REGS(__reg) \ 138 + { \ 139 + .name = __stringify(__reg), \ 140 + .offset = __reg(0), \ 141 + } 142 + 143 + static const struct debugfs_reg32 lvts_regs[] = { 144 + LVTS_DEBUG_FS_REGS(LVTS_MONCTL0), 145 + LVTS_DEBUG_FS_REGS(LVTS_MONCTL1), 146 + LVTS_DEBUG_FS_REGS(LVTS_MONCTL2), 147 + LVTS_DEBUG_FS_REGS(LVTS_MONINT), 148 + LVTS_DEBUG_FS_REGS(LVTS_MONINTSTS), 149 + LVTS_DEBUG_FS_REGS(LVTS_MONIDET0), 150 + LVTS_DEBUG_FS_REGS(LVTS_MONIDET1), 151 + LVTS_DEBUG_FS_REGS(LVTS_MONIDET2), 152 + LVTS_DEBUG_FS_REGS(LVTS_MONIDET3), 153 + LVTS_DEBUG_FS_REGS(LVTS_H2NTHRE), 154 + LVTS_DEBUG_FS_REGS(LVTS_HTHRE), 155 + LVTS_DEBUG_FS_REGS(LVTS_OFFSETH), 156 + LVTS_DEBUG_FS_REGS(LVTS_OFFSETL), 157 + LVTS_DEBUG_FS_REGS(LVTS_MSRCTL0), 158 + LVTS_DEBUG_FS_REGS(LVTS_MSRCTL1), 159 + LVTS_DEBUG_FS_REGS(LVTS_TSSEL), 160 + LVTS_DEBUG_FS_REGS(LVTS_CALSCALE), 161 + LVTS_DEBUG_FS_REGS(LVTS_ID), 162 + LVTS_DEBUG_FS_REGS(LVTS_CONFIG), 163 + LVTS_DEBUG_FS_REGS(LVTS_EDATA00), 164 + LVTS_DEBUG_FS_REGS(LVTS_EDATA01), 165 + LVTS_DEBUG_FS_REGS(LVTS_EDATA02), 166 + LVTS_DEBUG_FS_REGS(LVTS_EDATA03), 167 + LVTS_DEBUG_FS_REGS(LVTS_MSR0), 168 + LVTS_DEBUG_FS_REGS(LVTS_MSR1), 169 + LVTS_DEBUG_FS_REGS(LVTS_MSR2), 170 + LVTS_DEBUG_FS_REGS(LVTS_MSR3), 171 + LVTS_DEBUG_FS_REGS(LVTS_IMMD0), 172 + LVTS_DEBUG_FS_REGS(LVTS_IMMD1), 173 + LVTS_DEBUG_FS_REGS(LVTS_IMMD2), 174 + LVTS_DEBUG_FS_REGS(LVTS_IMMD3), 175 + LVTS_DEBUG_FS_REGS(LVTS_PROTCTL), 176 + LVTS_DEBUG_FS_REGS(LVTS_PROTTA), 177 + LVTS_DEBUG_FS_REGS(LVTS_PROTTB), 178 + LVTS_DEBUG_FS_REGS(LVTS_PROTTC), 179 + LVTS_DEBUG_FS_REGS(LVTS_CLKEN), 180 + }; 181 + 182 + static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td) 183 + { 184 + struct debugfs_regset32 *regset; 185 + struct lvts_ctrl *lvts_ctrl; 186 + struct dentry *dentry; 187 + char name[64]; 188 + int i; 189 + 190 + lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL); 191 + if (!lvts_td->dom_dentry) 192 + return 0; 193 + 194 + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { 195 + 196 + lvts_ctrl = &lvts_td->lvts_ctrl[i]; 197 + 198 + sprintf(name, "controller%d", i); 199 + dentry = debugfs_create_dir(name, lvts_td->dom_dentry); 200 + if (!dentry) 201 + continue; 202 + 203 + regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); 204 + if (!regset) 205 + continue; 206 + 207 + regset->base = lvts_ctrl->base; 208 + regset->regs = lvts_regs; 209 + regset->nregs = ARRAY_SIZE(lvts_regs); 210 + 211 + debugfs_create_regset32("registers", 0400, dentry, regset); 212 + } 213 + 214 + return 0; 215 + } 216 + 217 + static void lvts_debugfs_exit(struct lvts_domain *lvts_td) 218 + { 219 + debugfs_remove_recursive(lvts_td->dom_dentry); 220 + } 221 + 222 + #else 223 + 224 + static inline int lvts_debugfs_init(struct device *dev, 225 + struct lvts_domain *lvts_td) 226 + { 227 + return 0; 228 + } 229 + 230 + static void lvts_debugfs_exit(struct lvts_domain *lvts_td) { } 231 + 232 + #endif 233 + 234 + static int lvts_raw_to_temp(u32 raw_temp) 235 + { 236 + int temperature; 237 + 238 + temperature = ((s64)(raw_temp & 0xFFFF) * LVTS_COEFF_A) >> 14; 239 + temperature += coeff_b; 240 + 241 + return temperature; 242 + } 243 + 244 + static u32 lvts_temp_to_raw(int temperature) 245 + { 246 + u32 raw_temp = ((s64)(coeff_b - temperature)) << 14; 247 + 248 + raw_temp = div_s64(raw_temp, -LVTS_COEFF_A); 249 + 250 + return raw_temp; 251 + } 252 + 253 + static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) 254 + { 255 + struct lvts_sensor *lvts_sensor = tz->devdata; 256 + void __iomem *msr = lvts_sensor->msr; 257 + u32 value; 258 + 259 + /* 260 + * Measurement registers: 261 + * 262 + * LVTS_MSR[0-3] / LVTS_IMMD[0-3] 263 + * 264 + * Bits: 265 + * 266 + * 32-17: Unused 267 + * 16 : Valid temperature 268 + * 15-0 : Raw temperature 269 + */ 270 + value = readl(msr); 271 + 272 + /* 273 + * As the thermal zone temperature will read before the 274 + * hardware sensor is fully initialized, we have to check the 275 + * validity of the temperature returned when reading the 276 + * measurement register. The thermal controller will set the 277 + * valid bit temperature only when it is totally initialized. 278 + * 279 + * Otherwise, we may end up with garbage values out of the 280 + * functionning temperature and directly jump to a system 281 + * shutdown. 282 + */ 283 + if (!(value & BIT(16))) 284 + return -EAGAIN; 285 + 286 + *temp = lvts_raw_to_temp(value & 0xFFFF); 287 + 288 + return 0; 289 + } 290 + 291 + static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) 292 + { 293 + struct lvts_sensor *lvts_sensor = tz->devdata; 294 + void __iomem *base = lvts_sensor->base; 295 + u32 raw_low = lvts_temp_to_raw(low); 296 + u32 raw_high = lvts_temp_to_raw(high); 297 + 298 + /* 299 + * Hot to normal temperature threshold 300 + * 301 + * LVTS_H2NTHRE 302 + * 303 + * Bits: 304 + * 305 + * 14-0 : Raw temperature for threshold 306 + */ 307 + if (low != -INT_MAX) { 308 + dev_dbg(&tz->device, "Setting low limit temperature interrupt: %d\n", low); 309 + writel(raw_low, LVTS_H2NTHRE(base)); 310 + } 311 + 312 + /* 313 + * Hot temperature threshold 314 + * 315 + * LVTS_HTHRE 316 + * 317 + * Bits: 318 + * 319 + * 14-0 : Raw temperature for threshold 320 + */ 321 + dev_dbg(&tz->device, "Setting high limit temperature interrupt: %d\n", high); 322 + writel(raw_high, LVTS_HTHRE(base)); 323 + 324 + return 0; 325 + } 326 + 327 + static irqreturn_t lvts_ctrl_irq_handler(struct lvts_ctrl *lvts_ctrl) 328 + { 329 + irqreturn_t iret = IRQ_NONE; 330 + u32 value; 331 + u32 masks[] = { 332 + LVTS_INT_SENSOR0, 333 + LVTS_INT_SENSOR1, 334 + LVTS_INT_SENSOR2, 335 + LVTS_INT_SENSOR3 336 + }; 337 + int i; 338 + 339 + /* 340 + * Interrupt monitoring status 341 + * 342 + * LVTS_MONINTST 343 + * 344 + * Bits: 345 + * 346 + * 31 : Interrupt for stage 3 347 + * 30 : Interrupt for stage 2 348 + * 29 : Interrupt for state 1 349 + * 28 : Interrupt using filter on sensor 3 350 + * 351 + * 27 : Interrupt using immediate on sensor 3 352 + * 26 : Interrupt normal to hot on sensor 3 353 + * 25 : Interrupt high offset on sensor 3 354 + * 24 : Interrupt low offset on sensor 3 355 + * 356 + * 23 : Interrupt hot threshold on sensor 3 357 + * 22 : Interrupt cold threshold on sensor 3 358 + * 21 : Interrupt using filter on sensor 2 359 + * 20 : Interrupt using filter on sensor 1 360 + * 361 + * 19 : Interrupt using filter on sensor 0 362 + * 18 : Interrupt using immediate on sensor 2 363 + * 17 : Interrupt using immediate on sensor 1 364 + * 16 : Interrupt using immediate on sensor 0 365 + * 366 + * 15 : Interrupt device access timeout interrupt 367 + * 14 : Interrupt normal to hot on sensor 2 368 + * 13 : Interrupt high offset interrupt on sensor 2 369 + * 12 : Interrupt low offset interrupt on sensor 2 370 + * 371 + * 11 : Interrupt hot threshold on sensor 2 372 + * 10 : Interrupt cold threshold on sensor 2 373 + * 9 : Interrupt normal to hot on sensor 1 374 + * 8 : Interrupt high offset interrupt on sensor 1 375 + * 376 + * 7 : Interrupt low offset interrupt on sensor 1 377 + * 6 : Interrupt hot threshold on sensor 1 378 + * 5 : Interrupt cold threshold on sensor 1 379 + * 4 : Interrupt normal to hot on sensor 0 380 + * 381 + * 3 : Interrupt high offset interrupt on sensor 0 382 + * 2 : Interrupt low offset interrupt on sensor 0 383 + * 1 : Interrupt hot threshold on sensor 0 384 + * 0 : Interrupt cold threshold on sensor 0 385 + * 386 + * We are interested in the sensor(s) responsible of the 387 + * interrupt event. We update the thermal framework with the 388 + * thermal zone associated with the sensor. The framework will 389 + * take care of the rest whatever the kind of interrupt, we 390 + * are only interested in which sensor raised the interrupt. 391 + * 392 + * sensor 3 interrupt: 0001 1111 1100 0000 0000 0000 0000 0000 393 + * => 0x1FC00000 394 + * sensor 2 interrupt: 0000 0000 0010 0100 0111 1100 0000 0000 395 + * => 0x00247C00 396 + * sensor 1 interrupt: 0000 0000 0001 0001 0000 0011 1110 0000 397 + * => 0X000881F0 398 + * sensor 0 interrupt: 0000 0000 0000 1001 0000 0000 0001 1111 399 + * => 0x0009001F 400 + */ 401 + value = readl(LVTS_MONINTSTS(lvts_ctrl->base)); 402 + 403 + /* 404 + * Let's figure out which sensors raised the interrupt 405 + * 406 + * NOTE: the masks array must be ordered with the index 407 + * corresponding to the sensor id eg. index=0, mask for 408 + * sensor0. 409 + */ 410 + for (i = 0; i < ARRAY_SIZE(masks); i++) { 411 + 412 + if (!(value & masks[i])) 413 + continue; 414 + 415 + thermal_zone_device_update(lvts_ctrl->sensors[i].tz, 416 + THERMAL_TRIP_VIOLATED); 417 + iret = IRQ_HANDLED; 418 + } 419 + 420 + /* 421 + * Write back to clear the interrupt status (W1C) 422 + */ 423 + writel(value, LVTS_MONINTSTS(lvts_ctrl->base)); 424 + 425 + return iret; 426 + } 427 + 428 + /* 429 + * Temperature interrupt handler. Even if the driver supports more 430 + * interrupt modes, we use the interrupt when the temperature crosses 431 + * the hot threshold the way up and the way down (modulo the 432 + * hysteresis). 433 + * 434 + * Each thermal domain has a couple of interrupts, one for hardware 435 + * reset and another one for all the thermal events happening on the 436 + * different sensors. 437 + * 438 + * The interrupt is configured for thermal events when crossing the 439 + * hot temperature limit. At each interrupt, we check in every 440 + * controller if there is an interrupt pending. 441 + */ 442 + static irqreturn_t lvts_irq_handler(int irq, void *data) 443 + { 444 + struct lvts_domain *lvts_td = data; 445 + irqreturn_t aux, iret = IRQ_NONE; 446 + int i; 447 + 448 + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { 449 + 450 + aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl); 451 + if (aux != IRQ_HANDLED) 452 + continue; 453 + 454 + iret = IRQ_HANDLED; 455 + } 456 + 457 + return iret; 458 + } 459 + 460 + static struct thermal_zone_device_ops lvts_ops = { 461 + .get_temp = lvts_get_temp, 462 + .set_trips = lvts_set_trips, 463 + }; 464 + 465 + static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, 466 + const struct lvts_ctrl_data *lvts_ctrl_data) 467 + { 468 + struct lvts_sensor *lvts_sensor = lvts_ctrl->sensors; 469 + void __iomem *msr_regs[] = { 470 + LVTS_MSR0(lvts_ctrl->base), 471 + LVTS_MSR1(lvts_ctrl->base), 472 + LVTS_MSR2(lvts_ctrl->base), 473 + LVTS_MSR3(lvts_ctrl->base) 474 + }; 475 + 476 + void __iomem *imm_regs[] = { 477 + LVTS_IMMD0(lvts_ctrl->base), 478 + LVTS_IMMD1(lvts_ctrl->base), 479 + LVTS_IMMD2(lvts_ctrl->base), 480 + LVTS_IMMD3(lvts_ctrl->base) 481 + }; 482 + 483 + int i; 484 + 485 + for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) { 486 + 487 + int dt_id = lvts_ctrl_data->lvts_sensor[i].dt_id; 488 + 489 + /* 490 + * At this point, we don't know which id matches which 491 + * sensor. Let's set arbitrally the id from the index. 492 + */ 493 + lvts_sensor[i].id = i; 494 + 495 + /* 496 + * The thermal zone registration will set the trip 497 + * point interrupt in the thermal controller 498 + * register. But this one will be reset in the 499 + * initialization after. So we need to post pone the 500 + * thermal zone creation after the controller is 501 + * setup. For this reason, we store the device tree 502 + * node id from the data in the sensor structure 503 + */ 504 + lvts_sensor[i].dt_id = dt_id; 505 + 506 + /* 507 + * We assign the base address of the thermal 508 + * controller as a back pointer. So it will be 509 + * accessible from the different thermal framework ops 510 + * as we pass the lvts_sensor pointer as thermal zone 511 + * private data. 512 + */ 513 + lvts_sensor[i].base = lvts_ctrl->base; 514 + 515 + /* 516 + * Each sensor has its own register address to read from. 517 + */ 518 + lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ? 519 + imm_regs[i] : msr_regs[i]; 520 + }; 521 + 522 + lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor; 523 + 524 + return 0; 525 + } 526 + 527 + /* 528 + * The efuse blob values follows the sensor enumeration per thermal 529 + * controller. The decoding of the stream is as follow: 530 + * 531 + * <--?-> <----big0 ???---> <-sensor0-> <-0-> 532 + * ------------------------------------------ 533 + * index in the stream: : | 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | 534 + * ------------------------------------------ 535 + * 536 + * <--sensor1--><-0-> <----big1 ???---> <-sen 537 + * ------------------------------------------ 538 + * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | 539 + * ------------------------------------------ 540 + * 541 + * sor0-> <-0-> <-sensor1-> <-0-> .......... 542 + * ------------------------------------------ 543 + * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | 544 + * ------------------------------------------ 545 + * 546 + * And so on ... 547 + * 548 + * The data description gives the offset of the calibration data in 549 + * this bytes stream for each sensor. 550 + * 551 + * Each thermal controller can handle up to 4 sensors max, we don't 552 + * care if there are less as the array of calibration is sized to 4 553 + * anyway. The unused sensor slot will be zeroed. 554 + */ 555 + static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, 556 + const struct lvts_ctrl_data *lvts_ctrl_data, 557 + u8 *efuse_calibration) 558 + { 559 + int i; 560 + 561 + for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) 562 + memcpy(&lvts_ctrl->calibration[i], 563 + efuse_calibration + lvts_ctrl_data->cal_offset[i], 2); 564 + 565 + return 0; 566 + } 567 + 568 + /* 569 + * The efuse bytes stream can be split into different chunk of 570 + * nvmems. This function reads and concatenate those into a single 571 + * buffer so it can be read sequentially when initializing the 572 + * calibration data. 573 + */ 574 + static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td, 575 + const struct lvts_data *lvts_data) 576 + { 577 + struct device_node *np = dev_of_node(dev); 578 + struct nvmem_cell *cell; 579 + struct property *prop; 580 + const char *cell_name; 581 + 582 + of_property_for_each_string(np, "nvmem-cell-names", prop, cell_name) { 583 + size_t len; 584 + u8 *efuse; 585 + 586 + cell = of_nvmem_cell_get(np, cell_name); 587 + if (IS_ERR(cell)) { 588 + dev_err(dev, "Failed to get cell '%s'\n", cell_name); 589 + return PTR_ERR(cell); 590 + } 591 + 592 + efuse = nvmem_cell_read(cell, &len); 593 + 594 + nvmem_cell_put(cell); 595 + 596 + if (IS_ERR(efuse)) { 597 + dev_err(dev, "Failed to read cell '%s'\n", cell_name); 598 + return PTR_ERR(efuse); 599 + } 600 + 601 + lvts_td->calib = devm_krealloc(dev, lvts_td->calib, 602 + lvts_td->calib_len + len, GFP_KERNEL); 603 + if (!lvts_td->calib) 604 + return -ENOMEM; 605 + 606 + memcpy(lvts_td->calib + lvts_td->calib_len, efuse, len); 607 + 608 + lvts_td->calib_len += len; 609 + 610 + kfree(efuse); 611 + } 612 + 613 + return 0; 614 + } 615 + 616 + static int lvts_golden_temp_init(struct device *dev, u32 *value) 617 + { 618 + u32 gt; 619 + 620 + gt = (*value) >> 24; 621 + 622 + if (gt && gt < LVTS_GOLDEN_TEMP_MAX) 623 + golden_temp = gt; 624 + 625 + coeff_b = golden_temp * 500 + LVTS_COEFF_B; 626 + 627 + return 0; 628 + } 629 + 630 + static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, 631 + const struct lvts_data *lvts_data) 632 + { 633 + size_t size = sizeof(*lvts_td->lvts_ctrl) * lvts_data->num_lvts_ctrl; 634 + struct lvts_ctrl *lvts_ctrl; 635 + int i, ret; 636 + 637 + /* 638 + * Create the calibration bytes stream from efuse data 639 + */ 640 + ret = lvts_calibration_read(dev, lvts_td, lvts_data); 641 + if (ret) 642 + return ret; 643 + 644 + /* 645 + * The golden temp information is contained in the first chunk 646 + * of efuse data. 647 + */ 648 + ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib); 649 + if (ret) 650 + return ret; 651 + 652 + lvts_ctrl = devm_kzalloc(dev, size, GFP_KERNEL); 653 + if (!lvts_ctrl) 654 + return -ENOMEM; 655 + 656 + for (i = 0; i < lvts_data->num_lvts_ctrl; i++) { 657 + 658 + lvts_ctrl[i].base = lvts_td->base + lvts_data->lvts_ctrl[i].offset; 659 + 660 + ret = lvts_sensor_init(dev, &lvts_ctrl[i], 661 + &lvts_data->lvts_ctrl[i]); 662 + if (ret) 663 + return ret; 664 + 665 + ret = lvts_calibration_init(dev, &lvts_ctrl[i], 666 + &lvts_data->lvts_ctrl[i], 667 + lvts_td->calib); 668 + if (ret) 669 + return ret; 670 + 671 + /* 672 + * The mode the ctrl will use to read the temperature 673 + * (filtered or immediate) 674 + */ 675 + lvts_ctrl[i].mode = lvts_data->lvts_ctrl[i].mode; 676 + 677 + /* 678 + * The temperature to raw temperature must be done 679 + * after initializing the calibration. 680 + */ 681 + lvts_ctrl[i].hw_tshut_raw_temp = 682 + lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); 683 + } 684 + 685 + /* 686 + * We no longer need the efuse bytes stream, let's free it 687 + */ 688 + devm_kfree(dev, lvts_td->calib); 689 + 690 + lvts_td->lvts_ctrl = lvts_ctrl; 691 + lvts_td->num_lvts_ctrl = lvts_data->num_lvts_ctrl; 692 + 693 + return 0; 694 + } 695 + 696 + /* 697 + * At this point the configuration register is the only place in the 698 + * driver where we write multiple values. Per hardware constraint, 699 + * each write in the configuration register must be separated by a 700 + * delay of 2 us. 701 + */ 702 + static void lvts_write_config(struct lvts_ctrl *lvts_ctrl, u32 *cmds, int nr_cmds) 703 + { 704 + int i; 705 + 706 + /* 707 + * Configuration register 708 + */ 709 + for (i = 0; i < nr_cmds; i++) { 710 + writel(cmds[i], LVTS_CONFIG(lvts_ctrl->base)); 711 + usleep_range(2, 4); 712 + } 713 + } 714 + 715 + static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl) 716 + { 717 + /* 718 + * LVTS_PROTCTL : Thermal Protection Sensor Selection 719 + * 720 + * Bits: 721 + * 722 + * 19-18 : Sensor to base the protection on 723 + * 17-16 : Strategy: 724 + * 00 : Average of 4 sensors 725 + * 01 : Max of 4 sensors 726 + * 10 : Selected sensor with bits 19-18 727 + * 11 : Reserved 728 + */ 729 + writel(BIT(16), LVTS_PROTCTL(lvts_ctrl->base)); 730 + 731 + /* 732 + * LVTS_PROTTA : Stage 1 temperature threshold 733 + * LVTS_PROTTB : Stage 2 temperature threshold 734 + * LVTS_PROTTC : Stage 3 temperature threshold 735 + * 736 + * Bits: 737 + * 738 + * 14-0: Raw temperature threshold 739 + * 740 + * writel(0x0, LVTS_PROTTA(lvts_ctrl->base)); 741 + * writel(0x0, LVTS_PROTTB(lvts_ctrl->base)); 742 + */ 743 + writel(lvts_ctrl->hw_tshut_raw_temp, LVTS_PROTTC(lvts_ctrl->base)); 744 + 745 + /* 746 + * LVTS_MONINT : Interrupt configuration register 747 + * 748 + * The LVTS_MONINT register layout is the same as the LVTS_MONINTSTS 749 + * register, except we set the bits to enable the interrupt. 750 + */ 751 + writel(LVTS_MONINT_CONF, LVTS_MONINT(lvts_ctrl->base)); 752 + 753 + return 0; 754 + } 755 + 756 + static int lvts_domain_reset(struct device *dev, struct reset_control *reset) 757 + { 758 + int ret; 759 + 760 + ret = reset_control_assert(reset); 761 + if (ret) 762 + return ret; 763 + 764 + return reset_control_deassert(reset); 765 + } 766 + 767 + /* 768 + * Enable or disable the clocks of a specified thermal controller 769 + */ 770 + static int lvts_ctrl_set_enable(struct lvts_ctrl *lvts_ctrl, int enable) 771 + { 772 + /* 773 + * LVTS_CLKEN : Internal LVTS clock 774 + * 775 + * Bits: 776 + * 777 + * 0 : enable / disable clock 778 + */ 779 + writel(enable, LVTS_CLKEN(lvts_ctrl->base)); 780 + 781 + return 0; 782 + } 783 + 784 + static int lvts_ctrl_connect(struct device *dev, struct lvts_ctrl *lvts_ctrl) 785 + { 786 + u32 id, cmds[] = { 0xC103FFFF, 0xC502FF55 }; 787 + 788 + lvts_write_config(lvts_ctrl, cmds, ARRAY_SIZE(cmds)); 789 + 790 + /* 791 + * LVTS_ID : Get ID and status of the thermal controller 792 + * 793 + * Bits: 794 + * 795 + * 0-5 : thermal controller id 796 + * 7 : thermal controller connection is valid 797 + */ 798 + id = readl(LVTS_ID(lvts_ctrl->base)); 799 + if (!(id & BIT(7))) 800 + return -EIO; 801 + 802 + return 0; 803 + } 804 + 805 + static int lvts_ctrl_initialize(struct device *dev, struct lvts_ctrl *lvts_ctrl) 806 + { 807 + /* 808 + * Write device mask: 0xC1030000 809 + */ 810 + u32 cmds[] = { 811 + 0xC1030E01, 0xC1030CFC, 0xC1030A8C, 0xC103098D, 0xC10308F1, 812 + 0xC10307A6, 0xC10306B8, 0xC1030500, 0xC1030420, 0xC1030300, 813 + 0xC1030030, 0xC10300F6, 0xC1030050, 0xC1030060, 0xC10300AC, 814 + 0xC10300FC, 0xC103009D, 0xC10300F1, 0xC10300E1 815 + }; 816 + 817 + lvts_write_config(lvts_ctrl, cmds, ARRAY_SIZE(cmds)); 818 + 819 + return 0; 820 + } 821 + 822 + static int lvts_ctrl_calibrate(struct device *dev, struct lvts_ctrl *lvts_ctrl) 823 + { 824 + int i; 825 + void __iomem *lvts_edata[] = { 826 + LVTS_EDATA00(lvts_ctrl->base), 827 + LVTS_EDATA01(lvts_ctrl->base), 828 + LVTS_EDATA02(lvts_ctrl->base), 829 + LVTS_EDATA03(lvts_ctrl->base) 830 + }; 831 + 832 + /* 833 + * LVTS_EDATA0X : Efuse calibration reference value for sensor X 834 + * 835 + * Bits: 836 + * 837 + * 20-0 : Efuse value for normalization data 838 + */ 839 + for (i = 0; i < LVTS_SENSOR_MAX; i++) 840 + writel(lvts_ctrl->calibration[i], lvts_edata[i]); 841 + 842 + return 0; 843 + } 844 + 845 + static int lvts_ctrl_configure(struct device *dev, struct lvts_ctrl *lvts_ctrl) 846 + { 847 + u32 value; 848 + 849 + /* 850 + * LVTS_TSSEL : Sensing point index numbering 851 + * 852 + * Bits: 853 + * 854 + * 31-24: ADC Sense 3 855 + * 23-16: ADC Sense 2 856 + * 15-8 : ADC Sense 1 857 + * 7-0 : ADC Sense 0 858 + */ 859 + value = LVTS_TSSEL_CONF; 860 + writel(value, LVTS_TSSEL(lvts_ctrl->base)); 861 + 862 + /* 863 + * LVTS_CALSCALE : ADC voltage round 864 + */ 865 + value = 0x300; 866 + value = LVTS_CALSCALE_CONF; 867 + 868 + /* 869 + * LVTS_MSRCTL0 : Sensor filtering strategy 870 + * 871 + * Filters: 872 + * 873 + * 000 : One sample 874 + * 001 : Avg 2 samples 875 + * 010 : 4 samples, drop min and max, avg 2 samples 876 + * 011 : 6 samples, drop min and max, avg 4 samples 877 + * 100 : 10 samples, drop min and max, avg 8 samples 878 + * 101 : 18 samples, drop min and max, avg 16 samples 879 + * 880 + * Bits: 881 + * 882 + * 0-2 : Sensor0 filter 883 + * 3-5 : Sensor1 filter 884 + * 6-8 : Sensor2 filter 885 + * 9-11 : Sensor3 filter 886 + */ 887 + value = LVTS_HW_FILTER << 9 | LVTS_HW_FILTER << 6 | 888 + LVTS_HW_FILTER << 3 | LVTS_HW_FILTER; 889 + writel(value, LVTS_MSRCTL0(lvts_ctrl->base)); 890 + 891 + /* 892 + * LVTS_MSRCTL1 : Measurement control 893 + * 894 + * Bits: 895 + * 896 + * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 897 + * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 898 + * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 899 + * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 900 + * 901 + * That configuration will ignore the filtering and the delays 902 + * introduced below in MONCTL1 and MONCTL2 903 + */ 904 + if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { 905 + value = BIT(9) | BIT(6) | BIT(5) | BIT(4); 906 + writel(value, LVTS_MSRCTL1(lvts_ctrl->base)); 907 + } 908 + 909 + /* 910 + * LVTS_MONCTL1 : Period unit and group interval configuration 911 + * 912 + * The clock source of LVTS thermal controller is 26MHz. 913 + * 914 + * The period unit is a time base for all the interval delays 915 + * specified in the registers. By default we use 12. The time 916 + * conversion is done by multiplying by 256 and 1/26.10^6 917 + * 918 + * An interval delay multiplied by the period unit gives the 919 + * duration in seconds. 920 + * 921 + * - Filter interval delay is a delay between two samples of 922 + * the same sensor. 923 + * 924 + * - Sensor interval delay is a delay between two samples of 925 + * different sensors. 926 + * 927 + * - Group interval delay is a delay between different rounds. 928 + * 929 + * For example: 930 + * If Period unit = C, filter delay = 1, sensor delay = 2, group delay = 1, 931 + * and two sensors, TS1 and TS2, are in a LVTS thermal controller 932 + * and then 933 + * Period unit time = C * 1/26M * 256 = 12 * 38.46ns * 256 = 118.149us 934 + * Filter interval delay = 1 * Period unit = 118.149us 935 + * Sensor interval delay = 2 * Period unit = 236.298us 936 + * Group interval delay = 1 * Period unit = 118.149us 937 + * 938 + * TS1 TS1 ... TS1 TS2 TS2 ... TS2 TS1... 939 + * <--> Filter interval delay 940 + * <--> Sensor interval delay 941 + * <--> Group interval delay 942 + * Bits: 943 + * 29 - 20 : Group interval 944 + * 16 - 13 : Send a single interrupt when crossing the hot threshold (1) 945 + * or an interrupt everytime the hot threshold is crossed (0) 946 + * 9 - 0 : Period unit 947 + * 948 + */ 949 + value = LVTS_GROUP_INTERVAL << 20 | LVTS_PERIOD_UNIT; 950 + writel(value, LVTS_MONCTL1(lvts_ctrl->base)); 951 + 952 + /* 953 + * LVTS_MONCTL2 : Filtering and sensor interval 954 + * 955 + * Bits: 956 + * 957 + * 25-16 : Interval unit in PERIOD_UNIT between sample on 958 + * the same sensor, filter interval 959 + * 9-0 : Interval unit in PERIOD_UNIT between each sensor 960 + * 961 + */ 962 + value = LVTS_FILTER_INTERVAL << 16 | LVTS_SENSOR_INTERVAL; 963 + writel(value, LVTS_MONCTL2(lvts_ctrl->base)); 964 + 965 + return lvts_irq_init(lvts_ctrl); 966 + } 967 + 968 + static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl) 969 + { 970 + struct lvts_sensor *lvts_sensors = lvts_ctrl->sensors; 971 + struct thermal_zone_device *tz; 972 + u32 sensor_map = 0; 973 + int i; 974 + 975 + for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) { 976 + 977 + int dt_id = lvts_sensors[i].dt_id; 978 + 979 + tz = devm_thermal_of_zone_register(dev, dt_id, &lvts_sensors[i], 980 + &lvts_ops); 981 + if (IS_ERR(tz)) { 982 + /* 983 + * This thermal zone is not described in the 984 + * device tree. It is not an error from the 985 + * thermal OF code POV, we just continue. 986 + */ 987 + if (PTR_ERR(tz) == -ENODEV) 988 + continue; 989 + 990 + return PTR_ERR(tz); 991 + } 992 + 993 + /* 994 + * The thermal zone pointer will be needed in the 995 + * interrupt handler, we store it in the sensor 996 + * structure. The thermal domain structure will be 997 + * passed to the interrupt handler private data as the 998 + * interrupt is shared for all the controller 999 + * belonging to the thermal domain. 1000 + */ 1001 + lvts_sensors[i].tz = tz; 1002 + 1003 + /* 1004 + * This sensor was correctly associated with a thermal 1005 + * zone, let's set the corresponding bit in the sensor 1006 + * map, so we can enable the temperature monitoring in 1007 + * the hardware thermal controller. 1008 + */ 1009 + sensor_map |= BIT(i); 1010 + } 1011 + 1012 + /* 1013 + * Bits: 1014 + * 9: Single point access flow 1015 + * 0-3: Enable sensing point 0-3 1016 + * 1017 + * The initialization of the thermal zones give us 1018 + * which sensor point to enable. If any thermal zone 1019 + * was not described in the device tree, it won't be 1020 + * enabled here in the sensor map. 1021 + */ 1022 + writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); 1023 + 1024 + return 0; 1025 + } 1026 + 1027 + static int lvts_domain_init(struct device *dev, struct lvts_domain *lvts_td, 1028 + const struct lvts_data *lvts_data) 1029 + { 1030 + struct lvts_ctrl *lvts_ctrl; 1031 + int i, ret; 1032 + 1033 + ret = lvts_ctrl_init(dev, lvts_td, lvts_data); 1034 + if (ret) 1035 + return ret; 1036 + 1037 + ret = lvts_domain_reset(dev, lvts_td->reset); 1038 + if (ret) { 1039 + dev_dbg(dev, "Failed to reset domain"); 1040 + return ret; 1041 + } 1042 + 1043 + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { 1044 + 1045 + lvts_ctrl = &lvts_td->lvts_ctrl[i]; 1046 + 1047 + /* 1048 + * Initialization steps: 1049 + * 1050 + * - Enable the clock 1051 + * - Connect to the LVTS 1052 + * - Initialize the LVTS 1053 + * - Prepare the calibration data 1054 + * - Select monitored sensors 1055 + * [ Configure sampling ] 1056 + * [ Configure the interrupt ] 1057 + * - Start measurement 1058 + */ 1059 + ret = lvts_ctrl_set_enable(lvts_ctrl, true); 1060 + if (ret) { 1061 + dev_dbg(dev, "Failed to enable LVTS clock"); 1062 + return ret; 1063 + } 1064 + 1065 + ret = lvts_ctrl_connect(dev, lvts_ctrl); 1066 + if (ret) { 1067 + dev_dbg(dev, "Failed to connect to LVTS controller"); 1068 + return ret; 1069 + } 1070 + 1071 + ret = lvts_ctrl_initialize(dev, lvts_ctrl); 1072 + if (ret) { 1073 + dev_dbg(dev, "Failed to initialize controller"); 1074 + return ret; 1075 + } 1076 + 1077 + ret = lvts_ctrl_calibrate(dev, lvts_ctrl); 1078 + if (ret) { 1079 + dev_dbg(dev, "Failed to calibrate controller"); 1080 + return ret; 1081 + } 1082 + 1083 + ret = lvts_ctrl_configure(dev, lvts_ctrl); 1084 + if (ret) { 1085 + dev_dbg(dev, "Failed to configure controller"); 1086 + return ret; 1087 + } 1088 + 1089 + ret = lvts_ctrl_start(dev, lvts_ctrl); 1090 + if (ret) { 1091 + dev_dbg(dev, "Failed to start controller"); 1092 + return ret; 1093 + } 1094 + } 1095 + 1096 + return lvts_debugfs_init(dev, lvts_td); 1097 + } 1098 + 1099 + static int lvts_probe(struct platform_device *pdev) 1100 + { 1101 + const struct lvts_data *lvts_data; 1102 + struct lvts_domain *lvts_td; 1103 + struct device *dev = &pdev->dev; 1104 + struct resource *res; 1105 + int irq, ret; 1106 + 1107 + lvts_td = devm_kzalloc(dev, sizeof(*lvts_td), GFP_KERNEL); 1108 + if (!lvts_td) 1109 + return -ENOMEM; 1110 + 1111 + lvts_data = of_device_get_match_data(dev); 1112 + 1113 + lvts_td->clk = devm_clk_get_enabled(dev, NULL); 1114 + if (IS_ERR(lvts_td->clk)) 1115 + return dev_err_probe(dev, PTR_ERR(lvts_td->clk), "Failed to retrieve clock\n"); 1116 + 1117 + res = platform_get_mem_or_io(pdev, 0); 1118 + if (!res) 1119 + return dev_err_probe(dev, (-ENXIO), "No IO resource\n"); 1120 + 1121 + lvts_td->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 1122 + if (IS_ERR(lvts_td->base)) 1123 + return dev_err_probe(dev, PTR_ERR(lvts_td->base), "Failed to map io resource\n"); 1124 + 1125 + lvts_td->reset = devm_reset_control_get_by_index(dev, 0); 1126 + if (IS_ERR(lvts_td->reset)) 1127 + return dev_err_probe(dev, PTR_ERR(lvts_td->reset), "Failed to get reset control\n"); 1128 + 1129 + irq = platform_get_irq(pdev, 0); 1130 + if (irq < 0) 1131 + return dev_err_probe(dev, irq, "No irq resource\n"); 1132 + 1133 + ret = lvts_domain_init(dev, lvts_td, lvts_data); 1134 + if (ret) 1135 + return dev_err_probe(dev, ret, "Failed to initialize the lvts domain\n"); 1136 + 1137 + /* 1138 + * At this point the LVTS is initialized and enabled. We can 1139 + * safely enable the interrupt. 1140 + */ 1141 + ret = devm_request_threaded_irq(dev, irq, NULL, lvts_irq_handler, 1142 + IRQF_ONESHOT, dev_name(dev), lvts_td); 1143 + if (ret) 1144 + return dev_err_probe(dev, ret, "Failed to request interrupt\n"); 1145 + 1146 + platform_set_drvdata(pdev, lvts_td); 1147 + 1148 + return 0; 1149 + } 1150 + 1151 + static int lvts_remove(struct platform_device *pdev) 1152 + { 1153 + struct lvts_domain *lvts_td; 1154 + int i; 1155 + 1156 + lvts_td = platform_get_drvdata(pdev); 1157 + 1158 + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) 1159 + lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); 1160 + 1161 + lvts_debugfs_exit(lvts_td); 1162 + 1163 + return 0; 1164 + } 1165 + 1166 + static const struct lvts_ctrl_data mt8195_lvts_data_ctrl[] = { 1167 + { 1168 + .cal_offset = { 0x04, 0x07 }, 1169 + .lvts_sensor = { 1170 + { .dt_id = MT8195_MCU_BIG_CPU0 }, 1171 + { .dt_id = MT8195_MCU_BIG_CPU1 } 1172 + }, 1173 + .num_lvts_sensor = 2, 1174 + .offset = 0x0, 1175 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, 1176 + }, 1177 + { 1178 + .cal_offset = { 0x0d, 0x10 }, 1179 + .lvts_sensor = { 1180 + { .dt_id = MT8195_MCU_BIG_CPU2 }, 1181 + { .dt_id = MT8195_MCU_BIG_CPU3 } 1182 + }, 1183 + .num_lvts_sensor = 2, 1184 + .offset = 0x100, 1185 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, 1186 + }, 1187 + { 1188 + .cal_offset = { 0x16, 0x19, 0x1c, 0x1f }, 1189 + .lvts_sensor = { 1190 + { .dt_id = MT8195_MCU_LITTLE_CPU0 }, 1191 + { .dt_id = MT8195_MCU_LITTLE_CPU1 }, 1192 + { .dt_id = MT8195_MCU_LITTLE_CPU2 }, 1193 + { .dt_id = MT8195_MCU_LITTLE_CPU3 } 1194 + }, 1195 + .num_lvts_sensor = 4, 1196 + .offset = 0x200, 1197 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, 1198 + } 1199 + }; 1200 + 1201 + static const struct lvts_data mt8195_lvts_mcu_data = { 1202 + .lvts_ctrl = mt8195_lvts_data_ctrl, 1203 + .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_data_ctrl), 1204 + }; 1205 + 1206 + static const struct of_device_id lvts_of_match[] = { 1207 + { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, 1208 + {}, 1209 + }; 1210 + MODULE_DEVICE_TABLE(of, lvts_of_match); 1211 + 1212 + static struct platform_driver lvts_driver = { 1213 + .probe = lvts_probe, 1214 + .remove = lvts_remove, 1215 + .driver = { 1216 + .name = "mtk-lvts-thermal", 1217 + .of_match_table = lvts_of_match, 1218 + }, 1219 + }; 1220 + module_platform_driver(lvts_driver); 1221 + 1222 + MODULE_AUTHOR("Balsam CHIHI <bchihi@baylibre.com>"); 1223 + MODULE_DESCRIPTION("MediaTek LVTS Thermal Driver"); 1224 + MODULE_LICENSE("GPL");
+136 -15
drivers/thermal/mtk_thermal.c drivers/thermal/mediatek/auxadc_thermal.c
··· 23 23 #include <linux/reset.h> 24 24 #include <linux/types.h> 25 25 26 - #include "thermal_hwmon.h" 26 + #include "../thermal_hwmon.h" 27 27 28 28 /* AUXADC Registers */ 29 29 #define AUXADC_CON1_SET_V 0x008 ··· 150 150 #define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) 151 151 #define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) 152 152 153 + /* 154 + * Layout of the fuses providing the calibration data 155 + * These macros can be used for MT7981 and MT7986. 156 + */ 157 + #define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff) 158 + #define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f) 159 + #define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f) 160 + #define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff) 161 + #define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff) 162 + #define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff) 163 + #define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1) 164 + #define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1) 165 + #define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1) 166 + 153 167 enum { 154 168 VTS1, 155 169 VTS2, ··· 177 163 enum mtk_thermal_version { 178 164 MTK_THERMAL_V1 = 1, 179 165 MTK_THERMAL_V2, 166 + MTK_THERMAL_V3, 180 167 }; 181 168 182 169 /* MT2701 thermal sensors */ ··· 260 245 /* The calibration coefficient of sensor */ 261 246 #define MT8183_CALIBRATION 153 262 247 248 + /* AUXADC channel 11 is used for the temperature sensors */ 249 + #define MT7986_TEMP_AUXADC_CHANNEL 11 250 + 251 + /* The total number of temperature sensors in the MT7986 */ 252 + #define MT7986_NUM_SENSORS 1 253 + 254 + /* The number of banks in the MT7986 */ 255 + #define MT7986_NUM_ZONES 1 256 + 257 + /* The number of sensing points per bank */ 258 + #define MT7986_NUM_SENSORS_PER_ZONE 1 259 + 260 + /* MT7986 thermal sensors */ 261 + #define MT7986_TS1 0 262 + 263 + /* The number of controller in the MT7986 */ 264 + #define MT7986_NUM_CONTROLLER 1 265 + 266 + /* The calibration coefficient of sensor */ 267 + #define MT7986_CALIBRATION 165 268 + 263 269 struct mtk_thermal; 264 270 265 271 struct thermal_bank_cfg { ··· 328 292 329 293 const struct mtk_thermal_data *conf; 330 294 struct mtk_thermal_bank banks[MAX_NUM_ZONES]; 295 + 296 + int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); 331 297 }; 332 298 333 299 /* MT8183 thermal sensor data */ ··· 423 385 static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, }; 424 386 static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 }; 425 387 static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, }; 388 + 389 + /* MT7986 thermal sensor data */ 390 + static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, }; 391 + static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; 392 + static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; 393 + static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, }; 394 + static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; 395 + static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; 426 396 427 397 /* 428 398 * The MT8173 thermal controller has four banks. Each bank can read up to ··· 595 549 .version = MTK_THERMAL_V1, 596 550 }; 597 551 552 + /* 553 + * MT7986 uses AUXADC Channel 11 for raw data access. 554 + */ 555 + static const struct mtk_thermal_data mt7986_thermal_data = { 556 + .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL, 557 + .num_banks = MT7986_NUM_ZONES, 558 + .num_sensors = MT7986_NUM_SENSORS, 559 + .vts_index = mt7986_vts_index, 560 + .cali_val = MT7986_CALIBRATION, 561 + .num_controller = MT7986_NUM_CONTROLLER, 562 + .controller_offset = mt7986_tc_offset, 563 + .need_switch_bank = true, 564 + .bank_data = { 565 + { 566 + .num_sensors = 1, 567 + .sensors = mt7986_bank_data, 568 + }, 569 + }, 570 + .msr = mt7986_msr, 571 + .adcpnp = mt7986_adcpnp, 572 + .sensor_mux_values = mt7986_mux_values, 573 + .version = MTK_THERMAL_V3, 574 + }; 575 + 598 576 /** 599 - * raw_to_mcelsius - convert a raw ADC value to mcelsius 577 + * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius 600 578 * @mt: The thermal controller 601 579 * @sensno: sensor number 602 580 * @raw: raw ADC value ··· 671 601 tmp = tmp / (165 + mt->o_slope); 672 602 673 603 return (format_2 - tmp) * 100; 604 + } 605 + 606 + static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw) 607 + { 608 + s32 tmp; 609 + 610 + if (raw == 0) 611 + return 0; 612 + 613 + raw &= 0xfff; 614 + tmp = 100000 * 15 / 16 * 10000; 615 + tmp /= 4096 - 512 + mt->adc_ge; 616 + tmp /= 1490; 617 + tmp *= raw - mt->vts[sensno] - 2900; 618 + 619 + return mt->degc_cali * 500 - tmp; 674 620 } 675 621 676 622 /** ··· 742 656 for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { 743 657 raw = readl(mt->thermal_base + conf->msr[i]); 744 658 745 - if (mt->conf->version == MTK_THERMAL_V1) { 746 - temp = raw_to_mcelsius_v1( 747 - mt, conf->bank_data[bank->id].sensors[i], raw); 748 - } else { 749 - temp = raw_to_mcelsius_v2( 750 - mt, conf->bank_data[bank->id].sensors[i], raw); 751 - } 659 + temp = mt->raw_to_mcelsius( 660 + mt, conf->bank_data[bank->id].sensors[i], raw); 661 + 752 662 753 663 /* 754 664 * The first read of a sensor often contains very high bogus ··· 969 887 return 0; 970 888 } 971 889 890 + static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) 891 + { 892 + if (!CALIB_BUF1_VALID_V3(buf[1])) 893 + return -EINVAL; 894 + 895 + mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]); 896 + mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]); 897 + mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]); 898 + mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]); 899 + mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]); 900 + mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]); 901 + mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]); 902 + 903 + if (CALIB_BUF1_ID_V3(buf[1]) == 0) 904 + mt->o_slope = 0; 905 + 906 + return 0; 907 + } 908 + 972 909 static int mtk_thermal_get_calibration_data(struct device *dev, 973 910 struct mtk_thermal *mt) 974 911 { ··· 998 897 999 898 /* Start with default values */ 1000 899 mt->adc_ge = 512; 900 + mt->adc_oe = 512; 1001 901 for (i = 0; i < mt->conf->num_sensors; i++) 1002 902 mt->vts[i] = 260; 1003 903 mt->degc_cali = 40; ··· 1024 922 goto out; 1025 923 } 1026 924 1027 - if (mt->conf->version == MTK_THERMAL_V1) 925 + switch (mt->conf->version) { 926 + case MTK_THERMAL_V1: 1028 927 ret = mtk_thermal_extract_efuse_v1(mt, buf); 1029 - else 928 + break; 929 + case MTK_THERMAL_V2: 1030 930 ret = mtk_thermal_extract_efuse_v2(mt, buf); 931 + break; 932 + case MTK_THERMAL_V3: 933 + ret = mtk_thermal_extract_efuse_v3(mt, buf); 934 + break; 935 + default: 936 + ret = -EINVAL; 937 + break; 938 + } 1031 939 1032 940 if (ret) { 1033 941 dev_info(dev, "Device not calibrated, using default calibration values\n"); ··· 1066 954 { 1067 955 .compatible = "mediatek,mt7622-thermal", 1068 956 .data = (void *)&mt7622_thermal_data, 957 + }, 958 + { 959 + .compatible = "mediatek,mt7986-thermal", 960 + .data = (void *)&mt7986_thermal_data, 1069 961 }, 1070 962 { 1071 963 .compatible = "mediatek,mt8183-thermal", ··· 1106 990 int ret, i, ctrl_id; 1107 991 struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; 1108 992 struct mtk_thermal *mt; 1109 - struct resource *res; 1110 993 u64 auxadc_phys_base, apmixed_phys_base; 1111 994 struct thermal_zone_device *tzdev; 1112 995 void __iomem *apmixed_base, *auxadc_base; ··· 1124 1009 if (IS_ERR(mt->clk_auxadc)) 1125 1010 return PTR_ERR(mt->clk_auxadc); 1126 1011 1127 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1128 - mt->thermal_base = devm_ioremap_resource(&pdev->dev, res); 1012 + mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 1129 1013 if (IS_ERR(mt->thermal_base)) 1130 1014 return PTR_ERR(mt->thermal_base); 1131 1015 ··· 1184 1070 goto err_disable_clk_auxadc; 1185 1071 } 1186 1072 1187 - if (mt->conf->version == MTK_THERMAL_V2) { 1073 + if (mt->conf->version != MTK_THERMAL_V1) { 1188 1074 mtk_thermal_turn_on_buffer(apmixed_base); 1189 1075 mtk_thermal_release_periodic_ts(mt, auxadc_base); 1190 1076 } 1077 + 1078 + if (mt->conf->version == MTK_THERMAL_V1) 1079 + mt->raw_to_mcelsius = raw_to_mcelsius_v1; 1080 + else if (mt->conf->version == MTK_THERMAL_V2) 1081 + mt->raw_to_mcelsius = raw_to_mcelsius_v2; 1082 + else 1083 + mt->raw_to_mcelsius = raw_to_mcelsius_v3; 1191 1084 1192 1085 for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) 1193 1086 for (i = 0; i < mt->conf->num_banks; i++)
+2 -1
drivers/thermal/qcom/qcom-spmi-adc-tm5.c
··· 18 18 #include <linux/platform_device.h> 19 19 #include <linux/regmap.h> 20 20 #include <linux/thermal.h> 21 - #include <asm-generic/unaligned.h> 21 + 22 + #include <asm/unaligned.h> 22 23 23 24 #include "../thermal_hwmon.h" 24 25
+19 -20
drivers/thermal/qcom/qcom-spmi-temp-alarm.c
··· 15 15 #include <linux/regmap.h> 16 16 #include <linux/thermal.h> 17 17 18 - #include "../thermal_core.h" 19 18 #include "../thermal_hwmon.h" 20 19 21 20 #define QPNP_TM_REG_DIG_MAJOR 0x01 ··· 263 264 return qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg); 264 265 } 265 266 266 - static int qpnp_tm_set_trip_temp(struct thermal_zone_device *tz, int trip, int temp) 267 + static int qpnp_tm_set_trip_temp(struct thermal_zone_device *tz, int trip_id, int temp) 267 268 { 268 269 struct qpnp_tm_chip *chip = tz->devdata; 269 - const struct thermal_trip *trip_points; 270 + struct thermal_trip trip; 270 271 int ret; 271 272 272 - trip_points = of_thermal_get_trip_points(chip->tz_dev); 273 - if (!trip_points) 274 - return -EINVAL; 273 + ret = __thermal_zone_get_trip(chip->tz_dev, trip_id, &trip); 274 + if (ret) 275 + return ret; 275 276 276 - if (trip_points[trip].type != THERMAL_TRIP_CRITICAL) 277 + if (trip.type != THERMAL_TRIP_CRITICAL) 277 278 return 0; 278 279 279 280 mutex_lock(&chip->lock); ··· 299 300 300 301 static int qpnp_tm_get_critical_trip_temp(struct qpnp_tm_chip *chip) 301 302 { 302 - int ntrips; 303 - const struct thermal_trip *trips; 304 - int i; 303 + struct thermal_trip trip; 304 + int i, ret; 305 305 306 - ntrips = of_thermal_get_ntrips(chip->tz_dev); 307 - if (ntrips <= 0) 308 - return THERMAL_TEMP_INVALID; 306 + for (i = 0; i < thermal_zone_get_num_trips(chip->tz_dev); i++) { 309 307 310 - trips = of_thermal_get_trip_points(chip->tz_dev); 311 - if (!trips) 312 - return THERMAL_TEMP_INVALID; 308 + ret = thermal_zone_get_trip(chip->tz_dev, i, &trip); 309 + if (ret) 310 + continue; 313 311 314 - for (i = 0; i < ntrips; i++) { 315 - if (of_thermal_is_trip_valid(chip->tz_dev, i) && 316 - trips[i].type == THERMAL_TRIP_CRITICAL) 317 - return trips[i].temperature; 312 + if (trip.type == THERMAL_TRIP_CRITICAL) 313 + return trip.temperature; 318 314 } 319 315 320 316 return THERMAL_TEMP_INVALID; ··· 347 353 if (stage) 348 354 chip->temp = qpnp_tm_decode_temp(chip, stage); 349 355 356 + mutex_unlock(&chip->lock); 357 + 350 358 crit_temp = qpnp_tm_get_critical_trip_temp(chip); 359 + 360 + mutex_lock(&chip->lock); 361 + 351 362 ret = qpnp_tm_update_critical_trip_temp(chip, crit_temp); 352 363 if (ret < 0) 353 364 goto out;
+182 -459
drivers/thermal/qcom/tsens-v0_1.c
··· 3 3 * Copyright (c) 2015, The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 + #include <linux/bitfield.h> 7 + #include <linux/nvmem-consumer.h> 6 8 #include <linux/platform_device.h> 7 9 #include "tsens.h" 8 10 ··· 17 15 #define TM_Sn_STATUS_OFF 0x0030 18 16 #define TM_TRDY_OFF 0x005c 19 17 20 - /* eeprom layout data for 8916 */ 21 - #define MSM8916_BASE0_MASK 0x0000007f 22 - #define MSM8916_BASE1_MASK 0xfe000000 23 - #define MSM8916_BASE0_SHIFT 0 24 - #define MSM8916_BASE1_SHIFT 25 25 - 26 - #define MSM8916_S0_P1_MASK 0x00000f80 27 - #define MSM8916_S1_P1_MASK 0x003e0000 28 - #define MSM8916_S2_P1_MASK 0xf8000000 29 - #define MSM8916_S3_P1_MASK 0x000003e0 30 - #define MSM8916_S4_P1_MASK 0x000f8000 31 - 32 - #define MSM8916_S0_P2_MASK 0x0001f000 33 - #define MSM8916_S1_P2_MASK 0x07c00000 34 - #define MSM8916_S2_P2_MASK 0x0000001f 35 - #define MSM8916_S3_P2_MASK 0x00007c00 36 - #define MSM8916_S4_P2_MASK 0x01f00000 37 - 38 - #define MSM8916_S0_P1_SHIFT 7 39 - #define MSM8916_S1_P1_SHIFT 17 40 - #define MSM8916_S2_P1_SHIFT 27 41 - #define MSM8916_S3_P1_SHIFT 5 42 - #define MSM8916_S4_P1_SHIFT 15 43 - 44 - #define MSM8916_S0_P2_SHIFT 12 45 - #define MSM8916_S1_P2_SHIFT 22 46 - #define MSM8916_S2_P2_SHIFT 0 47 - #define MSM8916_S3_P2_SHIFT 10 48 - #define MSM8916_S4_P2_SHIFT 20 49 - 50 - #define MSM8916_CAL_SEL_MASK 0xe0000000 51 - #define MSM8916_CAL_SEL_SHIFT 29 52 - 53 - /* eeprom layout data for 8939 */ 54 - #define MSM8939_BASE0_MASK 0x000000ff 55 - #define MSM8939_BASE1_MASK 0xff000000 56 - #define MSM8939_BASE0_SHIFT 0 57 - #define MSM8939_BASE1_SHIFT 24 58 - 59 - #define MSM8939_S0_P1_MASK 0x000001f8 60 - #define MSM8939_S1_P1_MASK 0x001f8000 61 - #define MSM8939_S2_P1_MASK_0_4 0xf8000000 62 - #define MSM8939_S2_P1_MASK_5 0x00000001 63 - #define MSM8939_S3_P1_MASK 0x00001f80 64 - #define MSM8939_S4_P1_MASK 0x01f80000 65 - #define MSM8939_S5_P1_MASK 0x00003f00 66 - #define MSM8939_S6_P1_MASK 0x03f00000 67 - #define MSM8939_S7_P1_MASK 0x0000003f 68 - #define MSM8939_S8_P1_MASK 0x0003f000 69 - #define MSM8939_S9_P1_MASK 0x07e00000 70 - 71 - #define MSM8939_S0_P2_MASK 0x00007e00 72 - #define MSM8939_S1_P2_MASK 0x07e00000 73 - #define MSM8939_S2_P2_MASK 0x0000007e 74 - #define MSM8939_S3_P2_MASK 0x0007e000 75 - #define MSM8939_S4_P2_MASK 0x7e000000 76 - #define MSM8939_S5_P2_MASK 0x000fc000 77 - #define MSM8939_S6_P2_MASK 0xfc000000 78 - #define MSM8939_S7_P2_MASK 0x00000fc0 79 - #define MSM8939_S8_P2_MASK 0x00fc0000 80 - #define MSM8939_S9_P2_MASK_0_4 0xf8000000 81 - #define MSM8939_S9_P2_MASK_5 0x00002000 82 - 83 - #define MSM8939_S0_P1_SHIFT 3 84 - #define MSM8939_S1_P1_SHIFT 15 85 - #define MSM8939_S2_P1_SHIFT_0_4 27 86 - #define MSM8939_S2_P1_SHIFT_5 0 87 - #define MSM8939_S3_P1_SHIFT 7 88 - #define MSM8939_S4_P1_SHIFT 19 89 - #define MSM8939_S5_P1_SHIFT 8 90 - #define MSM8939_S6_P1_SHIFT 20 91 - #define MSM8939_S7_P1_SHIFT 0 92 - #define MSM8939_S8_P1_SHIFT 12 93 - #define MSM8939_S9_P1_SHIFT 21 94 - 95 - #define MSM8939_S0_P2_SHIFT 9 96 - #define MSM8939_S1_P2_SHIFT 21 97 - #define MSM8939_S2_P2_SHIFT 1 98 - #define MSM8939_S3_P2_SHIFT 13 99 - #define MSM8939_S4_P2_SHIFT 25 100 - #define MSM8939_S5_P2_SHIFT 14 101 - #define MSM8939_S6_P2_SHIFT 26 102 - #define MSM8939_S7_P2_SHIFT 6 103 - #define MSM8939_S8_P2_SHIFT 18 104 - #define MSM8939_S9_P2_SHIFT_0_4 27 105 - #define MSM8939_S9_P2_SHIFT_5 13 106 - 107 - #define MSM8939_CAL_SEL_MASK 0x7 108 - #define MSM8939_CAL_SEL_SHIFT 0 109 - 110 - /* eeprom layout data for 8974 */ 111 - #define BASE1_MASK 0xff 112 - #define S0_P1_MASK 0x3f00 113 - #define S1_P1_MASK 0xfc000 114 - #define S2_P1_MASK 0x3f00000 115 - #define S3_P1_MASK 0xfc000000 116 - #define S4_P1_MASK 0x3f 117 - #define S5_P1_MASK 0xfc0 118 - #define S6_P1_MASK 0x3f000 119 - #define S7_P1_MASK 0xfc0000 120 - #define S8_P1_MASK 0x3f000000 121 - #define S8_P1_MASK_BKP 0x3f 122 - #define S9_P1_MASK 0x3f 123 - #define S9_P1_MASK_BKP 0xfc0 124 - #define S10_P1_MASK 0xfc0 125 - #define S10_P1_MASK_BKP 0x3f000 126 - #define CAL_SEL_0_1 0xc0000000 127 - #define CAL_SEL_2 0x40000000 128 - #define CAL_SEL_SHIFT 30 129 - #define CAL_SEL_SHIFT_2 28 130 - 131 - #define S0_P1_SHIFT 8 132 - #define S1_P1_SHIFT 14 133 - #define S2_P1_SHIFT 20 134 - #define S3_P1_SHIFT 26 135 - #define S5_P1_SHIFT 6 136 - #define S6_P1_SHIFT 12 137 - #define S7_P1_SHIFT 18 138 - #define S8_P1_SHIFT 24 139 - #define S9_P1_BKP_SHIFT 6 140 - #define S10_P1_SHIFT 6 141 - #define S10_P1_BKP_SHIFT 12 142 - 143 - #define BASE2_SHIFT 12 144 - #define BASE2_BKP_SHIFT 18 145 - #define S0_P2_SHIFT 20 146 - #define S0_P2_BKP_SHIFT 26 147 - #define S1_P2_SHIFT 26 148 - #define S2_P2_BKP_SHIFT 6 149 - #define S3_P2_SHIFT 6 150 - #define S3_P2_BKP_SHIFT 12 151 - #define S4_P2_SHIFT 12 152 - #define S4_P2_BKP_SHIFT 18 153 - #define S5_P2_SHIFT 18 154 - #define S5_P2_BKP_SHIFT 24 155 - #define S6_P2_SHIFT 24 156 - #define S7_P2_BKP_SHIFT 6 157 - #define S8_P2_SHIFT 6 158 - #define S8_P2_BKP_SHIFT 12 159 - #define S9_P2_SHIFT 12 160 - #define S9_P2_BKP_SHIFT 18 161 - #define S10_P2_SHIFT 18 162 - #define S10_P2_BKP_SHIFT 24 163 - 164 - #define BASE2_MASK 0xff000 165 - #define BASE2_BKP_MASK 0xfc0000 166 - #define S0_P2_MASK 0x3f00000 167 - #define S0_P2_BKP_MASK 0xfc000000 168 - #define S1_P2_MASK 0xfc000000 169 - #define S1_P2_BKP_MASK 0x3f 170 - #define S2_P2_MASK 0x3f 171 - #define S2_P2_BKP_MASK 0xfc0 172 - #define S3_P2_MASK 0xfc0 173 - #define S3_P2_BKP_MASK 0x3f000 174 - #define S4_P2_MASK 0x3f000 175 - #define S4_P2_BKP_MASK 0xfc0000 176 - #define S5_P2_MASK 0xfc0000 177 - #define S5_P2_BKP_MASK 0x3f000000 178 - #define S6_P2_MASK 0x3f000000 179 - #define S6_P2_BKP_MASK 0x3f 180 - #define S7_P2_MASK 0x3f 181 - #define S7_P2_BKP_MASK 0xfc0 182 - #define S8_P2_MASK 0xfc0 183 - #define S8_P2_BKP_MASK 0x3f000 184 - #define S9_P2_MASK 0x3f000 185 - #define S9_P2_BKP_MASK 0xfc0000 186 - #define S10_P2_MASK 0xfc0000 187 - #define S10_P2_BKP_MASK 0x3f000000 188 - 18 + /* extra data for 8974 */ 189 19 #define BKP_SEL 0x3 190 20 #define BKP_REDUN_SEL 0xe0000000 191 - #define BKP_REDUN_SHIFT 29 192 21 193 22 #define BIT_APPEND 0x3 194 23 195 - /* eeprom layout data for mdm9607 */ 196 - #define MDM9607_BASE0_MASK 0x000000ff 197 - #define MDM9607_BASE1_MASK 0x000ff000 198 - #define MDM9607_BASE0_SHIFT 0 199 - #define MDM9607_BASE1_SHIFT 12 24 + struct tsens_legacy_calibration_format tsens_8916_nvmem = { 25 + .base_len = 7, 26 + .base_shift = 3, 27 + .sp_len = 5, 28 + .mode = { 0, 29, 1 }, 29 + .invalid = { 0, 31, 1 }, 30 + .base = { { 0, 0 }, { 1, 25 } }, 31 + .sp = { 32 + { { 0, 7 }, { 0, 12 } }, 33 + { { 0, 17 }, { 0, 22 } }, 34 + { { 0, 27 }, { 1, 0 } }, 35 + { { 1, 5 }, { 1, 10 } }, 36 + { { 1, 15 }, { 1, 20 } }, 37 + }, 38 + }; 200 39 201 - #define MDM9607_S0_P1_MASK 0x00003f00 202 - #define MDM9607_S1_P1_MASK 0x03f00000 203 - #define MDM9607_S2_P1_MASK 0x0000003f 204 - #define MDM9607_S3_P1_MASK 0x0003f000 205 - #define MDM9607_S4_P1_MASK 0x0000003f 40 + struct tsens_legacy_calibration_format tsens_8939_nvmem = { 41 + .base_len = 8, 42 + .base_shift = 2, 43 + .sp_len = 6, 44 + .mode = { 12, 0 }, 45 + .invalid = { 12, 2 }, 46 + .base = { { 0, 0 }, { 1, 24 } }, 47 + .sp = { 48 + { { 12, 3 }, { 12, 9 } }, 49 + { { 12, 15 }, { 12, 21 } }, 50 + { { 12, 27 }, { 13, 1 } }, 51 + { { 13, 7 }, { 13, 13 } }, 52 + { { 13, 19 }, { 13, 25 } }, 53 + { { 0, 8 }, { 0, 14 } }, 54 + { { 0, 20 }, { 0, 26 } }, 55 + { { 1, 0 }, { 1, 6 } }, 56 + { { 1, 12 }, { 1, 18 } }, 57 + }, 58 + }; 206 59 207 - #define MDM9607_S0_P2_MASK 0x000fc000 208 - #define MDM9607_S1_P2_MASK 0xfc000000 209 - #define MDM9607_S2_P2_MASK 0x00000fc0 210 - #define MDM9607_S3_P2_MASK 0x00fc0000 211 - #define MDM9607_S4_P2_MASK 0x00000fc0 60 + struct tsens_legacy_calibration_format tsens_8974_nvmem = { 61 + .base_len = 8, 62 + .base_shift = 2, 63 + .sp_len = 6, 64 + .mode = { 1, 30 }, 65 + .invalid = { 3, 30 }, 66 + .base = { { 0, 0 }, { 2, 12 } }, 67 + .sp = { 68 + { { 0, 8 }, { 2, 20 } }, 69 + { { 0, 14 }, { 2, 26 } }, 70 + { { 0, 20 }, { 3, 0 } }, 71 + { { 0, 26 }, { 3, 6 } }, 72 + { { 1, 0 }, { 3, 12 } }, 73 + { { 1, 6 }, { 3, 18 } }, 74 + { { 1, 12 }, { 3, 24 } }, 75 + { { 1, 18 }, { 4, 0 } }, 76 + { { 1, 24 }, { 4, 6 } }, 77 + { { 2, 0 }, { 4, 12 } }, 78 + { { 2, 6 }, { 4, 18 } }, 79 + }, 80 + }; 212 81 213 - #define MDM9607_S0_P1_SHIFT 8 214 - #define MDM9607_S1_P1_SHIFT 20 215 - #define MDM9607_S2_P1_SHIFT 0 216 - #define MDM9607_S3_P1_SHIFT 12 217 - #define MDM9607_S4_P1_SHIFT 0 82 + struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = { 83 + .base_len = 8, 84 + .base_shift = 2, 85 + .sp_len = 6, 86 + .mode = { 4, 30, 1 }, 87 + .invalid = { 5, 30, 1 }, 88 + .base = { { 0, 0 }, { 2, 18 } }, 89 + .sp = { 90 + { { 0, 8 }, { 2, 26 } }, 91 + { { 0, 14 }, { 3, 0 } }, 92 + { { 0, 20 }, { 3, 6 } }, 93 + { { 0, 26 }, { 3, 12 } }, 94 + { { 1, 0 }, { 3, 18 } }, 95 + { { 1, 6 }, { 3, 24, 1 } }, 96 + { { 1, 12 }, { 4, 0, 1 } }, 97 + { { 1, 18 }, { 4, 6, 1 } }, 98 + { { 2, 0 }, { 4, 12, 1 } }, 99 + { { 2, 6 }, { 4, 18, 1 } }, 100 + { { 2, 12 }, { 4, 24, 1 } }, 101 + }, 102 + }; 218 103 219 - #define MDM9607_S0_P2_SHIFT 14 220 - #define MDM9607_S1_P2_SHIFT 26 221 - #define MDM9607_S2_P2_SHIFT 6 222 - #define MDM9607_S3_P2_SHIFT 18 223 - #define MDM9607_S4_P2_SHIFT 6 224 - 225 - #define MDM9607_CAL_SEL_MASK 0x00700000 226 - #define MDM9607_CAL_SEL_SHIFT 20 104 + struct tsens_legacy_calibration_format tsens_9607_nvmem = { 105 + .base_len = 8, 106 + .base_shift = 2, 107 + .sp_len = 6, 108 + .mode = { 2, 20 }, 109 + .invalid = { 2, 22 }, 110 + .base = { { 0, 0 }, { 2, 12 } }, 111 + .sp = { 112 + { { 0, 8 }, { 0, 14 } }, 113 + { { 0, 20 }, { 0, 26 } }, 114 + { { 1, 0 }, { 1, 6 } }, 115 + { { 1, 12 }, { 1, 18 } }, 116 + { { 2, 0 }, { 2, 6 } }, 117 + }, 118 + }; 227 119 228 120 static int calibrate_8916(struct tsens_priv *priv) 229 121 { 230 - int base0 = 0, base1 = 0, i; 231 122 u32 p1[5], p2[5]; 232 - int mode = 0; 233 123 u32 *qfprom_cdata, *qfprom_csel; 124 + int mode, ret; 125 + 126 + ret = tsens_calibrate_nvmem(priv, 3); 127 + if (!ret) 128 + return 0; 234 129 235 130 qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 236 131 if (IS_ERR(qfprom_cdata)) ··· 139 240 return PTR_ERR(qfprom_csel); 140 241 } 141 242 142 - mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT; 143 - dev_dbg(priv->dev, "calibration mode is %d\n", mode); 144 - 145 - switch (mode) { 146 - case TWO_PT_CALIB: 147 - base1 = (qfprom_cdata[1] & MSM8916_BASE1_MASK) >> MSM8916_BASE1_SHIFT; 148 - p2[0] = (qfprom_cdata[0] & MSM8916_S0_P2_MASK) >> MSM8916_S0_P2_SHIFT; 149 - p2[1] = (qfprom_cdata[0] & MSM8916_S1_P2_MASK) >> MSM8916_S1_P2_SHIFT; 150 - p2[2] = (qfprom_cdata[1] & MSM8916_S2_P2_MASK) >> MSM8916_S2_P2_SHIFT; 151 - p2[3] = (qfprom_cdata[1] & MSM8916_S3_P2_MASK) >> MSM8916_S3_P2_SHIFT; 152 - p2[4] = (qfprom_cdata[1] & MSM8916_S4_P2_MASK) >> MSM8916_S4_P2_SHIFT; 153 - for (i = 0; i < priv->num_sensors; i++) 154 - p2[i] = ((base1 + p2[i]) << 3); 155 - fallthrough; 156 - case ONE_PT_CALIB2: 157 - base0 = (qfprom_cdata[0] & MSM8916_BASE0_MASK); 158 - p1[0] = (qfprom_cdata[0] & MSM8916_S0_P1_MASK) >> MSM8916_S0_P1_SHIFT; 159 - p1[1] = (qfprom_cdata[0] & MSM8916_S1_P1_MASK) >> MSM8916_S1_P1_SHIFT; 160 - p1[2] = (qfprom_cdata[0] & MSM8916_S2_P1_MASK) >> MSM8916_S2_P1_SHIFT; 161 - p1[3] = (qfprom_cdata[1] & MSM8916_S3_P1_MASK) >> MSM8916_S3_P1_SHIFT; 162 - p1[4] = (qfprom_cdata[1] & MSM8916_S4_P1_MASK) >> MSM8916_S4_P1_SHIFT; 163 - for (i = 0; i < priv->num_sensors; i++) 164 - p1[i] = (((base0) + p1[i]) << 3); 165 - break; 166 - default: 167 - for (i = 0; i < priv->num_sensors; i++) { 168 - p1[i] = 500; 169 - p2[i] = 780; 170 - } 171 - break; 172 - } 243 + mode = tsens_read_calibration_legacy(priv, &tsens_8916_nvmem, 244 + p1, p2, 245 + qfprom_cdata, qfprom_csel); 173 246 174 247 compute_intercept_slope(priv, p1, p2, mode); 175 248 kfree(qfprom_cdata); ··· 150 279 return 0; 151 280 } 152 281 153 - static int calibrate_8939(struct tsens_priv *priv) 282 + static void fixup_8974_points(int mode, u32 *p1, u32 *p2) 154 283 { 155 - int base0 = 0, base1 = 0, i; 156 - u32 p1[10], p2[10]; 157 - int mode = 0; 158 - u32 *qfprom_cdata; 159 - u32 cdata[6]; 284 + int i; 160 285 161 - qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 162 - if (IS_ERR(qfprom_cdata)) 163 - return PTR_ERR(qfprom_cdata); 164 - 165 - /* Mapping between qfprom nvmem and calibration data */ 166 - cdata[0] = qfprom_cdata[12]; 167 - cdata[1] = qfprom_cdata[13]; 168 - cdata[2] = qfprom_cdata[0]; 169 - cdata[3] = qfprom_cdata[1]; 170 - cdata[4] = qfprom_cdata[22]; 171 - cdata[5] = qfprom_cdata[21]; 172 - 173 - mode = (cdata[0] & MSM8939_CAL_SEL_MASK) >> MSM8939_CAL_SEL_SHIFT; 174 - dev_dbg(priv->dev, "calibration mode is %d\n", mode); 175 - 176 - switch (mode) { 177 - case TWO_PT_CALIB: 178 - base1 = (cdata[3] & MSM8939_BASE1_MASK) >> MSM8939_BASE1_SHIFT; 179 - p2[0] = (cdata[0] & MSM8939_S0_P2_MASK) >> MSM8939_S0_P2_SHIFT; 180 - p2[1] = (cdata[0] & MSM8939_S1_P2_MASK) >> MSM8939_S1_P2_SHIFT; 181 - p2[2] = (cdata[1] & MSM8939_S2_P2_MASK) >> MSM8939_S2_P2_SHIFT; 182 - p2[3] = (cdata[1] & MSM8939_S3_P2_MASK) >> MSM8939_S3_P2_SHIFT; 183 - p2[4] = (cdata[1] & MSM8939_S4_P2_MASK) >> MSM8939_S4_P2_SHIFT; 184 - p2[5] = (cdata[2] & MSM8939_S5_P2_MASK) >> MSM8939_S5_P2_SHIFT; 185 - p2[6] = (cdata[2] & MSM8939_S6_P2_MASK) >> MSM8939_S6_P2_SHIFT; 186 - p2[7] = (cdata[3] & MSM8939_S7_P2_MASK) >> MSM8939_S7_P2_SHIFT; 187 - p2[8] = (cdata[3] & MSM8939_S8_P2_MASK) >> MSM8939_S8_P2_SHIFT; 188 - p2[9] = (cdata[4] & MSM8939_S9_P2_MASK_0_4) >> MSM8939_S9_P2_SHIFT_0_4; 189 - p2[9] |= ((cdata[5] & MSM8939_S9_P2_MASK_5) >> MSM8939_S9_P2_SHIFT_5) << 5; 190 - for (i = 0; i < priv->num_sensors; i++) 191 - p2[i] = (base1 + p2[i]) << 2; 192 - fallthrough; 193 - case ONE_PT_CALIB2: 194 - base0 = (cdata[2] & MSM8939_BASE0_MASK) >> MSM8939_BASE0_SHIFT; 195 - p1[0] = (cdata[0] & MSM8939_S0_P1_MASK) >> MSM8939_S0_P1_SHIFT; 196 - p1[1] = (cdata[0] & MSM8939_S1_P1_MASK) >> MSM8939_S1_P1_SHIFT; 197 - p1[2] = (cdata[0] & MSM8939_S2_P1_MASK_0_4) >> MSM8939_S2_P1_SHIFT_0_4; 198 - p1[2] |= ((cdata[1] & MSM8939_S2_P1_MASK_5) >> MSM8939_S2_P1_SHIFT_5) << 5; 199 - p1[3] = (cdata[1] & MSM8939_S3_P1_MASK) >> MSM8939_S3_P1_SHIFT; 200 - p1[4] = (cdata[1] & MSM8939_S4_P1_MASK) >> MSM8939_S4_P1_SHIFT; 201 - p1[5] = (cdata[2] & MSM8939_S5_P1_MASK) >> MSM8939_S5_P1_SHIFT; 202 - p1[6] = (cdata[2] & MSM8939_S6_P1_MASK) >> MSM8939_S6_P1_SHIFT; 203 - p1[7] = (cdata[3] & MSM8939_S7_P1_MASK) >> MSM8939_S7_P1_SHIFT; 204 - p1[8] = (cdata[3] & MSM8939_S8_P1_MASK) >> MSM8939_S8_P1_SHIFT; 205 - p1[9] = (cdata[4] & MSM8939_S9_P1_MASK) >> MSM8939_S9_P1_SHIFT; 206 - for (i = 0; i < priv->num_sensors; i++) 207 - p1[i] = ((base0) + p1[i]) << 2; 208 - break; 209 - default: 210 - for (i = 0; i < priv->num_sensors; i++) { 211 - p1[i] = 500; 212 - p2[i] = 780; 286 + if (mode == NO_PT_CALIB) { 287 + p1[0] += 2; 288 + p1[1] += 9; 289 + p1[2] += 3; 290 + p1[3] += 9; 291 + p1[4] += 5; 292 + p1[5] += 9; 293 + p1[6] += 7; 294 + p1[7] += 10; 295 + p1[8] += 8; 296 + p1[9] += 9; 297 + p1[10] += 8; 298 + } else { 299 + for (i = 0; i < 11; i++) { 300 + /* 301 + * ONE_PT_CALIB requires using addition here instead of 302 + * using OR operation. 303 + */ 304 + p1[i] += BIT_APPEND; 305 + p2[i] += BIT_APPEND; 213 306 } 214 - break; 215 307 } 216 308 309 + } 310 + 311 + static int calibrate_8974_nvmem(struct tsens_priv *priv) 312 + { 313 + u32 p1[11], p2[11]; 314 + u32 backup; 315 + int ret, mode; 316 + 317 + ret = nvmem_cell_read_variable_le_u32(priv->dev, "use_backup", &backup); 318 + if (ret == -ENOENT) 319 + dev_warn(priv->dev, "Please migrate to separate nvmem cells for calibration data\n"); 320 + if (ret < 0) 321 + return ret; 322 + 323 + mode = tsens_read_calibration(priv, 2, p1, p2, backup == BKP_SEL); 324 + if (mode < 0) 325 + return mode; 326 + 327 + fixup_8974_points(mode, p1, p2); 328 + 217 329 compute_intercept_slope(priv, p1, p2, mode); 218 - kfree(qfprom_cdata); 219 330 220 331 return 0; 221 332 } 222 333 223 334 static int calibrate_8974(struct tsens_priv *priv) 224 335 { 225 - int base1 = 0, base2 = 0, i; 226 336 u32 p1[11], p2[11]; 227 - int mode = 0; 228 337 u32 *calib, *bkp; 229 338 u32 calib_redun_sel; 339 + int mode, ret; 340 + 341 + ret = calibrate_8974_nvmem(priv); 342 + if (ret == 0) 343 + return 0; 230 344 231 345 calib = (u32 *)qfprom_read(priv->dev, "calib"); 232 346 if (IS_ERR(calib)) ··· 223 367 return PTR_ERR(bkp); 224 368 } 225 369 226 - calib_redun_sel = bkp[1] & BKP_REDUN_SEL; 227 - calib_redun_sel >>= BKP_REDUN_SHIFT; 370 + calib_redun_sel = FIELD_GET(BKP_REDUN_SEL, bkp[1]); 228 371 229 - if (calib_redun_sel == BKP_SEL) { 230 - mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT; 231 - mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2; 372 + if (calib_redun_sel == BKP_SEL) 373 + mode = tsens_read_calibration_legacy(priv, &tsens_8974_backup_nvmem, 374 + p1, p2, 375 + bkp, calib); 376 + else 377 + mode = tsens_read_calibration_legacy(priv, &tsens_8974_nvmem, 378 + p1, p2, 379 + calib, NULL); 232 380 233 - switch (mode) { 234 - case TWO_PT_CALIB: 235 - base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT; 236 - p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT; 237 - p2[1] = (bkp[3] & S1_P2_BKP_MASK); 238 - p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT; 239 - p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT; 240 - p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT; 241 - p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT; 242 - p2[6] = (calib[5] & S6_P2_BKP_MASK); 243 - p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT; 244 - p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT; 245 - p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT; 246 - p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT; 247 - fallthrough; 248 - case ONE_PT_CALIB: 249 - case ONE_PT_CALIB2: 250 - base1 = bkp[0] & BASE1_MASK; 251 - p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT; 252 - p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT; 253 - p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT; 254 - p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT; 255 - p1[4] = (bkp[1] & S4_P1_MASK); 256 - p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT; 257 - p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT; 258 - p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT; 259 - p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT; 260 - p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT; 261 - p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT; 262 - break; 263 - } 264 - } else { 265 - mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT; 266 - mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2; 267 - 268 - switch (mode) { 269 - case TWO_PT_CALIB: 270 - base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT; 271 - p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT; 272 - p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT; 273 - p2[2] = (calib[3] & S2_P2_MASK); 274 - p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT; 275 - p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT; 276 - p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT; 277 - p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT; 278 - p2[7] = (calib[4] & S7_P2_MASK); 279 - p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT; 280 - p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT; 281 - p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT; 282 - fallthrough; 283 - case ONE_PT_CALIB: 284 - case ONE_PT_CALIB2: 285 - base1 = calib[0] & BASE1_MASK; 286 - p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT; 287 - p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT; 288 - p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT; 289 - p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT; 290 - p1[4] = (calib[1] & S4_P1_MASK); 291 - p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT; 292 - p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT; 293 - p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT; 294 - p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT; 295 - p1[9] = (calib[2] & S9_P1_MASK); 296 - p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT; 297 - break; 298 - } 299 - } 300 - 301 - switch (mode) { 302 - case ONE_PT_CALIB: 303 - for (i = 0; i < priv->num_sensors; i++) 304 - p1[i] += (base1 << 2) | BIT_APPEND; 305 - break; 306 - case TWO_PT_CALIB: 307 - for (i = 0; i < priv->num_sensors; i++) { 308 - p2[i] += base2; 309 - p2[i] <<= 2; 310 - p2[i] |= BIT_APPEND; 311 - } 312 - fallthrough; 313 - case ONE_PT_CALIB2: 314 - for (i = 0; i < priv->num_sensors; i++) { 315 - p1[i] += base1; 316 - p1[i] <<= 2; 317 - p1[i] |= BIT_APPEND; 318 - } 319 - break; 320 - default: 321 - for (i = 0; i < priv->num_sensors; i++) 322 - p2[i] = 780; 323 - p1[0] = 502; 324 - p1[1] = 509; 325 - p1[2] = 503; 326 - p1[3] = 509; 327 - p1[4] = 505; 328 - p1[5] = 509; 329 - p1[6] = 507; 330 - p1[7] = 510; 331 - p1[8] = 508; 332 - p1[9] = 509; 333 - p1[10] = 508; 334 - break; 335 - } 381 + fixup_8974_points(mode, p1, p2); 336 382 337 383 compute_intercept_slope(priv, p1, p2, mode); 338 384 kfree(calib); ··· 243 485 return 0; 244 486 } 245 487 246 - static int calibrate_9607(struct tsens_priv *priv) 247 - { 248 - int base, i; 249 - u32 p1[5], p2[5]; 250 - int mode = 0; 251 - u32 *qfprom_cdata; 488 + static int __init init_8939(struct tsens_priv *priv) { 489 + priv->sensor[0].slope = 2911; 490 + priv->sensor[1].slope = 2789; 491 + priv->sensor[2].slope = 2906; 492 + priv->sensor[3].slope = 2763; 493 + priv->sensor[4].slope = 2922; 494 + priv->sensor[5].slope = 2867; 495 + priv->sensor[6].slope = 2833; 496 + priv->sensor[7].slope = 2838; 497 + priv->sensor[8].slope = 2840; 498 + /* priv->sensor[9].slope = 2852; */ 252 499 253 - qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 254 - if (IS_ERR(qfprom_cdata)) 255 - return PTR_ERR(qfprom_cdata); 256 - 257 - mode = (qfprom_cdata[2] & MDM9607_CAL_SEL_MASK) >> MDM9607_CAL_SEL_SHIFT; 258 - dev_dbg(priv->dev, "calibration mode is %d\n", mode); 259 - 260 - switch (mode) { 261 - case TWO_PT_CALIB: 262 - base = (qfprom_cdata[2] & MDM9607_BASE1_MASK) >> MDM9607_BASE1_SHIFT; 263 - p2[0] = (qfprom_cdata[0] & MDM9607_S0_P2_MASK) >> MDM9607_S0_P2_SHIFT; 264 - p2[1] = (qfprom_cdata[0] & MDM9607_S1_P2_MASK) >> MDM9607_S1_P2_SHIFT; 265 - p2[2] = (qfprom_cdata[1] & MDM9607_S2_P2_MASK) >> MDM9607_S2_P2_SHIFT; 266 - p2[3] = (qfprom_cdata[1] & MDM9607_S3_P2_MASK) >> MDM9607_S3_P2_SHIFT; 267 - p2[4] = (qfprom_cdata[2] & MDM9607_S4_P2_MASK) >> MDM9607_S4_P2_SHIFT; 268 - for (i = 0; i < priv->num_sensors; i++) 269 - p2[i] = ((base + p2[i]) << 2); 270 - fallthrough; 271 - case ONE_PT_CALIB2: 272 - base = (qfprom_cdata[0] & MDM9607_BASE0_MASK); 273 - p1[0] = (qfprom_cdata[0] & MDM9607_S0_P1_MASK) >> MDM9607_S0_P1_SHIFT; 274 - p1[1] = (qfprom_cdata[0] & MDM9607_S1_P1_MASK) >> MDM9607_S1_P1_SHIFT; 275 - p1[2] = (qfprom_cdata[1] & MDM9607_S2_P1_MASK) >> MDM9607_S2_P1_SHIFT; 276 - p1[3] = (qfprom_cdata[1] & MDM9607_S3_P1_MASK) >> MDM9607_S3_P1_SHIFT; 277 - p1[4] = (qfprom_cdata[2] & MDM9607_S4_P1_MASK) >> MDM9607_S4_P1_SHIFT; 278 - for (i = 0; i < priv->num_sensors; i++) 279 - p1[i] = ((base + p1[i]) << 2); 280 - break; 281 - default: 282 - for (i = 0; i < priv->num_sensors; i++) { 283 - p1[i] = 500; 284 - p2[i] = 780; 285 - } 286 - break; 287 - } 288 - 289 - compute_intercept_slope(priv, p1, p2, mode); 290 - kfree(qfprom_cdata); 291 - 292 - return 0; 500 + return init_common(priv); 293 501 } 294 502 295 503 /* v0.1: 8916, 8939, 8974, 9607 */ ··· 307 583 [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), 308 584 }; 309 585 586 + static const struct tsens_ops ops_v0_1 = { 587 + .init = init_common, 588 + .calibrate = tsens_calibrate_common, 589 + .get_temp = get_temp_common, 590 + }; 591 + 310 592 static const struct tsens_ops ops_8916 = { 311 593 .init = init_common, 312 594 .calibrate = calibrate_8916, ··· 329 599 }; 330 600 331 601 static const struct tsens_ops ops_8939 = { 332 - .init = init_common, 333 - .calibrate = calibrate_8939, 602 + .init = init_8939, 603 + .calibrate = tsens_calibrate_common, 334 604 .get_temp = get_temp_common, 335 605 }; 336 606 337 607 struct tsens_plat_data data_8939 = { 338 - .num_sensors = 10, 608 + .num_sensors = 9, 339 609 .ops = &ops_8939, 340 - .hw_ids = (unsigned int []){ 0, 1, 2, 3, 5, 6, 7, 8, 9, 10 }, 610 + .hw_ids = (unsigned int []){ 0, 1, 2, 3, 5, 6, 7, 8, 9, /* 10 */ }, 341 611 342 612 .feat = &tsens_v0_1_feat, 343 613 .fields = tsens_v0_1_regfields, ··· 356 626 .fields = tsens_v0_1_regfields, 357 627 }; 358 628 359 - static const struct tsens_ops ops_9607 = { 360 - .init = init_common, 361 - .calibrate = calibrate_9607, 362 - .get_temp = get_temp_common, 363 - }; 364 - 365 629 struct tsens_plat_data data_9607 = { 366 630 .num_sensors = 5, 367 - .ops = &ops_9607, 368 - .hw_ids = (unsigned int []){ 0, 1, 2, 3, 4 }, 631 + .ops = &ops_v0_1, 369 632 .feat = &tsens_v0_1_feat, 370 633 .fields = tsens_v0_1_regfields, 371 634 };
+81 -263
drivers/thermal/qcom/tsens-v1.c
··· 21 21 #define TM_HIGH_LOW_INT_STATUS_OFF 0x0088 22 22 #define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x0090 23 23 24 - /* eeprom layout data for msm8956/76 (v1) */ 25 - #define MSM8976_BASE0_MASK 0xff 26 - #define MSM8976_BASE1_MASK 0xff 27 - #define MSM8976_BASE1_SHIFT 8 24 + struct tsens_legacy_calibration_format tsens_qcs404_nvmem = { 25 + .base_len = 8, 26 + .base_shift = 2, 27 + .sp_len = 6, 28 + .mode = { 4, 0 }, 29 + .invalid = { 4, 2 }, 30 + .base = { { 4, 3 }, { 4, 11 } }, 31 + .sp = { 32 + { { 0, 0 }, { 0, 6 } }, 33 + { { 0, 12 }, { 0, 18 } }, 34 + { { 0, 24 }, { 0, 30 } }, 35 + { { 1, 4 }, { 1, 10 } }, 36 + { { 1, 16 }, { 1, 22 } }, 37 + { { 2, 0 }, { 2, 6 } }, 38 + { { 2, 12 }, { 2, 18 } }, 39 + { { 2, 24 }, { 2, 30 } }, 40 + { { 3, 4 }, { 3, 10 } }, 41 + { { 3, 16 }, { 3, 22 } }, 42 + }, 43 + }; 28 44 29 - #define MSM8976_S0_P1_MASK 0x3f00 30 - #define MSM8976_S1_P1_MASK 0x3f00000 31 - #define MSM8976_S2_P1_MASK 0x3f 32 - #define MSM8976_S3_P1_MASK 0x3f000 33 - #define MSM8976_S4_P1_MASK 0x3f00 34 - #define MSM8976_S5_P1_MASK 0x3f00000 35 - #define MSM8976_S6_P1_MASK 0x3f 36 - #define MSM8976_S7_P1_MASK 0x3f000 37 - #define MSM8976_S8_P1_MASK 0x1f8 38 - #define MSM8976_S9_P1_MASK 0x1f8000 39 - #define MSM8976_S10_P1_MASK 0xf8000000 40 - #define MSM8976_S10_P1_MASK_1 0x1 41 - 42 - #define MSM8976_S0_P2_MASK 0xfc000 43 - #define MSM8976_S1_P2_MASK 0xfc000000 44 - #define MSM8976_S2_P2_MASK 0xfc0 45 - #define MSM8976_S3_P2_MASK 0xfc0000 46 - #define MSM8976_S4_P2_MASK 0xfc000 47 - #define MSM8976_S5_P2_MASK 0xfc000000 48 - #define MSM8976_S6_P2_MASK 0xfc0 49 - #define MSM8976_S7_P2_MASK 0xfc0000 50 - #define MSM8976_S8_P2_MASK 0x7e00 51 - #define MSM8976_S9_P2_MASK 0x7e00000 52 - #define MSM8976_S10_P2_MASK 0x7e 53 - 54 - #define MSM8976_S0_P1_SHIFT 8 55 - #define MSM8976_S1_P1_SHIFT 20 56 - #define MSM8976_S2_P1_SHIFT 0 57 - #define MSM8976_S3_P1_SHIFT 12 58 - #define MSM8976_S4_P1_SHIFT 8 59 - #define MSM8976_S5_P1_SHIFT 20 60 - #define MSM8976_S6_P1_SHIFT 0 61 - #define MSM8976_S7_P1_SHIFT 12 62 - #define MSM8976_S8_P1_SHIFT 3 63 - #define MSM8976_S9_P1_SHIFT 15 64 - #define MSM8976_S10_P1_SHIFT 27 65 - #define MSM8976_S10_P1_SHIFT_1 0 66 - 67 - #define MSM8976_S0_P2_SHIFT 14 68 - #define MSM8976_S1_P2_SHIFT 26 69 - #define MSM8976_S2_P2_SHIFT 6 70 - #define MSM8976_S3_P2_SHIFT 18 71 - #define MSM8976_S4_P2_SHIFT 14 72 - #define MSM8976_S5_P2_SHIFT 26 73 - #define MSM8976_S6_P2_SHIFT 6 74 - #define MSM8976_S7_P2_SHIFT 18 75 - #define MSM8976_S8_P2_SHIFT 9 76 - #define MSM8976_S9_P2_SHIFT 21 77 - #define MSM8976_S10_P2_SHIFT 1 78 - 79 - #define MSM8976_CAL_SEL_MASK 0x3 80 - 81 - #define MSM8976_CAL_DEGC_PT1 30 82 - #define MSM8976_CAL_DEGC_PT2 120 83 - #define MSM8976_SLOPE_FACTOR 1000 84 - #define MSM8976_SLOPE_DEFAULT 3200 85 - 86 - /* eeprom layout data for qcs404/405 (v1) */ 87 - #define BASE0_MASK 0x000007f8 88 - #define BASE1_MASK 0x0007f800 89 - #define BASE0_SHIFT 3 90 - #define BASE1_SHIFT 11 91 - 92 - #define S0_P1_MASK 0x0000003f 93 - #define S1_P1_MASK 0x0003f000 94 - #define S2_P1_MASK 0x3f000000 95 - #define S3_P1_MASK 0x000003f0 96 - #define S4_P1_MASK 0x003f0000 97 - #define S5_P1_MASK 0x0000003f 98 - #define S6_P1_MASK 0x0003f000 99 - #define S7_P1_MASK 0x3f000000 100 - #define S8_P1_MASK 0x000003f0 101 - #define S9_P1_MASK 0x003f0000 102 - 103 - #define S0_P2_MASK 0x00000fc0 104 - #define S1_P2_MASK 0x00fc0000 105 - #define S2_P2_MASK_1_0 0xc0000000 106 - #define S2_P2_MASK_5_2 0x0000000f 107 - #define S3_P2_MASK 0x0000fc00 108 - #define S4_P2_MASK 0x0fc00000 109 - #define S5_P2_MASK 0x00000fc0 110 - #define S6_P2_MASK 0x00fc0000 111 - #define S7_P2_MASK_1_0 0xc0000000 112 - #define S7_P2_MASK_5_2 0x0000000f 113 - #define S8_P2_MASK 0x0000fc00 114 - #define S9_P2_MASK 0x0fc00000 115 - 116 - #define S0_P1_SHIFT 0 117 - #define S0_P2_SHIFT 6 118 - #define S1_P1_SHIFT 12 119 - #define S1_P2_SHIFT 18 120 - #define S2_P1_SHIFT 24 121 - #define S2_P2_SHIFT_1_0 30 122 - 123 - #define S2_P2_SHIFT_5_2 0 124 - #define S3_P1_SHIFT 4 125 - #define S3_P2_SHIFT 10 126 - #define S4_P1_SHIFT 16 127 - #define S4_P2_SHIFT 22 128 - 129 - #define S5_P1_SHIFT 0 130 - #define S5_P2_SHIFT 6 131 - #define S6_P1_SHIFT 12 132 - #define S6_P2_SHIFT 18 133 - #define S7_P1_SHIFT 24 134 - #define S7_P2_SHIFT_1_0 30 135 - 136 - #define S7_P2_SHIFT_5_2 0 137 - #define S8_P1_SHIFT 4 138 - #define S8_P2_SHIFT 10 139 - #define S9_P1_SHIFT 16 140 - #define S9_P2_SHIFT 22 141 - 142 - #define CAL_SEL_MASK 7 143 - #define CAL_SEL_SHIFT 0 144 - 145 - static void compute_intercept_slope_8976(struct tsens_priv *priv, 146 - u32 *p1, u32 *p2, u32 mode) 147 - { 148 - int i; 149 - 150 - priv->sensor[0].slope = 3313; 151 - priv->sensor[1].slope = 3275; 152 - priv->sensor[2].slope = 3320; 153 - priv->sensor[3].slope = 3246; 154 - priv->sensor[4].slope = 3279; 155 - priv->sensor[5].slope = 3257; 156 - priv->sensor[6].slope = 3234; 157 - priv->sensor[7].slope = 3269; 158 - priv->sensor[8].slope = 3255; 159 - priv->sensor[9].slope = 3239; 160 - priv->sensor[10].slope = 3286; 161 - 162 - for (i = 0; i < priv->num_sensors; i++) { 163 - priv->sensor[i].offset = (p1[i] * MSM8976_SLOPE_FACTOR) - 164 - (MSM8976_CAL_DEGC_PT1 * 165 - priv->sensor[i].slope); 166 - } 167 - } 45 + struct tsens_legacy_calibration_format tsens_8976_nvmem = { 46 + .base_len = 8, 47 + .base_shift = 2, 48 + .sp_len = 6, 49 + .mode = { 4, 0 }, 50 + .invalid = { 4, 2 }, 51 + .base = { { 0, 0 }, { 2, 8 } }, 52 + .sp = { 53 + { { 0, 8 }, { 0, 14 } }, 54 + { { 0, 20 }, { 0, 26 } }, 55 + { { 1, 0 }, { 1, 6 } }, 56 + { { 1, 12 }, { 1, 18 } }, 57 + { { 2, 8 }, { 2, 14 } }, 58 + { { 2, 20 }, { 2, 26 } }, 59 + { { 3, 0 }, { 3, 6 } }, 60 + { { 3, 12 }, { 3, 18 } }, 61 + { { 4, 2 }, { 4, 9 } }, 62 + { { 4, 14 }, { 4, 21 } }, 63 + { { 4, 26 }, { 5, 1 } }, 64 + }, 65 + }; 168 66 169 67 static int calibrate_v1(struct tsens_priv *priv) 170 68 { 171 - u32 base0 = 0, base1 = 0; 172 69 u32 p1[10], p2[10]; 173 - u32 mode = 0, lsb = 0, msb = 0; 174 70 u32 *qfprom_cdata; 175 - int i; 71 + int mode, ret; 72 + 73 + ret = tsens_calibrate_common(priv); 74 + if (!ret) 75 + return 0; 176 76 177 77 qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 178 78 if (IS_ERR(qfprom_cdata)) 179 79 return PTR_ERR(qfprom_cdata); 180 80 181 - mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT; 182 - dev_dbg(priv->dev, "calibration mode is %d\n", mode); 183 - 184 - switch (mode) { 185 - case TWO_PT_CALIB: 186 - base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT; 187 - p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT; 188 - p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT; 189 - /* This value is split over two registers, 2 bits and 4 bits */ 190 - lsb = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0; 191 - msb = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2; 192 - p2[2] = msb << 2 | lsb; 193 - p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT; 194 - p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT; 195 - p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT; 196 - p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT; 197 - /* This value is split over two registers, 2 bits and 4 bits */ 198 - lsb = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0; 199 - msb = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2; 200 - p2[7] = msb << 2 | lsb; 201 - p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT; 202 - p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT; 203 - for (i = 0; i < priv->num_sensors; i++) 204 - p2[i] = ((base1 + p2[i]) << 2); 205 - fallthrough; 206 - case ONE_PT_CALIB2: 207 - base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT; 208 - p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT; 209 - p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT; 210 - p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT; 211 - p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT; 212 - p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT; 213 - p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT; 214 - p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT; 215 - p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT; 216 - p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT; 217 - p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT; 218 - for (i = 0; i < priv->num_sensors; i++) 219 - p1[i] = (((base0) + p1[i]) << 2); 220 - break; 221 - default: 222 - for (i = 0; i < priv->num_sensors; i++) { 223 - p1[i] = 500; 224 - p2[i] = 780; 225 - } 226 - break; 227 - } 81 + mode = tsens_read_calibration_legacy(priv, &tsens_qcs404_nvmem, 82 + p1, p2, 83 + qfprom_cdata, NULL); 228 84 229 85 compute_intercept_slope(priv, p1, p2, mode); 230 - kfree(qfprom_cdata); 231 - 232 - return 0; 233 - } 234 - 235 - static int calibrate_8976(struct tsens_priv *priv) 236 - { 237 - int base0 = 0, base1 = 0, i; 238 - u32 p1[11], p2[11]; 239 - int mode = 0, tmp = 0; 240 - u32 *qfprom_cdata; 241 - 242 - qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 243 - if (IS_ERR(qfprom_cdata)) 244 - return PTR_ERR(qfprom_cdata); 245 - 246 - mode = (qfprom_cdata[4] & MSM8976_CAL_SEL_MASK); 247 - dev_dbg(priv->dev, "calibration mode is %d\n", mode); 248 - 249 - switch (mode) { 250 - case TWO_PT_CALIB: 251 - base1 = (qfprom_cdata[2] & MSM8976_BASE1_MASK) >> MSM8976_BASE1_SHIFT; 252 - p2[0] = (qfprom_cdata[0] & MSM8976_S0_P2_MASK) >> MSM8976_S0_P2_SHIFT; 253 - p2[1] = (qfprom_cdata[0] & MSM8976_S1_P2_MASK) >> MSM8976_S1_P2_SHIFT; 254 - p2[2] = (qfprom_cdata[1] & MSM8976_S2_P2_MASK) >> MSM8976_S2_P2_SHIFT; 255 - p2[3] = (qfprom_cdata[1] & MSM8976_S3_P2_MASK) >> MSM8976_S3_P2_SHIFT; 256 - p2[4] = (qfprom_cdata[2] & MSM8976_S4_P2_MASK) >> MSM8976_S4_P2_SHIFT; 257 - p2[5] = (qfprom_cdata[2] & MSM8976_S5_P2_MASK) >> MSM8976_S5_P2_SHIFT; 258 - p2[6] = (qfprom_cdata[3] & MSM8976_S6_P2_MASK) >> MSM8976_S6_P2_SHIFT; 259 - p2[7] = (qfprom_cdata[3] & MSM8976_S7_P2_MASK) >> MSM8976_S7_P2_SHIFT; 260 - p2[8] = (qfprom_cdata[4] & MSM8976_S8_P2_MASK) >> MSM8976_S8_P2_SHIFT; 261 - p2[9] = (qfprom_cdata[4] & MSM8976_S9_P2_MASK) >> MSM8976_S9_P2_SHIFT; 262 - p2[10] = (qfprom_cdata[5] & MSM8976_S10_P2_MASK) >> MSM8976_S10_P2_SHIFT; 263 - 264 - for (i = 0; i < priv->num_sensors; i++) 265 - p2[i] = ((base1 + p2[i]) << 2); 266 - fallthrough; 267 - case ONE_PT_CALIB2: 268 - base0 = qfprom_cdata[0] & MSM8976_BASE0_MASK; 269 - p1[0] = (qfprom_cdata[0] & MSM8976_S0_P1_MASK) >> MSM8976_S0_P1_SHIFT; 270 - p1[1] = (qfprom_cdata[0] & MSM8976_S1_P1_MASK) >> MSM8976_S1_P1_SHIFT; 271 - p1[2] = (qfprom_cdata[1] & MSM8976_S2_P1_MASK) >> MSM8976_S2_P1_SHIFT; 272 - p1[3] = (qfprom_cdata[1] & MSM8976_S3_P1_MASK) >> MSM8976_S3_P1_SHIFT; 273 - p1[4] = (qfprom_cdata[2] & MSM8976_S4_P1_MASK) >> MSM8976_S4_P1_SHIFT; 274 - p1[5] = (qfprom_cdata[2] & MSM8976_S5_P1_MASK) >> MSM8976_S5_P1_SHIFT; 275 - p1[6] = (qfprom_cdata[3] & MSM8976_S6_P1_MASK) >> MSM8976_S6_P1_SHIFT; 276 - p1[7] = (qfprom_cdata[3] & MSM8976_S7_P1_MASK) >> MSM8976_S7_P1_SHIFT; 277 - p1[8] = (qfprom_cdata[4] & MSM8976_S8_P1_MASK) >> MSM8976_S8_P1_SHIFT; 278 - p1[9] = (qfprom_cdata[4] & MSM8976_S9_P1_MASK) >> MSM8976_S9_P1_SHIFT; 279 - p1[10] = (qfprom_cdata[4] & MSM8976_S10_P1_MASK) >> MSM8976_S10_P1_SHIFT; 280 - tmp = (qfprom_cdata[5] & MSM8976_S10_P1_MASK_1) << MSM8976_S10_P1_SHIFT_1; 281 - p1[10] |= tmp; 282 - 283 - for (i = 0; i < priv->num_sensors; i++) 284 - p1[i] = (((base0) + p1[i]) << 2); 285 - break; 286 - default: 287 - for (i = 0; i < priv->num_sensors; i++) { 288 - p1[i] = 500; 289 - p2[i] = 780; 290 - } 291 - break; 292 - } 293 - 294 - compute_intercept_slope_8976(priv, p1, p2, mode); 295 86 kfree(qfprom_cdata); 296 87 297 88 return 0; ··· 156 365 [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), 157 366 }; 158 367 368 + static int __init init_8956(struct tsens_priv *priv) { 369 + priv->sensor[0].slope = 3313; 370 + priv->sensor[1].slope = 3275; 371 + priv->sensor[2].slope = 3320; 372 + priv->sensor[3].slope = 3246; 373 + priv->sensor[4].slope = 3279; 374 + priv->sensor[5].slope = 3257; 375 + priv->sensor[6].slope = 3234; 376 + priv->sensor[7].slope = 3269; 377 + priv->sensor[8].slope = 3255; 378 + priv->sensor[9].slope = 3239; 379 + priv->sensor[10].slope = 3286; 380 + 381 + return init_common(priv); 382 + } 383 + 159 384 static const struct tsens_ops ops_generic_v1 = { 160 385 .init = init_common, 161 386 .calibrate = calibrate_v1, ··· 184 377 .fields = tsens_v1_regfields, 185 378 }; 186 379 187 - static const struct tsens_ops ops_8976 = { 188 - .init = init_common, 189 - .calibrate = calibrate_8976, 380 + static const struct tsens_ops ops_8956 = { 381 + .init = init_8956, 382 + .calibrate = tsens_calibrate_common, 190 383 .get_temp = get_temp_tsens_valid, 191 384 }; 192 385 193 - /* Valid for both MSM8956 and MSM8976. */ 386 + struct tsens_plat_data data_8956 = { 387 + .num_sensors = 11, 388 + .ops = &ops_8956, 389 + .feat = &tsens_v1_feat, 390 + .fields = tsens_v1_regfields, 391 + }; 392 + 393 + static const struct tsens_ops ops_8976 = { 394 + .init = init_common, 395 + .calibrate = tsens_calibrate_common, 396 + .get_temp = get_temp_tsens_valid, 397 + }; 398 + 194 399 struct tsens_plat_data data_8976 = { 195 400 .num_sensors = 11, 196 401 .ops = &ops_8976, 197 - .hw_ids = (unsigned int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 198 402 .feat = &tsens_v1_feat, 199 403 .fields = tsens_v1_regfields, 200 404 };
+170 -49
drivers/thermal/qcom/tsens.c
··· 70 70 return ret; 71 71 } 72 72 73 + int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2, bool backup) 74 + { 75 + u32 mode; 76 + u32 base1, base2; 77 + char name[] = "sXX_pY_backup"; /* s10_p1_backup */ 78 + int i, ret; 79 + 80 + if (priv->num_sensors > MAX_SENSORS) 81 + return -EINVAL; 82 + 83 + ret = snprintf(name, sizeof(name), "mode%s", backup ? "_backup" : ""); 84 + if (ret < 0) 85 + return ret; 86 + 87 + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &mode); 88 + if (ret == -ENOENT) 89 + dev_warn(priv->dev, "Please migrate to separate nvmem cells for calibration data\n"); 90 + if (ret < 0) 91 + return ret; 92 + 93 + dev_dbg(priv->dev, "calibration mode is %d\n", mode); 94 + 95 + ret = snprintf(name, sizeof(name), "base1%s", backup ? "_backup" : ""); 96 + if (ret < 0) 97 + return ret; 98 + 99 + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &base1); 100 + if (ret < 0) 101 + return ret; 102 + 103 + ret = snprintf(name, sizeof(name), "base2%s", backup ? "_backup" : ""); 104 + if (ret < 0) 105 + return ret; 106 + 107 + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &base2); 108 + if (ret < 0) 109 + return ret; 110 + 111 + for (i = 0; i < priv->num_sensors; i++) { 112 + ret = snprintf(name, sizeof(name), "s%d_p1%s", priv->sensor[i].hw_id, 113 + backup ? "_backup" : ""); 114 + if (ret < 0) 115 + return ret; 116 + 117 + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &p1[i]); 118 + if (ret) 119 + return ret; 120 + 121 + ret = snprintf(name, sizeof(name), "s%d_p2%s", priv->sensor[i].hw_id, 122 + backup ? "_backup" : ""); 123 + if (ret < 0) 124 + return ret; 125 + 126 + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &p2[i]); 127 + if (ret) 128 + return ret; 129 + } 130 + 131 + switch (mode) { 132 + case ONE_PT_CALIB: 133 + for (i = 0; i < priv->num_sensors; i++) 134 + p1[i] = p1[i] + (base1 << shift); 135 + break; 136 + case TWO_PT_CALIB: 137 + for (i = 0; i < priv->num_sensors; i++) 138 + p2[i] = (p2[i] + base2) << shift; 139 + fallthrough; 140 + case ONE_PT_CALIB2: 141 + for (i = 0; i < priv->num_sensors; i++) 142 + p1[i] = (p1[i] + base1) << shift; 143 + break; 144 + default: 145 + dev_dbg(priv->dev, "calibrationless mode\n"); 146 + for (i = 0; i < priv->num_sensors; i++) { 147 + p1[i] = 500; 148 + p2[i] = 780; 149 + } 150 + } 151 + 152 + return mode; 153 + } 154 + 155 + int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift) 156 + { 157 + u32 p1[MAX_SENSORS], p2[MAX_SENSORS]; 158 + int mode; 159 + 160 + mode = tsens_read_calibration(priv, shift, p1, p2, false); 161 + if (mode < 0) 162 + return mode; 163 + 164 + compute_intercept_slope(priv, p1, p2, mode); 165 + 166 + return 0; 167 + } 168 + 169 + int tsens_calibrate_common(struct tsens_priv *priv) 170 + { 171 + return tsens_calibrate_nvmem(priv, 2); 172 + } 173 + 174 + static u32 tsens_read_cell(const struct tsens_single_value *cell, u8 len, u32 *data0, u32 *data1) 175 + { 176 + u32 val; 177 + u32 *data = cell->blob ? data1 : data0; 178 + 179 + if (cell->shift + len <= 32) { 180 + val = data[cell->idx] >> cell->shift; 181 + } else { 182 + u8 part = 32 - cell->shift; 183 + 184 + val = data[cell->idx] >> cell->shift; 185 + val |= data[cell->idx + 1] << part; 186 + } 187 + 188 + return val & ((1 << len) - 1); 189 + } 190 + 191 + int tsens_read_calibration_legacy(struct tsens_priv *priv, 192 + const struct tsens_legacy_calibration_format *format, 193 + u32 *p1, u32 *p2, 194 + u32 *cdata0, u32 *cdata1) 195 + { 196 + u32 mode, invalid; 197 + u32 base1, base2; 198 + int i; 199 + 200 + mode = tsens_read_cell(&format->mode, 2, cdata0, cdata1); 201 + invalid = tsens_read_cell(&format->invalid, 1, cdata0, cdata1); 202 + if (invalid) 203 + mode = NO_PT_CALIB; 204 + dev_dbg(priv->dev, "calibration mode is %d\n", mode); 205 + 206 + base1 = tsens_read_cell(&format->base[0], format->base_len, cdata0, cdata1); 207 + base2 = tsens_read_cell(&format->base[1], format->base_len, cdata0, cdata1); 208 + 209 + for (i = 0; i < priv->num_sensors; i++) { 210 + p1[i] = tsens_read_cell(&format->sp[i][0], format->sp_len, cdata0, cdata1); 211 + p2[i] = tsens_read_cell(&format->sp[i][1], format->sp_len, cdata0, cdata1); 212 + } 213 + 214 + switch (mode) { 215 + case ONE_PT_CALIB: 216 + for (i = 0; i < priv->num_sensors; i++) 217 + p1[i] = p1[i] + (base1 << format->base_shift); 218 + break; 219 + case TWO_PT_CALIB: 220 + for (i = 0; i < priv->num_sensors; i++) 221 + p2[i] = (p2[i] + base2) << format->base_shift; 222 + fallthrough; 223 + case ONE_PT_CALIB2: 224 + for (i = 0; i < priv->num_sensors; i++) 225 + p1[i] = (p1[i] + base1) << format->base_shift; 226 + break; 227 + default: 228 + dev_dbg(priv->dev, "calibrationless mode\n"); 229 + for (i = 0; i < priv->num_sensors; i++) { 230 + p1[i] = 500; 231 + p2[i] = 780; 232 + } 233 + } 234 + 235 + return mode; 236 + } 237 + 73 238 /* 74 239 * Use this function on devices where slope and offset calculations 75 240 * depend on calibration data read from qfprom. On others the slope ··· 624 459 { 625 460 struct tsens_priv *priv = data; 626 461 struct tsens_irq_data d; 627 - bool enable = true, disable = false; 628 - unsigned long flags; 629 - int temp, ret, i; 462 + int i; 630 463 631 464 for (i = 0; i < priv->num_sensors; i++) { 632 - bool trigger = false; 633 465 const struct tsens_sensor *s = &priv->sensor[i]; 634 466 u32 hw_id = s->hw_id; 635 467 ··· 634 472 continue; 635 473 if (!tsens_threshold_violated(priv, hw_id, &d)) 636 474 continue; 637 - ret = get_temp_tsens_valid(s, &temp); 638 - if (ret) { 639 - dev_err(priv->dev, "[%u] %s: error reading sensor\n", 640 - hw_id, __func__); 641 - continue; 642 - } 643 475 644 - spin_lock_irqsave(&priv->ul_lock, flags); 645 - 646 - tsens_read_irq_state(priv, hw_id, s, &d); 647 - 648 - if (d.up_viol && 649 - !masked_irq(hw_id, d.up_irq_mask, tsens_version(priv))) { 650 - tsens_set_interrupt(priv, hw_id, UPPER, disable); 651 - if (d.up_thresh > temp) { 652 - dev_dbg(priv->dev, "[%u] %s: re-arm upper\n", 653 - hw_id, __func__); 654 - tsens_set_interrupt(priv, hw_id, UPPER, enable); 655 - } else { 656 - trigger = true; 657 - /* Keep irq masked */ 658 - } 659 - } else if (d.low_viol && 660 - !masked_irq(hw_id, d.low_irq_mask, tsens_version(priv))) { 661 - tsens_set_interrupt(priv, hw_id, LOWER, disable); 662 - if (d.low_thresh < temp) { 663 - dev_dbg(priv->dev, "[%u] %s: re-arm low\n", 664 - hw_id, __func__); 665 - tsens_set_interrupt(priv, hw_id, LOWER, enable); 666 - } else { 667 - trigger = true; 668 - /* Keep irq masked */ 669 - } 670 - } 671 - 672 - spin_unlock_irqrestore(&priv->ul_lock, flags); 673 - 674 - if (trigger) { 675 - dev_dbg(priv->dev, "[%u] %s: TZ update trigger (%d mC)\n", 676 - hw_id, __func__, temp); 677 - thermal_zone_device_update(s->tzd, 678 - THERMAL_EVENT_UNSPECIFIED); 679 - } else { 680 - dev_dbg(priv->dev, "[%u] %s: no violation: %d\n", 681 - hw_id, __func__, temp); 682 - } 476 + thermal_zone_device_update(s->tzd, THERMAL_EVENT_UNSPECIFIED); 683 477 684 478 if (tsens_version(priv) < VER_0_1) { 685 479 /* Constraint: There is only 1 interrupt control register for all ··· 1101 983 }, { 1102 984 .compatible = "qcom,msm8939-tsens", 1103 985 .data = &data_8939, 986 + }, { 987 + .compatible = "qcom,msm8956-tsens", 988 + .data = &data_8956, 1104 989 }, { 1105 990 .compatible = "qcom,msm8960-tsens", 1106 991 .data = &data_8960,
+45 -1
drivers/thermal/qcom/tsens.h
··· 6 6 #ifndef __QCOM_TSENS_H__ 7 7 #define __QCOM_TSENS_H__ 8 8 9 + #define NO_PT_CALIB 0x0 9 10 #define ONE_PT_CALIB 0x1 10 11 #define ONE_PT_CALIB2 0x2 11 12 #define TWO_PT_CALIB 0x3 ··· 17 16 #define TIMEOUT_US 100 18 17 #define THRESHOLD_MAX_ADC_CODE 0x3ff 19 18 #define THRESHOLD_MIN_ADC_CODE 0x0 19 + 20 + #define MAX_SENSORS 16 20 21 21 22 #include <linux/interrupt.h> 22 23 #include <linux/thermal.h> ··· 584 581 struct tsens_sensor sensor[]; 585 582 }; 586 583 584 + /** 585 + * struct tsens_single_value - internal representation of a single field inside nvmem calibration data 586 + * @idx: index into the u32 data array 587 + * @shift: the shift of the first bit in the value 588 + * @blob: index of the data blob to use for this cell 589 + */ 590 + struct tsens_single_value { 591 + u8 idx; 592 + u8 shift; 593 + u8 blob; 594 + }; 595 + 596 + /** 597 + * struct tsens_legacy_calibration_format - description of calibration data used when parsing the legacy nvmem blob 598 + * @base_len: the length of the base fields inside calibration data 599 + * @base_shift: the shift to be applied to base data 600 + * @sp_len: the length of the sN_pM fields inside calibration data 601 + * @mode: descriptor of the calibration mode field 602 + * @invalid: descriptor of the calibration mode invalid field 603 + * @base: descriptors of the base0 and base1 fields 604 + * @sp: descriptors of the sN_pM fields 605 + */ 606 + struct tsens_legacy_calibration_format { 607 + unsigned int base_len; 608 + unsigned int base_shift; 609 + unsigned int sp_len; 610 + /* just two bits */ 611 + struct tsens_single_value mode; 612 + /* on all platforms except 8974 invalid is the third bit of what downstream calls 'mode' */ 613 + struct tsens_single_value invalid; 614 + struct tsens_single_value base[2]; 615 + struct tsens_single_value sp[][2]; 616 + }; 617 + 587 618 char *qfprom_read(struct device *dev, const char *cname); 619 + int tsens_read_calibration_legacy(struct tsens_priv *priv, 620 + const struct tsens_legacy_calibration_format *format, 621 + u32 *p1, u32 *p2, 622 + u32 *cdata, u32 *csel); 623 + int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2, bool backup); 624 + int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift); 625 + int tsens_calibrate_common(struct tsens_priv *priv); 588 626 void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode); 589 627 int init_common(struct tsens_priv *priv); 590 628 int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp); ··· 638 594 extern struct tsens_plat_data data_8916, data_8939, data_8974, data_9607; 639 595 640 596 /* TSENS v1 targets */ 641 - extern struct tsens_plat_data data_tsens_v1, data_8976; 597 + extern struct tsens_plat_data data_tsens_v1, data_8976, data_8956; 642 598 643 599 /* TSENS v2 targets */ 644 600 extern struct tsens_plat_data data_8996, data_ipq8074, data_tsens_v2;
-1
drivers/thermal/qoriq_thermal.c
··· 13 13 #include <linux/thermal.h> 14 14 #include <linux/units.h> 15 15 16 - #include "thermal_core.h" 17 16 #include "thermal_hwmon.h" 18 17 19 18 #define SITES_MAX 16
+23 -20
drivers/thermal/rcar_gen3_thermal.c
··· 17 17 #include <linux/sys_soc.h> 18 18 #include <linux/thermal.h> 19 19 20 - #include "thermal_core.h" 21 20 #include "thermal_hwmon.h" 22 21 23 22 /* Register offsets */ ··· 86 87 87 88 struct rcar_gen3_thermal_priv { 88 89 struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM]; 90 + struct thermal_zone_device_ops ops; 89 91 unsigned int num_tscs; 90 - void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc); 92 + void (*thermal_init)(struct rcar_gen3_thermal_priv *priv, 93 + struct rcar_gen3_thermal_tsc *tsc); 91 94 int ptat[3]; 92 95 }; 93 96 ··· 226 225 return 0; 227 226 } 228 227 229 - static struct thermal_zone_device_ops rcar_gen3_tz_of_ops = { 228 + static const struct thermal_zone_device_ops rcar_gen3_tz_of_ops = { 230 229 .get_temp = rcar_gen3_thermal_get_temp, 231 230 .set_trips = rcar_gen3_thermal_set_trips, 232 231 }; ··· 240 239 for (i = 0; i < priv->num_tscs; i++) { 241 240 status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR); 242 241 rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0); 243 - if (status) 242 + if (status && priv->tscs[i]->zone) 244 243 thermal_zone_device_update(priv->tscs[i]->zone, 245 244 THERMAL_EVENT_UNSPECIFIED); 246 245 } ··· 311 310 return true; 312 311 } 313 312 314 - static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_tsc *tsc) 313 + static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_priv *priv, 314 + struct rcar_gen3_thermal_tsc *tsc) 315 315 { 316 316 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR); 317 317 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 0x0); ··· 323 321 324 322 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); 325 323 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0); 326 - if (tsc->zone->ops->set_trips) 324 + if (priv->ops.set_trips) 327 325 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, 328 326 IRQ_TEMPD1 | IRQ_TEMP2); 329 327 ··· 339 337 usleep_range(1000, 2000); 340 338 } 341 339 342 - static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc) 340 + static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv, 341 + struct rcar_gen3_thermal_tsc *tsc) 343 342 { 344 343 u32 reg_val; 345 344 ··· 352 349 353 350 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0); 354 351 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0); 355 - if (tsc->zone->ops->set_trips) 352 + if (priv->ops.set_trips) 356 353 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, 357 354 IRQ_TEMPD1 | IRQ_TEMP2); 358 355 ··· 404 401 }, 405 402 { 406 403 .compatible = "renesas,r8a779f0-thermal", 404 + .data = &rcar_gen3_ths_tj_1, 405 + }, 406 + { 407 + .compatible = "renesas,r8a779g0-thermal", 407 408 .data = &rcar_gen3_ths_tj_1, 408 409 }, 409 410 {}, ··· 473 466 if (!priv) 474 467 return -ENOMEM; 475 468 469 + priv->ops = rcar_gen3_tz_of_ops; 476 470 priv->thermal_init = rcar_gen3_thermal_init; 477 471 if (soc_device_match(r8a7795es1)) 478 472 priv->thermal_init = rcar_gen3_thermal_init_r8a7795es1; ··· 481 473 platform_set_drvdata(pdev, priv); 482 474 483 475 if (rcar_gen3_thermal_request_irqs(priv, pdev)) 484 - rcar_gen3_tz_of_ops.set_trips = NULL; 476 + priv->ops.set_trips = NULL; 485 477 486 478 pm_runtime_enable(dev); 487 479 pm_runtime_get_sync(dev); ··· 516 508 for (i = 0; i < priv->num_tscs; i++) { 517 509 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; 518 510 519 - zone = devm_thermal_of_zone_register(dev, i, tsc, 520 - &rcar_gen3_tz_of_ops); 511 + priv->thermal_init(priv, tsc); 512 + rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1); 513 + 514 + zone = devm_thermal_of_zone_register(dev, i, tsc, &priv->ops); 521 515 if (IS_ERR(zone)) { 522 516 dev_err(dev, "Sensor %u: Can't register thermal zone\n", i); 523 517 ret = PTR_ERR(zone); 524 518 goto error_unregister; 525 519 } 526 520 tsc->zone = zone; 527 - 528 - priv->thermal_init(tsc); 529 - rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1); 530 521 531 522 tsc->zone->tzp->no_hwmon = false; 532 523 ret = thermal_add_hwmon_sysfs(tsc->zone); ··· 536 529 if (ret) 537 530 goto error_unregister; 538 531 539 - ret = of_thermal_get_ntrips(tsc->zone); 532 + ret = thermal_zone_get_num_trips(tsc->zone); 540 533 if (ret < 0) 541 534 goto error_unregister; 542 535 ··· 563 556 564 557 for (i = 0; i < priv->num_tscs; i++) { 565 558 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; 566 - struct thermal_zone_device *zone = tsc->zone; 567 559 568 - priv->thermal_init(tsc); 569 - if (zone->ops->set_trips) 570 - rcar_gen3_thermal_set_trips(zone, zone->prev_low_trip, 571 - zone->prev_high_trip); 560 + priv->thermal_init(priv, tsc); 572 561 } 573 562 574 563 return 0;
+6 -47
drivers/thermal/rcar_thermal.c
··· 278 278 return rcar_thermal_get_current_temp(priv, temp); 279 279 } 280 280 281 - static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone, 282 - int trip, enum thermal_trip_type *type) 283 - { 284 - struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); 285 - struct device *dev = rcar_priv_to_dev(priv); 286 - 287 - /* see rcar_thermal_get_temp() */ 288 - switch (trip) { 289 - case 0: /* +90 <= temp */ 290 - *type = THERMAL_TRIP_CRITICAL; 291 - break; 292 - default: 293 - dev_err(dev, "rcar driver trip error\n"); 294 - return -EINVAL; 295 - } 296 - 297 - return 0; 298 - } 299 - 300 - static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone, 301 - int trip, int *temp) 302 - { 303 - struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); 304 - struct device *dev = rcar_priv_to_dev(priv); 305 - 306 - /* see rcar_thermal_get_temp() */ 307 - switch (trip) { 308 - case 0: /* +90 <= temp */ 309 - *temp = MCELSIUS(90); 310 - break; 311 - default: 312 - dev_err(dev, "rcar driver trip error\n"); 313 - return -EINVAL; 314 - } 315 - 316 - return 0; 317 - } 318 - 319 - static const struct thermal_zone_device_ops rcar_thermal_zone_of_ops = { 281 + static struct thermal_zone_device_ops rcar_thermal_zone_ops = { 320 282 .get_temp = rcar_thermal_get_temp, 321 283 }; 322 284 323 - static struct thermal_zone_device_ops rcar_thermal_zone_ops = { 324 - .get_temp = rcar_thermal_get_temp, 325 - .get_trip_type = rcar_thermal_get_trip_type, 326 - .get_trip_temp = rcar_thermal_get_trip_temp, 285 + static struct thermal_trip trips[] = { 286 + { .type = THERMAL_TRIP_CRITICAL, .temperature = 90000 } 327 287 }; 328 288 329 289 /* ··· 489 529 if (chip->use_of_thermal) { 490 530 priv->zone = devm_thermal_of_zone_register( 491 531 dev, i, priv, 492 - &rcar_thermal_zone_of_ops); 532 + &rcar_thermal_zone_ops); 493 533 } else { 494 - priv->zone = thermal_zone_device_register( 495 - "rcar_thermal", 496 - 1, 0, priv, 534 + priv->zone = thermal_zone_device_register_with_trips( 535 + "rcar_thermal", trips, ARRAY_SIZE(trips), 0, priv, 497 536 &rcar_thermal_zone_ops, NULL, 0, 498 537 idle); 499 538
+4 -6
drivers/thermal/rockchip_thermal.c
··· 60 60 61 61 #include "thermal_hwmon.h" 62 62 63 - /** 63 + /* 64 64 * The max sensors is two in rockchip SoCs. 65 65 * Two sensors: CPU and GPU sensor. 66 66 */ ··· 169 169 enum tshut_polarity tshut_polarity; 170 170 }; 171 171 172 - /** 172 + /* 173 173 * TSADC Sensor Register description: 174 174 * 175 175 * TSADCV2_* are used for RK3288 SoCs, the other chips can reuse it. ··· 1339 1339 } 1340 1340 1341 1341 /** 1342 - * Reset TSADC Controller, reset all tsadc registers. 1342 + * rockchip_thermal_reset_controller - Reset TSADC Controller, reset all tsadc registers. 1343 1343 * @reset: the reset controller of tsadc 1344 1344 */ 1345 1345 static void rockchip_thermal_reset_controller(struct reset_control *reset) ··· 1354 1354 struct device_node *np = pdev->dev.of_node; 1355 1355 struct rockchip_thermal_data *thermal; 1356 1356 const struct of_device_id *match; 1357 - struct resource *res; 1358 1357 int irq; 1359 1358 int i; 1360 1359 int error; ··· 1377 1378 if (!thermal->chip) 1378 1379 return -EINVAL; 1379 1380 1380 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1381 - thermal->regs = devm_ioremap_resource(&pdev->dev, res); 1381 + thermal->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 1382 1382 if (IS_ERR(thermal->regs)) 1383 1383 return PTR_ERR(thermal->regs); 1384 1384
+29 -36
drivers/thermal/samsung/exynos_tmu.c
··· 20 20 #include <linux/of_irq.h> 21 21 #include <linux/platform_device.h> 22 22 #include <linux/regulator/consumer.h> 23 + #include <linux/thermal.h> 23 24 24 25 #include <dt-bindings/thermal/thermal_exynos.h> 25 - 26 - #include "../thermal_core.h" 27 26 28 27 /* Exynos generic registers */ 29 28 #define EXYNOS_TMU_REG_TRIMINFO 0x0 ··· 259 260 { 260 261 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 261 262 struct thermal_zone_device *tzd = data->tzd; 262 - const struct thermal_trip * const trips = 263 - of_thermal_get_trip_points(tzd); 263 + int num_trips = thermal_zone_get_num_trips(tzd); 264 264 unsigned int status; 265 - int ret = 0, temp, hyst; 265 + int ret = 0, temp; 266 266 267 - if (!trips) { 268 - dev_err(&pdev->dev, 269 - "Cannot get trip points from device tree!\n"); 270 - return -ENODEV; 271 - } 272 - 273 - if (data->soc != SOC_ARCH_EXYNOS5433) /* FIXME */ 274 - ret = tzd->ops->get_crit_temp(tzd, &temp); 275 - if (ret) { 267 + ret = thermal_zone_get_crit_temp(tzd, &temp); 268 + if (ret && data->soc != SOC_ARCH_EXYNOS5433) { /* FIXME */ 276 269 dev_err(&pdev->dev, 277 270 "No CRITICAL trip point defined in device tree!\n"); 278 271 goto out; 279 272 } 280 273 281 - if (of_thermal_get_ntrips(tzd) > data->ntrip) { 274 + if (num_trips > data->ntrip) { 282 275 dev_info(&pdev->dev, 283 276 "More trip points than supported by this TMU.\n"); 284 277 dev_info(&pdev->dev, 285 278 "%d trip points should be configured in polling mode.\n", 286 - (of_thermal_get_ntrips(tzd) - data->ntrip)); 279 + num_trips - data->ntrip); 287 280 } 288 281 289 282 mutex_lock(&data->lock); ··· 288 297 ret = -EBUSY; 289 298 } else { 290 299 int i, ntrips = 291 - min_t(int, of_thermal_get_ntrips(tzd), data->ntrip); 300 + min_t(int, num_trips, data->ntrip); 292 301 293 302 data->tmu_initialize(pdev); 294 303 295 304 /* Write temperature code for rising and falling threshold */ 296 305 for (i = 0; i < ntrips; i++) { 297 - /* Write temperature code for rising threshold */ 298 - ret = tzd->ops->get_trip_temp(tzd, i, &temp); 299 - if (ret) 300 - goto err; 301 - temp /= MCELSIUS; 302 - data->tmu_set_trip_temp(data, i, temp); 303 306 304 - /* Write temperature code for falling threshold */ 305 - ret = tzd->ops->get_trip_hyst(tzd, i, &hyst); 307 + struct thermal_trip trip; 308 + 309 + ret = thermal_zone_get_trip(tzd, i, &trip); 306 310 if (ret) 307 311 goto err; 308 - hyst /= MCELSIUS; 309 - data->tmu_set_trip_hyst(data, i, temp, hyst); 312 + 313 + data->tmu_set_trip_temp(data, i, trip.temperature / MCELSIUS); 314 + data->tmu_set_trip_hyst(data, i, trip.temperature / MCELSIUS, 315 + trip.hysteresis / MCELSIUS); 310 316 } 311 317 312 318 data->tmu_clear_irqs(data); ··· 348 360 } 349 361 350 362 static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data, 351 - int trip, u8 temp) 363 + int trip_id, u8 temp) 352 364 { 353 - const struct thermal_trip * const trips = 354 - of_thermal_get_trip_points(data->tzd); 365 + struct thermal_trip trip; 355 366 u8 ref, th_code; 356 367 357 - ref = trips[0].temperature / MCELSIUS; 368 + if (thermal_zone_get_trip(data->tzd, 0, &trip)) 369 + return; 358 370 359 - if (trip == 0) { 371 + ref = trip.temperature / MCELSIUS; 372 + 373 + if (trip_id == 0) { 360 374 th_code = temp_to_code(data, ref); 361 375 writeb(th_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); 362 376 } 363 377 364 378 temp -= ref; 365 - writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip * 4); 379 + writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip_id * 4); 366 380 } 367 381 368 382 /* failing thresholds are not supported on Exynos4210 */ ··· 552 562 { 553 563 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 554 564 struct thermal_zone_device *tz = data->tzd; 565 + struct thermal_trip trip; 555 566 unsigned int con, interrupt_en = 0, i; 556 567 557 568 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); 558 569 559 570 if (on) { 560 571 for (i = 0; i < data->ntrip; i++) { 561 - if (!of_thermal_is_trip_valid(tz, i)) 572 + if (thermal_zone_get_trip(tz, i, &trip)) 562 573 continue; 563 574 564 575 interrupt_en |= ··· 583 592 { 584 593 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 585 594 struct thermal_zone_device *tz = data->tzd; 595 + struct thermal_trip trip; 586 596 unsigned int con, interrupt_en = 0, pd_det_en, i; 587 597 588 598 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); 589 599 590 600 if (on) { 591 601 for (i = 0; i < data->ntrip; i++) { 592 - if (!of_thermal_is_trip_valid(tz, i)) 602 + if (thermal_zone_get_trip(tz, i, &trip)) 593 603 continue; 594 604 595 605 interrupt_en |= ··· 615 623 { 616 624 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 617 625 struct thermal_zone_device *tz = data->tzd; 626 + struct thermal_trip trip; 618 627 unsigned int con, interrupt_en = 0, i; 619 628 620 629 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); 621 630 622 631 if (on) { 623 632 for (i = 0; i < data->ntrip; i++) { 624 - if (!of_thermal_is_trip_valid(tz, i)) 633 + if (thermal_zone_get_trip(tz, i, &trip)) 625 634 continue; 626 635 627 636 interrupt_en |=
+1 -3
drivers/thermal/spear_thermal.c
··· 91 91 struct thermal_zone_device *spear_thermal = NULL; 92 92 struct spear_thermal_dev *stdev; 93 93 struct device_node *np = pdev->dev.of_node; 94 - struct resource *res; 95 94 int ret = 0, val; 96 95 97 96 if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) { ··· 103 104 return -ENOMEM; 104 105 105 106 /* Enable thermal sensor */ 106 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 107 - stdev->thermal_base = devm_ioremap_resource(&pdev->dev, res); 107 + stdev->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 108 108 if (IS_ERR(stdev->thermal_base)) 109 109 return PTR_ERR(stdev->thermal_base); 110 110
-4
drivers/thermal/st/Kconfig
··· 8 8 help 9 9 Support for thermal sensors on STMicroelectronics STi series of SoCs. 10 10 11 - config ST_THERMAL_SYSCFG 12 - select ST_THERMAL 13 - tristate "STi series syscfg register access based thermal sensors" 14 - 15 11 config ST_THERMAL_MEMMAP 16 12 select ST_THERMAL 17 13 tristate "STi series memory mapped access based thermal sensors"
-1
drivers/thermal/st/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 obj-$(CONFIG_ST_THERMAL) := st_thermal.o 3 - obj-$(CONFIG_ST_THERMAL_SYSCFG) += st_thermal_syscfg.o 4 3 obj-$(CONFIG_ST_THERMAL_MEMMAP) += st_thermal_memmap.o 5 4 obj-$(CONFIG_STM32_THERMAL) += stm_thermal.o
+7 -40
drivers/thermal/st/st_thermal.c
··· 134 134 return 0; 135 135 } 136 136 137 - static int st_thermal_get_trip_type(struct thermal_zone_device *th, 138 - int trip, enum thermal_trip_type *type) 139 - { 140 - struct st_thermal_sensor *sensor = th->devdata; 141 - struct device *dev = sensor->dev; 142 - 143 - switch (trip) { 144 - case 0: 145 - *type = THERMAL_TRIP_CRITICAL; 146 - break; 147 - default: 148 - dev_err(dev, "invalid trip point\n"); 149 - return -EINVAL; 150 - } 151 - 152 - return 0; 153 - } 154 - 155 - static int st_thermal_get_trip_temp(struct thermal_zone_device *th, 156 - int trip, int *temp) 157 - { 158 - struct st_thermal_sensor *sensor = th->devdata; 159 - struct device *dev = sensor->dev; 160 - 161 - switch (trip) { 162 - case 0: 163 - *temp = mcelsius(sensor->cdata->crit_temp); 164 - break; 165 - default: 166 - dev_err(dev, "Invalid trip point\n"); 167 - return -EINVAL; 168 - } 169 - 170 - return 0; 171 - } 172 - 173 137 static struct thermal_zone_device_ops st_tz_ops = { 174 138 .get_temp = st_thermal_get_temp, 175 - .get_trip_type = st_thermal_get_trip_type, 176 - .get_trip_temp = st_thermal_get_trip_temp, 177 139 }; 140 + 141 + static struct thermal_trip trip; 178 142 179 143 int st_thermal_register(struct platform_device *pdev, 180 144 const struct of_device_id *st_thermal_of_match) ··· 202 238 203 239 polling_delay = sensor->ops->register_enable_irq ? 0 : 1000; 204 240 241 + trip.temperature = sensor->cdata->crit_temp; 242 + trip.type = THERMAL_TRIP_CRITICAL; 243 + 205 244 sensor->thermal_dev = 206 - thermal_zone_device_register(dev_name(dev), 1, 0, sensor, 207 - &st_tz_ops, NULL, 0, polling_delay); 245 + thermal_zone_device_register_with_trips(dev_name(dev), &trip, 1, 0, sensor, 246 + &st_tz_ops, NULL, 0, polling_delay); 208 247 if (IS_ERR(sensor->thermal_dev)) { 209 248 dev_err(dev, "failed to register thermal zone device\n"); 210 249 ret = PTR_ERR(sensor->thermal_dev);
-174
drivers/thermal/st/st_thermal_syscfg.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * ST Thermal Sensor Driver for syscfg based sensors. 4 - * Author: Ajit Pal Singh <ajitpal.singh@st.com> 5 - * 6 - * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited 7 - */ 8 - 9 - #include <linux/of.h> 10 - #include <linux/module.h> 11 - #include <linux/mfd/syscon.h> 12 - 13 - #include "st_thermal.h" 14 - 15 - /* STiH415 */ 16 - #define STIH415_SYSCFG_FRONT(num) ((num - 100) * 4) 17 - #define STIH415_SAS_THSENS_CONF STIH415_SYSCFG_FRONT(178) 18 - #define STIH415_SAS_THSENS_STATUS STIH415_SYSCFG_FRONT(198) 19 - #define STIH415_SYSCFG_MPE(num) ((num - 600) * 4) 20 - #define STIH415_MPE_THSENS_CONF STIH415_SYSCFG_MPE(607) 21 - #define STIH415_MPE_THSENS_STATUS STIH415_SYSCFG_MPE(667) 22 - 23 - /* STiH416 */ 24 - #define STIH416_SYSCFG_FRONT(num) ((num - 1000) * 4) 25 - #define STIH416_SAS_THSENS_CONF STIH416_SYSCFG_FRONT(1552) 26 - #define STIH416_SAS_THSENS_STATUS1 STIH416_SYSCFG_FRONT(1554) 27 - #define STIH416_SAS_THSENS_STATUS2 STIH416_SYSCFG_FRONT(1594) 28 - 29 - /* STiD127 */ 30 - #define STID127_SYSCFG_CPU(num) ((num - 700) * 4) 31 - #define STID127_THSENS_CONF STID127_SYSCFG_CPU(743) 32 - #define STID127_THSENS_STATUS STID127_SYSCFG_CPU(767) 33 - 34 - static const struct reg_field st_415sas_regfields[MAX_REGFIELDS] = { 35 - [TEMP_PWR] = REG_FIELD(STIH415_SAS_THSENS_CONF, 9, 9), 36 - [DCORRECT] = REG_FIELD(STIH415_SAS_THSENS_CONF, 4, 8), 37 - [OVERFLOW] = REG_FIELD(STIH415_SAS_THSENS_STATUS, 8, 8), 38 - [DATA] = REG_FIELD(STIH415_SAS_THSENS_STATUS, 10, 16), 39 - }; 40 - 41 - static const struct reg_field st_415mpe_regfields[MAX_REGFIELDS] = { 42 - [TEMP_PWR] = REG_FIELD(STIH415_MPE_THSENS_CONF, 8, 8), 43 - [DCORRECT] = REG_FIELD(STIH415_MPE_THSENS_CONF, 3, 7), 44 - [OVERFLOW] = REG_FIELD(STIH415_MPE_THSENS_STATUS, 9, 9), 45 - [DATA] = REG_FIELD(STIH415_MPE_THSENS_STATUS, 11, 18), 46 - }; 47 - 48 - static const struct reg_field st_416sas_regfields[MAX_REGFIELDS] = { 49 - [TEMP_PWR] = REG_FIELD(STIH416_SAS_THSENS_CONF, 9, 9), 50 - [DCORRECT] = REG_FIELD(STIH416_SAS_THSENS_CONF, 4, 8), 51 - [OVERFLOW] = REG_FIELD(STIH416_SAS_THSENS_STATUS1, 8, 8), 52 - [DATA] = REG_FIELD(STIH416_SAS_THSENS_STATUS2, 10, 16), 53 - }; 54 - 55 - static const struct reg_field st_127_regfields[MAX_REGFIELDS] = { 56 - [TEMP_PWR] = REG_FIELD(STID127_THSENS_CONF, 7, 7), 57 - [DCORRECT] = REG_FIELD(STID127_THSENS_CONF, 2, 6), 58 - [OVERFLOW] = REG_FIELD(STID127_THSENS_STATUS, 9, 9), 59 - [DATA] = REG_FIELD(STID127_THSENS_STATUS, 11, 18), 60 - }; 61 - 62 - /* Private OPs for System Configuration Register based thermal sensors */ 63 - static int st_syscfg_power_ctrl(struct st_thermal_sensor *sensor, 64 - enum st_thermal_power_state power_state) 65 - { 66 - return regmap_field_write(sensor->pwr, power_state); 67 - } 68 - 69 - static int st_syscfg_alloc_regfields(struct st_thermal_sensor *sensor) 70 - { 71 - struct device *dev = sensor->dev; 72 - 73 - sensor->pwr = devm_regmap_field_alloc(dev, sensor->regmap, 74 - sensor->cdata->reg_fields[TEMP_PWR]); 75 - 76 - if (IS_ERR(sensor->pwr)) { 77 - dev_err(dev, "failed to alloc syscfg regfields\n"); 78 - return PTR_ERR(sensor->pwr); 79 - } 80 - 81 - return 0; 82 - } 83 - 84 - static int st_syscfg_regmap_init(struct st_thermal_sensor *sensor) 85 - { 86 - sensor->regmap = 87 - syscon_regmap_lookup_by_compatible(sensor->cdata->sys_compat); 88 - if (IS_ERR(sensor->regmap)) { 89 - dev_err(sensor->dev, "failed to find syscfg regmap\n"); 90 - return PTR_ERR(sensor->regmap); 91 - } 92 - 93 - return 0; 94 - } 95 - 96 - static const struct st_thermal_sensor_ops st_syscfg_sensor_ops = { 97 - .power_ctrl = st_syscfg_power_ctrl, 98 - .alloc_regfields = st_syscfg_alloc_regfields, 99 - .regmap_init = st_syscfg_regmap_init, 100 - }; 101 - 102 - /* Compatible device data for stih415 sas thermal sensor */ 103 - static const struct st_thermal_compat_data st_415sas_cdata = { 104 - .sys_compat = "st,stih415-front-syscfg", 105 - .reg_fields = st_415sas_regfields, 106 - .ops = &st_syscfg_sensor_ops, 107 - .calibration_val = 16, 108 - .temp_adjust_val = 20, 109 - .crit_temp = 120, 110 - }; 111 - 112 - /* Compatible device data for stih415 mpe thermal sensor */ 113 - static const struct st_thermal_compat_data st_415mpe_cdata = { 114 - .sys_compat = "st,stih415-system-syscfg", 115 - .reg_fields = st_415mpe_regfields, 116 - .ops = &st_syscfg_sensor_ops, 117 - .calibration_val = 16, 118 - .temp_adjust_val = -103, 119 - .crit_temp = 120, 120 - }; 121 - 122 - /* Compatible device data for stih416 sas thermal sensor */ 123 - static const struct st_thermal_compat_data st_416sas_cdata = { 124 - .sys_compat = "st,stih416-front-syscfg", 125 - .reg_fields = st_416sas_regfields, 126 - .ops = &st_syscfg_sensor_ops, 127 - .calibration_val = 16, 128 - .temp_adjust_val = 20, 129 - .crit_temp = 120, 130 - }; 131 - 132 - /* Compatible device data for stid127 thermal sensor */ 133 - static const struct st_thermal_compat_data st_127_cdata = { 134 - .sys_compat = "st,stid127-cpu-syscfg", 135 - .reg_fields = st_127_regfields, 136 - .ops = &st_syscfg_sensor_ops, 137 - .calibration_val = 8, 138 - .temp_adjust_val = -103, 139 - .crit_temp = 120, 140 - }; 141 - 142 - static const struct of_device_id st_syscfg_thermal_of_match[] = { 143 - { .compatible = "st,stih415-sas-thermal", .data = &st_415sas_cdata }, 144 - { .compatible = "st,stih415-mpe-thermal", .data = &st_415mpe_cdata }, 145 - { .compatible = "st,stih416-sas-thermal", .data = &st_416sas_cdata }, 146 - { .compatible = "st,stid127-thermal", .data = &st_127_cdata }, 147 - { /* sentinel */ } 148 - }; 149 - MODULE_DEVICE_TABLE(of, st_syscfg_thermal_of_match); 150 - 151 - static int st_syscfg_probe(struct platform_device *pdev) 152 - { 153 - return st_thermal_register(pdev, st_syscfg_thermal_of_match); 154 - } 155 - 156 - static int st_syscfg_remove(struct platform_device *pdev) 157 - { 158 - return st_thermal_unregister(pdev); 159 - } 160 - 161 - static struct platform_driver st_syscfg_thermal_driver = { 162 - .driver = { 163 - .name = "st_syscfg_thermal", 164 - .pm = &st_thermal_pm_ops, 165 - .of_match_table = st_syscfg_thermal_of_match, 166 - }, 167 - .probe = st_syscfg_probe, 168 - .remove = st_syscfg_remove, 169 - }; 170 - module_platform_driver(st_syscfg_thermal_driver); 171 - 172 - MODULE_AUTHOR("STMicroelectronics (R&D) Limited <ajitpal.singh@st.com>"); 173 - MODULE_DESCRIPTION("STMicroelectronics STi SoC Thermal Sensor Driver"); 174 - MODULE_LICENSE("GPL v2");
-1
drivers/thermal/st/stm_thermal.c
··· 19 19 #include <linux/platform_device.h> 20 20 #include <linux/thermal.h> 21 21 22 - #include "../thermal_core.h" 23 22 #include "../thermal_hwmon.h" 24 23 25 24 /* DTS register offsets */
+2 -2
drivers/thermal/sun8i_thermal.c
··· 210 210 211 211 regmap_update_bits(tmdev->regmap, 212 212 SUN8I_THS_TEMP_CALIB + (4 * (i >> 1)), 213 - 0xfff << offset, 213 + TEMP_CALIB_MASK << offset, 214 214 caldata[i] << offset); 215 215 } 216 216 ··· 271 271 offset = (i % 2) * 16; 272 272 regmap_update_bits(tmdev->regmap, 273 273 SUN50I_H6_THS_TEMP_CALIB + (i / 2 * 4), 274 - 0xfff << offset, 274 + TEMP_CALIB_MASK << offset, 275 275 cdata << offset); 276 276 } 277 277
+15 -20
drivers/thermal/tegra/soctherm.c
··· 582 582 return temp; 583 583 } 584 584 585 - static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip, int temp) 585 + static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip_id, int temp) 586 586 { 587 587 struct tegra_thermctl_zone *zone = tz->devdata; 588 588 struct tegra_soctherm *ts = zone->ts; 589 + struct thermal_trip trip; 589 590 const struct tegra_tsensor_group *sg = zone->sg; 590 591 struct device *dev = zone->dev; 591 - enum thermal_trip_type type; 592 592 int ret; 593 593 594 594 if (!tz) 595 595 return -EINVAL; 596 596 597 - ret = tz->ops->get_trip_type(tz, trip, &type); 597 + ret = __thermal_zone_get_trip(tz, trip_id, &trip); 598 598 if (ret) 599 599 return ret; 600 600 601 - if (type == THERMAL_TRIP_CRITICAL) { 601 + if (trip.type == THERMAL_TRIP_CRITICAL) { 602 602 /* 603 603 * If thermtrips property is set in DT, 604 604 * doesn't need to program critical type trip to HW, ··· 609 609 else 610 610 return 0; 611 611 612 - } else if (type == THERMAL_TRIP_HOT) { 612 + } else if (trip.type == THERMAL_TRIP_HOT) { 613 613 int i; 614 614 615 615 for (i = 0; i < THROTTLE_SIZE; i++) { ··· 620 620 continue; 621 621 622 622 cdev = ts->throt_cfgs[i].cdev; 623 - if (get_thermal_instance(tz, cdev, trip)) 623 + if (get_thermal_instance(tz, cdev, trip_id)) 624 624 stc = find_throttle_cfg_by_name(ts, cdev->type); 625 625 else 626 626 continue; ··· 687 687 .set_trips = tegra_thermctl_set_trips, 688 688 }; 689 689 690 - static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp) 690 + static int get_hot_temp(struct thermal_zone_device *tz, int *trip_id, int *temp) 691 691 { 692 - int ntrips, i, ret; 693 - enum thermal_trip_type type; 692 + int i, ret; 693 + struct thermal_trip trip; 694 694 695 - ntrips = of_thermal_get_ntrips(tz); 696 - if (ntrips <= 0) 697 - return -EINVAL; 695 + for (i = 0; i < thermal_zone_get_num_trips(tz); i++) { 698 696 699 - for (i = 0; i < ntrips; i++) { 700 - ret = tz->ops->get_trip_type(tz, i, &type); 697 + ret = thermal_zone_get_trip(tz, i, &trip); 701 698 if (ret) 702 699 return -EINVAL; 703 - if (type == THERMAL_TRIP_HOT) { 704 - ret = tz->ops->get_trip_temp(tz, i, temp); 705 - if (!ret) 706 - *trip = i; 707 700 708 - return ret; 701 + if (trip.type == THERMAL_TRIP_HOT) { 702 + *trip_id = i; 703 + return 0; 709 704 } 710 705 } 711 706 ··· 742 747 /* Get thermtrips. If missing, try to get critical trips. */ 743 748 temperature = tsensor_group_thermtrip_get(ts, sg->id); 744 749 if (min_low_temp == temperature) 745 - if (tz->ops->get_crit_temp(tz, &temperature)) 750 + if (thermal_zone_get_crit_temp(tz, &temperature)) 746 751 temperature = max_high_temp; 747 752 748 753 ret = thermtrip_program(dev, sg, temperature);
+8 -10
drivers/thermal/tegra/tegra30-tsensor.c
··· 28 28 29 29 #include <soc/tegra/fuse.h> 30 30 31 - #include "../thermal_core.h" 32 31 #include "../thermal_hwmon.h" 33 32 34 33 #define TSENSOR_SENSOR0_CONFIG0 0x0 ··· 315 316 *hot_trip = 85000; 316 317 *crit_trip = 90000; 317 318 318 - for (i = 0; i < tzd->num_trips; i++) { 319 - enum thermal_trip_type type; 320 - int trip_temp; 319 + for (i = 0; i < thermal_zone_get_num_trips(tzd); i++) { 321 320 322 - tzd->ops->get_trip_temp(tzd, i, &trip_temp); 323 - tzd->ops->get_trip_type(tzd, i, &type); 321 + struct thermal_trip trip; 324 322 325 - if (type == THERMAL_TRIP_HOT) 326 - *hot_trip = trip_temp; 323 + thermal_zone_get_trip(tzd, i, &trip); 327 324 328 - if (type == THERMAL_TRIP_CRITICAL) 329 - *crit_trip = trip_temp; 325 + if (trip.type == THERMAL_TRIP_HOT) 326 + *hot_trip = trip.temperature; 327 + 328 + if (trip.type == THERMAL_TRIP_CRITICAL) 329 + *crit_trip = trip.temperature; 330 330 } 331 331 332 332 /* clamp hardware trips to the calibration limits */
+117
drivers/thermal/thermal_acpi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2023 Linaro Limited 4 + * Copyright 2023 Intel Corporation 5 + * 6 + * Library routines for populating a generic thermal trip point structure 7 + * with data obtained by evaluating a specific object in the ACPI Namespace. 8 + */ 9 + #include <linux/acpi.h> 10 + #include <linux/units.h> 11 + 12 + #include "thermal_core.h" 13 + 14 + /* 15 + * Minimum temperature for full military grade is 218°K (-55°C) and 16 + * max temperature is 448°K (175°C). We can consider those values as 17 + * the boundaries for the [trips] temperature returned by the 18 + * firmware. Any values out of these boundaries may be considered 19 + * bogus and we can assume the firmware has no data to provide. 20 + */ 21 + #define TEMP_MIN_DECIK 2180 22 + #define TEMP_MAX_DECIK 4480 23 + 24 + static int thermal_acpi_trip_temp(struct acpi_device *adev, char *obj_name, 25 + int *ret_temp) 26 + { 27 + unsigned long long temp; 28 + acpi_status status; 29 + 30 + status = acpi_evaluate_integer(adev->handle, obj_name, NULL, &temp); 31 + if (ACPI_FAILURE(status)) { 32 + acpi_handle_debug(adev->handle, "%s evaluation failed\n", obj_name); 33 + return -ENODATA; 34 + } 35 + 36 + if (temp >= TEMP_MIN_DECIK && temp <= TEMP_MAX_DECIK) { 37 + *ret_temp = deci_kelvin_to_millicelsius(temp); 38 + } else { 39 + acpi_handle_debug(adev->handle, "%s result %llu out of range\n", 40 + obj_name, temp); 41 + *ret_temp = THERMAL_TEMP_INVALID; 42 + } 43 + 44 + return 0; 45 + } 46 + 47 + /** 48 + * thermal_acpi_active_trip_temp - Retrieve active trip point temperature 49 + * @adev: Target thermal zone ACPI device object. 50 + * @id: Active cooling level (0 - 9). 51 + * @ret_temp: Address to store the retrieved temperature value on success. 52 + * 53 + * Evaluate the _ACx object for the thermal zone represented by @adev to obtain 54 + * the temperature of the active cooling trip point corresponding to the active 55 + * cooling level given by @id. 56 + * 57 + * Return 0 on success or a negative error value on failure. 58 + */ 59 + int thermal_acpi_active_trip_temp(struct acpi_device *adev, int id, int *ret_temp) 60 + { 61 + char obj_name[] = {'_', 'A', 'C', '0' + id, '\0'}; 62 + 63 + if (id < 0 || id > 9) 64 + return -EINVAL; 65 + 66 + return thermal_acpi_trip_temp(adev, obj_name, ret_temp); 67 + } 68 + EXPORT_SYMBOL_GPL(thermal_acpi_active_trip_temp); 69 + 70 + /** 71 + * thermal_acpi_passive_trip_temp - Retrieve passive trip point temperature 72 + * @adev: Target thermal zone ACPI device object. 73 + * @ret_temp: Address to store the retrieved temperature value on success. 74 + * 75 + * Evaluate the _PSV object for the thermal zone represented by @adev to obtain 76 + * the temperature of the passive cooling trip point. 77 + * 78 + * Return 0 on success or -ENODATA on failure. 79 + */ 80 + int thermal_acpi_passive_trip_temp(struct acpi_device *adev, int *ret_temp) 81 + { 82 + return thermal_acpi_trip_temp(adev, "_PSV", ret_temp); 83 + } 84 + EXPORT_SYMBOL_GPL(thermal_acpi_passive_trip_temp); 85 + 86 + /** 87 + * thermal_acpi_hot_trip_temp - Retrieve hot trip point temperature 88 + * @adev: Target thermal zone ACPI device object. 89 + * @ret_temp: Address to store the retrieved temperature value on success. 90 + * 91 + * Evaluate the _HOT object for the thermal zone represented by @adev to obtain 92 + * the temperature of the trip point at which the system is expected to be put 93 + * into the S4 sleep state. 94 + * 95 + * Return 0 on success or -ENODATA on failure. 96 + */ 97 + int thermal_acpi_hot_trip_temp(struct acpi_device *adev, int *ret_temp) 98 + { 99 + return thermal_acpi_trip_temp(adev, "_HOT", ret_temp); 100 + } 101 + EXPORT_SYMBOL_GPL(thermal_acpi_hot_trip_temp); 102 + 103 + /** 104 + * thermal_acpi_critical_trip_temp - Retrieve critical trip point temperature 105 + * @adev: Target thermal zone ACPI device object. 106 + * @ret_temp: Address to store the retrieved temperature value on success. 107 + * 108 + * Evaluate the _CRT object for the thermal zone represented by @adev to obtain 109 + * the temperature of the critical cooling trip point. 110 + * 111 + * Return 0 on success or -ENODATA on failure. 112 + */ 113 + int thermal_acpi_critical_trip_temp(struct acpi_device *adev, int *ret_temp) 114 + { 115 + return thermal_acpi_trip_temp(adev, "_CRT", ret_temp); 116 + } 117 + EXPORT_SYMBOL_GPL(thermal_acpi_critical_trip_temp);
+87 -58
drivers/thermal/thermal_core.c
··· 229 229 mutex_lock(&thermal_governor_lock); 230 230 231 231 list_for_each_entry(pos, &thermal_governor_list, governor_list) { 232 - count += scnprintf(buf + count, PAGE_SIZE - count, "%s ", 233 - pos->name); 232 + count += sysfs_emit_at(buf, count, "%s ", pos->name); 234 233 } 235 - count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); 234 + count += sysfs_emit_at(buf, count, "\n"); 236 235 237 236 mutex_unlock(&thermal_governor_lock); 238 237 ··· 343 344 tz->ops->critical(tz); 344 345 } 345 346 346 - static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) 347 + static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id) 347 348 { 348 - enum thermal_trip_type type; 349 - int trip_temp, hyst = 0; 349 + struct thermal_trip trip; 350 350 351 351 /* Ignore disabled trip points */ 352 - if (test_bit(trip, &tz->trips_disabled)) 352 + if (test_bit(trip_id, &tz->trips_disabled)) 353 353 return; 354 354 355 - tz->ops->get_trip_temp(tz, trip, &trip_temp); 356 - tz->ops->get_trip_type(tz, trip, &type); 357 - if (tz->ops->get_trip_hyst) 358 - tz->ops->get_trip_hyst(tz, trip, &hyst); 355 + __thermal_zone_get_trip(tz, trip_id, &trip); 359 356 360 357 if (tz->last_temperature != THERMAL_TEMP_INVALID) { 361 - if (tz->last_temperature < trip_temp && 362 - tz->temperature >= trip_temp) 363 - thermal_notify_tz_trip_up(tz->id, trip, 358 + if (tz->last_temperature < trip.temperature && 359 + tz->temperature >= trip.temperature) 360 + thermal_notify_tz_trip_up(tz->id, trip_id, 364 361 tz->temperature); 365 - if (tz->last_temperature >= trip_temp && 366 - tz->temperature < (trip_temp - hyst)) 367 - thermal_notify_tz_trip_down(tz->id, trip, 362 + if (tz->last_temperature >= trip.temperature && 363 + tz->temperature < (trip.temperature - trip.hysteresis)) 364 + thermal_notify_tz_trip_down(tz->id, trip_id, 368 365 tz->temperature); 369 366 } 370 367 371 - if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) 372 - handle_critical_trips(tz, trip, trip_temp, type); 368 + if (trip.type == THERMAL_TRIP_CRITICAL || trip.type == THERMAL_TRIP_HOT) 369 + handle_critical_trips(tz, trip_id, trip.temperature, trip.type); 373 370 else 374 - handle_non_critical_trips(tz, trip); 371 + handle_non_critical_trips(tz, trip_id); 375 372 } 376 373 377 374 static void update_temperature(struct thermal_zone_device *tz) ··· 769 774 } else if (!strncmp(dev_name(dev), "cooling_device", 770 775 sizeof("cooling_device") - 1)) { 771 776 cdev = to_cooling_device(dev); 777 + thermal_cooling_device_destroy_sysfs(cdev); 778 + kfree(cdev->type); 779 + ida_free(&thermal_cdev_ida, cdev->id); 772 780 kfree(cdev); 773 781 } 774 782 } 775 783 776 - static struct class thermal_class = { 777 - .name = "thermal", 778 - .dev_release = thermal_release, 779 - }; 784 + static struct class *thermal_class; 780 785 781 786 static inline 782 787 void print_bind_err_msg(struct thermal_zone_device *tz, ··· 879 884 !ops->set_cur_state) 880 885 return ERR_PTR(-EINVAL); 881 886 887 + if (!thermal_class) 888 + return ERR_PTR(-ENODEV); 889 + 882 890 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 883 891 if (!cdev) 884 892 return ERR_PTR(-ENOMEM); ··· 903 905 cdev->np = np; 904 906 cdev->ops = ops; 905 907 cdev->updated = false; 906 - cdev->device.class = &thermal_class; 908 + cdev->device.class = thermal_class; 907 909 cdev->devdata = devdata; 908 910 909 911 ret = cdev->ops->get_max_state(cdev, &cdev->max_state); 910 - if (ret) { 911 - kfree(cdev->type); 912 - goto out_ida_remove; 913 - } 912 + if (ret) 913 + goto out_cdev_type; 914 914 915 915 thermal_cooling_device_setup_sysfs(cdev); 916 916 917 917 ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); 918 - if (ret) { 919 - kfree(cdev->type); 920 - thermal_cooling_device_destroy_sysfs(cdev); 921 - goto out_ida_remove; 922 - } 918 + if (ret) 919 + goto out_cooling_dev; 923 920 924 921 ret = device_register(&cdev->device); 925 - if (ret) 926 - goto out_kfree_type; 922 + if (ret) { 923 + /* thermal_release() handles rest of the cleanup */ 924 + put_device(&cdev->device); 925 + return ERR_PTR(ret); 926 + } 927 927 928 928 /* Add 'this' new cdev to the global cdev list */ 929 929 mutex_lock(&thermal_list_lock); ··· 940 944 941 945 return cdev; 942 946 943 - out_kfree_type: 947 + out_cooling_dev: 944 948 thermal_cooling_device_destroy_sysfs(cdev); 949 + out_cdev_type: 945 950 kfree(cdev->type); 946 - put_device(&cdev->device); 947 - 948 - /* thermal_release() takes care of the rest */ 949 - cdev = NULL; 950 951 out_ida_remove: 951 952 ida_free(&thermal_cdev_ida, id); 952 953 out_kfree_cdev: ··· 1104 1111 1105 1112 mutex_unlock(&thermal_list_lock); 1106 1113 1107 - ida_free(&thermal_cdev_ida, cdev->id); 1108 - device_del(&cdev->device); 1109 - thermal_cooling_device_destroy_sysfs(cdev); 1110 - kfree(cdev->type); 1111 - put_device(&cdev->device); 1114 + device_unregister(&cdev->device); 1112 1115 } 1113 1116 EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister); 1114 1117 ··· 1155 1166 *delay_jiffies = round_jiffies(*delay_jiffies); 1156 1167 } 1157 1168 1169 + int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp) 1170 + { 1171 + int i, ret = -EINVAL; 1172 + 1173 + if (tz->ops->get_crit_temp) 1174 + return tz->ops->get_crit_temp(tz, temp); 1175 + 1176 + if (!tz->trips) 1177 + return -EINVAL; 1178 + 1179 + mutex_lock(&tz->lock); 1180 + 1181 + for (i = 0; i < tz->num_trips; i++) { 1182 + if (tz->trips[i].type == THERMAL_TRIP_CRITICAL) { 1183 + *temp = tz->trips[i].temperature; 1184 + ret = 0; 1185 + break; 1186 + } 1187 + } 1188 + 1189 + mutex_unlock(&tz->lock); 1190 + 1191 + return ret; 1192 + } 1193 + EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp); 1194 + 1158 1195 /** 1159 1196 * thermal_zone_device_register_with_trips() - register a new thermal zone device 1160 1197 * @type: the thermal zone device type ··· 1213 1198 int polling_delay) 1214 1199 { 1215 1200 struct thermal_zone_device *tz; 1216 - enum thermal_trip_type trip_type; 1217 - int trip_temp; 1218 1201 int id; 1219 1202 int result; 1220 1203 int count; ··· 1252 1239 return ERR_PTR(-EINVAL); 1253 1240 } 1254 1241 1255 - if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp)) 1242 + if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp) && !trips) 1256 1243 return ERR_PTR(-EINVAL); 1244 + 1245 + if (!thermal_class) 1246 + return ERR_PTR(-ENODEV); 1257 1247 1258 1248 tz = kzalloc(sizeof(*tz), GFP_KERNEL); 1259 1249 if (!tz) ··· 1279 1263 1280 1264 tz->ops = ops; 1281 1265 tz->tzp = tzp; 1282 - tz->device.class = &thermal_class; 1266 + tz->device.class = thermal_class; 1283 1267 tz->devdata = devdata; 1284 1268 tz->trips = trips; 1285 1269 tz->num_trips = num_trips; ··· 1306 1290 goto release_device; 1307 1291 1308 1292 for (count = 0; count < num_trips; count++) { 1309 - if (tz->ops->get_trip_type(tz, count, &trip_type) || 1310 - tz->ops->get_trip_temp(tz, count, &trip_temp) || 1311 - !trip_temp) 1293 + struct thermal_trip trip; 1294 + 1295 + result = thermal_zone_get_trip(tz, count, &trip); 1296 + if (result) 1312 1297 set_bit(count, &tz->trips_disabled); 1313 1298 } 1314 1299 ··· 1522 1505 1523 1506 result = thermal_register_governors(); 1524 1507 if (result) 1525 - goto error; 1508 + goto unregister_netlink; 1526 1509 1527 - result = class_register(&thermal_class); 1528 - if (result) 1510 + thermal_class = kzalloc(sizeof(*thermal_class), GFP_KERNEL); 1511 + if (!thermal_class) { 1512 + result = -ENOMEM; 1529 1513 goto unregister_governors; 1514 + } 1515 + 1516 + thermal_class->name = "thermal"; 1517 + thermal_class->dev_release = thermal_release; 1518 + 1519 + result = class_register(thermal_class); 1520 + if (result) { 1521 + kfree(thermal_class); 1522 + thermal_class = NULL; 1523 + goto unregister_governors; 1524 + } 1530 1525 1531 1526 result = register_pm_notifier(&thermal_pm_nb); 1532 1527 if (result) ··· 1549 1520 1550 1521 unregister_governors: 1551 1522 thermal_unregister_governors(); 1523 + unregister_netlink: 1524 + thermal_netlink_exit(); 1552 1525 error: 1553 - ida_destroy(&thermal_tz_ida); 1554 - ida_destroy(&thermal_cdev_ida); 1555 1526 mutex_destroy(&thermal_list_lock); 1556 1527 mutex_destroy(&thermal_governor_lock); 1557 1528 return result;
+6 -22
drivers/thermal/thermal_core.h
··· 52 52 int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), 53 53 void *thermal_governor); 54 54 55 + int __for_each_thermal_trip(struct thermal_zone_device *, 56 + int (*cb)(struct thermal_trip *, void *), 57 + void *); 58 + 55 59 struct thermal_zone_device *thermal_zone_get_by_id(int id); 56 60 57 61 struct thermal_attr { ··· 118 114 119 115 /* Helpers */ 120 116 void __thermal_zone_set_trips(struct thermal_zone_device *tz); 117 + int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, 118 + struct thermal_trip *trip); 121 119 int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); 122 120 123 121 /* sysfs I/F */ ··· 143 137 #endif /* CONFIG_THERMAL_STATISTICS */ 144 138 145 139 /* device tree support */ 146 - #ifdef CONFIG_THERMAL_OF 147 - int of_thermal_get_ntrips(struct thermal_zone_device *); 148 - bool of_thermal_is_trip_valid(struct thermal_zone_device *, int); 149 - const struct thermal_trip * 150 - of_thermal_get_trip_points(struct thermal_zone_device *); 151 - #else 152 - static inline int of_thermal_get_ntrips(struct thermal_zone_device *tz) 153 - { 154 - return 0; 155 - } 156 - static inline bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, 157 - int trip) 158 - { 159 - return false; 160 - } 161 - static inline const struct thermal_trip * 162 - of_thermal_get_trip_points(struct thermal_zone_device *tz) 163 - { 164 - return NULL; 165 - } 166 - #endif 167 - 168 140 int thermal_zone_device_is_enabled(struct thermal_zone_device *tz); 169 141 170 142 #endif /* __THERMAL_CORE_H__ */
+4 -66
drivers/thermal/thermal_helpers.c
··· 83 83 int ret = -EINVAL; 84 84 int count; 85 85 int crit_temp = INT_MAX; 86 - enum thermal_trip_type type; 86 + struct thermal_trip trip; 87 87 88 88 lockdep_assert_held(&tz->lock); 89 89 ··· 91 91 92 92 if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) { 93 93 for (count = 0; count < tz->num_trips; count++) { 94 - ret = tz->ops->get_trip_type(tz, count, &type); 95 - if (!ret && type == THERMAL_TRIP_CRITICAL) { 96 - ret = tz->ops->get_trip_temp(tz, count, 97 - &crit_temp); 94 + ret = __thermal_zone_get_trip(tz, count, &trip); 95 + if (!ret && trip.type == THERMAL_TRIP_CRITICAL) { 96 + crit_temp = trip.temperature; 98 97 break; 99 98 } 100 99 } ··· 145 146 return ret; 146 147 } 147 148 EXPORT_SYMBOL_GPL(thermal_zone_get_temp); 148 - 149 - /** 150 - * __thermal_zone_set_trips - Computes the next trip points for the driver 151 - * @tz: a pointer to a thermal zone device structure 152 - * 153 - * The function computes the next temperature boundaries by browsing 154 - * the trip points. The result is the closer low and high trip points 155 - * to the current temperature. These values are passed to the backend 156 - * driver to let it set its own notification mechanism (usually an 157 - * interrupt). 158 - * 159 - * This function must be called with tz->lock held. Both tz and tz->ops 160 - * must be valid pointers. 161 - * 162 - * It does not return a value 163 - */ 164 - void __thermal_zone_set_trips(struct thermal_zone_device *tz) 165 - { 166 - int low = -INT_MAX; 167 - int high = INT_MAX; 168 - int trip_temp, hysteresis; 169 - int i, ret; 170 - 171 - lockdep_assert_held(&tz->lock); 172 - 173 - if (!tz->ops->set_trips || !tz->ops->get_trip_hyst) 174 - return; 175 - 176 - for (i = 0; i < tz->num_trips; i++) { 177 - int trip_low; 178 - 179 - tz->ops->get_trip_temp(tz, i, &trip_temp); 180 - tz->ops->get_trip_hyst(tz, i, &hysteresis); 181 - 182 - trip_low = trip_temp - hysteresis; 183 - 184 - if (trip_low < tz->temperature && trip_low > low) 185 - low = trip_low; 186 - 187 - if (trip_temp > tz->temperature && trip_temp < high) 188 - high = trip_temp; 189 - } 190 - 191 - /* No need to change trip points */ 192 - if (tz->prev_low_trip == low && tz->prev_high_trip == high) 193 - return; 194 - 195 - tz->prev_low_trip = low; 196 - tz->prev_high_trip = high; 197 - 198 - dev_dbg(&tz->device, 199 - "new temperature boundaries: %d < x < %d\n", low, high); 200 - 201 - /* 202 - * Set a temperature window. When this window is left the driver 203 - * must inform the thermal core via thermal_zone_device_update. 204 - */ 205 - ret = tz->ops->set_trips(tz, low, high); 206 - if (ret) 207 - dev_err(&tz->device, "Failed to set trips: %d\n", ret); 208 - } 209 149 210 150 static void thermal_cdev_set_cur_state(struct thermal_cooling_device *cdev, 211 151 int target)
+1 -3
drivers/thermal/thermal_mmio.c
··· 39 39 40 40 static int thermal_mmio_probe(struct platform_device *pdev) 41 41 { 42 - struct resource *resource; 43 42 struct thermal_mmio *sensor; 44 43 int (*sensor_init_func)(struct platform_device *pdev, 45 44 struct thermal_mmio *sensor); ··· 50 51 if (!sensor) 51 52 return -ENOMEM; 52 53 53 - resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); 54 - sensor->mmio_base = devm_ioremap_resource(&pdev->dev, resource); 54 + sensor->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 55 55 if (IS_ERR(sensor->mmio_base)) 56 56 return PTR_ERR(sensor->mmio_base); 57 57
+13 -11
drivers/thermal/thermal_netlink.c
··· 452 452 struct sk_buff *msg = p->msg; 453 453 struct thermal_zone_device *tz; 454 454 struct nlattr *start_trip; 455 - int i, id; 455 + struct thermal_trip trip; 456 + int ret, i, id; 456 457 457 458 if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) 458 459 return -EINVAL; ··· 472 471 473 472 for (i = 0; i < tz->num_trips; i++) { 474 473 475 - enum thermal_trip_type type; 476 - int temp, hyst = 0; 477 - 478 - tz->ops->get_trip_type(tz, i, &type); 479 - tz->ops->get_trip_temp(tz, i, &temp); 480 - if (tz->ops->get_trip_hyst) 481 - tz->ops->get_trip_hyst(tz, i, &hyst); 474 + ret = __thermal_zone_get_trip(tz, i, &trip); 475 + if (ret) 476 + goto out_cancel_nest; 482 477 483 478 if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, i) || 484 - nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, type) || 485 - nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, temp) || 486 - nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, hyst)) 479 + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, trip.type) || 480 + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, trip.temperature) || 481 + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, trip.hysteresis)) 487 482 goto out_cancel_nest; 488 483 } 489 484 ··· 698 701 int __init thermal_netlink_init(void) 699 702 { 700 703 return genl_register_family(&thermal_gnl_family); 704 + } 705 + 706 + void __init thermal_netlink_exit(void) 707 + { 708 + genl_unregister_family(&thermal_gnl_family); 701 709 }
+3
drivers/thermal/thermal_netlink.h
··· 13 13 /* Netlink notification function */ 14 14 #ifdef CONFIG_THERMAL_NETLINK 15 15 int __init thermal_netlink_init(void); 16 + void __init thermal_netlink_exit(void); 16 17 int thermal_notify_tz_create(int tz_id, const char *name); 17 18 int thermal_notify_tz_delete(int tz_id); 18 19 int thermal_notify_tz_enable(int tz_id); ··· 115 114 { 116 115 return 0; 117 116 } 117 + 118 + static inline void __init thermal_netlink_exit(void) {} 118 119 119 120 #endif /* CONFIG_THERMAL_NETLINK */
-116
drivers/thermal/thermal_of.c
··· 19 19 20 20 #include "thermal_core.h" 21 21 22 - /** 23 - * of_thermal_get_ntrips - function to export number of available trip 24 - * points. 25 - * @tz: pointer to a thermal zone 26 - * 27 - * This function is a globally visible wrapper to get number of trip points 28 - * stored in the local struct __thermal_zone 29 - * 30 - * Return: number of available trip points, -ENODEV when data not available 31 - */ 32 - int of_thermal_get_ntrips(struct thermal_zone_device *tz) 33 - { 34 - return tz->num_trips; 35 - } 36 - EXPORT_SYMBOL_GPL(of_thermal_get_ntrips); 37 - 38 - /** 39 - * of_thermal_is_trip_valid - function to check if trip point is valid 40 - * 41 - * @tz: pointer to a thermal zone 42 - * @trip: trip point to evaluate 43 - * 44 - * This function is responsible for checking if passed trip point is valid 45 - * 46 - * Return: true if trip point is valid, false otherwise 47 - */ 48 - bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, int trip) 49 - { 50 - if (trip >= tz->num_trips || trip < 0) 51 - return false; 52 - 53 - return true; 54 - } 55 - EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid); 56 - 57 - /** 58 - * of_thermal_get_trip_points - function to get access to a globally exported 59 - * trip points 60 - * 61 - * @tz: pointer to a thermal zone 62 - * 63 - * This function provides a pointer to trip points table 64 - * 65 - * Return: pointer to trip points table, NULL otherwise 66 - */ 67 - const struct thermal_trip * 68 - of_thermal_get_trip_points(struct thermal_zone_device *tz) 69 - { 70 - return tz->trips; 71 - } 72 - EXPORT_SYMBOL_GPL(of_thermal_get_trip_points); 73 - 74 - static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip, 75 - enum thermal_trip_type *type) 76 - { 77 - if (trip >= tz->num_trips || trip < 0) 78 - return -EDOM; 79 - 80 - *type = tz->trips[trip].type; 81 - 82 - return 0; 83 - } 84 - 85 - static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip, 86 - int *temp) 87 - { 88 - if (trip >= tz->num_trips || trip < 0) 89 - return -EDOM; 90 - 91 - *temp = tz->trips[trip].temperature; 92 - 93 - return 0; 94 - } 95 - 96 - static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip, 97 - int *hyst) 98 - { 99 - if (trip >= tz->num_trips || trip < 0) 100 - return -EDOM; 101 - 102 - *hyst = tz->trips[trip].hysteresis; 103 - 104 - return 0; 105 - } 106 - 107 - static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip, 108 - int hyst) 109 - { 110 - if (trip >= tz->num_trips || trip < 0) 111 - return -EDOM; 112 - 113 - /* thermal framework should take care of data->mask & (1 << trip) */ 114 - tz->trips[trip].hysteresis = hyst; 115 - 116 - return 0; 117 - } 118 - 119 - static int of_thermal_get_crit_temp(struct thermal_zone_device *tz, 120 - int *temp) 121 - { 122 - int i; 123 - 124 - for (i = 0; i < tz->num_trips; i++) 125 - if (tz->trips[i].type == THERMAL_TRIP_CRITICAL) { 126 - *temp = tz->trips[i].temperature; 127 - return 0; 128 - } 129 - 130 - return -EINVAL; 131 - } 132 - 133 22 /*** functions parsing device tree nodes ***/ 134 23 135 24 static int of_find_trip_id(struct device_node *np, struct device_node *trip) ··· 517 628 goto out_kfree_trips; 518 629 } 519 630 520 - of_ops->get_trip_type = of_ops->get_trip_type ? : of_thermal_get_trip_type; 521 - of_ops->get_trip_temp = of_ops->get_trip_temp ? : of_thermal_get_trip_temp; 522 - of_ops->get_trip_hyst = of_ops->get_trip_hyst ? : of_thermal_get_trip_hyst; 523 - of_ops->set_trip_hyst = of_ops->set_trip_hyst ? : of_thermal_set_trip_hyst; 524 - of_ops->get_crit_temp = of_ops->get_crit_temp ? : of_thermal_get_crit_temp; 525 631 of_ops->bind = thermal_of_bind; 526 632 of_ops->unbind = thermal_of_unbind; 527 633
+44 -91
drivers/thermal/thermal_sysfs.c
··· 83 83 char *buf) 84 84 { 85 85 struct thermal_zone_device *tz = to_thermal_zone(dev); 86 - enum thermal_trip_type type; 87 - int trip, result; 86 + struct thermal_trip trip; 87 + int trip_id, result; 88 88 89 - if (!tz->ops->get_trip_type) 90 - return -EPERM; 91 - 92 - if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1) 89 + if (sscanf(attr->attr.name, "trip_point_%d_type", &trip_id) != 1) 93 90 return -EINVAL; 94 91 95 92 mutex_lock(&tz->lock); 96 93 97 94 if (device_is_registered(dev)) 98 - result = tz->ops->get_trip_type(tz, trip, &type); 95 + result = __thermal_zone_get_trip(tz, trip_id, &trip); 99 96 else 100 97 result = -ENODEV; 101 98 102 99 mutex_unlock(&tz->lock); 100 + 103 101 if (result) 104 102 return result; 105 103 106 - switch (type) { 104 + switch (trip.type) { 107 105 case THERMAL_TRIP_CRITICAL: 108 106 return sprintf(buf, "critical\n"); 109 107 case THERMAL_TRIP_HOT: ··· 120 122 const char *buf, size_t count) 121 123 { 122 124 struct thermal_zone_device *tz = to_thermal_zone(dev); 123 - int trip, ret; 124 - int temperature, hyst = 0; 125 - enum thermal_trip_type type; 125 + struct thermal_trip trip; 126 + int trip_id, ret; 126 127 127 - if (!tz->ops->set_trip_temp && !tz->trips) 128 - return -EPERM; 129 - 130 - if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1) 131 - return -EINVAL; 132 - 133 - if (kstrtoint(buf, 10, &temperature)) 128 + if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1) 134 129 return -EINVAL; 135 130 136 131 mutex_lock(&tz->lock); ··· 133 142 goto unlock; 134 143 } 135 144 136 - if (tz->ops->set_trip_temp) { 137 - ret = tz->ops->set_trip_temp(tz, trip, temperature); 138 - if (ret) 139 - goto unlock; 140 - } 141 - 142 - if (tz->trips) 143 - tz->trips[trip].temperature = temperature; 144 - 145 - if (tz->ops->get_trip_hyst) { 146 - ret = tz->ops->get_trip_hyst(tz, trip, &hyst); 147 - if (ret) 148 - goto unlock; 149 - } 150 - 151 - ret = tz->ops->get_trip_type(tz, trip, &type); 145 + ret = __thermal_zone_get_trip(tz, trip_id, &trip); 152 146 if (ret) 153 147 goto unlock; 154 148 155 - thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst); 149 + ret = kstrtoint(buf, 10, &trip.temperature); 150 + if (ret) 151 + goto unlock; 156 152 157 - __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 158 - 153 + ret = thermal_zone_set_trip(tz, trip_id, &trip); 159 154 unlock: 160 155 mutex_unlock(&tz->lock); 161 - 162 - if (ret) 163 - return ret; 164 - 165 - return count; 156 + 157 + return ret ? ret : count; 166 158 } 167 159 168 160 static ssize_t ··· 153 179 char *buf) 154 180 { 155 181 struct thermal_zone_device *tz = to_thermal_zone(dev); 156 - int trip, ret; 157 - int temperature; 182 + struct thermal_trip trip; 183 + int trip_id, ret; 158 184 159 - if (!tz->ops->get_trip_temp) 160 - return -EPERM; 161 - 162 - if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1) 185 + if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1) 163 186 return -EINVAL; 164 187 165 188 mutex_lock(&tz->lock); 166 189 167 190 if (device_is_registered(dev)) 168 - ret = tz->ops->get_trip_temp(tz, trip, &temperature); 191 + ret = __thermal_zone_get_trip(tz, trip_id, &trip); 169 192 else 170 193 ret = -ENODEV; 171 194 ··· 171 200 if (ret) 172 201 return ret; 173 202 174 - return sprintf(buf, "%d\n", temperature); 203 + return sprintf(buf, "%d\n", trip.temperature); 175 204 } 176 205 177 206 static ssize_t ··· 179 208 const char *buf, size_t count) 180 209 { 181 210 struct thermal_zone_device *tz = to_thermal_zone(dev); 182 - int trip, ret; 183 - int temperature; 211 + struct thermal_trip trip; 212 + int trip_id, ret; 184 213 185 - if (!tz->ops->set_trip_hyst) 186 - return -EPERM; 187 - 188 - if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1) 214 + if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1) 189 215 return -EINVAL; 190 216 191 - if (kstrtoint(buf, 10, &temperature)) 217 + if (kstrtoint(buf, 10, &trip.hysteresis)) 192 218 return -EINVAL; 193 219 194 220 mutex_lock(&tz->lock); ··· 195 227 goto unlock; 196 228 } 197 229 198 - /* 199 - * We are not doing any check on the 'temperature' value 200 - * here. The driver implementing 'set_trip_hyst' has to 201 - * take care of this. 202 - */ 203 - ret = tz->ops->set_trip_hyst(tz, trip, temperature); 204 - 205 - if (!ret) 206 - __thermal_zone_set_trips(tz); 207 - 230 + ret = __thermal_zone_get_trip(tz, trip_id, &trip); 231 + if (ret) 232 + goto unlock; 233 + 234 + ret = thermal_zone_set_trip(tz, trip_id, &trip); 208 235 unlock: 209 236 mutex_unlock(&tz->lock); 210 237 ··· 211 248 char *buf) 212 249 { 213 250 struct thermal_zone_device *tz = to_thermal_zone(dev); 214 - int trip, ret; 215 - int temperature; 251 + struct thermal_trip trip; 252 + int trip_id, ret; 216 253 217 - if (!tz->ops->get_trip_hyst) 218 - return -EPERM; 219 - 220 - if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1) 254 + if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1) 221 255 return -EINVAL; 222 256 223 257 mutex_lock(&tz->lock); 224 258 225 259 if (device_is_registered(dev)) 226 - ret = tz->ops->get_trip_hyst(tz, trip, &temperature); 260 + ret = __thermal_zone_get_trip(tz, trip_id, &trip); 227 261 else 228 262 ret = -ENODEV; 229 263 230 264 mutex_unlock(&tz->lock); 231 265 232 - return ret ? ret : sprintf(buf, "%d\n", temperature); 266 + return ret ? ret : sprintf(buf, "%d\n", trip.hysteresis); 233 267 } 234 268 235 269 static ssize_t ··· 451 491 return -ENOMEM; 452 492 } 453 493 454 - if (tz->ops->get_trip_hyst) { 455 - tz->trip_hyst_attrs = kcalloc(tz->num_trips, 456 - sizeof(*tz->trip_hyst_attrs), 457 - GFP_KERNEL); 458 - if (!tz->trip_hyst_attrs) { 459 - kfree(tz->trip_type_attrs); 460 - kfree(tz->trip_temp_attrs); 461 - return -ENOMEM; 462 - } 494 + tz->trip_hyst_attrs = kcalloc(tz->num_trips, 495 + sizeof(*tz->trip_hyst_attrs), 496 + GFP_KERNEL); 497 + if (!tz->trip_hyst_attrs) { 498 + kfree(tz->trip_type_attrs); 499 + kfree(tz->trip_temp_attrs); 500 + return -ENOMEM; 463 501 } 464 502 465 503 attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL); 466 504 if (!attrs) { 467 505 kfree(tz->trip_type_attrs); 468 506 kfree(tz->trip_temp_attrs); 469 - if (tz->ops->get_trip_hyst) 470 - kfree(tz->trip_hyst_attrs); 507 + kfree(tz->trip_hyst_attrs); 471 508 return -ENOMEM; 472 509 } 473 510 ··· 497 540 } 498 541 attrs[indx + tz->num_trips] = &tz->trip_temp_attrs[indx].attr.attr; 499 542 500 - /* create Optional trip hyst attribute */ 501 - if (!tz->ops->get_trip_hyst) 502 - continue; 503 543 snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH, 504 544 "trip_point_%d_hyst", indx); 505 545 ··· 533 579 534 580 kfree(tz->trip_type_attrs); 535 581 kfree(tz->trip_temp_attrs); 536 - if (tz->ops->get_trip_hyst) 537 - kfree(tz->trip_hyst_attrs); 582 + kfree(tz->trip_hyst_attrs); 538 583 kfree(tz->trips_attribute_group.attrs); 539 584 } 540 585
+182
drivers/thermal/thermal_trip.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2008 Intel Corp 4 + * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com> 5 + * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com> 6 + * Copyright 2022 Linaro Limited 7 + * 8 + * Thermal trips handling 9 + */ 10 + #include "thermal_core.h" 11 + 12 + int __for_each_thermal_trip(struct thermal_zone_device *tz, 13 + int (*cb)(struct thermal_trip *, void *), 14 + void *data) 15 + { 16 + int i, ret; 17 + struct thermal_trip trip; 18 + 19 + lockdep_assert_held(&tz->lock); 20 + 21 + for (i = 0; i < tz->num_trips; i++) { 22 + 23 + ret = __thermal_zone_get_trip(tz, i, &trip); 24 + if (ret) 25 + return ret; 26 + 27 + ret = cb(&trip, data); 28 + if (ret) 29 + return ret; 30 + } 31 + 32 + return 0; 33 + } 34 + 35 + int thermal_zone_get_num_trips(struct thermal_zone_device *tz) 36 + { 37 + return tz->num_trips; 38 + } 39 + EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips); 40 + 41 + /** 42 + * __thermal_zone_set_trips - Computes the next trip points for the driver 43 + * @tz: a pointer to a thermal zone device structure 44 + * 45 + * The function computes the next temperature boundaries by browsing 46 + * the trip points. The result is the closer low and high trip points 47 + * to the current temperature. These values are passed to the backend 48 + * driver to let it set its own notification mechanism (usually an 49 + * interrupt). 50 + * 51 + * This function must be called with tz->lock held. Both tz and tz->ops 52 + * must be valid pointers. 53 + * 54 + * It does not return a value 55 + */ 56 + void __thermal_zone_set_trips(struct thermal_zone_device *tz) 57 + { 58 + struct thermal_trip trip; 59 + int low = -INT_MAX, high = INT_MAX; 60 + int i, ret; 61 + 62 + lockdep_assert_held(&tz->lock); 63 + 64 + if (!tz->ops->set_trips) 65 + return; 66 + 67 + for (i = 0; i < tz->num_trips; i++) { 68 + int trip_low; 69 + 70 + ret = __thermal_zone_get_trip(tz, i , &trip); 71 + if (ret) 72 + return; 73 + 74 + trip_low = trip.temperature - trip.hysteresis; 75 + 76 + if (trip_low < tz->temperature && trip_low > low) 77 + low = trip_low; 78 + 79 + if (trip.temperature > tz->temperature && 80 + trip.temperature < high) 81 + high = trip.temperature; 82 + } 83 + 84 + /* No need to change trip points */ 85 + if (tz->prev_low_trip == low && tz->prev_high_trip == high) 86 + return; 87 + 88 + tz->prev_low_trip = low; 89 + tz->prev_high_trip = high; 90 + 91 + dev_dbg(&tz->device, 92 + "new temperature boundaries: %d < x < %d\n", low, high); 93 + 94 + /* 95 + * Set a temperature window. When this window is left the driver 96 + * must inform the thermal core via thermal_zone_device_update. 97 + */ 98 + ret = tz->ops->set_trips(tz, low, high); 99 + if (ret) 100 + dev_err(&tz->device, "Failed to set trips: %d\n", ret); 101 + } 102 + 103 + int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, 104 + struct thermal_trip *trip) 105 + { 106 + int ret; 107 + 108 + if (!tz || trip_id < 0 || trip_id >= tz->num_trips || !trip) 109 + return -EINVAL; 110 + 111 + if (tz->trips) { 112 + *trip = tz->trips[trip_id]; 113 + return 0; 114 + } 115 + 116 + if (tz->ops->get_trip_hyst) { 117 + ret = tz->ops->get_trip_hyst(tz, trip_id, &trip->hysteresis); 118 + if (ret) 119 + return ret; 120 + } else { 121 + trip->hysteresis = 0; 122 + } 123 + 124 + ret = tz->ops->get_trip_temp(tz, trip_id, &trip->temperature); 125 + if (ret) 126 + return ret; 127 + 128 + return tz->ops->get_trip_type(tz, trip_id, &trip->type); 129 + } 130 + EXPORT_SYMBOL_GPL(__thermal_zone_get_trip); 131 + 132 + int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, 133 + struct thermal_trip *trip) 134 + { 135 + int ret; 136 + 137 + mutex_lock(&tz->lock); 138 + ret = __thermal_zone_get_trip(tz, trip_id, trip); 139 + mutex_unlock(&tz->lock); 140 + 141 + return ret; 142 + } 143 + EXPORT_SYMBOL_GPL(thermal_zone_get_trip); 144 + 145 + int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id, 146 + const struct thermal_trip *trip) 147 + { 148 + struct thermal_trip t; 149 + int ret; 150 + 151 + if (!tz->ops->set_trip_temp && !tz->ops->set_trip_hyst && !tz->trips) 152 + return -EINVAL; 153 + 154 + ret = __thermal_zone_get_trip(tz, trip_id, &t); 155 + if (ret) 156 + return ret; 157 + 158 + if (t.type != trip->type) 159 + return -EINVAL; 160 + 161 + if (t.temperature != trip->temperature && tz->ops->set_trip_temp) { 162 + ret = tz->ops->set_trip_temp(tz, trip_id, trip->temperature); 163 + if (ret) 164 + return ret; 165 + } 166 + 167 + if (t.hysteresis != trip->hysteresis && tz->ops->set_trip_hyst) { 168 + ret = tz->ops->set_trip_hyst(tz, trip_id, trip->hysteresis); 169 + if (ret) 170 + return ret; 171 + } 172 + 173 + if (tz->trips && (t.temperature != trip->temperature || t.hysteresis != trip->hysteresis)) 174 + tz->trips[trip_id] = *trip; 175 + 176 + thermal_notify_tz_trip_change(tz->id, trip_id, trip->type, 177 + trip->temperature, trip->hysteresis); 178 + 179 + __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED); 180 + 181 + return 0; 182 + }
-15
drivers/thermal/ti-soc-thermal/ti-thermal.h
··· 38 38 /* Update rates */ 39 39 #define FAST_TEMP_MONITORING_RATE 250 40 40 41 - /* helper macros */ 42 - /** 43 - * ti_thermal_get_trip_value - returns trip temperature based on index 44 - * @i: trip index 45 - */ 46 - #define ti_thermal_get_trip_value(i) \ 47 - (OMAP_TRIP_HOT + ((i) * OMAP_TRIP_STEP)) 48 - 49 - /** 50 - * ti_thermal_is_valid_trip - check for trip index 51 - * @i: trip index 52 - */ 53 - #define ti_thermal_is_valid_trip(trip) \ 54 - ((trip) >= 0 && (trip) < OMAP_TRIP_NUMBER) 55 - 56 41 #ifdef CONFIG_TI_THERMAL 57 42 int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain); 58 43 int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id);
+13 -18
drivers/thermal/uniphier_thermal.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - /** 2 + /* 3 3 * uniphier_thermal.c - Socionext UniPhier thermal driver 4 4 * Copyright 2014 Panasonic Corporation 5 5 * Copyright 2016-2017 Socionext Inc. ··· 16 16 #include <linux/platform_device.h> 17 17 #include <linux/regmap.h> 18 18 #include <linux/thermal.h> 19 - 20 - #include "thermal_core.h" 21 19 22 20 /* 23 21 * block registers ··· 246 248 struct regmap *regmap; 247 249 struct device_node *parent; 248 250 struct uniphier_tm_dev *tdev; 249 - const struct thermal_trip *trips; 250 - int i, ret, irq, ntrips, crit_temp = INT_MAX; 251 + int i, ret, irq, crit_temp = INT_MAX; 251 252 252 253 tdev = devm_kzalloc(dev, sizeof(*tdev), GFP_KERNEL); 253 254 if (!tdev) ··· 293 296 return PTR_ERR(tdev->tz_dev); 294 297 } 295 298 296 - /* get trip points */ 297 - trips = of_thermal_get_trip_points(tdev->tz_dev); 298 - ntrips = of_thermal_get_ntrips(tdev->tz_dev); 299 - if (ntrips > ALERT_CH_NUM) { 300 - dev_err(dev, "thermal zone has too many trips\n"); 301 - return -E2BIG; 302 - } 303 - 304 299 /* set alert temperatures */ 305 - for (i = 0; i < ntrips; i++) { 306 - if (trips[i].type == THERMAL_TRIP_CRITICAL && 307 - trips[i].temperature < crit_temp) 308 - crit_temp = trips[i].temperature; 309 - uniphier_tm_set_alert(tdev, i, trips[i].temperature); 300 + for (i = 0; i < thermal_zone_get_num_trips(tdev->tz_dev); i++) { 301 + struct thermal_trip trip; 302 + 303 + ret = thermal_zone_get_trip(tdev->tz_dev, i, &trip); 304 + if (ret) 305 + return ret; 306 + 307 + if (trip.type == THERMAL_TRIP_CRITICAL && 308 + trip.temperature < crit_temp) 309 + crit_temp = trip.temperature; 310 + uniphier_tm_set_alert(tdev, i, trip.temperature); 310 311 tdev->alert_en[i] = true; 311 312 } 312 313 if (crit_temp > CRITICAL_TEMP_LIMIT) {
+19
include/dt-bindings/thermal/mediatek,lvts-thermal.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + /* 3 + * Copyright (c) 2023 MediaTek Inc. 4 + * Author: Balsam CHIHI <bchihi@baylibre.com> 5 + */ 6 + 7 + #ifndef __MEDIATEK_LVTS_DT_H 8 + #define __MEDIATEK_LVTS_DT_H 9 + 10 + #define MT8195_MCU_BIG_CPU0 0 11 + #define MT8195_MCU_BIG_CPU1 1 12 + #define MT8195_MCU_BIG_CPU2 2 13 + #define MT8195_MCU_BIG_CPU3 3 14 + #define MT8195_MCU_LITTLE_CPU0 4 15 + #define MT8195_MCU_LITTLE_CPU1 5 16 + #define MT8195_MCU_LITTLE_CPU2 6 17 + #define MT8195_MCU_LITTLE_CPU3 7 18 + 19 + #endif /* __MEDIATEK_LVTS_DT_H */
+3
include/linux/idle_inject.h
··· 13 13 14 14 struct idle_inject_device *idle_inject_register(struct cpumask *cpumask); 15 15 16 + struct idle_inject_device *idle_inject_register_full(struct cpumask *cpumask, 17 + bool (*update)(void)); 18 + 16 19 void idle_inject_unregister(struct idle_inject_device *ii_dev); 17 20 18 21 int idle_inject_start(struct idle_inject_device *ii_dev);
+18
include/linux/intel_tcc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * header for Intel TCC (thermal control circuitry) library 4 + * 5 + * Copyright (C) 2022 Intel Corporation. 6 + */ 7 + 8 + #ifndef __INTEL_TCC_H__ 9 + #define __INTEL_TCC_H__ 10 + 11 + #include <linux/types.h> 12 + 13 + int intel_tcc_get_tjmax(int cpu); 14 + int intel_tcc_get_offset(int cpu); 15 + int intel_tcc_set_offset(int cpu, int offset); 16 + int intel_tcc_get_temp(int cpu, bool pkg); 17 + 18 + #endif /* __INTEL_TCC_H__ */
+19
include/linux/thermal.h
··· 334 334 } 335 335 #endif 336 336 337 + int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, 338 + struct thermal_trip *trip); 339 + int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, 340 + struct thermal_trip *trip); 341 + 342 + int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id, 343 + const struct thermal_trip *trip); 344 + 345 + int thermal_zone_get_num_trips(struct thermal_zone_device *tz); 346 + 347 + int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp); 348 + 349 + #ifdef CONFIG_THERMAL_ACPI 350 + int thermal_acpi_active_trip_temp(struct acpi_device *adev, int id, int *ret_temp); 351 + int thermal_acpi_passive_trip_temp(struct acpi_device *adev, int *ret_temp); 352 + int thermal_acpi_hot_trip_temp(struct acpi_device *adev, int *ret_temp); 353 + int thermal_acpi_critical_trip_temp(struct acpi_device *adev, int *ret_temp); 354 + #endif 355 + 337 356 #ifdef CONFIG_THERMAL 338 357 struct thermal_zone_device *thermal_zone_device_register(const char *, int, int, 339 358 void *, struct thermal_zone_device_ops *,
+1 -1
tools/lib/thermal/libthermal.pc.template
··· 9 9 Requires: libnl-3.0 libnl-genl-3.0 10 10 Version: @VERSION@ 11 11 Libs: -L${libdir} -lnl-genl-3 -lnl-3 12 - Cflags: -I${includedir} -I{include}/libnl3 12 + Cflags: -I${includedir} -I${include}/libnl3
+1 -1
tools/lib/thermal/sampling.c
··· 54 54 thermal_error_t thermal_sampling_exit(struct thermal_handler *th) 55 55 { 56 56 if (nl_unsubscribe_thermal(th->sk_sampling, th->cb_sampling, 57 - THERMAL_GENL_EVENT_GROUP_NAME)) 57 + THERMAL_GENL_SAMPLING_GROUP_NAME)) 58 58 return THERMAL_ERROR; 59 59 60 60 nl_thermal_disconnect(th->sk_sampling, th->cb_sampling);