aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-11 12:03:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-11 12:03:01 -0500
commitbaf51c43926ec9aa42ef9d33ca6ee9e3e043aebe (patch)
tree3ae0fbc2389f8264f195699721c9489dc347ff4f
parentc5a37883f42be712a989e54d5d6c0159b0e56599 (diff)
parent7c5b2759bf8c2cbc60e5560c72cf51a2628f6d30 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal updates from Zhang Rui: - Implement generic devfreq cooling mechanism through frequency reduction for devices using devfreq. From Ørjan Eide and Javi Merino. - Introduce OMAP3 support on TI SoC thermal driver. From Pavel Mack and Eduardo Valentin. - A bounch of small fixes on devfreq_cooling, Exynos, IMX, Armada, and Rockchip thermal drivers. * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (24 commits) thermal: exynos: Directly return 0 instead of using local ret variable thermal: exynos: Remove unneeded semicolon thermal: exynos: Use IS_ERR() because regulator cannot be NULL thermal: exynos: Fix first temperature read after registering sensor thermal: exynos: Fix unbalanced regulator disable on probe failure devfreq_cooling: return on allocation failure thermal: rockchip: support the sleep pinctrl state to avoid glitches in s2r dt-bindings: rockchip-thermal: Add the pinctrl states in this document thermal: devfreq_cooling: Make power a u64 thermal: devfreq_cooling: use a thermal_cooling_device for register and unregister thermal: underflow bug in imx_set_trip_temp() thermal: armada: Fix possible overflow in the Armada 380 thermal sensor formula thermal: imx: register irq handler later in probe thermal: rockhip: fix setting thermal shutdown polarity thermal: rockchip: fix handling of invalid readings devfreq_cooling: add trace information thermal: Add devfreq cooling PM / OPP: get the voltage for all OPPs tools/thermal: tmon: use pkg-config also for CFLAGS linux/thermal.h: rename KELVIN_TO_CELSIUS to DECI_KELVIN_TO_CELSIUS ...
-rw-r--r--Documentation/devicetree/bindings/thermal/rockchip-thermal.txt11
-rw-r--r--Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt14
-rw-r--r--drivers/acpi/thermal.c12
-rw-r--r--drivers/base/power/opp/core.c4
-rw-r--r--drivers/platform/x86/asus-wmi.c2
-rw-r--r--drivers/platform/x86/intel_menlow.c8
-rw-r--r--drivers/thermal/Kconfig17
-rw-r--r--drivers/thermal/Makefile3
-rw-r--r--drivers/thermal/armada_thermal.c6
-rw-r--r--drivers/thermal/cpu_cooling.c8
-rw-r--r--drivers/thermal/devfreq_cooling.c573
-rw-r--r--drivers/thermal/imx_thermal.c21
-rw-r--r--drivers/thermal/rockchip_thermal.c42
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c68
-rw-r--r--drivers/thermal/ti-soc-thermal/Kconfig15
-rw-r--r--drivers/thermal/ti-soc-thermal/Makefile1
-rw-r--r--drivers/thermal/ti-soc-thermal/omap3-thermal-data.c176
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c14
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.h11
-rw-r--r--include/linux/devfreq_cooling.h81
-rw-r--r--include/linux/thermal.h8
-rw-r--r--include/trace/events/thermal.h53
-rw-r--r--tools/thermal/tmon/Makefile3
23 files changed, 1065 insertions, 86 deletions
diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
index ef802de4957a..b38200d2583a 100644
--- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
@@ -12,6 +12,11 @@ Required properties:
12- resets : Must contain an entry for each entry in reset-names. 12- resets : Must contain an entry for each entry in reset-names.
13 See ../reset/reset.txt for details. 13 See ../reset/reset.txt for details.
14- reset-names : Must include the name "tsadc-apb". 14- reset-names : Must include the name "tsadc-apb".
15- pinctrl-names : The pin control state names;
16- pinctrl-0 : The "init" pinctrl state, it will be set before device probe.
17- pinctrl-1 : The "default" pinctrl state, it will be set after reset the
18 TSADC controller.
19- pinctrl-2 : The "sleep" pinctrl state, it will be in for suspend.
15- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description. 20- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
16- rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value. 21- rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.
17- rockchip,hw-tshut-mode : The hardware-controlled shutdown mode 0:CRU 1:GPIO. 22- rockchip,hw-tshut-mode : The hardware-controlled shutdown mode 0:CRU 1:GPIO.
@@ -27,8 +32,10 @@ tsadc: tsadc@ff280000 {
27 clock-names = "tsadc", "apb_pclk"; 32 clock-names = "tsadc", "apb_pclk";
28 resets = <&cru SRST_TSADC>; 33 resets = <&cru SRST_TSADC>;
29 reset-names = "tsadc-apb"; 34 reset-names = "tsadc-apb";
30 pinctrl-names = "default"; 35 pinctrl-names = "init", "default", "sleep";
31 pinctrl-0 = <&otp_out>; 36 pinctrl-0 = <&otp_gpio>;
37 pinctrl-1 = <&otp_out>;
38 pinctrl-2 = <&otp_gpio>;
32 #thermal-sensor-cells = <1>; 39 #thermal-sensor-cells = <1>;
33 rockchip,hw-tshut-temp = <95000>; 40 rockchip,hw-tshut-temp = <95000>;
34 rockchip,hw-tshut-mode = <0>; 41 rockchip,hw-tshut-mode = <0>;
diff --git a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt
index 0c9222d27fae..6299dd8de339 100644
--- a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt
@@ -10,6 +10,8 @@ to the silicon temperature.
10 10
11Required properties: 11Required properties:
12- compatible : Should be: 12- compatible : Should be:
13 - "ti,omap34xx-bandgap" : for OMAP34xx bandgap
14 - "ti,omap36xx-bandgap" : for OMAP36xx bandgap
13 - "ti,omap4430-bandgap" : for OMAP4430 bandgap 15 - "ti,omap4430-bandgap" : for OMAP4430 bandgap
14 - "ti,omap4460-bandgap" : for OMAP4460 bandgap 16 - "ti,omap4460-bandgap" : for OMAP4460 bandgap
15 - "ti,omap4470-bandgap" : for OMAP4470 bandgap 17 - "ti,omap4470-bandgap" : for OMAP4470 bandgap
@@ -25,6 +27,18 @@ to each bandgap version, because the mapping may change from
25soc to soc, apart of depending on available features. 27soc to soc, apart of depending on available features.
26 28
27Example: 29Example:
30OMAP34xx:
31bandgap {
32 reg = <0x48002524 0x4>;
33 compatible = "ti,omap34xx-bandgap";
34};
35
36OMAP36xx:
37bandgap {
38 reg = <0x48002524 0x4>;
39 compatible = "ti,omap36xx-bandgap";
40};
41
28OMAP4430: 42OMAP4430:
29bandgap { 43bandgap {
30 reg = <0x4a002260 0x4 0x4a00232C 0x4>; 44 reg = <0x4a002260 0x4 0x4a00232C 0x4>;
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 30d8518b25fb..82707f9824ca 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -315,7 +315,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
315 if (crt == -1) { 315 if (crt == -1) {
316 tz->trips.critical.flags.valid = 0; 316 tz->trips.critical.flags.valid = 0;
317 } else if (crt > 0) { 317 } else if (crt > 0) {
318 unsigned long crt_k = CELSIUS_TO_KELVIN(crt); 318 unsigned long crt_k = CELSIUS_TO_DECI_KELVIN(crt);
319 /* 319 /*
320 * Allow override critical threshold 320 * Allow override critical threshold
321 */ 321 */
@@ -351,7 +351,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
351 if (psv == -1) { 351 if (psv == -1) {
352 status = AE_SUPPORT; 352 status = AE_SUPPORT;
353 } else if (psv > 0) { 353 } else if (psv > 0) {
354 tmp = CELSIUS_TO_KELVIN(psv); 354 tmp = CELSIUS_TO_DECI_KELVIN(psv);
355 status = AE_OK; 355 status = AE_OK;
356 } else { 356 } else {
357 status = acpi_evaluate_integer(tz->device->handle, 357 status = acpi_evaluate_integer(tz->device->handle,
@@ -431,7 +431,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
431 break; 431 break;
432 if (i == 1) 432 if (i == 1)
433 tz->trips.active[0].temperature = 433 tz->trips.active[0].temperature =
434 CELSIUS_TO_KELVIN(act); 434 CELSIUS_TO_DECI_KELVIN(act);
435 else 435 else
436 /* 436 /*
437 * Don't allow override higher than 437 * Don't allow override higher than
@@ -439,9 +439,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
439 */ 439 */
440 tz->trips.active[i - 1].temperature = 440 tz->trips.active[i - 1].temperature =
441 (tz->trips.active[i - 2].temperature < 441 (tz->trips.active[i - 2].temperature <
442 CELSIUS_TO_KELVIN(act) ? 442 CELSIUS_TO_DECI_KELVIN(act) ?
443 tz->trips.active[i - 2].temperature : 443 tz->trips.active[i - 2].temperature :
444 CELSIUS_TO_KELVIN(act)); 444 CELSIUS_TO_DECI_KELVIN(act));
445 break; 445 break;
446 } else { 446 } else {
447 tz->trips.active[i].temperature = tmp; 447 tz->trips.active[i].temperature = tmp;
@@ -1105,7 +1105,7 @@ static int acpi_thermal_add(struct acpi_device *device)
1105 INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn); 1105 INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
1106 1106
1107 pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), 1107 pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
1108 acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature)); 1108 acpi_device_bid(device), DECI_KELVIN_TO_CELSIUS(tz->temperature));
1109 goto end; 1109 goto end;
1110 1110
1111free_memory: 1111free_memory:
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index d5c1149ff123..270902007055 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -100,7 +100,7 @@ struct device_opp *_find_device_opp(struct device *dev)
100} 100}
101 101
102/** 102/**
103 * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an available opp 103 * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp
104 * @opp: opp for which voltage has to be returned for 104 * @opp: opp for which voltage has to be returned for
105 * 105 *
106 * Return: voltage in micro volt corresponding to the opp, else 106 * Return: voltage in micro volt corresponding to the opp, else
@@ -122,7 +122,7 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
122 opp_rcu_lockdep_assert(); 122 opp_rcu_lockdep_assert();
123 123
124 tmp_opp = rcu_dereference(opp); 124 tmp_opp = rcu_dereference(opp);
125 if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available) 125 if (IS_ERR_OR_NULL(tmp_opp))
126 pr_err("%s: Invalid parameters\n", __func__); 126 pr_err("%s: Invalid parameters\n", __func__);
127 else 127 else
128 v = tmp_opp->u_volt; 128 v = tmp_opp->u_volt;
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 1f7d80ff8cb4..e3a750224ae2 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -1320,7 +1320,7 @@ static ssize_t asus_hwmon_temp1(struct device *dev,
1320 if (err < 0) 1320 if (err < 0)
1321 return err; 1321 return err;
1322 1322
1323 value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000; 1323 value = DECI_KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
1324 1324
1325 return sprintf(buf, "%d\n", value); 1325 return sprintf(buf, "%d\n", value);
1326} 1326}
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index e8b46d2c468c..0a919d81662c 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -315,7 +315,7 @@ static ssize_t aux0_show(struct device *dev,
315 315
316 result = sensor_get_auxtrip(attr->handle, 0, &value); 316 result = sensor_get_auxtrip(attr->handle, 0, &value);
317 317
318 return result ? result : sprintf(buf, "%lu", KELVIN_TO_CELSIUS(value)); 318 return result ? result : sprintf(buf, "%lu", DECI_KELVIN_TO_CELSIUS(value));
319} 319}
320 320
321static ssize_t aux1_show(struct device *dev, 321static ssize_t aux1_show(struct device *dev,
@@ -327,7 +327,7 @@ static ssize_t aux1_show(struct device *dev,
327 327
328 result = sensor_get_auxtrip(attr->handle, 1, &value); 328 result = sensor_get_auxtrip(attr->handle, 1, &value);
329 329
330 return result ? result : sprintf(buf, "%lu", KELVIN_TO_CELSIUS(value)); 330 return result ? result : sprintf(buf, "%lu", DECI_KELVIN_TO_CELSIUS(value));
331} 331}
332 332
333static ssize_t aux0_store(struct device *dev, 333static ssize_t aux0_store(struct device *dev,
@@ -345,7 +345,7 @@ static ssize_t aux0_store(struct device *dev,
345 if (value < 0) 345 if (value < 0)
346 return -EINVAL; 346 return -EINVAL;
347 347
348 result = sensor_set_auxtrip(attr->handle, 0, CELSIUS_TO_KELVIN(value)); 348 result = sensor_set_auxtrip(attr->handle, 0, CELSIUS_TO_DECI_KELVIN(value));
349 return result ? result : count; 349 return result ? result : count;
350} 350}
351 351
@@ -364,7 +364,7 @@ static ssize_t aux1_store(struct device *dev,
364 if (value < 0) 364 if (value < 0)
365 return -EINVAL; 365 return -EINVAL;
366 366
367 result = sensor_set_auxtrip(attr->handle, 1, CELSIUS_TO_KELVIN(value)); 367 result = sensor_set_auxtrip(attr->handle, 1, CELSIUS_TO_DECI_KELVIN(value));
368 return result ? result : count; 368 return result ? result : count;
369} 369}
370 370
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 5aabc4bc0d75..c463c89b90ef 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -147,6 +147,20 @@ config CLOCK_THERMAL
147 device that is configured to use this cooling mechanism will be 147 device that is configured to use this cooling mechanism will be
148 controlled to reduce clock frequency whenever temperature is high. 148 controlled to reduce clock frequency whenever temperature is high.
149 149
150config DEVFREQ_THERMAL
151 bool "Generic device cooling support"
152 depends on PM_DEVFREQ
153 depends on PM_OPP
154 help
155 This implements the generic devfreq cooling mechanism through
156 frequency reduction for devices using devfreq.
157
158 This will throttle the device by limiting the maximum allowed DVFS
159 frequency corresponding to the cooling level.
160
161 In order to use the power extensions of the cooling device,
162 devfreq should use the simple_ondemand governor.
163
150 If you want this support, you should say Y here. 164 If you want this support, you should say Y here.
151 165
152config THERMAL_EMULATION 166config THERMAL_EMULATION
@@ -275,6 +289,7 @@ config X86_PKG_TEMP_THERMAL
275 tristate "X86 package temperature thermal driver" 289 tristate "X86 package temperature thermal driver"
276 depends on X86_THERMAL_VECTOR 290 depends on X86_THERMAL_VECTOR
277 select THERMAL_GOV_USER_SPACE 291 select THERMAL_GOV_USER_SPACE
292 select THERMAL_WRITABLE_TRIPS
278 default m 293 default m
279 help 294 help
280 Enable this to register CPU digital sensor for package temperature as 295 Enable this to register CPU digital sensor for package temperature as
@@ -296,6 +311,7 @@ config INTEL_SOC_DTS_THERMAL
296 tristate "Intel SoCs DTS thermal driver" 311 tristate "Intel SoCs DTS thermal driver"
297 depends on X86 312 depends on X86
298 select INTEL_SOC_DTS_IOSF_CORE 313 select INTEL_SOC_DTS_IOSF_CORE
314 select THERMAL_WRITABLE_TRIPS
299 help 315 help
300 Enable this to register Intel SoCs (e.g. Bay Trail) platform digital 316 Enable this to register Intel SoCs (e.g. Bay Trail) platform digital
301 temperature sensor (DTS). These SoCs have two additional DTSs in 317 temperature sensor (DTS). These SoCs have two additional DTSs in
@@ -322,6 +338,7 @@ config INT340X_THERMAL
322 select ACPI_THERMAL_REL 338 select ACPI_THERMAL_REL
323 select ACPI_FAN 339 select ACPI_FAN
324 select INTEL_SOC_DTS_IOSF_CORE 340 select INTEL_SOC_DTS_IOSF_CORE
341 select THERMAL_WRITABLE_TRIPS
325 help 342 help
326 Newer laptops and tablets that use ACPI may have thermal sensors and 343 Newer laptops and tablets that use ACPI may have thermal sensors and
327 other devices with thermal control capabilities outside the core 344 other devices with thermal control capabilities outside the core
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 26f160809959..cfae6a654793 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -22,6 +22,9 @@ thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
22# clock cooling 22# clock cooling
23thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o 23thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
24 24
25# devfreq cooling
26thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
27
25# platform thermal drivers 28# platform thermal drivers
26obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o 29obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
27obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 30obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index 26b8d326546a..ae75328945f7 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -224,9 +224,9 @@ static const struct armada_thermal_data armada380_data = {
224 .is_valid_shift = 10, 224 .is_valid_shift = 10,
225 .temp_shift = 0, 225 .temp_shift = 0,
226 .temp_mask = 0x3ff, 226 .temp_mask = 0x3ff,
227 .coef_b = 2931108200UL, 227 .coef_b = 1172499100UL,
228 .coef_m = 5000000UL, 228 .coef_m = 2000096UL,
229 .coef_div = 10502, 229 .coef_div = 4201,
230 .inverted = true, 230 .inverted = true,
231}; 231};
232 232
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 42c6f71bdcc1..e3fbc5a5d88f 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -591,8 +591,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
591 if (trace_thermal_power_cpu_get_power_enabled()) { 591 if (trace_thermal_power_cpu_get_power_enabled()) {
592 u32 ncpus = cpumask_weight(&cpufreq_device->allowed_cpus); 592 u32 ncpus = cpumask_weight(&cpufreq_device->allowed_cpus);
593 593
594 load_cpu = devm_kcalloc(&cdev->device, ncpus, sizeof(*load_cpu), 594 load_cpu = kcalloc(ncpus, sizeof(*load_cpu), GFP_KERNEL);
595 GFP_KERNEL);
596 } 595 }
597 596
598 for_each_cpu(cpu, &cpufreq_device->allowed_cpus) { 597 for_each_cpu(cpu, &cpufreq_device->allowed_cpus) {
@@ -615,8 +614,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
615 dynamic_power = get_dynamic_power(cpufreq_device, freq); 614 dynamic_power = get_dynamic_power(cpufreq_device, freq);
616 ret = get_static_power(cpufreq_device, tz, freq, &static_power); 615 ret = get_static_power(cpufreq_device, tz, freq, &static_power);
617 if (ret) { 616 if (ret) {
618 if (load_cpu) 617 kfree(load_cpu);
619 devm_kfree(&cdev->device, load_cpu);
620 return ret; 618 return ret;
621 } 619 }
622 620
@@ -625,7 +623,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
625 &cpufreq_device->allowed_cpus, 623 &cpufreq_device->allowed_cpus,
626 freq, load_cpu, i, dynamic_power, static_power); 624 freq, load_cpu, i, dynamic_power, static_power);
627 625
628 devm_kfree(&cdev->device, load_cpu); 626 kfree(load_cpu);
629 } 627 }
630 628
631 *power = static_power + dynamic_power; 629 *power = static_power + dynamic_power;
diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c
new file mode 100644
index 000000000000..01f0015f80dc
--- /dev/null
+++ b/drivers/thermal/devfreq_cooling.c
@@ -0,0 +1,573 @@
1/*
2 * devfreq_cooling: Thermal cooling device implementation for devices using
3 * devfreq
4 *
5 * Copyright (C) 2014-2015 ARM Limited
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12 * kind, whether express or implied; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * TODO:
17 * - If OPPs are added or removed after devfreq cooling has
18 * registered, the devfreq cooling won't react to it.
19 */
20
21#include <linux/devfreq.h>
22#include <linux/devfreq_cooling.h>
23#include <linux/export.h>
24#include <linux/slab.h>
25#include <linux/pm_opp.h>
26#include <linux/thermal.h>
27
28#include <trace/events/thermal.h>
29
30static DEFINE_MUTEX(devfreq_lock);
31static DEFINE_IDR(devfreq_idr);
32
33/**
34 * struct devfreq_cooling_device - Devfreq cooling device
35 * @id: unique integer value corresponding to each
36 * devfreq_cooling_device registered.
37 * @cdev: Pointer to associated thermal cooling device.
38 * @devfreq: Pointer to associated devfreq device.
39 * @cooling_state: Current cooling state.
40 * @power_table: Pointer to table with maximum power draw for each
41 * cooling state. State is the index into the table, and
42 * the power is in mW.
43 * @freq_table: Pointer to a table with the frequencies sorted in descending
44 * order. You can index the table by cooling device state
45 * @freq_table_size: Size of the @freq_table and @power_table
46 * @power_ops: Pointer to devfreq_cooling_power, used to generate the
47 * @power_table.
48 */
49struct devfreq_cooling_device {
50 int id;
51 struct thermal_cooling_device *cdev;
52 struct devfreq *devfreq;
53 unsigned long cooling_state;
54 u32 *power_table;
55 u32 *freq_table;
56 size_t freq_table_size;
57 struct devfreq_cooling_power *power_ops;
58};
59
60/**
61 * get_idr - function to get a unique id.
62 * @idr: struct idr * handle used to create a id.
63 * @id: int * value generated by this function.
64 *
65 * This function will populate @id with an unique
66 * id, using the idr API.
67 *
68 * Return: 0 on success, an error code on failure.
69 */
70static int get_idr(struct idr *idr, int *id)
71{
72 int ret;
73
74 mutex_lock(&devfreq_lock);
75 ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
76 mutex_unlock(&devfreq_lock);
77 if (unlikely(ret < 0))
78 return ret;
79 *id = ret;
80
81 return 0;
82}
83
84/**
85 * release_idr - function to free the unique id.
86 * @idr: struct idr * handle used for creating the id.
87 * @id: int value representing the unique id.
88 */
89static void release_idr(struct idr *idr, int id)
90{
91 mutex_lock(&devfreq_lock);
92 idr_remove(idr, id);
93 mutex_unlock(&devfreq_lock);
94}
95
96/**
97 * partition_enable_opps() - disable all opps above a given state
98 * @dfc: Pointer to devfreq we are operating on
99 * @cdev_state: cooling device state we're setting
100 *
101 * Go through the OPPs of the device, enabling all OPPs until
102 * @cdev_state and disabling those frequencies above it.
103 */
104static int partition_enable_opps(struct devfreq_cooling_device *dfc,
105 unsigned long cdev_state)
106{
107 int i;
108 struct device *dev = dfc->devfreq->dev.parent;
109
110 for (i = 0; i < dfc->freq_table_size; i++) {
111 struct dev_pm_opp *opp;
112 int ret = 0;
113 unsigned int freq = dfc->freq_table[i];
114 bool want_enable = i >= cdev_state ? true : false;
115
116 rcu_read_lock();
117 opp = dev_pm_opp_find_freq_exact(dev, freq, !want_enable);
118 rcu_read_unlock();
119
120 if (PTR_ERR(opp) == -ERANGE)
121 continue;
122 else if (IS_ERR(opp))
123 return PTR_ERR(opp);
124
125 if (want_enable)
126 ret = dev_pm_opp_enable(dev, freq);
127 else
128 ret = dev_pm_opp_disable(dev, freq);
129
130 if (ret)
131 return ret;
132 }
133
134 return 0;
135}
136
137static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev,
138 unsigned long *state)
139{
140 struct devfreq_cooling_device *dfc = cdev->devdata;
141
142 *state = dfc->freq_table_size - 1;
143
144 return 0;
145}
146
147static int devfreq_cooling_get_cur_state(struct thermal_cooling_device *cdev,
148 unsigned long *state)
149{
150 struct devfreq_cooling_device *dfc = cdev->devdata;
151
152 *state = dfc->cooling_state;
153
154 return 0;
155}
156
157static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev,
158 unsigned long state)
159{
160 struct devfreq_cooling_device *dfc = cdev->devdata;
161 struct devfreq *df = dfc->devfreq;
162 struct device *dev = df->dev.parent;
163 int ret;
164
165 if (state == dfc->cooling_state)
166 return 0;
167
168 dev_dbg(dev, "Setting cooling state %lu\n", state);
169
170 if (state >= dfc->freq_table_size)
171 return -EINVAL;
172
173 ret = partition_enable_opps(dfc, state);
174 if (ret)
175 return ret;
176
177 dfc->cooling_state = state;
178
179 return 0;
180}
181
182/**
183 * freq_get_state() - get the cooling state corresponding to a frequency
184 * @dfc: Pointer to devfreq cooling device
185 * @freq: frequency in Hz
186 *
187 * Return: the cooling state associated with the @freq, or
188 * THERMAL_CSTATE_INVALID if it wasn't found.
189 */
190static unsigned long
191freq_get_state(struct devfreq_cooling_device *dfc, unsigned long freq)
192{
193 int i;
194
195 for (i = 0; i < dfc->freq_table_size; i++) {
196 if (dfc->freq_table[i] == freq)
197 return i;
198 }
199
200 return THERMAL_CSTATE_INVALID;
201}
202
203/**
204 * get_static_power() - calculate the static power
205 * @dfc: Pointer to devfreq cooling device
206 * @freq: Frequency in Hz
207 *
208 * Calculate the static power in milliwatts using the supplied
209 * get_static_power(). The current voltage is calculated using the
210 * OPP library. If no get_static_power() was supplied, assume the
211 * static power is negligible.
212 */
213static unsigned long
214get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
215{
216 struct devfreq *df = dfc->devfreq;
217 struct device *dev = df->dev.parent;
218 unsigned long voltage;
219 struct dev_pm_opp *opp;
220
221 if (!dfc->power_ops->get_static_power)
222 return 0;
223
224 rcu_read_lock();
225
226 opp = dev_pm_opp_find_freq_exact(dev, freq, true);
227 if (IS_ERR(opp) && (PTR_ERR(opp) == -ERANGE))
228 opp = dev_pm_opp_find_freq_exact(dev, freq, false);
229
230 voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */
231
232 rcu_read_unlock();
233
234 if (voltage == 0) {
235 dev_warn_ratelimited(dev,
236 "Failed to get voltage for frequency %lu: %ld\n",
237 freq, IS_ERR(opp) ? PTR_ERR(opp) : 0);
238 return 0;
239 }
240
241 return dfc->power_ops->get_static_power(voltage);
242}
243
244/**
245 * get_dynamic_power - calculate the dynamic power
246 * @dfc: Pointer to devfreq cooling device
247 * @freq: Frequency in Hz
248 * @voltage: Voltage in millivolts
249 *
250 * Calculate the dynamic power in milliwatts consumed by the device at
251 * frequency @freq and voltage @voltage. If the get_dynamic_power()
252 * was supplied as part of the devfreq_cooling_power struct, then that
253 * function is used. Otherwise, a simple power model (Pdyn = Coeff *
254 * Voltage^2 * Frequency) is used.
255 */
256static unsigned long
257get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq,
258 unsigned long voltage)
259{
260 u64 power;
261 u32 freq_mhz;
262 struct devfreq_cooling_power *dfc_power = dfc->power_ops;
263
264 if (dfc_power->get_dynamic_power)
265 return dfc_power->get_dynamic_power(freq, voltage);
266
267 freq_mhz = freq / 1000000;
268 power = (u64)dfc_power->dyn_power_coeff * freq_mhz * voltage * voltage;
269 do_div(power, 1000000000);
270
271 return power;
272}
273
274static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev,
275 struct thermal_zone_device *tz,
276 u32 *power)
277{
278 struct devfreq_cooling_device *dfc = cdev->devdata;
279 struct devfreq *df = dfc->devfreq;
280 struct devfreq_dev_status *status = &df->last_status;
281 unsigned long state;
282 unsigned long freq = status->current_frequency;
283 u32 dyn_power, static_power;
284
285 /* Get dynamic power for state */
286 state = freq_get_state(dfc, freq);
287 if (state == THERMAL_CSTATE_INVALID)
288 return -EAGAIN;
289
290 dyn_power = dfc->power_table[state];
291
292 /* Scale dynamic power for utilization */
293 dyn_power = (dyn_power * status->busy_time) / status->total_time;
294
295 /* Get static power */
296 static_power = get_static_power(dfc, freq);
297
298 trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power,
299 static_power);
300
301 *power = dyn_power + static_power;
302
303 return 0;
304}
305
306static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev,
307 struct thermal_zone_device *tz,
308 unsigned long state,
309 u32 *power)
310{
311 struct devfreq_cooling_device *dfc = cdev->devdata;
312 unsigned long freq;
313 u32 static_power;
314
315 if (state < 0 || state >= dfc->freq_table_size)
316 return -EINVAL;
317
318 freq = dfc->freq_table[state];
319 static_power = get_static_power(dfc, freq);
320
321 *power = dfc->power_table[state] + static_power;
322 return 0;
323}
324
325static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
326 struct thermal_zone_device *tz,
327 u32 power, unsigned long *state)
328{
329 struct devfreq_cooling_device *dfc = cdev->devdata;
330 struct devfreq *df = dfc->devfreq;
331 struct devfreq_dev_status *status = &df->last_status;
332 unsigned long freq = status->current_frequency;
333 unsigned long busy_time;
334 s32 dyn_power;
335 u32 static_power;
336 int i;
337
338 static_power = get_static_power(dfc, freq);
339
340 dyn_power = power - static_power;
341 dyn_power = dyn_power > 0 ? dyn_power : 0;
342
343 /* Scale dynamic power for utilization */
344 busy_time = status->busy_time ?: 1;
345 dyn_power = (dyn_power * status->total_time) / busy_time;
346
347 /*
348 * Find the first cooling state that is within the power
349 * budget for dynamic power.
350 */
351 for (i = 0; i < dfc->freq_table_size - 1; i++)
352 if (dyn_power >= dfc->power_table[i])
353 break;
354
355 *state = i;
356 trace_thermal_power_devfreq_limit(cdev, freq, *state, power);
357 return 0;
358}
359
360static struct thermal_cooling_device_ops devfreq_cooling_ops = {
361 .get_max_state = devfreq_cooling_get_max_state,
362 .get_cur_state = devfreq_cooling_get_cur_state,
363 .set_cur_state = devfreq_cooling_set_cur_state,
364};
365
366/**
367 * devfreq_cooling_gen_tables() - Generate power and freq tables.
368 * @dfc: Pointer to devfreq cooling device.
369 *
370 * Generate power and frequency tables: the power table hold the
371 * device's maximum power usage at each cooling state (OPP). The
372 * static and dynamic power using the appropriate voltage and
373 * frequency for the state, is acquired from the struct
374 * devfreq_cooling_power, and summed to make the maximum power draw.
375 *
376 * The frequency table holds the frequencies in descending order.
377 * That way its indexed by cooling device state.
378 *
379 * The tables are malloced, and pointers put in dfc. They must be
380 * freed when unregistering the devfreq cooling device.
381 *
382 * Return: 0 on success, negative error code on failure.
383 */
384static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc)
385{
386 struct devfreq *df = dfc->devfreq;
387 struct device *dev = df->dev.parent;
388 int ret, num_opps;
389 unsigned long freq;
390 u32 *power_table = NULL;
391 u32 *freq_table;
392 int i;
393
394 num_opps = dev_pm_opp_get_opp_count(dev);
395
396 if (dfc->power_ops) {
397 power_table = kcalloc(num_opps, sizeof(*power_table),
398 GFP_KERNEL);
399 if (!power_table)
400 return -ENOMEM;
401 }
402
403 freq_table = kcalloc(num_opps, sizeof(*freq_table),
404 GFP_KERNEL);
405 if (!freq_table) {
406 ret = -ENOMEM;
407 goto free_power_table;
408 }
409
410 for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) {
411 unsigned long power_dyn, voltage;
412 struct dev_pm_opp *opp;
413
414 rcu_read_lock();
415
416 opp = dev_pm_opp_find_freq_floor(dev, &freq);
417 if (IS_ERR(opp)) {
418 rcu_read_unlock();
419 ret = PTR_ERR(opp);
420 goto free_tables;
421 }
422
423 voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */
424
425 rcu_read_unlock();
426
427 if (dfc->power_ops) {
428 power_dyn = get_dynamic_power(dfc, freq, voltage);
429
430 dev_dbg(dev, "Dynamic power table: %lu MHz @ %lu mV: %lu = %lu mW\n",
431 freq / 1000000, voltage, power_dyn, power_dyn);
432
433 power_table[i] = power_dyn;
434 }
435
436 freq_table[i] = freq;
437 }
438
439 if (dfc->power_ops)
440 dfc->power_table = power_table;
441
442 dfc->freq_table = freq_table;
443 dfc->freq_table_size = num_opps;
444
445 return 0;
446
447free_tables:
448 kfree(freq_table);
449free_power_table:
450 kfree(power_table);
451
452 return ret;
453}
454
455/**
456 * of_devfreq_cooling_register_power() - Register devfreq cooling device,
457 * with OF and power information.
458 * @np: Pointer to OF device_node.
459 * @df: Pointer to devfreq device.
460 * @dfc_power: Pointer to devfreq_cooling_power.
461 *
462 * Register a devfreq cooling device. The available OPPs must be
463 * registered on the device.
464 *
465 * If @dfc_power is provided, the cooling device is registered with the
466 * power extensions. For the power extensions to work correctly,
467 * devfreq should use the simple_ondemand governor, other governors
468 * are not currently supported.
469 */
470struct thermal_cooling_device *
471of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
472 struct devfreq_cooling_power *dfc_power)
473{
474 struct thermal_cooling_device *cdev;
475 struct devfreq_cooling_device *dfc;
476 char dev_name[THERMAL_NAME_LENGTH];
477 int err;
478
479 dfc = kzalloc(sizeof(*dfc), GFP_KERNEL);
480 if (!dfc)
481 return ERR_PTR(-ENOMEM);
482
483 dfc->devfreq = df;
484
485 if (dfc_power) {
486 dfc->power_ops = dfc_power;
487
488 devfreq_cooling_ops.get_requested_power =
489 devfreq_cooling_get_requested_power;
490 devfreq_cooling_ops.state2power = devfreq_cooling_state2power;
491 devfreq_cooling_ops.power2state = devfreq_cooling_power2state;
492 }
493
494 err = devfreq_cooling_gen_tables(dfc);
495 if (err)
496 goto free_dfc;
497
498 err = get_idr(&devfreq_idr, &dfc->id);
499 if (err)
500 goto free_tables;
501
502 snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id);
503
504 cdev = thermal_of_cooling_device_register(np, dev_name, dfc,
505 &devfreq_cooling_ops);
506 if (IS_ERR(cdev)) {
507 err = PTR_ERR(cdev);
508 dev_err(df->dev.parent,
509 "Failed to register devfreq cooling device (%d)\n",
510 err);
511 goto release_idr;
512 }
513
514 dfc->cdev = cdev;
515
516 return cdev;
517
518release_idr:
519 release_idr(&devfreq_idr, dfc->id);
520free_tables:
521 kfree(dfc->power_table);
522 kfree(dfc->freq_table);
523free_dfc:
524 kfree(dfc);
525
526 return ERR_PTR(err);
527}
528EXPORT_SYMBOL_GPL(of_devfreq_cooling_register_power);
529
530/**
531 * of_devfreq_cooling_register() - Register devfreq cooling device,
532 * with OF information.
533 * @np: Pointer to OF device_node.
534 * @df: Pointer to devfreq device.
535 */
536struct thermal_cooling_device *
537of_devfreq_cooling_register(struct device_node *np, struct devfreq *df)
538{
539 return of_devfreq_cooling_register_power(np, df, NULL);
540}
541EXPORT_SYMBOL_GPL(of_devfreq_cooling_register);
542
543/**
544 * devfreq_cooling_register() - Register devfreq cooling device.
545 * @df: Pointer to devfreq device.
546 */
547struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df)
548{
549 return of_devfreq_cooling_register(NULL, df);
550}
551EXPORT_SYMBOL_GPL(devfreq_cooling_register);
552
553/**
554 * devfreq_cooling_unregister() - Unregister devfreq cooling device.
555 * @dfc: Pointer to devfreq cooling device to unregister.
556 */
557void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
558{
559 struct devfreq_cooling_device *dfc;
560
561 if (!cdev)
562 return;
563
564 dfc = cdev->devdata;
565
566 thermal_cooling_device_unregister(dfc->cdev);
567 release_idr(&devfreq_idr, dfc->id);
568 kfree(dfc->power_table);
569 kfree(dfc->freq_table);
570
571 kfree(dfc);
572}
573EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 4bec1d3c3d27..c8fe3cac2e0e 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -288,7 +288,7 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
288 if (trip == IMX_TRIP_CRITICAL) 288 if (trip == IMX_TRIP_CRITICAL)
289 return -EPERM; 289 return -EPERM;
290 290
291 if (temp > IMX_TEMP_PASSIVE) 291 if (temp < 0 || temp > IMX_TEMP_PASSIVE)
292 return -EINVAL; 292 return -EINVAL;
293 293
294 data->temp_passive = temp; 294 data->temp_passive = temp;
@@ -487,14 +487,6 @@ static int imx_thermal_probe(struct platform_device *pdev)
487 if (data->irq < 0) 487 if (data->irq < 0)
488 return data->irq; 488 return data->irq;
489 489
490 ret = devm_request_threaded_irq(&pdev->dev, data->irq,
491 imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
492 0, "imx_thermal", data);
493 if (ret < 0) {
494 dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
495 return ret;
496 }
497
498 platform_set_drvdata(pdev, data); 490 platform_set_drvdata(pdev, data);
499 491
500 ret = imx_get_sensor_data(pdev); 492 ret = imx_get_sensor_data(pdev);
@@ -571,6 +563,17 @@ static int imx_thermal_probe(struct platform_device *pdev)
571 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); 563 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
572 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); 564 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
573 565
566 ret = devm_request_threaded_irq(&pdev->dev, data->irq,
567 imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
568 0, "imx_thermal", data);
569 if (ret < 0) {
570 dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
571 clk_disable_unprepare(data->thermal_clk);
572 thermal_zone_device_unregister(data->tz);
573 cpufreq_cooling_unregister(data->cdev);
574 return ret;
575 }
576
574 data->irq_enabled = true; 577 data->irq_enabled = true;
575 data->mode = THERMAL_DEVICE_ENABLED; 578 data->mode = THERMAL_DEVICE_ENABLED;
576 579
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index c89ffb26a354..2b58870c3e25 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -106,16 +106,14 @@ struct rockchip_thermal_data {
106#define TSADCV2_AUTO_PERIOD_HT 0x6c 106#define TSADCV2_AUTO_PERIOD_HT 0x6c
107 107
108#define TSADCV2_AUTO_EN BIT(0) 108#define TSADCV2_AUTO_EN BIT(0)
109#define TSADCV2_AUTO_DISABLE ~BIT(0)
110#define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn)) 109#define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn))
111#define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8) 110#define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8)
112#define TSADCV2_AUTO_TSHUT_POLARITY_LOW ~BIT(8)
113 111
114#define TSADCV2_INT_SRC_EN(chn) BIT(chn) 112#define TSADCV2_INT_SRC_EN(chn) BIT(chn)
115#define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn)) 113#define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn))
116#define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn)) 114#define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn))
117 115
118#define TSADCV2_INT_PD_CLEAR ~BIT(8) 116#define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8)
119 117
120#define TSADCV2_DATA_MASK 0xfff 118#define TSADCV2_DATA_MASK 0xfff
121#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4 119#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4
@@ -124,7 +122,7 @@ struct rockchip_thermal_data {
124#define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* msec */ 122#define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* msec */
125 123
126struct tsadc_table { 124struct tsadc_table {
127 unsigned long code; 125 u32 code;
128 long temp; 126 long temp;
129}; 127};
130 128
@@ -164,7 +162,6 @@ static const struct tsadc_table v2_code_table[] = {
164 {3452, 115000}, 162 {3452, 115000},
165 {3437, 120000}, 163 {3437, 120000},
166 {3421, 125000}, 164 {3421, 125000},
167 {0, 125000},
168}; 165};
169 166
170static u32 rk_tsadcv2_temp_to_code(long temp) 167static u32 rk_tsadcv2_temp_to_code(long temp)
@@ -191,19 +188,21 @@ static u32 rk_tsadcv2_temp_to_code(long temp)
191 return 0; 188 return 0;
192} 189}
193 190
194static int rk_tsadcv2_code_to_temp(u32 code) 191static int rk_tsadcv2_code_to_temp(u32 code, int *temp)
195{ 192{
196 unsigned int low = 0; 193 unsigned int low = 1;
197 unsigned int high = ARRAY_SIZE(v2_code_table) - 1; 194 unsigned int high = ARRAY_SIZE(v2_code_table) - 1;
198 unsigned int mid = (low + high) / 2; 195 unsigned int mid = (low + high) / 2;
199 unsigned int num; 196 unsigned int num;
200 unsigned long denom; 197 unsigned long denom;
201 198
202 /* Invalid code, return -EAGAIN */ 199 BUILD_BUG_ON(ARRAY_SIZE(v2_code_table) < 2);
203 if (code > TSADCV2_DATA_MASK)
204 return -EAGAIN;
205 200
206 while (low <= high && mid) { 201 code &= TSADCV2_DATA_MASK;
202 if (code < v2_code_table[high].code)
203 return -EAGAIN; /* Incorrect reading */
204
205 while (low <= high) {
207 if (code >= v2_code_table[mid].code && 206 if (code >= v2_code_table[mid].code &&
208 code < v2_code_table[mid - 1].code) 207 code < v2_code_table[mid - 1].code)
209 break; 208 break;
@@ -223,7 +222,9 @@ static int rk_tsadcv2_code_to_temp(u32 code)
223 num = v2_code_table[mid].temp - v2_code_table[mid - 1].temp; 222 num = v2_code_table[mid].temp - v2_code_table[mid - 1].temp;
224 num *= v2_code_table[mid - 1].code - code; 223 num *= v2_code_table[mid - 1].code - code;
225 denom = v2_code_table[mid - 1].code - v2_code_table[mid].code; 224 denom = v2_code_table[mid - 1].code - v2_code_table[mid].code;
226 return v2_code_table[mid - 1].temp + (num / denom); 225 *temp = v2_code_table[mid - 1].temp + (num / denom);
226
227 return 0;
227} 228}
228 229
229/** 230/**
@@ -241,10 +242,10 @@ static void rk_tsadcv2_initialize(void __iomem *regs,
241 enum tshut_polarity tshut_polarity) 242 enum tshut_polarity tshut_polarity)
242{ 243{
243 if (tshut_polarity == TSHUT_HIGH_ACTIVE) 244 if (tshut_polarity == TSHUT_HIGH_ACTIVE)
244 writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_HIGH), 245 writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
245 regs + TSADCV2_AUTO_CON); 246 regs + TSADCV2_AUTO_CON);
246 else 247 else
247 writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_LOW), 248 writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
248 regs + TSADCV2_AUTO_CON); 249 regs + TSADCV2_AUTO_CON);
249 250
250 writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD); 251 writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
@@ -261,7 +262,7 @@ static void rk_tsadcv2_irq_ack(void __iomem *regs)
261 u32 val; 262 u32 val;
262 263
263 val = readl_relaxed(regs + TSADCV2_INT_PD); 264 val = readl_relaxed(regs + TSADCV2_INT_PD);
264 writel_relaxed(val & TSADCV2_INT_PD_CLEAR, regs + TSADCV2_INT_PD); 265 writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
265} 266}
266 267
267static void rk_tsadcv2_control(void __iomem *regs, bool enable) 268static void rk_tsadcv2_control(void __iomem *regs, bool enable)
@@ -281,14 +282,9 @@ static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, int *temp)
281{ 282{
282 u32 val; 283 u32 val;
283 284
284 /* the A/D value of the channel last conversion need some time */
285 val = readl_relaxed(regs + TSADCV2_DATA(chn)); 285 val = readl_relaxed(regs + TSADCV2_DATA(chn));
286 if (val == 0)
287 return -EAGAIN;
288 286
289 *temp = rk_tsadcv2_code_to_temp(val); 287 return rk_tsadcv2_code_to_temp(val, temp);
290
291 return 0;
292} 288}
293 289
294static void rk_tsadcv2_tshut_temp(int chn, void __iomem *regs, long temp) 290static void rk_tsadcv2_tshut_temp(int chn, void __iomem *regs, long temp)
@@ -642,6 +638,8 @@ static int __maybe_unused rockchip_thermal_suspend(struct device *dev)
642 clk_disable(thermal->pclk); 638 clk_disable(thermal->pclk);
643 clk_disable(thermal->clk); 639 clk_disable(thermal->clk);
644 640
641 pinctrl_pm_select_sleep_state(dev);
642
645 return 0; 643 return 0;
646} 644}
647 645
@@ -678,6 +676,8 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev)
678 for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++) 676 for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++)
679 rockchip_thermal_toggle_sensor(&thermal->sensors[i], true); 677 rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
680 678
679 pinctrl_pm_select_default_state(dev);
680
681 return 0; 681 return 0;
682} 682}
683 683
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index ca920b0ecf8f..fa61eff88496 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -548,7 +548,7 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev)
548 default: 548 default:
549 pdata->cal_type = TYPE_ONE_POINT_TRIMMING; 549 pdata->cal_type = TYPE_ONE_POINT_TRIMMING;
550 break; 550 break;
551 }; 551 }
552 552
553 dev_info(&pdev->dev, "Calibration type is %d-point calibration\n", 553 dev_info(&pdev->dev, "Calibration type is %d-point calibration\n",
554 cal_type ? 2 : 1); 554 cal_type ? 2 : 1);
@@ -608,7 +608,7 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
608{ 608{
609 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 609 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
610 unsigned int trim_info = 0, con, rising_threshold; 610 unsigned int trim_info = 0, con, rising_threshold;
611 int ret = 0, threshold_code; 611 int threshold_code;
612 int crit_temp = 0; 612 int crit_temp = 0;
613 613
614 /* 614 /*
@@ -651,7 +651,8 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
651 /* Clear the PMIN in the common TMU register */ 651 /* Clear the PMIN in the common TMU register */
652 if (!data->id) 652 if (!data->id)
653 writel(0, data->base_second + EXYNOS5440_TMU_PMIN); 653 writel(0, data->base_second + EXYNOS5440_TMU_PMIN);
654 return ret; 654
655 return 0;
655} 656}
656 657
657static int exynos7_tmu_initialize(struct platform_device *pdev) 658static int exynos7_tmu_initialize(struct platform_device *pdev)
@@ -1168,27 +1169,10 @@ static int exynos_map_dt_data(struct platform_device *pdev)
1168 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 1169 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1169 struct exynos_tmu_platform_data *pdata; 1170 struct exynos_tmu_platform_data *pdata;
1170 struct resource res; 1171 struct resource res;
1171 int ret;
1172 1172
1173 if (!data || !pdev->dev.of_node) 1173 if (!data || !pdev->dev.of_node)
1174 return -ENODEV; 1174 return -ENODEV;
1175 1175
1176 /*
1177 * Try enabling the regulator if found
1178 * TODO: Add regulator as an SOC feature, so that regulator enable
1179 * is a compulsory call.
1180 */
1181 data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
1182 if (!IS_ERR(data->regulator)) {
1183 ret = regulator_enable(data->regulator);
1184 if (ret) {
1185 dev_err(&pdev->dev, "failed to enable vtmu\n");
1186 return ret;
1187 }
1188 } else {
1189 dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
1190 }
1191
1192 data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl"); 1176 data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
1193 if (data->id < 0) 1177 if (data->id < 0)
1194 data->id = 0; 1178 data->id = 0;
@@ -1306,12 +1290,22 @@ static int exynos_tmu_probe(struct platform_device *pdev)
1306 platform_set_drvdata(pdev, data); 1290 platform_set_drvdata(pdev, data);
1307 mutex_init(&data->lock); 1291 mutex_init(&data->lock);
1308 1292
1309 data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data, 1293 /*
1310 &exynos_sensor_ops); 1294 * Try enabling the regulator if found
1311 if (IS_ERR(data->tzd)) { 1295 * TODO: Add regulator as an SOC feature, so that regulator enable
1312 pr_err("thermal: tz: %p ERROR\n", data->tzd); 1296 * is a compulsory call.
1313 return PTR_ERR(data->tzd); 1297 */
1298 data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
1299 if (!IS_ERR(data->regulator)) {
1300 ret = regulator_enable(data->regulator);
1301 if (ret) {
1302 dev_err(&pdev->dev, "failed to enable vtmu\n");
1303 return ret;
1304 }
1305 } else {
1306 dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
1314 } 1307 }
1308
1315 ret = exynos_map_dt_data(pdev); 1309 ret = exynos_map_dt_data(pdev);
1316 if (ret) 1310 if (ret)
1317 goto err_sensor; 1311 goto err_sensor;
@@ -1363,23 +1357,38 @@ static int exynos_tmu_probe(struct platform_device *pdev)
1363 break; 1357 break;
1364 default: 1358 default:
1365 break; 1359 break;
1366 }; 1360 }
1361
1362 /*
1363 * data->tzd must be registered before calling exynos_tmu_initialize(),
1364 * requesting irq and calling exynos_tmu_control().
1365 */
1366 data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
1367 &exynos_sensor_ops);
1368 if (IS_ERR(data->tzd)) {
1369 ret = PTR_ERR(data->tzd);
1370 dev_err(&pdev->dev, "Failed to register sensor: %d\n", ret);
1371 goto err_sclk;
1372 }
1367 1373
1368 ret = exynos_tmu_initialize(pdev); 1374 ret = exynos_tmu_initialize(pdev);
1369 if (ret) { 1375 if (ret) {
1370 dev_err(&pdev->dev, "Failed to initialize TMU\n"); 1376 dev_err(&pdev->dev, "Failed to initialize TMU\n");
1371 goto err_sclk; 1377 goto err_thermal;
1372 } 1378 }
1373 1379
1374 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq, 1380 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
1375 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data); 1381 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
1376 if (ret) { 1382 if (ret) {
1377 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq); 1383 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
1378 goto err_sclk; 1384 goto err_thermal;
1379 } 1385 }
1380 1386
1381 exynos_tmu_control(pdev, true); 1387 exynos_tmu_control(pdev, true);
1382 return 0; 1388 return 0;
1389
1390err_thermal:
1391 thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd);
1383err_sclk: 1392err_sclk:
1384 clk_disable_unprepare(data->sclk); 1393 clk_disable_unprepare(data->sclk);
1385err_clk: 1394err_clk:
@@ -1388,9 +1397,8 @@ err_clk_sec:
1388 if (!IS_ERR(data->clk_sec)) 1397 if (!IS_ERR(data->clk_sec))
1389 clk_unprepare(data->clk_sec); 1398 clk_unprepare(data->clk_sec);
1390err_sensor: 1399err_sensor:
1391 if (!IS_ERR_OR_NULL(data->regulator)) 1400 if (!IS_ERR(data->regulator))
1392 regulator_disable(data->regulator); 1401 regulator_disable(data->regulator);
1393 thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd);
1394 1402
1395 return ret; 1403 return ret;
1396} 1404}
diff --git a/drivers/thermal/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig
index cb6686ff09ae..ea8283f08aa6 100644
--- a/drivers/thermal/ti-soc-thermal/Kconfig
+++ b/drivers/thermal/ti-soc-thermal/Kconfig
@@ -19,6 +19,21 @@ config TI_THERMAL
19 This includes trip points definitions, extrapolation rules and 19 This includes trip points definitions, extrapolation rules and
20 CPU cooling device bindings. 20 CPU cooling device bindings.
21 21
22config OMAP3_THERMAL
23 bool "Texas Instruments OMAP3 thermal support"
24 depends on TI_SOC_THERMAL
25 depends on ARCH_OMAP3 || COMPILE_TEST
26 help
27 If you say yes here you get thermal support for the Texas Instruments
28 OMAP3 SoC family. The current chips supported are:
29 - OMAP3430
30
31 OMAP3 chips normally don't need thermal management, and sensors in
32 this generation are not accurate, nor they are very close to
33 the important hotspots.
34
35 Say 'N' here.
36
22config OMAP4_THERMAL 37config OMAP4_THERMAL
23 bool "Texas Instruments OMAP4 thermal support" 38 bool "Texas Instruments OMAP4 thermal support"
24 depends on TI_SOC_THERMAL 39 depends on TI_SOC_THERMAL
diff --git a/drivers/thermal/ti-soc-thermal/Makefile b/drivers/thermal/ti-soc-thermal/Makefile
index 1226b2484e55..0f89bdf03790 100644
--- a/drivers/thermal/ti-soc-thermal/Makefile
+++ b/drivers/thermal/ti-soc-thermal/Makefile
@@ -2,5 +2,6 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o
2ti-soc-thermal-y := ti-bandgap.o 2ti-soc-thermal-y := ti-bandgap.o
3ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o 3ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o
4ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o 4ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o
5ti-soc-thermal-$(CONFIG_OMAP3_THERMAL) += omap3-thermal-data.o
5ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o 6ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o
6ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o 7ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o
diff --git a/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
new file mode 100644
index 000000000000..3ee34340edab
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
@@ -0,0 +1,176 @@
1/*
2 * OMAP3 thermal driver.
3 *
4 * Copyright (C) 2011-2012 Texas Instruments Inc.
5 * Copyright (C) 2014 Pavel Machek <pavel@ucw.cz>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
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 * Note
17 * http://www.ti.com/lit/er/sprz278f/sprz278f.pdf "Advisory
18 * 3.1.1.186 MMC OCP Clock Not Gated When Thermal Sensor Is Used"
19 *
20 * Also TI says:
21 * Just be careful when you try to make thermal policy like decisions
22 * based on this sensor. Placement of the sensor w.r.t the actual logic
23 * generating heat has to be a factor as well. If you are just looking
24 * for an approximation temperature (thermometerish kind), you might be
25 * ok with this. I am not sure we'd find any TI data around this.. just a
26 * heads up.
27 */
28
29#include "ti-thermal.h"
30#include "ti-bandgap.h"
31
32/*
33 * OMAP34XX has one instance of thermal sensor for MPU
34 * need to describe the individual bit fields
35 */
36static struct temp_sensor_registers
37omap34xx_mpu_temp_sensor_registers = {
38 .temp_sensor_ctrl = 0,
39 .bgap_soc_mask = BIT(8),
40 .bgap_eocz_mask = BIT(7),
41 .bgap_dtemp_mask = 0x7f,
42
43 .bgap_mode_ctrl = 0,
44 .mode_ctrl_mask = BIT(9),
45};
46
47/* Thresholds and limits for OMAP34XX MPU temperature sensor */
48static struct temp_sensor_data omap34xx_mpu_temp_sensor_data = {
49 .min_freq = 32768,
50 .max_freq = 32768,
51 .max_temp = 125000,
52 .min_temp = -40000,
53 .hyst_val = 5000,
54};
55
56/*
57 * Temperature values in milli degree celsius
58 */
59static const int
60omap34xx_adc_to_temp[128] = {
61 -40000, -40000, -40000, -40000, -40000, -39000, -38000, -36000,
62 -34000, -32000, -31000, -29000, -28000, -26000, -25000, -24000,
63 -22000, -21000, -19000, -18000, -17000, -15000, -14000, -12000,
64 -11000, -9000, -8000, -7000, -5000, -4000, -2000, -1000, 0000,
65 1000, 3000, 4000, 5000, 7000, 8000, 10000, 11000, 13000, 14000,
66 15000, 17000, 18000, 20000, 21000, 22000, 24000, 25000, 27000,
67 28000, 30000, 31000, 32000, 34000, 35000, 37000, 38000, 39000,
68 41000, 42000, 44000, 45000, 47000, 48000, 49000, 51000, 52000,
69 53000, 55000, 56000, 58000, 59000, 60000, 62000, 63000, 65000,
70 66000, 67000, 69000, 70000, 72000, 73000, 74000, 76000, 77000,
71 79000, 80000, 81000, 83000, 84000, 85000, 87000, 88000, 89000,
72 91000, 92000, 94000, 95000, 96000, 98000, 99000, 100000,
73 102000, 103000, 105000, 106000, 107000, 109000, 110000, 111000,
74 113000, 114000, 116000, 117000, 118000, 120000, 121000, 122000,
75 124000, 124000, 125000, 125000, 125000, 125000, 125000
76};
77
78/* OMAP34XX data */
79const struct ti_bandgap_data omap34xx_data = {
80 .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE,
81 .fclock_name = "ts_fck",
82 .div_ck_name = "ts_fck",
83 .conv_table = omap34xx_adc_to_temp,
84 .adc_start_val = 0,
85 .adc_end_val = 127,
86 .expose_sensor = ti_thermal_expose_sensor,
87 .remove_sensor = ti_thermal_remove_sensor,
88
89 .sensors = {
90 {
91 .registers = &omap34xx_mpu_temp_sensor_registers,
92 .ts_data = &omap34xx_mpu_temp_sensor_data,
93 .domain = "cpu",
94 .slope = 0,
95 .constant = 20000,
96 .slope_pcb = 0,
97 .constant_pcb = 20000,
98 .register_cooling = NULL,
99 .unregister_cooling = NULL,
100 },
101 },
102 .sensor_count = 1,
103};
104
105/*
106 * OMAP36XX has one instance of thermal sensor for MPU
107 * need to describe the individual bit fields
108 */
109static struct temp_sensor_registers
110omap36xx_mpu_temp_sensor_registers = {
111 .temp_sensor_ctrl = 0,
112 .bgap_soc_mask = BIT(9),
113 .bgap_eocz_mask = BIT(8),
114 .bgap_dtemp_mask = 0xFF,
115
116 .bgap_mode_ctrl = 0,
117 .mode_ctrl_mask = BIT(10),
118};
119
120/* Thresholds and limits for OMAP36XX MPU temperature sensor */
121static struct temp_sensor_data omap36xx_mpu_temp_sensor_data = {
122 .min_freq = 32768,
123 .max_freq = 32768,
124 .max_temp = 125000,
125 .min_temp = -40000,
126 .hyst_val = 5000,
127};
128
129/*
130 * Temperature values in milli degree celsius
131 */
132static const int
133omap36xx_adc_to_temp[128] = {
134 -40000, -40000, -40000, -40000, -40000, -40000, -40000, -40000,
135 -40000, -40000, -40000, -40000, -40000, -38000, -35000, -34000,
136 -32000, -30000, -28000, -26000, -24000, -22000, -20000, -18500,
137 -17000, -15000, -13500, -12000, -10000, -8000, -6500, -5000, -3500,
138 -1500, 0, 2000, 3500, 5000, 6500, 8500, 10000, 12000, 13500,
139 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28500, 30000,
140 32000, 33500, 35000, 37000, 38500, 40000, 42000, 43500, 45000,
141 47000, 48500, 50000, 52000, 53500, 55000, 57000, 58500, 60000,
142 62000, 64000, 66000, 68000, 70000, 71500, 73500, 75000, 77000,
143 78500, 80000, 82000, 83500, 85000, 87000, 88500, 90000, 92000,
144 93500, 95000, 97000, 98500, 100000, 102000, 103500, 105000, 107000,
145 109000, 111000, 113000, 115000, 117000, 118500, 120000, 122000,
146 123500, 125000, 125000, 125000, 125000, 125000, 125000, 125000,
147 125000, 125000, 125000, 125000, 125000, 125000, 125000, 125000,
148 125000, 125000, 125000, 125000, 125000, 125000, 125000
149};
150
151/* OMAP36XX data */
152const struct ti_bandgap_data omap36xx_data = {
153 .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE,
154 .fclock_name = "ts_fck",
155 .div_ck_name = "ts_fck",
156 .conv_table = omap36xx_adc_to_temp,
157 .adc_start_val = 0,
158 .adc_end_val = 127,
159 .expose_sensor = ti_thermal_expose_sensor,
160 .remove_sensor = ti_thermal_remove_sensor,
161
162 .sensors = {
163 {
164 .registers = &omap36xx_mpu_temp_sensor_registers,
165 .ts_data = &omap36xx_mpu_temp_sensor_data,
166 .domain = "cpu",
167 .slope = 0,
168 .constant = 20000,
169 .slope_pcb = 0,
170 .constant_pcb = 20000,
171 .register_cooling = NULL,
172 .unregister_cooling = NULL,
173 },
174 },
175 .sensor_count = 1,
176};
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
index 10c47c048f7a..1e34a1efc554 100644
--- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
@@ -1274,6 +1274,10 @@ int ti_bandgap_probe(struct platform_device *pdev)
1274 } 1274 }
1275 bgp->dev = &pdev->dev; 1275 bgp->dev = &pdev->dev;
1276 1276
1277 if (TI_BANDGAP_HAS(bgp, UNRELIABLE))
1278 dev_warn(&pdev->dev,
1279 "This OMAP thermal sensor is unreliable. You've been warned\n");
1280
1277 if (TI_BANDGAP_HAS(bgp, TSHUT)) { 1281 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1278 ret = ti_bandgap_tshut_init(bgp, pdev); 1282 ret = ti_bandgap_tshut_init(bgp, pdev);
1279 if (ret) { 1283 if (ret) {
@@ -1579,6 +1583,16 @@ static SIMPLE_DEV_PM_OPS(ti_bandgap_dev_pm_ops, ti_bandgap_suspend,
1579#endif 1583#endif
1580 1584
1581static const struct of_device_id of_ti_bandgap_match[] = { 1585static const struct of_device_id of_ti_bandgap_match[] = {
1586#ifdef CONFIG_OMAP3_THERMAL
1587 {
1588 .compatible = "ti,omap34xx-bandgap",
1589 .data = (void *)&omap34xx_data,
1590 },
1591 {
1592 .compatible = "ti,omap36xx-bandgap",
1593 .data = (void *)&omap36xx_data,
1594 },
1595#endif
1582#ifdef CONFIG_OMAP4_THERMAL 1596#ifdef CONFIG_OMAP4_THERMAL
1583 { 1597 {
1584 .compatible = "ti,omap4430-bandgap", 1598 .compatible = "ti,omap4430-bandgap",
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
index 0c52f7afba00..fe0adb898764 100644
--- a/drivers/thermal/ti-soc-thermal/ti-bandgap.h
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
@@ -322,6 +322,8 @@ struct ti_temp_sensor {
322 * has Errata 814 322 * has Errata 814
323 * TI_BANDGAP_FEATURE_ERRATA_813 - used to workaorund when the bandgap device 323 * TI_BANDGAP_FEATURE_ERRATA_813 - used to workaorund when the bandgap device
324 * has Errata 813 324 * has Errata 813
325 * TI_BANDGAP_FEATURE_UNRELIABLE - used when the sensor readings are too
326 * inaccurate.
325 * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a 327 * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a
326 * specific feature (above) or not. Return non-zero, if yes. 328 * specific feature (above) or not. Return non-zero, if yes.
327 */ 329 */
@@ -337,6 +339,7 @@ struct ti_temp_sensor {
337#define TI_BANDGAP_FEATURE_HISTORY_BUFFER BIT(9) 339#define TI_BANDGAP_FEATURE_HISTORY_BUFFER BIT(9)
338#define TI_BANDGAP_FEATURE_ERRATA_814 BIT(10) 340#define TI_BANDGAP_FEATURE_ERRATA_814 BIT(10)
339#define TI_BANDGAP_FEATURE_ERRATA_813 BIT(11) 341#define TI_BANDGAP_FEATURE_ERRATA_813 BIT(11)
342#define TI_BANDGAP_FEATURE_UNRELIABLE BIT(12)
340#define TI_BANDGAP_HAS(b, f) \ 343#define TI_BANDGAP_HAS(b, f) \
341 ((b)->conf->features & TI_BANDGAP_FEATURE_ ## f) 344 ((b)->conf->features & TI_BANDGAP_FEATURE_ ## f)
342 345
@@ -390,6 +393,14 @@ int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data);
390void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id); 393void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id);
391int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend); 394int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend);
392 395
396#ifdef CONFIG_OMAP3_THERMAL
397extern const struct ti_bandgap_data omap34xx_data;
398extern const struct ti_bandgap_data omap36xx_data;
399#else
400#define omap34xx_data NULL
401#define omap36xx_data NULL
402#endif
403
393#ifdef CONFIG_OMAP4_THERMAL 404#ifdef CONFIG_OMAP4_THERMAL
394extern const struct ti_bandgap_data omap4430_data; 405extern const struct ti_bandgap_data omap4430_data;
395extern const struct ti_bandgap_data omap4460_data; 406extern const struct ti_bandgap_data omap4460_data;
diff --git a/include/linux/devfreq_cooling.h b/include/linux/devfreq_cooling.h
new file mode 100644
index 000000000000..7adf6cc4b305
--- /dev/null
+++ b/include/linux/devfreq_cooling.h
@@ -0,0 +1,81 @@
1/*
2 * devfreq_cooling: Thermal cooling device implementation for devices using
3 * devfreq
4 *
5 * Copyright (C) 2014-2015 ARM Limited
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12 * kind, whether express or implied; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#ifndef __DEVFREQ_COOLING_H__
18#define __DEVFREQ_COOLING_H__
19
20#include <linux/devfreq.h>
21#include <linux/thermal.h>
22
23#ifdef CONFIG_DEVFREQ_THERMAL
24
25/**
26 * struct devfreq_cooling_power - Devfreq cooling power ops
27 * @get_static_power: Take voltage, in mV, and return the static power
28 * in mW. If NULL, the static power is assumed
29 * to be 0.
30 * @get_dynamic_power: Take voltage, in mV, and frequency, in HZ, and
31 * return the dynamic power draw in mW. If NULL,
32 * a simple power model is used.
33 * @dyn_power_coeff: Coefficient for the simple dynamic power model in
34 * mW/(MHz mV mV).
35 * If get_dynamic_power() is NULL, then the
36 * dynamic power is calculated as
37 * @dyn_power_coeff * frequency * voltage^2
38 */
39struct devfreq_cooling_power {
40 unsigned long (*get_static_power)(unsigned long voltage);
41 unsigned long (*get_dynamic_power)(unsigned long freq,
42 unsigned long voltage);
43 unsigned long dyn_power_coeff;
44};
45
46struct thermal_cooling_device *
47of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
48 struct devfreq_cooling_power *dfc_power);
49struct thermal_cooling_device *
50of_devfreq_cooling_register(struct device_node *np, struct devfreq *df);
51struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df);
52void devfreq_cooling_unregister(struct thermal_cooling_device *dfc);
53
54#else /* !CONFIG_DEVFREQ_THERMAL */
55
56struct thermal_cooling_device *
57of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
58 struct devfreq_cooling_power *dfc_power)
59{
60 return ERR_PTR(-EINVAL);
61}
62
63static inline struct thermal_cooling_device *
64of_devfreq_cooling_register(struct device_node *np, struct devfreq *df)
65{
66 return ERR_PTR(-EINVAL);
67}
68
69static inline struct thermal_cooling_device *
70devfreq_cooling_register(struct devfreq *df)
71{
72 return ERR_PTR(-EINVAL);
73}
74
75static inline void
76devfreq_cooling_unregister(struct thermal_cooling_device *dfc)
77{
78}
79
80#endif /* CONFIG_DEVFREQ_THERMAL */
81#endif /* __DEVFREQ_COOLING_H__ */
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 157d366e761b..4014a59828fc 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -44,9 +44,11 @@
44#define THERMAL_WEIGHT_DEFAULT 0 44#define THERMAL_WEIGHT_DEFAULT 0
45 45
46/* Unit conversion macros */ 46/* Unit conversion macros */
47#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \ 47#define DECI_KELVIN_TO_CELSIUS(t) ({ \
48 ((long)t-2732+5)/10 : ((long)t-2732-5)/10) 48 long _t = (t); \
49#define CELSIUS_TO_KELVIN(t) ((t)*10+2732) 49 ((_t-2732 >= 0) ? (_t-2732+5)/10 : (_t-2732-5)/10); \
50})
51#define CELSIUS_TO_DECI_KELVIN(t) ((t)*10+2732)
50#define DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, off) (((t) - (off)) * 100) 52#define DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, off) (((t) - (off)) * 100)
51#define DECI_KELVIN_TO_MILLICELSIUS(t) DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, 2732) 53#define DECI_KELVIN_TO_MILLICELSIUS(t) DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, 2732)
52#define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off)) 54#define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off))
diff --git a/include/trace/events/thermal.h b/include/trace/events/thermal.h
index 8b1f80682b80..5738bb3e2343 100644
--- a/include/trace/events/thermal.h
+++ b/include/trace/events/thermal.h
@@ -4,6 +4,7 @@
4#if !defined(_TRACE_THERMAL_H) || defined(TRACE_HEADER_MULTI_READ) 4#if !defined(_TRACE_THERMAL_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_THERMAL_H 5#define _TRACE_THERMAL_H
6 6
7#include <linux/devfreq.h>
7#include <linux/thermal.h> 8#include <linux/thermal.h>
8#include <linux/tracepoint.h> 9#include <linux/tracepoint.h>
9 10
@@ -135,6 +136,58 @@ TRACE_EVENT(thermal_power_cpu_limit,
135 __entry->power) 136 __entry->power)
136); 137);
137 138
139TRACE_EVENT(thermal_power_devfreq_get_power,
140 TP_PROTO(struct thermal_cooling_device *cdev,
141 struct devfreq_dev_status *status, unsigned long freq,
142 u32 dynamic_power, u32 static_power),
143
144 TP_ARGS(cdev, status, freq, dynamic_power, static_power),
145
146 TP_STRUCT__entry(
147 __string(type, cdev->type )
148 __field(unsigned long, freq )
149 __field(u32, load )
150 __field(u32, dynamic_power )
151 __field(u32, static_power )
152 ),
153
154 TP_fast_assign(
155 __assign_str(type, cdev->type);
156 __entry->freq = freq;
157 __entry->load = (100 * status->busy_time) / status->total_time;
158 __entry->dynamic_power = dynamic_power;
159 __entry->static_power = static_power;
160 ),
161
162 TP_printk("type=%s freq=%lu load=%u dynamic_power=%u static_power=%u",
163 __get_str(type), __entry->freq,
164 __entry->load, __entry->dynamic_power, __entry->static_power)
165);
166
167TRACE_EVENT(thermal_power_devfreq_limit,
168 TP_PROTO(struct thermal_cooling_device *cdev, unsigned long freq,
169 unsigned long cdev_state, u32 power),
170
171 TP_ARGS(cdev, freq, cdev_state, power),
172
173 TP_STRUCT__entry(
174 __string(type, cdev->type)
175 __field(unsigned int, freq )
176 __field(unsigned long, cdev_state)
177 __field(u32, power )
178 ),
179
180 TP_fast_assign(
181 __assign_str(type, cdev->type);
182 __entry->freq = freq;
183 __entry->cdev_state = cdev_state;
184 __entry->power = power;
185 ),
186
187 TP_printk("type=%s freq=%u cdev_state=%lu power=%u",
188 __get_str(type), __entry->freq, __entry->cdev_state,
189 __entry->power)
190);
138#endif /* _TRACE_THERMAL_H */ 191#endif /* _TRACE_THERMAL_H */
139 192
140/* This part must be outside protection */ 193/* This part must be outside protection */
diff --git a/tools/thermal/tmon/Makefile b/tools/thermal/tmon/Makefile
index 2e83dd3655a2..3a961e998281 100644
--- a/tools/thermal/tmon/Makefile
+++ b/tools/thermal/tmon/Makefile
@@ -22,6 +22,9 @@ TMON_LIBS += $(shell pkg-config --libs $(STATIC) panelw ncursesw 2> /dev/null ||
22 pkg-config --libs $(STATIC) panel ncurses 2> /dev/null || \ 22 pkg-config --libs $(STATIC) panel ncurses 2> /dev/null || \
23 echo -lpanel -lncurses) 23 echo -lpanel -lncurses)
24 24
25CFLAGS += $(shell pkg-config --cflags $(STATIC) panelw ncursesw 2> /dev/null || \
26 pkg-config --cflags $(STATIC) panel ncurses 2> /dev/null)
27
25OBJS = tmon.o tui.o sysfs.o pid.o 28OBJS = tmon.o tui.o sysfs.o pid.o
26OBJS += 29OBJS +=
27 30