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

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

Pull thermal updates from Daniel Lezcano:

- Remove duplicate error message for the amlogic driver (Tang Bin)

- Fix spellos in comments for the tegra and sun8i (Bhaskar Chowdhury)

- Add the missing fifth node on the rcar_gen3 sensor (Niklas Söderlund)

- Remove duplicate include in ti-bandgap (Zhang Yunkai)

- Assign error code in the error path in the function
thermal_of_populate_bind_params() (Jia-Ju Bai)

- Fix spelling mistake in a comment 'disabed' -> 'disabled' (Colin Ian
King)

- Use the device name instead of auto-numbering for a better
identification of the cooling device (Daniel Lezcano)

- Improve a bit the division accuracy in the power allocator governor
(Jeson Gao)

- Enable the missing third sensor on msm8976 (Konrad Dybcio)

- Add QCom tsens driver co-maintainer (Thara Gopinath)

- Fix memory leak and use after free errors in the core code (Daniel
Lezcano)

- Add the MDM9607 compatible bindings (Konrad Dybcio)

- Fix trivial spello in the copyright name for Hisilicon (Hao Fang)

- Fix negative index array access when converting the frequency to
power in the energy model (Brian-sy Yang)

- Add support for Gen2 new PMIC support for Qcom SPMI (David Collins)

- Update maintainer file for CPU cooling device section (Lukasz Luba)

- Fix missing put_device on error in the Qcom tsens driver (Guangqing
Zhu)

- Add compatible DT binding for sm8350 (Robert Foss)

- Add support for the MDM9607's tsens driver (Konrad Dybcio)

- Remove duplicate error messages in thermal_mmio and the bcm2835
driver (Ruiqi Gong)

- Add the Thermal Temperature Cooling driver (Zhang Rui)

- Remove duplicate error messages in the Hisilicon sensor driver (Ye
Bin)

- Use the devm_platform_ioremap_resource_byname() function instead of a
couple of corresponding calls (dingsenjie)

- Sort the headers alphabetically in the ti-bandgap driver (Zhen Lei)

- Add missing property in the DT thermal sensor binding (Rafał Miłecki)

- Remove dead code in the ti-bandgap sensor driver (Lin Ruizhe)

- Convert the BRCM DT bindings to the yaml schema (Rafał Miłecki)

- Replace the thermal_notify_framework() call by a call to the
thermal_zone_device_update() function. Remove the function as well as
the corresponding documentation (Thara Gopinath)

- Add support for the ipq8064-tsens sensor along with a set of cleanups
and code preparation (Ansuel Smith)

- Add a lockless __thermal_cdev_update() function to improve the
locking scheme in the core code and governors (Lukasz Luba)

- Fix multiple cooling device notification changes (Lukasz Luba)

- Remove unneeded variable initialization (Colin Ian King)

* tag 'thermal-v5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (55 commits)
thermal/drivers/mtk_thermal: Remove redundant initializations of several variables
thermal/core/power allocator: Use the lockless __thermal_cdev_update() function
thermal/core/fair share: Use the lockless __thermal_cdev_update() function
thermal/core/fair share: Lock the thermal zone while looping over instances
thermal/core/power_allocator: Update once cooling devices when temp is low
thermal/core/power_allocator: Maintain the device statistics from going stale
thermal/core: Create a helper __thermal_cdev_update() without a lock
dt-bindings: thermal: tsens: Document ipq8064 bindings
thermal/drivers/tsens: Add support for ipq8064-tsens
thermal/drivers/tsens: Drop unused define for msm8960
thermal/drivers/tsens: Replace custom 8960 apis with generic apis
thermal/drivers/tsens: Fix bug in sensor enable for msm8960
thermal/drivers/tsens: Use init_common for msm8960
thermal/drivers/tsens: Add VER_0 tsens version
thermal/drivers/tsens: Convert msm8960 to reg_field
thermal/drivers/tsens: Don't hardcode sensor slope
Documentation: driver-api: thermal: Remove thermal_notify_framework from documentation
thermal/core: Remove thermal_notify_framework
iwlwifi: mvm: tt: Replace thermal_notify_framework
dt-bindings: thermal: brcm,ns-thermal: Convert to the json-schema
...

+863 -446
-37
Documentation/devicetree/bindings/thermal/brcm,ns-thermal.txt
··· 1 - * Broadcom Northstar Thermal 2 - 3 - This binding describes thermal sensor that is part of Northstar's DMU (Device 4 - Management Unit). 5 - 6 - Required properties: 7 - - compatible : Must be "brcm,ns-thermal" 8 - - reg : iomem address range of PVTMON registers 9 - - #thermal-sensor-cells : Should be <0> 10 - 11 - Example: 12 - 13 - thermal: thermal@1800c2c0 { 14 - compatible = "brcm,ns-thermal"; 15 - reg = <0x1800c2c0 0x10>; 16 - #thermal-sensor-cells = <0>; 17 - }; 18 - 19 - thermal-zones { 20 - cpu_thermal: cpu-thermal { 21 - polling-delay-passive = <0>; 22 - polling-delay = <1000>; 23 - coefficients = <(-556) 418000>; 24 - thermal-sensors = <&thermal>; 25 - 26 - trips { 27 - cpu-crit { 28 - temperature = <125000>; 29 - hysteresis = <0>; 30 - type = "critical"; 31 - }; 32 - }; 33 - 34 - cooling-maps { 35 - }; 36 - }; 37 - };
+60
Documentation/devicetree/bindings/thermal/brcm,ns-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/brcm,ns-thermal.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Broadcom Northstar Thermal 8 + 9 + maintainers: 10 + - Rafał Miłecki <rafal@milecki.pl> 11 + 12 + description: 13 + Thermal sensor that is part of Northstar's DMU (Device Management Unit). 14 + 15 + allOf: 16 + - $ref: thermal-sensor.yaml# 17 + 18 + properties: 19 + compatible: 20 + const: brcm,ns-thermal 21 + 22 + reg: 23 + description: PVTMON registers range 24 + maxItems: 1 25 + 26 + "#thermal-sensor-cells": 27 + const: 0 28 + 29 + unevaluatedProperties: false 30 + 31 + required: 32 + - reg 33 + 34 + examples: 35 + - | 36 + thermal: thermal@1800c2c0 { 37 + compatible = "brcm,ns-thermal"; 38 + reg = <0x1800c2c0 0x10>; 39 + #thermal-sensor-cells = <0>; 40 + }; 41 + 42 + thermal-zones { 43 + cpu-thermal { 44 + polling-delay-passive = <0>; 45 + polling-delay = <1000>; 46 + coefficients = <(-556) 418000>; 47 + thermal-sensors = <&thermal>; 48 + 49 + trips { 50 + cpu-crit { 51 + temperature = <125000>; 52 + hysteresis = <0>; 53 + type = "critical"; 54 + }; 55 + }; 56 + 57 + cooling-maps { 58 + }; 59 + }; 60 + };
+51 -8
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
··· 19 19 properties: 20 20 compatible: 21 21 oneOf: 22 + - description: msm9860 TSENS based 23 + items: 24 + - enum: 25 + - qcom,ipq8064-tsens 26 + 22 27 - description: v0.1 of TSENS 23 28 items: 24 29 - enum: 30 + - qcom,mdm9607-tsens 25 31 - qcom,msm8916-tsens 26 32 - qcom,msm8939-tsens 27 33 - qcom,msm8974-tsens ··· 49 43 - qcom,sdm845-tsens 50 44 - qcom,sm8150-tsens 51 45 - qcom,sm8250-tsens 46 + - qcom,sm8350-tsens 52 47 - const: qcom,tsens-v2 53 48 54 49 reg: ··· 80 73 maxItems: 2 81 74 items: 82 75 - const: calib 83 - - const: calib_sel 76 + - enum: 77 + - calib_backup 78 + - calib_sel 84 79 85 80 "#qcom,sensors": 86 81 description: ··· 97 88 Number of cells required to uniquely identify the thermal sensors. Since 98 89 we have multiple sensors this is set to 1 99 90 91 + required: 92 + - compatible 93 + - interrupts 94 + - interrupt-names 95 + - "#thermal-sensor-cells" 96 + - "#qcom,sensors" 97 + 100 98 allOf: 101 99 - if: 102 100 properties: 103 101 compatible: 104 102 contains: 105 103 enum: 104 + - qcom,ipq8064-tsens 105 + - qcom,mdm9607-tsens 106 106 - qcom,msm8916-tsens 107 107 - qcom,msm8974-tsens 108 108 - qcom,msm8976-tsens ··· 132 114 interrupt-names: 133 115 minItems: 2 134 116 135 - required: 136 - - compatible 137 - - reg 138 - - "#qcom,sensors" 139 - - interrupts 140 - - interrupt-names 141 - - "#thermal-sensor-cells" 117 + - if: 118 + properties: 119 + compatible: 120 + contains: 121 + enum: 122 + - qcom,tsens-v0_1 123 + - qcom,tsens-v1 124 + - qcom,tsens-v2 125 + 126 + then: 127 + required: 128 + - reg 142 129 143 130 additionalProperties: false 144 131 145 132 examples: 133 + - | 134 + #include <dt-bindings/interrupt-controller/arm-gic.h> 135 + // Example msm9860 based SoC (ipq8064): 136 + gcc: clock-controller { 137 + 138 + /* ... */ 139 + 140 + tsens: thermal-sensor { 141 + compatible = "qcom,ipq8064-tsens"; 142 + 143 + nvmem-cells = <&tsens_calib>, <&tsens_calib_backup>; 144 + nvmem-cell-names = "calib", "calib_backup"; 145 + interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>; 146 + interrupt-names = "uplow"; 147 + 148 + #qcom,sensors = <11>; 149 + #thermal-sensor-cells = <1>; 150 + }; 151 + }; 152 + 146 153 - | 147 154 #include <dt-bindings/interrupt-controller/arm-gic.h> 148 155 // Example 1 (legacy: for pre v1 IP):
+35 -8
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 31 - reg: 32 - minItems: 2 33 - maxItems: 4 34 - items: 35 - - description: TSC1 registers 36 - - description: TSC2 registers 37 - - description: TSC3 registers 38 - - description: TSC4 registers 31 + reg: true 39 32 40 33 interrupts: 41 34 items: ··· 64 71 enum: 65 72 - renesas,r8a779a0-thermal 66 73 then: 74 + properties: 75 + reg: 76 + minItems: 2 77 + maxItems: 3 78 + items: 79 + - description: TSC1 registers 80 + - description: TSC2 registers 81 + - description: TSC3 registers 67 82 required: 68 83 - interrupts 84 + else: 85 + properties: 86 + reg: 87 + items: 88 + - description: TSC0 registers 89 + - description: TSC1 registers 90 + - description: TSC2 registers 91 + - description: TSC3 registers 92 + - description: TSC4 registers 69 93 70 94 additionalProperties: false 71 95 ··· 120 110 }; 121 111 }; 122 112 }; 113 + }; 114 + - | 115 + #include <dt-bindings/clock/r8a779a0-cpg-mssr.h> 116 + #include <dt-bindings/interrupt-controller/arm-gic.h> 117 + #include <dt-bindings/power/r8a779a0-sysc.h> 118 + 119 + tsc_r8a779a0: thermal@e6190000 { 120 + compatible = "renesas,r8a779a0-thermal"; 121 + reg = <0xe6190000 0x200>, 122 + <0xe6198000 0x200>, 123 + <0xe61a0000 0x200>, 124 + <0xe61a8000 0x200>, 125 + <0xe61b0000 0x200>; 126 + clocks = <&cpg CPG_MOD 919>; 127 + power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; 128 + resets = <&cpg 919>; 129 + #thermal-sensor-cells = <1>; 123 130 };
+3
Documentation/devicetree/bindings/thermal/thermal-sensor.yaml
··· 36 36 containing several internal sensors. 37 37 enum: [0, 1] 38 38 39 + required: 40 + - "#thermal-sensor-cells" 41 + 39 42 additionalProperties: true 40 43 41 44 examples:
+1 -11
Documentation/driver-api/thermal/sysfs-api.rst
··· 730 730 {thermal_zone, cooling_device, trip_point} combination. Returns NULL 731 731 if such an instance does not exist. 732 732 733 - 4.3. thermal_notify_framework 734 - ----------------------------- 735 - 736 - This function handles the trip events from sensor drivers. It starts 737 - throttling the cooling devices according to the policy configured. 738 - For CRITICAL and HOT trip points, this notifies the respective drivers, 739 - and does actual throttling for other trip points i.e ACTIVE and PASSIVE. 740 - The throttling policy is based on the configured platform data; if no 741 - platform data is provided, this uses the step_wise throttling policy. 742 - 743 - 4.4. thermal_cdev_update 733 + 4.3. thermal_cdev_update 744 734 ------------------------ 745 735 746 736 This function serves as an arbitrator to set the state of a cooling
+2 -1
MAINTAINERS
··· 15197 15197 15198 15198 QUALCOMM TSENS THERMAL DRIVER 15199 15199 M: Amit Kucheria <amitk@kernel.org> 15200 + M: Thara Gopinath <thara.gopinath@linaro.org> 15200 15201 L: linux-pm@vger.kernel.org 15201 15202 L: linux-arm-msm@vger.kernel.org 15202 15203 S: Maintained ··· 18102 18101 M: Amit Daniel Kachhap <amit.kachhap@gmail.com> 18103 18102 M: Daniel Lezcano <daniel.lezcano@linaro.org> 18104 18103 M: Viresh Kumar <viresh.kumar@linaro.org> 18105 - M: Javi Merino <javi.merino@kernel.org> 18104 + R: Lukasz Luba <lukasz.luba@arm.com> 18106 18105 L: linux-pm@vger.kernel.org 18107 18106 S: Supported 18108 18107 F: Documentation/driver-api/thermal/cpu-cooling-api.rst
+1 -1
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
··· 132 132 /* Allow mlxsw thermal zone binding to an external cooling device */ 133 133 for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) { 134 134 if (strnstr(cdev->type, mlxsw_thermal_external_allowed_cdev[i], 135 - sizeof(cdev->type))) 135 + strlen(cdev->type))) 136 136 return 0; 137 137 } 138 138
+2 -2
drivers/net/wireless/intel/iwlwifi/mvm/tt.c
··· 146 146 if (mvm->tz_device.tzone) { 147 147 struct iwl_mvm_thermal_device *tz_dev = &mvm->tz_device; 148 148 149 - thermal_notify_framework(tz_dev->tzone, 150 - tz_dev->fw_trips_index[ths_crossed]); 149 + thermal_zone_device_update(tz_dev->tzone, 150 + THERMAL_TRIP_VIOLATED); 151 151 } 152 152 #endif /* CONFIG_THERMAL */ 153 153 }
+1 -3
drivers/thermal/amlogic_thermal.c
··· 254 254 platform_set_drvdata(pdev, pdata); 255 255 256 256 base = devm_platform_ioremap_resource(pdev, 0); 257 - if (IS_ERR(base)) { 258 - dev_err(dev, "failed to get io address\n"); 257 + if (IS_ERR(base)) 259 258 return PTR_ERR(base); 260 - } 261 259 262 260 pdata->regmap = devm_regmap_init_mmio(dev, base, 263 261 pdata->data->regmap_config);
-1
drivers/thermal/broadcom/bcm2835_thermal.c
··· 184 184 data->regs = devm_ioremap_resource(&pdev->dev, res); 185 185 if (IS_ERR(data->regs)) { 186 186 err = PTR_ERR(data->regs); 187 - dev_err(&pdev->dev, "Could not get registers: %d\n", err); 188 187 return err; 189 188 } 190 189
+14 -37
drivers/thermal/cpufreq_cooling.c
··· 13 13 #include <linux/cpu.h> 14 14 #include <linux/cpufreq.h> 15 15 #include <linux/cpu_cooling.h> 16 + #include <linux/device.h> 16 17 #include <linux/energy_model.h> 17 18 #include <linux/err.h> 18 19 #include <linux/export.h> 19 - #include <linux/idr.h> 20 20 #include <linux/pm_opp.h> 21 21 #include <linux/pm_qos.h> 22 22 #include <linux/slab.h> ··· 50 50 51 51 /** 52 52 * struct cpufreq_cooling_device - data for cooling device with cpufreq 53 - * @id: unique integer value corresponding to each cpufreq_cooling_device 54 - * registered. 55 53 * @last_load: load measured by the latest call to cpufreq_get_requested_power() 56 54 * @cpufreq_state: integer value representing the current state of cpufreq 57 55 * cooling devices. ··· 59 61 * @cdev: thermal_cooling_device pointer to keep track of the 60 62 * registered cooling device. 61 63 * @policy: cpufreq policy. 62 - * @node: list_head to link all cpufreq_cooling_device together. 63 64 * @idle_time: idle time stats 64 65 * @qos_req: PM QoS contraint to apply 65 66 * ··· 66 69 * cpufreq_cooling_device. 67 70 */ 68 71 struct cpufreq_cooling_device { 69 - int id; 70 72 u32 last_load; 71 73 unsigned int cpufreq_state; 72 74 unsigned int max_level; 73 75 struct em_perf_domain *em; 74 76 struct cpufreq_policy *policy; 75 - struct list_head node; 76 77 #ifndef CONFIG_SMP 77 78 struct time_in_idle *idle_time; 78 79 #endif 79 80 struct freq_qos_request qos_req; 80 81 }; 81 - 82 - static DEFINE_IDA(cpufreq_ida); 83 - static DEFINE_MUTEX(cooling_list_lock); 84 - static LIST_HEAD(cpufreq_cdev_list); 85 82 86 83 #ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR 87 84 /** ··· 116 125 { 117 126 int i; 118 127 119 - for (i = cpufreq_cdev->max_level; i >= 0; i--) { 128 + for (i = cpufreq_cdev->max_level; i > 0; i--) { 120 129 if (power >= cpufreq_cdev->em->table[i].power) 121 130 break; 122 131 } ··· 519 528 { 520 529 struct thermal_cooling_device *cdev; 521 530 struct cpufreq_cooling_device *cpufreq_cdev; 522 - char dev_name[THERMAL_NAME_LENGTH]; 523 531 unsigned int i; 524 532 struct device *dev; 525 533 int ret; 526 534 struct thermal_cooling_device_ops *cooling_ops; 535 + char *name; 527 536 528 537 dev = get_cpu_device(policy->cpu); 529 538 if (unlikely(!dev)) { ··· 558 567 /* max_level is an index, not a counter */ 559 568 cpufreq_cdev->max_level = i - 1; 560 569 561 - ret = ida_simple_get(&cpufreq_ida, 0, 0, GFP_KERNEL); 562 - if (ret < 0) { 563 - cdev = ERR_PTR(ret); 564 - goto free_idle_time; 565 - } 566 - cpufreq_cdev->id = ret; 567 - 568 - snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d", 569 - cpufreq_cdev->id); 570 - 571 570 cooling_ops = &cpufreq_cooling_ops; 572 571 573 572 #ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR ··· 572 591 pr_err("%s: unsorted frequency tables are not supported\n", 573 592 __func__); 574 593 cdev = ERR_PTR(-EINVAL); 575 - goto remove_ida; 594 + goto free_idle_time; 576 595 } 577 596 578 597 ret = freq_qos_add_request(&policy->constraints, ··· 582 601 pr_err("%s: Failed to add freq constraint (%d)\n", __func__, 583 602 ret); 584 603 cdev = ERR_PTR(ret); 585 - goto remove_ida; 604 + goto free_idle_time; 586 605 } 587 606 588 - cdev = thermal_of_cooling_device_register(np, dev_name, cpufreq_cdev, 589 - cooling_ops); 590 - if (IS_ERR(cdev)) 607 + cdev = ERR_PTR(-ENOMEM); 608 + name = kasprintf(GFP_KERNEL, "cpufreq-%s", dev_name(dev)); 609 + if (!name) 591 610 goto remove_qos_req; 592 611 593 - mutex_lock(&cooling_list_lock); 594 - list_add(&cpufreq_cdev->node, &cpufreq_cdev_list); 595 - mutex_unlock(&cooling_list_lock); 612 + cdev = thermal_of_cooling_device_register(np, name, cpufreq_cdev, 613 + cooling_ops); 614 + kfree(name); 615 + 616 + if (IS_ERR(cdev)) 617 + goto remove_qos_req; 596 618 597 619 return cdev; 598 620 599 621 remove_qos_req: 600 622 freq_qos_remove_request(&cpufreq_cdev->qos_req); 601 - remove_ida: 602 - ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id); 603 623 free_idle_time: 604 624 free_idle_time(cpufreq_cdev); 605 625 free_cdev: ··· 688 706 689 707 cpufreq_cdev = cdev->devdata; 690 708 691 - mutex_lock(&cooling_list_lock); 692 - list_del(&cpufreq_cdev->node); 693 - mutex_unlock(&cooling_list_lock); 694 - 695 709 thermal_cooling_device_unregister(cdev); 696 710 freq_qos_remove_request(&cpufreq_cdev->qos_req); 697 - ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id); 698 711 free_idle_time(cpufreq_cdev); 699 712 kfree(cpufreq_cdev); 700 713 }
+21 -20
drivers/thermal/cpuidle_cooling.c
··· 9 9 10 10 #include <linux/cpu_cooling.h> 11 11 #include <linux/cpuidle.h> 12 + #include <linux/device.h> 12 13 #include <linux/err.h> 13 14 #include <linux/idle_inject.h> 14 - #include <linux/idr.h> 15 15 #include <linux/of_device.h> 16 16 #include <linux/slab.h> 17 17 #include <linux/thermal.h> ··· 25 25 struct idle_inject_device *ii_dev; 26 26 unsigned long state; 27 27 }; 28 - 29 - static DEFINE_IDA(cpuidle_ida); 30 28 31 29 /** 32 30 * cpuidle_cooling_runtime - Running time computation ··· 172 174 struct idle_inject_device *ii_dev; 173 175 struct cpuidle_cooling_device *idle_cdev; 174 176 struct thermal_cooling_device *cdev; 177 + struct device *dev; 175 178 unsigned int idle_duration_us = TICK_USEC; 176 179 unsigned int latency_us = UINT_MAX; 177 - char dev_name[THERMAL_NAME_LENGTH]; 178 - int id, ret; 180 + char *name; 181 + int ret; 179 182 180 183 idle_cdev = kzalloc(sizeof(*idle_cdev), GFP_KERNEL); 181 184 if (!idle_cdev) { ··· 184 185 goto out; 185 186 } 186 187 187 - id = ida_simple_get(&cpuidle_ida, 0, 0, GFP_KERNEL); 188 - if (id < 0) { 189 - ret = id; 190 - goto out_kfree; 191 - } 192 - 193 188 ii_dev = idle_inject_register(drv->cpumask); 194 189 if (!ii_dev) { 195 190 ret = -EINVAL; 196 - goto out_id; 191 + goto out_kfree; 197 192 } 198 193 199 194 of_property_read_u32(np, "duration-us", &idle_duration_us); ··· 198 205 199 206 idle_cdev->ii_dev = ii_dev; 200 207 201 - snprintf(dev_name, sizeof(dev_name), "thermal-idle-%d", id); 208 + dev = get_cpu_device(cpumask_first(drv->cpumask)); 202 209 203 - cdev = thermal_of_cooling_device_register(np, dev_name, idle_cdev, 204 - &cpuidle_cooling_ops); 205 - if (IS_ERR(cdev)) { 206 - ret = PTR_ERR(cdev); 210 + name = kasprintf(GFP_KERNEL, "idle-%s", dev_name(dev)); 211 + if (!name) { 212 + ret = -ENOMEM; 207 213 goto out_unregister; 208 214 } 209 215 216 + cdev = thermal_of_cooling_device_register(np, name, idle_cdev, 217 + &cpuidle_cooling_ops); 218 + if (IS_ERR(cdev)) { 219 + ret = PTR_ERR(cdev); 220 + goto out_kfree_name; 221 + } 222 + 210 223 pr_debug("%s: Idle injection set with idle duration=%u, latency=%u\n", 211 - dev_name, idle_duration_us, latency_us); 224 + name, idle_duration_us, latency_us); 225 + 226 + kfree(name); 212 227 213 228 return 0; 214 229 230 + out_kfree_name: 231 + kfree(name); 215 232 out_unregister: 216 233 idle_inject_unregister(ii_dev); 217 - out_id: 218 - ida_simple_remove(&cpuidle_ida, id); 219 234 out_kfree: 220 235 kfree(idle_cdev); 221 236 out:
+8 -17
drivers/thermal/devfreq_cooling.c
··· 14 14 #include <linux/devfreq_cooling.h> 15 15 #include <linux/energy_model.h> 16 16 #include <linux/export.h> 17 - #include <linux/idr.h> 18 17 #include <linux/slab.h> 19 18 #include <linux/pm_opp.h> 20 19 #include <linux/pm_qos.h> ··· 24 25 #define HZ_PER_KHZ 1000 25 26 #define SCALE_ERROR_MITIGATION 100 26 27 27 - static DEFINE_IDA(devfreq_ida); 28 - 29 28 /** 30 29 * struct devfreq_cooling_device - Devfreq cooling device 31 - * @id: unique integer value corresponding to each 32 30 * devfreq_cooling_device registered. 33 31 * @cdev: Pointer to associated thermal cooling device. 34 32 * @devfreq: Pointer to associated devfreq device. ··· 47 51 * @em_pd: Energy Model for the associated Devfreq device 48 52 */ 49 53 struct devfreq_cooling_device { 50 - int id; 51 54 struct thermal_cooling_device *cdev; 52 55 struct devfreq *devfreq; 53 56 unsigned long cooling_state; ··· 358 363 struct thermal_cooling_device *cdev; 359 364 struct device *dev = df->dev.parent; 360 365 struct devfreq_cooling_device *dfc; 361 - char dev_name[THERMAL_NAME_LENGTH]; 366 + char *name; 362 367 int err, num_opps; 363 368 364 369 dfc = kzalloc(sizeof(*dfc), GFP_KERNEL); ··· 402 407 if (err < 0) 403 408 goto free_table; 404 409 405 - err = ida_simple_get(&devfreq_ida, 0, 0, GFP_KERNEL); 406 - if (err < 0) 410 + err = -ENOMEM; 411 + name = kasprintf(GFP_KERNEL, "devfreq-%s", dev_name(dev)); 412 + if (!name) 407 413 goto remove_qos_req; 408 414 409 - dfc->id = err; 410 - 411 - snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id); 412 - 413 - cdev = thermal_of_cooling_device_register(np, dev_name, dfc, 415 + cdev = thermal_of_cooling_device_register(np, name, dfc, 414 416 &devfreq_cooling_ops); 417 + kfree(name); 418 + 415 419 if (IS_ERR(cdev)) { 416 420 err = PTR_ERR(cdev); 417 421 dev_err(dev, 418 422 "Failed to register devfreq cooling device (%d)\n", 419 423 err); 420 - goto release_ida; 424 + goto remove_qos_req; 421 425 } 422 426 423 427 dfc->cdev = cdev; 424 428 425 429 return cdev; 426 430 427 - release_ida: 428 - ida_simple_remove(&devfreq_ida, dfc->id); 429 431 remove_qos_req: 430 432 dev_pm_qos_remove_request(&dfc->req_max_freq); 431 433 free_table: ··· 519 527 dev = dfc->devfreq->dev.parent; 520 528 521 529 thermal_cooling_device_unregister(dfc->cdev); 522 - ida_simple_remove(&devfreq_ida, dfc->id); 523 530 dev_pm_qos_remove_request(&dfc->req_max_freq); 524 531 525 532 em_dev_unregister_perf_domain(dev);
+7 -4
drivers/thermal/gov_fair_share.c
··· 82 82 int total_instance = 0; 83 83 int cur_trip_level = get_trip_level(tz); 84 84 85 + mutex_lock(&tz->lock); 86 + 85 87 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 86 88 if (instance->trip != trip) 87 89 continue; ··· 107 105 instance->target = get_target_state(tz, cdev, percentage, 108 106 cur_trip_level); 109 107 110 - mutex_lock(&instance->cdev->lock); 111 - instance->cdev->updated = false; 112 - mutex_unlock(&instance->cdev->lock); 113 - thermal_cdev_update(cdev); 108 + mutex_lock(&cdev->lock); 109 + __thermal_cdev_update(cdev); 110 + mutex_unlock(&cdev->lock); 114 111 } 112 + 113 + mutex_unlock(&tz->lock); 115 114 return 0; 116 115 } 117 116
+23 -9
drivers/thermal/gov_power_allocator.c
··· 301 301 302 302 instance->target = clamp_val(state, instance->lower, instance->upper); 303 303 mutex_lock(&cdev->lock); 304 - cdev->updated = false; 304 + __thermal_cdev_update(cdev); 305 305 mutex_unlock(&cdev->lock); 306 - thermal_cdev_update(cdev); 307 306 308 307 return 0; 309 308 } ··· 373 374 */ 374 375 extra_power = min(extra_power, capped_extra_power); 375 376 if (capped_extra_power > 0) 376 - for (i = 0; i < num_actors; i++) 377 - granted_power[i] += (extra_actor_power[i] * 378 - extra_power) / capped_extra_power; 377 + for (i = 0; i < num_actors; i++) { 378 + u64 extra_range = (u64)extra_actor_power[i] * extra_power; 379 + granted_power[i] += DIV_ROUND_CLOSEST_ULL(extra_range, 380 + capped_extra_power); 381 + } 379 382 } 380 383 381 384 static int allocate_power(struct thermal_zone_device *tz, ··· 570 569 params->prev_err = 0; 571 570 } 572 571 573 - static void allow_maximum_power(struct thermal_zone_device *tz) 572 + static void allow_maximum_power(struct thermal_zone_device *tz, bool update) 574 573 { 575 574 struct thermal_instance *instance; 576 575 struct power_allocator_params *params = tz->governor_data; 576 + u32 req_power; 577 577 578 578 mutex_lock(&tz->lock); 579 579 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 580 + struct thermal_cooling_device *cdev = instance->cdev; 581 + 580 582 if ((instance->trip != params->trip_max_desired_temperature) || 581 583 (!cdev_is_power_actor(instance->cdev))) 582 584 continue; 583 585 584 586 instance->target = 0; 585 587 mutex_lock(&instance->cdev->lock); 586 - instance->cdev->updated = false; 588 + /* 589 + * Call for updating the cooling devices local stats and avoid 590 + * periods of dozen of seconds when those have not been 591 + * maintained. 592 + */ 593 + cdev->ops->get_requested_power(cdev, &req_power); 594 + 595 + if (update) 596 + __thermal_cdev_update(instance->cdev); 597 + 587 598 mutex_unlock(&instance->cdev->lock); 588 - thermal_cdev_update(instance->cdev); 589 599 } 590 600 mutex_unlock(&tz->lock); 591 601 } ··· 710 698 int ret; 711 699 int switch_on_temp, control_temp; 712 700 struct power_allocator_params *params = tz->governor_data; 701 + bool update; 713 702 714 703 /* 715 704 * We get called for every trip point but we only need to do ··· 722 709 ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, 723 710 &switch_on_temp); 724 711 if (!ret && (tz->temperature < switch_on_temp)) { 712 + update = (tz->last_temperature >= switch_on_temp); 725 713 tz->passive = 0; 726 714 reset_pid_controller(params); 727 - allow_maximum_power(tz); 715 + allow_maximum_power(tz, update); 728 716 return 0; 729 717 } 730 718
+4 -6
drivers/thermal/hisi_thermal.c
··· 1 1 /* 2 - * Hisilicon thermal sensor driver 2 + * HiSilicon thermal sensor driver 3 3 * 4 - * Copyright (c) 2014-2015 Hisilicon Limited. 4 + * Copyright (c) 2014-2015 HiSilicon Limited. 5 5 * Copyright (c) 2014-2015 Linaro Limited. 6 6 * 7 7 * Xinwei Kong <kong.kongxinwei@hisilicon.com> ··· 572 572 573 573 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 574 574 data->regs = devm_ioremap_resource(dev, res); 575 - if (IS_ERR(data->regs)) { 576 - dev_err(dev, "failed to get io address\n"); 575 + if (IS_ERR(data->regs)) 577 576 return PTR_ERR(data->regs); 578 - } 579 577 580 578 ret = data->ops->probe(data); 581 579 if (ret) ··· 670 672 671 673 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>"); 672 674 MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>"); 673 - MODULE_DESCRIPTION("Hisilicon thermal driver"); 675 + MODULE_DESCRIPTION("HiSilicon thermal driver"); 674 676 MODULE_LICENSE("GPL v2");
+11
drivers/thermal/intel/Kconfig
··· 79 79 Enable this to support thermal reporting on certain intel PCHs. 80 80 Thermal reporting device will provide temperature reading, 81 81 programmable trip points and other information. 82 + 83 + config INTEL_TCC_COOLING 84 + tristate "Intel TCC offset cooling Driver" 85 + depends on X86 86 + help 87 + Enable this to support system cooling by adjusting the effective TCC 88 + activation temperature via the TCC Offset register, which is widely 89 + supported on modern Intel platforms. 90 + Note that, on different platforms, the behavior might be different 91 + on how fast the setting takes effect, and how much the CPU frequency 92 + is reduced.
+1
drivers/thermal/intel/Makefile
··· 10 10 obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/ 11 11 obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o 12 12 obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o 13 + obj-$(CONFIG_INTEL_TCC_COOLING) += intel_tcc_cooling.o 13 14 obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o
+129
drivers/thermal/intel/intel_tcc_cooling.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * cooling device driver that activates the processor throttling by 4 + * programming the TCC Offset register. 5 + * Copyright (c) 2021, Intel Corporation. 6 + */ 7 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 + 9 + #include <linux/device.h> 10 + #include <linux/module.h> 11 + #include <linux/thermal.h> 12 + #include <asm/cpu_device_id.h> 13 + 14 + #define TCC_SHIFT 24 15 + #define TCC_MASK (0x3fULL<<24) 16 + #define TCC_PROGRAMMABLE BIT(30) 17 + 18 + static struct thermal_cooling_device *tcc_cdev; 19 + 20 + static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long 21 + *state) 22 + { 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 + 43 + return 0; 44 + } 45 + 46 + static int tcc_get_cur_state(struct thermal_cooling_device *cdev, unsigned long 47 + *state) 48 + { 49 + u64 val; 50 + int err; 51 + 52 + err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val); 53 + if (err) 54 + return err; 55 + 56 + *state = (val & TCC_MASK) >> TCC_SHIFT; 57 + return 0; 58 + } 59 + 60 + static int tcc_set_cur_state(struct thermal_cooling_device *cdev, unsigned long 61 + state) 62 + { 63 + return tcc_offset_update(state); 64 + } 65 + 66 + static const struct thermal_cooling_device_ops tcc_cooling_ops = { 67 + .get_max_state = tcc_get_max_state, 68 + .get_cur_state = tcc_get_cur_state, 69 + .set_cur_state = tcc_set_cur_state, 70 + }; 71 + 72 + static const struct x86_cpu_id tcc_ids[] __initconst = { 73 + X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, NULL), 74 + X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, NULL), 75 + X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, NULL), 76 + X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, NULL), 77 + X86_MATCH_INTEL_FAM6_MODEL(ICELAKE, NULL), 78 + X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, NULL), 79 + X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, NULL), 80 + X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL), 81 + X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, NULL), 82 + {} 83 + }; 84 + 85 + MODULE_DEVICE_TABLE(x86cpu, tcc_ids); 86 + 87 + static int __init tcc_cooling_init(void) 88 + { 89 + int ret; 90 + u64 val; 91 + const struct x86_cpu_id *id; 92 + 93 + int err; 94 + 95 + id = x86_match_cpu(tcc_ids); 96 + if (!id) 97 + return -ENODEV; 98 + 99 + err = rdmsrl_safe(MSR_PLATFORM_INFO, &val); 100 + if (err) 101 + return err; 102 + 103 + if (!(val & TCC_PROGRAMMABLE)) 104 + return -ENODEV; 105 + 106 + pr_info("Programmable TCC Offset detected\n"); 107 + 108 + tcc_cdev = 109 + thermal_cooling_device_register("TCC Offset", NULL, 110 + &tcc_cooling_ops); 111 + if (IS_ERR(tcc_cdev)) { 112 + ret = PTR_ERR(tcc_cdev); 113 + return ret; 114 + } 115 + return 0; 116 + } 117 + 118 + module_init(tcc_cooling_init) 119 + 120 + static void __exit tcc_cooling_exit(void) 121 + { 122 + thermal_cooling_device_unregister(tcc_cdev); 123 + } 124 + 125 + module_exit(tcc_cooling_exit) 126 + 127 + MODULE_DESCRIPTION("TCC offset cooling device Driver"); 128 + MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>"); 129 + MODULE_LICENSE("GPL v2");
+6 -6
drivers/thermal/mtk_thermal.c
··· 573 573 574 574 static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw) 575 575 { 576 - s32 format_1 = 0; 577 - s32 format_2 = 0; 578 - s32 g_oe = 1; 579 - s32 g_gain = 1; 580 - s32 g_x_roomt = 0; 581 - s32 tmp = 0; 576 + s32 format_1; 577 + s32 format_2; 578 + s32 g_oe; 579 + s32 g_gain; 580 + s32 g_x_roomt; 581 + s32 tmp; 582 582 583 583 if (raw == 0) 584 584 return 0;
+61 -30
drivers/thermal/qcom/qcom-spmi-temp-alarm.c
··· 17 17 18 18 #include "../thermal_core.h" 19 19 20 + #define QPNP_TM_REG_DIG_MAJOR 0x01 20 21 #define QPNP_TM_REG_TYPE 0x04 21 22 #define QPNP_TM_REG_SUBTYPE 0x05 22 23 #define QPNP_TM_REG_STATUS 0x08 ··· 39 38 40 39 #define ALARM_CTRL_FORCE_ENABLE BIT(7) 41 40 42 - /* 43 - * Trip point values based on threshold control 44 - * 0 = {105 C, 125 C, 145 C} 45 - * 1 = {110 C, 130 C, 150 C} 46 - * 2 = {115 C, 135 C, 155 C} 47 - * 3 = {120 C, 140 C, 160 C} 48 - */ 49 - #define TEMP_STAGE_STEP 20000 /* Stage step: 20.000 C */ 50 - #define TEMP_STAGE_HYSTERESIS 2000 41 + #define THRESH_COUNT 4 42 + #define STAGE_COUNT 3 51 43 52 - #define TEMP_THRESH_MIN 105000 /* Threshold Min: 105 C */ 53 - #define TEMP_THRESH_STEP 5000 /* Threshold step: 5 C */ 44 + /* Over-temperature trip point values in mC */ 45 + static const long temp_map_gen1[THRESH_COUNT][STAGE_COUNT] = { 46 + { 105000, 125000, 145000 }, 47 + { 110000, 130000, 150000 }, 48 + { 115000, 135000, 155000 }, 49 + { 120000, 140000, 160000 }, 50 + }; 51 + 52 + static const long temp_map_gen2_v1[THRESH_COUNT][STAGE_COUNT] = { 53 + { 90000, 110000, 140000 }, 54 + { 95000, 115000, 145000 }, 55 + { 100000, 120000, 150000 }, 56 + { 105000, 125000, 155000 }, 57 + }; 58 + 59 + #define TEMP_THRESH_STEP 5000 /* Threshold step: 5 C */ 54 60 55 61 #define THRESH_MIN 0 56 62 #define THRESH_MAX 3 57 63 58 - /* Stage 2 Threshold Min: 125 C */ 59 - #define STAGE2_THRESHOLD_MIN 125000 60 - /* Stage 2 Threshold Max: 140 C */ 61 - #define STAGE2_THRESHOLD_MAX 140000 64 + #define TEMP_STAGE_HYSTERESIS 2000 62 65 63 66 /* Temperature in Milli Celsius reported during stage 0 if no ADC is present */ 64 67 #define DEFAULT_TEMP 37000 ··· 82 77 bool initialized; 83 78 84 79 struct iio_channel *adc; 80 + const long (*temp_map)[THRESH_COUNT][STAGE_COUNT]; 85 81 }; 86 82 87 83 /* This array maps from GEN2 alarm state to GEN1 alarm stage */ ··· 104 98 static int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 data) 105 99 { 106 100 return regmap_write(chip->map, chip->base + addr, data); 101 + } 102 + 103 + /** 104 + * qpnp_tm_decode_temp() - return temperature in mC corresponding to the 105 + * specified over-temperature stage 106 + * @chip: Pointer to the qpnp_tm chip 107 + * @stage: Over-temperature stage 108 + * 109 + * Return: temperature in mC 110 + */ 111 + static long qpnp_tm_decode_temp(struct qpnp_tm_chip *chip, unsigned int stage) 112 + { 113 + if (!chip->temp_map || chip->thresh >= THRESH_COUNT || stage == 0 || 114 + stage > STAGE_COUNT) 115 + return 0; 116 + 117 + return (*chip->temp_map)[chip->thresh][stage - 1]; 107 118 } 108 119 109 120 /** ··· 172 149 173 150 if (stage_new > stage_old) { 174 151 /* increasing stage, use lower bound */ 175 - chip->temp = (stage_new - 1) * TEMP_STAGE_STEP + 176 - chip->thresh * TEMP_THRESH_STEP + 177 - TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN; 152 + chip->temp = qpnp_tm_decode_temp(chip, stage_new) 153 + + TEMP_STAGE_HYSTERESIS; 178 154 } else if (stage_new < stage_old) { 179 155 /* decreasing stage, use upper bound */ 180 - chip->temp = stage_new * TEMP_STAGE_STEP + 181 - chip->thresh * TEMP_THRESH_STEP - 182 - TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN; 156 + chip->temp = qpnp_tm_decode_temp(chip, stage_new + 1) 157 + - TEMP_STAGE_HYSTERESIS; 183 158 } 184 159 185 160 chip->stage = stage; ··· 220 199 static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip, 221 200 int temp) 222 201 { 223 - u8 reg; 202 + long stage2_threshold_min = (*chip->temp_map)[THRESH_MIN][1]; 203 + long stage2_threshold_max = (*chip->temp_map)[THRESH_MAX][1]; 224 204 bool disable_s2_shutdown = false; 205 + u8 reg; 225 206 226 207 WARN_ON(!mutex_is_locked(&chip->lock)); 227 208 228 209 /* 229 210 * Default: S2 and S3 shutdown enabled, thresholds at 230 - * 105C/125C/145C, monitoring at 25Hz 211 + * lowest threshold set, monitoring at 25Hz 231 212 */ 232 213 reg = SHUTDOWN_CTRL1_RATE_25HZ; 233 214 234 215 if (temp == THERMAL_TEMP_INVALID || 235 - temp < STAGE2_THRESHOLD_MIN) { 216 + temp < stage2_threshold_min) { 236 217 chip->thresh = THRESH_MIN; 237 218 goto skip; 238 219 } 239 220 240 - if (temp <= STAGE2_THRESHOLD_MAX) { 221 + if (temp <= stage2_threshold_max) { 241 222 chip->thresh = THRESH_MAX - 242 - ((STAGE2_THRESHOLD_MAX - temp) / 223 + ((stage2_threshold_max - temp) / 243 224 TEMP_THRESH_STEP); 244 225 disable_s2_shutdown = true; 245 226 } else { ··· 349 326 ? chip->stage : alarm_state_map[chip->stage]; 350 327 351 328 if (stage) 352 - chip->temp = chip->thresh * TEMP_THRESH_STEP + 353 - (stage - 1) * TEMP_STAGE_STEP + 354 - TEMP_THRESH_MIN; 329 + chip->temp = qpnp_tm_decode_temp(chip, stage); 355 330 356 331 crit_temp = qpnp_tm_get_critical_trip_temp(chip); 357 332 ret = qpnp_tm_update_critical_trip_temp(chip, crit_temp); ··· 371 350 { 372 351 struct qpnp_tm_chip *chip; 373 352 struct device_node *node; 374 - u8 type, subtype; 353 + u8 type, subtype, dig_major; 375 354 u32 res; 376 355 int ret, irq; 377 356 ··· 421 400 return ret; 422 401 } 423 402 403 + ret = qpnp_tm_read(chip, QPNP_TM_REG_DIG_MAJOR, &dig_major); 404 + if (ret < 0) { 405 + dev_err(&pdev->dev, "could not read dig_major\n"); 406 + return ret; 407 + } 408 + 424 409 if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1 425 410 && subtype != QPNP_TM_SUBTYPE_GEN2)) { 426 411 dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n", ··· 435 408 } 436 409 437 410 chip->subtype = subtype; 411 + if (subtype == QPNP_TM_SUBTYPE_GEN2 && dig_major >= 1) 412 + chip->temp_map = &temp_map_gen2_v1; 413 + else 414 + chip->temp_map = &temp_map_gen1; 438 415 439 416 /* 440 417 * Register the sensor before initializing the hardware to be able to
+110 -113
drivers/thermal/qcom/tsens-8960.c
··· 10 10 #include <linux/thermal.h> 11 11 #include "tsens.h" 12 12 13 - #define CAL_MDEGC 30000 14 - 15 13 #define CONFIG_ADDR 0x3640 16 14 #define CONFIG_ADDR_8660 0x3620 17 15 /* CONFIG_ADDR bitmasks */ ··· 19 21 #define CONFIG_SHIFT_8660 28 20 22 #define CONFIG_MASK_8660 (3 << CONFIG_SHIFT_8660) 21 23 22 - #define STATUS_CNTL_ADDR_8064 0x3660 23 24 #define CNTL_ADDR 0x3620 24 25 /* CNTL_ADDR bitmasks */ 25 26 #define EN BIT(0) 26 27 #define SW_RST BIT(1) 27 - #define SENSOR0_EN BIT(3) 28 + 29 + #define MEASURE_PERIOD BIT(18) 28 30 #define SLP_CLK_ENA BIT(26) 29 31 #define SLP_CLK_ENA_8660 BIT(24) 30 - #define MEASURE_PERIOD 1 31 32 #define SENSOR0_SHIFT 3 32 33 33 - /* INT_STATUS_ADDR bitmasks */ 34 - #define MIN_STATUS_MASK BIT(0) 35 - #define LOWER_STATUS_CLR BIT(1) 36 - #define UPPER_STATUS_CLR BIT(2) 37 - #define MAX_STATUS_MASK BIT(3) 38 - 39 34 #define THRESHOLD_ADDR 0x3624 40 - /* THRESHOLD_ADDR bitmasks */ 41 - #define THRESHOLD_MAX_LIMIT_SHIFT 24 42 - #define THRESHOLD_MIN_LIMIT_SHIFT 16 43 - #define THRESHOLD_UPPER_LIMIT_SHIFT 8 44 - #define THRESHOLD_LOWER_LIMIT_SHIFT 0 45 35 46 - /* Initial temperature threshold values */ 47 - #define LOWER_LIMIT_TH 0x50 48 - #define UPPER_LIMIT_TH 0xdf 49 - #define MIN_LIMIT_TH 0x0 50 - #define MAX_LIMIT_TH 0xff 51 - 52 - #define S0_STATUS_ADDR 0x3628 53 36 #define INT_STATUS_ADDR 0x363c 54 - #define TRDY_MASK BIT(7) 55 - #define TIMEOUT_US 100 37 + 38 + #define S0_STATUS_OFF 0x3628 39 + #define S1_STATUS_OFF 0x362c 40 + #define S2_STATUS_OFF 0x3630 41 + #define S3_STATUS_OFF 0x3634 42 + #define S4_STATUS_OFF 0x3638 43 + #define S5_STATUS_OFF 0x3664 /* Sensors 5-10 found on apq8064/msm8960 */ 44 + #define S6_STATUS_OFF 0x3668 45 + #define S7_STATUS_OFF 0x366c 46 + #define S8_STATUS_OFF 0x3670 47 + #define S9_STATUS_OFF 0x3674 48 + #define S10_STATUS_OFF 0x3678 49 + 50 + /* Original slope - 350 to compensate mC to C inaccuracy */ 51 + static u32 tsens_msm8960_slope[] = { 52 + 826, 826, 804, 826, 53 + 761, 782, 782, 849, 54 + 782, 849, 782 55 + }; 56 56 57 57 static int suspend_8960(struct tsens_priv *priv) 58 58 { ··· 111 115 static int enable_8960(struct tsens_priv *priv, int id) 112 116 { 113 117 int ret; 114 - u32 reg, mask; 118 + u32 reg, mask = BIT(id); 115 119 116 120 ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg); 117 121 if (ret) 118 122 return ret; 119 123 120 - mask = BIT(id + SENSOR0_SHIFT); 124 + /* HARDWARE BUG: 125 + * On platforms with more than 6 sensors, all remaining sensors 126 + * must be enabled together, otherwise undefined results are expected. 127 + * (Sensor 6-7 disabled, Sensor 3 disabled...) In the original driver, 128 + * all the sensors are enabled in one step hence this bug is not 129 + * triggered. 130 + */ 131 + if (id > 5) 132 + mask = GENMASK(10, 6); 133 + 134 + mask <<= SENSOR0_SHIFT; 135 + 136 + /* Sensors already enabled. Skip. */ 137 + if ((reg & mask) == mask) 138 + return 0; 139 + 121 140 ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST); 122 141 if (ret) 123 142 return ret; 143 + 144 + reg |= MEASURE_PERIOD; 124 145 125 146 if (priv->num_sensors > 1) 126 147 reg |= mask | SLP_CLK_ENA | EN; ··· 175 162 regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl); 176 163 } 177 164 178 - static int init_8960(struct tsens_priv *priv) 179 - { 180 - int ret, i; 181 - u32 reg_cntl; 182 - 183 - priv->tm_map = dev_get_regmap(priv->dev, NULL); 184 - if (!priv->tm_map) 185 - return -ENODEV; 186 - 187 - /* 188 - * The status registers for each sensor are discontiguous 189 - * because some SoCs have 5 sensors while others have more 190 - * but the control registers stay in the same place, i.e 191 - * directly after the first 5 status registers. 192 - */ 193 - for (i = 0; i < priv->num_sensors; i++) { 194 - if (i >= 5) 195 - priv->sensor[i].status = S0_STATUS_ADDR + 40; 196 - priv->sensor[i].status += i * 4; 197 - } 198 - 199 - reg_cntl = SW_RST; 200 - ret = regmap_update_bits(priv->tm_map, CNTL_ADDR, SW_RST, reg_cntl); 201 - if (ret) 202 - return ret; 203 - 204 - if (priv->num_sensors > 1) { 205 - reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18); 206 - reg_cntl &= ~SW_RST; 207 - ret = regmap_update_bits(priv->tm_map, CONFIG_ADDR, 208 - CONFIG_MASK, CONFIG); 209 - } else { 210 - reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16); 211 - reg_cntl &= ~CONFIG_MASK_8660; 212 - reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660; 213 - } 214 - 215 - reg_cntl |= GENMASK(priv->num_sensors - 1, 0) << SENSOR0_SHIFT; 216 - ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl); 217 - if (ret) 218 - return ret; 219 - 220 - reg_cntl |= EN; 221 - ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl); 222 - if (ret) 223 - return ret; 224 - 225 - return 0; 226 - } 227 - 228 165 static int calibrate_8960(struct tsens_priv *priv) 229 166 { 230 167 int i; 231 168 char *data; 232 - 233 - ssize_t num_read = priv->num_sensors; 234 - struct tsens_sensor *s = priv->sensor; 169 + u32 p1[11]; 235 170 236 171 data = qfprom_read(priv->dev, "calib"); 237 172 if (IS_ERR(data)) ··· 187 226 if (IS_ERR(data)) 188 227 return PTR_ERR(data); 189 228 190 - for (i = 0; i < num_read; i++, s++) 191 - s->offset = data[i]; 229 + for (i = 0; i < priv->num_sensors; i++) { 230 + p1[i] = data[i]; 231 + priv->sensor[i].slope = tsens_msm8960_slope[i]; 232 + } 233 + 234 + compute_intercept_slope(priv, p1, NULL, ONE_PT_CALIB); 192 235 193 236 kfree(data); 194 237 195 238 return 0; 196 239 } 197 240 198 - /* Temperature on y axis and ADC-code on x-axis */ 199 - static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s) 200 - { 201 - int slope, offset; 241 + static const struct reg_field tsens_8960_regfields[MAX_REGFIELDS] = { 242 + /* ----- SROT ------ */ 243 + /* No VERSION information */ 202 244 203 - slope = thermal_zone_get_slope(s->tzd); 204 - offset = CAL_MDEGC - slope * s->offset; 245 + /* CNTL */ 246 + [TSENS_EN] = REG_FIELD(CNTL_ADDR, 0, 0), 247 + [TSENS_SW_RST] = REG_FIELD(CNTL_ADDR, 1, 1), 248 + /* 8960 has 5 sensors, 8660 has 11, we only handle 5 */ 249 + [SENSOR_EN] = REG_FIELD(CNTL_ADDR, 3, 7), 205 250 206 - return adc_code * slope + offset; 207 - } 251 + /* ----- TM ------ */ 252 + /* INTERRUPT ENABLE */ 253 + /* NO INTERRUPT ENABLE */ 208 254 209 - static int get_temp_8960(const struct tsens_sensor *s, int *temp) 210 - { 211 - int ret; 212 - u32 code, trdy; 213 - struct tsens_priv *priv = s->priv; 214 - unsigned long timeout; 255 + /* Single UPPER/LOWER TEMPERATURE THRESHOLD for all sensors */ 256 + [LOW_THRESH_0] = REG_FIELD(THRESHOLD_ADDR, 0, 7), 257 + [UP_THRESH_0] = REG_FIELD(THRESHOLD_ADDR, 8, 15), 258 + /* MIN_THRESH_0 and MAX_THRESH_0 are not present in the regfield 259 + * Recycle CRIT_THRESH_0 and 1 to set the required regs to hardcoded temp 260 + * MIN_THRESH_0 -> CRIT_THRESH_1 261 + * MAX_THRESH_0 -> CRIT_THRESH_0 262 + */ 263 + [CRIT_THRESH_1] = REG_FIELD(THRESHOLD_ADDR, 16, 23), 264 + [CRIT_THRESH_0] = REG_FIELD(THRESHOLD_ADDR, 24, 31), 215 265 216 - timeout = jiffies + usecs_to_jiffies(TIMEOUT_US); 217 - do { 218 - ret = regmap_read(priv->tm_map, INT_STATUS_ADDR, &trdy); 219 - if (ret) 220 - return ret; 221 - if (!(trdy & TRDY_MASK)) 222 - continue; 223 - ret = regmap_read(priv->tm_map, s->status, &code); 224 - if (ret) 225 - return ret; 226 - *temp = code_to_mdegC(code, s); 227 - return 0; 228 - } while (time_before(jiffies, timeout)); 266 + /* UPPER/LOWER INTERRUPT [CLEAR/STATUS] */ 267 + /* 1 == clear, 0 == normal operation */ 268 + [LOW_INT_CLEAR_0] = REG_FIELD(CNTL_ADDR, 9, 9), 269 + [UP_INT_CLEAR_0] = REG_FIELD(CNTL_ADDR, 10, 10), 229 270 230 - return -ETIMEDOUT; 231 - } 271 + /* NO CRITICAL INTERRUPT SUPPORT on 8960 */ 272 + 273 + /* Sn_STATUS */ 274 + [LAST_TEMP_0] = REG_FIELD(S0_STATUS_OFF, 0, 7), 275 + [LAST_TEMP_1] = REG_FIELD(S1_STATUS_OFF, 0, 7), 276 + [LAST_TEMP_2] = REG_FIELD(S2_STATUS_OFF, 0, 7), 277 + [LAST_TEMP_3] = REG_FIELD(S3_STATUS_OFF, 0, 7), 278 + [LAST_TEMP_4] = REG_FIELD(S4_STATUS_OFF, 0, 7), 279 + [LAST_TEMP_5] = REG_FIELD(S5_STATUS_OFF, 0, 7), 280 + [LAST_TEMP_6] = REG_FIELD(S6_STATUS_OFF, 0, 7), 281 + [LAST_TEMP_7] = REG_FIELD(S7_STATUS_OFF, 0, 7), 282 + [LAST_TEMP_8] = REG_FIELD(S8_STATUS_OFF, 0, 7), 283 + [LAST_TEMP_9] = REG_FIELD(S9_STATUS_OFF, 0, 7), 284 + [LAST_TEMP_10] = REG_FIELD(S10_STATUS_OFF, 0, 7), 285 + 286 + /* No VALID field on 8960 */ 287 + /* TSENS_INT_STATUS bits: 1 == threshold violated */ 288 + [MIN_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 0, 0), 289 + [LOWER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 1, 1), 290 + [UPPER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 2, 2), 291 + /* No CRITICAL field on 8960 */ 292 + [MAX_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 3, 3), 293 + 294 + /* TRDY: 1=ready, 0=in progress */ 295 + [TRDY] = REG_FIELD(INT_STATUS_ADDR, 7, 7), 296 + }; 232 297 233 298 static const struct tsens_ops ops_8960 = { 234 - .init = init_8960, 299 + .init = init_common, 235 300 .calibrate = calibrate_8960, 236 - .get_temp = get_temp_8960, 301 + .get_temp = get_temp_common, 237 302 .enable = enable_8960, 238 303 .disable = disable_8960, 239 304 .suspend = suspend_8960, 240 305 .resume = resume_8960, 241 306 }; 242 307 308 + static struct tsens_features tsens_8960_feat = { 309 + .ver_major = VER_0, 310 + .crit_int = 0, 311 + .adc = 1, 312 + .srot_split = 0, 313 + .max_sensors = 11, 314 + }; 315 + 243 316 struct tsens_plat_data data_8960 = { 244 317 .num_sensors = 11, 245 318 .ops = &ops_8960, 319 + .feat = &tsens_8960_feat, 320 + .fields = tsens_8960_regfields, 246 321 };
+97 -1
drivers/thermal/qcom/tsens-v0_1.c
··· 190 190 191 191 #define BIT_APPEND 0x3 192 192 193 + /* eeprom layout data for mdm9607 */ 194 + #define MDM9607_BASE0_MASK 0x000000ff 195 + #define MDM9607_BASE1_MASK 0x000ff000 196 + #define MDM9607_BASE0_SHIFT 0 197 + #define MDM9607_BASE1_SHIFT 12 198 + 199 + #define MDM9607_S0_P1_MASK 0x00003f00 200 + #define MDM9607_S1_P1_MASK 0x03f00000 201 + #define MDM9607_S2_P1_MASK 0x0000003f 202 + #define MDM9607_S3_P1_MASK 0x0003f000 203 + #define MDM9607_S4_P1_MASK 0x0000003f 204 + 205 + #define MDM9607_S0_P2_MASK 0x000fc000 206 + #define MDM9607_S1_P2_MASK 0xfc000000 207 + #define MDM9607_S2_P2_MASK 0x00000fc0 208 + #define MDM9607_S3_P2_MASK 0x00fc0000 209 + #define MDM9607_S4_P2_MASK 0x00000fc0 210 + 211 + #define MDM9607_S0_P1_SHIFT 8 212 + #define MDM9607_S1_P1_SHIFT 20 213 + #define MDM9607_S2_P1_SHIFT 0 214 + #define MDM9607_S3_P1_SHIFT 12 215 + #define MDM9607_S4_P1_SHIFT 0 216 + 217 + #define MDM9607_S0_P2_SHIFT 14 218 + #define MDM9607_S1_P2_SHIFT 26 219 + #define MDM9607_S2_P2_SHIFT 6 220 + #define MDM9607_S3_P2_SHIFT 18 221 + #define MDM9607_S4_P2_SHIFT 6 222 + 223 + #define MDM9607_CAL_SEL_MASK 0x00700000 224 + #define MDM9607_CAL_SEL_SHIFT 20 225 + 193 226 static int calibrate_8916(struct tsens_priv *priv) 194 227 { 195 228 int base0 = 0, base1 = 0, i; ··· 485 452 return 0; 486 453 } 487 454 488 - /* v0.1: 8916, 8939, 8974 */ 455 + static int calibrate_9607(struct tsens_priv *priv) 456 + { 457 + int base, i; 458 + u32 p1[5], p2[5]; 459 + int mode = 0; 460 + u32 *qfprom_cdata; 461 + 462 + qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 463 + if (IS_ERR(qfprom_cdata)) 464 + return PTR_ERR(qfprom_cdata); 465 + 466 + mode = (qfprom_cdata[2] & MDM9607_CAL_SEL_MASK) >> MDM9607_CAL_SEL_SHIFT; 467 + dev_dbg(priv->dev, "calibration mode is %d\n", mode); 468 + 469 + switch (mode) { 470 + case TWO_PT_CALIB: 471 + base = (qfprom_cdata[2] & MDM9607_BASE1_MASK) >> MDM9607_BASE1_SHIFT; 472 + p2[0] = (qfprom_cdata[0] & MDM9607_S0_P2_MASK) >> MDM9607_S0_P2_SHIFT; 473 + p2[1] = (qfprom_cdata[0] & MDM9607_S1_P2_MASK) >> MDM9607_S1_P2_SHIFT; 474 + p2[2] = (qfprom_cdata[1] & MDM9607_S2_P2_MASK) >> MDM9607_S2_P2_SHIFT; 475 + p2[3] = (qfprom_cdata[1] & MDM9607_S3_P2_MASK) >> MDM9607_S3_P2_SHIFT; 476 + p2[4] = (qfprom_cdata[2] & MDM9607_S4_P2_MASK) >> MDM9607_S4_P2_SHIFT; 477 + for (i = 0; i < priv->num_sensors; i++) 478 + p2[i] = ((base + p2[i]) << 2); 479 + fallthrough; 480 + case ONE_PT_CALIB2: 481 + base = (qfprom_cdata[0] & MDM9607_BASE0_MASK); 482 + p1[0] = (qfprom_cdata[0] & MDM9607_S0_P1_MASK) >> MDM9607_S0_P1_SHIFT; 483 + p1[1] = (qfprom_cdata[0] & MDM9607_S1_P1_MASK) >> MDM9607_S1_P1_SHIFT; 484 + p1[2] = (qfprom_cdata[1] & MDM9607_S2_P1_MASK) >> MDM9607_S2_P1_SHIFT; 485 + p1[3] = (qfprom_cdata[1] & MDM9607_S3_P1_MASK) >> MDM9607_S3_P1_SHIFT; 486 + p1[4] = (qfprom_cdata[2] & MDM9607_S4_P1_MASK) >> MDM9607_S4_P1_SHIFT; 487 + for (i = 0; i < priv->num_sensors; i++) 488 + p1[i] = ((base + p1[i]) << 2); 489 + break; 490 + default: 491 + for (i = 0; i < priv->num_sensors; i++) { 492 + p1[i] = 500; 493 + p2[i] = 780; 494 + } 495 + break; 496 + } 497 + 498 + compute_intercept_slope(priv, p1, p2, mode); 499 + kfree(qfprom_cdata); 500 + 501 + return 0; 502 + } 503 + 504 + /* v0.1: 8916, 8939, 8974, 9607 */ 489 505 490 506 static struct tsens_features tsens_v0_1_feat = { 491 507 .ver_major = VER_0_1, ··· 619 537 struct tsens_plat_data data_8974 = { 620 538 .num_sensors = 11, 621 539 .ops = &ops_8974, 540 + .feat = &tsens_v0_1_feat, 541 + .fields = tsens_v0_1_regfields, 542 + }; 543 + 544 + static const struct tsens_ops ops_9607 = { 545 + .init = init_common, 546 + .calibrate = calibrate_9607, 547 + .get_temp = get_temp_common, 548 + }; 549 + 550 + struct tsens_plat_data data_9607 = { 551 + .num_sensors = 5, 552 + .ops = &ops_9607, 553 + .hw_ids = (unsigned int []){ 0, 1, 2, 3, 4 }, 622 554 .feat = &tsens_v0_1_feat, 623 555 .fields = tsens_v0_1_regfields, 624 556 };
+2 -2
drivers/thermal/qcom/tsens-v1.c
··· 380 380 .get_temp = get_temp_tsens_valid, 381 381 }; 382 382 383 - /* Valid for both MSM8956 and MSM8976. Sensor ID 3 is unused. */ 383 + /* Valid for both MSM8956 and MSM8976. */ 384 384 struct tsens_plat_data data_8976 = { 385 385 .num_sensors = 11, 386 386 .ops = &ops_8976, 387 - .hw_ids = (unsigned int[]){0, 1, 2, 4, 5, 6, 7, 8, 9, 10}, 387 + .hw_ids = (unsigned int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 388 388 .feat = &tsens_v1_feat, 389 389 .fields = tsens_v1_regfields, 390 390 };
+134 -33
drivers/thermal/qcom/tsens.c
··· 12 12 #include <linux/of.h> 13 13 #include <linux/of_address.h> 14 14 #include <linux/of_platform.h> 15 + #include <linux/mfd/syscon.h> 15 16 #include <linux/platform_device.h> 16 17 #include <linux/pm.h> 17 18 #include <linux/regmap.h> ··· 86 85 "%s: sensor%d - data_point1:%#x data_point2:%#x\n", 87 86 __func__, i, p1[i], p2[i]); 88 87 89 - priv->sensor[i].slope = SLOPE_DEFAULT; 88 + if (!priv->sensor[i].slope) 89 + priv->sensor[i].slope = SLOPE_DEFAULT; 90 90 if (mode == TWO_PT_CALIB) { 91 91 /* 92 92 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/ ··· 517 515 dev_dbg(priv->dev, "[%u] %s: no violation: %d\n", 518 516 hw_id, __func__, temp); 519 517 } 518 + 519 + if (tsens_version(priv) < VER_0_1) { 520 + /* Constraint: There is only 1 interrupt control register for all 521 + * 11 temperature sensor. So monitoring more than 1 sensor based 522 + * on interrupts will yield inconsistent result. To overcome this 523 + * issue we will monitor only sensor 0 which is the master sensor. 524 + */ 525 + break; 526 + } 520 527 } 521 528 522 529 return IRQ_HANDLED; ··· 540 529 unsigned long flags; 541 530 int high_val, low_val, cl_high, cl_low; 542 531 u32 hw_id = s->hw_id; 532 + 533 + if (tsens_version(priv) < VER_0_1) { 534 + /* Pre v0.1 IP had a single register for each type of interrupt 535 + * and thresholds 536 + */ 537 + hw_id = 0; 538 + } 543 539 544 540 dev_dbg(dev, "[%u] %s: proposed thresholds: (%d:%d)\n", 545 541 hw_id, __func__, low, high); ··· 602 584 u32 valid; 603 585 int ret; 604 586 605 - ret = regmap_field_read(priv->rf[valid_idx], &valid); 606 - if (ret) 607 - return ret; 608 - while (!valid) { 609 - /* Valid bit is 0 for 6 AHB clock cycles. 610 - * At 19.2MHz, 1 AHB clock is ~60ns. 611 - * We should enter this loop very, very rarely. 612 - */ 613 - ndelay(400); 587 + /* VER_0 doesn't have VALID bit */ 588 + if (tsens_version(priv) >= VER_0_1) { 614 589 ret = regmap_field_read(priv->rf[valid_idx], &valid); 615 590 if (ret) 616 591 return ret; 592 + while (!valid) { 593 + /* Valid bit is 0 for 6 AHB clock cycles. 594 + * At 19.2MHz, 1 AHB clock is ~60ns. 595 + * We should enter this loop very, very rarely. 596 + */ 597 + ndelay(400); 598 + ret = regmap_field_read(priv->rf[valid_idx], &valid); 599 + if (ret) 600 + return ret; 601 + } 617 602 } 618 603 619 604 /* Valid bit is set, OK to read the temperature */ ··· 629 608 { 630 609 struct tsens_priv *priv = s->priv; 631 610 int hw_id = s->hw_id; 632 - int last_temp = 0, ret; 611 + int last_temp = 0, ret, trdy; 612 + unsigned long timeout; 633 613 634 - ret = regmap_field_read(priv->rf[LAST_TEMP_0 + hw_id], &last_temp); 635 - if (ret) 636 - return ret; 614 + timeout = jiffies + usecs_to_jiffies(TIMEOUT_US); 615 + do { 616 + if (tsens_version(priv) == VER_0) { 617 + ret = regmap_field_read(priv->rf[TRDY], &trdy); 618 + if (ret) 619 + return ret; 620 + if (!trdy) 621 + continue; 622 + } 637 623 638 - *temp = code_to_degc(last_temp, s) * 1000; 624 + ret = regmap_field_read(priv->rf[LAST_TEMP_0 + hw_id], &last_temp); 625 + if (ret) 626 + return ret; 639 627 640 - return 0; 628 + *temp = code_to_degc(last_temp, s) * 1000; 629 + 630 + return 0; 631 + } while (time_before(jiffies, timeout)); 632 + 633 + return -ETIMEDOUT; 641 634 } 642 635 643 636 #ifdef CONFIG_DEBUG_FS ··· 773 738 priv->tm_offset = 0x1000; 774 739 } 775 740 776 - res = platform_get_resource(op, IORESOURCE_MEM, 0); 777 - tm_base = devm_ioremap_resource(dev, res); 778 - if (IS_ERR(tm_base)) { 779 - ret = PTR_ERR(tm_base); 741 + if (tsens_version(priv) >= VER_0_1) { 742 + res = platform_get_resource(op, IORESOURCE_MEM, 0); 743 + tm_base = devm_ioremap_resource(dev, res); 744 + if (IS_ERR(tm_base)) { 745 + ret = PTR_ERR(tm_base); 746 + goto err_put_device; 747 + } 748 + 749 + priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config); 750 + } else { /* VER_0 share the same gcc regs using a syscon */ 751 + struct device *parent = priv->dev->parent; 752 + 753 + if (parent) 754 + priv->tm_map = syscon_node_to_regmap(parent->of_node); 755 + } 756 + 757 + if (IS_ERR_OR_NULL(priv->tm_map)) { 758 + if (!priv->tm_map) 759 + ret = -ENODEV; 760 + else 761 + ret = PTR_ERR(priv->tm_map); 780 762 goto err_put_device; 781 763 } 782 764 783 - priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config); 784 - if (IS_ERR(priv->tm_map)) { 785 - ret = PTR_ERR(priv->tm_map); 786 - goto err_put_device; 787 - } 765 + /* VER_0 have only tm_map */ 766 + if (!priv->srot_map) 767 + priv->srot_map = priv->tm_map; 788 768 789 769 if (tsens_version(priv) > VER_0_1) { 790 770 for (i = VER_MAJOR; i <= VER_STEP; i++) { 791 771 priv->rf[i] = devm_regmap_field_alloc(dev, priv->srot_map, 792 772 priv->fields[i]); 793 - if (IS_ERR(priv->rf[i])) 794 - return PTR_ERR(priv->rf[i]); 773 + if (IS_ERR(priv->rf[i])) { 774 + ret = PTR_ERR(priv->rf[i]); 775 + goto err_put_device; 776 + } 795 777 } 796 778 ret = regmap_field_read(priv->rf[VER_MINOR], &ver_minor); 797 779 if (ret) ··· 821 769 ret = PTR_ERR(priv->rf[TSENS_EN]); 822 770 goto err_put_device; 823 771 } 772 + /* in VER_0 TSENS need to be explicitly enabled */ 773 + if (tsens_version(priv) == VER_0) 774 + regmap_field_write(priv->rf[TSENS_EN], 1); 775 + 824 776 ret = regmap_field_read(priv->rf[TSENS_EN], &enabled); 825 777 if (ret) 826 778 goto err_put_device; ··· 847 791 goto err_put_device; 848 792 } 849 793 794 + priv->rf[TSENS_SW_RST] = 795 + devm_regmap_field_alloc(dev, priv->srot_map, priv->fields[TSENS_SW_RST]); 796 + if (IS_ERR(priv->rf[TSENS_SW_RST])) { 797 + ret = PTR_ERR(priv->rf[TSENS_SW_RST]); 798 + goto err_put_device; 799 + } 800 + 801 + priv->rf[TRDY] = devm_regmap_field_alloc(dev, priv->tm_map, priv->fields[TRDY]); 802 + if (IS_ERR(priv->rf[TRDY])) { 803 + ret = PTR_ERR(priv->rf[TRDY]); 804 + goto err_put_device; 805 + } 806 + 850 807 /* This loop might need changes if enum regfield_ids is reordered */ 851 808 for (j = LAST_TEMP_0; j <= UP_THRESH_15; j += 16) { 852 809 for (i = 0; i < priv->feat->max_sensors; i++) { ··· 875 806 } 876 807 } 877 808 878 - if (priv->feat->crit_int) { 809 + if (priv->feat->crit_int || tsens_version(priv) < VER_0_1) { 879 810 /* Loop might need changes if enum regfield_ids is reordered */ 880 811 for (j = CRITICAL_STATUS_0; j <= CRIT_THRESH_15; j += 16) { 881 812 for (i = 0; i < priv->feat->max_sensors; i++) { ··· 913 844 } 914 845 915 846 spin_lock_init(&priv->ul_lock); 916 - tsens_enable_irq(priv); 847 + 848 + /* VER_0 interrupt doesn't need to be enabled */ 849 + if (tsens_version(priv) >= VER_0_1) 850 + tsens_enable_irq(priv); 851 + 917 852 tsens_debug_init(op); 918 853 919 854 err_put_device: ··· 968 895 969 896 static const struct of_device_id tsens_table[] = { 970 897 { 898 + .compatible = "qcom,ipq8064-tsens", 899 + .data = &data_8960, 900 + }, { 901 + .compatible = "qcom,mdm9607-tsens", 902 + .data = &data_9607, 903 + }, { 971 904 .compatible = "qcom,msm8916-tsens", 972 905 .data = &data_8916, 973 906 }, { ··· 1022 943 if (irq == -ENXIO) 1023 944 ret = 0; 1024 945 } else { 1025 - ret = devm_request_threaded_irq(&pdev->dev, irq, 1026 - NULL, thread_fn, 1027 - IRQF_ONESHOT, 1028 - dev_name(&pdev->dev), priv); 946 + /* VER_0 interrupt is TRIGGER_RISING, VER_0_1 and up is ONESHOT */ 947 + if (tsens_version(priv) == VER_0) 948 + ret = devm_request_threaded_irq(&pdev->dev, irq, 949 + thread_fn, NULL, 950 + IRQF_TRIGGER_RISING, 951 + dev_name(&pdev->dev), 952 + priv); 953 + else 954 + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 955 + thread_fn, IRQF_ONESHOT, 956 + dev_name(&pdev->dev), 957 + priv); 958 + 1029 959 if (ret) 1030 960 dev_err(&pdev->dev, "%s: failed to get irq\n", 1031 961 __func__); ··· 1061 973 priv->sensor[i].tzd = tzd; 1062 974 if (priv->ops->enable) 1063 975 priv->ops->enable(priv, i); 976 + } 977 + 978 + /* VER_0 require to set MIN and MAX THRESH 979 + * These 2 regs are set using the: 980 + * - CRIT_THRESH_0 for MAX THRESH hardcoded to 120°C 981 + * - CRIT_THRESH_1 for MIN THRESH hardcoded to 0°C 982 + */ 983 + if (tsens_version(priv) < VER_0_1) { 984 + regmap_field_write(priv->rf[CRIT_THRESH_0], 985 + tsens_mC_to_hw(priv->sensor, 120000)); 986 + 987 + regmap_field_write(priv->rf[CRIT_THRESH_1], 988 + tsens_mC_to_hw(priv->sensor, 0)); 1064 989 } 1065 990 1066 991 ret = tsens_register_irq(priv, "uplow", tsens_irq_thread);
+4 -2
drivers/thermal/qcom/tsens.h
··· 13 13 #define CAL_DEGC_PT2 120 14 14 #define SLOPE_FACTOR 1000 15 15 #define SLOPE_DEFAULT 3200 16 + #define TIMEOUT_US 100 16 17 #define THRESHOLD_MAX_ADC_CODE 0x3ff 17 18 #define THRESHOLD_MIN_ADC_CODE 0x0 18 19 ··· 26 25 27 26 /* IP version numbers in ascending order */ 28 27 enum tsens_ver { 29 - VER_0_1 = 0, 28 + VER_0 = 0, 29 + VER_0_1, 30 30 VER_1_X, 31 31 VER_2_X, 32 32 }; ··· 587 585 extern struct tsens_plat_data data_8960; 588 586 589 587 /* TSENS v0.1 targets */ 590 - extern struct tsens_plat_data data_8916, data_8939, data_8974; 588 + extern struct tsens_plat_data data_8916, data_8939, data_8974, data_9607; 591 589 592 590 /* TSENS v1 targets */ 593 591 extern struct tsens_plat_data data_tsens_v1, data_8976;
+2 -1
drivers/thermal/rcar_gen3_thermal.c
··· 60 60 #define MCELSIUS(temp) ((temp) * 1000) 61 61 #define GEN3_FUSE_MASK 0xFFF 62 62 63 - #define TSC_MAX_NUM 4 63 + #define TSC_MAX_NUM 5 64 64 65 65 /* default THCODE values if FUSEs are missing */ 66 66 static const int thcodes[TSC_MAX_NUM][3] = { ··· 68 68 { 3393, 2795, 2216 }, 69 69 { 3389, 2805, 2237 }, 70 70 { 3415, 2694, 2195 }, 71 + { 3356, 2724, 2244 }, 71 72 }; 72 73 73 74 /* Structure for thermal temperature calculation */
+2 -2
drivers/thermal/sun8i_thermal.c
··· 300 300 * or 0x8xx, so they won't be away from the default value 301 301 * for a lot. 302 302 * 303 - * So here we do not return error if the calibartion data is 303 + * So here we do not return error if the calibration data is 304 304 * not available, except the probe needs deferring. 305 305 */ 306 306 goto out; ··· 418 418 } 419 419 420 420 /* 421 - * Without this undocummented value, the returned temperatures would 421 + * Without this undocumented value, the returned temperatures would 422 422 * be higher than real ones by about 20C. 423 423 */ 424 424 #define SUN50I_H6_CTRL0_UNK 0x0000002f
+4 -11
drivers/thermal/tegra/soctherm.c
··· 2118 2118 struct tegra_soctherm *tegra; 2119 2119 struct thermal_zone_device *z; 2120 2120 struct tsensor_shared_calib shared_calib; 2121 - struct resource *res; 2122 2121 struct tegra_soctherm_soc *soc; 2123 2122 unsigned int i; 2124 2123 int err; ··· 2139 2140 2140 2141 tegra->soc = soc; 2141 2142 2142 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 2143 - "soctherm-reg"); 2144 - tegra->regs = devm_ioremap_resource(&pdev->dev, res); 2143 + tegra->regs = devm_platform_ioremap_resource_byname(pdev, "soctherm-reg"); 2145 2144 if (IS_ERR(tegra->regs)) { 2146 2145 dev_err(&pdev->dev, "can't get soctherm registers"); 2147 2146 return PTR_ERR(tegra->regs); 2148 2147 } 2149 2148 2150 2149 if (!tegra->soc->use_ccroc) { 2151 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 2152 - "car-reg"); 2153 - tegra->clk_regs = devm_ioremap_resource(&pdev->dev, res); 2150 + tegra->clk_regs = devm_platform_ioremap_resource_byname(pdev, "car-reg"); 2154 2151 if (IS_ERR(tegra->clk_regs)) { 2155 2152 dev_err(&pdev->dev, "can't get car clk registers"); 2156 2153 return PTR_ERR(tegra->clk_regs); 2157 2154 } 2158 2155 } else { 2159 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 2160 - "ccroc-reg"); 2161 - tegra->ccroc_regs = devm_ioremap_resource(&pdev->dev, res); 2156 + tegra->ccroc_regs = devm_platform_ioremap_resource_byname(pdev, "ccroc-reg"); 2162 2157 if (IS_ERR(tegra->ccroc_regs)) { 2163 2158 dev_err(&pdev->dev, "can't get ccroc registers"); 2164 2159 return PTR_ERR(tegra->ccroc_regs); ··· 2188 2195 if (err) 2189 2196 return err; 2190 2197 2191 - /* calculate tsensor calibaration data */ 2198 + /* calculate tsensor calibration data */ 2192 2199 for (i = 0; i < soc->num_tsensors; ++i) { 2193 2200 err = tegra_calc_tsensor_calib(&soc->tsensors[i], 2194 2201 &shared_calib,
+23 -34
drivers/thermal/thermal_core.c
··· 561 561 } 562 562 EXPORT_SYMBOL_GPL(thermal_zone_device_update); 563 563 564 - /** 565 - * thermal_notify_framework - Sensor drivers use this API to notify framework 566 - * @tz: thermal zone device 567 - * @trip: indicates which trip point has been crossed 568 - * 569 - * This function handles the trip events from sensor drivers. It starts 570 - * throttling the cooling devices according to the policy configured. 571 - * For CRITICAL and HOT trip points, this notifies the respective drivers, 572 - * and does actual throttling for other trip points i.e ACTIVE and PASSIVE. 573 - * The throttling policy is based on the configured platform data; if no 574 - * platform data is provided, this uses the step_wise throttling policy. 575 - */ 576 - void thermal_notify_framework(struct thermal_zone_device *tz, int trip) 577 - { 578 - handle_thermal_trip(tz, trip); 579 - } 580 - EXPORT_SYMBOL_GPL(thermal_notify_framework); 581 - 582 564 static void thermal_zone_device_check(struct work_struct *work) 583 565 { 584 566 struct thermal_zone_device *tz = container_of(work, struct ··· 942 960 { 943 961 struct thermal_cooling_device *cdev; 944 962 struct thermal_zone_device *pos = NULL; 945 - int result; 946 - 947 - if (type && strlen(type) >= THERMAL_NAME_LENGTH) 948 - return ERR_PTR(-EINVAL); 963 + int ret; 949 964 950 965 if (!ops || !ops->get_max_state || !ops->get_cur_state || 951 966 !ops->set_cur_state) ··· 952 973 if (!cdev) 953 974 return ERR_PTR(-ENOMEM); 954 975 955 - result = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL); 956 - if (result < 0) { 957 - kfree(cdev); 958 - return ERR_PTR(result); 976 + ret = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL); 977 + if (ret < 0) 978 + goto out_kfree_cdev; 979 + cdev->id = ret; 980 + 981 + cdev->type = kstrdup(type ? type : "", GFP_KERNEL); 982 + if (!cdev->type) { 983 + ret = -ENOMEM; 984 + goto out_ida_remove; 959 985 } 960 986 961 - cdev->id = result; 962 - strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); 963 987 mutex_init(&cdev->lock); 964 988 INIT_LIST_HEAD(&cdev->thermal_instances); 965 989 cdev->np = np; ··· 972 990 cdev->devdata = devdata; 973 991 thermal_cooling_device_setup_sysfs(cdev); 974 992 dev_set_name(&cdev->device, "cooling_device%d", cdev->id); 975 - result = device_register(&cdev->device); 976 - if (result) { 977 - ida_simple_remove(&thermal_cdev_ida, cdev->id); 978 - put_device(&cdev->device); 979 - return ERR_PTR(result); 980 - } 993 + ret = device_register(&cdev->device); 994 + if (ret) 995 + goto out_kfree_type; 981 996 982 997 /* Add 'this' new cdev to the global cdev list */ 983 998 mutex_lock(&thermal_list_lock); ··· 992 1013 mutex_unlock(&thermal_list_lock); 993 1014 994 1015 return cdev; 1016 + 1017 + out_kfree_type: 1018 + kfree(cdev->type); 1019 + put_device(&cdev->device); 1020 + out_ida_remove: 1021 + ida_simple_remove(&thermal_cdev_ida, cdev->id); 1022 + out_kfree_cdev: 1023 + kfree(cdev); 1024 + return ERR_PTR(ret); 995 1025 } 996 1026 997 1027 /** ··· 1159 1171 ida_simple_remove(&thermal_cdev_ida, cdev->id); 1160 1172 device_del(&cdev->device); 1161 1173 thermal_cooling_device_destroy_sysfs(cdev); 1174 + kfree(cdev->type); 1162 1175 put_device(&cdev->device); 1163 1176 } 1164 1177 EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);
+1
drivers/thermal/thermal_core.h
··· 66 66 } 67 67 68 68 void thermal_cdev_update(struct thermal_cooling_device *); 69 + void __thermal_cdev_update(struct thermal_cooling_device *cdev); 69 70 70 71 /** 71 72 * struct thermal_trip - representation of a point in temperature domain
+17 -10
drivers/thermal/thermal_helpers.c
··· 192 192 thermal_cooling_device_stats_update(cdev, target); 193 193 } 194 194 195 - void thermal_cdev_update(struct thermal_cooling_device *cdev) 195 + void __thermal_cdev_update(struct thermal_cooling_device *cdev) 196 196 { 197 197 struct thermal_instance *instance; 198 198 unsigned long target = 0; 199 - 200 - mutex_lock(&cdev->lock); 201 - /* cooling device is updated*/ 202 - if (cdev->updated) { 203 - mutex_unlock(&cdev->lock); 204 - return; 205 - } 206 199 207 200 /* Make sure cdev enters the deepest cooling state */ 208 201 list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { ··· 209 216 210 217 thermal_cdev_set_cur_state(cdev, target); 211 218 212 - cdev->updated = true; 213 - mutex_unlock(&cdev->lock); 214 219 trace_cdev_update(cdev, target); 215 220 dev_dbg(&cdev->device, "set to state %lu\n", target); 221 + } 222 + 223 + /** 224 + * thermal_cdev_update - update cooling device state if needed 225 + * @cdev: pointer to struct thermal_cooling_device 226 + * 227 + * Update the cooling device state if there is a need. 228 + */ 229 + void thermal_cdev_update(struct thermal_cooling_device *cdev) 230 + { 231 + mutex_lock(&cdev->lock); 232 + if (!cdev->updated) { 233 + __thermal_cdev_update(cdev); 234 + cdev->updated = true; 235 + } 236 + mutex_unlock(&cdev->lock); 216 237 } 217 238 EXPORT_SYMBOL(thermal_cdev_update); 218 239
+1 -4
drivers/thermal/thermal_mmio.c
··· 54 54 55 55 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); 56 56 sensor->mmio_base = devm_ioremap_resource(&pdev->dev, resource); 57 - if (IS_ERR(sensor->mmio_base)) { 58 - dev_err(&pdev->dev, "failed to ioremap memory (%ld)\n", 59 - PTR_ERR(sensor->mmio_base)); 57 + if (IS_ERR(sensor->mmio_base)) 60 58 return PTR_ERR(sensor->mmio_base); 61 - } 62 59 63 60 sensor_init_func = device_get_match_data(&pdev->dev); 64 61 if (sensor_init_func) {
+5 -2
drivers/thermal/thermal_of.c
··· 704 704 705 705 count = of_count_phandle_with_args(np, "cooling-device", 706 706 "#cooling-cells"); 707 - if (!count) { 707 + if (count <= 0) { 708 708 pr_err("Add a cooling_device property with at least one device\n"); 709 + ret = -ENOENT; 709 710 goto end; 710 711 } 711 712 712 713 __tcbp = kcalloc(count, sizeof(*__tcbp), GFP_KERNEL); 713 - if (!__tcbp) 714 + if (!__tcbp) { 715 + ret = -ENOMEM; 714 716 goto end; 717 + } 715 718 716 719 for (i = 0; i < count; i++) { 717 720 ret = of_parse_phandle_with_args(np, "cooling-device",
+18 -23
drivers/thermal/ti-soc-thermal/ti-bandgap.c
··· 9 9 * Eduardo Valentin <eduardo.valentin@ti.com> 10 10 */ 11 11 12 - #include <linux/module.h> 13 - #include <linux/export.h> 14 - #include <linux/init.h> 15 - #include <linux/kernel.h> 16 - #include <linux/interrupt.h> 17 12 #include <linux/clk.h> 18 - #include <linux/gpio/consumer.h> 19 - #include <linux/platform_device.h> 20 - #include <linux/err.h> 21 - #include <linux/types.h> 22 - #include <linux/spinlock.h> 23 - #include <linux/sys_soc.h> 24 - #include <linux/reboot.h> 25 - #include <linux/of_device.h> 26 - #include <linux/of_platform.h> 27 - #include <linux/of_irq.h> 28 - #include <linux/io.h> 29 - #include <linux/iopoll.h> 30 13 #include <linux/cpu_pm.h> 31 14 #include <linux/device.h> 32 - #include <linux/pm_runtime.h> 33 - #include <linux/pm.h> 15 + #include <linux/err.h> 16 + #include <linux/export.h> 17 + #include <linux/gpio/consumer.h> 18 + #include <linux/init.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/io.h> 21 + #include <linux/iopoll.h> 22 + #include <linux/kernel.h> 23 + #include <linux/module.h> 34 24 #include <linux/of.h> 35 25 #include <linux/of_device.h> 26 + #include <linux/of_irq.h> 27 + #include <linux/of_platform.h> 28 + #include <linux/platform_device.h> 29 + #include <linux/pm.h> 30 + #include <linux/pm_runtime.h> 31 + #include <linux/reboot.h> 32 + #include <linux/spinlock.h> 33 + #include <linux/sys_soc.h> 34 + #include <linux/types.h> 36 35 37 36 #include "ti-bandgap.h" 38 37 ··· 1142 1143 for (i = 0; i < bgp->conf->sensor_count; i++) { 1143 1144 struct temp_sensor_registers *tsr; 1144 1145 struct temp_sensor_regval *rval; 1145 - u32 val = 0; 1146 1146 1147 1147 rval = &bgp->regval[i]; 1148 1148 tsr = bgp->conf->sensors[i].registers; 1149 - 1150 - if (TI_BANDGAP_HAS(bgp, COUNTER)) 1151 - val = ti_bandgap_readl(bgp, tsr->bgap_counter); 1152 1149 1153 1150 if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG)) 1154 1151 ti_bandgap_writel(bgp, rval->tshut_threshold,
+1 -6
include/linux/thermal.h
··· 91 91 92 92 struct thermal_cooling_device { 93 93 int id; 94 - char type[THERMAL_NAME_LENGTH]; 94 + char *type; 95 95 struct device device; 96 96 struct device_node *np; 97 97 void *devdata; ··· 390 390 int thermal_zone_get_slope(struct thermal_zone_device *tz); 391 391 int thermal_zone_get_offset(struct thermal_zone_device *tz); 392 392 393 - void thermal_notify_framework(struct thermal_zone_device *, int); 394 393 int thermal_zone_device_enable(struct thermal_zone_device *tz); 395 394 int thermal_zone_device_disable(struct thermal_zone_device *tz); 396 395 void thermal_zone_device_critical(struct thermal_zone_device *tz); ··· 434 435 static inline int thermal_zone_get_offset( 435 436 struct thermal_zone_device *tz) 436 437 { return -ENODEV; } 437 - 438 - static inline void thermal_notify_framework(struct thermal_zone_device *tz, 439 - int trip) 440 - { } 441 438 442 439 static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) 443 440 { return -ENODEV; }
+1 -1
include/uapi/linux/thermal.h
··· 60 60 THERMAL_GENL_EVENT_UNSPEC, 61 61 THERMAL_GENL_EVENT_TZ_CREATE, /* Thermal zone creation */ 62 62 THERMAL_GENL_EVENT_TZ_DELETE, /* Thermal zone deletion */ 63 - THERMAL_GENL_EVENT_TZ_DISABLE, /* Thermal zone disabed */ 63 + THERMAL_GENL_EVENT_TZ_DISABLE, /* Thermal zone disabled */ 64 64 THERMAL_GENL_EVENT_TZ_ENABLE, /* Thermal zone enabled */ 65 65 THERMAL_GENL_EVENT_TZ_TRIP_UP, /* Trip point crossed the way up */ 66 66 THERMAL_GENL_EVENT_TZ_TRIP_DOWN, /* Trip point crossed the way down */