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

Merge tag 'thermal-v5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux

Pull thermal updates from Daniel Lezcano:

- Convert tsens configuration DT binding to yaml (Rajeshwari)

- Add interrupt support on the rcar sensor (Niklas Söderlund)

- Add a new Spreadtrum thermal driver (Baolin Wang)

- Add thermal binding for the fsl scu board, a new API to retrieve the
sensor id bound to the thermal zone and i.MX system controller sensor
(Anson Huang))

- Remove warning log when a deferred probe is requested on Exynos
(Marek Szyprowski)

- Add the thermal monitoring unit support for imx8mm with its DT
bindings (Anson Huang)

- Rephrase the Kconfig text for clarity (Linus Walleij)

- Use the gpio descriptor for the ti-soc-thermal (Linus Walleij)

- Align msg structure to 4 bytes for i.MX SC, fix the Kconfig
dependency, add the __may_be unused annotation for PM functions and
the COMPILE_TEST option for imx8mm (Anson Huang)

- Fix a dependency on regmap in Kconfig for qoriq (Yuantian Tang)

- Add DT binding and support for the rcar gen3 r8a77961 and improve the
error path on the rcar init function (Niklas Söderlund)

- Cleanup and improvements for the tsens Qcom sensor (Amit Kucheria)

- Improve code by removing lock and caching values in the rcar thermal
sensor (Niklas Söderlund)

- Cleanup in the qoriq drivers and add a call to
imx_thermal_unregister_legacy_cooling in the removal function (Anson
Huang)

- Remove redundant 'maxItems' in tsens and sprd DT bindings (Rob
Herring)

- Change the thermal DT bindings by making the cooling-maps optional
(Yuantian Tang)

- Add Tiger Lake support (Sumeet Pawnikar)

- Use scnprintf() for avoiding potential buffer overflow (Takashi Iwai)

- Make pkg_temp_lock a raw_spinlock_t(Clark Williams)

- Fix incorrect data types by changing them to signed on i.MX SC (Anson
Huang)

- Replace zero-length array with flexible-array member (Gustavo A. R.
Silva)

- Add support for i.MX8MP in the driver and in the DT bindings (Anson
Huang)

- Fix return value of the cpufreq_set_cur_state() function (Willy
Wolff)

- Remove abusing and scary WARN_ON in the cpufreq cooling device
(Daniel Lezcano)

- Fix build warning of incorrect argument type reported by sparse on
imx8mm (Anson Huang)

- Fix stub for the devfreq cooling device (Martin Blumenstingl)

- Fix cpu idle cooling documentation (Sergey Vidishev)

* tag 'thermal-v5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (52 commits)
Documentation: cpu-idle-cooling: Fix diagram for 33% duty cycle
thermal: devfreq_cooling: inline all stubs for CONFIG_DEVFREQ_THERMAL=n
thermal: imx8mm: Fix build warning of incorrect argument type
thermal/drivers/cpufreq_cooling: Remove abusing WARN_ON
thermal/drivers/cpufreq_cooling: Fix return of cpufreq_set_cur_state
thermal: imx8mm: Add i.MX8MP support
dt-bindings: thermal: imx8mm-thermal: Add support for i.MX8MP
thermal: qcom: tsens.h: Replace zero-length array with flexible-array member
thermal: imx_sc_thermal: Fix incorrect data type
thermal: int340x_thermal: Use scnprintf() for avoiding potential buffer overflow
thermal: int340x: processor_thermal: Add Tiger Lake support
thermal/x86_pkg_temp: Make pkg_temp_lock a raw_spinlock_t
dt-bindings: thermal: make cooling-maps property optional
dt-bindings: thermal: qcom-tsens: Remove redundant 'maxItems'
dt-bindings: thermal: sprd: Remove redundant 'maxItems'
thermal: imx: Calling imx_thermal_unregister_legacy_cooling() in .remove
thermal: qoriq: Sort includes alphabetically
thermal: qoriq: Use devm_add_action_or_reset() to handle all cleanups
thermal: rcar_thermal: Remove lock in rcar_thermal_get_current_temp()
thermal: rcar_thermal: Do not store ctemp in rcar_thermal_priv
...

+1598 -241
+16
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
··· 166 166 followed by "fsl,imx-sc-key"; 167 167 - linux,keycodes: See Documentation/devicetree/bindings/input/input.yaml 168 168 169 + Thermal bindings based on SCU Message Protocol 170 + ------------------------------------------------------------ 171 + 172 + Required properties: 173 + - compatible: Should be : 174 + "fsl,imx8qxp-sc-thermal" 175 + followed by "fsl,imx-sc-thermal"; 176 + 177 + - #thermal-sensor-cells: See Documentation/devicetree/bindings/thermal/thermal.txt 178 + for a description. 179 + 169 180 Example (imx8qxp): 170 181 ------------- 171 182 aliases { ··· 248 237 watchdog { 249 238 compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt"; 250 239 timeout-sec = <60>; 240 + }; 241 + 242 + tsens: thermal-sensor { 243 + compatible = "fsl,imx8qxp-sc-thermal", "fsl,imx-sc-thermal"; 244 + #thermal-sensor-cells = <1>; 251 245 }; 252 246 }; 253 247 };
+15
Documentation/devicetree/bindings/thermal/imx8mm-thermal.txt
··· 1 + * Thermal Monitoring Unit (TMU) on Freescale i.MX8MM SoC 2 + 3 + Required properties: 4 + - compatible : Must be "fsl,imx8mm-tmu" or "fsl,imx8mp-tmu". 5 + - reg : Address range of TMU registers. 6 + - clocks : TMU's clock source. 7 + - #thermal-sensor-cells : Should be 0 or 1. See ./thermal.txt for a description. 8 + 9 + Example: 10 + tmu: tmu@30260000 { 11 + compatible = "fsl,imx8mm-tmu"; 12 + reg = <0x30260000 0x10000>; 13 + clocks = <&clk IMX8MM_CLK_TMU_ROOT>; 14 + #thermal-sensor-cells = <0>; 15 + };
+1 -1
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
··· 38 38 - enum: 39 39 - qcom,msm8996-tsens 40 40 - qcom,msm8998-tsens 41 + - qcom,sc7180-tsens 41 42 - qcom,sdm845-tsens 42 43 - const: qcom,tsens-v2 43 44 44 45 reg: 45 - maxItems: 2 46 46 items: 47 47 - description: TM registers 48 48 - description: SROT registers
+1
Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt
··· 11 11 - "renesas,r8a774b1-thermal" (RZ/G2N) 12 12 - "renesas,r8a7795-thermal" (R-Car H3) 13 13 - "renesas,r8a7796-thermal" (R-Car M3-W) 14 + - "renesas,r8a77961-thermal" (R-Car M3-W+) 14 15 - "renesas,r8a77965-thermal" (R-Car M3-N) 15 16 - "renesas,r8a77980-thermal" (R-Car V3H) 16 17 - reg : Address ranges of the thermal registers. Each sensor
+107
Documentation/devicetree/bindings/thermal/sprd-thermal.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/thermal/sprd-thermal.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Spreadtrum thermal sensor controller bindings 8 + 9 + maintainers: 10 + - Orson Zhai <orsonzhai@gmail.com> 11 + - Baolin Wang <baolin.wang7@gmail.com> 12 + - Chunyan Zhang <zhang.lyra@gmail.com> 13 + 14 + properties: 15 + compatible: 16 + const: sprd,ums512-thermal 17 + 18 + reg: 19 + maxItems: 1 20 + 21 + clocks: 22 + maxItems: 1 23 + 24 + clock-names: 25 + items: 26 + - const: enable 27 + 28 + nvmem-cells: 29 + maxItems: 2 30 + description: 31 + Reference to nvmem nodes for the calibration data. 32 + 33 + nvmem-cell-names: 34 + items: 35 + - const: thm_sign_cal 36 + - const: thm_ratio_cal 37 + 38 + "#thermal-sensor-cells": 39 + const: 1 40 + 41 + "#address-cells": 42 + const: 1 43 + 44 + "#size-cells": 45 + const: 0 46 + 47 + patternProperties: 48 + "^([a-z]*-)?sensor(-section)?@[0-9]+$": 49 + type: object 50 + description: 51 + Represent one thermal sensor. 52 + 53 + properties: 54 + reg: 55 + description: Specify the sensor id. 56 + maxItems: 1 57 + 58 + nvmem-cells: 59 + maxItems: 1 60 + description: 61 + Reference to an nvmem node for the calibration data. 62 + 63 + nvmem-cell-names: 64 + const: sen_delta_cal 65 + 66 + required: 67 + - reg 68 + - nvmem-cells 69 + - nvmem-cell-names 70 + 71 + required: 72 + - compatible 73 + - reg 74 + - clocks 75 + - clock-names 76 + - nvmem-cells 77 + - nvmem-cell-names 78 + - "#thermal-sensor-cells" 79 + - "#address-cells" 80 + - "#size-cells" 81 + 82 + examples: 83 + - | 84 + ap_thm0: thermal@32200000 { 85 + compatible = "sprd,ums512-thermal"; 86 + reg = <0 0x32200000 0 0x10000>; 87 + clock-names = "enable"; 88 + clocks = <&aonapb_gate 32>; 89 + #thermal-sensor-cells = <1>; 90 + nvmem-cells = <&thm0_sign>, <&thm0_ratio>; 91 + nvmem-cell-names = "thm_sign_cal", "thm_ratio_cal"; 92 + #address-cells = <1>; 93 + #size-cells = <0>; 94 + 95 + prometheus-sensor@0 { 96 + reg = <0>; 97 + nvmem-cells = <&thm0_sen0>; 98 + nvmem-cell-names = "sen_delta_cal"; 99 + }; 100 + 101 + ank-sensor@1 { 102 + reg = <1>; 103 + nvmem-cells = <&thm0_sen1>; 104 + nvmem-cell-names = "sen_delta_cal"; 105 + }; 106 + }; 107 + ...
+1 -1
Documentation/devicetree/bindings/thermal/thermal.txt
··· 142 142 - trips: A sub-node which is a container of only trip point nodes 143 143 Type: sub-node required to describe the thermal zone. 144 144 145 + Optional property: 145 146 - cooling-maps: A sub-node which is a container of only cooling device 146 147 Type: sub-node map nodes, used to describe the relation between trips 147 148 and cooling devices. 148 149 149 - Optional property: 150 150 - coefficients: An array of integers (one signed cell) containing 151 151 Type: array coefficients to compose a linear relation between 152 152 Elem size: one cell the sensors listed in the thermal-sensors property.
+2 -2
Documentation/driver-api/thermal/cpu-idle-cooling.rst
··· 105 105 idle <--------------> 106 106 running 107 107 108 - <-----------------------------> 109 - duty cycle 33% 108 + <---------------------> 109 + duty cycle 33% 110 110 111 111 112 112 ^
+36 -6
drivers/thermal/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 # 3 - # Generic thermal sysfs drivers configuration 3 + # Generic thermal drivers configuration 4 4 # 5 5 6 6 menuconfig THERMAL 7 - bool "Generic Thermal sysfs driver" 7 + bool "Thermal drivers" 8 8 help 9 - Generic Thermal Sysfs driver offers a generic mechanism for 9 + Thermal drivers offer a generic mechanism for 10 10 thermal management. Usually it's made up of one or more thermal 11 - zone and cooling device. 11 + zones and cooling devices. 12 12 Each thermal zone contains its own temperature, trip points, 13 - cooling devices. 14 - All platforms with ACPI thermal support can use this driver. 13 + and cooling devices. 14 + All platforms with ACPI or Open Firmware thermal support can use 15 + this driver. 15 16 If you want this support, you should say Y here. 16 17 17 18 if THERMAL ··· 252 251 cpufreq is used as the cooling device to throttle CPUs when the 253 252 passive trip is crossed. 254 253 254 + config IMX_SC_THERMAL 255 + tristate "Temperature sensor driver for NXP i.MX SoCs with System Controller" 256 + depends on IMX_SCU 257 + depends on OF 258 + help 259 + Support for Temperature Monitor (TEMPMON) found on NXP i.MX SoCs with 260 + system controller inside, Linux kernel has to communicate with system 261 + controller via MU (message unit) IPC to get temperature from thermal 262 + sensor. It supports one critical trip point and one 263 + passive trip point for each thermal sensor. 264 + 265 + config IMX8MM_THERMAL 266 + tristate "Temperature sensor driver for Freescale i.MX8MM SoC" 267 + depends on ARCH_MXC || COMPILE_TEST 268 + depends on OF 269 + help 270 + Support for Thermal Monitoring Unit (TMU) found on Freescale i.MX8MM SoC. 271 + It supports one critical trip point and one passive trip point. The 272 + cpufreq is used as the cooling device to throttle CPUs when the passive 273 + trip is crossed. 274 + 255 275 config MAX77620_THERMAL 256 276 tristate "Temperature sensor driver for Maxim MAX77620 PMIC" 257 277 depends on MFD_MAX77620 ··· 287 265 tristate "QorIQ Thermal Monitoring Unit" 288 266 depends on THERMAL_OF 289 267 depends on HAS_IOMEM 268 + select REGMAP_MMIO 290 269 help 291 270 Support for Thermal Monitoring Unit (TMU) found on QorIQ platforms. 292 271 It supports one critical trip point and one passive trip point. The ··· 483 460 Enable this to plug in UniPhier on-chip PVT thermal driver into the 484 461 thermal framework. The driver supports CPU thermal zone temperature 485 462 reporting and a couple of trip points. 463 + 464 + config SPRD_THERMAL 465 + tristate "Temperature sensor on Spreadtrum SoCs" 466 + depends on ARCH_SPRD || COMPILE_TEST 467 + help 468 + Support for the Spreadtrum thermal sensor driver in the Linux thermal 469 + framework. 486 470 endif
+3
drivers/thermal/Makefile
··· 43 43 obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o 44 44 obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o 45 45 obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o 46 + obj-$(CONFIG_IMX_SC_THERMAL) += imx_sc_thermal.o 47 + obj-$(CONFIG_IMX8MM_THERMAL) += imx8mm_thermal.o 46 48 obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o 47 49 obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o 48 50 obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o ··· 59 57 obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o 60 58 obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o 61 59 obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o 60 + obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o
+3 -2
drivers/thermal/cpufreq_cooling.c
··· 273 273 struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; 274 274 275 275 /* Request state should be less than max_level */ 276 - if (WARN_ON(state > cpufreq_cdev->max_level)) 276 + if (state > cpufreq_cdev->max_level) 277 277 return -EINVAL; 278 278 279 279 num_cpus = cpumask_weight(cpufreq_cdev->policy->cpus); ··· 437 437 int ret; 438 438 439 439 /* Request state should be less than max_level */ 440 - if (WARN_ON(state > cpufreq_cdev->max_level)) 440 + if (state > cpufreq_cdev->max_level) 441 441 return -EINVAL; 442 442 443 443 /* Check if the old cooling action is same as new cooling action */ ··· 456 456 capacity = frequency * max_capacity; 457 457 capacity /= cpufreq_cdev->policy->cpuinfo.max_freq; 458 458 arch_set_thermal_pressure(cpus, max_capacity - capacity); 459 + ret = 0; 459 460 } 460 461 461 462 return ret;
+236
drivers/thermal/imx8mm_thermal.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020 NXP. 4 + * 5 + * Author: Anson Huang <Anson.Huang@nxp.com> 6 + */ 7 + 8 + #include <linux/bitfield.h> 9 + #include <linux/clk.h> 10 + #include <linux/err.h> 11 + #include <linux/io.h> 12 + #include <linux/module.h> 13 + #include <linux/of.h> 14 + #include <linux/of_device.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/thermal.h> 17 + 18 + #include "thermal_core.h" 19 + 20 + #define TER 0x0 /* TMU enable */ 21 + #define TPS 0x4 22 + #define TRITSR 0x20 /* TMU immediate temp */ 23 + 24 + #define TER_EN BIT(31) 25 + #define TRITSR_TEMP0_VAL_MASK 0xff 26 + #define TRITSR_TEMP1_VAL_MASK 0xff0000 27 + 28 + #define PROBE_SEL_ALL GENMASK(31, 30) 29 + 30 + #define probe_status_offset(x) (30 + x) 31 + #define SIGN_BIT BIT(7) 32 + #define TEMP_VAL_MASK GENMASK(6, 0) 33 + 34 + #define VER1_TEMP_LOW_LIMIT 10000 35 + #define VER2_TEMP_LOW_LIMIT -40000 36 + #define VER2_TEMP_HIGH_LIMIT 125000 37 + 38 + #define TMU_VER1 0x1 39 + #define TMU_VER2 0x2 40 + 41 + struct thermal_soc_data { 42 + u32 num_sensors; 43 + u32 version; 44 + int (*get_temp)(void *, int *); 45 + }; 46 + 47 + struct tmu_sensor { 48 + struct imx8mm_tmu *priv; 49 + u32 hw_id; 50 + struct thermal_zone_device *tzd; 51 + }; 52 + 53 + struct imx8mm_tmu { 54 + void __iomem *base; 55 + struct clk *clk; 56 + const struct thermal_soc_data *socdata; 57 + struct tmu_sensor sensors[0]; 58 + }; 59 + 60 + static int imx8mm_tmu_get_temp(void *data, int *temp) 61 + { 62 + struct tmu_sensor *sensor = data; 63 + struct imx8mm_tmu *tmu = sensor->priv; 64 + u32 val; 65 + 66 + val = readl_relaxed(tmu->base + TRITSR) & TRITSR_TEMP0_VAL_MASK; 67 + *temp = val * 1000; 68 + if (*temp < VER1_TEMP_LOW_LIMIT) 69 + return -EAGAIN; 70 + 71 + return 0; 72 + } 73 + 74 + static int imx8mp_tmu_get_temp(void *data, int *temp) 75 + { 76 + struct tmu_sensor *sensor = data; 77 + struct imx8mm_tmu *tmu = sensor->priv; 78 + unsigned long val; 79 + bool ready; 80 + 81 + val = readl_relaxed(tmu->base + TRITSR); 82 + ready = test_bit(probe_status_offset(sensor->hw_id), &val); 83 + if (!ready) 84 + return -EAGAIN; 85 + 86 + val = sensor->hw_id ? FIELD_GET(TRITSR_TEMP1_VAL_MASK, val) : 87 + FIELD_GET(TRITSR_TEMP0_VAL_MASK, val); 88 + if (val & SIGN_BIT) /* negative */ 89 + val = (~(val & TEMP_VAL_MASK) + 1); 90 + 91 + *temp = val * 1000; 92 + if (*temp < VER2_TEMP_LOW_LIMIT || *temp > VER2_TEMP_HIGH_LIMIT) 93 + return -EAGAIN; 94 + 95 + return 0; 96 + } 97 + 98 + static int tmu_get_temp(void *data, int *temp) 99 + { 100 + struct tmu_sensor *sensor = data; 101 + struct imx8mm_tmu *tmu = sensor->priv; 102 + 103 + return tmu->socdata->get_temp(data, temp); 104 + } 105 + 106 + static struct thermal_zone_of_device_ops tmu_tz_ops = { 107 + .get_temp = tmu_get_temp, 108 + }; 109 + 110 + static void imx8mm_tmu_enable(struct imx8mm_tmu *tmu, bool enable) 111 + { 112 + u32 val; 113 + 114 + val = readl_relaxed(tmu->base + TER); 115 + val = enable ? (val | TER_EN) : (val & ~TER_EN); 116 + writel_relaxed(val, tmu->base + TER); 117 + } 118 + 119 + static void imx8mm_tmu_probe_sel_all(struct imx8mm_tmu *tmu) 120 + { 121 + u32 val; 122 + 123 + val = readl_relaxed(tmu->base + TPS); 124 + val |= PROBE_SEL_ALL; 125 + writel_relaxed(val, tmu->base + TPS); 126 + } 127 + 128 + static int imx8mm_tmu_probe(struct platform_device *pdev) 129 + { 130 + const struct thermal_soc_data *data; 131 + struct imx8mm_tmu *tmu; 132 + int ret; 133 + int i; 134 + 135 + data = of_device_get_match_data(&pdev->dev); 136 + 137 + tmu = devm_kzalloc(&pdev->dev, struct_size(tmu, sensors, 138 + data->num_sensors), GFP_KERNEL); 139 + if (!tmu) 140 + return -ENOMEM; 141 + 142 + tmu->socdata = data; 143 + 144 + tmu->base = devm_platform_ioremap_resource(pdev, 0); 145 + if (IS_ERR(tmu->base)) 146 + return PTR_ERR(tmu->base); 147 + 148 + tmu->clk = devm_clk_get(&pdev->dev, NULL); 149 + if (IS_ERR(tmu->clk)) { 150 + ret = PTR_ERR(tmu->clk); 151 + if (ret != -EPROBE_DEFER) 152 + dev_err(&pdev->dev, 153 + "failed to get tmu clock: %d\n", ret); 154 + return ret; 155 + } 156 + 157 + ret = clk_prepare_enable(tmu->clk); 158 + if (ret) { 159 + dev_err(&pdev->dev, "failed to enable tmu clock: %d\n", ret); 160 + return ret; 161 + } 162 + 163 + /* disable the monitor during initialization */ 164 + imx8mm_tmu_enable(tmu, false); 165 + 166 + for (i = 0; i < data->num_sensors; i++) { 167 + tmu->sensors[i].priv = tmu; 168 + tmu->sensors[i].tzd = 169 + devm_thermal_zone_of_sensor_register(&pdev->dev, i, 170 + &tmu->sensors[i], 171 + &tmu_tz_ops); 172 + if (IS_ERR(tmu->sensors[i].tzd)) { 173 + dev_err(&pdev->dev, 174 + "failed to register thermal zone sensor[%d]: %d\n", 175 + i, ret); 176 + return PTR_ERR(tmu->sensors[i].tzd); 177 + } 178 + tmu->sensors[i].hw_id = i; 179 + } 180 + 181 + platform_set_drvdata(pdev, tmu); 182 + 183 + /* enable all the probes for V2 TMU */ 184 + if (tmu->socdata->version == TMU_VER2) 185 + imx8mm_tmu_probe_sel_all(tmu); 186 + 187 + /* enable the monitor */ 188 + imx8mm_tmu_enable(tmu, true); 189 + 190 + return 0; 191 + } 192 + 193 + static int imx8mm_tmu_remove(struct platform_device *pdev) 194 + { 195 + struct imx8mm_tmu *tmu = platform_get_drvdata(pdev); 196 + 197 + /* disable TMU */ 198 + imx8mm_tmu_enable(tmu, false); 199 + 200 + clk_disable_unprepare(tmu->clk); 201 + platform_set_drvdata(pdev, NULL); 202 + 203 + return 0; 204 + } 205 + 206 + static struct thermal_soc_data imx8mm_tmu_data = { 207 + .num_sensors = 1, 208 + .version = TMU_VER1, 209 + .get_temp = imx8mm_tmu_get_temp, 210 + }; 211 + 212 + static struct thermal_soc_data imx8mp_tmu_data = { 213 + .num_sensors = 2, 214 + .version = TMU_VER2, 215 + .get_temp = imx8mp_tmu_get_temp, 216 + }; 217 + 218 + static const struct of_device_id imx8mm_tmu_table[] = { 219 + { .compatible = "fsl,imx8mm-tmu", .data = &imx8mm_tmu_data, }, 220 + { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, }, 221 + { }, 222 + }; 223 + 224 + static struct platform_driver imx8mm_tmu = { 225 + .driver = { 226 + .name = "i.mx8mm_thermal", 227 + .of_match_table = imx8mm_tmu_table, 228 + }, 229 + .probe = imx8mm_tmu_probe, 230 + .remove = imx8mm_tmu_remove, 231 + }; 232 + module_platform_driver(imx8mm_tmu); 233 + 234 + MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>"); 235 + MODULE_DESCRIPTION("i.MX8MM Thermal Monitor Unit driver"); 236 + MODULE_LICENSE("GPL v2");
+148
drivers/thermal/imx_sc_thermal.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright 2018-2020 NXP. 4 + */ 5 + 6 + #include <linux/err.h> 7 + #include <linux/firmware/imx/sci.h> 8 + #include <linux/firmware/imx/types.h> 9 + #include <linux/module.h> 10 + #include <linux/of.h> 11 + #include <linux/of_device.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/slab.h> 14 + #include <linux/thermal.h> 15 + 16 + #include "thermal_core.h" 17 + 18 + #define IMX_SC_MISC_FUNC_GET_TEMP 13 19 + 20 + static struct imx_sc_ipc *thermal_ipc_handle; 21 + 22 + struct imx_sc_sensor { 23 + struct thermal_zone_device *tzd; 24 + u32 resource_id; 25 + }; 26 + 27 + struct req_get_temp { 28 + u16 resource_id; 29 + u8 type; 30 + } __packed __aligned(4); 31 + 32 + struct resp_get_temp { 33 + s16 celsius; 34 + s8 tenths; 35 + } __packed __aligned(4); 36 + 37 + struct imx_sc_msg_misc_get_temp { 38 + struct imx_sc_rpc_msg hdr; 39 + union { 40 + struct req_get_temp req; 41 + struct resp_get_temp resp; 42 + } data; 43 + } __packed __aligned(4); 44 + 45 + static int imx_sc_thermal_get_temp(void *data, int *temp) 46 + { 47 + struct imx_sc_msg_misc_get_temp msg; 48 + struct imx_sc_rpc_msg *hdr = &msg.hdr; 49 + struct imx_sc_sensor *sensor = data; 50 + int ret; 51 + 52 + msg.data.req.resource_id = sensor->resource_id; 53 + msg.data.req.type = IMX_SC_C_TEMP; 54 + 55 + hdr->ver = IMX_SC_RPC_VERSION; 56 + hdr->svc = IMX_SC_RPC_SVC_MISC; 57 + hdr->func = IMX_SC_MISC_FUNC_GET_TEMP; 58 + hdr->size = 2; 59 + 60 + ret = imx_scu_call_rpc(thermal_ipc_handle, &msg, true); 61 + if (ret) { 62 + dev_err(&sensor->tzd->device, "read temp sensor %d failed, ret %d\n", 63 + sensor->resource_id, ret); 64 + return ret; 65 + } 66 + 67 + *temp = msg.data.resp.celsius * 1000 + msg.data.resp.tenths * 100; 68 + 69 + return 0; 70 + } 71 + 72 + static const struct thermal_zone_of_device_ops imx_sc_thermal_ops = { 73 + .get_temp = imx_sc_thermal_get_temp, 74 + }; 75 + 76 + static int imx_sc_thermal_probe(struct platform_device *pdev) 77 + { 78 + struct device_node *np, *child, *sensor_np; 79 + struct imx_sc_sensor *sensor; 80 + int ret; 81 + 82 + ret = imx_scu_get_handle(&thermal_ipc_handle); 83 + if (ret) 84 + return ret; 85 + 86 + np = of_find_node_by_name(NULL, "thermal-zones"); 87 + if (!np) 88 + return -ENODEV; 89 + 90 + sensor_np = of_node_get(pdev->dev.of_node); 91 + 92 + for_each_available_child_of_node(np, child) { 93 + sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL); 94 + if (!sensor) { 95 + of_node_put(sensor_np); 96 + return -ENOMEM; 97 + } 98 + 99 + ret = thermal_zone_of_get_sensor_id(child, 100 + sensor_np, 101 + &sensor->resource_id); 102 + if (ret < 0) { 103 + dev_err(&pdev->dev, 104 + "failed to get valid sensor resource id: %d\n", 105 + ret); 106 + break; 107 + } 108 + 109 + sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 110 + sensor->resource_id, 111 + sensor, 112 + &imx_sc_thermal_ops); 113 + if (IS_ERR(sensor->tzd)) { 114 + dev_err(&pdev->dev, "failed to register thermal zone\n"); 115 + ret = PTR_ERR(sensor->tzd); 116 + break; 117 + } 118 + } 119 + 120 + of_node_put(sensor_np); 121 + 122 + return ret; 123 + } 124 + 125 + static int imx_sc_thermal_remove(struct platform_device *pdev) 126 + { 127 + return 0; 128 + } 129 + 130 + static const struct of_device_id imx_sc_thermal_table[] = { 131 + { .compatible = "fsl,imx-sc-thermal", }, 132 + {} 133 + }; 134 + MODULE_DEVICE_TABLE(of, imx_sc_thermal_table); 135 + 136 + static struct platform_driver imx_sc_thermal_driver = { 137 + .probe = imx_sc_thermal_probe, 138 + .remove = imx_sc_thermal_remove, 139 + .driver = { 140 + .name = "imx-sc-thermal", 141 + .of_match_table = imx_sc_thermal_table, 142 + }, 143 + }; 144 + module_platform_driver(imx_sc_thermal_driver); 145 + 146 + MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>"); 147 + MODULE_DESCRIPTION("Thermal driver for NXP i.MX SoCs with system controller"); 148 + MODULE_LICENSE("GPL v2");
+3 -13
drivers/thermal/imx_thermal.c
··· 3 3 // Copyright 2013 Freescale Semiconductor, Inc. 4 4 5 5 #include <linux/clk.h> 6 - #include <linux/cpu.h> 7 6 #include <linux/cpufreq.h> 8 7 #include <linux/cpu_cooling.h> 9 8 #include <linux/delay.h> 10 - #include <linux/device.h> 11 - #include <linux/init.h> 12 9 #include <linux/interrupt.h> 13 10 #include <linux/io.h> 14 - #include <linux/kernel.h> 15 11 #include <linux/mfd/syscon.h> 16 12 #include <linux/module.h> 17 13 #include <linux/of.h> 18 14 #include <linux/of_device.h> 19 - #include <linux/platform_device.h> 20 15 #include <linux/regmap.h> 21 - #include <linux/slab.h> 22 16 #include <linux/thermal.h> 23 - #include <linux/types.h> 24 17 #include <linux/nvmem-consumer.h> 25 18 26 19 #define REG_SET 0x4 ··· 865 872 clk_disable_unprepare(data->thermal_clk); 866 873 867 874 thermal_zone_device_unregister(data->tz); 868 - cpufreq_cooling_unregister(data->cdev); 869 - cpufreq_cpu_put(data->policy); 875 + imx_thermal_unregister_legacy_cooling(data); 870 876 871 877 return 0; 872 878 } 873 879 874 - #ifdef CONFIG_PM_SLEEP 875 - static int imx_thermal_suspend(struct device *dev) 880 + static int __maybe_unused imx_thermal_suspend(struct device *dev) 876 881 { 877 882 struct imx_thermal_data *data = dev_get_drvdata(dev); 878 883 struct regmap *map = data->tempmon; ··· 891 900 return 0; 892 901 } 893 902 894 - static int imx_thermal_resume(struct device *dev) 903 + static int __maybe_unused imx_thermal_resume(struct device *dev) 895 904 { 896 905 struct imx_thermal_data *data = dev_get_drvdata(dev); 897 906 struct regmap *map = data->tempmon; ··· 909 918 910 919 return 0; 911 920 } 912 - #endif 913 921 914 922 static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops, 915 923 imx_thermal_suspend, imx_thermal_resume);
+1 -1
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
··· 65 65 for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) { 66 66 if (priv->uuid_bitmap & (1 << i)) 67 67 if (PAGE_SIZE - length > 0) 68 - length += snprintf(&buf[length], 68 + length += scnprintf(&buf[length], 69 69 PAGE_SIZE - length, 70 70 "%s\n", 71 71 int3400_thermal_uuids[i]);
+5
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
··· 45 45 /* JasperLake thermal reporting device */ 46 46 #define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4503 47 47 48 + /* TigerLake thermal reporting device */ 49 + #define PCI_DEVICE_ID_PROC_TGL_THERMAL 0x9A03 50 + 48 51 #define DRV_NAME "proc_thermal" 49 52 50 53 struct power_config { ··· 731 728 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_ICL_THERMAL), 732 729 .driver_data = (kernel_ulong_t)&rapl_mmio_hsw, }, 733 730 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_JSL_THERMAL)}, 731 + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_TGL_THERMAL), 732 + .driver_data = (kernel_ulong_t)&rapl_mmio_hsw, }, 734 733 { 0, }, 735 734 }; 736 735
+46 -16
drivers/thermal/of-thermal.c
··· 449 449 } 450 450 451 451 /** 452 + * thermal_zone_of_get_sensor_id - get sensor ID from a DT thermal zone 453 + * @tz_np: a valid thermal zone device node. 454 + * @sensor_np: a sensor node of a valid sensor device. 455 + * @id: the sensor ID returned if success. 456 + * 457 + * This function will get sensor ID from a given thermal zone node and 458 + * the sensor node must match the temperature provider @sensor_np. 459 + * 460 + * Return: 0 on success, proper error code otherwise. 461 + */ 462 + 463 + int thermal_zone_of_get_sensor_id(struct device_node *tz_np, 464 + struct device_node *sensor_np, 465 + u32 *id) 466 + { 467 + struct of_phandle_args sensor_specs; 468 + int ret; 469 + 470 + ret = of_parse_phandle_with_args(tz_np, 471 + "thermal-sensors", 472 + "#thermal-sensor-cells", 473 + 0, 474 + &sensor_specs); 475 + if (ret) 476 + return ret; 477 + 478 + if (sensor_specs.np != sensor_np) { 479 + of_node_put(sensor_specs.np); 480 + return -ENODEV; 481 + } 482 + 483 + if (sensor_specs.args_count > 1) 484 + pr_warn("%pOFn: too many cells in sensor specifier %d\n", 485 + sensor_specs.np, sensor_specs.args_count); 486 + 487 + *id = sensor_specs.args_count ? sensor_specs.args[0] : 0; 488 + 489 + of_node_put(sensor_specs.np); 490 + 491 + return 0; 492 + } 493 + EXPORT_SYMBOL_GPL(thermal_zone_of_get_sensor_id); 494 + 495 + /** 452 496 * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone 453 497 * @dev: a valid struct device pointer of a sensor device. Must contain 454 498 * a valid .of_node, for the sensor node. ··· 543 499 sensor_np = of_node_get(dev->of_node); 544 500 545 501 for_each_available_child_of_node(np, child) { 546 - struct of_phandle_args sensor_specs; 547 502 int ret, id; 548 503 549 504 /* For now, thermal framework supports only 1 sensor per zone */ 550 - ret = of_parse_phandle_with_args(child, "thermal-sensors", 551 - "#thermal-sensor-cells", 552 - 0, &sensor_specs); 505 + ret = thermal_zone_of_get_sensor_id(child, sensor_np, &id); 553 506 if (ret) 554 507 continue; 555 508 556 - if (sensor_specs.args_count >= 1) { 557 - id = sensor_specs.args[0]; 558 - WARN(sensor_specs.args_count > 1, 559 - "%pOFn: too many cells in sensor specifier %d\n", 560 - sensor_specs.np, sensor_specs.args_count); 561 - } else { 562 - id = 0; 563 - } 564 - 565 - if (sensor_specs.np == sensor_np && id == sensor_id) { 509 + if (id == sensor_id) { 566 510 tzd = thermal_zone_of_add_sensor(child, sensor_np, 567 511 data, ops); 568 512 if (!IS_ERR(tzd)) 569 513 tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED); 570 514 571 - of_node_put(sensor_specs.np); 572 515 of_node_put(child); 573 516 goto exit; 574 517 } 575 - of_node_put(sensor_specs.np); 576 518 } 577 519 exit: 578 520 of_node_put(sensor_np);
+2 -2
drivers/thermal/qcom/tsens-8960.c
··· 245 245 return adc_code * slope + offset; 246 246 } 247 247 248 - static int get_temp_8960(struct tsens_sensor *s, int *temp) 248 + static int get_temp_8960(const struct tsens_sensor *s, int *temp) 249 249 { 250 250 int ret; 251 251 u32 code, trdy; ··· 279 279 .resume = resume_8960, 280 280 }; 281 281 282 - const struct tsens_plat_data data_8960 = { 282 + struct tsens_plat_data data_8960 = { 283 283 .num_sensors = 11, 284 284 .ops = &ops_8960, 285 285 };
+171 -23
drivers/thermal/qcom/tsens-common.c
··· 23 23 * @low_thresh: lower threshold temperature value 24 24 * @low_irq_mask: mask register for lower threshold irqs 25 25 * @low_irq_clear: clear register for lower threshold irqs 26 + * @crit_viol: critical threshold violated 27 + * @crit_thresh: critical threshold temperature value 28 + * @crit_irq_mask: mask register for critical threshold irqs 29 + * @crit_irq_clear: clear register for critical threshold irqs 26 30 * 27 31 * Structure containing data about temperature threshold settings and 28 32 * irq status if they were violated. ··· 40 36 int low_thresh; 41 37 u32 low_irq_mask; 42 38 u32 low_irq_clear; 39 + u32 crit_viol; 40 + u32 crit_thresh; 41 + u32 crit_irq_mask; 42 + u32 crit_irq_clear; 43 43 }; 44 44 45 45 char *qfprom_read(struct device *dev, const char *cname) ··· 136 128 * Return: Temperature in milliCelsius on success, a negative errno will 137 129 * be returned in error cases 138 130 */ 139 - static int tsens_hw_to_mC(struct tsens_sensor *s, int field) 131 + static int tsens_hw_to_mC(const struct tsens_sensor *s, int field) 140 132 { 141 133 struct tsens_priv *priv = s->priv; 142 134 u32 resolution; ··· 168 160 * 169 161 * Return: ADC code or temperature in deciCelsius. 170 162 */ 171 - static int tsens_mC_to_hw(struct tsens_sensor *s, int temp) 163 + static int tsens_mC_to_hw(const struct tsens_sensor *s, int temp) 172 164 { 173 165 struct tsens_priv *priv = s->priv; 174 166 ··· 197 189 case LOWER: 198 190 index = LOW_INT_CLEAR_0 + hw_id; 199 191 break; 192 + case CRITICAL: 193 + /* No critical interrupts before v2 */ 194 + return; 200 195 } 201 196 regmap_field_write(priv->rf[index], enable ? 0 : 1); 202 197 } ··· 224 213 case LOWER: 225 214 index_mask = LOW_INT_MASK_0 + hw_id; 226 215 index_clear = LOW_INT_CLEAR_0 + hw_id; 216 + break; 217 + case CRITICAL: 218 + index_mask = CRIT_INT_MASK_0 + hw_id; 219 + index_clear = CRIT_INT_CLEAR_0 + hw_id; 227 220 break; 228 221 } 229 222 ··· 283 268 ret = regmap_field_read(priv->rf[LOWER_STATUS_0 + hw_id], &d->low_viol); 284 269 if (ret) 285 270 return ret; 286 - if (d->up_viol || d->low_viol) 271 + 272 + if (priv->feat->crit_int) { 273 + ret = regmap_field_read(priv->rf[CRITICAL_STATUS_0 + hw_id], 274 + &d->crit_viol); 275 + if (ret) 276 + return ret; 277 + } 278 + 279 + if (d->up_viol || d->low_viol || d->crit_viol) 287 280 return 1; 288 281 289 282 return 0; 290 283 } 291 284 292 285 static int tsens_read_irq_state(struct tsens_priv *priv, u32 hw_id, 293 - struct tsens_sensor *s, struct tsens_irq_data *d) 286 + const struct tsens_sensor *s, 287 + struct tsens_irq_data *d) 294 288 { 295 289 int ret; 296 290 ··· 316 292 ret = regmap_field_read(priv->rf[LOW_INT_MASK_0 + hw_id], &d->low_irq_mask); 317 293 if (ret) 318 294 return ret; 295 + ret = regmap_field_read(priv->rf[CRIT_INT_CLEAR_0 + hw_id], 296 + &d->crit_irq_clear); 297 + if (ret) 298 + return ret; 299 + ret = regmap_field_read(priv->rf[CRIT_INT_MASK_0 + hw_id], 300 + &d->crit_irq_mask); 301 + if (ret) 302 + return ret; 303 + 304 + d->crit_thresh = tsens_hw_to_mC(s, CRIT_THRESH_0 + hw_id); 319 305 } else { 320 306 /* No mask register on older TSENS */ 321 307 d->up_irq_mask = 0; 322 308 d->low_irq_mask = 0; 309 + d->crit_irq_clear = 0; 310 + d->crit_irq_mask = 0; 311 + d->crit_thresh = 0; 323 312 } 324 313 325 314 d->up_thresh = tsens_hw_to_mC(s, UP_THRESH_0 + hw_id); 326 315 d->low_thresh = tsens_hw_to_mC(s, LOW_THRESH_0 + hw_id); 327 316 328 - dev_dbg(priv->dev, "[%u] %s%s: status(%u|%u) | clr(%u|%u) | mask(%u|%u)\n", 329 - hw_id, __func__, (d->up_viol || d->low_viol) ? "(V)" : "", 330 - d->low_viol, d->up_viol, d->low_irq_clear, d->up_irq_clear, 331 - d->low_irq_mask, d->up_irq_mask); 332 - dev_dbg(priv->dev, "[%u] %s%s: thresh: (%d:%d)\n", hw_id, __func__, 333 - (d->up_viol || d->low_viol) ? "(violation)" : "", 334 - d->low_thresh, d->up_thresh); 317 + dev_dbg(priv->dev, "[%u] %s%s: status(%u|%u|%u) | clr(%u|%u|%u) | mask(%u|%u|%u)\n", 318 + hw_id, __func__, 319 + (d->up_viol || d->low_viol || d->crit_viol) ? "(V)" : "", 320 + d->low_viol, d->up_viol, d->crit_viol, 321 + d->low_irq_clear, d->up_irq_clear, d->crit_irq_clear, 322 + d->low_irq_mask, d->up_irq_mask, d->crit_irq_mask); 323 + dev_dbg(priv->dev, "[%u] %s%s: thresh: (%d:%d:%d)\n", hw_id, __func__, 324 + (d->up_viol || d->low_viol || d->crit_viol) ? "(V)" : "", 325 + d->low_thresh, d->up_thresh, d->crit_thresh); 335 326 336 327 return 0; 337 328 } ··· 358 319 359 320 /* v1, v0.1 don't have a irq mask register */ 360 321 return 0; 322 + } 323 + 324 + /** 325 + * tsens_critical_irq_thread() - Threaded handler for critical interrupts 326 + * @irq: irq number 327 + * @data: tsens controller private data 328 + * 329 + * Check FSM watchdog bark status and clear if needed. 330 + * Check all sensors to find ones that violated their critical threshold limits. 331 + * Clear and then re-enable the interrupt. 332 + * 333 + * The level-triggered interrupt might deassert if the temperature returned to 334 + * within the threshold limits by the time the handler got scheduled. We 335 + * consider the irq to have been handled in that case. 336 + * 337 + * Return: IRQ_HANDLED 338 + */ 339 + irqreturn_t tsens_critical_irq_thread(int irq, void *data) 340 + { 341 + struct tsens_priv *priv = data; 342 + struct tsens_irq_data d; 343 + int temp, ret, i; 344 + u32 wdog_status, wdog_count; 345 + 346 + if (priv->feat->has_watchdog) { 347 + ret = regmap_field_read(priv->rf[WDOG_BARK_STATUS], 348 + &wdog_status); 349 + if (ret) 350 + return ret; 351 + 352 + if (wdog_status) { 353 + /* Clear WDOG interrupt */ 354 + regmap_field_write(priv->rf[WDOG_BARK_CLEAR], 1); 355 + regmap_field_write(priv->rf[WDOG_BARK_CLEAR], 0); 356 + ret = regmap_field_read(priv->rf[WDOG_BARK_COUNT], 357 + &wdog_count); 358 + if (ret) 359 + return ret; 360 + if (wdog_count) 361 + dev_dbg(priv->dev, "%s: watchdog count: %d\n", 362 + __func__, wdog_count); 363 + 364 + /* Fall through to handle critical interrupts if any */ 365 + } 366 + } 367 + 368 + for (i = 0; i < priv->num_sensors; i++) { 369 + const struct tsens_sensor *s = &priv->sensor[i]; 370 + u32 hw_id = s->hw_id; 371 + 372 + if (IS_ERR(s->tzd)) 373 + continue; 374 + if (!tsens_threshold_violated(priv, hw_id, &d)) 375 + continue; 376 + ret = get_temp_tsens_valid(s, &temp); 377 + if (ret) { 378 + dev_err(priv->dev, "[%u] %s: error reading sensor\n", 379 + hw_id, __func__); 380 + continue; 381 + } 382 + 383 + tsens_read_irq_state(priv, hw_id, s, &d); 384 + if (d.crit_viol && 385 + !masked_irq(hw_id, d.crit_irq_mask, tsens_version(priv))) { 386 + /* Mask critical interrupts, unused on Linux */ 387 + tsens_set_interrupt(priv, hw_id, CRITICAL, false); 388 + } 389 + } 390 + 391 + return IRQ_HANDLED; 361 392 } 362 393 363 394 /** ··· 455 346 456 347 for (i = 0; i < priv->num_sensors; i++) { 457 348 bool trigger = false; 458 - struct tsens_sensor *s = &priv->sensor[i]; 349 + const struct tsens_sensor *s = &priv->sensor[i]; 459 350 u32 hw_id = s->hw_id; 460 351 461 - if (IS_ERR(priv->sensor[i].tzd)) 352 + if (IS_ERR(s->tzd)) 462 353 continue; 463 354 if (!tsens_threshold_violated(priv, hw_id, &d)) 464 355 continue; ··· 477 368 tsens_set_interrupt(priv, hw_id, UPPER, disable); 478 369 if (d.up_thresh > temp) { 479 370 dev_dbg(priv->dev, "[%u] %s: re-arm upper\n", 480 - priv->sensor[i].hw_id, __func__); 371 + hw_id, __func__); 481 372 tsens_set_interrupt(priv, hw_id, UPPER, enable); 482 373 } else { 483 374 trigger = true; ··· 488 379 tsens_set_interrupt(priv, hw_id, LOWER, disable); 489 380 if (d.low_thresh < temp) { 490 381 dev_dbg(priv->dev, "[%u] %s: re-arm low\n", 491 - priv->sensor[i].hw_id, __func__); 382 + hw_id, __func__); 492 383 tsens_set_interrupt(priv, hw_id, LOWER, enable); 493 384 } else { 494 385 trigger = true; ··· 501 392 if (trigger) { 502 393 dev_dbg(priv->dev, "[%u] %s: TZ update trigger (%d mC)\n", 503 394 hw_id, __func__, temp); 504 - thermal_zone_device_update(priv->sensor[i].tzd, 395 + thermal_zone_device_update(s->tzd, 505 396 THERMAL_EVENT_UNSPECIFIED); 506 397 } else { 507 398 dev_dbg(priv->dev, "[%u] %s: no violation: %d\n", ··· 544 435 spin_unlock_irqrestore(&priv->ul_lock, flags); 545 436 546 437 dev_dbg(dev, "[%u] %s: (%d:%d)->(%d:%d)\n", 547 - s->hw_id, __func__, d.low_thresh, d.up_thresh, cl_low, cl_high); 438 + hw_id, __func__, d.low_thresh, d.up_thresh, cl_low, cl_high); 548 439 549 440 return 0; 550 441 } ··· 566 457 regmap_field_write(priv->rf[INT_EN], 0); 567 458 } 568 459 569 - int get_temp_tsens_valid(struct tsens_sensor *s, int *temp) 460 + int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp) 570 461 { 571 462 struct tsens_priv *priv = s->priv; 572 463 int hw_id = s->hw_id; ··· 595 486 return 0; 596 487 } 597 488 598 - int get_temp_common(struct tsens_sensor *s, int *temp) 489 + int get_temp_common(const struct tsens_sensor *s, int *temp) 599 490 { 600 491 struct tsens_priv *priv = s->priv; 601 492 int hw_id = s->hw_id; ··· 699 590 { 700 591 void __iomem *tm_base, *srot_base; 701 592 struct device *dev = priv->dev; 593 + u32 ver_minor; 702 594 struct resource *res; 703 595 u32 enabled; 704 596 int ret, i, j; ··· 712 602 /* DT with separate SROT and TM address space */ 713 603 priv->tm_offset = 0; 714 604 res = platform_get_resource(op, IORESOURCE_MEM, 1); 715 - srot_base = devm_ioremap_resource(&op->dev, res); 605 + srot_base = devm_ioremap_resource(dev, res); 716 606 if (IS_ERR(srot_base)) { 717 607 ret = PTR_ERR(srot_base); 718 608 goto err_put_device; ··· 730 620 } 731 621 732 622 res = platform_get_resource(op, IORESOURCE_MEM, 0); 733 - tm_base = devm_ioremap_resource(&op->dev, res); 623 + tm_base = devm_ioremap_resource(dev, res); 734 624 if (IS_ERR(tm_base)) { 735 625 ret = PTR_ERR(tm_base); 736 626 goto err_put_device; ··· 749 639 if (IS_ERR(priv->rf[i])) 750 640 return PTR_ERR(priv->rf[i]); 751 641 } 642 + ret = regmap_field_read(priv->rf[VER_MINOR], &ver_minor); 643 + if (ret) 644 + goto err_put_device; 752 645 } 753 646 754 647 priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map, ··· 796 683 } 797 684 } 798 685 686 + if (priv->feat->crit_int) { 687 + /* Loop might need changes if enum regfield_ids is reordered */ 688 + for (j = CRITICAL_STATUS_0; j <= CRIT_THRESH_15; j += 16) { 689 + for (i = 0; i < priv->feat->max_sensors; i++) { 690 + int idx = j + i; 691 + 692 + priv->rf[idx] = 693 + devm_regmap_field_alloc(dev, 694 + priv->tm_map, 695 + priv->fields[idx]); 696 + if (IS_ERR(priv->rf[idx])) { 697 + ret = PTR_ERR(priv->rf[idx]); 698 + goto err_put_device; 699 + } 700 + } 701 + } 702 + } 703 + 704 + if (tsens_version(priv) > VER_1_X && ver_minor > 2) { 705 + /* Watchdog is present only on v2.3+ */ 706 + priv->feat->has_watchdog = 1; 707 + for (i = WDOG_BARK_STATUS; i <= CC_MON_MASK; i++) { 708 + priv->rf[i] = devm_regmap_field_alloc(dev, priv->tm_map, 709 + priv->fields[i]); 710 + if (IS_ERR(priv->rf[i])) { 711 + ret = PTR_ERR(priv->rf[i]); 712 + goto err_put_device; 713 + } 714 + } 715 + /* 716 + * Watchdog is already enabled, unmask the bark. 717 + * Disable cycle completion monitoring 718 + */ 719 + regmap_field_write(priv->rf[WDOG_BARK_MASK], 0); 720 + regmap_field_write(priv->rf[CC_MON_MASK], 1); 721 + } 722 + 799 723 spin_lock_init(&priv->ul_lock); 800 724 tsens_enable_irq(priv); 801 725 tsens_debug_init(op); 802 - 803 - return 0; 804 726 805 727 err_put_device: 806 728 put_device(&op->dev);
+3 -3
drivers/thermal/qcom/tsens-v0_1.c
··· 327 327 328 328 /* v0.1: 8916, 8974 */ 329 329 330 - static const struct tsens_features tsens_v0_1_feat = { 330 + static struct tsens_features tsens_v0_1_feat = { 331 331 .ver_major = VER_0_1, 332 332 .crit_int = 0, 333 333 .adc = 1, ··· 377 377 .get_temp = get_temp_common, 378 378 }; 379 379 380 - const struct tsens_plat_data data_8916 = { 380 + struct tsens_plat_data data_8916 = { 381 381 .num_sensors = 5, 382 382 .ops = &ops_8916, 383 383 .hw_ids = (unsigned int []){0, 1, 2, 4, 5 }, ··· 392 392 .get_temp = get_temp_common, 393 393 }; 394 394 395 - const struct tsens_plat_data data_8974 = { 395 + struct tsens_plat_data data_8974 = { 396 396 .num_sensors = 11, 397 397 .ops = &ops_8974, 398 398 .feat = &tsens_v0_1_feat,
+3 -3
drivers/thermal/qcom/tsens-v1.c
··· 299 299 300 300 /* v1.x: msm8956,8976,qcs404,405 */ 301 301 302 - static const struct tsens_features tsens_v1_feat = { 302 + static struct tsens_features tsens_v1_feat = { 303 303 .ver_major = VER_1_X, 304 304 .crit_int = 0, 305 305 .adc = 1, ··· 368 368 .get_temp = get_temp_tsens_valid, 369 369 }; 370 370 371 - const struct tsens_plat_data data_tsens_v1 = { 371 + struct tsens_plat_data data_tsens_v1 = { 372 372 .ops = &ops_generic_v1, 373 373 .feat = &tsens_v1_feat, 374 374 .fields = tsens_v1_regfields, ··· 381 381 }; 382 382 383 383 /* Valid for both MSM8956 and MSM8976. Sensor ID 3 is unused. */ 384 - const struct tsens_plat_data data_8976 = { 384 + struct tsens_plat_data data_8976 = { 385 385 .num_sensors = 11, 386 386 .ops = &ops_8976, 387 387 .hw_ids = (unsigned int[]){0, 1, 2, 4, 5, 6, 7, 8, 9, 10},
+19 -5
drivers/thermal/qcom/tsens-v2.c
··· 24 24 #define TM_Sn_CRITICAL_THRESHOLD_OFF 0x0060 25 25 #define TM_Sn_STATUS_OFF 0x00a0 26 26 #define TM_TRDY_OFF 0x00e4 27 + #define TM_WDOG_LOG_OFF 0x013c 27 28 28 29 /* v2.x: 8996, 8998, sdm845 */ 29 30 30 - static const struct tsens_features tsens_v2_feat = { 31 + static struct tsens_features tsens_v2_feat = { 31 32 .ver_major = VER_2_X, 32 33 .crit_int = 1, 33 34 .adc = 0, ··· 52 51 [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 2), 53 52 54 53 /* TEMPERATURE THRESHOLDS */ 55 - REG_FIELD_FOR_EACH_SENSOR16(LOW_THRESH, TM_Sn_UPPER_LOWER_THRESHOLD_OFF, 0, 11), 56 - REG_FIELD_FOR_EACH_SENSOR16(UP_THRESH, TM_Sn_UPPER_LOWER_THRESHOLD_OFF, 12, 23), 54 + REG_FIELD_FOR_EACH_SENSOR16(LOW_THRESH, TM_Sn_UPPER_LOWER_THRESHOLD_OFF, 0, 11), 55 + REG_FIELD_FOR_EACH_SENSOR16(UP_THRESH, TM_Sn_UPPER_LOWER_THRESHOLD_OFF, 12, 23), 56 + REG_FIELD_FOR_EACH_SENSOR16(CRIT_THRESH, TM_Sn_CRITICAL_THRESHOLD_OFF, 0, 11), 57 57 58 58 /* INTERRUPTS [CLEAR/STATUS/MASK] */ 59 59 REG_FIELD_SPLIT_BITS_0_15(LOW_INT_STATUS, TM_UPPER_LOWER_INT_STATUS_OFF), ··· 63 61 REG_FIELD_SPLIT_BITS_16_31(UP_INT_STATUS, TM_UPPER_LOWER_INT_STATUS_OFF), 64 62 REG_FIELD_SPLIT_BITS_16_31(UP_INT_CLEAR, TM_UPPER_LOWER_INT_CLEAR_OFF), 65 63 REG_FIELD_SPLIT_BITS_16_31(UP_INT_MASK, TM_UPPER_LOWER_INT_MASK_OFF), 64 + REG_FIELD_SPLIT_BITS_0_15(CRIT_INT_STATUS, TM_CRITICAL_INT_STATUS_OFF), 65 + REG_FIELD_SPLIT_BITS_0_15(CRIT_INT_CLEAR, TM_CRITICAL_INT_CLEAR_OFF), 66 + REG_FIELD_SPLIT_BITS_0_15(CRIT_INT_MASK, TM_CRITICAL_INT_MASK_OFF), 67 + 68 + /* WATCHDOG on v2.3 or later */ 69 + [WDOG_BARK_STATUS] = REG_FIELD(TM_CRITICAL_INT_STATUS_OFF, 31, 31), 70 + [WDOG_BARK_CLEAR] = REG_FIELD(TM_CRITICAL_INT_CLEAR_OFF, 31, 31), 71 + [WDOG_BARK_MASK] = REG_FIELD(TM_CRITICAL_INT_MASK_OFF, 31, 31), 72 + [CC_MON_STATUS] = REG_FIELD(TM_CRITICAL_INT_STATUS_OFF, 30, 30), 73 + [CC_MON_CLEAR] = REG_FIELD(TM_CRITICAL_INT_CLEAR_OFF, 30, 30), 74 + [CC_MON_MASK] = REG_FIELD(TM_CRITICAL_INT_MASK_OFF, 30, 30), 75 + [WDOG_BARK_COUNT] = REG_FIELD(TM_WDOG_LOG_OFF, 0, 7), 66 76 67 77 /* Sn_STATUS */ 68 78 REG_FIELD_FOR_EACH_SENSOR16(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 11), ··· 95 81 .get_temp = get_temp_tsens_valid, 96 82 }; 97 83 98 - const struct tsens_plat_data data_tsens_v2 = { 84 + struct tsens_plat_data data_tsens_v2 = { 99 85 .ops = &ops_generic_v2, 100 86 .feat = &tsens_v2_feat, 101 87 .fields = tsens_v2_regfields, 102 88 }; 103 89 104 90 /* Kept around for backward compatibility with old msm8996.dtsi */ 105 - const struct tsens_plat_data data_8996 = { 91 + struct tsens_plat_data data_8996 = { 106 92 .num_sensors = 13, 107 93 .ops = &ops_generic_v2, 108 94 .feat = &tsens_v2_feat,
+39 -26
drivers/thermal/qcom/tsens.c
··· 85 85 .set_trips = tsens_set_trips, 86 86 }; 87 87 88 + static int tsens_register_irq(struct tsens_priv *priv, char *irqname, 89 + irq_handler_t thread_fn) 90 + { 91 + struct platform_device *pdev; 92 + int ret, irq; 93 + 94 + pdev = of_find_device_by_node(priv->dev->of_node); 95 + if (!pdev) 96 + return -ENODEV; 97 + 98 + irq = platform_get_irq_byname(pdev, irqname); 99 + if (irq < 0) { 100 + ret = irq; 101 + /* For old DTs with no IRQ defined */ 102 + if (irq == -ENXIO) 103 + ret = 0; 104 + } else { 105 + ret = devm_request_threaded_irq(&pdev->dev, irq, 106 + NULL, thread_fn, 107 + IRQF_ONESHOT, 108 + dev_name(&pdev->dev), priv); 109 + if (ret) 110 + dev_err(&pdev->dev, "%s: failed to get irq\n", 111 + __func__); 112 + else 113 + enable_irq_wake(irq); 114 + } 115 + 116 + put_device(&pdev->dev); 117 + return ret; 118 + } 119 + 88 120 static int tsens_register(struct tsens_priv *priv) 89 121 { 90 - int i, ret, irq; 122 + int i, ret; 91 123 struct thermal_zone_device *tzd; 92 - struct platform_device *pdev; 93 124 94 125 for (i = 0; i < priv->num_sensors; i++) { 95 126 priv->sensor[i].priv = priv; ··· 134 103 priv->ops->enable(priv, i); 135 104 } 136 105 137 - pdev = of_find_device_by_node(priv->dev->of_node); 138 - if (!pdev) 139 - return -ENODEV; 106 + ret = tsens_register_irq(priv, "uplow", tsens_irq_thread); 107 + if (ret < 0) 108 + return ret; 140 109 141 - irq = platform_get_irq_byname(pdev, "uplow"); 142 - if (irq < 0) { 143 - ret = irq; 144 - /* For old DTs with no IRQ defined */ 145 - if (irq == -ENXIO) 146 - ret = 0; 147 - goto err_put_device; 148 - } 110 + if (priv->feat->crit_int) 111 + ret = tsens_register_irq(priv, "critical", 112 + tsens_critical_irq_thread); 149 113 150 - ret = devm_request_threaded_irq(&pdev->dev, irq, 151 - NULL, tsens_irq_thread, 152 - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 153 - dev_name(&pdev->dev), priv); 154 - if (ret) { 155 - dev_err(&pdev->dev, "%s: failed to get irq\n", __func__); 156 - goto err_put_device; 157 - } 158 - 159 - enable_irq_wake(irq); 160 - 161 - err_put_device: 162 - put_device(&pdev->dev); 163 114 return ret; 164 115 } 165 116
+95 -10
drivers/thermal/qcom/tsens.h
··· 23 23 24 24 struct tsens_priv; 25 25 26 + /* IP version numbers in ascending order */ 26 27 enum tsens_ver { 27 28 VER_0_1 = 0, 28 29 VER_1_X, ··· 33 32 enum tsens_irq_type { 34 33 LOWER, 35 34 UPPER, 35 + CRITICAL, 36 36 }; 37 37 38 38 /** ··· 69 67 /* mandatory callbacks */ 70 68 int (*init)(struct tsens_priv *priv); 71 69 int (*calibrate)(struct tsens_priv *priv); 72 - int (*get_temp)(struct tsens_sensor *s, int *temp); 70 + int (*get_temp)(const struct tsens_sensor *s, int *temp); 73 71 /* optional callbacks */ 74 72 int (*enable)(struct tsens_priv *priv, int i); 75 73 void (*disable)(struct tsens_priv *priv); ··· 376 374 CRITICAL_STATUS_13, 377 375 CRITICAL_STATUS_14, 378 376 CRITICAL_STATUS_15, 377 + CRIT_INT_STATUS_0, /* CRITICAL interrupt status */ 378 + CRIT_INT_STATUS_1, 379 + CRIT_INT_STATUS_2, 380 + CRIT_INT_STATUS_3, 381 + CRIT_INT_STATUS_4, 382 + CRIT_INT_STATUS_5, 383 + CRIT_INT_STATUS_6, 384 + CRIT_INT_STATUS_7, 385 + CRIT_INT_STATUS_8, 386 + CRIT_INT_STATUS_9, 387 + CRIT_INT_STATUS_10, 388 + CRIT_INT_STATUS_11, 389 + CRIT_INT_STATUS_12, 390 + CRIT_INT_STATUS_13, 391 + CRIT_INT_STATUS_14, 392 + CRIT_INT_STATUS_15, 393 + CRIT_INT_CLEAR_0, /* CRITICAL interrupt clear */ 394 + CRIT_INT_CLEAR_1, 395 + CRIT_INT_CLEAR_2, 396 + CRIT_INT_CLEAR_3, 397 + CRIT_INT_CLEAR_4, 398 + CRIT_INT_CLEAR_5, 399 + CRIT_INT_CLEAR_6, 400 + CRIT_INT_CLEAR_7, 401 + CRIT_INT_CLEAR_8, 402 + CRIT_INT_CLEAR_9, 403 + CRIT_INT_CLEAR_10, 404 + CRIT_INT_CLEAR_11, 405 + CRIT_INT_CLEAR_12, 406 + CRIT_INT_CLEAR_13, 407 + CRIT_INT_CLEAR_14, 408 + CRIT_INT_CLEAR_15, 409 + CRIT_INT_MASK_0, /* CRITICAL interrupt mask */ 410 + CRIT_INT_MASK_1, 411 + CRIT_INT_MASK_2, 412 + CRIT_INT_MASK_3, 413 + CRIT_INT_MASK_4, 414 + CRIT_INT_MASK_5, 415 + CRIT_INT_MASK_6, 416 + CRIT_INT_MASK_7, 417 + CRIT_INT_MASK_8, 418 + CRIT_INT_MASK_9, 419 + CRIT_INT_MASK_10, 420 + CRIT_INT_MASK_11, 421 + CRIT_INT_MASK_12, 422 + CRIT_INT_MASK_13, 423 + CRIT_INT_MASK_14, 424 + CRIT_INT_MASK_15, 425 + CRIT_THRESH_0, /* CRITICAL threshold values */ 426 + CRIT_THRESH_1, 427 + CRIT_THRESH_2, 428 + CRIT_THRESH_3, 429 + CRIT_THRESH_4, 430 + CRIT_THRESH_5, 431 + CRIT_THRESH_6, 432 + CRIT_THRESH_7, 433 + CRIT_THRESH_8, 434 + CRIT_THRESH_9, 435 + CRIT_THRESH_10, 436 + CRIT_THRESH_11, 437 + CRIT_THRESH_12, 438 + CRIT_THRESH_13, 439 + CRIT_THRESH_14, 440 + CRIT_THRESH_15, 441 + 442 + /* WATCHDOG */ 443 + WDOG_BARK_STATUS, 444 + WDOG_BARK_CLEAR, 445 + WDOG_BARK_MASK, 446 + WDOG_BARK_COUNT, 447 + 448 + /* CYCLE COMPLETION MONITOR */ 449 + CC_MON_STATUS, 450 + CC_MON_CLEAR, 451 + CC_MON_MASK, 452 + 379 453 MIN_STATUS_0, /* MIN threshold violated */ 380 454 MIN_STATUS_1, 381 455 MIN_STATUS_2, ··· 496 418 * @adc: do the sensors only output adc code (instead of temperature)? 497 419 * @srot_split: does the IP neatly splits the register space into SROT and TM, 498 420 * with SROT only being available to secure boot firmware? 421 + * @has_watchdog: does this IP support watchdog functionality? 499 422 * @max_sensors: maximum sensors supported by this version of the IP 500 423 */ 501 424 struct tsens_features { ··· 504 425 unsigned int crit_int:1; 505 426 unsigned int adc:1; 506 427 unsigned int srot_split:1; 428 + unsigned int has_watchdog:1; 507 429 unsigned int max_sensors; 508 430 }; 509 431 ··· 520 440 const u32 num_sensors; 521 441 const struct tsens_ops *ops; 522 442 unsigned int *hw_ids; 523 - const struct tsens_features *feat; 443 + struct tsens_features *feat; 524 444 const struct reg_field *fields; 525 445 }; 526 446 527 447 /** 528 448 * struct tsens_context - Registers to be saved/restored across a context loss 449 + * @threshold: Threshold register value 450 + * @control: Control register value 529 451 */ 530 452 struct tsens_context { 531 453 int threshold; ··· 542 460 * @srot_map: pointer to SROT register address space 543 461 * @tm_offset: deal with old device trees that don't address TM and SROT 544 462 * address space separately 463 + * @ul_lock: lock while processing upper/lower threshold interrupts 464 + * @crit_lock: lock while processing critical threshold interrupts 545 465 * @rf: array of regmap_fields used to store value of the field 546 466 * @ctx: registers to be saved and restored during suspend/resume 547 467 * @feat: features of the IP ··· 565 481 566 482 struct regmap_field *rf[MAX_REGFIELDS]; 567 483 struct tsens_context ctx; 568 - const struct tsens_features *feat; 484 + struct tsens_features *feat; 569 485 const struct reg_field *fields; 570 486 const struct tsens_ops *ops; 571 487 572 488 struct dentry *debug_root; 573 489 struct dentry *debug; 574 490 575 - struct tsens_sensor sensor[0]; 491 + struct tsens_sensor sensor[]; 576 492 }; 577 493 578 494 char *qfprom_read(struct device *dev, const char *cname); 579 495 void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode); 580 496 int init_common(struct tsens_priv *priv); 581 - int get_temp_tsens_valid(struct tsens_sensor *s, int *temp); 582 - int get_temp_common(struct tsens_sensor *s, int *temp); 497 + int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp); 498 + int get_temp_common(const struct tsens_sensor *s, int *temp); 583 499 int tsens_enable_irq(struct tsens_priv *priv); 584 500 void tsens_disable_irq(struct tsens_priv *priv); 585 501 int tsens_set_trips(void *_sensor, int low, int high); 586 502 irqreturn_t tsens_irq_thread(int irq, void *data); 503 + irqreturn_t tsens_critical_irq_thread(int irq, void *data); 587 504 588 505 /* TSENS target */ 589 - extern const struct tsens_plat_data data_8960; 506 + extern struct tsens_plat_data data_8960; 590 507 591 508 /* TSENS v0.1 targets */ 592 - extern const struct tsens_plat_data data_8916, data_8974; 509 + extern struct tsens_plat_data data_8916, data_8974; 593 510 594 511 /* TSENS v1 targets */ 595 - extern const struct tsens_plat_data data_tsens_v1, data_8976; 512 + extern struct tsens_plat_data data_tsens_v1, data_8976; 596 513 597 514 /* TSENS v2 targets */ 598 - extern const struct tsens_plat_data data_8996, data_tsens_v2; 515 + extern struct tsens_plat_data data_8996, data_tsens_v2; 599 516 600 517 #endif /* __QCOM_TSENS_H__ */
+16 -24
drivers/thermal/qoriq_thermal.c
··· 3 3 // Copyright 2016 Freescale Semiconductor, Inc. 4 4 5 5 #include <linux/clk.h> 6 - #include <linux/module.h> 7 - #include <linux/platform_device.h> 8 6 #include <linux/err.h> 9 7 #include <linux/io.h> 8 + #include <linux/module.h> 10 9 #include <linux/of.h> 11 - #include <linux/of_address.h> 10 + #include <linux/platform_device.h> 12 11 #include <linux/regmap.h> 13 12 #include <linux/sizes.h> 14 13 #include <linux/thermal.h> ··· 227 228 .n_yes_ranges = ARRAY_SIZE(qoriq_yes_ranges), 228 229 }; 229 230 231 + static void qoriq_tmu_action(void *p) 232 + { 233 + struct qoriq_tmu_data *data = p; 234 + 235 + regmap_write(data->regmap, REGS_TMR, TMR_DISABLE); 236 + clk_disable_unprepare(data->clk); 237 + } 238 + 230 239 static int qoriq_tmu_probe(struct platform_device *pdev) 231 240 { 232 241 int ret; ··· 285 278 return ret; 286 279 } 287 280 281 + ret = devm_add_action_or_reset(dev, qoriq_tmu_action, data); 282 + if (ret) 283 + return ret; 284 + 288 285 /* version register offset at: 0xbf8 on both v1 and v2 */ 289 286 ret = regmap_read(data->regmap, REGS_IPBRR(0), &ver); 290 287 if (ret) { ··· 301 290 302 291 ret = qoriq_tmu_calibration(dev, data); /* TMU calibration */ 303 292 if (ret < 0) 304 - goto err; 293 + return ret; 305 294 306 295 ret = qoriq_tmu_register_tmu_zone(dev, data); 307 296 if (ret < 0) { 308 297 dev_err(dev, "Failed to register sensors\n"); 309 - ret = -ENODEV; 310 - goto err; 298 + return ret; 311 299 } 312 300 313 301 platform_set_drvdata(pdev, data); 314 - 315 - return 0; 316 - 317 - err: 318 - clk_disable_unprepare(data->clk); 319 - 320 - return ret; 321 - } 322 - 323 - static int qoriq_tmu_remove(struct platform_device *pdev) 324 - { 325 - struct qoriq_tmu_data *data = platform_get_drvdata(pdev); 326 - 327 - /* Disable monitoring */ 328 - regmap_write(data->regmap, REGS_TMR, TMR_DISABLE); 329 - 330 - clk_disable_unprepare(data->clk); 331 302 332 303 return 0; 333 304 } ··· 358 365 .of_match_table = qoriq_tmu_match, 359 366 }, 360 367 .probe = qoriq_tmu_probe, 361 - .remove = qoriq_tmu_remove, 362 368 }; 363 369 module_platform_driver(qoriq_tmu); 364 370
+17 -14
drivers/thermal/rcar_gen3_thermal.c
··· 81 81 void __iomem *base; 82 82 struct thermal_zone_device *zone; 83 83 struct equation_coefs coef; 84 - int low; 85 - int high; 86 84 int tj_t; 87 85 int id; /* thermal channel id */ 88 86 }; ··· 202 204 return INT_FIXPT(val); 203 205 } 204 206 205 - static int rcar_gen3_thermal_set_trips(void *devdata, int low, int high) 207 + static int rcar_gen3_thermal_update_range(struct rcar_gen3_thermal_tsc *tsc) 206 208 { 207 - struct rcar_gen3_thermal_tsc *tsc = devdata; 209 + int temperature, low, high; 208 210 209 - low = clamp_val(low, -40000, 120000); 210 - high = clamp_val(high, -40000, 120000); 211 + rcar_gen3_thermal_get_temp(tsc, &temperature); 212 + 213 + low = temperature - MCELSIUS(1); 214 + high = temperature + MCELSIUS(1); 211 215 212 216 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1, 213 217 rcar_gen3_thermal_mcelsius_to_temp(tsc, low)); ··· 217 217 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP2, 218 218 rcar_gen3_thermal_mcelsius_to_temp(tsc, high)); 219 219 220 - tsc->low = low; 221 - tsc->high = high; 222 - 223 220 return 0; 224 221 } 225 222 226 223 static const struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = { 227 224 .get_temp = rcar_gen3_thermal_get_temp, 228 - .set_trips = rcar_gen3_thermal_set_trips, 229 225 }; 230 226 231 227 static void rcar_thermal_irq_set(struct rcar_gen3_thermal_priv *priv, bool on) ··· 242 246 for (i = 0; i < priv->num_tscs; i++) { 243 247 status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR); 244 248 rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0); 245 - if (status) 249 + if (status) { 250 + rcar_gen3_thermal_update_range(priv->tscs[i]); 246 251 thermal_zone_device_update(priv->tscs[i]->zone, 247 252 THERMAL_EVENT_UNSPECIFIED); 253 + } 248 254 } 249 255 250 256 return IRQ_HANDLED; ··· 320 322 }, 321 323 { 322 324 .compatible = "renesas,r8a7796-thermal", 325 + .data = &rcar_gen3_ths_tj_1_m3_w, 326 + }, 327 + { 328 + .compatible = "renesas,r8a77961-thermal", 323 329 .data = &rcar_gen3_ths_tj_1_m3_w, 324 330 }, 325 331 { ··· 448 446 goto error_unregister; 449 447 450 448 ret = devm_add_action_or_reset(dev, rcar_gen3_hwmon_action, zone); 451 - if (ret) { 449 + if (ret) 452 450 goto error_unregister; 453 - } 454 451 455 452 ret = of_thermal_get_ntrips(tsc->zone); 456 453 if (ret < 0) 457 454 goto error_unregister; 455 + 456 + rcar_gen3_thermal_update_range(tsc); 458 457 459 458 dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret); 460 459 } ··· 495 492 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; 496 493 497 494 priv->thermal_init(tsc); 498 - rcar_gen3_thermal_set_trips(tsc, tsc->low, tsc->high); 495 + rcar_gen3_thermal_update_range(tsc); 499 496 } 500 497 501 498 rcar_thermal_irq_set(priv, true);
+17 -36
drivers/thermal/rcar_thermal.c
··· 95 95 struct mutex lock; 96 96 struct list_head list; 97 97 int id; 98 - u32 ctemp; 99 98 }; 100 99 101 100 #define rcar_thermal_for_each_priv(pos, common) \ ··· 200 201 struct device *dev = rcar_priv_to_dev(priv); 201 202 int i; 202 203 u32 ctemp, old, new; 203 - int ret = -EINVAL; 204 204 205 205 mutex_lock(&priv->lock); 206 206 ··· 245 247 ((ctemp - 1) << 0))); 246 248 } 247 249 248 - dev_dbg(dev, "thermal%d %d -> %d\n", priv->id, priv->ctemp, ctemp); 249 - 250 - priv->ctemp = ctemp; 251 - ret = 0; 252 250 err_out_unlock: 253 251 mutex_unlock(&priv->lock); 254 - return ret; 252 + 253 + return ctemp ? ctemp : -EINVAL; 255 254 } 256 255 257 256 static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv, 258 257 int *temp) 259 258 { 260 - int tmp; 261 - int ret; 259 + int ctemp; 262 260 263 - ret = rcar_thermal_update_temp(priv); 264 - if (ret < 0) 265 - return ret; 266 - 267 - mutex_lock(&priv->lock); 268 - if (priv->chip->ctemp_bands == 1) 269 - tmp = MCELSIUS((priv->ctemp * 5) - 65); 270 - else if (priv->ctemp < 24) 271 - tmp = MCELSIUS(((priv->ctemp * 55) - 720) / 10); 272 - else 273 - tmp = MCELSIUS((priv->ctemp * 5) - 60); 274 - mutex_unlock(&priv->lock); 261 + ctemp = rcar_thermal_update_temp(priv); 262 + if (ctemp < 0) 263 + return ctemp; 275 264 276 265 /* Guaranteed operating range is -45C to 125C. */ 277 266 278 - *temp = tmp; 267 + if (priv->chip->ctemp_bands == 1) 268 + *temp = MCELSIUS((ctemp * 5) - 65); 269 + else if (ctemp < 24) 270 + *temp = MCELSIUS(((ctemp * 55) - 720) / 10); 271 + else 272 + *temp = MCELSIUS((ctemp * 5) - 60); 279 273 280 274 return 0; 281 275 } ··· 377 387 static void rcar_thermal_work(struct work_struct *work) 378 388 { 379 389 struct rcar_thermal_priv *priv; 380 - int cctemp, nctemp; 381 390 int ret; 382 391 383 392 priv = container_of(work, struct rcar_thermal_priv, work.work); 384 - 385 - ret = rcar_thermal_get_current_temp(priv, &cctemp); 386 - if (ret < 0) 387 - return; 388 393 389 394 ret = rcar_thermal_update_temp(priv); 390 395 if (ret < 0) ··· 387 402 388 403 rcar_thermal_irq_enable(priv); 389 404 390 - ret = rcar_thermal_get_current_temp(priv, &nctemp); 391 - if (ret < 0) 392 - return; 393 - 394 - if (nctemp != cctemp) 395 - thermal_zone_device_update(priv->zone, 396 - THERMAL_EVENT_UNSPECIFIED); 405 + thermal_zone_device_update(priv->zone, THERMAL_EVENT_UNSPECIFIED); 397 406 } 398 407 399 408 static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status) ··· 500 521 res = platform_get_resource(pdev, IORESOURCE_MEM, 501 522 mres++); 502 523 common->base = devm_ioremap_resource(dev, res); 503 - if (IS_ERR(common->base)) 504 - return PTR_ERR(common->base); 524 + if (IS_ERR(common->base)) { 525 + ret = PTR_ERR(common->base); 526 + goto error_unregister; 527 + } 505 528 506 529 idle = 0; /* polling delay is not needed */ 507 530 }
+3 -1
drivers/thermal/samsung/exynos_tmu.c
··· 1094 1094 &exynos_sensor_ops); 1095 1095 if (IS_ERR(data->tzd)) { 1096 1096 ret = PTR_ERR(data->tzd); 1097 - dev_err(&pdev->dev, "Failed to register sensor: %d\n", ret); 1097 + if (ret != -EPROBE_DEFER) 1098 + dev_err(&pdev->dev, "Failed to register sensor: %d\n", 1099 + ret); 1098 1100 goto err_sclk; 1099 1101 } 1100 1102
+552
drivers/thermal/sprd_thermal.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (C) 2020 Spreadtrum Communications Inc. 3 + 4 + #include <linux/clk.h> 5 + #include <linux/io.h> 6 + #include <linux/iopoll.h> 7 + #include <linux/module.h> 8 + #include <linux/nvmem-consumer.h> 9 + #include <linux/of_device.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/slab.h> 12 + #include <linux/thermal.h> 13 + 14 + #define SPRD_THM_CTL 0x0 15 + #define SPRD_THM_INT_EN 0x4 16 + #define SPRD_THM_INT_STS 0x8 17 + #define SPRD_THM_INT_RAW_STS 0xc 18 + #define SPRD_THM_DET_PERIOD 0x10 19 + #define SPRD_THM_INT_CLR 0x14 20 + #define SPRD_THM_INT_CLR_ST 0x18 21 + #define SPRD_THM_MON_PERIOD 0x4c 22 + #define SPRD_THM_MON_CTL 0x50 23 + #define SPRD_THM_INTERNAL_STS1 0x54 24 + #define SPRD_THM_RAW_READ_MSK 0x3ff 25 + 26 + #define SPRD_THM_OFFSET(id) ((id) * 0x4) 27 + #define SPRD_THM_TEMP(id) (SPRD_THM_OFFSET(id) + 0x5c) 28 + #define SPRD_THM_THRES(id) (SPRD_THM_OFFSET(id) + 0x2c) 29 + 30 + #define SPRD_THM_SEN(id) BIT((id) + 2) 31 + #define SPRD_THM_SEN_OVERHEAT_EN(id) BIT((id) + 8) 32 + #define SPRD_THM_SEN_OVERHEAT_ALARM_EN(id) BIT((id) + 0) 33 + 34 + /* bits definitions for register THM_CTL */ 35 + #define SPRD_THM_SET_RDY_ST BIT(13) 36 + #define SPRD_THM_SET_RDY BIT(12) 37 + #define SPRD_THM_MON_EN BIT(1) 38 + #define SPRD_THM_EN BIT(0) 39 + 40 + /* bits definitions for register THM_INT_CTL */ 41 + #define SPRD_THM_BIT_INT_EN BIT(26) 42 + #define SPRD_THM_OVERHEAT_EN BIT(25) 43 + #define SPRD_THM_OTP_TRIP_SHIFT 10 44 + 45 + /* bits definitions for register SPRD_THM_INTERNAL_STS1 */ 46 + #define SPRD_THM_TEMPER_RDY BIT(0) 47 + 48 + #define SPRD_THM_DET_PERIOD_DATA 0x800 49 + #define SPRD_THM_DET_PERIOD_MASK GENMASK(19, 0) 50 + #define SPRD_THM_MON_MODE 0x7 51 + #define SPRD_THM_MON_MODE_MASK GENMASK(3, 0) 52 + #define SPRD_THM_MON_PERIOD_DATA 0x10 53 + #define SPRD_THM_MON_PERIOD_MASK GENMASK(15, 0) 54 + #define SPRD_THM_THRES_MASK GENMASK(19, 0) 55 + #define SPRD_THM_INT_CLR_MASK GENMASK(24, 0) 56 + 57 + /* thermal sensor calibration parameters */ 58 + #define SPRD_THM_TEMP_LOW -40000 59 + #define SPRD_THM_TEMP_HIGH 120000 60 + #define SPRD_THM_OTP_TEMP 120000 61 + #define SPRD_THM_HOT_TEMP 75000 62 + #define SPRD_THM_RAW_DATA_LOW 0 63 + #define SPRD_THM_RAW_DATA_HIGH 1000 64 + #define SPRD_THM_SEN_NUM 8 65 + #define SPRD_THM_DT_OFFSET 24 66 + #define SPRD_THM_RATION_OFFSET 17 67 + #define SPRD_THM_RATION_SIGN 16 68 + 69 + #define SPRD_THM_RDYST_POLLING_TIME 10 70 + #define SPRD_THM_RDYST_TIMEOUT 700 71 + #define SPRD_THM_TEMP_READY_POLL_TIME 10000 72 + #define SPRD_THM_TEMP_READY_TIMEOUT 600000 73 + #define SPRD_THM_MAX_SENSOR 8 74 + 75 + struct sprd_thermal_sensor { 76 + struct thermal_zone_device *tzd; 77 + struct sprd_thermal_data *data; 78 + struct device *dev; 79 + int cal_slope; 80 + int cal_offset; 81 + int id; 82 + }; 83 + 84 + struct sprd_thermal_data { 85 + const struct sprd_thm_variant_data *var_data; 86 + struct sprd_thermal_sensor *sensor[SPRD_THM_MAX_SENSOR]; 87 + struct clk *clk; 88 + void __iomem *base; 89 + u32 ratio_off; 90 + int ratio_sign; 91 + int nr_sensors; 92 + }; 93 + 94 + /* 95 + * The conversion between ADC and temperature is based on linear relationship, 96 + * and use idea_k to specify the slope and ideal_b to specify the offset. 97 + * 98 + * Since different Spreadtrum SoCs have different ideal_k and ideal_b, 99 + * we should save ideal_k and ideal_b in the device data structure. 100 + */ 101 + struct sprd_thm_variant_data { 102 + u32 ideal_k; 103 + u32 ideal_b; 104 + }; 105 + 106 + static const struct sprd_thm_variant_data ums512_data = { 107 + .ideal_k = 262, 108 + .ideal_b = 66400, 109 + }; 110 + 111 + static inline void sprd_thm_update_bits(void __iomem *reg, u32 mask, u32 val) 112 + { 113 + u32 tmp, orig; 114 + 115 + orig = readl(reg); 116 + tmp = orig & ~mask; 117 + tmp |= val & mask; 118 + writel(tmp, reg); 119 + } 120 + 121 + static int sprd_thm_cal_read(struct device_node *np, const char *cell_id, 122 + u32 *val) 123 + { 124 + struct nvmem_cell *cell; 125 + void *buf; 126 + size_t len; 127 + 128 + cell = of_nvmem_cell_get(np, cell_id); 129 + if (IS_ERR(cell)) 130 + return PTR_ERR(cell); 131 + 132 + buf = nvmem_cell_read(cell, &len); 133 + nvmem_cell_put(cell); 134 + if (IS_ERR(buf)) 135 + return PTR_ERR(buf); 136 + 137 + if (len > sizeof(u32)) { 138 + kfree(buf); 139 + return -EINVAL; 140 + } 141 + 142 + memcpy(val, buf, len); 143 + 144 + kfree(buf); 145 + return 0; 146 + } 147 + 148 + static int sprd_thm_sensor_calibration(struct device_node *np, 149 + struct sprd_thermal_data *thm, 150 + struct sprd_thermal_sensor *sen) 151 + { 152 + int ret; 153 + /* 154 + * According to thermal datasheet, the default calibration offset is 64, 155 + * and the default ratio is 1000. 156 + */ 157 + int dt_offset = 64, ratio = 1000; 158 + 159 + ret = sprd_thm_cal_read(np, "sen_delta_cal", &dt_offset); 160 + if (ret) 161 + return ret; 162 + 163 + ratio += thm->ratio_sign * thm->ratio_off; 164 + 165 + /* 166 + * According to the ideal slope K and ideal offset B, combined with 167 + * calibration value of thermal from efuse, then calibrate the real 168 + * slope k and offset b: 169 + * k_cal = (k * ratio) / 1000. 170 + * b_cal = b + (dt_offset - 64) * 500. 171 + */ 172 + sen->cal_slope = (thm->var_data->ideal_k * ratio) / 1000; 173 + sen->cal_offset = thm->var_data->ideal_b + (dt_offset - 128) * 250; 174 + 175 + return 0; 176 + } 177 + 178 + static int sprd_thm_rawdata_to_temp(struct sprd_thermal_sensor *sen, 179 + u32 rawdata) 180 + { 181 + clamp(rawdata, (u32)SPRD_THM_RAW_DATA_LOW, (u32)SPRD_THM_RAW_DATA_HIGH); 182 + 183 + /* 184 + * According to the thermal datasheet, the formula of converting 185 + * adc value to the temperature value should be: 186 + * T_final = k_cal * x - b_cal. 187 + */ 188 + return sen->cal_slope * rawdata - sen->cal_offset; 189 + } 190 + 191 + static int sprd_thm_temp_to_rawdata(int temp, struct sprd_thermal_sensor *sen) 192 + { 193 + u32 val; 194 + 195 + clamp(temp, (int)SPRD_THM_TEMP_LOW, (int)SPRD_THM_TEMP_HIGH); 196 + 197 + /* 198 + * According to the thermal datasheet, the formula of converting 199 + * adc value to the temperature value should be: 200 + * T_final = k_cal * x - b_cal. 201 + */ 202 + val = (temp + sen->cal_offset) / sen->cal_slope; 203 + 204 + return clamp(val, val, (u32)(SPRD_THM_RAW_DATA_HIGH - 1)); 205 + } 206 + 207 + static int sprd_thm_read_temp(void *devdata, int *temp) 208 + { 209 + struct sprd_thermal_sensor *sen = devdata; 210 + u32 data; 211 + 212 + data = readl(sen->data->base + SPRD_THM_TEMP(sen->id)) & 213 + SPRD_THM_RAW_READ_MSK; 214 + 215 + *temp = sprd_thm_rawdata_to_temp(sen, data); 216 + 217 + return 0; 218 + } 219 + 220 + static const struct thermal_zone_of_device_ops sprd_thm_ops = { 221 + .get_temp = sprd_thm_read_temp, 222 + }; 223 + 224 + static int sprd_thm_poll_ready_status(struct sprd_thermal_data *thm) 225 + { 226 + u32 val; 227 + int ret; 228 + 229 + /* 230 + * Wait for thermal ready status before configuring thermal parameters. 231 + */ 232 + ret = readl_poll_timeout(thm->base + SPRD_THM_CTL, val, 233 + !(val & SPRD_THM_SET_RDY_ST), 234 + SPRD_THM_RDYST_POLLING_TIME, 235 + SPRD_THM_RDYST_TIMEOUT); 236 + if (ret) 237 + return ret; 238 + 239 + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_MON_EN, 240 + SPRD_THM_MON_EN); 241 + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_SET_RDY, 242 + SPRD_THM_SET_RDY); 243 + return 0; 244 + } 245 + 246 + static int sprd_thm_wait_temp_ready(struct sprd_thermal_data *thm) 247 + { 248 + u32 val; 249 + 250 + /* Wait for first temperature data ready before reading temperature */ 251 + return readl_poll_timeout(thm->base + SPRD_THM_INTERNAL_STS1, val, 252 + !(val & SPRD_THM_TEMPER_RDY), 253 + SPRD_THM_TEMP_READY_POLL_TIME, 254 + SPRD_THM_TEMP_READY_TIMEOUT); 255 + } 256 + 257 + static int sprd_thm_set_ready(struct sprd_thermal_data *thm) 258 + { 259 + int ret; 260 + 261 + ret = sprd_thm_poll_ready_status(thm); 262 + if (ret) 263 + return ret; 264 + 265 + /* 266 + * Clear interrupt status, enable thermal interrupt and enable thermal. 267 + * 268 + * The SPRD thermal controller integrates a hardware interrupt signal, 269 + * which means if the temperature is overheat, it will generate an 270 + * interrupt and notify the event to PMIC automatically to shutdown the 271 + * system. So here we should enable the interrupt bits, though we have 272 + * not registered an irq handler. 273 + */ 274 + writel(SPRD_THM_INT_CLR_MASK, thm->base + SPRD_THM_INT_CLR); 275 + sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN, 276 + SPRD_THM_BIT_INT_EN, SPRD_THM_BIT_INT_EN); 277 + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, 278 + SPRD_THM_EN, SPRD_THM_EN); 279 + return 0; 280 + } 281 + 282 + static void sprd_thm_sensor_init(struct sprd_thermal_data *thm, 283 + struct sprd_thermal_sensor *sen) 284 + { 285 + u32 otp_rawdata, hot_rawdata; 286 + 287 + otp_rawdata = sprd_thm_temp_to_rawdata(SPRD_THM_OTP_TEMP, sen); 288 + hot_rawdata = sprd_thm_temp_to_rawdata(SPRD_THM_HOT_TEMP, sen); 289 + 290 + /* Enable the sensor' overheat temperature protection interrupt */ 291 + sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN, 292 + SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id), 293 + SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id)); 294 + 295 + /* Set the sensor' overheat and hot threshold temperature */ 296 + sprd_thm_update_bits(thm->base + SPRD_THM_THRES(sen->id), 297 + SPRD_THM_THRES_MASK, 298 + (otp_rawdata << SPRD_THM_OTP_TRIP_SHIFT) | 299 + hot_rawdata); 300 + 301 + /* Enable the corresponding sensor */ 302 + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_SEN(sen->id), 303 + SPRD_THM_SEN(sen->id)); 304 + } 305 + 306 + static void sprd_thm_para_config(struct sprd_thermal_data *thm) 307 + { 308 + /* Set the period of two valid temperature detection action */ 309 + sprd_thm_update_bits(thm->base + SPRD_THM_DET_PERIOD, 310 + SPRD_THM_DET_PERIOD_MASK, SPRD_THM_DET_PERIOD); 311 + 312 + /* Set the sensors' monitor mode */ 313 + sprd_thm_update_bits(thm->base + SPRD_THM_MON_CTL, 314 + SPRD_THM_MON_MODE_MASK, SPRD_THM_MON_MODE); 315 + 316 + /* Set the sensors' monitor period */ 317 + sprd_thm_update_bits(thm->base + SPRD_THM_MON_PERIOD, 318 + SPRD_THM_MON_PERIOD_MASK, SPRD_THM_MON_PERIOD); 319 + } 320 + 321 + static void sprd_thm_toggle_sensor(struct sprd_thermal_sensor *sen, bool on) 322 + { 323 + struct thermal_zone_device *tzd = sen->tzd; 324 + 325 + tzd->ops->set_mode(tzd, 326 + on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); 327 + } 328 + 329 + static int sprd_thm_probe(struct platform_device *pdev) 330 + { 331 + struct device_node *np = pdev->dev.of_node; 332 + struct device_node *sen_child; 333 + struct sprd_thermal_data *thm; 334 + struct sprd_thermal_sensor *sen; 335 + const struct sprd_thm_variant_data *pdata; 336 + int ret, i; 337 + u32 val; 338 + 339 + pdata = of_device_get_match_data(&pdev->dev); 340 + if (!pdata) { 341 + dev_err(&pdev->dev, "No matching driver data found\n"); 342 + return -EINVAL; 343 + } 344 + 345 + thm = devm_kzalloc(&pdev->dev, sizeof(*thm), GFP_KERNEL); 346 + if (!thm) 347 + return -ENOMEM; 348 + 349 + thm->var_data = pdata; 350 + thm->base = devm_platform_ioremap_resource(pdev, 0); 351 + if (!thm->base) 352 + return -ENOMEM; 353 + 354 + thm->nr_sensors = of_get_child_count(np); 355 + if (thm->nr_sensors == 0 || thm->nr_sensors > SPRD_THM_MAX_SENSOR) { 356 + dev_err(&pdev->dev, "incorrect sensor count\n"); 357 + return -EINVAL; 358 + } 359 + 360 + thm->clk = devm_clk_get(&pdev->dev, "enable"); 361 + if (IS_ERR(thm->clk)) { 362 + dev_err(&pdev->dev, "failed to get enable clock\n"); 363 + return PTR_ERR(thm->clk); 364 + } 365 + 366 + ret = clk_prepare_enable(thm->clk); 367 + if (ret) 368 + return ret; 369 + 370 + sprd_thm_para_config(thm); 371 + 372 + ret = sprd_thm_cal_read(np, "thm_sign_cal", &val); 373 + if (ret) 374 + goto disable_clk; 375 + 376 + if (val > 0) 377 + thm->ratio_sign = -1; 378 + else 379 + thm->ratio_sign = 1; 380 + 381 + ret = sprd_thm_cal_read(np, "thm_ratio_cal", &thm->ratio_off); 382 + if (ret) 383 + goto disable_clk; 384 + 385 + for_each_child_of_node(np, sen_child) { 386 + sen = devm_kzalloc(&pdev->dev, sizeof(*sen), GFP_KERNEL); 387 + if (!sen) { 388 + ret = -ENOMEM; 389 + goto disable_clk; 390 + } 391 + 392 + sen->data = thm; 393 + sen->dev = &pdev->dev; 394 + 395 + ret = of_property_read_u32(sen_child, "reg", &sen->id); 396 + if (ret) { 397 + dev_err(&pdev->dev, "get sensor reg failed"); 398 + goto disable_clk; 399 + } 400 + 401 + ret = sprd_thm_sensor_calibration(sen_child, thm, sen); 402 + if (ret) { 403 + dev_err(&pdev->dev, "efuse cal analysis failed"); 404 + goto disable_clk; 405 + } 406 + 407 + sprd_thm_sensor_init(thm, sen); 408 + 409 + sen->tzd = devm_thermal_zone_of_sensor_register(sen->dev, 410 + sen->id, 411 + sen, 412 + &sprd_thm_ops); 413 + if (IS_ERR(sen->tzd)) { 414 + dev_err(&pdev->dev, "register thermal zone failed %d\n", 415 + sen->id); 416 + ret = PTR_ERR(sen->tzd); 417 + goto disable_clk; 418 + } 419 + 420 + thm->sensor[sen->id] = sen; 421 + } 422 + 423 + ret = sprd_thm_set_ready(thm); 424 + if (ret) 425 + goto disable_clk; 426 + 427 + ret = sprd_thm_wait_temp_ready(thm); 428 + if (ret) 429 + goto disable_clk; 430 + 431 + for (i = 0; i < thm->nr_sensors; i++) 432 + sprd_thm_toggle_sensor(thm->sensor[i], true); 433 + 434 + platform_set_drvdata(pdev, thm); 435 + return 0; 436 + 437 + disable_clk: 438 + clk_disable_unprepare(thm->clk); 439 + return ret; 440 + } 441 + 442 + #ifdef CONFIG_PM_SLEEP 443 + static void sprd_thm_hw_suspend(struct sprd_thermal_data *thm) 444 + { 445 + int i; 446 + 447 + for (i = 0; i < thm->nr_sensors; i++) { 448 + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, 449 + SPRD_THM_SEN(thm->sensor[i]->id), 0); 450 + } 451 + 452 + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, 453 + SPRD_THM_EN, 0x0); 454 + } 455 + 456 + static int sprd_thm_suspend(struct device *dev) 457 + { 458 + struct sprd_thermal_data *thm = dev_get_drvdata(dev); 459 + int i; 460 + 461 + for (i = 0; i < thm->nr_sensors; i++) 462 + sprd_thm_toggle_sensor(thm->sensor[i], false); 463 + 464 + sprd_thm_hw_suspend(thm); 465 + clk_disable_unprepare(thm->clk); 466 + 467 + return 0; 468 + } 469 + 470 + static int sprd_thm_hw_resume(struct sprd_thermal_data *thm) 471 + { 472 + int ret, i; 473 + 474 + for (i = 0; i < thm->nr_sensors; i++) { 475 + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, 476 + SPRD_THM_SEN(thm->sensor[i]->id), 477 + SPRD_THM_SEN(thm->sensor[i]->id)); 478 + } 479 + 480 + ret = sprd_thm_poll_ready_status(thm); 481 + if (ret) 482 + return ret; 483 + 484 + writel(SPRD_THM_INT_CLR_MASK, thm->base + SPRD_THM_INT_CLR); 485 + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, 486 + SPRD_THM_EN, SPRD_THM_EN); 487 + return sprd_thm_wait_temp_ready(thm); 488 + } 489 + 490 + static int sprd_thm_resume(struct device *dev) 491 + { 492 + struct sprd_thermal_data *thm = dev_get_drvdata(dev); 493 + int ret, i; 494 + 495 + ret = clk_prepare_enable(thm->clk); 496 + if (ret) 497 + return ret; 498 + 499 + ret = sprd_thm_hw_resume(thm); 500 + if (ret) 501 + goto disable_clk; 502 + 503 + for (i = 0; i < thm->nr_sensors; i++) 504 + sprd_thm_toggle_sensor(thm->sensor[i], true); 505 + 506 + return 0; 507 + 508 + disable_clk: 509 + clk_disable_unprepare(thm->clk); 510 + return ret; 511 + } 512 + #endif 513 + 514 + static int sprd_thm_remove(struct platform_device *pdev) 515 + { 516 + struct sprd_thermal_data *thm = platform_get_drvdata(pdev); 517 + int i; 518 + 519 + for (i = 0; i < thm->nr_sensors; i++) { 520 + sprd_thm_toggle_sensor(thm->sensor[i], false); 521 + devm_thermal_zone_of_sensor_unregister(&pdev->dev, 522 + thm->sensor[i]->tzd); 523 + } 524 + 525 + clk_disable_unprepare(thm->clk); 526 + return 0; 527 + } 528 + 529 + static const struct of_device_id sprd_thermal_of_match[] = { 530 + { .compatible = "sprd,ums512-thermal", .data = &ums512_data }, 531 + { }, 532 + }; 533 + 534 + static const struct dev_pm_ops sprd_thermal_pm_ops = { 535 + SET_SYSTEM_SLEEP_PM_OPS(sprd_thm_suspend, sprd_thm_resume) 536 + }; 537 + 538 + static struct platform_driver sprd_thermal_driver = { 539 + .probe = sprd_thm_probe, 540 + .remove = sprd_thm_remove, 541 + .driver = { 542 + .name = "sprd-thermal", 543 + .pm = &sprd_thermal_pm_ops, 544 + .of_match_table = sprd_thermal_of_match, 545 + }, 546 + }; 547 + 548 + module_platform_driver(sprd_thermal_driver); 549 + 550 + MODULE_AUTHOR("Freeman Liu <freeman.liu@unisoc.com>"); 551 + MODULE_DESCRIPTION("Spreadtrum thermal driver"); 552 + MODULE_LICENSE("GPL v2");
+2 -1
drivers/thermal/st/stm_thermal.c
··· 478 478 } 479 479 #endif /* CONFIG_PM_SLEEP */ 480 480 481 - SIMPLE_DEV_PM_OPS(stm_thermal_pm_ops, stm_thermal_suspend, stm_thermal_resume); 481 + static SIMPLE_DEV_PM_OPS(stm_thermal_pm_ops, 482 + stm_thermal_suspend, stm_thermal_resume); 482 483 483 484 static const struct thermal_zone_of_device_ops stm_tz_ops = { 484 485 .get_temp = stm_thermal_get_temp,
+12 -32
drivers/thermal/ti-soc-thermal/ti-bandgap.c
··· 15 15 #include <linux/kernel.h> 16 16 #include <linux/interrupt.h> 17 17 #include <linux/clk.h> 18 - #include <linux/gpio.h> 18 + #include <linux/gpio/consumer.h> 19 19 #include <linux/platform_device.h> 20 20 #include <linux/err.h> 21 21 #include <linux/types.h> ··· 24 24 #include <linux/of_device.h> 25 25 #include <linux/of_platform.h> 26 26 #include <linux/of_irq.h> 27 - #include <linux/of_gpio.h> 28 27 #include <linux/io.h> 29 28 30 29 #include "ti-bandgap.h" ··· 742 743 static int ti_bandgap_tshut_init(struct ti_bandgap *bgp, 743 744 struct platform_device *pdev) 744 745 { 745 - int gpio_nr = bgp->tshut_gpio; 746 746 int status; 747 747 748 - /* Request for gpio_86 line */ 749 - status = gpio_request(gpio_nr, "tshut"); 750 - if (status < 0) { 751 - dev_err(bgp->dev, "Could not request for TSHUT GPIO:%i\n", 86); 752 - return status; 753 - } 754 - status = gpio_direction_input(gpio_nr); 755 - if (status) { 756 - dev_err(bgp->dev, "Cannot set input TSHUT GPIO %d\n", gpio_nr); 757 - return status; 758 - } 759 - 760 - status = request_irq(gpio_to_irq(gpio_nr), ti_bandgap_tshut_irq_handler, 748 + status = request_irq(gpiod_to_irq(bgp->tshut_gpiod), 749 + ti_bandgap_tshut_irq_handler, 761 750 IRQF_TRIGGER_RISING, "tshut", NULL); 762 - if (status) { 763 - gpio_free(gpio_nr); 751 + if (status) 764 752 dev_err(bgp->dev, "request irq failed for TSHUT"); 765 - } 766 753 767 754 return 0; 768 755 } ··· 845 860 } while (res); 846 861 847 862 if (TI_BANDGAP_HAS(bgp, TSHUT)) { 848 - bgp->tshut_gpio = of_get_gpio(node, 0); 849 - if (!gpio_is_valid(bgp->tshut_gpio)) { 850 - dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n", 851 - bgp->tshut_gpio); 852 - return ERR_PTR(-EINVAL); 863 + bgp->tshut_gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_IN); 864 + if (IS_ERR(bgp->tshut_gpiod)) { 865 + dev_err(&pdev->dev, "invalid gpio for tshut\n"); 866 + return ERR_CAST(bgp->tshut_gpiod); 853 867 } 854 868 } 855 869 ··· 1030 1046 put_fclock: 1031 1047 clk_put(bgp->fclock); 1032 1048 free_irqs: 1033 - if (TI_BANDGAP_HAS(bgp, TSHUT)) { 1034 - free_irq(gpio_to_irq(bgp->tshut_gpio), NULL); 1035 - gpio_free(bgp->tshut_gpio); 1036 - } 1049 + if (TI_BANDGAP_HAS(bgp, TSHUT)) 1050 + free_irq(gpiod_to_irq(bgp->tshut_gpiod), NULL); 1037 1051 1038 1052 return ret; 1039 1053 } ··· 1061 1079 if (TI_BANDGAP_HAS(bgp, TALERT)) 1062 1080 free_irq(bgp->irq, bgp); 1063 1081 1064 - if (TI_BANDGAP_HAS(bgp, TSHUT)) { 1065 - free_irq(gpio_to_irq(bgp->tshut_gpio), NULL); 1066 - gpio_free(bgp->tshut_gpio); 1067 - } 1082 + if (TI_BANDGAP_HAS(bgp, TSHUT)) 1083 + free_irq(gpiod_to_irq(bgp->tshut_gpiod), NULL); 1068 1084 1069 1085 return 0; 1070 1086 }
+3 -1
drivers/thermal/ti-soc-thermal/ti-bandgap.h
··· 13 13 #include <linux/types.h> 14 14 #include <linux/err.h> 15 15 16 + struct gpio_desc; 17 + 16 18 /** 17 19 * DOC: bandgap driver data structure 18 20 * ================================== ··· 201 199 struct clk *div_clk; 202 200 spinlock_t lock; /* shields this struct */ 203 201 int irq; 204 - int tshut_gpio; 202 + struct gpio_desc *tshut_gpiod; 205 203 u32 clk_rate; 206 204 }; 207 205
+1 -1
include/linux/devfreq_cooling.h
··· 75 75 76 76 #else /* !CONFIG_DEVFREQ_THERMAL */ 77 77 78 - struct thermal_cooling_device * 78 + static inline struct thermal_cooling_device * 79 79 of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, 80 80 struct devfreq_cooling_power *dfc_power) 81 81 {
+10
include/linux/thermal.h
··· 364 364 365 365 /* Function declarations */ 366 366 #ifdef CONFIG_THERMAL_OF 367 + int thermal_zone_of_get_sensor_id(struct device_node *tz_np, 368 + struct device_node *sensor_np, 369 + u32 *id); 367 370 struct thermal_zone_device * 368 371 thermal_zone_of_sensor_register(struct device *dev, int id, void *data, 369 372 const struct thermal_zone_of_device_ops *ops); ··· 378 375 void devm_thermal_zone_of_sensor_unregister(struct device *dev, 379 376 struct thermal_zone_device *tz); 380 377 #else 378 + 379 + static inline int thermal_zone_of_get_sensor_id(struct device_node *tz_np, 380 + struct device_node *sensor_np, 381 + u32 *id) 382 + { 383 + return -ENOENT; 384 + } 381 385 static inline struct thermal_zone_device * 382 386 thermal_zone_of_sensor_register(struct device *dev, int id, void *data, 383 387 const struct thermal_zone_of_device_ops *ops)
+9 -17
tools/thermal/tmon/tmon.c
··· 46 46 47 47 pthread_t event_tid; 48 48 pthread_mutex_t input_lock; 49 - void usage() 49 + void usage(void) 50 50 { 51 51 printf("Usage: tmon [OPTION...]\n"); 52 52 printf(" -c, --control cooling device in control\n"); ··· 62 62 exit(0); 63 63 } 64 64 65 - void version() 65 + void version(void) 66 66 { 67 67 printf("TMON version %s\n", VERSION); 68 68 exit(EXIT_SUCCESS); ··· 70 70 71 71 static void tmon_cleanup(void) 72 72 { 73 - 74 73 syslog(LOG_INFO, "TMON exit cleanup\n"); 75 74 fflush(stdout); 76 75 refresh(); ··· 95 96 exit(1); 96 97 } 97 98 98 - 99 99 static void tmon_sig_handler(int sig) 100 100 { 101 101 syslog(LOG_INFO, "TMON caught signal %d\n", sig); ··· 117 119 } 118 120 tmon_exit = true; 119 121 } 120 - 121 122 122 123 static void start_syslog(void) 123 124 { ··· 164 167 return; 165 168 } 166 169 167 - 168 170 fprintf(tmon_log, "#----------- THERMAL SYSTEM CONFIG -------------\n"); 169 171 for (i = 0; i < ptdata.nr_tz_sensor; i++) { 170 172 char binding_str[33]; /* size of long + 1 */ ··· 171 175 172 176 memset(binding_str, 0, sizeof(binding_str)); 173 177 for (j = 0; j < 32; j++) 174 - binding_str[j] = (ptdata.tzi[i].cdev_binding & 1<<j) ? 178 + binding_str[j] = (ptdata.tzi[i].cdev_binding & (1 << j)) ? 175 179 '1' : '0'; 176 180 177 181 fprintf(tmon_log, "#thermal zone %s%02d cdevs binding: %32s\n", ··· 183 187 trip_type_name[ptdata.tzi[i].tp[j].type], 184 188 ptdata.tzi[i].tp[j].temp); 185 189 } 186 - 187 190 } 188 191 189 192 for (i = 0; i < ptdata.nr_cooling_dev; i++) ··· 213 218 { "debug", 0, NULL, 'g' }, 214 219 { 0, 0, NULL, 0 } 215 220 }; 216 - 217 221 218 222 int main(int argc, char **argv) 219 223 { ··· 277 283 if (signal(SIGINT, tmon_sig_handler) == SIG_ERR) 278 284 syslog(LOG_DEBUG, "Cannot handle SIGINT\n"); 279 285 if (signal(SIGTERM, tmon_sig_handler) == SIG_ERR) 280 - syslog(LOG_DEBUG, "Cannot handle SIGINT\n"); 286 + syslog(LOG_DEBUG, "Cannot handle SIGTERM\n"); 281 287 282 288 if (probe_thermal_sysfs()) { 283 289 pthread_mutex_destroy(&input_lock); ··· 322 328 show_cooling_device(); 323 329 } 324 330 time_elapsed += ticktime; 325 - controller_handler(trec[0].temp[target_tz_index] / 1000, 326 - &yk); 331 + controller_handler(trec[0].temp[target_tz_index] / 1000, &yk); 327 332 trec[0].pid_out_pct = yk; 328 333 if (!dialogue_on) 329 334 show_control_w(); ··· 333 340 return 0; 334 341 } 335 342 336 - static void start_daemon_mode() 343 + static void start_daemon_mode(void) 337 344 { 338 345 daemon_mode = 1; 339 346 /* fork */ 340 347 pid_t sid, pid = fork(); 341 - if (pid < 0) { 348 + 349 + if (pid < 0) 342 350 exit(EXIT_FAILURE); 343 - } else if (pid > 0) 351 + else if (pid > 0) 344 352 /* kill parent */ 345 353 exit(EXIT_SUCCESS); 346 354 ··· 360 366 if ((chdir("/")) < 0) 361 367 exit(EXIT_FAILURE); 362 368 363 - 364 369 sleep(10); 365 370 366 371 close(STDIN_FILENO); 367 372 close(STDOUT_FILENO); 368 373 close(STDERR_FILENO); 369 - 370 374 }