History

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 ...

Linus Torvalds committed 6 years ago

Commit 96e3f3c2 parents ed35832 c569e8075 files · +1632 −1609Browse files

Unified · Split

75 files
  1. Documentation/devicetree/bindings/arm/arm,scmi.txt +1 −1
  2. Documentation/devicetree/bindings/arm/arm,scpi.txt +1 −1
  3. Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt +1 −1
  4. Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt +1 −1
  5. Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +1 −1
  6. Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt +2 −1
  7. Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt +2 −2
  8. Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt +1 −1
  9. Documentation/devicetree/bindings/hwmon/gpio-fan.txt +2 −1
  10. Documentation/devicetree/bindings/hwmon/lm90.txt +2 −2
  11. Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml +1 −1
  12. Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt +1 −1
  13. Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml +1 −1
  14. Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt +1 −1
  15. Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt +1 −1
  16. Documentation/devicetree/bindings/thermal/max77620_thermal.txt +3 −3
  17. Documentation/devicetree/bindings/thermal/mediatek-thermal.txt +1 −1
  18. Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt +6 −4
  19. Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt +1 −1
  20. Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt +1 −1
  21. Documentation/devicetree/bindings/thermal/qcom-tsens.yaml +1 −0
  22. Documentation/devicetree/bindings/thermal/rockchip-thermal.txt +1 −1
  23. Documentation/devicetree/bindings/thermal/tango-thermal.txt +1 −1
  24. Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt +1 −1
  25. Documentation/devicetree/bindings/thermal/thermal.txt +0 −586
  26. MAINTAINERS +8 −0
  27. drivers/acpi/thermal.c +21 −55
  28. drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c +8 −0
  29. drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +17 −74
  30. drivers/net/wireless/intel/iwlwifi/mvm/tt.c +8 −1
  31. drivers/platform/x86/acerhdf.c +13 −20
  32. drivers/platform/x86/intel_mid_thermal.c +6 −0
  33. drivers/power/supply/power_supply_core.c +7 −2
  34. drivers/thermal/Kconfig +10 −10
  35. drivers/thermal/Makefile +3 −3
  36. drivers/thermal/armada_thermal.c +6 −0
  37. drivers/thermal/clock_cooling.c +0 −445
  38. drivers/thermal/da9062-thermal.c +5 −11
  39. drivers/thermal/devfreq_cooling.c +1 −9
  40. drivers/thermal/dove_thermal.c +6 −0
  41. drivers/thermal/gov_power_allocator.c +1 −8
  42. drivers/thermal/hisi_thermal.c +4 −2
  43. drivers/thermal/imx8mm_thermal.c +1 −0
  44. drivers/thermal/imx_thermal.c +19 −41
  45. drivers/thermal/intel/int340x_thermal/int3400_thermal.c +7 −31
  46. drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c +5 −0
  47. drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +1 −1
  48. drivers/thermal/intel/intel_pch_thermal.c +8 −0
  49. drivers/thermal/intel/intel_quark_dts_thermal.c +6 −28
  50. drivers/thermal/intel/intel_soc_dts_iosf.c +3 −0
  51. drivers/thermal/intel/x86_pkg_temp_thermal.c +6 −0
  52. drivers/thermal/kirkwood_thermal.c +7 −0
  53. drivers/thermal/mtk_thermal.c +181 −53
  54. drivers/thermal/qcom/tsens-v0_1.c +143 −1
  55. drivers/thermal/qcom/tsens.c +3 −0
  56. drivers/thermal/qcom/tsens.h +1 −1
  57. drivers/thermal/rcar_gen3_thermal.c +7 −3
  58. drivers/thermal/rcar_thermal.c +8 −1
  59. drivers/thermal/rockchip_thermal.c +4 −2
  60. drivers/thermal/spear_thermal.c +7 −0
  61. drivers/thermal/sprd_thermal.c +4 −2
  62. drivers/thermal/st/st_thermal.c +5 −0
  63. drivers/thermal/thermal_core.c +165 −9
  64. drivers/thermal/thermal_core.h +15 −0
  65. drivers/thermal/thermal_helpers.c +11 −2
  66. drivers/thermal/thermal_netlink.c +647 −0
  67. drivers/thermal/thermal_netlink.h +104 −0
  68. drivers/thermal/thermal_of.c +1 −40
  69. drivers/thermal/thermal_sysfs.c +18 −34
  70. drivers/thermal/ti-soc-thermal/ti-thermal-common.c +1 −1
  71. include/linux/clock_cooling.h +0 −57
  72. include/linux/devfreq_cooling.h +1 −8
  73. include/linux/thermal.h +11 −20
  74. include/uapi/linux/thermal.h +72 −17
  75. net/netlink/genetlink.c +1 −1
Documentation/devicetree/bindings/arm/arm,scmi.txt+1−1
@@ -102,7 +102,7 @@ Required sub-node properties: · 101 unmodified lines
102[0] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html102[0] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html
103[1] Documentation/devicetree/bindings/clock/clock-bindings.txt103[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
104[2] Documentation/devicetree/bindings/power/power-domain.yaml104[2] Documentation/devicetree/bindings/power/power-domain.yaml
105[3] Documentation/devicetree/bindings/thermal/thermal.txt105[3] Documentation/devicetree/bindings/thermal/thermal*.yaml
106[4] Documentation/devicetree/bindings/sram/sram.yaml106[4] Documentation/devicetree/bindings/sram/sram.yaml
107[5] Documentation/devicetree/bindings/reset/reset.txt107[5] Documentation/devicetree/bindings/reset/reset.txt
108 108
Documentation/devicetree/bindings/arm/arm,scpi.txt+1−1
@@ -108,7 +108,7 @@ Required properties: · 107 unmodified lines
108 108
109[0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html109[0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html
110[1] Documentation/devicetree/bindings/clock/clock-bindings.txt110[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
111[2] Documentation/devicetree/bindings/thermal/thermal.txt111[2] Documentation/devicetree/bindings/thermal/thermal*.yaml
112[3] Documentation/devicetree/bindings/sram/sram.yaml112[3] Documentation/devicetree/bindings/sram/sram.yaml
113[4] Documentation/devicetree/bindings/power/power-domain.yaml113[4] Documentation/devicetree/bindings/power/power-domain.yaml
114 114
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt+1−1
@@ -176,7 +176,7 @@ Required properties: · 175 unmodified lines
176 "fsl,imx8qxp-sc-thermal"176 "fsl,imx8qxp-sc-thermal"
177 followed by "fsl,imx-sc-thermal";177 followed by "fsl,imx-sc-thermal";
178 178
179- #thermal-sensor-cells: See Documentation/devicetree/bindings/thermal/thermal.txt179- #thermal-sensor-cells: See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml
180 for a description.180 for a description.
181 181
182Example (imx8qxp):182Example (imx8qxp):
Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt+1−1
@@ -111,7 +111,7 @@ Thermal: · 110 unmodified lines
111--------111--------
112 112
113For common binding part and usage, refer to113For common binding part and usage, refer to
114Documentation/devicetree/bindings/thermal/thermal.txt114Documentation/devicetree/bindings/thermal/thermal*.yaml
115 115
116The thermal IP can probe the temperature all around the processor. It116The thermal IP can probe the temperature all around the processor. It
117may feature several channels, each of them wired to one sensor.117may feature several channels, each of them wired to one sensor.
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt+1−1
@@ -203,7 +203,7 @@ It is possible to setup an overheat interrupt by giving at least one · 202 unmodified lines
203critical point to any subnode of the thermal-zone node.203critical point to any subnode of the thermal-zone node.
204 204
205For common binding part and usage, refer to205For common binding part and usage, refer to
206Documentation/devicetree/bindings/thermal/thermal.txt206Documentation/devicetree/bindings/thermal/thermal*.yaml
207 207
208Required properties:208Required properties:
209- compatible: must be one of:209- compatible: must be one of:
Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt+2−1
@@ -18,7 +18,8 @@ Optional properties: · 17 unmodified lines
18 in unit of nanoseconds.18 in unit of nanoseconds.
19- voltage-tolerance: Specify the CPU voltage tolerance in percentage.19- voltage-tolerance: Specify the CPU voltage tolerance in percentage.
20- #cooling-cells: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
23Examples:24Examples:
24 25
Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt+2−2
@@ -21,8 +21,8 @@ Optional properties: · 20 unmodified lines
21 flow is handled by hardware, hence no software "voltage tracking" is21 flow is handled by hardware, hence no software "voltage tracking" is
22 needed.22 needed.
23- #cooling-cells:23- #cooling-cells:
24 Please refer to Documentation/devicetree/bindings/thermal/thermal.txt24 For details, please refer to
25 for detail.25 Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
26 26
27Example 1 (MT7623 SoC):27Example 1 (MT7623 SoC):
28 28
Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt+1−1
@@ -5,7 +5,7 @@ Required properties: · 4 unmodified lines
5- clocks: Must contain an entry for the CPU clock.5- clocks: Must contain an entry for the CPU clock.
6 See ../clocks/clock-bindings.txt for details.6 See ../clocks/clock-bindings.txt for details.
7- operating-points-v2: See ../bindings/opp/opp.txt for details.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
10For each opp entry in 'operating-points-v2' table:10For each opp entry in 'operating-points-v2' table:
11- opp-supported-hw: Two bitfields indicating:11- opp-supported-hw: Two bitfields indicating:
Documentation/devicetree/bindings/hwmon/gpio-fan.txt+2−1
@@ -12,7 +12,8 @@ Optional properties: · 11 unmodified lines
12- alarm-gpios: This pin going active indicates something is wrong with12- alarm-gpios: This pin going active indicates something is wrong with
13 the fan, and a udev event will be fired.13 the fan, and a udev event will be fired.
14- #cooling-cells: If used as a cooling device, must be <2>14- #cooling-cells: If used as a cooling device, must be <2>
15 Also see: Documentation/devicetree/bindings/thermal/thermal.txt15 Also see:
16 Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
16 min and max states are derived from the speed-map of the fan.17 min and max states are derived from the speed-map of the fan.
17 18
18Note: At least one the "gpios" or "alarm-gpios" properties must be set.19Note: At least one the "gpios" or "alarm-gpios" properties must be set.
Documentation/devicetree/bindings/hwmon/lm90.txt+2−2
@@ -34,8 +34,8 @@ Optional properties: · 33 unmodified lines
34 LM90 "-ALERT" pin output.34 LM90 "-ALERT" pin output.
35 See interrupt-controller/interrupts.txt for the format.35 See interrupt-controller/interrupts.txt for the format.
36 36
37- #thermal-sensor-cells: should be set to 1. See thermal/thermal.txt for37- #thermal-sensor-cells: should be set to 1. See thermal/thermal-sensor.yaml
38 details. See <include/dt-bindings/thermal/lm90.h> for the38 for details. See <include/dt-bindings/thermal/lm90.h> for the
39 definition of the local, remote and 2nd remote sensor index39 definition of the local, remote and 2nd remote sensor index
40 constants.40 constants.
41 41
Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml+1−1
@@ -50,7 +50,7 @@ properties: · 49 unmodified lines
50 nvmem-cell-names:50 nvmem-cell-names:
51 const: calibration51 const: calibration
52 52
53 # See ./thermal.txt for details53 # See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
54 "#thermal-sensor-cells":54 "#thermal-sensor-cells":
55 enum:55 enum:
56 - 056 - 0
Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt+1−1
@@ -6,7 +6,7 @@ transaction. · 5 unmodified lines
6Required properties:6Required properties:
7- compatible: "amazon,al-thermal".7- compatible: "amazon,al-thermal".
8- reg: The physical base address and length of the sensor's registers.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
11Example:11Example:
12 thermal: thermal {12 thermal: thermal {
Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml+1−1
@@ -23,7 +23,7 @@ properties: · 22 unmodified lines
23 compatible:23 compatible:
24 const: brcm,bcm2711-thermal24 const: brcm,bcm2711-thermal
25 25
26 # See ./thermal.txt for details26 # See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
27 "#thermal-sensor-cells":27 "#thermal-sensor-cells":
28 const: 028 const: 0
29 29
Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt+1−1
@@ -7,7 +7,7 @@ compatible: should be one of: "brcm,bcm2835-thermal", · 6 unmodified lines
7 "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"7 "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
8reg: Address range of the thermal registers.8reg: Address range of the thermal registers.
9clocks: Phandle of the clock used by the thermal sensor.9clocks: 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
12Example:12Example:
13 13
Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt+1−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
9 by /SOCTHERM/tsensor.9 by /SOCTHERM/tsensor.
10- clock-names: Input clock name, should be 'thermal_clk'.10- clock-names: Input clock name, should be 'thermal_clk'.
11- clocks: phandles for clock specified in "clock-names" property.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
14Example :14Example :
15 15
Documentation/devicetree/bindings/thermal/max77620_thermal.txt+3−3
@@ -8,12 +8,12 @@ below threshold level. · 7 unmodified lines
8 8
9Required properties:9Required properties:
10-------------------10-------------------
11#thermal-sensor-cells: Please refer <devicetree/bindings/thermal/thermal.txt>11#thermal-sensor-cells: For more details, please refer to
12 for more details.12 <devicetree/bindings/thermal/thermal-sensor.yaml>
13 The value must be 0.13 The value must be 0.
14 14
15For more details, please refer generic thermal DT binding document15For more details, please refer generic thermal DT binding document
16<devicetree/bindings/thermal/thermal.txt>.16<devicetree/bindings/thermal/thermal*.yaml>.
17 17
18Please refer <devicetree/bindings/mfd/max77620.txt> for mfd DT binding18Please refer <devicetree/bindings/mfd/max77620.txt> for mfd DT binding
19document for the MAX77620.19document for the MAX77620.
Documentation/devicetree/bindings/thermal/mediatek-thermal.txt+1−1
@@ -23,7 +23,7 @@ Required properties: · 22 unmodified lines
23- resets: Reference to the reset controller controlling the thermal controller.23- resets: Reference to the reset controller controlling the thermal controller.
24- mediatek,auxadc: A phandle to the AUXADC which the thermal controller uses24- mediatek,auxadc: A phandle to the AUXADC which the thermal controller uses
25- mediatek,apmixedsys: A phandle to the APMIXEDSYS controller.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
28Optional properties:28Optional properties:
29- nvmem-cells: A phandle to the calibration data provided by a nvmem device. If29- nvmem-cells: A phandle to the calibration data provided by a nvmem device. If
Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt+6−4
@@ -28,9 +28,10 @@ Required properties : · 27 unmodified lines
28 See ../reset/reset.txt for details.28 See ../reset/reset.txt for details.
29- reset-names : Must include the following entries:29- reset-names : Must include the following entries:
30 - soctherm30 - soctherm
31- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description31- #thermal-sensor-cells : Should be 1. For a description of this property, see
32 of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a32 Documentation/devicetree/bindings/thermal/thermal-sensor.yaml.
33 list of valid values when referring to thermal sensors.33 See <dt-bindings/thermal/tegra124-soctherm.h> for a list of valid values
34 when referring to thermal sensors.
34- throttle-cfgs: A sub-node which is a container of configuration for each35- throttle-cfgs: A sub-node which is a container of configuration for each
35 hardware throttle events. These events can be set as cooling devices.36 hardware throttle events. These events can be set as cooling devices.
36 * throttle events: Sub-nodes must be named as "light" or "heavy".37 * throttle events: Sub-nodes must be named as "light" or "heavy".
@@ -62,7 +63,8 @@ Required properties : · 25 unmodified lines
62 TEGRA_SOCTHERM_THROT_LEVEL_MED (75%),63 TEGRA_SOCTHERM_THROT_LEVEL_MED (75%),
63 TEGRA_SOCTHERM_THROT_LEVEL_HIGH (85%).64 TEGRA_SOCTHERM_THROT_LEVEL_HIGH (85%).
64 - #cooling-cells: Should be 1. This cooling device only support on/off state.65 - #cooling-cells: Should be 1. This cooling device only support on/off state.
65 See ./thermal.txt for a description of this property.66 For a description of this property see:
67 Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
66 68
67 Optional properties: The following properties are T210 specific and69 Optional properties: The following properties are T210 specific and
68 valid only for OCx throttle events.70 valid only for OCx throttle events.
Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt+1−1
@@ -8,7 +8,7 @@ exposed by BPMP. · 7 unmodified lines
8The BPMP thermal node must be located directly inside the main BPMP node. See8The BPMP thermal node must be located directly inside the main BPMP node. See
9../firmware/nvidia,tegra186-bpmp.txt for details of the BPMP binding.9../firmware/nvidia,tegra186-bpmp.txt for details of the BPMP binding.
10 10
11This node represents a thermal sensor. See thermal.txt for details of the11This node represents a thermal sensor. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details of the
12core thermal binding.12core thermal binding.
13 13
14Required properties:14Required properties:
Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt+1−1
@@ -8,7 +8,7 @@ Required properties: · 7 unmodified lines
8- compatible: Should contain "qcom,spmi-temp-alarm".8- compatible: Should contain "qcom,spmi-temp-alarm".
9- reg: Specifies the SPMI address.9- reg: Specifies the SPMI address.
10- interrupts: PMIC temperature alarm interrupt.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
13Optional properties:13Optional properties:
14- io-channels: Should contain IIO channel specifier for the ADC channel,14- io-channels: Should contain IIO channel specifier for the ADC channel,
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml+1−0
@@ -23,6 +23,7 @@ properties: · 22 unmodified lines
23 items:23 items:
24 - enum:24 - enum:
25 - qcom,msm8916-tsens25 - qcom,msm8916-tsens
26 - qcom,msm8939-tsens
26 - qcom,msm8974-tsens27 - qcom,msm8974-tsens
27 - const: qcom,tsens-v0_128 - const: qcom,tsens-v0_1
28 29
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt+1−1
@@ -24,7 +24,7 @@ Required properties: · 23 unmodified lines
24- pinctrl-1 : The "default" pinctrl state, it will be set after reset the24- pinctrl-1 : The "default" pinctrl state, it will be set after reset the
25 TSADC controller.25 TSADC controller.
26- pinctrl-2 : The "sleep" pinctrl state, it will be in for suspend.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
29Optional properties:29Optional properties:
30- rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.30- rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.
Documentation/devicetree/bindings/thermal/tango-thermal.txt+1−1
@@ -4,7 +4,7 @@ The SMP8758 SoC includes 3 instances of this temperature sensor · 3 unmodified lines
4(in the CPU, video decoder, and PCIe controller).4(in the CPU, video decoder, and PCIe controller).
5 5
6Required properties:6Required 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- compatible: "sigma,smp8758-thermal"8- compatible: "sigma,smp8758-thermal"
9- reg: Address range of the thermal registers9- reg: Address range of the thermal registers
10 10
Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt+1−1
@@ -8,7 +8,7 @@ temperature using voltage-temperature lookup table. · 7 unmodified lines
8Required properties:8Required properties:
9===================9===================
10- compatible: Must be "generic-adc-thermal".10- compatible: Must be "generic-adc-thermal".
11- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description11- #thermal-sensor-cells: Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description
12 of this property.12 of this property.
13Optional properties:13Optional properties:
14===================14===================
Documentation/devicetree/bindings/thermal/thermal.txt+0−586
@@ -1,586 +0,0 @@
1* Thermal Framework Device Tree descriptor
2
3This file describes a generic binding to provide a way of
4defining hardware thermal structure using device tree.
5A thermal structure includes thermal zones and their components,
6such as trip points, polling intervals, sensors and cooling devices
7binding descriptors.
8
9The target of device tree thermal descriptors is to describe only
10the hardware thermal aspects. The thermal device tree bindings are
11not about how the system must control or which algorithm or policy
12must be taken in place.
13
14There 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
23The following is a description of each of these node types.
24
25* Thermal sensor devices
26
27Thermal sensor devices are nodes providing temperature sensing capabilities on
28thermal zones. Typical devices are I2C ADC converters and bandgaps. These are
29nodes providing temperature data to thermal zones. Thermal sensor devices may
30control one or more internal sensors.
31
32Required 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
43Cooling devices are nodes providing control on power dissipation. There
44are essentially two ways to provide control on power dissipation. First
45is by means of regulating device performance, which is known as passive
46cooling. A typical passive cooling is a CPU that has dynamic voltage and
47frequency scaling (DVFS), and uses lower frequencies as cooling states.
48Second is by means of activating devices in order to remove
49the dissipated heat, which is known as active cooling, e.g. regulating
50fan speeds. In both cases, cooling devices shall have a way to determine
51the state of cooling in which the device is.
52
53Any cooling device has a range of cooling states (i.e. different levels
54of heat dissipation). For example a fan's cooling states correspond to
55the different fan speeds possible. Cooling states are referred to by
56single unsigned integers, where larger numbers mean greater heat
57dissipation. The precise set of cooling states associated with a device
58should be defined in a particular device's binding.
59For more examples of cooling devices, refer to the example sections below.
60
61Required 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
73The trip node is a node to describe a point in the temperature domain
74in which the system takes an action. This node describes just the point,
75not the action.
76
77Required 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
95The cooling device maps node is a node to describe how cooling devices
96get assigned to trip points of the zone. The cooling devices are expected
97to be loaded in the target system.
98
99Required 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
109Optional 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
115Note: Using the THERMAL_NO_LIMIT (-1UL) constant in the cooling-device phandle
116limit 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.
119Refer to include/dt-bindings/thermal/thermal.h for definition of this constant.
120
121* Thermal zone nodes
122
123The thermal zone node is the node containing all the required info
124for describing a thermal zone, including its cooling device bindings. The
125thermal zone node must contain, apart from its own properties, one sub-node
126containing trip nodes and one sub-node containing all the zone cooling maps.
127
128Required 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
145Optional 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
168Note: The delay properties are bound to the maximum dT/dt (temperature
169derivative 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
172when active cooling is activated.
173
174The maximum dT/dt is highly bound to hardware power consumption and dissipation
175capability. The delays should be chosen to account for said max dT/dt,
176such that a device does not cross several trip boundaries unexpectedly
177between polls. Choosing the right polling delays shall avoid having the
178device in temperature ranges that may damage the silicon structures and
179reduce silicon lifetime.
180
181* The thermal-zones node
182
183The "thermal-zones" node is a container for all thermal zone nodes. It shall
184contain only sub-nodes describing thermal zones as in the section
185"Thermal zone nodes". The "thermal-zones" node appears under "/".
186
187* Examples
188
189Below are several examples on how to use thermal data descriptors
190using device tree bindings:
191
192(a) - CPU thermal zone
193
194The CPU thermal zone example below describes how to setup one thermal zone
195using one single sensor as temperature source and many cooling devices and
196power dissipation control sources.
197
198#include <dt-bindings/thermal/thermal.h>
199
200cpus {
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
236ocp {
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
247thermal-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
285In the example above, the ADC sensor (bandgap0) at address 0x0000ED00 is
286used to monitor the zone 'cpu-thermal' using its sole sensor. A fan
287device (fan0) is controlled via I2C bus 1, at address 0x48, and has ten
288different cooling states 0-9. It is used to remove the heat out of
289the thermal zone 'cpu-thermal' using its cooling states
290from its minimum to 4, when it reaches trip point 'cpu_alert0'
291at 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
293linked to the same thermal zone, 'cpu-thermal', as a passive cooling device,
294using all its cooling states at trip point 'cpu_alert1',
295which is a trip point at 100C. On the thermal zone 'cpu-thermal', at the
296temperature of 125C, represented by the trip point 'cpu_crit', the silicon
297is not reliable anymore.
298
299(b) - IC with several internal sensors
300
301The example below describes how to deploy several thermal zones based off a
302single sensor IC, assuming it has several internal sensors. This is a common
303case on SoC designs with several internal IPs that may need different thermal
304requirements, and thus may have their own sensor to monitor or detect internal
305hotspots in their silicon.
306
307#include <dt-bindings/thermal/thermal.h>
308
309ocp {
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
320thermal-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
403In the example above, there is one bandgap IC which has the capability to
404monitor three sensors. The hardware has been designed so that sensors are
405placed on different places in the DIE to monitor different temperature
406hotspots: one for CPU thermal zone, one for GPU thermal zone and the
407other to monitor a DSP thermal zone.
408
409Thus, there is a need to assign each sensor provided by the bandgap IC
410to different thermal zones. This is achieved by means of using the
411#thermal-sensor-cells property and using the first cell of the sensor
412specifier as sensor ID. In the example, then, <bandgap 0> is used to
413monitor CPU thermal zone, <bandgap 1> is used to monitor GPU thermal
414zone and <bandgap 2> is used to monitor DSP thermal zone. Each zone
415may be uncorrelated, having its own dT/dt requirements, trips
416and cooling maps.
417
418
419(c) - Several sensors within one single thermal zone
420
421The example below illustrates how to use more than one sensor within
422one 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
437ocp {
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
448thermal-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
469In some cases, there is a need to use more than one sensor to extrapolate
470a thermal hotspot in the silicon. The above example illustrates this situation.
471For instance, it may be the case that a sensor external to CPU IP may be placed
472close to CPU hotspot and together with internal CPU sensor, it is used
473to determine the hotspot. Assuming this is the case for the above example,
474the hypothetical extrapolation rule would be:
475 hotspot = 100 * bandgap - 120 * adc + 484
476
477In other context, the same idea can be used to add fixed offset. For instance,
478consider the hotspot extrapolation rule below:
479 hotspot = 1 * adc + 6000
480
481In the above equation, the hotspot is always 6C higher than what is read
482from 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
490The board thermal example below illustrates how to setup one thermal zone
491with 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
506thermal-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
584The above example is a mix of previous examples, a sensor IP with several internal
585sensors used to monitor different zones, one of them is composed by several sensors and
586with different cooling devices.
MAINTAINERS+8−0
@@ -17086,6 +17086,14 @@ F: drivers/thermal/cpufreq_cooling.c · 17085 unmodified lines
17086F: drivers/thermal/cpuidle_cooling.c17086F: drivers/thermal/cpuidle_cooling.c
17087F: include/linux/cpu_cooling.h17087F: include/linux/cpu_cooling.h
17088 17088
17089THERMAL/POWER_ALLOCATOR
17090M: Lukasz Luba <lukasz.luba@arm.com>
17091L: linux-pm@vger.kernel.org
17092S: Maintained
17093F: Documentation/driver-api/thermal/power_allocator.rst
17094F: drivers/thermal/gov_power_allocator.c
17095F: include/trace/events/thermal_power_allocator.h
17096
17089THINKPAD ACPI EXTRAS DRIVER17097THINKPAD ACPI EXTRAS DRIVER
17090M: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>17098M: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
17091L: ibm-acpi-devel@lists.sourceforge.net17099L: ibm-acpi-devel@lists.sourceforge.net
drivers/acpi/thermal.c+21−55
@@ -172,7 +172,6 @@ struct acpi_thermal { · 171 unmodified lines
172 struct acpi_thermal_trips trips;172 struct acpi_thermal_trips trips;
173 struct acpi_handle_list devices;173 struct acpi_handle_list devices;
174 struct thermal_zone_device *thermal_zone;174 struct thermal_zone_device *thermal_zone;
175 int tz_enabled;
176 int kelvin_offset; /* in millidegrees */175 int kelvin_offset; /* in millidegrees */
177 struct work_struct thermal_check_work;176 struct work_struct thermal_check_work;
178};177};
@@ -500,9 +499,6 @@ static void acpi_thermal_check(void *data) · 321 unmodified lines
500{499{
501 struct acpi_thermal *tz = data;500 struct acpi_thermal *tz = data;
502 501
503 if (!tz->tz_enabled)
504 return;
505
506 thermal_zone_device_update(tz->thermal_zone,502 thermal_zone_device_update(tz->thermal_zone,
507 THERMAL_EVENT_UNSPECIFIED);503 THERMAL_EVENT_UNSPECIFIED);
508}504}
@@ -526,50 +522,6 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) · 17 unmodified lines
526 return 0;522 return 0;
527}523}
528 524
529static int thermal_get_mode(struct thermal_zone_device *thermal,
530 enum thermal_device_mode *mode)
531{
532 struct acpi_thermal *tz = thermal->devdata;
533
534 if (!tz)
535 return -EINVAL;
536
537 *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED :
538 THERMAL_DEVICE_DISABLED;
539
540 return 0;
541}
542
543static int thermal_set_mode(struct thermal_zone_device *thermal,
544 enum thermal_device_mode mode)
545{
546 struct acpi_thermal *tz = thermal->devdata;
547 int enable;
548
549 if (!tz)
550 return -EINVAL;
551
552 /*
553 * enable/disable thermal management from ACPI thermal driver
554 */
555 if (mode == THERMAL_DEVICE_ENABLED)
556 enable = 1;
557 else if (mode == THERMAL_DEVICE_DISABLED) {
558 enable = 0;
559 pr_warn("thermal zone will be disabled\n");
560 } else
561 return -EINVAL;
562
563 if (enable != tz->tz_enabled) {
564 tz->tz_enabled = enable;
565 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
566 "%s kernel ACPI thermal control\n",
567 tz->tz_enabled ? "Enable" : "Disable"));
568 acpi_thermal_check(tz);
569 }
570 return 0;
571}
572
573static int thermal_get_trip_type(struct thermal_zone_device *thermal,525static int thermal_get_trip_type(struct thermal_zone_device *thermal,
574 int trip, enum thermal_trip_type *type)526 int trip, enum thermal_trip_type *type)
575{527{
@@ -856,8 +808,6 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = { · 280 unmodified lines
856 .bind = acpi_thermal_bind_cooling_device,808 .bind = acpi_thermal_bind_cooling_device,
857 .unbind = acpi_thermal_unbind_cooling_device,809 .unbind = acpi_thermal_unbind_cooling_device,
858 .get_temp = thermal_get_temp,810 .get_temp = thermal_get_temp,
859 .get_mode = thermal_get_mode,
860 .set_mode = thermal_set_mode,
861 .get_trip_type = thermal_get_trip_type,811 .get_trip_type = thermal_get_trip_type,
862 .get_trip_temp = thermal_get_trip_temp,812 .get_trip_temp = thermal_get_trip_temp,
863 .get_crit_temp = thermal_get_crit_temp,813 .get_crit_temp = thermal_get_crit_temp,
@@ -901,23 +851,39 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) · 37 unmodified lines
901 result = sysfs_create_link(&tz->device->dev.kobj,851 result = sysfs_create_link(&tz->device->dev.kobj,
902 &tz->thermal_zone->device.kobj, "thermal_zone");852 &tz->thermal_zone->device.kobj, "thermal_zone");
903 if (result)853 if (result)
904 return result;854 goto unregister_tzd;
905 855
906 result = sysfs_create_link(&tz->thermal_zone->device.kobj,856 result = sysfs_create_link(&tz->thermal_zone->device.kobj,
907 &tz->device->dev.kobj, "device");857 &tz->device->dev.kobj, "device");
908 if (result)858 if (result)
909 return result;859 goto remove_tz_link;
910 860
911 status = acpi_bus_attach_private_data(tz->device->handle,861 status = acpi_bus_attach_private_data(tz->device->handle,
912 tz->thermal_zone);862 tz->thermal_zone);
913 if (ACPI_FAILURE(status))863 if (ACPI_FAILURE(status)) {
914 return -ENODEV;864 result = -ENODEV;
865 goto remove_dev_link;
866 }
915 867
916 tz->tz_enabled = 1;868 result = thermal_zone_device_enable(tz->thermal_zone);
869 if (result)
870 goto acpi_bus_detach;
917 871
918 dev_info(&tz->device->dev, "registered as thermal_zone%d\n",872 dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
919 tz->thermal_zone->id);873 tz->thermal_zone->id);
874
920 return 0;875 return 0;
876
877acpi_bus_detach:
878 acpi_bus_detach_private_data(tz->device->handle);
879remove_dev_link:
880 sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
881remove_tz_link:
882 sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
883unregister_tzd:
884 thermal_zone_device_unregister(tz->thermal_zone);
885
886 return result;
921}887}
922 888
923static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)889static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c+8−0
@@ -92,6 +92,14 @@ int cxgb4_thermal_init(struct adapter *adap) · 91 unmodified lines
92 ch_thermal->tzdev = NULL;92 ch_thermal->tzdev = NULL;
93 return ret;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 return 0;103 return 0;
96}104}
97 105
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c+17−74
@@ -98,7 +98,6 @@ struct mlxsw_thermal_module { · 97 unmodified lines
98 struct mlxsw_thermal *parent;98 struct mlxsw_thermal *parent;
99 struct thermal_zone_device *tzdev;99 struct thermal_zone_device *tzdev;
100 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];100 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
101 enum thermal_device_mode mode;
102 int module; /* Module or gearbox number */101 int module; /* Module or gearbox number */
103};102};
104 103
@@ -110,7 +109,6 @@ struct mlxsw_thermal { · 5 unmodified lines
110 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];109 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
111 u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];110 u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
112 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];111 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
113 enum thermal_device_mode mode;
114 struct mlxsw_thermal_module *tz_module_arr;112 struct mlxsw_thermal_module *tz_module_arr;
115 u8 tz_module_num;113 u8 tz_module_num;
116 struct mlxsw_thermal_module *tz_gearbox_arr;114 struct mlxsw_thermal_module *tz_gearbox_arr;
@@ -277,36 +275,6 @@ static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev, · 160 unmodified lines
277 return 0;275 return 0;
278}276}
279 277
280static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev,
281 enum thermal_device_mode *mode)
282{
283 struct mlxsw_thermal *thermal = tzdev->devdata;
284
285 *mode = thermal->mode;
286
287 return 0;
288}
289
290static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
291 enum thermal_device_mode mode)
292{
293 struct mlxsw_thermal *thermal = tzdev->devdata;
294
295 mutex_lock(&tzdev->lock);
296
297 if (mode == THERMAL_DEVICE_ENABLED)
298 tzdev->polling_delay = thermal->polling_delay;
299 else
300 tzdev->polling_delay = 0;
301
302 mutex_unlock(&tzdev->lock);
303
304 thermal->mode = mode;
305 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
306
307 return 0;
308}
309
310static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,278static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
311 int *p_temp)279 int *p_temp)
312{280{
@@ -406,8 +374,6 @@ static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev, · 93 unmodified lines
406static struct thermal_zone_device_ops mlxsw_thermal_ops = {374static struct thermal_zone_device_ops mlxsw_thermal_ops = {
407 .bind = mlxsw_thermal_bind,375 .bind = mlxsw_thermal_bind,
408 .unbind = mlxsw_thermal_unbind,376 .unbind = mlxsw_thermal_unbind,
409 .get_mode = mlxsw_thermal_get_mode,
410 .set_mode = mlxsw_thermal_set_mode,
411 .get_temp = mlxsw_thermal_get_temp,377 .get_temp = mlxsw_thermal_get_temp,
412 .get_trip_type = mlxsw_thermal_get_trip_type,378 .get_trip_type = mlxsw_thermal_get_trip_type,
413 .get_trip_temp = mlxsw_thermal_get_trip_temp,379 .get_trip_temp = mlxsw_thermal_get_trip_temp,
@@ -465,37 +431,6 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev, · 51 unmodified lines
465 return err;431 return err;
466}432}
467 433
468static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev,
469 enum thermal_device_mode *mode)
470{
471 struct mlxsw_thermal_module *tz = tzdev->devdata;
472
473 *mode = tz->mode;
474
475 return 0;
476}
477
478static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev,
479 enum thermal_device_mode mode)
480{
481 struct mlxsw_thermal_module *tz = tzdev->devdata;
482 struct mlxsw_thermal *thermal = tz->parent;
483
484 mutex_lock(&tzdev->lock);
485
486 if (mode == THERMAL_DEVICE_ENABLED)
487 tzdev->polling_delay = thermal->polling_delay;
488 else
489 tzdev->polling_delay = 0;
490
491 mutex_unlock(&tzdev->lock);
492
493 tz->mode = mode;
494 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
495
496 return 0;
497}
498
499static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,434static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
500 int *p_temp)435 int *p_temp)
501{436{
@@ -611,8 +546,6 @@ static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev, · 109 unmodified lines
611static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {546static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
612 .bind = mlxsw_thermal_module_bind,547 .bind = mlxsw_thermal_module_bind,
613 .unbind = mlxsw_thermal_module_unbind,548 .unbind = mlxsw_thermal_module_unbind,
614 .get_mode = mlxsw_thermal_module_mode_get,
615 .set_mode = mlxsw_thermal_module_mode_set,
616 .get_temp = mlxsw_thermal_module_temp_get,549 .get_temp = mlxsw_thermal_module_temp_get,
617 .get_trip_type = mlxsw_thermal_module_trip_type_get,550 .get_trip_type = mlxsw_thermal_module_trip_type_get,
618 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,551 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
@@ -650,8 +583,6 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, · 31 unmodified lines
650static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {583static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
651 .bind = mlxsw_thermal_module_bind,584 .bind = mlxsw_thermal_module_bind,
652 .unbind = mlxsw_thermal_module_unbind,585 .unbind = mlxsw_thermal_module_unbind,
653 .get_mode = mlxsw_thermal_module_mode_get,
654 .set_mode = mlxsw_thermal_module_mode_set,
655 .get_temp = mlxsw_thermal_gearbox_temp_get,586 .get_temp = mlxsw_thermal_gearbox_temp_get,
656 .get_trip_type = mlxsw_thermal_module_trip_type_get,587 .get_trip_type = mlxsw_thermal_module_trip_type_get,
657 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,588 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
@@ -780,8 +711,11 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) · 122 unmodified lines
780 return err;711 return err;
781 }712 }
782 713
783 module_tz->mode = THERMAL_DEVICE_ENABLED;714 err = thermal_zone_device_enable(module_tz->tzdev);
784 return 0;715 if (err)
716 thermal_zone_device_unregister(module_tz->tzdev);
717
718 return err;
785}719}
786 720
787static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)721static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
@@ -884,6 +818,7 @@ static int · 96 unmodified lines
884mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)818mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
885{819{
886 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];820 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
821 int ret;
887 822
888 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",823 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
889 gearbox_tz->module + 1);824 gearbox_tz->module + 1);
@@ -896,8 +831,11 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) · 6 unmodified lines
896 if (IS_ERR(gearbox_tz->tzdev))831 if (IS_ERR(gearbox_tz->tzdev))
897 return PTR_ERR(gearbox_tz->tzdev);832 return PTR_ERR(gearbox_tz->tzdev);
898 833
899 gearbox_tz->mode = THERMAL_DEVICE_ENABLED;834 ret = thermal_zone_device_enable(gearbox_tz->tzdev);
900 return 0;835 if (ret)
836 thermal_zone_device_unregister(gearbox_tz->tzdev);
837
838 return ret;
901}839}
902 840
903static void841static void
@@ -1065,10 +1003,15 @@ int mlxsw_thermal_init(struct mlxsw_core *core, · 161 unmodified lines
1065 if (err)1003 if (err)
1066 goto err_unreg_modules_tzdev;1004 goto err_unreg_modules_tzdev;
1067 1005
1068 thermal->mode = THERMAL_DEVICE_ENABLED;1006 err = thermal_zone_device_enable(thermal->tzdev);
1007 if (err)
1008 goto err_unreg_gearboxes;
1009
1069 *p_thermal = thermal;1010 *p_thermal = thermal;
1070 return 0;1011 return 0;
1071 1012
1013err_unreg_gearboxes:
1014 mlxsw_thermal_gearboxes_fini(thermal);
1072err_unreg_modules_tzdev:1015err_unreg_modules_tzdev:
1073 mlxsw_thermal_modules_fini(thermal);1016 mlxsw_thermal_modules_fini(thermal);
1074err_unreg_tzdev:1017err_unreg_tzdev:
drivers/net/wireless/intel/iwlwifi/mvm/tt.c+8−1
@@ -733,7 +733,7 @@ static struct thermal_zone_device_ops tzone_ops = { · 732 unmodified lines
733 733
734static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)734static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
735{735{
736 int i;736 int i, ret;
737 char name[16];737 char name[16];
738 static atomic_t counter = ATOMIC_INIT(0);738 static atomic_t counter = ATOMIC_INIT(0);
739 739
@@ -759,6 +759,13 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) · 19 unmodified lines
759 return;759 return;
760 }760 }
761 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);
766 return;
767 }
768
762 /* 0 is a valid temperature,769 /* 0 is a valid temperature,
763 * so initialize the array with S16_MIN which invalid temperature770 * so initialize the array with S16_MIN which invalid temperature
764 */771 */
drivers/platform/x86/acerhdf.c+13−20
@@ -397,39 +397,24 @@ static inline void acerhdf_revert_to_bios_mode(void) · 396 unmodified lines
397{397{
398 acerhdf_change_fanstate(ACERHDF_FAN_AUTO);398 acerhdf_change_fanstate(ACERHDF_FAN_AUTO);
399 kernelmode = 0;399 kernelmode = 0;
400 if (thz_dev)400
401 thz_dev->polling_delay = 0;
402 pr_notice("kernel mode fan control OFF\n");401 pr_notice("kernel mode fan control OFF\n");
403}402}
404static inline void acerhdf_enable_kernelmode(void)403static inline void acerhdf_enable_kernelmode(void)
405{404{
406 kernelmode = 1;405 kernelmode = 1;
407 406
408 thz_dev->polling_delay = interval*1000;
409 thermal_zone_device_update(thz_dev, THERMAL_EVENT_UNSPECIFIED);
410 pr_notice("kernel mode fan control ON\n");407 pr_notice("kernel mode fan control ON\n");
411}408}
412 409
413static 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}
424
425/*410/*
426 * set operation mode;411 * set operation mode;
427 * enabled: the thermal layer of the kernel takes care about412 * enabled: the thermal layer of the kernel takes care about
428 * the temperature and the fan.413 * the temperature and the fan.
429 * disabled: the BIOS takes control of the fan.414 * disabled: the BIOS takes control of the fan.
430 */415 */
431static int acerhdf_set_mode(struct thermal_zone_device *thermal,416static int acerhdf_change_mode(struct thermal_zone_device *thermal,
432 enum thermal_device_mode mode)417 enum thermal_device_mode mode)
433{418{
434 if (mode == THERMAL_DEVICE_DISABLED && kernelmode)419 if (mode == THERMAL_DEVICE_DISABLED && kernelmode)
435 acerhdf_revert_to_bios_mode();420 acerhdf_revert_to_bios_mode();
@@ -488,8 +473,7 @@ static struct thermal_zone_device_ops acerhdf_dev_ops = { · 52 unmodified lines
488 .bind = acerhdf_bind,473 .bind = acerhdf_bind,
489 .unbind = acerhdf_unbind,474 .unbind = acerhdf_unbind,
490 .get_temp = acerhdf_get_ec_temp,475 .get_temp = acerhdf_get_ec_temp,
491 .get_mode = acerhdf_get_mode,476 .change_mode = acerhdf_change_mode,
492 .set_mode = acerhdf_set_mode,
493 .get_trip_type = acerhdf_get_trip_type,477 .get_trip_type = acerhdf_get_trip_type,
494 .get_trip_hyst = acerhdf_get_trip_hyst,478 .get_trip_hyst = acerhdf_get_trip_hyst,
495 .get_trip_temp = acerhdf_get_trip_temp,479 .get_trip_temp = acerhdf_get_trip_temp,
@@ -733,6 +717,8 @@ static void acerhdf_unregister_platform(void) · 237 unmodified lines
733 717
734static int __init acerhdf_register_thermal(void)718static int __init acerhdf_register_thermal(void)
735{719{
720 int ret;
721
736 cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL,722 cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL,
737 &acerhdf_cooling_ops);723 &acerhdf_cooling_ops);
738 724
@@ -746,6 +732,13 @@ static int __init acerhdf_register_thermal(void) · 7 unmodified lines
746 if (IS_ERR(thz_dev))732 if (IS_ERR(thz_dev))
747 return -EINVAL;733 return -EINVAL;
748 734
735 if (kernelmode)
736 ret = thermal_zone_device_enable(thz_dev);
737 else
738 ret = thermal_zone_device_disable(thz_dev);
739 if (ret)
740 return ret;
741
749 if (strcmp(thz_dev->governor->name,742 if (strcmp(thz_dev->governor->name,
750 acerhdf_zone_params.governor_name)) {743 acerhdf_zone_params.governor_name)) {
751 pr_err("Didn't get thermal governor %s, perhaps not compiled into thermal subsystem.\n",744 pr_err("Didn't get thermal governor %s, perhaps not compiled into thermal subsystem.\n",
drivers/platform/x86/intel_mid_thermal.c+6−0
@@ -493,6 +493,12 @@ static int mid_thermal_probe(struct platform_device *pdev) · 492 unmodified lines
493 ret = PTR_ERR(pinfo->tzd[i]);493 ret = PTR_ERR(pinfo->tzd[i]);
494 goto err;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 pinfo->pdev = pdev;504 pinfo->pdev = pdev;
drivers/power/supply/power_supply_core.c+7−2
@@ -939,7 +939,7 @@ static struct thermal_zone_device_ops psy_tzd_ops = { · 938 unmodified lines
939 939
940static int psy_register_thermal(struct power_supply *psy)940static int psy_register_thermal(struct power_supply *psy)
941{941{
942 int i;942 int i, ret;
943 943
944 if (psy->desc->no_thermal)944 if (psy->desc->no_thermal)
945 return 0;945 return 0;
@@ -949,7 +949,12 @@ static int psy_register_thermal(struct power_supply *psy) · 3 unmodified lines
949 if (psy->desc->properties[i] == POWER_SUPPLY_PROP_TEMP) {949 if (psy->desc->properties[i] == POWER_SUPPLY_PROP_TEMP) {
950 psy->tzd = thermal_zone_device_register(psy->desc->name,950 psy->tzd = thermal_zone_device_register(psy->desc->name,
951 0, 0, psy, &psy_tzd_ops, NULL, 0, 0);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 return 0;960 return 0;
drivers/thermal/Kconfig+10−10
@@ -17,6 +17,16 @@ menuconfig THERMAL · 16 unmodified lines
17 17
18if THERMAL18if THERMAL
19 19
20config 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
20config THERMAL_STATISTICS30config THERMAL_STATISTICS
21 bool "Thermal state transition statistics"31 bool "Thermal state transition statistics"
22 help32 help
@@ -180,16 +190,6 @@ config CPU_IDLE_THERMAL · 157 unmodified lines
180 idle cycle.190 idle cycle.
181endif191endif
182 192
183config CLOCK_THERMAL
184 bool "Generic clock cooling support"
185 depends on COMMON_CLK
186 depends on PM_OPP
187 help
188 This entry implements the generic clock cooling mechanism through
189 frequency clipping. Typically used to cool off co-processors. The
190 device that is configured to use this cooling mechanism will be
191 controlled to reduce clock frequency whenever temperature is high.
192
193config DEVFREQ_THERMAL193config DEVFREQ_THERMAL
194 bool "Generic device cooling support"194 bool "Generic device cooling support"
195 depends on PM_DEVFREQ195 depends on PM_DEVFREQ
drivers/thermal/Makefile+3−3
@@ -7,6 +7,9 @@ obj-$(CONFIG_THERMAL) += thermal_sys.o · 6 unmodified lines
7thermal_sys-y += thermal_core.o thermal_sysfs.o \7thermal_sys-y += thermal_core.o thermal_sysfs.o \
8 thermal_helpers.o8 thermal_helpers.o
9 9
10# netlink interface to manage the thermal framework
11thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o
12
10# interface to/from other layers providing sensors13# interface to/from other layers providing sensors
11thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o14thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
12thermal_sys-$(CONFIG_THERMAL_OF) += thermal_of.o15thermal_sys-$(CONFIG_THERMAL_OF) += thermal_of.o
@@ -22,9 +25,6 @@ thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR) += gov_power_allocator.o · 9 unmodified lines
22thermal_sys-$(CONFIG_CPU_FREQ_THERMAL) += cpufreq_cooling.o25thermal_sys-$(CONFIG_CPU_FREQ_THERMAL) += cpufreq_cooling.o
23thermal_sys-$(CONFIG_CPU_IDLE_THERMAL) += cpuidle_cooling.o26thermal_sys-$(CONFIG_CPU_IDLE_THERMAL) += cpuidle_cooling.o
24 27
25# clock cooling
26thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
27
28# devfreq cooling28# devfreq cooling
29thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o29thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
30 30
drivers/thermal/armada_thermal.c+6−0
@@ -874,6 +874,12 @@ static int armada_thermal_probe(struct platform_device *pdev) · 873 unmodified lines
874 return PTR_ERR(tz);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 drvdata->type = LEGACY;883 drvdata->type = LEGACY;
878 drvdata->data.tz = tz;884 drvdata->data.tz = tz;
879 platform_set_drvdata(pdev, drvdata);885 platform_set_drvdata(pdev, drvdata);
drivers/thermal/clock_cooling.c+0−445
@@ -1,445 +0,0 @@
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 */
48struct 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)
61static DEFINE_IDA(clock_ida);
62
63/* Below code defines functions to be used for clock as cooling device */
64
65enum 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 */
90static 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 */
172unsigned 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}
184EXPORT_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 */
198static unsigned long
199clock_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 */
224static 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 */
264static 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 */
300static 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 */
324static 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 */
344static 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 */
353static 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 */
375struct thermal_cooling_device *
376clock_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}
422EXPORT_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 */
430void 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}
445EXPORT_SYMBOL_GPL(clock_cooling_unregister);
drivers/thermal/da9062-thermal.c+5−11
@@ -49,7 +49,6 @@ struct da9062_thermal { · 48 unmodified lines
49 struct da9062 *hw;49 struct da9062 *hw;
50 struct delayed_work work;50 struct delayed_work work;
51 struct thermal_zone_device *zone;51 struct thermal_zone_device *zone;
52 enum thermal_device_mode mode;
53 struct mutex lock; /* protection for da9062_thermal temperature */52 struct mutex lock; /* protection for da9062_thermal temperature */
54 int temperature;53 int temperature;
55 int irq;54 int irq;
@@ -121,14 +120,6 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data) · 65 unmodified lines
121 return IRQ_HANDLED;120 return IRQ_HANDLED;
122}121}
123 122
124static int da9062_thermal_get_mode(struct thermal_zone_device *z,
125 enum thermal_device_mode *mode)
126{
127 struct da9062_thermal *thermal = z->devdata;
128 *mode = thermal->mode;
129 return 0;
130}
131
132static int da9062_thermal_get_trip_type(struct thermal_zone_device *z,123static int da9062_thermal_get_trip_type(struct thermal_zone_device *z,
133 int trip,124 int trip,
134 enum thermal_trip_type *type)125 enum thermal_trip_type *type)
@@ -181,7 +172,6 @@ static int da9062_thermal_get_temp(struct thermal_zone_device *z, · 46 unmodified lines
181 172
182static struct thermal_zone_device_ops da9062_thermal_ops = {173static struct thermal_zone_device_ops da9062_thermal_ops = {
183 .get_temp = da9062_thermal_get_temp,174 .get_temp = da9062_thermal_get_temp,
184 .get_mode = da9062_thermal_get_mode,
185 .get_trip_type = da9062_thermal_get_trip_type,175 .get_trip_type = da9062_thermal_get_trip_type,
186 .get_trip_temp = da9062_thermal_get_trip_temp,176 .get_trip_temp = da9062_thermal_get_trip_temp,
187};177};
@@ -233,7 +223,6 @@ static int da9062_thermal_probe(struct platform_device *pdev) · 45 unmodified lines
233 223
234 thermal->config = match->data;224 thermal->config = match->data;
235 thermal->hw = chip;225 thermal->hw = chip;
236 thermal->mode = THERMAL_DEVICE_ENABLED;
237 thermal->dev = &pdev->dev;226 thermal->dev = &pdev->dev;
238 227
239 INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);228 INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);
@@ -248,6 +237,11 @@ static int da9062_thermal_probe(struct platform_device *pdev) · 8 unmodified lines
248 ret = PTR_ERR(thermal->zone);237 ret = PTR_ERR(thermal->zone);
249 goto err;238 goto err;
250 }239 }
240 ret = thermal_zone_device_enable(thermal->zone);
241 if (ret) {
242 dev_err(&pdev->dev, "Cannot enable thermal zone device\n");
243 goto err_zone;
244 }
251 245
252 dev_dbg(&pdev->dev,246 dev_dbg(&pdev->dev,
253 "TJUNC temperature polling period set at %d ms\n",247 "TJUNC temperature polling period set at %d ms\n",
drivers/thermal/devfreq_cooling.c+1−9
@@ -1,18 +1,10 @@
1// SPDX-License-Identifier: GPL-2.0
1/*2/*
2 * devfreq_cooling: Thermal cooling device implementation for devices using3 * devfreq_cooling: Thermal cooling device implementation for devices using
3 * devfreq4 * devfreq
4 *5 *
5 * Copyright (C) 2014-2015 ARM Limited6 * 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 *
16 * TODO:8 * TODO:
17 * - If OPPs are added or removed after devfreq cooling has9 * - If OPPs are added or removed after devfreq cooling has
18 * registered, the devfreq cooling won't react to it.10 * registered, the devfreq cooling won't react to it.
drivers/thermal/dove_thermal.c+6−0
@@ -153,6 +153,12 @@ static int dove_thermal_probe(struct platform_device *pdev) · 152 unmodified lines
153 return PTR_ERR(thermal);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 platform_set_drvdata(pdev, thermal);162 platform_set_drvdata(pdev, thermal);
157 163
158 return 0;164 return 0;
drivers/thermal/gov_power_allocator.c+1−8
@@ -1,16 +1,9 @@
1// SPDX-License-Identifier: GPL-2.0
1/*2/*
2 * A power allocator to manage temperature3 * A power allocator to manage temperature
3 *4 *
4 * Copyright (C) 2014 ARM Ltd.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#define pr_fmt(fmt) "Power allocator: " fmt9#define pr_fmt(fmt) "Power allocator: " fmt
drivers/thermal/hisi_thermal.c+4−2
@@ -549,8 +549,10 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, · 548 unmodified lines
549{549{
550 struct thermal_zone_device *tzd = sensor->tzd;550 struct thermal_zone_device *tzd = sensor->tzd;
551 551
552 tzd->ops->set_mode(tzd,552 if (on)
553 on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);553 thermal_zone_device_enable(tzd);
554 else
555 thermal_zone_device_disable(tzd);
554}556}
555 557
556static int hisi_thermal_probe(struct platform_device *pdev)558static int hisi_thermal_probe(struct platform_device *pdev)
drivers/thermal/imx8mm_thermal.c+1−0
@@ -220,6 +220,7 @@ static const struct of_device_id imx8mm_tmu_table[] = { · 219 unmodified lines
220 { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, },220 { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, },
221 { },221 { },
222};222};
223MODULE_DEVICE_TABLE(of, imx8mm_tmu_table);
223 224
224static struct platform_driver imx8mm_tmu = {225static struct platform_driver imx8mm_tmu = {
225 .driver = {226 .driver = {
drivers/thermal/imx_thermal.c+19−41
@@ -197,7 +197,6 @@ struct imx_thermal_data { · 196 unmodified lines
197 struct cpufreq_policy *policy;197 struct cpufreq_policy *policy;
198 struct thermal_zone_device *tz;198 struct thermal_zone_device *tz;
199 struct thermal_cooling_device *cdev;199 struct thermal_cooling_device *cdev;
200 enum thermal_device_mode mode;
201 struct regmap *tempmon;200 struct regmap *tempmon;
202 u32 c1, c2; /* See formula in imx_init_calib() */201 u32 c1, c2; /* See formula in imx_init_calib() */
203 int temp_passive;202 int temp_passive;
@@ -253,10 +252,11 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) · 49 unmodified lines
253 const struct thermal_soc_data *soc_data = data->socdata;252 const struct thermal_soc_data *soc_data = data->socdata;
254 struct regmap *map = data->tempmon;253 struct regmap *map = data->tempmon;
255 unsigned int n_meas;254 unsigned int n_meas;
256 bool wait;255 bool wait, run_measurement;
257 u32 val;256 u32 val;
258 257
259 if (data->mode == THERMAL_DEVICE_ENABLED) {258 run_measurement = !data->irq_enabled;
259 if (!run_measurement) {
260 /* Check if a measurement is currently in progress */260 /* Check if a measurement is currently in progress */
261 regmap_read(map, soc_data->temp_data, &val);261 regmap_read(map, soc_data->temp_data, &val);
262 wait = !(val & soc_data->temp_valid_mask);262 wait = !(val & soc_data->temp_valid_mask);
@@ -283,7 +283,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) · 20 unmodified lines
283 283
284 regmap_read(map, soc_data->temp_data, &val);284 regmap_read(map, soc_data->temp_data, &val);
285 285
286 if (data->mode != THERMAL_DEVICE_ENABLED) {286 if (run_measurement) {
287 regmap_write(map, soc_data->sensor_ctrl + REG_CLR,287 regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
288 soc_data->measure_temp_mask);288 soc_data->measure_temp_mask);
289 regmap_write(map, soc_data->sensor_ctrl + REG_SET,289 regmap_write(map, soc_data->sensor_ctrl + REG_SET,
@@ -331,27 +331,14 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) · 41 unmodified lines
331 return 0;331 return 0;
332}332}
333 333
334static int imx_get_mode(struct thermal_zone_device *tz,334static int imx_change_mode(struct thermal_zone_device *tz,
335 enum thermal_device_mode *mode)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
344static int imx_set_mode(struct thermal_zone_device *tz,
345 enum thermal_device_mode mode)
346{336{
347 struct imx_thermal_data *data = tz->devdata;337 struct imx_thermal_data *data = tz->devdata;
348 struct regmap *map = data->tempmon;338 struct regmap *map = data->tempmon;
349 const struct thermal_soc_data *soc_data = data->socdata;339 const struct thermal_soc_data *soc_data = data->socdata;
350 340
351 if (mode == THERMAL_DEVICE_ENABLED) {341 if (mode == THERMAL_DEVICE_ENABLED) {
352 tz->polling_delay = IMX_POLLING_DELAY;
353 tz->passive_delay = IMX_PASSIVE_DELAY;
354
355 regmap_write(map, soc_data->sensor_ctrl + REG_CLR,342 regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
356 soc_data->power_down_mask);343 soc_data->power_down_mask);
357 regmap_write(map, soc_data->sensor_ctrl + REG_SET,344 regmap_write(map, soc_data->sensor_ctrl + REG_SET,
@@ -367,18 +354,12 @@ static int imx_set_mode(struct thermal_zone_device *tz, · 9 unmodified lines
367 regmap_write(map, soc_data->sensor_ctrl + REG_SET,354 regmap_write(map, soc_data->sensor_ctrl + REG_SET,
368 soc_data->power_down_mask);355 soc_data->power_down_mask);
369 356
370 tz->polling_delay = 0;
371 tz->passive_delay = 0;
372
373 if (data->irq_enabled) {357 if (data->irq_enabled) {
374 disable_irq(data->irq);358 disable_irq(data->irq);
375 data->irq_enabled = false;359 data->irq_enabled = false;
376 }360 }
377 }361 }
378 362
379 data->mode = mode;
380 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
381
382 return 0;363 return 0;
383}364}
384 365
@@ -467,8 +448,7 @@ static struct thermal_zone_device_ops imx_tz_ops = { · 82 unmodified lines
467 .bind = imx_bind,448 .bind = imx_bind,
468 .unbind = imx_unbind,449 .unbind = imx_unbind,
469 .get_temp = imx_get_temp,450 .get_temp = imx_get_temp,
470 .get_mode = imx_get_mode,451 .change_mode = imx_change_mode,
471 .set_mode = imx_set_mode,
472 .get_trip_type = imx_get_trip_type,452 .get_trip_type = imx_get_trip_type,
473 .get_trip_temp = imx_get_trip_temp,453 .get_trip_temp = imx_get_trip_temp,
474 .get_crit_temp = imx_get_crit_temp,454 .get_crit_temp = imx_get_crit_temp,
@@ -832,7 +812,9 @@ static int imx_thermal_probe(struct platform_device *pdev) · 357 unmodified lines
832 data->socdata->measure_temp_mask);812 data->socdata->measure_temp_mask);
833 813
834 data->irq_enabled = true;814 data->irq_enabled = true;
835 data->mode = THERMAL_DEVICE_ENABLED;815 ret = thermal_zone_device_enable(data->tz);
816 if (ret)
817 goto thermal_zone_unregister;
836 818
837 ret = devm_request_threaded_irq(&pdev->dev, data->irq,819 ret = devm_request_threaded_irq(&pdev->dev, data->irq,
838 imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,820 imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
@@ -874,19 +856,18 @@ static int imx_thermal_remove(struct platform_device *pdev) · 35 unmodified lines
874static int __maybe_unused imx_thermal_suspend(struct device *dev)856static int __maybe_unused imx_thermal_suspend(struct device *dev)
875{857{
876 struct imx_thermal_data *data = dev_get_drvdata(dev);858 struct imx_thermal_data *data = dev_get_drvdata(dev);
877 struct regmap *map = data->tempmon;859 int ret;
878 860
879 /*861 /*
880 * Need to disable thermal sensor, otherwise, when thermal core862 * Need to disable thermal sensor, otherwise, when thermal core
881 * try to get temperature before thermal sensor resume, a wrong863 * try to get temperature before thermal sensor resume, a wrong
882 * temperature will be read as the thermal sensor is powered864 * temperature will be read as the thermal sensor is powered
883 * down.865 * down. This is done in change_mode() operation called from
866 * thermal_zone_device_disable()
884 */867 */
885 regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,868 ret = thermal_zone_device_disable(data->tz);
886 data->socdata->measure_temp_mask);869 if (ret)
887 regmap_write(map, data->socdata->sensor_ctrl + REG_SET,870 return ret;
888 data->socdata->power_down_mask);
889 data->mode = THERMAL_DEVICE_DISABLED;
890 clk_disable_unprepare(data->thermal_clk);871 clk_disable_unprepare(data->thermal_clk);
891 872
892 return 0;873 return 0;
@@ -895,18 +876,15 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev) · 2 unmodified lines
895static int __maybe_unused imx_thermal_resume(struct device *dev)876static int __maybe_unused imx_thermal_resume(struct device *dev)
896{877{
897 struct imx_thermal_data *data = dev_get_drvdata(dev);878 struct imx_thermal_data *data = dev_get_drvdata(dev);
898 struct regmap *map = data->tempmon;
899 int ret;879 int ret;
900 880
901 ret = clk_prepare_enable(data->thermal_clk);881 ret = clk_prepare_enable(data->thermal_clk);
902 if (ret)882 if (ret)
903 return ret;883 return ret;
904 /* Enabled thermal sensor after resume */884 /* Enabled thermal sensor after resume */
905 regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,885 ret = thermal_zone_device_enable(data->tz);
906 data->socdata->power_down_mask);886 if (ret)
907 regmap_write(map, data->socdata->sensor_ctrl + REG_SET,887 return ret;
908 data->socdata->measure_temp_mask);
909 data->mode = THERMAL_DEVICE_ENABLED;
910 888
911 return 0;889 return 0;
912}890}
drivers/thermal/intel/int340x_thermal/int3400_thermal.c+7−31
@@ -48,7 +48,6 @@ struct int3400_thermal_priv { · 47 unmodified lines
48 struct acpi_device *adev;48 struct acpi_device *adev;
49 struct platform_device *pdev;49 struct platform_device *pdev;
50 struct thermal_zone_device *thermal;50 struct thermal_zone_device *thermal;
51 int mode;
52 int art_count;51 int art_count;
53 struct art *arts;52 struct art *arts;
54 int trt_count;53 int trt_count;
@@ -383,42 +382,20 @@ static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, · 328 unmodified lines
383 return 0;382 return 0;
384}383}
385 384
386static int int3400_thermal_get_mode(struct thermal_zone_device *thermal,385static int int3400_thermal_change_mode(struct thermal_zone_device *thermal,
387 enum thermal_device_mode *mode)386 enum thermal_device_mode mode)
388{387{
389 struct int3400_thermal_priv *priv = thermal->devdata;388 struct int3400_thermal_priv *priv = thermal->devdata;
390
391 if (!priv)
392 return -EINVAL;
393
394 *mode = priv->mode;
395
396 return 0;
397}
398
399static int int3400_thermal_set_mode(struct thermal_zone_device *thermal,
400 enum thermal_device_mode mode)
401{
402 struct int3400_thermal_priv *priv = thermal->devdata;
403 bool enable;
404 int result = 0;389 int result = 0;
405 390
406 if (!priv)391 if (!priv)
407 return -EINVAL;392 return -EINVAL;
408 393
409 if (mode == THERMAL_DEVICE_ENABLED)394 if (mode != thermal->mode)
410 enable = true;
411 else if (mode == THERMAL_DEVICE_DISABLED)
412 enable = false;
413 else
414 return -EINVAL;
415
416 if (enable != priv->mode) {
417 priv->mode = enable;
418 result = int3400_thermal_run_osc(priv->adev->handle,395 result = int3400_thermal_run_osc(priv->adev->handle,
419 priv->current_uuid_index,396 priv->current_uuid_index,
420 enable);397 mode == THERMAL_DEVICE_ENABLED);
421 }398
422 399
423 evaluate_odvp(priv);400 evaluate_odvp(priv);
424 401
@@ -427,8 +404,7 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, · 2 unmodified lines
427 404
428static struct thermal_zone_device_ops int3400_thermal_ops = {405static struct thermal_zone_device_ops int3400_thermal_ops = {
429 .get_temp = int3400_thermal_get_temp,406 .get_temp = int3400_thermal_get_temp,
430 .get_mode = int3400_thermal_get_mode,407 .change_mode = int3400_thermal_change_mode,
431 .set_mode = int3400_thermal_set_mode,
432};408};
433 409
434static struct thermal_zone_params int3400_thermal_params = {410static struct thermal_zone_params int3400_thermal_params = {
drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c+5−0
@@ -259,9 +259,14 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, · 258 unmodified lines
259 ret = PTR_ERR(int34x_thermal_zone->zone);259 ret = PTR_ERR(int34x_thermal_zone->zone);
260 goto err_thermal_zone;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 return int34x_thermal_zone;266 return int34x_thermal_zone;
264 267
268err_enable:
269 thermal_zone_device_unregister(int34x_thermal_zone->zone);
265err_thermal_zone:270err_thermal_zone:
266 acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);271 acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
267 kfree(int34x_thermal_zone->aux_trips);272 kfree(int34x_thermal_zone->aux_trips);
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c+1−1
@@ -43,7 +43,7 @@ · 42 unmodified lines
43#define PCI_DEVICE_ID_PROC_ICL_THERMAL 0x8a0343#define PCI_DEVICE_ID_PROC_ICL_THERMAL 0x8a03
44 44
45/* JasperLake thermal reporting device */45/* JasperLake thermal reporting device */
46#define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x450346#define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4E03
47 47
48/* TigerLake thermal reporting device */48/* TigerLake thermal reporting device */
49#define PCI_DEVICE_ID_PROC_TGL_THERMAL 0x9A0349#define PCI_DEVICE_ID_PROC_TGL_THERMAL 0x9A03
drivers/thermal/intel/intel_pch_thermal.c+8−0
@@ -24,6 +24,7 @@ · 23 unmodified lines
24#define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */24#define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */
25#define PCH_THERMAL_DID_CNL 0x9Df9 /* CNL PCH */25#define PCH_THERMAL_DID_CNL 0x9Df9 /* CNL PCH */
26#define PCH_THERMAL_DID_CNL_H 0xA379 /* CNL-H PCH */26#define PCH_THERMAL_DID_CNL_H 0xA379 /* CNL-H PCH */
27#define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */
27#define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */28#define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */
28 29
29/* Wildcat Point-LP PCH Thermal registers */30/* Wildcat Point-LP PCH Thermal registers */
@@ -352,9 +353,14 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev, · 322 unmodified lines
352 err = PTR_ERR(ptd->tzd);353 err = PTR_ERR(ptd->tzd);
353 goto error_cleanup;354 goto error_cleanup;
354 }355 }
356 err = thermal_zone_device_enable(ptd->tzd);
357 if (err)
358 goto err_unregister;
355 359
356 return 0;360 return 0;
357 361
362err_unregister:
363 thermal_zone_device_unregister(ptd->tzd);
358error_cleanup:364error_cleanup:
359 iounmap(ptd->hw_base);365 iounmap(ptd->hw_base);
360error_release:366error_release:
@@ -405,6 +411,8 @@ static const struct pci_device_id intel_pch_thermal_id[] = { · 44 unmodified lines
405 .driver_data = board_cnl, },411 .driver_data = board_cnl, },
406 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H),412 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H),
407 .driver_data = board_cnl, },413 .driver_data = board_cnl, },
414 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_LP),
415 .driver_data = board_cnl, },
408 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CML_H),416 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CML_H),
409 .driver_data = board_cml, },417 .driver_data = board_cml, },
410 { 0, },418 { 0, },
drivers/thermal/intel/intel_quark_dts_thermal.c+6−28
@@ -103,7 +103,6 @@ struct soc_sensor_entry { · 102 unmodified lines
103 bool locked;103 bool locked;
104 u32 store_ptps;104 u32 store_ptps;
105 u32 store_dts_enable;105 u32 store_dts_enable;
106 enum thermal_device_mode mode;
107 struct thermal_zone_device *tzone;106 struct thermal_zone_device *tzone;
108};107};
109 108
@@ -127,10 +126,8 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) · 17 unmodified lines
127 if (ret)126 if (ret)
128 return ret;127 return ret;
129 128
130 if (out & QRK_DTS_ENABLE_BIT) {129 if (out & QRK_DTS_ENABLE_BIT)
131 aux_entry->mode = THERMAL_DEVICE_ENABLED;
132 return 0;130 return 0;
133 }
134 131
135 if (!aux_entry->locked) {132 if (!aux_entry->locked) {
136 out |= QRK_DTS_ENABLE_BIT;133 out |= QRK_DTS_ENABLE_BIT;
@@ -138,10 +135,7 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) · 1 unmodified line
138 QRK_DTS_REG_OFFSET_ENABLE, out);135 QRK_DTS_REG_OFFSET_ENABLE, out);
139 if (ret)136 if (ret)
140 return ret;137 return ret;
141
142 aux_entry->mode = THERMAL_DEVICE_ENABLED;
143 } else {138 } else {
144 aux_entry->mode = THERMAL_DEVICE_DISABLED;
145 pr_info("DTS is locked. Cannot enable DTS\n");139 pr_info("DTS is locked. Cannot enable DTS\n");
146 ret = -EPERM;140 ret = -EPERM;
147 }141 }
@@ -160,10 +154,8 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) · 12 unmodified lines
160 if (ret)154 if (ret)
161 return ret;155 return ret;
162 156
163 if (!(out & QRK_DTS_ENABLE_BIT)) {157 if (!(out & QRK_DTS_ENABLE_BIT))
164 aux_entry->mode = THERMAL_DEVICE_DISABLED;
165 return 0;158 return 0;
166 }
167 159
168 if (!aux_entry->locked) {160 if (!aux_entry->locked) {
169 out &= ~QRK_DTS_ENABLE_BIT;161 out &= ~QRK_DTS_ENABLE_BIT;
@@ -172,10 +164,7 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) · 2 unmodified lines
172 164
173 if (ret)165 if (ret)
174 return ret;166 return ret;
175
176 aux_entry->mode = THERMAL_DEVICE_DISABLED;
177 } else {167 } else {
178 aux_entry->mode = THERMAL_DEVICE_ENABLED;
179 pr_info("DTS is locked. Cannot disable DTS\n");168 pr_info("DTS is locked. Cannot disable DTS\n");
180 ret = -EPERM;169 ret = -EPERM;
181 }170 }
@@ -309,16 +298,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, · 127 unmodified lines
309 return 0;298 return 0;
310}299}
311 300
312static int sys_get_mode(struct thermal_zone_device *tzd,301static int sys_change_mode(struct thermal_zone_device *tzd,
313 enum thermal_device_mode *mode)302 enum thermal_device_mode mode)
314{
315 struct soc_sensor_entry *aux_entry = tzd->devdata;
316 *mode = aux_entry->mode;
317 return 0;
318}
319
320static int sys_set_mode(struct thermal_zone_device *tzd,
321 enum thermal_device_mode mode)
322{303{
323 int ret;304 int ret;
324 305
@@ -338,8 +319,7 @@ static struct thermal_zone_device_ops tzone_ops = { · 13 unmodified lines
338 .get_trip_type = sys_get_trip_type,319 .get_trip_type = sys_get_trip_type,
339 .set_trip_temp = sys_set_trip_temp,320 .set_trip_temp = sys_set_trip_temp,
340 .get_crit_temp = sys_get_crit_temp,321 .get_crit_temp = sys_get_crit_temp,
341 .get_mode = sys_get_mode,322 .change_mode = sys_change_mode,
342 .set_mode = sys_set_mode,
343};323};
344 324
345static void free_soc_dts(struct soc_sensor_entry *aux_entry)325static void free_soc_dts(struct soc_sensor_entry *aux_entry)
@@ -414,9 +394,7 @@ static struct soc_sensor_entry *alloc_soc_dts(void) · 68 unmodified lines
414 goto err_ret;394 goto err_ret;
415 }395 }
416 396
417 mutex_lock(&dts_update_mutex);397 err = thermal_zone_device_enable(aux_entry->tzone);
418 err = soc_dts_enable(aux_entry->tzone);
419 mutex_unlock(&dts_update_mutex);
420 if (err)398 if (err)
421 goto err_aux_status;399 goto err_aux_status;
422 400
drivers/thermal/intel/intel_soc_dts_iosf.c+3−0
@@ -329,6 +329,9 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, · 328 unmodified lines
329 ret = PTR_ERR(dts->tzone);329 ret = PTR_ERR(dts->tzone);
330 goto err_ret;330 goto err_ret;
331 }331 }
332 ret = thermal_zone_device_enable(dts->tzone);
333 if (ret)
334 goto err_enable;
332 335
333 ret = soc_dts_enable(id);336 ret = soc_dts_enable(id);
334 if (ret)337 if (ret)
drivers/thermal/intel/x86_pkg_temp_thermal.c+6−0
@@ -363,6 +363,12 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) · 362 unmodified lines
363 kfree(zonedev);363 kfree(zonedev);
364 return err;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 /* Store MSR value for package thermal interrupt, to restore at exit */372 /* Store MSR value for package thermal interrupt, to restore at exit */
367 rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low,373 rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low,
368 zonedev->msr_pkg_therm_high);374 zonedev->msr_pkg_therm_high);
drivers/thermal/kirkwood_thermal.c+7−0
@@ -65,6 +65,7 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) · 64 unmodified lines
65 struct thermal_zone_device *thermal = NULL;65 struct thermal_zone_device *thermal = NULL;
66 struct kirkwood_thermal_priv *priv;66 struct kirkwood_thermal_priv *priv;
67 struct resource *res;67 struct resource *res;
68 int ret;
68 69
69 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);70 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
70 if (!priv)71 if (!priv)
@@ -82,6 +83,12 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) · 11 unmodified lines
82 "Failed to register thermal zone device\n");83 "Failed to register thermal zone device\n");
83 return PTR_ERR(thermal);84 return PTR_ERR(thermal);
84 }85 }
86 ret = thermal_zone_device_enable(thermal);
87 if (ret) {
88 thermal_zone_device_unregister(thermal);
89 dev_err(&pdev->dev, "Failed to enable thermal zone device\n");
90 return ret;
91 }
85 92
86 platform_set_drvdata(pdev, thermal);93 platform_set_drvdata(pdev, thermal);
87 94
drivers/thermal/mtk_thermal.c+181−53
@@ -38,6 +38,7 @@ · 37 unmodified lines
38#define TEMP_MONIDET0 0x01438#define TEMP_MONIDET0 0x014
39#define TEMP_MONIDET1 0x01839#define TEMP_MONIDET1 0x018
40#define TEMP_MSRCTL0 0x03840#define TEMP_MSRCTL0 0x038
41#define TEMP_MSRCTL1 0x03c
41#define TEMP_AHBPOLL 0x04042#define TEMP_AHBPOLL 0x040
42#define TEMP_AHBTO 0x04443#define TEMP_AHBTO 0x044
43#define TEMP_ADCPNP0 0x04844#define TEMP_ADCPNP0 0x048
@@ -120,18 +121,32 @@ · 76 unmodified lines
120 * MT2701 has 3 sensors and needs 3 VTS calibration data.121 * MT2701 has 3 sensors and needs 3 VTS calibration data.
121 * MT2712 has 4 sensors and needs 4 VTS calibration data.122 * MT2712 has 4 sensors and needs 4 VTS calibration data.
122 */123 */
123#define CALIB_BUF0_VALID BIT(0)124#define CALIB_BUF0_VALID_V1 BIT(0)
124#define CALIB_BUF1_ADC_GE(x) (((x) >> 22) & 0x3ff)125#define CALIB_BUF1_ADC_GE_V1(x) (((x) >> 22) & 0x3ff)
125#define CALIB_BUF0_VTS_TS1(x) (((x) >> 17) & 0x1ff)126#define CALIB_BUF0_VTS_TS1_V1(x) (((x) >> 17) & 0x1ff)
126#define CALIB_BUF0_VTS_TS2(x) (((x) >> 8) & 0x1ff)127#define CALIB_BUF0_VTS_TS2_V1(x) (((x) >> 8) & 0x1ff)
127#define CALIB_BUF1_VTS_TS3(x) (((x) >> 0) & 0x1ff)128#define CALIB_BUF1_VTS_TS3_V1(x) (((x) >> 0) & 0x1ff)
128#define CALIB_BUF2_VTS_TS4(x) (((x) >> 23) & 0x1ff)129#define CALIB_BUF2_VTS_TS4_V1(x) (((x) >> 23) & 0x1ff)
129#define CALIB_BUF2_VTS_TS5(x) (((x) >> 5) & 0x1ff)130#define CALIB_BUF2_VTS_TS5_V1(x) (((x) >> 5) & 0x1ff)
130#define CALIB_BUF2_VTS_TSABB(x) (((x) >> 14) & 0x1ff)131#define CALIB_BUF2_VTS_TSABB_V1(x) (((x) >> 14) & 0x1ff)
131#define CALIB_BUF0_DEGC_CALI(x) (((x) >> 1) & 0x3f)132#define CALIB_BUF0_DEGC_CALI_V1(x) (((x) >> 1) & 0x3f)
132#define CALIB_BUF0_O_SLOPE(x) (((x) >> 26) & 0x3f)133#define CALIB_BUF0_O_SLOPE_V1(x) (((x) >> 26) & 0x3f)
133#define CALIB_BUF0_O_SLOPE_SIGN(x) (((x) >> 7) & 0x1)134#define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1)
134#define CALIB_BUF1_ID(x) (((x) >> 9) & 0x1)135#define CALIB_BUF1_ID_V1(x) (((x) >> 9) & 0x1)
136
137/*
138 * Layout of the fuses providing the calibration data
139 * These macros could be used for MT7622.
140 */
141#define CALIB_BUF0_ADC_OE_V2(x) (((x) >> 22) & 0x3ff)
142#define CALIB_BUF0_ADC_GE_V2(x) (((x) >> 12) & 0x3ff)
143#define CALIB_BUF0_DEGC_CALI_V2(x) (((x) >> 6) & 0x3f)
144#define CALIB_BUF0_O_SLOPE_V2(x) (((x) >> 0) & 0x3f)
145#define CALIB_BUF1_VTS_TS1_V2(x) (((x) >> 23) & 0x1ff)
146#define CALIB_BUF1_VTS_TS2_V2(x) (((x) >> 14) & 0x1ff)
147#define CALIB_BUF1_VTS_TSABB_V2(x) (((x) >> 5) & 0x1ff)
148#define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1)
149#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1)
135 150
136enum {151enum {
137 VTS1,152 VTS1,
@@ -143,6 +158,11 @@ enum { · 5 unmodified lines
143 MAX_NUM_VTS,158 MAX_NUM_VTS,
144};159};
145 160
161enum mtk_thermal_version {
162 MTK_THERMAL_V1 = 1,
163 MTK_THERMAL_V2,
164};
165
146/* MT2701 thermal sensors */166/* MT2701 thermal sensors */
147#define MT2701_TS1 0167#define MT2701_TS1 0
148#define MT2701_TS2 1168#define MT2701_TS2 1
@@ -248,6 +268,7 @@ struct mtk_thermal_data { · 99 unmodified lines
248 const int *controller_offset;268 const int *controller_offset;
249 bool need_switch_bank;269 bool need_switch_bank;
250 struct thermal_bank_cfg bank_data[MAX_NUM_ZONES];270 struct thermal_bank_cfg bank_data[MAX_NUM_ZONES];
271 enum mtk_thermal_version version;
251};272};
252 273
253struct mtk_thermal {274struct mtk_thermal {
@@ -261,8 +282,10 @@ struct mtk_thermal { · 7 unmodified lines
261 282
262 /* Calibration values */283 /* Calibration values */
263 s32 adc_ge;284 s32 adc_ge;
285 s32 adc_oe;
264 s32 degc_cali;286 s32 degc_cali;
265 s32 o_slope;287 s32 o_slope;
288 s32 o_slope_sign;
266 s32 vts[MAX_NUM_VTS];289 s32 vts[MAX_NUM_VTS];
267 290
268 const struct mtk_thermal_data *conf;291 const struct mtk_thermal_data *conf;
@@ -401,6 +424,7 @@ static const struct mtk_thermal_data mt8173_thermal_data = { · 132 unmodified lines
401 .msr = mt8173_msr,424 .msr = mt8173_msr,
402 .adcpnp = mt8173_adcpnp,425 .adcpnp = mt8173_adcpnp,
403 .sensor_mux_values = mt8173_mux_values,426 .sensor_mux_values = mt8173_mux_values,
427 .version = MTK_THERMAL_V1,
404};428};
405 429
406/*430/*
@@ -431,6 +455,7 @@ static const struct mtk_thermal_data mt2701_thermal_data = { · 24 unmodified lines
431 .msr = mt2701_msr,455 .msr = mt2701_msr,
432 .adcpnp = mt2701_adcpnp,456 .adcpnp = mt2701_adcpnp,
433 .sensor_mux_values = mt2701_mux_values,457 .sensor_mux_values = mt2701_mux_values,
458 .version = MTK_THERMAL_V1,
434};459};
435 460
436/*461/*
@@ -461,6 +486,7 @@ static const struct mtk_thermal_data mt2712_thermal_data = { · 24 unmodified lines
461 .msr = mt2712_msr,486 .msr = mt2712_msr,
462 .adcpnp = mt2712_adcpnp,487 .adcpnp = mt2712_adcpnp,
463 .sensor_mux_values = mt2712_mux_values,488 .sensor_mux_values = mt2712_mux_values,
489 .version = MTK_THERMAL_V1,
464};490};
465 491
466/*492/*
@@ -485,6 +511,7 @@ static const struct mtk_thermal_data mt7622_thermal_data = { · 18 unmodified lines
485 .msr = mt7622_msr,511 .msr = mt7622_msr,
486 .adcpnp = mt7622_adcpnp,512 .adcpnp = mt7622_adcpnp,
487 .sensor_mux_values = mt7622_mux_values,513 .sensor_mux_values = mt7622_mux_values,
514 .version = MTK_THERMAL_V2,
488};515};
489 516
490/*517/*
@@ -517,6 +544,7 @@ static const struct mtk_thermal_data mt8183_thermal_data = { · 26 unmodified lines
517 .msr = mt8183_msr,544 .msr = mt8183_msr,
518 .adcpnp = mt8183_adcpnp,545 .adcpnp = mt8183_adcpnp,
519 .sensor_mux_values = mt8183_mux_values,546 .sensor_mux_values = mt8183_mux_values,
547 .version = MTK_THERMAL_V1,
520};548};
521 549
522/**550/**
@@ -528,7 +556,7 @@ static const struct mtk_thermal_data mt8183_thermal_data = { · 5 unmodified lines
528 * This converts the raw ADC value to mcelsius using the SoC specific556 * This converts the raw ADC value to mcelsius using the SoC specific
529 * calibration constants557 * calibration constants
530 */558 */
531static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw)559static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw)
532{560{
533 s32 tmp;561 s32 tmp;
534 562
@@ -543,6 +571,36 @@ static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw) · 8 unmodified lines
543 return mt->degc_cali * 500 - tmp;571 return mt->degc_cali * 500 - tmp;
544}572}
545 573
574static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw)
575{
576 s32 format_1 = 0;
577 s32 format_2 = 0;
578 s32 g_oe = 1;
579 s32 g_gain = 1;
580 s32 g_x_roomt = 0;
581 s32 tmp = 0;
582
583 if (raw == 0)
584 return 0;
585
586 raw &= 0xfff;
587 g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12);
588 g_oe = mt->adc_oe - 512;
589 format_1 = mt->vts[VTS2] + 3105 - g_oe;
590 format_2 = (mt->degc_cali * 10) >> 1;
591 g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain;
592
593 tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt;
594 tmp = tmp * 10 * 100 / 11;
595
596 if (mt->o_slope_sign == 0)
597 tmp = tmp / (165 - mt->o_slope);
598 else
599 tmp = tmp / (165 + mt->o_slope);
600
601 return (format_2 - tmp) * 100;
602}
603
546/**604/**
547 * mtk_thermal_get_bank - get bank605 * mtk_thermal_get_bank - get bank
548 * @bank: The bank606 * @bank: The bank
@@ -596,9 +654,13 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) · 47 unmodified lines
596 for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {654 for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
597 raw = readl(mt->thermal_base + conf->msr[i]);655 raw = readl(mt->thermal_base + conf->msr[i]);
598 656
599 temp = raw_to_mcelsius(mt,657 if (mt->conf->version == MTK_THERMAL_V1) {
600 conf->bank_data[bank->id].sensors[i],658 temp = raw_to_mcelsius_v1(
601 raw);659 mt, conf->bank_data[bank->id].sensors[i], raw);
660 } else {
661 temp = raw_to_mcelsius_v2(
662 mt, conf->bank_data[bank->id].sensors[i], raw);
663 }
602 664
603 /*665 /*
604 * The first read of a sensor often contains very high bogus666 * The first read of a sensor often contains very high bogus
@@ -700,9 +762,11 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num, · 95 unmodified lines
700 writel(auxadc_phys_base + AUXADC_CON1_CLR_V,762 writel(auxadc_phys_base + AUXADC_CON1_CLR_V,
701 controller_base + TEMP_ADCMUXADDR);763 controller_base + TEMP_ADCMUXADDR);
702 764
703 /* AHB address for pnp sensor mux selection */765 if (mt->conf->version == MTK_THERMAL_V1) {
704 writel(apmixed_phys_base + APMIXED_SYS_TS_CON1,766 /* AHB address for pnp sensor mux selection */
705 controller_base + TEMP_PNPMUXADDR);767 writel(apmixed_phys_base + APMIXED_SYS_TS_CON1,
768 controller_base + TEMP_PNPMUXADDR);
769 }
706 770
707 /* AHB value for auxadc enable */771 /* AHB value for auxadc enable */
708 writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN);772 writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN);
@@ -759,6 +823,68 @@ static u64 of_get_phys_base(struct device_node *np) · 50 unmodified lines
759 return of_translate_address(np, regaddr_p);823 return of_translate_address(np, regaddr_p);
760}824}
761 825
826static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf)
827{
828 int i;
829
830 if (!(buf[0] & CALIB_BUF0_VALID_V1))
831 return -EINVAL;
832
833 mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]);
834
835 for (i = 0; i < mt->conf->num_sensors; i++) {
836 switch (mt->conf->vts_index[i]) {
837 case VTS1:
838 mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]);
839 break;
840 case VTS2:
841 mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]);
842 break;
843 case VTS3:
844 mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]);
845 break;
846 case VTS4:
847 mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]);
848 break;
849 case VTS5:
850 mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]);
851 break;
852 case VTSABB:
853 mt->vts[VTSABB] =
854 CALIB_BUF2_VTS_TSABB_V1(buf[2]);
855 break;
856 default:
857 break;
858 }
859 }
860
861 mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]);
862 if (CALIB_BUF1_ID_V1(buf[1]) &
863 CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0]))
864 mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]);
865 else
866 mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]);
867
868 return 0;
869}
870
871static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf)
872{
873 if (!CALIB_BUF1_VALID_V2(buf[1]))
874 return -EINVAL;
875
876 mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]);
877 mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]);
878 mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]);
879 mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]);
880 mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]);
881 mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]);
882 mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]);
883 mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]);
884
885 return 0;
886}
887
762static int mtk_thermal_get_calibration_data(struct device *dev,888static int mtk_thermal_get_calibration_data(struct device *dev,
763 struct mtk_thermal *mt)889 struct mtk_thermal *mt)
764{890{
@@ -794,42 +920,14 @@ static int mtk_thermal_get_calibration_data(struct device *dev, · 29 unmodified lines
794 goto out;920 goto out;
795 }921 }
796 922
797 if (buf[0] & CALIB_BUF0_VALID) {923 if (mt->conf->version == MTK_THERMAL_V1)
798 mt->adc_ge = CALIB_BUF1_ADC_GE(buf[1]);924 ret = mtk_thermal_extract_efuse_v1(mt, buf);
799 925 else
800 for (i = 0; i < mt->conf->num_sensors; i++) {926 ret = mtk_thermal_extract_efuse_v2(mt, buf);
801 switch (mt->conf->vts_index[i]) {
802 case VTS1:
803 mt->vts[VTS1] = CALIB_BUF0_VTS_TS1(buf[0]);
804 break;
805 case VTS2:
806 mt->vts[VTS2] = CALIB_BUF0_VTS_TS2(buf[0]);
807 break;
808 case VTS3:
809 mt->vts[VTS3] = CALIB_BUF1_VTS_TS3(buf[1]);
810 break;
811 case VTS4:
812 mt->vts[VTS4] = CALIB_BUF2_VTS_TS4(buf[2]);
813 break;
814 case VTS5:
815 mt->vts[VTS5] = CALIB_BUF2_VTS_TS5(buf[2]);
816 break;
817 case VTSABB:
818 mt->vts[VTSABB] = CALIB_BUF2_VTS_TSABB(buf[2]);
819 break;
820 default:
821 break;
822 }
823 }
824 927
825 mt->degc_cali = CALIB_BUF0_DEGC_CALI(buf[0]);928 if (ret) {
826 if (CALIB_BUF1_ID(buf[1]) &
827 CALIB_BUF0_O_SLOPE_SIGN(buf[0]))
828 mt->o_slope = -CALIB_BUF0_O_SLOPE(buf[0]);
829 else
830 mt->o_slope = CALIB_BUF0_O_SLOPE(buf[0]);
831 } else {
832 dev_info(dev, "Device not calibrated, using default calibration values\n");929 dev_info(dev, "Device not calibrated, using default calibration values\n");
930 ret = 0;
833 }931 }
834 932
835out:933out:
@@ -863,6 +961,28 @@ static const struct of_device_id mtk_thermal_of_match[] = { · 27 unmodified lines
863};961};
864MODULE_DEVICE_TABLE(of, mtk_thermal_of_match);962MODULE_DEVICE_TABLE(of, mtk_thermal_of_match);
865 963
964static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base)
965{
966 int tmp;
967
968 tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1);
969 tmp &= ~(0x37);
970 tmp |= 0x1;
971 writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1);
972 udelay(200);
973}
974
975static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt,
976 void __iomem *auxadc_base)
977{
978 int tmp;
979
980 writel(0x800, auxadc_base + AUXADC_CON1_SET_V);
981 writel(0x1, mt->thermal_base + TEMP_MONCTL0);
982 tmp = readl(mt->thermal_base + TEMP_MSRCTL1);
983 writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1);
984}
985
866static int mtk_thermal_probe(struct platform_device *pdev)986static int mtk_thermal_probe(struct platform_device *pdev)
867{987{
868 int ret, i, ctrl_id;988 int ret, i, ctrl_id;
@@ -871,6 +991,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) · 2 unmodified lines
871 struct resource *res;991 struct resource *res;
872 u64 auxadc_phys_base, apmixed_phys_base;992 u64 auxadc_phys_base, apmixed_phys_base;
873 struct thermal_zone_device *tzdev;993 struct thermal_zone_device *tzdev;
994 void __iomem *apmixed_base, *auxadc_base;
874 995
875 mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);996 mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
876 if (!mt)997 if (!mt)
@@ -905,6 +1026,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) · 28 unmodified lines
905 return -ENODEV;1026 return -ENODEV;
906 }1027 }
907 1028
1029 auxadc_base = of_iomap(auxadc, 0);
908 auxadc_phys_base = of_get_phys_base(auxadc);1030 auxadc_phys_base = of_get_phys_base(auxadc);
909 1031
910 of_node_put(auxadc);1032 of_node_put(auxadc);
@@ -920,6 +1042,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) · 9 unmodified lines
920 return -ENODEV;1042 return -ENODEV;
921 }1043 }
922 1044
1045 apmixed_base = of_iomap(apmixedsys, 0);
923 apmixed_phys_base = of_get_phys_base(apmixedsys);1046 apmixed_phys_base = of_get_phys_base(apmixedsys);
924 1047
925 of_node_put(apmixedsys);1048 of_node_put(apmixedsys);
@@ -945,6 +1068,11 @@ static int mtk_thermal_probe(struct platform_device *pdev) · 19 unmodified lines
945 goto err_disable_clk_auxadc;1068 goto err_disable_clk_auxadc;
946 }1069 }
947 1070
1071 if (mt->conf->version == MTK_THERMAL_V2) {
1072 mtk_thermal_turn_on_buffer(apmixed_base);
1073 mtk_thermal_release_periodic_ts(mt, auxadc_base);
1074 }
1075
948 for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)1076 for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
949 for (i = 0; i < mt->conf->num_banks; i++)1077 for (i = 0; i < mt->conf->num_banks; i++)
950 mtk_thermal_init_bank(mt, i, apmixed_phys_base,1078 mtk_thermal_init_bank(mt, i, apmixed_phys_base,
drivers/thermal/qcom/tsens-v0_1.c+143−1
@@ -48,6 +48,63 @@ · 47 unmodified lines
48#define MSM8916_CAL_SEL_MASK 0xe000000048#define MSM8916_CAL_SEL_MASK 0xe0000000
49#define MSM8916_CAL_SEL_SHIFT 2949#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/* eeprom layout data for 8974 */108/* eeprom layout data for 8974 */
52#define BASE1_MASK 0xff109#define BASE1_MASK 0xff
53#define S0_P1_MASK 0x3f00110#define S0_P1_MASK 0x3f00
@@ -189,6 +246,76 @@ static int calibrate_8916(struct tsens_priv *priv) · 135 unmodified lines
189 return 0;246 return 0;
190}247}
191 248
249static int calibrate_8939(struct tsens_priv *priv)
250{
251 int base0 = 0, base1 = 0, i;
252 u32 p1[10], p2[10];
253 int mode = 0;
254 u32 *qfprom_cdata;
255 u32 cdata[6];
256
257 qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
258 if (IS_ERR(qfprom_cdata))
259 return PTR_ERR(qfprom_cdata);
260
261 /* Mapping between qfprom nvmem and calibration data */
262 cdata[0] = qfprom_cdata[12];
263 cdata[1] = qfprom_cdata[13];
264 cdata[2] = qfprom_cdata[0];
265 cdata[3] = qfprom_cdata[1];
266 cdata[4] = qfprom_cdata[22];
267 cdata[5] = qfprom_cdata[21];
268
269 mode = (cdata[0] & MSM8939_CAL_SEL_MASK) >> MSM8939_CAL_SEL_SHIFT;
270 dev_dbg(priv->dev, "calibration mode is %d\n", mode);
271
272 switch (mode) {
273 case TWO_PT_CALIB:
274 base1 = (cdata[3] & MSM8939_BASE1_MASK) >> MSM8939_BASE1_SHIFT;
275 p2[0] = (cdata[0] & MSM8939_S0_P2_MASK) >> MSM8939_S0_P2_SHIFT;
276 p2[1] = (cdata[0] & MSM8939_S1_P2_MASK) >> MSM8939_S1_P2_SHIFT;
277 p2[2] = (cdata[1] & MSM8939_S2_P2_MASK) >> MSM8939_S2_P2_SHIFT;
278 p2[3] = (cdata[1] & MSM8939_S3_P2_MASK) >> MSM8939_S3_P2_SHIFT;
279 p2[4] = (cdata[1] & MSM8939_S4_P2_MASK) >> MSM8939_S4_P2_SHIFT;
280 p2[5] = (cdata[2] & MSM8939_S5_P2_MASK) >> MSM8939_S5_P2_SHIFT;
281 p2[6] = (cdata[2] & MSM8939_S6_P2_MASK) >> MSM8939_S6_P2_SHIFT;
282 p2[7] = (cdata[3] & MSM8939_S7_P2_MASK) >> MSM8939_S7_P2_SHIFT;
283 p2[8] = (cdata[3] & MSM8939_S8_P2_MASK) >> MSM8939_S8_P2_SHIFT;
284 p2[9] = (cdata[4] & MSM8939_S9_P2_MASK_0_4) >> MSM8939_S9_P2_SHIFT_0_4;
285 p2[9] |= ((cdata[5] & MSM8939_S9_P2_MASK_5) >> MSM8939_S9_P2_SHIFT_5) << 5;
286 for (i = 0; i < priv->num_sensors; i++)
287 p2[i] = (base1 + p2[i]) << 2;
288 fallthrough;
289 case ONE_PT_CALIB2:
290 base0 = (cdata[2] & MSM8939_BASE0_MASK) >> MSM8939_BASE0_SHIFT;
291 p1[0] = (cdata[0] & MSM8939_S0_P1_MASK) >> MSM8939_S0_P1_SHIFT;
292 p1[1] = (cdata[0] & MSM8939_S1_P1_MASK) >> MSM8939_S1_P1_SHIFT;
293 p1[2] = (cdata[0] & MSM8939_S2_P1_MASK_0_4) >> MSM8939_S2_P1_SHIFT_0_4;
294 p1[2] |= ((cdata[1] & MSM8939_S2_P1_MASK_5) >> MSM8939_S2_P1_SHIFT_5) << 5;
295 p1[3] = (cdata[1] & MSM8939_S3_P1_MASK) >> MSM8939_S3_P1_SHIFT;
296 p1[4] = (cdata[1] & MSM8939_S4_P1_MASK) >> MSM8939_S4_P1_SHIFT;
297 p1[5] = (cdata[2] & MSM8939_S5_P1_MASK) >> MSM8939_S5_P1_SHIFT;
298 p1[6] = (cdata[2] & MSM8939_S6_P1_MASK) >> MSM8939_S6_P1_SHIFT;
299 p1[7] = (cdata[3] & MSM8939_S7_P1_MASK) >> MSM8939_S7_P1_SHIFT;
300 p1[8] = (cdata[3] & MSM8939_S8_P1_MASK) >> MSM8939_S8_P1_SHIFT;
301 p1[9] = (cdata[4] & MSM8939_S9_P1_MASK) >> MSM8939_S9_P1_SHIFT;
302 for (i = 0; i < priv->num_sensors; i++)
303 p1[i] = ((base0) + p1[i]) << 2;
304 break;
305 default:
306 for (i = 0; i < priv->num_sensors; i++) {
307 p1[i] = 500;
308 p2[i] = 780;
309 }
310 break;
311 }
312
313 compute_intercept_slope(priv, p1, p2, mode);
314 kfree(qfprom_cdata);
315
316 return 0;
317}
318
192static int calibrate_8974(struct tsens_priv *priv)319static int calibrate_8974(struct tsens_priv *priv)
193{320{
194 int base1 = 0, base2 = 0, i;321 int base1 = 0, base2 = 0, i;
@@ -325,7 +452,7 @@ static int calibrate_8974(struct tsens_priv *priv) · 130 unmodified lines
325 return 0;452 return 0;
326}453}
327 454
328/* v0.1: 8916, 8974 */455/* v0.1: 8916, 8939, 8974 */
329 456
330static struct tsens_features tsens_v0_1_feat = {457static struct tsens_features tsens_v0_1_feat = {
331 .ver_major = VER_0_1,458 .ver_major = VER_0_1,
@@ -386,6 +513,21 @@ struct tsens_plat_data data_8916 = { · 54 unmodified lines
386 .fields = tsens_v0_1_regfields,513 .fields = tsens_v0_1_regfields,
387};514};
388 515
516static const struct tsens_ops ops_8939 = {
517 .init = init_common,
518 .calibrate = calibrate_8939,
519 .get_temp = get_temp_common,
520};
521
522struct tsens_plat_data data_8939 = {
523 .num_sensors = 10,
524 .ops = &ops_8939,
525 .hw_ids = (unsigned int []){ 0, 1, 2, 4, 5, 6, 7, 8, 9, 10 },
526
527 .feat = &tsens_v0_1_feat,
528 .fields = tsens_v0_1_regfields,
529};
530
389static const struct tsens_ops ops_8974 = {531static const struct tsens_ops ops_8974 = {
390 .init = init_common,532 .init = init_common,
391 .calibrate = calibrate_8974,533 .calibrate = calibrate_8974,
drivers/thermal/qcom/tsens.c+3−0
@@ -897,6 +897,9 @@ static const struct of_device_id tsens_table[] = { · 896 unmodified lines
897 {897 {
898 .compatible = "qcom,msm8916-tsens",898 .compatible = "qcom,msm8916-tsens",
899 .data = &data_8916,899 .data = &data_8916,
900 }, {
901 .compatible = "qcom,msm8939-tsens",
902 .data = &data_8939,
900 }, {903 }, {
901 .compatible = "qcom,msm8974-tsens",904 .compatible = "qcom,msm8974-tsens",
902 .data = &data_8974,905 .data = &data_8974,
drivers/thermal/qcom/tsens.h+1−1
@@ -585,7 +585,7 @@ int get_temp_common(const struct tsens_sensor *s, int *temp); · 584 unmodified lines
585extern struct tsens_plat_data data_8960;585extern struct tsens_plat_data data_8960;
586 586
587/* TSENS v0.1 targets */587/* TSENS v0.1 targets */
588extern struct tsens_plat_data data_8916, data_8974;588extern struct tsens_plat_data data_8916, data_8939, data_8974;
589 589
590/* TSENS v1 targets */590/* TSENS v1 targets */
591extern struct tsens_plat_data data_tsens_v1, data_8976;591extern struct tsens_plat_data data_tsens_v1, data_8976;
drivers/thermal/rcar_gen3_thermal.c+7−3
@@ -63,7 +63,7 @@ · 62 unmodified lines
63#define TSC_MAX_NUM 363#define TSC_MAX_NUM 3
64 64
65/* default THCODE values if FUSEs are missing */65/* default THCODE values if FUSEs are missing */
66static const int thcode[TSC_MAX_NUM][3] = {66static const int thcodes[TSC_MAX_NUM][3] = {
67 { 3397, 2800, 2221 },67 { 3397, 2800, 2221 },
68 { 3393, 2795, 2216 },68 { 3393, 2795, 2216 },
69 { 3389, 2805, 2237 },69 { 3389, 2805, 2237 },
@@ -172,7 +172,7 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp) · 102 unmodified lines
172 /* Read register and convert to mili Celsius */172 /* Read register and convert to mili Celsius */
173 reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;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 val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1,176 val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1,
177 tsc->coef.a1);177 tsc->coef.a1);
178 else178 else
@@ -314,6 +314,10 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { · 135 unmodified lines
314 .compatible = "renesas,r8a774b1-thermal",314 .compatible = "renesas,r8a774b1-thermal",
315 .data = &rcar_gen3_ths_tj_1,315 .data = &rcar_gen3_ths_tj_1,
316 },316 },
317 {
318 .compatible = "renesas,r8a774e1-thermal",
319 .data = &rcar_gen3_ths_tj_1,
320 },
317 {321 {
318 .compatible = "renesas,r8a7795-thermal",322 .compatible = "renesas,r8a7795-thermal",
319 .data = &rcar_gen3_ths_tj_1,323 .data = &rcar_gen3_ths_tj_1,
@@ -430,7 +434,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) · 110 unmodified lines
430 priv->tscs[i] = tsc;434 priv->tscs[i] = tsc;
431 435
432 priv->thermal_init(tsc);436 priv->thermal_init(tsc);
433 rcar_gen3_thermal_calc_coefs(tsc, ptat, thcode[i],437 rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i],
434 *rcar_gen3_ths_tj_1);438 *rcar_gen3_ths_tj_1);
435 439
436 zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,440 zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
drivers/thermal/rcar_thermal.c+8−1
@@ -550,12 +550,19 @@ static int rcar_thermal_probe(struct platform_device *pdev) · 549 unmodified lines
550 priv->zone = devm_thermal_zone_of_sensor_register(550 priv->zone = devm_thermal_zone_of_sensor_register(
551 dev, i, priv,551 dev, i, priv,
552 &rcar_thermal_zone_of_ops);552 &rcar_thermal_zone_of_ops);
553 else553 else {
554 priv->zone = thermal_zone_device_register(554 priv->zone = thermal_zone_device_register(
555 "rcar_thermal",555 "rcar_thermal",
556 1, 0, priv,556 1, 0, priv,
557 &rcar_thermal_zone_ops, NULL, 0,557 &rcar_thermal_zone_ops, NULL, 0,
558 idle);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 if (IS_ERR(priv->zone)) {566 if (IS_ERR(priv->zone)) {
560 dev_err(dev, "can't register thermal zone\n");567 dev_err(dev, "can't register thermal zone\n");
561 ret = PTR_ERR(priv->zone);568 ret = PTR_ERR(priv->zone);
drivers/thermal/rockchip_thermal.c+4−2
@@ -1068,8 +1068,10 @@ rockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor *sensor, bool on) · 1067 unmodified lines
1068{1068{
1069 struct thermal_zone_device *tzd = sensor->tzd;1069 struct thermal_zone_device *tzd = sensor->tzd;
1070 1070
1071 tzd->ops->set_mode(tzd,1071 if (on)
1072 on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);1072 thermal_zone_device_enable(tzd);
1073 else
1074 thermal_zone_device_disable(tzd);
1073}1075}
1074 1076
1075static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)1077static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
drivers/thermal/spear_thermal.c+7−0
@@ -131,6 +131,11 @@ static int spear_thermal_probe(struct platform_device *pdev) · 130 unmodified lines
131 ret = PTR_ERR(spear_thermal);131 ret = PTR_ERR(spear_thermal);
132 goto disable_clk;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 platform_set_drvdata(pdev, spear_thermal);140 platform_set_drvdata(pdev, spear_thermal);
136 141
@@ -139,6 +144,8 @@ static int spear_thermal_probe(struct platform_device *pdev) · 2 unmodified lines
139 144
140 return 0;145 return 0;
141 146
147unregister_tzd:
148 thermal_zone_device_unregister(spear_thermal);
142disable_clk:149disable_clk:
143 clk_disable(stdev->clk);150 clk_disable(stdev->clk);
144 151
drivers/thermal/sprd_thermal.c+4−2
@@ -322,8 +322,10 @@ static void sprd_thm_toggle_sensor(struct sprd_thermal_sensor *sen, bool on) · 321 unmodified lines
322{322{
323 struct thermal_zone_device *tzd = sen->tzd;323 struct thermal_zone_device *tzd = sen->tzd;
324 324
325 tzd->ops->set_mode(tzd,325 if (on)
326 on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);326 thermal_zone_device_enable(tzd);
327 else
328 thermal_zone_device_disable(tzd);
327}329}
328 330
329static int sprd_thm_probe(struct platform_device *pdev)331static int sprd_thm_probe(struct platform_device *pdev)
drivers/thermal/st/st_thermal.c+5−0
@@ -246,11 +246,16 @@ int st_thermal_register(struct platform_device *pdev, · 245 unmodified lines
246 ret = PTR_ERR(sensor->thermal_dev);246 ret = PTR_ERR(sensor->thermal_dev);
247 goto sensor_off;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 platform_set_drvdata(pdev, sensor);253 platform_set_drvdata(pdev, sensor);
251 254
252 return 0;255 return 0;
253 256
257tzd_unregister:
258 thermal_zone_device_unregister(sensor->thermal_dev);
254sensor_off:259sensor_off:
255 st_thermal_sensor_off(sensor);260 st_thermal_sensor_off(sensor);
256 261
drivers/thermal/thermal_core.c+165−9
@@ -215,6 +215,8 @@ exit: · 214 unmodified lines
215 mutex_unlock(&tz->lock);215 mutex_unlock(&tz->lock);
216 mutex_unlock(&thermal_governor_lock);216 mutex_unlock(&thermal_governor_lock);
217 217
218 thermal_notify_tz_gov_change(tz->id, policy);
219
218 return ret;220 return ret;
219}221}
220 222
@@ -301,13 +303,22 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, · 80 unmodified lines
301 cancel_delayed_work(&tz->poll_queue);303 cancel_delayed_work(&tz->poll_queue);
302}304}
303 305
306static inline bool should_stop_polling(struct thermal_zone_device *tz)
307{
308 return !thermal_zone_device_is_enabled(tz);
309}
310
304static void monitor_thermal_zone(struct thermal_zone_device *tz)311static void monitor_thermal_zone(struct thermal_zone_device *tz)
305{312{
313 bool stop;
314
315 stop = should_stop_polling(tz);
316
306 mutex_lock(&tz->lock);317 mutex_lock(&tz->lock);
307 318
308 if (tz->passive)319 if (!stop && tz->passive)
309 thermal_zone_device_set_polling(tz, tz->passive_delay);320 thermal_zone_device_set_polling(tz, tz->passive_delay);
310 else if (tz->polling_delay)321 else if (!stop && tz->polling_delay)
311 thermal_zone_device_set_polling(tz, tz->polling_delay);322 thermal_zone_device_set_polling(tz, tz->polling_delay);
312 else323 else
313 thermal_zone_device_set_polling(tz, 0);324 thermal_zone_device_set_polling(tz, 0);
@@ -406,12 +417,25 @@ static void handle_critical_trips(struct thermal_zone_device *tz, · 92 unmodified lines
406static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)417static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
407{418{
408 enum thermal_trip_type type;419 enum thermal_trip_type type;
420 int trip_temp, hyst = 0;
409 421
410 /* Ignore disabled trip points */422 /* Ignore disabled trip points */
411 if (test_bit(trip, &tz->trips_disabled))423 if (test_bit(trip, &tz->trips_disabled))
412 return;424 return;
413 425
426 tz->ops->get_trip_temp(tz, trip, &trip_temp);
414 tz->ops->get_trip_type(tz, trip, &type);427 tz->ops->get_trip_type(tz, trip, &type);
428 if (tz->ops->get_trip_hyst)
429 tz->ops->get_trip_hyst(tz, trip, &hyst);
430
431 if (tz->last_temperature != THERMAL_TEMP_INVALID) {
432 if (tz->last_temperature < trip_temp &&
433 tz->temperature >= trip_temp)
434 thermal_notify_tz_trip_up(tz->id, trip);
435 if (tz->last_temperature >= trip_temp &&
436 tz->temperature < (trip_temp - hyst))
437 thermal_notify_tz_trip_down(tz->id, trip);
438 }
415 439
416 if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)440 if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
417 handle_critical_trips(tz, trip, type);441 handle_critical_trips(tz, trip, type);
@@ -443,6 +467,8 @@ static void update_temperature(struct thermal_zone_device *tz) · 25 unmodified lines
443 mutex_unlock(&tz->lock);467 mutex_unlock(&tz->lock);
444 468
445 trace_thermal_temperature(tz);469 trace_thermal_temperature(tz);
470
471 thermal_genl_sampling_temp(tz->id, temp);
446}472}
447 473
448static void thermal_zone_device_init(struct thermal_zone_device *tz)474static void thermal_zone_device_init(struct thermal_zone_device *tz)
@@ -459,11 +485,71 @@ static void thermal_zone_device_reset(struct thermal_zone_device *tz) · 10 unmodified lines
459 thermal_zone_device_init(tz);485 thermal_zone_device_init(tz);
460}486}
461 487
488static int thermal_zone_device_set_mode(struct thermal_zone_device *tz,
489 enum thermal_device_mode mode)
490{
491 int ret = 0;
492
493 mutex_lock(&tz->lock);
494
495 /* do nothing if mode isn't changing */
496 if (mode == tz->mode) {
497 mutex_unlock(&tz->lock);
498
499 return ret;
500 }
501
502 if (tz->ops->change_mode)
503 ret = tz->ops->change_mode(tz, mode);
504
505 if (!ret)
506 tz->mode = mode;
507
508 mutex_unlock(&tz->lock);
509
510 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
511
512 if (mode == THERMAL_DEVICE_ENABLED)
513 thermal_notify_tz_enable(tz->id);
514 else
515 thermal_notify_tz_disable(tz->id);
516
517 return ret;
518}
519
520int thermal_zone_device_enable(struct thermal_zone_device *tz)
521{
522 return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_ENABLED);
523}
524EXPORT_SYMBOL_GPL(thermal_zone_device_enable);
525
526int thermal_zone_device_disable(struct thermal_zone_device *tz)
527{
528 return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_DISABLED);
529}
530EXPORT_SYMBOL_GPL(thermal_zone_device_disable);
531
532int thermal_zone_device_is_enabled(struct thermal_zone_device *tz)
533{
534 enum thermal_device_mode mode;
535
536 mutex_lock(&tz->lock);
537
538 mode = tz->mode;
539
540 mutex_unlock(&tz->lock);
541
542 return mode == THERMAL_DEVICE_ENABLED;
543}
544
462void thermal_zone_device_update(struct thermal_zone_device *tz,545void thermal_zone_device_update(struct thermal_zone_device *tz,
463 enum thermal_notify_event event)546 enum thermal_notify_event event)
464{547{
465 int count;548 int count;
466 549
550 if (should_stop_polling(tz))
551 return;
552
467 if (atomic_read(&in_suspend))553 if (atomic_read(&in_suspend))
468 return;554 return;
469 555
@@ -617,6 +703,73 @@ void thermal_zone_device_rebind_exception(struct thermal_zone_device *tz, · 147 unmodified lines
617 mutex_unlock(&thermal_list_lock);703 mutex_unlock(&thermal_list_lock);
618}704}
619 705
706int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *),
707 void *data)
708{
709 struct thermal_governor *gov;
710 int ret = 0;
711
712 mutex_lock(&thermal_governor_lock);
713 list_for_each_entry(gov, &thermal_governor_list, governor_list) {
714 ret = cb(gov, data);
715 if (ret)
716 break;
717 }
718 mutex_unlock(&thermal_governor_lock);
719
720 return ret;
721}
722
723int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *,
724 void *), void *data)
725{
726 struct thermal_cooling_device *cdev;
727 int ret = 0;
728
729 mutex_lock(&thermal_list_lock);
730 list_for_each_entry(cdev, &thermal_cdev_list, node) {
731 ret = cb(cdev, data);
732 if (ret)
733 break;
734 }
735 mutex_unlock(&thermal_list_lock);
736
737 return ret;
738}
739
740int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *),
741 void *data)
742{
743 struct thermal_zone_device *tz;
744 int ret = 0;
745
746 mutex_lock(&thermal_list_lock);
747 list_for_each_entry(tz, &thermal_tz_list, node) {
748 ret = cb(tz, data);
749 if (ret)
750 break;
751 }
752 mutex_unlock(&thermal_list_lock);
753
754 return ret;
755}
756
757struct thermal_zone_device *thermal_zone_get_by_id(int id)
758{
759 struct thermal_zone_device *tz, *match = NULL;
760
761 mutex_lock(&thermal_list_lock);
762 list_for_each_entry(tz, &thermal_tz_list, node) {
763 if (tz->id == id) {
764 match = tz;
765 break;
766 }
767 }
768 mutex_unlock(&thermal_list_lock);
769
770 return match;
771}
772
620void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,773void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,
621 const char *cdev_type, size_t size)774 const char *cdev_type, size_t size)
622{775{
@@ -1340,6 +1493,8 @@ thermal_zone_device_register(const char *type, int trips, int mask, · 717 unmodified lines
1340 if (atomic_cmpxchg(&tz->need_update, 1, 0))1493 if (atomic_cmpxchg(&tz->need_update, 1, 0))
1341 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);1494 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
1342 1495
1496 thermal_notify_tz_create(tz->id, tz->type);
1497
1343 return tz;1498 return tz;
1344 1499
1345unregister:1500unregister:
@@ -1411,6 +1566,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) · 65 unmodified lines
1411 ida_destroy(&tz->ida);1566 ida_destroy(&tz->ida);
1412 mutex_destroy(&tz->lock);1567 mutex_destroy(&tz->lock);
1413 device_unregister(&tz->device);1568 device_unregister(&tz->device);
1569
1570 thermal_notify_tz_delete(tz->id);
1414}1571}
1415EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);1572EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
1416 1573
@@ -1456,7 +1613,6 @@ static int thermal_pm_notify(struct notifier_block *nb, · 39 unmodified lines
1456 unsigned long mode, void *_unused)1613 unsigned long mode, void *_unused)
1457{1614{
1458 struct thermal_zone_device *tz;1615 struct thermal_zone_device *tz;
1459 enum thermal_device_mode tz_mode;
1460 1616
1461 switch (mode) {1617 switch (mode) {
1462 case PM_HIBERNATION_PREPARE:1618 case PM_HIBERNATION_PREPARE:
@@ -1469,11 +1625,7 @@ static int thermal_pm_notify(struct notifier_block *nb, · 6 unmodified lines
1469 case PM_POST_SUSPEND:1625 case PM_POST_SUSPEND:
1470 atomic_set(&in_suspend, 0);1626 atomic_set(&in_suspend, 0);
1471 list_for_each_entry(tz, &thermal_tz_list, node) {1627 list_for_each_entry(tz, &thermal_tz_list, node) {
1472 tz_mode = THERMAL_DEVICE_ENABLED;1628 if (!thermal_zone_device_is_enabled(tz))
1473 if (tz->ops->get_mode)
1474 tz->ops->get_mode(tz, &tz_mode);
1475
1476 if (tz_mode == THERMAL_DEVICE_DISABLED)
1477 continue;1629 continue;
1478 1630
1479 thermal_zone_device_init(tz);1631 thermal_zone_device_init(tz);
@@ -1495,6 +1647,10 @@ static int __init thermal_init(void) · 15 unmodified lines
1495{1647{
1496 int result;1648 int result;
1497 1649
1650 result = thermal_netlink_init();
1651 if (result)
1652 goto error;
1653
1498 mutex_init(&poweroff_lock);1654 mutex_init(&poweroff_lock);
1499 result = thermal_register_governors();1655 result = thermal_register_governors();
1500 if (result)1656 if (result)
@@ -1527,4 +1683,4 @@ error: · 26 unmodified lines
1527 mutex_destroy(&poweroff_lock);1683 mutex_destroy(&poweroff_lock);
1528 return result;1684 return result;
1529}1685}
1530core_initcall(thermal_init);1686postcore_initcall(thermal_init);
drivers/thermal/thermal_core.h+15−0
@@ -12,6 +12,8 @@ · 11 unmodified lines
12#include <linux/device.h>12#include <linux/device.h>
13#include <linux/thermal.h>13#include <linux/thermal.h>
14 14
15#include "thermal_netlink.h"
16
15/* Default Thermal Governor */17/* Default Thermal Governor */
16#if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)18#if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
17#define DEFAULT_THERMAL_GOVERNOR "step_wise"19#define DEFAULT_THERMAL_GOVERNOR "step_wise"
@@ -41,6 +43,17 @@ extern struct thermal_governor *__governor_thermal_table_end[]; · 23 unmodified lines
41 __governor < __governor_thermal_table_end; \43 __governor < __governor_thermal_table_end; \
42 __governor++)44 __governor++)
43 45
46int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *),
47 void *);
48
49int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *,
50 void *), void *);
51
52int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *),
53 void *thermal_governor);
54
55struct thermal_zone_device *thermal_zone_get_by_id(int id);
56
44struct thermal_attr {57struct thermal_attr {
45 struct device_attribute attr;58 struct device_attribute attr;
46 char name[THERMAL_NAME_LENGTH];59 char name[THERMAL_NAME_LENGTH];
@@ -166,4 +179,6 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz) · 119 unmodified lines
166}179}
167#endif180#endif
168 181
182int thermal_zone_device_is_enabled(struct thermal_zone_device *tz);
183
169#endif /* __THERMAL_CORE_H__ */184#endif /* __THERMAL_CORE_H__ */
drivers/thermal/thermal_helpers.c+11−2
@@ -175,6 +175,16 @@ exit: · 174 unmodified lines
175 mutex_unlock(&tz->lock);175 mutex_unlock(&tz->lock);
176}176}
177 177
178static 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
178void thermal_cdev_update(struct thermal_cooling_device *cdev)188void thermal_cdev_update(struct thermal_cooling_device *cdev)
179{189{
180 struct thermal_instance *instance;190 struct thermal_instance *instance;
@@ -197,8 +207,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) · 16 unmodified lines
197 target = instance->target;207 target = instance->target;
198 }208 }
199 209
200 if (!cdev->ops->set_cur_state(cdev, target))210 thermal_cdev_set_cur_state(cdev, target);
201 thermal_cooling_device_stats_update(cdev, target);
202 211
203 cdev->updated = true;212 cdev->updated = true;
204 mutex_unlock(&cdev->lock);213 mutex_unlock(&cdev->lock);
drivers/thermal/thermal_netlink.c+647−0
@@ -0,0 +1,647 @@
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
16static const struct genl_multicast_group thermal_genl_mcgrps[] = {
17 { .name = THERMAL_GENL_SAMPLING_GROUP_NAME, },
18 { .name = THERMAL_GENL_EVENT_GROUP_NAME, },
19};
20
21static 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
48struct 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
63typedef int (*cb_t)(struct param *);
64
65static struct genl_family thermal_gnl_family;
66
67/************************** Sampling encoding *******************************/
68
69int 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;
94out_cancel:
95 genlmsg_cancel(skb, hdr);
96 nlmsg_free(skb);
97
98 return -EMSGSIZE;
99}
100
101/**************************** Event encoding *********************************/
102
103static 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
112static 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
120static 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
129static 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
141static 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
150static 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
163static 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
171static 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
182static 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
191int thermal_genl_event_tz_delete(struct param *p)
192 __attribute__((alias("thermal_genl_event_tz")));
193
194int thermal_genl_event_tz_enable(struct param *p)
195 __attribute__((alias("thermal_genl_event_tz")));
196
197int thermal_genl_event_tz_disable(struct param *p)
198 __attribute__((alias("thermal_genl_event_tz")));
199
200int thermal_genl_event_tz_trip_down(struct param *p)
201 __attribute__((alias("thermal_genl_event_tz_trip_up")));
202
203int thermal_genl_event_tz_trip_change(struct param *p)
204 __attribute__((alias("thermal_genl_event_tz_trip_add")));
205
206static 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 */
225static 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
251out_cancel_msg:
252 genlmsg_cancel(msg, hdr);
253out_free_msg:
254 nlmsg_free(msg);
255
256 return ret;
257}
258
259int 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
266int 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
273int 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
280int 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
287int 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
294int 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
301int 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
311int 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
318int 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
328int 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
335int 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
343int 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
350int 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
359static 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
371static 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
389out_cancel_nest:
390 nla_nest_cancel(msg, start_tz);
391
392 return ret;
393}
394
395static 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
439out_cancel_nest:
440 mutex_unlock(&tz->lock);
441
442 return -EMSGSIZE;
443}
444
445static 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
471static 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
498static 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
512static 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;
529out_cancel_nest:
530 nla_nest_cancel(msg, start_cdev);
531
532 return ret;
533}
534
535static 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
543static 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
564out_cancel_msg:
565 genlmsg_cancel(skb, hdr);
566
567 return ret;
568}
569
570static 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
596out_cancel_msg:
597 genlmsg_cancel(msg, hdr);
598out_free_msg:
599 nlmsg_free(msg);
600
601 return ret;
602}
603
604static 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
632static 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
644int __init thermal_netlink_init(void)
645{
646 return genl_register_family(&thermal_gnl_family);
647}
drivers/thermal/thermal_netlink.h+104−0
@@ -0,0 +1,104 @@
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
9int __init thermal_netlink_init(void);
10int thermal_notify_tz_create(int tz_id, const char *name);
11int thermal_notify_tz_delete(int tz_id);
12int thermal_notify_tz_enable(int tz_id);
13int thermal_notify_tz_disable(int tz_id);
14int thermal_notify_tz_trip_down(int tz_id, int id);
15int thermal_notify_tz_trip_up(int tz_id, int id);
16int thermal_notify_tz_trip_delete(int tz_id, int id);
17int thermal_notify_tz_trip_add(int tz_id, int id, int type,
18 int temp, int hyst);
19int thermal_notify_tz_trip_change(int tz_id, int id, int type,
20 int temp, int hyst);
21int thermal_notify_cdev_state_update(int cdev_id, int state);
22int thermal_notify_cdev_add(int cdev_id, const char *name, int max_state);
23int thermal_notify_cdev_delete(int cdev_id);
24int thermal_notify_tz_gov_change(int tz_id, const char *name);
25int thermal_genl_sampling_temp(int id, int temp);
26#else
27static inline int thermal_netlink_init(void)
28{
29 return 0;
30}
31
32static inline int thermal_notify_tz_create(int tz_id, const char *name)
33{
34 return 0;
35}
36
37static inline int thermal_notify_tz_delete(int tz_id)
38{
39 return 0;
40}
41
42static inline int thermal_notify_tz_enable(int tz_id)
43{
44 return 0;
45}
46
47static inline int thermal_notify_tz_disable(int tz_id)
48{
49 return 0;
50}
51
52static inline int thermal_notify_tz_trip_down(int tz_id, int id)
53{
54 return 0;
55}
56
57static inline int thermal_notify_tz_trip_up(int tz_id, int id)
58{
59 return 0;
60}
61
62static inline int thermal_notify_tz_trip_delete(int tz_id, int id)
63{
64 return 0;
65}
66
67static 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
73static 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
79static inline int thermal_notify_cdev_state_update(int cdev_id, int state)
80{
81 return 0;
82}
83
84static inline int thermal_notify_cdev_add(int cdev_id, const char *name,
85 int max_state)
86{
87 return 0;
88}
89
90static inline int thermal_notify_cdev_delete(int cdev_id)
91{
92 return 0;
93}
94
95static inline int thermal_notify_tz_gov_change(int tz_id, const char *name)
96{
97 return 0;
98}
99
100static inline int thermal_genl_sampling_temp(int id, int temp)
101{
102 return 0;
103}
104#endif /* CONFIG_THERMAL_NETLINK */
drivers/thermal/thermal_of.c+1−40
@@ -51,7 +51,6 @@ struct __thermal_bind_params { · 50 unmodified lines
51 51
52/**52/**
53 * struct __thermal_zone - internal representation of a thermal zone53 * struct __thermal_zone - internal representation of a thermal zone
54 * @mode: current thermal zone device mode (enabled/disabled)
55 * @passive_delay: polling interval while passive cooling is activated54 * @passive_delay: polling interval while passive cooling is activated
56 * @polling_delay: zone polling interval55 * @polling_delay: zone polling interval
57 * @slope: slope of the temperature adjustment curve56 * @slope: slope of the temperature adjustment curve
@@ -65,7 +64,6 @@ struct __thermal_bind_params { · 7 unmodified lines
65 */64 */
66 65
67struct __thermal_zone {66struct __thermal_zone {
68 enum thermal_device_mode mode;
69 int passive_delay;67 int passive_delay;
70 int polling_delay;68 int polling_delay;
71 int slope;69 int slope;
@@ -269,39 +267,6 @@ static int of_thermal_unbind(struct thermal_zone_device *thermal, · 197 unmodified lines
269 return 0;267 return 0;
270}268}
271 269
272static int of_thermal_get_mode(struct thermal_zone_device *tz,
273 enum thermal_device_mode *mode)
274{
275 struct __thermal_zone *data = tz->devdata;
276
277 *mode = data->mode;
278
279 return 0;
280}
281
282static int of_thermal_set_mode(struct thermal_zone_device *tz,
283 enum thermal_device_mode mode)
284{
285 struct __thermal_zone *data = tz->devdata;
286
287 mutex_lock(&tz->lock);
288
289 if (mode == THERMAL_DEVICE_ENABLED) {
290 tz->polling_delay = data->polling_delay;
291 tz->passive_delay = data->passive_delay;
292 } else {
293 tz->polling_delay = 0;
294 tz->passive_delay = 0;
295 }
296
297 mutex_unlock(&tz->lock);
298
299 data->mode = mode;
300 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
301
302 return 0;
303}
304
305static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,270static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
306 enum thermal_trip_type *type)271 enum thermal_trip_type *type)
307{272{
@@ -393,9 +358,6 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz, · 85 unmodified lines
393}358}
394 359
395static struct thermal_zone_device_ops of_thermal_ops = {360static struct thermal_zone_device_ops of_thermal_ops = {
396 .get_mode = of_thermal_get_mode,
397 .set_mode = of_thermal_set_mode,
398
399 .get_trip_type = of_thermal_get_trip_type,361 .get_trip_type = of_thermal_get_trip_type,
400 .get_trip_temp = of_thermal_get_trip_temp,362 .get_trip_temp = of_thermal_get_trip_temp,
401 .set_trip_temp = of_thermal_set_trip_temp,363 .set_trip_temp = of_thermal_set_trip_temp,
@@ -554,7 +516,7 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data, · 152 unmodified lines
554 tzd = thermal_zone_of_add_sensor(child, sensor_np,516 tzd = thermal_zone_of_add_sensor(child, sensor_np,
555 data, ops);517 data, ops);
556 if (!IS_ERR(tzd))518 if (!IS_ERR(tzd))
557 tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);519 thermal_zone_device_enable(tzd);
558 520
559 of_node_put(child);521 of_node_put(child);
560 goto exit;522 goto exit;
@@ -979,7 +941,6 @@ __init *thermal_of_build_thermal_zone(struct device_node *np) · 418 unmodified lines
979 941
980finish:942finish:
981 of_node_put(child);943 of_node_put(child);
982 tz->mode = THERMAL_DEVICE_DISABLED;
983 944
984 return tz;945 return tz;
985 946
drivers/thermal/thermal_sysfs.c+18−34
@@ -49,18 +49,9 @@ static ssize_t · 48 unmodified lines
49mode_show(struct device *dev, struct device_attribute *attr, char *buf)49mode_show(struct device *dev, struct device_attribute *attr, char *buf)
50{50{
51 struct thermal_zone_device *tz = to_thermal_zone(dev);51 struct thermal_zone_device *tz = to_thermal_zone(dev);
52 enum thermal_device_mode mode;52 int enabled = thermal_zone_device_is_enabled(tz);
53 int result;
54
55 if (!tz->ops->get_mode)
56 return -EPERM;
57 53
58 result = tz->ops->get_mode(tz, &mode);54 return sprintf(buf, "%s\n", enabled ? "enabled" : "disabled");
59 if (result)
60 return result;
61
62 return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
63 : "disabled");
64}55}
65 56
66static ssize_t57static ssize_t
@@ -70,13 +61,10 @@ mode_store(struct device *dev, struct device_attribute *attr, · 3 unmodified lines
70 struct thermal_zone_device *tz = to_thermal_zone(dev);61 struct thermal_zone_device *tz = to_thermal_zone(dev);
71 int result;62 int result;
72 63
73 if (!tz->ops->set_mode)
74 return -EPERM;
75
76 if (!strncmp(buf, "enabled", sizeof("enabled") - 1))64 if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
77 result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);65 result = thermal_zone_device_enable(tz);
78 else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))66 else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
79 result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);67 result = thermal_zone_device_disable(tz);
80 else68 else
81 result = -EINVAL;69 result = -EINVAL;
82 70
@@ -124,7 +112,8 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, · 41 unmodified lines
124{112{
125 struct thermal_zone_device *tz = to_thermal_zone(dev);113 struct thermal_zone_device *tz = to_thermal_zone(dev);
126 int trip, ret;114 int trip, ret;
127 int temperature;115 int temperature, hyst = 0;
116 enum thermal_trip_type type;
128 117
129 if (!tz->ops->set_trip_temp)118 if (!tz->ops->set_trip_temp)
130 return -EPERM;119 return -EPERM;
@@ -139,6 +128,18 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, · 8 unmodified lines
139 if (ret)128 if (ret)
140 return ret;129 return ret;
141 130
131 if (tz->ops->get_trip_hyst) {
132 ret = tz->ops->get_trip_hyst(tz, trip, &hyst);
133 if (ret)
134 return ret;
135 }
136
137 ret = tz->ops->get_trip_type(tz, trip, &type);
138 if (ret)
139 return ret;
140
141 thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst);
142
142 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);143 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
143 144
144 return count;145 return count;
@@ -428,30 +429,13 @@ static struct attribute_group thermal_zone_attribute_group = { · 283 unmodified lines
428 .attrs = thermal_zone_dev_attrs,429 .attrs = thermal_zone_dev_attrs,
429};430};
430 431
431/* We expose mode only if .get_mode is present */
432static struct attribute *thermal_zone_mode_attrs[] = {432static struct attribute *thermal_zone_mode_attrs[] = {
433 &dev_attr_mode.attr,433 &dev_attr_mode.attr,
434 NULL,434 NULL,
435};435};
436 436
437static umode_t thermal_zone_mode_is_visible(struct kobject *kobj,
438 struct attribute *attr,
439 int attrno)
440{
441 struct device *dev = container_of(kobj, struct device, kobj);
442 struct thermal_zone_device *tz;
443
444 tz = container_of(dev, struct thermal_zone_device, device);
445
446 if (tz->ops->get_mode)
447 return attr->mode;
448
449 return 0;
450}
451
452static struct attribute_group thermal_zone_mode_attribute_group = {437static struct attribute_group thermal_zone_mode_attribute_group = {
453 .attrs = thermal_zone_mode_attrs,438 .attrs = thermal_zone_mode_attrs,
454 .is_visible = thermal_zone_mode_is_visible,
455};439};
456 440
457/* We expose passive only if passive trips are present */441/* We expose passive only if passive trips are present */
drivers/thermal/ti-soc-thermal/ti-thermal-common.c+1−1
@@ -169,7 +169,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, · 168 unmodified lines
169 169
170 data = ti_bandgap_get_sensor_data(bgp, id);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 data = ti_thermal_build_data(bgp, id);173 data = ti_thermal_build_data(bgp, id);
174 174
175 if (!data)175 if (!data)
include/linux/clock_cooling.h+0−57
@@ -1,57 +0,0 @@
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 */
28struct thermal_cooling_device *
29clock_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 */
35void clock_cooling_unregister(struct thermal_cooling_device *cdev);
36
37unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev,
38 unsigned long freq);
39#else /* !CONFIG_CLOCK_THERMAL */
40static inline struct thermal_cooling_device *
41clock_cooling_register(struct device *dev, const char *clock_name)
42{
43 return NULL;
44}
45static inline
46void clock_cooling_unregister(struct thermal_cooling_device *cdev)
47{
48}
49static inline
50unsigned 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__ */
include/linux/devfreq_cooling.h+1−8
@@ -1,17 +1,10 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/*2/*
2 * devfreq_cooling: Thermal cooling device implementation for devices using3 * devfreq_cooling: Thermal cooling device implementation for devices using
3 * devfreq4 * devfreq
4 *5 *
5 * Copyright (C) 2014-2015 ARM Limited6 * 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#ifndef __DEVFREQ_COOLING_H__10#ifndef __DEVFREQ_COOLING_H__
include/linux/thermal.h+11−20
@@ -37,18 +37,6 @@ struct thermal_cooling_device; · 36 unmodified lines
37struct thermal_instance;37struct thermal_instance;
38struct thermal_attr;38struct thermal_attr;
39 39
40enum thermal_device_mode {
41 THERMAL_DEVICE_DISABLED = 0,
42 THERMAL_DEVICE_ENABLED,
43};
44
45enum thermal_trip_type {
46 THERMAL_TRIP_ACTIVE = 0,
47 THERMAL_TRIP_PASSIVE,
48 THERMAL_TRIP_HOT,
49 THERMAL_TRIP_CRITICAL,
50};
51
52enum thermal_trend {40enum thermal_trend {
53 THERMAL_TREND_STABLE, /* temperature is stable */41 THERMAL_TREND_STABLE, /* temperature is stable */
54 THERMAL_TREND_RAISING, /* temperature is raising */42 THERMAL_TREND_RAISING, /* temperature is raising */
@@ -76,9 +64,7 @@ struct thermal_zone_device_ops { · 21 unmodified lines
76 struct thermal_cooling_device *);64 struct thermal_cooling_device *);
77 int (*get_temp) (struct thermal_zone_device *, int *);65 int (*get_temp) (struct thermal_zone_device *, int *);
78 int (*set_trips) (struct thermal_zone_device *, int, int);66 int (*set_trips) (struct thermal_zone_device *, int, int);
79 int (*get_mode) (struct thermal_zone_device *,67 int (*change_mode) (struct thermal_zone_device *,
80 enum thermal_device_mode *);
81 int (*set_mode) (struct thermal_zone_device *,
82 enum thermal_device_mode);68 enum thermal_device_mode);
83 int (*get_trip_type) (struct thermal_zone_device *, int,69 int (*get_trip_type) (struct thermal_zone_device *, int,
84 enum thermal_trip_type *);70 enum thermal_trip_type *);
@@ -128,6 +114,7 @@ struct thermal_cooling_device { · 43 unmodified lines
128 * @trip_temp_attrs: attributes for trip points for sysfs: trip temperature114 * @trip_temp_attrs: attributes for trip points for sysfs: trip temperature
129 * @trip_type_attrs: attributes for trip points for sysfs: trip type115 * @trip_type_attrs: attributes for trip points for sysfs: trip type
130 * @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis116 * @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis
117 * @mode: current mode of this thermal zone
131 * @devdata: private pointer for device private data118 * @devdata: private pointer for device private data
132 * @trips: number of trip points the thermal zone supports119 * @trips: number of trip points the thermal zone supports
133 * @trips_disabled; bitmap for disabled trips120 * @trips_disabled; bitmap for disabled trips
@@ -170,6 +157,7 @@ struct thermal_zone_device { · 36 unmodified lines
170 struct thermal_attr *trip_temp_attrs;157 struct thermal_attr *trip_temp_attrs;
171 struct thermal_attr *trip_type_attrs;158 struct thermal_attr *trip_type_attrs;
172 struct thermal_attr *trip_hyst_attrs;159 struct thermal_attr *trip_hyst_attrs;
160 enum thermal_device_mode mode;
173 void *devdata;161 void *devdata;
174 int trips;162 int trips;
175 unsigned long trips_disabled; /* bitmap for disabled trips */163 unsigned long trips_disabled; /* bitmap for disabled trips */
@@ -303,11 +291,6 @@ struct thermal_zone_params { · 127 unmodified lines
303 int offset;291 int offset;
304};292};
305 293
306struct thermal_genl_event {
307 u32 orig;
308 enum events event;
309};
310
311/**294/**
312 * struct thermal_zone_of_device_ops - scallbacks for handling DT based zones295 * struct thermal_zone_of_device_ops - scallbacks for handling DT based zones
313 *296 *
@@ -416,6 +399,8 @@ int thermal_zone_get_offset(struct thermal_zone_device *tz); · 102 unmodified lines
416 399
417void thermal_cdev_update(struct thermal_cooling_device *);400void thermal_cdev_update(struct thermal_cooling_device *);
418void thermal_notify_framework(struct thermal_zone_device *, int);401void thermal_notify_framework(struct thermal_zone_device *, int);
402int thermal_zone_device_enable(struct thermal_zone_device *tz);
403int thermal_zone_device_disable(struct thermal_zone_device *tz);
419#else404#else
420static inline struct thermal_zone_device *thermal_zone_device_register(405static inline struct thermal_zone_device *thermal_zone_device_register(
421 const char *type, int trips, int mask, void *devdata,406 const char *type, int trips, int mask, void *devdata,
@@ -463,6 +448,12 @@ static inline void thermal_cdev_update(struct thermal_cooling_device *cdev) · 41 unmodified lines
463static inline void thermal_notify_framework(struct thermal_zone_device *tz,448static inline void thermal_notify_framework(struct thermal_zone_device *tz,
464 int trip)449 int trip)
465{ }450{ }
451
452static inline int thermal_zone_device_enable(struct thermal_zone_device *tz)
453{ return -ENODEV; }
454
455static inline int thermal_zone_device_disable(struct thermal_zone_device *tz)
456{ return -ENODEV; }
466#endif /* CONFIG_THERMAL */457#endif /* CONFIG_THERMAL */
467 458
468#endif /* __THERMAL_H__ */459#endif /* __THERMAL_H__ */
include/uapi/linux/thermal.h+72−17
@@ -4,31 +4,86 @@ · 3 unmodified lines
4 4
5#define THERMAL_NAME_LENGTH 205#define THERMAL_NAME_LENGTH 20
6 6
7/* Adding event notification support elements */7enum thermal_device_mode {
8#define THERMAL_GENL_FAMILY_NAME "thermal_event"8 THERMAL_DEVICE_DISABLED = 0,
9#define THERMAL_GENL_VERSION 0x019 THERMAL_DEVICE_ENABLED,
10#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_grp"10};
11 11
12/* Events supported by Thermal Netlink */12enum thermal_trip_type {
13enum events {13 THERMAL_TRIP_ACTIVE = 0,
14 THERMAL_AUX0,14 THERMAL_TRIP_PASSIVE,
15 THERMAL_AUX1,15 THERMAL_TRIP_HOT,
16 THERMAL_CRITICAL,16 THERMAL_TRIP_CRITICAL,
17 THERMAL_DEV_FAULT,
18};17};
19 18
20/* attributes of thermal_genl_family */19/* Adding event notification support elements */
21enum {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 */
26enum thermal_genl_attr {
22 THERMAL_GENL_ATTR_UNSPEC,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 __THERMAL_GENL_ATTR_MAX,48 __THERMAL_GENL_ATTR_MAX,
25};49};
26#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)50#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
27 51
28/* commands supported by the thermal_genl_family */52enum thermal_genl_sampling {
29enum {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 */
59enum 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 */
79enum thermal_genl_cmd {
30 THERMAL_GENL_CMD_UNSPEC,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 __THERMAL_GENL_CMD_MAX,87 __THERMAL_GENL_CMD_MAX,
33};88};
34#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)89#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
net/netlink/genetlink.c+1−1
@@ -1192,7 +1192,7 @@ problem: · 1191 unmodified lines
1192 panic("GENL: Cannot register controller: %d\n", err);1192 panic("GENL: Cannot register controller: %d\n", err);
1193}1193}
1194 1194
1195subsys_initcall(genl_init);1195core_initcall(genl_init);
1196 1196
1197static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,1197static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
1198 gfp_t flags)1198 gfp_t flags)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t