aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-12 14:58:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-12 14:58:45 -0400
commit6a776e47a045462a1df1a3a9592598259ffd614f (patch)
tree79c3ea4b96e48c7c4389114e738dcc0a972c97c0
parenta34ab101a9d27a2995142b47f9857fb46fcb072a (diff)
parentcb15c81a0c1c1f7829b9809a209ecacc77f5aa63 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management updates from Zhang Rui: - Fix a problem where orderly_shutdown() is called for multiple times due to multiple critical overheating events raised in a short period by platform thermal driver. (Keerthy) - Introduce a backup thermal shutdown mechanism, which invokes kernel_power_off()/emergency_restart() directly, after orderly_shutdown() being issued for certain amount of time(specified via Kconfig). This is useful in certain conditions that userspace may be unable to power off the system in a clean manner and leaves the system in a critical state, like in the middle of driver probing phase. (Keerthy) - Introduce a new interface in thermal devfreq_cooling code so that the driver can provide more precise data regarding actual power to the thermal governor every time the power budget is calculated. (Lukasz Luba) - Introduce BCM 2835 soc thermal driver and northstar thermal driver, within a new sub-folder. (Rafał Miłecki) - Introduce DA9062/61 thermal driver. (Steve Twiss) - Remove non-DT booting on TI-SoC driver. Also add support to fetching coefficients from DT. (Keerthy) - Refactorf RCAR Gen3 thermal driver. (Niklas Söderlund) - Small fix on MTK and intel-soc-dts thermal driver. (Dawei Chien, Brian Bian) * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (25 commits) thermal: core: Add a back up thermal shutdown mechanism thermal: core: Allow orderly_poweroff to be called only once Thermal: Intel SoC DTS: Change interrupt request behavior trace: thermal: add another parameter 'power' to the tracing function thermal: devfreq_cooling: add new interface for direct power read thermal: devfreq_cooling: refactor code and add get_voltage function thermal: mt8173: minor mtk_thermal.c cleanups thermal: bcm2835: move to the broadcom subdirectory thermal: broadcom: ns: specify myself as MODULE_AUTHOR thermal: da9062/61: Thermal junction temperature monitoring driver Documentation: devicetree: thermal: da9062/61 TJUNC temperature binding thermal: broadcom: add Northstar thermal driver dt-bindings: thermal: add support for Broadcom's Northstar thermal thermal: bcm2835: add thermal driver for bcm2835 SoC dt-bindings: Add thermal zone to bcm2835-thermal example thermal: rcar_gen3_thermal: add suspend and resume support thermal: rcar_gen3_thermal: store device match data in private structure thermal: rcar_gen3_thermal: enable hardware interrupts for trip points thermal: rcar_gen3_thermal: record and check number of TSCs found thermal: rcar_gen3_thermal: check that TSC exists before memory allocation ...
-rw-r--r--Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt32
-rw-r--r--Documentation/devicetree/bindings/thermal/brcm,ns-thermal37
-rw-r--r--Documentation/devicetree/bindings/thermal/da9062-thermal.txt36
-rw-r--r--Documentation/thermal/sysfs-api.txt21
-rw-r--r--drivers/thermal/Kconfig32
-rw-r--r--drivers/thermal/Makefile2
-rw-r--r--drivers/thermal/broadcom/Kconfig16
-rw-r--r--drivers/thermal/broadcom/Makefile2
-rw-r--r--drivers/thermal/broadcom/bcm2835_thermal.c314
-rw-r--r--drivers/thermal/broadcom/ns-thermal.c106
-rw-r--r--drivers/thermal/da9062-thermal.c315
-rw-r--r--drivers/thermal/devfreq_cooling.c152
-rw-r--r--drivers/thermal/intel_soc_dts_thermal.c9
-rw-r--r--drivers/thermal/mtk_thermal.c2
-rw-r--r--drivers/thermal/rcar_gen3_thermal.c199
-rw-r--r--drivers/thermal/thermal_core.c64
-rw-r--r--drivers/thermal/ti-soc-thermal/dra752-thermal-data.c10
-rw-r--r--drivers/thermal/ti-soc-thermal/omap3-thermal-data.c4
-rw-r--r--drivers/thermal/ti-soc-thermal/omap4-thermal-data.c6
-rw-r--r--drivers/thermal/ti-soc-thermal/omap5-thermal-data.c4
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.h4
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal-common.c158
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal.h16
-rw-r--r--include/linux/devfreq_cooling.h19
-rw-r--r--include/trace/events/thermal.h11
25 files changed, 1305 insertions, 266 deletions
diff --git a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
index 474531d2b2c5..da8c5b73ad10 100644
--- a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
@@ -3,15 +3,39 @@ Binding for Thermal Sensor driver for BCM2835 SoCs.
3Required parameters: 3Required parameters:
4------------------- 4-------------------
5 5
6compatible: should be one of: "brcm,bcm2835-thermal", 6compatible: should be one of: "brcm,bcm2835-thermal",
7 "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal" 7 "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
8reg: Address range of the thermal registers. 8reg: Address range of the thermal registers.
9clocks: Phandle of the clock used by the thermal sensor. 9clocks: Phandle of the clock used by the thermal sensor.
10#thermal-sensor-cells: should be 0 (see thermal.txt)
10 11
11Example: 12Example:
12 13
14thermal-zones {
15 cpu_thermal: cpu-thermal {
16 polling-delay-passive = <0>;
17 polling-delay = <1000>;
18
19 thermal-sensors = <&thermal>;
20
21 trips {
22 cpu-crit {
23 temperature = <80000>;
24 hysteresis = <0>;
25 type = "critical";
26 };
27 };
28
29 coefficients = <(-538) 407000>;
30
31 cooling-maps {
32 };
33 };
34};
35
13thermal: thermal@7e212000 { 36thermal: thermal@7e212000 {
14 compatible = "brcm,bcm2835-thermal"; 37 compatible = "brcm,bcm2835-thermal";
15 reg = <0x7e212000 0x8>; 38 reg = <0x7e212000 0x8>;
16 clocks = <&clocks BCM2835_CLOCK_TSENS>; 39 clocks = <&clocks BCM2835_CLOCK_TSENS>;
40 #thermal-sensor-cells = <0>;
17}; 41};
diff --git a/Documentation/devicetree/bindings/thermal/brcm,ns-thermal b/Documentation/devicetree/bindings/thermal/brcm,ns-thermal
new file mode 100644
index 000000000000..68e047170039
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/brcm,ns-thermal
@@ -0,0 +1,37 @@
1* Broadcom Northstar Thermal
2
3This binding describes thermal sensor that is part of Northstar's DMU (Device
4Management Unit).
5
6Required properties:
7- compatible : Must be "brcm,ns-thermal"
8- reg : iomem address range of PVTMON registers
9- #thermal-sensor-cells : Should be <0>
10
11Example:
12
13thermal: thermal@1800c2c0 {
14 compatible = "brcm,ns-thermal";
15 reg = <0x1800c2c0 0x10>;
16 #thermal-sensor-cells = <0>;
17};
18
19thermal-zones {
20 cpu_thermal: cpu-thermal {
21 polling-delay-passive = <0>;
22 polling-delay = <1000>;
23 coefficients = <(-556) 418000>;
24 thermal-sensors = <&thermal>;
25
26 trips {
27 cpu-crit {
28 temperature = <125000>;
29 hysteresis = <0>;
30 type = "critical";
31 };
32 };
33
34 cooling-maps {
35 };
36 };
37};
diff --git a/Documentation/devicetree/bindings/thermal/da9062-thermal.txt b/Documentation/devicetree/bindings/thermal/da9062-thermal.txt
new file mode 100644
index 000000000000..e241bb5a5584
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/da9062-thermal.txt
@@ -0,0 +1,36 @@
1* Dialog DA9062/61 TJUNC Thermal Module
2
3This module is part of the DA9061/DA9062. For more details about entire
4DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
5
6Junction temperature thermal module uses an interrupt signal to identify
7high THERMAL_TRIP_HOT temperatures for the PMIC device.
8
9Required properties:
10
11- compatible: should be one of the following valid compatible string lines:
12 "dlg,da9061-thermal", "dlg,da9062-thermal"
13 "dlg,da9062-thermal"
14
15Optional properties:
16
17- polling-delay-passive : Specify the polling period, measured in
18 milliseconds, between thermal zone device update checks.
19
20Example: DA9062
21
22 pmic0: da9062@58 {
23 thermal {
24 compatible = "dlg,da9062-thermal";
25 polling-delay-passive = <3000>;
26 };
27 };
28
29Example: DA9061 using a fall-back compatible for the DA9062 onkey driver
30
31 pmic0: da9061@58 {
32 thermal {
33 compatible = "dlg,da9061-thermal", "dlg,da9062-thermal";
34 polling-delay-passive = <3000>;
35 };
36 };
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index ef473dc7f55e..bb9a0a53e76b 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -582,3 +582,24 @@ platform data is provided, this uses the step_wise throttling policy.
582This function serves as an arbitrator to set the state of a cooling 582This function serves as an arbitrator to set the state of a cooling
583device. It sets the cooling device to the deepest cooling state if 583device. It sets the cooling device to the deepest cooling state if
584possible. 584possible.
585
5866. thermal_emergency_poweroff:
587
588On an event of critical trip temperature crossing. Thermal framework
589allows the system to shutdown gracefully by calling orderly_poweroff().
590In the event of a failure of orderly_poweroff() to shut down the system
591we are in danger of keeping the system alive at undesirably high
592temperatures. To mitigate this high risk scenario we program a work
593queue to fire after a pre-determined number of seconds to start
594an emergency shutdown of the device using the kernel_power_off()
595function. In case kernel_power_off() fails then finally
596emergency_restart() is called in the worst case.
597
598The delay should be carefully profiled so as to give adequate time for
599orderly_poweroff(). In case of failure of an orderly_poweroff() the
600emergency poweroff kicks in after the delay has elapsed and shuts down
601the system.
602
603If set to 0 emergency poweroff will not be supported. So a carefully
604profiled non-zero positive value is a must for emergerncy poweroff to be
605triggered.
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 6871ecc5b951..b5b5facb8747 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -15,6 +15,23 @@ menuconfig THERMAL
15 15
16if THERMAL 16if THERMAL
17 17
18config THERMAL_EMERGENCY_POWEROFF_DELAY_MS
19 int "Emergency poweroff delay in milli-seconds"
20 depends on THERMAL
21 default 0
22 help
23 Thermal subsystem will issue a graceful shutdown when
24 critical temperatures are reached using orderly_poweroff(). In
25 case of failure of an orderly_poweroff(), the thermal emergency
26 poweroff kicks in after a delay has elapsed and shuts down the system.
27 This config is number of milliseconds to delay before emergency
28 poweroff kicks in. Similarly to the critical trip point,
29 the delay should be carefully profiled so as to give adequate
30 time for orderly_poweroff() to finish on regular execution.
31 If set to 0 emergency poweroff will not be supported.
32
33 In doubt, leave as 0.
34
18config THERMAL_HWMON 35config THERMAL_HWMON
19 bool 36 bool
20 prompt "Expose thermal sensors as hwmon device" 37 prompt "Expose thermal sensors as hwmon device"
@@ -291,6 +308,16 @@ config ARMADA_THERMAL
291 Enable this option if you want to have support for thermal management 308 Enable this option if you want to have support for thermal management
292 controller present in Armada 370 and Armada XP SoC. 309 controller present in Armada 370 and Armada XP SoC.
293 310
311config DA9062_THERMAL
312 tristate "DA9062/DA9061 Dialog Semiconductor thermal driver"
313 depends on MFD_DA9062 || COMPILE_TEST
314 depends on OF
315 help
316 Enable this for the Dialog Semiconductor thermal sensor driver.
317 This will report PMIC junction over-temperature for one thermal trip
318 zone.
319 Compatible with the DA9062 and DA9061 PMICs.
320
294config INTEL_POWERCLAMP 321config INTEL_POWERCLAMP
295 tristate "Intel PowerClamp idle injection driver" 322 tristate "Intel PowerClamp idle injection driver"
296 depends on THERMAL 323 depends on THERMAL
@@ -380,6 +407,11 @@ config MTK_THERMAL
380 Enable this option if you want to have support for thermal management 407 Enable this option if you want to have support for thermal management
381 controller present in Mediatek SoCs 408 controller present in Mediatek SoCs
382 409
410menu "Broadcom thermal drivers"
411depends on ARCH_BCM || COMPILE_TEST
412source "drivers/thermal/broadcom/Kconfig"
413endmenu
414
383menu "Texas Instruments thermal drivers" 415menu "Texas Instruments thermal drivers"
384depends on ARCH_HAS_BANDGAP || COMPILE_TEST 416depends on ARCH_HAS_BANDGAP || COMPILE_TEST
385depends on HAS_IOMEM 417depends on HAS_IOMEM
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index c2372f10dae5..094d7039981c 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -27,6 +27,7 @@ thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
27thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o 27thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
28 28
29# platform thermal drivers 29# platform thermal drivers
30obj-y += broadcom/
30obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o 31obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
31obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 32obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
32obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o 33obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
@@ -41,6 +42,7 @@ obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o
41obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o 42obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
42obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o 43obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
43obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o 44obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
45obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o
44obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 46obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
45obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o 47obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
46obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o 48obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
diff --git a/drivers/thermal/broadcom/Kconfig b/drivers/thermal/broadcom/Kconfig
new file mode 100644
index 000000000000..ab08af4654ef
--- /dev/null
+++ b/drivers/thermal/broadcom/Kconfig
@@ -0,0 +1,16 @@
1config BCM2835_THERMAL
2 tristate "Thermal sensors on bcm2835 SoC"
3 depends on ARCH_BCM2835 || COMPILE_TEST
4 depends on HAS_IOMEM
5 depends on THERMAL_OF
6 help
7 Support for thermal sensors on Broadcom bcm2835 SoCs.
8
9config BCM_NS_THERMAL
10 tristate "Northstar thermal driver"
11 depends on ARCH_BCM_IPROC || COMPILE_TEST
12 help
13 Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081,
14 BCM4709 and BCM47094. It contains DMU (Device Management Unit) block
15 with a thermal sensor that allows checking CPU temperature. This
16 driver provides support for it.
diff --git a/drivers/thermal/broadcom/Makefile b/drivers/thermal/broadcom/Makefile
new file mode 100644
index 000000000000..c6f62e4fd0ee
--- /dev/null
+++ b/drivers/thermal/broadcom/Makefile
@@ -0,0 +1,2 @@
1obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o
2obj-$(CONFIG_BCM_NS_THERMAL) += ns-thermal.o
diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
new file mode 100644
index 000000000000..0ecf80890c84
--- /dev/null
+++ b/drivers/thermal/broadcom/bcm2835_thermal.c
@@ -0,0 +1,314 @@
1/*
2 * Driver for Broadcom BCM2835 SoC temperature sensor
3 *
4 * Copyright (C) 2016 Martin Sperl
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk.h>
18#include <linux/debugfs.h>
19#include <linux/device.h>
20#include <linux/err.h>
21#include <linux/io.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/of.h>
25#include <linux/of_address.h>
26#include <linux/of_device.h>
27#include <linux/platform_device.h>
28#include <linux/thermal.h>
29
30#define BCM2835_TS_TSENSCTL 0x00
31#define BCM2835_TS_TSENSSTAT 0x04
32
33#define BCM2835_TS_TSENSCTL_PRWDW BIT(0)
34#define BCM2835_TS_TSENSCTL_RSTB BIT(1)
35
36/*
37 * bandgap reference voltage in 6 mV increments
38 * 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV
39 */
40#define BCM2835_TS_TSENSCTL_CTRL_BITS 3
41#define BCM2835_TS_TSENSCTL_CTRL_SHIFT 2
42#define BCM2835_TS_TSENSCTL_CTRL_MASK \
43 GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS + \
44 BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
45 BCM2835_TS_TSENSCTL_CTRL_SHIFT)
46#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT 1
47#define BCM2835_TS_TSENSCTL_EN_INT BIT(5)
48#define BCM2835_TS_TSENSCTL_DIRECT BIT(6)
49#define BCM2835_TS_TSENSCTL_CLR_INT BIT(7)
50#define BCM2835_TS_TSENSCTL_THOLD_SHIFT 8
51#define BCM2835_TS_TSENSCTL_THOLD_BITS 10
52#define BCM2835_TS_TSENSCTL_THOLD_MASK \
53 GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS + \
54 BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
55 BCM2835_TS_TSENSCTL_THOLD_SHIFT)
56/*
57 * time how long the block to be asserted in reset
58 * which based on a clock counter (TSENS clock assumed)
59 */
60#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT 18
61#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS 8
62#define BCM2835_TS_TSENSCTL_REGULEN BIT(26)
63
64#define BCM2835_TS_TSENSSTAT_DATA_BITS 10
65#define BCM2835_TS_TSENSSTAT_DATA_SHIFT 0
66#define BCM2835_TS_TSENSSTAT_DATA_MASK \
67 GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS + \
68 BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
69 BCM2835_TS_TSENSSTAT_DATA_SHIFT)
70#define BCM2835_TS_TSENSSTAT_VALID BIT(10)
71#define BCM2835_TS_TSENSSTAT_INTERRUPT BIT(11)
72
73struct bcm2835_thermal_data {
74 struct thermal_zone_device *tz;
75 void __iomem *regs;
76 struct clk *clk;
77 struct dentry *debugfsdir;
78};
79
80static int bcm2835_thermal_adc2temp(u32 adc, int offset, int slope)
81{
82 return offset + slope * adc;
83}
84
85static int bcm2835_thermal_temp2adc(int temp, int offset, int slope)
86{
87 temp -= offset;
88 temp /= slope;
89
90 if (temp < 0)
91 temp = 0;
92 if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))
93 temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;
94
95 return temp;
96}
97
98static int bcm2835_thermal_get_temp(void *d, int *temp)
99{
100 struct bcm2835_thermal_data *data = d;
101 u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
102
103 if (!(val & BCM2835_TS_TSENSSTAT_VALID))
104 return -EIO;
105
106 val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
107
108 *temp = bcm2835_thermal_adc2temp(
109 val,
110 thermal_zone_get_offset(data->tz),
111 thermal_zone_get_slope(data->tz));
112
113 return 0;
114}
115
116static const struct debugfs_reg32 bcm2835_thermal_regs[] = {
117 {
118 .name = "ctl",
119 .offset = 0
120 },
121 {
122 .name = "stat",
123 .offset = 4
124 }
125};
126
127static void bcm2835_thermal_debugfs(struct platform_device *pdev)
128{
129 struct thermal_zone_device *tz = platform_get_drvdata(pdev);
130 struct bcm2835_thermal_data *data = tz->devdata;
131 struct debugfs_regset32 *regset;
132
133 data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
134 if (!data->debugfsdir)
135 return;
136
137 regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
138 if (!regset)
139 return;
140
141 regset->regs = bcm2835_thermal_regs;
142 regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);
143 regset->base = data->regs;
144
145 debugfs_create_regset32("regset", 0444, data->debugfsdir, regset);
146}
147
148static struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
149 .get_temp = bcm2835_thermal_get_temp,
150};
151
152/*
153 * Note: as per Raspberry Foundation FAQ
154 * (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature)
155 * the recommended temperature range for the SoC -40C to +85C
156 * so the trip limit is set to 80C.
157 * this applies to all the BCM283X SoC
158 */
159
160static const struct of_device_id bcm2835_thermal_of_match_table[] = {
161 {
162 .compatible = "brcm,bcm2835-thermal",
163 },
164 {
165 .compatible = "brcm,bcm2836-thermal",
166 },
167 {
168 .compatible = "brcm,bcm2837-thermal",
169 },
170 {},
171};
172MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
173
174static int bcm2835_thermal_probe(struct platform_device *pdev)
175{
176 const struct of_device_id *match;
177 struct thermal_zone_device *tz;
178 struct bcm2835_thermal_data *data;
179 struct resource *res;
180 int err = 0;
181 u32 val;
182 unsigned long rate;
183
184 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
185 if (!data)
186 return -ENOMEM;
187
188 match = of_match_device(bcm2835_thermal_of_match_table,
189 &pdev->dev);
190 if (!match)
191 return -EINVAL;
192
193 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
194 data->regs = devm_ioremap_resource(&pdev->dev, res);
195 if (IS_ERR(data->regs)) {
196 err = PTR_ERR(data->regs);
197 dev_err(&pdev->dev, "Could not get registers: %d\n", err);
198 return err;
199 }
200
201 data->clk = devm_clk_get(&pdev->dev, NULL);
202 if (IS_ERR(data->clk)) {
203 err = PTR_ERR(data->clk);
204 if (err != -EPROBE_DEFER)
205 dev_err(&pdev->dev, "Could not get clk: %d\n", err);
206 return err;
207 }
208
209 err = clk_prepare_enable(data->clk);
210 if (err)
211 return err;
212
213 rate = clk_get_rate(data->clk);
214 if ((rate < 1920000) || (rate > 5000000))
215 dev_warn(&pdev->dev,
216 "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n",
217 data->clk, data->clk);
218
219 /* register of thermal sensor and get info from DT */
220 tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
221 &bcm2835_thermal_ops);
222 if (IS_ERR(tz)) {
223 err = PTR_ERR(tz);
224 dev_err(&pdev->dev,
225 "Failed to register the thermal device: %d\n",
226 err);
227 goto err_clk;
228 }
229
230 /*
231 * right now the FW does set up the HW-block, so we are not
232 * touching the configuration registers.
233 * But if the HW is not enabled, then set it up
234 * using "sane" values used by the firmware right now.
235 */
236 val = readl(data->regs + BCM2835_TS_TSENSCTL);
237 if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
238 int trip_temp, offset, slope;
239
240 slope = thermal_zone_get_slope(tz);
241 offset = thermal_zone_get_offset(tz);
242 /*
243 * For now we deal only with critical, otherwise
244 * would need to iterate
245 */
246 err = tz->ops->get_trip_temp(tz, 0, &trip_temp);
247 if (err < 0) {
248 err = PTR_ERR(tz);
249 dev_err(&pdev->dev,
250 "Not able to read trip_temp: %d\n",
251 err);
252 goto err_tz;
253 }
254
255 /* set bandgap reference voltage and enable voltage regulator */
256 val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
257 BCM2835_TS_TSENSCTL_CTRL_SHIFT) |
258 BCM2835_TS_TSENSCTL_REGULEN;
259
260 /* use the recommended reset duration */
261 val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
262
263 /* trip_adc value from info */
264 val |= bcm2835_thermal_temp2adc(trip_temp,
265 offset,
266 slope)
267 << BCM2835_TS_TSENSCTL_THOLD_SHIFT;
268
269 /* write the value back to the register as 2 steps */
270 writel(val, data->regs + BCM2835_TS_TSENSCTL);
271 val |= BCM2835_TS_TSENSCTL_RSTB;
272 writel(val, data->regs + BCM2835_TS_TSENSCTL);
273 }
274
275 data->tz = tz;
276
277 platform_set_drvdata(pdev, tz);
278
279 bcm2835_thermal_debugfs(pdev);
280
281 return 0;
282err_tz:
283 thermal_zone_of_sensor_unregister(&pdev->dev, tz);
284err_clk:
285 clk_disable_unprepare(data->clk);
286
287 return err;
288}
289
290static int bcm2835_thermal_remove(struct platform_device *pdev)
291{
292 struct thermal_zone_device *tz = platform_get_drvdata(pdev);
293 struct bcm2835_thermal_data *data = tz->devdata;
294
295 debugfs_remove_recursive(data->debugfsdir);
296 thermal_zone_of_sensor_unregister(&pdev->dev, tz);
297 clk_disable_unprepare(data->clk);
298
299 return 0;
300}
301
302static struct platform_driver bcm2835_thermal_driver = {
303 .probe = bcm2835_thermal_probe,
304 .remove = bcm2835_thermal_remove,
305 .driver = {
306 .name = "bcm2835_thermal",
307 .of_match_table = bcm2835_thermal_of_match_table,
308 },
309};
310module_platform_driver(bcm2835_thermal_driver);
311
312MODULE_AUTHOR("Martin Sperl");
313MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
314MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/broadcom/ns-thermal.c b/drivers/thermal/broadcom/ns-thermal.c
new file mode 100644
index 000000000000..322e741a2463
--- /dev/null
+++ b/drivers/thermal/broadcom/ns-thermal.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
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 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/of_address.h>
11#include <linux/platform_device.h>
12#include <linux/thermal.h>
13
14#define PVTMON_CONTROL0 0x00
15#define PVTMON_CONTROL0_SEL_MASK 0x0000000e
16#define PVTMON_CONTROL0_SEL_TEMP_MONITOR 0x00000000
17#define PVTMON_CONTROL0_SEL_TEST_MODE 0x0000000e
18#define PVTMON_STATUS 0x08
19
20struct ns_thermal {
21 struct thermal_zone_device *tz;
22 void __iomem *pvtmon;
23};
24
25static int ns_thermal_get_temp(void *data, int *temp)
26{
27 struct ns_thermal *ns_thermal = data;
28 int offset = thermal_zone_get_offset(ns_thermal->tz);
29 int slope = thermal_zone_get_slope(ns_thermal->tz);
30 u32 val;
31
32 val = readl(ns_thermal->pvtmon + PVTMON_CONTROL0);
33 if ((val & PVTMON_CONTROL0_SEL_MASK) != PVTMON_CONTROL0_SEL_TEMP_MONITOR) {
34 /* Clear current mode selection */
35 val &= ~PVTMON_CONTROL0_SEL_MASK;
36
37 /* Set temp monitor mode (it's the default actually) */
38 val |= PVTMON_CONTROL0_SEL_TEMP_MONITOR;
39
40 writel(val, ns_thermal->pvtmon + PVTMON_CONTROL0);
41 }
42
43 val = readl(ns_thermal->pvtmon + PVTMON_STATUS);
44 *temp = slope * val + offset;
45
46 return 0;
47}
48
49static const struct thermal_zone_of_device_ops ns_thermal_ops = {
50 .get_temp = ns_thermal_get_temp,
51};
52
53static int ns_thermal_probe(struct platform_device *pdev)
54{
55 struct device *dev = &pdev->dev;
56 struct ns_thermal *ns_thermal;
57
58 ns_thermal = devm_kzalloc(dev, sizeof(*ns_thermal), GFP_KERNEL);
59 if (!ns_thermal)
60 return -ENOMEM;
61
62 ns_thermal->pvtmon = of_iomap(dev_of_node(dev), 0);
63 if (WARN_ON(!ns_thermal->pvtmon))
64 return -ENOENT;
65
66 ns_thermal->tz = devm_thermal_zone_of_sensor_register(dev, 0,
67 ns_thermal,
68 &ns_thermal_ops);
69 if (IS_ERR(ns_thermal->tz)) {
70 iounmap(ns_thermal->pvtmon);
71 return PTR_ERR(ns_thermal->tz);
72 }
73
74 platform_set_drvdata(pdev, ns_thermal);
75
76 return 0;
77}
78
79static int ns_thermal_remove(struct platform_device *pdev)
80{
81 struct ns_thermal *ns_thermal = platform_get_drvdata(pdev);
82
83 iounmap(ns_thermal->pvtmon);
84
85 return 0;
86}
87
88static const struct of_device_id ns_thermal_of_match[] = {
89 { .compatible = "brcm,ns-thermal", },
90 {},
91};
92MODULE_DEVICE_TABLE(of, ns_thermal_of_match);
93
94static struct platform_driver ns_thermal_driver = {
95 .probe = ns_thermal_probe,
96 .remove = ns_thermal_remove,
97 .driver = {
98 .name = "ns-thermal",
99 .of_match_table = ns_thermal_of_match,
100 },
101};
102module_platform_driver(ns_thermal_driver);
103
104MODULE_AUTHOR("Rafał Miłecki <rafal@milecki.pl>");
105MODULE_DESCRIPTION("Northstar thermal driver");
106MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c
new file mode 100644
index 000000000000..dd8dd947b7f0
--- /dev/null
+++ b/drivers/thermal/da9062-thermal.c
@@ -0,0 +1,315 @@
1/*
2 * Thermal device driver for DA9062 and DA9061
3 * Copyright (C) 2017 Dialog Semiconductor
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
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/* When over-temperature is reached, an interrupt from the device will be
17 * triggered. Following this event the interrupt will be disabled and
18 * periodic transmission of uevents (HOT trip point) should define the
19 * first level of temperature supervision. It is expected that any final
20 * implementation of the thermal driver will include a .notify() function
21 * to implement these uevents to userspace.
22 *
23 * These uevents are intended to indicate non-invasive temperature control
24 * of the system, where the necessary measures for cooling are the
25 * responsibility of the host software. Once the temperature falls again,
26 * the IRQ is re-enabled so the start of a new over-temperature event can
27 * be detected without constant software monitoring.
28 */
29
30#include <linux/errno.h>
31#include <linux/interrupt.h>
32#include <linux/module.h>
33#include <linux/of.h>
34#include <linux/platform_device.h>
35#include <linux/regmap.h>
36#include <linux/thermal.h>
37#include <linux/workqueue.h>
38
39#include <linux/mfd/da9062/core.h>
40#include <linux/mfd/da9062/registers.h>
41
42/* Minimum, maximum and default polling millisecond periods are provided
43 * here as an example. It is expected that any final implementation to also
44 * include a modification of these settings to match the required
45 * application.
46 */
47#define DA9062_DEFAULT_POLLING_MS_PERIOD 3000
48#define DA9062_MAX_POLLING_MS_PERIOD 10000
49#define DA9062_MIN_POLLING_MS_PERIOD 1000
50
51#define DA9062_MILLI_CELSIUS(t) ((t) * 1000)
52
53struct da9062_thermal_config {
54 const char *name;
55};
56
57struct da9062_thermal {
58 struct da9062 *hw;
59 struct delayed_work work;
60 struct thermal_zone_device *zone;
61 enum thermal_device_mode mode;
62 struct mutex lock; /* protection for da9062_thermal temperature */
63 int temperature;
64 int irq;
65 const struct da9062_thermal_config *config;
66 struct device *dev;
67};
68
69static void da9062_thermal_poll_on(struct work_struct *work)
70{
71 struct da9062_thermal *thermal = container_of(work,
72 struct da9062_thermal,
73 work.work);
74 unsigned long delay;
75 unsigned int val;
76 int ret;
77
78 /* clear E_TEMP */
79 ret = regmap_write(thermal->hw->regmap,
80 DA9062AA_EVENT_B,
81 DA9062AA_E_TEMP_MASK);
82 if (ret < 0) {
83 dev_err(thermal->dev,
84 "Cannot clear the TJUNC temperature status\n");
85 goto err_enable_irq;
86 }
87
88 /* Now read E_TEMP again: it is acting like a status bit.
89 * If over-temperature, then this status will be true.
90 * If not over-temperature, this status will be false.
91 */
92 ret = regmap_read(thermal->hw->regmap,
93 DA9062AA_EVENT_B,
94 &val);
95 if (ret < 0) {
96 dev_err(thermal->dev,
97 "Cannot check the TJUNC temperature status\n");
98 goto err_enable_irq;
99 }
100
101 if (val & DA9062AA_E_TEMP_MASK) {
102 mutex_lock(&thermal->lock);
103 thermal->temperature = DA9062_MILLI_CELSIUS(125);
104 mutex_unlock(&thermal->lock);
105 thermal_zone_device_update(thermal->zone,
106 THERMAL_EVENT_UNSPECIFIED);
107
108 delay = msecs_to_jiffies(thermal->zone->passive_delay);
109 schedule_delayed_work(&thermal->work, delay);
110 return;
111 }
112
113 mutex_lock(&thermal->lock);
114 thermal->temperature = DA9062_MILLI_CELSIUS(0);
115 mutex_unlock(&thermal->lock);
116 thermal_zone_device_update(thermal->zone,
117 THERMAL_EVENT_UNSPECIFIED);
118
119err_enable_irq:
120 enable_irq(thermal->irq);
121}
122
123static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)
124{
125 struct da9062_thermal *thermal = data;
126
127 disable_irq_nosync(thermal->irq);
128 schedule_delayed_work(&thermal->work, 0);
129
130 return IRQ_HANDLED;
131}
132
133static int da9062_thermal_get_mode(struct thermal_zone_device *z,
134 enum thermal_device_mode *mode)
135{
136 struct da9062_thermal *thermal = z->devdata;
137 *mode = thermal->mode;
138 return 0;
139}
140
141static int da9062_thermal_get_trip_type(struct thermal_zone_device *z,
142 int trip,
143 enum thermal_trip_type *type)
144{
145 struct da9062_thermal *thermal = z->devdata;
146
147 switch (trip) {
148 case 0:
149 *type = THERMAL_TRIP_HOT;
150 break;
151 default:
152 dev_err(thermal->dev,
153 "Driver does not support more than 1 trip-wire\n");
154 return -EINVAL;
155 }
156
157 return 0;
158}
159
160static int da9062_thermal_get_trip_temp(struct thermal_zone_device *z,
161 int trip,
162 int *temp)
163{
164 struct da9062_thermal *thermal = z->devdata;
165
166 switch (trip) {
167 case 0:
168 *temp = DA9062_MILLI_CELSIUS(125);
169 break;
170 default:
171 dev_err(thermal->dev,
172 "Driver does not support more than 1 trip-wire\n");
173 return -EINVAL;
174 }
175
176 return 0;
177}
178
179static int da9062_thermal_get_temp(struct thermal_zone_device *z,
180 int *temp)
181{
182 struct da9062_thermal *thermal = z->devdata;
183
184 mutex_lock(&thermal->lock);
185 *temp = thermal->temperature;
186 mutex_unlock(&thermal->lock);
187
188 return 0;
189}
190
191static struct thermal_zone_device_ops da9062_thermal_ops = {
192 .get_temp = da9062_thermal_get_temp,
193 .get_mode = da9062_thermal_get_mode,
194 .get_trip_type = da9062_thermal_get_trip_type,
195 .get_trip_temp = da9062_thermal_get_trip_temp,
196};
197
198static const struct da9062_thermal_config da9062_config = {
199 .name = "da9062-thermal",
200};
201
202static const struct of_device_id da9062_compatible_reg_id_table[] = {
203 { .compatible = "dlg,da9062-thermal", .data = &da9062_config },
204 { },
205};
206
207MODULE_DEVICE_TABLE(of, da9062_compatible_reg_id_table);
208
209static int da9062_thermal_probe(struct platform_device *pdev)
210{
211 struct da9062 *chip = dev_get_drvdata(pdev->dev.parent);
212 struct da9062_thermal *thermal;
213 unsigned int pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;
214 const struct of_device_id *match;
215 int ret = 0;
216
217 match = of_match_node(da9062_compatible_reg_id_table,
218 pdev->dev.of_node);
219 if (!match)
220 return -ENXIO;
221
222 if (pdev->dev.of_node) {
223 if (!of_property_read_u32(pdev->dev.of_node,
224 "polling-delay-passive",
225 &pp_tmp)) {
226 if (pp_tmp < DA9062_MIN_POLLING_MS_PERIOD ||
227 pp_tmp > DA9062_MAX_POLLING_MS_PERIOD) {
228 dev_warn(&pdev->dev,
229 "Out-of-range polling period %d ms\n",
230 pp_tmp);
231 pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;
232 }
233 }
234 }
235
236 thermal = devm_kzalloc(&pdev->dev, sizeof(struct da9062_thermal),
237 GFP_KERNEL);
238 if (!thermal) {
239 ret = -ENOMEM;
240 goto err;
241 }
242
243 thermal->config = match->data;
244 thermal->hw = chip;
245 thermal->mode = THERMAL_DEVICE_ENABLED;
246 thermal->dev = &pdev->dev;
247
248 INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);
249 mutex_init(&thermal->lock);
250
251 thermal->zone = thermal_zone_device_register(thermal->config->name,
252 1, 0, thermal,
253 &da9062_thermal_ops, NULL, pp_tmp,
254 0);
255 if (IS_ERR(thermal->zone)) {
256 dev_err(&pdev->dev, "Cannot register thermal zone device\n");
257 ret = PTR_ERR(thermal->zone);
258 goto err;
259 }
260
261 dev_dbg(&pdev->dev,
262 "TJUNC temperature polling period set at %d ms\n",
263 thermal->zone->passive_delay);
264
265 ret = platform_get_irq_byname(pdev, "THERMAL");
266 if (ret < 0) {
267 dev_err(&pdev->dev, "Failed to get platform IRQ.\n");
268 goto err_zone;
269 }
270 thermal->irq = ret;
271
272 ret = request_threaded_irq(thermal->irq, NULL,
273 da9062_thermal_irq_handler,
274 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
275 "THERMAL", thermal);
276 if (ret) {
277 dev_err(&pdev->dev,
278 "Failed to request thermal device IRQ.\n");
279 goto err_zone;
280 }
281
282 platform_set_drvdata(pdev, thermal);
283 return 0;
284
285err_zone:
286 thermal_zone_device_unregister(thermal->zone);
287err:
288 return ret;
289}
290
291static int da9062_thermal_remove(struct platform_device *pdev)
292{
293 struct da9062_thermal *thermal = platform_get_drvdata(pdev);
294
295 free_irq(thermal->irq, thermal);
296 cancel_delayed_work_sync(&thermal->work);
297 thermal_zone_device_unregister(thermal->zone);
298 return 0;
299}
300
301static struct platform_driver da9062_thermal_driver = {
302 .probe = da9062_thermal_probe,
303 .remove = da9062_thermal_remove,
304 .driver = {
305 .name = "da9062-thermal",
306 .of_match_table = da9062_compatible_reg_id_table,
307 },
308};
309
310module_platform_driver(da9062_thermal_driver);
311
312MODULE_AUTHOR("Steve Twiss");
313MODULE_DESCRIPTION("Thermal TJUNC device driver for Dialog DA9062 and DA9061");
314MODULE_LICENSE("GPL");
315MODULE_ALIAS("platform:da9062-thermal");
diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c
index 4bf4ad58cffd..ef59256887ff 100644
--- a/drivers/thermal/devfreq_cooling.c
+++ b/drivers/thermal/devfreq_cooling.c
@@ -28,6 +28,8 @@
28 28
29#include <trace/events/thermal.h> 29#include <trace/events/thermal.h>
30 30
31#define SCALE_ERROR_MITIGATION 100
32
31static DEFINE_IDA(devfreq_ida); 33static DEFINE_IDA(devfreq_ida);
32 34
33/** 35/**
@@ -45,6 +47,12 @@ static DEFINE_IDA(devfreq_ida);
45 * @freq_table_size: Size of the @freq_table and @power_table 47 * @freq_table_size: Size of the @freq_table and @power_table
46 * @power_ops: Pointer to devfreq_cooling_power, used to generate the 48 * @power_ops: Pointer to devfreq_cooling_power, used to generate the
47 * @power_table. 49 * @power_table.
50 * @res_util: Resource utilization scaling factor for the power.
51 * It is multiplied by 100 to minimize the error. It is used
52 * for estimation of the power budget instead of using
53 * 'utilization' (which is 'busy_time / 'total_time').
54 * The 'res_util' range is from 100 to (power_table[state] * 100)
55 * for the corresponding 'state'.
48 */ 56 */
49struct devfreq_cooling_device { 57struct devfreq_cooling_device {
50 int id; 58 int id;
@@ -55,6 +63,8 @@ struct devfreq_cooling_device {
55 u32 *freq_table; 63 u32 *freq_table;
56 size_t freq_table_size; 64 size_t freq_table_size;
57 struct devfreq_cooling_power *power_ops; 65 struct devfreq_cooling_power *power_ops;
66 u32 res_util;
67 int capped_state;
58}; 68};
59 69
60/** 70/**
@@ -164,27 +174,12 @@ freq_get_state(struct devfreq_cooling_device *dfc, unsigned long freq)
164 return THERMAL_CSTATE_INVALID; 174 return THERMAL_CSTATE_INVALID;
165} 175}
166 176
167/** 177static unsigned long get_voltage(struct devfreq *df, unsigned long freq)
168 * get_static_power() - calculate the static power
169 * @dfc: Pointer to devfreq cooling device
170 * @freq: Frequency in Hz
171 *
172 * Calculate the static power in milliwatts using the supplied
173 * get_static_power(). The current voltage is calculated using the
174 * OPP library. If no get_static_power() was supplied, assume the
175 * static power is negligible.
176 */
177static unsigned long
178get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
179{ 178{
180 struct devfreq *df = dfc->devfreq;
181 struct device *dev = df->dev.parent; 179 struct device *dev = df->dev.parent;
182 unsigned long voltage; 180 unsigned long voltage;
183 struct dev_pm_opp *opp; 181 struct dev_pm_opp *opp;
184 182
185 if (!dfc->power_ops->get_static_power)
186 return 0;
187
188 opp = dev_pm_opp_find_freq_exact(dev, freq, true); 183 opp = dev_pm_opp_find_freq_exact(dev, freq, true);
189 if (PTR_ERR(opp) == -ERANGE) 184 if (PTR_ERR(opp) == -ERANGE)
190 opp = dev_pm_opp_find_freq_exact(dev, freq, false); 185 opp = dev_pm_opp_find_freq_exact(dev, freq, false);
@@ -202,9 +197,35 @@ get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
202 dev_err_ratelimited(dev, 197 dev_err_ratelimited(dev,
203 "Failed to get voltage for frequency %lu\n", 198 "Failed to get voltage for frequency %lu\n",
204 freq); 199 freq);
205 return 0;
206 } 200 }
207 201
202 return voltage;
203}
204
205/**
206 * get_static_power() - calculate the static power
207 * @dfc: Pointer to devfreq cooling device
208 * @freq: Frequency in Hz
209 *
210 * Calculate the static power in milliwatts using the supplied
211 * get_static_power(). The current voltage is calculated using the
212 * OPP library. If no get_static_power() was supplied, assume the
213 * static power is negligible.
214 */
215static unsigned long
216get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
217{
218 struct devfreq *df = dfc->devfreq;
219 unsigned long voltage;
220
221 if (!dfc->power_ops->get_static_power)
222 return 0;
223
224 voltage = get_voltage(df, freq);
225
226 if (voltage == 0)
227 return 0;
228
208 return dfc->power_ops->get_static_power(df, voltage); 229 return dfc->power_ops->get_static_power(df, voltage);
209} 230}
210 231
@@ -239,6 +260,16 @@ get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq,
239 return power; 260 return power;
240} 261}
241 262
263
264static inline unsigned long get_total_power(struct devfreq_cooling_device *dfc,
265 unsigned long freq,
266 unsigned long voltage)
267{
268 return get_static_power(dfc, freq) + get_dynamic_power(dfc, freq,
269 voltage);
270}
271
272
242static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev, 273static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev,
243 struct thermal_zone_device *tz, 274 struct thermal_zone_device *tz,
244 u32 *power) 275 u32 *power)
@@ -248,27 +279,55 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd
248 struct devfreq_dev_status *status = &df->last_status; 279 struct devfreq_dev_status *status = &df->last_status;
249 unsigned long state; 280 unsigned long state;
250 unsigned long freq = status->current_frequency; 281 unsigned long freq = status->current_frequency;
251 u32 dyn_power, static_power; 282 unsigned long voltage;
283 u32 dyn_power = 0;
284 u32 static_power = 0;
285 int res;
252 286
253 /* Get dynamic power for state */
254 state = freq_get_state(dfc, freq); 287 state = freq_get_state(dfc, freq);
255 if (state == THERMAL_CSTATE_INVALID) 288 if (state == THERMAL_CSTATE_INVALID) {
256 return -EAGAIN; 289 res = -EAGAIN;
290 goto fail;
291 }
257 292
258 dyn_power = dfc->power_table[state]; 293 if (dfc->power_ops->get_real_power) {
294 voltage = get_voltage(df, freq);
295 if (voltage == 0) {
296 res = -EINVAL;
297 goto fail;
298 }
259 299
260 /* Scale dynamic power for utilization */ 300 res = dfc->power_ops->get_real_power(df, power, freq, voltage);
261 dyn_power = (dyn_power * status->busy_time) / status->total_time; 301 if (!res) {
302 state = dfc->capped_state;
303 dfc->res_util = dfc->power_table[state];
304 dfc->res_util *= SCALE_ERROR_MITIGATION;
262 305
263 /* Get static power */ 306 if (*power > 1)
264 static_power = get_static_power(dfc, freq); 307 dfc->res_util /= *power;
308 } else {
309 goto fail;
310 }
311 } else {
312 dyn_power = dfc->power_table[state];
265 313
266 trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power, 314 /* Scale dynamic power for utilization */
267 static_power); 315 dyn_power *= status->busy_time;
316 dyn_power /= status->total_time;
317 /* Get static power */
318 static_power = get_static_power(dfc, freq);
268 319
269 *power = dyn_power + static_power; 320 *power = dyn_power + static_power;
321 }
322
323 trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power,
324 static_power, *power);
270 325
271 return 0; 326 return 0;
327fail:
328 /* It is safe to set max in this case */
329 dfc->res_util = SCALE_ERROR_MITIGATION;
330 return res;
272} 331}
273 332
274static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, 333static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev,
@@ -301,26 +360,34 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
301 unsigned long busy_time; 360 unsigned long busy_time;
302 s32 dyn_power; 361 s32 dyn_power;
303 u32 static_power; 362 u32 static_power;
363 s32 est_power;
304 int i; 364 int i;
305 365
306 static_power = get_static_power(dfc, freq); 366 if (dfc->power_ops->get_real_power) {
367 /* Scale for resource utilization */
368 est_power = power * dfc->res_util;
369 est_power /= SCALE_ERROR_MITIGATION;
370 } else {
371 static_power = get_static_power(dfc, freq);
307 372
308 dyn_power = power - static_power; 373 dyn_power = power - static_power;
309 dyn_power = dyn_power > 0 ? dyn_power : 0; 374 dyn_power = dyn_power > 0 ? dyn_power : 0;
310 375
311 /* Scale dynamic power for utilization */ 376 /* Scale dynamic power for utilization */
312 busy_time = status->busy_time ?: 1; 377 busy_time = status->busy_time ?: 1;
313 dyn_power = (dyn_power * status->total_time) / busy_time; 378 est_power = (dyn_power * status->total_time) / busy_time;
379 }
314 380
315 /* 381 /*
316 * Find the first cooling state that is within the power 382 * Find the first cooling state that is within the power
317 * budget for dynamic power. 383 * budget for dynamic power.
318 */ 384 */
319 for (i = 0; i < dfc->freq_table_size - 1; i++) 385 for (i = 0; i < dfc->freq_table_size - 1; i++)
320 if (dyn_power >= dfc->power_table[i]) 386 if (est_power >= dfc->power_table[i])
321 break; 387 break;
322 388
323 *state = i; 389 *state = i;
390 dfc->capped_state = i;
324 trace_thermal_power_devfreq_limit(cdev, freq, *state, power); 391 trace_thermal_power_devfreq_limit(cdev, freq, *state, power);
325 return 0; 392 return 0;
326} 393}
@@ -376,7 +443,7 @@ static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc)
376 } 443 }
377 444
378 for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) { 445 for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) {
379 unsigned long power_dyn, voltage; 446 unsigned long power, voltage;
380 struct dev_pm_opp *opp; 447 struct dev_pm_opp *opp;
381 448
382 opp = dev_pm_opp_find_freq_floor(dev, &freq); 449 opp = dev_pm_opp_find_freq_floor(dev, &freq);
@@ -389,12 +456,15 @@ static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc)
389 dev_pm_opp_put(opp); 456 dev_pm_opp_put(opp);
390 457
391 if (dfc->power_ops) { 458 if (dfc->power_ops) {
392 power_dyn = get_dynamic_power(dfc, freq, voltage); 459 if (dfc->power_ops->get_real_power)
460 power = get_total_power(dfc, freq, voltage);
461 else
462 power = get_dynamic_power(dfc, freq, voltage);
393 463
394 dev_dbg(dev, "Dynamic power table: %lu MHz @ %lu mV: %lu = %lu mW\n", 464 dev_dbg(dev, "Power table: %lu MHz @ %lu mV: %lu = %lu mW\n",
395 freq / 1000000, voltage, power_dyn, power_dyn); 465 freq / 1000000, voltage, power, power);
396 466
397 power_table[i] = power_dyn; 467 power_table[i] = power;
398 } 468 }
399 469
400 freq_table[i] = freq; 470 freq_table[i] = freq;
diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c
index b2bbaa1c60b0..c27868b2c6af 100644
--- a/drivers/thermal/intel_soc_dts_thermal.c
+++ b/drivers/thermal/intel_soc_dts_thermal.c
@@ -73,8 +73,12 @@ static int __init intel_soc_thermal_init(void)
73 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 73 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
74 "soc_dts", soc_dts); 74 "soc_dts", soc_dts);
75 if (err) { 75 if (err) {
76 pr_err("request_threaded_irq ret %d\n", err); 76 /*
77 goto error_irq; 77 * Do not just error out because the user space thermal
78 * daemon such as DPTF may use polling instead of being
79 * interrupt driven.
80 */
81 pr_warn("request_threaded_irq ret %d\n", err);
78 } 82 }
79 } 83 }
80 84
@@ -88,7 +92,6 @@ static int __init intel_soc_thermal_init(void)
88error_trips: 92error_trips:
89 if (soc_dts_thres_irq) 93 if (soc_dts_thres_irq)
90 free_irq(soc_dts_thres_irq, soc_dts); 94 free_irq(soc_dts_thres_irq, soc_dts);
91error_irq:
92 intel_soc_dts_iosf_exit(soc_dts); 95 intel_soc_dts_iosf_exit(soc_dts);
93 96
94 return err; 97 return err;
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index 1aff7fde54b1..7737f14846f9 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -191,7 +191,7 @@ static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = {
191}; 191};
192 192
193static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = { 193static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = {
194 TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR2 194 TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3
195}; 195};
196 196
197static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = { 197static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
index d33c845244b1..37fcefd06d9f 100644
--- a/drivers/thermal/rcar_gen3_thermal.c
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -20,12 +20,14 @@
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/io.h> 21#include <linux/io.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/mutex.h>
24#include <linux/of_device.h> 23#include <linux/of_device.h>
25#include <linux/platform_device.h> 24#include <linux/platform_device.h>
26#include <linux/pm_runtime.h> 25#include <linux/pm_runtime.h>
26#include <linux/spinlock.h>
27#include <linux/thermal.h> 27#include <linux/thermal.h>
28 28
29#include "thermal_core.h"
30
29/* Register offsets */ 31/* Register offsets */
30#define REG_GEN3_IRQSTR 0x04 32#define REG_GEN3_IRQSTR 0x04
31#define REG_GEN3_IRQMSK 0x08 33#define REG_GEN3_IRQMSK 0x08
@@ -41,6 +43,14 @@
41#define REG_GEN3_THCODE2 0x54 43#define REG_GEN3_THCODE2 0x54
42#define REG_GEN3_THCODE3 0x58 44#define REG_GEN3_THCODE3 0x58
43 45
46/* IRQ{STR,MSK,EN} bits */
47#define IRQ_TEMP1 BIT(0)
48#define IRQ_TEMP2 BIT(1)
49#define IRQ_TEMP3 BIT(2)
50#define IRQ_TEMPD1 BIT(3)
51#define IRQ_TEMPD2 BIT(4)
52#define IRQ_TEMPD3 BIT(5)
53
44/* CTSR bits */ 54/* CTSR bits */
45#define CTSR_PONM BIT(8) 55#define CTSR_PONM BIT(8)
46#define CTSR_AOUT BIT(7) 56#define CTSR_AOUT BIT(7)
@@ -72,11 +82,15 @@ struct rcar_gen3_thermal_tsc {
72 void __iomem *base; 82 void __iomem *base;
73 struct thermal_zone_device *zone; 83 struct thermal_zone_device *zone;
74 struct equation_coefs coef; 84 struct equation_coefs coef;
75 struct mutex lock; 85 int low;
86 int high;
76}; 87};
77 88
78struct rcar_gen3_thermal_priv { 89struct rcar_gen3_thermal_priv {
79 struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM]; 90 struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM];
91 unsigned int num_tscs;
92 spinlock_t lock; /* Protect interrupts on and off */
93 const struct rcar_gen3_thermal_data *data;
80}; 94};
81 95
82struct rcar_gen3_thermal_data { 96struct rcar_gen3_thermal_data {
@@ -114,6 +128,7 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
114 128
115#define FIXPT_SHIFT 7 129#define FIXPT_SHIFT 7
116#define FIXPT_INT(_x) ((_x) << FIXPT_SHIFT) 130#define FIXPT_INT(_x) ((_x) << FIXPT_SHIFT)
131#define INT_FIXPT(_x) ((_x) >> FIXPT_SHIFT)
117#define FIXPT_DIV(_a, _b) DIV_ROUND_CLOSEST(((_a) << FIXPT_SHIFT), (_b)) 132#define FIXPT_DIV(_a, _b) DIV_ROUND_CLOSEST(((_a) << FIXPT_SHIFT), (_b))
118#define FIXPT_TO_MCELSIUS(_x) ((_x) * 1000 >> FIXPT_SHIFT) 133#define FIXPT_TO_MCELSIUS(_x) ((_x) * 1000 >> FIXPT_SHIFT)
119 134
@@ -163,16 +178,12 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
163 u32 reg; 178 u32 reg;
164 179
165 /* Read register and convert to mili Celsius */ 180 /* Read register and convert to mili Celsius */
166 mutex_lock(&tsc->lock);
167
168 reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK; 181 reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;
169 182
170 val1 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, tsc->coef.a1); 183 val1 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, tsc->coef.a1);
171 val2 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b2, tsc->coef.a2); 184 val2 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b2, tsc->coef.a2);
172 mcelsius = FIXPT_TO_MCELSIUS((val1 + val2) / 2); 185 mcelsius = FIXPT_TO_MCELSIUS((val1 + val2) / 2);
173 186
174 mutex_unlock(&tsc->lock);
175
176 /* Make sure we are inside specifications */ 187 /* Make sure we are inside specifications */
177 if ((mcelsius < MCELSIUS(-40)) || (mcelsius > MCELSIUS(125))) 188 if ((mcelsius < MCELSIUS(-40)) || (mcelsius > MCELSIUS(125)))
178 return -EIO; 189 return -EIO;
@@ -183,10 +194,90 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
183 return 0; 194 return 0;
184} 195}
185 196
197static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc,
198 int mcelsius)
199{
200 int celsius, val1, val2;
201
202 celsius = DIV_ROUND_CLOSEST(mcelsius, 1000);
203 val1 = celsius * tsc->coef.a1 + tsc->coef.b1;
204 val2 = celsius * tsc->coef.a2 + tsc->coef.b2;
205
206 return INT_FIXPT((val1 + val2) / 2);
207}
208
209static int rcar_gen3_thermal_set_trips(void *devdata, int low, int high)
210{
211 struct rcar_gen3_thermal_tsc *tsc = devdata;
212
213 low = clamp_val(low, -40000, 125000);
214 high = clamp_val(high, -40000, 125000);
215
216 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1,
217 rcar_gen3_thermal_mcelsius_to_temp(tsc, low));
218
219 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP2,
220 rcar_gen3_thermal_mcelsius_to_temp(tsc, high));
221
222 tsc->low = low;
223 tsc->high = high;
224
225 return 0;
226}
227
186static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = { 228static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = {
187 .get_temp = rcar_gen3_thermal_get_temp, 229 .get_temp = rcar_gen3_thermal_get_temp,
230 .set_trips = rcar_gen3_thermal_set_trips,
188}; 231};
189 232
233static void rcar_thermal_irq_set(struct rcar_gen3_thermal_priv *priv, bool on)
234{
235 unsigned int i;
236 u32 val = on ? IRQ_TEMPD1 | IRQ_TEMP2 : 0;
237
238 for (i = 0; i < priv->num_tscs; i++)
239 rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQMSK, val);
240}
241
242static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
243{
244 struct rcar_gen3_thermal_priv *priv = data;
245 u32 status;
246 int i, ret = IRQ_HANDLED;
247
248 spin_lock(&priv->lock);
249 for (i = 0; i < priv->num_tscs; i++) {
250 status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR);
251 rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0);
252 if (status)
253 ret = IRQ_WAKE_THREAD;
254 }
255
256 if (ret == IRQ_WAKE_THREAD)
257 rcar_thermal_irq_set(priv, false);
258
259 spin_unlock(&priv->lock);
260
261 return ret;
262}
263
264static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data)
265{
266 struct rcar_gen3_thermal_priv *priv = data;
267 unsigned long flags;
268 int i;
269
270 for (i = 0; i < priv->num_tscs; i++)
271 thermal_zone_device_update(priv->tscs[i]->zone,
272 THERMAL_EVENT_UNSPECIFIED);
273
274 spin_lock_irqsave(&priv->lock, flags);
275 rcar_thermal_irq_set(priv, true);
276 spin_unlock_irqrestore(&priv->lock, flags);
277
278 return IRQ_HANDLED;
279}
280
190static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc) 281static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
191{ 282{
192 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR); 283 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR);
@@ -195,7 +286,11 @@ static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
195 usleep_range(1000, 2000); 286 usleep_range(1000, 2000);
196 287
197 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_PONM); 288 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_PONM);
289
198 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); 290 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F);
291 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0);
292 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2);
293
199 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 294 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR,
200 CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN); 295 CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN);
201 296
@@ -219,9 +314,14 @@ static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
219 usleep_range(1000, 2000); 314 usleep_range(1000, 2000);
220 315
221 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); 316 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F);
317 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0);
318 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2);
319
222 reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR); 320 reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR);
223 reg_val |= THCTR_THSST; 321 reg_val |= THCTR_THSST;
224 rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val); 322 rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val);
323
324 usleep_range(1000, 2000);
225} 325}
226 326
227static const struct rcar_gen3_thermal_data r8a7795_data = { 327static const struct rcar_gen3_thermal_data r8a7795_data = {
@@ -255,9 +355,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
255 struct device *dev = &pdev->dev; 355 struct device *dev = &pdev->dev;
256 struct resource *res; 356 struct resource *res;
257 struct thermal_zone_device *zone; 357 struct thermal_zone_device *zone;
258 int ret, i; 358 int ret, irq, i;
259 const struct rcar_gen3_thermal_data *match_data = 359 char *irqname;
260 of_device_get_match_data(dev);
261 360
262 /* default values if FUSEs are missing */ 361 /* default values if FUSEs are missing */
263 /* TODO: Read values from hardware on supported platforms */ 362 /* TODO: Read values from hardware on supported platforms */
@@ -272,24 +371,50 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
272 if (!priv) 371 if (!priv)
273 return -ENOMEM; 372 return -ENOMEM;
274 373
374 priv->data = of_device_get_match_data(dev);
375
376 spin_lock_init(&priv->lock);
377
275 platform_set_drvdata(pdev, priv); 378 platform_set_drvdata(pdev, priv);
276 379
380 /*
381 * Request 2 (of the 3 possible) IRQs, the driver only needs to
382 * to trigger on the low and high trip points of the current
383 * temp window at this point.
384 */
385 for (i = 0; i < 2; i++) {
386 irq = platform_get_irq(pdev, i);
387 if (irq < 0)
388 return irq;
389
390 irqname = devm_kasprintf(dev, GFP_KERNEL, "%s:ch%d",
391 dev_name(dev), i);
392 if (!irqname)
393 return -ENOMEM;
394
395 ret = devm_request_threaded_irq(dev, irq, rcar_gen3_thermal_irq,
396 rcar_gen3_thermal_irq_thread,
397 IRQF_SHARED, irqname, priv);
398 if (ret)
399 return ret;
400 }
401
277 pm_runtime_enable(dev); 402 pm_runtime_enable(dev);
278 pm_runtime_get_sync(dev); 403 pm_runtime_get_sync(dev);
279 404
280 for (i = 0; i < TSC_MAX_NUM; i++) { 405 for (i = 0; i < TSC_MAX_NUM; i++) {
281 struct rcar_gen3_thermal_tsc *tsc; 406 struct rcar_gen3_thermal_tsc *tsc;
282 407
408 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
409 if (!res)
410 break;
411
283 tsc = devm_kzalloc(dev, sizeof(*tsc), GFP_KERNEL); 412 tsc = devm_kzalloc(dev, sizeof(*tsc), GFP_KERNEL);
284 if (!tsc) { 413 if (!tsc) {
285 ret = -ENOMEM; 414 ret = -ENOMEM;
286 goto error_unregister; 415 goto error_unregister;
287 } 416 }
288 417
289 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
290 if (!res)
291 break;
292
293 tsc->base = devm_ioremap_resource(dev, res); 418 tsc->base = devm_ioremap_resource(dev, res);
294 if (IS_ERR(tsc->base)) { 419 if (IS_ERR(tsc->base)) {
295 ret = PTR_ERR(tsc->base); 420 ret = PTR_ERR(tsc->base);
@@ -297,9 +422,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
297 } 422 }
298 423
299 priv->tscs[i] = tsc; 424 priv->tscs[i] = tsc;
300 mutex_init(&tsc->lock);
301 425
302 match_data->thermal_init(tsc); 426 priv->data->thermal_init(tsc);
303 rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]); 427 rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]);
304 428
305 zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, 429 zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
@@ -310,8 +434,23 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
310 goto error_unregister; 434 goto error_unregister;
311 } 435 }
312 tsc->zone = zone; 436 tsc->zone = zone;
437
438 ret = of_thermal_get_ntrips(tsc->zone);
439 if (ret < 0)
440 goto error_unregister;
441
442 dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret);
313 } 443 }
314 444
445 priv->num_tscs = i;
446
447 if (!priv->num_tscs) {
448 ret = -ENODEV;
449 goto error_unregister;
450 }
451
452 rcar_thermal_irq_set(priv, true);
453
315 return 0; 454 return 0;
316 455
317error_unregister: 456error_unregister:
@@ -320,9 +459,39 @@ error_unregister:
320 return ret; 459 return ret;
321} 460}
322 461
462static int __maybe_unused rcar_gen3_thermal_suspend(struct device *dev)
463{
464 struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
465
466 rcar_thermal_irq_set(priv, false);
467
468 return 0;
469}
470
471static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev)
472{
473 struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
474 unsigned int i;
475
476 for (i = 0; i < priv->num_tscs; i++) {
477 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
478
479 priv->data->thermal_init(tsc);
480 rcar_gen3_thermal_set_trips(tsc, tsc->low, tsc->high);
481 }
482
483 rcar_thermal_irq_set(priv, true);
484
485 return 0;
486}
487
488static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, rcar_gen3_thermal_suspend,
489 rcar_gen3_thermal_resume);
490
323static struct platform_driver rcar_gen3_thermal_driver = { 491static struct platform_driver rcar_gen3_thermal_driver = {
324 .driver = { 492 .driver = {
325 .name = "rcar_gen3_thermal", 493 .name = "rcar_gen3_thermal",
494 .pm = &rcar_gen3_thermal_pm_ops,
326 .of_match_table = rcar_gen3_thermal_dt_ids, 495 .of_match_table = rcar_gen3_thermal_dt_ids,
327 }, 496 },
328 .probe = rcar_gen3_thermal_probe, 497 .probe = rcar_gen3_thermal_probe,
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 11f0675cb7e5..b21b9cc2c8d6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -45,8 +45,10 @@ static LIST_HEAD(thermal_governor_list);
45 45
46static DEFINE_MUTEX(thermal_list_lock); 46static DEFINE_MUTEX(thermal_list_lock);
47static DEFINE_MUTEX(thermal_governor_lock); 47static DEFINE_MUTEX(thermal_governor_lock);
48static DEFINE_MUTEX(poweroff_lock);
48 49
49static atomic_t in_suspend; 50static atomic_t in_suspend;
51static bool power_off_triggered;
50 52
51static struct thermal_governor *def_governor; 53static struct thermal_governor *def_governor;
52 54
@@ -322,6 +324,54 @@ static void handle_non_critical_trips(struct thermal_zone_device *tz,
322 def_governor->throttle(tz, trip); 324 def_governor->throttle(tz, trip);
323} 325}
324 326
327/**
328 * thermal_emergency_poweroff_func - emergency poweroff work after a known delay
329 * @work: work_struct associated with the emergency poweroff function
330 *
331 * This function is called in very critical situations to force
332 * a kernel poweroff after a configurable timeout value.
333 */
334static void thermal_emergency_poweroff_func(struct work_struct *work)
335{
336 /*
337 * We have reached here after the emergency thermal shutdown
338 * Waiting period has expired. This means orderly_poweroff has
339 * not been able to shut off the system for some reason.
340 * Try to shut down the system immediately using kernel_power_off
341 * if populated
342 */
343 WARN(1, "Attempting kernel_power_off: Temperature too high\n");
344 kernel_power_off();
345
346 /*
347 * Worst of the worst case trigger emergency restart
348 */
349 WARN(1, "Attempting emergency_restart: Temperature too high\n");
350 emergency_restart();
351}
352
353static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work,
354 thermal_emergency_poweroff_func);
355
356/**
357 * thermal_emergency_poweroff - Trigger an emergency system poweroff
358 *
359 * This may be called from any critical situation to trigger a system shutdown
360 * after a known period of time. By default this is not scheduled.
361 */
362void thermal_emergency_poweroff(void)
363{
364 int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;
365 /*
366 * poweroff_delay_ms must be a carefully profiled positive value.
367 * Its a must for thermal_emergency_poweroff_work to be scheduled
368 */
369 if (poweroff_delay_ms <= 0)
370 return;
371 schedule_delayed_work(&thermal_emergency_poweroff_work,
372 msecs_to_jiffies(poweroff_delay_ms));
373}
374
325static void handle_critical_trips(struct thermal_zone_device *tz, 375static void handle_critical_trips(struct thermal_zone_device *tz,
326 int trip, enum thermal_trip_type trip_type) 376 int trip, enum thermal_trip_type trip_type)
327{ 377{
@@ -342,7 +392,17 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
342 dev_emerg(&tz->device, 392 dev_emerg(&tz->device,
343 "critical temperature reached(%d C),shutting down\n", 393 "critical temperature reached(%d C),shutting down\n",
344 tz->temperature / 1000); 394 tz->temperature / 1000);
345 orderly_poweroff(true); 395 mutex_lock(&poweroff_lock);
396 if (!power_off_triggered) {
397 /*
398 * Queue a backup emergency shutdown in the event of
399 * orderly_poweroff failure
400 */
401 thermal_emergency_poweroff();
402 orderly_poweroff(true);
403 power_off_triggered = true;
404 }
405 mutex_unlock(&poweroff_lock);
346 } 406 }
347} 407}
348 408
@@ -1463,6 +1523,7 @@ static int __init thermal_init(void)
1463{ 1523{
1464 int result; 1524 int result;
1465 1525
1526 mutex_init(&poweroff_lock);
1466 result = thermal_register_governors(); 1527 result = thermal_register_governors();
1467 if (result) 1528 if (result)
1468 goto error; 1529 goto error;
@@ -1497,6 +1558,7 @@ error:
1497 ida_destroy(&thermal_cdev_ida); 1558 ida_destroy(&thermal_cdev_ida);
1498 mutex_destroy(&thermal_list_lock); 1559 mutex_destroy(&thermal_list_lock);
1499 mutex_destroy(&thermal_governor_lock); 1560 mutex_destroy(&thermal_governor_lock);
1561 mutex_destroy(&poweroff_lock);
1500 return result; 1562 return result;
1501} 1563}
1502 1564
diff --git a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
index 118d7d847715..4167373327d9 100644
--- a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
+++ b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
@@ -410,8 +410,6 @@ const struct ti_bandgap_data dra752_data = {
410 .domain = "cpu", 410 .domain = "cpu",
411 .register_cooling = ti_thermal_register_cpu_cooling, 411 .register_cooling = ti_thermal_register_cpu_cooling,
412 .unregister_cooling = ti_thermal_unregister_cpu_cooling, 412 .unregister_cooling = ti_thermal_unregister_cpu_cooling,
413 .slope = DRA752_GRADIENT_SLOPE,
414 .constant = DRA752_GRADIENT_CONST,
415 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 413 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
416 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 414 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
417 }, 415 },
@@ -419,8 +417,6 @@ const struct ti_bandgap_data dra752_data = {
419 .registers = &dra752_gpu_temp_sensor_registers, 417 .registers = &dra752_gpu_temp_sensor_registers,
420 .ts_data = &dra752_gpu_temp_sensor_data, 418 .ts_data = &dra752_gpu_temp_sensor_data,
421 .domain = "gpu", 419 .domain = "gpu",
422 .slope = DRA752_GRADIENT_SLOPE,
423 .constant = DRA752_GRADIENT_CONST,
424 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 420 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
425 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 421 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
426 }, 422 },
@@ -428,8 +424,6 @@ const struct ti_bandgap_data dra752_data = {
428 .registers = &dra752_core_temp_sensor_registers, 424 .registers = &dra752_core_temp_sensor_registers,
429 .ts_data = &dra752_core_temp_sensor_data, 425 .ts_data = &dra752_core_temp_sensor_data,
430 .domain = "core", 426 .domain = "core",
431 .slope = DRA752_GRADIENT_SLOPE,
432 .constant = DRA752_GRADIENT_CONST,
433 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 427 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
434 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 428 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
435 }, 429 },
@@ -437,8 +431,6 @@ const struct ti_bandgap_data dra752_data = {
437 .registers = &dra752_dspeve_temp_sensor_registers, 431 .registers = &dra752_dspeve_temp_sensor_registers,
438 .ts_data = &dra752_dspeve_temp_sensor_data, 432 .ts_data = &dra752_dspeve_temp_sensor_data,
439 .domain = "dspeve", 433 .domain = "dspeve",
440 .slope = DRA752_GRADIENT_SLOPE,
441 .constant = DRA752_GRADIENT_CONST,
442 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 434 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
443 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 435 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
444 }, 436 },
@@ -446,8 +438,6 @@ const struct ti_bandgap_data dra752_data = {
446 .registers = &dra752_iva_temp_sensor_registers, 438 .registers = &dra752_iva_temp_sensor_registers,
447 .ts_data = &dra752_iva_temp_sensor_data, 439 .ts_data = &dra752_iva_temp_sensor_data,
448 .domain = "iva", 440 .domain = "iva",
449 .slope = DRA752_GRADIENT_SLOPE,
450 .constant = DRA752_GRADIENT_CONST,
451 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 441 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
452 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 442 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
453 }, 443 },
diff --git a/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
index 3ee34340edab..c6d217913dd1 100644
--- a/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
+++ b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
@@ -91,8 +91,6 @@ const struct ti_bandgap_data omap34xx_data = {
91 .registers = &omap34xx_mpu_temp_sensor_registers, 91 .registers = &omap34xx_mpu_temp_sensor_registers,
92 .ts_data = &omap34xx_mpu_temp_sensor_data, 92 .ts_data = &omap34xx_mpu_temp_sensor_data,
93 .domain = "cpu", 93 .domain = "cpu",
94 .slope = 0,
95 .constant = 20000,
96 .slope_pcb = 0, 94 .slope_pcb = 0,
97 .constant_pcb = 20000, 95 .constant_pcb = 20000,
98 .register_cooling = NULL, 96 .register_cooling = NULL,
@@ -164,8 +162,6 @@ const struct ti_bandgap_data omap36xx_data = {
164 .registers = &omap36xx_mpu_temp_sensor_registers, 162 .registers = &omap36xx_mpu_temp_sensor_registers,
165 .ts_data = &omap36xx_mpu_temp_sensor_data, 163 .ts_data = &omap36xx_mpu_temp_sensor_data,
166 .domain = "cpu", 164 .domain = "cpu",
167 .slope = 0,
168 .constant = 20000,
169 .slope_pcb = 0, 165 .slope_pcb = 0,
170 .constant_pcb = 20000, 166 .constant_pcb = 20000,
171 .register_cooling = NULL, 167 .register_cooling = NULL,
diff --git a/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
index d255d33da9eb..fd1113360603 100644
--- a/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
+++ b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
@@ -82,8 +82,6 @@ const struct ti_bandgap_data omap4430_data = {
82 .registers = &omap4430_mpu_temp_sensor_registers, 82 .registers = &omap4430_mpu_temp_sensor_registers,
83 .ts_data = &omap4430_mpu_temp_sensor_data, 83 .ts_data = &omap4430_mpu_temp_sensor_data,
84 .domain = "cpu", 84 .domain = "cpu",
85 .slope = OMAP_GRADIENT_SLOPE_4430,
86 .constant = OMAP_GRADIENT_CONST_4430,
87 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4430, 85 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4430,
88 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4430, 86 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4430,
89 .register_cooling = ti_thermal_register_cpu_cooling, 87 .register_cooling = ti_thermal_register_cpu_cooling,
@@ -222,8 +220,6 @@ const struct ti_bandgap_data omap4460_data = {
222 .registers = &omap4460_mpu_temp_sensor_registers, 220 .registers = &omap4460_mpu_temp_sensor_registers,
223 .ts_data = &omap4460_mpu_temp_sensor_data, 221 .ts_data = &omap4460_mpu_temp_sensor_data,
224 .domain = "cpu", 222 .domain = "cpu",
225 .slope = OMAP_GRADIENT_SLOPE_4460,
226 .constant = OMAP_GRADIENT_CONST_4460,
227 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460, 223 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460,
228 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460, 224 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460,
229 .register_cooling = ti_thermal_register_cpu_cooling, 225 .register_cooling = ti_thermal_register_cpu_cooling,
@@ -255,8 +251,6 @@ const struct ti_bandgap_data omap4470_data = {
255 .registers = &omap4460_mpu_temp_sensor_registers, 251 .registers = &omap4460_mpu_temp_sensor_registers,
256 .ts_data = &omap4460_mpu_temp_sensor_data, 252 .ts_data = &omap4460_mpu_temp_sensor_data,
257 .domain = "cpu", 253 .domain = "cpu",
258 .slope = OMAP_GRADIENT_SLOPE_4470,
259 .constant = OMAP_GRADIENT_CONST_4470,
260 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470, 254 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470,
261 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470, 255 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470,
262 .register_cooling = ti_thermal_register_cpu_cooling, 256 .register_cooling = ti_thermal_register_cpu_cooling,
diff --git a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
index 79ff70c446ba..cd9a304fb571 100644
--- a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
+++ b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
@@ -336,8 +336,6 @@ const struct ti_bandgap_data omap5430_data = {
336 .domain = "cpu", 336 .domain = "cpu",
337 .register_cooling = ti_thermal_register_cpu_cooling, 337 .register_cooling = ti_thermal_register_cpu_cooling,
338 .unregister_cooling = ti_thermal_unregister_cpu_cooling, 338 .unregister_cooling = ti_thermal_unregister_cpu_cooling,
339 .slope = OMAP_GRADIENT_SLOPE_5430_CPU,
340 .constant = OMAP_GRADIENT_CONST_5430_CPU,
341 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU, 339 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU,
342 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU, 340 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU,
343 }, 341 },
@@ -345,8 +343,6 @@ const struct ti_bandgap_data omap5430_data = {
345 .registers = &omap5430_gpu_temp_sensor_registers, 343 .registers = &omap5430_gpu_temp_sensor_registers,
346 .ts_data = &omap5430_gpu_temp_sensor_data, 344 .ts_data = &omap5430_gpu_temp_sensor_data,
347 .domain = "gpu", 345 .domain = "gpu",
348 .slope = OMAP_GRADIENT_SLOPE_5430_GPU,
349 .constant = OMAP_GRADIENT_CONST_5430_GPU,
350 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU, 346 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU,
351 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU, 347 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU,
352 }, 348 },
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
index fe0adb898764..209c664c2823 100644
--- a/drivers/thermal/ti-soc-thermal/ti-bandgap.h
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
@@ -254,8 +254,6 @@ struct ti_bandgap {
254 * @ts_data: pointer to struct with thresholds, limits of temperature sensor 254 * @ts_data: pointer to struct with thresholds, limits of temperature sensor
255 * @registers: pointer to the list of register offsets and bitfields 255 * @registers: pointer to the list of register offsets and bitfields
256 * @domain: the name of the domain where the sensor is located 256 * @domain: the name of the domain where the sensor is located
257 * @slope: sensor gradient slope info for hotspot extrapolation equation
258 * @constant: sensor gradient const info for hotspot extrapolation equation
259 * @slope_pcb: sensor gradient slope info for hotspot extrapolation equation 257 * @slope_pcb: sensor gradient slope info for hotspot extrapolation equation
260 * with no external influence 258 * with no external influence
261 * @constant_pcb: sensor gradient const info for hotspot extrapolation equation 259 * @constant_pcb: sensor gradient const info for hotspot extrapolation equation
@@ -274,8 +272,6 @@ struct ti_temp_sensor {
274 struct temp_sensor_registers *registers; 272 struct temp_sensor_registers *registers;
275 char *domain; 273 char *domain;
276 /* for hotspot extrapolation */ 274 /* for hotspot extrapolation */
277 const int slope;
278 const int constant;
279 const int slope_pcb; 275 const int slope_pcb;
280 const int constant_pcb; 276 const int constant_pcb;
281 int (*register_cooling)(struct ti_bandgap *bgp, int id); 277 int (*register_cooling)(struct ti_bandgap *bgp, int id);
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 0586bd0f2bab..02790f69e26c 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -96,8 +96,8 @@ static inline int __ti_thermal_get_temp(void *devdata, int *temp)
96 return ret; 96 return ret;
97 97
98 /* Default constants */ 98 /* Default constants */
99 slope = s->slope; 99 slope = thermal_zone_get_slope(data->ti_thermal);
100 constant = s->constant; 100 constant = thermal_zone_get_offset(data->ti_thermal);
101 101
102 pcb_tz = data->pcb_tz; 102 pcb_tz = data->pcb_tz;
103 /* In case pcb zone is available, use the extrapolation rule with it */ 103 /* In case pcb zone is available, use the extrapolation rule with it */
@@ -126,119 +126,6 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
126 return __ti_thermal_get_temp(data, temp); 126 return __ti_thermal_get_temp(data, temp);
127} 127}
128 128
129/* Bind callback functions for thermal zone */
130static int ti_thermal_bind(struct thermal_zone_device *thermal,
131 struct thermal_cooling_device *cdev)
132{
133 struct ti_thermal_data *data = thermal->devdata;
134 int id;
135
136 if (!data || IS_ERR(data))
137 return -ENODEV;
138
139 /* check if this is the cooling device we registered */
140 if (data->cool_dev != cdev)
141 return 0;
142
143 id = data->sensor_id;
144
145 /* Simple thing, two trips, one passive another critical */
146 return thermal_zone_bind_cooling_device(thermal, 0, cdev,
147 /* bind with min and max states defined by cpu_cooling */
148 THERMAL_NO_LIMIT,
149 THERMAL_NO_LIMIT,
150 THERMAL_WEIGHT_DEFAULT);
151}
152
153/* Unbind callback functions for thermal zone */
154static int ti_thermal_unbind(struct thermal_zone_device *thermal,
155 struct thermal_cooling_device *cdev)
156{
157 struct ti_thermal_data *data = thermal->devdata;
158
159 if (!data || IS_ERR(data))
160 return -ENODEV;
161
162 /* check if this is the cooling device we registered */
163 if (data->cool_dev != cdev)
164 return 0;
165
166 /* Simple thing, two trips, one passive another critical */
167 return thermal_zone_unbind_cooling_device(thermal, 0, cdev);
168}
169
170/* Get mode callback functions for thermal zone */
171static int ti_thermal_get_mode(struct thermal_zone_device *thermal,
172 enum thermal_device_mode *mode)
173{
174 struct ti_thermal_data *data = thermal->devdata;
175
176 if (data)
177 *mode = data->mode;
178
179 return 0;
180}
181
182/* Set mode callback functions for thermal zone */
183static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
184 enum thermal_device_mode mode)
185{
186 struct ti_thermal_data *data = thermal->devdata;
187 struct ti_bandgap *bgp;
188
189 bgp = data->bgp;
190
191 if (!data->ti_thermal) {
192 dev_notice(&thermal->device, "thermal zone not registered\n");
193 return 0;
194 }
195
196 mutex_lock(&data->ti_thermal->lock);
197
198 if (mode == THERMAL_DEVICE_ENABLED)
199 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
200 else
201 data->ti_thermal->polling_delay = 0;
202
203 mutex_unlock(&data->ti_thermal->lock);
204
205 data->mode = mode;
206 ti_bandgap_write_update_interval(bgp, data->sensor_id,
207 data->ti_thermal->polling_delay);
208 thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
209 dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
210 data->ti_thermal->polling_delay);
211
212 return 0;
213}
214
215/* Get trip type callback functions for thermal zone */
216static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
217 int trip, enum thermal_trip_type *type)
218{
219 if (!ti_thermal_is_valid_trip(trip))
220 return -EINVAL;
221
222 if (trip + 1 == OMAP_TRIP_NUMBER)
223 *type = THERMAL_TRIP_CRITICAL;
224 else
225 *type = THERMAL_TRIP_PASSIVE;
226
227 return 0;
228}
229
230/* Get trip temperature callback functions for thermal zone */
231static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
232 int trip, int *temp)
233{
234 if (!ti_thermal_is_valid_trip(trip))
235 return -EINVAL;
236
237 *temp = ti_thermal_get_trip_value(trip);
238
239 return 0;
240}
241
242static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend) 129static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
243{ 130{
244 struct ti_thermal_data *data = p; 131 struct ti_thermal_data *data = p;
@@ -262,38 +149,11 @@ static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
262 return 0; 149 return 0;
263} 150}
264 151
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
272/* Get critical temperature callback functions for thermal zone */
273static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
274 int *temp)
275{
276 /* shutdown zone */
277 return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
278}
279
280static const struct thermal_zone_of_device_ops ti_of_thermal_ops = { 152static const struct thermal_zone_of_device_ops ti_of_thermal_ops = {
281 .get_temp = __ti_thermal_get_temp, 153 .get_temp = __ti_thermal_get_temp,
282 .get_trend = __ti_thermal_get_trend, 154 .get_trend = __ti_thermal_get_trend,
283}; 155};
284 156
285static struct thermal_zone_device_ops ti_thermal_ops = {
286 .get_temp = ti_thermal_get_temp,
287 .get_trend = ti_thermal_get_trend,
288 .bind = ti_thermal_bind,
289 .unbind = ti_thermal_unbind,
290 .get_mode = ti_thermal_get_mode,
291 .set_mode = ti_thermal_set_mode,
292 .get_trip_type = ti_thermal_get_trip_type,
293 .get_trip_temp = ti_thermal_get_trip_temp,
294 .get_crit_temp = ti_thermal_get_crit_temp,
295};
296
297static struct ti_thermal_data 157static struct ti_thermal_data
298*ti_thermal_build_data(struct ti_bandgap *bgp, int id) 158*ti_thermal_build_data(struct ti_bandgap *bgp, int id)
299{ 159{
@@ -331,18 +191,10 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
331 data->ti_thermal = devm_thermal_zone_of_sensor_register(bgp->dev, id, 191 data->ti_thermal = devm_thermal_zone_of_sensor_register(bgp->dev, id,
332 data, &ti_of_thermal_ops); 192 data, &ti_of_thermal_ops);
333 if (IS_ERR(data->ti_thermal)) { 193 if (IS_ERR(data->ti_thermal)) {
334 /* Create thermal zone */ 194 dev_err(bgp->dev, "thermal zone device is NULL\n");
335 data->ti_thermal = thermal_zone_device_register(domain, 195 return PTR_ERR(data->ti_thermal);
336 OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
337 NULL, FAST_TEMP_MONITORING_RATE,
338 FAST_TEMP_MONITORING_RATE);
339 if (IS_ERR(data->ti_thermal)) {
340 dev_err(bgp->dev, "thermal zone device is NULL\n");
341 return PTR_ERR(data->ti_thermal);
342 }
343 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
344 data->our_zone = true;
345 } 196 }
197
346 ti_bandgap_set_sensor_data(bgp, id, data); 198 ti_bandgap_set_sensor_data(bgp, id, data);
347 ti_bandgap_write_update_interval(bgp, data->sensor_id, 199 ti_bandgap_write_update_interval(bgp, data->sensor_id,
348 data->ti_thermal->polling_delay); 200 data->ti_thermal->polling_delay);
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal.h b/drivers/thermal/ti-soc-thermal/ti-thermal.h
index f8b7ffea6194..8e85ca973967 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal.h
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal.h
@@ -25,22 +25,6 @@
25 25
26#include "ti-bandgap.h" 26#include "ti-bandgap.h"
27 27
28/* sensors gradient and offsets */
29#define OMAP_GRADIENT_SLOPE_4430 0
30#define OMAP_GRADIENT_CONST_4430 20000
31#define OMAP_GRADIENT_SLOPE_4460 348
32#define OMAP_GRADIENT_CONST_4460 -9301
33#define OMAP_GRADIENT_SLOPE_4470 308
34#define OMAP_GRADIENT_CONST_4470 -7896
35
36#define OMAP_GRADIENT_SLOPE_5430_CPU 65
37#define OMAP_GRADIENT_CONST_5430_CPU -1791
38#define OMAP_GRADIENT_SLOPE_5430_GPU 117
39#define OMAP_GRADIENT_CONST_5430_GPU -2992
40
41#define DRA752_GRADIENT_SLOPE 0
42#define DRA752_GRADIENT_CONST 2000
43
44/* PCB sensor calculation constants */ 28/* PCB sensor calculation constants */
45#define OMAP_GRADIENT_SLOPE_W_PCB_4430 0 29#define OMAP_GRADIENT_SLOPE_W_PCB_4430 0
46#define OMAP_GRADIENT_CONST_W_PCB_4430 20000 30#define OMAP_GRADIENT_CONST_W_PCB_4430 20000
diff --git a/include/linux/devfreq_cooling.h b/include/linux/devfreq_cooling.h
index c35d0c0e0ada..4635f95000a4 100644
--- a/include/linux/devfreq_cooling.h
+++ b/include/linux/devfreq_cooling.h
@@ -34,6 +34,23 @@
34 * If get_dynamic_power() is NULL, then the 34 * If get_dynamic_power() is NULL, then the
35 * dynamic power is calculated as 35 * dynamic power is calculated as
36 * @dyn_power_coeff * frequency * voltage^2 36 * @dyn_power_coeff * frequency * voltage^2
37 * @get_real_power: When this is set, the framework uses it to ask the
38 * device driver for the actual power.
39 * Some devices have more sophisticated methods
40 * (like power counters) to approximate the actual power
41 * that they use.
42 * This function provides more accurate data to the
43 * thermal governor. When the driver does not provide
44 * such function, framework just uses pre-calculated
45 * table and scale the power by 'utilization'
46 * (based on 'busy_time' and 'total_time' taken from
47 * devfreq 'last_status').
48 * The value returned by this function must be lower
49 * or equal than the maximum power value
50 * for the current state
51 * (which can be found in power_table[state]).
52 * When this interface is used, the power_table holds
53 * max total (static + dynamic) power value for each OPP.
37 */ 54 */
38struct devfreq_cooling_power { 55struct devfreq_cooling_power {
39 unsigned long (*get_static_power)(struct devfreq *devfreq, 56 unsigned long (*get_static_power)(struct devfreq *devfreq,
@@ -41,6 +58,8 @@ struct devfreq_cooling_power {
41 unsigned long (*get_dynamic_power)(struct devfreq *devfreq, 58 unsigned long (*get_dynamic_power)(struct devfreq *devfreq,
42 unsigned long freq, 59 unsigned long freq,
43 unsigned long voltage); 60 unsigned long voltage);
61 int (*get_real_power)(struct devfreq *df, u32 *power,
62 unsigned long freq, unsigned long voltage);
44 unsigned long dyn_power_coeff; 63 unsigned long dyn_power_coeff;
45}; 64};
46 65
diff --git a/include/trace/events/thermal.h b/include/trace/events/thermal.h
index 2b4a8ff72d0d..6cde5b3514c2 100644
--- a/include/trace/events/thermal.h
+++ b/include/trace/events/thermal.h
@@ -151,9 +151,9 @@ TRACE_EVENT(thermal_power_cpu_limit,
151TRACE_EVENT(thermal_power_devfreq_get_power, 151TRACE_EVENT(thermal_power_devfreq_get_power,
152 TP_PROTO(struct thermal_cooling_device *cdev, 152 TP_PROTO(struct thermal_cooling_device *cdev,
153 struct devfreq_dev_status *status, unsigned long freq, 153 struct devfreq_dev_status *status, unsigned long freq,
154 u32 dynamic_power, u32 static_power), 154 u32 dynamic_power, u32 static_power, u32 power),
155 155
156 TP_ARGS(cdev, status, freq, dynamic_power, static_power), 156 TP_ARGS(cdev, status, freq, dynamic_power, static_power, power),
157 157
158 TP_STRUCT__entry( 158 TP_STRUCT__entry(
159 __string(type, cdev->type ) 159 __string(type, cdev->type )
@@ -161,6 +161,7 @@ TRACE_EVENT(thermal_power_devfreq_get_power,
161 __field(u32, load ) 161 __field(u32, load )
162 __field(u32, dynamic_power ) 162 __field(u32, dynamic_power )
163 __field(u32, static_power ) 163 __field(u32, static_power )
164 __field(u32, power)
164 ), 165 ),
165 166
166 TP_fast_assign( 167 TP_fast_assign(
@@ -169,11 +170,13 @@ TRACE_EVENT(thermal_power_devfreq_get_power,
169 __entry->load = (100 * status->busy_time) / status->total_time; 170 __entry->load = (100 * status->busy_time) / status->total_time;
170 __entry->dynamic_power = dynamic_power; 171 __entry->dynamic_power = dynamic_power;
171 __entry->static_power = static_power; 172 __entry->static_power = static_power;
173 __entry->power = power;
172 ), 174 ),
173 175
174 TP_printk("type=%s freq=%lu load=%u dynamic_power=%u static_power=%u", 176 TP_printk("type=%s freq=%lu load=%u dynamic_power=%u static_power=%u power=%u",
175 __get_str(type), __entry->freq, 177 __get_str(type), __entry->freq,
176 __entry->load, __entry->dynamic_power, __entry->static_power) 178 __entry->load, __entry->dynamic_power, __entry->static_power,
179 __entry->power)
177); 180);
178 181
179TRACE_EVENT(thermal_power_devfreq_limit, 182TRACE_EVENT(thermal_power_devfreq_limit,