aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-12 14:05:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-12 14:05:23 -0400
commit2d2474a194652f55c7af51068db3c1b851f16711 (patch)
tree82d197a2f5eb6a38979c61c27b45fe332a87a610
parent084165a3f8c8a88c83bdfa3941f897ae0f020211 (diff)
parent43720df96023b762843e7ddcc319fc99989ba3c2 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal managament updates from Zhang Rui: - Enhance thermal "userspace" governor to export the reason when a thermal event is triggered and delivered to user space. From Srinivas Pandruvada - Introduce a single TSENS thermal driver for the different versions of the TSENS IP that exist, on different qcom msm/apq SoCs'. Support for msm8916, msm8960, msm8974 and msm8996 families is also added. From Rajendra Nayak - Introduce hardware-tracked trip points support to the device tree thermal sensor framework. The framework supports an arbitrary number of trip points. Whenever the current temperature is changed, the trip points immediately below and above the current temperature are found, driver callback is invoked to program the hardware to get notified when either of the two trip points are triggered. Hardware-tracked trip points support for rockchip thermal driver is also added at the same time. From Sascha Hauer, Caesar Wang - Introduce a new thermal driver, which enables TMU (Thermal Monitor Unit) on QorIQ platform. From Jia Hongtao - Introduce a new thermal driver for Maxim MAX77620. From Laxman Dewangan - Introduce a new thermal driver for Intel platforms using WhiskeyCove PMIC. From Bin Gao - Add mt2701 chip support to MTK thermal driver. From Dawei Chien - Enhance Tegra thermal driver to enable soctherm node and set "critical", "hot" trips, for Tegra124, Tegra132, Tegra210. From Wei Ni - Add resume support for tango thermal driver. From Marc Gonzalez - several small fixes and improvements for rockchip, qcom, imx, rcar, mtk thermal drivers and thermal core code. From Caesar Wang, Keerthy, Rocky Hao, Wei Yongjun, Peter Robinson, Bui Duc Phuc, Axel Lin, Hugh Kang * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (48 commits) thermal: int3403: Process trip change notification thermal: int340x: New Interface to read trip and notify thermal: user_space gov: Add additional information in uevent thermal: Enhance thermal_zone_device_update for events arm64: tegra: set hot trips for Tegra210 arm64: tegra: set critical trips for Tegra210 arm64: tegra: add soctherm node for Tegra210 arm64: tegra: set hot trips for Tegra132 arm64: tegra: set critical trips for Tegra132 arm64: tegra: use tegra132-soctherm for Tegra132 arm: tegra: set hot trips for Tegra124 arm: tegra: set critical trips for Tegra124 thermal: tegra: add hw-throttle for Tegra132 thermal: tegra: add hw-throttle function of: Add bindings of hw throttle for Tegra soctherm thermal: mtk_thermal: Check return value of devm_thermal_zone_of_sensor_register thermal: Add Mediatek thermal driver for mt2701. dt-bindings: thermal: Add binding document for Mediatek thermal controller thermal: max77620: Add thermal driver for reporting junction temp thermal: max77620: Add DT binding doc for thermal driver ...
-rw-r--r--Documentation/devicetree/bindings/thermal/max77620_thermal.txt70
-rw-r--r--Documentation/devicetree/bindings/thermal/mediatek-thermal.txt4
-rw-r--r--Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt121
-rw-r--r--Documentation/devicetree/bindings/thermal/qcom-tsens.txt21
-rw-r--r--Documentation/thermal/sysfs-api.txt19
-rw-r--r--arch/arm/boot/dts/tegra124-jetson-tk1.dts18
-rw-r--r--arch/arm/boot/dts/tegra124.dtsi83
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra132.dtsi119
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra210.dtsi127
-rw-r--r--drivers/acpi/thermal.c3
-rw-r--r--drivers/platform/x86/acerhdf.c2
-rw-r--r--drivers/regulator/max8973-regulator.c3
-rw-r--r--drivers/thermal/Kconfig37
-rw-r--r--drivers/thermal/Makefile4
-rw-r--r--drivers/thermal/cpu_cooling.c2
-rw-r--r--drivers/thermal/db8500_thermal.c2
-rw-r--r--drivers/thermal/devfreq_cooling.c2
-rw-r--r--drivers/thermal/gov_bang_bang.c2
-rw-r--r--drivers/thermal/hisi_thermal.c3
-rw-r--r--drivers/thermal/imx_thermal.c4
-rw-r--r--drivers/thermal/int340x_thermal/int3402_thermal.c3
-rw-r--r--drivers/thermal/int340x_thermal/int3403_thermal.c9
-rw-r--r--drivers/thermal/int340x_thermal/int340x_thermal_zone.c60
-rw-r--r--drivers/thermal/int340x_thermal/int340x_thermal_zone.h6
-rw-r--r--drivers/thermal/int340x_thermal/processor_thermal_device.c3
-rw-r--r--drivers/thermal/intel_bxt_pmic_thermal.c300
-rw-r--r--drivers/thermal/intel_soc_dts_iosf.c3
-rw-r--r--drivers/thermal/max77620_thermal.c166
-rw-r--r--drivers/thermal/mtk_thermal.c226
-rw-r--r--drivers/thermal/of-thermal.c46
-rw-r--r--drivers/thermal/qcom-spmi-temp-alarm.c2
-rw-r--r--drivers/thermal/qcom/Kconfig11
-rw-r--r--drivers/thermal/qcom/Makefile2
-rw-r--r--drivers/thermal/qcom/tsens-8916.c113
-rw-r--r--drivers/thermal/qcom/tsens-8960.c292
-rw-r--r--drivers/thermal/qcom/tsens-8974.c244
-rw-r--r--drivers/thermal/qcom/tsens-8996.c84
-rw-r--r--drivers/thermal/qcom/tsens-common.c141
-rw-r--r--drivers/thermal/qcom/tsens.c200
-rw-r--r--drivers/thermal/qcom/tsens.h94
-rw-r--r--drivers/thermal/qoriq_thermal.c328
-rw-r--r--drivers/thermal/rcar_thermal.c26
-rw-r--r--drivers/thermal/rockchip_thermal.c107
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c2
-rw-r--r--drivers/thermal/st/st_thermal_memmap.c3
-rw-r--r--drivers/thermal/tango_thermal.c19
-rw-r--r--drivers/thermal/tegra/soctherm.c842
-rw-r--r--drivers/thermal/tegra/soctherm.h10
-rw-r--r--drivers/thermal/tegra/tegra124-soctherm.c18
-rw-r--r--drivers/thermal/tegra/tegra132-soctherm.c18
-rw-r--r--drivers/thermal/tegra/tegra210-soctherm.c18
-rw-r--r--drivers/thermal/thermal_core.c106
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal-common.c29
-rw-r--r--drivers/thermal/user_space.c15
-rw-r--r--drivers/thermal/x86_pkg_temp_thermal.c3
-rw-r--r--include/dt-bindings/thermal/tegra124-soctherm.h5
-rw-r--r--include/linux/thermal.h43
57 files changed, 4021 insertions, 222 deletions
diff --git a/Documentation/devicetree/bindings/thermal/max77620_thermal.txt b/Documentation/devicetree/bindings/thermal/max77620_thermal.txt
new file mode 100644
index 000000000000..323a3b3822aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/max77620_thermal.txt
@@ -0,0 +1,70 @@
1Thermal driver for MAX77620 Power management IC from Maxim Semiconductor.
2
3Maxim Semiconductor MAX77620 supports alarm interrupts when its
4die temperature crosses 120C and 140C. These threshold temperatures
5are not configurable. Device does not provide the real temperature
6of die other than just indicating whether temperature is above or
7below threshold level.
8
9Required properties:
10-------------------
11#thermal-sensor-cells: Please refer <devicetree/bindings/thermal/thermal.txt>
12 for more details.
13 The value must be 0.
14
15For more details, please refer generic thermal DT binding document
16<devicetree/bindings/thermal/thermal.txt>.
17
18Please refer <devicetree/bindings/mfd/max77620.txt> for mfd DT binding
19document for the MAX77620.
20
21Example:
22--------
23#include <dt-bindings/mfd/max77620.h>
24#include <dt-bindings/thermal/thermal.h>
25...
26
27i2c@7000d000 {
28 spmic: max77620@3c {
29 compatible = "maxim,max77620";
30 :::::
31 #thermal-sensor-cells = <0>;
32 :::
33 };
34};
35
36cool_dev: cool-dev {
37 compatible = "cooling-dev";
38 #cooling-cells = <2>;
39};
40
41thermal-zones {
42 PMIC-Die {
43 polling-delay = <0>;
44 polling-delay-passive = <0>;
45 thermal-sensors = <&spmic>;
46
47 trips {
48 pmic_die_warn_temp_thresh: hot-die {
49 temperature = <120000>;
50 type = "hot";
51 hysteresis = <0>;
52 };
53
54 pmic_die_cirt_temp_thresh: cirtical-die {
55 temperature = <140000>;
56 type = "critical";
57 hysteresis = <0>;
58 };
59 };
60
61 cooling-maps {
62 map0 {
63 trip = <&pmic_die_warn_temp_thresh>;
64 cooling-device = <&cool_dev THERMAL_NO_LIMIT
65 THERMAL_NO_LIMIT>;
66 contribution = <100>;
67 };
68 };
69 };
70};
diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
index 81f9a512bc2a..e2f494d74d8a 100644
--- a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
@@ -8,7 +8,9 @@ apmixedsys register space via AHB bus accesses, so a phandle to the APMIXEDSYS
8is also needed. 8is also needed.
9 9
10Required properties: 10Required properties:
11- compatible: "mediatek,mt8173-thermal" 11- compatible:
12 - "mediatek,mt8173-thermal" : For MT8173 family of SoCs
13 - "mediatek,mt2701-thermal" : For MT2701 family of SoCs
12- reg: Address range of the thermal controller 14- reg: Address range of the thermal controller
13- interrupts: IRQ for the thermal controller 15- interrupts: IRQ for the thermal controller
14- clocks, clock-names: Clocks needed for the thermal controller. required 16- clocks, clock-names: Clocks needed for the thermal controller. required
diff --git a/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt b/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt
index edebfa0a985e..b6c0ae53d4dc 100644
--- a/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt
+++ b/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt
@@ -10,8 +10,14 @@ Required properties :
10- compatible : For Tegra124, must contain "nvidia,tegra124-soctherm". 10- compatible : For Tegra124, must contain "nvidia,tegra124-soctherm".
11 For Tegra132, must contain "nvidia,tegra132-soctherm". 11 For Tegra132, must contain "nvidia,tegra132-soctherm".
12 For Tegra210, must contain "nvidia,tegra210-soctherm". 12 For Tegra210, must contain "nvidia,tegra210-soctherm".
13- reg : Should contain 1 entry: 13- reg : Should contain at least 2 entries for each entry in reg-names:
14 - SOCTHERM register set 14 - SOCTHERM register set
15 - Tegra CAR register set: Required for Tegra124 and Tegra210.
16 - CCROC register set: Required for Tegra132.
17- reg-names : Should contain at least 2 entries:
18 - soctherm-reg
19 - car-reg
20 - ccroc-reg
15- interrupts : Defines the interrupt used by SOCTHERM 21- interrupts : Defines the interrupt used by SOCTHERM
16- clocks : Must contain an entry for each entry in clock-names. 22- clocks : Must contain an entry for each entry in clock-names.
17 See ../clocks/clock-bindings.txt for details. 23 See ../clocks/clock-bindings.txt for details.
@@ -25,17 +31,45 @@ Required properties :
25- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description 31- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description
26 of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a 32 of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a
27 list of valid values when referring to thermal sensors. 33 list of valid values when referring to thermal sensors.
34- throttle-cfgs: A sub-node which is a container of configuration for each
35 hardware throttle events. These events can be set as cooling devices.
36 * throttle events: Sub-nodes must be named as "light" or "heavy".
37 Properties:
38 - nvidia,priority: Each throttles has its own throttle settings, so the
39 SW need to set priorities for various throttle, the HW arbiter can select
40 the final throttle settings.
41 Bigger value indicates higher priority, In general, higher priority
42 translates to lower target frequency. SW needs to ensure that critical
43 thermal alarms are given higher priority, and ensure that there is
44 no race if priority of two vectors is set to the same value.
45 The range of this value is 1~100.
46 - nvidia,cpu-throt-percent: This property is for Tegra124 and Tegra210.
47 It is the throttling depth of pulse skippers, it's the percentage
48 throttling.
49 - nvidia,cpu-throt-level: This property is only for Tegra132, it is the
50 level of pulse skippers, which used to throttle clock frequencies. It
51 indicates cpu clock throttling depth, and the depth can be programmed.
52 Must set as following values:
53 TEGRA_SOCTHERM_THROT_LEVEL_LOW, TEGRA_SOCTHERM_THROT_LEVEL_MED
54 TEGRA_SOCTHERM_THROT_LEVEL_HIGH, TEGRA_SOCTHERM_THROT_LEVEL_NONE
55 - #cooling-cells: Should be 1. This cooling device only support on/off state.
56 See ./thermal.txt for a description of this property.
28 57
29Note: 58Note:
30- the "critical" type trip points will be set to SOC_THERM hardware as the 59- the "critical" type trip points will be set to SOC_THERM hardware as the
31shut down temperature. Once the temperature of this thermal zone is higher 60shut down temperature. Once the temperature of this thermal zone is higher
32than it, the system will be shutdown or reset by hardware. 61than it, the system will be shutdown or reset by hardware.
62- the "hot" type trip points will be set to SOC_THERM hardware as the throttle
63temperature. Once the the temperature of this thermal zone is higher
64than it, it will trigger the HW throttle event.
33 65
34Example : 66Example :
35 67
36 soctherm@700e2000 { 68 soctherm@700e2000 {
37 compatible = "nvidia,tegra124-soctherm"; 69 compatible = "nvidia,tegra124-soctherm";
38 reg = <0x0 0x700e2000 0x0 0x1000>; 70 reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */
71 0x0 0x60006000 0x0 0x400 /* CAR reg_base */
72 reg-names = "soctherm-reg", "car-reg";
39 interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; 73 interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
40 clocks = <&tegra_car TEGRA124_CLK_TSENSOR>, 74 clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
41 <&tegra_car TEGRA124_CLK_SOC_THERM>; 75 <&tegra_car TEGRA124_CLK_SOC_THERM>;
@@ -44,6 +78,76 @@ Example :
44 reset-names = "soctherm"; 78 reset-names = "soctherm";
45 79
46 #thermal-sensor-cells = <1>; 80 #thermal-sensor-cells = <1>;
81
82 throttle-cfgs {
83 /*
84 * When the "heavy" cooling device triggered,
85 * the HW will skip cpu clock's pulse in 85% depth
86 */
87 throttle_heavy: heavy {
88 nvidia,priority = <100>;
89 nvidia,cpu-throt-percent = <85>;
90
91 #cooling-cells = <1>;
92 };
93
94 /*
95 * When the "light" cooling device triggered,
96 * the HW will skip cpu clock's pulse in 50% depth
97 */
98 throttle_light: light {
99 nvidia,priority = <80>;
100 nvidia,cpu-throt-percent = <50>;
101
102 #cooling-cells = <1>;
103 };
104
105 /*
106 * If these two devices are triggered in same time, the HW throttle
107 * arbiter will select the highest priority as the final throttle
108 * settings to skip cpu pulse.
109 */
110 };
111 };
112
113Example: referring to Tegra132's "reg", "reg-names" and "throttle-cfgs" :
114
115 soctherm@700e2000 {
116 compatible = "nvidia,tegra132-soctherm";
117 reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */
118 0x0 0x70040000 0x0 0x200>; /* CCROC reg_base */;
119 reg-names = "soctherm-reg", "ccroc-reg";
120
121 throttle-cfgs {
122 /*
123 * When the "heavy" cooling device triggered,
124 * the HW will skip cpu clock's pulse in HIGH level
125 */
126 throttle_heavy: heavy {
127 nvidia,priority = <100>;
128 nvidia,cpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_HIGH>;
129
130 #cooling-cells = <1>;
131 };
132
133 /*
134 * When the "light" cooling device triggered,
135 * the HW will skip cpu clock's pulse in MED level
136 */
137 throttle_light: light {
138 nvidia,priority = <80>;
139 nvidia,cpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_MED>;
140
141 #cooling-cells = <1>;
142 };
143
144 /*
145 * If these two devices are triggered in same time, the HW throttle
146 * arbiter will select the highest priority as the final throttle
147 * settings to skip cpu pulse.
148 */
149
150 };
47 }; 151 };
48 152
49Example: referring to thermal sensors : 153Example: referring to thermal sensors :
@@ -62,6 +166,19 @@ Example: referring to thermal sensors :
62 hysteresis = <1000>; 166 hysteresis = <1000>;
63 type = "critical"; 167 type = "critical";
64 }; 168 };
169
170 cpu_throttle_trip: throttle-trip {
171 temperature = <100000>;
172 hysteresis = <1000>;
173 type = "hot";
174 };
175 };
176
177 cooling-maps {
178 map0 {
179 trip = <&cpu_throttle_trip>;
180 cooling-device = <&throttle_heavy 1 1>;
181 };
65 }; 182 };
66 }; 183 };
67 }; 184 };
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
new file mode 100644
index 000000000000..292ed89d900b
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
@@ -0,0 +1,21 @@
1* QCOM SoC Temperature Sensor (TSENS)
2
3Required properties:
4- compatible :
5 - "qcom,msm8916-tsens" : For 8916 Family of SoCs
6 - "qcom,msm8974-tsens" : For 8974 Family of SoCs
7 - "qcom,msm8996-tsens" : For 8996 Family of SoCs
8
9- reg: Address range of the thermal registers
10- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
11- Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify
12nvmem cells
13
14Example:
15tsens: thermal-sensor@900000 {
16 compatible = "qcom,msm8916-tsens";
17 reg = <0x4a8000 0x2000>;
18 nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
19 nvmem-cell-names = "caldata", "calsel";
20 #thermal-sensor-cells = <1>;
21 };
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index efc3f3d293c4..ef473dc7f55e 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -49,6 +49,9 @@ temperature) and throttle appropriate devices.
49 .bind: bind the thermal zone device with a thermal cooling device. 49 .bind: bind the thermal zone device with a thermal cooling device.
50 .unbind: unbind the thermal zone device with a thermal cooling device. 50 .unbind: unbind the thermal zone device with a thermal cooling device.
51 .get_temp: get the current temperature of the thermal zone. 51 .get_temp: get the current temperature of the thermal zone.
52 .set_trips: set the trip points window. Whenever the current temperature
53 is updated, the trip points immediately below and above the
54 current temperature are found.
52 .get_mode: get the current mode (enabled/disabled) of the thermal zone. 55 .get_mode: get the current mode (enabled/disabled) of the thermal zone.
53 - "enabled" means the kernel thermal management is enabled. 56 - "enabled" means the kernel thermal management is enabled.
54 - "disabled" will prevent kernel thermal driver action upon trip points 57 - "disabled" will prevent kernel thermal driver action upon trip points
@@ -95,6 +98,10 @@ temperature) and throttle appropriate devices.
95 get_temp: a pointer to a function that reads the 98 get_temp: a pointer to a function that reads the
96 sensor temperature. This is mandatory 99 sensor temperature. This is mandatory
97 callback provided by sensor driver. 100 callback provided by sensor driver.
101 set_trips: a pointer to a function that sets a
102 temperature window. When this window is
103 left the driver must inform the thermal
104 core via thermal_zone_device_update.
98 get_trend: a pointer to a function that reads the 105 get_trend: a pointer to a function that reads the
99 sensor temperature trend. 106 sensor temperature trend.
100 set_emul_temp: a pointer to a function that sets 107 set_emul_temp: a pointer to a function that sets
@@ -140,6 +147,18 @@ temperature) and throttle appropriate devices.
140 Normally this function will not need to be called and the resource 147 Normally this function will not need to be called and the resource
141 management code will ensure that the resource is freed. 148 management code will ensure that the resource is freed.
142 149
1501.1.7 int thermal_zone_get_slope(struct thermal_zone_device *tz)
151
152 This interface is used to read the slope attribute value
153 for the thermal zone device, which might be useful for platform
154 drivers for temperature calculations.
155
1561.1.8 int thermal_zone_get_offset(struct thermal_zone_device *tz)
157
158 This interface is used to read the offset attribute value
159 for the thermal zone device, which might be useful for platform
160 drivers for temperature calculations.
161
1431.2 thermal cooling device interface 1621.2 thermal cooling device interface
1441.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name, 1631.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name,
145 void *devdata, struct thermal_cooling_device_ops *) 164 void *devdata, struct thermal_cooling_device_ops *)
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index e52b82449a79..53994f9fbbcc 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -2045,44 +2045,32 @@
2045 thermal-zones { 2045 thermal-zones {
2046 cpu { 2046 cpu {
2047 trips { 2047 trips {
2048 trip { 2048 cpu-shutdown-trip {
2049 temperature = <101000>; 2049 temperature = <101000>;
2050 hysteresis = <0>; 2050 hysteresis = <0>;
2051 type = "critical"; 2051 type = "critical";
2052 }; 2052 };
2053 }; 2053 };
2054
2055 cooling-maps {
2056 /* There are currently no cooling maps because there are no cooling devices */
2057 };
2058 }; 2054 };
2059 2055
2060 mem { 2056 mem {
2061 trips { 2057 trips {
2062 trip { 2058 mem-shutdown-trip {
2063 temperature = <101000>; 2059 temperature = <101000>;
2064 hysteresis = <0>; 2060 hysteresis = <0>;
2065 type = "critical"; 2061 type = "critical";
2066 }; 2062 };
2067 }; 2063 };
2068
2069 cooling-maps {
2070 /* There are currently no cooling maps because there are no cooling devices */
2071 };
2072 }; 2064 };
2073 2065
2074 gpu { 2066 gpu {
2075 trips { 2067 trips {
2076 trip { 2068 gpu-shutdown-trip {
2077 temperature = <101000>; 2069 temperature = <101000>;
2078 hysteresis = <0>; 2070 hysteresis = <0>;
2079 type = "critical"; 2071 type = "critical";
2080 }; 2072 };
2081 }; 2073 };
2082
2083 cooling-maps {
2084 /* There are currently no cooling maps because there are no cooling devices */
2085 };
2086 }; 2074 };
2087 }; 2075 };
2088}; 2076};
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index ea340f9de448..187a36c6d0fc 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -851,7 +851,9 @@
851 851
852 soctherm: thermal-sensor@700e2000 { 852 soctherm: thermal-sensor@700e2000 {
853 compatible = "nvidia,tegra124-soctherm"; 853 compatible = "nvidia,tegra124-soctherm";
854 reg = <0x0 0x700e2000 0x0 0x1000>; 854 reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */
855 0x0 0x60006000 0x0 0x400>; /* CAR reg_base */
856 reg-names = "soctherm-reg", "car-reg";
855 interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; 857 interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
856 clocks = <&tegra_car TEGRA124_CLK_TSENSOR>, 858 clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
857 <&tegra_car TEGRA124_CLK_SOC_THERM>; 859 <&tegra_car TEGRA124_CLK_SOC_THERM>;
@@ -859,6 +861,15 @@
859 resets = <&tegra_car 78>; 861 resets = <&tegra_car 78>;
860 reset-names = "soctherm"; 862 reset-names = "soctherm";
861 #thermal-sensor-cells = <1>; 863 #thermal-sensor-cells = <1>;
864
865 throttle-cfgs {
866 throttle_heavy: heavy {
867 nvidia,priority = <100>;
868 nvidia,cpu-throt-percent = <85>;
869
870 #cooling-cells = <2>;
871 };
872 };
862 }; 873 };
863 874
864 dfll: clock@70110000 { 875 dfll: clock@70110000 {
@@ -1154,6 +1165,26 @@
1154 1165
1155 thermal-sensors = 1166 thermal-sensors =
1156 <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>; 1167 <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
1168
1169 trips {
1170 cpu-shutdown-trip {
1171 temperature = <103000>;
1172 hysteresis = <0>;
1173 type = "critical";
1174 };
1175 cpu_throttle_trip: throttle-trip {
1176 temperature = <100000>;
1177 hysteresis = <1000>;
1178 type = "hot";
1179 };
1180 };
1181
1182 cooling-maps {
1183 map0 {
1184 trip = <&cpu_throttle_trip>;
1185 cooling-device = <&throttle_heavy 1 1>;
1186 };
1187 };
1157 }; 1188 };
1158 1189
1159 mem { 1190 mem {
@@ -1162,6 +1193,21 @@
1162 1193
1163 thermal-sensors = 1194 thermal-sensors =
1164 <&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>; 1195 <&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>;
1196
1197 trips {
1198 mem-shutdown-trip {
1199 temperature = <103000>;
1200 hysteresis = <0>;
1201 type = "critical";
1202 };
1203 };
1204
1205 cooling-maps {
1206 /*
1207 * There are currently no cooling maps,
1208 * because there are no cooling devices.
1209 */
1210 };
1165 }; 1211 };
1166 1212
1167 gpu { 1213 gpu {
@@ -1170,6 +1216,26 @@
1170 1216
1171 thermal-sensors = 1217 thermal-sensors =
1172 <&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>; 1218 <&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>;
1219
1220 trips {
1221 gpu-shutdown-trip {
1222 temperature = <101000>;
1223 hysteresis = <0>;
1224 type = "critical";
1225 };
1226 gpu_throttle_trip: throttle-trip {
1227 temperature = <99000>;
1228 hysteresis = <1000>;
1229 type = "hot";
1230 };
1231 };
1232
1233 cooling-maps {
1234 map0 {
1235 trip = <&gpu_throttle_trip>;
1236 cooling-device = <&throttle_heavy 1 1>;
1237 };
1238 };
1173 }; 1239 };
1174 1240
1175 pllx { 1241 pllx {
@@ -1178,6 +1244,21 @@
1178 1244
1179 thermal-sensors = 1245 thermal-sensors =
1180 <&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>; 1246 <&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>;
1247
1248 trips {
1249 pllx-shutdown-trip {
1250 temperature = <103000>;
1251 hysteresis = <0>;
1252 type = "critical";
1253 };
1254 };
1255
1256 cooling-maps {
1257 /*
1258 * There are currently no cooling maps,
1259 * because there are no cooling devices.
1260 */
1261 };
1181 }; 1262 };
1182 }; 1263 };
1183 1264
diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
index 2013f8916084..3f3a46a4bd01 100644
--- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
@@ -4,6 +4,7 @@
4#include <dt-bindings/pinctrl/pinctrl-tegra.h> 4#include <dt-bindings/pinctrl/pinctrl-tegra.h>
5#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> 5#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
6#include <dt-bindings/interrupt-controller/arm-gic.h> 6#include <dt-bindings/interrupt-controller/arm-gic.h>
7#include <dt-bindings/thermal/tegra124-soctherm.h>
7 8
8/ { 9/ {
9 compatible = "nvidia,tegra132", "nvidia,tegra124"; 10 compatible = "nvidia,tegra132", "nvidia,tegra124";
@@ -727,8 +728,10 @@
727 }; 728 };
728 729
729 soctherm: thermal-sensor@700e2000 { 730 soctherm: thermal-sensor@700e2000 {
730 compatible = "nvidia,tegra124-soctherm"; 731 compatible = "nvidia,tegra132-soctherm";
731 reg = <0x0 0x700e2000 0x0 0x1000>; 732 reg = <0x0 0x700e2000 0x0 0x600 /* 0: SOC_THERM reg_base */
733 0x0 0x70040000 0x0 0x200>; /* 2: CCROC reg_base */
734 reg-names = "soctherm-reg", "ccroc-reg";
732 interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; 735 interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
733 clocks = <&tegra_car TEGRA124_CLK_TSENSOR>, 736 clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
734 <&tegra_car TEGRA124_CLK_SOC_THERM>; 737 <&tegra_car TEGRA124_CLK_SOC_THERM>;
@@ -736,6 +739,118 @@
736 resets = <&tegra_car 78>; 739 resets = <&tegra_car 78>;
737 reset-names = "soctherm"; 740 reset-names = "soctherm";
738 #thermal-sensor-cells = <1>; 741 #thermal-sensor-cells = <1>;
742
743 throttle-cfgs {
744 throttle_heavy: heavy {
745 nvidia,priority = <100>;
746 nvidia,cpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_HIGH>;
747
748 #cooling-cells = <2>;
749 };
750 };
751 };
752
753 thermal-zones {
754 cpu {
755 polling-delay-passive = <1000>;
756 polling-delay = <0>;
757
758 thermal-sensors =
759 <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
760
761 trips {
762 cpu_shutdown_trip {
763 temperature = <105000>;
764 hysteresis = <1000>;
765 type = "critical";
766 };
767
768 cpu_throttle_trip: throttle-trip {
769 temperature = <102000>;
770 hysteresis = <1000>;
771 type = "hot";
772 };
773 };
774
775 cooling-maps {
776 map0 {
777 trip = <&cpu_throttle_trip>;
778 cooling-device = <&throttle_heavy 1 1>;
779 };
780 };
781 };
782 mem {
783 polling-delay-passive = <0>;
784 polling-delay = <0>;
785
786 thermal-sensors =
787 <&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>;
788
789 trips {
790 mem_shutdown_trip {
791 temperature = <101000>;
792 hysteresis = <1000>;
793 type = "critical";
794 };
795 };
796
797 cooling-maps {
798 /*
799 * There are currently no cooling maps,
800 * because there are no cooling devices.
801 */
802 };
803 };
804 gpu {
805 polling-delay-passive = <1000>;
806 polling-delay = <0>;
807
808 thermal-sensors =
809 <&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>;
810
811 trips {
812 gpu_shutdown_trip {
813 temperature = <101000>;
814 hysteresis = <1000>;
815 type = "critical";
816 };
817
818 gpu_throttle_trip: throttle-trip {
819 temperature = <99000>;
820 hysteresis = <1000>;
821 type = "hot";
822 };
823 };
824
825 cooling-maps {
826 map0 {
827 trip = <&gpu_throttle_trip>;
828 cooling-device = <&throttle_heavy 1 1>;
829 };
830 };
831 };
832 pllx {
833 polling-delay-passive = <0>;
834 polling-delay = <0>;
835
836 thermal-sensors =
837 <&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>;
838
839 trips {
840 pllx_shutdown_trip {
841 temperature = <105000>;
842 hysteresis = <1000>;
843 type = "critical";
844 };
845 };
846
847 cooling-maps {
848 /*
849 * There are currently no cooling maps,
850 * because there are no cooling devices.
851 */
852 };
853 };
739 }; 854 };
740 855
741 ahub@70300000 { 856 ahub@70300000 {
diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index f6739797150a..46045fe719da 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -3,6 +3,7 @@
3#include <dt-bindings/memory/tegra210-mc.h> 3#include <dt-bindings/memory/tegra210-mc.h>
4#include <dt-bindings/pinctrl/pinctrl-tegra.h> 4#include <dt-bindings/pinctrl/pinctrl-tegra.h>
5#include <dt-bindings/interrupt-controller/arm-gic.h> 5#include <dt-bindings/interrupt-controller/arm-gic.h>
6#include <dt-bindings/thermal/tegra124-soctherm.h>
6 7
7/ { 8/ {
8 compatible = "nvidia,tegra210"; 9 compatible = "nvidia,tegra210";
@@ -1159,4 +1160,130 @@
1159 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; 1160 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
1160 interrupt-parent = <&gic>; 1161 interrupt-parent = <&gic>;
1161 }; 1162 };
1163
1164 soctherm: thermal-sensor@700e2000 {
1165 compatible = "nvidia,tegra210-soctherm";
1166 reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */
1167 0x0 0x60006000 0x0 0x400>; /* CAR reg_base */
1168 reg-names = "soctherm-reg", "car-reg";
1169 interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
1170 clocks = <&tegra_car TEGRA210_CLK_TSENSOR>,
1171 <&tegra_car TEGRA210_CLK_SOC_THERM>;
1172 clock-names = "tsensor", "soctherm";
1173 resets = <&tegra_car 78>;
1174 reset-names = "soctherm";
1175 #thermal-sensor-cells = <1>;
1176
1177 throttle-cfgs {
1178 throttle_heavy: heavy {
1179 nvidia,priority = <100>;
1180 nvidia,cpu-throt-percent = <85>;
1181
1182 #cooling-cells = <2>;
1183 };
1184 };
1185 };
1186
1187 thermal-zones {
1188 cpu {
1189 polling-delay-passive = <1000>;
1190 polling-delay = <0>;
1191
1192 thermal-sensors =
1193 <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
1194
1195 trips {
1196 cpu-shutdown-trip {
1197 temperature = <102500>;
1198 hysteresis = <0>;
1199 type = "critical";
1200 };
1201
1202 cpu_throttle_trip: throttle-trip {
1203 temperature = <98500>;
1204 hysteresis = <1000>;
1205 type = "hot";
1206 };
1207 };
1208
1209 cooling-maps {
1210 map0 {
1211 trip = <&cpu_throttle_trip>;
1212 cooling-device = <&throttle_heavy 1 1>;
1213 };
1214 };
1215 };
1216 mem {
1217 polling-delay-passive = <0>;
1218 polling-delay = <0>;
1219
1220 thermal-sensors =
1221 <&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>;
1222
1223 trips {
1224 mem-shutdown-trip {
1225 temperature = <103000>;
1226 hysteresis = <0>;
1227 type = "critical";
1228 };
1229 };
1230
1231 cooling-maps {
1232 /*
1233 * There are currently no cooling maps,
1234 * because there are no cooling devices.
1235 */
1236 };
1237 };
1238 gpu {
1239 polling-delay-passive = <1000>;
1240 polling-delay = <0>;
1241
1242 thermal-sensors =
1243 <&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>;
1244
1245 trips {
1246 gpu-shutdown-trip {
1247 temperature = <103000>;
1248 hysteresis = <0>;
1249 type = "critical";
1250 };
1251
1252 gpu_throttle_trip: throttle-trip {
1253 temperature = <100000>;
1254 hysteresis = <1000>;
1255 type = "hot";
1256 };
1257 };
1258
1259 cooling-maps {
1260 map0 {
1261 trip = <&gpu_throttle_trip>;
1262 cooling-device = <&throttle_heavy 1 1>;
1263 };
1264 };
1265 };
1266 pllx {
1267 polling-delay-passive = <0>;
1268 polling-delay = <0>;
1269
1270 thermal-sensors =
1271 <&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>;
1272
1273 trips {
1274 pllx-shutdown-trip {
1275 temperature = <103000>;
1276 hysteresis = <0>;
1277 type = "critical";
1278 };
1279 };
1280
1281 cooling-maps {
1282 /*
1283 * There are currently no cooling maps,
1284 * because there are no cooling devices.
1285 */
1286 };
1287 };
1288 };
1162}; 1289};
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index f4ebe39539af..35e8fbca10ad 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -520,7 +520,8 @@ static void acpi_thermal_check(void *data)
520 if (!tz->tz_enabled) 520 if (!tz->tz_enabled)
521 return; 521 return;
522 522
523 thermal_zone_device_update(tz->thermal_zone); 523 thermal_zone_device_update(tz->thermal_zone,
524 THERMAL_EVENT_UNSPECIFIED);
524} 525}
525 526
526/* sys I/F for generic thermal sysfs support */ 527/* sys I/F for generic thermal sysfs support */
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 460fa6708bfc..2acdb0d6ea89 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -405,7 +405,7 @@ static inline void acerhdf_enable_kernelmode(void)
405 kernelmode = 1; 405 kernelmode = 1;
406 406
407 thz_dev->polling_delay = interval*1000; 407 thz_dev->polling_delay = interval*1000;
408 thermal_zone_device_update(thz_dev); 408 thermal_zone_device_update(thz_dev, THERMAL_EVENT_UNSPECIFIED);
409 pr_notice("kernel mode fan control ON\n"); 409 pr_notice("kernel mode fan control ON\n");
410} 410}
411 411
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index 3958f50c5975..e0c747aa9f85 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -495,7 +495,8 @@ static irqreturn_t max8973_thermal_irq(int irq, void *data)
495{ 495{
496 struct max8973_chip *mchip = data; 496 struct max8973_chip *mchip = data;
497 497
498 thermal_zone_device_update(mchip->tz_device); 498 thermal_zone_device_update(mchip->tz_device,
499 THERMAL_EVENT_UNSPECIFIED);
499 500
500 return IRQ_HANDLED; 501 return IRQ_HANDLED;
501} 502}
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 2d702ca6556f..a13541bdc726 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -186,7 +186,7 @@ config HISI_THERMAL
186 186
187config IMX_THERMAL 187config IMX_THERMAL
188 tristate "Temperature sensor driver for Freescale i.MX SoCs" 188 tristate "Temperature sensor driver for Freescale i.MX SoCs"
189 depends on CPU_THERMAL 189 depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
190 depends on MFD_SYSCON 190 depends on MFD_SYSCON
191 depends on OF 191 depends on OF
192 help 192 help
@@ -195,6 +195,26 @@ config IMX_THERMAL
195 cpufreq is used as the cooling device to throttle CPUs when the 195 cpufreq is used as the cooling device to throttle CPUs when the
196 passive trip is crossed. 196 passive trip is crossed.
197 197
198config MAX77620_THERMAL
199 tristate "Temperature sensor driver for Maxim MAX77620 PMIC"
200 depends on MFD_MAX77620
201 depends on OF
202 help
203 Support for die junction temperature warning alarm for Maxim
204 Semiconductor PMIC MAX77620 device. Device generates two alarm
205 interrupts when PMIC die temperature cross the threshold of
206 120 degC and 140 degC.
207
208config QORIQ_THERMAL
209 tristate "QorIQ Thermal Monitoring Unit"
210 depends on THERMAL_OF
211 depends on HAS_IOMEM
212 help
213 Support for Thermal Monitoring Unit (TMU) found on QorIQ platforms.
214 It supports one critical trip point and one passive trip point. The
215 cpufreq is used as the cooling device to throttle CPUs when the
216 passive trip is crossed.
217
198config SPEAR_THERMAL 218config SPEAR_THERMAL
199 tristate "SPEAr thermal sensor driver" 219 tristate "SPEAr thermal sensor driver"
200 depends on PLAT_SPEAR || COMPILE_TEST 220 depends on PLAT_SPEAR || COMPILE_TEST
@@ -332,6 +352,16 @@ menu "ACPI INT340X thermal drivers"
332source drivers/thermal/int340x_thermal/Kconfig 352source drivers/thermal/int340x_thermal/Kconfig
333endmenu 353endmenu
334 354
355config INTEL_BXT_PMIC_THERMAL
356 tristate "Intel Broxton PMIC thermal driver"
357 depends on X86 && INTEL_SOC_PMIC && REGMAP
358 help
359 Select this driver for Intel Broxton PMIC with ADC channels monitoring
360 system temperature measurements and alerts.
361 This driver is used for monitoring the ADC channels of PMIC and handles
362 the alert trip point interrupts and notifies the thermal framework with
363 the trip point and temperature details of the zone.
364
335config INTEL_PCH_THERMAL 365config INTEL_PCH_THERMAL
336 tristate "Intel PCH Thermal Reporting Driver" 366 tristate "Intel PCH Thermal Reporting Driver"
337 depends on X86 && PCI 367 depends on X86 && PCI
@@ -399,4 +429,9 @@ config GENERIC_ADC_THERMAL
399 to this driver. This driver reports the temperature by reading ADC 429 to this driver. This driver reports the temperature by reading ADC
400 channel and converts it to temperature based on lookup table. 430 channel and converts it to temperature based on lookup table.
401 431
432menu "Qualcomm thermal drivers"
433depends on (ARCH_QCOM && OF) || COMPILE_TEST
434source "drivers/thermal/qcom/Kconfig"
435endmenu
436
402endif 437endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 10b07c14f8a9..c92eb22a41ff 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -37,6 +37,8 @@ obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
37obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o 37obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
38obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o 38obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o
39obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o 39obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
40obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
41obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
40obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o 42obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
41obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 43obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
42obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o 44obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
@@ -45,8 +47,10 @@ obj-$(CONFIG_INTEL_SOC_DTS_THERMAL) += intel_soc_dts_thermal.o
45obj-$(CONFIG_INTEL_QUARK_DTS_THERMAL) += intel_quark_dts_thermal.o 47obj-$(CONFIG_INTEL_QUARK_DTS_THERMAL) += intel_quark_dts_thermal.o
46obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ 48obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
47obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/ 49obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
50obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
48obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o 51obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
49obj-$(CONFIG_ST_THERMAL) += st/ 52obj-$(CONFIG_ST_THERMAL) += st/
53obj-$(CONFIG_QCOM_TSENS) += qcom/
50obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/ 54obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
51obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o 55obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
52obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o 56obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index a32b41783b77..9ce0e9eef923 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -74,7 +74,7 @@ struct power_table {
74 * cpufreq frequencies. 74 * cpufreq frequencies.
75 * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device. 75 * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device.
76 * @node: list_head to link all cpufreq_cooling_device together. 76 * @node: list_head to link all cpufreq_cooling_device together.
77 * @last_load: load measured by the latest call to cpufreq_get_actual_power() 77 * @last_load: load measured by the latest call to cpufreq_get_requested_power()
78 * @time_in_idle: previous reading of the absolute time that this cpu was idle 78 * @time_in_idle: previous reading of the absolute time that this cpu was idle
79 * @time_in_idle_timestamp: wall time of the last invocation of 79 * @time_in_idle_timestamp: wall time of the last invocation of
80 * get_cpu_idle_time_us() 80 * get_cpu_idle_time_us()
diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
index 652acd8fbe48..e776cea80cfc 100644
--- a/drivers/thermal/db8500_thermal.c
+++ b/drivers/thermal/db8500_thermal.c
@@ -306,7 +306,7 @@ static void db8500_thermal_work(struct work_struct *work)
306 if (cur_mode == THERMAL_DEVICE_DISABLED) 306 if (cur_mode == THERMAL_DEVICE_DISABLED)
307 return; 307 return;
308 308
309 thermal_zone_device_update(pzone->therm_dev); 309 thermal_zone_device_update(pzone->therm_dev, THERMAL_EVENT_UNSPECIFIED);
310 dev_dbg(&pzone->therm_dev->device, "thermal work finished.\n"); 310 dev_dbg(&pzone->therm_dev->device, "thermal work finished.\n");
311} 311}
312 312
diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c
index 01f0015f80dc..81631b110e17 100644
--- a/drivers/thermal/devfreq_cooling.c
+++ b/drivers/thermal/devfreq_cooling.c
@@ -312,7 +312,7 @@ static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev,
312 unsigned long freq; 312 unsigned long freq;
313 u32 static_power; 313 u32 static_power;
314 314
315 if (state < 0 || state >= dfc->freq_table_size) 315 if (state >= dfc->freq_table_size)
316 return -EINVAL; 316 return -EINVAL;
317 317
318 freq = dfc->freq_table[state]; 318 freq = dfc->freq_table[state];
diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c
index bb118a152cbb..fc5e5057f0de 100644
--- a/drivers/thermal/gov_bang_bang.c
+++ b/drivers/thermal/gov_bang_bang.c
@@ -65,7 +65,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
65 if (instance->target == 0 && tz->temperature >= trip_temp) 65 if (instance->target == 0 && tz->temperature >= trip_temp)
66 instance->target = 1; 66 instance->target = 1;
67 else if (instance->target == 1 && 67 else if (instance->target == 1 &&
68 tz->temperature < trip_temp - trip_hyst) 68 tz->temperature <= trip_temp - trip_hyst)
69 instance->target = 0; 69 instance->target = 0;
70 70
71 dev_dbg(&instance->cdev->device, "target=%d\n", 71 dev_dbg(&instance->cdev->device, "target=%d\n",
diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c
index 97fad8f51e1c..f6429666a1cf 100644
--- a/drivers/thermal/hisi_thermal.c
+++ b/drivers/thermal/hisi_thermal.c
@@ -237,7 +237,8 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev)
237 if (!data->sensors[i].tzd) 237 if (!data->sensors[i].tzd)
238 continue; 238 continue;
239 239
240 thermal_zone_device_update(data->sensors[i].tzd); 240 thermal_zone_device_update(data->sensors[i].tzd,
241 THERMAL_EVENT_UNSPECIFIED);
241 } 242 }
242 243
243 return IRQ_HANDLED; 244 return IRQ_HANDLED;
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index e473548b5d28..06912f0602b7 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -246,7 +246,7 @@ static int imx_set_mode(struct thermal_zone_device *tz,
246 } 246 }
247 247
248 data->mode = mode; 248 data->mode = mode;
249 thermal_zone_device_update(tz); 249 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
250 250
251 return 0; 251 return 0;
252} 252}
@@ -457,7 +457,7 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
457 dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n", 457 dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n",
458 data->alarm_temp / 1000); 458 data->alarm_temp / 1000);
459 459
460 thermal_zone_device_update(data->tz); 460 thermal_zone_device_update(data->tz, THERMAL_EVENT_UNSPECIFIED);
461 461
462 return IRQ_HANDLED; 462 return IRQ_HANDLED;
463} 463}
diff --git a/drivers/thermal/int340x_thermal/int3402_thermal.c b/drivers/thermal/int340x_thermal/int3402_thermal.c
index 69df3d960303..8e90b3151a42 100644
--- a/drivers/thermal/int340x_thermal/int3402_thermal.c
+++ b/drivers/thermal/int340x_thermal/int3402_thermal.c
@@ -35,7 +35,8 @@ static void int3402_notify(acpi_handle handle, u32 event, void *data)
35 case INT3402_PERF_CHANGED_EVENT: 35 case INT3402_PERF_CHANGED_EVENT:
36 break; 36 break;
37 case INT3402_THERMAL_EVENT: 37 case INT3402_THERMAL_EVENT:
38 int340x_thermal_zone_device_update(priv->int340x_zone); 38 int340x_thermal_zone_device_update(priv->int340x_zone,
39 THERMAL_TRIP_VIOLATED);
39 break; 40 break;
40 default: 41 default:
41 break; 42 break;
diff --git a/drivers/thermal/int340x_thermal/int3403_thermal.c b/drivers/thermal/int340x_thermal/int3403_thermal.c
index 50a7a08e3a15..c4890c9437eb 100644
--- a/drivers/thermal/int340x_thermal/int3403_thermal.c
+++ b/drivers/thermal/int340x_thermal/int3403_thermal.c
@@ -25,6 +25,7 @@
25#define INT3403_TYPE_CHARGER 0x0B 25#define INT3403_TYPE_CHARGER 0x0B
26#define INT3403_TYPE_BATTERY 0x0C 26#define INT3403_TYPE_BATTERY 0x0C
27#define INT3403_PERF_CHANGED_EVENT 0x80 27#define INT3403_PERF_CHANGED_EVENT 0x80
28#define INT3403_PERF_TRIP_POINT_CHANGED 0x81
28#define INT3403_THERMAL_EVENT 0x90 29#define INT3403_THERMAL_EVENT 0x90
29 30
30/* Preserved structure for future expandbility */ 31/* Preserved structure for future expandbility */
@@ -72,7 +73,13 @@ static void int3403_notify(acpi_handle handle,
72 case INT3403_PERF_CHANGED_EVENT: 73 case INT3403_PERF_CHANGED_EVENT:
73 break; 74 break;
74 case INT3403_THERMAL_EVENT: 75 case INT3403_THERMAL_EVENT:
75 int340x_thermal_zone_device_update(obj->int340x_zone); 76 int340x_thermal_zone_device_update(obj->int340x_zone,
77 THERMAL_TRIP_VIOLATED);
78 break;
79 case INT3403_PERF_TRIP_POINT_CHANGED:
80 int340x_thermal_read_trips(obj->int340x_zone);
81 int340x_thermal_zone_device_update(obj->int340x_zone,
82 THERMAL_TRIP_CHANGED);
76 break; 83 break;
77 default: 84 default:
78 dev_err(&priv->pdev->dev, "Unsupported event [0x%x]\n", event); 85 dev_err(&priv->pdev->dev, "Unsupported event [0x%x]\n", event);
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
index b9b2666aa94c..145a5c53ff5c 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
@@ -177,6 +177,42 @@ static int int340x_thermal_get_trip_config(acpi_handle handle, char *name,
177 return 0; 177 return 0;
178} 178}
179 179
180int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone)
181{
182 int trip_cnt = int34x_zone->aux_trip_nr;
183 int i;
184
185 int34x_zone->crt_trip_id = -1;
186 if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_CRT",
187 &int34x_zone->crt_temp))
188 int34x_zone->crt_trip_id = trip_cnt++;
189
190 int34x_zone->hot_trip_id = -1;
191 if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_HOT",
192 &int34x_zone->hot_temp))
193 int34x_zone->hot_trip_id = trip_cnt++;
194
195 int34x_zone->psv_trip_id = -1;
196 if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_PSV",
197 &int34x_zone->psv_temp))
198 int34x_zone->psv_trip_id = trip_cnt++;
199
200 for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
201 char name[5] = { '_', 'A', 'C', '0' + i, '\0' };
202
203 if (int340x_thermal_get_trip_config(int34x_zone->adev->handle,
204 name,
205 &int34x_zone->act_trips[i].temp))
206 break;
207
208 int34x_zone->act_trips[i].id = trip_cnt++;
209 int34x_zone->act_trips[i].valid = true;
210 }
211
212 return trip_cnt;
213}
214EXPORT_SYMBOL_GPL(int340x_thermal_read_trips);
215
180static struct thermal_zone_params int340x_thermal_params = { 216static struct thermal_zone_params int340x_thermal_params = {
181 .governor_name = "user_space", 217 .governor_name = "user_space",
182 .no_hwmon = true, 218 .no_hwmon = true,
@@ -188,7 +224,7 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
188 struct int34x_thermal_zone *int34x_thermal_zone; 224 struct int34x_thermal_zone *int34x_thermal_zone;
189 acpi_status status; 225 acpi_status status;
190 unsigned long long trip_cnt; 226 unsigned long long trip_cnt;
191 int trip_mask = 0, i; 227 int trip_mask = 0;
192 int ret; 228 int ret;
193 229
194 int34x_thermal_zone = kzalloc(sizeof(*int34x_thermal_zone), 230 int34x_thermal_zone = kzalloc(sizeof(*int34x_thermal_zone),
@@ -214,28 +250,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
214 int34x_thermal_zone->aux_trip_nr = trip_cnt; 250 int34x_thermal_zone->aux_trip_nr = trip_cnt;
215 } 251 }
216 252
217 int34x_thermal_zone->crt_trip_id = -1; 253 trip_cnt = int340x_thermal_read_trips(int34x_thermal_zone);
218 if (!int340x_thermal_get_trip_config(adev->handle, "_CRT",
219 &int34x_thermal_zone->crt_temp))
220 int34x_thermal_zone->crt_trip_id = trip_cnt++;
221 int34x_thermal_zone->hot_trip_id = -1;
222 if (!int340x_thermal_get_trip_config(adev->handle, "_HOT",
223 &int34x_thermal_zone->hot_temp))
224 int34x_thermal_zone->hot_trip_id = trip_cnt++;
225 int34x_thermal_zone->psv_trip_id = -1;
226 if (!int340x_thermal_get_trip_config(adev->handle, "_PSV",
227 &int34x_thermal_zone->psv_temp))
228 int34x_thermal_zone->psv_trip_id = trip_cnt++;
229 for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
230 char name[5] = { '_', 'A', 'C', '0' + i, '\0' };
231 254
232 if (int340x_thermal_get_trip_config(adev->handle, name,
233 &int34x_thermal_zone->act_trips[i].temp))
234 break;
235
236 int34x_thermal_zone->act_trips[i].id = trip_cnt++;
237 int34x_thermal_zone->act_trips[i].valid = true;
238 }
239 int34x_thermal_zone->lpat_table = acpi_lpat_get_conversion_table( 255 int34x_thermal_zone->lpat_table = acpi_lpat_get_conversion_table(
240 adev->handle); 256 adev->handle);
241 257
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
index aaadf724ff2e..5f3ba4775c5c 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
+++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
@@ -46,6 +46,7 @@ struct int34x_thermal_zone {
46struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *, 46struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *,
47 struct thermal_zone_device_ops *override_ops); 47 struct thermal_zone_device_ops *override_ops);
48void int340x_thermal_zone_remove(struct int34x_thermal_zone *); 48void int340x_thermal_zone_remove(struct int34x_thermal_zone *);
49int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone);
49 50
50static inline void int340x_thermal_zone_set_priv_data( 51static inline void int340x_thermal_zone_set_priv_data(
51 struct int34x_thermal_zone *tzone, void *priv_data) 52 struct int34x_thermal_zone *tzone, void *priv_data)
@@ -60,9 +61,10 @@ static inline void *int340x_thermal_zone_get_priv_data(
60} 61}
61 62
62static inline void int340x_thermal_zone_device_update( 63static inline void int340x_thermal_zone_device_update(
63 struct int34x_thermal_zone *tzone) 64 struct int34x_thermal_zone *tzone,
65 enum thermal_notify_event event)
64{ 66{
65 thermal_zone_device_update(tzone->zone); 67 thermal_zone_device_update(tzone->zone, event);
66} 68}
67 69
68#endif 70#endif
diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c
index 42c1ac057bad..ff3b36f339e3 100644
--- a/drivers/thermal/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c
@@ -258,7 +258,8 @@ static void proc_thermal_notify(acpi_handle handle, u32 event, void *data)
258 switch (event) { 258 switch (event) {
259 case PROC_POWER_CAPABILITY_CHANGED: 259 case PROC_POWER_CAPABILITY_CHANGED:
260 proc_thermal_read_ppcc(proc_priv); 260 proc_thermal_read_ppcc(proc_priv);
261 int340x_thermal_zone_device_update(proc_priv->int340x_zone); 261 int340x_thermal_zone_device_update(proc_priv->int340x_zone,
262 THERMAL_DEVICE_POWER_CAPABILITY_CHANGED);
262 break; 263 break;
263 default: 264 default:
264 dev_err(proc_priv->dev, "Unsupported event [0x%x]\n", event); 265 dev_err(proc_priv->dev, "Unsupported event [0x%x]\n", event);
diff --git a/drivers/thermal/intel_bxt_pmic_thermal.c b/drivers/thermal/intel_bxt_pmic_thermal.c
new file mode 100644
index 000000000000..0f19a393ddd8
--- /dev/null
+++ b/drivers/thermal/intel_bxt_pmic_thermal.c
@@ -0,0 +1,300 @@
1/*
2 * Intel Broxton PMIC thermal driver
3 *
4 * Copyright (C) 2016 Intel Corporation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/slab.h>
20#include <linux/delay.h>
21#include <linux/interrupt.h>
22#include <linux/device.h>
23#include <linux/thermal.h>
24#include <linux/platform_device.h>
25#include <linux/sched.h>
26#include <linux/mfd/intel_soc_pmic.h>
27
28#define BXTWC_THRM0IRQ 0x4E04
29#define BXTWC_THRM1IRQ 0x4E05
30#define BXTWC_THRM2IRQ 0x4E06
31#define BXTWC_MTHRM0IRQ 0x4E12
32#define BXTWC_MTHRM1IRQ 0x4E13
33#define BXTWC_MTHRM2IRQ 0x4E14
34#define BXTWC_STHRM0IRQ 0x4F19
35#define BXTWC_STHRM1IRQ 0x4F1A
36#define BXTWC_STHRM2IRQ 0x4F1B
37
38struct trip_config_map {
39 u16 irq_reg;
40 u16 irq_en;
41 u16 evt_stat;
42 u8 irq_mask;
43 u8 irq_en_mask;
44 u8 evt_mask;
45 u8 trip_num;
46};
47
48struct thermal_irq_map {
49 char handle[20];
50 int num_trips;
51 const struct trip_config_map *trip_config;
52};
53
54struct pmic_thermal_data {
55 const struct thermal_irq_map *maps;
56 int num_maps;
57};
58
59static const struct trip_config_map bxtwc_str0_trip_config[] = {
60 {
61 .irq_reg = BXTWC_THRM0IRQ,
62 .irq_mask = 0x01,
63 .irq_en = BXTWC_MTHRM0IRQ,
64 .irq_en_mask = 0x01,
65 .evt_stat = BXTWC_STHRM0IRQ,
66 .evt_mask = 0x01,
67 .trip_num = 0
68 },
69 {
70 .irq_reg = BXTWC_THRM0IRQ,
71 .irq_mask = 0x10,
72 .irq_en = BXTWC_MTHRM0IRQ,
73 .irq_en_mask = 0x10,
74 .evt_stat = BXTWC_STHRM0IRQ,
75 .evt_mask = 0x10,
76 .trip_num = 1
77 }
78};
79
80static const struct trip_config_map bxtwc_str1_trip_config[] = {
81 {
82 .irq_reg = BXTWC_THRM0IRQ,
83 .irq_mask = 0x02,
84 .irq_en = BXTWC_MTHRM0IRQ,
85 .irq_en_mask = 0x02,
86 .evt_stat = BXTWC_STHRM0IRQ,
87 .evt_mask = 0x02,
88 .trip_num = 0
89 },
90 {
91 .irq_reg = BXTWC_THRM0IRQ,
92 .irq_mask = 0x20,
93 .irq_en = BXTWC_MTHRM0IRQ,
94 .irq_en_mask = 0x20,
95 .evt_stat = BXTWC_STHRM0IRQ,
96 .evt_mask = 0x20,
97 .trip_num = 1
98 },
99};
100
101static const struct trip_config_map bxtwc_str2_trip_config[] = {
102 {
103 .irq_reg = BXTWC_THRM0IRQ,
104 .irq_mask = 0x04,
105 .irq_en = BXTWC_MTHRM0IRQ,
106 .irq_en_mask = 0x04,
107 .evt_stat = BXTWC_STHRM0IRQ,
108 .evt_mask = 0x04,
109 .trip_num = 0
110 },
111 {
112 .irq_reg = BXTWC_THRM0IRQ,
113 .irq_mask = 0x40,
114 .irq_en = BXTWC_MTHRM0IRQ,
115 .irq_en_mask = 0x40,
116 .evt_stat = BXTWC_STHRM0IRQ,
117 .evt_mask = 0x40,
118 .trip_num = 1
119 },
120};
121
122static const struct trip_config_map bxtwc_str3_trip_config[] = {
123 {
124 .irq_reg = BXTWC_THRM2IRQ,
125 .irq_mask = 0x10,
126 .irq_en = BXTWC_MTHRM2IRQ,
127 .irq_en_mask = 0x10,
128 .evt_stat = BXTWC_STHRM2IRQ,
129 .evt_mask = 0x10,
130 .trip_num = 0
131 },
132};
133
134static const struct thermal_irq_map bxtwc_thermal_irq_map[] = {
135 {
136 .handle = "STR0",
137 .trip_config = bxtwc_str0_trip_config,
138 .num_trips = ARRAY_SIZE(bxtwc_str0_trip_config),
139 },
140 {
141 .handle = "STR1",
142 .trip_config = bxtwc_str1_trip_config,
143 .num_trips = ARRAY_SIZE(bxtwc_str1_trip_config),
144 },
145 {
146 .handle = "STR2",
147 .trip_config = bxtwc_str2_trip_config,
148 .num_trips = ARRAY_SIZE(bxtwc_str2_trip_config),
149 },
150 {
151 .handle = "STR3",
152 .trip_config = bxtwc_str3_trip_config,
153 .num_trips = ARRAY_SIZE(bxtwc_str3_trip_config),
154 },
155};
156
157static const struct pmic_thermal_data bxtwc_thermal_data = {
158 .maps = bxtwc_thermal_irq_map,
159 .num_maps = ARRAY_SIZE(bxtwc_thermal_irq_map),
160};
161
162static irqreturn_t pmic_thermal_irq_handler(int irq, void *data)
163{
164 struct platform_device *pdev = data;
165 struct thermal_zone_device *tzd;
166 struct pmic_thermal_data *td;
167 struct intel_soc_pmic *pmic;
168 struct regmap *regmap;
169 u8 reg_val, mask, irq_stat, trip;
170 u16 reg, evt_stat_reg;
171 int i, j, ret;
172
173 pmic = dev_get_drvdata(pdev->dev.parent);
174 regmap = pmic->regmap;
175 td = (struct pmic_thermal_data *)
176 platform_get_device_id(pdev)->driver_data;
177
178 /* Resolve thermal irqs */
179 for (i = 0; i < td->num_maps; i++) {
180 for (j = 0; j < td->maps[i].num_trips; j++) {
181 reg = td->maps[i].trip_config[j].irq_reg;
182 mask = td->maps[i].trip_config[j].irq_mask;
183 /*
184 * Read the irq register to resolve whether the
185 * interrupt was triggered for this sensor
186 */
187 if (regmap_read(regmap, reg, &ret))
188 return IRQ_HANDLED;
189
190 reg_val = (u8)ret;
191 irq_stat = ((u8)ret & mask);
192
193 if (!irq_stat)
194 continue;
195
196 /*
197 * Read the status register to find out what
198 * event occurred i.e a high or a low
199 */
200 evt_stat_reg = td->maps[i].trip_config[j].evt_stat;
201 if (regmap_read(regmap, evt_stat_reg, &ret))
202 return IRQ_HANDLED;
203
204 trip = td->maps[i].trip_config[j].trip_num;
205 tzd = thermal_zone_get_zone_by_name(td->maps[i].handle);
206 if (!IS_ERR(tzd))
207 thermal_zone_device_update(tzd,
208 THERMAL_EVENT_UNSPECIFIED);
209
210 /* Clear the appropriate irq */
211 regmap_write(regmap, reg, reg_val & mask);
212 }
213 }
214
215 return IRQ_HANDLED;
216}
217
218static int pmic_thermal_probe(struct platform_device *pdev)
219{
220 struct regmap_irq_chip_data *regmap_irq_chip;
221 struct pmic_thermal_data *thermal_data;
222 int ret, irq, virq, i, j, pmic_irq_count;
223 struct intel_soc_pmic *pmic;
224 struct regmap *regmap;
225 struct device *dev;
226 u16 reg;
227 u8 mask;
228
229 dev = &pdev->dev;
230 pmic = dev_get_drvdata(pdev->dev.parent);
231 if (!pmic) {
232 dev_err(dev, "Failed to get struct intel_soc_pmic pointer\n");
233 return -ENODEV;
234 }
235
236 thermal_data = (struct pmic_thermal_data *)
237 platform_get_device_id(pdev)->driver_data;
238 if (!thermal_data) {
239 dev_err(dev, "No thermal data initialized!!\n");
240 return -ENODEV;
241 }
242
243 regmap = pmic->regmap;
244 regmap_irq_chip = pmic->irq_chip_data_level2;
245
246 pmic_irq_count = 0;
247 while ((irq = platform_get_irq(pdev, pmic_irq_count)) != -ENXIO) {
248 virq = regmap_irq_get_virq(regmap_irq_chip, irq);
249 if (virq < 0) {
250 dev_err(dev, "failed to get virq by irq %d\n", irq);
251 return virq;
252 }
253
254 ret = devm_request_threaded_irq(&pdev->dev, virq,
255 NULL, pmic_thermal_irq_handler,
256 IRQF_ONESHOT, "pmic_thermal", pdev);
257
258 if (ret) {
259 dev_err(dev, "request irq(%d) failed: %d\n", virq, ret);
260 return ret;
261 }
262 pmic_irq_count++;
263 }
264
265 /* Enable thermal interrupts */
266 for (i = 0; i < thermal_data->num_maps; i++) {
267 for (j = 0; j < thermal_data->maps[i].num_trips; j++) {
268 reg = thermal_data->maps[i].trip_config[j].irq_en;
269 mask = thermal_data->maps[i].trip_config[j].irq_en_mask;
270 ret = regmap_update_bits(regmap, reg, mask, 0x00);
271 if (ret)
272 return ret;
273 }
274 }
275
276 return 0;
277}
278
279static const struct platform_device_id pmic_thermal_id_table[] = {
280 {
281 .name = "bxt_wcove_thermal",
282 .driver_data = (kernel_ulong_t)&bxtwc_thermal_data,
283 },
284 {},
285};
286
287static struct platform_driver pmic_thermal_driver = {
288 .probe = pmic_thermal_probe,
289 .driver = {
290 .name = "pmic_thermal",
291 },
292 .id_table = pmic_thermal_id_table,
293};
294
295MODULE_DEVICE_TABLE(platform, pmic_thermal_id_table);
296module_platform_driver(pmic_thermal_driver);
297
298MODULE_AUTHOR("Yegnesh S Iyer <yegnesh.s.iyer@intel.com>");
299MODULE_DESCRIPTION("Intel Broxton PMIC Thermal Driver");
300MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/intel_soc_dts_iosf.c b/drivers/thermal/intel_soc_dts_iosf.c
index f72e1db3216f..e0813dfaa278 100644
--- a/drivers/thermal/intel_soc_dts_iosf.c
+++ b/drivers/thermal/intel_soc_dts_iosf.c
@@ -391,7 +391,8 @@ void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors)
391 391
392 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 392 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
393 pr_debug("TZD update for zone %d\n", i); 393 pr_debug("TZD update for zone %d\n", i);
394 thermal_zone_device_update(sensors->soc_dts[i].tzone); 394 thermal_zone_device_update(sensors->soc_dts[i].tzone,
395 THERMAL_EVENT_UNSPECIFIED);
395 } 396 }
396 } else 397 } else
397 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags); 398 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
diff --git a/drivers/thermal/max77620_thermal.c b/drivers/thermal/max77620_thermal.c
new file mode 100644
index 000000000000..83905ff46e40
--- /dev/null
+++ b/drivers/thermal/max77620_thermal.c
@@ -0,0 +1,166 @@
1/*
2 * Junction temperature thermal driver for Maxim Max77620.
3 *
4 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Laxman Dewangan <ldewangan@nvidia.com>
7 * Mallikarjun Kasoju <mkasoju@nvidia.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 */
13
14#include <linux/irq.h>
15#include <linux/interrupt.h>
16#include <linux/mfd/max77620.h>
17#include <linux/module.h>
18#include <linux/of.h>
19#include <linux/platform_device.h>
20#include <linux/regmap.h>
21#include <linux/slab.h>
22#include <linux/thermal.h>
23
24#define MAX77620_NORMAL_OPERATING_TEMP 100000
25#define MAX77620_TJALARM1_TEMP 120000
26#define MAX77620_TJALARM2_TEMP 140000
27
28struct max77620_therm_info {
29 struct device *dev;
30 struct regmap *rmap;
31 struct thermal_zone_device *tz_device;
32 int irq_tjalarm1;
33 int irq_tjalarm2;
34};
35
36/**
37 * max77620_thermal_read_temp: Read PMIC die temperatue.
38 * @data: Device specific data.
39 * temp: Temperature in millidegrees Celsius
40 *
41 * The actual temperature of PMIC die is not available from PMIC.
42 * PMIC only tells the status if it has crossed or not the threshold level
43 * of 120degC or 140degC.
44 * If threshold has not been crossed then assume die temperature as 100degC
45 * else 120degC or 140deG based on the PMIC die temp threshold status.
46 *
47 * Return 0 on success otherwise error number to show reason of failure.
48 */
49
50static int max77620_thermal_read_temp(void *data, int *temp)
51{
52 struct max77620_therm_info *mtherm = data;
53 unsigned int val;
54 int ret;
55
56 ret = regmap_read(mtherm->rmap, MAX77620_REG_STATLBT, &val);
57 if (ret < 0) {
58 dev_err(mtherm->dev, "Failed to read STATLBT: %d\n", ret);
59 return ret;
60 }
61
62 if (val & MAX77620_IRQ_TJALRM2_MASK)
63 *temp = MAX77620_TJALARM2_TEMP;
64 else if (val & MAX77620_IRQ_TJALRM1_MASK)
65 *temp = MAX77620_TJALARM1_TEMP;
66 else
67 *temp = MAX77620_NORMAL_OPERATING_TEMP;
68
69 return 0;
70}
71
72static const struct thermal_zone_of_device_ops max77620_thermal_ops = {
73 .get_temp = max77620_thermal_read_temp,
74};
75
76static irqreturn_t max77620_thermal_irq(int irq, void *data)
77{
78 struct max77620_therm_info *mtherm = data;
79
80 if (irq == mtherm->irq_tjalarm1)
81 dev_warn(mtherm->dev, "Junction Temp Alarm1(120C) occurred\n");
82 else if (irq == mtherm->irq_tjalarm2)
83 dev_crit(mtherm->dev, "Junction Temp Alarm2(140C) occurred\n");
84
85 thermal_zone_device_update(mtherm->tz_device,
86 THERMAL_EVENT_UNSPECIFIED);
87
88 return IRQ_HANDLED;
89}
90
91static int max77620_thermal_probe(struct platform_device *pdev)
92{
93 struct max77620_therm_info *mtherm;
94 int ret;
95
96 mtherm = devm_kzalloc(&pdev->dev, sizeof(*mtherm), GFP_KERNEL);
97 if (!mtherm)
98 return -ENOMEM;
99
100 mtherm->irq_tjalarm1 = platform_get_irq(pdev, 0);
101 mtherm->irq_tjalarm2 = platform_get_irq(pdev, 1);
102 if ((mtherm->irq_tjalarm1 < 0) || (mtherm->irq_tjalarm2 < 0)) {
103 dev_err(&pdev->dev, "Alarm irq number not available\n");
104 return -EINVAL;
105 }
106
107 pdev->dev.of_node = pdev->dev.parent->of_node;
108
109 mtherm->dev = &pdev->dev;
110 mtherm->rmap = dev_get_regmap(pdev->dev.parent, NULL);
111 if (!mtherm->rmap) {
112 dev_err(&pdev->dev, "Failed to get parent regmap\n");
113 return -ENODEV;
114 }
115
116 mtherm->tz_device = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
117 mtherm, &max77620_thermal_ops);
118 if (IS_ERR(mtherm->tz_device)) {
119 ret = PTR_ERR(mtherm->tz_device);
120 dev_err(&pdev->dev, "Failed to register thermal zone: %d\n",
121 ret);
122 return ret;
123 }
124
125 ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm1, NULL,
126 max77620_thermal_irq,
127 IRQF_ONESHOT | IRQF_SHARED,
128 dev_name(&pdev->dev), mtherm);
129 if (ret < 0) {
130 dev_err(&pdev->dev, "Failed to request irq1: %d\n", ret);
131 return ret;
132 }
133
134 ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm2, NULL,
135 max77620_thermal_irq,
136 IRQF_ONESHOT | IRQF_SHARED,
137 dev_name(&pdev->dev), mtherm);
138 if (ret < 0) {
139 dev_err(&pdev->dev, "Failed to request irq2: %d\n", ret);
140 return ret;
141 }
142
143 platform_set_drvdata(pdev, mtherm);
144
145 return 0;
146}
147
148static struct platform_device_id max77620_thermal_devtype[] = {
149 { .name = "max77620-thermal", },
150 {},
151};
152
153static struct platform_driver max77620_thermal_driver = {
154 .driver = {
155 .name = "max77620-thermal",
156 },
157 .probe = max77620_thermal_probe,
158 .id_table = max77620_thermal_devtype,
159};
160
161module_platform_driver(max77620_thermal_driver);
162
163MODULE_DESCRIPTION("Max77620 Junction temperature Thermal driver");
164MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
165MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>");
166MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index 262ab0a2266f..34169c32d495 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -2,6 +2,7 @@
2 * Copyright (c) 2015 MediaTek Inc. 2 * Copyright (c) 2015 MediaTek Inc.
3 * Author: Hanyi Wu <hanyi.wu@mediatek.com> 3 * Author: Hanyi Wu <hanyi.wu@mediatek.com>
4 * Sascha Hauer <s.hauer@pengutronix.de> 4 * Sascha Hauer <s.hauer@pengutronix.de>
5 * Dawei Chien <dawei.chien@mediatek.com>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -21,6 +22,7 @@
21#include <linux/nvmem-consumer.h> 22#include <linux/nvmem-consumer.h>
22#include <linux/of.h> 23#include <linux/of.h>
23#include <linux/of_address.h> 24#include <linux/of_address.h>
25#include <linux/of_device.h>
24#include <linux/platform_device.h> 26#include <linux/platform_device.h>
25#include <linux/slab.h> 27#include <linux/slab.h>
26#include <linux/io.h> 28#include <linux/io.h>
@@ -88,6 +90,7 @@
88#define TEMP_ADCVALIDMASK_VALID_HIGH BIT(5) 90#define TEMP_ADCVALIDMASK_VALID_HIGH BIT(5)
89#define TEMP_ADCVALIDMASK_VALID_POS(bit) (bit) 91#define TEMP_ADCVALIDMASK_VALID_POS(bit) (bit)
90 92
93/* MT8173 thermal sensors */
91#define MT8173_TS1 0 94#define MT8173_TS1 0
92#define MT8173_TS2 1 95#define MT8173_TS2 1
93#define MT8173_TS3 2 96#define MT8173_TS3 2
@@ -106,7 +109,12 @@
106/* The number of sensing points per bank */ 109/* The number of sensing points per bank */
107#define MT8173_NUM_SENSORS_PER_ZONE 4 110#define MT8173_NUM_SENSORS_PER_ZONE 4
108 111
109/* Layout of the fuses providing the calibration data */ 112/*
113 * Layout of the fuses providing the calibration data
114 * These macros could be used for both MT8173 and MT2701.
115 * MT8173 has five sensors and need five VTS calibration data,
116 * and MT2701 has three sensors and need three VTS calibration data.
117 */
110#define MT8173_CALIB_BUF0_VALID BIT(0) 118#define MT8173_CALIB_BUF0_VALID BIT(0)
111#define MT8173_CALIB_BUF1_ADC_GE(x) (((x) >> 22) & 0x3ff) 119#define MT8173_CALIB_BUF1_ADC_GE(x) (((x) >> 22) & 0x3ff)
112#define MT8173_CALIB_BUF0_VTS_TS1(x) (((x) >> 17) & 0x1ff) 120#define MT8173_CALIB_BUF0_VTS_TS1(x) (((x) >> 17) & 0x1ff)
@@ -117,24 +125,50 @@
117#define MT8173_CALIB_BUF0_DEGC_CALI(x) (((x) >> 1) & 0x3f) 125#define MT8173_CALIB_BUF0_DEGC_CALI(x) (((x) >> 1) & 0x3f)
118#define MT8173_CALIB_BUF0_O_SLOPE(x) (((x) >> 26) & 0x3f) 126#define MT8173_CALIB_BUF0_O_SLOPE(x) (((x) >> 26) & 0x3f)
119 127
128/* MT2701 thermal sensors */
129#define MT2701_TS1 0
130#define MT2701_TS2 1
131#define MT2701_TSABB 2
132
133/* AUXADC channel 11 is used for the temperature sensors */
134#define MT2701_TEMP_AUXADC_CHANNEL 11
135
136/* The total number of temperature sensors in the MT2701 */
137#define MT2701_NUM_SENSORS 3
138
120#define THERMAL_NAME "mtk-thermal" 139#define THERMAL_NAME "mtk-thermal"
121 140
141/* The number of sensing points per bank */
142#define MT2701_NUM_SENSORS_PER_ZONE 3
143
122struct mtk_thermal; 144struct mtk_thermal;
123 145
146struct thermal_bank_cfg {
147 unsigned int num_sensors;
148 const int *sensors;
149};
150
124struct mtk_thermal_bank { 151struct mtk_thermal_bank {
125 struct mtk_thermal *mt; 152 struct mtk_thermal *mt;
126 int id; 153 int id;
127}; 154};
128 155
156struct mtk_thermal_data {
157 s32 num_banks;
158 s32 num_sensors;
159 s32 auxadc_channel;
160 const int *sensor_mux_values;
161 const int *msr;
162 const int *adcpnp;
163 struct thermal_bank_cfg bank_data[];
164};
165
129struct mtk_thermal { 166struct mtk_thermal {
130 struct device *dev; 167 struct device *dev;
131 void __iomem *thermal_base; 168 void __iomem *thermal_base;
132 169
133 struct clk *clk_peri_therm; 170 struct clk *clk_peri_therm;
134 struct clk *clk_auxadc; 171 struct clk *clk_auxadc;
135
136 struct mtk_thermal_bank banks[MT8173_NUM_ZONES];
137
138 /* lock: for getting and putting banks */ 172 /* lock: for getting and putting banks */
139 struct mutex lock; 173 struct mutex lock;
140 174
@@ -144,16 +178,44 @@ struct mtk_thermal {
144 s32 o_slope; 178 s32 o_slope;
145 s32 vts[MT8173_NUM_SENSORS]; 179 s32 vts[MT8173_NUM_SENSORS];
146 180
181 const struct mtk_thermal_data *conf;
182 struct mtk_thermal_bank banks[];
147}; 183};
148 184
149struct mtk_thermal_bank_cfg { 185/* MT8173 thermal sensor data */
150 unsigned int num_sensors; 186const int mt8173_bank_data[MT8173_NUM_ZONES][3] = {
151 unsigned int sensors[MT8173_NUM_SENSORS_PER_ZONE]; 187 { MT8173_TS2, MT8173_TS3 },
188 { MT8173_TS2, MT8173_TS4 },
189 { MT8173_TS1, MT8173_TS2, MT8173_TSABB },
190 { MT8173_TS2 },
152}; 191};
153 192
154static const int sensor_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 }; 193const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = {
194 TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR2
195};
155 196
156/* 197const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
198 TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3
199};
200
201const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 };
202
203/* MT2701 thermal sensor data */
204const int mt2701_bank_data[MT2701_NUM_SENSORS] = {
205 MT2701_TS1, MT2701_TS2, MT2701_TSABB
206};
207
208const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = {
209 TEMP_MSR0, TEMP_MSR1, TEMP_MSR2
210};
211
212const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = {
213 TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2
214};
215
216const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 };
217
218/**
157 * The MT8173 thermal controller has four banks. Each bank can read up to 219 * The MT8173 thermal controller has four banks. Each bank can read up to
158 * four temperature sensors simultaneously. The MT8173 has a total of 5 220 * four temperature sensors simultaneously. The MT8173 has a total of 5
159 * temperature sensors. We use each bank to measure a certain area of the 221 * temperature sensors. We use each bank to measure a certain area of the
@@ -166,42 +228,53 @@ static const int sensor_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 };
166 * data, and this indeed needs the temperatures of the individual banks 228 * data, and this indeed needs the temperatures of the individual banks
167 * for making better decisions. 229 * for making better decisions.
168 */ 230 */
169static const struct mtk_thermal_bank_cfg bank_data[] = { 231static const struct mtk_thermal_data mt8173_thermal_data = {
170 { 232 .auxadc_channel = MT8173_TEMP_AUXADC_CHANNEL,
171 .num_sensors = 2, 233 .num_banks = MT8173_NUM_ZONES,
172 .sensors = { MT8173_TS2, MT8173_TS3 }, 234 .num_sensors = MT8173_NUM_SENSORS,
173 }, { 235 .bank_data = {
174 .num_sensors = 2, 236 {
175 .sensors = { MT8173_TS2, MT8173_TS4 }, 237 .num_sensors = 2,
176 }, { 238 .sensors = mt8173_bank_data[0],
177 .num_sensors = 3, 239 }, {
178 .sensors = { MT8173_TS1, MT8173_TS2, MT8173_TSABB }, 240 .num_sensors = 2,
179 }, { 241 .sensors = mt8173_bank_data[1],
180 .num_sensors = 1, 242 }, {
181 .sensors = { MT8173_TS2 }, 243 .num_sensors = 3,
244 .sensors = mt8173_bank_data[2],
245 }, {
246 .num_sensors = 1,
247 .sensors = mt8173_bank_data[3],
248 },
182 }, 249 },
250 .msr = mt8173_msr,
251 .adcpnp = mt8173_adcpnp,
252 .sensor_mux_values = mt8173_mux_values,
183}; 253};
184 254
185struct mtk_thermal_sense_point { 255/**
186 int msr; 256 * The MT2701 thermal controller has one bank, which can read up to
187 int adcpnp; 257 * three temperature sensors simultaneously. The MT2701 has a total of 3
188}; 258 * temperature sensors.
189 259 *
190static const struct mtk_thermal_sense_point 260 * The thermal core only gets the maximum temperature of this one bank,
191 sensing_points[MT8173_NUM_SENSORS_PER_ZONE] = { 261 * so the bank concept wouldn't be necessary here. However, the SVS (Smart
192 { 262 * Voltage Scaling) unit makes its decisions based on the same bank
193 .msr = TEMP_MSR0, 263 * data.
194 .adcpnp = TEMP_ADCPNP0, 264 */
195 }, { 265static const struct mtk_thermal_data mt2701_thermal_data = {
196 .msr = TEMP_MSR1, 266 .auxadc_channel = MT2701_TEMP_AUXADC_CHANNEL,
197 .adcpnp = TEMP_ADCPNP1, 267 .num_banks = 1,
198 }, { 268 .num_sensors = MT2701_NUM_SENSORS,
199 .msr = TEMP_MSR2, 269 .bank_data = {
200 .adcpnp = TEMP_ADCPNP2, 270 {
201 }, { 271 .num_sensors = 3,
202 .msr = TEMP_MSR3, 272 .sensors = mt2701_bank_data,
203 .adcpnp = TEMP_ADCPNP3, 273 },
204 }, 274 },
275 .msr = mt2701_msr,
276 .adcpnp = mt2701_adcpnp,
277 .sensor_mux_values = mt2701_mux_values,
205}; 278};
206 279
207/** 280/**
@@ -270,13 +343,16 @@ static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
270static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) 343static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
271{ 344{
272 struct mtk_thermal *mt = bank->mt; 345 struct mtk_thermal *mt = bank->mt;
346 const struct mtk_thermal_data *conf = mt->conf;
273 int i, temp = INT_MIN, max = INT_MIN; 347 int i, temp = INT_MIN, max = INT_MIN;
274 u32 raw; 348 u32 raw;
275 349
276 for (i = 0; i < bank_data[bank->id].num_sensors; i++) { 350 for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
277 raw = readl(mt->thermal_base + sensing_points[i].msr); 351 raw = readl(mt->thermal_base + conf->msr[i]);
278 352
279 temp = raw_to_mcelsius(mt, bank_data[bank->id].sensors[i], raw); 353 temp = raw_to_mcelsius(mt,
354 conf->bank_data[bank->id].sensors[i],
355 raw);
280 356
281 /* 357 /*
282 * The first read of a sensor often contains very high bogus 358 * The first read of a sensor often contains very high bogus
@@ -299,7 +375,7 @@ static int mtk_read_temp(void *data, int *temperature)
299 int i; 375 int i;
300 int tempmax = INT_MIN; 376 int tempmax = INT_MIN;
301 377
302 for (i = 0; i < MT8173_NUM_ZONES; i++) { 378 for (i = 0; i < mt->conf->num_banks; i++) {
303 struct mtk_thermal_bank *bank = &mt->banks[i]; 379 struct mtk_thermal_bank *bank = &mt->banks[i];
304 380
305 mtk_thermal_get_bank(bank); 381 mtk_thermal_get_bank(bank);
@@ -322,7 +398,7 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
322 u32 apmixed_phys_base, u32 auxadc_phys_base) 398 u32 apmixed_phys_base, u32 auxadc_phys_base)
323{ 399{
324 struct mtk_thermal_bank *bank = &mt->banks[num]; 400 struct mtk_thermal_bank *bank = &mt->banks[num];
325 const struct mtk_thermal_bank_cfg *cfg = &bank_data[num]; 401 const struct mtk_thermal_data *conf = mt->conf;
326 int i; 402 int i;
327 403
328 bank->id = num; 404 bank->id = num;
@@ -368,7 +444,7 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
368 * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0) 444 * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0)
369 * automatically by hw 445 * automatically by hw
370 */ 446 */
371 writel(BIT(MT8173_TEMP_AUXADC_CHANNEL), mt->thermal_base + TEMP_ADCMUX); 447 writel(BIT(conf->auxadc_channel), mt->thermal_base + TEMP_ADCMUX);
372 448
373 /* AHB address for auxadc mux selection */ 449 /* AHB address for auxadc mux selection */
374 writel(auxadc_phys_base + AUXADC_CON1_CLR_V, 450 writel(auxadc_phys_base + AUXADC_CON1_CLR_V,
@@ -379,18 +455,18 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
379 mt->thermal_base + TEMP_PNPMUXADDR); 455 mt->thermal_base + TEMP_PNPMUXADDR);
380 456
381 /* AHB value for auxadc enable */ 457 /* AHB value for auxadc enable */
382 writel(BIT(MT8173_TEMP_AUXADC_CHANNEL), mt->thermal_base + TEMP_ADCEN); 458 writel(BIT(conf->auxadc_channel), mt->thermal_base + TEMP_ADCEN);
383 459
384 /* AHB address for auxadc enable (channel 0 immediate mode selected) */ 460 /* AHB address for auxadc enable (channel 0 immediate mode selected) */
385 writel(auxadc_phys_base + AUXADC_CON1_SET_V, 461 writel(auxadc_phys_base + AUXADC_CON1_SET_V,
386 mt->thermal_base + TEMP_ADCENADDR); 462 mt->thermal_base + TEMP_ADCENADDR);
387 463
388 /* AHB address for auxadc valid bit */ 464 /* AHB address for auxadc valid bit */
389 writel(auxadc_phys_base + AUXADC_DATA(MT8173_TEMP_AUXADC_CHANNEL), 465 writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel),
390 mt->thermal_base + TEMP_ADCVALIDADDR); 466 mt->thermal_base + TEMP_ADCVALIDADDR);
391 467
392 /* AHB address for auxadc voltage output */ 468 /* AHB address for auxadc voltage output */
393 writel(auxadc_phys_base + AUXADC_DATA(MT8173_TEMP_AUXADC_CHANNEL), 469 writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel),
394 mt->thermal_base + TEMP_ADCVOLTADDR); 470 mt->thermal_base + TEMP_ADCVOLTADDR);
395 471
396 /* read valid & voltage are at the same register */ 472 /* read valid & voltage are at the same register */
@@ -407,11 +483,12 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
407 writel(TEMP_ADCWRITECTRL_ADC_MUX_WRITE, 483 writel(TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
408 mt->thermal_base + TEMP_ADCWRITECTRL); 484 mt->thermal_base + TEMP_ADCWRITECTRL);
409 485
410 for (i = 0; i < cfg->num_sensors; i++) 486 for (i = 0; i < conf->bank_data[num].num_sensors; i++)
411 writel(sensor_mux_values[cfg->sensors[i]], 487 writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]],
412 mt->thermal_base + sensing_points[i].adcpnp); 488 mt->thermal_base + conf->adcpnp[i]);
413 489
414 writel((1 << cfg->num_sensors) - 1, mt->thermal_base + TEMP_MONCTL0); 490 writel((1 << conf->bank_data[num].num_sensors) - 1,
491 mt->thermal_base + TEMP_MONCTL0);
415 492
416 writel(TEMP_ADCWRITECTRL_ADC_PNP_WRITE | 493 writel(TEMP_ADCWRITECTRL_ADC_PNP_WRITE |
417 TEMP_ADCWRITECTRL_ADC_MUX_WRITE, 494 TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
@@ -442,7 +519,7 @@ static int mtk_thermal_get_calibration_data(struct device *dev,
442 519
443 /* Start with default values */ 520 /* Start with default values */
444 mt->adc_ge = 512; 521 mt->adc_ge = 512;
445 for (i = 0; i < MT8173_NUM_SENSORS; i++) 522 for (i = 0; i < mt->conf->num_sensors; i++)
446 mt->vts[i] = 260; 523 mt->vts[i] = 260;
447 mt->degc_cali = 40; 524 mt->degc_cali = 40;
448 mt->o_slope = 0; 525 mt->o_slope = 0;
@@ -486,18 +563,37 @@ out:
486 return ret; 563 return ret;
487} 564}
488 565
566static const struct of_device_id mtk_thermal_of_match[] = {
567 {
568 .compatible = "mediatek,mt8173-thermal",
569 .data = (void *)&mt8173_thermal_data,
570 },
571 {
572 .compatible = "mediatek,mt2701-thermal",
573 .data = (void *)&mt2701_thermal_data,
574 }, {
575 },
576};
577MODULE_DEVICE_TABLE(of, mtk_thermal_of_match);
578
489static int mtk_thermal_probe(struct platform_device *pdev) 579static int mtk_thermal_probe(struct platform_device *pdev)
490{ 580{
491 int ret, i; 581 int ret, i;
492 struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; 582 struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
493 struct mtk_thermal *mt; 583 struct mtk_thermal *mt;
494 struct resource *res; 584 struct resource *res;
585 const struct of_device_id *of_id;
495 u64 auxadc_phys_base, apmixed_phys_base; 586 u64 auxadc_phys_base, apmixed_phys_base;
587 struct thermal_zone_device *tzdev;
496 588
497 mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL); 589 mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
498 if (!mt) 590 if (!mt)
499 return -ENOMEM; 591 return -ENOMEM;
500 592
593 of_id = of_match_device(mtk_thermal_of_match, &pdev->dev);
594 if (of_id)
595 mt->conf = (const struct mtk_thermal_data *)of_id->data;
596
501 mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm"); 597 mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
502 if (IS_ERR(mt->clk_peri_therm)) 598 if (IS_ERR(mt->clk_peri_therm))
503 return PTR_ERR(mt->clk_peri_therm); 599 return PTR_ERR(mt->clk_peri_therm);
@@ -565,17 +661,23 @@ static int mtk_thermal_probe(struct platform_device *pdev)
565 goto err_disable_clk_auxadc; 661 goto err_disable_clk_auxadc;
566 } 662 }
567 663
568 for (i = 0; i < MT8173_NUM_ZONES; i++) 664 for (i = 0; i < mt->conf->num_banks; i++)
569 mtk_thermal_init_bank(mt, i, apmixed_phys_base, 665 mtk_thermal_init_bank(mt, i, apmixed_phys_base,
570 auxadc_phys_base); 666 auxadc_phys_base);
571 667
572 platform_set_drvdata(pdev, mt); 668 platform_set_drvdata(pdev, mt);
573 669
574 devm_thermal_zone_of_sensor_register(&pdev->dev, 0, mt, 670 tzdev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, mt,
575 &mtk_thermal_ops); 671 &mtk_thermal_ops);
672 if (IS_ERR(tzdev)) {
673 ret = PTR_ERR(tzdev);
674 goto err_disable_clk_peri_therm;
675 }
576 676
577 return 0; 677 return 0;
578 678
679err_disable_clk_peri_therm:
680 clk_disable_unprepare(mt->clk_peri_therm);
579err_disable_clk_auxadc: 681err_disable_clk_auxadc:
580 clk_disable_unprepare(mt->clk_auxadc); 682 clk_disable_unprepare(mt->clk_auxadc);
581 683
@@ -592,13 +694,6 @@ static int mtk_thermal_remove(struct platform_device *pdev)
592 return 0; 694 return 0;
593} 695}
594 696
595static const struct of_device_id mtk_thermal_of_match[] = {
596 {
597 .compatible = "mediatek,mt8173-thermal",
598 }, {
599 },
600};
601
602static struct platform_driver mtk_thermal_driver = { 697static struct platform_driver mtk_thermal_driver = {
603 .probe = mtk_thermal_probe, 698 .probe = mtk_thermal_probe,
604 .remove = mtk_thermal_remove, 699 .remove = mtk_thermal_remove,
@@ -610,6 +705,7 @@ static struct platform_driver mtk_thermal_driver = {
610 705
611module_platform_driver(mtk_thermal_driver); 706module_platform_driver(mtk_thermal_driver);
612 707
708MODULE_AUTHOR("Dawei Chien <dawei.chien@mediatek.com>");
613MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); 709MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
614MODULE_AUTHOR("Hanyi Wu <hanyi.wu@mediatek.com>"); 710MODULE_AUTHOR("Hanyi Wu <hanyi.wu@mediatek.com>");
615MODULE_DESCRIPTION("Mediatek thermal driver"); 711MODULE_DESCRIPTION("Mediatek thermal driver");
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index b8e509c60848..d04ec3b9e5ff 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -101,6 +101,17 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
101 return data->ops->get_temp(data->sensor_data, temp); 101 return data->ops->get_temp(data->sensor_data, temp);
102} 102}
103 103
104static int of_thermal_set_trips(struct thermal_zone_device *tz,
105 int low, int high)
106{
107 struct __thermal_zone *data = tz->devdata;
108
109 if (!data->ops || !data->ops->set_trips)
110 return -EINVAL;
111
112 return data->ops->set_trips(data->sensor_data, low, high);
113}
114
104/** 115/**
105 * of_thermal_get_ntrips - function to export number of available trip 116 * of_thermal_get_ntrips - function to export number of available trip
106 * points. 117 * points.
@@ -181,9 +192,6 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
181{ 192{
182 struct __thermal_zone *data = tz->devdata; 193 struct __thermal_zone *data = tz->devdata;
183 194
184 if (!data->ops || !data->ops->set_emul_temp)
185 return -EINVAL;
186
187 return data->ops->set_emul_temp(data->sensor_data, temp); 195 return data->ops->set_emul_temp(data->sensor_data, temp);
188} 196}
189 197
@@ -191,25 +199,11 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
191 enum thermal_trend *trend) 199 enum thermal_trend *trend)
192{ 200{
193 struct __thermal_zone *data = tz->devdata; 201 struct __thermal_zone *data = tz->devdata;
194 long dev_trend;
195 int r;
196 202
197 if (!data->ops->get_trend) 203 if (!data->ops->get_trend)
198 return -EINVAL; 204 return -EINVAL;
199 205
200 r = data->ops->get_trend(data->sensor_data, &dev_trend); 206 return data->ops->get_trend(data->sensor_data, trip, trend);
201 if (r)
202 return r;
203
204 /* TODO: These intervals might have some thresholds, but in core code */
205 if (dev_trend > 0)
206 *trend = THERMAL_TREND_RAISING;
207 else if (dev_trend < 0)
208 *trend = THERMAL_TREND_DROPPING;
209 else
210 *trend = THERMAL_TREND_STABLE;
211
212 return 0;
213} 207}
214 208
215static int of_thermal_bind(struct thermal_zone_device *thermal, 209static int of_thermal_bind(struct thermal_zone_device *thermal,
@@ -292,7 +286,7 @@ static int of_thermal_set_mode(struct thermal_zone_device *tz,
292 mutex_unlock(&tz->lock); 286 mutex_unlock(&tz->lock);
293 287
294 data->mode = mode; 288 data->mode = mode;
295 thermal_zone_device_update(tz); 289 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
296 290
297 return 0; 291 return 0;
298} 292}
@@ -427,7 +421,17 @@ thermal_zone_of_add_sensor(struct device_node *zone,
427 421
428 tzd->ops->get_temp = of_thermal_get_temp; 422 tzd->ops->get_temp = of_thermal_get_temp;
429 tzd->ops->get_trend = of_thermal_get_trend; 423 tzd->ops->get_trend = of_thermal_get_trend;
430 tzd->ops->set_emul_temp = of_thermal_set_emul_temp; 424
425 /*
426 * The thermal zone core will calculate the window if they have set the
427 * optional set_trips pointer.
428 */
429 if (ops->set_trips)
430 tzd->ops->set_trips = of_thermal_set_trips;
431
432 if (ops->set_emul_temp)
433 tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
434
431 mutex_unlock(&tzd->lock); 435 mutex_unlock(&tzd->lock);
432 436
433 return tzd; 437 return tzd;
@@ -596,7 +600,7 @@ static int devm_thermal_zone_of_sensor_match(struct device *dev, void *res,
596 * Return: On success returns a valid struct thermal_zone_device, 600 * Return: On success returns a valid struct thermal_zone_device,
597 * otherwise, it returns a corresponding ERR_PTR(). Caller must 601 * otherwise, it returns a corresponding ERR_PTR(). Caller must
598 * check the return value with help of IS_ERR() helper. 602 * check the return value with help of IS_ERR() helper.
599 * Registered hermal_zone_device device will automatically be 603 * Registered thermal_zone_device device will automatically be
600 * released when device is unbounded. 604 * released when device is unbounded.
601 */ 605 */
602struct thermal_zone_device *devm_thermal_zone_of_sensor_register( 606struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c
index f8a3c60bef94..819c6d5d7aa7 100644
--- a/drivers/thermal/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom-spmi-temp-alarm.c
@@ -150,7 +150,7 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
150{ 150{
151 struct qpnp_tm_chip *chip = data; 151 struct qpnp_tm_chip *chip = data;
152 152
153 thermal_zone_device_update(chip->tz_dev); 153 thermal_zone_device_update(chip->tz_dev, THERMAL_EVENT_UNSPECIFIED);
154 154
155 return IRQ_HANDLED; 155 return IRQ_HANDLED;
156} 156}
diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig
new file mode 100644
index 000000000000..be32e5abce3c
--- /dev/null
+++ b/drivers/thermal/qcom/Kconfig
@@ -0,0 +1,11 @@
1config QCOM_TSENS
2 tristate "Qualcomm TSENS Temperature Alarm"
3 depends on THERMAL
4 depends on QCOM_QFPROM
5 depends on ARCH_QCOM || COMPILE_TEST
6 help
7 This enables the thermal sysfs driver for the TSENS device. It shows
8 up in Sysfs as a thermal zone with multiple trip points. Disabling the
9 thermal zone device via the mode file results in disabling the sensor.
10 Also able to set threshold temperature for both hot and cold and update
11 when a threshold is reached.
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
new file mode 100644
index 000000000000..2cc2193637e7
--- /dev/null
+++ b/drivers/thermal/qcom/Makefile
@@ -0,0 +1,2 @@
1obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
2qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o
diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-8916.c
new file mode 100644
index 000000000000..fdf561b8b81d
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8916.c
@@ -0,0 +1,113 @@
1/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/platform_device.h>
16#include "tsens.h"
17
18/* eeprom layout data for 8916 */
19#define BASE0_MASK 0x0000007f
20#define BASE1_MASK 0xfe000000
21#define BASE0_SHIFT 0
22#define BASE1_SHIFT 25
23
24#define S0_P1_MASK 0x00000f80
25#define S1_P1_MASK 0x003e0000
26#define S2_P1_MASK 0xf8000000
27#define S3_P1_MASK 0x000003e0
28#define S4_P1_MASK 0x000f8000
29
30#define S0_P2_MASK 0x0001f000
31#define S1_P2_MASK 0x07c00000
32#define S2_P2_MASK 0x0000001f
33#define S3_P2_MASK 0x00007c00
34#define S4_P2_MASK 0x01f00000
35
36#define S0_P1_SHIFT 7
37#define S1_P1_SHIFT 17
38#define S2_P1_SHIFT 27
39#define S3_P1_SHIFT 5
40#define S4_P1_SHIFT 15
41
42#define S0_P2_SHIFT 12
43#define S1_P2_SHIFT 22
44#define S2_P2_SHIFT 0
45#define S3_P2_SHIFT 10
46#define S4_P2_SHIFT 20
47
48#define CAL_SEL_MASK 0xe0000000
49#define CAL_SEL_SHIFT 29
50
51static int calibrate_8916(struct tsens_device *tmdev)
52{
53 int base0 = 0, base1 = 0, i;
54 u32 p1[5], p2[5];
55 int mode = 0;
56 u32 *qfprom_cdata, *qfprom_csel;
57
58 qfprom_cdata = (u32 *)qfprom_read(tmdev->dev, "calib");
59 if (IS_ERR(qfprom_cdata))
60 return PTR_ERR(qfprom_cdata);
61
62 qfprom_csel = (u32 *)qfprom_read(tmdev->dev, "calib_sel");
63 if (IS_ERR(qfprom_csel))
64 return PTR_ERR(qfprom_csel);
65
66 mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
67 dev_dbg(tmdev->dev, "calibration mode is %d\n", mode);
68
69 switch (mode) {
70 case TWO_PT_CALIB:
71 base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT;
72 p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
73 p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
74 p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT;
75 p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
76 p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
77 for (i = 0; i < tmdev->num_sensors; i++)
78 p2[i] = ((base1 + p2[i]) << 3);
79 /* Fall through */
80 case ONE_PT_CALIB2:
81 base0 = (qfprom_cdata[0] & BASE0_MASK);
82 p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
83 p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
84 p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
85 p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
86 p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
87 for (i = 0; i < tmdev->num_sensors; i++)
88 p1[i] = (((base0) + p1[i]) << 3);
89 break;
90 default:
91 for (i = 0; i < tmdev->num_sensors; i++) {
92 p1[i] = 500;
93 p2[i] = 780;
94 }
95 break;
96 }
97
98 compute_intercept_slope(tmdev, p1, p2, mode);
99
100 return 0;
101}
102
103static const struct tsens_ops ops_8916 = {
104 .init = init_common,
105 .calibrate = calibrate_8916,
106 .get_temp = get_temp_common,
107};
108
109const struct tsens_data data_8916 = {
110 .num_sensors = 5,
111 .ops = &ops_8916,
112 .hw_ids = (unsigned int []){0, 1, 2, 4, 5 },
113};
diff --git a/drivers/thermal/qcom/tsens-8960.c b/drivers/thermal/qcom/tsens-8960.c
new file mode 100644
index 000000000000..0451277d3a8f
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8960.c
@@ -0,0 +1,292 @@
1/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/platform_device.h>
16#include <linux/delay.h>
17#include <linux/bitops.h>
18#include <linux/regmap.h>
19#include <linux/thermal.h>
20#include "tsens.h"
21
22#define CAL_MDEGC 30000
23
24#define CONFIG_ADDR 0x3640
25#define CONFIG_ADDR_8660 0x3620
26/* CONFIG_ADDR bitmasks */
27#define CONFIG 0x9b
28#define CONFIG_MASK 0xf
29#define CONFIG_8660 1
30#define CONFIG_SHIFT_8660 28
31#define CONFIG_MASK_8660 (3 << CONFIG_SHIFT_8660)
32
33#define STATUS_CNTL_ADDR_8064 0x3660
34#define CNTL_ADDR 0x3620
35/* CNTL_ADDR bitmasks */
36#define EN BIT(0)
37#define SW_RST BIT(1)
38#define SENSOR0_EN BIT(3)
39#define SLP_CLK_ENA BIT(26)
40#define SLP_CLK_ENA_8660 BIT(24)
41#define MEASURE_PERIOD 1
42#define SENSOR0_SHIFT 3
43
44/* INT_STATUS_ADDR bitmasks */
45#define MIN_STATUS_MASK BIT(0)
46#define LOWER_STATUS_CLR BIT(1)
47#define UPPER_STATUS_CLR BIT(2)
48#define MAX_STATUS_MASK BIT(3)
49
50#define THRESHOLD_ADDR 0x3624
51/* THRESHOLD_ADDR bitmasks */
52#define THRESHOLD_MAX_LIMIT_SHIFT 24
53#define THRESHOLD_MIN_LIMIT_SHIFT 16
54#define THRESHOLD_UPPER_LIMIT_SHIFT 8
55#define THRESHOLD_LOWER_LIMIT_SHIFT 0
56
57/* Initial temperature threshold values */
58#define LOWER_LIMIT_TH 0x50
59#define UPPER_LIMIT_TH 0xdf
60#define MIN_LIMIT_TH 0x0
61#define MAX_LIMIT_TH 0xff
62
63#define S0_STATUS_ADDR 0x3628
64#define INT_STATUS_ADDR 0x363c
65#define TRDY_MASK BIT(7)
66#define TIMEOUT_US 100
67
68static int suspend_8960(struct tsens_device *tmdev)
69{
70 int ret;
71 unsigned int mask;
72 struct regmap *map = tmdev->map;
73
74 ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
75 if (ret)
76 return ret;
77
78 ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
79 if (ret)
80 return ret;
81
82 if (tmdev->num_sensors > 1)
83 mask = SLP_CLK_ENA | EN;
84 else
85 mask = SLP_CLK_ENA_8660 | EN;
86
87 ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
88 if (ret)
89 return ret;
90
91 return 0;
92}
93
94static int resume_8960(struct tsens_device *tmdev)
95{
96 int ret;
97 struct regmap *map = tmdev->map;
98
99 ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
100 if (ret)
101 return ret;
102
103 /*
104 * Separate CONFIG restore is not needed only for 8660 as
105 * config is part of CTRL Addr and its restored as such
106 */
107 if (tmdev->num_sensors > 1) {
108 ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
109 if (ret)
110 return ret;
111 }
112
113 ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
114 if (ret)
115 return ret;
116
117 ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
118 if (ret)
119 return ret;
120
121 return 0;
122}
123
124static int enable_8960(struct tsens_device *tmdev, int id)
125{
126 int ret;
127 u32 reg, mask;
128
129 ret = regmap_read(tmdev->map, CNTL_ADDR, &reg);
130 if (ret)
131 return ret;
132
133 mask = BIT(id + SENSOR0_SHIFT);
134 ret = regmap_write(tmdev->map, CNTL_ADDR, reg | SW_RST);
135 if (ret)
136 return ret;
137
138 if (tmdev->num_sensors > 1)
139 reg |= mask | SLP_CLK_ENA | EN;
140 else
141 reg |= mask | SLP_CLK_ENA_8660 | EN;
142
143 ret = regmap_write(tmdev->map, CNTL_ADDR, reg);
144 if (ret)
145 return ret;
146
147 return 0;
148}
149
150static void disable_8960(struct tsens_device *tmdev)
151{
152 int ret;
153 u32 reg_cntl;
154 u32 mask;
155
156 mask = GENMASK(tmdev->num_sensors - 1, 0);
157 mask <<= SENSOR0_SHIFT;
158 mask |= EN;
159
160 ret = regmap_read(tmdev->map, CNTL_ADDR, &reg_cntl);
161 if (ret)
162 return;
163
164 reg_cntl &= ~mask;
165
166 if (tmdev->num_sensors > 1)
167 reg_cntl &= ~SLP_CLK_ENA;
168 else
169 reg_cntl &= ~SLP_CLK_ENA_8660;
170
171 regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
172}
173
174static int init_8960(struct tsens_device *tmdev)
175{
176 int ret, i;
177 u32 reg_cntl;
178
179 tmdev->map = dev_get_regmap(tmdev->dev, NULL);
180 if (!tmdev->map)
181 return -ENODEV;
182
183 /*
184 * The status registers for each sensor are discontiguous
185 * because some SoCs have 5 sensors while others have more
186 * but the control registers stay in the same place, i.e
187 * directly after the first 5 status registers.
188 */
189 for (i = 0; i < tmdev->num_sensors; i++) {
190 if (i >= 5)
191 tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
192 tmdev->sensor[i].status += i * 4;
193 }
194
195 reg_cntl = SW_RST;
196 ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl);
197 if (ret)
198 return ret;
199
200 if (tmdev->num_sensors > 1) {
201 reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
202 reg_cntl &= ~SW_RST;
203 ret = regmap_update_bits(tmdev->map, CONFIG_ADDR,
204 CONFIG_MASK, CONFIG);
205 } else {
206 reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
207 reg_cntl &= ~CONFIG_MASK_8660;
208 reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
209 }
210
211 reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
212 ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
213 if (ret)
214 return ret;
215
216 reg_cntl |= EN;
217 ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
218 if (ret)
219 return ret;
220
221 return 0;
222}
223
224static int calibrate_8960(struct tsens_device *tmdev)
225{
226 int i;
227 char *data;
228
229 ssize_t num_read = tmdev->num_sensors;
230 struct tsens_sensor *s = tmdev->sensor;
231
232 data = qfprom_read(tmdev->dev, "calib");
233 if (IS_ERR(data))
234 data = qfprom_read(tmdev->dev, "calib_backup");
235 if (IS_ERR(data))
236 return PTR_ERR(data);
237
238 for (i = 0; i < num_read; i++, s++)
239 s->offset = data[i];
240
241 return 0;
242}
243
244/* Temperature on y axis and ADC-code on x-axis */
245static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
246{
247 int slope, offset;
248
249 slope = thermal_zone_get_slope(s->tzd);
250 offset = CAL_MDEGC - slope * s->offset;
251
252 return adc_code * slope + offset;
253}
254
255static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp)
256{
257 int ret;
258 u32 code, trdy;
259 const struct tsens_sensor *s = &tmdev->sensor[id];
260 unsigned long timeout;
261
262 timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
263 do {
264 ret = regmap_read(tmdev->map, INT_STATUS_ADDR, &trdy);
265 if (ret)
266 return ret;
267 if (!(trdy & TRDY_MASK))
268 continue;
269 ret = regmap_read(tmdev->map, s->status, &code);
270 if (ret)
271 return ret;
272 *temp = code_to_mdegC(code, s);
273 return 0;
274 } while (time_before(jiffies, timeout));
275
276 return -ETIMEDOUT;
277}
278
279static const struct tsens_ops ops_8960 = {
280 .init = init_8960,
281 .calibrate = calibrate_8960,
282 .get_temp = get_temp_8960,
283 .enable = enable_8960,
284 .disable = disable_8960,
285 .suspend = suspend_8960,
286 .resume = resume_8960,
287};
288
289const struct tsens_data data_8960 = {
290 .num_sensors = 11,
291 .ops = &ops_8960,
292};
diff --git a/drivers/thermal/qcom/tsens-8974.c b/drivers/thermal/qcom/tsens-8974.c
new file mode 100644
index 000000000000..9baf77e8cbe3
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8974.c
@@ -0,0 +1,244 @@
1/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/platform_device.h>
16#include "tsens.h"
17
18/* eeprom layout data for 8974 */
19#define BASE1_MASK 0xff
20#define S0_P1_MASK 0x3f00
21#define S1_P1_MASK 0xfc000
22#define S2_P1_MASK 0x3f00000
23#define S3_P1_MASK 0xfc000000
24#define S4_P1_MASK 0x3f
25#define S5_P1_MASK 0xfc0
26#define S6_P1_MASK 0x3f000
27#define S7_P1_MASK 0xfc0000
28#define S8_P1_MASK 0x3f000000
29#define S8_P1_MASK_BKP 0x3f
30#define S9_P1_MASK 0x3f
31#define S9_P1_MASK_BKP 0xfc0
32#define S10_P1_MASK 0xfc0
33#define S10_P1_MASK_BKP 0x3f000
34#define CAL_SEL_0_1 0xc0000000
35#define CAL_SEL_2 0x40000000
36#define CAL_SEL_SHIFT 30
37#define CAL_SEL_SHIFT_2 28
38
39#define S0_P1_SHIFT 8
40#define S1_P1_SHIFT 14
41#define S2_P1_SHIFT 20
42#define S3_P1_SHIFT 26
43#define S5_P1_SHIFT 6
44#define S6_P1_SHIFT 12
45#define S7_P1_SHIFT 18
46#define S8_P1_SHIFT 24
47#define S9_P1_BKP_SHIFT 6
48#define S10_P1_SHIFT 6
49#define S10_P1_BKP_SHIFT 12
50
51#define BASE2_SHIFT 12
52#define BASE2_BKP_SHIFT 18
53#define S0_P2_SHIFT 20
54#define S0_P2_BKP_SHIFT 26
55#define S1_P2_SHIFT 26
56#define S2_P2_BKP_SHIFT 6
57#define S3_P2_SHIFT 6
58#define S3_P2_BKP_SHIFT 12
59#define S4_P2_SHIFT 12
60#define S4_P2_BKP_SHIFT 18
61#define S5_P2_SHIFT 18
62#define S5_P2_BKP_SHIFT 24
63#define S6_P2_SHIFT 24
64#define S7_P2_BKP_SHIFT 6
65#define S8_P2_SHIFT 6
66#define S8_P2_BKP_SHIFT 12
67#define S9_P2_SHIFT 12
68#define S9_P2_BKP_SHIFT 18
69#define S10_P2_SHIFT 18
70#define S10_P2_BKP_SHIFT 24
71
72#define BASE2_MASK 0xff000
73#define BASE2_BKP_MASK 0xfc0000
74#define S0_P2_MASK 0x3f00000
75#define S0_P2_BKP_MASK 0xfc000000
76#define S1_P2_MASK 0xfc000000
77#define S1_P2_BKP_MASK 0x3f
78#define S2_P2_MASK 0x3f
79#define S2_P2_BKP_MASK 0xfc0
80#define S3_P2_MASK 0xfc0
81#define S3_P2_BKP_MASK 0x3f000
82#define S4_P2_MASK 0x3f000
83#define S4_P2_BKP_MASK 0xfc0000
84#define S5_P2_MASK 0xfc0000
85#define S5_P2_BKP_MASK 0x3f000000
86#define S6_P2_MASK 0x3f000000
87#define S6_P2_BKP_MASK 0x3f
88#define S7_P2_MASK 0x3f
89#define S7_P2_BKP_MASK 0xfc0
90#define S8_P2_MASK 0xfc0
91#define S8_P2_BKP_MASK 0x3f000
92#define S9_P2_MASK 0x3f000
93#define S9_P2_BKP_MASK 0xfc0000
94#define S10_P2_MASK 0xfc0000
95#define S10_P2_BKP_MASK 0x3f000000
96
97#define BKP_SEL 0x3
98#define BKP_REDUN_SEL 0xe0000000
99#define BKP_REDUN_SHIFT 29
100
101#define BIT_APPEND 0x3
102
103static int calibrate_8974(struct tsens_device *tmdev)
104{
105 int base1 = 0, base2 = 0, i;
106 u32 p1[11], p2[11];
107 int mode = 0;
108 u32 *calib, *bkp;
109 u32 calib_redun_sel;
110
111 calib = (u32 *)qfprom_read(tmdev->dev, "calib");
112 if (IS_ERR(calib))
113 return PTR_ERR(calib);
114
115 bkp = (u32 *)qfprom_read(tmdev->dev, "calib_backup");
116 if (IS_ERR(bkp))
117 return PTR_ERR(bkp);
118
119 calib_redun_sel = bkp[1] & BKP_REDUN_SEL;
120 calib_redun_sel >>= BKP_REDUN_SHIFT;
121
122 if (calib_redun_sel == BKP_SEL) {
123 mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
124 mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
125
126 switch (mode) {
127 case TWO_PT_CALIB:
128 base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT;
129 p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT;
130 p2[1] = (bkp[3] & S1_P2_BKP_MASK);
131 p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT;
132 p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT;
133 p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT;
134 p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT;
135 p2[6] = (calib[5] & S6_P2_BKP_MASK);
136 p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT;
137 p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT;
138 p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT;
139 p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT;
140 /* Fall through */
141 case ONE_PT_CALIB:
142 case ONE_PT_CALIB2:
143 base1 = bkp[0] & BASE1_MASK;
144 p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT;
145 p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT;
146 p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT;
147 p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT;
148 p1[4] = (bkp[1] & S4_P1_MASK);
149 p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT;
150 p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT;
151 p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT;
152 p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT;
153 p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT;
154 p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT;
155 break;
156 }
157 } else {
158 mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
159 mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
160
161 switch (mode) {
162 case TWO_PT_CALIB:
163 base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT;
164 p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT;
165 p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT;
166 p2[2] = (calib[3] & S2_P2_MASK);
167 p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT;
168 p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT;
169 p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT;
170 p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT;
171 p2[7] = (calib[4] & S7_P2_MASK);
172 p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT;
173 p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT;
174 p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT;
175 /* Fall through */
176 case ONE_PT_CALIB:
177 case ONE_PT_CALIB2:
178 base1 = calib[0] & BASE1_MASK;
179 p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT;
180 p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT;
181 p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT;
182 p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT;
183 p1[4] = (calib[1] & S4_P1_MASK);
184 p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT;
185 p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT;
186 p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT;
187 p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT;
188 p1[9] = (calib[2] & S9_P1_MASK);
189 p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT;
190 break;
191 }
192 }
193
194 switch (mode) {
195 case ONE_PT_CALIB:
196 for (i = 0; i < tmdev->num_sensors; i++)
197 p1[i] += (base1 << 2) | BIT_APPEND;
198 break;
199 case TWO_PT_CALIB:
200 for (i = 0; i < tmdev->num_sensors; i++) {
201 p2[i] += base2;
202 p2[i] <<= 2;
203 p2[i] |= BIT_APPEND;
204 }
205 /* Fall through */
206 case ONE_PT_CALIB2:
207 for (i = 0; i < tmdev->num_sensors; i++) {
208 p1[i] += base1;
209 p1[i] <<= 2;
210 p1[i] |= BIT_APPEND;
211 }
212 break;
213 default:
214 for (i = 0; i < tmdev->num_sensors; i++)
215 p2[i] = 780;
216 p1[0] = 502;
217 p1[1] = 509;
218 p1[2] = 503;
219 p1[3] = 509;
220 p1[4] = 505;
221 p1[5] = 509;
222 p1[6] = 507;
223 p1[7] = 510;
224 p1[8] = 508;
225 p1[9] = 509;
226 p1[10] = 508;
227 break;
228 }
229
230 compute_intercept_slope(tmdev, p1, p2, mode);
231
232 return 0;
233}
234
235static const struct tsens_ops ops_8974 = {
236 .init = init_common,
237 .calibrate = calibrate_8974,
238 .get_temp = get_temp_common,
239};
240
241const struct tsens_data data_8974 = {
242 .num_sensors = 11,
243 .ops = &ops_8974,
244};
diff --git a/drivers/thermal/qcom/tsens-8996.c b/drivers/thermal/qcom/tsens-8996.c
new file mode 100644
index 000000000000..e1f77818d8fa
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8996.c
@@ -0,0 +1,84 @@
1/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/platform_device.h>
16#include <linux/regmap.h>
17#include "tsens.h"
18
19#define STATUS_OFFSET 0x10a0
20#define LAST_TEMP_MASK 0xfff
21#define STATUS_VALID_BIT BIT(21)
22#define CODE_SIGN_BIT BIT(11)
23
24static int get_temp_8996(struct tsens_device *tmdev, int id, int *temp)
25{
26 struct tsens_sensor *s = &tmdev->sensor[id];
27 u32 code;
28 unsigned int sensor_addr;
29 int last_temp = 0, last_temp2 = 0, last_temp3 = 0, ret;
30
31 sensor_addr = STATUS_OFFSET + s->hw_id * 4;
32 ret = regmap_read(tmdev->map, sensor_addr, &code);
33 if (ret)
34 return ret;
35 last_temp = code & LAST_TEMP_MASK;
36 if (code & STATUS_VALID_BIT)
37 goto done;
38
39 /* Try a second time */
40 ret = regmap_read(tmdev->map, sensor_addr, &code);
41 if (ret)
42 return ret;
43 if (code & STATUS_VALID_BIT) {
44 last_temp = code & LAST_TEMP_MASK;
45 goto done;
46 } else {
47 last_temp2 = code & LAST_TEMP_MASK;
48 }
49
50 /* Try a third/last time */
51 ret = regmap_read(tmdev->map, sensor_addr, &code);
52 if (ret)
53 return ret;
54 if (code & STATUS_VALID_BIT) {
55 last_temp = code & LAST_TEMP_MASK;
56 goto done;
57 } else {
58 last_temp3 = code & LAST_TEMP_MASK;
59 }
60
61 if (last_temp == last_temp2)
62 last_temp = last_temp2;
63 else if (last_temp2 == last_temp3)
64 last_temp = last_temp3;
65done:
66 /* Code sign bit is the sign extension for a negative value */
67 if (last_temp & CODE_SIGN_BIT)
68 last_temp |= ~CODE_SIGN_BIT;
69
70 /* Temperatures are in deciCelicius */
71 *temp = last_temp * 100;
72
73 return 0;
74}
75
76static const struct tsens_ops ops_8996 = {
77 .init = init_common,
78 .get_temp = get_temp_8996,
79};
80
81const struct tsens_data data_8996 = {
82 .num_sensors = 13,
83 .ops = &ops_8996,
84};
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
new file mode 100644
index 000000000000..b1449ad67fc0
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -0,0 +1,141 @@
1/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/err.h>
16#include <linux/io.h>
17#include <linux/nvmem-consumer.h>
18#include <linux/of_address.h>
19#include <linux/platform_device.h>
20#include <linux/regmap.h>
21#include "tsens.h"
22
23#define S0_ST_ADDR 0x1030
24#define SN_ADDR_OFFSET 0x4
25#define SN_ST_TEMP_MASK 0x3ff
26#define CAL_DEGC_PT1 30
27#define CAL_DEGC_PT2 120
28#define SLOPE_FACTOR 1000
29#define SLOPE_DEFAULT 3200
30
31char *qfprom_read(struct device *dev, const char *cname)
32{
33 struct nvmem_cell *cell;
34 ssize_t data;
35 char *ret;
36
37 cell = nvmem_cell_get(dev, cname);
38 if (IS_ERR(cell))
39 return ERR_CAST(cell);
40
41 ret = nvmem_cell_read(cell, &data);
42 nvmem_cell_put(cell);
43
44 return ret;
45}
46
47/*
48 * Use this function on devices where slope and offset calculations
49 * depend on calibration data read from qfprom. On others the slope
50 * and offset values are derived from tz->tzp->slope and tz->tzp->offset
51 * resp.
52 */
53void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
54 u32 *p2, u32 mode)
55{
56 int i;
57 int num, den;
58
59 for (i = 0; i < tmdev->num_sensors; i++) {
60 dev_dbg(tmdev->dev,
61 "sensor%d - data_point1:%#x data_point2:%#x\n",
62 i, p1[i], p2[i]);
63
64 tmdev->sensor[i].slope = SLOPE_DEFAULT;
65 if (mode == TWO_PT_CALIB) {
66 /*
67 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
68 * temp_120_degc - temp_30_degc (x2 - x1)
69 */
70 num = p2[i] - p1[i];
71 num *= SLOPE_FACTOR;
72 den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
73 tmdev->sensor[i].slope = num / den;
74 }
75
76 tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
77 (CAL_DEGC_PT1 *
78 tmdev->sensor[i].slope);
79 dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset);
80 }
81}
82
83static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
84{
85 int degc, num, den;
86
87 num = (adc_code * SLOPE_FACTOR) - s->offset;
88 den = s->slope;
89
90 if (num > 0)
91 degc = num + (den / 2);
92 else if (num < 0)
93 degc = num - (den / 2);
94 else
95 degc = num;
96
97 degc /= den;
98
99 return degc;
100}
101
102int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
103{
104 struct tsens_sensor *s = &tmdev->sensor[id];
105 u32 code;
106 unsigned int sensor_addr;
107 int last_temp = 0, ret;
108
109 sensor_addr = S0_ST_ADDR + s->hw_id * SN_ADDR_OFFSET;
110 ret = regmap_read(tmdev->map, sensor_addr, &code);
111 if (ret)
112 return ret;
113 last_temp = code & SN_ST_TEMP_MASK;
114
115 *temp = code_to_degc(last_temp, s) * 1000;
116
117 return 0;
118}
119
120static const struct regmap_config tsens_config = {
121 .reg_bits = 32,
122 .val_bits = 32,
123 .reg_stride = 4,
124};
125
126int __init init_common(struct tsens_device *tmdev)
127{
128 void __iomem *base;
129
130 base = of_iomap(tmdev->dev->of_node, 0);
131 if (!base)
132 return -EINVAL;
133
134 tmdev->map = devm_regmap_init_mmio(tmdev->dev, base, &tsens_config);
135 if (IS_ERR(tmdev->map)) {
136 iounmap(base);
137 return PTR_ERR(tmdev->map);
138 }
139
140 return 0;
141}
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
new file mode 100644
index 000000000000..3f9fe6aa51cc
--- /dev/null
+++ b/drivers/thermal/qcom/tsens.c
@@ -0,0 +1,200 @@
1/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/err.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/platform_device.h>
19#include <linux/pm.h>
20#include <linux/slab.h>
21#include <linux/thermal.h>
22#include "tsens.h"
23
24static int tsens_get_temp(void *data, int *temp)
25{
26 const struct tsens_sensor *s = data;
27 struct tsens_device *tmdev = s->tmdev;
28
29 return tmdev->ops->get_temp(tmdev, s->id, temp);
30}
31
32static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend)
33{
34 const struct tsens_sensor *s = p;
35 struct tsens_device *tmdev = s->tmdev;
36
37 if (tmdev->ops->get_trend)
38 return tmdev->ops->get_trend(tmdev, s->id, trend);
39
40 return -ENOTSUPP;
41}
42
43static int __maybe_unused tsens_suspend(struct device *dev)
44{
45 struct tsens_device *tmdev = dev_get_drvdata(dev);
46
47 if (tmdev->ops && tmdev->ops->suspend)
48 return tmdev->ops->suspend(tmdev);
49
50 return 0;
51}
52
53static int __maybe_unused tsens_resume(struct device *dev)
54{
55 struct tsens_device *tmdev = dev_get_drvdata(dev);
56
57 if (tmdev->ops && tmdev->ops->resume)
58 return tmdev->ops->resume(tmdev);
59
60 return 0;
61}
62
63static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
64
65static const struct of_device_id tsens_table[] = {
66 {
67 .compatible = "qcom,msm8916-tsens",
68 .data = &data_8916,
69 }, {
70 .compatible = "qcom,msm8974-tsens",
71 .data = &data_8974,
72 }, {
73 .compatible = "qcom,msm8996-tsens",
74 .data = &data_8996,
75 },
76 {}
77};
78MODULE_DEVICE_TABLE(of, tsens_table);
79
80static const struct thermal_zone_of_device_ops tsens_of_ops = {
81 .get_temp = tsens_get_temp,
82 .get_trend = tsens_get_trend,
83};
84
85static int tsens_register(struct tsens_device *tmdev)
86{
87 int i;
88 struct thermal_zone_device *tzd;
89 u32 *hw_id, n = tmdev->num_sensors;
90
91 hw_id = devm_kcalloc(tmdev->dev, n, sizeof(u32), GFP_KERNEL);
92 if (!hw_id)
93 return -ENOMEM;
94
95 for (i = 0; i < tmdev->num_sensors; i++) {
96 tmdev->sensor[i].tmdev = tmdev;
97 tmdev->sensor[i].id = i;
98 tzd = devm_thermal_zone_of_sensor_register(tmdev->dev, i,
99 &tmdev->sensor[i],
100 &tsens_of_ops);
101 if (IS_ERR(tzd))
102 continue;
103 tmdev->sensor[i].tzd = tzd;
104 if (tmdev->ops->enable)
105 tmdev->ops->enable(tmdev, i);
106 }
107 return 0;
108}
109
110static int tsens_probe(struct platform_device *pdev)
111{
112 int ret, i;
113 struct device *dev;
114 struct device_node *np;
115 struct tsens_sensor *s;
116 struct tsens_device *tmdev;
117 const struct tsens_data *data;
118 const struct of_device_id *id;
119
120 if (pdev->dev.of_node)
121 dev = &pdev->dev;
122 else
123 dev = pdev->dev.parent;
124
125 np = dev->of_node;
126
127 id = of_match_node(tsens_table, np);
128 if (id)
129 data = id->data;
130 else
131 data = &data_8960;
132
133 if (data->num_sensors <= 0) {
134 dev_err(dev, "invalid number of sensors\n");
135 return -EINVAL;
136 }
137
138 tmdev = devm_kzalloc(dev, sizeof(*tmdev) +
139 data->num_sensors * sizeof(*s), GFP_KERNEL);
140 if (!tmdev)
141 return -ENOMEM;
142
143 tmdev->dev = dev;
144 tmdev->num_sensors = data->num_sensors;
145 tmdev->ops = data->ops;
146 for (i = 0; i < tmdev->num_sensors; i++) {
147 if (data->hw_ids)
148 tmdev->sensor[i].hw_id = data->hw_ids[i];
149 else
150 tmdev->sensor[i].hw_id = i;
151 }
152
153 if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->get_temp)
154 return -EINVAL;
155
156 ret = tmdev->ops->init(tmdev);
157 if (ret < 0) {
158 dev_err(dev, "tsens init failed\n");
159 return ret;
160 }
161
162 if (tmdev->ops->calibrate) {
163 ret = tmdev->ops->calibrate(tmdev);
164 if (ret < 0) {
165 dev_err(dev, "tsens calibration failed\n");
166 return ret;
167 }
168 }
169
170 ret = tsens_register(tmdev);
171
172 platform_set_drvdata(pdev, tmdev);
173
174 return ret;
175}
176
177static int tsens_remove(struct platform_device *pdev)
178{
179 struct tsens_device *tmdev = platform_get_drvdata(pdev);
180
181 if (tmdev->ops->disable)
182 tmdev->ops->disable(tmdev);
183
184 return 0;
185}
186
187static struct platform_driver tsens_driver = {
188 .probe = tsens_probe,
189 .remove = tsens_remove,
190 .driver = {
191 .name = "qcom-tsens",
192 .pm = &tsens_pm_ops,
193 .of_match_table = tsens_table,
194 },
195};
196module_platform_driver(tsens_driver);
197
198MODULE_LICENSE("GPL v2");
199MODULE_DESCRIPTION("QCOM Temperature Sensor driver");
200MODULE_ALIAS("platform:qcom-tsens");
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
new file mode 100644
index 000000000000..911c1978892b
--- /dev/null
+++ b/drivers/thermal/qcom/tsens.h
@@ -0,0 +1,94 @@
1/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#ifndef __QCOM_TSENS_H__
14#define __QCOM_TSENS_H__
15
16#define ONE_PT_CALIB 0x1
17#define ONE_PT_CALIB2 0x2
18#define TWO_PT_CALIB 0x3
19
20#include <linux/thermal.h>
21
22struct tsens_device;
23
24struct tsens_sensor {
25 struct tsens_device *tmdev;
26 struct thermal_zone_device *tzd;
27 int offset;
28 int id;
29 int hw_id;
30 int slope;
31 u32 status;
32};
33
34/**
35 * struct tsens_ops - operations as supported by the tsens device
36 * @init: Function to initialize the tsens device
37 * @calibrate: Function to calibrate the tsens device
38 * @get_temp: Function which returns the temp in millidegC
39 * @enable: Function to enable (clocks/power) tsens device
40 * @disable: Function to disable the tsens device
41 * @suspend: Function to suspend the tsens device
42 * @resume: Function to resume the tsens device
43 * @get_trend: Function to get the thermal/temp trend
44 */
45struct tsens_ops {
46 /* mandatory callbacks */
47 int (*init)(struct tsens_device *);
48 int (*calibrate)(struct tsens_device *);
49 int (*get_temp)(struct tsens_device *, int, int *);
50 /* optional callbacks */
51 int (*enable)(struct tsens_device *, int);
52 void (*disable)(struct tsens_device *);
53 int (*suspend)(struct tsens_device *);
54 int (*resume)(struct tsens_device *);
55 int (*get_trend)(struct tsens_device *, int, enum thermal_trend *);
56};
57
58/**
59 * struct tsens_data - tsens instance specific data
60 * @num_sensors: Max number of sensors supported by platform
61 * @ops: operations the tsens instance supports
62 * @hw_ids: Subset of sensors ids supported by platform, if not the first n
63 */
64struct tsens_data {
65 const u32 num_sensors;
66 const struct tsens_ops *ops;
67 unsigned int *hw_ids;
68};
69
70/* Registers to be saved/restored across a context loss */
71struct tsens_context {
72 int threshold;
73 int control;
74};
75
76struct tsens_device {
77 struct device *dev;
78 u32 num_sensors;
79 struct regmap *map;
80 struct regmap_field *status_field;
81 struct tsens_context ctx;
82 bool trdy;
83 const struct tsens_ops *ops;
84 struct tsens_sensor sensor[0];
85};
86
87char *qfprom_read(struct device *, const char *);
88void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
89int init_common(struct tsens_device *);
90int get_temp_common(struct tsens_device *, int, int *);
91
92extern const struct tsens_data data_8916, data_8974, data_8960, data_8996;
93
94#endif /* __QCOM_TSENS_H__ */
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
new file mode 100644
index 000000000000..644ba526d9ea
--- /dev/null
+++ b/drivers/thermal/qoriq_thermal.c
@@ -0,0 +1,328 @@
1/*
2 * Copyright 2016 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/err.h>
18#include <linux/io.h>
19#include <linux/of.h>
20#include <linux/of_address.h>
21#include <linux/thermal.h>
22
23#include "thermal_core.h"
24
25#define SITES_MAX 16
26
27/*
28 * QorIQ TMU Registers
29 */
30struct qoriq_tmu_site_regs {
31 u32 tritsr; /* Immediate Temperature Site Register */
32 u32 tratsr; /* Average Temperature Site Register */
33 u8 res0[0x8];
34};
35
36struct qoriq_tmu_regs {
37 u32 tmr; /* Mode Register */
38#define TMR_DISABLE 0x0
39#define TMR_ME 0x80000000
40#define TMR_ALPF 0x0c000000
41 u32 tsr; /* Status Register */
42 u32 tmtmir; /* Temperature measurement interval Register */
43#define TMTMIR_DEFAULT 0x0000000f
44 u8 res0[0x14];
45 u32 tier; /* Interrupt Enable Register */
46#define TIER_DISABLE 0x0
47 u32 tidr; /* Interrupt Detect Register */
48 u32 tiscr; /* Interrupt Site Capture Register */
49 u32 ticscr; /* Interrupt Critical Site Capture Register */
50 u8 res1[0x10];
51 u32 tmhtcrh; /* High Temperature Capture Register */
52 u32 tmhtcrl; /* Low Temperature Capture Register */
53 u8 res2[0x8];
54 u32 tmhtitr; /* High Temperature Immediate Threshold */
55 u32 tmhtatr; /* High Temperature Average Threshold */
56 u32 tmhtactr; /* High Temperature Average Crit Threshold */
57 u8 res3[0x24];
58 u32 ttcfgr; /* Temperature Configuration Register */
59 u32 tscfgr; /* Sensor Configuration Register */
60 u8 res4[0x78];
61 struct qoriq_tmu_site_regs site[SITES_MAX];
62 u8 res5[0x9f8];
63 u32 ipbrr0; /* IP Block Revision Register 0 */
64 u32 ipbrr1; /* IP Block Revision Register 1 */
65 u8 res6[0x310];
66 u32 ttr0cr; /* Temperature Range 0 Control Register */
67 u32 ttr1cr; /* Temperature Range 1 Control Register */
68 u32 ttr2cr; /* Temperature Range 2 Control Register */
69 u32 ttr3cr; /* Temperature Range 3 Control Register */
70};
71
72/*
73 * Thermal zone data
74 */
75struct qoriq_tmu_data {
76 struct thermal_zone_device *tz;
77 struct qoriq_tmu_regs __iomem *regs;
78 int sensor_id;
79 bool little_endian;
80};
81
82static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem *addr)
83{
84 if (p->little_endian)
85 iowrite32(val, addr);
86 else
87 iowrite32be(val, addr);
88}
89
90static u32 tmu_read(struct qoriq_tmu_data *p, void __iomem *addr)
91{
92 if (p->little_endian)
93 return ioread32(addr);
94 else
95 return ioread32be(addr);
96}
97
98static int tmu_get_temp(void *p, int *temp)
99{
100 u32 val;
101 struct qoriq_tmu_data *data = p;
102
103 val = tmu_read(data, &data->regs->site[data->sensor_id].tritsr);
104 *temp = (val & 0xff) * 1000;
105
106 return 0;
107}
108
109static int qoriq_tmu_get_sensor_id(void)
110{
111 int ret, id;
112 struct of_phandle_args sensor_specs;
113 struct device_node *np, *sensor_np;
114
115 np = of_find_node_by_name(NULL, "thermal-zones");
116 if (!np)
117 return -ENODEV;
118
119 sensor_np = of_get_next_child(np, NULL);
120 ret = of_parse_phandle_with_args(sensor_np, "thermal-sensors",
121 "#thermal-sensor-cells",
122 0, &sensor_specs);
123 if (ret) {
124 of_node_put(np);
125 of_node_put(sensor_np);
126 return ret;
127 }
128
129 if (sensor_specs.args_count >= 1) {
130 id = sensor_specs.args[0];
131 WARN(sensor_specs.args_count > 1,
132 "%s: too many cells in sensor specifier %d\n",
133 sensor_specs.np->name, sensor_specs.args_count);
134 } else {
135 id = 0;
136 }
137
138 of_node_put(np);
139 of_node_put(sensor_np);
140
141 return id;
142}
143
144static int qoriq_tmu_calibration(struct platform_device *pdev)
145{
146 int i, val, len;
147 u32 range[4];
148 const u32 *calibration;
149 struct device_node *np = pdev->dev.of_node;
150 struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
151
152 if (of_property_read_u32_array(np, "fsl,tmu-range", range, 4)) {
153 dev_err(&pdev->dev, "missing calibration range.\n");
154 return -ENODEV;
155 }
156
157 /* Init temperature range registers */
158 tmu_write(data, range[0], &data->regs->ttr0cr);
159 tmu_write(data, range[1], &data->regs->ttr1cr);
160 tmu_write(data, range[2], &data->regs->ttr2cr);
161 tmu_write(data, range[3], &data->regs->ttr3cr);
162
163 calibration = of_get_property(np, "fsl,tmu-calibration", &len);
164 if (calibration == NULL || len % 8) {
165 dev_err(&pdev->dev, "invalid calibration data.\n");
166 return -ENODEV;
167 }
168
169 for (i = 0; i < len; i += 8, calibration += 2) {
170 val = of_read_number(calibration, 1);
171 tmu_write(data, val, &data->regs->ttcfgr);
172 val = of_read_number(calibration + 1, 1);
173 tmu_write(data, val, &data->regs->tscfgr);
174 }
175
176 return 0;
177}
178
179static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
180{
181 /* Disable interrupt, using polling instead */
182 tmu_write(data, TIER_DISABLE, &data->regs->tier);
183
184 /* Set update_interval */
185 tmu_write(data, TMTMIR_DEFAULT, &data->regs->tmtmir);
186
187 /* Disable monitoring */
188 tmu_write(data, TMR_DISABLE, &data->regs->tmr);
189}
190
191static struct thermal_zone_of_device_ops tmu_tz_ops = {
192 .get_temp = tmu_get_temp,
193};
194
195static int qoriq_tmu_probe(struct platform_device *pdev)
196{
197 int ret;
198 const struct thermal_trip *trip;
199 struct qoriq_tmu_data *data;
200 struct device_node *np = pdev->dev.of_node;
201 u32 site = 0;
202
203 if (!np) {
204 dev_err(&pdev->dev, "Device OF-Node is NULL");
205 return -ENODEV;
206 }
207
208 data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data),
209 GFP_KERNEL);
210 if (!data)
211 return -ENOMEM;
212
213 platform_set_drvdata(pdev, data);
214
215 data->little_endian = of_property_read_bool(np, "little-endian");
216
217 data->sensor_id = qoriq_tmu_get_sensor_id();
218 if (data->sensor_id < 0) {
219 dev_err(&pdev->dev, "Failed to get sensor id\n");
220 ret = -ENODEV;
221 goto err_iomap;
222 }
223
224 data->regs = of_iomap(np, 0);
225 if (!data->regs) {
226 dev_err(&pdev->dev, "Failed to get memory region\n");
227 ret = -ENODEV;
228 goto err_iomap;
229 }
230
231 qoriq_tmu_init_device(data); /* TMU initialization */
232
233 ret = qoriq_tmu_calibration(pdev); /* TMU calibration */
234 if (ret < 0)
235 goto err_tmu;
236
237 data->tz = thermal_zone_of_sensor_register(&pdev->dev, data->sensor_id,
238 data, &tmu_tz_ops);
239 if (IS_ERR(data->tz)) {
240 ret = PTR_ERR(data->tz);
241 dev_err(&pdev->dev,
242 "Failed to register thermal zone device %d\n", ret);
243 goto err_tmu;
244 }
245
246 trip = of_thermal_get_trip_points(data->tz);
247
248 /* Enable monitoring */
249 site |= 0x1 << (15 - data->sensor_id);
250 tmu_write(data, site | TMR_ME | TMR_ALPF, &data->regs->tmr);
251
252 return 0;
253
254err_tmu:
255 iounmap(data->regs);
256
257err_iomap:
258 platform_set_drvdata(pdev, NULL);
259
260 return ret;
261}
262
263static int qoriq_tmu_remove(struct platform_device *pdev)
264{
265 struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
266
267 thermal_zone_of_sensor_unregister(&pdev->dev, data->tz);
268
269 /* Disable monitoring */
270 tmu_write(data, TMR_DISABLE, &data->regs->tmr);
271
272 iounmap(data->regs);
273 platform_set_drvdata(pdev, NULL);
274
275 return 0;
276}
277
278#ifdef CONFIG_PM_SLEEP
279static int qoriq_tmu_suspend(struct device *dev)
280{
281 u32 tmr;
282 struct qoriq_tmu_data *data = dev_get_drvdata(dev);
283
284 /* Disable monitoring */
285 tmr = tmu_read(data, &data->regs->tmr);
286 tmr &= ~TMR_ME;
287 tmu_write(data, tmr, &data->regs->tmr);
288
289 return 0;
290}
291
292static int qoriq_tmu_resume(struct device *dev)
293{
294 u32 tmr;
295 struct qoriq_tmu_data *data = dev_get_drvdata(dev);
296
297 /* Enable monitoring */
298 tmr = tmu_read(data, &data->regs->tmr);
299 tmr |= TMR_ME;
300 tmu_write(data, tmr, &data->regs->tmr);
301
302 return 0;
303}
304#endif
305
306static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
307 qoriq_tmu_suspend, qoriq_tmu_resume);
308
309static const struct of_device_id qoriq_tmu_match[] = {
310 { .compatible = "fsl,qoriq-tmu", },
311 {},
312};
313MODULE_DEVICE_TABLE(of, qoriq_tmu_match);
314
315static struct platform_driver qoriq_tmu = {
316 .driver = {
317 .name = "qoriq_thermal",
318 .pm = &qoriq_tmu_pm_ops,
319 .of_match_table = qoriq_tmu_match,
320 },
321 .probe = qoriq_tmu_probe,
322 .remove = qoriq_tmu_remove,
323};
324module_platform_driver(qoriq_tmu);
325
326MODULE_AUTHOR("Jia Hongtao <hongtao.jia@nxp.com>");
327MODULE_DESCRIPTION("QorIQ Thermal Monitoring Unit driver");
328MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index 5f817923f374..73e5fee6cf1d 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -31,6 +31,8 @@
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <linux/thermal.h> 32#include <linux/thermal.h>
33 33
34#include "thermal_hwmon.h"
35
34#define IDLE_INTERVAL 5000 36#define IDLE_INTERVAL 5000
35 37
36#define COMMON_STR 0x00 38#define COMMON_STR 0x00
@@ -75,6 +77,8 @@ struct rcar_thermal_priv {
75#define rcar_priv_to_dev(priv) ((priv)->common->dev) 77#define rcar_priv_to_dev(priv) ((priv)->common->dev)
76#define rcar_has_irq_support(priv) ((priv)->common->base) 78#define rcar_has_irq_support(priv) ((priv)->common->base)
77#define rcar_id_to_shift(priv) ((priv)->id * 8) 79#define rcar_id_to_shift(priv) ((priv)->id * 8)
80#define rcar_of_data(dev) ((unsigned long)of_device_get_match_data(dev))
81#define rcar_use_of_thermal(dev) (rcar_of_data(dev) == USE_OF_THERMAL)
78 82
79#define USE_OF_THERMAL 1 83#define USE_OF_THERMAL 1
80static const struct of_device_id rcar_thermal_dt_ids[] = { 84static const struct of_device_id rcar_thermal_dt_ids[] = {
@@ -354,7 +358,8 @@ static void rcar_thermal_work(struct work_struct *work)
354 return; 358 return;
355 359
356 if (nctemp != cctemp) 360 if (nctemp != cctemp)
357 thermal_zone_device_update(priv->zone); 361 thermal_zone_device_update(priv->zone,
362 THERMAL_EVENT_UNSPECIFIED);
358} 363}
359 364
360static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status) 365static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status)
@@ -415,7 +420,10 @@ static int rcar_thermal_remove(struct platform_device *pdev)
415 420
416 rcar_thermal_for_each_priv(priv, common) { 421 rcar_thermal_for_each_priv(priv, common) {
417 rcar_thermal_irq_disable(priv); 422 rcar_thermal_irq_disable(priv);
418 thermal_zone_device_unregister(priv->zone); 423 if (rcar_use_of_thermal(dev))
424 thermal_remove_hwmon_sysfs(priv->zone);
425 else
426 thermal_zone_device_unregister(priv->zone);
419 } 427 }
420 428
421 pm_runtime_put(dev); 429 pm_runtime_put(dev);
@@ -430,7 +438,6 @@ static int rcar_thermal_probe(struct platform_device *pdev)
430 struct rcar_thermal_priv *priv; 438 struct rcar_thermal_priv *priv;
431 struct device *dev = &pdev->dev; 439 struct device *dev = &pdev->dev;
432 struct resource *res, *irq; 440 struct resource *res, *irq;
433 unsigned long of_data = (unsigned long)of_device_get_match_data(dev);
434 int mres = 0; 441 int mres = 0;
435 int i; 442 int i;
436 int ret = -ENODEV; 443 int ret = -ENODEV;
@@ -491,7 +498,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
491 if (ret < 0) 498 if (ret < 0)
492 goto error_unregister; 499 goto error_unregister;
493 500
494 if (of_data == USE_OF_THERMAL) 501 if (rcar_use_of_thermal(dev))
495 priv->zone = devm_thermal_zone_of_sensor_register( 502 priv->zone = devm_thermal_zone_of_sensor_register(
496 dev, i, priv, 503 dev, i, priv,
497 &rcar_thermal_zone_of_ops); 504 &rcar_thermal_zone_of_ops);
@@ -508,6 +515,17 @@ static int rcar_thermal_probe(struct platform_device *pdev)
508 goto error_unregister; 515 goto error_unregister;
509 } 516 }
510 517
518 if (rcar_use_of_thermal(dev)) {
519 /*
520 * thermal_zone doesn't enable hwmon as default,
521 * but, enable it here to keep compatible
522 */
523 priv->zone->tzp->no_hwmon = false;
524 ret = thermal_add_hwmon_sysfs(priv->zone);
525 if (ret)
526 goto error_unregister;
527 }
528
511 rcar_thermal_irq_enable(priv); 529 rcar_thermal_irq_enable(priv);
512 530
513 list_move_tail(&priv->list, &common->head); 531 list_move_tail(&priv->list, &common->head);
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 5d491f16a866..e227a9f0acf7 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -96,6 +96,7 @@ struct chip_tsadc_table {
96 * @initialize: SoC special initialize tsadc controller method 96 * @initialize: SoC special initialize tsadc controller method
97 * @irq_ack: clear the interrupt 97 * @irq_ack: clear the interrupt
98 * @get_temp: get the temperature 98 * @get_temp: get the temperature
99 * @set_alarm_temp: set the high temperature interrupt
99 * @set_tshut_temp: set the hardware-controlled shutdown temperature 100 * @set_tshut_temp: set the hardware-controlled shutdown temperature
100 * @set_tshut_mode: set the hardware-controlled shutdown mode 101 * @set_tshut_mode: set the hardware-controlled shutdown mode
101 * @table: the chip-specific conversion table 102 * @table: the chip-specific conversion table
@@ -119,6 +120,8 @@ struct rockchip_tsadc_chip {
119 /* Per-sensor methods */ 120 /* Per-sensor methods */
120 int (*get_temp)(struct chip_tsadc_table table, 121 int (*get_temp)(struct chip_tsadc_table table,
121 int chn, void __iomem *reg, int *temp); 122 int chn, void __iomem *reg, int *temp);
123 void (*set_alarm_temp)(struct chip_tsadc_table table,
124 int chn, void __iomem *reg, int temp);
122 void (*set_tshut_temp)(struct chip_tsadc_table table, 125 void (*set_tshut_temp)(struct chip_tsadc_table table,
123 int chn, void __iomem *reg, int temp); 126 int chn, void __iomem *reg, int temp);
124 void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m); 127 void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
@@ -183,6 +186,7 @@ struct rockchip_thermal_data {
183#define TSADCV2_INT_EN 0x08 186#define TSADCV2_INT_EN 0x08
184#define TSADCV2_INT_PD 0x0c 187#define TSADCV2_INT_PD 0x0c
185#define TSADCV2_DATA(chn) (0x20 + (chn) * 0x04) 188#define TSADCV2_DATA(chn) (0x20 + (chn) * 0x04)
189#define TSADCV2_COMP_INT(chn) (0x30 + (chn) * 0x04)
186#define TSADCV2_COMP_SHUT(chn) (0x40 + (chn) * 0x04) 190#define TSADCV2_COMP_SHUT(chn) (0x40 + (chn) * 0x04)
187#define TSADCV2_HIGHT_INT_DEBOUNCE 0x60 191#define TSADCV2_HIGHT_INT_DEBOUNCE 0x60
188#define TSADCV2_HIGHT_TSHUT_DEBOUNCE 0x64 192#define TSADCV2_HIGHT_TSHUT_DEBOUNCE 0x64
@@ -207,18 +211,21 @@ struct rockchip_thermal_data {
207 211
208#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4 212#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4
209#define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4 213#define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4
210#define TSADCV2_AUTO_PERIOD_TIME 250 /* msec */ 214#define TSADCV2_AUTO_PERIOD_TIME 250 /* 250ms */
211#define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* msec */ 215#define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* 50ms */
216#define TSADCV3_AUTO_PERIOD_TIME 1875 /* 2.5ms */
217#define TSADCV3_AUTO_PERIOD_HT_TIME 1875 /* 2.5ms */
218
212#define TSADCV2_USER_INTER_PD_SOC 0x340 /* 13 clocks */ 219#define TSADCV2_USER_INTER_PD_SOC 0x340 /* 13 clocks */
213 220
214#define GRF_SARADC_TESTBIT 0x0e644 221#define GRF_SARADC_TESTBIT 0x0e644
215#define GRF_TSADC_TESTBIT_L 0x0e648 222#define GRF_TSADC_TESTBIT_L 0x0e648
216#define GRF_TSADC_TESTBIT_H 0x0e64c 223#define GRF_TSADC_TESTBIT_H 0x0e64c
217 224
218#define GRF_TSADC_TSEN_PD_ON (0x30003 << 0)
219#define GRF_TSADC_TSEN_PD_OFF (0x30000 << 0)
220#define GRF_SARADC_TESTBIT_ON (0x10001 << 2) 225#define GRF_SARADC_TESTBIT_ON (0x10001 << 2)
221#define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2) 226#define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
227#define GRF_TSADC_VCM_EN_L (0x10001 << 7)
228#define GRF_TSADC_VCM_EN_H (0x10001 << 7)
222 229
223/** 230/**
224 * struct tsadc_table - code to temperature conversion table 231 * struct tsadc_table - code to temperature conversion table
@@ -394,13 +401,17 @@ static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table,
394 int temp) 401 int temp)
395{ 402{
396 int high, low, mid; 403 int high, low, mid;
404 u32 error = 0;
397 405
398 low = 0; 406 low = 0;
399 high = table.length - 1; 407 high = table.length - 1;
400 mid = (high + low) / 2; 408 mid = (high + low) / 2;
401 409
402 if (temp < table.id[low].temp || temp > table.id[high].temp) 410 /* Return mask code data when the temp is over table range */
403 return 0; 411 if (temp < table.id[low].temp || temp > table.id[high].temp) {
412 error = table.data_mask;
413 goto exit;
414 }
404 415
405 while (low <= high) { 416 while (low <= high) {
406 if (temp == table.id[mid].temp) 417 if (temp == table.id[mid].temp)
@@ -412,7 +423,9 @@ static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table,
412 mid = (low + high) / 2; 423 mid = (low + high) / 2;
413 } 424 }
414 425
415 return 0; 426exit:
427 pr_err("Invalid the conversion, error=%d\n", error);
428 return error;
416} 429}
417 430
418static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, 431static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
@@ -543,14 +556,34 @@ static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs,
543 /* Set interleave value to workround ic time sync issue */ 556 /* Set interleave value to workround ic time sync issue */
544 writel_relaxed(TSADCV2_USER_INTER_PD_SOC, regs + 557 writel_relaxed(TSADCV2_USER_INTER_PD_SOC, regs +
545 TSADCV2_USER_CON); 558 TSADCV2_USER_CON);
559
560 writel_relaxed(TSADCV2_AUTO_PERIOD_TIME,
561 regs + TSADCV2_AUTO_PERIOD);
562 writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
563 regs + TSADCV2_HIGHT_INT_DEBOUNCE);
564 writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME,
565 regs + TSADCV2_AUTO_PERIOD_HT);
566 writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
567 regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
568
546 } else { 569 } else {
547 regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_ON); 570 /* Enable the voltage common mode feature */
548 mdelay(10); 571 regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_VCM_EN_L);
549 regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_OFF); 572 regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_VCM_EN_H);
573
550 usleep_range(15, 100); /* The spec note says at least 15 us */ 574 usleep_range(15, 100); /* The spec note says at least 15 us */
551 regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON); 575 regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON);
552 regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON); 576 regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON);
553 usleep_range(90, 200); /* The spec note says at least 90 us */ 577 usleep_range(90, 200); /* The spec note says at least 90 us */
578
579 writel_relaxed(TSADCV3_AUTO_PERIOD_TIME,
580 regs + TSADCV2_AUTO_PERIOD);
581 writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
582 regs + TSADCV2_HIGHT_INT_DEBOUNCE);
583 writel_relaxed(TSADCV3_AUTO_PERIOD_HT_TIME,
584 regs + TSADCV2_AUTO_PERIOD_HT);
585 writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
586 regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
554 } 587 }
555 588
556 if (tshut_polarity == TSHUT_HIGH_ACTIVE) 589 if (tshut_polarity == TSHUT_HIGH_ACTIVE)
@@ -559,14 +592,6 @@ static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs,
559 else 592 else
560 writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, 593 writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
561 regs + TSADCV2_AUTO_CON); 594 regs + TSADCV2_AUTO_CON);
562
563 writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
564 writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
565 regs + TSADCV2_HIGHT_INT_DEBOUNCE);
566 writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME,
567 regs + TSADCV2_AUTO_PERIOD_HT);
568 writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
569 regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
570} 595}
571 596
572static void rk_tsadcv2_irq_ack(void __iomem *regs) 597static void rk_tsadcv2_irq_ack(void __iomem *regs)
@@ -628,12 +653,34 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
628 return rk_tsadcv2_code_to_temp(table, val, temp); 653 return rk_tsadcv2_code_to_temp(table, val, temp);
629} 654}
630 655
656static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table,
657 int chn, void __iomem *regs, int temp)
658{
659 u32 alarm_value, int_en;
660
661 /* Make sure the value is valid */
662 alarm_value = rk_tsadcv2_temp_to_code(table, temp);
663 if (alarm_value == table.data_mask)
664 return;
665
666 writel_relaxed(alarm_value & table.data_mask,
667 regs + TSADCV2_COMP_INT(chn));
668
669 int_en = readl_relaxed(regs + TSADCV2_INT_EN);
670 int_en |= TSADCV2_INT_SRC_EN(chn);
671 writel_relaxed(int_en, regs + TSADCV2_INT_EN);
672}
673
631static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table, 674static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table,
632 int chn, void __iomem *regs, int temp) 675 int chn, void __iomem *regs, int temp)
633{ 676{
634 u32 tshut_value, val; 677 u32 tshut_value, val;
635 678
679 /* Make sure the value is valid */
636 tshut_value = rk_tsadcv2_temp_to_code(table, temp); 680 tshut_value = rk_tsadcv2_temp_to_code(table, temp);
681 if (tshut_value == table.data_mask)
682 return;
683
637 writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn)); 684 writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn));
638 685
639 /* TSHUT will be valid */ 686 /* TSHUT will be valid */
@@ -670,6 +717,7 @@ static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
670 .irq_ack = rk_tsadcv3_irq_ack, 717 .irq_ack = rk_tsadcv3_irq_ack,
671 .control = rk_tsadcv3_control, 718 .control = rk_tsadcv3_control,
672 .get_temp = rk_tsadcv2_get_temp, 719 .get_temp = rk_tsadcv2_get_temp,
720 .set_alarm_temp = rk_tsadcv2_alarm_temp,
673 .set_tshut_temp = rk_tsadcv2_tshut_temp, 721 .set_tshut_temp = rk_tsadcv2_tshut_temp,
674 .set_tshut_mode = rk_tsadcv2_tshut_mode, 722 .set_tshut_mode = rk_tsadcv2_tshut_mode,
675 723
@@ -694,6 +742,7 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
694 .irq_ack = rk_tsadcv2_irq_ack, 742 .irq_ack = rk_tsadcv2_irq_ack,
695 .control = rk_tsadcv2_control, 743 .control = rk_tsadcv2_control,
696 .get_temp = rk_tsadcv2_get_temp, 744 .get_temp = rk_tsadcv2_get_temp,
745 .set_alarm_temp = rk_tsadcv2_alarm_temp,
697 .set_tshut_temp = rk_tsadcv2_tshut_temp, 746 .set_tshut_temp = rk_tsadcv2_tshut_temp,
698 .set_tshut_mode = rk_tsadcv2_tshut_mode, 747 .set_tshut_mode = rk_tsadcv2_tshut_mode,
699 748
@@ -718,6 +767,7 @@ static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
718 .irq_ack = rk_tsadcv3_irq_ack, 767 .irq_ack = rk_tsadcv3_irq_ack,
719 .control = rk_tsadcv3_control, 768 .control = rk_tsadcv3_control,
720 .get_temp = rk_tsadcv2_get_temp, 769 .get_temp = rk_tsadcv2_get_temp,
770 .set_alarm_temp = rk_tsadcv2_alarm_temp,
721 .set_tshut_temp = rk_tsadcv2_tshut_temp, 771 .set_tshut_temp = rk_tsadcv2_tshut_temp,
722 .set_tshut_mode = rk_tsadcv2_tshut_mode, 772 .set_tshut_mode = rk_tsadcv2_tshut_mode,
723 773
@@ -742,6 +792,7 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
742 .irq_ack = rk_tsadcv2_irq_ack, 792 .irq_ack = rk_tsadcv2_irq_ack,
743 .control = rk_tsadcv2_control, 793 .control = rk_tsadcv2_control,
744 .get_temp = rk_tsadcv2_get_temp, 794 .get_temp = rk_tsadcv2_get_temp,
795 .set_alarm_temp = rk_tsadcv2_alarm_temp,
745 .set_tshut_temp = rk_tsadcv2_tshut_temp, 796 .set_tshut_temp = rk_tsadcv2_tshut_temp,
746 .set_tshut_mode = rk_tsadcv2_tshut_mode, 797 .set_tshut_mode = rk_tsadcv2_tshut_mode,
747 798
@@ -766,6 +817,7 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
766 .irq_ack = rk_tsadcv3_irq_ack, 817 .irq_ack = rk_tsadcv3_irq_ack,
767 .control = rk_tsadcv3_control, 818 .control = rk_tsadcv3_control,
768 .get_temp = rk_tsadcv2_get_temp, 819 .get_temp = rk_tsadcv2_get_temp,
820 .set_alarm_temp = rk_tsadcv2_alarm_temp,
769 .set_tshut_temp = rk_tsadcv2_tshut_temp, 821 .set_tshut_temp = rk_tsadcv2_tshut_temp,
770 .set_tshut_mode = rk_tsadcv2_tshut_mode, 822 .set_tshut_mode = rk_tsadcv2_tshut_mode,
771 823
@@ -821,11 +873,27 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
821 thermal->chip->irq_ack(thermal->regs); 873 thermal->chip->irq_ack(thermal->regs);
822 874
823 for (i = 0; i < thermal->chip->chn_num; i++) 875 for (i = 0; i < thermal->chip->chn_num; i++)
824 thermal_zone_device_update(thermal->sensors[i].tzd); 876 thermal_zone_device_update(thermal->sensors[i].tzd,
877 THERMAL_EVENT_UNSPECIFIED);
825 878
826 return IRQ_HANDLED; 879 return IRQ_HANDLED;
827} 880}
828 881
882static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
883{
884 struct rockchip_thermal_sensor *sensor = _sensor;
885 struct rockchip_thermal_data *thermal = sensor->thermal;
886 const struct rockchip_tsadc_chip *tsadc = thermal->chip;
887
888 dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
889 __func__, sensor->id, low, high);
890
891 tsadc->set_alarm_temp(tsadc->table,
892 sensor->id, thermal->regs, high);
893
894 return 0;
895}
896
829static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) 897static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
830{ 898{
831 struct rockchip_thermal_sensor *sensor = _sensor; 899 struct rockchip_thermal_sensor *sensor = _sensor;
@@ -843,6 +911,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
843 911
844static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = { 912static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
845 .get_temp = rockchip_thermal_get_temp, 913 .get_temp = rockchip_thermal_get_temp,
914 .set_trips = rockchip_thermal_set_trips,
846}; 915};
847 916
848static int rockchip_configure_from_dt(struct device *dev, 917static int rockchip_configure_from_dt(struct device *dev,
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index f3ce94ec73b5..ad1186dd6132 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -225,7 +225,7 @@ static void exynos_report_trigger(struct exynos_tmu_data *p)
225 return; 225 return;
226 } 226 }
227 227
228 thermal_zone_device_update(tz); 228 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
229 229
230 mutex_lock(&tz->lock); 230 mutex_lock(&tz->lock);
231 /* Find the level for which trip happened */ 231 /* Find the level for which trip happened */
diff --git a/drivers/thermal/st/st_thermal_memmap.c b/drivers/thermal/st/st_thermal_memmap.c
index fc0c9e198710..91d42319de27 100644
--- a/drivers/thermal/st/st_thermal_memmap.c
+++ b/drivers/thermal/st/st_thermal_memmap.c
@@ -42,7 +42,8 @@ static irqreturn_t st_mmap_thermal_trip_handler(int irq, void *sdata)
42{ 42{
43 struct st_thermal_sensor *sensor = sdata; 43 struct st_thermal_sensor *sensor = sdata;
44 44
45 thermal_zone_device_update(sensor->thermal_dev); 45 thermal_zone_device_update(sensor->thermal_dev,
46 THERMAL_EVENT_UNSPECIFIED);
46 47
47 return IRQ_HANDLED; 48 return IRQ_HANDLED;
48} 49}
diff --git a/drivers/thermal/tango_thermal.c b/drivers/thermal/tango_thermal.c
index 70e0d9f406e9..201304aeafeb 100644
--- a/drivers/thermal/tango_thermal.c
+++ b/drivers/thermal/tango_thermal.c
@@ -64,6 +64,12 @@ static const struct thermal_zone_of_device_ops ops = {
64 .get_temp = tango_get_temp, 64 .get_temp = tango_get_temp,
65}; 65};
66 66
67static void tango_thermal_init(struct tango_thermal_priv *priv)
68{
69 writel(0, priv->base + TEMPSI_CFG);
70 writel(CMD_ON, priv->base + TEMPSI_CMD);
71}
72
67static int tango_thermal_probe(struct platform_device *pdev) 73static int tango_thermal_probe(struct platform_device *pdev)
68{ 74{
69 struct resource *res; 75 struct resource *res;
@@ -79,14 +85,22 @@ static int tango_thermal_probe(struct platform_device *pdev)
79 if (IS_ERR(priv->base)) 85 if (IS_ERR(priv->base))
80 return PTR_ERR(priv->base); 86 return PTR_ERR(priv->base);
81 87
88 platform_set_drvdata(pdev, priv);
82 priv->thresh_idx = IDX_MIN; 89 priv->thresh_idx = IDX_MIN;
83 writel(0, priv->base + TEMPSI_CFG); 90 tango_thermal_init(priv);
84 writel(CMD_ON, priv->base + TEMPSI_CMD);
85 91
86 tzdev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &ops); 92 tzdev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &ops);
87 return PTR_ERR_OR_ZERO(tzdev); 93 return PTR_ERR_OR_ZERO(tzdev);
88} 94}
89 95
96static int __maybe_unused tango_thermal_resume(struct device *dev)
97{
98 tango_thermal_init(dev_get_drvdata(dev));
99 return 0;
100}
101
102static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume);
103
90static const struct of_device_id tango_sensor_ids[] = { 104static const struct of_device_id tango_sensor_ids[] = {
91 { 105 {
92 .compatible = "sigma,smp8758-thermal", 106 .compatible = "sigma,smp8758-thermal",
@@ -99,6 +113,7 @@ static struct platform_driver tango_thermal_driver = {
99 .driver = { 113 .driver = {
100 .name = "tango-thermal", 114 .name = "tango-thermal",
101 .of_match_table = tango_sensor_ids, 115 .of_match_table = tango_sensor_ids,
116 .pm = &tango_thermal_pm,
102 }, 117 },
103}; 118};
104 119
diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c
index b8651726201e..7d2db23d71a3 100644
--- a/drivers/thermal/tegra/soctherm.c
+++ b/drivers/thermal/tegra/soctherm.c
@@ -30,6 +30,7 @@
30 30
31#include <dt-bindings/thermal/tegra124-soctherm.h> 31#include <dt-bindings/thermal/tegra124-soctherm.h>
32 32
33#include "../thermal_core.h"
33#include "soctherm.h" 34#include "soctherm.h"
34 35
35#define SENSOR_CONFIG0 0 36#define SENSOR_CONFIG0 0
@@ -67,35 +68,228 @@
67#define READBACK_ADD_HALF BIT(7) 68#define READBACK_ADD_HALF BIT(7)
68#define READBACK_NEGATE BIT(0) 69#define READBACK_NEGATE BIT(0)
69 70
71/*
72 * THERMCTL_LEVEL0_GROUP_CPU is defined in soctherm.h
73 * because it will be used by tegraxxx_soctherm.c
74 */
75#define THERMCTL_LVL0_CPU0_EN_MASK BIT(8)
76#define THERMCTL_LVL0_CPU0_CPU_THROT_MASK (0x3 << 5)
77#define THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT 0x1
78#define THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY 0x2
79#define THERMCTL_LVL0_CPU0_GPU_THROT_MASK (0x3 << 3)
80#define THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT 0x1
81#define THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY 0x2
82#define THERMCTL_LVL0_CPU0_MEM_THROT_MASK BIT(2)
83#define THERMCTL_LVL0_CPU0_STATUS_MASK 0x3
84
85#define THERMCTL_LVL0_UP_STATS 0x10
86#define THERMCTL_LVL0_DN_STATS 0x14
87
88#define THERMCTL_STATS_CTL 0x94
89#define STATS_CTL_CLR_DN 0x8
90#define STATS_CTL_EN_DN 0x4
91#define STATS_CTL_CLR_UP 0x2
92#define STATS_CTL_EN_UP 0x1
93
94#define THROT_GLOBAL_CFG 0x400
95#define THROT_GLOBAL_ENB_MASK BIT(0)
96
97#define CPU_PSKIP_STATUS 0x418
98#define XPU_PSKIP_STATUS_M_MASK (0xff << 12)
99#define XPU_PSKIP_STATUS_N_MASK (0xff << 4)
100#define XPU_PSKIP_STATUS_SW_OVERRIDE_MASK BIT(1)
101#define XPU_PSKIP_STATUS_ENABLED_MASK BIT(0)
102
103#define THROT_PRIORITY_LOCK 0x424
104#define THROT_PRIORITY_LOCK_PRIORITY_MASK 0xff
105
106#define THROT_STATUS 0x428
107#define THROT_STATUS_BREACH_MASK BIT(12)
108#define THROT_STATUS_STATE_MASK (0xff << 4)
109#define THROT_STATUS_ENABLED_MASK BIT(0)
110
111#define THROT_PSKIP_CTRL_LITE_CPU 0x430
112#define THROT_PSKIP_CTRL_ENABLE_MASK BIT(31)
113#define THROT_PSKIP_CTRL_DIVIDEND_MASK (0xff << 8)
114#define THROT_PSKIP_CTRL_DIVISOR_MASK 0xff
115#define THROT_PSKIP_CTRL_VECT_GPU_MASK (0x7 << 16)
116#define THROT_PSKIP_CTRL_VECT_CPU_MASK (0x7 << 8)
117#define THROT_PSKIP_CTRL_VECT2_CPU_MASK 0x7
118
119#define THROT_VECT_NONE 0x0 /* 3'b000 */
120#define THROT_VECT_LOW 0x1 /* 3'b001 */
121#define THROT_VECT_MED 0x3 /* 3'b011 */
122#define THROT_VECT_HIGH 0x7 /* 3'b111 */
123
124#define THROT_PSKIP_RAMP_LITE_CPU 0x434
125#define THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK BIT(31)
126#define THROT_PSKIP_RAMP_DURATION_MASK (0xffff << 8)
127#define THROT_PSKIP_RAMP_STEP_MASK 0xff
128
129#define THROT_PRIORITY_LITE 0x444
130#define THROT_PRIORITY_LITE_PRIO_MASK 0xff
131
132#define THROT_DELAY_LITE 0x448
133#define THROT_DELAY_LITE_DELAY_MASK 0xff
134
135/* car register offsets needed for enabling HW throttling */
136#define CAR_SUPER_CCLKG_DIVIDER 0x36c
137#define CDIVG_USE_THERM_CONTROLS_MASK BIT(30)
138
139/* ccroc register offsets needed for enabling HW throttling for Tegra132 */
140#define CCROC_SUPER_CCLKG_DIVIDER 0x024
141
142#define CCROC_GLOBAL_CFG 0x148
143
144#define CCROC_THROT_PSKIP_RAMP_CPU 0x150
145#define CCROC_THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK BIT(31)
146#define CCROC_THROT_PSKIP_RAMP_DURATION_MASK (0xffff << 8)
147#define CCROC_THROT_PSKIP_RAMP_STEP_MASK 0xff
148
149#define CCROC_THROT_PSKIP_CTRL_CPU 0x154
150#define CCROC_THROT_PSKIP_CTRL_ENB_MASK BIT(31)
151#define CCROC_THROT_PSKIP_CTRL_DIVIDEND_MASK (0xff << 8)
152#define CCROC_THROT_PSKIP_CTRL_DIVISOR_MASK 0xff
153
70/* get val from register(r) mask bits(m) */ 154/* get val from register(r) mask bits(m) */
71#define REG_GET_MASK(r, m) (((r) & (m)) >> (ffs(m) - 1)) 155#define REG_GET_MASK(r, m) (((r) & (m)) >> (ffs(m) - 1))
72/* set val(v) to mask bits(m) of register(r) */ 156/* set val(v) to mask bits(m) of register(r) */
73#define REG_SET_MASK(r, m, v) (((r) & ~(m)) | \ 157#define REG_SET_MASK(r, m, v) (((r) & ~(m)) | \
74 (((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1))) 158 (((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1)))
75 159
160/* get dividend from the depth */
161#define THROT_DEPTH_DIVIDEND(depth) ((256 * (100 - (depth)) / 100) - 1)
162
163/* get THROT_PSKIP_xxx offset per LIGHT/HEAVY throt and CPU/GPU dev */
164#define THROT_OFFSET 0x30
165#define THROT_PSKIP_CTRL(throt, dev) (THROT_PSKIP_CTRL_LITE_CPU + \
166 (THROT_OFFSET * throt) + (8 * dev))
167#define THROT_PSKIP_RAMP(throt, dev) (THROT_PSKIP_RAMP_LITE_CPU + \
168 (THROT_OFFSET * throt) + (8 * dev))
169
170/* get THROT_xxx_CTRL offset per LIGHT/HEAVY throt */
171#define THROT_PRIORITY_CTRL(throt) (THROT_PRIORITY_LITE + \
172 (THROT_OFFSET * throt))
173#define THROT_DELAY_CTRL(throt) (THROT_DELAY_LITE + \
174 (THROT_OFFSET * throt))
175
176/* get CCROC_THROT_PSKIP_xxx offset per HIGH/MED/LOW vect*/
177#define CCROC_THROT_OFFSET 0x0c
178#define CCROC_THROT_PSKIP_CTRL_CPU_REG(vect) (CCROC_THROT_PSKIP_CTRL_CPU + \
179 (CCROC_THROT_OFFSET * vect))
180#define CCROC_THROT_PSKIP_RAMP_CPU_REG(vect) (CCROC_THROT_PSKIP_RAMP_CPU + \
181 (CCROC_THROT_OFFSET * vect))
182
183/* get THERMCTL_LEVELx offset per CPU/GPU/MEM/TSENSE rg and LEVEL0~3 lv */
184#define THERMCTL_LVL_REGS_SIZE 0x20
185#define THERMCTL_LVL_REG(rg, lv) ((rg) + ((lv) * THERMCTL_LVL_REGS_SIZE))
186
76static const int min_low_temp = -127000; 187static const int min_low_temp = -127000;
77static const int max_high_temp = 127000; 188static const int max_high_temp = 127000;
78 189
190enum soctherm_throttle_id {
191 THROTTLE_LIGHT = 0,
192 THROTTLE_HEAVY,
193 THROTTLE_SIZE,
194};
195
196enum soctherm_throttle_dev_id {
197 THROTTLE_DEV_CPU = 0,
198 THROTTLE_DEV_GPU,
199 THROTTLE_DEV_SIZE,
200};
201
202static const char *const throt_names[] = {
203 [THROTTLE_LIGHT] = "light",
204 [THROTTLE_HEAVY] = "heavy",
205};
206
207struct tegra_soctherm;
79struct tegra_thermctl_zone { 208struct tegra_thermctl_zone {
80 void __iomem *reg; 209 void __iomem *reg;
81 struct device *dev; 210 struct device *dev;
211 struct tegra_soctherm *ts;
82 struct thermal_zone_device *tz; 212 struct thermal_zone_device *tz;
83 const struct tegra_tsensor_group *sg; 213 const struct tegra_tsensor_group *sg;
84}; 214};
85 215
216struct soctherm_throt_cfg {
217 const char *name;
218 unsigned int id;
219 u8 priority;
220 u8 cpu_throt_level;
221 u32 cpu_throt_depth;
222 struct thermal_cooling_device *cdev;
223 bool init;
224};
225
86struct tegra_soctherm { 226struct tegra_soctherm {
87 struct reset_control *reset; 227 struct reset_control *reset;
88 struct clk *clock_tsensor; 228 struct clk *clock_tsensor;
89 struct clk *clock_soctherm; 229 struct clk *clock_soctherm;
90 void __iomem *regs; 230 void __iomem *regs;
91 struct thermal_zone_device **thermctl_tzs; 231 void __iomem *clk_regs;
232 void __iomem *ccroc_regs;
92 233
93 u32 *calib; 234 u32 *calib;
235 struct thermal_zone_device **thermctl_tzs;
94 struct tegra_soctherm_soc *soc; 236 struct tegra_soctherm_soc *soc;
95 237
238 struct soctherm_throt_cfg throt_cfgs[THROTTLE_SIZE];
239
96 struct dentry *debugfs_dir; 240 struct dentry *debugfs_dir;
97}; 241};
98 242
243/**
244 * clk_writel() - writes a value to a CAR register
245 * @ts: pointer to a struct tegra_soctherm
246 * @v: the value to write
247 * @reg: the register offset
248 *
249 * Writes @v to @reg. No return value.
250 */
251static inline void clk_writel(struct tegra_soctherm *ts, u32 value, u32 reg)
252{
253 writel(value, (ts->clk_regs + reg));
254}
255
256/**
257 * clk_readl() - reads specified register from CAR IP block
258 * @ts: pointer to a struct tegra_soctherm
259 * @reg: register address to be read
260 *
261 * Return: the value of the register
262 */
263static inline u32 clk_readl(struct tegra_soctherm *ts, u32 reg)
264{
265 return readl(ts->clk_regs + reg);
266}
267
268/**
269 * ccroc_writel() - writes a value to a CCROC register
270 * @ts: pointer to a struct tegra_soctherm
271 * @v: the value to write
272 * @reg: the register offset
273 *
274 * Writes @v to @reg. No return value.
275 */
276static inline void ccroc_writel(struct tegra_soctherm *ts, u32 value, u32 reg)
277{
278 writel(value, (ts->ccroc_regs + reg));
279}
280
281/**
282 * ccroc_readl() - reads specified register from CCROC IP block
283 * @ts: pointer to a struct tegra_soctherm
284 * @reg: register address to be read
285 *
286 * Return: the value of the register
287 */
288static inline u32 ccroc_readl(struct tegra_soctherm *ts, u32 reg)
289{
290 return readl(ts->ccroc_regs + reg);
291}
292
99static void enable_tsensor(struct tegra_soctherm *tegra, unsigned int i) 293static void enable_tsensor(struct tegra_soctherm *tegra, unsigned int i)
100{ 294{
101 const struct tegra_tsensor *sensor = &tegra->soc->tsensors[i]; 295 const struct tegra_tsensor *sensor = &tegra->soc->tsensors[i];
@@ -150,11 +344,17 @@ static int tegra_thermctl_get_temp(void *data, int *out_temp)
150static int 344static int
151thermtrip_program(struct device *dev, const struct tegra_tsensor_group *sg, 345thermtrip_program(struct device *dev, const struct tegra_tsensor_group *sg,
152 int trip_temp); 346 int trip_temp);
347static int
348throttrip_program(struct device *dev, const struct tegra_tsensor_group *sg,
349 struct soctherm_throt_cfg *stc, int trip_temp);
350static struct soctherm_throt_cfg *
351find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name);
153 352
154static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) 353static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
155{ 354{
156 struct tegra_thermctl_zone *zone = data; 355 struct tegra_thermctl_zone *zone = data;
157 struct thermal_zone_device *tz = zone->tz; 356 struct thermal_zone_device *tz = zone->tz;
357 struct tegra_soctherm *ts = zone->ts;
158 const struct tegra_tsensor_group *sg = zone->sg; 358 const struct tegra_tsensor_group *sg = zone->sg;
159 struct device *dev = zone->dev; 359 struct device *dev = zone->dev;
160 enum thermal_trip_type type; 360 enum thermal_trip_type type;
@@ -167,10 +367,29 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
167 if (ret) 367 if (ret)
168 return ret; 368 return ret;
169 369
170 if (type != THERMAL_TRIP_CRITICAL) 370 if (type == THERMAL_TRIP_CRITICAL) {
171 return 0; 371 return thermtrip_program(dev, sg, temp);
372 } else if (type == THERMAL_TRIP_HOT) {
373 int i;
374
375 for (i = 0; i < THROTTLE_SIZE; i++) {
376 struct thermal_cooling_device *cdev;
377 struct soctherm_throt_cfg *stc;
378
379 if (!ts->throt_cfgs[i].init)
380 continue;
381
382 cdev = ts->throt_cfgs[i].cdev;
383 if (get_thermal_instance(tz, cdev, trip))
384 stc = find_throttle_cfg_by_name(ts, cdev->type);
385 else
386 continue;
387
388 return throttrip_program(dev, sg, stc, temp);
389 }
390 }
172 391
173 return thermtrip_program(dev, sg, temp); 392 return 0;
174} 393}
175 394
176static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = { 395static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
@@ -238,14 +457,110 @@ static int thermtrip_program(struct device *dev,
238} 457}
239 458
240/** 459/**
460 * throttrip_program() - Configures the hardware to throttle the
461 * pulse if a given sensor group reaches a given temperature
462 * @dev: ptr to the struct device for the SOC_THERM IP block
463 * @sg: pointer to the sensor group to set the thermtrip temperature for
464 * @stc: pointer to the throttle need to be triggered
465 * @trip_temp: the temperature in millicelsius to trigger the thermal trip at
466 *
467 * Sets the thermal trip threshold and throttle event of the given sensor
468 * group. If this threshold is crossed, the hardware will trigger the
469 * throttle.
470 *
471 * Note that, although @trip_temp is specified in millicelsius, the
472 * hardware is programmed in degrees Celsius.
473 *
474 * Return: 0 upon success, or %-EINVAL upon failure.
475 */
476static int throttrip_program(struct device *dev,
477 const struct tegra_tsensor_group *sg,
478 struct soctherm_throt_cfg *stc,
479 int trip_temp)
480{
481 struct tegra_soctherm *ts = dev_get_drvdata(dev);
482 int temp, cpu_throt, gpu_throt;
483 unsigned int throt;
484 u32 r, reg_off;
485
486 if (!dev || !sg || !stc || !stc->init)
487 return -EINVAL;
488
489 temp = enforce_temp_range(dev, trip_temp) / ts->soc->thresh_grain;
490
491 /* Hardcode LIGHT on LEVEL1 and HEAVY on LEVEL2 */
492 throt = stc->id;
493 reg_off = THERMCTL_LVL_REG(sg->thermctl_lvl0_offset, throt + 1);
494
495 if (throt == THROTTLE_LIGHT) {
496 cpu_throt = THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT;
497 gpu_throt = THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT;
498 } else {
499 cpu_throt = THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY;
500 gpu_throt = THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY;
501 if (throt != THROTTLE_HEAVY)
502 dev_warn(dev,
503 "invalid throt id %d - assuming HEAVY",
504 throt);
505 }
506
507 r = readl(ts->regs + reg_off);
508 r = REG_SET_MASK(r, sg->thermctl_lvl0_up_thresh_mask, temp);
509 r = REG_SET_MASK(r, sg->thermctl_lvl0_dn_thresh_mask, temp);
510 r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_CPU_THROT_MASK, cpu_throt);
511 r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_GPU_THROT_MASK, gpu_throt);
512 r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 1);
513 writel(r, ts->regs + reg_off);
514
515 return 0;
516}
517
518static struct soctherm_throt_cfg *
519find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name)
520{
521 unsigned int i;
522
523 for (i = 0; ts->throt_cfgs[i].name; i++)
524 if (!strcmp(ts->throt_cfgs[i].name, name))
525 return &ts->throt_cfgs[i];
526
527 return NULL;
528}
529
530static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp)
531{
532 int ntrips, i, ret;
533 enum thermal_trip_type type;
534
535 ntrips = of_thermal_get_ntrips(tz);
536 if (ntrips <= 0)
537 return -EINVAL;
538
539 for (i = 0; i < ntrips; i++) {
540 ret = tz->ops->get_trip_type(tz, i, &type);
541 if (ret)
542 return -EINVAL;
543 if (type == THERMAL_TRIP_HOT) {
544 ret = tz->ops->get_trip_temp(tz, i, temp);
545 if (!ret)
546 *trip = i;
547
548 return ret;
549 }
550 }
551
552 return -EINVAL;
553}
554
555/**
241 * tegra_soctherm_set_hwtrips() - set HW trip point from DT data 556 * tegra_soctherm_set_hwtrips() - set HW trip point from DT data
242 * @dev: struct device * of the SOC_THERM instance 557 * @dev: struct device * of the SOC_THERM instance
243 * 558 *
244 * Configure the SOC_THERM HW trip points, setting "THERMTRIP" 559 * Configure the SOC_THERM HW trip points, setting "THERMTRIP"
245 * trip points , using "critical" type trip_temp from thermal 560 * "THROTTLE" trip points , using "critical" or "hot" type trip_temp
246 * zone. 561 * from thermal zone.
247 * After they have been configured, THERMTRIP will take action 562 * After they have been configured, THERMTRIP or THROTTLE will take
248 * when the configured SoC thermal sensor group reaches a 563 * action when the configured SoC thermal sensor group reaches a
249 * certain temperature. 564 * certain temperature.
250 * 565 *
251 * Return: 0 upon success, or a negative error code on failure. 566 * Return: 0 upon success, or a negative error code on failure.
@@ -254,19 +569,24 @@ static int thermtrip_program(struct device *dev,
254 * THERMTRIP has been enabled successfully when a message similar to 569 * THERMTRIP has been enabled successfully when a message similar to
255 * this one appears on the serial console: 570 * this one appears on the serial console:
256 * "thermtrip: will shut down when sensor group XXX reaches YYYYYY mC" 571 * "thermtrip: will shut down when sensor group XXX reaches YYYYYY mC"
572 * THROTTLE has been enabled successfully when a message similar to
573 * this one appears on the serial console:
574 * ""throttrip: will throttle when sensor group XXX reaches YYYYYY mC"
257 */ 575 */
258static int tegra_soctherm_set_hwtrips(struct device *dev, 576static int tegra_soctherm_set_hwtrips(struct device *dev,
259 const struct tegra_tsensor_group *sg, 577 const struct tegra_tsensor_group *sg,
260 struct thermal_zone_device *tz) 578 struct thermal_zone_device *tz)
261{ 579{
262 int temperature; 580 struct tegra_soctherm *ts = dev_get_drvdata(dev);
581 struct soctherm_throt_cfg *stc;
582 int i, trip, temperature;
263 int ret; 583 int ret;
264 584
265 ret = tz->ops->get_crit_temp(tz, &temperature); 585 ret = tz->ops->get_crit_temp(tz, &temperature);
266 if (ret) { 586 if (ret) {
267 dev_warn(dev, "thermtrip: %s: missing critical temperature\n", 587 dev_warn(dev, "thermtrip: %s: missing critical temperature\n",
268 sg->name); 588 sg->name);
269 return ret; 589 goto set_throttle;
270 } 590 }
271 591
272 ret = thermtrip_program(dev, sg, temperature); 592 ret = thermtrip_program(dev, sg, temperature);
@@ -280,6 +600,43 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
280 "thermtrip: will shut down when %s reaches %d mC\n", 600 "thermtrip: will shut down when %s reaches %d mC\n",
281 sg->name, temperature); 601 sg->name, temperature);
282 602
603set_throttle:
604 ret = get_hot_temp(tz, &trip, &temperature);
605 if (ret) {
606 dev_warn(dev, "throttrip: %s: missing hot temperature\n",
607 sg->name);
608 return 0;
609 }
610
611 for (i = 0; i < THROTTLE_SIZE; i++) {
612 struct thermal_cooling_device *cdev;
613
614 if (!ts->throt_cfgs[i].init)
615 continue;
616
617 cdev = ts->throt_cfgs[i].cdev;
618 if (get_thermal_instance(tz, cdev, trip))
619 stc = find_throttle_cfg_by_name(ts, cdev->type);
620 else
621 continue;
622
623 ret = throttrip_program(dev, sg, stc, temperature);
624 if (ret) {
625 dev_err(dev, "throttrip: %s: error during enable\n",
626 sg->name);
627 return ret;
628 }
629
630 dev_info(dev,
631 "throttrip: will throttle when %s reaches %d mC\n",
632 sg->name, temperature);
633 break;
634 }
635
636 if (i == THROTTLE_SIZE)
637 dev_warn(dev, "throttrip: %s: missing throttle cdev\n",
638 sg->name);
639
283 return 0; 640 return 0;
284} 641}
285 642
@@ -291,7 +648,7 @@ static int regs_show(struct seq_file *s, void *data)
291 const struct tegra_tsensor *tsensors = ts->soc->tsensors; 648 const struct tegra_tsensor *tsensors = ts->soc->tsensors;
292 const struct tegra_tsensor_group **ttgs = ts->soc->ttgs; 649 const struct tegra_tsensor_group **ttgs = ts->soc->ttgs;
293 u32 r, state; 650 u32 r, state;
294 int i; 651 int i, level;
295 652
296 seq_puts(s, "-----TSENSE (convert HW)-----\n"); 653 seq_puts(s, "-----TSENSE (convert HW)-----\n");
297 654
@@ -365,6 +722,81 @@ static int regs_show(struct seq_file *s, void *data)
365 state = REG_GET_MASK(r, SENSOR_TEMP2_MEM_TEMP_MASK); 722 state = REG_GET_MASK(r, SENSOR_TEMP2_MEM_TEMP_MASK);
366 seq_printf(s, " MEM(%d)\n", translate_temp(state)); 723 seq_printf(s, " MEM(%d)\n", translate_temp(state));
367 724
725 for (i = 0; i < ts->soc->num_ttgs; i++) {
726 seq_printf(s, "%s:\n", ttgs[i]->name);
727 for (level = 0; level < 4; level++) {
728 s32 v;
729 u32 mask;
730 u16 off = ttgs[i]->thermctl_lvl0_offset;
731
732 r = readl(ts->regs + THERMCTL_LVL_REG(off, level));
733
734 mask = ttgs[i]->thermctl_lvl0_up_thresh_mask;
735 state = REG_GET_MASK(r, mask);
736 v = sign_extend32(state, ts->soc->bptt - 1);
737 v *= ts->soc->thresh_grain;
738 seq_printf(s, " %d: Up/Dn(%d /", level, v);
739
740 mask = ttgs[i]->thermctl_lvl0_dn_thresh_mask;
741 state = REG_GET_MASK(r, mask);
742 v = sign_extend32(state, ts->soc->bptt - 1);
743 v *= ts->soc->thresh_grain;
744 seq_printf(s, "%d ) ", v);
745
746 mask = THERMCTL_LVL0_CPU0_EN_MASK;
747 state = REG_GET_MASK(r, mask);
748 seq_printf(s, "En(%d) ", state);
749
750 mask = THERMCTL_LVL0_CPU0_CPU_THROT_MASK;
751 state = REG_GET_MASK(r, mask);
752 seq_puts(s, "CPU Throt");
753 if (!state)
754 seq_printf(s, "(%s) ", "none");
755 else if (state == THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT)
756 seq_printf(s, "(%s) ", "L");
757 else if (state == THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY)
758 seq_printf(s, "(%s) ", "H");
759 else
760 seq_printf(s, "(%s) ", "H+L");
761
762 mask = THERMCTL_LVL0_CPU0_GPU_THROT_MASK;
763 state = REG_GET_MASK(r, mask);
764 seq_puts(s, "GPU Throt");
765 if (!state)
766 seq_printf(s, "(%s) ", "none");
767 else if (state == THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT)
768 seq_printf(s, "(%s) ", "L");
769 else if (state == THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY)
770 seq_printf(s, "(%s) ", "H");
771 else
772 seq_printf(s, "(%s) ", "H+L");
773
774 mask = THERMCTL_LVL0_CPU0_STATUS_MASK;
775 state = REG_GET_MASK(r, mask);
776 seq_printf(s, "Status(%s)\n",
777 state == 0 ? "LO" :
778 state == 1 ? "In" :
779 state == 2 ? "Res" : "HI");
780 }
781 }
782
783 r = readl(ts->regs + THERMCTL_STATS_CTL);
784 seq_printf(s, "STATS: Up(%s) Dn(%s)\n",
785 r & STATS_CTL_EN_UP ? "En" : "--",
786 r & STATS_CTL_EN_DN ? "En" : "--");
787
788 for (level = 0; level < 4; level++) {
789 u16 off;
790
791 off = THERMCTL_LVL0_UP_STATS;
792 r = readl(ts->regs + THERMCTL_LVL_REG(off, level));
793 seq_printf(s, " Level_%d Up(%d) ", level, r);
794
795 off = THERMCTL_LVL0_DN_STATS;
796 r = readl(ts->regs + THERMCTL_LVL_REG(off, level));
797 seq_printf(s, "Dn(%d)\n", r);
798 }
799
368 r = readl(ts->regs + THERMCTL_THERMTRIP_CTL); 800 r = readl(ts->regs + THERMCTL_THERMTRIP_CTL);
369 state = REG_GET_MASK(r, ttgs[0]->thermtrip_any_en_mask); 801 state = REG_GET_MASK(r, ttgs[0]->thermtrip_any_en_mask);
370 seq_printf(s, "Thermtrip Any En(%d)\n", state); 802 seq_printf(s, "Thermtrip Any En(%d)\n", state);
@@ -376,6 +808,32 @@ static int regs_show(struct seq_file *s, void *data)
376 seq_printf(s, "Thresh(%d)\n", state); 808 seq_printf(s, "Thresh(%d)\n", state);
377 } 809 }
378 810
811 r = readl(ts->regs + THROT_GLOBAL_CFG);
812 seq_puts(s, "\n");
813 seq_printf(s, "GLOBAL THROTTLE CONFIG: 0x%08x\n", r);
814
815 seq_puts(s, "---------------------------------------------------\n");
816 r = readl(ts->regs + THROT_STATUS);
817 state = REG_GET_MASK(r, THROT_STATUS_BREACH_MASK);
818 seq_printf(s, "THROT STATUS: breach(%d) ", state);
819 state = REG_GET_MASK(r, THROT_STATUS_STATE_MASK);
820 seq_printf(s, "state(%d) ", state);
821 state = REG_GET_MASK(r, THROT_STATUS_ENABLED_MASK);
822 seq_printf(s, "enabled(%d)\n", state);
823
824 r = readl(ts->regs + CPU_PSKIP_STATUS);
825 if (ts->soc->use_ccroc) {
826 state = REG_GET_MASK(r, XPU_PSKIP_STATUS_ENABLED_MASK);
827 seq_printf(s, "CPU PSKIP STATUS: enabled(%d)\n", state);
828 } else {
829 state = REG_GET_MASK(r, XPU_PSKIP_STATUS_M_MASK);
830 seq_printf(s, "CPU PSKIP STATUS: M(%d) ", state);
831 state = REG_GET_MASK(r, XPU_PSKIP_STATUS_N_MASK);
832 seq_printf(s, "N(%d) ", state);
833 state = REG_GET_MASK(r, XPU_PSKIP_STATUS_ENABLED_MASK);
834 seq_printf(s, "enabled(%d)\n", state);
835 }
836
379 return 0; 837 return 0;
380} 838}
381 839
@@ -449,6 +907,326 @@ static int soctherm_clk_enable(struct platform_device *pdev, bool enable)
449 return 0; 907 return 0;
450} 908}
451 909
910static int throt_get_cdev_max_state(struct thermal_cooling_device *cdev,
911 unsigned long *max_state)
912{
913 *max_state = 1;
914 return 0;
915}
916
917static int throt_get_cdev_cur_state(struct thermal_cooling_device *cdev,
918 unsigned long *cur_state)
919{
920 struct tegra_soctherm *ts = cdev->devdata;
921 u32 r;
922
923 r = readl(ts->regs + THROT_STATUS);
924 if (REG_GET_MASK(r, THROT_STATUS_STATE_MASK))
925 *cur_state = 1;
926 else
927 *cur_state = 0;
928
929 return 0;
930}
931
932static int throt_set_cdev_state(struct thermal_cooling_device *cdev,
933 unsigned long cur_state)
934{
935 return 0;
936}
937
938static struct thermal_cooling_device_ops throt_cooling_ops = {
939 .get_max_state = throt_get_cdev_max_state,
940 .get_cur_state = throt_get_cdev_cur_state,
941 .set_cur_state = throt_set_cdev_state,
942};
943
944/**
945 * soctherm_init_hw_throt_cdev() - Parse the HW throttle configurations
946 * and register them as cooling devices.
947 */
948static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
949{
950 struct device *dev = &pdev->dev;
951 struct tegra_soctherm *ts = dev_get_drvdata(dev);
952 struct device_node *np_stc, *np_stcc;
953 const char *name;
954 u32 val;
955 int i, r;
956
957 for (i = 0; i < THROTTLE_SIZE; i++) {
958 ts->throt_cfgs[i].name = throt_names[i];
959 ts->throt_cfgs[i].id = i;
960 ts->throt_cfgs[i].init = false;
961 }
962
963 np_stc = of_get_child_by_name(dev->of_node, "throttle-cfgs");
964 if (!np_stc) {
965 dev_info(dev,
966 "throttle-cfg: no throttle-cfgs - not enabling\n");
967 return;
968 }
969
970 for_each_child_of_node(np_stc, np_stcc) {
971 struct soctherm_throt_cfg *stc;
972 struct thermal_cooling_device *tcd;
973
974 name = np_stcc->name;
975 stc = find_throttle_cfg_by_name(ts, name);
976 if (!stc) {
977 dev_err(dev,
978 "throttle-cfg: could not find %s\n", name);
979 continue;
980 }
981
982 r = of_property_read_u32(np_stcc, "nvidia,priority", &val);
983 if (r) {
984 dev_info(dev,
985 "throttle-cfg: %s: missing priority\n", name);
986 continue;
987 }
988 stc->priority = val;
989
990 if (ts->soc->use_ccroc) {
991 r = of_property_read_u32(np_stcc,
992 "nvidia,cpu-throt-level",
993 &val);
994 if (r) {
995 dev_info(dev,
996 "throttle-cfg: %s: missing cpu-throt-level\n",
997 name);
998 continue;
999 }
1000 stc->cpu_throt_level = val;
1001 } else {
1002 r = of_property_read_u32(np_stcc,
1003 "nvidia,cpu-throt-percent",
1004 &val);
1005 if (r) {
1006 dev_info(dev,
1007 "throttle-cfg: %s: missing cpu-throt-percent\n",
1008 name);
1009 continue;
1010 }
1011 stc->cpu_throt_depth = val;
1012 }
1013
1014 tcd = thermal_of_cooling_device_register(np_stcc,
1015 (char *)name, ts,
1016 &throt_cooling_ops);
1017 of_node_put(np_stcc);
1018 if (IS_ERR_OR_NULL(tcd)) {
1019 dev_err(dev,
1020 "throttle-cfg: %s: failed to register cooling device\n",
1021 name);
1022 continue;
1023 }
1024
1025 stc->cdev = tcd;
1026 stc->init = true;
1027 }
1028
1029 of_node_put(np_stc);
1030}
1031
1032/**
1033 * throttlectl_cpu_level_cfg() - programs CCROC NV_THERM level config
1034 * @level: describing the level LOW/MED/HIGH of throttling
1035 *
1036 * It's necessary to set up the CPU-local CCROC NV_THERM instance with
1037 * the M/N values desired for each level. This function does this.
1038 *
1039 * This function pre-programs the CCROC NV_THERM levels in terms of
1040 * pre-configured "Low", "Medium" or "Heavy" throttle levels which are
1041 * mapped to THROT_LEVEL_LOW, THROT_LEVEL_MED and THROT_LEVEL_HVY.
1042 */
1043static void throttlectl_cpu_level_cfg(struct tegra_soctherm *ts, int level)
1044{
1045 u8 depth, dividend;
1046 u32 r;
1047
1048 switch (level) {
1049 case TEGRA_SOCTHERM_THROT_LEVEL_LOW:
1050 depth = 50;
1051 break;
1052 case TEGRA_SOCTHERM_THROT_LEVEL_MED:
1053 depth = 75;
1054 break;
1055 case TEGRA_SOCTHERM_THROT_LEVEL_HIGH:
1056 depth = 80;
1057 break;
1058 case TEGRA_SOCTHERM_THROT_LEVEL_NONE:
1059 return;
1060 default:
1061 return;
1062 }
1063
1064 dividend = THROT_DEPTH_DIVIDEND(depth);
1065
1066 /* setup PSKIP in ccroc nv_therm registers */
1067 r = ccroc_readl(ts, CCROC_THROT_PSKIP_RAMP_CPU_REG(level));
1068 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_RAMP_DURATION_MASK, 0xff);
1069 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_RAMP_STEP_MASK, 0xf);
1070 ccroc_writel(ts, r, CCROC_THROT_PSKIP_RAMP_CPU_REG(level));
1071
1072 r = ccroc_readl(ts, CCROC_THROT_PSKIP_CTRL_CPU_REG(level));
1073 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_ENB_MASK, 1);
1074 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_DIVIDEND_MASK, dividend);
1075 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_DIVISOR_MASK, 0xff);
1076 ccroc_writel(ts, r, CCROC_THROT_PSKIP_CTRL_CPU_REG(level));
1077}
1078
1079/**
1080 * throttlectl_cpu_level_select() - program CPU pulse skipper config
1081 * @throt: the LIGHT/HEAVY of throttle event id
1082 *
1083 * Pulse skippers are used to throttle clock frequencies. This
1084 * function programs the pulse skippers based on @throt and platform
1085 * data. This function is used on SoCs which have CPU-local pulse
1086 * skipper control, such as T13x. It programs soctherm's interface to
1087 * Denver:CCROC NV_THERM in terms of Low, Medium and HIGH throttling
1088 * vectors. PSKIP_BYPASS mode is set as required per HW spec.
1089 */
1090static void throttlectl_cpu_level_select(struct tegra_soctherm *ts,
1091 enum soctherm_throttle_id throt)
1092{
1093 u32 r, throt_vect;
1094
1095 /* Denver:CCROC NV_THERM interface N:3 Mapping */
1096 switch (ts->throt_cfgs[throt].cpu_throt_level) {
1097 case TEGRA_SOCTHERM_THROT_LEVEL_LOW:
1098 throt_vect = THROT_VECT_LOW;
1099 break;
1100 case TEGRA_SOCTHERM_THROT_LEVEL_MED:
1101 throt_vect = THROT_VECT_MED;
1102 break;
1103 case TEGRA_SOCTHERM_THROT_LEVEL_HIGH:
1104 throt_vect = THROT_VECT_HIGH;
1105 break;
1106 default:
1107 throt_vect = THROT_VECT_NONE;
1108 break;
1109 }
1110
1111 r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
1112 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);
1113 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT_CPU_MASK, throt_vect);
1114 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT2_CPU_MASK, throt_vect);
1115 writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
1116
1117 /* bypass sequencer in soc_therm as it is programmed in ccroc */
1118 r = REG_SET_MASK(0, THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK, 1);
1119 writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
1120}
1121
1122/**
1123 * throttlectl_cpu_mn() - program CPU pulse skipper configuration
1124 * @throt: the LIGHT/HEAVY of throttle event id
1125 *
1126 * Pulse skippers are used to throttle clock frequencies. This
1127 * function programs the pulse skippers based on @throt and platform
1128 * data. This function is used for CPUs that have "remote" pulse
1129 * skipper control, e.g., the CPU pulse skipper is controlled by the
1130 * SOC_THERM IP block. (SOC_THERM is located outside the CPU
1131 * complex.)
1132 */
1133static void throttlectl_cpu_mn(struct tegra_soctherm *ts,
1134 enum soctherm_throttle_id throt)
1135{
1136 u32 r;
1137 int depth;
1138 u8 dividend;
1139
1140 depth = ts->throt_cfgs[throt].cpu_throt_depth;
1141 dividend = THROT_DEPTH_DIVIDEND(depth);
1142
1143 r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
1144 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);
1145 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_DIVIDEND_MASK, dividend);
1146 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_DIVISOR_MASK, 0xff);
1147 writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
1148
1149 r = readl(ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
1150 r = REG_SET_MASK(r, THROT_PSKIP_RAMP_DURATION_MASK, 0xff);
1151 r = REG_SET_MASK(r, THROT_PSKIP_RAMP_STEP_MASK, 0xf);
1152 writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
1153}
1154
1155/**
1156 * soctherm_throttle_program() - programs pulse skippers' configuration
1157 * @throt: the LIGHT/HEAVY of the throttle event id.
1158 *
1159 * Pulse skippers are used to throttle clock frequencies.
1160 * This function programs the pulse skippers.
1161 */
1162static void soctherm_throttle_program(struct tegra_soctherm *ts,
1163 enum soctherm_throttle_id throt)
1164{
1165 u32 r;
1166 struct soctherm_throt_cfg stc = ts->throt_cfgs[throt];
1167
1168 if (!stc.init)
1169 return;
1170
1171 /* Setup PSKIP parameters */
1172 if (ts->soc->use_ccroc)
1173 throttlectl_cpu_level_select(ts, throt);
1174 else
1175 throttlectl_cpu_mn(ts, throt);
1176
1177 r = REG_SET_MASK(0, THROT_PRIORITY_LITE_PRIO_MASK, stc.priority);
1178 writel(r, ts->regs + THROT_PRIORITY_CTRL(throt));
1179
1180 r = REG_SET_MASK(0, THROT_DELAY_LITE_DELAY_MASK, 0);
1181 writel(r, ts->regs + THROT_DELAY_CTRL(throt));
1182
1183 r = readl(ts->regs + THROT_PRIORITY_LOCK);
1184 r = REG_GET_MASK(r, THROT_PRIORITY_LOCK_PRIORITY_MASK);
1185 if (r >= stc.priority)
1186 return;
1187 r = REG_SET_MASK(0, THROT_PRIORITY_LOCK_PRIORITY_MASK,
1188 stc.priority);
1189 writel(r, ts->regs + THROT_PRIORITY_LOCK);
1190}
1191
1192static void tegra_soctherm_throttle(struct device *dev)
1193{
1194 struct tegra_soctherm *ts = dev_get_drvdata(dev);
1195 u32 v;
1196 int i;
1197
1198 /* configure LOW, MED and HIGH levels for CCROC NV_THERM */
1199 if (ts->soc->use_ccroc) {
1200 throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_LOW);
1201 throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_MED);
1202 throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_HIGH);
1203 }
1204
1205 /* Thermal HW throttle programming */
1206 for (i = 0; i < THROTTLE_SIZE; i++)
1207 soctherm_throttle_program(ts, i);
1208
1209 v = REG_SET_MASK(0, THROT_GLOBAL_ENB_MASK, 1);
1210 if (ts->soc->use_ccroc) {
1211 ccroc_writel(ts, v, CCROC_GLOBAL_CFG);
1212
1213 v = ccroc_readl(ts, CCROC_SUPER_CCLKG_DIVIDER);
1214 v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);
1215 ccroc_writel(ts, v, CCROC_SUPER_CCLKG_DIVIDER);
1216 } else {
1217 writel(v, ts->regs + THROT_GLOBAL_CFG);
1218
1219 v = clk_readl(ts, CAR_SUPER_CCLKG_DIVIDER);
1220 v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);
1221 clk_writel(ts, v, CAR_SUPER_CCLKG_DIVIDER);
1222 }
1223
1224 /* initialize stats collection */
1225 v = STATS_CTL_CLR_DN | STATS_CTL_EN_DN |
1226 STATS_CTL_CLR_UP | STATS_CTL_EN_UP;
1227 writel(v, ts->regs + THERMCTL_STATS_CTL);
1228}
1229
452static void soctherm_init(struct platform_device *pdev) 1230static void soctherm_init(struct platform_device *pdev)
453{ 1231{
454 struct tegra_soctherm *tegra = platform_get_drvdata(pdev); 1232 struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
@@ -475,6 +1253,9 @@ static void soctherm_init(struct platform_device *pdev)
475 } 1253 }
476 writel(pdiv, tegra->regs + SENSOR_PDIV); 1254 writel(pdiv, tegra->regs + SENSOR_PDIV);
477 writel(hotspot, tegra->regs + SENSOR_HOTSPOT_OFF); 1255 writel(hotspot, tegra->regs + SENSOR_HOTSPOT_OFF);
1256
1257 /* Configure hw throttle */
1258 tegra_soctherm_throttle(&pdev->dev);
478} 1259}
479 1260
480static const struct of_device_id tegra_soctherm_of_match[] = { 1261static const struct of_device_id tegra_soctherm_of_match[] = {
@@ -527,10 +1308,31 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
527 1308
528 tegra->soc = soc; 1309 tegra->soc = soc;
529 1310
530 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1311 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1312 "soctherm-reg");
531 tegra->regs = devm_ioremap_resource(&pdev->dev, res); 1313 tegra->regs = devm_ioremap_resource(&pdev->dev, res);
532 if (IS_ERR(tegra->regs)) 1314 if (IS_ERR(tegra->regs)) {
1315 dev_err(&pdev->dev, "can't get soctherm registers");
533 return PTR_ERR(tegra->regs); 1316 return PTR_ERR(tegra->regs);
1317 }
1318
1319 if (!tegra->soc->use_ccroc) {
1320 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1321 "car-reg");
1322 tegra->clk_regs = devm_ioremap_resource(&pdev->dev, res);
1323 if (IS_ERR(tegra->clk_regs)) {
1324 dev_err(&pdev->dev, "can't get car clk registers");
1325 return PTR_ERR(tegra->clk_regs);
1326 }
1327 } else {
1328 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1329 "ccroc-reg");
1330 tegra->ccroc_regs = devm_ioremap_resource(&pdev->dev, res);
1331 if (IS_ERR(tegra->ccroc_regs)) {
1332 dev_err(&pdev->dev, "can't get ccroc registers");
1333 return PTR_ERR(tegra->ccroc_regs);
1334 }
1335 }
534 1336
535 tegra->reset = devm_reset_control_get(&pdev->dev, "soctherm"); 1337 tegra->reset = devm_reset_control_get(&pdev->dev, "soctherm");
536 if (IS_ERR(tegra->reset)) { 1338 if (IS_ERR(tegra->reset)) {
@@ -580,6 +1382,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
580 if (err) 1382 if (err)
581 return err; 1383 return err;
582 1384
1385 soctherm_init_hw_throt_cdev(pdev);
1386
583 soctherm_init(pdev); 1387 soctherm_init(pdev);
584 1388
585 for (i = 0; i < soc->num_ttgs; ++i) { 1389 for (i = 0; i < soc->num_ttgs; ++i) {
@@ -593,6 +1397,7 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
593 zone->reg = tegra->regs + soc->ttgs[i]->sensor_temp_offset; 1397 zone->reg = tegra->regs + soc->ttgs[i]->sensor_temp_offset;
594 zone->dev = &pdev->dev; 1398 zone->dev = &pdev->dev;
595 zone->sg = soc->ttgs[i]; 1399 zone->sg = soc->ttgs[i];
1400 zone->ts = tegra;
596 1401
597 z = devm_thermal_zone_of_sensor_register(&pdev->dev, 1402 z = devm_thermal_zone_of_sensor_register(&pdev->dev,
598 soc->ttgs[i]->id, zone, 1403 soc->ttgs[i]->id, zone,
@@ -608,7 +1413,9 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
608 tegra->thermctl_tzs[soc->ttgs[i]->id] = z; 1413 tegra->thermctl_tzs[soc->ttgs[i]->id] = z;
609 1414
610 /* Configure hw trip points */ 1415 /* Configure hw trip points */
611 tegra_soctherm_set_hwtrips(&pdev->dev, soc->ttgs[i], z); 1416 err = tegra_soctherm_set_hwtrips(&pdev->dev, soc->ttgs[i], z);
1417 if (err)
1418 goto disable_clocks;
612 } 1419 }
613 1420
614 soctherm_debug_init(pdev); 1421 soctherm_debug_init(pdev);
@@ -661,7 +1468,12 @@ static int __maybe_unused soctherm_resume(struct device *dev)
661 struct thermal_zone_device *tz; 1468 struct thermal_zone_device *tz;
662 1469
663 tz = tegra->thermctl_tzs[soc->ttgs[i]->id]; 1470 tz = tegra->thermctl_tzs[soc->ttgs[i]->id];
664 tegra_soctherm_set_hwtrips(dev, soc->ttgs[i], tz); 1471 err = tegra_soctherm_set_hwtrips(dev, soc->ttgs[i], tz);
1472 if (err) {
1473 dev_err(&pdev->dev,
1474 "Resume failed: set hwtrips failed\n");
1475 return err;
1476 }
665 } 1477 }
666 1478
667 return 0; 1479 return 0;
diff --git a/drivers/thermal/tegra/soctherm.h b/drivers/thermal/tegra/soctherm.h
index 28e18ec4b4c3..e96ca73fd780 100644
--- a/drivers/thermal/tegra/soctherm.h
+++ b/drivers/thermal/tegra/soctherm.h
@@ -15,6 +15,11 @@
15#ifndef __DRIVERS_THERMAL_TEGRA_SOCTHERM_H 15#ifndef __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
16#define __DRIVERS_THERMAL_TEGRA_SOCTHERM_H 16#define __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
17 17
18#define THERMCTL_LEVEL0_GROUP_CPU 0x0
19#define THERMCTL_LEVEL0_GROUP_GPU 0x4
20#define THERMCTL_LEVEL0_GROUP_MEM 0x8
21#define THERMCTL_LEVEL0_GROUP_TSENSE 0xc
22
18#define SENSOR_CONFIG2 8 23#define SENSOR_CONFIG2 8
19#define SENSOR_CONFIG2_THERMA_MASK (0xffff << 16) 24#define SENSOR_CONFIG2_THERMA_MASK (0xffff << 16)
20#define SENSOR_CONFIG2_THERMA_SHIFT 16 25#define SENSOR_CONFIG2_THERMA_SHIFT 16
@@ -65,6 +70,9 @@ struct tegra_tsensor_group {
65 u32 thermtrip_enable_mask; 70 u32 thermtrip_enable_mask;
66 u32 thermtrip_any_en_mask; 71 u32 thermtrip_any_en_mask;
67 u32 thermtrip_threshold_mask; 72 u32 thermtrip_threshold_mask;
73 u16 thermctl_lvl0_offset;
74 u32 thermctl_lvl0_up_thresh_mask;
75 u32 thermctl_lvl0_dn_thresh_mask;
68}; 76};
69 77
70struct tegra_tsensor_configuration { 78struct tegra_tsensor_configuration {
@@ -103,6 +111,8 @@ struct tegra_soctherm_soc {
103 const unsigned int num_ttgs; 111 const unsigned int num_ttgs;
104 const struct tegra_soctherm_fuse *tfuse; 112 const struct tegra_soctherm_fuse *tfuse;
105 const int thresh_grain; 113 const int thresh_grain;
114 const unsigned int bptt;
115 const bool use_ccroc;
106}; 116};
107 117
108int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse, 118int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse,
diff --git a/drivers/thermal/tegra/tegra124-soctherm.c b/drivers/thermal/tegra/tegra124-soctherm.c
index beb9d36b9c8a..36768630f78c 100644
--- a/drivers/thermal/tegra/tegra124-soctherm.c
+++ b/drivers/thermal/tegra/tegra124-soctherm.c
@@ -28,7 +28,11 @@
28#define TEGRA124_THERMTRIP_CPU_THRESH_MASK (0xff << 8) 28#define TEGRA124_THERMTRIP_CPU_THRESH_MASK (0xff << 8)
29#define TEGRA124_THERMTRIP_TSENSE_THRESH_MASK 0xff 29#define TEGRA124_THERMTRIP_TSENSE_THRESH_MASK 0xff
30 30
31#define TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK (0xff << 17)
32#define TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK (0xff << 9)
33
31#define TEGRA124_THRESH_GRAIN 1000 34#define TEGRA124_THRESH_GRAIN 1000
35#define TEGRA124_BPTT 8
32 36
33static const struct tegra_tsensor_configuration tegra124_tsensor_config = { 37static const struct tegra_tsensor_configuration tegra124_tsensor_config = {
34 .tall = 16300, 38 .tall = 16300,
@@ -51,6 +55,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_cpu = {
51 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK, 55 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
52 .thermtrip_enable_mask = TEGRA124_THERMTRIP_CPU_EN_MASK, 56 .thermtrip_enable_mask = TEGRA124_THERMTRIP_CPU_EN_MASK,
53 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_CPU_THRESH_MASK, 57 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_CPU_THRESH_MASK,
58 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
59 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
60 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
54}; 61};
55 62
56static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = { 63static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
@@ -66,6 +73,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
66 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK, 73 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
67 .thermtrip_enable_mask = TEGRA124_THERMTRIP_GPU_EN_MASK, 74 .thermtrip_enable_mask = TEGRA124_THERMTRIP_GPU_EN_MASK,
68 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK, 75 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
76 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
77 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
78 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
69}; 79};
70 80
71static const struct tegra_tsensor_group tegra124_tsensor_group_pll = { 81static const struct tegra_tsensor_group tegra124_tsensor_group_pll = {
@@ -79,6 +89,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_pll = {
79 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK, 89 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
80 .thermtrip_enable_mask = TEGRA124_THERMTRIP_TSENSE_EN_MASK, 90 .thermtrip_enable_mask = TEGRA124_THERMTRIP_TSENSE_EN_MASK,
81 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_TSENSE_THRESH_MASK, 91 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_TSENSE_THRESH_MASK,
92 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
93 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
94 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
82}; 95};
83 96
84static const struct tegra_tsensor_group tegra124_tsensor_group_mem = { 97static const struct tegra_tsensor_group tegra124_tsensor_group_mem = {
@@ -94,6 +107,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_mem = {
94 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK, 107 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
95 .thermtrip_enable_mask = TEGRA124_THERMTRIP_MEM_EN_MASK, 108 .thermtrip_enable_mask = TEGRA124_THERMTRIP_MEM_EN_MASK,
96 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK, 109 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
110 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
111 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
112 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
97}; 113};
98 114
99static const struct tegra_tsensor_group *tegra124_tsensor_groups[] = { 115static const struct tegra_tsensor_group *tegra124_tsensor_groups[] = {
@@ -193,4 +209,6 @@ const struct tegra_soctherm_soc tegra124_soctherm = {
193 .num_ttgs = ARRAY_SIZE(tegra124_tsensor_groups), 209 .num_ttgs = ARRAY_SIZE(tegra124_tsensor_groups),
194 .tfuse = &tegra124_soctherm_fuse, 210 .tfuse = &tegra124_soctherm_fuse,
195 .thresh_grain = TEGRA124_THRESH_GRAIN, 211 .thresh_grain = TEGRA124_THRESH_GRAIN,
212 .bptt = TEGRA124_BPTT,
213 .use_ccroc = false,
196}; 214};
diff --git a/drivers/thermal/tegra/tegra132-soctherm.c b/drivers/thermal/tegra/tegra132-soctherm.c
index e2aa84e1b307..97fa30501eb1 100644
--- a/drivers/thermal/tegra/tegra132-soctherm.c
+++ b/drivers/thermal/tegra/tegra132-soctherm.c
@@ -28,7 +28,11 @@
28#define TEGRA132_THERMTRIP_CPU_THRESH_MASK (0xff << 8) 28#define TEGRA132_THERMTRIP_CPU_THRESH_MASK (0xff << 8)
29#define TEGRA132_THERMTRIP_TSENSE_THRESH_MASK 0xff 29#define TEGRA132_THERMTRIP_TSENSE_THRESH_MASK 0xff
30 30
31#define TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK (0xff << 17)
32#define TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK (0xff << 9)
33
31#define TEGRA132_THRESH_GRAIN 1000 34#define TEGRA132_THRESH_GRAIN 1000
35#define TEGRA132_BPTT 8
32 36
33static const struct tegra_tsensor_configuration tegra132_tsensor_config = { 37static const struct tegra_tsensor_configuration tegra132_tsensor_config = {
34 .tall = 16300, 38 .tall = 16300,
@@ -51,6 +55,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_cpu = {
51 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK, 55 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
52 .thermtrip_enable_mask = TEGRA132_THERMTRIP_CPU_EN_MASK, 56 .thermtrip_enable_mask = TEGRA132_THERMTRIP_CPU_EN_MASK,
53 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_CPU_THRESH_MASK, 57 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_CPU_THRESH_MASK,
58 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
59 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
60 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
54}; 61};
55 62
56static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = { 63static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = {
@@ -66,6 +73,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = {
66 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK, 73 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
67 .thermtrip_enable_mask = TEGRA132_THERMTRIP_GPU_EN_MASK, 74 .thermtrip_enable_mask = TEGRA132_THERMTRIP_GPU_EN_MASK,
68 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK, 75 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
76 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
77 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
78 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
69}; 79};
70 80
71static const struct tegra_tsensor_group tegra132_tsensor_group_pll = { 81static const struct tegra_tsensor_group tegra132_tsensor_group_pll = {
@@ -79,6 +89,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_pll = {
79 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK, 89 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
80 .thermtrip_enable_mask = TEGRA132_THERMTRIP_TSENSE_EN_MASK, 90 .thermtrip_enable_mask = TEGRA132_THERMTRIP_TSENSE_EN_MASK,
81 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_TSENSE_THRESH_MASK, 91 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_TSENSE_THRESH_MASK,
92 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
93 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
94 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
82}; 95};
83 96
84static const struct tegra_tsensor_group tegra132_tsensor_group_mem = { 97static const struct tegra_tsensor_group tegra132_tsensor_group_mem = {
@@ -94,6 +107,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_mem = {
94 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK, 107 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
95 .thermtrip_enable_mask = TEGRA132_THERMTRIP_MEM_EN_MASK, 108 .thermtrip_enable_mask = TEGRA132_THERMTRIP_MEM_EN_MASK,
96 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK, 109 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
110 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
111 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
112 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
97}; 113};
98 114
99static const struct tegra_tsensor_group *tegra132_tsensor_groups[] = { 115static const struct tegra_tsensor_group *tegra132_tsensor_groups[] = {
@@ -193,4 +209,6 @@ const struct tegra_soctherm_soc tegra132_soctherm = {
193 .num_ttgs = ARRAY_SIZE(tegra132_tsensor_groups), 209 .num_ttgs = ARRAY_SIZE(tegra132_tsensor_groups),
194 .tfuse = &tegra132_soctherm_fuse, 210 .tfuse = &tegra132_soctherm_fuse,
195 .thresh_grain = TEGRA132_THRESH_GRAIN, 211 .thresh_grain = TEGRA132_THRESH_GRAIN,
212 .bptt = TEGRA132_BPTT,
213 .use_ccroc = true,
196}; 214};
diff --git a/drivers/thermal/tegra/tegra210-soctherm.c b/drivers/thermal/tegra/tegra210-soctherm.c
index 19cc0ab66f0e..ad53169a8e95 100644
--- a/drivers/thermal/tegra/tegra210-soctherm.c
+++ b/drivers/thermal/tegra/tegra210-soctherm.c
@@ -29,7 +29,11 @@
29#define TEGRA210_THERMTRIP_CPU_THRESH_MASK (0x1ff << 9) 29#define TEGRA210_THERMTRIP_CPU_THRESH_MASK (0x1ff << 9)
30#define TEGRA210_THERMTRIP_TSENSE_THRESH_MASK 0x1ff 30#define TEGRA210_THERMTRIP_TSENSE_THRESH_MASK 0x1ff
31 31
32#define TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK (0x1ff << 18)
33#define TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK (0x1ff << 9)
34
32#define TEGRA210_THRESH_GRAIN 500 35#define TEGRA210_THRESH_GRAIN 500
36#define TEGRA210_BPTT 9
33 37
34static const struct tegra_tsensor_configuration tegra210_tsensor_config = { 38static const struct tegra_tsensor_configuration tegra210_tsensor_config = {
35 .tall = 16300, 39 .tall = 16300,
@@ -52,6 +56,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_cpu = {
52 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, 56 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
53 .thermtrip_enable_mask = TEGRA210_THERMTRIP_CPU_EN_MASK, 57 .thermtrip_enable_mask = TEGRA210_THERMTRIP_CPU_EN_MASK,
54 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_CPU_THRESH_MASK, 58 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_CPU_THRESH_MASK,
59 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
60 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
61 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
55}; 62};
56 63
57static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = { 64static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = {
@@ -67,6 +74,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = {
67 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, 74 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
68 .thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK, 75 .thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK,
69 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK, 76 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
77 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
78 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
79 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
70}; 80};
71 81
72static const struct tegra_tsensor_group tegra210_tsensor_group_pll = { 82static const struct tegra_tsensor_group tegra210_tsensor_group_pll = {
@@ -80,6 +90,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_pll = {
80 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, 90 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
81 .thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK, 91 .thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK,
82 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK, 92 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK,
93 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
94 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
95 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
83}; 96};
84 97
85static const struct tegra_tsensor_group tegra210_tsensor_group_mem = { 98static const struct tegra_tsensor_group tegra210_tsensor_group_mem = {
@@ -95,6 +108,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_mem = {
95 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, 108 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
96 .thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK, 109 .thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK,
97 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK, 110 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
111 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
112 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
113 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
98}; 114};
99 115
100static const struct tegra_tsensor_group *tegra210_tsensor_groups[] = { 116static const struct tegra_tsensor_group *tegra210_tsensor_groups[] = {
@@ -194,4 +210,6 @@ const struct tegra_soctherm_soc tegra210_soctherm = {
194 .num_ttgs = ARRAY_SIZE(tegra210_tsensor_groups), 210 .num_ttgs = ARRAY_SIZE(tegra210_tsensor_groups),
195 .tfuse = &tegra210_soctherm_fuse, 211 .tfuse = &tegra210_soctherm_fuse,
196 .thresh_grain = TEGRA210_THRESH_GRAIN, 212 .thresh_grain = TEGRA210_THRESH_GRAIN,
213 .bptt = TEGRA210_BPTT,
214 .use_ccroc = false,
197}; 215};
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e2fc6161dded..226b0b4aced6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -520,6 +520,56 @@ exit:
520} 520}
521EXPORT_SYMBOL_GPL(thermal_zone_get_temp); 521EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
522 522
523void thermal_zone_set_trips(struct thermal_zone_device *tz)
524{
525 int low = -INT_MAX;
526 int high = INT_MAX;
527 int trip_temp, hysteresis;
528 int i, ret;
529
530 mutex_lock(&tz->lock);
531
532 if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
533 goto exit;
534
535 for (i = 0; i < tz->trips; i++) {
536 int trip_low;
537
538 tz->ops->get_trip_temp(tz, i, &trip_temp);
539 tz->ops->get_trip_hyst(tz, i, &hysteresis);
540
541 trip_low = trip_temp - hysteresis;
542
543 if (trip_low < tz->temperature && trip_low > low)
544 low = trip_low;
545
546 if (trip_temp > tz->temperature && trip_temp < high)
547 high = trip_temp;
548 }
549
550 /* No need to change trip points */
551 if (tz->prev_low_trip == low && tz->prev_high_trip == high)
552 goto exit;
553
554 tz->prev_low_trip = low;
555 tz->prev_high_trip = high;
556
557 dev_dbg(&tz->device,
558 "new temperature boundaries: %d < x < %d\n", low, high);
559
560 /*
561 * Set a temperature window. When this window is left the driver
562 * must inform the thermal core via thermal_zone_device_update.
563 */
564 ret = tz->ops->set_trips(tz, low, high);
565 if (ret)
566 dev_err(&tz->device, "Failed to set trips: %d\n", ret);
567
568exit:
569 mutex_unlock(&tz->lock);
570}
571EXPORT_SYMBOL_GPL(thermal_zone_set_trips);
572
523static void update_temperature(struct thermal_zone_device *tz) 573static void update_temperature(struct thermal_zone_device *tz)
524{ 574{
525 int temp, ret; 575 int temp, ret;
@@ -557,7 +607,8 @@ static void thermal_zone_device_reset(struct thermal_zone_device *tz)
557 pos->initialized = false; 607 pos->initialized = false;
558} 608}
559 609
560void thermal_zone_device_update(struct thermal_zone_device *tz) 610void thermal_zone_device_update(struct thermal_zone_device *tz,
611 enum thermal_notify_event event)
561{ 612{
562 int count; 613 int count;
563 614
@@ -569,6 +620,10 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
569 620
570 update_temperature(tz); 621 update_temperature(tz);
571 622
623 thermal_zone_set_trips(tz);
624
625 tz->notify_event = event;
626
572 for (count = 0; count < tz->trips; count++) 627 for (count = 0; count < tz->trips; count++)
573 handle_thermal_trip(tz, count); 628 handle_thermal_trip(tz, count);
574} 629}
@@ -579,7 +634,7 @@ static void thermal_zone_device_check(struct work_struct *work)
579 struct thermal_zone_device *tz = container_of(work, struct 634 struct thermal_zone_device *tz = container_of(work, struct
580 thermal_zone_device, 635 thermal_zone_device,
581 poll_queue.work); 636 poll_queue.work);
582 thermal_zone_device_update(tz); 637 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
583} 638}
584 639
585/* sys I/F for thermal zone */ 640/* sys I/F for thermal zone */
@@ -703,7 +758,7 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
703 if (ret) 758 if (ret)
704 return ret; 759 return ret;
705 760
706 thermal_zone_device_update(tz); 761 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
707 762
708 return count; 763 return count;
709} 764}
@@ -754,6 +809,9 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
754 */ 809 */
755 ret = tz->ops->set_trip_hyst(tz, trip, temperature); 810 ret = tz->ops->set_trip_hyst(tz, trip, temperature);
756 811
812 if (!ret)
813 thermal_zone_set_trips(tz);
814
757 return ret ? ret : count; 815 return ret ? ret : count;
758} 816}
759 817
@@ -822,7 +880,7 @@ passive_store(struct device *dev, struct device_attribute *attr,
822 880
823 tz->forced_passive = state; 881 tz->forced_passive = state;
824 882
825 thermal_zone_device_update(tz); 883 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
826 884
827 return count; 885 return count;
828} 886}
@@ -913,7 +971,7 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
913 } 971 }
914 972
915 if (!ret) 973 if (!ret)
916 thermal_zone_device_update(tz); 974 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
917 975
918 return ret ? ret : count; 976 return ret ? ret : count;
919} 977}
@@ -1509,7 +1567,8 @@ __thermal_cooling_device_register(struct device_node *np,
1509 mutex_lock(&thermal_list_lock); 1567 mutex_lock(&thermal_list_lock);
1510 list_for_each_entry(pos, &thermal_tz_list, node) 1568 list_for_each_entry(pos, &thermal_tz_list, node)
1511 if (atomic_cmpxchg(&pos->need_update, 1, 0)) 1569 if (atomic_cmpxchg(&pos->need_update, 1, 0))
1512 thermal_zone_device_update(pos); 1570 thermal_zone_device_update(pos,
1571 THERMAL_EVENT_UNSPECIFIED);
1513 mutex_unlock(&thermal_list_lock); 1572 mutex_unlock(&thermal_list_lock);
1514 1573
1515 return cdev; 1574 return cdev;
@@ -1952,7 +2011,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1952 thermal_zone_device_reset(tz); 2011 thermal_zone_device_reset(tz);
1953 /* Update the new thermal zone and mark it as already updated. */ 2012 /* Update the new thermal zone and mark it as already updated. */
1954 if (atomic_cmpxchg(&tz->need_update, 1, 0)) 2013 if (atomic_cmpxchg(&tz->need_update, 1, 0))
1955 thermal_zone_device_update(tz); 2014 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
1956 2015
1957 return tz; 2016 return tz;
1958 2017
@@ -2069,6 +2128,36 @@ exit:
2069} 2128}
2070EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name); 2129EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
2071 2130
2131/**
2132 * thermal_zone_get_slope - return the slope attribute of the thermal zone
2133 * @tz: thermal zone device with the slope attribute
2134 *
2135 * Return: If the thermal zone device has a slope attribute, return it, else
2136 * return 1.
2137 */
2138int thermal_zone_get_slope(struct thermal_zone_device *tz)
2139{
2140 if (tz && tz->tzp)
2141 return tz->tzp->slope;
2142 return 1;
2143}
2144EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
2145
2146/**
2147 * thermal_zone_get_offset - return the offset attribute of the thermal zone
2148 * @tz: thermal zone device with the offset attribute
2149 *
2150 * Return: If the thermal zone device has a offset attribute, return it, else
2151 * return 0.
2152 */
2153int thermal_zone_get_offset(struct thermal_zone_device *tz)
2154{
2155 if (tz && tz->tzp)
2156 return tz->tzp->offset;
2157 return 0;
2158}
2159EXPORT_SYMBOL_GPL(thermal_zone_get_offset);
2160
2072#ifdef CONFIG_NET 2161#ifdef CONFIG_NET
2073static const struct genl_multicast_group thermal_event_mcgrps[] = { 2162static const struct genl_multicast_group thermal_event_mcgrps[] = {
2074 { .name = THERMAL_GENL_MCAST_GROUP_NAME, }, 2163 { .name = THERMAL_GENL_MCAST_GROUP_NAME, },
@@ -2209,7 +2298,8 @@ static int thermal_pm_notify(struct notifier_block *nb,
2209 atomic_set(&in_suspend, 0); 2298 atomic_set(&in_suspend, 0);
2210 list_for_each_entry(tz, &thermal_tz_list, node) { 2299 list_for_each_entry(tz, &thermal_tz_list, node) {
2211 thermal_zone_device_reset(tz); 2300 thermal_zone_device_reset(tz);
2212 thermal_zone_device_update(tz); 2301 thermal_zone_device_update(tz,
2302 THERMAL_EVENT_UNSPECIFIED);
2213 } 2303 }
2214 break; 2304 break;
2215 default: 2305 default:
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 15c0a9ac2209..0586bd0f2bab 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -52,7 +52,7 @@ static void ti_thermal_work(struct work_struct *work)
52 struct ti_thermal_data *data = container_of(work, 52 struct ti_thermal_data *data = container_of(work,
53 struct ti_thermal_data, thermal_wq); 53 struct ti_thermal_data, thermal_wq);
54 54
55 thermal_zone_device_update(data->ti_thermal); 55 thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
56 56
57 dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n", 57 dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n",
58 data->ti_thermal->type); 58 data->ti_thermal->type);
@@ -205,7 +205,7 @@ static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
205 data->mode = mode; 205 data->mode = mode;
206 ti_bandgap_write_update_interval(bgp, data->sensor_id, 206 ti_bandgap_write_update_interval(bgp, data->sensor_id,
207 data->ti_thermal->polling_delay); 207 data->ti_thermal->polling_delay);
208 thermal_zone_device_update(data->ti_thermal); 208 thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
209 dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n", 209 dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
210 data->ti_thermal->polling_delay); 210 data->ti_thermal->polling_delay);
211 211
@@ -239,7 +239,7 @@ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
239 return 0; 239 return 0;
240} 240}
241 241
242static int __ti_thermal_get_trend(void *p, long *trend) 242static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
243{ 243{
244 struct ti_thermal_data *data = p; 244 struct ti_thermal_data *data = p;
245 struct ti_bandgap *bgp; 245 struct ti_bandgap *bgp;
@@ -252,22 +252,6 @@ static int __ti_thermal_get_trend(void *p, long *trend)
252 if (ret) 252 if (ret)
253 return ret; 253 return ret;
254 254
255 *trend = tr;
256
257 return 0;
258}
259
260/* Get the temperature trend callback functions for thermal zone */
261static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
262 int trip, enum thermal_trend *trend)
263{
264 int ret;
265 long tr;
266
267 ret = __ti_thermal_get_trend(thermal->devdata, &tr);
268 if (ret)
269 return ret;
270
271 if (tr > 0) 255 if (tr > 0)
272 *trend = THERMAL_TREND_RAISING; 256 *trend = THERMAL_TREND_RAISING;
273 else if (tr < 0) 257 else if (tr < 0)
@@ -278,6 +262,13 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
278 return 0; 262 return 0;
279} 263}
280 264
265/* Get the temperature trend callback functions for thermal zone */
266static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
267 int trip, enum thermal_trend *trend)
268{
269 return __ti_thermal_get_trend(thermal->devdata, trip, trend);
270}
271
281/* Get critical temperature callback functions for thermal zone */ 272/* Get critical temperature callback functions for thermal zone */
282static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal, 273static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
283 int *temp) 274 int *temp)
diff --git a/drivers/thermal/user_space.c b/drivers/thermal/user_space.c
index 10adcddc8821..c908150c268d 100644
--- a/drivers/thermal/user_space.c
+++ b/drivers/thermal/user_space.c
@@ -23,19 +23,30 @@
23 */ 23 */
24 24
25#include <linux/thermal.h> 25#include <linux/thermal.h>
26 26#include <linux/slab.h>
27#include "thermal_core.h" 27#include "thermal_core.h"
28 28
29/** 29/**
30 * notify_user_space - Notifies user space about thermal events 30 * notify_user_space - Notifies user space about thermal events
31 * @tz - thermal_zone_device 31 * @tz - thermal_zone_device
32 * @trip - Trip point index
32 * 33 *
33 * This function notifies the user space through UEvents. 34 * This function notifies the user space through UEvents.
34 */ 35 */
35static int notify_user_space(struct thermal_zone_device *tz, int trip) 36static int notify_user_space(struct thermal_zone_device *tz, int trip)
36{ 37{
38 char *thermal_prop[5];
39 int i;
40
37 mutex_lock(&tz->lock); 41 mutex_lock(&tz->lock);
38 kobject_uevent(&tz->device.kobj, KOBJ_CHANGE); 42 thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", tz->type);
43 thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", tz->temperature);
44 thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP=%d", trip);
45 thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", tz->notify_event);
46 thermal_prop[4] = NULL;
47 kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, thermal_prop);
48 for (i = 0; i < 4; ++i)
49 kfree(thermal_prop[i]);
39 mutex_unlock(&tz->lock); 50 mutex_unlock(&tz->lock);
40 return 0; 51 return 0;
41} 52}
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index 97f0a2bd93ed..95f4c1bcdb4c 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -348,7 +348,8 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
348 } 348 }
349 if (notify) { 349 if (notify) {
350 pr_debug("thermal_zone_device_update\n"); 350 pr_debug("thermal_zone_device_update\n");
351 thermal_zone_device_update(phdev->tzone); 351 thermal_zone_device_update(phdev->tzone,
352 THERMAL_EVENT_UNSPECIFIED);
352 } 353 }
353} 354}
354 355
diff --git a/include/dt-bindings/thermal/tegra124-soctherm.h b/include/dt-bindings/thermal/tegra124-soctherm.h
index 729ab9fc325e..2a99f1d52bb5 100644
--- a/include/dt-bindings/thermal/tegra124-soctherm.h
+++ b/include/dt-bindings/thermal/tegra124-soctherm.h
@@ -11,4 +11,9 @@
11#define TEGRA124_SOCTHERM_SENSOR_PLLX 3 11#define TEGRA124_SOCTHERM_SENSOR_PLLX 3
12#define TEGRA124_SOCTHERM_SENSOR_NUM 4 12#define TEGRA124_SOCTHERM_SENSOR_NUM 4
13 13
14#define TEGRA_SOCTHERM_THROT_LEVEL_LOW 0
15#define TEGRA_SOCTHERM_THROT_LEVEL_MED 1
16#define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 2
17#define TEGRA_SOCTHERM_THROT_LEVEL_NONE -1
18
14#endif 19#endif
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index ee517bef0db0..511182a88e76 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -92,12 +92,24 @@ enum thermal_trend {
92 THERMAL_TREND_DROP_FULL, /* apply lowest cooling action */ 92 THERMAL_TREND_DROP_FULL, /* apply lowest cooling action */
93}; 93};
94 94
95/* Thermal notification reason */
96enum thermal_notify_event {
97 THERMAL_EVENT_UNSPECIFIED, /* Unspecified event */
98 THERMAL_EVENT_TEMP_SAMPLE, /* New Temperature sample */
99 THERMAL_TRIP_VIOLATED, /* TRIP Point violation */
100 THERMAL_TRIP_CHANGED, /* TRIP Point temperature changed */
101 THERMAL_DEVICE_DOWN, /* Thermal device is down */
102 THERMAL_DEVICE_UP, /* Thermal device is up after a down event */
103 THERMAL_DEVICE_POWER_CAPABILITY_CHANGED, /* power capability changed */
104};
105
95struct thermal_zone_device_ops { 106struct thermal_zone_device_ops {
96 int (*bind) (struct thermal_zone_device *, 107 int (*bind) (struct thermal_zone_device *,
97 struct thermal_cooling_device *); 108 struct thermal_cooling_device *);
98 int (*unbind) (struct thermal_zone_device *, 109 int (*unbind) (struct thermal_zone_device *,
99 struct thermal_cooling_device *); 110 struct thermal_cooling_device *);
100 int (*get_temp) (struct thermal_zone_device *, int *); 111 int (*get_temp) (struct thermal_zone_device *, int *);
112 int (*set_trips) (struct thermal_zone_device *, int, int);
101 int (*get_mode) (struct thermal_zone_device *, 113 int (*get_mode) (struct thermal_zone_device *,
102 enum thermal_device_mode *); 114 enum thermal_device_mode *);
103 int (*set_mode) (struct thermal_zone_device *, 115 int (*set_mode) (struct thermal_zone_device *,
@@ -168,6 +180,10 @@ struct thermal_attr {
168 * @last_temperature: previous temperature read 180 * @last_temperature: previous temperature read
169 * @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION 181 * @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION
170 * @passive: 1 if you've crossed a passive trip point, 0 otherwise. 182 * @passive: 1 if you've crossed a passive trip point, 0 otherwise.
183 * @prev_low_trip: the low current temperature if you've crossed a passive
184 trip point.
185 * @prev_high_trip: the above current temperature if you've crossed a
186 passive trip point.
171 * @forced_passive: If > 0, temperature at which to switch on all ACPI 187 * @forced_passive: If > 0, temperature at which to switch on all ACPI
172 * processor cooling devices. Currently only used by the 188 * processor cooling devices. Currently only used by the
173 * step-wise governor. 189 * step-wise governor.
@@ -182,6 +198,7 @@ struct thermal_attr {
182 * @lock: lock to protect thermal_instances list 198 * @lock: lock to protect thermal_instances list
183 * @node: node in thermal_tz_list (in thermal_core.c) 199 * @node: node in thermal_tz_list (in thermal_core.c)
184 * @poll_queue: delayed work for polling 200 * @poll_queue: delayed work for polling
201 * @notify_event: Last notification event
185 */ 202 */
186struct thermal_zone_device { 203struct thermal_zone_device {
187 int id; 204 int id;
@@ -199,6 +216,8 @@ struct thermal_zone_device {
199 int last_temperature; 216 int last_temperature;
200 int emul_temperature; 217 int emul_temperature;
201 int passive; 218 int passive;
219 int prev_low_trip;
220 int prev_high_trip;
202 unsigned int forced_passive; 221 unsigned int forced_passive;
203 atomic_t need_update; 222 atomic_t need_update;
204 struct thermal_zone_device_ops *ops; 223 struct thermal_zone_device_ops *ops;
@@ -210,6 +229,7 @@ struct thermal_zone_device {
210 struct mutex lock; 229 struct mutex lock;
211 struct list_head node; 230 struct list_head node;
212 struct delayed_work poll_queue; 231 struct delayed_work poll_queue;
232 enum thermal_notify_event notify_event;
213}; 233};
214 234
215/** 235/**
@@ -333,6 +353,9 @@ struct thermal_genl_event {
333 * 353 *
334 * Optional: 354 * Optional:
335 * @get_trend: a pointer to a function that reads the sensor temperature trend. 355 * @get_trend: a pointer to a function that reads the sensor temperature trend.
356 * @set_trips: a pointer to a function that sets a temperature window. When
357 * this window is left the driver must inform the thermal core via
358 * thermal_zone_device_update.
336 * @set_emul_temp: a pointer to a function that sets sensor emulated 359 * @set_emul_temp: a pointer to a function that sets sensor emulated
337 * temperature. 360 * temperature.
338 * @set_trip_temp: a pointer to a function that sets the trip temperature on 361 * @set_trip_temp: a pointer to a function that sets the trip temperature on
@@ -340,7 +363,8 @@ struct thermal_genl_event {
340 */ 363 */
341struct thermal_zone_of_device_ops { 364struct thermal_zone_of_device_ops {
342 int (*get_temp)(void *, int *); 365 int (*get_temp)(void *, int *);
343 int (*get_trend)(void *, long *); 366 int (*get_trend)(void *, int, enum thermal_trend *);
367 int (*set_trips)(void *, int, int);
344 int (*set_emul_temp)(void *, int); 368 int (*set_emul_temp)(void *, int);
345 int (*set_trip_temp)(void *, int, int); 369 int (*set_trip_temp)(void *, int, int);
346}; 370};
@@ -425,7 +449,9 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
425 unsigned int); 449 unsigned int);
426int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, 450int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
427 struct thermal_cooling_device *); 451 struct thermal_cooling_device *);
428void thermal_zone_device_update(struct thermal_zone_device *); 452void thermal_zone_device_update(struct thermal_zone_device *,
453 enum thermal_notify_event);
454void thermal_zone_set_trips(struct thermal_zone_device *);
429 455
430struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, 456struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
431 const struct thermal_cooling_device_ops *); 457 const struct thermal_cooling_device_ops *);
@@ -435,6 +461,8 @@ thermal_of_cooling_device_register(struct device_node *np, char *, void *,
435void thermal_cooling_device_unregister(struct thermal_cooling_device *); 461void thermal_cooling_device_unregister(struct thermal_cooling_device *);
436struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name); 462struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
437int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); 463int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
464int thermal_zone_get_slope(struct thermal_zone_device *tz);
465int thermal_zone_get_offset(struct thermal_zone_device *tz);
438 466
439int get_tz_trend(struct thermal_zone_device *, int); 467int get_tz_trend(struct thermal_zone_device *, int);
440struct thermal_instance *get_thermal_instance(struct thermal_zone_device *, 468struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
@@ -473,7 +501,10 @@ static inline int thermal_zone_unbind_cooling_device(
473 struct thermal_zone_device *tz, int trip, 501 struct thermal_zone_device *tz, int trip,
474 struct thermal_cooling_device *cdev) 502 struct thermal_cooling_device *cdev)
475{ return -ENODEV; } 503{ return -ENODEV; }
476static inline void thermal_zone_device_update(struct thermal_zone_device *tz) 504static inline void thermal_zone_device_update(struct thermal_zone_device *tz,
505 enum thermal_notify_event event)
506{ }
507static inline void thermal_zone_set_trips(struct thermal_zone_device *tz)
477{ } 508{ }
478static inline struct thermal_cooling_device * 509static inline struct thermal_cooling_device *
479thermal_cooling_device_register(char *type, void *devdata, 510thermal_cooling_device_register(char *type, void *devdata,
@@ -492,6 +523,12 @@ static inline struct thermal_zone_device *thermal_zone_get_zone_by_name(
492static inline int thermal_zone_get_temp( 523static inline int thermal_zone_get_temp(
493 struct thermal_zone_device *tz, int *temp) 524 struct thermal_zone_device *tz, int *temp)
494{ return -ENODEV; } 525{ return -ENODEV; }
526static inline int thermal_zone_get_slope(
527 struct thermal_zone_device *tz)
528{ return -ENODEV; }
529static inline int thermal_zone_get_offset(
530 struct thermal_zone_device *tz)
531{ return -ENODEV; }
495static inline int get_tz_trend(struct thermal_zone_device *tz, int trip) 532static inline int get_tz_trend(struct thermal_zone_device *tz, int trip)
496{ return -ENODEV; } 533{ return -ENODEV; }
497static inline struct thermal_instance * 534static inline struct thermal_instance *