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

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

Pull thermal updates from Daniel Lezcano:

- Add support to enable/disable the thermal zones resulting on core
code and drivers cleanup (Andrzej Pietrasiewicz)

- Add generic netlink support for userspace notifications: events,
temperature and discovery commands (Daniel Lezcano)

- Fix redundant initialization for a ret variable (Colin Ian King)

- Remove the clock cooling code as it is used nowhere (Amit Kucheria)

- Add the rcar_gen3_thermal's r8a774e1 support (Marian-Cristian
Rotariu)

- Replace all references to thermal.txt in the documentation to the
corresponding yaml files (Amit Kucheria)

- Add maintainer entry for the IPA (Lukasz Luba)

- Add support for MSM8939 for the tsens (Shawn Guo)

- Update power allocator and devfreq cooling to SPDX licensing (Lukasz
Luba)

- Add Cannon Lake Low Power PCH support (Sumeet Pawnikar)

- Add tsensor support for V2 mediatek thermal system (Henry Yen)

- Fix thermal zone lookup by ID for the core code (Thierry Reding)

* tag 'thermal-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (40 commits)
thermal: intel: intel_pch_thermal: Add Cannon Lake Low Power PCH support
thermal: mediatek: Add tsensor support for V2 thermal system
thermal: mediatek: Prepare to add support for other platforms
thermal: Update power allocator and devfreq cooling to SPDX licensing
MAINTAINERS: update entry to thermal governors file name prefixing
thermal: core: Add thermal zone enable/disable notification
thermal: qcom: tsens-v0_1: Add support for MSM8939
dt-bindings: tsens: qcom: Document MSM8939 compatible
thermal: core: Fix thermal zone lookup by ID
thermal: int340x: processor_thermal: fix: update Jasper Lake PCI id
thermal: imx8mm: Support module autoloading
thermal: ti-soc-thermal: Fix reversed condition in ti_thermal_expose_sensor()
MAINTAINERS: Add maintenance information for IPA
thermal: rcar_gen3_thermal: Do not shadow thcode variable
dt-bindings: thermal: Get rid of thermal.txt and replace references
thermal: core: Move initialization after core initcall
thermal: netlink: Improve the initcall ordering
net: genetlink: Move initialization to core_initcall
thermal: rcar_gen3_thermal: Add r8a774e1 support
thermal/drivers/clock_cooling: Remove clock_cooling code
...

+1632 -1609
+1 -1
Documentation/devicetree/bindings/arm/arm,scmi.txt
··· 102 102 [0] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html 103 103 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt 104 104 [2] Documentation/devicetree/bindings/power/power-domain.yaml 105 - [3] Documentation/devicetree/bindings/thermal/thermal.txt 105 + [3] Documentation/devicetree/bindings/thermal/thermal*.yaml 106 106 [4] Documentation/devicetree/bindings/sram/sram.yaml 107 107 [5] Documentation/devicetree/bindings/reset/reset.txt 108 108
+1 -1
Documentation/devicetree/bindings/arm/arm,scpi.txt
··· 108 108 109 109 [0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html 110 110 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt 111 - [2] Documentation/devicetree/bindings/thermal/thermal.txt 111 + [2] Documentation/devicetree/bindings/thermal/thermal*.yaml 112 112 [3] Documentation/devicetree/bindings/sram/sram.yaml 113 113 [4] Documentation/devicetree/bindings/power/power-domain.yaml 114 114
+1 -1
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
··· 176 176 "fsl,imx8qxp-sc-thermal" 177 177 followed by "fsl,imx-sc-thermal"; 178 178 179 - - #thermal-sensor-cells: See Documentation/devicetree/bindings/thermal/thermal.txt 179 + - #thermal-sensor-cells: See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml 180 180 for a description. 181 181 182 182 Example (imx8qxp):
+1 -1
Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt
··· 111 111 -------- 112 112 113 113 For common binding part and usage, refer to 114 - Documentation/devicetree/bindings/thermal/thermal.txt 114 + Documentation/devicetree/bindings/thermal/thermal*.yaml 115 115 116 116 The thermal IP can probe the temperature all around the processor. It 117 117 may feature several channels, each of them wired to one sensor.
+1 -1
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt
··· 203 203 critical point to any subnode of the thermal-zone node. 204 204 205 205 For common binding part and usage, refer to 206 - Documentation/devicetree/bindings/thermal/thermal.txt 206 + Documentation/devicetree/bindings/thermal/thermal*.yaml 207 207 208 208 Required properties: 209 209 - compatible: must be one of:
+2 -1
Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt
··· 18 18 in unit of nanoseconds. 19 19 - voltage-tolerance: Specify the CPU voltage tolerance in percentage. 20 20 - #cooling-cells: 21 - Please refer to Documentation/devicetree/bindings/thermal/thermal.txt. 21 + Please refer to 22 + Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml. 22 23 23 24 Examples: 24 25
+2 -2
Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt
··· 21 21 flow is handled by hardware, hence no software "voltage tracking" is 22 22 needed. 23 23 - #cooling-cells: 24 - Please refer to Documentation/devicetree/bindings/thermal/thermal.txt 25 - for detail. 24 + For details, please refer to 25 + Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml 26 26 27 27 Example 1 (MT7623 SoC): 28 28
+1 -1
Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
··· 5 5 - clocks: Must contain an entry for the CPU clock. 6 6 See ../clocks/clock-bindings.txt for details. 7 7 - operating-points-v2: See ../bindings/opp/opp.txt for details. 8 - - #cooling-cells: Should be 2. See ../thermal/thermal.txt for details. 8 + - #cooling-cells: Should be 2. See ../thermal/thermal-cooling-devices.yaml for details. 9 9 10 10 For each opp entry in 'operating-points-v2' table: 11 11 - opp-supported-hw: Two bitfields indicating:
+2 -1
Documentation/devicetree/bindings/hwmon/gpio-fan.txt
··· 12 12 - alarm-gpios: This pin going active indicates something is wrong with 13 13 the fan, and a udev event will be fired. 14 14 - #cooling-cells: If used as a cooling device, must be <2> 15 - Also see: Documentation/devicetree/bindings/thermal/thermal.txt 15 + Also see: 16 + Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml 16 17 min and max states are derived from the speed-map of the fan. 17 18 18 19 Note: At least one the "gpios" or "alarm-gpios" properties must be set.
+2 -2
Documentation/devicetree/bindings/hwmon/lm90.txt
··· 34 34 LM90 "-ALERT" pin output. 35 35 See interrupt-controller/interrupts.txt for the format. 36 36 37 - - #thermal-sensor-cells: should be set to 1. See thermal/thermal.txt for 38 - details. See <include/dt-bindings/thermal/lm90.h> for the 37 + - #thermal-sensor-cells: should be set to 1. See thermal/thermal-sensor.yaml 38 + for details. See <include/dt-bindings/thermal/lm90.h> for the 39 39 definition of the local, remote and 2nd remote sensor index 40 40 constants. 41 41
+1 -1
Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml
··· 50 50 nvmem-cell-names: 51 51 const: calibration 52 52 53 - # See ./thermal.txt for details 53 + # See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details 54 54 "#thermal-sensor-cells": 55 55 enum: 56 56 - 0
+1 -1
Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt
··· 6 6 Required properties: 7 7 - compatible: "amazon,al-thermal". 8 8 - reg: The physical base address and length of the sensor's registers. 9 - - #thermal-sensor-cells: Must be 1. See ./thermal.txt for a description. 9 + - #thermal-sensor-cells: Must be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. 10 10 11 11 Example: 12 12 thermal: thermal {
+1 -1
Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml
··· 23 23 compatible: 24 24 const: brcm,bcm2711-thermal 25 25 26 - # See ./thermal.txt for details 26 + # See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details 27 27 "#thermal-sensor-cells": 28 28 const: 0 29 29
+1 -1
Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
··· 7 7 "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal" 8 8 reg: Address range of the thermal registers. 9 9 clocks: Phandle of the clock used by the thermal sensor. 10 - #thermal-sensor-cells: should be 0 (see thermal.txt) 10 + #thermal-sensor-cells: should be 0 (see Documentation/devicetree/bindings/thermal/thermal-sensor.yaml) 11 11 12 12 Example: 13 13
+1 -1
Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt
··· 9 9 by /SOCTHERM/tsensor. 10 10 - clock-names: Input clock name, should be 'thermal_clk'. 11 11 - clocks: phandles for clock specified in "clock-names" property. 12 - - #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description. 12 + - #thermal-sensor-cells: Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. 13 13 14 14 Example : 15 15
+3 -3
Documentation/devicetree/bindings/thermal/max77620_thermal.txt
··· 8 8 9 9 Required properties: 10 10 ------------------- 11 - #thermal-sensor-cells: Please refer <devicetree/bindings/thermal/thermal.txt> 12 - for more details. 11 + #thermal-sensor-cells: For more details, please refer to 12 + <devicetree/bindings/thermal/thermal-sensor.yaml> 13 13 The value must be 0. 14 14 15 15 For more details, please refer generic thermal DT binding document 16 - <devicetree/bindings/thermal/thermal.txt>. 16 + <devicetree/bindings/thermal/thermal*.yaml>. 17 17 18 18 Please refer <devicetree/bindings/mfd/max77620.txt> for mfd DT binding 19 19 document for the MAX77620.
+1 -1
Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
··· 23 23 - resets: Reference to the reset controller controlling the thermal controller. 24 24 - mediatek,auxadc: A phandle to the AUXADC which the thermal controller uses 25 25 - mediatek,apmixedsys: A phandle to the APMIXEDSYS controller. 26 - - #thermal-sensor-cells : Should be 0. See ./thermal.txt for a description. 26 + - #thermal-sensor-cells : Should be 0. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. 27 27 28 28 Optional properties: 29 29 - nvmem-cells: A phandle to the calibration data provided by a nvmem device. If
+6 -4
Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt
··· 28 28 See ../reset/reset.txt for details. 29 29 - reset-names : Must include the following entries: 30 30 - soctherm 31 - - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description 32 - of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a 33 - list of valid values when referring to thermal sensors. 31 + - #thermal-sensor-cells : Should be 1. For a description of this property, see 32 + Documentation/devicetree/bindings/thermal/thermal-sensor.yaml. 33 + See <dt-bindings/thermal/tegra124-soctherm.h> for a list of valid values 34 + when referring to thermal sensors. 34 35 - throttle-cfgs: A sub-node which is a container of configuration for each 35 36 hardware throttle events. These events can be set as cooling devices. 36 37 * throttle events: Sub-nodes must be named as "light" or "heavy". ··· 63 62 TEGRA_SOCTHERM_THROT_LEVEL_MED (75%), 64 63 TEGRA_SOCTHERM_THROT_LEVEL_HIGH (85%). 65 64 - #cooling-cells: Should be 1. This cooling device only support on/off state. 66 - See ./thermal.txt for a description of this property. 65 + For a description of this property see: 66 + Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml 67 67 68 68 Optional properties: The following properties are T210 specific and 69 69 valid only for OCx throttle events.
+1 -1
Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt
··· 8 8 The BPMP thermal node must be located directly inside the main BPMP node. See 9 9 ../firmware/nvidia,tegra186-bpmp.txt for details of the BPMP binding. 10 10 11 - This node represents a thermal sensor. See thermal.txt for details of the 11 + This node represents a thermal sensor. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details of the 12 12 core thermal binding. 13 13 14 14 Required properties:
+1 -1
Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt
··· 8 8 - compatible: Should contain "qcom,spmi-temp-alarm". 9 9 - reg: Specifies the SPMI address. 10 10 - interrupts: PMIC temperature alarm interrupt. 11 - - #thermal-sensor-cells: Should be 0. See thermal.txt for a description. 11 + - #thermal-sensor-cells: Should be 0. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. 12 12 13 13 Optional properties: 14 14 - io-channels: Should contain IIO channel specifier for the ADC channel,
+1
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
··· 23 23 items: 24 24 - enum: 25 25 - qcom,msm8916-tsens 26 + - qcom,msm8939-tsens 26 27 - qcom,msm8974-tsens 27 28 - const: qcom,tsens-v0_1 28 29
+1 -1
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
··· 24 24 - pinctrl-1 : The "default" pinctrl state, it will be set after reset the 25 25 TSADC controller. 26 26 - pinctrl-2 : The "sleep" pinctrl state, it will be in for suspend. 27 - - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description. 27 + - #thermal-sensor-cells : Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. 28 28 29 29 Optional properties: 30 30 - rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.
+1 -1
Documentation/devicetree/bindings/thermal/tango-thermal.txt
··· 4 4 (in the CPU, video decoder, and PCIe controller). 5 5 6 6 Required properties: 7 - - #thermal-sensor-cells: Should be 0 (see thermal.txt) 7 + - #thermal-sensor-cells: Should be 0 (see Documentation/devicetree/bindings/thermal/thermal-sensor.yaml) 8 8 - compatible: "sigma,smp8758-thermal" 9 9 - reg: Address range of the thermal registers 10 10
+1 -1
Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt
··· 8 8 Required properties: 9 9 =================== 10 10 - compatible: Must be "generic-adc-thermal". 11 - - #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description 11 + - #thermal-sensor-cells: Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description 12 12 of this property. 13 13 Optional properties: 14 14 ===================
-586
Documentation/devicetree/bindings/thermal/thermal.txt
··· 1 - * Thermal Framework Device Tree descriptor 2 - 3 - This file describes a generic binding to provide a way of 4 - defining hardware thermal structure using device tree. 5 - A thermal structure includes thermal zones and their components, 6 - such as trip points, polling intervals, sensors and cooling devices 7 - binding descriptors. 8 - 9 - The target of device tree thermal descriptors is to describe only 10 - the hardware thermal aspects. The thermal device tree bindings are 11 - not about how the system must control or which algorithm or policy 12 - must be taken in place. 13 - 14 - There are five types of nodes involved to describe thermal bindings: 15 - - thermal sensors: devices which may be used to take temperature 16 - measurements. 17 - - cooling devices: devices which may be used to dissipate heat. 18 - - trip points: describe key temperatures at which cooling is recommended. The 19 - set of points should be chosen based on hardware limits. 20 - - cooling maps: used to describe links between trip points and cooling devices; 21 - - thermal zones: used to describe thermal data within the hardware; 22 - 23 - The following is a description of each of these node types. 24 - 25 - * Thermal sensor devices 26 - 27 - Thermal sensor devices are nodes providing temperature sensing capabilities on 28 - thermal zones. Typical devices are I2C ADC converters and bandgaps. These are 29 - nodes providing temperature data to thermal zones. Thermal sensor devices may 30 - control one or more internal sensors. 31 - 32 - Required property: 33 - - #thermal-sensor-cells: Used to provide sensor device specific information 34 - Type: unsigned while referring to it. Typically 0 on thermal sensor 35 - Size: one cell nodes with only one sensor, and at least 1 on nodes 36 - with several internal sensors, in order 37 - to identify uniquely the sensor instances within 38 - the IC. See thermal zone binding for more details 39 - on how consumers refer to sensor devices. 40 - 41 - * Cooling device nodes 42 - 43 - Cooling devices are nodes providing control on power dissipation. There 44 - are essentially two ways to provide control on power dissipation. First 45 - is by means of regulating device performance, which is known as passive 46 - cooling. A typical passive cooling is a CPU that has dynamic voltage and 47 - frequency scaling (DVFS), and uses lower frequencies as cooling states. 48 - Second is by means of activating devices in order to remove 49 - the dissipated heat, which is known as active cooling, e.g. regulating 50 - fan speeds. In both cases, cooling devices shall have a way to determine 51 - the state of cooling in which the device is. 52 - 53 - Any cooling device has a range of cooling states (i.e. different levels 54 - of heat dissipation). For example a fan's cooling states correspond to 55 - the different fan speeds possible. Cooling states are referred to by 56 - single unsigned integers, where larger numbers mean greater heat 57 - dissipation. The precise set of cooling states associated with a device 58 - should be defined in a particular device's binding. 59 - For more examples of cooling devices, refer to the example sections below. 60 - 61 - Required properties: 62 - - #cooling-cells: Used to provide cooling device specific information 63 - Type: unsigned while referring to it. Must be at least 2, in order 64 - Size: one cell to specify minimum and maximum cooling state used 65 - in the reference. The first cell is the minimum 66 - cooling state requested and the second cell is 67 - the maximum cooling state requested in the reference. 68 - See Cooling device maps section below for more details 69 - on how consumers refer to cooling devices. 70 - 71 - * Trip points 72 - 73 - The trip node is a node to describe a point in the temperature domain 74 - in which the system takes an action. This node describes just the point, 75 - not the action. 76 - 77 - Required properties: 78 - - temperature: An integer indicating the trip temperature level, 79 - Type: signed in millicelsius. 80 - Size: one cell 81 - 82 - - hysteresis: A low hysteresis value on temperature property (above). 83 - Type: unsigned This is a relative value, in millicelsius. 84 - Size: one cell 85 - 86 - - type: a string containing the trip type. Expected values are: 87 - "active": A trip point to enable active cooling 88 - "passive": A trip point to enable passive cooling 89 - "hot": A trip point to notify emergency 90 - "critical": Hardware not reliable. 91 - Type: string 92 - 93 - * Cooling device maps 94 - 95 - The cooling device maps node is a node to describe how cooling devices 96 - get assigned to trip points of the zone. The cooling devices are expected 97 - to be loaded in the target system. 98 - 99 - Required properties: 100 - - cooling-device: A list of phandles of cooling devices with their specifiers, 101 - Type: phandle + referring to which cooling devices are used in this 102 - cooling specifier binding. In the cooling specifier, the first cell 103 - is the minimum cooling state and the second cell 104 - is the maximum cooling state used in this map. 105 - - trip: A phandle of a trip point node within the same thermal 106 - Type: phandle of zone. 107 - trip point node 108 - 109 - Optional property: 110 - - contribution: The cooling contribution to the thermal zone of the 111 - Type: unsigned referred cooling device at the referred trip point. 112 - Size: one cell The contribution is a ratio of the sum 113 - of all cooling contributions within a thermal zone. 114 - 115 - Note: Using the THERMAL_NO_LIMIT (-1UL) constant in the cooling-device phandle 116 - limit specifier means: 117 - (i) - minimum state allowed for minimum cooling state used in the reference. 118 - (ii) - maximum state allowed for maximum cooling state used in the reference. 119 - Refer to include/dt-bindings/thermal/thermal.h for definition of this constant. 120 - 121 - * Thermal zone nodes 122 - 123 - The thermal zone node is the node containing all the required info 124 - for describing a thermal zone, including its cooling device bindings. The 125 - thermal zone node must contain, apart from its own properties, one sub-node 126 - containing trip nodes and one sub-node containing all the zone cooling maps. 127 - 128 - Required properties: 129 - - polling-delay: The maximum number of milliseconds to wait between polls 130 - Type: unsigned when checking this thermal zone. 131 - Size: one cell 132 - 133 - - polling-delay-passive: The maximum number of milliseconds to wait 134 - Type: unsigned between polls when performing passive cooling. 135 - Size: one cell 136 - 137 - - thermal-sensors: A list of thermal sensor phandles and sensor specifier 138 - Type: list of used while monitoring the thermal zone. 139 - phandles + sensor 140 - specifier 141 - 142 - - trips: A sub-node which is a container of only trip point nodes 143 - Type: sub-node required to describe the thermal zone. 144 - 145 - Optional property: 146 - - cooling-maps: A sub-node which is a container of only cooling device 147 - Type: sub-node map nodes, used to describe the relation between trips 148 - and cooling devices. 149 - 150 - - coefficients: An array of integers (one signed cell) containing 151 - Type: array coefficients to compose a linear relation between 152 - Elem size: one cell the sensors listed in the thermal-sensors property. 153 - Elem type: signed Coefficients defaults to 1, in case this property 154 - is not specified. A simple linear polynomial is used: 155 - Z = c0 * x0 + c1 * x1 + ... + c(n-1) * x(n-1) + cn. 156 - 157 - The coefficients are ordered and they match with sensors 158 - by means of sensor ID. Additional coefficients are 159 - interpreted as constant offset. 160 - 161 - - sustainable-power: An estimate of the sustainable power (in mW) that the 162 - Type: unsigned thermal zone can dissipate at the desired 163 - Size: one cell control temperature. For reference, the 164 - sustainable power of a 4'' phone is typically 165 - 2000mW, while on a 10'' tablet is around 166 - 4500mW. 167 - 168 - Note: The delay properties are bound to the maximum dT/dt (temperature 169 - derivative over time) in two situations for a thermal zone: 170 - (i) - when passive cooling is activated (polling-delay-passive); and 171 - (ii) - when the zone just needs to be monitored (polling-delay) or 172 - when active cooling is activated. 173 - 174 - The maximum dT/dt is highly bound to hardware power consumption and dissipation 175 - capability. The delays should be chosen to account for said max dT/dt, 176 - such that a device does not cross several trip boundaries unexpectedly 177 - between polls. Choosing the right polling delays shall avoid having the 178 - device in temperature ranges that may damage the silicon structures and 179 - reduce silicon lifetime. 180 - 181 - * The thermal-zones node 182 - 183 - The "thermal-zones" node is a container for all thermal zone nodes. It shall 184 - contain only sub-nodes describing thermal zones as in the section 185 - "Thermal zone nodes". The "thermal-zones" node appears under "/". 186 - 187 - * Examples 188 - 189 - Below are several examples on how to use thermal data descriptors 190 - using device tree bindings: 191 - 192 - (a) - CPU thermal zone 193 - 194 - The CPU thermal zone example below describes how to setup one thermal zone 195 - using one single sensor as temperature source and many cooling devices and 196 - power dissipation control sources. 197 - 198 - #include <dt-bindings/thermal/thermal.h> 199 - 200 - cpus { 201 - /* 202 - * Here is an example of describing a cooling device for a DVFS 203 - * capable CPU. The CPU node describes its four OPPs. 204 - * The cooling states possible are 0..3, and they are 205 - * used as OPP indexes. The minimum cooling state is 0, which means 206 - * all four OPPs can be available to the system. The maximum 207 - * cooling state is 3, which means only the lowest OPPs (198MHz@0.85V) 208 - * can be available in the system. 209 - */ 210 - cpu0: cpu@0 { 211 - ... 212 - operating-points = < 213 - /* kHz uV */ 214 - 970000 1200000 215 - 792000 1100000 216 - 396000 950000 217 - 198000 850000 218 - >; 219 - #cooling-cells = <2>; /* min followed by max */ 220 - }; 221 - ... 222 - }; 223 - 224 - &i2c1 { 225 - ... 226 - /* 227 - * A simple fan controller which supports 10 speeds of operation 228 - * (represented as 0-9). 229 - */ 230 - fan0: fan@48 { 231 - ... 232 - #cooling-cells = <2>; /* min followed by max */ 233 - }; 234 - }; 235 - 236 - ocp { 237 - ... 238 - /* 239 - * A simple IC with a single bandgap temperature sensor. 240 - */ 241 - bandgap0: bandgap@0000ed00 { 242 - ... 243 - #thermal-sensor-cells = <0>; 244 - }; 245 - }; 246 - 247 - thermal-zones { 248 - cpu_thermal: cpu-thermal { 249 - polling-delay-passive = <250>; /* milliseconds */ 250 - polling-delay = <1000>; /* milliseconds */ 251 - 252 - thermal-sensors = <&bandgap0>; 253 - 254 - trips { 255 - cpu_alert0: cpu-alert0 { 256 - temperature = <90000>; /* millicelsius */ 257 - hysteresis = <2000>; /* millicelsius */ 258 - type = "active"; 259 - }; 260 - cpu_alert1: cpu-alert1 { 261 - temperature = <100000>; /* millicelsius */ 262 - hysteresis = <2000>; /* millicelsius */ 263 - type = "passive"; 264 - }; 265 - cpu_crit: cpu-crit { 266 - temperature = <125000>; /* millicelsius */ 267 - hysteresis = <2000>; /* millicelsius */ 268 - type = "critical"; 269 - }; 270 - }; 271 - 272 - cooling-maps { 273 - map0 { 274 - trip = <&cpu_alert0>; 275 - cooling-device = <&fan0 THERMAL_NO_LIMIT 4>; 276 - }; 277 - map1 { 278 - trip = <&cpu_alert1>; 279 - cooling-device = <&fan0 5 THERMAL_NO_LIMIT>, <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; 280 - }; 281 - }; 282 - }; 283 - }; 284 - 285 - In the example above, the ADC sensor (bandgap0) at address 0x0000ED00 is 286 - used to monitor the zone 'cpu-thermal' using its sole sensor. A fan 287 - device (fan0) is controlled via I2C bus 1, at address 0x48, and has ten 288 - different cooling states 0-9. It is used to remove the heat out of 289 - the thermal zone 'cpu-thermal' using its cooling states 290 - from its minimum to 4, when it reaches trip point 'cpu_alert0' 291 - at 90C, as an example of active cooling. The same cooling device is used at 292 - 'cpu_alert1', but from 5 to its maximum state. The cpu@0 device is also 293 - linked to the same thermal zone, 'cpu-thermal', as a passive cooling device, 294 - using all its cooling states at trip point 'cpu_alert1', 295 - which is a trip point at 100C. On the thermal zone 'cpu-thermal', at the 296 - temperature of 125C, represented by the trip point 'cpu_crit', the silicon 297 - is not reliable anymore. 298 - 299 - (b) - IC with several internal sensors 300 - 301 - The example below describes how to deploy several thermal zones based off a 302 - single sensor IC, assuming it has several internal sensors. This is a common 303 - case on SoC designs with several internal IPs that may need different thermal 304 - requirements, and thus may have their own sensor to monitor or detect internal 305 - hotspots in their silicon. 306 - 307 - #include <dt-bindings/thermal/thermal.h> 308 - 309 - ocp { 310 - ... 311 - /* 312 - * A simple IC with several bandgap temperature sensors. 313 - */ 314 - bandgap0: bandgap@0000ed00 { 315 - ... 316 - #thermal-sensor-cells = <1>; 317 - }; 318 - }; 319 - 320 - thermal-zones { 321 - cpu_thermal: cpu-thermal { 322 - polling-delay-passive = <250>; /* milliseconds */ 323 - polling-delay = <1000>; /* milliseconds */ 324 - 325 - /* sensor ID */ 326 - thermal-sensors = <&bandgap0 0>; 327 - 328 - trips { 329 - /* each zone within the SoC may have its own trips */ 330 - cpu_alert: cpu-alert { 331 - temperature = <100000>; /* millicelsius */ 332 - hysteresis = <2000>; /* millicelsius */ 333 - type = "passive"; 334 - }; 335 - cpu_crit: cpu-crit { 336 - temperature = <125000>; /* millicelsius */ 337 - hysteresis = <2000>; /* millicelsius */ 338 - type = "critical"; 339 - }; 340 - }; 341 - 342 - cooling-maps { 343 - /* each zone within the SoC may have its own cooling */ 344 - ... 345 - }; 346 - }; 347 - 348 - gpu_thermal: gpu-thermal { 349 - polling-delay-passive = <120>; /* milliseconds */ 350 - polling-delay = <1000>; /* milliseconds */ 351 - 352 - /* sensor ID */ 353 - thermal-sensors = <&bandgap0 1>; 354 - 355 - trips { 356 - /* each zone within the SoC may have its own trips */ 357 - gpu_alert: gpu-alert { 358 - temperature = <90000>; /* millicelsius */ 359 - hysteresis = <2000>; /* millicelsius */ 360 - type = "passive"; 361 - }; 362 - gpu_crit: gpu-crit { 363 - temperature = <105000>; /* millicelsius */ 364 - hysteresis = <2000>; /* millicelsius */ 365 - type = "critical"; 366 - }; 367 - }; 368 - 369 - cooling-maps { 370 - /* each zone within the SoC may have its own cooling */ 371 - ... 372 - }; 373 - }; 374 - 375 - dsp_thermal: dsp-thermal { 376 - polling-delay-passive = <50>; /* milliseconds */ 377 - polling-delay = <1000>; /* milliseconds */ 378 - 379 - /* sensor ID */ 380 - thermal-sensors = <&bandgap0 2>; 381 - 382 - trips { 383 - /* each zone within the SoC may have its own trips */ 384 - dsp_alert: dsp-alert { 385 - temperature = <90000>; /* millicelsius */ 386 - hysteresis = <2000>; /* millicelsius */ 387 - type = "passive"; 388 - }; 389 - dsp_crit: gpu-crit { 390 - temperature = <135000>; /* millicelsius */ 391 - hysteresis = <2000>; /* millicelsius */ 392 - type = "critical"; 393 - }; 394 - }; 395 - 396 - cooling-maps { 397 - /* each zone within the SoC may have its own cooling */ 398 - ... 399 - }; 400 - }; 401 - }; 402 - 403 - In the example above, there is one bandgap IC which has the capability to 404 - monitor three sensors. The hardware has been designed so that sensors are 405 - placed on different places in the DIE to monitor different temperature 406 - hotspots: one for CPU thermal zone, one for GPU thermal zone and the 407 - other to monitor a DSP thermal zone. 408 - 409 - Thus, there is a need to assign each sensor provided by the bandgap IC 410 - to different thermal zones. This is achieved by means of using the 411 - #thermal-sensor-cells property and using the first cell of the sensor 412 - specifier as sensor ID. In the example, then, <bandgap 0> is used to 413 - monitor CPU thermal zone, <bandgap 1> is used to monitor GPU thermal 414 - zone and <bandgap 2> is used to monitor DSP thermal zone. Each zone 415 - may be uncorrelated, having its own dT/dt requirements, trips 416 - and cooling maps. 417 - 418 - 419 - (c) - Several sensors within one single thermal zone 420 - 421 - The example below illustrates how to use more than one sensor within 422 - one thermal zone. 423 - 424 - #include <dt-bindings/thermal/thermal.h> 425 - 426 - &i2c1 { 427 - ... 428 - /* 429 - * A simple IC with a single temperature sensor. 430 - */ 431 - adc: sensor@49 { 432 - ... 433 - #thermal-sensor-cells = <0>; 434 - }; 435 - }; 436 - 437 - ocp { 438 - ... 439 - /* 440 - * A simple IC with a single bandgap temperature sensor. 441 - */ 442 - bandgap0: bandgap@0000ed00 { 443 - ... 444 - #thermal-sensor-cells = <0>; 445 - }; 446 - }; 447 - 448 - thermal-zones { 449 - cpu_thermal: cpu-thermal { 450 - polling-delay-passive = <250>; /* milliseconds */ 451 - polling-delay = <1000>; /* milliseconds */ 452 - 453 - thermal-sensors = <&bandgap0>, /* cpu */ 454 - <&adc>; /* pcb north */ 455 - 456 - /* hotspot = 100 * bandgap - 120 * adc + 484 */ 457 - coefficients = <100 -120 484>; 458 - 459 - trips { 460 - ... 461 - }; 462 - 463 - cooling-maps { 464 - ... 465 - }; 466 - }; 467 - }; 468 - 469 - In some cases, there is a need to use more than one sensor to extrapolate 470 - a thermal hotspot in the silicon. The above example illustrates this situation. 471 - For instance, it may be the case that a sensor external to CPU IP may be placed 472 - close to CPU hotspot and together with internal CPU sensor, it is used 473 - to determine the hotspot. Assuming this is the case for the above example, 474 - the hypothetical extrapolation rule would be: 475 - hotspot = 100 * bandgap - 120 * adc + 484 476 - 477 - In other context, the same idea can be used to add fixed offset. For instance, 478 - consider the hotspot extrapolation rule below: 479 - hotspot = 1 * adc + 6000 480 - 481 - In the above equation, the hotspot is always 6C higher than what is read 482 - from the ADC sensor. The binding would be then: 483 - thermal-sensors = <&adc>; 484 - 485 - /* hotspot = 1 * adc + 6000 */ 486 - coefficients = <1 6000>; 487 - 488 - (d) - Board thermal 489 - 490 - The board thermal example below illustrates how to setup one thermal zone 491 - with many sensors and many cooling devices. 492 - 493 - #include <dt-bindings/thermal/thermal.h> 494 - 495 - &i2c1 { 496 - ... 497 - /* 498 - * An IC with several temperature sensor. 499 - */ 500 - adc_dummy: sensor@50 { 501 - ... 502 - #thermal-sensor-cells = <1>; /* sensor internal ID */ 503 - }; 504 - }; 505 - 506 - thermal-zones { 507 - batt-thermal { 508 - polling-delay-passive = <500>; /* milliseconds */ 509 - polling-delay = <2500>; /* milliseconds */ 510 - 511 - /* sensor ID */ 512 - thermal-sensors = <&adc_dummy 4>; 513 - 514 - trips { 515 - ... 516 - }; 517 - 518 - cooling-maps { 519 - ... 520 - }; 521 - }; 522 - 523 - board_thermal: board-thermal { 524 - polling-delay-passive = <1000>; /* milliseconds */ 525 - polling-delay = <2500>; /* milliseconds */ 526 - 527 - /* sensor ID */ 528 - thermal-sensors = <&adc_dummy 0>, /* pcb top edge */ 529 - <&adc_dummy 1>, /* lcd */ 530 - <&adc_dummy 2>; /* back cover */ 531 - /* 532 - * An array of coefficients describing the sensor 533 - * linear relation. E.g.: 534 - * z = c1*x1 + c2*x2 + c3*x3 535 - */ 536 - coefficients = <1200 -345 890>; 537 - 538 - sustainable-power = <2500>; 539 - 540 - trips { 541 - /* Trips are based on resulting linear equation */ 542 - cpu_trip: cpu-trip { 543 - temperature = <60000>; /* millicelsius */ 544 - hysteresis = <2000>; /* millicelsius */ 545 - type = "passive"; 546 - }; 547 - gpu_trip: gpu-trip { 548 - temperature = <55000>; /* millicelsius */ 549 - hysteresis = <2000>; /* millicelsius */ 550 - type = "passive"; 551 - } 552 - lcd_trip: lcp-trip { 553 - temperature = <53000>; /* millicelsius */ 554 - hysteresis = <2000>; /* millicelsius */ 555 - type = "passive"; 556 - }; 557 - crit_trip: crit-trip { 558 - temperature = <68000>; /* millicelsius */ 559 - hysteresis = <2000>; /* millicelsius */ 560 - type = "critical"; 561 - }; 562 - }; 563 - 564 - cooling-maps { 565 - map0 { 566 - trip = <&cpu_trip>; 567 - cooling-device = <&cpu0 0 2>; 568 - contribution = <55>; 569 - }; 570 - map1 { 571 - trip = <&gpu_trip>; 572 - cooling-device = <&gpu0 0 2>; 573 - contribution = <20>; 574 - }; 575 - map2 { 576 - trip = <&lcd_trip>; 577 - cooling-device = <&lcd0 5 10>; 578 - contribution = <15>; 579 - }; 580 - }; 581 - }; 582 - }; 583 - 584 - The above example is a mix of previous examples, a sensor IP with several internal 585 - sensors used to monitor different zones, one of them is composed by several sensors and 586 - with different cooling devices.
+8
MAINTAINERS
··· 17086 17086 F: drivers/thermal/cpuidle_cooling.c 17087 17087 F: include/linux/cpu_cooling.h 17088 17088 17089 + THERMAL/POWER_ALLOCATOR 17090 + M: Lukasz Luba <lukasz.luba@arm.com> 17091 + L: linux-pm@vger.kernel.org 17092 + S: Maintained 17093 + F: Documentation/driver-api/thermal/power_allocator.rst 17094 + F: drivers/thermal/gov_power_allocator.c 17095 + F: include/trace/events/thermal_power_allocator.h 17096 + 17089 17097 THINKPAD ACPI EXTRAS DRIVER 17090 17098 M: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br> 17091 17099 L: ibm-acpi-devel@lists.sourceforge.net
+21 -55
drivers/acpi/thermal.c
··· 172 172 struct acpi_thermal_trips trips; 173 173 struct acpi_handle_list devices; 174 174 struct thermal_zone_device *thermal_zone; 175 - int tz_enabled; 176 175 int kelvin_offset; /* in millidegrees */ 177 176 struct work_struct thermal_check_work; 178 177 }; ··· 499 500 { 500 501 struct acpi_thermal *tz = data; 501 502 502 - if (!tz->tz_enabled) 503 - return; 504 - 505 503 thermal_zone_device_update(tz->thermal_zone, 506 504 THERMAL_EVENT_UNSPECIFIED); 507 505 } ··· 519 523 520 524 *temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature, 521 525 tz->kelvin_offset); 522 - return 0; 523 - } 524 - 525 - static int thermal_get_mode(struct thermal_zone_device *thermal, 526 - enum thermal_device_mode *mode) 527 - { 528 - struct acpi_thermal *tz = thermal->devdata; 529 - 530 - if (!tz) 531 - return -EINVAL; 532 - 533 - *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED : 534 - THERMAL_DEVICE_DISABLED; 535 - 536 - return 0; 537 - } 538 - 539 - static int thermal_set_mode(struct thermal_zone_device *thermal, 540 - enum thermal_device_mode mode) 541 - { 542 - struct acpi_thermal *tz = thermal->devdata; 543 - int enable; 544 - 545 - if (!tz) 546 - return -EINVAL; 547 - 548 - /* 549 - * enable/disable thermal management from ACPI thermal driver 550 - */ 551 - if (mode == THERMAL_DEVICE_ENABLED) 552 - enable = 1; 553 - else if (mode == THERMAL_DEVICE_DISABLED) { 554 - enable = 0; 555 - pr_warn("thermal zone will be disabled\n"); 556 - } else 557 - return -EINVAL; 558 - 559 - if (enable != tz->tz_enabled) { 560 - tz->tz_enabled = enable; 561 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, 562 - "%s kernel ACPI thermal control\n", 563 - tz->tz_enabled ? "Enable" : "Disable")); 564 - acpi_thermal_check(tz); 565 - } 566 526 return 0; 567 527 } 568 528 ··· 808 856 .bind = acpi_thermal_bind_cooling_device, 809 857 .unbind = acpi_thermal_unbind_cooling_device, 810 858 .get_temp = thermal_get_temp, 811 - .get_mode = thermal_get_mode, 812 - .set_mode = thermal_set_mode, 813 859 .get_trip_type = thermal_get_trip_type, 814 860 .get_trip_temp = thermal_get_trip_temp, 815 861 .get_crit_temp = thermal_get_crit_temp, ··· 851 901 result = sysfs_create_link(&tz->device->dev.kobj, 852 902 &tz->thermal_zone->device.kobj, "thermal_zone"); 853 903 if (result) 854 - return result; 904 + goto unregister_tzd; 855 905 856 906 result = sysfs_create_link(&tz->thermal_zone->device.kobj, 857 907 &tz->device->dev.kobj, "device"); 858 908 if (result) 859 - return result; 909 + goto remove_tz_link; 860 910 861 911 status = acpi_bus_attach_private_data(tz->device->handle, 862 912 tz->thermal_zone); 863 - if (ACPI_FAILURE(status)) 864 - return -ENODEV; 913 + if (ACPI_FAILURE(status)) { 914 + result = -ENODEV; 915 + goto remove_dev_link; 916 + } 865 917 866 - tz->tz_enabled = 1; 918 + result = thermal_zone_device_enable(tz->thermal_zone); 919 + if (result) 920 + goto acpi_bus_detach; 867 921 868 922 dev_info(&tz->device->dev, "registered as thermal_zone%d\n", 869 923 tz->thermal_zone->id); 924 + 870 925 return 0; 926 + 927 + acpi_bus_detach: 928 + acpi_bus_detach_private_data(tz->device->handle); 929 + remove_dev_link: 930 + sysfs_remove_link(&tz->thermal_zone->device.kobj, "device"); 931 + remove_tz_link: 932 + sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone"); 933 + unregister_tzd: 934 + thermal_zone_device_unregister(tz->thermal_zone); 935 + 936 + return result; 871 937 } 872 938 873 939 static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
+8
drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
··· 92 92 ch_thermal->tzdev = NULL; 93 93 return ret; 94 94 } 95 + 96 + ret = thermal_zone_device_enable(ch_thermal->tzdev); 97 + if (ret) { 98 + dev_err(adap->pdev_dev, "Failed to enable thermal zone\n"); 99 + thermal_zone_device_unregister(adap->ch_thermal.tzdev); 100 + return ret; 101 + } 102 + 95 103 return 0; 96 104 } 97 105
+17 -74
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
··· 98 98 struct mlxsw_thermal *parent; 99 99 struct thermal_zone_device *tzdev; 100 100 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; 101 - enum thermal_device_mode mode; 102 101 int module; /* Module or gearbox number */ 103 102 }; 104 103 ··· 109 110 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; 110 111 u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; 111 112 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; 112 - enum thermal_device_mode mode; 113 113 struct mlxsw_thermal_module *tz_module_arr; 114 114 u8 tz_module_num; 115 115 struct mlxsw_thermal_module *tz_gearbox_arr; ··· 275 277 return 0; 276 278 } 277 279 278 - static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev, 279 - enum thermal_device_mode *mode) 280 - { 281 - struct mlxsw_thermal *thermal = tzdev->devdata; 282 - 283 - *mode = thermal->mode; 284 - 285 - return 0; 286 - } 287 - 288 - static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev, 289 - enum thermal_device_mode mode) 290 - { 291 - struct mlxsw_thermal *thermal = tzdev->devdata; 292 - 293 - mutex_lock(&tzdev->lock); 294 - 295 - if (mode == THERMAL_DEVICE_ENABLED) 296 - tzdev->polling_delay = thermal->polling_delay; 297 - else 298 - tzdev->polling_delay = 0; 299 - 300 - mutex_unlock(&tzdev->lock); 301 - 302 - thermal->mode = mode; 303 - thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); 304 - 305 - return 0; 306 - } 307 - 308 280 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, 309 281 int *p_temp) 310 282 { ··· 374 406 static struct thermal_zone_device_ops mlxsw_thermal_ops = { 375 407 .bind = mlxsw_thermal_bind, 376 408 .unbind = mlxsw_thermal_unbind, 377 - .get_mode = mlxsw_thermal_get_mode, 378 - .set_mode = mlxsw_thermal_set_mode, 379 409 .get_temp = mlxsw_thermal_get_temp, 380 410 .get_trip_type = mlxsw_thermal_get_trip_type, 381 411 .get_trip_temp = mlxsw_thermal_get_trip_temp, ··· 429 463 WARN_ON(err); 430 464 } 431 465 return err; 432 - } 433 - 434 - static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev, 435 - enum thermal_device_mode *mode) 436 - { 437 - struct mlxsw_thermal_module *tz = tzdev->devdata; 438 - 439 - *mode = tz->mode; 440 - 441 - return 0; 442 - } 443 - 444 - static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev, 445 - enum thermal_device_mode mode) 446 - { 447 - struct mlxsw_thermal_module *tz = tzdev->devdata; 448 - struct mlxsw_thermal *thermal = tz->parent; 449 - 450 - mutex_lock(&tzdev->lock); 451 - 452 - if (mode == THERMAL_DEVICE_ENABLED) 453 - tzdev->polling_delay = thermal->polling_delay; 454 - else 455 - tzdev->polling_delay = 0; 456 - 457 - mutex_unlock(&tzdev->lock); 458 - 459 - tz->mode = mode; 460 - thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); 461 - 462 - return 0; 463 466 } 464 467 465 468 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, ··· 546 611 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { 547 612 .bind = mlxsw_thermal_module_bind, 548 613 .unbind = mlxsw_thermal_module_unbind, 549 - .get_mode = mlxsw_thermal_module_mode_get, 550 - .set_mode = mlxsw_thermal_module_mode_set, 551 614 .get_temp = mlxsw_thermal_module_temp_get, 552 615 .get_trip_type = mlxsw_thermal_module_trip_type_get, 553 616 .get_trip_temp = mlxsw_thermal_module_trip_temp_get, ··· 583 650 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = { 584 651 .bind = mlxsw_thermal_module_bind, 585 652 .unbind = mlxsw_thermal_module_unbind, 586 - .get_mode = mlxsw_thermal_module_mode_get, 587 - .set_mode = mlxsw_thermal_module_mode_set, 588 653 .get_temp = mlxsw_thermal_gearbox_temp_get, 589 654 .get_trip_type = mlxsw_thermal_module_trip_type_get, 590 655 .get_trip_temp = mlxsw_thermal_module_trip_temp_get, ··· 711 780 return err; 712 781 } 713 782 714 - module_tz->mode = THERMAL_DEVICE_ENABLED; 715 - return 0; 783 + err = thermal_zone_device_enable(module_tz->tzdev); 784 + if (err) 785 + thermal_zone_device_unregister(module_tz->tzdev); 786 + 787 + return err; 716 788 } 717 789 718 790 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev) ··· 818 884 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) 819 885 { 820 886 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; 887 + int ret; 821 888 822 889 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d", 823 890 gearbox_tz->module + 1); ··· 831 896 if (IS_ERR(gearbox_tz->tzdev)) 832 897 return PTR_ERR(gearbox_tz->tzdev); 833 898 834 - gearbox_tz->mode = THERMAL_DEVICE_ENABLED; 835 - return 0; 899 + ret = thermal_zone_device_enable(gearbox_tz->tzdev); 900 + if (ret) 901 + thermal_zone_device_unregister(gearbox_tz->tzdev); 902 + 903 + return ret; 836 904 } 837 905 838 906 static void ··· 1003 1065 if (err) 1004 1066 goto err_unreg_modules_tzdev; 1005 1067 1006 - thermal->mode = THERMAL_DEVICE_ENABLED; 1068 + err = thermal_zone_device_enable(thermal->tzdev); 1069 + if (err) 1070 + goto err_unreg_gearboxes; 1071 + 1007 1072 *p_thermal = thermal; 1008 1073 return 0; 1009 1074 1075 + err_unreg_gearboxes: 1076 + mlxsw_thermal_gearboxes_fini(thermal); 1010 1077 err_unreg_modules_tzdev: 1011 1078 mlxsw_thermal_modules_fini(thermal); 1012 1079 err_unreg_tzdev:
+8 -1
drivers/net/wireless/intel/iwlwifi/mvm/tt.c
··· 733 733 734 734 static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) 735 735 { 736 - int i; 736 + int i, ret; 737 737 char name[16]; 738 738 static atomic_t counter = ATOMIC_INIT(0); 739 739 ··· 756 756 "Failed to register to thermal zone (err = %ld)\n", 757 757 PTR_ERR(mvm->tz_device.tzone)); 758 758 mvm->tz_device.tzone = NULL; 759 + return; 760 + } 761 + 762 + ret = thermal_zone_device_enable(mvm->tz_device.tzone); 763 + if (ret) { 764 + IWL_DEBUG_TEMP(mvm, "Failed to enable thermal zone\n"); 765 + thermal_zone_device_unregister(mvm->tz_device.tzone); 759 766 return; 760 767 } 761 768
+13 -20
drivers/platform/x86/acerhdf.c
··· 397 397 { 398 398 acerhdf_change_fanstate(ACERHDF_FAN_AUTO); 399 399 kernelmode = 0; 400 - if (thz_dev) 401 - thz_dev->polling_delay = 0; 400 + 402 401 pr_notice("kernel mode fan control OFF\n"); 403 402 } 404 403 static inline void acerhdf_enable_kernelmode(void) 405 404 { 406 405 kernelmode = 1; 407 406 408 - thz_dev->polling_delay = interval*1000; 409 - thermal_zone_device_update(thz_dev, THERMAL_EVENT_UNSPECIFIED); 410 407 pr_notice("kernel mode fan control ON\n"); 411 - } 412 - 413 - static int acerhdf_get_mode(struct thermal_zone_device *thermal, 414 - enum thermal_device_mode *mode) 415 - { 416 - if (verbose) 417 - pr_notice("kernel mode fan control %d\n", kernelmode); 418 - 419 - *mode = (kernelmode) ? THERMAL_DEVICE_ENABLED 420 - : THERMAL_DEVICE_DISABLED; 421 - 422 - return 0; 423 408 } 424 409 425 410 /* ··· 413 428 * the temperature and the fan. 414 429 * disabled: the BIOS takes control of the fan. 415 430 */ 416 - static int acerhdf_set_mode(struct thermal_zone_device *thermal, 417 - enum thermal_device_mode mode) 431 + static int acerhdf_change_mode(struct thermal_zone_device *thermal, 432 + enum thermal_device_mode mode) 418 433 { 419 434 if (mode == THERMAL_DEVICE_DISABLED && kernelmode) 420 435 acerhdf_revert_to_bios_mode(); ··· 473 488 .bind = acerhdf_bind, 474 489 .unbind = acerhdf_unbind, 475 490 .get_temp = acerhdf_get_ec_temp, 476 - .get_mode = acerhdf_get_mode, 477 - .set_mode = acerhdf_set_mode, 491 + .change_mode = acerhdf_change_mode, 478 492 .get_trip_type = acerhdf_get_trip_type, 479 493 .get_trip_hyst = acerhdf_get_trip_hyst, 480 494 .get_trip_temp = acerhdf_get_trip_temp, ··· 717 733 718 734 static int __init acerhdf_register_thermal(void) 719 735 { 736 + int ret; 737 + 720 738 cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL, 721 739 &acerhdf_cooling_ops); 722 740 ··· 731 745 (kernelmode) ? interval*1000 : 0); 732 746 if (IS_ERR(thz_dev)) 733 747 return -EINVAL; 748 + 749 + if (kernelmode) 750 + ret = thermal_zone_device_enable(thz_dev); 751 + else 752 + ret = thermal_zone_device_disable(thz_dev); 753 + if (ret) 754 + return ret; 734 755 735 756 if (strcmp(thz_dev->governor->name, 736 757 acerhdf_zone_params.governor_name)) {
+6
drivers/platform/x86/intel_mid_thermal.c
··· 493 493 ret = PTR_ERR(pinfo->tzd[i]); 494 494 goto err; 495 495 } 496 + ret = thermal_zone_device_enable(pinfo->tzd[i]); 497 + if (ret) { 498 + kfree(td_info); 499 + thermal_zone_device_unregister(pinfo->tzd[i]); 500 + goto err; 501 + } 496 502 } 497 503 498 504 pinfo->pdev = pdev;
+7 -2
drivers/power/supply/power_supply_core.c
··· 939 939 940 940 static int psy_register_thermal(struct power_supply *psy) 941 941 { 942 - int i; 942 + int i, ret; 943 943 944 944 if (psy->desc->no_thermal) 945 945 return 0; ··· 949 949 if (psy->desc->properties[i] == POWER_SUPPLY_PROP_TEMP) { 950 950 psy->tzd = thermal_zone_device_register(psy->desc->name, 951 951 0, 0, psy, &psy_tzd_ops, NULL, 0, 0); 952 - return PTR_ERR_OR_ZERO(psy->tzd); 952 + if (IS_ERR(psy->tzd)) 953 + return PTR_ERR(psy->tzd); 954 + ret = thermal_zone_device_enable(psy->tzd); 955 + if (ret) 956 + thermal_zone_device_unregister(psy->tzd); 957 + return ret; 953 958 } 954 959 } 955 960 return 0;
+10 -10
drivers/thermal/Kconfig
··· 17 17 18 18 if THERMAL 19 19 20 + config THERMAL_NETLINK 21 + bool "Thermal netlink management" 22 + depends on NET 23 + default y 24 + help 25 + The thermal framework has a netlink interface to do thermal 26 + zones discovery, temperature readings and events such as 27 + trip point crossed, cooling device update or governor 28 + change. It is recommended to enable the feature. 29 + 20 30 config THERMAL_STATISTICS 21 31 bool "Thermal state transition statistics" 22 32 help ··· 189 179 idle injection. This will throttle the CPU by injecting 190 180 idle cycle. 191 181 endif 192 - 193 - config CLOCK_THERMAL 194 - bool "Generic clock cooling support" 195 - depends on COMMON_CLK 196 - depends on PM_OPP 197 - help 198 - This entry implements the generic clock cooling mechanism through 199 - frequency clipping. Typically used to cool off co-processors. The 200 - device that is configured to use this cooling mechanism will be 201 - controlled to reduce clock frequency whenever temperature is high. 202 182 203 183 config DEVFREQ_THERMAL 204 184 bool "Generic device cooling support"
+3 -3
drivers/thermal/Makefile
··· 7 7 thermal_sys-y += thermal_core.o thermal_sysfs.o \ 8 8 thermal_helpers.o 9 9 10 + # netlink interface to manage the thermal framework 11 + thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o 12 + 10 13 # interface to/from other layers providing sensors 11 14 thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o 12 15 thermal_sys-$(CONFIG_THERMAL_OF) += thermal_of.o ··· 24 21 # cpufreq cooling 25 22 thermal_sys-$(CONFIG_CPU_FREQ_THERMAL) += cpufreq_cooling.o 26 23 thermal_sys-$(CONFIG_CPU_IDLE_THERMAL) += cpuidle_cooling.o 27 - 28 - # clock cooling 29 - thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o 30 24 31 25 # devfreq cooling 32 26 thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
+6
drivers/thermal/armada_thermal.c
··· 874 874 return PTR_ERR(tz); 875 875 } 876 876 877 + ret = thermal_zone_device_enable(tz); 878 + if (ret) { 879 + thermal_zone_device_unregister(tz); 880 + return ret; 881 + } 882 + 877 883 drvdata->type = LEGACY; 878 884 drvdata->data.tz = tz; 879 885 platform_set_drvdata(pdev, drvdata);
-445
drivers/thermal/clock_cooling.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * drivers/thermal/clock_cooling.c 4 - * 5 - * Copyright (C) 2014 Eduardo Valentin <edubezval@gmail.com> 6 - * 7 - * Copyright (C) 2013 Texas Instruments Inc. 8 - * Contact: Eduardo Valentin <eduardo.valentin@ti.com> 9 - * 10 - * Highly based on cpufreq_cooling.c. 11 - * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) 12 - * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org> 13 - */ 14 - #include <linux/clk.h> 15 - #include <linux/clock_cooling.h> 16 - #include <linux/cpufreq.h> 17 - #include <linux/device.h> 18 - #include <linux/err.h> 19 - #include <linux/export.h> 20 - #include <linux/idr.h> 21 - #include <linux/mutex.h> 22 - #include <linux/pm_opp.h> 23 - #include <linux/slab.h> 24 - #include <linux/thermal.h> 25 - 26 - /** 27 - * struct clock_cooling_device - data for cooling device with clock 28 - * @id: unique integer value corresponding to each clock_cooling_device 29 - * registered. 30 - * @dev: struct device pointer to the device being used to cool off using 31 - * clock frequencies. 32 - * @cdev: thermal_cooling_device pointer to keep track of the 33 - * registered cooling device. 34 - * @clk_rate_change_nb: reference to notifier block used to receive clock 35 - * rate changes. 36 - * @freq_table: frequency table used to keep track of available frequencies. 37 - * @clock_state: integer value representing the current state of clock 38 - * cooling devices. 39 - * @clock_val: integer value representing the absolute value of the clipped 40 - * frequency. 41 - * @clk: struct clk reference used to enforce clock limits. 42 - * @lock: mutex lock to protect this struct. 43 - * 44 - * This structure is required for keeping information of each 45 - * clock_cooling_device registered. In order to prevent corruption of this a 46 - * mutex @lock is used. 47 - */ 48 - struct clock_cooling_device { 49 - int id; 50 - struct device *dev; 51 - struct thermal_cooling_device *cdev; 52 - struct notifier_block clk_rate_change_nb; 53 - struct cpufreq_frequency_table *freq_table; 54 - unsigned long clock_state; 55 - unsigned long clock_val; 56 - struct clk *clk; 57 - struct mutex lock; /* lock to protect the content of this struct */ 58 - }; 59 - #define to_clock_cooling_device(x) \ 60 - container_of(x, struct clock_cooling_device, clk_rate_change_nb) 61 - static DEFINE_IDA(clock_ida); 62 - 63 - /* Below code defines functions to be used for clock as cooling device */ 64 - 65 - enum clock_cooling_property { 66 - GET_LEVEL, 67 - GET_FREQ, 68 - GET_MAXL, 69 - }; 70 - 71 - /** 72 - * clock_cooling_get_property - fetch a property of interest for a give cpu. 73 - * @ccdev: clock cooling device reference 74 - * @input: query parameter 75 - * @output: query return 76 - * @property: type of query (frequency, level, max level) 77 - * 78 - * This is the common function to 79 - * 1. get maximum clock cooling states 80 - * 2. translate frequency to cooling state 81 - * 3. translate cooling state to frequency 82 - * Note that the code may be not in good shape 83 - * but it is written in this way in order to: 84 - * a) reduce duplicate code as most of the code can be shared. 85 - * b) make sure the logic is consistent when translating between 86 - * cooling states and frequencies. 87 - * 88 - * Return: 0 on success, -EINVAL when invalid parameters are passed. 89 - */ 90 - static int clock_cooling_get_property(struct clock_cooling_device *ccdev, 91 - unsigned long input, 92 - unsigned long *output, 93 - enum clock_cooling_property property) 94 - { 95 - int i; 96 - unsigned long max_level = 0, level = 0; 97 - unsigned int freq = CPUFREQ_ENTRY_INVALID; 98 - int descend = -1; 99 - struct cpufreq_frequency_table *pos, *table = ccdev->freq_table; 100 - 101 - if (!output) 102 - return -EINVAL; 103 - 104 - if (!table) 105 - return -EINVAL; 106 - 107 - cpufreq_for_each_valid_entry(pos, table) { 108 - /* ignore duplicate entry */ 109 - if (freq == pos->frequency) 110 - continue; 111 - 112 - /* get the frequency order */ 113 - if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) 114 - descend = freq > pos->frequency; 115 - 116 - freq = pos->frequency; 117 - max_level++; 118 - } 119 - 120 - /* No valid cpu frequency entry */ 121 - if (max_level == 0) 122 - return -EINVAL; 123 - 124 - /* max_level is an index, not a counter */ 125 - max_level--; 126 - 127 - /* get max level */ 128 - if (property == GET_MAXL) { 129 - *output = max_level; 130 - return 0; 131 - } 132 - 133 - if (property == GET_FREQ) 134 - level = descend ? input : (max_level - input); 135 - 136 - i = 0; 137 - cpufreq_for_each_valid_entry(pos, table) { 138 - /* ignore duplicate entry */ 139 - if (freq == pos->frequency) 140 - continue; 141 - 142 - /* now we have a valid frequency entry */ 143 - freq = pos->frequency; 144 - 145 - if (property == GET_LEVEL && (unsigned int)input == freq) { 146 - /* get level by frequency */ 147 - *output = descend ? i : (max_level - i); 148 - return 0; 149 - } 150 - if (property == GET_FREQ && level == i) { 151 - /* get frequency by level */ 152 - *output = freq; 153 - return 0; 154 - } 155 - i++; 156 - } 157 - 158 - return -EINVAL; 159 - } 160 - 161 - /** 162 - * clock_cooling_get_level - return the cooling level of given clock cooling. 163 - * @cdev: reference of a thermal cooling device of used as clock cooling device 164 - * @freq: the frequency of interest 165 - * 166 - * This function will match the cooling level corresponding to the 167 - * requested @freq and return it. 168 - * 169 - * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID 170 - * otherwise. 171 - */ 172 - unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, 173 - unsigned long freq) 174 - { 175 - struct clock_cooling_device *ccdev = cdev->devdata; 176 - unsigned long val; 177 - 178 - if (clock_cooling_get_property(ccdev, (unsigned long)freq, &val, 179 - GET_LEVEL)) 180 - return THERMAL_CSTATE_INVALID; 181 - 182 - return val; 183 - } 184 - EXPORT_SYMBOL_GPL(clock_cooling_get_level); 185 - 186 - /** 187 - * clock_cooling_get_frequency - get the absolute value of frequency from level. 188 - * @ccdev: clock cooling device reference 189 - * @level: cooling level 190 - * 191 - * This function matches cooling level with frequency. Based on a cooling level 192 - * of frequency, equals cooling state of cpu cooling device, it will return 193 - * the corresponding frequency. 194 - * e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc 195 - * 196 - * Return: 0 on error, the corresponding frequency otherwise. 197 - */ 198 - static unsigned long 199 - clock_cooling_get_frequency(struct clock_cooling_device *ccdev, 200 - unsigned long level) 201 - { 202 - int ret = 0; 203 - unsigned long freq; 204 - 205 - ret = clock_cooling_get_property(ccdev, level, &freq, GET_FREQ); 206 - if (ret) 207 - return 0; 208 - 209 - return freq; 210 - } 211 - 212 - /** 213 - * clock_cooling_apply - function to apply frequency clipping. 214 - * @ccdev: clock_cooling_device pointer containing frequency clipping data. 215 - * @cooling_state: value of the cooling state. 216 - * 217 - * Function used to make sure the clock layer is aware of current thermal 218 - * limits. The limits are applied by updating the clock rate in case it is 219 - * higher than the corresponding frequency based on the requested cooling_state. 220 - * 221 - * Return: 0 on success, an error code otherwise (-EINVAL in case wrong 222 - * cooling state). 223 - */ 224 - static int clock_cooling_apply(struct clock_cooling_device *ccdev, 225 - unsigned long cooling_state) 226 - { 227 - unsigned long clip_freq, cur_freq; 228 - int ret = 0; 229 - 230 - /* Here we write the clipping */ 231 - /* Check if the old cooling action is same as new cooling action */ 232 - if (ccdev->clock_state == cooling_state) 233 - return 0; 234 - 235 - clip_freq = clock_cooling_get_frequency(ccdev, cooling_state); 236 - if (!clip_freq) 237 - return -EINVAL; 238 - 239 - cur_freq = clk_get_rate(ccdev->clk); 240 - 241 - mutex_lock(&ccdev->lock); 242 - ccdev->clock_state = cooling_state; 243 - ccdev->clock_val = clip_freq; 244 - /* enforce clock level */ 245 - if (cur_freq > clip_freq) 246 - ret = clk_set_rate(ccdev->clk, clip_freq); 247 - mutex_unlock(&ccdev->lock); 248 - 249 - return ret; 250 - } 251 - 252 - /** 253 - * clock_cooling_clock_notifier - notifier callback on clock rate changes. 254 - * @nb: struct notifier_block * with callback info. 255 - * @event: value showing clock event for which this function invoked. 256 - * @data: callback-specific data 257 - * 258 - * Callback to hijack the notification on clock transition. 259 - * Every time there is a clock change, we intercept all pre change events 260 - * and block the transition in case the new rate infringes thermal limits. 261 - * 262 - * Return: NOTIFY_DONE (success) or NOTIFY_BAD (new_rate > thermal limit). 263 - */ 264 - static int clock_cooling_clock_notifier(struct notifier_block *nb, 265 - unsigned long event, void *data) 266 - { 267 - struct clk_notifier_data *ndata = data; 268 - struct clock_cooling_device *ccdev = to_clock_cooling_device(nb); 269 - 270 - switch (event) { 271 - case PRE_RATE_CHANGE: 272 - /* 273 - * checks on current state 274 - * TODO: current method is not best we can find as it 275 - * allows possibly voltage transitions, in case DVFS 276 - * layer is also hijacking clock pre notifications. 277 - */ 278 - if (ndata->new_rate > ccdev->clock_val) 279 - return NOTIFY_BAD; 280 - /* fall through */ 281 - case POST_RATE_CHANGE: 282 - case ABORT_RATE_CHANGE: 283 - default: 284 - return NOTIFY_DONE; 285 - } 286 - } 287 - 288 - /* clock cooling device thermal callback functions are defined below */ 289 - 290 - /** 291 - * clock_cooling_get_max_state - callback function to get the max cooling state. 292 - * @cdev: thermal cooling device pointer. 293 - * @state: fill this variable with the max cooling state. 294 - * 295 - * Callback for the thermal cooling device to return the clock 296 - * max cooling state. 297 - * 298 - * Return: 0 on success, an error code otherwise. 299 - */ 300 - static int clock_cooling_get_max_state(struct thermal_cooling_device *cdev, 301 - unsigned long *state) 302 - { 303 - struct clock_cooling_device *ccdev = cdev->devdata; 304 - unsigned long count = 0; 305 - int ret; 306 - 307 - ret = clock_cooling_get_property(ccdev, 0, &count, GET_MAXL); 308 - if (!ret) 309 - *state = count; 310 - 311 - return ret; 312 - } 313 - 314 - /** 315 - * clock_cooling_get_cur_state - function to get the current cooling state. 316 - * @cdev: thermal cooling device pointer. 317 - * @state: fill this variable with the current cooling state. 318 - * 319 - * Callback for the thermal cooling device to return the clock 320 - * current cooling state. 321 - * 322 - * Return: 0 (success) 323 - */ 324 - static int clock_cooling_get_cur_state(struct thermal_cooling_device *cdev, 325 - unsigned long *state) 326 - { 327 - struct clock_cooling_device *ccdev = cdev->devdata; 328 - 329 - *state = ccdev->clock_state; 330 - 331 - return 0; 332 - } 333 - 334 - /** 335 - * clock_cooling_set_cur_state - function to set the current cooling state. 336 - * @cdev: thermal cooling device pointer. 337 - * @state: set this variable to the current cooling state. 338 - * 339 - * Callback for the thermal cooling device to change the clock cooling 340 - * current cooling state. 341 - * 342 - * Return: 0 on success, an error code otherwise. 343 - */ 344 - static int clock_cooling_set_cur_state(struct thermal_cooling_device *cdev, 345 - unsigned long state) 346 - { 347 - struct clock_cooling_device *clock_device = cdev->devdata; 348 - 349 - return clock_cooling_apply(clock_device, state); 350 - } 351 - 352 - /* Bind clock callbacks to thermal cooling device ops */ 353 - static struct thermal_cooling_device_ops const clock_cooling_ops = { 354 - .get_max_state = clock_cooling_get_max_state, 355 - .get_cur_state = clock_cooling_get_cur_state, 356 - .set_cur_state = clock_cooling_set_cur_state, 357 - }; 358 - 359 - /** 360 - * clock_cooling_register - function to create clock cooling device. 361 - * @dev: struct device pointer to the device used as clock cooling device. 362 - * @clock_name: string containing the clock used as cooling mechanism. 363 - * 364 - * This interface function registers the clock cooling device with the name 365 - * "thermal-clock-%x". The cooling device is based on clock frequencies. 366 - * The struct device is assumed to be capable of DVFS transitions. 367 - * The OPP layer is used to fetch and fill the available frequencies for 368 - * the referred device. The ordered frequency table is used to control 369 - * the clock cooling device cooling states and to limit clock transitions 370 - * based on the cooling state requested by the thermal framework. 371 - * 372 - * Return: a valid struct thermal_cooling_device pointer on success, 373 - * on failure, it returns a corresponding ERR_PTR(). 374 - */ 375 - struct thermal_cooling_device * 376 - clock_cooling_register(struct device *dev, const char *clock_name) 377 - { 378 - struct thermal_cooling_device *cdev; 379 - struct clock_cooling_device *ccdev = NULL; 380 - char dev_name[THERMAL_NAME_LENGTH]; 381 - int ret = 0; 382 - 383 - ccdev = devm_kzalloc(dev, sizeof(*ccdev), GFP_KERNEL); 384 - if (!ccdev) 385 - return ERR_PTR(-ENOMEM); 386 - 387 - mutex_init(&ccdev->lock); 388 - ccdev->dev = dev; 389 - ccdev->clk = devm_clk_get(dev, clock_name); 390 - if (IS_ERR(ccdev->clk)) 391 - return ERR_CAST(ccdev->clk); 392 - 393 - ret = ida_simple_get(&clock_ida, 0, 0, GFP_KERNEL); 394 - if (ret < 0) 395 - return ERR_PTR(ret); 396 - ccdev->id = ret; 397 - 398 - snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id); 399 - 400 - cdev = thermal_cooling_device_register(dev_name, ccdev, 401 - &clock_cooling_ops); 402 - if (IS_ERR(cdev)) { 403 - ida_simple_remove(&clock_ida, ccdev->id); 404 - return ERR_PTR(-EINVAL); 405 - } 406 - ccdev->cdev = cdev; 407 - ccdev->clk_rate_change_nb.notifier_call = clock_cooling_clock_notifier; 408 - 409 - /* Assuming someone has already filled the opp table for this device */ 410 - ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table); 411 - if (ret) { 412 - ida_simple_remove(&clock_ida, ccdev->id); 413 - return ERR_PTR(ret); 414 - } 415 - ccdev->clock_state = 0; 416 - ccdev->clock_val = clock_cooling_get_frequency(ccdev, 0); 417 - 418 - clk_notifier_register(ccdev->clk, &ccdev->clk_rate_change_nb); 419 - 420 - return cdev; 421 - } 422 - EXPORT_SYMBOL_GPL(clock_cooling_register); 423 - 424 - /** 425 - * clock_cooling_unregister - function to remove clock cooling device. 426 - * @cdev: thermal cooling device pointer. 427 - * 428 - * This interface function unregisters the "thermal-clock-%x" cooling device. 429 - */ 430 - void clock_cooling_unregister(struct thermal_cooling_device *cdev) 431 - { 432 - struct clock_cooling_device *ccdev; 433 - 434 - if (!cdev) 435 - return; 436 - 437 - ccdev = cdev->devdata; 438 - 439 - clk_notifier_unregister(ccdev->clk, &ccdev->clk_rate_change_nb); 440 - dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table); 441 - 442 - thermal_cooling_device_unregister(ccdev->cdev); 443 - ida_simple_remove(&clock_ida, ccdev->id); 444 - } 445 - EXPORT_SYMBOL_GPL(clock_cooling_unregister);
+5 -11
drivers/thermal/da9062-thermal.c
··· 49 49 struct da9062 *hw; 50 50 struct delayed_work work; 51 51 struct thermal_zone_device *zone; 52 - enum thermal_device_mode mode; 53 52 struct mutex lock; /* protection for da9062_thermal temperature */ 54 53 int temperature; 55 54 int irq; ··· 120 121 return IRQ_HANDLED; 121 122 } 122 123 123 - static int da9062_thermal_get_mode(struct thermal_zone_device *z, 124 - enum thermal_device_mode *mode) 125 - { 126 - struct da9062_thermal *thermal = z->devdata; 127 - *mode = thermal->mode; 128 - return 0; 129 - } 130 - 131 124 static int da9062_thermal_get_trip_type(struct thermal_zone_device *z, 132 125 int trip, 133 126 enum thermal_trip_type *type) ··· 172 181 173 182 static struct thermal_zone_device_ops da9062_thermal_ops = { 174 183 .get_temp = da9062_thermal_get_temp, 175 - .get_mode = da9062_thermal_get_mode, 176 184 .get_trip_type = da9062_thermal_get_trip_type, 177 185 .get_trip_temp = da9062_thermal_get_trip_temp, 178 186 }; ··· 223 233 224 234 thermal->config = match->data; 225 235 thermal->hw = chip; 226 - thermal->mode = THERMAL_DEVICE_ENABLED; 227 236 thermal->dev = &pdev->dev; 228 237 229 238 INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on); ··· 236 247 dev_err(&pdev->dev, "Cannot register thermal zone device\n"); 237 248 ret = PTR_ERR(thermal->zone); 238 249 goto err; 250 + } 251 + ret = thermal_zone_device_enable(thermal->zone); 252 + if (ret) { 253 + dev_err(&pdev->dev, "Cannot enable thermal zone device\n"); 254 + goto err_zone; 239 255 } 240 256 241 257 dev_dbg(&pdev->dev,
+1 -9
drivers/thermal/devfreq_cooling.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * devfreq_cooling: Thermal cooling device implementation for devices using 3 4 * devfreq 4 5 * 5 6 * Copyright (C) 2014-2015 ARM Limited 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License version 2 as 9 - * published by the Free Software Foundation. 10 - * 11 - * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12 - * kind, whether express or implied; without even the implied warranty 13 - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 - * GNU General Public License for more details. 15 7 * 16 8 * TODO: 17 9 * - If OPPs are added or removed after devfreq cooling has
+6
drivers/thermal/dove_thermal.c
··· 153 153 return PTR_ERR(thermal); 154 154 } 155 155 156 + ret = thermal_zone_device_enable(thermal); 157 + if (ret) { 158 + thermal_zone_device_unregister(thermal); 159 + return ret; 160 + } 161 + 156 162 platform_set_drvdata(pdev, thermal); 157 163 158 164 return 0;
+1 -8
drivers/thermal/gov_power_allocator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * A power allocator to manage temperature 3 4 * 4 5 * Copyright (C) 2014 ARM Ltd. 5 6 * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License version 2 as 8 - * published by the Free Software Foundation. 9 - * 10 - * This program is distributed "as is" WITHOUT ANY WARRANTY of any 11 - * kind, whether express or implied; without even the implied warranty 12 - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 7 */ 15 8 16 9 #define pr_fmt(fmt) "Power allocator: " fmt
+4 -2
drivers/thermal/hisi_thermal.c
··· 549 549 { 550 550 struct thermal_zone_device *tzd = sensor->tzd; 551 551 552 - tzd->ops->set_mode(tzd, 553 - on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); 552 + if (on) 553 + thermal_zone_device_enable(tzd); 554 + else 555 + thermal_zone_device_disable(tzd); 554 556 } 555 557 556 558 static int hisi_thermal_probe(struct platform_device *pdev)
+1
drivers/thermal/imx8mm_thermal.c
··· 220 220 { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, }, 221 221 { }, 222 222 }; 223 + MODULE_DEVICE_TABLE(of, imx8mm_tmu_table); 223 224 224 225 static struct platform_driver imx8mm_tmu = { 225 226 .driver = {
+19 -41
drivers/thermal/imx_thermal.c
··· 197 197 struct cpufreq_policy *policy; 198 198 struct thermal_zone_device *tz; 199 199 struct thermal_cooling_device *cdev; 200 - enum thermal_device_mode mode; 201 200 struct regmap *tempmon; 202 201 u32 c1, c2; /* See formula in imx_init_calib() */ 203 202 int temp_passive; ··· 252 253 const struct thermal_soc_data *soc_data = data->socdata; 253 254 struct regmap *map = data->tempmon; 254 255 unsigned int n_meas; 255 - bool wait; 256 + bool wait, run_measurement; 256 257 u32 val; 257 258 258 - if (data->mode == THERMAL_DEVICE_ENABLED) { 259 + run_measurement = !data->irq_enabled; 260 + if (!run_measurement) { 259 261 /* Check if a measurement is currently in progress */ 260 262 regmap_read(map, soc_data->temp_data, &val); 261 263 wait = !(val & soc_data->temp_valid_mask); ··· 283 283 284 284 regmap_read(map, soc_data->temp_data, &val); 285 285 286 - if (data->mode != THERMAL_DEVICE_ENABLED) { 286 + if (run_measurement) { 287 287 regmap_write(map, soc_data->sensor_ctrl + REG_CLR, 288 288 soc_data->measure_temp_mask); 289 289 regmap_write(map, soc_data->sensor_ctrl + REG_SET, ··· 331 331 return 0; 332 332 } 333 333 334 - static int imx_get_mode(struct thermal_zone_device *tz, 335 - enum thermal_device_mode *mode) 336 - { 337 - struct imx_thermal_data *data = tz->devdata; 338 - 339 - *mode = data->mode; 340 - 341 - return 0; 342 - } 343 - 344 - static int imx_set_mode(struct thermal_zone_device *tz, 345 - enum thermal_device_mode mode) 334 + static int imx_change_mode(struct thermal_zone_device *tz, 335 + enum thermal_device_mode mode) 346 336 { 347 337 struct imx_thermal_data *data = tz->devdata; 348 338 struct regmap *map = data->tempmon; 349 339 const struct thermal_soc_data *soc_data = data->socdata; 350 340 351 341 if (mode == THERMAL_DEVICE_ENABLED) { 352 - tz->polling_delay = IMX_POLLING_DELAY; 353 - tz->passive_delay = IMX_PASSIVE_DELAY; 354 - 355 342 regmap_write(map, soc_data->sensor_ctrl + REG_CLR, 356 343 soc_data->power_down_mask); 357 344 regmap_write(map, soc_data->sensor_ctrl + REG_SET, ··· 354 367 regmap_write(map, soc_data->sensor_ctrl + REG_SET, 355 368 soc_data->power_down_mask); 356 369 357 - tz->polling_delay = 0; 358 - tz->passive_delay = 0; 359 - 360 370 if (data->irq_enabled) { 361 371 disable_irq(data->irq); 362 372 data->irq_enabled = false; 363 373 } 364 374 } 365 - 366 - data->mode = mode; 367 - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 368 375 369 376 return 0; 370 377 } ··· 448 467 .bind = imx_bind, 449 468 .unbind = imx_unbind, 450 469 .get_temp = imx_get_temp, 451 - .get_mode = imx_get_mode, 452 - .set_mode = imx_set_mode, 470 + .change_mode = imx_change_mode, 453 471 .get_trip_type = imx_get_trip_type, 454 472 .get_trip_temp = imx_get_trip_temp, 455 473 .get_crit_temp = imx_get_crit_temp, ··· 812 832 data->socdata->measure_temp_mask); 813 833 814 834 data->irq_enabled = true; 815 - data->mode = THERMAL_DEVICE_ENABLED; 835 + ret = thermal_zone_device_enable(data->tz); 836 + if (ret) 837 + goto thermal_zone_unregister; 816 838 817 839 ret = devm_request_threaded_irq(&pdev->dev, data->irq, 818 840 imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, ··· 856 874 static int __maybe_unused imx_thermal_suspend(struct device *dev) 857 875 { 858 876 struct imx_thermal_data *data = dev_get_drvdata(dev); 859 - struct regmap *map = data->tempmon; 877 + int ret; 860 878 861 879 /* 862 880 * Need to disable thermal sensor, otherwise, when thermal core 863 881 * try to get temperature before thermal sensor resume, a wrong 864 882 * temperature will be read as the thermal sensor is powered 865 - * down. 883 + * down. This is done in change_mode() operation called from 884 + * thermal_zone_device_disable() 866 885 */ 867 - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, 868 - data->socdata->measure_temp_mask); 869 - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, 870 - data->socdata->power_down_mask); 871 - data->mode = THERMAL_DEVICE_DISABLED; 886 + ret = thermal_zone_device_disable(data->tz); 887 + if (ret) 888 + return ret; 872 889 clk_disable_unprepare(data->thermal_clk); 873 890 874 891 return 0; ··· 876 895 static int __maybe_unused imx_thermal_resume(struct device *dev) 877 896 { 878 897 struct imx_thermal_data *data = dev_get_drvdata(dev); 879 - struct regmap *map = data->tempmon; 880 898 int ret; 881 899 882 900 ret = clk_prepare_enable(data->thermal_clk); 883 901 if (ret) 884 902 return ret; 885 903 /* Enabled thermal sensor after resume */ 886 - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, 887 - data->socdata->power_down_mask); 888 - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, 889 - data->socdata->measure_temp_mask); 890 - data->mode = THERMAL_DEVICE_ENABLED; 904 + ret = thermal_zone_device_enable(data->tz); 905 + if (ret) 906 + return ret; 891 907 892 908 return 0; 893 909 }
+7 -31
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
··· 48 48 struct acpi_device *adev; 49 49 struct platform_device *pdev; 50 50 struct thermal_zone_device *thermal; 51 - int mode; 52 51 int art_count; 53 52 struct art *arts; 54 53 int trt_count; ··· 382 383 return 0; 383 384 } 384 385 385 - static int int3400_thermal_get_mode(struct thermal_zone_device *thermal, 386 - enum thermal_device_mode *mode) 386 + static int int3400_thermal_change_mode(struct thermal_zone_device *thermal, 387 + enum thermal_device_mode mode) 387 388 { 388 389 struct int3400_thermal_priv *priv = thermal->devdata; 389 - 390 - if (!priv) 391 - return -EINVAL; 392 - 393 - *mode = priv->mode; 394 - 395 - return 0; 396 - } 397 - 398 - static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, 399 - enum thermal_device_mode mode) 400 - { 401 - struct int3400_thermal_priv *priv = thermal->devdata; 402 - bool enable; 403 390 int result = 0; 404 391 405 392 if (!priv) 406 393 return -EINVAL; 407 394 408 - if (mode == THERMAL_DEVICE_ENABLED) 409 - enable = true; 410 - else if (mode == THERMAL_DEVICE_DISABLED) 411 - enable = false; 412 - else 413 - return -EINVAL; 414 - 415 - if (enable != priv->mode) { 416 - priv->mode = enable; 395 + if (mode != thermal->mode) 417 396 result = int3400_thermal_run_osc(priv->adev->handle, 418 - priv->current_uuid_index, 419 - enable); 420 - } 397 + priv->current_uuid_index, 398 + mode == THERMAL_DEVICE_ENABLED); 399 + 421 400 422 401 evaluate_odvp(priv); 423 402 ··· 404 427 405 428 static struct thermal_zone_device_ops int3400_thermal_ops = { 406 429 .get_temp = int3400_thermal_get_temp, 407 - .get_mode = int3400_thermal_get_mode, 408 - .set_mode = int3400_thermal_set_mode, 430 + .change_mode = int3400_thermal_change_mode, 409 431 }; 410 432 411 433 static struct thermal_zone_params int3400_thermal_params = {
+5
drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
··· 259 259 ret = PTR_ERR(int34x_thermal_zone->zone); 260 260 goto err_thermal_zone; 261 261 } 262 + ret = thermal_zone_device_enable(int34x_thermal_zone->zone); 263 + if (ret) 264 + goto err_enable; 262 265 263 266 return int34x_thermal_zone; 264 267 268 + err_enable: 269 + thermal_zone_device_unregister(int34x_thermal_zone->zone); 265 270 err_thermal_zone: 266 271 acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table); 267 272 kfree(int34x_thermal_zone->aux_trips);
+1 -1
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
··· 43 43 #define PCI_DEVICE_ID_PROC_ICL_THERMAL 0x8a03 44 44 45 45 /* JasperLake thermal reporting device */ 46 - #define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4503 46 + #define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4E03 47 47 48 48 /* TigerLake thermal reporting device */ 49 49 #define PCI_DEVICE_ID_PROC_TGL_THERMAL 0x9A03
+8
drivers/thermal/intel/intel_pch_thermal.c
··· 24 24 #define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */ 25 25 #define PCH_THERMAL_DID_CNL 0x9Df9 /* CNL PCH */ 26 26 #define PCH_THERMAL_DID_CNL_H 0xA379 /* CNL-H PCH */ 27 + #define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */ 27 28 #define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */ 28 29 29 30 /* Wildcat Point-LP PCH Thermal registers */ ··· 353 352 err = PTR_ERR(ptd->tzd); 354 353 goto error_cleanup; 355 354 } 355 + err = thermal_zone_device_enable(ptd->tzd); 356 + if (err) 357 + goto err_unregister; 356 358 357 359 return 0; 358 360 361 + err_unregister: 362 + thermal_zone_device_unregister(ptd->tzd); 359 363 error_cleanup: 360 364 iounmap(ptd->hw_base); 361 365 error_release: ··· 410 404 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL), 411 405 .driver_data = board_cnl, }, 412 406 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H), 407 + .driver_data = board_cnl, }, 408 + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_LP), 413 409 .driver_data = board_cnl, }, 414 410 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CML_H), 415 411 .driver_data = board_cml, },
+6 -28
drivers/thermal/intel/intel_quark_dts_thermal.c
··· 103 103 bool locked; 104 104 u32 store_ptps; 105 105 u32 store_dts_enable; 106 - enum thermal_device_mode mode; 107 106 struct thermal_zone_device *tzone; 108 107 }; 109 108 ··· 126 127 if (ret) 127 128 return ret; 128 129 129 - if (out & QRK_DTS_ENABLE_BIT) { 130 - aux_entry->mode = THERMAL_DEVICE_ENABLED; 130 + if (out & QRK_DTS_ENABLE_BIT) 131 131 return 0; 132 - } 133 132 134 133 if (!aux_entry->locked) { 135 134 out |= QRK_DTS_ENABLE_BIT; ··· 135 138 QRK_DTS_REG_OFFSET_ENABLE, out); 136 139 if (ret) 137 140 return ret; 138 - 139 - aux_entry->mode = THERMAL_DEVICE_ENABLED; 140 141 } else { 141 - aux_entry->mode = THERMAL_DEVICE_DISABLED; 142 142 pr_info("DTS is locked. Cannot enable DTS\n"); 143 143 ret = -EPERM; 144 144 } ··· 154 160 if (ret) 155 161 return ret; 156 162 157 - if (!(out & QRK_DTS_ENABLE_BIT)) { 158 - aux_entry->mode = THERMAL_DEVICE_DISABLED; 163 + if (!(out & QRK_DTS_ENABLE_BIT)) 159 164 return 0; 160 - } 161 165 162 166 if (!aux_entry->locked) { 163 167 out &= ~QRK_DTS_ENABLE_BIT; ··· 164 172 165 173 if (ret) 166 174 return ret; 167 - 168 - aux_entry->mode = THERMAL_DEVICE_DISABLED; 169 175 } else { 170 - aux_entry->mode = THERMAL_DEVICE_ENABLED; 171 176 pr_info("DTS is locked. Cannot disable DTS\n"); 172 177 ret = -EPERM; 173 178 } ··· 298 309 return 0; 299 310 } 300 311 301 - static int sys_get_mode(struct thermal_zone_device *tzd, 302 - enum thermal_device_mode *mode) 303 - { 304 - struct soc_sensor_entry *aux_entry = tzd->devdata; 305 - *mode = aux_entry->mode; 306 - return 0; 307 - } 308 - 309 - static int sys_set_mode(struct thermal_zone_device *tzd, 310 - enum thermal_device_mode mode) 312 + static int sys_change_mode(struct thermal_zone_device *tzd, 313 + enum thermal_device_mode mode) 311 314 { 312 315 int ret; 313 316 ··· 319 338 .get_trip_type = sys_get_trip_type, 320 339 .set_trip_temp = sys_set_trip_temp, 321 340 .get_crit_temp = sys_get_crit_temp, 322 - .get_mode = sys_get_mode, 323 - .set_mode = sys_set_mode, 341 + .change_mode = sys_change_mode, 324 342 }; 325 343 326 344 static void free_soc_dts(struct soc_sensor_entry *aux_entry) ··· 394 414 goto err_ret; 395 415 } 396 416 397 - mutex_lock(&dts_update_mutex); 398 - err = soc_dts_enable(aux_entry->tzone); 399 - mutex_unlock(&dts_update_mutex); 417 + err = thermal_zone_device_enable(aux_entry->tzone); 400 418 if (err) 401 419 goto err_aux_status; 402 420
+3
drivers/thermal/intel/intel_soc_dts_iosf.c
··· 329 329 ret = PTR_ERR(dts->tzone); 330 330 goto err_ret; 331 331 } 332 + ret = thermal_zone_device_enable(dts->tzone); 333 + if (ret) 334 + goto err_enable; 332 335 333 336 ret = soc_dts_enable(id); 334 337 if (ret)
+6
drivers/thermal/intel/x86_pkg_temp_thermal.c
··· 363 363 kfree(zonedev); 364 364 return err; 365 365 } 366 + err = thermal_zone_device_enable(zonedev->tzone); 367 + if (err) { 368 + thermal_zone_device_unregister(zonedev->tzone); 369 + kfree(zonedev); 370 + return err; 371 + } 366 372 /* Store MSR value for package thermal interrupt, to restore at exit */ 367 373 rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low, 368 374 zonedev->msr_pkg_therm_high);
+7
drivers/thermal/kirkwood_thermal.c
··· 65 65 struct thermal_zone_device *thermal = NULL; 66 66 struct kirkwood_thermal_priv *priv; 67 67 struct resource *res; 68 + int ret; 68 69 69 70 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 70 71 if (!priv) ··· 82 81 dev_err(&pdev->dev, 83 82 "Failed to register thermal zone device\n"); 84 83 return PTR_ERR(thermal); 84 + } 85 + ret = thermal_zone_device_enable(thermal); 86 + if (ret) { 87 + thermal_zone_device_unregister(thermal); 88 + dev_err(&pdev->dev, "Failed to enable thermal zone device\n"); 89 + return ret; 85 90 } 86 91 87 92 platform_set_drvdata(pdev, thermal);
+181 -53
drivers/thermal/mtk_thermal.c
··· 38 38 #define TEMP_MONIDET0 0x014 39 39 #define TEMP_MONIDET1 0x018 40 40 #define TEMP_MSRCTL0 0x038 41 + #define TEMP_MSRCTL1 0x03c 41 42 #define TEMP_AHBPOLL 0x040 42 43 #define TEMP_AHBTO 0x044 43 44 #define TEMP_ADCPNP0 0x048 ··· 121 120 * MT2701 has 3 sensors and needs 3 VTS calibration data. 122 121 * MT2712 has 4 sensors and needs 4 VTS calibration data. 123 122 */ 124 - #define CALIB_BUF0_VALID BIT(0) 125 - #define CALIB_BUF1_ADC_GE(x) (((x) >> 22) & 0x3ff) 126 - #define CALIB_BUF0_VTS_TS1(x) (((x) >> 17) & 0x1ff) 127 - #define CALIB_BUF0_VTS_TS2(x) (((x) >> 8) & 0x1ff) 128 - #define CALIB_BUF1_VTS_TS3(x) (((x) >> 0) & 0x1ff) 129 - #define CALIB_BUF2_VTS_TS4(x) (((x) >> 23) & 0x1ff) 130 - #define CALIB_BUF2_VTS_TS5(x) (((x) >> 5) & 0x1ff) 131 - #define CALIB_BUF2_VTS_TSABB(x) (((x) >> 14) & 0x1ff) 132 - #define CALIB_BUF0_DEGC_CALI(x) (((x) >> 1) & 0x3f) 133 - #define CALIB_BUF0_O_SLOPE(x) (((x) >> 26) & 0x3f) 134 - #define CALIB_BUF0_O_SLOPE_SIGN(x) (((x) >> 7) & 0x1) 135 - #define CALIB_BUF1_ID(x) (((x) >> 9) & 0x1) 123 + #define CALIB_BUF0_VALID_V1 BIT(0) 124 + #define CALIB_BUF1_ADC_GE_V1(x) (((x) >> 22) & 0x3ff) 125 + #define CALIB_BUF0_VTS_TS1_V1(x) (((x) >> 17) & 0x1ff) 126 + #define CALIB_BUF0_VTS_TS2_V1(x) (((x) >> 8) & 0x1ff) 127 + #define CALIB_BUF1_VTS_TS3_V1(x) (((x) >> 0) & 0x1ff) 128 + #define CALIB_BUF2_VTS_TS4_V1(x) (((x) >> 23) & 0x1ff) 129 + #define CALIB_BUF2_VTS_TS5_V1(x) (((x) >> 5) & 0x1ff) 130 + #define CALIB_BUF2_VTS_TSABB_V1(x) (((x) >> 14) & 0x1ff) 131 + #define CALIB_BUF0_DEGC_CALI_V1(x) (((x) >> 1) & 0x3f) 132 + #define CALIB_BUF0_O_SLOPE_V1(x) (((x) >> 26) & 0x3f) 133 + #define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1) 134 + #define CALIB_BUF1_ID_V1(x) (((x) >> 9) & 0x1) 135 + 136 + /* 137 + * Layout of the fuses providing the calibration data 138 + * These macros could be used for MT7622. 139 + */ 140 + #define CALIB_BUF0_ADC_OE_V2(x) (((x) >> 22) & 0x3ff) 141 + #define CALIB_BUF0_ADC_GE_V2(x) (((x) >> 12) & 0x3ff) 142 + #define CALIB_BUF0_DEGC_CALI_V2(x) (((x) >> 6) & 0x3f) 143 + #define CALIB_BUF0_O_SLOPE_V2(x) (((x) >> 0) & 0x3f) 144 + #define CALIB_BUF1_VTS_TS1_V2(x) (((x) >> 23) & 0x1ff) 145 + #define CALIB_BUF1_VTS_TS2_V2(x) (((x) >> 14) & 0x1ff) 146 + #define CALIB_BUF1_VTS_TSABB_V2(x) (((x) >> 5) & 0x1ff) 147 + #define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) 148 + #define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) 136 149 137 150 enum { 138 151 VTS1, ··· 156 141 VTS5, 157 142 VTSABB, 158 143 MAX_NUM_VTS, 144 + }; 145 + 146 + enum mtk_thermal_version { 147 + MTK_THERMAL_V1 = 1, 148 + MTK_THERMAL_V2, 159 149 }; 160 150 161 151 /* MT2701 thermal sensors */ ··· 268 248 const int *controller_offset; 269 249 bool need_switch_bank; 270 250 struct thermal_bank_cfg bank_data[MAX_NUM_ZONES]; 251 + enum mtk_thermal_version version; 271 252 }; 272 253 273 254 struct mtk_thermal { ··· 282 261 283 262 /* Calibration values */ 284 263 s32 adc_ge; 264 + s32 adc_oe; 285 265 s32 degc_cali; 286 266 s32 o_slope; 267 + s32 o_slope_sign; 287 268 s32 vts[MAX_NUM_VTS]; 288 269 289 270 const struct mtk_thermal_data *conf; ··· 424 401 .msr = mt8173_msr, 425 402 .adcpnp = mt8173_adcpnp, 426 403 .sensor_mux_values = mt8173_mux_values, 404 + .version = MTK_THERMAL_V1, 427 405 }; 428 406 429 407 /* ··· 455 431 .msr = mt2701_msr, 456 432 .adcpnp = mt2701_adcpnp, 457 433 .sensor_mux_values = mt2701_mux_values, 434 + .version = MTK_THERMAL_V1, 458 435 }; 459 436 460 437 /* ··· 486 461 .msr = mt2712_msr, 487 462 .adcpnp = mt2712_adcpnp, 488 463 .sensor_mux_values = mt2712_mux_values, 464 + .version = MTK_THERMAL_V1, 489 465 }; 490 466 491 467 /* ··· 511 485 .msr = mt7622_msr, 512 486 .adcpnp = mt7622_adcpnp, 513 487 .sensor_mux_values = mt7622_mux_values, 488 + .version = MTK_THERMAL_V2, 514 489 }; 515 490 516 491 /* ··· 544 517 .msr = mt8183_msr, 545 518 .adcpnp = mt8183_adcpnp, 546 519 .sensor_mux_values = mt8183_mux_values, 520 + .version = MTK_THERMAL_V1, 547 521 }; 548 522 549 523 /** ··· 556 528 * This converts the raw ADC value to mcelsius using the SoC specific 557 529 * calibration constants 558 530 */ 559 - static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw) 531 + static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw) 560 532 { 561 533 s32 tmp; 562 534 ··· 569 541 tmp >>= 3; 570 542 571 543 return mt->degc_cali * 500 - tmp; 544 + } 545 + 546 + static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw) 547 + { 548 + s32 format_1 = 0; 549 + s32 format_2 = 0; 550 + s32 g_oe = 1; 551 + s32 g_gain = 1; 552 + s32 g_x_roomt = 0; 553 + s32 tmp = 0; 554 + 555 + if (raw == 0) 556 + return 0; 557 + 558 + raw &= 0xfff; 559 + g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12); 560 + g_oe = mt->adc_oe - 512; 561 + format_1 = mt->vts[VTS2] + 3105 - g_oe; 562 + format_2 = (mt->degc_cali * 10) >> 1; 563 + g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain; 564 + 565 + tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt; 566 + tmp = tmp * 10 * 100 / 11; 567 + 568 + if (mt->o_slope_sign == 0) 569 + tmp = tmp / (165 - mt->o_slope); 570 + else 571 + tmp = tmp / (165 + mt->o_slope); 572 + 573 + return (format_2 - tmp) * 100; 572 574 } 573 575 574 576 /** ··· 654 596 for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { 655 597 raw = readl(mt->thermal_base + conf->msr[i]); 656 598 657 - temp = raw_to_mcelsius(mt, 658 - conf->bank_data[bank->id].sensors[i], 659 - raw); 599 + if (mt->conf->version == MTK_THERMAL_V1) { 600 + temp = raw_to_mcelsius_v1( 601 + mt, conf->bank_data[bank->id].sensors[i], raw); 602 + } else { 603 + temp = raw_to_mcelsius_v2( 604 + mt, conf->bank_data[bank->id].sensors[i], raw); 605 + } 660 606 661 607 /* 662 608 * The first read of a sensor often contains very high bogus ··· 762 700 writel(auxadc_phys_base + AUXADC_CON1_CLR_V, 763 701 controller_base + TEMP_ADCMUXADDR); 764 702 765 - /* AHB address for pnp sensor mux selection */ 766 - writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, 767 - controller_base + TEMP_PNPMUXADDR); 703 + if (mt->conf->version == MTK_THERMAL_V1) { 704 + /* AHB address for pnp sensor mux selection */ 705 + writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, 706 + controller_base + TEMP_PNPMUXADDR); 707 + } 768 708 769 709 /* AHB value for auxadc enable */ 770 710 writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN); ··· 823 759 return of_translate_address(np, regaddr_p); 824 760 } 825 761 762 + static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) 763 + { 764 + int i; 765 + 766 + if (!(buf[0] & CALIB_BUF0_VALID_V1)) 767 + return -EINVAL; 768 + 769 + mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]); 770 + 771 + for (i = 0; i < mt->conf->num_sensors; i++) { 772 + switch (mt->conf->vts_index[i]) { 773 + case VTS1: 774 + mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]); 775 + break; 776 + case VTS2: 777 + mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]); 778 + break; 779 + case VTS3: 780 + mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]); 781 + break; 782 + case VTS4: 783 + mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]); 784 + break; 785 + case VTS5: 786 + mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]); 787 + break; 788 + case VTSABB: 789 + mt->vts[VTSABB] = 790 + CALIB_BUF2_VTS_TSABB_V1(buf[2]); 791 + break; 792 + default: 793 + break; 794 + } 795 + } 796 + 797 + mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]); 798 + if (CALIB_BUF1_ID_V1(buf[1]) & 799 + CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0])) 800 + mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]); 801 + else 802 + mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]); 803 + 804 + return 0; 805 + } 806 + 807 + static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf) 808 + { 809 + if (!CALIB_BUF1_VALID_V2(buf[1])) 810 + return -EINVAL; 811 + 812 + mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]); 813 + mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]); 814 + mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]); 815 + mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]); 816 + mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]); 817 + mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]); 818 + mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]); 819 + mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]); 820 + 821 + return 0; 822 + } 823 + 826 824 static int mtk_thermal_get_calibration_data(struct device *dev, 827 825 struct mtk_thermal *mt) 828 826 { ··· 920 794 goto out; 921 795 } 922 796 923 - if (buf[0] & CALIB_BUF0_VALID) { 924 - mt->adc_ge = CALIB_BUF1_ADC_GE(buf[1]); 797 + if (mt->conf->version == MTK_THERMAL_V1) 798 + ret = mtk_thermal_extract_efuse_v1(mt, buf); 799 + else 800 + ret = mtk_thermal_extract_efuse_v2(mt, buf); 925 801 926 - for (i = 0; i < mt->conf->num_sensors; i++) { 927 - switch (mt->conf->vts_index[i]) { 928 - case VTS1: 929 - mt->vts[VTS1] = CALIB_BUF0_VTS_TS1(buf[0]); 930 - break; 931 - case VTS2: 932 - mt->vts[VTS2] = CALIB_BUF0_VTS_TS2(buf[0]); 933 - break; 934 - case VTS3: 935 - mt->vts[VTS3] = CALIB_BUF1_VTS_TS3(buf[1]); 936 - break; 937 - case VTS4: 938 - mt->vts[VTS4] = CALIB_BUF2_VTS_TS4(buf[2]); 939 - break; 940 - case VTS5: 941 - mt->vts[VTS5] = CALIB_BUF2_VTS_TS5(buf[2]); 942 - break; 943 - case VTSABB: 944 - mt->vts[VTSABB] = CALIB_BUF2_VTS_TSABB(buf[2]); 945 - break; 946 - default: 947 - break; 948 - } 949 - } 950 - 951 - mt->degc_cali = CALIB_BUF0_DEGC_CALI(buf[0]); 952 - if (CALIB_BUF1_ID(buf[1]) & 953 - CALIB_BUF0_O_SLOPE_SIGN(buf[0])) 954 - mt->o_slope = -CALIB_BUF0_O_SLOPE(buf[0]); 955 - else 956 - mt->o_slope = CALIB_BUF0_O_SLOPE(buf[0]); 957 - } else { 802 + if (ret) { 958 803 dev_info(dev, "Device not calibrated, using default calibration values\n"); 804 + ret = 0; 959 805 } 960 806 961 807 out: ··· 961 863 }; 962 864 MODULE_DEVICE_TABLE(of, mtk_thermal_of_match); 963 865 866 + static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base) 867 + { 868 + int tmp; 869 + 870 + tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1); 871 + tmp &= ~(0x37); 872 + tmp |= 0x1; 873 + writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1); 874 + udelay(200); 875 + } 876 + 877 + static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt, 878 + void __iomem *auxadc_base) 879 + { 880 + int tmp; 881 + 882 + writel(0x800, auxadc_base + AUXADC_CON1_SET_V); 883 + writel(0x1, mt->thermal_base + TEMP_MONCTL0); 884 + tmp = readl(mt->thermal_base + TEMP_MSRCTL1); 885 + writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1); 886 + } 887 + 964 888 static int mtk_thermal_probe(struct platform_device *pdev) 965 889 { 966 890 int ret, i, ctrl_id; ··· 991 871 struct resource *res; 992 872 u64 auxadc_phys_base, apmixed_phys_base; 993 873 struct thermal_zone_device *tzdev; 874 + void __iomem *apmixed_base, *auxadc_base; 994 875 995 876 mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL); 996 877 if (!mt) ··· 1026 905 return -ENODEV; 1027 906 } 1028 907 908 + auxadc_base = of_iomap(auxadc, 0); 1029 909 auxadc_phys_base = of_get_phys_base(auxadc); 1030 910 1031 911 of_node_put(auxadc); ··· 1042 920 return -ENODEV; 1043 921 } 1044 922 923 + apmixed_base = of_iomap(apmixedsys, 0); 1045 924 apmixed_phys_base = of_get_phys_base(apmixedsys); 1046 925 1047 926 of_node_put(apmixedsys); ··· 1066 943 if (ret) { 1067 944 dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret); 1068 945 goto err_disable_clk_auxadc; 946 + } 947 + 948 + if (mt->conf->version == MTK_THERMAL_V2) { 949 + mtk_thermal_turn_on_buffer(apmixed_base); 950 + mtk_thermal_release_periodic_ts(mt, auxadc_base); 1069 951 } 1070 952 1071 953 for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
+143 -1
drivers/thermal/qcom/tsens-v0_1.c
··· 48 48 #define MSM8916_CAL_SEL_MASK 0xe0000000 49 49 #define MSM8916_CAL_SEL_SHIFT 29 50 50 51 + /* eeprom layout data for 8939 */ 52 + #define MSM8939_BASE0_MASK 0x000000ff 53 + #define MSM8939_BASE1_MASK 0xff000000 54 + #define MSM8939_BASE0_SHIFT 0 55 + #define MSM8939_BASE1_SHIFT 24 56 + 57 + #define MSM8939_S0_P1_MASK 0x000001f8 58 + #define MSM8939_S1_P1_MASK 0x001f8000 59 + #define MSM8939_S2_P1_MASK_0_4 0xf8000000 60 + #define MSM8939_S2_P1_MASK_5 0x00000001 61 + #define MSM8939_S3_P1_MASK 0x00001f80 62 + #define MSM8939_S4_P1_MASK 0x01f80000 63 + #define MSM8939_S5_P1_MASK 0x00003f00 64 + #define MSM8939_S6_P1_MASK 0x03f00000 65 + #define MSM8939_S7_P1_MASK 0x0000003f 66 + #define MSM8939_S8_P1_MASK 0x0003f000 67 + #define MSM8939_S9_P1_MASK 0x07e00000 68 + 69 + #define MSM8939_S0_P2_MASK 0x00007e00 70 + #define MSM8939_S1_P2_MASK 0x07e00000 71 + #define MSM8939_S2_P2_MASK 0x0000007e 72 + #define MSM8939_S3_P2_MASK 0x0007e000 73 + #define MSM8939_S4_P2_MASK 0x7e000000 74 + #define MSM8939_S5_P2_MASK 0x000fc000 75 + #define MSM8939_S6_P2_MASK 0xfc000000 76 + #define MSM8939_S7_P2_MASK 0x00000fc0 77 + #define MSM8939_S8_P2_MASK 0x00fc0000 78 + #define MSM8939_S9_P2_MASK_0_4 0xf8000000 79 + #define MSM8939_S9_P2_MASK_5 0x00002000 80 + 81 + #define MSM8939_S0_P1_SHIFT 3 82 + #define MSM8939_S1_P1_SHIFT 15 83 + #define MSM8939_S2_P1_SHIFT_0_4 27 84 + #define MSM8939_S2_P1_SHIFT_5 0 85 + #define MSM8939_S3_P1_SHIFT 7 86 + #define MSM8939_S4_P1_SHIFT 19 87 + #define MSM8939_S5_P1_SHIFT 8 88 + #define MSM8939_S6_P1_SHIFT 20 89 + #define MSM8939_S7_P1_SHIFT 0 90 + #define MSM8939_S8_P1_SHIFT 12 91 + #define MSM8939_S9_P1_SHIFT 21 92 + 93 + #define MSM8939_S0_P2_SHIFT 9 94 + #define MSM8939_S1_P2_SHIFT 21 95 + #define MSM8939_S2_P2_SHIFT 1 96 + #define MSM8939_S3_P2_SHIFT 13 97 + #define MSM8939_S4_P2_SHIFT 25 98 + #define MSM8939_S5_P2_SHIFT 14 99 + #define MSM8939_S6_P2_SHIFT 26 100 + #define MSM8939_S7_P2_SHIFT 6 101 + #define MSM8939_S8_P2_SHIFT 18 102 + #define MSM8939_S9_P2_SHIFT_0_4 27 103 + #define MSM8939_S9_P2_SHIFT_5 13 104 + 105 + #define MSM8939_CAL_SEL_MASK 0x7 106 + #define MSM8939_CAL_SEL_SHIFT 0 107 + 51 108 /* eeprom layout data for 8974 */ 52 109 #define BASE1_MASK 0xff 53 110 #define S0_P1_MASK 0x3f00 ··· 246 189 return 0; 247 190 } 248 191 192 + static int calibrate_8939(struct tsens_priv *priv) 193 + { 194 + int base0 = 0, base1 = 0, i; 195 + u32 p1[10], p2[10]; 196 + int mode = 0; 197 + u32 *qfprom_cdata; 198 + u32 cdata[6]; 199 + 200 + qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 201 + if (IS_ERR(qfprom_cdata)) 202 + return PTR_ERR(qfprom_cdata); 203 + 204 + /* Mapping between qfprom nvmem and calibration data */ 205 + cdata[0] = qfprom_cdata[12]; 206 + cdata[1] = qfprom_cdata[13]; 207 + cdata[2] = qfprom_cdata[0]; 208 + cdata[3] = qfprom_cdata[1]; 209 + cdata[4] = qfprom_cdata[22]; 210 + cdata[5] = qfprom_cdata[21]; 211 + 212 + mode = (cdata[0] & MSM8939_CAL_SEL_MASK) >> MSM8939_CAL_SEL_SHIFT; 213 + dev_dbg(priv->dev, "calibration mode is %d\n", mode); 214 + 215 + switch (mode) { 216 + case TWO_PT_CALIB: 217 + base1 = (cdata[3] & MSM8939_BASE1_MASK) >> MSM8939_BASE1_SHIFT; 218 + p2[0] = (cdata[0] & MSM8939_S0_P2_MASK) >> MSM8939_S0_P2_SHIFT; 219 + p2[1] = (cdata[0] & MSM8939_S1_P2_MASK) >> MSM8939_S1_P2_SHIFT; 220 + p2[2] = (cdata[1] & MSM8939_S2_P2_MASK) >> MSM8939_S2_P2_SHIFT; 221 + p2[3] = (cdata[1] & MSM8939_S3_P2_MASK) >> MSM8939_S3_P2_SHIFT; 222 + p2[4] = (cdata[1] & MSM8939_S4_P2_MASK) >> MSM8939_S4_P2_SHIFT; 223 + p2[5] = (cdata[2] & MSM8939_S5_P2_MASK) >> MSM8939_S5_P2_SHIFT; 224 + p2[6] = (cdata[2] & MSM8939_S6_P2_MASK) >> MSM8939_S6_P2_SHIFT; 225 + p2[7] = (cdata[3] & MSM8939_S7_P2_MASK) >> MSM8939_S7_P2_SHIFT; 226 + p2[8] = (cdata[3] & MSM8939_S8_P2_MASK) >> MSM8939_S8_P2_SHIFT; 227 + p2[9] = (cdata[4] & MSM8939_S9_P2_MASK_0_4) >> MSM8939_S9_P2_SHIFT_0_4; 228 + p2[9] |= ((cdata[5] & MSM8939_S9_P2_MASK_5) >> MSM8939_S9_P2_SHIFT_5) << 5; 229 + for (i = 0; i < priv->num_sensors; i++) 230 + p2[i] = (base1 + p2[i]) << 2; 231 + fallthrough; 232 + case ONE_PT_CALIB2: 233 + base0 = (cdata[2] & MSM8939_BASE0_MASK) >> MSM8939_BASE0_SHIFT; 234 + p1[0] = (cdata[0] & MSM8939_S0_P1_MASK) >> MSM8939_S0_P1_SHIFT; 235 + p1[1] = (cdata[0] & MSM8939_S1_P1_MASK) >> MSM8939_S1_P1_SHIFT; 236 + p1[2] = (cdata[0] & MSM8939_S2_P1_MASK_0_4) >> MSM8939_S2_P1_SHIFT_0_4; 237 + p1[2] |= ((cdata[1] & MSM8939_S2_P1_MASK_5) >> MSM8939_S2_P1_SHIFT_5) << 5; 238 + p1[3] = (cdata[1] & MSM8939_S3_P1_MASK) >> MSM8939_S3_P1_SHIFT; 239 + p1[4] = (cdata[1] & MSM8939_S4_P1_MASK) >> MSM8939_S4_P1_SHIFT; 240 + p1[5] = (cdata[2] & MSM8939_S5_P1_MASK) >> MSM8939_S5_P1_SHIFT; 241 + p1[6] = (cdata[2] & MSM8939_S6_P1_MASK) >> MSM8939_S6_P1_SHIFT; 242 + p1[7] = (cdata[3] & MSM8939_S7_P1_MASK) >> MSM8939_S7_P1_SHIFT; 243 + p1[8] = (cdata[3] & MSM8939_S8_P1_MASK) >> MSM8939_S8_P1_SHIFT; 244 + p1[9] = (cdata[4] & MSM8939_S9_P1_MASK) >> MSM8939_S9_P1_SHIFT; 245 + for (i = 0; i < priv->num_sensors; i++) 246 + p1[i] = ((base0) + p1[i]) << 2; 247 + break; 248 + default: 249 + for (i = 0; i < priv->num_sensors; i++) { 250 + p1[i] = 500; 251 + p2[i] = 780; 252 + } 253 + break; 254 + } 255 + 256 + compute_intercept_slope(priv, p1, p2, mode); 257 + kfree(qfprom_cdata); 258 + 259 + return 0; 260 + } 261 + 249 262 static int calibrate_8974(struct tsens_priv *priv) 250 263 { 251 264 int base1 = 0, base2 = 0, i; ··· 452 325 return 0; 453 326 } 454 327 455 - /* v0.1: 8916, 8974 */ 328 + /* v0.1: 8916, 8939, 8974 */ 456 329 457 330 static struct tsens_features tsens_v0_1_feat = { 458 331 .ver_major = VER_0_1, ··· 508 381 .num_sensors = 5, 509 382 .ops = &ops_8916, 510 383 .hw_ids = (unsigned int []){0, 1, 2, 4, 5 }, 384 + 385 + .feat = &tsens_v0_1_feat, 386 + .fields = tsens_v0_1_regfields, 387 + }; 388 + 389 + static const struct tsens_ops ops_8939 = { 390 + .init = init_common, 391 + .calibrate = calibrate_8939, 392 + .get_temp = get_temp_common, 393 + }; 394 + 395 + struct tsens_plat_data data_8939 = { 396 + .num_sensors = 10, 397 + .ops = &ops_8939, 398 + .hw_ids = (unsigned int []){ 0, 1, 2, 4, 5, 6, 7, 8, 9, 10 }, 511 399 512 400 .feat = &tsens_v0_1_feat, 513 401 .fields = tsens_v0_1_regfields,
+3
drivers/thermal/qcom/tsens.c
··· 898 898 .compatible = "qcom,msm8916-tsens", 899 899 .data = &data_8916, 900 900 }, { 901 + .compatible = "qcom,msm8939-tsens", 902 + .data = &data_8939, 903 + }, { 901 904 .compatible = "qcom,msm8974-tsens", 902 905 .data = &data_8974, 903 906 }, {
+1 -1
drivers/thermal/qcom/tsens.h
··· 585 585 extern struct tsens_plat_data data_8960; 586 586 587 587 /* TSENS v0.1 targets */ 588 - extern struct tsens_plat_data data_8916, data_8974; 588 + extern struct tsens_plat_data data_8916, data_8939, data_8974; 589 589 590 590 /* TSENS v1 targets */ 591 591 extern struct tsens_plat_data data_tsens_v1, data_8976;
+7 -3
drivers/thermal/rcar_gen3_thermal.c
··· 63 63 #define TSC_MAX_NUM 3 64 64 65 65 /* default THCODE values if FUSEs are missing */ 66 - static const int thcode[TSC_MAX_NUM][3] = { 66 + static const int thcodes[TSC_MAX_NUM][3] = { 67 67 { 3397, 2800, 2221 }, 68 68 { 3393, 2795, 2216 }, 69 69 { 3389, 2805, 2237 }, ··· 172 172 /* Read register and convert to mili Celsius */ 173 173 reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK; 174 174 175 - if (reg <= thcode[tsc->id][1]) 175 + if (reg <= thcodes[tsc->id][1]) 176 176 val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, 177 177 tsc->coef.a1); 178 178 else ··· 315 315 .data = &rcar_gen3_ths_tj_1, 316 316 }, 317 317 { 318 + .compatible = "renesas,r8a774e1-thermal", 319 + .data = &rcar_gen3_ths_tj_1, 320 + }, 321 + { 318 322 .compatible = "renesas,r8a7795-thermal", 319 323 .data = &rcar_gen3_ths_tj_1, 320 324 }, ··· 434 430 priv->tscs[i] = tsc; 435 431 436 432 priv->thermal_init(tsc); 437 - rcar_gen3_thermal_calc_coefs(tsc, ptat, thcode[i], 433 + rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i], 438 434 *rcar_gen3_ths_tj_1); 439 435 440 436 zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
+8 -1
drivers/thermal/rcar_thermal.c
··· 550 550 priv->zone = devm_thermal_zone_of_sensor_register( 551 551 dev, i, priv, 552 552 &rcar_thermal_zone_of_ops); 553 - else 553 + else { 554 554 priv->zone = thermal_zone_device_register( 555 555 "rcar_thermal", 556 556 1, 0, priv, 557 557 &rcar_thermal_zone_ops, NULL, 0, 558 558 idle); 559 + 560 + ret = thermal_zone_device_enable(priv->zone); 561 + if (ret) { 562 + thermal_zone_device_unregister(priv->zone); 563 + priv->zone = ERR_PTR(ret); 564 + } 565 + } 559 566 if (IS_ERR(priv->zone)) { 560 567 dev_err(dev, "can't register thermal zone\n"); 561 568 ret = PTR_ERR(priv->zone);
+4 -2
drivers/thermal/rockchip_thermal.c
··· 1068 1068 { 1069 1069 struct thermal_zone_device *tzd = sensor->tzd; 1070 1070 1071 - tzd->ops->set_mode(tzd, 1072 - on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); 1071 + if (on) 1072 + thermal_zone_device_enable(tzd); 1073 + else 1074 + thermal_zone_device_disable(tzd); 1073 1075 } 1074 1076 1075 1077 static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
+7
drivers/thermal/spear_thermal.c
··· 131 131 ret = PTR_ERR(spear_thermal); 132 132 goto disable_clk; 133 133 } 134 + ret = thermal_zone_device_enable(spear_thermal); 135 + if (ret) { 136 + dev_err(&pdev->dev, "Cannot enable thermal zone\n"); 137 + goto unregister_tzd; 138 + } 134 139 135 140 platform_set_drvdata(pdev, spear_thermal); 136 141 ··· 144 139 145 140 return 0; 146 141 142 + unregister_tzd: 143 + thermal_zone_device_unregister(spear_thermal); 147 144 disable_clk: 148 145 clk_disable(stdev->clk); 149 146
+4 -2
drivers/thermal/sprd_thermal.c
··· 322 322 { 323 323 struct thermal_zone_device *tzd = sen->tzd; 324 324 325 - tzd->ops->set_mode(tzd, 326 - on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); 325 + if (on) 326 + thermal_zone_device_enable(tzd); 327 + else 328 + thermal_zone_device_disable(tzd); 327 329 } 328 330 329 331 static int sprd_thm_probe(struct platform_device *pdev)
+5
drivers/thermal/st/st_thermal.c
··· 246 246 ret = PTR_ERR(sensor->thermal_dev); 247 247 goto sensor_off; 248 248 } 249 + ret = thermal_zone_device_enable(sensor->thermal_dev); 250 + if (ret) 251 + goto tzd_unregister; 249 252 250 253 platform_set_drvdata(pdev, sensor); 251 254 252 255 return 0; 253 256 257 + tzd_unregister: 258 + thermal_zone_device_unregister(sensor->thermal_dev); 254 259 sensor_off: 255 260 st_thermal_sensor_off(sensor); 256 261
+165 -9
drivers/thermal/thermal_core.c
··· 215 215 mutex_unlock(&tz->lock); 216 216 mutex_unlock(&thermal_governor_lock); 217 217 218 + thermal_notify_tz_gov_change(tz->id, policy); 219 + 218 220 return ret; 219 221 } 220 222 ··· 303 301 cancel_delayed_work(&tz->poll_queue); 304 302 } 305 303 304 + static inline bool should_stop_polling(struct thermal_zone_device *tz) 305 + { 306 + return !thermal_zone_device_is_enabled(tz); 307 + } 308 + 306 309 static void monitor_thermal_zone(struct thermal_zone_device *tz) 307 310 { 311 + bool stop; 312 + 313 + stop = should_stop_polling(tz); 314 + 308 315 mutex_lock(&tz->lock); 309 316 310 - if (tz->passive) 317 + if (!stop && tz->passive) 311 318 thermal_zone_device_set_polling(tz, tz->passive_delay); 312 - else if (tz->polling_delay) 319 + else if (!stop && tz->polling_delay) 313 320 thermal_zone_device_set_polling(tz, tz->polling_delay); 314 321 else 315 322 thermal_zone_device_set_polling(tz, 0); ··· 417 406 static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) 418 407 { 419 408 enum thermal_trip_type type; 409 + int trip_temp, hyst = 0; 420 410 421 411 /* Ignore disabled trip points */ 422 412 if (test_bit(trip, &tz->trips_disabled)) 423 413 return; 424 414 415 + tz->ops->get_trip_temp(tz, trip, &trip_temp); 425 416 tz->ops->get_trip_type(tz, trip, &type); 417 + if (tz->ops->get_trip_hyst) 418 + tz->ops->get_trip_hyst(tz, trip, &hyst); 419 + 420 + if (tz->last_temperature != THERMAL_TEMP_INVALID) { 421 + if (tz->last_temperature < trip_temp && 422 + tz->temperature >= trip_temp) 423 + thermal_notify_tz_trip_up(tz->id, trip); 424 + if (tz->last_temperature >= trip_temp && 425 + tz->temperature < (trip_temp - hyst)) 426 + thermal_notify_tz_trip_down(tz->id, trip); 427 + } 426 428 427 429 if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) 428 430 handle_critical_trips(tz, trip, type); ··· 467 443 mutex_unlock(&tz->lock); 468 444 469 445 trace_thermal_temperature(tz); 446 + 447 + thermal_genl_sampling_temp(tz->id, temp); 470 448 } 471 449 472 450 static void thermal_zone_device_init(struct thermal_zone_device *tz) ··· 485 459 thermal_zone_device_init(tz); 486 460 } 487 461 462 + static int thermal_zone_device_set_mode(struct thermal_zone_device *tz, 463 + enum thermal_device_mode mode) 464 + { 465 + int ret = 0; 466 + 467 + mutex_lock(&tz->lock); 468 + 469 + /* do nothing if mode isn't changing */ 470 + if (mode == tz->mode) { 471 + mutex_unlock(&tz->lock); 472 + 473 + return ret; 474 + } 475 + 476 + if (tz->ops->change_mode) 477 + ret = tz->ops->change_mode(tz, mode); 478 + 479 + if (!ret) 480 + tz->mode = mode; 481 + 482 + mutex_unlock(&tz->lock); 483 + 484 + thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 485 + 486 + if (mode == THERMAL_DEVICE_ENABLED) 487 + thermal_notify_tz_enable(tz->id); 488 + else 489 + thermal_notify_tz_disable(tz->id); 490 + 491 + return ret; 492 + } 493 + 494 + int thermal_zone_device_enable(struct thermal_zone_device *tz) 495 + { 496 + return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_ENABLED); 497 + } 498 + EXPORT_SYMBOL_GPL(thermal_zone_device_enable); 499 + 500 + int thermal_zone_device_disable(struct thermal_zone_device *tz) 501 + { 502 + return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_DISABLED); 503 + } 504 + EXPORT_SYMBOL_GPL(thermal_zone_device_disable); 505 + 506 + int thermal_zone_device_is_enabled(struct thermal_zone_device *tz) 507 + { 508 + enum thermal_device_mode mode; 509 + 510 + mutex_lock(&tz->lock); 511 + 512 + mode = tz->mode; 513 + 514 + mutex_unlock(&tz->lock); 515 + 516 + return mode == THERMAL_DEVICE_ENABLED; 517 + } 518 + 488 519 void thermal_zone_device_update(struct thermal_zone_device *tz, 489 520 enum thermal_notify_event event) 490 521 { 491 522 int count; 523 + 524 + if (should_stop_polling(tz)) 525 + return; 492 526 493 527 if (atomic_read(&in_suspend)) 494 528 return; ··· 701 615 THERMAL_WEIGHT_DEFAULT); 702 616 } 703 617 mutex_unlock(&thermal_list_lock); 618 + } 619 + 620 + int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), 621 + void *data) 622 + { 623 + struct thermal_governor *gov; 624 + int ret = 0; 625 + 626 + mutex_lock(&thermal_governor_lock); 627 + list_for_each_entry(gov, &thermal_governor_list, governor_list) { 628 + ret = cb(gov, data); 629 + if (ret) 630 + break; 631 + } 632 + mutex_unlock(&thermal_governor_lock); 633 + 634 + return ret; 635 + } 636 + 637 + int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, 638 + void *), void *data) 639 + { 640 + struct thermal_cooling_device *cdev; 641 + int ret = 0; 642 + 643 + mutex_lock(&thermal_list_lock); 644 + list_for_each_entry(cdev, &thermal_cdev_list, node) { 645 + ret = cb(cdev, data); 646 + if (ret) 647 + break; 648 + } 649 + mutex_unlock(&thermal_list_lock); 650 + 651 + return ret; 652 + } 653 + 654 + int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *), 655 + void *data) 656 + { 657 + struct thermal_zone_device *tz; 658 + int ret = 0; 659 + 660 + mutex_lock(&thermal_list_lock); 661 + list_for_each_entry(tz, &thermal_tz_list, node) { 662 + ret = cb(tz, data); 663 + if (ret) 664 + break; 665 + } 666 + mutex_unlock(&thermal_list_lock); 667 + 668 + return ret; 669 + } 670 + 671 + struct thermal_zone_device *thermal_zone_get_by_id(int id) 672 + { 673 + struct thermal_zone_device *tz, *match = NULL; 674 + 675 + mutex_lock(&thermal_list_lock); 676 + list_for_each_entry(tz, &thermal_tz_list, node) { 677 + if (tz->id == id) { 678 + match = tz; 679 + break; 680 + } 681 + } 682 + mutex_unlock(&thermal_list_lock); 683 + 684 + return match; 704 685 } 705 686 706 687 void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz, ··· 1493 1340 if (atomic_cmpxchg(&tz->need_update, 1, 0)) 1494 1341 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 1495 1342 1343 + thermal_notify_tz_create(tz->id, tz->type); 1344 + 1496 1345 return tz; 1497 1346 1498 1347 unregister: ··· 1566 1411 ida_destroy(&tz->ida); 1567 1412 mutex_destroy(&tz->lock); 1568 1413 device_unregister(&tz->device); 1414 + 1415 + thermal_notify_tz_delete(tz->id); 1569 1416 } 1570 1417 EXPORT_SYMBOL_GPL(thermal_zone_device_unregister); 1571 1418 ··· 1613 1456 unsigned long mode, void *_unused) 1614 1457 { 1615 1458 struct thermal_zone_device *tz; 1616 - enum thermal_device_mode tz_mode; 1617 1459 1618 1460 switch (mode) { 1619 1461 case PM_HIBERNATION_PREPARE: ··· 1625 1469 case PM_POST_SUSPEND: 1626 1470 atomic_set(&in_suspend, 0); 1627 1471 list_for_each_entry(tz, &thermal_tz_list, node) { 1628 - tz_mode = THERMAL_DEVICE_ENABLED; 1629 - if (tz->ops->get_mode) 1630 - tz->ops->get_mode(tz, &tz_mode); 1631 - 1632 - if (tz_mode == THERMAL_DEVICE_DISABLED) 1472 + if (!thermal_zone_device_is_enabled(tz)) 1633 1473 continue; 1634 1474 1635 1475 thermal_zone_device_init(tz); ··· 1646 1494 static int __init thermal_init(void) 1647 1495 { 1648 1496 int result; 1497 + 1498 + result = thermal_netlink_init(); 1499 + if (result) 1500 + goto error; 1649 1501 1650 1502 mutex_init(&poweroff_lock); 1651 1503 result = thermal_register_governors(); ··· 1683 1527 mutex_destroy(&poweroff_lock); 1684 1528 return result; 1685 1529 } 1686 - core_initcall(thermal_init); 1530 + postcore_initcall(thermal_init);
+15
drivers/thermal/thermal_core.h
··· 12 12 #include <linux/device.h> 13 13 #include <linux/thermal.h> 14 14 15 + #include "thermal_netlink.h" 16 + 15 17 /* Default Thermal Governor */ 16 18 #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE) 17 19 #define DEFAULT_THERMAL_GOVERNOR "step_wise" ··· 42 40 for (__governor = __governor_thermal_table; \ 43 41 __governor < __governor_thermal_table_end; \ 44 42 __governor++) 43 + 44 + int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *), 45 + void *); 46 + 47 + int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, 48 + void *), void *); 49 + 50 + int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), 51 + void *thermal_governor); 52 + 53 + struct thermal_zone_device *thermal_zone_get_by_id(int id); 45 54 46 55 struct thermal_attr { 47 56 struct device_attribute attr; ··· 178 165 return NULL; 179 166 } 180 167 #endif 168 + 169 + int thermal_zone_device_is_enabled(struct thermal_zone_device *tz); 181 170 182 171 #endif /* __THERMAL_CORE_H__ */
+11 -2
drivers/thermal/thermal_helpers.c
··· 175 175 mutex_unlock(&tz->lock); 176 176 } 177 177 178 + static void thermal_cdev_set_cur_state(struct thermal_cooling_device *cdev, 179 + int target) 180 + { 181 + if (cdev->ops->set_cur_state(cdev, target)) 182 + return; 183 + 184 + thermal_notify_cdev_state_update(cdev->id, target); 185 + thermal_cooling_device_stats_update(cdev, target); 186 + } 187 + 178 188 void thermal_cdev_update(struct thermal_cooling_device *cdev) 179 189 { 180 190 struct thermal_instance *instance; ··· 207 197 target = instance->target; 208 198 } 209 199 210 - if (!cdev->ops->set_cur_state(cdev, target)) 211 - thermal_cooling_device_stats_update(cdev, target); 200 + thermal_cdev_set_cur_state(cdev, target); 212 201 213 202 cdev->updated = true; 214 203 mutex_unlock(&cdev->lock);
+647
drivers/thermal/thermal_netlink.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020 Linaro Limited 4 + * 5 + * Author: Daniel Lezcano <daniel.lezcano@linaro.org> 6 + * 7 + * Generic netlink for thermal management framework 8 + */ 9 + #include <linux/module.h> 10 + #include <linux/kernel.h> 11 + #include <net/genetlink.h> 12 + #include <uapi/linux/thermal.h> 13 + 14 + #include "thermal_core.h" 15 + 16 + static const struct genl_multicast_group thermal_genl_mcgrps[] = { 17 + { .name = THERMAL_GENL_SAMPLING_GROUP_NAME, }, 18 + { .name = THERMAL_GENL_EVENT_GROUP_NAME, }, 19 + }; 20 + 21 + static const struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = { 22 + /* Thermal zone */ 23 + [THERMAL_GENL_ATTR_TZ] = { .type = NLA_NESTED }, 24 + [THERMAL_GENL_ATTR_TZ_ID] = { .type = NLA_U32 }, 25 + [THERMAL_GENL_ATTR_TZ_TEMP] = { .type = NLA_U32 }, 26 + [THERMAL_GENL_ATTR_TZ_TRIP] = { .type = NLA_NESTED }, 27 + [THERMAL_GENL_ATTR_TZ_TRIP_ID] = { .type = NLA_U32 }, 28 + [THERMAL_GENL_ATTR_TZ_TRIP_TEMP] = { .type = NLA_U32 }, 29 + [THERMAL_GENL_ATTR_TZ_TRIP_TYPE] = { .type = NLA_U32 }, 30 + [THERMAL_GENL_ATTR_TZ_TRIP_HYST] = { .type = NLA_U32 }, 31 + [THERMAL_GENL_ATTR_TZ_MODE] = { .type = NLA_U32 }, 32 + [THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT] = { .type = NLA_U32 }, 33 + [THERMAL_GENL_ATTR_TZ_NAME] = { .type = NLA_STRING, 34 + .len = THERMAL_NAME_LENGTH }, 35 + /* Governor(s) */ 36 + [THERMAL_GENL_ATTR_TZ_GOV] = { .type = NLA_NESTED }, 37 + [THERMAL_GENL_ATTR_TZ_GOV_NAME] = { .type = NLA_STRING, 38 + .len = THERMAL_NAME_LENGTH }, 39 + /* Cooling devices */ 40 + [THERMAL_GENL_ATTR_CDEV] = { .type = NLA_NESTED }, 41 + [THERMAL_GENL_ATTR_CDEV_ID] = { .type = NLA_U32 }, 42 + [THERMAL_GENL_ATTR_CDEV_CUR_STATE] = { .type = NLA_U32 }, 43 + [THERMAL_GENL_ATTR_CDEV_MAX_STATE] = { .type = NLA_U32 }, 44 + [THERMAL_GENL_ATTR_CDEV_NAME] = { .type = NLA_STRING, 45 + .len = THERMAL_NAME_LENGTH }, 46 + }; 47 + 48 + struct param { 49 + struct nlattr **attrs; 50 + struct sk_buff *msg; 51 + const char *name; 52 + int tz_id; 53 + int cdev_id; 54 + int trip_id; 55 + int trip_temp; 56 + int trip_type; 57 + int trip_hyst; 58 + int temp; 59 + int cdev_state; 60 + int cdev_max_state; 61 + }; 62 + 63 + typedef int (*cb_t)(struct param *); 64 + 65 + static struct genl_family thermal_gnl_family; 66 + 67 + /************************** Sampling encoding *******************************/ 68 + 69 + int thermal_genl_sampling_temp(int id, int temp) 70 + { 71 + struct sk_buff *skb; 72 + void *hdr; 73 + 74 + skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 75 + if (!skb) 76 + return -ENOMEM; 77 + 78 + hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, 79 + THERMAL_GENL_SAMPLING_TEMP); 80 + if (!hdr) 81 + return -EMSGSIZE; 82 + 83 + if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_ID, id)) 84 + goto out_cancel; 85 + 86 + if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_TEMP, temp)) 87 + goto out_cancel; 88 + 89 + genlmsg_end(skb, hdr); 90 + 91 + genlmsg_multicast(&thermal_gnl_family, skb, 0, 0, GFP_KERNEL); 92 + 93 + return 0; 94 + out_cancel: 95 + genlmsg_cancel(skb, hdr); 96 + nlmsg_free(skb); 97 + 98 + return -EMSGSIZE; 99 + } 100 + 101 + /**************************** Event encoding *********************************/ 102 + 103 + static int thermal_genl_event_tz_create(struct param *p) 104 + { 105 + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || 106 + nla_put_string(p->msg, THERMAL_GENL_ATTR_TZ_NAME, p->name)) 107 + return -EMSGSIZE; 108 + 109 + return 0; 110 + } 111 + 112 + static int thermal_genl_event_tz(struct param *p) 113 + { 114 + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id)) 115 + return -EMSGSIZE; 116 + 117 + return 0; 118 + } 119 + 120 + static int thermal_genl_event_tz_trip_up(struct param *p) 121 + { 122 + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || 123 + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id)) 124 + return -EMSGSIZE; 125 + 126 + return 0; 127 + } 128 + 129 + static int thermal_genl_event_tz_trip_add(struct param *p) 130 + { 131 + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || 132 + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id) || 133 + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, p->trip_type) || 134 + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, p->trip_temp) || 135 + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, p->trip_hyst)) 136 + return -EMSGSIZE; 137 + 138 + return 0; 139 + } 140 + 141 + static int thermal_genl_event_tz_trip_delete(struct param *p) 142 + { 143 + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || 144 + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id)) 145 + return -EMSGSIZE; 146 + 147 + return 0; 148 + } 149 + 150 + static int thermal_genl_event_cdev_add(struct param *p) 151 + { 152 + if (nla_put_string(p->msg, THERMAL_GENL_ATTR_CDEV_NAME, 153 + p->name) || 154 + nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, 155 + p->cdev_id) || 156 + nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_MAX_STATE, 157 + p->cdev_max_state)) 158 + return -EMSGSIZE; 159 + 160 + return 0; 161 + } 162 + 163 + static int thermal_genl_event_cdev_delete(struct param *p) 164 + { 165 + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, p->cdev_id)) 166 + return -EMSGSIZE; 167 + 168 + return 0; 169 + } 170 + 171 + static int thermal_genl_event_cdev_state_update(struct param *p) 172 + { 173 + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, 174 + p->cdev_id) || 175 + nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_CUR_STATE, 176 + p->cdev_state)) 177 + return -EMSGSIZE; 178 + 179 + return 0; 180 + } 181 + 182 + static int thermal_genl_event_gov_change(struct param *p) 183 + { 184 + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || 185 + nla_put_string(p->msg, THERMAL_GENL_ATTR_GOV_NAME, p->name)) 186 + return -EMSGSIZE; 187 + 188 + return 0; 189 + } 190 + 191 + int thermal_genl_event_tz_delete(struct param *p) 192 + __attribute__((alias("thermal_genl_event_tz"))); 193 + 194 + int thermal_genl_event_tz_enable(struct param *p) 195 + __attribute__((alias("thermal_genl_event_tz"))); 196 + 197 + int thermal_genl_event_tz_disable(struct param *p) 198 + __attribute__((alias("thermal_genl_event_tz"))); 199 + 200 + int thermal_genl_event_tz_trip_down(struct param *p) 201 + __attribute__((alias("thermal_genl_event_tz_trip_up"))); 202 + 203 + int thermal_genl_event_tz_trip_change(struct param *p) 204 + __attribute__((alias("thermal_genl_event_tz_trip_add"))); 205 + 206 + static cb_t event_cb[] = { 207 + [THERMAL_GENL_EVENT_TZ_CREATE] = thermal_genl_event_tz_create, 208 + [THERMAL_GENL_EVENT_TZ_DELETE] = thermal_genl_event_tz_delete, 209 + [THERMAL_GENL_EVENT_TZ_ENABLE] = thermal_genl_event_tz_enable, 210 + [THERMAL_GENL_EVENT_TZ_DISABLE] = thermal_genl_event_tz_disable, 211 + [THERMAL_GENL_EVENT_TZ_TRIP_UP] = thermal_genl_event_tz_trip_up, 212 + [THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = thermal_genl_event_tz_trip_down, 213 + [THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = thermal_genl_event_tz_trip_change, 214 + [THERMAL_GENL_EVENT_TZ_TRIP_ADD] = thermal_genl_event_tz_trip_add, 215 + [THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = thermal_genl_event_tz_trip_delete, 216 + [THERMAL_GENL_EVENT_CDEV_ADD] = thermal_genl_event_cdev_add, 217 + [THERMAL_GENL_EVENT_CDEV_DELETE] = thermal_genl_event_cdev_delete, 218 + [THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = thermal_genl_event_cdev_state_update, 219 + [THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = thermal_genl_event_gov_change, 220 + }; 221 + 222 + /* 223 + * Generic netlink event encoding 224 + */ 225 + static int thermal_genl_send_event(enum thermal_genl_event event, 226 + struct param *p) 227 + { 228 + struct sk_buff *msg; 229 + int ret = -EMSGSIZE; 230 + void *hdr; 231 + 232 + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 233 + if (!msg) 234 + return -ENOMEM; 235 + p->msg = msg; 236 + 237 + hdr = genlmsg_put(msg, 0, 0, &thermal_gnl_family, 0, event); 238 + if (!hdr) 239 + goto out_free_msg; 240 + 241 + ret = event_cb[event](p); 242 + if (ret) 243 + goto out_cancel_msg; 244 + 245 + genlmsg_end(msg, hdr); 246 + 247 + genlmsg_multicast(&thermal_gnl_family, msg, 0, 1, GFP_KERNEL); 248 + 249 + return 0; 250 + 251 + out_cancel_msg: 252 + genlmsg_cancel(msg, hdr); 253 + out_free_msg: 254 + nlmsg_free(msg); 255 + 256 + return ret; 257 + } 258 + 259 + int thermal_notify_tz_create(int tz_id, const char *name) 260 + { 261 + struct param p = { .tz_id = tz_id, .name = name }; 262 + 263 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_CREATE, &p); 264 + } 265 + 266 + int thermal_notify_tz_delete(int tz_id) 267 + { 268 + struct param p = { .tz_id = tz_id }; 269 + 270 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DELETE, &p); 271 + } 272 + 273 + int thermal_notify_tz_enable(int tz_id) 274 + { 275 + struct param p = { .tz_id = tz_id }; 276 + 277 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_ENABLE, &p); 278 + } 279 + 280 + int thermal_notify_tz_disable(int tz_id) 281 + { 282 + struct param p = { .tz_id = tz_id }; 283 + 284 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DISABLE, &p); 285 + } 286 + 287 + int thermal_notify_tz_trip_down(int tz_id, int trip_id) 288 + { 289 + struct param p = { .tz_id = tz_id, .trip_id = trip_id }; 290 + 291 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DOWN, &p); 292 + } 293 + 294 + int thermal_notify_tz_trip_up(int tz_id, int trip_id) 295 + { 296 + struct param p = { .tz_id = tz_id, .trip_id = trip_id }; 297 + 298 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_UP, &p); 299 + } 300 + 301 + int thermal_notify_tz_trip_add(int tz_id, int trip_id, int trip_type, 302 + int trip_temp, int trip_hyst) 303 + { 304 + struct param p = { .tz_id = tz_id, .trip_id = trip_id, 305 + .trip_type = trip_type, .trip_temp = trip_temp, 306 + .trip_hyst = trip_hyst }; 307 + 308 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_ADD, &p); 309 + } 310 + 311 + int thermal_notify_tz_trip_delete(int tz_id, int trip_id) 312 + { 313 + struct param p = { .tz_id = tz_id, .trip_id = trip_id }; 314 + 315 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DELETE, &p); 316 + } 317 + 318 + int thermal_notify_tz_trip_change(int tz_id, int trip_id, int trip_type, 319 + int trip_temp, int trip_hyst) 320 + { 321 + struct param p = { .tz_id = tz_id, .trip_id = trip_id, 322 + .trip_type = trip_type, .trip_temp = trip_temp, 323 + .trip_hyst = trip_hyst }; 324 + 325 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_CHANGE, &p); 326 + } 327 + 328 + int thermal_notify_cdev_state_update(int cdev_id, int cdev_state) 329 + { 330 + struct param p = { .cdev_id = cdev_id, .cdev_state = cdev_state }; 331 + 332 + return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_STATE_UPDATE, &p); 333 + } 334 + 335 + int thermal_notify_cdev_add(int cdev_id, const char *name, int cdev_max_state) 336 + { 337 + struct param p = { .cdev_id = cdev_id, .name = name, 338 + .cdev_max_state = cdev_max_state }; 339 + 340 + return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_ADD, &p); 341 + } 342 + 343 + int thermal_notify_cdev_delete(int cdev_id) 344 + { 345 + struct param p = { .cdev_id = cdev_id }; 346 + 347 + return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_DELETE, &p); 348 + } 349 + 350 + int thermal_notify_tz_gov_change(int tz_id, const char *name) 351 + { 352 + struct param p = { .tz_id = tz_id, .name = name }; 353 + 354 + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_GOV_CHANGE, &p); 355 + } 356 + 357 + /*************************** Command encoding ********************************/ 358 + 359 + static int __thermal_genl_cmd_tz_get_id(struct thermal_zone_device *tz, 360 + void *data) 361 + { 362 + struct sk_buff *msg = data; 363 + 364 + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, tz->id) || 365 + nla_put_string(msg, THERMAL_GENL_ATTR_TZ_NAME, tz->type)) 366 + return -EMSGSIZE; 367 + 368 + return 0; 369 + } 370 + 371 + static int thermal_genl_cmd_tz_get_id(struct param *p) 372 + { 373 + struct sk_buff *msg = p->msg; 374 + struct nlattr *start_tz; 375 + int ret; 376 + 377 + start_tz = nla_nest_start(msg, THERMAL_GENL_ATTR_TZ); 378 + if (!start_tz) 379 + return -EMSGSIZE; 380 + 381 + ret = for_each_thermal_zone(__thermal_genl_cmd_tz_get_id, msg); 382 + if (ret) 383 + goto out_cancel_nest; 384 + 385 + nla_nest_end(msg, start_tz); 386 + 387 + return 0; 388 + 389 + out_cancel_nest: 390 + nla_nest_cancel(msg, start_tz); 391 + 392 + return ret; 393 + } 394 + 395 + static int thermal_genl_cmd_tz_get_trip(struct param *p) 396 + { 397 + struct sk_buff *msg = p->msg; 398 + struct thermal_zone_device *tz; 399 + struct nlattr *start_trip; 400 + int i, id; 401 + 402 + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) 403 + return -EINVAL; 404 + 405 + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); 406 + 407 + tz = thermal_zone_get_by_id(id); 408 + if (!tz) 409 + return -EINVAL; 410 + 411 + start_trip = nla_nest_start(msg, THERMAL_GENL_ATTR_TZ_TRIP); 412 + if (!start_trip) 413 + return -EMSGSIZE; 414 + 415 + mutex_lock(&tz->lock); 416 + 417 + for (i = 0; i < tz->trips; i++) { 418 + 419 + enum thermal_trip_type type; 420 + int temp, hyst; 421 + 422 + tz->ops->get_trip_type(tz, i, &type); 423 + tz->ops->get_trip_temp(tz, i, &temp); 424 + tz->ops->get_trip_hyst(tz, i, &hyst); 425 + 426 + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, i) || 427 + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, type) || 428 + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, temp) || 429 + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, hyst)) 430 + goto out_cancel_nest; 431 + } 432 + 433 + mutex_unlock(&tz->lock); 434 + 435 + nla_nest_end(msg, start_trip); 436 + 437 + return 0; 438 + 439 + out_cancel_nest: 440 + mutex_unlock(&tz->lock); 441 + 442 + return -EMSGSIZE; 443 + } 444 + 445 + static int thermal_genl_cmd_tz_get_temp(struct param *p) 446 + { 447 + struct sk_buff *msg = p->msg; 448 + struct thermal_zone_device *tz; 449 + int temp, ret, id; 450 + 451 + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) 452 + return -EINVAL; 453 + 454 + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); 455 + 456 + tz = thermal_zone_get_by_id(id); 457 + if (!tz) 458 + return -EINVAL; 459 + 460 + ret = thermal_zone_get_temp(tz, &temp); 461 + if (ret) 462 + return ret; 463 + 464 + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id) || 465 + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TEMP, temp)) 466 + return -EMSGSIZE; 467 + 468 + return 0; 469 + } 470 + 471 + static int thermal_genl_cmd_tz_get_gov(struct param *p) 472 + { 473 + struct sk_buff *msg = p->msg; 474 + struct thermal_zone_device *tz; 475 + int id, ret = 0; 476 + 477 + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) 478 + return -EINVAL; 479 + 480 + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); 481 + 482 + tz = thermal_zone_get_by_id(id); 483 + if (!tz) 484 + return -EINVAL; 485 + 486 + mutex_lock(&tz->lock); 487 + 488 + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id) || 489 + nla_put_string(msg, THERMAL_GENL_ATTR_TZ_GOV_NAME, 490 + tz->governor->name)) 491 + ret = -EMSGSIZE; 492 + 493 + mutex_unlock(&tz->lock); 494 + 495 + return ret; 496 + } 497 + 498 + static int __thermal_genl_cmd_cdev_get(struct thermal_cooling_device *cdev, 499 + void *data) 500 + { 501 + struct sk_buff *msg = data; 502 + 503 + if (nla_put_u32(msg, THERMAL_GENL_ATTR_CDEV_ID, cdev->id)) 504 + return -EMSGSIZE; 505 + 506 + if (nla_put_string(msg, THERMAL_GENL_ATTR_CDEV_NAME, cdev->type)) 507 + return -EMSGSIZE; 508 + 509 + return 0; 510 + } 511 + 512 + static int thermal_genl_cmd_cdev_get(struct param *p) 513 + { 514 + struct sk_buff *msg = p->msg; 515 + struct nlattr *start_cdev; 516 + int ret; 517 + 518 + start_cdev = nla_nest_start(msg, THERMAL_GENL_ATTR_CDEV); 519 + if (!start_cdev) 520 + return -EMSGSIZE; 521 + 522 + ret = for_each_thermal_cooling_device(__thermal_genl_cmd_cdev_get, msg); 523 + if (ret) 524 + goto out_cancel_nest; 525 + 526 + nla_nest_end(msg, start_cdev); 527 + 528 + return 0; 529 + out_cancel_nest: 530 + nla_nest_cancel(msg, start_cdev); 531 + 532 + return ret; 533 + } 534 + 535 + static cb_t cmd_cb[] = { 536 + [THERMAL_GENL_CMD_TZ_GET_ID] = thermal_genl_cmd_tz_get_id, 537 + [THERMAL_GENL_CMD_TZ_GET_TRIP] = thermal_genl_cmd_tz_get_trip, 538 + [THERMAL_GENL_CMD_TZ_GET_TEMP] = thermal_genl_cmd_tz_get_temp, 539 + [THERMAL_GENL_CMD_TZ_GET_GOV] = thermal_genl_cmd_tz_get_gov, 540 + [THERMAL_GENL_CMD_CDEV_GET] = thermal_genl_cmd_cdev_get, 541 + }; 542 + 543 + static int thermal_genl_cmd_dumpit(struct sk_buff *skb, 544 + struct netlink_callback *cb) 545 + { 546 + struct param p = { .msg = skb }; 547 + const struct genl_dumpit_info *info = genl_dumpit_info(cb); 548 + int cmd = info->ops->cmd; 549 + int ret; 550 + void *hdr; 551 + 552 + hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, cmd); 553 + if (!hdr) 554 + return -EMSGSIZE; 555 + 556 + ret = cmd_cb[cmd](&p); 557 + if (ret) 558 + goto out_cancel_msg; 559 + 560 + genlmsg_end(skb, hdr); 561 + 562 + return 0; 563 + 564 + out_cancel_msg: 565 + genlmsg_cancel(skb, hdr); 566 + 567 + return ret; 568 + } 569 + 570 + static int thermal_genl_cmd_doit(struct sk_buff *skb, 571 + struct genl_info *info) 572 + { 573 + struct param p = { .attrs = info->attrs }; 574 + struct sk_buff *msg; 575 + void *hdr; 576 + int cmd = info->genlhdr->cmd; 577 + int ret = -EMSGSIZE; 578 + 579 + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 580 + if (!msg) 581 + return -ENOMEM; 582 + p.msg = msg; 583 + 584 + hdr = genlmsg_put_reply(msg, info, &thermal_gnl_family, 0, cmd); 585 + if (!hdr) 586 + goto out_free_msg; 587 + 588 + ret = cmd_cb[cmd](&p); 589 + if (ret) 590 + goto out_cancel_msg; 591 + 592 + genlmsg_end(msg, hdr); 593 + 594 + return genlmsg_reply(msg, info); 595 + 596 + out_cancel_msg: 597 + genlmsg_cancel(msg, hdr); 598 + out_free_msg: 599 + nlmsg_free(msg); 600 + 601 + return ret; 602 + } 603 + 604 + static const struct genl_ops thermal_genl_ops[] = { 605 + { 606 + .cmd = THERMAL_GENL_CMD_TZ_GET_ID, 607 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 608 + .dumpit = thermal_genl_cmd_dumpit, 609 + }, 610 + { 611 + .cmd = THERMAL_GENL_CMD_TZ_GET_TRIP, 612 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 613 + .doit = thermal_genl_cmd_doit, 614 + }, 615 + { 616 + .cmd = THERMAL_GENL_CMD_TZ_GET_TEMP, 617 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 618 + .doit = thermal_genl_cmd_doit, 619 + }, 620 + { 621 + .cmd = THERMAL_GENL_CMD_TZ_GET_GOV, 622 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 623 + .doit = thermal_genl_cmd_doit, 624 + }, 625 + { 626 + .cmd = THERMAL_GENL_CMD_CDEV_GET, 627 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 628 + .dumpit = thermal_genl_cmd_dumpit, 629 + }, 630 + }; 631 + 632 + static struct genl_family thermal_gnl_family __ro_after_init = { 633 + .hdrsize = 0, 634 + .name = THERMAL_GENL_FAMILY_NAME, 635 + .version = THERMAL_GENL_VERSION, 636 + .maxattr = THERMAL_GENL_ATTR_MAX, 637 + .policy = thermal_genl_policy, 638 + .ops = thermal_genl_ops, 639 + .n_ops = ARRAY_SIZE(thermal_genl_ops), 640 + .mcgrps = thermal_genl_mcgrps, 641 + .n_mcgrps = ARRAY_SIZE(thermal_genl_mcgrps), 642 + }; 643 + 644 + int __init thermal_netlink_init(void) 645 + { 646 + return genl_register_family(&thermal_gnl_family); 647 + }
+104
drivers/thermal/thermal_netlink.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) Linaro Ltd 2020 4 + * Author: Daniel Lezcano <daniel.lezcano@linaro.org> 5 + */ 6 + 7 + /* Netlink notification function */ 8 + #ifdef CONFIG_THERMAL_NETLINK 9 + int __init thermal_netlink_init(void); 10 + int thermal_notify_tz_create(int tz_id, const char *name); 11 + int thermal_notify_tz_delete(int tz_id); 12 + int thermal_notify_tz_enable(int tz_id); 13 + int thermal_notify_tz_disable(int tz_id); 14 + int thermal_notify_tz_trip_down(int tz_id, int id); 15 + int thermal_notify_tz_trip_up(int tz_id, int id); 16 + int thermal_notify_tz_trip_delete(int tz_id, int id); 17 + int thermal_notify_tz_trip_add(int tz_id, int id, int type, 18 + int temp, int hyst); 19 + int thermal_notify_tz_trip_change(int tz_id, int id, int type, 20 + int temp, int hyst); 21 + int thermal_notify_cdev_state_update(int cdev_id, int state); 22 + int thermal_notify_cdev_add(int cdev_id, const char *name, int max_state); 23 + int thermal_notify_cdev_delete(int cdev_id); 24 + int thermal_notify_tz_gov_change(int tz_id, const char *name); 25 + int thermal_genl_sampling_temp(int id, int temp); 26 + #else 27 + static inline int thermal_netlink_init(void) 28 + { 29 + return 0; 30 + } 31 + 32 + static inline int thermal_notify_tz_create(int tz_id, const char *name) 33 + { 34 + return 0; 35 + } 36 + 37 + static inline int thermal_notify_tz_delete(int tz_id) 38 + { 39 + return 0; 40 + } 41 + 42 + static inline int thermal_notify_tz_enable(int tz_id) 43 + { 44 + return 0; 45 + } 46 + 47 + static inline int thermal_notify_tz_disable(int tz_id) 48 + { 49 + return 0; 50 + } 51 + 52 + static inline int thermal_notify_tz_trip_down(int tz_id, int id) 53 + { 54 + return 0; 55 + } 56 + 57 + static inline int thermal_notify_tz_trip_up(int tz_id, int id) 58 + { 59 + return 0; 60 + } 61 + 62 + static inline int thermal_notify_tz_trip_delete(int tz_id, int id) 63 + { 64 + return 0; 65 + } 66 + 67 + static inline int thermal_notify_tz_trip_add(int tz_id, int id, int type, 68 + int temp, int hyst) 69 + { 70 + return 0; 71 + } 72 + 73 + static inline int thermal_notify_tz_trip_change(int tz_id, int id, int type, 74 + int temp, int hyst) 75 + { 76 + return 0; 77 + } 78 + 79 + static inline int thermal_notify_cdev_state_update(int cdev_id, int state) 80 + { 81 + return 0; 82 + } 83 + 84 + static inline int thermal_notify_cdev_add(int cdev_id, const char *name, 85 + int max_state) 86 + { 87 + return 0; 88 + } 89 + 90 + static inline int thermal_notify_cdev_delete(int cdev_id) 91 + { 92 + return 0; 93 + } 94 + 95 + static inline int thermal_notify_tz_gov_change(int tz_id, const char *name) 96 + { 97 + return 0; 98 + } 99 + 100 + static inline int thermal_genl_sampling_temp(int id, int temp) 101 + { 102 + return 0; 103 + } 104 + #endif /* CONFIG_THERMAL_NETLINK */
+1 -40
drivers/thermal/thermal_of.c
··· 51 51 52 52 /** 53 53 * struct __thermal_zone - internal representation of a thermal zone 54 - * @mode: current thermal zone device mode (enabled/disabled) 55 54 * @passive_delay: polling interval while passive cooling is activated 56 55 * @polling_delay: zone polling interval 57 56 * @slope: slope of the temperature adjustment curve ··· 64 65 */ 65 66 66 67 struct __thermal_zone { 67 - enum thermal_device_mode mode; 68 68 int passive_delay; 69 69 int polling_delay; 70 70 int slope; ··· 267 269 return 0; 268 270 } 269 271 270 - static int of_thermal_get_mode(struct thermal_zone_device *tz, 271 - enum thermal_device_mode *mode) 272 - { 273 - struct __thermal_zone *data = tz->devdata; 274 - 275 - *mode = data->mode; 276 - 277 - return 0; 278 - } 279 - 280 - static int of_thermal_set_mode(struct thermal_zone_device *tz, 281 - enum thermal_device_mode mode) 282 - { 283 - struct __thermal_zone *data = tz->devdata; 284 - 285 - mutex_lock(&tz->lock); 286 - 287 - if (mode == THERMAL_DEVICE_ENABLED) { 288 - tz->polling_delay = data->polling_delay; 289 - tz->passive_delay = data->passive_delay; 290 - } else { 291 - tz->polling_delay = 0; 292 - tz->passive_delay = 0; 293 - } 294 - 295 - mutex_unlock(&tz->lock); 296 - 297 - data->mode = mode; 298 - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 299 - 300 - return 0; 301 - } 302 - 303 272 static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip, 304 273 enum thermal_trip_type *type) 305 274 { ··· 358 393 } 359 394 360 395 static struct thermal_zone_device_ops of_thermal_ops = { 361 - .get_mode = of_thermal_get_mode, 362 - .set_mode = of_thermal_set_mode, 363 - 364 396 .get_trip_type = of_thermal_get_trip_type, 365 397 .get_trip_temp = of_thermal_get_trip_temp, 366 398 .set_trip_temp = of_thermal_set_trip_temp, ··· 516 554 tzd = thermal_zone_of_add_sensor(child, sensor_np, 517 555 data, ops); 518 556 if (!IS_ERR(tzd)) 519 - tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED); 557 + thermal_zone_device_enable(tzd); 520 558 521 559 of_node_put(child); 522 560 goto exit; ··· 941 979 942 980 finish: 943 981 of_node_put(child); 944 - tz->mode = THERMAL_DEVICE_DISABLED; 945 982 946 983 return tz; 947 984
+18 -34
drivers/thermal/thermal_sysfs.c
··· 49 49 mode_show(struct device *dev, struct device_attribute *attr, char *buf) 50 50 { 51 51 struct thermal_zone_device *tz = to_thermal_zone(dev); 52 - enum thermal_device_mode mode; 53 - int result; 52 + int enabled = thermal_zone_device_is_enabled(tz); 54 53 55 - if (!tz->ops->get_mode) 56 - return -EPERM; 57 - 58 - result = tz->ops->get_mode(tz, &mode); 59 - if (result) 60 - return result; 61 - 62 - return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled" 63 - : "disabled"); 54 + return sprintf(buf, "%s\n", enabled ? "enabled" : "disabled"); 64 55 } 65 56 66 57 static ssize_t ··· 61 70 struct thermal_zone_device *tz = to_thermal_zone(dev); 62 71 int result; 63 72 64 - if (!tz->ops->set_mode) 65 - return -EPERM; 66 - 67 73 if (!strncmp(buf, "enabled", sizeof("enabled") - 1)) 68 - result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED); 74 + result = thermal_zone_device_enable(tz); 69 75 else if (!strncmp(buf, "disabled", sizeof("disabled") - 1)) 70 - result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED); 76 + result = thermal_zone_device_disable(tz); 71 77 else 72 78 result = -EINVAL; 73 79 ··· 112 124 { 113 125 struct thermal_zone_device *tz = to_thermal_zone(dev); 114 126 int trip, ret; 115 - int temperature; 127 + int temperature, hyst = 0; 128 + enum thermal_trip_type type; 116 129 117 130 if (!tz->ops->set_trip_temp) 118 131 return -EPERM; ··· 127 138 ret = tz->ops->set_trip_temp(tz, trip, temperature); 128 139 if (ret) 129 140 return ret; 141 + 142 + if (tz->ops->get_trip_hyst) { 143 + ret = tz->ops->get_trip_hyst(tz, trip, &hyst); 144 + if (ret) 145 + return ret; 146 + } 147 + 148 + ret = tz->ops->get_trip_type(tz, trip, &type); 149 + if (ret) 150 + return ret; 151 + 152 + thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst); 130 153 131 154 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 132 155 ··· 429 428 .attrs = thermal_zone_dev_attrs, 430 429 }; 431 430 432 - /* We expose mode only if .get_mode is present */ 433 431 static struct attribute *thermal_zone_mode_attrs[] = { 434 432 &dev_attr_mode.attr, 435 433 NULL, 436 434 }; 437 435 438 - static umode_t thermal_zone_mode_is_visible(struct kobject *kobj, 439 - struct attribute *attr, 440 - int attrno) 441 - { 442 - struct device *dev = container_of(kobj, struct device, kobj); 443 - struct thermal_zone_device *tz; 444 - 445 - tz = container_of(dev, struct thermal_zone_device, device); 446 - 447 - if (tz->ops->get_mode) 448 - return attr->mode; 449 - 450 - return 0; 451 - } 452 - 453 436 static struct attribute_group thermal_zone_mode_attribute_group = { 454 437 .attrs = thermal_zone_mode_attrs, 455 - .is_visible = thermal_zone_mode_is_visible, 456 438 }; 457 439 458 440 /* We expose passive only if passive trips are present */
+1 -1
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
··· 169 169 170 170 data = ti_bandgap_get_sensor_data(bgp, id); 171 171 172 - if (!IS_ERR_OR_NULL(data)) 172 + if (IS_ERR_OR_NULL(data)) 173 173 data = ti_thermal_build_data(bgp, id); 174 174 175 175 if (!data)
-57
include/linux/clock_cooling.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* 3 - * linux/include/linux/clock_cooling.h 4 - * 5 - * Copyright (C) 2014 Eduardo Valentin <edubezval@gmail.com> 6 - * 7 - * Copyright (C) 2013 Texas Instruments Inc. 8 - * Contact: Eduardo Valentin <eduardo.valentin@ti.com> 9 - * 10 - * Highly based on cpufreq_cooling.c. 11 - * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) 12 - * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org> 13 - */ 14 - 15 - #ifndef __CPU_COOLING_H__ 16 - #define __CPU_COOLING_H__ 17 - 18 - #include <linux/of.h> 19 - #include <linux/thermal.h> 20 - #include <linux/cpumask.h> 21 - 22 - #ifdef CONFIG_CLOCK_THERMAL 23 - /** 24 - * clock_cooling_register - function to create clock cooling device. 25 - * @dev: struct device pointer to the device used as clock cooling device. 26 - * @clock_name: string containing the clock used as cooling mechanism. 27 - */ 28 - struct thermal_cooling_device * 29 - clock_cooling_register(struct device *dev, const char *clock_name); 30 - 31 - /** 32 - * clock_cooling_unregister - function to remove clock cooling device. 33 - * @cdev: thermal cooling device pointer. 34 - */ 35 - void clock_cooling_unregister(struct thermal_cooling_device *cdev); 36 - 37 - unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, 38 - unsigned long freq); 39 - #else /* !CONFIG_CLOCK_THERMAL */ 40 - static inline struct thermal_cooling_device * 41 - clock_cooling_register(struct device *dev, const char *clock_name) 42 - { 43 - return NULL; 44 - } 45 - static inline 46 - void clock_cooling_unregister(struct thermal_cooling_device *cdev) 47 - { 48 - } 49 - static inline 50 - unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, 51 - unsigned long freq) 52 - { 53 - return THERMAL_CSTATE_INVALID; 54 - } 55 - #endif /* CONFIG_CLOCK_THERMAL */ 56 - 57 - #endif /* __CPU_COOLING_H__ */
+1 -8
include/linux/devfreq_cooling.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 1 2 /* 2 3 * devfreq_cooling: Thermal cooling device implementation for devices using 3 4 * devfreq 4 5 * 5 6 * Copyright (C) 2014-2015 ARM Limited 6 7 * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License version 2 as 9 - * published by the Free Software Foundation. 10 - * 11 - * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12 - * kind, whether express or implied; without even the implied warranty 13 - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 - * GNU General Public License for more details. 15 8 */ 16 9 17 10 #ifndef __DEVFREQ_COOLING_H__
+11 -20
include/linux/thermal.h
··· 37 37 struct thermal_instance; 38 38 struct thermal_attr; 39 39 40 - enum thermal_device_mode { 41 - THERMAL_DEVICE_DISABLED = 0, 42 - THERMAL_DEVICE_ENABLED, 43 - }; 44 - 45 - enum thermal_trip_type { 46 - THERMAL_TRIP_ACTIVE = 0, 47 - THERMAL_TRIP_PASSIVE, 48 - THERMAL_TRIP_HOT, 49 - THERMAL_TRIP_CRITICAL, 50 - }; 51 - 52 40 enum thermal_trend { 53 41 THERMAL_TREND_STABLE, /* temperature is stable */ 54 42 THERMAL_TREND_RAISING, /* temperature is raising */ ··· 64 76 struct thermal_cooling_device *); 65 77 int (*get_temp) (struct thermal_zone_device *, int *); 66 78 int (*set_trips) (struct thermal_zone_device *, int, int); 67 - int (*get_mode) (struct thermal_zone_device *, 68 - enum thermal_device_mode *); 69 - int (*set_mode) (struct thermal_zone_device *, 79 + int (*change_mode) (struct thermal_zone_device *, 70 80 enum thermal_device_mode); 71 81 int (*get_trip_type) (struct thermal_zone_device *, int, 72 82 enum thermal_trip_type *); ··· 114 128 * @trip_temp_attrs: attributes for trip points for sysfs: trip temperature 115 129 * @trip_type_attrs: attributes for trip points for sysfs: trip type 116 130 * @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis 131 + * @mode: current mode of this thermal zone 117 132 * @devdata: private pointer for device private data 118 133 * @trips: number of trip points the thermal zone supports 119 134 * @trips_disabled; bitmap for disabled trips ··· 157 170 struct thermal_attr *trip_temp_attrs; 158 171 struct thermal_attr *trip_type_attrs; 159 172 struct thermal_attr *trip_hyst_attrs; 173 + enum thermal_device_mode mode; 160 174 void *devdata; 161 175 int trips; 162 176 unsigned long trips_disabled; /* bitmap for disabled trips */ ··· 291 303 int offset; 292 304 }; 293 305 294 - struct thermal_genl_event { 295 - u32 orig; 296 - enum events event; 297 - }; 298 - 299 306 /** 300 307 * struct thermal_zone_of_device_ops - scallbacks for handling DT based zones 301 308 * ··· 399 416 400 417 void thermal_cdev_update(struct thermal_cooling_device *); 401 418 void thermal_notify_framework(struct thermal_zone_device *, int); 419 + int thermal_zone_device_enable(struct thermal_zone_device *tz); 420 + int thermal_zone_device_disable(struct thermal_zone_device *tz); 402 421 #else 403 422 static inline struct thermal_zone_device *thermal_zone_device_register( 404 423 const char *type, int trips, int mask, void *devdata, ··· 448 463 static inline void thermal_notify_framework(struct thermal_zone_device *tz, 449 464 int trip) 450 465 { } 466 + 467 + static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) 468 + { return -ENODEV; } 469 + 470 + static inline int thermal_zone_device_disable(struct thermal_zone_device *tz) 471 + { return -ENODEV; } 451 472 #endif /* CONFIG_THERMAL */ 452 473 453 474 #endif /* __THERMAL_H__ */
+72 -17
include/uapi/linux/thermal.h
··· 4 4 5 5 #define THERMAL_NAME_LENGTH 20 6 6 7 - /* Adding event notification support elements */ 8 - #define THERMAL_GENL_FAMILY_NAME "thermal_event" 9 - #define THERMAL_GENL_VERSION 0x01 10 - #define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_grp" 11 - 12 - /* Events supported by Thermal Netlink */ 13 - enum events { 14 - THERMAL_AUX0, 15 - THERMAL_AUX1, 16 - THERMAL_CRITICAL, 17 - THERMAL_DEV_FAULT, 7 + enum thermal_device_mode { 8 + THERMAL_DEVICE_DISABLED = 0, 9 + THERMAL_DEVICE_ENABLED, 18 10 }; 19 11 20 - /* attributes of thermal_genl_family */ 21 - enum { 12 + enum thermal_trip_type { 13 + THERMAL_TRIP_ACTIVE = 0, 14 + THERMAL_TRIP_PASSIVE, 15 + THERMAL_TRIP_HOT, 16 + THERMAL_TRIP_CRITICAL, 17 + }; 18 + 19 + /* Adding event notification support elements */ 20 + #define THERMAL_GENL_FAMILY_NAME "thermal" 21 + #define THERMAL_GENL_VERSION 0x01 22 + #define THERMAL_GENL_SAMPLING_GROUP_NAME "sampling" 23 + #define THERMAL_GENL_EVENT_GROUP_NAME "event" 24 + 25 + /* Attributes of thermal_genl_family */ 26 + enum thermal_genl_attr { 22 27 THERMAL_GENL_ATTR_UNSPEC, 23 - THERMAL_GENL_ATTR_EVENT, 28 + THERMAL_GENL_ATTR_TZ, 29 + THERMAL_GENL_ATTR_TZ_ID, 30 + THERMAL_GENL_ATTR_TZ_TEMP, 31 + THERMAL_GENL_ATTR_TZ_TRIP, 32 + THERMAL_GENL_ATTR_TZ_TRIP_ID, 33 + THERMAL_GENL_ATTR_TZ_TRIP_TYPE, 34 + THERMAL_GENL_ATTR_TZ_TRIP_TEMP, 35 + THERMAL_GENL_ATTR_TZ_TRIP_HYST, 36 + THERMAL_GENL_ATTR_TZ_MODE, 37 + THERMAL_GENL_ATTR_TZ_NAME, 38 + THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT, 39 + THERMAL_GENL_ATTR_TZ_GOV, 40 + THERMAL_GENL_ATTR_TZ_GOV_NAME, 41 + THERMAL_GENL_ATTR_CDEV, 42 + THERMAL_GENL_ATTR_CDEV_ID, 43 + THERMAL_GENL_ATTR_CDEV_CUR_STATE, 44 + THERMAL_GENL_ATTR_CDEV_MAX_STATE, 45 + THERMAL_GENL_ATTR_CDEV_NAME, 46 + THERMAL_GENL_ATTR_GOV_NAME, 47 + 24 48 __THERMAL_GENL_ATTR_MAX, 25 49 }; 26 50 #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1) 27 51 28 - /* commands supported by the thermal_genl_family */ 29 - enum { 52 + enum thermal_genl_sampling { 53 + THERMAL_GENL_SAMPLING_TEMP, 54 + __THERMAL_GENL_SAMPLING_MAX, 55 + }; 56 + #define THERMAL_GENL_SAMPLING_MAX (__THERMAL_GENL_SAMPLING_MAX - 1) 57 + 58 + /* Events of thermal_genl_family */ 59 + enum thermal_genl_event { 60 + THERMAL_GENL_EVENT_UNSPEC, 61 + THERMAL_GENL_EVENT_TZ_CREATE, /* Thermal zone creation */ 62 + THERMAL_GENL_EVENT_TZ_DELETE, /* Thermal zone deletion */ 63 + THERMAL_GENL_EVENT_TZ_DISABLE, /* Thermal zone disabed */ 64 + THERMAL_GENL_EVENT_TZ_ENABLE, /* Thermal zone enabled */ 65 + THERMAL_GENL_EVENT_TZ_TRIP_UP, /* Trip point crossed the way up */ 66 + THERMAL_GENL_EVENT_TZ_TRIP_DOWN, /* Trip point crossed the way down */ 67 + THERMAL_GENL_EVENT_TZ_TRIP_CHANGE, /* Trip point changed */ 68 + THERMAL_GENL_EVENT_TZ_TRIP_ADD, /* Trip point added */ 69 + THERMAL_GENL_EVENT_TZ_TRIP_DELETE, /* Trip point deleted */ 70 + THERMAL_GENL_EVENT_CDEV_ADD, /* Cdev bound to the thermal zone */ 71 + THERMAL_GENL_EVENT_CDEV_DELETE, /* Cdev unbound */ 72 + THERMAL_GENL_EVENT_CDEV_STATE_UPDATE, /* Cdev state updated */ 73 + THERMAL_GENL_EVENT_TZ_GOV_CHANGE, /* Governor policy changed */ 74 + __THERMAL_GENL_EVENT_MAX, 75 + }; 76 + #define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1) 77 + 78 + /* Commands supported by the thermal_genl_family */ 79 + enum thermal_genl_cmd { 30 80 THERMAL_GENL_CMD_UNSPEC, 31 - THERMAL_GENL_CMD_EVENT, 81 + THERMAL_GENL_CMD_TZ_GET_ID, /* List of thermal zones id */ 82 + THERMAL_GENL_CMD_TZ_GET_TRIP, /* List of thermal trips */ 83 + THERMAL_GENL_CMD_TZ_GET_TEMP, /* Get the thermal zone temperature */ 84 + THERMAL_GENL_CMD_TZ_GET_GOV, /* Get the thermal zone governor */ 85 + THERMAL_GENL_CMD_TZ_GET_MODE, /* Get the thermal zone mode */ 86 + THERMAL_GENL_CMD_CDEV_GET, /* List of cdev id */ 32 87 __THERMAL_GENL_CMD_MAX, 33 88 }; 34 89 #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
+1 -1
net/netlink/genetlink.c
··· 1192 1192 panic("GENL: Cannot register controller: %d\n", err); 1193 1193 } 1194 1194 1195 - subsys_initcall(genl_init); 1195 + core_initcall(genl_init); 1196 1196 1197 1197 static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group, 1198 1198 gfp_t flags)