Merge tag 'thermal-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Aug 2020 01:10:55 +0000 (18:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Aug 2020 01:10:55 +0000 (18:10 -0700)
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
  ...

75 files changed:
Documentation/devicetree/bindings/arm/arm,scmi.txt
Documentation/devicetree/bindings/arm/arm,scpi.txt
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt
Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt
Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt
Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
Documentation/devicetree/bindings/hwmon/gpio-fan.txt
Documentation/devicetree/bindings/hwmon/lm90.txt
Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml
Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt
Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml
Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt
Documentation/devicetree/bindings/thermal/max77620_thermal.txt
Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt
Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt
Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
Documentation/devicetree/bindings/thermal/tango-thermal.txt
Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt
Documentation/devicetree/bindings/thermal/thermal.txt [deleted file]
MAINTAINERS
drivers/acpi/thermal.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
drivers/net/wireless/intel/iwlwifi/mvm/tt.c
drivers/platform/x86/acerhdf.c
drivers/platform/x86/intel_mid_thermal.c
drivers/power/supply/power_supply_core.c
drivers/thermal/Kconfig
drivers/thermal/Makefile
drivers/thermal/armada_thermal.c
drivers/thermal/clock_cooling.c [deleted file]
drivers/thermal/da9062-thermal.c
drivers/thermal/devfreq_cooling.c
drivers/thermal/dove_thermal.c
drivers/thermal/gov_power_allocator.c
drivers/thermal/hisi_thermal.c
drivers/thermal/imx8mm_thermal.c
drivers/thermal/imx_thermal.c
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
drivers/thermal/intel/intel_pch_thermal.c
drivers/thermal/intel/intel_quark_dts_thermal.c
drivers/thermal/intel/intel_soc_dts_iosf.c
drivers/thermal/intel/x86_pkg_temp_thermal.c
drivers/thermal/kirkwood_thermal.c
drivers/thermal/mtk_thermal.c
drivers/thermal/qcom/tsens-v0_1.c
drivers/thermal/qcom/tsens.c
drivers/thermal/qcom/tsens.h
drivers/thermal/rcar_gen3_thermal.c
drivers/thermal/rcar_thermal.c
drivers/thermal/rockchip_thermal.c
drivers/thermal/spear_thermal.c
drivers/thermal/sprd_thermal.c
drivers/thermal/st/st_thermal.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_core.h
drivers/thermal/thermal_helpers.c
drivers/thermal/thermal_netlink.c [new file with mode: 0644]
drivers/thermal/thermal_netlink.h [new file with mode: 0644]
drivers/thermal/thermal_of.c
drivers/thermal/thermal_sysfs.c
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
include/linux/clock_cooling.h [deleted file]
include/linux/devfreq_cooling.h
include/linux/thermal.h
include/uapi/linux/thermal.h
net/netlink/genetlink.c

index 1f293ea24cd85793402cf0b2f72b21db4a460594..55deb68230ebb2af17fe5185b1d93cc9af16bfb5 100644 (file)
@@ -102,7 +102,7 @@ Required sub-node properties:
 [0] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 [2] Documentation/devicetree/bindings/power/power-domain.yaml
-[3] Documentation/devicetree/bindings/thermal/thermal.txt
+[3] Documentation/devicetree/bindings/thermal/thermal*.yaml
 [4] Documentation/devicetree/bindings/sram/sram.yaml
 [5] Documentation/devicetree/bindings/reset/reset.txt
 
index dd04d9d9a1b8e0b06e43d16683feb440ebbff4d5..bcd6c3ec471e68b3892ebc4703d04ff2a870fc26 100644 (file)
@@ -108,7 +108,7 @@ Required properties:
 
 [0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] Documentation/devicetree/bindings/thermal/thermal.txt
+[2] Documentation/devicetree/bindings/thermal/thermal*.yaml
 [3] Documentation/devicetree/bindings/sram/sram.yaml
 [4] Documentation/devicetree/bindings/power/power-domain.yaml
 
index 10b8459e49f8c22a4ff12c2485b00030dc72df64..6064d98b103144e07e8a4d02853bc3fba5d9b02d 100644 (file)
@@ -176,7 +176,7 @@ Required properties:
                                  "fsl,imx8qxp-sc-thermal"
                                followed by "fsl,imx-sc-thermal";
 
-- #thermal-sensor-cells:       See Documentation/devicetree/bindings/thermal/thermal.txt
+- #thermal-sensor-cells:       See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml
                                for a description.
 
 Example (imx8qxp):
index 098d932fc9630a49a5c83b16231def0fb521c87e..e31511255d8e3b6aeb3215f996a42c07445d7b02 100644 (file)
@@ -111,7 +111,7 @@ Thermal:
 --------
 
 For common binding part and usage, refer to
-Documentation/devicetree/bindings/thermal/thermal.txt
+Documentation/devicetree/bindings/thermal/thermal*.yaml
 
 The thermal IP can probe the temperature all around the processor. It
 may feature several channels, each of them wired to one sensor.
index f982a8ed93968f18957b88d37d1cb287327532e2..a21f7709596c08cc0c40c3ddeb4525073b618dae 100644 (file)
@@ -203,7 +203,7 @@ It is possible to setup an overheat interrupt by giving at least one
 critical point to any subnode of the thermal-zone node.
 
 For common binding part and usage, refer to
-Documentation/devicetree/bindings/thermal/thermal.txt
+Documentation/devicetree/bindings/thermal/thermal*.yaml
 
 Required properties:
 - compatible: must be one of:
index 332aed8f4597a86240e498f03933497028a66029..56f4423743838fcba50511a12cedd7e301bb3194 100644 (file)
@@ -18,7 +18,8 @@ Optional properties:
   in unit of nanoseconds.
 - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
 - #cooling-cells:
-     Please refer to Documentation/devicetree/bindings/thermal/thermal.txt.
+     Please refer to
+     Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml.
 
 Examples:
 
index 0551c78619de807b99908d76eaf76cd6831ee3a5..ea4994b35207d9757997d80de6a05bd73a300828 100644 (file)
@@ -21,8 +21,8 @@ Optional properties:
               flow is handled by hardware, hence no software "voltage tracking" is
               needed.
 - #cooling-cells:
-       Please refer to Documentation/devicetree/bindings/thermal/thermal.txt
-       for detail.
+       For details, please refer to
+       Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
 
 Example 1 (MT7623 SoC):
 
index daeca6ae6b769b1084058ce0922d92f6bbc40076..52a24b82fd8643fd8eb72cd37d6d2a9fca2aa8ce 100644 (file)
@@ -5,7 +5,7 @@ Required properties:
 - clocks: Must contain an entry for the CPU clock.
   See ../clocks/clock-bindings.txt for details.
 - operating-points-v2: See ../bindings/opp/opp.txt for details.
-- #cooling-cells: Should be 2. See ../thermal/thermal.txt for details.
+- #cooling-cells: Should be 2. See ../thermal/thermal-cooling-devices.yaml for details.
 
 For each opp entry in 'operating-points-v2' table:
 - opp-supported-hw: Two bitfields indicating:
index 2becdcfdc840c60e6d02ffe0f3893c00eb80321d..f4cfa350f6a1448f88805158b0e03512cf45a95e 100644 (file)
@@ -12,7 +12,8 @@ Optional properties:
 - alarm-gpios: This pin going active indicates something is wrong with
   the fan, and a udev event will be fired.
 - #cooling-cells: If used as a cooling device, must be <2>
-  Also see: Documentation/devicetree/bindings/thermal/thermal.txt
+  Also see:
+  Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
   min and max states are derived from the speed-map of the fan.
 
 Note: At least one the "gpios" or "alarm-gpios" properties must be set.
index c76a7ac47c3426361d02ced15f3458c709bc4a3e..398dcb9657514e5729006e6bed45656ac7daaeac 100644 (file)
@@ -34,8 +34,8 @@ Optional properties:
               LM90 "-ALERT" pin output.
               See interrupt-controller/interrupts.txt for the format.
 
-- #thermal-sensor-cells: should be set to 1. See thermal/thermal.txt for
-             details. See <include/dt-bindings/thermal/lm90.h> for the
+- #thermal-sensor-cells: should be set to 1. See thermal/thermal-sensor.yaml
+             for details. See <include/dt-bindings/thermal/lm90.h> for the
              definition of the local, remote and 2nd remote sensor index
              constants.
 
index 87369264feb96fcac3ef48ec0613e9730175cabc..44ba6765697d891b219d2fc50d28a0933e269982 100644 (file)
@@ -50,7 +50,7 @@ properties:
   nvmem-cell-names:
     const: calibration
 
-  # See ./thermal.txt for details
+  # See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
   "#thermal-sensor-cells":
     enum:
       - 0
index 703979dbd577d7d57754cc192bc718632cc2c809..12fc4ef04837f7cf0c1542d8147498507ba1240e 100644 (file)
@@ -6,7 +6,7 @@ transaction.
 Required properties:
 - compatible: "amazon,al-thermal".
 - reg: The physical base address and length of the sensor's registers.
-- #thermal-sensor-cells: Must be 1. See ./thermal.txt for a description.
+- #thermal-sensor-cells: Must be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description.
 
 Example:
        thermal: thermal {
index f3e68ed03abf89d290fba1016363959140bf56fd..1ab5070c751d5fc24cda59c832a4d80b3c483725 100644 (file)
@@ -23,7 +23,7 @@ properties:
   compatible:
     const: brcm,bcm2711-thermal
 
-  # See ./thermal.txt for details
+  # See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
   "#thermal-sensor-cells":
     const: 0
 
index da8c5b73ad105a5fa5bf1510f5ec1f2d1ab462f9..a3e9ec5dc7ac4c91c8694b42f53f5a16cea96ffd 100644 (file)
@@ -7,7 +7,7 @@ compatible:             should be one of: "brcm,bcm2835-thermal",
                        "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
 reg:                   Address range of the thermal registers.
 clocks:                Phandle of the clock used by the thermal sensor.
-#thermal-sensor-cells: should be 0 (see thermal.txt)
+#thermal-sensor-cells: should be 0 (see Documentation/devicetree/bindings/thermal/thermal-sensor.yaml)
 
 Example:
 
index cef716a236f1a94179d5c61bde45c79df0890e8f..4b19d80e6558b8faa4cbac6d413933292a9eb5cd 100644 (file)
@@ -9,7 +9,7 @@
   by /SOCTHERM/tsensor.
 - clock-names: Input clock name, should be 'thermal_clk'.
 - clocks: phandles for clock specified in "clock-names" property.
-- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
+- #thermal-sensor-cells: Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description.
 
 Example :
 
index 323a3b3822aacfb8236222933ab916df1e58d340..82ed5d4879666b21b97f340e213d5527af037d6a 100644 (file)
@@ -8,12 +8,12 @@ below threshold level.
 
 Required properties:
 -------------------
-#thermal-sensor-cells: Please refer <devicetree/bindings/thermal/thermal.txt>
-                       for more details.
+#thermal-sensor-cells: For more details, please refer to
+                       <devicetree/bindings/thermal/thermal-sensor.yaml>
                        The value must be 0.
 
 For more details, please refer generic thermal DT binding document
-<devicetree/bindings/thermal/thermal.txt>.
+<devicetree/bindings/thermal/thermal*.yaml>.
 
 Please refer <devicetree/bindings/mfd/max77620.txt> for mfd DT binding
 document for the MAX77620.
index f8d7831f39740b16225d730b0e698354c1f4d746..1e249c42fae04b4d7dcf59888b8b9a9a7eb260f0 100644 (file)
@@ -23,7 +23,7 @@ Required properties:
 - resets: Reference to the reset controller controlling the thermal controller.
 - mediatek,auxadc: A phandle to the AUXADC which the thermal controller uses
 - mediatek,apmixedsys: A phandle to the APMIXEDSYS controller.
-- #thermal-sensor-cells : Should be 0. See ./thermal.txt for a description.
+- #thermal-sensor-cells : Should be 0. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description.
 
 Optional properties:
 - nvmem-cells: A phandle to the calibration data provided by a nvmem device. If
index f02f38527a6b6397a73f0c3c3935918c7d1d64fb..db880e7ed713e4f9ebe25be652c116ce5a38219a 100644 (file)
@@ -28,9 +28,10 @@ Required properties :
   See ../reset/reset.txt for details.
 - reset-names : Must include the following entries:
   - soctherm
-- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description
-    of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a
-    list of valid values when referring to thermal sensors.
+- #thermal-sensor-cells : Should be 1. For a description of this property, see
+     Documentation/devicetree/bindings/thermal/thermal-sensor.yaml.
+    See <dt-bindings/thermal/tegra124-soctherm.h> for a list of valid values
+    when referring to thermal sensors.
 - throttle-cfgs: A sub-node which is a container of configuration for each
     hardware throttle events. These events can be set as cooling devices.
   * throttle events: Sub-nodes must be named as "light" or "heavy".
@@ -62,7 +63,8 @@ Required properties :
         TEGRA_SOCTHERM_THROT_LEVEL_MED (75%),
         TEGRA_SOCTHERM_THROT_LEVEL_HIGH (85%).
       - #cooling-cells: Should be 1. This cooling device only support on/off state.
-        See ./thermal.txt for a description of this property.
+        For a description of this property see:
+       Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
 
       Optional properties: The following properties are T210 specific and
       valid only for OCx throttle events.
index e17c07be270b7ebfe26c1b45a0d02974b0663d84..fc87f6aa1b8f5393d3d9ff8b7acf65b5221f746f 100644 (file)
@@ -8,7 +8,7 @@ exposed by BPMP.
 The BPMP thermal node must be located directly inside the main BPMP node. See
 ../firmware/nvidia,tegra186-bpmp.txt for details of the BPMP binding.
 
-This node represents a thermal sensor. See thermal.txt for details of the
+This node represents a thermal sensor. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details of the
 core thermal binding.
 
 Required properties:
index 0273a92a2a849bb6bcc8b97f4291124b0eec2044..2d5b2ad03314bc7ea2b03cc5209d68db4ebc6258 100644 (file)
@@ -8,7 +8,7 @@ Required properties:
 - compatible:      Should contain "qcom,spmi-temp-alarm".
 - reg:             Specifies the SPMI address.
 - interrupts:      PMIC temperature alarm interrupt.
-- #thermal-sensor-cells: Should be 0. See thermal.txt for a description.
+- #thermal-sensor-cells: Should be 0. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description.
 
 Optional properties:
 - io-channels:     Should contain IIO channel specifier for the ADC channel,
index adac01c9d9cd3bcd0cd1c147ebf6a0d8a45ba47d..95462e071ab4791297e6e824063b61391d919af4 100644 (file)
@@ -23,6 +23,7 @@ properties:
         items:
           - enum:
               - qcom,msm8916-tsens
+              - qcom,msm8939-tsens
               - qcom,msm8974-tsens
           - const: qcom,tsens-v0_1
 
index c6aac9bcacf1cd673244ba8a3d7dce8b38088889..7f94669e9ebef75694e932df25b1a5517577e180 100644 (file)
@@ -24,7 +24,7 @@ Required properties:
 - pinctrl-1 : The "default" pinctrl state, it will be set after reset the
              TSADC controller.
 - pinctrl-2 : The "sleep" pinctrl state, it will be in for suspend.
-- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
+- #thermal-sensor-cells : Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description.
 
 Optional properties:
 - rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.
index 212198d4b9379b70c3ca7572f4619479541bb487..2c918d742867a72c8e549c9f13728aa3c16bd975 100644 (file)
@@ -4,7 +4,7 @@ The SMP8758 SoC includes 3 instances of this temperature sensor
 (in the CPU, video decoder, and PCIe controller).
 
 Required properties:
-- #thermal-sensor-cells: Should be 0 (see thermal.txt)
+- #thermal-sensor-cells: Should be 0 (see Documentation/devicetree/bindings/thermal/thermal-sensor.yaml)
 - compatible: "sigma,smp8758-thermal"
 - reg: Address range of the thermal registers
 
index 691a09db2fefca3a13ba655fcb323d69e55c90e4..e136946a2f4fd9f42c2736a6e0926166bdc82e2c 100644 (file)
@@ -8,7 +8,7 @@ temperature using voltage-temperature lookup table.
 Required properties:
 ===================
 - compatible:               Must be "generic-adc-thermal".
-- #thermal-sensor-cells:     Should be 1. See ./thermal.txt for a description
+- #thermal-sensor-cells:     Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description
                             of this property.
 Optional properties:
 ===================
diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
deleted file mode 100644 (file)
index f78bec1..0000000
+++ /dev/null
@@ -1,586 +0,0 @@
-* Thermal Framework Device Tree descriptor
-
-This file describes a generic binding to provide a way of
-defining hardware thermal structure using device tree.
-A thermal structure includes thermal zones and their components,
-such as trip points, polling intervals, sensors and cooling devices
-binding descriptors.
-
-The target of device tree thermal descriptors is to describe only
-the hardware thermal aspects. The thermal device tree bindings are
-not about how the system must control or which algorithm or policy
-must be taken in place.
-
-There are five types of nodes involved to describe thermal bindings:
-- thermal sensors: devices which may be used to take temperature
-  measurements.
-- cooling devices: devices which may be used to dissipate heat.
-- trip points: describe key temperatures at which cooling is recommended. The
-  set of points should be chosen based on hardware limits.
-- cooling maps: used to describe links between trip points and cooling devices;
-- thermal zones: used to describe thermal data within the hardware;
-
-The following is a description of each of these node types.
-
-* Thermal sensor devices
-
-Thermal sensor devices are nodes providing temperature sensing capabilities on
-thermal zones. Typical devices are I2C ADC converters and bandgaps. These are
-nodes providing temperature data to thermal zones. Thermal sensor devices may
-control one or more internal sensors.
-
-Required property:
-- #thermal-sensor-cells: Used to provide sensor device specific information
-  Type: unsigned        while referring to it. Typically 0 on thermal sensor
-  Size: one cell        nodes with only one sensor, and at least 1 on nodes
-                        with several internal sensors, in order
-                        to identify uniquely the sensor instances within
-                        the IC. See thermal zone binding for more details
-                        on how consumers refer to sensor devices.
-
-* Cooling device nodes
-
-Cooling devices are nodes providing control on power dissipation. There
-are essentially two ways to provide control on power dissipation. First
-is by means of regulating device performance, which is known as passive
-cooling. A typical passive cooling is a CPU that has dynamic voltage and
-frequency scaling (DVFS), and uses lower frequencies as cooling states.
-Second is by means of activating devices in order to remove
-the dissipated heat, which is known as active cooling, e.g. regulating
-fan speeds. In both cases, cooling devices shall have a way to determine
-the state of cooling in which the device is.
-
-Any cooling device has a range of cooling states (i.e. different levels
-of heat dissipation). For example a fan's cooling states correspond to
-the different fan speeds possible. Cooling states are referred to by
-single unsigned integers, where larger numbers mean greater heat
-dissipation. The precise set of cooling states associated with a device
-should be defined in a particular device's binding.
-For more examples of cooling devices, refer to the example sections below.
-
-Required properties:
-- #cooling-cells:      Used to provide cooling device specific information
-  Type: unsigned       while referring to it. Must be at least 2, in order
-  Size: one cell       to specify minimum and maximum cooling state used
-                       in the reference. The first cell is the minimum
-                       cooling state requested and the second cell is
-                       the maximum cooling state requested in the reference.
-                       See Cooling device maps section below for more details
-                       on how consumers refer to cooling devices.
-
-* Trip points
-
-The trip node is a node to describe a point in the temperature domain
-in which the system takes an action. This node describes just the point,
-not the action.
-
-Required properties:
-- temperature:         An integer indicating the trip temperature level,
-  Type: signed         in millicelsius.
-  Size: one cell
-
-- hysteresis:          A low hysteresis value on temperature property (above).
-  Type: unsigned       This is a relative value, in millicelsius.
-  Size: one cell
-
-- type:                        a string containing the trip type. Expected values are:
-       "active":       A trip point to enable active cooling
-       "passive":      A trip point to enable passive cooling
-       "hot":          A trip point to notify emergency
-       "critical":     Hardware not reliable.
-  Type: string
-
-* Cooling device maps
-
-The cooling device maps node is a node to describe how cooling devices
-get assigned to trip points of the zone. The cooling devices are expected
-to be loaded in the target system.
-
-Required properties:
-- cooling-device:      A list of phandles of cooling devices with their specifiers,
-  Type: phandle +      referring to which cooling devices are used in this
-    cooling specifier  binding. In the cooling specifier, the first cell
-                       is the minimum cooling state and the second cell
-                       is the maximum cooling state used in this map.
-- trip:                        A phandle of a trip point node within the same thermal
-  Type: phandle of     zone.
-   trip point node
-
-Optional property:
-- contribution:                The cooling contribution to the thermal zone of the
-  Type: unsigned       referred cooling device at the referred trip point.
-  Size: one cell       The contribution is a ratio of the sum
-                       of all cooling contributions within a thermal zone.
-
-Note: Using the THERMAL_NO_LIMIT (-1UL) constant in the cooling-device phandle
-limit specifier means:
-(i)   - minimum state allowed for minimum cooling state used in the reference.
-(ii)  - maximum state allowed for maximum cooling state used in the reference.
-Refer to include/dt-bindings/thermal/thermal.h for definition of this constant.
-
-* Thermal zone nodes
-
-The thermal zone node is the node containing all the required info
-for describing a thermal zone, including its cooling device bindings. The
-thermal zone node must contain, apart from its own properties, one sub-node
-containing trip nodes and one sub-node containing all the zone cooling maps.
-
-Required properties:
-- polling-delay:       The maximum number of milliseconds to wait between polls
-  Type: unsigned       when checking this thermal zone.
-  Size: one cell
-
-- polling-delay-passive: The maximum number of milliseconds to wait
-  Type: unsigned       between polls when performing passive cooling.
-  Size: one cell
-
-- thermal-sensors:     A list of thermal sensor phandles and sensor specifier
-  Type: list of                used while monitoring the thermal zone.
-  phandles + sensor
-  specifier
-
-- trips:               A sub-node which is a container of only trip point nodes
-  Type: sub-node       required to describe the thermal zone.
-
-Optional property:
-- cooling-maps:                A sub-node which is a container of only cooling device
-  Type: sub-node       map nodes, used to describe the relation between trips
-                       and cooling devices.
-
-- coefficients:                An array of integers (one signed cell) containing
-  Type: array          coefficients to compose a linear relation between
-  Elem size: one cell  the sensors listed in the thermal-sensors property.
-  Elem type: signed    Coefficients defaults to 1, in case this property
-                       is not specified. A simple linear polynomial is used:
-                       Z = c0 * x0 + c1 * x1 + ... + c(n-1) * x(n-1) + cn.
-
-                       The coefficients are ordered and they match with sensors
-                       by means of sensor ID. Additional coefficients are
-                       interpreted as constant offset.
-
-- sustainable-power:   An estimate of the sustainable power (in mW) that the
-  Type: unsigned       thermal zone can dissipate at the desired
-  Size: one cell       control temperature.  For reference, the
-                       sustainable power of a 4'' phone is typically
-                       2000mW, while on a 10'' tablet is around
-                       4500mW.
-
-Note: The delay properties are bound to the maximum dT/dt (temperature
-derivative over time) in two situations for a thermal zone:
-(i)  - when passive cooling is activated (polling-delay-passive); and
-(ii) - when the zone just needs to be monitored (polling-delay) or
-when active cooling is activated.
-
-The maximum dT/dt is highly bound to hardware power consumption and dissipation
-capability. The delays should be chosen to account for said max dT/dt,
-such that a device does not cross several trip boundaries unexpectedly
-between polls. Choosing the right polling delays shall avoid having the
-device in temperature ranges that may damage the silicon structures and
-reduce silicon lifetime.
-
-* The thermal-zones node
-
-The "thermal-zones" node is a container for all thermal zone nodes. It shall
-contain only sub-nodes describing thermal zones as in the section
-"Thermal zone nodes". The "thermal-zones" node appears under "/".
-
-* Examples
-
-Below are several examples on how to use thermal data descriptors
-using device tree bindings:
-
-(a) - CPU thermal zone
-
-The CPU thermal zone example below describes how to setup one thermal zone
-using one single sensor as temperature source and many cooling devices and
-power dissipation control sources.
-
-#include <dt-bindings/thermal/thermal.h>
-
-cpus {
-       /*
-        * Here is an example of describing a cooling device for a DVFS
-        * capable CPU. The CPU node describes its four OPPs.
-        * The cooling states possible are 0..3, and they are
-        * used as OPP indexes. The minimum cooling state is 0, which means
-        * all four OPPs can be available to the system. The maximum
-        * cooling state is 3, which means only the lowest OPPs (198MHz@0.85V)
-        * can be available in the system.
-        */
-       cpu0: cpu@0 {
-               ...
-               operating-points = <
-                       /* kHz    uV */
-                       970000  1200000
-                       792000  1100000
-                       396000  950000
-                       198000  850000
-               >;
-               #cooling-cells = <2>; /* min followed by max */
-       };
-       ...
-};
-
-&i2c1 {
-       ...
-       /*
-        * A simple fan controller which supports 10 speeds of operation
-        * (represented as 0-9).
-        */
-       fan0: fan@48 {
-               ...
-               #cooling-cells = <2>; /* min followed by max */
-       };
-};
-
-ocp {
-       ...
-       /*
-        * A simple IC with a single bandgap temperature sensor.
-        */
-       bandgap0: bandgap@0000ed00 {
-               ...
-               #thermal-sensor-cells = <0>;
-       };
-};
-
-thermal-zones {
-       cpu_thermal: cpu-thermal {
-               polling-delay-passive = <250>; /* milliseconds */
-               polling-delay = <1000>; /* milliseconds */
-
-               thermal-sensors = <&bandgap0>;
-
-               trips {
-                       cpu_alert0: cpu-alert0 {
-                               temperature = <90000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "active";
-                       };
-                       cpu_alert1: cpu-alert1 {
-                               temperature = <100000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "passive";
-                       };
-                       cpu_crit: cpu-crit {
-                               temperature = <125000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "critical";
-                       };
-               };
-
-               cooling-maps {
-                       map0 {
-                               trip = <&cpu_alert0>;
-                               cooling-device = <&fan0 THERMAL_NO_LIMIT 4>;
-                       };
-                       map1 {
-                               trip = <&cpu_alert1>;
-                               cooling-device = <&fan0 5 THERMAL_NO_LIMIT>, <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-                       };
-               };
-       };
-};
-
-In the example above, the ADC sensor (bandgap0) at address 0x0000ED00 is
-used to monitor the zone 'cpu-thermal' using its sole sensor. A fan
-device (fan0) is controlled via I2C bus 1, at address 0x48, and has ten
-different cooling states 0-9. It is used to remove the heat out of
-the thermal zone 'cpu-thermal' using its cooling states
-from its minimum to 4, when it reaches trip point 'cpu_alert0'
-at 90C, as an example of active cooling. The same cooling device is used at
-'cpu_alert1', but from 5 to its maximum state. The cpu@0 device is also
-linked to the same thermal zone, 'cpu-thermal', as a passive cooling device,
-using all its cooling states at trip point 'cpu_alert1',
-which is a trip point at 100C. On the thermal zone 'cpu-thermal', at the
-temperature of 125C, represented by the trip point 'cpu_crit', the silicon
-is not reliable anymore.
-
-(b) - IC with several internal sensors
-
-The example below describes how to deploy several thermal zones based off a
-single sensor IC, assuming it has several internal sensors. This is a common
-case on SoC designs with several internal IPs that may need different thermal
-requirements, and thus may have their own sensor to monitor or detect internal
-hotspots in their silicon.
-
-#include <dt-bindings/thermal/thermal.h>
-
-ocp {
-       ...
-       /*
-        * A simple IC with several bandgap temperature sensors.
-        */
-       bandgap0: bandgap@0000ed00 {
-               ...
-               #thermal-sensor-cells = <1>;
-       };
-};
-
-thermal-zones {
-       cpu_thermal: cpu-thermal {
-               polling-delay-passive = <250>; /* milliseconds */
-               polling-delay = <1000>; /* milliseconds */
-
-                               /* sensor       ID */
-               thermal-sensors = <&bandgap0     0>;
-
-               trips {
-                       /* each zone within the SoC may have its own trips */
-                       cpu_alert: cpu-alert {
-                               temperature = <100000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "passive";
-                       };
-                       cpu_crit: cpu-crit {
-                               temperature = <125000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "critical";
-                       };
-               };
-
-               cooling-maps {
-                       /* each zone within the SoC may have its own cooling */
-                       ...
-               };
-       };
-
-       gpu_thermal: gpu-thermal {
-               polling-delay-passive = <120>; /* milliseconds */
-               polling-delay = <1000>; /* milliseconds */
-
-                               /* sensor       ID */
-               thermal-sensors = <&bandgap0     1>;
-
-               trips {
-                       /* each zone within the SoC may have its own trips */
-                       gpu_alert: gpu-alert {
-                               temperature = <90000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "passive";
-                       };
-                       gpu_crit: gpu-crit {
-                               temperature = <105000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "critical";
-                       };
-               };
-
-               cooling-maps {
-                       /* each zone within the SoC may have its own cooling */
-                       ...
-               };
-       };
-
-       dsp_thermal: dsp-thermal {
-               polling-delay-passive = <50>; /* milliseconds */
-               polling-delay = <1000>; /* milliseconds */
-
-                               /* sensor       ID */
-               thermal-sensors = <&bandgap0     2>;
-
-               trips {
-                       /* each zone within the SoC may have its own trips */
-                       dsp_alert: dsp-alert {
-                               temperature = <90000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "passive";
-                       };
-                       dsp_crit: gpu-crit {
-                               temperature = <135000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "critical";
-                       };
-               };
-
-               cooling-maps {
-                       /* each zone within the SoC may have its own cooling */
-                       ...
-               };
-       };
-};
-
-In the example above, there is one bandgap IC which has the capability to
-monitor three sensors. The hardware has been designed so that sensors are
-placed on different places in the DIE to monitor different temperature
-hotspots: one for CPU thermal zone, one for GPU thermal zone and the
-other to monitor a DSP thermal zone.
-
-Thus, there is a need to assign each sensor provided by the bandgap IC
-to different thermal zones. This is achieved by means of using the
-#thermal-sensor-cells property and using the first cell of the sensor
-specifier as sensor ID. In the example, then, <bandgap 0> is used to
-monitor CPU thermal zone, <bandgap 1> is used to monitor GPU thermal
-zone and <bandgap 2> is used to monitor DSP thermal zone. Each zone
-may be uncorrelated, having its own dT/dt requirements, trips
-and cooling maps.
-
-
-(c) - Several sensors within one single thermal zone
-
-The example below illustrates how to use more than one sensor within
-one thermal zone.
-
-#include <dt-bindings/thermal/thermal.h>
-
-&i2c1 {
-       ...
-       /*
-        * A simple IC with a single temperature sensor.
-        */
-       adc: sensor@49 {
-               ...
-               #thermal-sensor-cells = <0>;
-       };
-};
-
-ocp {
-       ...
-       /*
-        * A simple IC with a single bandgap temperature sensor.
-        */
-       bandgap0: bandgap@0000ed00 {
-               ...
-               #thermal-sensor-cells = <0>;
-       };
-};
-
-thermal-zones {
-       cpu_thermal: cpu-thermal {
-               polling-delay-passive = <250>; /* milliseconds */
-               polling-delay = <1000>; /* milliseconds */
-
-               thermal-sensors = <&bandgap0>,  /* cpu */
-                                 <&adc>;       /* pcb north */
-
-               /* hotspot = 100 * bandgap - 120 * adc + 484 */
-               coefficients =          <100    -120    484>;
-
-               trips {
-                       ...
-               };
-
-               cooling-maps {
-                       ...
-               };
-       };
-};
-
-In some cases, there is a need to use more than one sensor to extrapolate
-a thermal hotspot in the silicon. The above example illustrates this situation.
-For instance, it may be the case that a sensor external to CPU IP may be placed
-close to CPU hotspot and together with internal CPU sensor, it is used
-to determine the hotspot. Assuming this is the case for the above example,
-the hypothetical extrapolation rule would be:
-               hotspot = 100 * bandgap - 120 * adc + 484
-
-In other context, the same idea can be used to add fixed offset. For instance,
-consider the hotspot extrapolation rule below:
-               hotspot = 1 * adc + 6000
-
-In the above equation, the hotspot is always 6C higher than what is read
-from the ADC sensor. The binding would be then:
-        thermal-sensors =  <&adc>;
-
-               /* hotspot = 1 * adc + 6000 */
-       coefficients =          <1      6000>;
-
-(d) - Board thermal
-
-The board thermal example below illustrates how to setup one thermal zone
-with many sensors and many cooling devices.
-
-#include <dt-bindings/thermal/thermal.h>
-
-&i2c1 {
-       ...
-       /*
-        * An IC with several temperature sensor.
-        */
-       adc_dummy: sensor@50 {
-               ...
-               #thermal-sensor-cells = <1>; /* sensor internal ID */
-       };
-};
-
-thermal-zones {
-       batt-thermal {
-               polling-delay-passive = <500>; /* milliseconds */
-               polling-delay = <2500>; /* milliseconds */
-
-                               /* sensor       ID */
-               thermal-sensors = <&adc_dummy     4>;
-
-               trips {
-                       ...
-               };
-
-               cooling-maps {
-                       ...
-               };
-       };
-
-       board_thermal: board-thermal {
-               polling-delay-passive = <1000>; /* milliseconds */
-               polling-delay = <2500>; /* milliseconds */
-
-                               /* sensor       ID */
-               thermal-sensors = <&adc_dummy     0>, /* pcb top edge */
-                                 <&adc_dummy     1>, /* lcd */
-                                 <&adc_dummy     2>; /* back cover */
-               /*
-                * An array of coefficients describing the sensor
-                * linear relation. E.g.:
-                * z = c1*x1 + c2*x2 + c3*x3
-                */
-               coefficients =          <1200   -345    890>;
-
-               sustainable-power = <2500>;
-
-               trips {
-                       /* Trips are based on resulting linear equation */
-                       cpu_trip: cpu-trip {
-                               temperature = <60000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "passive";
-                       };
-                       gpu_trip: gpu-trip {
-                               temperature = <55000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "passive";
-                       }
-                       lcd_trip: lcp-trip {
-                               temperature = <53000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "passive";
-                       };
-                       crit_trip: crit-trip {
-                               temperature = <68000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "critical";
-                       };
-               };
-
-               cooling-maps {
-                       map0 {
-                               trip = <&cpu_trip>;
-                               cooling-device = <&cpu0 0 2>;
-                               contribution = <55>;
-                       };
-                       map1 {
-                               trip = <&gpu_trip>;
-                               cooling-device = <&gpu0 0 2>;
-                               contribution = <20>;
-                       };
-                       map2 {
-                               trip = <&lcd_trip>;
-                               cooling-device = <&lcd0 5 10>;
-                               contribution = <15>;
-                       };
-               };
-       };
-};
-
-The above example is a mix of previous examples, a sensor IP with several internal
-sensors used to monitor different zones, one of them is composed by several sensors and
-with different cooling devices.
index 5511d95b939349d382f5ec62d8ad1c91420fe3f1..a45fe1a6251ea83296be259c54b92ffc2730f00e 100644 (file)
@@ -17086,6 +17086,14 @@ F:     drivers/thermal/cpufreq_cooling.c
 F:     drivers/thermal/cpuidle_cooling.c
 F:     include/linux/cpu_cooling.h
 
+THERMAL/POWER_ALLOCATOR
+M:     Lukasz Luba <lukasz.luba@arm.com>
+L:     linux-pm@vger.kernel.org
+S:     Maintained
+F:     Documentation/driver-api/thermal/power_allocator.rst
+F:     drivers/thermal/gov_power_allocator.c
+F:     include/trace/events/thermal_power_allocator.h
+
 THINKPAD ACPI EXTRAS DRIVER
 M:     Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
 L:     ibm-acpi-devel@lists.sourceforge.net
index 19067a5e52934e6fb356448fe13457409176e58a..12c0ece746f04ac763bf2630185d40fe9ac36fe7 100644 (file)
@@ -172,7 +172,6 @@ struct acpi_thermal {
        struct acpi_thermal_trips trips;
        struct acpi_handle_list devices;
        struct thermal_zone_device *thermal_zone;
-       int tz_enabled;
        int kelvin_offset;      /* in millidegrees */
        struct work_struct thermal_check_work;
 };
@@ -500,9 +499,6 @@ static void acpi_thermal_check(void *data)
 {
        struct acpi_thermal *tz = data;
 
-       if (!tz->tz_enabled)
-               return;
-
        thermal_zone_device_update(tz->thermal_zone,
                                   THERMAL_EVENT_UNSPECIFIED);
 }
@@ -526,50 +522,6 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
        return 0;
 }
 
-static int thermal_get_mode(struct thermal_zone_device *thermal,
-                               enum thermal_device_mode *mode)
-{
-       struct acpi_thermal *tz = thermal->devdata;
-
-       if (!tz)
-               return -EINVAL;
-
-       *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED :
-               THERMAL_DEVICE_DISABLED;
-
-       return 0;
-}
-
-static int thermal_set_mode(struct thermal_zone_device *thermal,
-                               enum thermal_device_mode mode)
-{
-       struct acpi_thermal *tz = thermal->devdata;
-       int enable;
-
-       if (!tz)
-               return -EINVAL;
-
-       /*
-        * enable/disable thermal management from ACPI thermal driver
-        */
-       if (mode == THERMAL_DEVICE_ENABLED)
-               enable = 1;
-       else if (mode == THERMAL_DEVICE_DISABLED) {
-               enable = 0;
-               pr_warn("thermal zone will be disabled\n");
-       } else
-               return -EINVAL;
-
-       if (enable != tz->tz_enabled) {
-               tz->tz_enabled = enable;
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                       "%s kernel ACPI thermal control\n",
-                       tz->tz_enabled ? "Enable" : "Disable"));
-               acpi_thermal_check(tz);
-       }
-       return 0;
-}
-
 static int thermal_get_trip_type(struct thermal_zone_device *thermal,
                                 int trip, enum thermal_trip_type *type)
 {
@@ -856,8 +808,6 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
        .bind = acpi_thermal_bind_cooling_device,
        .unbind = acpi_thermal_unbind_cooling_device,
        .get_temp = thermal_get_temp,
-       .get_mode = thermal_get_mode,
-       .set_mode = thermal_set_mode,
        .get_trip_type = thermal_get_trip_type,
        .get_trip_temp = thermal_get_trip_temp,
        .get_crit_temp = thermal_get_crit_temp,
@@ -901,23 +851,39 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
        result = sysfs_create_link(&tz->device->dev.kobj,
                                   &tz->thermal_zone->device.kobj, "thermal_zone");
        if (result)
-               return result;
+               goto unregister_tzd;
 
        result = sysfs_create_link(&tz->thermal_zone->device.kobj,
                                   &tz->device->dev.kobj, "device");
        if (result)
-               return result;
+               goto remove_tz_link;
 
        status =  acpi_bus_attach_private_data(tz->device->handle,
                                               tz->thermal_zone);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
+       if (ACPI_FAILURE(status)) {
+               result = -ENODEV;
+               goto remove_dev_link;
+       }
 
-       tz->tz_enabled = 1;
+       result = thermal_zone_device_enable(tz->thermal_zone);
+       if (result)
+               goto acpi_bus_detach;
 
        dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
                 tz->thermal_zone->id);
+
        return 0;
+
+acpi_bus_detach:
+       acpi_bus_detach_private_data(tz->device->handle);
+remove_dev_link:
+       sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
+remove_tz_link:
+       sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
+unregister_tzd:
+       thermal_zone_device_unregister(tz->thermal_zone);
+
+       return result;
 }
 
 static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
index 3de8a5e83b6c7f73ac3868d2550bfef45f7fd073..e3510e9b21f3ceed337f92ede334d50a9efd7c7c 100644 (file)
@@ -92,6 +92,14 @@ int cxgb4_thermal_init(struct adapter *adap)
                ch_thermal->tzdev = NULL;
                return ret;
        }
+
+       ret = thermal_zone_device_enable(ch_thermal->tzdev);
+       if (ret) {
+               dev_err(adap->pdev_dev, "Failed to enable thermal zone\n");
+               thermal_zone_device_unregister(adap->ch_thermal.tzdev);
+               return ret;
+       }
+
        return 0;
 }
 
index 05f8d5a92862f490424e98180f11fe31aa84297e..8fa286ccdd6bb281a834bc135593487878930403 100644 (file)
@@ -98,7 +98,6 @@ struct mlxsw_thermal_module {
        struct mlxsw_thermal *parent;
        struct thermal_zone_device *tzdev;
        struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
-       enum thermal_device_mode mode;
        int module; /* Module or gearbox number */
 };
 
@@ -110,7 +109,6 @@ struct mlxsw_thermal {
        struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
        u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
        struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
-       enum thermal_device_mode mode;
        struct mlxsw_thermal_module *tz_module_arr;
        u8 tz_module_num;
        struct mlxsw_thermal_module *tz_gearbox_arr;
@@ -277,36 +275,6 @@ static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
        return 0;
 }
 
-static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev,
-                                 enum thermal_device_mode *mode)
-{
-       struct mlxsw_thermal *thermal = tzdev->devdata;
-
-       *mode = thermal->mode;
-
-       return 0;
-}
-
-static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
-                                 enum thermal_device_mode mode)
-{
-       struct mlxsw_thermal *thermal = tzdev->devdata;
-
-       mutex_lock(&tzdev->lock);
-
-       if (mode == THERMAL_DEVICE_ENABLED)
-               tzdev->polling_delay = thermal->polling_delay;
-       else
-               tzdev->polling_delay = 0;
-
-       mutex_unlock(&tzdev->lock);
-
-       thermal->mode = mode;
-       thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
-
-       return 0;
-}
-
 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
                                  int *p_temp)
 {
@@ -406,8 +374,6 @@ static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev,
 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
        .bind = mlxsw_thermal_bind,
        .unbind = mlxsw_thermal_unbind,
-       .get_mode = mlxsw_thermal_get_mode,
-       .set_mode = mlxsw_thermal_set_mode,
        .get_temp = mlxsw_thermal_get_temp,
        .get_trip_type  = mlxsw_thermal_get_trip_type,
        .get_trip_temp  = mlxsw_thermal_get_trip_temp,
@@ -465,37 +431,6 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
        return err;
 }
 
-static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev,
-                                        enum thermal_device_mode *mode)
-{
-       struct mlxsw_thermal_module *tz = tzdev->devdata;
-
-       *mode = tz->mode;
-
-       return 0;
-}
-
-static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev,
-                                        enum thermal_device_mode mode)
-{
-       struct mlxsw_thermal_module *tz = tzdev->devdata;
-       struct mlxsw_thermal *thermal = tz->parent;
-
-       mutex_lock(&tzdev->lock);
-
-       if (mode == THERMAL_DEVICE_ENABLED)
-               tzdev->polling_delay = thermal->polling_delay;
-       else
-               tzdev->polling_delay = 0;
-
-       mutex_unlock(&tzdev->lock);
-
-       tz->mode = mode;
-       thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
-
-       return 0;
-}
-
 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
                                         int *p_temp)
 {
@@ -611,8 +546,6 @@ static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev,
 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
        .bind           = mlxsw_thermal_module_bind,
        .unbind         = mlxsw_thermal_module_unbind,
-       .get_mode       = mlxsw_thermal_module_mode_get,
-       .set_mode       = mlxsw_thermal_module_mode_set,
        .get_temp       = mlxsw_thermal_module_temp_get,
        .get_trip_type  = mlxsw_thermal_module_trip_type_get,
        .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,
 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
        .bind           = mlxsw_thermal_module_bind,
        .unbind         = mlxsw_thermal_module_unbind,
-       .get_mode       = mlxsw_thermal_module_mode_get,
-       .set_mode       = mlxsw_thermal_module_mode_set,
        .get_temp       = mlxsw_thermal_gearbox_temp_get,
        .get_trip_type  = mlxsw_thermal_module_trip_type_get,
        .get_trip_temp  = mlxsw_thermal_module_trip_temp_get,
@@ -780,8 +711,11 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
                return err;
        }
 
-       module_tz->mode = THERMAL_DEVICE_ENABLED;
-       return 0;
+       err = thermal_zone_device_enable(module_tz->tzdev);
+       if (err)
+               thermal_zone_device_unregister(module_tz->tzdev);
+
+       return err;
 }
 
 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
@@ -884,6 +818,7 @@ static int
 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
 {
        char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
+       int ret;
 
        snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
                 gearbox_tz->module + 1);
@@ -896,8 +831,11 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
        if (IS_ERR(gearbox_tz->tzdev))
                return PTR_ERR(gearbox_tz->tzdev);
 
-       gearbox_tz->mode = THERMAL_DEVICE_ENABLED;
-       return 0;
+       ret = thermal_zone_device_enable(gearbox_tz->tzdev);
+       if (ret)
+               thermal_zone_device_unregister(gearbox_tz->tzdev);
+
+       return ret;
 }
 
 static void
@@ -1065,10 +1003,15 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
        if (err)
                goto err_unreg_modules_tzdev;
 
-       thermal->mode = THERMAL_DEVICE_ENABLED;
+       err = thermal_zone_device_enable(thermal->tzdev);
+       if (err)
+               goto err_unreg_gearboxes;
+
        *p_thermal = thermal;
        return 0;
 
+err_unreg_gearboxes:
+       mlxsw_thermal_gearboxes_fini(thermal);
 err_unreg_modules_tzdev:
        mlxsw_thermal_modules_fini(thermal);
 err_unreg_tzdev:
index 418e59b7c6719d5c7bb9d51d2606edeecfef0727..0c95663bf9edcf26195facde3f351b5af40e05d5 100644 (file)
@@ -733,7 +733,7 @@ static  struct thermal_zone_device_ops tzone_ops = {
 
 static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
 {
-       int i;
+       int i, ret;
        char name[16];
        static atomic_t counter = ATOMIC_INIT(0);
 
@@ -759,6 +759,13 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
                return;
        }
 
+       ret = thermal_zone_device_enable(mvm->tz_device.tzone);
+       if (ret) {
+               IWL_DEBUG_TEMP(mvm, "Failed to enable thermal zone\n");
+               thermal_zone_device_unregister(mvm->tz_device.tzone);
+               return;
+       }
+
        /* 0 is a valid temperature,
         * so initialize the array with S16_MIN which invalid temperature
         */
index a7a0b2e0ceb936599941b573431fb7c75970b7c1..44b6bfbd32dff8e09263a521eda7f0573c6fb1e7 100644 (file)
@@ -397,39 +397,24 @@ static inline void acerhdf_revert_to_bios_mode(void)
 {
        acerhdf_change_fanstate(ACERHDF_FAN_AUTO);
        kernelmode = 0;
-       if (thz_dev)
-               thz_dev->polling_delay = 0;
+
        pr_notice("kernel mode fan control OFF\n");
 }
 static inline void acerhdf_enable_kernelmode(void)
 {
        kernelmode = 1;
 
-       thz_dev->polling_delay = interval*1000;
-       thermal_zone_device_update(thz_dev, THERMAL_EVENT_UNSPECIFIED);
        pr_notice("kernel mode fan control ON\n");
 }
 
-static int acerhdf_get_mode(struct thermal_zone_device *thermal,
-                           enum thermal_device_mode *mode)
-{
-       if (verbose)
-               pr_notice("kernel mode fan control %d\n", kernelmode);
-
-       *mode = (kernelmode) ? THERMAL_DEVICE_ENABLED
-                            : THERMAL_DEVICE_DISABLED;
-
-       return 0;
-}
-
 /*
  * set operation mode;
  * enabled: the thermal layer of the kernel takes care about
  *          the temperature and the fan.
  * disabled: the BIOS takes control of the fan.
  */
-static int acerhdf_set_mode(struct thermal_zone_device *thermal,
-                           enum thermal_device_mode mode)
+static int acerhdf_change_mode(struct thermal_zone_device *thermal,
+                              enum thermal_device_mode mode)
 {
        if (mode == THERMAL_DEVICE_DISABLED && kernelmode)
                acerhdf_revert_to_bios_mode();
@@ -488,8 +473,7 @@ static struct thermal_zone_device_ops acerhdf_dev_ops = {
        .bind = acerhdf_bind,
        .unbind = acerhdf_unbind,
        .get_temp = acerhdf_get_ec_temp,
-       .get_mode = acerhdf_get_mode,
-       .set_mode = acerhdf_set_mode,
+       .change_mode = acerhdf_change_mode,
        .get_trip_type = acerhdf_get_trip_type,
        .get_trip_hyst = acerhdf_get_trip_hyst,
        .get_trip_temp = acerhdf_get_trip_temp,
@@ -733,6 +717,8 @@ static void acerhdf_unregister_platform(void)
 
 static int __init acerhdf_register_thermal(void)
 {
+       int ret;
+
        cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL,
                                                 &acerhdf_cooling_ops);
 
@@ -746,6 +732,13 @@ static int __init acerhdf_register_thermal(void)
        if (IS_ERR(thz_dev))
                return -EINVAL;
 
+       if (kernelmode)
+               ret = thermal_zone_device_enable(thz_dev);
+       else
+               ret = thermal_zone_device_disable(thz_dev);
+       if (ret)
+               return ret;
+
        if (strcmp(thz_dev->governor->name,
                                acerhdf_zone_params.governor_name)) {
                pr_err("Didn't get thermal governor %s, perhaps not compiled into thermal subsystem.\n",
index f402e2e74a38392e9abf1eae8debc3630dcc828c..f12f4e7bd971c14e2a737c1a1fe61435a1f23ee4 100644 (file)
@@ -493,6 +493,12 @@ static int mid_thermal_probe(struct platform_device *pdev)
                        ret = PTR_ERR(pinfo->tzd[i]);
                        goto err;
                }
+               ret = thermal_zone_device_enable(pinfo->tzd[i]);
+               if (ret) {
+                       kfree(td_info);
+                       thermal_zone_device_unregister(pinfo->tzd[i]);
+                       goto err;
+               }
        }
 
        pinfo->pdev = pdev;
index 02b37fe6061c08ee0b9ad97ccc8ff228f12d6fd2..90e56736d4794f6cdf68e9aa387857465bf9ae9c 100644 (file)
@@ -939,7 +939,7 @@ static struct thermal_zone_device_ops psy_tzd_ops = {
 
 static int psy_register_thermal(struct power_supply *psy)
 {
-       int i;
+       int i, ret;
 
        if (psy->desc->no_thermal)
                return 0;
@@ -949,7 +949,12 @@ static int psy_register_thermal(struct power_supply *psy)
                if (psy->desc->properties[i] == POWER_SUPPLY_PROP_TEMP) {
                        psy->tzd = thermal_zone_device_register(psy->desc->name,
                                        0, 0, psy, &psy_tzd_ops, NULL, 0, 0);
-                       return PTR_ERR_OR_ZERO(psy->tzd);
+                       if (IS_ERR(psy->tzd))
+                               return PTR_ERR(psy->tzd);
+                       ret = thermal_zone_device_enable(psy->tzd);
+                       if (ret)
+                               thermal_zone_device_unregister(psy->tzd);
+                       return ret;
                }
        }
        return 0;
index 3eb2348e52427495bb36a0fc1b6bb34453a319a7..13991d68c844384e2bb4c6ce316a0d2bfd72a7d8 100644 (file)
@@ -17,6 +17,16 @@ menuconfig THERMAL
 
 if THERMAL
 
+config THERMAL_NETLINK
+       bool "Thermal netlink management"
+       depends on NET
+       default y
+       help
+         The thermal framework has a netlink interface to do thermal
+         zones discovery, temperature readings and events such as
+         trip point crossed, cooling device update or governor
+         change. It is recommended to enable the feature.
+
 config THERMAL_STATISTICS
        bool "Thermal state transition statistics"
        help
@@ -180,16 +190,6 @@ config CPU_IDLE_THERMAL
          idle cycle.
 endif
 
-config CLOCK_THERMAL
-       bool "Generic clock cooling support"
-       depends on COMMON_CLK
-       depends on PM_OPP
-       help
-         This entry implements the generic clock cooling mechanism through
-         frequency clipping. Typically used to cool off co-processors. The
-         device that is configured to use this cooling mechanism will be
-         controlled to reduce clock frequency whenever temperature is high.
-
 config DEVFREQ_THERMAL
        bool "Generic device cooling support"
        depends on PM_DEVFREQ
index 0c8b84a09b9aa7555b811ebe0da5a9b898ced8de..b8d96d26f9ec3f6c74c5a4f40fb81fcdc91cc091 100644 (file)
@@ -7,6 +7,9 @@ obj-$(CONFIG_THERMAL)           += thermal_sys.o
 thermal_sys-y                  += thermal_core.o thermal_sysfs.o \
                                        thermal_helpers.o
 
+# netlink interface to manage the thermal framework
+thermal_sys-$(CONFIG_THERMAL_NETLINK)          += thermal_netlink.o
+
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)            += thermal_hwmon.o
 thermal_sys-$(CONFIG_THERMAL_OF)               += thermal_of.o
@@ -22,9 +25,6 @@ thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR)     += gov_power_allocator.o
 thermal_sys-$(CONFIG_CPU_FREQ_THERMAL) += cpufreq_cooling.o
 thermal_sys-$(CONFIG_CPU_IDLE_THERMAL) += cpuidle_cooling.o
 
-# clock cooling
-thermal_sys-$(CONFIG_CLOCK_THERMAL)    += clock_cooling.o
-
 # devfreq cooling
 thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 
index 7c447cd149e7fab3c25939041c4e6bf98e783167..c2ebfb5be4b3dc715c49b1bfec275df6836a34ba 100644 (file)
@@ -874,6 +874,12 @@ static int armada_thermal_probe(struct platform_device *pdev)
                        return PTR_ERR(tz);
                }
 
+               ret = thermal_zone_device_enable(tz);
+               if (ret) {
+                       thermal_zone_device_unregister(tz);
+                       return ret;
+               }
+
                drvdata->type = LEGACY;
                drvdata->data.tz = tz;
                platform_set_drvdata(pdev, drvdata);
diff --git a/drivers/thermal/clock_cooling.c b/drivers/thermal/clock_cooling.c
deleted file mode 100644 (file)
index 56cb1f4..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- *  drivers/thermal/clock_cooling.c
- *
- *  Copyright (C) 2014 Eduardo Valentin <edubezval@gmail.com>
- *
- *  Copyright (C) 2013 Texas Instruments Inc.
- *  Contact:  Eduardo Valentin <eduardo.valentin@ti.com>
- *
- *  Highly based on cpufreq_cooling.c.
- *  Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
- *  Copyright (C) 2012  Amit Daniel <amit.kachhap@linaro.org>
- */
-#include <linux/clk.h>
-#include <linux/clock_cooling.h>
-#include <linux/cpufreq.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/idr.h>
-#include <linux/mutex.h>
-#include <linux/pm_opp.h>
-#include <linux/slab.h>
-#include <linux/thermal.h>
-
-/**
- * struct clock_cooling_device - data for cooling device with clock
- * @id: unique integer value corresponding to each clock_cooling_device
- *     registered.
- * @dev: struct device pointer to the device being used to cool off using
- *       clock frequencies.
- * @cdev: thermal_cooling_device pointer to keep track of the
- *     registered cooling device.
- * @clk_rate_change_nb: reference to notifier block used to receive clock
- *                      rate changes.
- * @freq_table: frequency table used to keep track of available frequencies.
- * @clock_state: integer value representing the current state of clock
- *     cooling devices.
- * @clock_val: integer value representing the absolute value of the clipped
- *     frequency.
- * @clk: struct clk reference used to enforce clock limits.
- * @lock: mutex lock to protect this struct.
- *
- * This structure is required for keeping information of each
- * clock_cooling_device registered. In order to prevent corruption of this a
- * mutex @lock is used.
- */
-struct clock_cooling_device {
-       int id;
-       struct device *dev;
-       struct thermal_cooling_device *cdev;
-       struct notifier_block clk_rate_change_nb;
-       struct cpufreq_frequency_table *freq_table;
-       unsigned long clock_state;
-       unsigned long clock_val;
-       struct clk *clk;
-       struct mutex lock; /* lock to protect the content of this struct */
-};
-#define to_clock_cooling_device(x) \
-               container_of(x, struct clock_cooling_device, clk_rate_change_nb)
-static DEFINE_IDA(clock_ida);
-
-/* Below code defines functions to be used for clock as cooling device */
-
-enum clock_cooling_property {
-       GET_LEVEL,
-       GET_FREQ,
-       GET_MAXL,
-};
-
-/**
- * clock_cooling_get_property - fetch a property of interest for a give cpu.
- * @ccdev: clock cooling device reference
- * @input: query parameter
- * @output: query return
- * @property: type of query (frequency, level, max level)
- *
- * This is the common function to
- * 1. get maximum clock cooling states
- * 2. translate frequency to cooling state
- * 3. translate cooling state to frequency
- * Note that the code may be not in good shape
- * but it is written in this way in order to:
- * a) reduce duplicate code as most of the code can be shared.
- * b) make sure the logic is consistent when translating between
- *    cooling states and frequencies.
- *
- * Return: 0 on success, -EINVAL when invalid parameters are passed.
- */
-static int clock_cooling_get_property(struct clock_cooling_device *ccdev,
-                                     unsigned long input,
-                                     unsigned long *output,
-                                     enum clock_cooling_property property)
-{
-       int i;
-       unsigned long max_level = 0, level = 0;
-       unsigned int freq = CPUFREQ_ENTRY_INVALID;
-       int descend = -1;
-       struct cpufreq_frequency_table *pos, *table = ccdev->freq_table;
-
-       if (!output)
-               return -EINVAL;
-
-       if (!table)
-               return -EINVAL;
-
-       cpufreq_for_each_valid_entry(pos, table) {
-               /* ignore duplicate entry */
-               if (freq == pos->frequency)
-                       continue;
-
-               /* get the frequency order */
-               if (freq != CPUFREQ_ENTRY_INVALID && descend == -1)
-                       descend = freq > pos->frequency;
-
-               freq = pos->frequency;
-               max_level++;
-       }
-
-       /* No valid cpu frequency entry */
-       if (max_level == 0)
-               return -EINVAL;
-
-       /* max_level is an index, not a counter */
-       max_level--;
-
-       /* get max level */
-       if (property == GET_MAXL) {
-               *output = max_level;
-               return 0;
-       }
-
-       if (property == GET_FREQ)
-               level = descend ? input : (max_level - input);
-
-       i = 0;
-       cpufreq_for_each_valid_entry(pos, table) {
-               /* ignore duplicate entry */
-               if (freq == pos->frequency)
-                       continue;
-
-               /* now we have a valid frequency entry */
-               freq = pos->frequency;
-
-               if (property == GET_LEVEL && (unsigned int)input == freq) {
-                       /* get level by frequency */
-                       *output = descend ? i : (max_level - i);
-                       return 0;
-               }
-               if (property == GET_FREQ && level == i) {
-                       /* get frequency by level */
-                       *output = freq;
-                       return 0;
-               }
-               i++;
-       }
-
-       return -EINVAL;
-}
-
-/**
- * clock_cooling_get_level - return the cooling level of given clock cooling.
- * @cdev: reference of a thermal cooling device of used as clock cooling device
- * @freq: the frequency of interest
- *
- * This function will match the cooling level corresponding to the
- * requested @freq and return it.
- *
- * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID
- * otherwise.
- */
-unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev,
-                                     unsigned long freq)
-{
-       struct clock_cooling_device *ccdev = cdev->devdata;
-       unsigned long val;
-
-       if (clock_cooling_get_property(ccdev, (unsigned long)freq, &val,
-                                      GET_LEVEL))
-               return THERMAL_CSTATE_INVALID;
-
-       return val;
-}
-EXPORT_SYMBOL_GPL(clock_cooling_get_level);
-
-/**
- * clock_cooling_get_frequency - get the absolute value of frequency from level.
- * @ccdev: clock cooling device reference
- * @level: cooling level
- *
- * This function matches cooling level with frequency. Based on a cooling level
- * of frequency, equals cooling state of cpu cooling device, it will return
- * the corresponding frequency.
- *     e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc
- *
- * Return: 0 on error, the corresponding frequency otherwise.
- */
-static unsigned long
-clock_cooling_get_frequency(struct clock_cooling_device *ccdev,
-                           unsigned long level)
-{
-       int ret = 0;
-       unsigned long freq;
-
-       ret = clock_cooling_get_property(ccdev, level, &freq, GET_FREQ);
-       if (ret)
-               return 0;
-
-       return freq;
-}
-
-/**
- * clock_cooling_apply - function to apply frequency clipping.
- * @ccdev: clock_cooling_device pointer containing frequency clipping data.
- * @cooling_state: value of the cooling state.
- *
- * Function used to make sure the clock layer is aware of current thermal
- * limits. The limits are applied by updating the clock rate in case it is
- * higher than the corresponding frequency based on the requested cooling_state.
- *
- * Return: 0 on success, an error code otherwise (-EINVAL in case wrong
- * cooling state).
- */
-static int clock_cooling_apply(struct clock_cooling_device *ccdev,
-                              unsigned long cooling_state)
-{
-       unsigned long clip_freq, cur_freq;
-       int ret = 0;
-
-       /* Here we write the clipping */
-       /* Check if the old cooling action is same as new cooling action */
-       if (ccdev->clock_state == cooling_state)
-               return 0;
-
-       clip_freq = clock_cooling_get_frequency(ccdev, cooling_state);
-       if (!clip_freq)
-               return -EINVAL;
-
-       cur_freq = clk_get_rate(ccdev->clk);
-
-       mutex_lock(&ccdev->lock);
-       ccdev->clock_state = cooling_state;
-       ccdev->clock_val = clip_freq;
-       /* enforce clock level */
-       if (cur_freq > clip_freq)
-               ret = clk_set_rate(ccdev->clk, clip_freq);
-       mutex_unlock(&ccdev->lock);
-
-       return ret;
-}
-
-/**
- * clock_cooling_clock_notifier - notifier callback on clock rate changes.
- * @nb:        struct notifier_block * with callback info.
- * @event: value showing clock event for which this function invoked.
- * @data: callback-specific data
- *
- * Callback to hijack the notification on clock transition.
- * Every time there is a clock change, we intercept all pre change events
- * and block the transition in case the new rate infringes thermal limits.
- *
- * Return: NOTIFY_DONE (success) or NOTIFY_BAD (new_rate > thermal limit).
- */
-static int clock_cooling_clock_notifier(struct notifier_block *nb,
-                                       unsigned long event, void *data)
-{
-       struct clk_notifier_data *ndata = data;
-       struct clock_cooling_device *ccdev = to_clock_cooling_device(nb);
-
-       switch (event) {
-       case PRE_RATE_CHANGE:
-               /*
-                * checks on current state
-                * TODO: current method is not best we can find as it
-                * allows possibly voltage transitions, in case DVFS
-                * layer is also hijacking clock pre notifications.
-                */
-               if (ndata->new_rate > ccdev->clock_val)
-                       return NOTIFY_BAD;
-               /* fall through */
-       case POST_RATE_CHANGE:
-       case ABORT_RATE_CHANGE:
-       default:
-               return NOTIFY_DONE;
-       }
-}
-
-/* clock cooling device thermal callback functions are defined below */
-
-/**
- * clock_cooling_get_max_state - callback function to get the max cooling state.
- * @cdev: thermal cooling device pointer.
- * @state: fill this variable with the max cooling state.
- *
- * Callback for the thermal cooling device to return the clock
- * max cooling state.
- *
- * Return: 0 on success, an error code otherwise.
- */
-static int clock_cooling_get_max_state(struct thermal_cooling_device *cdev,
-                                      unsigned long *state)
-{
-       struct clock_cooling_device *ccdev = cdev->devdata;
-       unsigned long count = 0;
-       int ret;
-
-       ret = clock_cooling_get_property(ccdev, 0, &count, GET_MAXL);
-       if (!ret)
-               *state = count;
-
-       return ret;
-}
-
-/**
- * clock_cooling_get_cur_state - function to get the current cooling state.
- * @cdev: thermal cooling device pointer.
- * @state: fill this variable with the current cooling state.
- *
- * Callback for the thermal cooling device to return the clock
- * current cooling state.
- *
- * Return: 0 (success)
- */
-static int clock_cooling_get_cur_state(struct thermal_cooling_device *cdev,
-                                      unsigned long *state)
-{
-       struct clock_cooling_device *ccdev = cdev->devdata;
-
-       *state = ccdev->clock_state;
-
-       return 0;
-}
-
-/**
- * clock_cooling_set_cur_state - function to set the current cooling state.
- * @cdev: thermal cooling device pointer.
- * @state: set this variable to the current cooling state.
- *
- * Callback for the thermal cooling device to change the clock cooling
- * current cooling state.
- *
- * Return: 0 on success, an error code otherwise.
- */
-static int clock_cooling_set_cur_state(struct thermal_cooling_device *cdev,
-                                      unsigned long state)
-{
-       struct clock_cooling_device *clock_device = cdev->devdata;
-
-       return clock_cooling_apply(clock_device, state);
-}
-
-/* Bind clock callbacks to thermal cooling device ops */
-static struct thermal_cooling_device_ops const clock_cooling_ops = {
-       .get_max_state = clock_cooling_get_max_state,
-       .get_cur_state = clock_cooling_get_cur_state,
-       .set_cur_state = clock_cooling_set_cur_state,
-};
-
-/**
- * clock_cooling_register - function to create clock cooling device.
- * @dev: struct device pointer to the device used as clock cooling device.
- * @clock_name: string containing the clock used as cooling mechanism.
- *
- * This interface function registers the clock cooling device with the name
- * "thermal-clock-%x". The cooling device is based on clock frequencies.
- * The struct device is assumed to be capable of DVFS transitions.
- * The OPP layer is used to fetch and fill the available frequencies for
- * the referred device. The ordered frequency table is used to control
- * the clock cooling device cooling states and to limit clock transitions
- * based on the cooling state requested by the thermal framework.
- *
- * Return: a valid struct thermal_cooling_device pointer on success,
- * on failure, it returns a corresponding ERR_PTR().
- */
-struct thermal_cooling_device *
-clock_cooling_register(struct device *dev, const char *clock_name)
-{
-       struct thermal_cooling_device *cdev;
-       struct clock_cooling_device *ccdev = NULL;
-       char dev_name[THERMAL_NAME_LENGTH];
-       int ret = 0;
-
-       ccdev = devm_kzalloc(dev, sizeof(*ccdev), GFP_KERNEL);
-       if (!ccdev)
-               return ERR_PTR(-ENOMEM);
-
-       mutex_init(&ccdev->lock);
-       ccdev->dev = dev;
-       ccdev->clk = devm_clk_get(dev, clock_name);
-       if (IS_ERR(ccdev->clk))
-               return ERR_CAST(ccdev->clk);
-
-       ret = ida_simple_get(&clock_ida, 0, 0, GFP_KERNEL);
-       if (ret < 0)
-               return ERR_PTR(ret);
-       ccdev->id = ret;
-
-       snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id);
-
-       cdev = thermal_cooling_device_register(dev_name, ccdev,
-                                              &clock_cooling_ops);
-       if (IS_ERR(cdev)) {
-               ida_simple_remove(&clock_ida, ccdev->id);
-               return ERR_PTR(-EINVAL);
-       }
-       ccdev->cdev = cdev;
-       ccdev->clk_rate_change_nb.notifier_call = clock_cooling_clock_notifier;
-
-       /* Assuming someone has already filled the opp table for this device */
-       ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table);
-       if (ret) {
-               ida_simple_remove(&clock_ida, ccdev->id);
-               return ERR_PTR(ret);
-       }
-       ccdev->clock_state = 0;
-       ccdev->clock_val = clock_cooling_get_frequency(ccdev, 0);
-
-       clk_notifier_register(ccdev->clk, &ccdev->clk_rate_change_nb);
-
-       return cdev;
-}
-EXPORT_SYMBOL_GPL(clock_cooling_register);
-
-/**
- * clock_cooling_unregister - function to remove clock cooling device.
- * @cdev: thermal cooling device pointer.
- *
- * This interface function unregisters the "thermal-clock-%x" cooling device.
- */
-void clock_cooling_unregister(struct thermal_cooling_device *cdev)
-{
-       struct clock_cooling_device *ccdev;
-
-       if (!cdev)
-               return;
-
-       ccdev = cdev->devdata;
-
-       clk_notifier_unregister(ccdev->clk, &ccdev->clk_rate_change_nb);
-       dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table);
-
-       thermal_cooling_device_unregister(ccdev->cdev);
-       ida_simple_remove(&clock_ida, ccdev->id);
-}
-EXPORT_SYMBOL_GPL(clock_cooling_unregister);
index c32709badeda7bbf36e85cedd470bddad2c01532..4d74994f160aebfa6c37cbc62a06eb88576f3601 100644 (file)
@@ -49,7 +49,6 @@ struct da9062_thermal {
        struct da9062 *hw;
        struct delayed_work work;
        struct thermal_zone_device *zone;
-       enum thermal_device_mode mode;
        struct mutex lock; /* protection for da9062_thermal temperature */
        int temperature;
        int irq;
@@ -121,14 +120,6 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static int da9062_thermal_get_mode(struct thermal_zone_device *z,
-                                  enum thermal_device_mode *mode)
-{
-       struct da9062_thermal *thermal = z->devdata;
-       *mode = thermal->mode;
-       return 0;
-}
-
 static int da9062_thermal_get_trip_type(struct thermal_zone_device *z,
                                        int trip,
                                        enum thermal_trip_type *type)
@@ -181,7 +172,6 @@ static int da9062_thermal_get_temp(struct thermal_zone_device *z,
 
 static struct thermal_zone_device_ops da9062_thermal_ops = {
        .get_temp       = da9062_thermal_get_temp,
-       .get_mode       = da9062_thermal_get_mode,
        .get_trip_type  = da9062_thermal_get_trip_type,
        .get_trip_temp  = da9062_thermal_get_trip_temp,
 };
@@ -233,7 +223,6 @@ static int da9062_thermal_probe(struct platform_device *pdev)
 
        thermal->config = match->data;
        thermal->hw = chip;
-       thermal->mode = THERMAL_DEVICE_ENABLED;
        thermal->dev = &pdev->dev;
 
        INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);
@@ -248,6 +237,11 @@ static int da9062_thermal_probe(struct platform_device *pdev)
                ret = PTR_ERR(thermal->zone);
                goto err;
        }
+       ret = thermal_zone_device_enable(thermal->zone);
+       if (ret) {
+               dev_err(&pdev->dev, "Cannot enable thermal zone device\n");
+               goto err_zone;
+       }
 
        dev_dbg(&pdev->dev,
                "TJUNC temperature polling period set at %d ms\n",
index f7f32e98331b1e1ba41d7b6b7b15a437d7306f42..a12d2909622956d9ab2373abe7f4e663372a35a4 100644 (file)
@@ -1,18 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * devfreq_cooling: Thermal cooling device implementation for devices using
  *                  devfreq
  *
  * Copyright (C) 2014-2015 ARM Limited
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * TODO:
  *    - If OPPs are added or removed after devfreq cooling has
  *      registered, the devfreq cooling won't react to it.
index 75901ced4a622f10484de23d1e36338a3dcdbe76..73182eb94bc08b6ccea494eb06c833010f0bd307 100644 (file)
@@ -153,6 +153,12 @@ static int dove_thermal_probe(struct platform_device *pdev)
                return PTR_ERR(thermal);
        }
 
+       ret = thermal_zone_device_enable(thermal);
+       if (ret) {
+               thermal_zone_device_unregister(thermal);
+               return ret;
+       }
+
        platform_set_drvdata(pdev, thermal);
 
        return 0;
index 44636475b2a348e115a9027a29d77a45f35fc91b..5cb518d8f1562573425ab498ee1f7cd164c7815f 100644 (file)
@@ -1,16 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * A power allocator to manage temperature
  *
  * Copyright (C) 2014 ARM Ltd.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
  */
 
 #define pr_fmt(fmt) "Power allocator: " fmt
index 2d26ae80e20228e96bcb2e4b4a2958f2dd57bbee..ee05950afd2f97df7d954eb0830a2f688b52270c 100644 (file)
@@ -549,8 +549,10 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor,
 {
        struct thermal_zone_device *tzd = sensor->tzd;
 
-       tzd->ops->set_mode(tzd,
-               on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
+       if (on)
+               thermal_zone_device_enable(tzd);
+       else
+               thermal_zone_device_disable(tzd);
 }
 
 static int hisi_thermal_probe(struct platform_device *pdev)
index e6061e26d4ac001734b905efe5231bd1acc3085b..f5124f14cf81386126c540841410c7c2d5b74679 100644 (file)
@@ -220,6 +220,7 @@ static const struct of_device_id imx8mm_tmu_table[] = {
        { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, },
        { },
 };
+MODULE_DEVICE_TABLE(of, imx8mm_tmu_table);
 
 static struct platform_driver imx8mm_tmu = {
        .driver = {
index 1b84ea674edb740d140ae547f3da685266e64b68..3f74ab4c1ab9f184a3e0c449a0f91951a7bd46a4 100644 (file)
@@ -197,7 +197,6 @@ struct imx_thermal_data {
        struct cpufreq_policy *policy;
        struct thermal_zone_device *tz;
        struct thermal_cooling_device *cdev;
-       enum thermal_device_mode mode;
        struct regmap *tempmon;
        u32 c1, c2; /* See formula in imx_init_calib() */
        int temp_passive;
@@ -253,10 +252,11 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
        const struct thermal_soc_data *soc_data = data->socdata;
        struct regmap *map = data->tempmon;
        unsigned int n_meas;
-       bool wait;
+       bool wait, run_measurement;
        u32 val;
 
-       if (data->mode == THERMAL_DEVICE_ENABLED) {
+       run_measurement = !data->irq_enabled;
+       if (!run_measurement) {
                /* Check if a measurement is currently in progress */
                regmap_read(map, soc_data->temp_data, &val);
                wait = !(val & soc_data->temp_valid_mask);
@@ -283,7 +283,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
 
        regmap_read(map, soc_data->temp_data, &val);
 
-       if (data->mode != THERMAL_DEVICE_ENABLED) {
+       if (run_measurement) {
                regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
                             soc_data->measure_temp_mask);
                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)
        return 0;
 }
 
-static int imx_get_mode(struct thermal_zone_device *tz,
-                       enum thermal_device_mode *mode)
-{
-       struct imx_thermal_data *data = tz->devdata;
-
-       *mode = data->mode;
-
-       return 0;
-}
-
-static int imx_set_mode(struct thermal_zone_device *tz,
-                       enum thermal_device_mode mode)
+static int imx_change_mode(struct thermal_zone_device *tz,
+                          enum thermal_device_mode mode)
 {
        struct imx_thermal_data *data = tz->devdata;
        struct regmap *map = data->tempmon;
        const struct thermal_soc_data *soc_data = data->socdata;
 
        if (mode == THERMAL_DEVICE_ENABLED) {
-               tz->polling_delay = IMX_POLLING_DELAY;
-               tz->passive_delay = IMX_PASSIVE_DELAY;
-
                regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
                             soc_data->power_down_mask);
                regmap_write(map, soc_data->sensor_ctrl + REG_SET,
@@ -367,18 +354,12 @@ static int imx_set_mode(struct thermal_zone_device *tz,
                regmap_write(map, soc_data->sensor_ctrl + REG_SET,
                             soc_data->power_down_mask);
 
-               tz->polling_delay = 0;
-               tz->passive_delay = 0;
-
                if (data->irq_enabled) {
                        disable_irq(data->irq);
                        data->irq_enabled = false;
                }
        }
 
-       data->mode = mode;
-       thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
        return 0;
 }
 
@@ -467,8 +448,7 @@ static struct thermal_zone_device_ops imx_tz_ops = {
        .bind = imx_bind,
        .unbind = imx_unbind,
        .get_temp = imx_get_temp,
-       .get_mode = imx_get_mode,
-       .set_mode = imx_set_mode,
+       .change_mode = imx_change_mode,
        .get_trip_type = imx_get_trip_type,
        .get_trip_temp = imx_get_trip_temp,
        .get_crit_temp = imx_get_crit_temp,
@@ -832,7 +812,9 @@ static int imx_thermal_probe(struct platform_device *pdev)
                     data->socdata->measure_temp_mask);
 
        data->irq_enabled = true;
-       data->mode = THERMAL_DEVICE_ENABLED;
+       ret = thermal_zone_device_enable(data->tz);
+       if (ret)
+               goto thermal_zone_unregister;
 
        ret = devm_request_threaded_irq(&pdev->dev, data->irq,
                        imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
@@ -874,19 +856,18 @@ static int imx_thermal_remove(struct platform_device *pdev)
 static int __maybe_unused imx_thermal_suspend(struct device *dev)
 {
        struct imx_thermal_data *data = dev_get_drvdata(dev);
-       struct regmap *map = data->tempmon;
+       int ret;
 
        /*
         * Need to disable thermal sensor, otherwise, when thermal core
         * try to get temperature before thermal sensor resume, a wrong
         * temperature will be read as the thermal sensor is powered
-        * down.
+        * down. This is done in change_mode() operation called from
+        * thermal_zone_device_disable()
         */
-       regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
-                    data->socdata->measure_temp_mask);
-       regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
-                    data->socdata->power_down_mask);
-       data->mode = THERMAL_DEVICE_DISABLED;
+       ret = thermal_zone_device_disable(data->tz);
+       if (ret)
+               return ret;
        clk_disable_unprepare(data->thermal_clk);
 
        return 0;
@@ -895,18 +876,15 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev)
 static int __maybe_unused imx_thermal_resume(struct device *dev)
 {
        struct imx_thermal_data *data = dev_get_drvdata(dev);
-       struct regmap *map = data->tempmon;
        int ret;
 
        ret = clk_prepare_enable(data->thermal_clk);
        if (ret)
                return ret;
        /* Enabled thermal sensor after resume */
-       regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
-                    data->socdata->power_down_mask);
-       regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
-                    data->socdata->measure_temp_mask);
-       data->mode = THERMAL_DEVICE_ENABLED;
+       ret = thermal_zone_device_enable(data->tz);
+       if (ret)
+               return ret;
 
        return 0;
 }
index 12448ccd27f16806f715dcd211ba0b426b47396d..4f5859d4c780f9a25f2f424540be07ec61269e47 100644 (file)
@@ -48,7 +48,6 @@ struct int3400_thermal_priv {
        struct acpi_device *adev;
        struct platform_device *pdev;
        struct thermal_zone_device *thermal;
-       int mode;
        int art_count;
        struct art *arts;
        int trt_count;
@@ -383,42 +382,20 @@ static int int3400_thermal_get_temp(struct thermal_zone_device *thermal,
        return 0;
 }
 
-static int int3400_thermal_get_mode(struct thermal_zone_device *thermal,
-                               enum thermal_device_mode *mode)
+static int int3400_thermal_change_mode(struct thermal_zone_device *thermal,
+                                      enum thermal_device_mode mode)
 {
        struct int3400_thermal_priv *priv = thermal->devdata;
-
-       if (!priv)
-               return -EINVAL;
-
-       *mode = priv->mode;
-
-       return 0;
-}
-
-static int int3400_thermal_set_mode(struct thermal_zone_device *thermal,
-                               enum thermal_device_mode mode)
-{
-       struct int3400_thermal_priv *priv = thermal->devdata;
-       bool enable;
        int result = 0;
 
        if (!priv)
                return -EINVAL;
 
-       if (mode == THERMAL_DEVICE_ENABLED)
-               enable = true;
-       else if (mode == THERMAL_DEVICE_DISABLED)
-               enable = false;
-       else
-               return -EINVAL;
-
-       if (enable != priv->mode) {
-               priv->mode = enable;
+       if (mode != thermal->mode)
                result = int3400_thermal_run_osc(priv->adev->handle,
-                                                priv->current_uuid_index,
-                                                enable);
-       }
+                                               priv->current_uuid_index,
+                                               mode == THERMAL_DEVICE_ENABLED);
+
 
        evaluate_odvp(priv);
 
@@ -427,8 +404,7 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal,
 
 static struct thermal_zone_device_ops int3400_thermal_ops = {
        .get_temp = int3400_thermal_get_temp,
-       .get_mode = int3400_thermal_get_mode,
-       .set_mode = int3400_thermal_set_mode,
+       .change_mode = int3400_thermal_change_mode,
 };
 
 static struct thermal_zone_params int3400_thermal_params = {
index 432213272f1e7d88e1f3b494cd3b0792de4f38d5..6e479deff76b040d98870c415210896008a3027e 100644 (file)
@@ -259,9 +259,14 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
                ret = PTR_ERR(int34x_thermal_zone->zone);
                goto err_thermal_zone;
        }
+       ret = thermal_zone_device_enable(int34x_thermal_zone->zone);
+       if (ret)
+               goto err_enable;
 
        return int34x_thermal_zone;
 
+err_enable:
+       thermal_zone_device_unregister(int34x_thermal_zone->zone);
 err_thermal_zone:
        acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
        kfree(int34x_thermal_zone->aux_trips);
index 297db1d2d960c6ab3d11a4ce724f9c11c585ed55..81e8b15ef405d581121a0ad873ef399ad99bac6c 100644 (file)
@@ -43,7 +43,7 @@
 #define PCI_DEVICE_ID_PROC_ICL_THERMAL 0x8a03
 
 /* JasperLake thermal reporting device */
-#define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4503
+#define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4E03
 
 /* TigerLake thermal reporting device */
 #define PCI_DEVICE_ID_PROC_TGL_THERMAL 0x9A03
index 56401fd4708d9904585bd9c4a37df798b91cafd9..3b813ebb6ca1db1f9a0b8447a02de9ec46d7f6cf 100644 (file)
@@ -24,6 +24,7 @@
 #define PCH_THERMAL_DID_SKL_H  0xA131 /* Skylake PCH 100 series */
 #define PCH_THERMAL_DID_CNL    0x9Df9 /* CNL PCH */
 #define PCH_THERMAL_DID_CNL_H  0xA379 /* CNL-H PCH */
+#define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */
 #define PCH_THERMAL_DID_CML_H  0X06F9 /* CML-H PCH */
 
 /* Wildcat Point-LP  PCH Thermal registers */
@@ -352,9 +353,14 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev,
                err = PTR_ERR(ptd->tzd);
                goto error_cleanup;
        }
+       err = thermal_zone_device_enable(ptd->tzd);
+       if (err)
+               goto err_unregister;
 
        return 0;
 
+err_unregister:
+       thermal_zone_device_unregister(ptd->tzd);
 error_cleanup:
        iounmap(ptd->hw_base);
 error_release:
@@ -405,6 +411,8 @@ static const struct pci_device_id intel_pch_thermal_id[] = {
                .driver_data = board_cnl, },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H),
                .driver_data = board_cnl, },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_LP),
+               .driver_data = board_cnl, },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CML_H),
                .driver_data = board_cml, },
        { 0, },
index d704fc104cfd6ef7300d37ad704c2627cb91aef8..3eafc6b0e6c307a951148f4dd5543aaef133b550 100644 (file)
@@ -103,7 +103,6 @@ struct soc_sensor_entry {
        bool locked;
        u32 store_ptps;
        u32 store_dts_enable;
-       enum thermal_device_mode mode;
        struct thermal_zone_device *tzone;
 };
 
@@ -127,10 +126,8 @@ static int soc_dts_enable(struct thermal_zone_device *tzd)
        if (ret)
                return ret;
 
-       if (out & QRK_DTS_ENABLE_BIT) {
-               aux_entry->mode = THERMAL_DEVICE_ENABLED;
+       if (out & QRK_DTS_ENABLE_BIT)
                return 0;
-       }
 
        if (!aux_entry->locked) {
                out |= QRK_DTS_ENABLE_BIT;
@@ -138,10 +135,7 @@ static int soc_dts_enable(struct thermal_zone_device *tzd)
                                     QRK_DTS_REG_OFFSET_ENABLE, out);
                if (ret)
                        return ret;
-
-               aux_entry->mode = THERMAL_DEVICE_ENABLED;
        } else {
-               aux_entry->mode = THERMAL_DEVICE_DISABLED;
                pr_info("DTS is locked. Cannot enable DTS\n");
                ret = -EPERM;
        }
@@ -160,10 +154,8 @@ static int soc_dts_disable(struct thermal_zone_device *tzd)
        if (ret)
                return ret;
 
-       if (!(out & QRK_DTS_ENABLE_BIT)) {
-               aux_entry->mode = THERMAL_DEVICE_DISABLED;
+       if (!(out & QRK_DTS_ENABLE_BIT))
                return 0;
-       }
 
        if (!aux_entry->locked) {
                out &= ~QRK_DTS_ENABLE_BIT;
@@ -172,10 +164,7 @@ static int soc_dts_disable(struct thermal_zone_device *tzd)
 
                if (ret)
                        return ret;
-
-               aux_entry->mode = THERMAL_DEVICE_DISABLED;
        } else {
-               aux_entry->mode = THERMAL_DEVICE_ENABLED;
                pr_info("DTS is locked. Cannot disable DTS\n");
                ret = -EPERM;
        }
@@ -309,16 +298,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd,
        return 0;
 }
 
-static int sys_get_mode(struct thermal_zone_device *tzd,
-                               enum thermal_device_mode *mode)
-{
-       struct soc_sensor_entry *aux_entry = tzd->devdata;
-       *mode = aux_entry->mode;
-       return 0;
-}
-
-static int sys_set_mode(struct thermal_zone_device *tzd,
-                               enum thermal_device_mode mode)
+static int sys_change_mode(struct thermal_zone_device *tzd,
+                          enum thermal_device_mode mode)
 {
        int ret;
 
@@ -338,8 +319,7 @@ static struct thermal_zone_device_ops tzone_ops = {
        .get_trip_type = sys_get_trip_type,
        .set_trip_temp = sys_set_trip_temp,
        .get_crit_temp = sys_get_crit_temp,
-       .get_mode = sys_get_mode,
-       .set_mode = sys_set_mode,
+       .change_mode = sys_change_mode,
 };
 
 static void free_soc_dts(struct soc_sensor_entry *aux_entry)
@@ -414,9 +394,7 @@ static struct soc_sensor_entry *alloc_soc_dts(void)
                goto err_ret;
        }
 
-       mutex_lock(&dts_update_mutex);
-       err = soc_dts_enable(aux_entry->tzone);
-       mutex_unlock(&dts_update_mutex);
+       err = thermal_zone_device_enable(aux_entry->tzone);
        if (err)
                goto err_aux_status;
 
index f75271b669c654b2690382075366e9015f6cd1f2..4f1a2f7c016cc14edc25a1af043a9d30e3a0e650 100644 (file)
@@ -329,6 +329,9 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
                ret = PTR_ERR(dts->tzone);
                goto err_ret;
        }
+       ret = thermal_zone_device_enable(dts->tzone);
+       if (ret)
+               goto err_enable;
 
        ret = soc_dts_enable(id);
        if (ret)
index a006b9fd1d72b04bf4381b0905d1728cded7c1eb..b81c33202f41a02e7a1f3fb8d3754fcf589a3504 100644 (file)
@@ -363,6 +363,12 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
                kfree(zonedev);
                return err;
        }
+       err = thermal_zone_device_enable(zonedev->tzone);
+       if (err) {
+               thermal_zone_device_unregister(zonedev->tzone);
+               kfree(zonedev);
+               return err;
+       }
        /* Store MSR value for package thermal interrupt, to restore at exit */
        rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low,
              zonedev->msr_pkg_therm_high);
index 189b675cf14d9233cbd688c0e46108b1ac06a53e..7fb6e476c82a4be1982bfce70a35e0f7ea9bc35c 100644 (file)
@@ -65,6 +65,7 @@ static int kirkwood_thermal_probe(struct platform_device *pdev)
        struct thermal_zone_device *thermal = NULL;
        struct kirkwood_thermal_priv *priv;
        struct resource *res;
+       int ret;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -82,6 +83,12 @@ static int kirkwood_thermal_probe(struct platform_device *pdev)
                        "Failed to register thermal zone device\n");
                return PTR_ERR(thermal);
        }
+       ret = thermal_zone_device_enable(thermal);
+       if (ret) {
+               thermal_zone_device_unregister(thermal);
+               dev_err(&pdev->dev, "Failed to enable thermal zone device\n");
+               return ret;
+       }
 
        platform_set_drvdata(pdev, thermal);
 
index 42c9cd0e5f7754c5c7087224c9cc6227d967e3fe..0bd7aa564bc25cc6d9d9303c59a6d9f0f8b5986b 100644 (file)
@@ -38,6 +38,7 @@
 #define TEMP_MONIDET0          0x014
 #define TEMP_MONIDET1          0x018
 #define TEMP_MSRCTL0           0x038
+#define TEMP_MSRCTL1           0x03c
 #define TEMP_AHBPOLL           0x040
 #define TEMP_AHBTO             0x044
 #define TEMP_ADCPNP0           0x048
  * MT2701 has 3 sensors and needs 3 VTS calibration data.
  * MT2712 has 4 sensors and needs 4 VTS calibration data.
  */
-#define CALIB_BUF0_VALID               BIT(0)
-#define CALIB_BUF1_ADC_GE(x)           (((x) >> 22) & 0x3ff)
-#define CALIB_BUF0_VTS_TS1(x)          (((x) >> 17) & 0x1ff)
-#define CALIB_BUF0_VTS_TS2(x)          (((x) >> 8) & 0x1ff)
-#define CALIB_BUF1_VTS_TS3(x)          (((x) >> 0) & 0x1ff)
-#define CALIB_BUF2_VTS_TS4(x)          (((x) >> 23) & 0x1ff)
-#define CALIB_BUF2_VTS_TS5(x)          (((x) >> 5) & 0x1ff)
-#define CALIB_BUF2_VTS_TSABB(x)                (((x) >> 14) & 0x1ff)
-#define CALIB_BUF0_DEGC_CALI(x)                (((x) >> 1) & 0x3f)
-#define CALIB_BUF0_O_SLOPE(x)          (((x) >> 26) & 0x3f)
-#define CALIB_BUF0_O_SLOPE_SIGN(x)     (((x) >> 7) & 0x1)
-#define CALIB_BUF1_ID(x)               (((x) >> 9) & 0x1)
+#define CALIB_BUF0_VALID_V1            BIT(0)
+#define CALIB_BUF1_ADC_GE_V1(x)                (((x) >> 22) & 0x3ff)
+#define CALIB_BUF0_VTS_TS1_V1(x)       (((x) >> 17) & 0x1ff)
+#define CALIB_BUF0_VTS_TS2_V1(x)       (((x) >> 8) & 0x1ff)
+#define CALIB_BUF1_VTS_TS3_V1(x)       (((x) >> 0) & 0x1ff)
+#define CALIB_BUF2_VTS_TS4_V1(x)       (((x) >> 23) & 0x1ff)
+#define CALIB_BUF2_VTS_TS5_V1(x)       (((x) >> 5) & 0x1ff)
+#define CALIB_BUF2_VTS_TSABB_V1(x)     (((x) >> 14) & 0x1ff)
+#define CALIB_BUF0_DEGC_CALI_V1(x)     (((x) >> 1) & 0x3f)
+#define CALIB_BUF0_O_SLOPE_V1(x)       (((x) >> 26) & 0x3f)
+#define CALIB_BUF0_O_SLOPE_SIGN_V1(x)  (((x) >> 7) & 0x1)
+#define CALIB_BUF1_ID_V1(x)            (((x) >> 9) & 0x1)
+
+/*
+ * Layout of the fuses providing the calibration data
+ * These macros could be used for MT7622.
+ */
+#define CALIB_BUF0_ADC_OE_V2(x)                (((x) >> 22) & 0x3ff)
+#define CALIB_BUF0_ADC_GE_V2(x)                (((x) >> 12) & 0x3ff)
+#define CALIB_BUF0_DEGC_CALI_V2(x)     (((x) >> 6) & 0x3f)
+#define CALIB_BUF0_O_SLOPE_V2(x)       (((x) >> 0) & 0x3f)
+#define CALIB_BUF1_VTS_TS1_V2(x)       (((x) >> 23) & 0x1ff)
+#define CALIB_BUF1_VTS_TS2_V2(x)       (((x) >> 14) & 0x1ff)
+#define CALIB_BUF1_VTS_TSABB_V2(x)     (((x) >> 5) & 0x1ff)
+#define CALIB_BUF1_VALID_V2(x)         (((x) >> 4) & 0x1)
+#define CALIB_BUF1_O_SLOPE_SIGN_V2(x)  (((x) >> 3) & 0x1)
 
 enum {
        VTS1,
@@ -143,6 +158,11 @@ enum {
        MAX_NUM_VTS,
 };
 
+enum mtk_thermal_version {
+       MTK_THERMAL_V1 = 1,
+       MTK_THERMAL_V2,
+};
+
 /* MT2701 thermal sensors */
 #define MT2701_TS1     0
 #define MT2701_TS2     1
@@ -248,6 +268,7 @@ struct mtk_thermal_data {
        const int *controller_offset;
        bool need_switch_bank;
        struct thermal_bank_cfg bank_data[MAX_NUM_ZONES];
+       enum mtk_thermal_version version;
 };
 
 struct mtk_thermal {
@@ -261,8 +282,10 @@ struct mtk_thermal {
 
        /* Calibration values */
        s32 adc_ge;
+       s32 adc_oe;
        s32 degc_cali;
        s32 o_slope;
+       s32 o_slope_sign;
        s32 vts[MAX_NUM_VTS];
 
        const struct mtk_thermal_data *conf;
@@ -401,6 +424,7 @@ static const struct mtk_thermal_data mt8173_thermal_data = {
        .msr = mt8173_msr,
        .adcpnp = mt8173_adcpnp,
        .sensor_mux_values = mt8173_mux_values,
+       .version = MTK_THERMAL_V1,
 };
 
 /*
@@ -431,6 +455,7 @@ static const struct mtk_thermal_data mt2701_thermal_data = {
        .msr = mt2701_msr,
        .adcpnp = mt2701_adcpnp,
        .sensor_mux_values = mt2701_mux_values,
+       .version = MTK_THERMAL_V1,
 };
 
 /*
@@ -461,6 +486,7 @@ static const struct mtk_thermal_data mt2712_thermal_data = {
        .msr = mt2712_msr,
        .adcpnp = mt2712_adcpnp,
        .sensor_mux_values = mt2712_mux_values,
+       .version = MTK_THERMAL_V1,
 };
 
 /*
@@ -485,6 +511,7 @@ static const struct mtk_thermal_data mt7622_thermal_data = {
        .msr = mt7622_msr,
        .adcpnp = mt7622_adcpnp,
        .sensor_mux_values = mt7622_mux_values,
+       .version = MTK_THERMAL_V2,
 };
 
 /*
@@ -517,6 +544,7 @@ static const struct mtk_thermal_data mt8183_thermal_data = {
        .msr = mt8183_msr,
        .adcpnp = mt8183_adcpnp,
        .sensor_mux_values = mt8183_mux_values,
+       .version = MTK_THERMAL_V1,
 };
 
 /**
@@ -528,7 +556,7 @@ static const struct mtk_thermal_data mt8183_thermal_data = {
  * This converts the raw ADC value to mcelsius using the SoC specific
  * calibration constants
  */
-static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw)
+static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw)
 {
        s32 tmp;
 
@@ -543,6 +571,36 @@ static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw)
        return mt->degc_cali * 500 - tmp;
 }
 
+static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw)
+{
+       s32 format_1 = 0;
+       s32 format_2 = 0;
+       s32 g_oe = 1;
+       s32 g_gain = 1;
+       s32 g_x_roomt = 0;
+       s32 tmp = 0;
+
+       if (raw == 0)
+               return 0;
+
+       raw &= 0xfff;
+       g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12);
+       g_oe = mt->adc_oe - 512;
+       format_1 = mt->vts[VTS2] + 3105 - g_oe;
+       format_2 = (mt->degc_cali * 10) >> 1;
+       g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain;
+
+       tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt;
+       tmp = tmp * 10 * 100 / 11;
+
+       if (mt->o_slope_sign == 0)
+               tmp = tmp / (165 - mt->o_slope);
+       else
+               tmp = tmp / (165 + mt->o_slope);
+
+       return (format_2 - tmp) * 100;
+}
+
 /**
  * mtk_thermal_get_bank - get bank
  * @bank:      The bank
@@ -596,9 +654,13 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
        for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
                raw = readl(mt->thermal_base + conf->msr[i]);
 
-               temp = raw_to_mcelsius(mt,
-                                      conf->bank_data[bank->id].sensors[i],
-                                      raw);
+               if (mt->conf->version == MTK_THERMAL_V1) {
+                       temp = raw_to_mcelsius_v1(
+                               mt, conf->bank_data[bank->id].sensors[i], raw);
+               } else {
+                       temp = raw_to_mcelsius_v2(
+                               mt, conf->bank_data[bank->id].sensors[i], raw);
+               }
 
                /*
                 * 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,
        writel(auxadc_phys_base + AUXADC_CON1_CLR_V,
               controller_base + TEMP_ADCMUXADDR);
 
-       /* AHB address for pnp sensor mux selection */
-       writel(apmixed_phys_base + APMIXED_SYS_TS_CON1,
-              controller_base + TEMP_PNPMUXADDR);
+       if (mt->conf->version == MTK_THERMAL_V1) {
+               /* AHB address for pnp sensor mux selection */
+               writel(apmixed_phys_base + APMIXED_SYS_TS_CON1,
+                      controller_base + TEMP_PNPMUXADDR);
+       }
 
        /* AHB value for auxadc enable */
        writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN);
@@ -759,6 +823,68 @@ static u64 of_get_phys_base(struct device_node *np)
        return of_translate_address(np, regaddr_p);
 }
 
+static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf)
+{
+       int i;
+
+       if (!(buf[0] & CALIB_BUF0_VALID_V1))
+               return -EINVAL;
+
+       mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]);
+
+       for (i = 0; i < mt->conf->num_sensors; i++) {
+               switch (mt->conf->vts_index[i]) {
+               case VTS1:
+                       mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]);
+                       break;
+               case VTS2:
+                       mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]);
+                       break;
+               case VTS3:
+                       mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]);
+                       break;
+               case VTS4:
+                       mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]);
+                       break;
+               case VTS5:
+                       mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]);
+                       break;
+               case VTSABB:
+                       mt->vts[VTSABB] =
+                               CALIB_BUF2_VTS_TSABB_V1(buf[2]);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]);
+       if (CALIB_BUF1_ID_V1(buf[1]) &
+           CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0]))
+               mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]);
+       else
+               mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]);
+
+       return 0;
+}
+
+static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf)
+{
+       if (!CALIB_BUF1_VALID_V2(buf[1]))
+               return -EINVAL;
+
+       mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]);
+       mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]);
+       mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]);
+       mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]);
+       mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]);
+       mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]);
+       mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]);
+       mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]);
+
+       return 0;
+}
+
 static int mtk_thermal_get_calibration_data(struct device *dev,
                                            struct mtk_thermal *mt)
 {
@@ -794,42 +920,14 @@ static int mtk_thermal_get_calibration_data(struct device *dev,
                goto out;
        }
 
-       if (buf[0] & CALIB_BUF0_VALID) {
-               mt->adc_ge = CALIB_BUF1_ADC_GE(buf[1]);
-
-               for (i = 0; i < mt->conf->num_sensors; i++) {
-                       switch (mt->conf->vts_index[i]) {
-                       case VTS1:
-                               mt->vts[VTS1] = CALIB_BUF0_VTS_TS1(buf[0]);
-                               break;
-                       case VTS2:
-                               mt->vts[VTS2] = CALIB_BUF0_VTS_TS2(buf[0]);
-                               break;
-                       case VTS3:
-                               mt->vts[VTS3] = CALIB_BUF1_VTS_TS3(buf[1]);
-                               break;
-                       case VTS4:
-                               mt->vts[VTS4] = CALIB_BUF2_VTS_TS4(buf[2]);
-                               break;
-                       case VTS5:
-                               mt->vts[VTS5] = CALIB_BUF2_VTS_TS5(buf[2]);
-                               break;
-                       case VTSABB:
-                               mt->vts[VTSABB] = CALIB_BUF2_VTS_TSABB(buf[2]);
-                               break;
-                       default:
-                               break;
-                       }
-               }
+       if (mt->conf->version == MTK_THERMAL_V1)
+               ret = mtk_thermal_extract_efuse_v1(mt, buf);
+       else
+               ret = mtk_thermal_extract_efuse_v2(mt, buf);
 
-               mt->degc_cali = CALIB_BUF0_DEGC_CALI(buf[0]);
-               if (CALIB_BUF1_ID(buf[1]) &
-                   CALIB_BUF0_O_SLOPE_SIGN(buf[0]))
-                       mt->o_slope = -CALIB_BUF0_O_SLOPE(buf[0]);
-               else
-                       mt->o_slope = CALIB_BUF0_O_SLOPE(buf[0]);
-       } else {
+       if (ret) {
                dev_info(dev, "Device not calibrated, using default calibration values\n");
+               ret = 0;
        }
 
 out:
@@ -863,6 +961,28 @@ static const struct of_device_id mtk_thermal_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mtk_thermal_of_match);
 
+static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base)
+{
+       int tmp;
+
+       tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1);
+       tmp &= ~(0x37);
+       tmp |= 0x1;
+       writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1);
+       udelay(200);
+}
+
+static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt,
+                                           void __iomem *auxadc_base)
+{
+       int tmp;
+
+       writel(0x800, auxadc_base + AUXADC_CON1_SET_V);
+       writel(0x1, mt->thermal_base + TEMP_MONCTL0);
+       tmp = readl(mt->thermal_base + TEMP_MSRCTL1);
+       writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1);
+}
+
 static int mtk_thermal_probe(struct platform_device *pdev)
 {
        int ret, i, ctrl_id;
@@ -871,6 +991,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
        struct resource *res;
        u64 auxadc_phys_base, apmixed_phys_base;
        struct thermal_zone_device *tzdev;
+       void __iomem *apmixed_base, *auxadc_base;
 
        mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
        if (!mt)
@@ -905,6 +1026,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       auxadc_base = of_iomap(auxadc, 0);
        auxadc_phys_base = of_get_phys_base(auxadc);
 
        of_node_put(auxadc);
@@ -920,6 +1042,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       apmixed_base = of_iomap(apmixedsys, 0);
        apmixed_phys_base = of_get_phys_base(apmixedsys);
 
        of_node_put(apmixedsys);
@@ -945,6 +1068,11 @@ static int mtk_thermal_probe(struct platform_device *pdev)
                goto err_disable_clk_auxadc;
        }
 
+       if (mt->conf->version == MTK_THERMAL_V2) {
+               mtk_thermal_turn_on_buffer(apmixed_base);
+               mtk_thermal_release_periodic_ts(mt, auxadc_base);
+       }
+
        for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
                for (i = 0; i < mt->conf->num_banks; i++)
                        mtk_thermal_init_bank(mt, i, apmixed_phys_base,
index 959a9371d205c9d96b6da0791a4d7718dc157204..e64db5f80d909a8ad980c177986b5f069168b45b 100644 (file)
 #define MSM8916_CAL_SEL_MASK   0xe0000000
 #define MSM8916_CAL_SEL_SHIFT  29
 
+/* eeprom layout data for 8939 */
+#define MSM8939_BASE0_MASK     0x000000ff
+#define MSM8939_BASE1_MASK     0xff000000
+#define MSM8939_BASE0_SHIFT    0
+#define MSM8939_BASE1_SHIFT    24
+
+#define MSM8939_S0_P1_MASK     0x000001f8
+#define MSM8939_S1_P1_MASK     0x001f8000
+#define MSM8939_S2_P1_MASK_0_4 0xf8000000
+#define MSM8939_S2_P1_MASK_5   0x00000001
+#define MSM8939_S3_P1_MASK     0x00001f80
+#define MSM8939_S4_P1_MASK     0x01f80000
+#define MSM8939_S5_P1_MASK     0x00003f00
+#define MSM8939_S6_P1_MASK     0x03f00000
+#define MSM8939_S7_P1_MASK     0x0000003f
+#define MSM8939_S8_P1_MASK     0x0003f000
+#define MSM8939_S9_P1_MASK     0x07e00000
+
+#define MSM8939_S0_P2_MASK     0x00007e00
+#define MSM8939_S1_P2_MASK     0x07e00000
+#define MSM8939_S2_P2_MASK     0x0000007e
+#define MSM8939_S3_P2_MASK     0x0007e000
+#define MSM8939_S4_P2_MASK     0x7e000000
+#define MSM8939_S5_P2_MASK     0x000fc000
+#define MSM8939_S6_P2_MASK     0xfc000000
+#define MSM8939_S7_P2_MASK     0x00000fc0
+#define MSM8939_S8_P2_MASK     0x00fc0000
+#define MSM8939_S9_P2_MASK_0_4 0xf8000000
+#define MSM8939_S9_P2_MASK_5   0x00002000
+
+#define MSM8939_S0_P1_SHIFT    3
+#define MSM8939_S1_P1_SHIFT    15
+#define MSM8939_S2_P1_SHIFT_0_4        27
+#define MSM8939_S2_P1_SHIFT_5  0
+#define MSM8939_S3_P1_SHIFT    7
+#define MSM8939_S4_P1_SHIFT    19
+#define MSM8939_S5_P1_SHIFT    8
+#define MSM8939_S6_P1_SHIFT    20
+#define MSM8939_S7_P1_SHIFT    0
+#define MSM8939_S8_P1_SHIFT    12
+#define MSM8939_S9_P1_SHIFT    21
+
+#define MSM8939_S0_P2_SHIFT    9
+#define MSM8939_S1_P2_SHIFT    21
+#define MSM8939_S2_P2_SHIFT    1
+#define MSM8939_S3_P2_SHIFT    13
+#define MSM8939_S4_P2_SHIFT    25
+#define MSM8939_S5_P2_SHIFT    14
+#define MSM8939_S6_P2_SHIFT    26
+#define MSM8939_S7_P2_SHIFT    6
+#define MSM8939_S8_P2_SHIFT    18
+#define MSM8939_S9_P2_SHIFT_0_4        27
+#define MSM8939_S9_P2_SHIFT_5  13
+
+#define MSM8939_CAL_SEL_MASK   0x7
+#define MSM8939_CAL_SEL_SHIFT  0
+
 /* eeprom layout data for 8974 */
 #define BASE1_MASK             0xff
 #define S0_P1_MASK             0x3f00
@@ -189,6 +246,76 @@ static int calibrate_8916(struct tsens_priv *priv)
        return 0;
 }
 
+static int calibrate_8939(struct tsens_priv *priv)
+{
+       int base0 = 0, base1 = 0, i;
+       u32 p1[10], p2[10];
+       int mode = 0;
+       u32 *qfprom_cdata;
+       u32 cdata[6];
+
+       qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
+       if (IS_ERR(qfprom_cdata))
+               return PTR_ERR(qfprom_cdata);
+
+       /* Mapping between qfprom nvmem and calibration data */
+       cdata[0] = qfprom_cdata[12];
+       cdata[1] = qfprom_cdata[13];
+       cdata[2] = qfprom_cdata[0];
+       cdata[3] = qfprom_cdata[1];
+       cdata[4] = qfprom_cdata[22];
+       cdata[5] = qfprom_cdata[21];
+
+       mode = (cdata[0] & MSM8939_CAL_SEL_MASK) >> MSM8939_CAL_SEL_SHIFT;
+       dev_dbg(priv->dev, "calibration mode is %d\n", mode);
+
+       switch (mode) {
+       case TWO_PT_CALIB:
+               base1 = (cdata[3] & MSM8939_BASE1_MASK) >> MSM8939_BASE1_SHIFT;
+               p2[0] = (cdata[0] & MSM8939_S0_P2_MASK) >> MSM8939_S0_P2_SHIFT;
+               p2[1] = (cdata[0] & MSM8939_S1_P2_MASK) >> MSM8939_S1_P2_SHIFT;
+               p2[2] = (cdata[1] & MSM8939_S2_P2_MASK) >> MSM8939_S2_P2_SHIFT;
+               p2[3] = (cdata[1] & MSM8939_S3_P2_MASK) >> MSM8939_S3_P2_SHIFT;
+               p2[4] = (cdata[1] & MSM8939_S4_P2_MASK) >> MSM8939_S4_P2_SHIFT;
+               p2[5] = (cdata[2] & MSM8939_S5_P2_MASK) >> MSM8939_S5_P2_SHIFT;
+               p2[6] = (cdata[2] & MSM8939_S6_P2_MASK) >> MSM8939_S6_P2_SHIFT;
+               p2[7] = (cdata[3] & MSM8939_S7_P2_MASK) >> MSM8939_S7_P2_SHIFT;
+               p2[8] = (cdata[3] & MSM8939_S8_P2_MASK) >> MSM8939_S8_P2_SHIFT;
+               p2[9] = (cdata[4] & MSM8939_S9_P2_MASK_0_4) >> MSM8939_S9_P2_SHIFT_0_4;
+               p2[9] |= ((cdata[5] & MSM8939_S9_P2_MASK_5) >> MSM8939_S9_P2_SHIFT_5) << 5;
+               for (i = 0; i < priv->num_sensors; i++)
+                       p2[i] = (base1 + p2[i]) << 2;
+               fallthrough;
+       case ONE_PT_CALIB2:
+               base0 = (cdata[2] & MSM8939_BASE0_MASK) >> MSM8939_BASE0_SHIFT;
+               p1[0] = (cdata[0] & MSM8939_S0_P1_MASK) >> MSM8939_S0_P1_SHIFT;
+               p1[1] = (cdata[0] & MSM8939_S1_P1_MASK) >> MSM8939_S1_P1_SHIFT;
+               p1[2] = (cdata[0] & MSM8939_S2_P1_MASK_0_4) >> MSM8939_S2_P1_SHIFT_0_4;
+               p1[2] |= ((cdata[1] & MSM8939_S2_P1_MASK_5) >> MSM8939_S2_P1_SHIFT_5) << 5;
+               p1[3] = (cdata[1] & MSM8939_S3_P1_MASK) >> MSM8939_S3_P1_SHIFT;
+               p1[4] = (cdata[1] & MSM8939_S4_P1_MASK) >> MSM8939_S4_P1_SHIFT;
+               p1[5] = (cdata[2] & MSM8939_S5_P1_MASK) >> MSM8939_S5_P1_SHIFT;
+               p1[6] = (cdata[2] & MSM8939_S6_P1_MASK) >> MSM8939_S6_P1_SHIFT;
+               p1[7] = (cdata[3] & MSM8939_S7_P1_MASK) >> MSM8939_S7_P1_SHIFT;
+               p1[8] = (cdata[3] & MSM8939_S8_P1_MASK) >> MSM8939_S8_P1_SHIFT;
+               p1[9] = (cdata[4] & MSM8939_S9_P1_MASK) >> MSM8939_S9_P1_SHIFT;
+               for (i = 0; i < priv->num_sensors; i++)
+                       p1[i] = ((base0) + p1[i]) << 2;
+               break;
+       default:
+               for (i = 0; i < priv->num_sensors; i++) {
+                       p1[i] = 500;
+                       p2[i] = 780;
+               }
+               break;
+       }
+
+       compute_intercept_slope(priv, p1, p2, mode);
+       kfree(qfprom_cdata);
+
+       return 0;
+}
+
 static int calibrate_8974(struct tsens_priv *priv)
 {
        int base1 = 0, base2 = 0, i;
@@ -325,7 +452,7 @@ static int calibrate_8974(struct tsens_priv *priv)
        return 0;
 }
 
-/* v0.1: 8916, 8974 */
+/* v0.1: 8916, 8939, 8974 */
 
 static struct tsens_features tsens_v0_1_feat = {
        .ver_major      = VER_0_1,
@@ -386,6 +513,21 @@ struct tsens_plat_data data_8916 = {
        .fields = tsens_v0_1_regfields,
 };
 
+static const struct tsens_ops ops_8939 = {
+       .init           = init_common,
+       .calibrate      = calibrate_8939,
+       .get_temp       = get_temp_common,
+};
+
+struct tsens_plat_data data_8939 = {
+       .num_sensors    = 10,
+       .ops            = &ops_8939,
+       .hw_ids         = (unsigned int []){ 0, 1, 2, 4, 5, 6, 7, 8, 9, 10 },
+
+       .feat           = &tsens_v0_1_feat,
+       .fields = tsens_v0_1_regfields,
+};
+
 static const struct tsens_ops ops_8974 = {
        .init           = init_common,
        .calibrate      = calibrate_8974,
index 39c4462e38f622031e729059263f58b857558503..d8ce3a687b80d470ae911026074b4e27810091a5 100644 (file)
@@ -897,6 +897,9 @@ static const struct of_device_id tsens_table[] = {
        {
                .compatible = "qcom,msm8916-tsens",
                .data = &data_8916,
+       }, {
+               .compatible = "qcom,msm8939-tsens",
+               .data = &data_8939,
        }, {
                .compatible = "qcom,msm8974-tsens",
                .data = &data_8974,
index 59d01162c66afbe1109fb07ea583792792577ba0..f40b625f897e8c096b9884c90c0ee0bedc59a012 100644 (file)
@@ -585,7 +585,7 @@ int get_temp_common(const struct tsens_sensor *s, int *temp);
 extern struct tsens_plat_data data_8960;
 
 /* TSENS v0.1 targets */
-extern struct tsens_plat_data data_8916, data_8974;
+extern struct tsens_plat_data data_8916, data_8939, data_8974;
 
 /* TSENS v1 targets */
 extern struct tsens_plat_data data_tsens_v1, data_8976;
index c48c5e9b8f203dd106839e69e7d0f1db948a64bf..0dd47dca3e7712563ed007c63cacee78dd3bdc5d 100644 (file)
@@ -63,7 +63,7 @@
 #define TSC_MAX_NUM    3
 
 /* default THCODE values if FUSEs are missing */
-static const int thcode[TSC_MAX_NUM][3] = {
+static const int thcodes[TSC_MAX_NUM][3] = {
        { 3397, 2800, 2221 },
        { 3393, 2795, 2216 },
        { 3389, 2805, 2237 },
@@ -172,7 +172,7 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
        /* Read register and convert to mili Celsius */
        reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;
 
-       if (reg <= thcode[tsc->id][1])
+       if (reg <= thcodes[tsc->id][1])
                val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1,
                                tsc->coef.a1);
        else
@@ -314,6 +314,10 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
                .compatible = "renesas,r8a774b1-thermal",
                .data = &rcar_gen3_ths_tj_1,
        },
+       {
+               .compatible = "renesas,r8a774e1-thermal",
+               .data = &rcar_gen3_ths_tj_1,
+       },
        {
                .compatible = "renesas,r8a7795-thermal",
                .data = &rcar_gen3_ths_tj_1,
@@ -430,7 +434,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
                priv->tscs[i] = tsc;
 
                priv->thermal_init(tsc);
-               rcar_gen3_thermal_calc_coefs(tsc, ptat, thcode[i],
+               rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i],
                                             *rcar_gen3_ths_tj_1);
 
                zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
index 46aeb28b4e901133ce06d07d4b78252e4f60ec8f..787710bb88fee890cc6afc419e5521e7d9092bfa 100644 (file)
@@ -550,12 +550,19 @@ static int rcar_thermal_probe(struct platform_device *pdev)
                        priv->zone = devm_thermal_zone_of_sensor_register(
                                                dev, i, priv,
                                                &rcar_thermal_zone_of_ops);
-               else
+               else {
                        priv->zone = thermal_zone_device_register(
                                                "rcar_thermal",
                                                1, 0, priv,
                                                &rcar_thermal_zone_ops, NULL, 0,
                                                idle);
+
+                       ret = thermal_zone_device_enable(priv->zone);
+                       if (ret) {
+                               thermal_zone_device_unregister(priv->zone);
+                               priv->zone = ERR_PTR(ret);
+                       }
+               }
                if (IS_ERR(priv->zone)) {
                        dev_err(dev, "can't register thermal zone\n");
                        ret = PTR_ERR(priv->zone);
index 15a71ecc916c1a619c5997f3a693b97a2798484e..aa9e0e31ef9849cb1d849a6f74392f970a541d2a 100644 (file)
@@ -1068,8 +1068,10 @@ rockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor *sensor, bool on)
 {
        struct thermal_zone_device *tzd = sensor->tzd;
 
-       tzd->ops->set_mode(tzd,
-               on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
+       if (on)
+               thermal_zone_device_enable(tzd);
+       else
+               thermal_zone_device_disable(tzd);
 }
 
 static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
index f68f581fd669202f600696221b0e2f79d140f580..ee33ed692e4f7ee13983e7fffee97d346a7a5e55 100644 (file)
@@ -131,6 +131,11 @@ static int spear_thermal_probe(struct platform_device *pdev)
                ret = PTR_ERR(spear_thermal);
                goto disable_clk;
        }
+       ret = thermal_zone_device_enable(spear_thermal);
+       if (ret) {
+               dev_err(&pdev->dev, "Cannot enable thermal zone\n");
+               goto unregister_tzd;
+       }
 
        platform_set_drvdata(pdev, spear_thermal);
 
@@ -139,6 +144,8 @@ static int spear_thermal_probe(struct platform_device *pdev)
 
        return 0;
 
+unregister_tzd:
+       thermal_zone_device_unregister(spear_thermal);
 disable_clk:
        clk_disable(stdev->clk);
 
index 4cde70dcf655659f6a36135ddf8a2e502d2b6f90..3682edb2f46692d0892abfe34524f75328bcfe93 100644 (file)
@@ -322,8 +322,10 @@ static void sprd_thm_toggle_sensor(struct sprd_thermal_sensor *sen, bool on)
 {
        struct thermal_zone_device *tzd = sen->tzd;
 
-       tzd->ops->set_mode(tzd,
-               on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
+       if (on)
+               thermal_zone_device_enable(tzd);
+       else
+               thermal_zone_device_disable(tzd);
 }
 
 static int sprd_thm_probe(struct platform_device *pdev)
index b928ca6a289b73a94af830ff8062bd62548c87a1..1276b95604fed7dc7b8a038ca95871ba0a136ff7 100644 (file)
@@ -246,11 +246,16 @@ int st_thermal_register(struct platform_device *pdev,
                ret = PTR_ERR(sensor->thermal_dev);
                goto sensor_off;
        }
+       ret = thermal_zone_device_enable(sensor->thermal_dev);
+       if (ret)
+               goto tzd_unregister;
 
        platform_set_drvdata(pdev, sensor);
 
        return 0;
 
+tzd_unregister:
+       thermal_zone_device_unregister(sensor->thermal_dev);
 sensor_off:
        st_thermal_sensor_off(sensor);
 
index b71196eaf90e8247a551556483370150dedd7e72..72bf159bceccd83c187bb114ad9eacb175dfa6a0 100644 (file)
@@ -215,6 +215,8 @@ exit:
        mutex_unlock(&tz->lock);
        mutex_unlock(&thermal_governor_lock);
 
+       thermal_notify_tz_gov_change(tz->id, policy);
+
        return ret;
 }
 
@@ -301,13 +303,22 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
                cancel_delayed_work(&tz->poll_queue);
 }
 
+static inline bool should_stop_polling(struct thermal_zone_device *tz)
+{
+       return !thermal_zone_device_is_enabled(tz);
+}
+
 static void monitor_thermal_zone(struct thermal_zone_device *tz)
 {
+       bool stop;
+
+       stop = should_stop_polling(tz);
+
        mutex_lock(&tz->lock);
 
-       if (tz->passive)
+       if (!stop && tz->passive)
                thermal_zone_device_set_polling(tz, tz->passive_delay);
-       else if (tz->polling_delay)
+       else if (!stop && tz->polling_delay)
                thermal_zone_device_set_polling(tz, tz->polling_delay);
        else
                thermal_zone_device_set_polling(tz, 0);
@@ -406,12 +417,25 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
 static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
 {
        enum thermal_trip_type type;
+       int trip_temp, hyst = 0;
 
        /* Ignore disabled trip points */
        if (test_bit(trip, &tz->trips_disabled))
                return;
 
+       tz->ops->get_trip_temp(tz, trip, &trip_temp);
        tz->ops->get_trip_type(tz, trip, &type);
+       if (tz->ops->get_trip_hyst)
+               tz->ops->get_trip_hyst(tz, trip, &hyst);
+
+       if (tz->last_temperature != THERMAL_TEMP_INVALID) {
+               if (tz->last_temperature < trip_temp &&
+                   tz->temperature >= trip_temp)
+                       thermal_notify_tz_trip_up(tz->id, trip);
+               if (tz->last_temperature >= trip_temp &&
+                   tz->temperature < (trip_temp - hyst))
+                       thermal_notify_tz_trip_down(tz->id, trip);
+       }
 
        if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
                handle_critical_trips(tz, trip, type);
@@ -443,6 +467,8 @@ static void update_temperature(struct thermal_zone_device *tz)
        mutex_unlock(&tz->lock);
 
        trace_thermal_temperature(tz);
+
+       thermal_genl_sampling_temp(tz->id, temp);
 }
 
 static 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)
        thermal_zone_device_init(tz);
 }
 
+static int thermal_zone_device_set_mode(struct thermal_zone_device *tz,
+                                       enum thermal_device_mode mode)
+{
+       int ret = 0;
+
+       mutex_lock(&tz->lock);
+
+       /* do nothing if mode isn't changing */
+       if (mode == tz->mode) {
+               mutex_unlock(&tz->lock);
+
+               return ret;
+       }
+
+       if (tz->ops->change_mode)
+               ret = tz->ops->change_mode(tz, mode);
+
+       if (!ret)
+               tz->mode = mode;
+
+       mutex_unlock(&tz->lock);
+
+       thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+       if (mode == THERMAL_DEVICE_ENABLED)
+               thermal_notify_tz_enable(tz->id);
+       else
+               thermal_notify_tz_disable(tz->id);
+
+       return ret;
+}
+
+int thermal_zone_device_enable(struct thermal_zone_device *tz)
+{
+       return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_ENABLED);
+}
+EXPORT_SYMBOL_GPL(thermal_zone_device_enable);
+
+int thermal_zone_device_disable(struct thermal_zone_device *tz)
+{
+       return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_DISABLED);
+}
+EXPORT_SYMBOL_GPL(thermal_zone_device_disable);
+
+int thermal_zone_device_is_enabled(struct thermal_zone_device *tz)
+{
+       enum thermal_device_mode mode;
+
+       mutex_lock(&tz->lock);
+
+       mode = tz->mode;
+
+       mutex_unlock(&tz->lock);
+
+       return mode == THERMAL_DEVICE_ENABLED;
+}
+
 void thermal_zone_device_update(struct thermal_zone_device *tz,
                                enum thermal_notify_event event)
 {
        int count;
 
+       if (should_stop_polling(tz))
+               return;
+
        if (atomic_read(&in_suspend))
                return;
 
@@ -617,6 +703,73 @@ void thermal_zone_device_rebind_exception(struct thermal_zone_device *tz,
        mutex_unlock(&thermal_list_lock);
 }
 
+int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *),
+                             void *data)
+{
+       struct thermal_governor *gov;
+       int ret = 0;
+
+       mutex_lock(&thermal_governor_lock);
+       list_for_each_entry(gov, &thermal_governor_list, governor_list) {
+               ret = cb(gov, data);
+               if (ret)
+                       break;
+       }
+       mutex_unlock(&thermal_governor_lock);
+
+       return ret;
+}
+
+int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *,
+                                             void *), void *data)
+{
+       struct thermal_cooling_device *cdev;
+       int ret = 0;
+
+       mutex_lock(&thermal_list_lock);
+       list_for_each_entry(cdev, &thermal_cdev_list, node) {
+               ret = cb(cdev, data);
+               if (ret)
+                       break;
+       }
+       mutex_unlock(&thermal_list_lock);
+
+       return ret;
+}
+
+int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *),
+                         void *data)
+{
+       struct thermal_zone_device *tz;
+       int ret = 0;
+
+       mutex_lock(&thermal_list_lock);
+       list_for_each_entry(tz, &thermal_tz_list, node) {
+               ret = cb(tz, data);
+               if (ret)
+                       break;
+       }
+       mutex_unlock(&thermal_list_lock);
+
+       return ret;
+}
+
+struct thermal_zone_device *thermal_zone_get_by_id(int id)
+{
+       struct thermal_zone_device *tz, *match = NULL;
+
+       mutex_lock(&thermal_list_lock);
+       list_for_each_entry(tz, &thermal_tz_list, node) {
+               if (tz->id == id) {
+                       match = tz;
+                       break;
+               }
+       }
+       mutex_unlock(&thermal_list_lock);
+
+       return match;
+}
+
 void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,
                                          const char *cdev_type, size_t size)
 {
@@ -1340,6 +1493,8 @@ thermal_zone_device_register(const char *type, int trips, int mask,
        if (atomic_cmpxchg(&tz->need_update, 1, 0))
                thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
 
+       thermal_notify_tz_create(tz->id, tz->type);
+
        return tz;
 
 unregister:
@@ -1411,6 +1566,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
        ida_destroy(&tz->ida);
        mutex_destroy(&tz->lock);
        device_unregister(&tz->device);
+
+       thermal_notify_tz_delete(tz->id);
 }
 EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
 
@@ -1456,7 +1613,6 @@ static int thermal_pm_notify(struct notifier_block *nb,
                             unsigned long mode, void *_unused)
 {
        struct thermal_zone_device *tz;
-       enum thermal_device_mode tz_mode;
 
        switch (mode) {
        case PM_HIBERNATION_PREPARE:
@@ -1469,11 +1625,7 @@ static int thermal_pm_notify(struct notifier_block *nb,
        case PM_POST_SUSPEND:
                atomic_set(&in_suspend, 0);
                list_for_each_entry(tz, &thermal_tz_list, node) {
-                       tz_mode = THERMAL_DEVICE_ENABLED;
-                       if (tz->ops->get_mode)
-                               tz->ops->get_mode(tz, &tz_mode);
-
-                       if (tz_mode == THERMAL_DEVICE_DISABLED)
+                       if (!thermal_zone_device_is_enabled(tz))
                                continue;
 
                        thermal_zone_device_init(tz);
@@ -1495,6 +1647,10 @@ static int __init thermal_init(void)
 {
        int result;
 
+       result = thermal_netlink_init();
+       if (result)
+               goto error;
+
        mutex_init(&poweroff_lock);
        result = thermal_register_governors();
        if (result)
@@ -1527,4 +1683,4 @@ error:
        mutex_destroy(&poweroff_lock);
        return result;
 }
-core_initcall(thermal_init);
+postcore_initcall(thermal_init);
index c95689586e19ac77df86ae84b734db25922c50e6..e00fc5585ea805680c56e0dd1a029fae41f965dd 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/device.h>
 #include <linux/thermal.h>
 
+#include "thermal_netlink.h"
+
 /* Default Thermal Governor */
 #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
 #define DEFAULT_THERMAL_GOVERNOR       "step_wise"
@@ -41,6 +43,17 @@ extern struct thermal_governor *__governor_thermal_table_end[];
             __governor < __governor_thermal_table_end; \
             __governor++)
 
+int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *),
+                         void *);
+
+int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *,
+                                             void *), void *);
+
+int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *),
+                             void *thermal_governor);
+
+struct thermal_zone_device *thermal_zone_get_by_id(int id);
+
 struct thermal_attr {
        struct device_attribute attr;
        char name[THERMAL_NAME_LENGTH];
@@ -166,4 +179,6 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz)
 }
 #endif
 
+int thermal_zone_device_is_enabled(struct thermal_zone_device *tz);
+
 #endif /* __THERMAL_CORE_H__ */
index 87b1256fa2f206a03b6eb19f07d9203ae0677cfa..c94bc824e5d36ab34594cc35e0bcf2444efc85d9 100644 (file)
@@ -175,6 +175,16 @@ exit:
        mutex_unlock(&tz->lock);
 }
 
+static void thermal_cdev_set_cur_state(struct thermal_cooling_device *cdev,
+                                      int target)
+{
+       if (cdev->ops->set_cur_state(cdev, target))
+               return;
+
+       thermal_notify_cdev_state_update(cdev->id, target);
+       thermal_cooling_device_stats_update(cdev, target);
+}
+
 void thermal_cdev_update(struct thermal_cooling_device *cdev)
 {
        struct thermal_instance *instance;
@@ -197,8 +207,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
                        target = instance->target;
        }
 
-       if (!cdev->ops->set_cur_state(cdev, target))
-               thermal_cooling_device_stats_update(cdev, target);
+       thermal_cdev_set_cur_state(cdev, target);
 
        cdev->updated = true;
        mutex_unlock(&cdev->lock);
diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c
new file mode 100644 (file)
index 0000000..af7b238
--- /dev/null
@@ -0,0 +1,647 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020 Linaro Limited
+ *
+ * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+ * Generic netlink for thermal management framework
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <net/genetlink.h>
+#include <uapi/linux/thermal.h>
+
+#include "thermal_core.h"
+
+static const struct genl_multicast_group thermal_genl_mcgrps[] = {
+       { .name = THERMAL_GENL_SAMPLING_GROUP_NAME, },
+       { .name = THERMAL_GENL_EVENT_GROUP_NAME,  },
+};
+
+static const struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = {
+       /* Thermal zone */
+       [THERMAL_GENL_ATTR_TZ]                  = { .type = NLA_NESTED },
+       [THERMAL_GENL_ATTR_TZ_ID]               = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_TZ_TEMP]             = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_TZ_TRIP]             = { .type = NLA_NESTED },
+       [THERMAL_GENL_ATTR_TZ_TRIP_ID]          = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_TZ_TRIP_TEMP]        = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_TZ_TRIP_TYPE]        = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_TZ_TRIP_HYST]        = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_TZ_MODE]             = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT]      = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_TZ_NAME]             = { .type = NLA_STRING,
+                                                   .len = THERMAL_NAME_LENGTH },
+       /* Governor(s) */
+       [THERMAL_GENL_ATTR_TZ_GOV]              = { .type = NLA_NESTED },
+       [THERMAL_GENL_ATTR_TZ_GOV_NAME]         = { .type = NLA_STRING,
+                                                   .len = THERMAL_NAME_LENGTH },
+       /* Cooling devices */
+       [THERMAL_GENL_ATTR_CDEV]                = { .type = NLA_NESTED },
+       [THERMAL_GENL_ATTR_CDEV_ID]             = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_CDEV_CUR_STATE]      = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_CDEV_MAX_STATE]      = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_CDEV_NAME]           = { .type = NLA_STRING,
+                                                   .len = THERMAL_NAME_LENGTH },
+};
+
+struct param {
+       struct nlattr **attrs;
+       struct sk_buff *msg;
+       const char *name;
+       int tz_id;
+       int cdev_id;
+       int trip_id;
+       int trip_temp;
+       int trip_type;
+       int trip_hyst;
+       int temp;
+       int cdev_state;
+       int cdev_max_state;
+};
+
+typedef int (*cb_t)(struct param *);
+
+static struct genl_family thermal_gnl_family;
+
+/************************** Sampling encoding *******************************/
+
+int thermal_genl_sampling_temp(int id, int temp)
+{
+       struct sk_buff *skb;
+       void *hdr;
+
+       skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+       if (!skb)
+               return -ENOMEM;
+
+       hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0,
+                         THERMAL_GENL_SAMPLING_TEMP);
+       if (!hdr)
+               return -EMSGSIZE;
+
+       if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_ID, id))
+               goto out_cancel;
+
+       if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_TEMP, temp))
+               goto out_cancel;
+
+       genlmsg_end(skb, hdr);
+
+       genlmsg_multicast(&thermal_gnl_family, skb, 0, 0, GFP_KERNEL);
+
+       return 0;
+out_cancel:
+       genlmsg_cancel(skb, hdr);
+       nlmsg_free(skb);
+
+       return -EMSGSIZE;
+}
+
+/**************************** Event encoding *********************************/
+
+static int thermal_genl_event_tz_create(struct param *p)
+{
+       if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) ||
+           nla_put_string(p->msg, THERMAL_GENL_ATTR_TZ_NAME, p->name))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_event_tz(struct param *p)
+{
+       if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_event_tz_trip_up(struct param *p)
+{
+       if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) ||
+           nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_event_tz_trip_add(struct param *p)
+{
+       if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) ||
+           nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id) ||
+           nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, p->trip_type) ||
+           nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, p->trip_temp) ||
+           nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, p->trip_hyst))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_event_tz_trip_delete(struct param *p)
+{
+       if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) ||
+           nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_event_cdev_add(struct param *p)
+{
+       if (nla_put_string(p->msg, THERMAL_GENL_ATTR_CDEV_NAME,
+                          p->name) ||
+           nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID,
+                       p->cdev_id) ||
+           nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_MAX_STATE,
+                       p->cdev_max_state))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_event_cdev_delete(struct param *p)
+{
+       if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, p->cdev_id))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_event_cdev_state_update(struct param *p)
+{
+       if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID,
+                       p->cdev_id) ||
+           nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_CUR_STATE,
+                       p->cdev_state))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_event_gov_change(struct param *p)
+{
+       if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) ||
+           nla_put_string(p->msg, THERMAL_GENL_ATTR_GOV_NAME, p->name))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+int thermal_genl_event_tz_delete(struct param *p)
+       __attribute__((alias("thermal_genl_event_tz")));
+
+int thermal_genl_event_tz_enable(struct param *p)
+       __attribute__((alias("thermal_genl_event_tz")));
+
+int thermal_genl_event_tz_disable(struct param *p)
+       __attribute__((alias("thermal_genl_event_tz")));
+
+int thermal_genl_event_tz_trip_down(struct param *p)
+       __attribute__((alias("thermal_genl_event_tz_trip_up")));
+
+int thermal_genl_event_tz_trip_change(struct param *p)
+       __attribute__((alias("thermal_genl_event_tz_trip_add")));
+
+static cb_t event_cb[] = {
+       [THERMAL_GENL_EVENT_TZ_CREATE]          = thermal_genl_event_tz_create,
+       [THERMAL_GENL_EVENT_TZ_DELETE]          = thermal_genl_event_tz_delete,
+       [THERMAL_GENL_EVENT_TZ_ENABLE]          = thermal_genl_event_tz_enable,
+       [THERMAL_GENL_EVENT_TZ_DISABLE]         = thermal_genl_event_tz_disable,
+       [THERMAL_GENL_EVENT_TZ_TRIP_UP]         = thermal_genl_event_tz_trip_up,
+       [THERMAL_GENL_EVENT_TZ_TRIP_DOWN]       = thermal_genl_event_tz_trip_down,
+       [THERMAL_GENL_EVENT_TZ_TRIP_CHANGE]     = thermal_genl_event_tz_trip_change,
+       [THERMAL_GENL_EVENT_TZ_TRIP_ADD]        = thermal_genl_event_tz_trip_add,
+       [THERMAL_GENL_EVENT_TZ_TRIP_DELETE]     = thermal_genl_event_tz_trip_delete,
+       [THERMAL_GENL_EVENT_CDEV_ADD]           = thermal_genl_event_cdev_add,
+       [THERMAL_GENL_EVENT_CDEV_DELETE]        = thermal_genl_event_cdev_delete,
+       [THERMAL_GENL_EVENT_CDEV_STATE_UPDATE]  = thermal_genl_event_cdev_state_update,
+       [THERMAL_GENL_EVENT_TZ_GOV_CHANGE]      = thermal_genl_event_gov_change,
+};
+
+/*
+ * Generic netlink event encoding
+ */
+static int thermal_genl_send_event(enum thermal_genl_event event,
+                                  struct param *p)
+{
+       struct sk_buff *msg;
+       int ret = -EMSGSIZE;
+       void *hdr;
+
+       msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+       p->msg = msg;
+
+       hdr = genlmsg_put(msg, 0, 0, &thermal_gnl_family, 0, event);
+       if (!hdr)
+               goto out_free_msg;
+
+       ret = event_cb[event](p);
+       if (ret)
+               goto out_cancel_msg;
+
+       genlmsg_end(msg, hdr);
+
+       genlmsg_multicast(&thermal_gnl_family, msg, 0, 1, GFP_KERNEL);
+
+       return 0;
+
+out_cancel_msg:
+       genlmsg_cancel(msg, hdr);
+out_free_msg:
+       nlmsg_free(msg);
+
+       return ret;
+}
+
+int thermal_notify_tz_create(int tz_id, const char *name)
+{
+       struct param p = { .tz_id = tz_id, .name = name };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_CREATE, &p);
+}
+
+int thermal_notify_tz_delete(int tz_id)
+{
+       struct param p = { .tz_id = tz_id };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DELETE, &p);
+}
+
+int thermal_notify_tz_enable(int tz_id)
+{
+       struct param p = { .tz_id = tz_id };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_ENABLE, &p);
+}
+
+int thermal_notify_tz_disable(int tz_id)
+{
+       struct param p = { .tz_id = tz_id };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DISABLE, &p);
+}
+
+int thermal_notify_tz_trip_down(int tz_id, int trip_id)
+{
+       struct param p = { .tz_id = tz_id, .trip_id = trip_id };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DOWN, &p);
+}
+
+int thermal_notify_tz_trip_up(int tz_id, int trip_id)
+{
+       struct param p = { .tz_id = tz_id, .trip_id = trip_id };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_UP, &p);
+}
+
+int thermal_notify_tz_trip_add(int tz_id, int trip_id, int trip_type,
+                              int trip_temp, int trip_hyst)
+{
+       struct param p = { .tz_id = tz_id, .trip_id = trip_id,
+                          .trip_type = trip_type, .trip_temp = trip_temp,
+                          .trip_hyst = trip_hyst };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_ADD, &p);
+}
+
+int thermal_notify_tz_trip_delete(int tz_id, int trip_id)
+{
+       struct param p = { .tz_id = tz_id, .trip_id = trip_id };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DELETE, &p);
+}
+
+int thermal_notify_tz_trip_change(int tz_id, int trip_id, int trip_type,
+                                 int trip_temp, int trip_hyst)
+{
+       struct param p = { .tz_id = tz_id, .trip_id = trip_id,
+                          .trip_type = trip_type, .trip_temp = trip_temp,
+                          .trip_hyst = trip_hyst };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_CHANGE, &p);
+}
+
+int thermal_notify_cdev_state_update(int cdev_id, int cdev_state)
+{
+       struct param p = { .cdev_id = cdev_id, .cdev_state = cdev_state };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_STATE_UPDATE, &p);
+}
+
+int thermal_notify_cdev_add(int cdev_id, const char *name, int cdev_max_state)
+{
+       struct param p = { .cdev_id = cdev_id, .name = name,
+                          .cdev_max_state = cdev_max_state };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_ADD, &p);
+}
+
+int thermal_notify_cdev_delete(int cdev_id)
+{
+       struct param p = { .cdev_id = cdev_id };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_DELETE, &p);
+}
+
+int thermal_notify_tz_gov_change(int tz_id, const char *name)
+{
+       struct param p = { .tz_id = tz_id, .name = name };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_GOV_CHANGE, &p);
+}
+
+/*************************** Command encoding ********************************/
+
+static int __thermal_genl_cmd_tz_get_id(struct thermal_zone_device *tz,
+                                       void *data)
+{
+       struct sk_buff *msg = data;
+
+       if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, tz->id) ||
+           nla_put_string(msg, THERMAL_GENL_ATTR_TZ_NAME, tz->type))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_cmd_tz_get_id(struct param *p)
+{
+       struct sk_buff *msg = p->msg;
+       struct nlattr *start_tz;
+       int ret;
+
+       start_tz = nla_nest_start(msg, THERMAL_GENL_ATTR_TZ);
+       if (!start_tz)
+               return -EMSGSIZE;
+
+       ret = for_each_thermal_zone(__thermal_genl_cmd_tz_get_id, msg);
+       if (ret)
+               goto out_cancel_nest;
+
+       nla_nest_end(msg, start_tz);
+
+       return 0;
+
+out_cancel_nest:
+       nla_nest_cancel(msg, start_tz);
+
+       return ret;
+}
+
+static int thermal_genl_cmd_tz_get_trip(struct param *p)
+{
+       struct sk_buff *msg = p->msg;
+       struct thermal_zone_device *tz;
+       struct nlattr *start_trip;
+       int i, id;
+
+       if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID])
+               return -EINVAL;
+
+       id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]);
+
+       tz = thermal_zone_get_by_id(id);
+       if (!tz)
+               return -EINVAL;
+
+       start_trip = nla_nest_start(msg, THERMAL_GENL_ATTR_TZ_TRIP);
+       if (!start_trip)
+               return -EMSGSIZE;
+
+       mutex_lock(&tz->lock);
+
+       for (i = 0; i < tz->trips; i++) {
+
+               enum thermal_trip_type type;
+               int temp, hyst;
+
+               tz->ops->get_trip_type(tz, i, &type);
+               tz->ops->get_trip_temp(tz, i, &temp);
+               tz->ops->get_trip_hyst(tz, i, &hyst);
+
+               if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, i) ||
+                   nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, type) ||
+                   nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, temp) ||
+                   nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, hyst))
+                       goto out_cancel_nest;
+       }
+
+       mutex_unlock(&tz->lock);
+
+       nla_nest_end(msg, start_trip);
+
+       return 0;
+
+out_cancel_nest:
+       mutex_unlock(&tz->lock);
+
+       return -EMSGSIZE;
+}
+
+static int thermal_genl_cmd_tz_get_temp(struct param *p)
+{
+       struct sk_buff *msg = p->msg;
+       struct thermal_zone_device *tz;
+       int temp, ret, id;
+
+       if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID])
+               return -EINVAL;
+
+       id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]);
+
+       tz = thermal_zone_get_by_id(id);
+       if (!tz)
+               return -EINVAL;
+
+       ret = thermal_zone_get_temp(tz, &temp);
+       if (ret)
+               return ret;
+
+       if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id) ||
+           nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TEMP, temp))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_cmd_tz_get_gov(struct param *p)
+{
+       struct sk_buff *msg = p->msg;
+       struct thermal_zone_device *tz;
+       int id, ret = 0;
+
+       if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID])
+               return -EINVAL;
+
+       id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]);
+
+       tz = thermal_zone_get_by_id(id);
+       if (!tz)
+               return -EINVAL;
+
+       mutex_lock(&tz->lock);
+
+       if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id) ||
+           nla_put_string(msg, THERMAL_GENL_ATTR_TZ_GOV_NAME,
+                          tz->governor->name))
+               ret = -EMSGSIZE;
+
+       mutex_unlock(&tz->lock);
+
+       return ret;
+}
+
+static int __thermal_genl_cmd_cdev_get(struct thermal_cooling_device *cdev,
+                                      void *data)
+{
+       struct sk_buff *msg = data;
+
+       if (nla_put_u32(msg, THERMAL_GENL_ATTR_CDEV_ID, cdev->id))
+               return -EMSGSIZE;
+
+       if (nla_put_string(msg, THERMAL_GENL_ATTR_CDEV_NAME, cdev->type))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int thermal_genl_cmd_cdev_get(struct param *p)
+{
+       struct sk_buff *msg = p->msg;
+       struct nlattr *start_cdev;
+       int ret;
+
+       start_cdev = nla_nest_start(msg, THERMAL_GENL_ATTR_CDEV);
+       if (!start_cdev)
+               return -EMSGSIZE;
+
+       ret = for_each_thermal_cooling_device(__thermal_genl_cmd_cdev_get, msg);
+       if (ret)
+               goto out_cancel_nest;
+
+       nla_nest_end(msg, start_cdev);
+
+       return 0;
+out_cancel_nest:
+       nla_nest_cancel(msg, start_cdev);
+
+       return ret;
+}
+
+static cb_t cmd_cb[] = {
+       [THERMAL_GENL_CMD_TZ_GET_ID]    = thermal_genl_cmd_tz_get_id,
+       [THERMAL_GENL_CMD_TZ_GET_TRIP]  = thermal_genl_cmd_tz_get_trip,
+       [THERMAL_GENL_CMD_TZ_GET_TEMP]  = thermal_genl_cmd_tz_get_temp,
+       [THERMAL_GENL_CMD_TZ_GET_GOV]   = thermal_genl_cmd_tz_get_gov,
+       [THERMAL_GENL_CMD_CDEV_GET]     = thermal_genl_cmd_cdev_get,
+};
+
+static int thermal_genl_cmd_dumpit(struct sk_buff *skb,
+                                  struct netlink_callback *cb)
+{
+       struct param p = { .msg = skb };
+       const struct genl_dumpit_info *info = genl_dumpit_info(cb);
+       int cmd = info->ops->cmd;
+       int ret;
+       void *hdr;
+
+       hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, cmd);
+       if (!hdr)
+               return -EMSGSIZE;
+
+       ret = cmd_cb[cmd](&p);
+       if (ret)
+               goto out_cancel_msg;
+
+       genlmsg_end(skb, hdr);
+
+       return 0;
+
+out_cancel_msg:
+       genlmsg_cancel(skb, hdr);
+
+       return ret;
+}
+
+static int thermal_genl_cmd_doit(struct sk_buff *skb,
+                                struct genl_info *info)
+{
+       struct param p = { .attrs = info->attrs };
+       struct sk_buff *msg;
+       void *hdr;
+       int cmd = info->genlhdr->cmd;
+       int ret = -EMSGSIZE;
+
+       msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+       p.msg = msg;
+
+       hdr = genlmsg_put_reply(msg, info, &thermal_gnl_family, 0, cmd);
+       if (!hdr)
+               goto out_free_msg;
+
+       ret = cmd_cb[cmd](&p);
+       if (ret)
+               goto out_cancel_msg;
+
+       genlmsg_end(msg, hdr);
+
+       return genlmsg_reply(msg, info);
+
+out_cancel_msg:
+       genlmsg_cancel(msg, hdr);
+out_free_msg:
+       nlmsg_free(msg);
+
+       return ret;
+}
+
+static const struct genl_ops thermal_genl_ops[] = {
+       {
+               .cmd = THERMAL_GENL_CMD_TZ_GET_ID,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+               .dumpit = thermal_genl_cmd_dumpit,
+       },
+       {
+               .cmd = THERMAL_GENL_CMD_TZ_GET_TRIP,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+               .doit = thermal_genl_cmd_doit,
+       },
+       {
+               .cmd = THERMAL_GENL_CMD_TZ_GET_TEMP,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+               .doit = thermal_genl_cmd_doit,
+       },
+       {
+               .cmd = THERMAL_GENL_CMD_TZ_GET_GOV,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+               .doit = thermal_genl_cmd_doit,
+       },
+       {
+               .cmd = THERMAL_GENL_CMD_CDEV_GET,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+               .dumpit = thermal_genl_cmd_dumpit,
+       },
+};
+
+static struct genl_family thermal_gnl_family __ro_after_init = {
+       .hdrsize        = 0,
+       .name           = THERMAL_GENL_FAMILY_NAME,
+       .version        = THERMAL_GENL_VERSION,
+       .maxattr        = THERMAL_GENL_ATTR_MAX,
+       .policy         = thermal_genl_policy,
+       .ops            = thermal_genl_ops,
+       .n_ops          = ARRAY_SIZE(thermal_genl_ops),
+       .mcgrps         = thermal_genl_mcgrps,
+       .n_mcgrps       = ARRAY_SIZE(thermal_genl_mcgrps),
+};
+
+int __init thermal_netlink_init(void)
+{
+       return genl_register_family(&thermal_gnl_family);
+}
diff --git a/drivers/thermal/thermal_netlink.h b/drivers/thermal/thermal_netlink.h
new file mode 100644 (file)
index 0000000..828d1dd
--- /dev/null
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (C) Linaro Ltd 2020
+ *  Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ */
+
+/* Netlink notification function */
+#ifdef CONFIG_THERMAL_NETLINK
+int __init thermal_netlink_init(void);
+int thermal_notify_tz_create(int tz_id, const char *name);
+int thermal_notify_tz_delete(int tz_id);
+int thermal_notify_tz_enable(int tz_id);
+int thermal_notify_tz_disable(int tz_id);
+int thermal_notify_tz_trip_down(int tz_id, int id);
+int thermal_notify_tz_trip_up(int tz_id, int id);
+int thermal_notify_tz_trip_delete(int tz_id, int id);
+int thermal_notify_tz_trip_add(int tz_id, int id, int type,
+                              int temp, int hyst);
+int thermal_notify_tz_trip_change(int tz_id, int id, int type,
+                                 int temp, int hyst);
+int thermal_notify_cdev_state_update(int cdev_id, int state);
+int thermal_notify_cdev_add(int cdev_id, const char *name, int max_state);
+int thermal_notify_cdev_delete(int cdev_id);
+int thermal_notify_tz_gov_change(int tz_id, const char *name);
+int thermal_genl_sampling_temp(int id, int temp);
+#else
+static inline int thermal_netlink_init(void)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_create(int tz_id, const char *name)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_delete(int tz_id)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_enable(int tz_id)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_disable(int tz_id)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_trip_down(int tz_id, int id)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_trip_up(int tz_id, int id)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_trip_delete(int tz_id, int id)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_trip_add(int tz_id, int id, int type,
+                                            int temp, int hyst)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_trip_change(int tz_id, int id, int type,
+                                               int temp, int hyst)
+{
+       return 0;
+}
+
+static inline int thermal_notify_cdev_state_update(int cdev_id, int state)
+{
+       return 0;
+}
+
+static inline int thermal_notify_cdev_add(int cdev_id, const char *name,
+                                         int max_state)
+{
+       return 0;
+}
+
+static inline int thermal_notify_cdev_delete(int cdev_id)
+{
+       return 0;
+}
+
+static inline int thermal_notify_tz_gov_change(int tz_id, const char *name)
+{
+       return 0;
+}
+
+static inline int thermal_genl_sampling_temp(int id, int temp)
+{
+       return 0;
+}
+#endif /* CONFIG_THERMAL_NETLINK */
index ddf88dbe7ba2934721c240811b22e3a6930210c3..69ef12f852b7d56c6251dc0834e3873c7df6b6a2 100644 (file)
@@ -51,7 +51,6 @@ struct __thermal_bind_params {
 
 /**
  * struct __thermal_zone - internal representation of a thermal zone
- * @mode: current thermal zone device mode (enabled/disabled)
  * @passive_delay: polling interval while passive cooling is activated
  * @polling_delay: zone polling interval
  * @slope: slope of the temperature adjustment curve
@@ -65,7 +64,6 @@ struct __thermal_bind_params {
  */
 
 struct __thermal_zone {
-       enum thermal_device_mode mode;
        int passive_delay;
        int polling_delay;
        int slope;
@@ -269,39 +267,6 @@ static int of_thermal_unbind(struct thermal_zone_device *thermal,
        return 0;
 }
 
-static int of_thermal_get_mode(struct thermal_zone_device *tz,
-                              enum thermal_device_mode *mode)
-{
-       struct __thermal_zone *data = tz->devdata;
-
-       *mode = data->mode;
-
-       return 0;
-}
-
-static int of_thermal_set_mode(struct thermal_zone_device *tz,
-                              enum thermal_device_mode mode)
-{
-       struct __thermal_zone *data = tz->devdata;
-
-       mutex_lock(&tz->lock);
-
-       if (mode == THERMAL_DEVICE_ENABLED) {
-               tz->polling_delay = data->polling_delay;
-               tz->passive_delay = data->passive_delay;
-       } else {
-               tz->polling_delay = 0;
-               tz->passive_delay = 0;
-       }
-
-       mutex_unlock(&tz->lock);
-
-       data->mode = mode;
-       thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
-       return 0;
-}
-
 static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
                                    enum thermal_trip_type *type)
 {
@@ -393,9 +358,6 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
 }
 
 static struct thermal_zone_device_ops of_thermal_ops = {
-       .get_mode = of_thermal_get_mode,
-       .set_mode = of_thermal_set_mode,
-
        .get_trip_type = of_thermal_get_trip_type,
        .get_trip_temp = of_thermal_get_trip_temp,
        .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,
                        tzd = thermal_zone_of_add_sensor(child, sensor_np,
                                                         data, ops);
                        if (!IS_ERR(tzd))
-                               tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);
+                               thermal_zone_device_enable(tzd);
 
                        of_node_put(child);
                        goto exit;
@@ -979,7 +941,6 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
 
 finish:
        of_node_put(child);
-       tz->mode = THERMAL_DEVICE_DISABLED;
 
        return tz;
 
index aa99edb4dff7dca35439ed9536dee82f1e1c5b8c..8c231219e15dd088699ce6fb2c1a113db1351f9a 100644 (file)
@@ -49,18 +49,9 @@ static ssize_t
 mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct thermal_zone_device *tz = to_thermal_zone(dev);
-       enum thermal_device_mode mode;
-       int result;
-
-       if (!tz->ops->get_mode)
-               return -EPERM;
+       int enabled = thermal_zone_device_is_enabled(tz);
 
-       result = tz->ops->get_mode(tz, &mode);
-       if (result)
-               return result;
-
-       return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
-                      : "disabled");
+       return sprintf(buf, "%s\n", enabled ? "enabled" : "disabled");
 }
 
 static ssize_t
@@ -70,13 +61,10 @@ mode_store(struct device *dev, struct device_attribute *attr,
        struct thermal_zone_device *tz = to_thermal_zone(dev);
        int result;
 
-       if (!tz->ops->set_mode)
-               return -EPERM;
-
        if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
-               result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
+               result = thermal_zone_device_enable(tz);
        else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
-               result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
+               result = thermal_zone_device_disable(tz);
        else
                result = -EINVAL;
 
@@ -124,7 +112,8 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
 {
        struct thermal_zone_device *tz = to_thermal_zone(dev);
        int trip, ret;
-       int temperature;
+       int temperature, hyst = 0;
+       enum thermal_trip_type type;
 
        if (!tz->ops->set_trip_temp)
                return -EPERM;
@@ -139,6 +128,18 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
        if (ret)
                return ret;
 
+       if (tz->ops->get_trip_hyst) {
+               ret = tz->ops->get_trip_hyst(tz, trip, &hyst);
+               if (ret)
+                       return ret;
+       }
+
+       ret = tz->ops->get_trip_type(tz, trip, &type);
+       if (ret)
+               return ret;
+
+       thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst);
+
        thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
 
        return count;
@@ -428,30 +429,13 @@ static struct attribute_group thermal_zone_attribute_group = {
        .attrs = thermal_zone_dev_attrs,
 };
 
-/* We expose mode only if .get_mode is present */
 static struct attribute *thermal_zone_mode_attrs[] = {
        &dev_attr_mode.attr,
        NULL,
 };
 
-static umode_t thermal_zone_mode_is_visible(struct kobject *kobj,
-                                           struct attribute *attr,
-                                           int attrno)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct thermal_zone_device *tz;
-
-       tz = container_of(dev, struct thermal_zone_device, device);
-
-       if (tz->ops->get_mode)
-               return attr->mode;
-
-       return 0;
-}
-
 static struct attribute_group thermal_zone_mode_attribute_group = {
        .attrs = thermal_zone_mode_attrs,
-       .is_visible = thermal_zone_mode_is_visible,
 };
 
 /* We expose passive only if passive trips are present */
index 85776db4bf3461d112926cd47487dd3269a54fe7..2ce4b19f312ac66724788dc9f1f628ffb3ea6f01 100644 (file)
@@ -169,7 +169,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
 
        data = ti_bandgap_get_sensor_data(bgp, id);
 
-       if (!IS_ERR_OR_NULL(data))
+       if (IS_ERR_OR_NULL(data))
                data = ti_thermal_build_data(bgp, id);
 
        if (!data)
diff --git a/include/linux/clock_cooling.h b/include/linux/clock_cooling.h
deleted file mode 100644 (file)
index 4b0a698..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- *  linux/include/linux/clock_cooling.h
- *
- *  Copyright (C) 2014 Eduardo Valentin <edubezval@gmail.com>
- *
- *  Copyright (C) 2013 Texas Instruments Inc.
- *  Contact:  Eduardo Valentin <eduardo.valentin@ti.com>
- *
- *  Highly based on cpufreq_cooling.c.
- *  Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
- *  Copyright (C) 2012  Amit Daniel <amit.kachhap@linaro.org>
- */
-
-#ifndef __CPU_COOLING_H__
-#define __CPU_COOLING_H__
-
-#include <linux/of.h>
-#include <linux/thermal.h>
-#include <linux/cpumask.h>
-
-#ifdef CONFIG_CLOCK_THERMAL
-/**
- * clock_cooling_register - function to create clock cooling device.
- * @dev: struct device pointer to the device used as clock cooling device.
- * @clock_name: string containing the clock used as cooling mechanism.
- */
-struct thermal_cooling_device *
-clock_cooling_register(struct device *dev, const char *clock_name);
-
-/**
- * clock_cooling_unregister - function to remove clock cooling device.
- * @cdev: thermal cooling device pointer.
- */
-void clock_cooling_unregister(struct thermal_cooling_device *cdev);
-
-unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev,
-                                     unsigned long freq);
-#else /* !CONFIG_CLOCK_THERMAL */
-static inline struct thermal_cooling_device *
-clock_cooling_register(struct device *dev, const char *clock_name)
-{
-       return NULL;
-}
-static inline
-void clock_cooling_unregister(struct thermal_cooling_device *cdev)
-{
-}
-static inline
-unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev,
-                                     unsigned long freq)
-{
-       return THERMAL_CSTATE_INVALID;
-}
-#endif /* CONFIG_CLOCK_THERMAL */
-
-#endif /* __CPU_COOLING_H__ */
index 79a6e37a1d6f641bcd56e15af8d2b009cb321f88..9df2dfca68dd967aa449bc409282de0297f4b3a6 100644 (file)
@@ -1,17 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * devfreq_cooling: Thermal cooling device implementation for devices using
  *                  devfreq
  *
  * Copyright (C) 2014-2015 ARM Limited
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef __DEVFREQ_COOLING_H__
index 216185bb3014a510122aea63a99edf877fb36890..42ef807e5d84eb6dc2457a9c13f15342ff18f4ed 100644 (file)
@@ -37,18 +37,6 @@ struct thermal_cooling_device;
 struct thermal_instance;
 struct thermal_attr;
 
-enum thermal_device_mode {
-       THERMAL_DEVICE_DISABLED = 0,
-       THERMAL_DEVICE_ENABLED,
-};
-
-enum thermal_trip_type {
-       THERMAL_TRIP_ACTIVE = 0,
-       THERMAL_TRIP_PASSIVE,
-       THERMAL_TRIP_HOT,
-       THERMAL_TRIP_CRITICAL,
-};
-
 enum thermal_trend {
        THERMAL_TREND_STABLE, /* temperature is stable */
        THERMAL_TREND_RAISING, /* temperature is raising */
@@ -76,9 +64,7 @@ struct thermal_zone_device_ops {
                       struct thermal_cooling_device *);
        int (*get_temp) (struct thermal_zone_device *, int *);
        int (*set_trips) (struct thermal_zone_device *, int, int);
-       int (*get_mode) (struct thermal_zone_device *,
-                        enum thermal_device_mode *);
-       int (*set_mode) (struct thermal_zone_device *,
+       int (*change_mode) (struct thermal_zone_device *,
                enum thermal_device_mode);
        int (*get_trip_type) (struct thermal_zone_device *, int,
                enum thermal_trip_type *);
@@ -128,6 +114,7 @@ struct thermal_cooling_device {
  * @trip_temp_attrs:   attributes for trip points for sysfs: trip temperature
  * @trip_type_attrs:   attributes for trip points for sysfs: trip type
  * @trip_hyst_attrs:   attributes for trip points for sysfs: trip hysteresis
+ * @mode:              current mode of this thermal zone
  * @devdata:   private pointer for device private data
  * @trips:     number of trip points the thermal zone supports
  * @trips_disabled;    bitmap for disabled trips
@@ -170,6 +157,7 @@ struct thermal_zone_device {
        struct thermal_attr *trip_temp_attrs;
        struct thermal_attr *trip_type_attrs;
        struct thermal_attr *trip_hyst_attrs;
+       enum thermal_device_mode mode;
        void *devdata;
        int trips;
        unsigned long trips_disabled;   /* bitmap for disabled trips */
@@ -303,11 +291,6 @@ struct thermal_zone_params {
        int offset;
 };
 
-struct thermal_genl_event {
-       u32 orig;
-       enum events event;
-};
-
 /**
  * struct thermal_zone_of_device_ops - scallbacks for handling DT based zones
  *
@@ -416,6 +399,8 @@ int thermal_zone_get_offset(struct thermal_zone_device *tz);
 
 void thermal_cdev_update(struct thermal_cooling_device *);
 void thermal_notify_framework(struct thermal_zone_device *, int);
+int thermal_zone_device_enable(struct thermal_zone_device *tz);
+int thermal_zone_device_disable(struct thermal_zone_device *tz);
 #else
 static inline struct thermal_zone_device *thermal_zone_device_register(
        const char *type, int trips, int mask, void *devdata,
@@ -463,6 +448,12 @@ static inline void thermal_cdev_update(struct thermal_cooling_device *cdev)
 static inline void thermal_notify_framework(struct thermal_zone_device *tz,
        int trip)
 { }
+
+static inline int thermal_zone_device_enable(struct thermal_zone_device *tz)
+{ return -ENODEV; }
+
+static inline int thermal_zone_device_disable(struct thermal_zone_device *tz)
+{ return -ENODEV; }
 #endif /* CONFIG_THERMAL */
 
 #endif /* __THERMAL_H__ */
index 96218378dda8c581115b93e640b3d718d3f0f5ac..c105054cbb57acb9dbef29790822c9f6830a0969 100644 (file)
@@ -4,31 +4,86 @@
 
 #define THERMAL_NAME_LENGTH    20
 
-/* Adding event notification support elements */
-#define THERMAL_GENL_FAMILY_NAME                "thermal_event"
-#define THERMAL_GENL_VERSION                    0x01
-#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_grp"
-
-/* Events supported by Thermal Netlink */
-enum events {
-       THERMAL_AUX0,
-       THERMAL_AUX1,
-       THERMAL_CRITICAL,
-       THERMAL_DEV_FAULT,
+enum thermal_device_mode {
+       THERMAL_DEVICE_DISABLED = 0,
+       THERMAL_DEVICE_ENABLED,
+};
+
+enum thermal_trip_type {
+       THERMAL_TRIP_ACTIVE = 0,
+       THERMAL_TRIP_PASSIVE,
+       THERMAL_TRIP_HOT,
+       THERMAL_TRIP_CRITICAL,
 };
 
-/* attributes of thermal_genl_family */
-enum {
+/* Adding event notification support elements */
+#define THERMAL_GENL_FAMILY_NAME               "thermal"
+#define THERMAL_GENL_VERSION                   0x01
+#define THERMAL_GENL_SAMPLING_GROUP_NAME       "sampling"
+#define THERMAL_GENL_EVENT_GROUP_NAME          "event"
+
+/* Attributes of thermal_genl_family */
+enum thermal_genl_attr {
        THERMAL_GENL_ATTR_UNSPEC,
-       THERMAL_GENL_ATTR_EVENT,
+       THERMAL_GENL_ATTR_TZ,
+       THERMAL_GENL_ATTR_TZ_ID,
+       THERMAL_GENL_ATTR_TZ_TEMP,
+       THERMAL_GENL_ATTR_TZ_TRIP,
+       THERMAL_GENL_ATTR_TZ_TRIP_ID,
+       THERMAL_GENL_ATTR_TZ_TRIP_TYPE,
+       THERMAL_GENL_ATTR_TZ_TRIP_TEMP,
+       THERMAL_GENL_ATTR_TZ_TRIP_HYST,
+       THERMAL_GENL_ATTR_TZ_MODE,
+       THERMAL_GENL_ATTR_TZ_NAME,
+       THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT,
+       THERMAL_GENL_ATTR_TZ_GOV,
+       THERMAL_GENL_ATTR_TZ_GOV_NAME,
+       THERMAL_GENL_ATTR_CDEV,
+       THERMAL_GENL_ATTR_CDEV_ID,
+       THERMAL_GENL_ATTR_CDEV_CUR_STATE,
+       THERMAL_GENL_ATTR_CDEV_MAX_STATE,
+       THERMAL_GENL_ATTR_CDEV_NAME,
+       THERMAL_GENL_ATTR_GOV_NAME,
+
        __THERMAL_GENL_ATTR_MAX,
 };
 #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
 
-/* commands supported by the thermal_genl_family */
-enum {
+enum thermal_genl_sampling {
+       THERMAL_GENL_SAMPLING_TEMP,
+       __THERMAL_GENL_SAMPLING_MAX,
+};
+#define THERMAL_GENL_SAMPLING_MAX (__THERMAL_GENL_SAMPLING_MAX - 1)
+
+/* Events of thermal_genl_family */
+enum thermal_genl_event {
+       THERMAL_GENL_EVENT_UNSPEC,
+       THERMAL_GENL_EVENT_TZ_CREATE,           /* Thermal zone creation */
+       THERMAL_GENL_EVENT_TZ_DELETE,           /* Thermal zone deletion */
+       THERMAL_GENL_EVENT_TZ_DISABLE,          /* Thermal zone disabed */
+       THERMAL_GENL_EVENT_TZ_ENABLE,           /* Thermal zone enabled */
+       THERMAL_GENL_EVENT_TZ_TRIP_UP,          /* Trip point crossed the way up */
+       THERMAL_GENL_EVENT_TZ_TRIP_DOWN,        /* Trip point crossed the way down */
+       THERMAL_GENL_EVENT_TZ_TRIP_CHANGE,      /* Trip point changed */
+       THERMAL_GENL_EVENT_TZ_TRIP_ADD,         /* Trip point added */
+       THERMAL_GENL_EVENT_TZ_TRIP_DELETE,      /* Trip point deleted */
+       THERMAL_GENL_EVENT_CDEV_ADD,            /* Cdev bound to the thermal zone */
+       THERMAL_GENL_EVENT_CDEV_DELETE,         /* Cdev unbound */
+       THERMAL_GENL_EVENT_CDEV_STATE_UPDATE,   /* Cdev state updated */
+       THERMAL_GENL_EVENT_TZ_GOV_CHANGE,       /* Governor policy changed  */
+       __THERMAL_GENL_EVENT_MAX,
+};
+#define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1)
+
+/* Commands supported by the thermal_genl_family */
+enum thermal_genl_cmd {
        THERMAL_GENL_CMD_UNSPEC,
-       THERMAL_GENL_CMD_EVENT,
+       THERMAL_GENL_CMD_TZ_GET_ID,     /* List of thermal zones id */
+       THERMAL_GENL_CMD_TZ_GET_TRIP,   /* List of thermal trips */
+       THERMAL_GENL_CMD_TZ_GET_TEMP,   /* Get the thermal zone temperature */
+       THERMAL_GENL_CMD_TZ_GET_GOV,    /* Get the thermal zone governor */
+       THERMAL_GENL_CMD_TZ_GET_MODE,   /* Get the thermal zone mode */
+       THERMAL_GENL_CMD_CDEV_GET,      /* List of cdev id */
        __THERMAL_GENL_CMD_MAX,
 };
 #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
index 9395ee8a868dbedba93547cb7d948c53b21ec9cb..1eb65a7a27fdf301b97cc3f15d27fb35d3c02b93 100644 (file)
@@ -1192,7 +1192,7 @@ problem:
        panic("GENL: Cannot register controller: %d\n", err);
 }
 
-subsys_initcall(genl_init);
+core_initcall(genl_init);
 
 static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
                         gfp_t flags)