aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-24 20:13:49 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-24 20:13:49 -0500
commit91466574be1a3701fab4abf5ac1539b556575a81 (patch)
tree89373ef6b0c9e024a9688207b832552dfbcca666 /drivers/thermal
parent09da8dfa98682d871987145ed11e3232accac860 (diff)
parentc698a4492f01127ca90fc28cd5157f3d616fe4ff (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management updates from Zhang Rui: "This time, the biggest change is the work of representing hardware thermal properties in device tree infrastructure. This work includes the introduction of a device tree bindings for describing the hardware thermal behavior and limits, and also a parser to read and interpret the data, and build thermal zones and thermal binding parameters. It also contains three examples on how to use the new representation on sensor devices, using three different drivers to accomplish it. One driver is in thermal subsystem, the TI SoC thermal, and the other two drivers are in hwmon subsystem. Actually, this would be the first step of the complete work because we still need to check other potential drivers to be converted and then validate the proposed API. But the reason why I include it in this pull request is that, first, this change does not hurt any others without using this approach, second, the principle and concept of this change would not break after converting the remaining drivers. BTW, as you can see, there are several points in this change that do not belong to thermal subsystem. Because it has been suggested by Guenter R that in such cases, it is recommended to send the complete series via one single subsystem. Specifics: - representing hardware thermal properties in device tree infrastructure - fix a regression that the imx thermal driver breaks system suspend. - introduce ACPI INT3403 thermal driver to retrieve temperature data from the INT3403 ACPI device object present on some systems. - introduce debug statement for thermal core and step_wise governor. - assorted fixes and cleanups for thermal core, cpu cooling, exynos thrmal, intel powerclamp and imx thermal driver" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (34 commits) thermal: remove const flag from .ops of imx thermal Thermal: update thermal zone device after setting emul_temp intel_powerclamp: Fix cstate counter detection. thermal: imx: add necessary clk operation Thermal cpu cooling: return error if no valid cpu frequency entry thermal: fix cpu_cooling max_level behavior thermal: rcar-thermal: Enable driver compilation with COMPILE_TEST thermal: debug: add debug statement for core and step_wise thermal: imx_thermal: add module device table drivers: thermal: Mark function as static in x86_pkg_temp_thermal.c thermal:samsung: fix compilation warning thermal: imx: correct suspend/resume flow thermal: exynos: fix error return code Thermal: ACPI INT3403 thermal driver MAINTAINERS: add thermal bindings entry in thermal domain arm: dts: make OMAP4460 bandgap node to belong to OCP arm: dts: make OMAP443x bandgap node to belong to OCP arm: dts: add cooling properties on omap5 cpu node arm: dts: add omap5 thermal data arm: dts: add omap5 CORE thermal data ...
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/Kconfig23
-rw-r--r--drivers/thermal/Makefile2
-rw-r--r--drivers/thermal/cpu_cooling.c67
-rw-r--r--drivers/thermal/imx_thermal.c54
-rw-r--r--drivers/thermal/int3403_thermal.c237
-rw-r--r--drivers/thermal/intel_powerclamp.c11
-rw-r--r--drivers/thermal/of-thermal.c849
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.c2
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c1
-rw-r--r--drivers/thermal/step_wise.c6
-rw-r--r--drivers/thermal/thermal_core.c86
-rw-r--r--drivers/thermal/thermal_core.h9
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal-common.c77
-rw-r--r--drivers/thermal/x86_pkg_temp_thermal.c2
14 files changed, 1377 insertions, 49 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index f35a1f75b15b..35c066489a19 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -29,6 +29,19 @@ config THERMAL_HWMON
29 Say 'Y' here if you want all thermal sensors to 29 Say 'Y' here if you want all thermal sensors to
30 have hwmon sysfs interface too. 30 have hwmon sysfs interface too.
31 31
32config THERMAL_OF
33 bool
34 prompt "APIs to parse thermal data out of device tree"
35 depends on OF
36 default y
37 help
38 This options provides helpers to add the support to
39 read and parse thermal data definitions out of the
40 device tree blob.
41
42 Say 'Y' here if you need to build thermal infrastructure
43 based on device tree.
44
32choice 45choice
33 prompt "Default Thermal governor" 46 prompt "Default Thermal governor"
34 default THERMAL_DEFAULT_GOV_STEP_WISE 47 default THERMAL_DEFAULT_GOV_STEP_WISE
@@ -79,6 +92,7 @@ config THERMAL_GOV_USER_SPACE
79config CPU_THERMAL 92config CPU_THERMAL
80 bool "generic cpu cooling support" 93 bool "generic cpu cooling support"
81 depends on CPU_FREQ 94 depends on CPU_FREQ
95 depends on THERMAL_OF
82 help 96 help
83 This implements the generic cpu cooling mechanism through frequency 97 This implements the generic cpu cooling mechanism through frequency
84 reduction. An ACPI version of this already exists 98 reduction. An ACPI version of this already exists
@@ -121,7 +135,7 @@ config SPEAR_THERMAL
121 135
122config RCAR_THERMAL 136config RCAR_THERMAL
123 tristate "Renesas R-Car thermal driver" 137 tristate "Renesas R-Car thermal driver"
124 depends on ARCH_SHMOBILE 138 depends on ARCH_SHMOBILE || COMPILE_TEST
125 help 139 help
126 Enable this to plug the R-Car thermal sensor driver into the Linux 140 Enable this to plug the R-Car thermal sensor driver into the Linux
127 thermal framework. 141 thermal framework.
@@ -192,6 +206,13 @@ config X86_PKG_TEMP_THERMAL
192 two trip points which can be set by user to get notifications via thermal 206 two trip points which can be set by user to get notifications via thermal
193 notification methods. 207 notification methods.
194 208
209config ACPI_INT3403_THERMAL
210 tristate "ACPI INT3403 thermal driver"
211 depends on X86 && ACPI
212 help
213 This driver uses ACPI INT3403 device objects. If present, it will
214 register each INT3403 thermal sensor as a thermal zone.
215
195menu "Texas Instruments thermal drivers" 216menu "Texas Instruments thermal drivers"
196source "drivers/thermal/ti-soc-thermal/Kconfig" 217source "drivers/thermal/ti-soc-thermal/Kconfig"
197endmenu 218endmenu
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 584b36319d51..54e4ec9eb5df 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -7,6 +7,7 @@ thermal_sys-y += thermal_core.o
7 7
8# interface to/from other layers providing sensors 8# interface to/from other layers providing sensors
9thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o 9thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
10thermal_sys-$(CONFIG_THERMAL_OF) += of-thermal.o
10 11
11# governors 12# governors
12thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o 13thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o
@@ -29,3 +30,4 @@ obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
29obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 30obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
30obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o 31obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
31obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ 32obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
33obj-$(CONFIG_ACPI_INT3403_THERMAL) += int3403_thermal.o
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 02a46f23d14c..4246262c4bd2 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -174,6 +174,13 @@ static int get_property(unsigned int cpu, unsigned long input,
174 max_level++; 174 max_level++;
175 } 175 }
176 176
177 /* No valid cpu frequency entry */
178 if (max_level == 0)
179 return -EINVAL;
180
181 /* max_level is an index, not a counter */
182 max_level--;
183
177 /* get max level */ 184 /* get max level */
178 if (property == GET_MAXL) { 185 if (property == GET_MAXL) {
179 *output = (unsigned int)max_level; 186 *output = (unsigned int)max_level;
@@ -181,7 +188,7 @@ static int get_property(unsigned int cpu, unsigned long input,
181 } 188 }
182 189
183 if (property == GET_FREQ) 190 if (property == GET_FREQ)
184 level = descend ? input : (max_level - input - 1); 191 level = descend ? input : (max_level - input);
185 192
186 for (i = 0, j = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { 193 for (i = 0, j = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
187 /* ignore invalid entry */ 194 /* ignore invalid entry */
@@ -197,7 +204,7 @@ static int get_property(unsigned int cpu, unsigned long input,
197 204
198 if (property == GET_LEVEL && (unsigned int)input == freq) { 205 if (property == GET_LEVEL && (unsigned int)input == freq) {
199 /* get level by frequency */ 206 /* get level by frequency */
200 *output = descend ? j : (max_level - j - 1); 207 *output = descend ? j : (max_level - j);
201 return 0; 208 return 0;
202 } 209 }
203 if (property == GET_FREQ && level == j) { 210 if (property == GET_FREQ && level == j) {
@@ -417,18 +424,21 @@ static struct notifier_block thermal_cpufreq_notifier_block = {
417}; 424};
418 425
419/** 426/**
420 * cpufreq_cooling_register - function to create cpufreq cooling device. 427 * __cpufreq_cooling_register - helper function to create cpufreq cooling device
428 * @np: a valid struct device_node to the cooling device device tree node
421 * @clip_cpus: cpumask of cpus where the frequency constraints will happen. 429 * @clip_cpus: cpumask of cpus where the frequency constraints will happen.
422 * 430 *
423 * This interface function registers the cpufreq cooling device with the name 431 * This interface function registers the cpufreq cooling device with the name
424 * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq 432 * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
425 * cooling devices. 433 * cooling devices. It also gives the opportunity to link the cooling device
434 * with a device tree node, in order to bind it via the thermal DT code.
426 * 435 *
427 * Return: a valid struct thermal_cooling_device pointer on success, 436 * Return: a valid struct thermal_cooling_device pointer on success,
428 * on failure, it returns a corresponding ERR_PTR(). 437 * on failure, it returns a corresponding ERR_PTR().
429 */ 438 */
430struct thermal_cooling_device * 439static struct thermal_cooling_device *
431cpufreq_cooling_register(const struct cpumask *clip_cpus) 440__cpufreq_cooling_register(struct device_node *np,
441 const struct cpumask *clip_cpus)
432{ 442{
433 struct thermal_cooling_device *cool_dev; 443 struct thermal_cooling_device *cool_dev;
434 struct cpufreq_cooling_device *cpufreq_dev = NULL; 444 struct cpufreq_cooling_device *cpufreq_dev = NULL;
@@ -467,8 +477,8 @@ cpufreq_cooling_register(const struct cpumask *clip_cpus)
467 snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d", 477 snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
468 cpufreq_dev->id); 478 cpufreq_dev->id);
469 479
470 cool_dev = thermal_cooling_device_register(dev_name, cpufreq_dev, 480 cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev,
471 &cpufreq_cooling_ops); 481 &cpufreq_cooling_ops);
472 if (IS_ERR(cool_dev)) { 482 if (IS_ERR(cool_dev)) {
473 release_idr(&cpufreq_idr, cpufreq_dev->id); 483 release_idr(&cpufreq_idr, cpufreq_dev->id);
474 kfree(cpufreq_dev); 484 kfree(cpufreq_dev);
@@ -488,9 +498,50 @@ cpufreq_cooling_register(const struct cpumask *clip_cpus)
488 498
489 return cool_dev; 499 return cool_dev;
490} 500}
501
502/**
503 * cpufreq_cooling_register - function to create cpufreq cooling device.
504 * @clip_cpus: cpumask of cpus where the frequency constraints will happen.
505 *
506 * This interface function registers the cpufreq cooling device with the name
507 * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
508 * cooling devices.
509 *
510 * Return: a valid struct thermal_cooling_device pointer on success,
511 * on failure, it returns a corresponding ERR_PTR().
512 */
513struct thermal_cooling_device *
514cpufreq_cooling_register(const struct cpumask *clip_cpus)
515{
516 return __cpufreq_cooling_register(NULL, clip_cpus);
517}
491EXPORT_SYMBOL_GPL(cpufreq_cooling_register); 518EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
492 519
493/** 520/**
521 * of_cpufreq_cooling_register - function to create cpufreq cooling device.
522 * @np: a valid struct device_node to the cooling device device tree node
523 * @clip_cpus: cpumask of cpus where the frequency constraints will happen.
524 *
525 * This interface function registers the cpufreq cooling device with the name
526 * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
527 * cooling devices. Using this API, the cpufreq cooling device will be
528 * linked to the device tree node provided.
529 *
530 * Return: a valid struct thermal_cooling_device pointer on success,
531 * on failure, it returns a corresponding ERR_PTR().
532 */
533struct thermal_cooling_device *
534of_cpufreq_cooling_register(struct device_node *np,
535 const struct cpumask *clip_cpus)
536{
537 if (!np)
538 return ERR_PTR(-EINVAL);
539
540 return __cpufreq_cooling_register(np, clip_cpus);
541}
542EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
543
544/**
494 * cpufreq_cooling_unregister - function to remove cpufreq cooling device. 545 * cpufreq_cooling_unregister - function to remove cpufreq cooling device.
495 * @cdev: thermal cooling device pointer. 546 * @cdev: thermal cooling device pointer.
496 * 547 *
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 1d6c801c1eb9..45af765a3198 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -7,6 +7,7 @@
7 * 7 *
8 */ 8 */
9 9
10#include <linux/clk.h>
10#include <linux/cpu_cooling.h> 11#include <linux/cpu_cooling.h>
11#include <linux/cpufreq.h> 12#include <linux/cpufreq.h>
12#include <linux/delay.h> 13#include <linux/delay.h>
@@ -73,6 +74,7 @@ struct imx_thermal_data {
73 unsigned long last_temp; 74 unsigned long last_temp;
74 bool irq_enabled; 75 bool irq_enabled;
75 int irq; 76 int irq;
77 struct clk *thermal_clk;
76}; 78};
77 79
78static void imx_set_alarm_temp(struct imx_thermal_data *data, 80static void imx_set_alarm_temp(struct imx_thermal_data *data,
@@ -284,7 +286,7 @@ static int imx_unbind(struct thermal_zone_device *tz,
284 return 0; 286 return 0;
285} 287}
286 288
287static const struct thermal_zone_device_ops imx_tz_ops = { 289static struct thermal_zone_device_ops imx_tz_ops = {
288 .bind = imx_bind, 290 .bind = imx_bind,
289 .unbind = imx_unbind, 291 .unbind = imx_unbind,
290 .get_temp = imx_get_temp, 292 .get_temp = imx_get_temp,
@@ -457,6 +459,22 @@ static int imx_thermal_probe(struct platform_device *pdev)
457 return ret; 459 return ret;
458 } 460 }
459 461
462 data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
463 if (IS_ERR(data->thermal_clk)) {
464 dev_warn(&pdev->dev, "failed to get thermal clk!\n");
465 } else {
466 /*
467 * Thermal sensor needs clk on to get correct value, normally
468 * we should enable its clk before taking measurement and disable
469 * clk after measurement is done, but if alarm function is enabled,
470 * hardware will auto measure the temperature periodically, so we
471 * need to keep the clk always on for alarm function.
472 */
473 ret = clk_prepare_enable(data->thermal_clk);
474 if (ret)
475 dev_warn(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
476 }
477
460 /* Enable measurements at ~ 10 Hz */ 478 /* Enable measurements at ~ 10 Hz */
461 regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ); 479 regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
462 measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */ 480 measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
@@ -478,6 +496,8 @@ static int imx_thermal_remove(struct platform_device *pdev)
478 496
479 /* Disable measurements */ 497 /* Disable measurements */
480 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); 498 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
499 if (!IS_ERR(data->thermal_clk))
500 clk_disable_unprepare(data->thermal_clk);
481 501
482 thermal_zone_device_unregister(data->tz); 502 thermal_zone_device_unregister(data->tz);
483 cpufreq_cooling_unregister(data->cdev); 503 cpufreq_cooling_unregister(data->cdev);
@@ -490,27 +510,30 @@ static int imx_thermal_suspend(struct device *dev)
490{ 510{
491 struct imx_thermal_data *data = dev_get_drvdata(dev); 511 struct imx_thermal_data *data = dev_get_drvdata(dev);
492 struct regmap *map = data->tempmon; 512 struct regmap *map = data->tempmon;
493 u32 val;
494 513
495 regmap_read(map, TEMPSENSE0, &val); 514 /*
496 if ((val & TEMPSENSE0_POWER_DOWN) == 0) { 515 * Need to disable thermal sensor, otherwise, when thermal core
497 /* 516 * try to get temperature before thermal sensor resume, a wrong
498 * If a measurement is taking place, wait for a long enough 517 * temperature will be read as the thermal sensor is powered
499 * time for it to finish, and then check again. If it still 518 * down.
500 * does not finish, something must go wrong. 519 */
501 */ 520 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
502 udelay(50); 521 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
503 regmap_read(map, TEMPSENSE0, &val); 522 data->mode = THERMAL_DEVICE_DISABLED;
504 if ((val & TEMPSENSE0_POWER_DOWN) == 0)
505 return -ETIMEDOUT;
506 }
507 523
508 return 0; 524 return 0;
509} 525}
510 526
511static int imx_thermal_resume(struct device *dev) 527static int imx_thermal_resume(struct device *dev)
512{ 528{
513 /* Nothing to do for now */ 529 struct imx_thermal_data *data = dev_get_drvdata(dev);
530 struct regmap *map = data->tempmon;
531
532 /* Enabled thermal sensor after resume */
533 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
534 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
535 data->mode = THERMAL_DEVICE_ENABLED;
536
514 return 0; 537 return 0;
515} 538}
516#endif 539#endif
@@ -522,6 +545,7 @@ static const struct of_device_id of_imx_thermal_match[] = {
522 { .compatible = "fsl,imx6q-tempmon", }, 545 { .compatible = "fsl,imx6q-tempmon", },
523 { /* end */ } 546 { /* end */ }
524}; 547};
548MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
525 549
526static struct platform_driver imx_thermal = { 550static struct platform_driver imx_thermal = {
527 .driver = { 551 .driver = {
diff --git a/drivers/thermal/int3403_thermal.c b/drivers/thermal/int3403_thermal.c
new file mode 100644
index 000000000000..1301681d9a77
--- /dev/null
+++ b/drivers/thermal/int3403_thermal.c
@@ -0,0 +1,237 @@
1/*
2 * ACPI INT3403 thermal driver
3 * Copyright (c) 2013, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/types.h>
19#include <linux/acpi.h>
20#include <linux/thermal.h>
21
22#define INT3403_TYPE_SENSOR 0x03
23#define INT3403_PERF_CHANGED_EVENT 0x80
24#define INT3403_THERMAL_EVENT 0x90
25
26#define DECI_KELVIN_TO_MILLI_CELSIUS(t, off) (((t) - (off)) * 100)
27#define KELVIN_OFFSET 2732
28#define MILLI_CELSIUS_TO_DECI_KELVIN(t, off) (((t) / 100) + (off))
29
30#define ACPI_INT3403_CLASS "int3403"
31#define ACPI_INT3403_FILE_STATE "state"
32
33struct int3403_sensor {
34 struct thermal_zone_device *tzone;
35 unsigned long *thresholds;
36};
37
38static int sys_get_curr_temp(struct thermal_zone_device *tzone,
39 unsigned long *temp)
40{
41 struct acpi_device *device = tzone->devdata;
42 unsigned long long tmp;
43 acpi_status status;
44
45 status = acpi_evaluate_integer(device->handle, "_TMP", NULL, &tmp);
46 if (ACPI_FAILURE(status))
47 return -EIO;
48
49 *temp = DECI_KELVIN_TO_MILLI_CELSIUS(tmp, KELVIN_OFFSET);
50
51 return 0;
52}
53
54static int sys_get_trip_hyst(struct thermal_zone_device *tzone,
55 int trip, unsigned long *temp)
56{
57 struct acpi_device *device = tzone->devdata;
58 unsigned long long hyst;
59 acpi_status status;
60
61 status = acpi_evaluate_integer(device->handle, "GTSH", NULL, &hyst);
62 if (ACPI_FAILURE(status))
63 return -EIO;
64
65 *temp = DECI_KELVIN_TO_MILLI_CELSIUS(hyst, KELVIN_OFFSET);
66
67 return 0;
68}
69
70static int sys_get_trip_temp(struct thermal_zone_device *tzone,
71 int trip, unsigned long *temp)
72{
73 struct acpi_device *device = tzone->devdata;
74 struct int3403_sensor *obj = acpi_driver_data(device);
75
76 /*
77 * get_trip_temp is a mandatory callback but
78 * PATx method doesn't return any value, so return
79 * cached value, which was last set from user space.
80 */
81 *temp = obj->thresholds[trip];
82
83 return 0;
84}
85
86static int sys_get_trip_type(struct thermal_zone_device *thermal,
87 int trip, enum thermal_trip_type *type)
88{
89 /* Mandatory callback, may not mean much here */
90 *type = THERMAL_TRIP_PASSIVE;
91
92 return 0;
93}
94
95int sys_set_trip_temp(struct thermal_zone_device *tzone, int trip,
96 unsigned long temp)
97{
98 struct acpi_device *device = tzone->devdata;
99 acpi_status status;
100 char name[10];
101 int ret = 0;
102 struct int3403_sensor *obj = acpi_driver_data(device);
103
104 snprintf(name, sizeof(name), "PAT%d", trip);
105 if (acpi_has_method(device->handle, name)) {
106 status = acpi_execute_simple_method(device->handle, name,
107 MILLI_CELSIUS_TO_DECI_KELVIN(temp,
108 KELVIN_OFFSET));
109 if (ACPI_FAILURE(status))
110 ret = -EIO;
111 else
112 obj->thresholds[trip] = temp;
113 } else {
114 ret = -EIO;
115 dev_err(&device->dev, "sys_set_trip_temp: method not found\n");
116 }
117
118 return ret;
119}
120
121static struct thermal_zone_device_ops tzone_ops = {
122 .get_temp = sys_get_curr_temp,
123 .get_trip_temp = sys_get_trip_temp,
124 .get_trip_type = sys_get_trip_type,
125 .set_trip_temp = sys_set_trip_temp,
126 .get_trip_hyst = sys_get_trip_hyst,
127};
128
129static void acpi_thermal_notify(struct acpi_device *device, u32 event)
130{
131 struct int3403_sensor *obj;
132
133 if (!device)
134 return;
135
136 obj = acpi_driver_data(device);
137 if (!obj)
138 return;
139
140 switch (event) {
141 case INT3403_PERF_CHANGED_EVENT:
142 break;
143 case INT3403_THERMAL_EVENT:
144 thermal_zone_device_update(obj->tzone);
145 break;
146 default:
147 dev_err(&device->dev, "Unsupported event [0x%x]\n", event);
148 break;
149 }
150}
151
152static int acpi_int3403_add(struct acpi_device *device)
153{
154 int result = 0;
155 unsigned long long ptyp;
156 acpi_status status;
157 struct int3403_sensor *obj;
158 unsigned long long trip_cnt;
159 int trip_mask = 0;
160
161 if (!device)
162 return -EINVAL;
163
164 status = acpi_evaluate_integer(device->handle, "PTYP", NULL, &ptyp);
165 if (ACPI_FAILURE(status))
166 return -EINVAL;
167
168 if (ptyp != INT3403_TYPE_SENSOR)
169 return -EINVAL;
170
171 obj = devm_kzalloc(&device->dev, sizeof(*obj), GFP_KERNEL);
172 if (!obj)
173 return -ENOMEM;
174
175 device->driver_data = obj;
176
177 status = acpi_evaluate_integer(device->handle, "PATC", NULL,
178 &trip_cnt);
179 if (ACPI_FAILURE(status))
180 trip_cnt = 0;
181
182 if (trip_cnt) {
183 /* We have to cache, thresholds can't be readback */
184 obj->thresholds = devm_kzalloc(&device->dev,
185 sizeof(*obj->thresholds) * trip_cnt,
186 GFP_KERNEL);
187 if (!obj->thresholds)
188 return -ENOMEM;
189 trip_mask = BIT(trip_cnt) - 1;
190 }
191 obj->tzone = thermal_zone_device_register(acpi_device_bid(device),
192 trip_cnt, trip_mask, device, &tzone_ops,
193 NULL, 0, 0);
194 if (IS_ERR(obj->tzone)) {
195 result = PTR_ERR(obj->tzone);
196 return result;
197 }
198
199 strcpy(acpi_device_name(device), "INT3403");
200 strcpy(acpi_device_class(device), ACPI_INT3403_CLASS);
201
202 return 0;
203}
204
205static int acpi_int3403_remove(struct acpi_device *device)
206{
207 struct int3403_sensor *obj;
208
209 obj = acpi_driver_data(device);
210 thermal_zone_device_unregister(obj->tzone);
211
212 return 0;
213}
214
215ACPI_MODULE_NAME("int3403");
216static const struct acpi_device_id int3403_device_ids[] = {
217 {"INT3403", 0},
218 {"", 0},
219};
220MODULE_DEVICE_TABLE(acpi, int3403_device_ids);
221
222static struct acpi_driver acpi_int3403_driver = {
223 .name = "INT3403",
224 .class = ACPI_INT3403_CLASS,
225 .ids = int3403_device_ids,
226 .ops = {
227 .add = acpi_int3403_add,
228 .remove = acpi_int3403_remove,
229 .notify = acpi_thermal_notify,
230 },
231};
232
233module_acpi_driver(acpi_int3403_driver);
234
235MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
236MODULE_LICENSE("GPL v2");
237MODULE_DESCRIPTION("ACPI INT3403 thermal driver");
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c
index d833c8f5b465..a084325f1386 100644
--- a/drivers/thermal/intel_powerclamp.c
+++ b/drivers/thermal/intel_powerclamp.c
@@ -206,6 +206,15 @@ static void find_target_mwait(void)
206 206
207} 207}
208 208
209static bool has_pkg_state_counter(void)
210{
211 u64 tmp;
212 return !rdmsrl_safe(MSR_PKG_C2_RESIDENCY, &tmp) ||
213 !rdmsrl_safe(MSR_PKG_C3_RESIDENCY, &tmp) ||
214 !rdmsrl_safe(MSR_PKG_C6_RESIDENCY, &tmp) ||
215 !rdmsrl_safe(MSR_PKG_C7_RESIDENCY, &tmp);
216}
217
209static u64 pkg_state_counter(void) 218static u64 pkg_state_counter(void)
210{ 219{
211 u64 val; 220 u64 val;
@@ -498,7 +507,7 @@ static int start_power_clamp(void)
498 struct task_struct *thread; 507 struct task_struct *thread;
499 508
500 /* check if pkg cstate counter is completely 0, abort in this case */ 509 /* check if pkg cstate counter is completely 0, abort in this case */
501 if (!pkg_state_counter()) { 510 if (!has_pkg_state_counter()) {
502 pr_err("pkg cstate counter not functional, abort\n"); 511 pr_err("pkg cstate counter not functional, abort\n");
503 return -EINVAL; 512 return -EINVAL;
504 } 513 }
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
new file mode 100644
index 000000000000..04b1be7fa018
--- /dev/null
+++ b/drivers/thermal/of-thermal.c
@@ -0,0 +1,849 @@
1/*
2 * of-thermal.c - Generic Thermal Management device tree support.
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
6 *
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2 of the License.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25#include <linux/thermal.h>
26#include <linux/slab.h>
27#include <linux/types.h>
28#include <linux/of_device.h>
29#include <linux/of_platform.h>
30#include <linux/err.h>
31#include <linux/export.h>
32#include <linux/string.h>
33
34#include "thermal_core.h"
35
36/*** Private data structures to represent thermal device tree data ***/
37
38/**
39 * struct __thermal_trip - representation of a point in temperature domain
40 * @np: pointer to struct device_node that this trip point was created from
41 * @temperature: temperature value in miliCelsius
42 * @hysteresis: relative hysteresis in miliCelsius
43 * @type: trip point type
44 */
45
46struct __thermal_trip {
47 struct device_node *np;
48 unsigned long int temperature;
49 unsigned long int hysteresis;
50 enum thermal_trip_type type;
51};
52
53/**
54 * struct __thermal_bind_param - a match between trip and cooling device
55 * @cooling_device: a pointer to identify the referred cooling device
56 * @trip_id: the trip point index
57 * @usage: the percentage (from 0 to 100) of cooling contribution
58 * @min: minimum cooling state used at this trip point
59 * @max: maximum cooling state used at this trip point
60 */
61
62struct __thermal_bind_params {
63 struct device_node *cooling_device;
64 unsigned int trip_id;
65 unsigned int usage;
66 unsigned long min;
67 unsigned long max;
68};
69
70/**
71 * struct __thermal_zone - internal representation of a thermal zone
72 * @mode: current thermal zone device mode (enabled/disabled)
73 * @passive_delay: polling interval while passive cooling is activated
74 * @polling_delay: zone polling interval
75 * @ntrips: number of trip points
76 * @trips: an array of trip points (0..ntrips - 1)
77 * @num_tbps: number of thermal bind params
78 * @tbps: an array of thermal bind params (0..num_tbps - 1)
79 * @sensor_data: sensor private data used while reading temperature and trend
80 * @get_temp: sensor callback to read temperature
81 * @get_trend: sensor callback to read temperature trend
82 */
83
84struct __thermal_zone {
85 enum thermal_device_mode mode;
86 int passive_delay;
87 int polling_delay;
88
89 /* trip data */
90 int ntrips;
91 struct __thermal_trip *trips;
92
93 /* cooling binding data */
94 int num_tbps;
95 struct __thermal_bind_params *tbps;
96
97 /* sensor interface */
98 void *sensor_data;
99 int (*get_temp)(void *, long *);
100 int (*get_trend)(void *, long *);
101};
102
103/*** DT thermal zone device callbacks ***/
104
105static int of_thermal_get_temp(struct thermal_zone_device *tz,
106 unsigned long *temp)
107{
108 struct __thermal_zone *data = tz->devdata;
109
110 if (!data->get_temp)
111 return -EINVAL;
112
113 return data->get_temp(data->sensor_data, temp);
114}
115
116static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
117 enum thermal_trend *trend)
118{
119 struct __thermal_zone *data = tz->devdata;
120 long dev_trend;
121 int r;
122
123 if (!data->get_trend)
124 return -EINVAL;
125
126 r = data->get_trend(data->sensor_data, &dev_trend);
127 if (r)
128 return r;
129
130 /* TODO: These intervals might have some thresholds, but in core code */
131 if (dev_trend > 0)
132 *trend = THERMAL_TREND_RAISING;
133 else if (dev_trend < 0)
134 *trend = THERMAL_TREND_DROPPING;
135 else
136 *trend = THERMAL_TREND_STABLE;
137
138 return 0;
139}
140
141static int of_thermal_bind(struct thermal_zone_device *thermal,
142 struct thermal_cooling_device *cdev)
143{
144 struct __thermal_zone *data = thermal->devdata;
145 int i;
146
147 if (!data || IS_ERR(data))
148 return -ENODEV;
149
150 /* find where to bind */
151 for (i = 0; i < data->num_tbps; i++) {
152 struct __thermal_bind_params *tbp = data->tbps + i;
153
154 if (tbp->cooling_device == cdev->np) {
155 int ret;
156
157 ret = thermal_zone_bind_cooling_device(thermal,
158 tbp->trip_id, cdev,
159 tbp->min,
160 tbp->max);
161 if (ret)
162 return ret;
163 }
164 }
165
166 return 0;
167}
168
169static int of_thermal_unbind(struct thermal_zone_device *thermal,
170 struct thermal_cooling_device *cdev)
171{
172 struct __thermal_zone *data = thermal->devdata;
173 int i;
174
175 if (!data || IS_ERR(data))
176 return -ENODEV;
177
178 /* find where to unbind */
179 for (i = 0; i < data->num_tbps; i++) {
180 struct __thermal_bind_params *tbp = data->tbps + i;
181
182 if (tbp->cooling_device == cdev->np) {
183 int ret;
184
185 ret = thermal_zone_unbind_cooling_device(thermal,
186 tbp->trip_id, cdev);
187 if (ret)
188 return ret;
189 }
190 }
191
192 return 0;
193}
194
195static int of_thermal_get_mode(struct thermal_zone_device *tz,
196 enum thermal_device_mode *mode)
197{
198 struct __thermal_zone *data = tz->devdata;
199
200 *mode = data->mode;
201
202 return 0;
203}
204
205static int of_thermal_set_mode(struct thermal_zone_device *tz,
206 enum thermal_device_mode mode)
207{
208 struct __thermal_zone *data = tz->devdata;
209
210 mutex_lock(&tz->lock);
211
212 if (mode == THERMAL_DEVICE_ENABLED)
213 tz->polling_delay = data->polling_delay;
214 else
215 tz->polling_delay = 0;
216
217 mutex_unlock(&tz->lock);
218
219 data->mode = mode;
220 thermal_zone_device_update(tz);
221
222 return 0;
223}
224
225static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
226 enum thermal_trip_type *type)
227{
228 struct __thermal_zone *data = tz->devdata;
229
230 if (trip >= data->ntrips || trip < 0)
231 return -EDOM;
232
233 *type = data->trips[trip].type;
234
235 return 0;
236}
237
238static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
239 unsigned long *temp)
240{
241 struct __thermal_zone *data = tz->devdata;
242
243 if (trip >= data->ntrips || trip < 0)
244 return -EDOM;
245
246 *temp = data->trips[trip].temperature;
247
248 return 0;
249}
250
251static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
252 unsigned long temp)
253{
254 struct __thermal_zone *data = tz->devdata;
255
256 if (trip >= data->ntrips || trip < 0)
257 return -EDOM;
258
259 /* thermal framework should take care of data->mask & (1 << trip) */
260 data->trips[trip].temperature = temp;
261
262 return 0;
263}
264
265static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
266 unsigned long *hyst)
267{
268 struct __thermal_zone *data = tz->devdata;
269
270 if (trip >= data->ntrips || trip < 0)
271 return -EDOM;
272
273 *hyst = data->trips[trip].hysteresis;
274
275 return 0;
276}
277
278static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
279 unsigned long hyst)
280{
281 struct __thermal_zone *data = tz->devdata;
282
283 if (trip >= data->ntrips || trip < 0)
284 return -EDOM;
285
286 /* thermal framework should take care of data->mask & (1 << trip) */
287 data->trips[trip].hysteresis = hyst;
288
289 return 0;
290}
291
292static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
293 unsigned long *temp)
294{
295 struct __thermal_zone *data = tz->devdata;
296 int i;
297
298 for (i = 0; i < data->ntrips; i++)
299 if (data->trips[i].type == THERMAL_TRIP_CRITICAL) {
300 *temp = data->trips[i].temperature;
301 return 0;
302 }
303
304 return -EINVAL;
305}
306
307static struct thermal_zone_device_ops of_thermal_ops = {
308 .get_mode = of_thermal_get_mode,
309 .set_mode = of_thermal_set_mode,
310
311 .get_trip_type = of_thermal_get_trip_type,
312 .get_trip_temp = of_thermal_get_trip_temp,
313 .set_trip_temp = of_thermal_set_trip_temp,
314 .get_trip_hyst = of_thermal_get_trip_hyst,
315 .set_trip_hyst = of_thermal_set_trip_hyst,
316 .get_crit_temp = of_thermal_get_crit_temp,
317
318 .bind = of_thermal_bind,
319 .unbind = of_thermal_unbind,
320};
321
322/*** sensor API ***/
323
324static struct thermal_zone_device *
325thermal_zone_of_add_sensor(struct device_node *zone,
326 struct device_node *sensor, void *data,
327 int (*get_temp)(void *, long *),
328 int (*get_trend)(void *, long *))
329{
330 struct thermal_zone_device *tzd;
331 struct __thermal_zone *tz;
332
333 tzd = thermal_zone_get_zone_by_name(zone->name);
334 if (IS_ERR(tzd))
335 return ERR_PTR(-EPROBE_DEFER);
336
337 tz = tzd->devdata;
338
339 mutex_lock(&tzd->lock);
340 tz->get_temp = get_temp;
341 tz->get_trend = get_trend;
342 tz->sensor_data = data;
343
344 tzd->ops->get_temp = of_thermal_get_temp;
345 tzd->ops->get_trend = of_thermal_get_trend;
346 mutex_unlock(&tzd->lock);
347
348 return tzd;
349}
350
351/**
352 * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone
353 * @dev: a valid struct device pointer of a sensor device. Must contain
354 * a valid .of_node, for the sensor node.
355 * @sensor_id: a sensor identifier, in case the sensor IP has more
356 * than one sensors
357 * @data: a private pointer (owned by the caller) that will be passed
358 * back, when a temperature reading is needed.
359 * @get_temp: a pointer to a function that reads the sensor temperature.
360 * @get_trend: a pointer to a function that reads the sensor temperature trend.
361 *
362 * This function will search the list of thermal zones described in device
363 * tree and look for the zone that refer to the sensor device pointed by
364 * @dev->of_node as temperature providers. For the zone pointing to the
365 * sensor node, the sensor will be added to the DT thermal zone device.
366 *
367 * The thermal zone temperature is provided by the @get_temp function
368 * pointer. When called, it will have the private pointer @data back.
369 *
370 * The thermal zone temperature trend is provided by the @get_trend function
371 * pointer. When called, it will have the private pointer @data back.
372 *
373 * TODO:
374 * 01 - This function must enqueue the new sensor instead of using
375 * it as the only source of temperature values.
376 *
377 * 02 - There must be a way to match the sensor with all thermal zones
378 * that refer to it.
379 *
380 * Return: On success returns a valid struct thermal_zone_device,
381 * otherwise, it returns a corresponding ERR_PTR(). Caller must
382 * check the return value with help of IS_ERR() helper.
383 */
384struct thermal_zone_device *
385thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
386 void *data, int (*get_temp)(void *, long *),
387 int (*get_trend)(void *, long *))
388{
389 struct device_node *np, *child, *sensor_np;
390
391 np = of_find_node_by_name(NULL, "thermal-zones");
392 if (!np)
393 return ERR_PTR(-ENODEV);
394
395 if (!dev || !dev->of_node)
396 return ERR_PTR(-EINVAL);
397
398 sensor_np = dev->of_node;
399
400 for_each_child_of_node(np, child) {
401 struct of_phandle_args sensor_specs;
402 int ret, id;
403
404 /* For now, thermal framework supports only 1 sensor per zone */
405 ret = of_parse_phandle_with_args(child, "thermal-sensors",
406 "#thermal-sensor-cells",
407 0, &sensor_specs);
408 if (ret)
409 continue;
410
411 if (sensor_specs.args_count >= 1) {
412 id = sensor_specs.args[0];
413 WARN(sensor_specs.args_count > 1,
414 "%s: too many cells in sensor specifier %d\n",
415 sensor_specs.np->name, sensor_specs.args_count);
416 } else {
417 id = 0;
418 }
419
420 if (sensor_specs.np == sensor_np && id == sensor_id) {
421 of_node_put(np);
422 return thermal_zone_of_add_sensor(child, sensor_np,
423 data,
424 get_temp,
425 get_trend);
426 }
427 }
428 of_node_put(np);
429
430 return ERR_PTR(-ENODEV);
431}
432EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register);
433
434/**
435 * thermal_zone_of_sensor_unregister - unregisters a sensor from a DT thermal zone
436 * @dev: a valid struct device pointer of a sensor device. Must contain
437 * a valid .of_node, for the sensor node.
438 * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
439 *
440 * This function removes the sensor callbacks and private data from the
441 * thermal zone device registered with thermal_zone_of_sensor_register()
442 * API. It will also silent the zone by remove the .get_temp() and .get_trend()
443 * thermal zone device callbacks.
444 *
445 * TODO: When the support to several sensors per zone is added, this
446 * function must search the sensor list based on @dev parameter.
447 *
448 */
449void thermal_zone_of_sensor_unregister(struct device *dev,
450 struct thermal_zone_device *tzd)
451{
452 struct __thermal_zone *tz;
453
454 if (!dev || !tzd || !tzd->devdata)
455 return;
456
457 tz = tzd->devdata;
458
459 /* no __thermal_zone, nothing to be done */
460 if (!tz)
461 return;
462
463 mutex_lock(&tzd->lock);
464 tzd->ops->get_temp = NULL;
465 tzd->ops->get_trend = NULL;
466
467 tz->get_temp = NULL;
468 tz->get_trend = NULL;
469 tz->sensor_data = NULL;
470 mutex_unlock(&tzd->lock);
471}
472EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
473
474/*** functions parsing device tree nodes ***/
475
476/**
477 * thermal_of_populate_bind_params - parse and fill cooling map data
478 * @np: DT node containing a cooling-map node
479 * @__tbp: data structure to be filled with cooling map info
480 * @trips: array of thermal zone trip points
481 * @ntrips: number of trip points inside trips.
482 *
483 * This function parses a cooling-map type of node represented by
484 * @np parameter and fills the read data into @__tbp data structure.
485 * It needs the already parsed array of trip points of the thermal zone
486 * in consideration.
487 *
488 * Return: 0 on success, proper error code otherwise
489 */
490static int thermal_of_populate_bind_params(struct device_node *np,
491 struct __thermal_bind_params *__tbp,
492 struct __thermal_trip *trips,
493 int ntrips)
494{
495 struct of_phandle_args cooling_spec;
496 struct device_node *trip;
497 int ret, i;
498 u32 prop;
499
500 /* Default weight. Usage is optional */
501 __tbp->usage = 0;
502 ret = of_property_read_u32(np, "contribution", &prop);
503 if (ret == 0)
504 __tbp->usage = prop;
505
506 trip = of_parse_phandle(np, "trip", 0);
507 if (!trip) {
508 pr_err("missing trip property\n");
509 return -ENODEV;
510 }
511
512 /* match using device_node */
513 for (i = 0; i < ntrips; i++)
514 if (trip == trips[i].np) {
515 __tbp->trip_id = i;
516 break;
517 }
518
519 if (i == ntrips) {
520 ret = -ENODEV;
521 goto end;
522 }
523
524 ret = of_parse_phandle_with_args(np, "cooling-device", "#cooling-cells",
525 0, &cooling_spec);
526 if (ret < 0) {
527 pr_err("missing cooling_device property\n");
528 goto end;
529 }
530 __tbp->cooling_device = cooling_spec.np;
531 if (cooling_spec.args_count >= 2) { /* at least min and max */
532 __tbp->min = cooling_spec.args[0];
533 __tbp->max = cooling_spec.args[1];
534 } else {
535 pr_err("wrong reference to cooling device, missing limits\n");
536 }
537
538end:
539 of_node_put(trip);
540
541 return ret;
542}
543
544/**
545 * It maps 'enum thermal_trip_type' found in include/linux/thermal.h
546 * into the device tree binding of 'trip', property type.
547 */
548static const char * const trip_types[] = {
549 [THERMAL_TRIP_ACTIVE] = "active",
550 [THERMAL_TRIP_PASSIVE] = "passive",
551 [THERMAL_TRIP_HOT] = "hot",
552 [THERMAL_TRIP_CRITICAL] = "critical",
553};
554
555/**
556 * thermal_of_get_trip_type - Get phy mode for given device_node
557 * @np: Pointer to the given device_node
558 * @type: Pointer to resulting trip type
559 *
560 * The function gets trip type string from property 'type',
561 * and store its index in trip_types table in @type,
562 *
563 * Return: 0 on success, or errno in error case.
564 */
565static int thermal_of_get_trip_type(struct device_node *np,
566 enum thermal_trip_type *type)
567{
568 const char *t;
569 int err, i;
570
571 err = of_property_read_string(np, "type", &t);
572 if (err < 0)
573 return err;
574
575 for (i = 0; i < ARRAY_SIZE(trip_types); i++)
576 if (!strcasecmp(t, trip_types[i])) {
577 *type = i;
578 return 0;
579 }
580
581 return -ENODEV;
582}
583
584/**
585 * thermal_of_populate_trip - parse and fill one trip point data
586 * @np: DT node containing a trip point node
587 * @trip: trip point data structure to be filled up
588 *
589 * This function parses a trip point type of node represented by
590 * @np parameter and fills the read data into @trip data structure.
591 *
592 * Return: 0 on success, proper error code otherwise
593 */
594static int thermal_of_populate_trip(struct device_node *np,
595 struct __thermal_trip *trip)
596{
597 int prop;
598 int ret;
599
600 ret = of_property_read_u32(np, "temperature", &prop);
601 if (ret < 0) {
602 pr_err("missing temperature property\n");
603 return ret;
604 }
605 trip->temperature = prop;
606
607 ret = of_property_read_u32(np, "hysteresis", &prop);
608 if (ret < 0) {
609 pr_err("missing hysteresis property\n");
610 return ret;
611 }
612 trip->hysteresis = prop;
613
614 ret = thermal_of_get_trip_type(np, &trip->type);
615 if (ret < 0) {
616 pr_err("wrong trip type property\n");
617 return ret;
618 }
619
620 /* Required for cooling map matching */
621 trip->np = np;
622
623 return 0;
624}
625
626/**
627 * thermal_of_build_thermal_zone - parse and fill one thermal zone data
628 * @np: DT node containing a thermal zone node
629 *
630 * This function parses a thermal zone type of node represented by
631 * @np parameter and fills the read data into a __thermal_zone data structure
632 * and return this pointer.
633 *
634 * TODO: Missing properties to parse: thermal-sensor-names and coefficients
635 *
636 * Return: On success returns a valid struct __thermal_zone,
637 * otherwise, it returns a corresponding ERR_PTR(). Caller must
638 * check the return value with help of IS_ERR() helper.
639 */
640static struct __thermal_zone *
641thermal_of_build_thermal_zone(struct device_node *np)
642{
643 struct device_node *child = NULL, *gchild;
644 struct __thermal_zone *tz;
645 int ret, i;
646 u32 prop;
647
648 if (!np) {
649 pr_err("no thermal zone np\n");
650 return ERR_PTR(-EINVAL);
651 }
652
653 tz = kzalloc(sizeof(*tz), GFP_KERNEL);
654 if (!tz)
655 return ERR_PTR(-ENOMEM);
656
657 ret = of_property_read_u32(np, "polling-delay-passive", &prop);
658 if (ret < 0) {
659 pr_err("missing polling-delay-passive property\n");
660 goto free_tz;
661 }
662 tz->passive_delay = prop;
663
664 ret = of_property_read_u32(np, "polling-delay", &prop);
665 if (ret < 0) {
666 pr_err("missing polling-delay property\n");
667 goto free_tz;
668 }
669 tz->polling_delay = prop;
670
671 /* trips */
672 child = of_get_child_by_name(np, "trips");
673
674 /* No trips provided */
675 if (!child)
676 goto finish;
677
678 tz->ntrips = of_get_child_count(child);
679 if (tz->ntrips == 0) /* must have at least one child */
680 goto finish;
681
682 tz->trips = kzalloc(tz->ntrips * sizeof(*tz->trips), GFP_KERNEL);
683 if (!tz->trips) {
684 ret = -ENOMEM;
685 goto free_tz;
686 }
687
688 i = 0;
689 for_each_child_of_node(child, gchild) {
690 ret = thermal_of_populate_trip(gchild, &tz->trips[i++]);
691 if (ret)
692 goto free_trips;
693 }
694
695 of_node_put(child);
696
697 /* cooling-maps */
698 child = of_get_child_by_name(np, "cooling-maps");
699
700 /* cooling-maps not provided */
701 if (!child)
702 goto finish;
703
704 tz->num_tbps = of_get_child_count(child);
705 if (tz->num_tbps == 0)
706 goto finish;
707
708 tz->tbps = kzalloc(tz->num_tbps * sizeof(*tz->tbps), GFP_KERNEL);
709 if (!tz->tbps) {
710 ret = -ENOMEM;
711 goto free_trips;
712 }
713
714 i = 0;
715 for_each_child_of_node(child, gchild)
716 ret = thermal_of_populate_bind_params(gchild, &tz->tbps[i++],
717 tz->trips, tz->ntrips);
718 if (ret)
719 goto free_tbps;
720
721finish:
722 of_node_put(child);
723 tz->mode = THERMAL_DEVICE_DISABLED;
724
725 return tz;
726
727free_tbps:
728 kfree(tz->tbps);
729free_trips:
730 kfree(tz->trips);
731free_tz:
732 kfree(tz);
733 of_node_put(child);
734
735 return ERR_PTR(ret);
736}
737
738static inline void of_thermal_free_zone(struct __thermal_zone *tz)
739{
740 kfree(tz->tbps);
741 kfree(tz->trips);
742 kfree(tz);
743}
744
745/**
746 * of_parse_thermal_zones - parse device tree thermal data
747 *
748 * Initialization function that can be called by machine initialization
749 * code to parse thermal data and populate the thermal framework
750 * with hardware thermal zones info. This function only parses thermal zones.
751 * Cooling devices and sensor devices nodes are supposed to be parsed
752 * by their respective drivers.
753 *
754 * Return: 0 on success, proper error code otherwise
755 *
756 */
757int __init of_parse_thermal_zones(void)
758{
759 struct device_node *np, *child;
760 struct __thermal_zone *tz;
761 struct thermal_zone_device_ops *ops;
762
763 np = of_find_node_by_name(NULL, "thermal-zones");
764 if (!np) {
765 pr_debug("unable to find thermal zones\n");
766 return 0; /* Run successfully on systems without thermal DT */
767 }
768
769 for_each_child_of_node(np, child) {
770 struct thermal_zone_device *zone;
771 struct thermal_zone_params *tzp;
772
773 tz = thermal_of_build_thermal_zone(child);
774 if (IS_ERR(tz)) {
775 pr_err("failed to build thermal zone %s: %ld\n",
776 child->name,
777 PTR_ERR(tz));
778 continue;
779 }
780
781 ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
782 if (!ops)
783 goto exit_free;
784
785 tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
786 if (!tzp) {
787 kfree(ops);
788 goto exit_free;
789 }
790
791 /* No hwmon because there might be hwmon drivers registering */
792 tzp->no_hwmon = true;
793
794 zone = thermal_zone_device_register(child->name, tz->ntrips,
795 0, tz,
796 ops, tzp,
797 tz->passive_delay,
798 tz->polling_delay);
799 if (IS_ERR(zone)) {
800 pr_err("Failed to build %s zone %ld\n", child->name,
801 PTR_ERR(zone));
802 kfree(tzp);
803 kfree(ops);
804 of_thermal_free_zone(tz);
805 /* attempting to build remaining zones still */
806 }
807 }
808
809 return 0;
810
811exit_free:
812 of_thermal_free_zone(tz);
813
814 /* no memory available, so free what we have built */
815 of_thermal_destroy_zones();
816
817 return -ENOMEM;
818}
819
820/**
821 * of_thermal_destroy_zones - remove all zones parsed and allocated resources
822 *
823 * Finds all zones parsed and added to the thermal framework and remove them
824 * from the system, together with their resources.
825 *
826 */
827void of_thermal_destroy_zones(void)
828{
829 struct device_node *np, *child;
830
831 np = of_find_node_by_name(NULL, "thermal-zones");
832 if (!np) {
833 pr_err("unable to find thermal zones\n");
834 return;
835 }
836
837 for_each_child_of_node(np, child) {
838 struct thermal_zone_device *zone;
839
840 zone = thermal_zone_get_zone_by_name(child->name);
841 if (IS_ERR(zone))
842 continue;
843
844 thermal_zone_device_unregister(zone);
845 kfree(zone->tzp);
846 kfree(zone->ops);
847 of_thermal_free_zone(zone->devdata);
848 }
849}
diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
index c2301da08ac7..3f5ad25ddca8 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -280,7 +280,7 @@ static int exynos_get_trend(struct thermal_zone_device *thermal,
280 return 0; 280 return 0;
281} 281}
282/* Operation callback functions for thermal zone */ 282/* Operation callback functions for thermal zone */
283static struct thermal_zone_device_ops const exynos_dev_ops = { 283static struct thermal_zone_device_ops exynos_dev_ops = {
284 .bind = exynos_bind, 284 .bind = exynos_bind,
285 .unbind = exynos_unbind, 285 .unbind = exynos_unbind,
286 .get_temp = exynos_get_temp, 286 .get_temp = exynos_get_temp,
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 32f38b90c4f6..0d96a510389f 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -205,6 +205,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
205skip_calib_data: 205skip_calib_data:
206 if (pdata->max_trigger_level > MAX_THRESHOLD_LEVS) { 206 if (pdata->max_trigger_level > MAX_THRESHOLD_LEVS) {
207 dev_err(&pdev->dev, "Invalid max trigger level\n"); 207 dev_err(&pdev->dev, "Invalid max trigger level\n");
208 ret = -EINVAL;
208 goto out; 209 goto out;
209 } 210 }
210 211
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
index d89e781b0a18..f251521baaa2 100644
--- a/drivers/thermal/step_wise.c
+++ b/drivers/thermal/step_wise.c
@@ -60,6 +60,7 @@ static unsigned long get_target_state(struct thermal_instance *instance,
60 */ 60 */
61 cdev->ops->get_cur_state(cdev, &cur_state); 61 cdev->ops->get_cur_state(cdev, &cur_state);
62 next_target = instance->target; 62 next_target = instance->target;
63 dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
63 64
64 switch (trend) { 65 switch (trend) {
65 case THERMAL_TREND_RAISING: 66 case THERMAL_TREND_RAISING:
@@ -131,6 +132,9 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
131 if (tz->temperature >= trip_temp) 132 if (tz->temperature >= trip_temp)
132 throttle = true; 133 throttle = true;
133 134
135 dev_dbg(&tz->device, "Trip%d[type=%d,temp=%ld]:trend=%d,throttle=%d\n",
136 trip, trip_type, trip_temp, trend, throttle);
137
134 mutex_lock(&tz->lock); 138 mutex_lock(&tz->lock);
135 139
136 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 140 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
@@ -139,6 +143,8 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
139 143
140 old_target = instance->target; 144 old_target = instance->target;
141 instance->target = get_target_state(instance, trend, throttle); 145 instance->target = get_target_state(instance, trend, throttle);
146 dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
147 old_target, (int)instance->target);
142 148
143 if (old_target == instance->target) 149 if (old_target == instance->target)
144 continue; 150 continue;
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index f1d511a9475b..338a88bf6662 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -34,6 +34,7 @@
34#include <linux/thermal.h> 34#include <linux/thermal.h>
35#include <linux/reboot.h> 35#include <linux/reboot.h>
36#include <linux/string.h> 36#include <linux/string.h>
37#include <linux/of.h>
37#include <net/netlink.h> 38#include <net/netlink.h>
38#include <net/genetlink.h> 39#include <net/genetlink.h>
39 40
@@ -403,7 +404,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
403 enum thermal_trip_type type; 404 enum thermal_trip_type type;
404#endif 405#endif
405 406
406 if (!tz || IS_ERR(tz)) 407 if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
407 goto exit; 408 goto exit;
408 409
409 mutex_lock(&tz->lock); 410 mutex_lock(&tz->lock);
@@ -450,12 +451,18 @@ static void update_temperature(struct thermal_zone_device *tz)
450 tz->last_temperature = tz->temperature; 451 tz->last_temperature = tz->temperature;
451 tz->temperature = temp; 452 tz->temperature = temp;
452 mutex_unlock(&tz->lock); 453 mutex_unlock(&tz->lock);
454
455 dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
456 tz->last_temperature, tz->temperature);
453} 457}
454 458
455void thermal_zone_device_update(struct thermal_zone_device *tz) 459void thermal_zone_device_update(struct thermal_zone_device *tz)
456{ 460{
457 int count; 461 int count;
458 462
463 if (!tz->ops->get_temp)
464 return;
465
459 update_temperature(tz); 466 update_temperature(tz);
460 467
461 for (count = 0; count < tz->trips; count++) 468 for (count = 0; count < tz->trips; count++)
@@ -774,6 +781,9 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
774 ret = tz->ops->set_emul_temp(tz, temperature); 781 ret = tz->ops->set_emul_temp(tz, temperature);
775 } 782 }
776 783
784 if (!ret)
785 thermal_zone_device_update(tz);
786
777 return ret ? ret : count; 787 return ret ? ret : count;
778} 788}
779static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); 789static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
@@ -1052,7 +1062,8 @@ static struct class thermal_class = {
1052}; 1062};
1053 1063
1054/** 1064/**
1055 * thermal_cooling_device_register() - register a new thermal cooling device 1065 * __thermal_cooling_device_register() - register a new thermal cooling device
1066 * @np: a pointer to a device tree node.
1056 * @type: the thermal cooling device type. 1067 * @type: the thermal cooling device type.
1057 * @devdata: device private data. 1068 * @devdata: device private data.
1058 * @ops: standard thermal cooling devices callbacks. 1069 * @ops: standard thermal cooling devices callbacks.
@@ -1060,13 +1071,16 @@ static struct class thermal_class = {
1060 * This interface function adds a new thermal cooling device (fan/processor/...) 1071 * This interface function adds a new thermal cooling device (fan/processor/...)
1061 * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself 1072 * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself
1062 * to all the thermal zone devices registered at the same time. 1073 * to all the thermal zone devices registered at the same time.
1074 * It also gives the opportunity to link the cooling device to a device tree
1075 * node, so that it can be bound to a thermal zone created out of device tree.
1063 * 1076 *
1064 * Return: a pointer to the created struct thermal_cooling_device or an 1077 * Return: a pointer to the created struct thermal_cooling_device or an
1065 * ERR_PTR. Caller must check return value with IS_ERR*() helpers. 1078 * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
1066 */ 1079 */
1067struct thermal_cooling_device * 1080static struct thermal_cooling_device *
1068thermal_cooling_device_register(char *type, void *devdata, 1081__thermal_cooling_device_register(struct device_node *np,
1069 const struct thermal_cooling_device_ops *ops) 1082 char *type, void *devdata,
1083 const struct thermal_cooling_device_ops *ops)
1070{ 1084{
1071 struct thermal_cooling_device *cdev; 1085 struct thermal_cooling_device *cdev;
1072 int result; 1086 int result;
@@ -1091,6 +1105,7 @@ thermal_cooling_device_register(char *type, void *devdata,
1091 strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); 1105 strlcpy(cdev->type, type ? : "", sizeof(cdev->type));
1092 mutex_init(&cdev->lock); 1106 mutex_init(&cdev->lock);
1093 INIT_LIST_HEAD(&cdev->thermal_instances); 1107 INIT_LIST_HEAD(&cdev->thermal_instances);
1108 cdev->np = np;
1094 cdev->ops = ops; 1109 cdev->ops = ops;
1095 cdev->updated = true; 1110 cdev->updated = true;
1096 cdev->device.class = &thermal_class; 1111 cdev->device.class = &thermal_class;
@@ -1133,9 +1148,53 @@ unregister:
1133 device_unregister(&cdev->device); 1148 device_unregister(&cdev->device);
1134 return ERR_PTR(result); 1149 return ERR_PTR(result);
1135} 1150}
1151
1152/**
1153 * thermal_cooling_device_register() - register a new thermal cooling device
1154 * @type: the thermal cooling device type.
1155 * @devdata: device private data.
1156 * @ops: standard thermal cooling devices callbacks.
1157 *
1158 * This interface function adds a new thermal cooling device (fan/processor/...)
1159 * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself
1160 * to all the thermal zone devices registered at the same time.
1161 *
1162 * Return: a pointer to the created struct thermal_cooling_device or an
1163 * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
1164 */
1165struct thermal_cooling_device *
1166thermal_cooling_device_register(char *type, void *devdata,
1167 const struct thermal_cooling_device_ops *ops)
1168{
1169 return __thermal_cooling_device_register(NULL, type, devdata, ops);
1170}
1136EXPORT_SYMBOL_GPL(thermal_cooling_device_register); 1171EXPORT_SYMBOL_GPL(thermal_cooling_device_register);
1137 1172
1138/** 1173/**
1174 * thermal_of_cooling_device_register() - register an OF thermal cooling device
1175 * @np: a pointer to a device tree node.
1176 * @type: the thermal cooling device type.
1177 * @devdata: device private data.
1178 * @ops: standard thermal cooling devices callbacks.
1179 *
1180 * This function will register a cooling device with device tree node reference.
1181 * This interface function adds a new thermal cooling device (fan/processor/...)
1182 * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself
1183 * to all the thermal zone devices registered at the same time.
1184 *
1185 * Return: a pointer to the created struct thermal_cooling_device or an
1186 * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
1187 */
1188struct thermal_cooling_device *
1189thermal_of_cooling_device_register(struct device_node *np,
1190 char *type, void *devdata,
1191 const struct thermal_cooling_device_ops *ops)
1192{
1193 return __thermal_cooling_device_register(np, type, devdata, ops);
1194}
1195EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register);
1196
1197/**
1139 * thermal_cooling_device_unregister - removes the registered thermal cooling device 1198 * thermal_cooling_device_unregister - removes the registered thermal cooling device
1140 * @cdev: the thermal cooling device to remove. 1199 * @cdev: the thermal cooling device to remove.
1141 * 1200 *
@@ -1207,6 +1266,8 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
1207 mutex_lock(&cdev->lock); 1266 mutex_lock(&cdev->lock);
1208 /* Make sure cdev enters the deepest cooling state */ 1267 /* Make sure cdev enters the deepest cooling state */
1209 list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { 1268 list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
1269 dev_dbg(&cdev->device, "zone%d->target=%lu\n",
1270 instance->tz->id, instance->target);
1210 if (instance->target == THERMAL_NO_TARGET) 1271 if (instance->target == THERMAL_NO_TARGET)
1211 continue; 1272 continue;
1212 if (instance->target > target) 1273 if (instance->target > target)
@@ -1215,6 +1276,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
1215 mutex_unlock(&cdev->lock); 1276 mutex_unlock(&cdev->lock);
1216 cdev->ops->set_cur_state(cdev, target); 1277 cdev->ops->set_cur_state(cdev, target);
1217 cdev->updated = true; 1278 cdev->updated = true;
1279 dev_dbg(&cdev->device, "set to state %lu\n", target);
1218} 1280}
1219EXPORT_SYMBOL(thermal_cdev_update); 1281EXPORT_SYMBOL(thermal_cdev_update);
1220 1282
@@ -1370,7 +1432,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
1370 */ 1432 */
1371struct thermal_zone_device *thermal_zone_device_register(const char *type, 1433struct thermal_zone_device *thermal_zone_device_register(const char *type,
1372 int trips, int mask, void *devdata, 1434 int trips, int mask, void *devdata,
1373 const struct thermal_zone_device_ops *ops, 1435 struct thermal_zone_device_ops *ops,
1374 const struct thermal_zone_params *tzp, 1436 const struct thermal_zone_params *tzp,
1375 int passive_delay, int polling_delay) 1437 int passive_delay, int polling_delay)
1376{ 1438{
@@ -1386,7 +1448,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1386 if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) 1448 if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips)
1387 return ERR_PTR(-EINVAL); 1449 return ERR_PTR(-EINVAL);
1388 1450
1389 if (!ops || !ops->get_temp) 1451 if (!ops)
1390 return ERR_PTR(-EINVAL); 1452 return ERR_PTR(-EINVAL);
1391 1453
1392 if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp)) 1454 if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
@@ -1490,6 +1552,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1490 1552
1491 INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); 1553 INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
1492 1554
1555 if (!tz->ops->get_temp)
1556 thermal_zone_device_set_polling(tz, 0);
1557
1493 thermal_zone_device_update(tz); 1558 thermal_zone_device_update(tz);
1494 1559
1495 if (!result) 1560 if (!result)
@@ -1740,8 +1805,14 @@ static int __init thermal_init(void)
1740 if (result) 1805 if (result)
1741 goto unregister_class; 1806 goto unregister_class;
1742 1807
1808 result = of_parse_thermal_zones();
1809 if (result)
1810 goto exit_netlink;
1811
1743 return 0; 1812 return 0;
1744 1813
1814exit_netlink:
1815 genetlink_exit();
1745unregister_governors: 1816unregister_governors:
1746 thermal_unregister_governors(); 1817 thermal_unregister_governors();
1747unregister_class: 1818unregister_class:
@@ -1757,6 +1828,7 @@ error:
1757 1828
1758static void __exit thermal_exit(void) 1829static void __exit thermal_exit(void)
1759{ 1830{
1831 of_thermal_destroy_zones();
1760 genetlink_exit(); 1832 genetlink_exit();
1761 class_unregister(&thermal_class); 1833 class_unregister(&thermal_class);
1762 thermal_unregister_governors(); 1834 thermal_unregister_governors();
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 7cf2f6626251..3db339fb636f 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -77,4 +77,13 @@ static inline int thermal_gov_user_space_register(void) { return 0; }
77static inline void thermal_gov_user_space_unregister(void) {} 77static inline void thermal_gov_user_space_unregister(void) {}
78#endif /* CONFIG_THERMAL_GOV_USER_SPACE */ 78#endif /* CONFIG_THERMAL_GOV_USER_SPACE */
79 79
80/* device tree support */
81#ifdef CONFIG_THERMAL_OF
82int of_parse_thermal_zones(void);
83void of_thermal_destroy_zones(void);
84#else
85static inline int of_parse_thermal_zones(void) { return 0; }
86static inline void of_thermal_destroy_zones(void) { }
87#endif
88
80#endif /* __THERMAL_CORE_H__ */ 89#endif /* __THERMAL_CORE_H__ */
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 5a47cc8c8f85..9eec26dc0448 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -31,6 +31,7 @@
31#include <linux/cpufreq.h> 31#include <linux/cpufreq.h>
32#include <linux/cpumask.h> 32#include <linux/cpumask.h>
33#include <linux/cpu_cooling.h> 33#include <linux/cpu_cooling.h>
34#include <linux/of.h>
34 35
35#include "ti-thermal.h" 36#include "ti-thermal.h"
36#include "ti-bandgap.h" 37#include "ti-bandgap.h"
@@ -44,6 +45,7 @@ struct ti_thermal_data {
44 enum thermal_device_mode mode; 45 enum thermal_device_mode mode;
45 struct work_struct thermal_wq; 46 struct work_struct thermal_wq;
46 int sensor_id; 47 int sensor_id;
48 bool our_zone;
47}; 49};
48 50
49static void ti_thermal_work(struct work_struct *work) 51static void ti_thermal_work(struct work_struct *work)
@@ -75,11 +77,10 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
75 77
76/* thermal zone ops */ 78/* thermal zone ops */
77/* Get temperature callback function for thermal zone*/ 79/* Get temperature callback function for thermal zone*/
78static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, 80static inline int __ti_thermal_get_temp(void *devdata, long *temp)
79 unsigned long *temp)
80{ 81{
81 struct thermal_zone_device *pcb_tz = NULL; 82 struct thermal_zone_device *pcb_tz = NULL;
82 struct ti_thermal_data *data = thermal->devdata; 83 struct ti_thermal_data *data = devdata;
83 struct ti_bandgap *bgp; 84 struct ti_bandgap *bgp;
84 const struct ti_temp_sensor *s; 85 const struct ti_temp_sensor *s;
85 int ret, tmp, slope, constant; 86 int ret, tmp, slope, constant;
@@ -118,6 +119,14 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
118 return ret; 119 return ret;
119} 120}
120 121
122static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
123 unsigned long *temp)
124{
125 struct ti_thermal_data *data = thermal->devdata;
126
127 return __ti_thermal_get_temp(data, temp);
128}
129
121/* Bind callback functions for thermal zone */ 130/* Bind callback functions for thermal zone */
122static int ti_thermal_bind(struct thermal_zone_device *thermal, 131static int ti_thermal_bind(struct thermal_zone_device *thermal,
123 struct thermal_cooling_device *cdev) 132 struct thermal_cooling_device *cdev)
@@ -230,11 +239,9 @@ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
230 return 0; 239 return 0;
231} 240}
232 241
233/* Get the temperature trend callback functions for thermal zone */ 242static int __ti_thermal_get_trend(void *p, long *trend)
234static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
235 int trip, enum thermal_trend *trend)
236{ 243{
237 struct ti_thermal_data *data = thermal->devdata; 244 struct ti_thermal_data *data = p;
238 struct ti_bandgap *bgp; 245 struct ti_bandgap *bgp;
239 int id, tr, ret = 0; 246 int id, tr, ret = 0;
240 247
@@ -245,6 +252,22 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
245 if (ret) 252 if (ret)
246 return ret; 253 return ret;
247 254
255 *trend = tr;
256
257 return 0;
258}
259
260/* Get the temperature trend callback functions for thermal zone */
261static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
262 int trip, enum thermal_trend *trend)
263{
264 int ret;
265 long tr;
266
267 ret = __ti_thermal_get_trend(thermal->devdata, &tr);
268 if (ret)
269 return ret;
270
248 if (tr > 0) 271 if (tr > 0)
249 *trend = THERMAL_TREND_RAISING; 272 *trend = THERMAL_TREND_RAISING;
250 else if (tr < 0) 273 else if (tr < 0)
@@ -308,16 +331,23 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
308 if (!data) 331 if (!data)
309 return -EINVAL; 332 return -EINVAL;
310 333
311 /* Create thermal zone */ 334 /* in case this is specified by DT */
312 data->ti_thermal = thermal_zone_device_register(domain, 335 data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id,
336 data, __ti_thermal_get_temp,
337 __ti_thermal_get_trend);
338 if (IS_ERR(data->ti_thermal)) {
339 /* Create thermal zone */
340 data->ti_thermal = thermal_zone_device_register(domain,
313 OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, 341 OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
314 NULL, FAST_TEMP_MONITORING_RATE, 342 NULL, FAST_TEMP_MONITORING_RATE,
315 FAST_TEMP_MONITORING_RATE); 343 FAST_TEMP_MONITORING_RATE);
316 if (IS_ERR(data->ti_thermal)) { 344 if (IS_ERR(data->ti_thermal)) {
317 dev_err(bgp->dev, "thermal zone device is NULL\n"); 345 dev_err(bgp->dev, "thermal zone device is NULL\n");
318 return PTR_ERR(data->ti_thermal); 346 return PTR_ERR(data->ti_thermal);
347 }
348 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
349 data->our_zone = true;
319 } 350 }
320 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
321 ti_bandgap_set_sensor_data(bgp, id, data); 351 ti_bandgap_set_sensor_data(bgp, id, data);
322 ti_bandgap_write_update_interval(bgp, data->sensor_id, 352 ti_bandgap_write_update_interval(bgp, data->sensor_id,
323 data->ti_thermal->polling_delay); 353 data->ti_thermal->polling_delay);
@@ -331,7 +361,13 @@ int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
331 361
332 data = ti_bandgap_get_sensor_data(bgp, id); 362 data = ti_bandgap_get_sensor_data(bgp, id);
333 363
334 thermal_zone_device_unregister(data->ti_thermal); 364 if (data && data->ti_thermal) {
365 if (data->our_zone)
366 thermal_zone_device_unregister(data->ti_thermal);
367 else
368 thermal_zone_of_sensor_unregister(bgp->dev,
369 data->ti_thermal);
370 }
335 371
336 return 0; 372 return 0;
337} 373}
@@ -350,6 +386,15 @@ int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
350int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) 386int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
351{ 387{
352 struct ti_thermal_data *data; 388 struct ti_thermal_data *data;
389 struct device_node *np = bgp->dev->of_node;
390
391 /*
392 * We are assuming here that if one deploys the zone
393 * using DT, then it must be aware that the cooling device
394 * loading has to happen via cpufreq driver.
395 */
396 if (of_find_property(np, "#thermal-sensor-cells", NULL))
397 return 0;
353 398
354 data = ti_bandgap_get_sensor_data(bgp, id); 399 data = ti_bandgap_get_sensor_data(bgp, id);
355 if (!data || IS_ERR(data)) 400 if (!data || IS_ERR(data))
@@ -380,7 +425,9 @@ int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
380 struct ti_thermal_data *data; 425 struct ti_thermal_data *data;
381 426
382 data = ti_bandgap_get_sensor_data(bgp, id); 427 data = ti_bandgap_get_sensor_data(bgp, id);
383 cpufreq_cooling_unregister(data->cool_dev); 428
429 if (data && data->cool_dev)
430 cpufreq_cooling_unregister(data->cool_dev);
384 431
385 return 0; 432 return 0;
386} 433}
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index 7722cb9d5a80..972e1c73722a 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -215,7 +215,7 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
215 return 0; 215 return 0;
216} 216}
217 217
218int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, 218static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
219 unsigned long temp) 219 unsigned long temp)
220{ 220{
221 u32 l, h; 221 u32 l, h;