aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/thermal
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/Kconfig107
-rw-r--r--drivers/thermal/Makefile15
-rw-r--r--drivers/thermal/cpu_cooling.c398
-rw-r--r--drivers/thermal/db8500_cpufreq_cooling.c108
-rw-r--r--drivers/thermal/db8500_thermal.c531
-rw-r--r--drivers/thermal/exynos_thermal.c997
-rw-r--r--drivers/thermal/fair_share.c133
-rw-r--r--drivers/thermal/rcar_thermal.c249
-rw-r--r--drivers/thermal/spear_thermal.c212
-rw-r--r--drivers/thermal/step_wise.c194
-rw-r--r--drivers/thermal/thermal_core.h53
-rw-r--r--drivers/thermal/thermal_sys.c1040
-rw-r--r--drivers/thermal/user_space.c68
13 files changed, 317 insertions, 3788 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index c2c77d1ac49..f7f71b2d310 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -13,113 +13,8 @@ menuconfig THERMAL
13 All platforms with ACPI thermal support can use this driver. 13 All platforms with ACPI thermal support can use this driver.
14 If you want this support, you should say Y or M here. 14 If you want this support, you should say Y or M here.
15 15
16if THERMAL
17
18config THERMAL_HWMON 16config THERMAL_HWMON
19 bool 17 bool
18 depends on THERMAL
20 depends on HWMON=y || HWMON=THERMAL 19 depends on HWMON=y || HWMON=THERMAL
21 default y 20 default y
22
23choice
24 prompt "Default Thermal governor"
25 default THERMAL_DEFAULT_GOV_STEP_WISE
26 help
27 This option sets which thermal governor shall be loaded at
28 startup. If in doubt, select 'step_wise'.
29
30config THERMAL_DEFAULT_GOV_STEP_WISE
31 bool "step_wise"
32 select STEP_WISE
33 help
34 Use the step_wise governor as default. This throttles the
35 devices one step at a time.
36
37config THERMAL_DEFAULT_GOV_FAIR_SHARE
38 bool "fair_share"
39 select FAIR_SHARE
40 help
41 Use the fair_share governor as default. This throttles the
42 devices based on their 'contribution' to a zone. The
43 contribution should be provided through platform data.
44
45config THERMAL_DEFAULT_GOV_USER_SPACE
46 bool "user_space"
47 select USER_SPACE
48 help
49 Select this if you want to let the user space manage the
50 lpatform thermals.
51
52endchoice
53
54config FAIR_SHARE
55 bool "Fair-share thermal governor"
56 help
57 Enable this to manage platform thermals using fair-share governor.
58
59config STEP_WISE
60 bool "Step_wise thermal governor"
61 help
62 Enable this to manage platform thermals using a simple linear
63
64config USER_SPACE
65 bool "User_space thermal governor"
66 help
67 Enable this to let the user space manage the platform thermals.
68
69config CPU_THERMAL
70 tristate "generic cpu cooling support"
71 depends on CPU_FREQ
72 select CPU_FREQ_TABLE
73 help
74 This implements the generic cpu cooling mechanism through frequency
75 reduction, cpu hotplug and any other ways of reducing temperature. An
76 ACPI version of this already exists(drivers/acpi/processor_thermal.c).
77 This will be useful for platforms using the generic thermal interface
78 and not the ACPI interface.
79 If you want this support, you should say Y here.
80
81config SPEAR_THERMAL
82 bool "SPEAr thermal sensor driver"
83 depends on PLAT_SPEAR
84 depends on OF
85 help
86 Enable this to plug the SPEAr thermal sensor driver into the Linux
87 thermal framework
88
89config RCAR_THERMAL
90 tristate "Renesas R-Car thermal driver"
91 depends on ARCH_SHMOBILE
92 help
93 Enable this to plug the R-Car thermal sensor driver into the Linux
94 thermal framework
95
96config EXYNOS_THERMAL
97 tristate "Temperature sensor on Samsung EXYNOS"
98 depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
99 depends on CPU_THERMAL
100 help
101 If you say yes here you get support for TMU (Thermal Management
102 Unit) on SAMSUNG EXYNOS series of SoC.
103
104config DB8500_THERMAL
105 bool "DB8500 thermal management"
106 depends on ARCH_U8500
107 default y
108 help
109 Adds DB8500 thermal management implementation according to the thermal
110 management framework. A thermal zone with several trip points will be
111 created. Cooling devices can be bound to the trip points to cool this
112 thermal zone if trip points reached.
113
114config DB8500_CPUFREQ_COOLING
115 tristate "DB8500 cpufreq cooling"
116 depends on ARCH_U8500
117 depends on CPU_THERMAL
118 default y
119 help
120 Adds DB8500 cpufreq cooling devices, and these cooling devices can be
121 bound to thermal zone trip points. When a trip point reached, the
122 bound cpufreq cooling device turns active to set CPU frequency low to
123 cool down the CPU.
124
125endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index d8da683245f..31108a01c22 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -3,18 +3,3 @@
3# 3#
4 4
5obj-$(CONFIG_THERMAL) += thermal_sys.o 5obj-$(CONFIG_THERMAL) += thermal_sys.o
6
7# governors
8obj-$(CONFIG_FAIR_SHARE) += fair_share.o
9obj-$(CONFIG_STEP_WISE) += step_wise.o
10obj-$(CONFIG_USER_SPACE) += user_space.o
11
12# cpufreq cooling
13obj-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
14
15# platform thermal drivers
16obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
17obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
18obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
19obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
20obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
deleted file mode 100644
index 836828e29a8..00000000000
--- a/drivers/thermal/cpu_cooling.c
+++ /dev/null
@@ -1,398 +0,0 @@
1/*
2 * linux/drivers/thermal/cpu_cooling.c
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
5 * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 *
21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 */
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/thermal.h>
26#include <linux/platform_device.h>
27#include <linux/cpufreq.h>
28#include <linux/err.h>
29#include <linux/slab.h>
30#include <linux/cpu.h>
31#include <linux/cpu_cooling.h>
32
33/**
34 * struct cpufreq_cooling_device
35 * @id: unique integer value corresponding to each cpufreq_cooling_device
36 * registered.
37 * @cool_dev: thermal_cooling_device pointer to keep track of the the
38 * egistered cooling device.
39 * @cpufreq_state: integer value representing the current state of cpufreq
40 * cooling devices.
41 * @cpufreq_val: integer value representing the absolute value of the clipped
42 * frequency.
43 * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device.
44 * @node: list_head to link all cpufreq_cooling_device together.
45 *
46 * This structure is required for keeping information of each
47 * cpufreq_cooling_device registered as a list whose head is represented by
48 * cooling_cpufreq_list. In order to prevent corruption of this list a
49 * mutex lock cooling_cpufreq_lock is used.
50 */
51struct cpufreq_cooling_device {
52 int id;
53 struct thermal_cooling_device *cool_dev;
54 unsigned int cpufreq_state;
55 unsigned int cpufreq_val;
56 struct cpumask allowed_cpus;
57 struct list_head node;
58};
59static LIST_HEAD(cooling_cpufreq_list);
60static DEFINE_IDR(cpufreq_idr);
61static DEFINE_MUTEX(cooling_cpufreq_lock);
62
63static unsigned int cpufreq_dev_count;
64
65/* notify_table passes value to the CPUFREQ_ADJUST callback function. */
66#define NOTIFY_INVALID NULL
67static struct cpufreq_cooling_device *notify_device;
68
69/**
70 * get_idr - function to get a unique id.
71 * @idr: struct idr * handle used to create a id.
72 * @id: int * value generated by this function.
73 */
74static int get_idr(struct idr *idr, int *id)
75{
76 int err;
77again:
78 if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
79 return -ENOMEM;
80
81 mutex_lock(&cooling_cpufreq_lock);
82 err = idr_get_new(idr, NULL, id);
83 mutex_unlock(&cooling_cpufreq_lock);
84
85 if (unlikely(err == -EAGAIN))
86 goto again;
87 else if (unlikely(err))
88 return err;
89
90 *id = *id & MAX_IDR_MASK;
91 return 0;
92}
93
94/**
95 * release_idr - function to free the unique id.
96 * @idr: struct idr * handle used for creating the id.
97 * @id: int value representing the unique id.
98 */
99static void release_idr(struct idr *idr, int id)
100{
101 mutex_lock(&cooling_cpufreq_lock);
102 idr_remove(idr, id);
103 mutex_unlock(&cooling_cpufreq_lock);
104}
105
106/* Below code defines functions to be used for cpufreq as cooling device */
107
108/**
109 * is_cpufreq_valid - function to check if a cpu has frequency transition policy.
110 * @cpu: cpu for which check is needed.
111 */
112static int is_cpufreq_valid(int cpu)
113{
114 struct cpufreq_policy policy;
115 return !cpufreq_get_policy(&policy, cpu);
116}
117
118/**
119 * get_cpu_frequency - get the absolute value of frequency from level.
120 * @cpu: cpu for which frequency is fetched.
121 * @level: level of frequency of the CPU
122 * e.g level=1 --> 1st MAX FREQ, LEVEL=2 ---> 2nd MAX FREQ, .... etc
123 */
124static unsigned int get_cpu_frequency(unsigned int cpu, unsigned long level)
125{
126 int ret = 0, i = 0;
127 unsigned long level_index;
128 bool descend = false;
129 struct cpufreq_frequency_table *table =
130 cpufreq_frequency_get_table(cpu);
131 if (!table)
132 return ret;
133
134 while (table[i].frequency != CPUFREQ_TABLE_END) {
135 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
136 continue;
137
138 /*check if table in ascending or descending order*/
139 if ((table[i + 1].frequency != CPUFREQ_TABLE_END) &&
140 (table[i + 1].frequency < table[i].frequency)
141 && !descend) {
142 descend = true;
143 }
144
145 /*return if level matched and table in descending order*/
146 if (descend && i == level)
147 return table[i].frequency;
148 i++;
149 }
150 i--;
151
152 if (level > i || descend)
153 return ret;
154 level_index = i - level;
155
156 /*Scan the table in reverse order and match the level*/
157 while (i >= 0) {
158 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
159 continue;
160 /*return if level matched*/
161 if (i == level_index)
162 return table[i].frequency;
163 i--;
164 }
165 return ret;
166}
167
168/**
169 * cpufreq_apply_cooling - function to apply frequency clipping.
170 * @cpufreq_device: cpufreq_cooling_device pointer containing frequency
171 * clipping data.
172 * @cooling_state: value of the cooling state.
173 */
174static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device,
175 unsigned long cooling_state)
176{
177 unsigned int cpuid, clip_freq;
178 struct cpumask *maskPtr = &cpufreq_device->allowed_cpus;
179 unsigned int cpu = cpumask_any(maskPtr);
180
181
182 /* Check if the old cooling action is same as new cooling action */
183 if (cpufreq_device->cpufreq_state == cooling_state)
184 return 0;
185
186 clip_freq = get_cpu_frequency(cpu, cooling_state);
187 if (!clip_freq)
188 return -EINVAL;
189
190 cpufreq_device->cpufreq_state = cooling_state;
191 cpufreq_device->cpufreq_val = clip_freq;
192 notify_device = cpufreq_device;
193
194 for_each_cpu(cpuid, maskPtr) {
195 if (is_cpufreq_valid(cpuid))
196 cpufreq_update_policy(cpuid);
197 }
198
199 notify_device = NOTIFY_INVALID;
200
201 return 0;
202}
203
204/**
205 * cpufreq_thermal_notifier - notifier callback for cpufreq policy change.
206 * @nb: struct notifier_block * with callback info.
207 * @event: value showing cpufreq event for which this function invoked.
208 * @data: callback-specific data
209 */
210static int cpufreq_thermal_notifier(struct notifier_block *nb,
211 unsigned long event, void *data)
212{
213 struct cpufreq_policy *policy = data;
214 unsigned long max_freq = 0;
215
216 if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
217 return 0;
218
219 if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus))
220 max_freq = notify_device->cpufreq_val;
221
222 /* Never exceed user_policy.max*/
223 if (max_freq > policy->user_policy.max)
224 max_freq = policy->user_policy.max;
225
226 if (policy->max != max_freq)
227 cpufreq_verify_within_limits(policy, 0, max_freq);
228
229 return 0;
230}
231
232/*
233 * cpufreq cooling device callback functions are defined below
234 */
235
236/**
237 * cpufreq_get_max_state - callback function to get the max cooling state.
238 * @cdev: thermal cooling device pointer.
239 * @state: fill this variable with the max cooling state.
240 */
241static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
242 unsigned long *state)
243{
244 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
245 struct cpumask *maskPtr = &cpufreq_device->allowed_cpus;
246 unsigned int cpu;
247 struct cpufreq_frequency_table *table;
248 unsigned long count = 0;
249 int i = 0;
250
251 cpu = cpumask_any(maskPtr);
252 table = cpufreq_frequency_get_table(cpu);
253 if (!table) {
254 *state = 0;
255 return 0;
256 }
257
258 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
259 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
260 continue;
261 count++;
262 }
263
264 if (count > 0) {
265 *state = --count;
266 return 0;
267 }
268
269 return -EINVAL;
270}
271
272/**
273 * cpufreq_get_cur_state - callback function to get the current cooling state.
274 * @cdev: thermal cooling device pointer.
275 * @state: fill this variable with the current cooling state.
276 */
277static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
278 unsigned long *state)
279{
280 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
281
282 *state = cpufreq_device->cpufreq_state;
283 return 0;
284}
285
286/**
287 * cpufreq_set_cur_state - callback function to set the current cooling state.
288 * @cdev: thermal cooling device pointer.
289 * @state: set this variable to the current cooling state.
290 */
291static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
292 unsigned long state)
293{
294 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
295
296 return cpufreq_apply_cooling(cpufreq_device, state);
297}
298
299/* Bind cpufreq callbacks to thermal cooling device ops */
300static struct thermal_cooling_device_ops const cpufreq_cooling_ops = {
301 .get_max_state = cpufreq_get_max_state,
302 .get_cur_state = cpufreq_get_cur_state,
303 .set_cur_state = cpufreq_set_cur_state,
304};
305
306/* Notifier for cpufreq policy change */
307static struct notifier_block thermal_cpufreq_notifier_block = {
308 .notifier_call = cpufreq_thermal_notifier,
309};
310
311/**
312 * cpufreq_cooling_register - function to create cpufreq cooling device.
313 * @clip_cpus: cpumask of cpus where the frequency constraints will happen.
314 */
315struct thermal_cooling_device *cpufreq_cooling_register(
316 const struct cpumask *clip_cpus)
317{
318 struct thermal_cooling_device *cool_dev;
319 struct cpufreq_cooling_device *cpufreq_dev = NULL;
320 unsigned int min = 0, max = 0;
321 char dev_name[THERMAL_NAME_LENGTH];
322 int ret = 0, i;
323 struct cpufreq_policy policy;
324
325 /*Verify that all the clip cpus have same freq_min, freq_max limit*/
326 for_each_cpu(i, clip_cpus) {
327 /*continue if cpufreq policy not found and not return error*/
328 if (!cpufreq_get_policy(&policy, i))
329 continue;
330 if (min == 0 && max == 0) {
331 min = policy.cpuinfo.min_freq;
332 max = policy.cpuinfo.max_freq;
333 } else {
334 if (min != policy.cpuinfo.min_freq ||
335 max != policy.cpuinfo.max_freq)
336 return ERR_PTR(-EINVAL);
337 }
338 }
339 cpufreq_dev = kzalloc(sizeof(struct cpufreq_cooling_device),
340 GFP_KERNEL);
341 if (!cpufreq_dev)
342 return ERR_PTR(-ENOMEM);
343
344 cpumask_copy(&cpufreq_dev->allowed_cpus, clip_cpus);
345
346 ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
347 if (ret) {
348 kfree(cpufreq_dev);
349 return ERR_PTR(-EINVAL);
350 }
351
352 sprintf(dev_name, "thermal-cpufreq-%d", cpufreq_dev->id);
353
354 cool_dev = thermal_cooling_device_register(dev_name, cpufreq_dev,
355 &cpufreq_cooling_ops);
356 if (!cool_dev) {
357 release_idr(&cpufreq_idr, cpufreq_dev->id);
358 kfree(cpufreq_dev);
359 return ERR_PTR(-EINVAL);
360 }
361 cpufreq_dev->cool_dev = cool_dev;
362 cpufreq_dev->cpufreq_state = 0;
363 mutex_lock(&cooling_cpufreq_lock);
364
365 /* Register the notifier for first cpufreq cooling device */
366 if (cpufreq_dev_count == 0)
367 cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
368 CPUFREQ_POLICY_NOTIFIER);
369 cpufreq_dev_count++;
370
371 mutex_unlock(&cooling_cpufreq_lock);
372 return cool_dev;
373}
374EXPORT_SYMBOL(cpufreq_cooling_register);
375
376/**
377 * cpufreq_cooling_unregister - function to remove cpufreq cooling device.
378 * @cdev: thermal cooling device pointer.
379 */
380void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
381{
382 struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
383
384 mutex_lock(&cooling_cpufreq_lock);
385 cpufreq_dev_count--;
386
387 /* Unregister the notifier for the last cpufreq cooling device */
388 if (cpufreq_dev_count == 0) {
389 cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
390 CPUFREQ_POLICY_NOTIFIER);
391 }
392 mutex_unlock(&cooling_cpufreq_lock);
393
394 thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
395 release_idr(&cpufreq_idr, cpufreq_dev->id);
396 kfree(cpufreq_dev);
397}
398EXPORT_SYMBOL(cpufreq_cooling_unregister);
diff --git a/drivers/thermal/db8500_cpufreq_cooling.c b/drivers/thermal/db8500_cpufreq_cooling.c
deleted file mode 100644
index 4cf8e72af90..00000000000
--- a/drivers/thermal/db8500_cpufreq_cooling.c
+++ /dev/null
@@ -1,108 +0,0 @@
1/*
2 * db8500_cpufreq_cooling.c - DB8500 cpufreq works as cooling device.
3 *
4 * Copyright (C) 2012 ST-Ericsson
5 * Copyright (C) 2012 Linaro Ltd.
6 *
7 * Author: Hongbo Zhang <hongbo.zhang@linaro.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/cpu_cooling.h>
21#include <linux/cpufreq.h>
22#include <linux/err.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26
27static int db8500_cpufreq_cooling_probe(struct platform_device *pdev)
28{
29 struct thermal_cooling_device *cdev;
30 struct cpumask mask_val;
31
32 /* make sure cpufreq driver has been initialized */
33 if (!cpufreq_frequency_get_table(0))
34 return -EPROBE_DEFER;
35
36 cpumask_set_cpu(0, &mask_val);
37 cdev = cpufreq_cooling_register(&mask_val);
38
39 if (IS_ERR_OR_NULL(cdev)) {
40 dev_err(&pdev->dev, "Failed to register cooling device\n");
41 return PTR_ERR(cdev);
42 }
43
44 platform_set_drvdata(pdev, cdev);
45
46 dev_info(&pdev->dev, "Cooling device registered: %s\n", cdev->type);
47
48 return 0;
49}
50
51static int db8500_cpufreq_cooling_remove(struct platform_device *pdev)
52{
53 struct thermal_cooling_device *cdev = platform_get_drvdata(pdev);
54
55 cpufreq_cooling_unregister(cdev);
56
57 return 0;
58}
59
60static int db8500_cpufreq_cooling_suspend(struct platform_device *pdev,
61 pm_message_t state)
62{
63 return -ENOSYS;
64}
65
66static int db8500_cpufreq_cooling_resume(struct platform_device *pdev)
67{
68 return -ENOSYS;
69}
70
71#ifdef CONFIG_OF
72static const struct of_device_id db8500_cpufreq_cooling_match[] = {
73 { .compatible = "stericsson,db8500-cpufreq-cooling" },
74 {},
75};
76#else
77#define db8500_cpufreq_cooling_match NULL
78#endif
79
80static struct platform_driver db8500_cpufreq_cooling_driver = {
81 .driver = {
82 .owner = THIS_MODULE,
83 .name = "db8500-cpufreq-cooling",
84 .of_match_table = db8500_cpufreq_cooling_match,
85 },
86 .probe = db8500_cpufreq_cooling_probe,
87 .suspend = db8500_cpufreq_cooling_suspend,
88 .resume = db8500_cpufreq_cooling_resume,
89 .remove = db8500_cpufreq_cooling_remove,
90};
91
92static int __init db8500_cpufreq_cooling_init(void)
93{
94 return platform_driver_register(&db8500_cpufreq_cooling_driver);
95}
96
97static void __exit db8500_cpufreq_cooling_exit(void)
98{
99 platform_driver_unregister(&db8500_cpufreq_cooling_driver);
100}
101
102/* Should be later than db8500_cpufreq_register */
103late_initcall(db8500_cpufreq_cooling_init);
104module_exit(db8500_cpufreq_cooling_exit);
105
106MODULE_AUTHOR("Hongbo Zhang <hongbo.zhang@stericsson.com>");
107MODULE_DESCRIPTION("DB8500 cpufreq cooling driver");
108MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
deleted file mode 100644
index ec71ade3e31..00000000000
--- a/drivers/thermal/db8500_thermal.c
+++ /dev/null
@@ -1,531 +0,0 @@
1/*
2 * db8500_thermal.c - DB8500 Thermal Management Implementation
3 *
4 * Copyright (C) 2012 ST-Ericsson
5 * Copyright (C) 2012 Linaro Ltd.
6 *
7 * Author: Hongbo Zhang <hongbo.zhang@linaro.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/cpu_cooling.h>
21#include <linux/interrupt.h>
22#include <linux/mfd/dbx500-prcmu.h>
23#include <linux/module.h>
24#include <linux/of.h>
25#include <linux/platform_data/db8500_thermal.h>
26#include <linux/platform_device.h>
27#include <linux/slab.h>
28#include <linux/thermal.h>
29
30#define PRCMU_DEFAULT_MEASURE_TIME 0xFFF
31#define PRCMU_DEFAULT_LOW_TEMP 0
32
33struct db8500_thermal_zone {
34 struct thermal_zone_device *therm_dev;
35 struct mutex th_lock;
36 struct work_struct therm_work;
37 struct db8500_thsens_platform_data *trip_tab;
38 enum thermal_device_mode mode;
39 enum thermal_trend trend;
40 unsigned long cur_temp_pseudo;
41 unsigned int cur_index;
42};
43
44/* Local function to check if thermal zone matches cooling devices */
45static int db8500_thermal_match_cdev(struct thermal_cooling_device *cdev,
46 struct db8500_trip_point *trip_point)
47{
48 int i;
49
50 if (!strlen(cdev->type))
51 return -EINVAL;
52
53 for (i = 0; i < COOLING_DEV_MAX; i++) {
54 if (!strcmp(trip_point->cdev_name[i], cdev->type))
55 return 0;
56 }
57
58 return -ENODEV;
59}
60
61/* Callback to bind cooling device to thermal zone */
62static int db8500_cdev_bind(struct thermal_zone_device *thermal,
63 struct thermal_cooling_device *cdev)
64{
65 struct db8500_thermal_zone *pzone = thermal->devdata;
66 struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
67 unsigned long max_state, upper, lower;
68 int i, ret = -EINVAL;
69
70 cdev->ops->get_max_state(cdev, &max_state);
71
72 for (i = 0; i < ptrips->num_trips; i++) {
73 if (db8500_thermal_match_cdev(cdev, &ptrips->trip_points[i]))
74 continue;
75
76 upper = lower = i > max_state ? max_state : i;
77
78 ret = thermal_zone_bind_cooling_device(thermal, i, cdev,
79 upper, lower);
80
81 dev_info(&cdev->device, "%s bind to %d: %d-%s\n", cdev->type,
82 i, ret, ret ? "fail" : "succeed");
83 }
84
85 return ret;
86}
87
88/* Callback to unbind cooling device from thermal zone */
89static int db8500_cdev_unbind(struct thermal_zone_device *thermal,
90 struct thermal_cooling_device *cdev)
91{
92 struct db8500_thermal_zone *pzone = thermal->devdata;
93 struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
94 int i, ret = -EINVAL;
95
96 for (i = 0; i < ptrips->num_trips; i++) {
97 if (db8500_thermal_match_cdev(cdev, &ptrips->trip_points[i]))
98 continue;
99
100 ret = thermal_zone_unbind_cooling_device(thermal, i, cdev);
101
102 dev_info(&cdev->device, "%s unbind from %d: %s\n", cdev->type,
103 i, ret ? "fail" : "succeed");
104 }
105
106 return ret;
107}
108
109/* Callback to get current temperature */
110static int db8500_sys_get_temp(struct thermal_zone_device *thermal,
111 unsigned long *temp)
112{
113 struct db8500_thermal_zone *pzone = thermal->devdata;
114
115 /*
116 * TODO: There is no PRCMU interface to get temperature data currently,
117 * so a pseudo temperature is returned , it works for thermal framework
118 * and this will be fixed when the PRCMU interface is available.
119 */
120 *temp = pzone->cur_temp_pseudo;
121
122 return 0;
123}
124
125/* Callback to get temperature changing trend */
126static int db8500_sys_get_trend(struct thermal_zone_device *thermal,
127 int trip, enum thermal_trend *trend)
128{
129 struct db8500_thermal_zone *pzone = thermal->devdata;
130
131 *trend = pzone->trend;
132
133 return 0;
134}
135
136/* Callback to get thermal zone mode */
137static int db8500_sys_get_mode(struct thermal_zone_device *thermal,
138 enum thermal_device_mode *mode)
139{
140 struct db8500_thermal_zone *pzone = thermal->devdata;
141
142 mutex_lock(&pzone->th_lock);
143 *mode = pzone->mode;
144 mutex_unlock(&pzone->th_lock);
145
146 return 0;
147}
148
149/* Callback to set thermal zone mode */
150static int db8500_sys_set_mode(struct thermal_zone_device *thermal,
151 enum thermal_device_mode mode)
152{
153 struct db8500_thermal_zone *pzone = thermal->devdata;
154
155 mutex_lock(&pzone->th_lock);
156
157 pzone->mode = mode;
158 if (mode == THERMAL_DEVICE_ENABLED)
159 schedule_work(&pzone->therm_work);
160
161 mutex_unlock(&pzone->th_lock);
162
163 return 0;
164}
165
166/* Callback to get trip point type */
167static int db8500_sys_get_trip_type(struct thermal_zone_device *thermal,
168 int trip, enum thermal_trip_type *type)
169{
170 struct db8500_thermal_zone *pzone = thermal->devdata;
171 struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
172
173 if (trip >= ptrips->num_trips)
174 return -EINVAL;
175
176 *type = ptrips->trip_points[trip].type;
177
178 return 0;
179}
180
181/* Callback to get trip point temperature */
182static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal,
183 int trip, unsigned long *temp)
184{
185 struct db8500_thermal_zone *pzone = thermal->devdata;
186 struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
187
188 if (trip >= ptrips->num_trips)
189 return -EINVAL;
190
191 *temp = ptrips->trip_points[trip].temp;
192
193 return 0;
194}
195
196/* Callback to get critical trip point temperature */
197static int db8500_sys_get_crit_temp(struct thermal_zone_device *thermal,
198 unsigned long *temp)
199{
200 struct db8500_thermal_zone *pzone = thermal->devdata;
201 struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
202 int i;
203
204 for (i = ptrips->num_trips - 1; i > 0; i--) {
205 if (ptrips->trip_points[i].type == THERMAL_TRIP_CRITICAL) {
206 *temp = ptrips->trip_points[i].temp;
207 return 0;
208 }
209 }
210
211 return -EINVAL;
212}
213
214static struct thermal_zone_device_ops thdev_ops = {
215 .bind = db8500_cdev_bind,
216 .unbind = db8500_cdev_unbind,
217 .get_temp = db8500_sys_get_temp,
218 .get_trend = db8500_sys_get_trend,
219 .get_mode = db8500_sys_get_mode,
220 .set_mode = db8500_sys_set_mode,
221 .get_trip_type = db8500_sys_get_trip_type,
222 .get_trip_temp = db8500_sys_get_trip_temp,
223 .get_crit_temp = db8500_sys_get_crit_temp,
224};
225
226static void db8500_thermal_update_config(struct db8500_thermal_zone *pzone,
227 unsigned int idx, enum thermal_trend trend,
228 unsigned long next_low, unsigned long next_high)
229{
230 prcmu_stop_temp_sense();
231
232 pzone->cur_index = idx;
233 pzone->cur_temp_pseudo = (next_low + next_high)/2;
234 pzone->trend = trend;
235
236 prcmu_config_hotmon((u8)(next_low/1000), (u8)(next_high/1000));
237 prcmu_start_temp_sense(PRCMU_DEFAULT_MEASURE_TIME);
238}
239
240static irqreturn_t prcmu_low_irq_handler(int irq, void *irq_data)
241{
242 struct db8500_thermal_zone *pzone = irq_data;
243 struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
244 unsigned int idx = pzone->cur_index;
245 unsigned long next_low, next_high;
246
247 if (unlikely(idx == 0))
248 /* Meaningless for thermal management, ignoring it */
249 return IRQ_HANDLED;
250
251 if (idx == 1) {
252 next_high = ptrips->trip_points[0].temp;
253 next_low = PRCMU_DEFAULT_LOW_TEMP;
254 } else {
255 next_high = ptrips->trip_points[idx-1].temp;
256 next_low = ptrips->trip_points[idx-2].temp;
257 }
258 idx -= 1;
259
260 db8500_thermal_update_config(pzone, idx, THERMAL_TREND_DROPPING,
261 next_low, next_high);
262
263 dev_dbg(&pzone->therm_dev->device,
264 "PRCMU set max %ld, min %ld\n", next_high, next_low);
265
266 schedule_work(&pzone->therm_work);
267
268 return IRQ_HANDLED;
269}
270
271static irqreturn_t prcmu_high_irq_handler(int irq, void *irq_data)
272{
273 struct db8500_thermal_zone *pzone = irq_data;
274 struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
275 unsigned int idx = pzone->cur_index;
276 unsigned long next_low, next_high;
277
278 if (idx < ptrips->num_trips - 1) {
279 next_high = ptrips->trip_points[idx+1].temp;
280 next_low = ptrips->trip_points[idx].temp;
281 idx += 1;
282
283 db8500_thermal_update_config(pzone, idx, THERMAL_TREND_RAISING,
284 next_low, next_high);
285
286 dev_dbg(&pzone->therm_dev->device,
287 "PRCMU set max %ld, min %ld\n", next_high, next_low);
288 } else if (idx == ptrips->num_trips - 1)
289 pzone->cur_temp_pseudo = ptrips->trip_points[idx].temp + 1;
290
291 schedule_work(&pzone->therm_work);
292
293 return IRQ_HANDLED;
294}
295
296static void db8500_thermal_work(struct work_struct *work)
297{
298 enum thermal_device_mode cur_mode;
299 struct db8500_thermal_zone *pzone;
300
301 pzone = container_of(work, struct db8500_thermal_zone, therm_work);
302
303 mutex_lock(&pzone->th_lock);
304 cur_mode = pzone->mode;
305 mutex_unlock(&pzone->th_lock);
306
307 if (cur_mode == THERMAL_DEVICE_DISABLED)
308 return;
309
310 thermal_zone_device_update(pzone->therm_dev);
311 dev_dbg(&pzone->therm_dev->device, "thermal work finished.\n");
312}
313
314#ifdef CONFIG_OF
315static struct db8500_thsens_platform_data*
316 db8500_thermal_parse_dt(struct platform_device *pdev)
317{
318 struct db8500_thsens_platform_data *ptrips;
319 struct device_node *np = pdev->dev.of_node;
320 char prop_name[32];
321 const char *tmp_str;
322 u32 tmp_data;
323 int i, j;
324
325 ptrips = devm_kzalloc(&pdev->dev, sizeof(*ptrips), GFP_KERNEL);
326 if (!ptrips)
327 return NULL;
328
329 if (of_property_read_u32(np, "num-trips", &tmp_data))
330 goto err_parse_dt;
331
332 if (tmp_data > THERMAL_MAX_TRIPS)
333 goto err_parse_dt;
334
335 ptrips->num_trips = tmp_data;
336
337 for (i = 0; i < ptrips->num_trips; i++) {
338 sprintf(prop_name, "trip%d-temp", i);
339 if (of_property_read_u32(np, prop_name, &tmp_data))
340 goto err_parse_dt;
341
342 ptrips->trip_points[i].temp = tmp_data;
343
344 sprintf(prop_name, "trip%d-type", i);
345 if (of_property_read_string(np, prop_name, &tmp_str))
346 goto err_parse_dt;
347
348 if (!strcmp(tmp_str, "active"))
349 ptrips->trip_points[i].type = THERMAL_TRIP_ACTIVE;
350 else if (!strcmp(tmp_str, "passive"))
351 ptrips->trip_points[i].type = THERMAL_TRIP_PASSIVE;
352 else if (!strcmp(tmp_str, "hot"))
353 ptrips->trip_points[i].type = THERMAL_TRIP_HOT;
354 else if (!strcmp(tmp_str, "critical"))
355 ptrips->trip_points[i].type = THERMAL_TRIP_CRITICAL;
356 else
357 goto err_parse_dt;
358
359 sprintf(prop_name, "trip%d-cdev-num", i);
360 if (of_property_read_u32(np, prop_name, &tmp_data))
361 goto err_parse_dt;
362
363 if (tmp_data > COOLING_DEV_MAX)
364 goto err_parse_dt;
365
366 for (j = 0; j < tmp_data; j++) {
367 sprintf(prop_name, "trip%d-cdev-name%d", i, j);
368 if (of_property_read_string(np, prop_name, &tmp_str))
369 goto err_parse_dt;
370
371 if (strlen(tmp_str) >= THERMAL_NAME_LENGTH)
372 goto err_parse_dt;
373
374 strcpy(ptrips->trip_points[i].cdev_name[j], tmp_str);
375 }
376 }
377 return ptrips;
378
379err_parse_dt:
380 dev_err(&pdev->dev, "Parsing device tree data error.\n");
381 return NULL;
382}
383#else
384static inline struct db8500_thsens_platform_data*
385 db8500_thermal_parse_dt(struct platform_device *pdev)
386{
387 return NULL;
388}
389#endif
390
391static int db8500_thermal_probe(struct platform_device *pdev)
392{
393 struct db8500_thermal_zone *pzone = NULL;
394 struct db8500_thsens_platform_data *ptrips = NULL;
395 struct device_node *np = pdev->dev.of_node;
396 int low_irq, high_irq, ret = 0;
397 unsigned long dft_low, dft_high;
398
399 if (np)
400 ptrips = db8500_thermal_parse_dt(pdev);
401 else
402 ptrips = dev_get_platdata(&pdev->dev);
403
404 if (!ptrips)
405 return -EINVAL;
406
407 pzone = devm_kzalloc(&pdev->dev, sizeof(*pzone), GFP_KERNEL);
408 if (!pzone)
409 return -ENOMEM;
410
411 mutex_init(&pzone->th_lock);
412 mutex_lock(&pzone->th_lock);
413
414 pzone->mode = THERMAL_DEVICE_DISABLED;
415 pzone->trip_tab = ptrips;
416
417 INIT_WORK(&pzone->therm_work, db8500_thermal_work);
418
419 low_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW");
420 if (low_irq < 0) {
421 dev_err(&pdev->dev, "Get IRQ_HOTMON_LOW failed.\n");
422 return low_irq;
423 }
424
425 ret = devm_request_threaded_irq(&pdev->dev, low_irq, NULL,
426 prcmu_low_irq_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
427 "dbx500_temp_low", pzone);
428 if (ret < 0) {
429 dev_err(&pdev->dev, "Failed to allocate temp low irq.\n");
430 return ret;
431 }
432
433 high_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH");
434 if (high_irq < 0) {
435 dev_err(&pdev->dev, "Get IRQ_HOTMON_HIGH failed.\n");
436 return high_irq;
437 }
438
439 ret = devm_request_threaded_irq(&pdev->dev, high_irq, NULL,
440 prcmu_high_irq_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
441 "dbx500_temp_high", pzone);
442 if (ret < 0) {
443 dev_err(&pdev->dev, "Failed to allocate temp high irq.\n");
444 return ret;
445 }
446
447 pzone->therm_dev = thermal_zone_device_register("db8500_thermal_zone",
448 ptrips->num_trips, 0, pzone, &thdev_ops, NULL, 0, 0);
449
450 if (IS_ERR_OR_NULL(pzone->therm_dev)) {
451 dev_err(&pdev->dev, "Register thermal zone device failed.\n");
452 return PTR_ERR(pzone->therm_dev);
453 }
454 dev_info(&pdev->dev, "Thermal zone device registered.\n");
455
456 dft_low = PRCMU_DEFAULT_LOW_TEMP;
457 dft_high = ptrips->trip_points[0].temp;
458
459 db8500_thermal_update_config(pzone, 0, THERMAL_TREND_STABLE,
460 dft_low, dft_high);
461
462 platform_set_drvdata(pdev, pzone);
463 pzone->mode = THERMAL_DEVICE_ENABLED;
464 mutex_unlock(&pzone->th_lock);
465
466 return 0;
467}
468
469static int db8500_thermal_remove(struct platform_device *pdev)
470{
471 struct db8500_thermal_zone *pzone = platform_get_drvdata(pdev);
472
473 thermal_zone_device_unregister(pzone->therm_dev);
474 cancel_work_sync(&pzone->therm_work);
475 mutex_destroy(&pzone->th_lock);
476
477 return 0;
478}
479
480static int db8500_thermal_suspend(struct platform_device *pdev,
481 pm_message_t state)
482{
483 struct db8500_thermal_zone *pzone = platform_get_drvdata(pdev);
484
485 flush_work(&pzone->therm_work);
486 prcmu_stop_temp_sense();
487
488 return 0;
489}
490
491static int db8500_thermal_resume(struct platform_device *pdev)
492{
493 struct db8500_thermal_zone *pzone = platform_get_drvdata(pdev);
494 struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
495 unsigned long dft_low, dft_high;
496
497 dft_low = PRCMU_DEFAULT_LOW_TEMP;
498 dft_high = ptrips->trip_points[0].temp;
499
500 db8500_thermal_update_config(pzone, 0, THERMAL_TREND_STABLE,
501 dft_low, dft_high);
502
503 return 0;
504}
505
506#ifdef CONFIG_OF
507static const struct of_device_id db8500_thermal_match[] = {
508 { .compatible = "stericsson,db8500-thermal" },
509 {},
510};
511#else
512#define db8500_thermal_match NULL
513#endif
514
515static struct platform_driver db8500_thermal_driver = {
516 .driver = {
517 .owner = THIS_MODULE,
518 .name = "db8500-thermal",
519 .of_match_table = db8500_thermal_match,
520 },
521 .probe = db8500_thermal_probe,
522 .suspend = db8500_thermal_suspend,
523 .resume = db8500_thermal_resume,
524 .remove = db8500_thermal_remove,
525};
526
527module_platform_driver(db8500_thermal_driver);
528
529MODULE_AUTHOR("Hongbo Zhang <hongbo.zhang@stericsson.com>");
530MODULE_DESCRIPTION("DB8500 thermal driver");
531MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
deleted file mode 100644
index 224751e9f5f..00000000000
--- a/drivers/thermal/exynos_thermal.c
+++ /dev/null
@@ -1,997 +0,0 @@
1/*
2 * exynos_thermal.c - Samsung EXYNOS TMU (Thermal Management Unit)
3 *
4 * Copyright (C) 2011 Samsung Electronics
5 * Donggeun Kim <dg77.kim@samsung.com>
6 * Amit Daniel Kachhap <amit.kachhap@linaro.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/err.h>
26#include <linux/kernel.h>
27#include <linux/slab.h>
28#include <linux/platform_device.h>
29#include <linux/interrupt.h>
30#include <linux/clk.h>
31#include <linux/workqueue.h>
32#include <linux/sysfs.h>
33#include <linux/kobject.h>
34#include <linux/io.h>
35#include <linux/mutex.h>
36#include <linux/platform_data/exynos_thermal.h>
37#include <linux/thermal.h>
38#include <linux/cpufreq.h>
39#include <linux/cpu_cooling.h>
40#include <linux/of.h>
41
42#include <plat/cpu.h>
43
44/* Exynos generic registers */
45#define EXYNOS_TMU_REG_TRIMINFO 0x0
46#define EXYNOS_TMU_REG_CONTROL 0x20
47#define EXYNOS_TMU_REG_STATUS 0x28
48#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
49#define EXYNOS_TMU_REG_INTEN 0x70
50#define EXYNOS_TMU_REG_INTSTAT 0x74
51#define EXYNOS_TMU_REG_INTCLEAR 0x78
52
53#define EXYNOS_TMU_TRIM_TEMP_MASK 0xff
54#define EXYNOS_TMU_GAIN_SHIFT 8
55#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
56#define EXYNOS_TMU_CORE_ON 3
57#define EXYNOS_TMU_CORE_OFF 2
58#define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET 50
59
60/* Exynos4210 specific registers */
61#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
62#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
63#define EXYNOS4210_TMU_REG_TRIG_LEVEL1 0x54
64#define EXYNOS4210_TMU_REG_TRIG_LEVEL2 0x58
65#define EXYNOS4210_TMU_REG_TRIG_LEVEL3 0x5C
66#define EXYNOS4210_TMU_REG_PAST_TEMP0 0x60
67#define EXYNOS4210_TMU_REG_PAST_TEMP1 0x64
68#define EXYNOS4210_TMU_REG_PAST_TEMP2 0x68
69#define EXYNOS4210_TMU_REG_PAST_TEMP3 0x6C
70
71#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK 0x1
72#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK 0x10
73#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK 0x100
74#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK 0x1000
75#define EXYNOS4210_TMU_INTCLEAR_VAL 0x1111
76
77/* Exynos5250 and Exynos4412 specific registers */
78#define EXYNOS_TMU_TRIMINFO_CON 0x14
79#define EXYNOS_THD_TEMP_RISE 0x50
80#define EXYNOS_THD_TEMP_FALL 0x54
81#define EXYNOS_EMUL_CON 0x80
82
83#define EXYNOS_TRIMINFO_RELOAD 0x1
84#define EXYNOS_TMU_CLEAR_RISE_INT 0x111
85#define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 16)
86#define EXYNOS_MUX_ADDR_VALUE 6
87#define EXYNOS_MUX_ADDR_SHIFT 20
88#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
89
90#define EFUSE_MIN_VALUE 40
91#define EFUSE_MAX_VALUE 100
92
93/* In-kernel thermal framework related macros & definations */
94#define SENSOR_NAME_LEN 16
95#define MAX_TRIP_COUNT 8
96#define MAX_COOLING_DEVICE 4
97
98#define ACTIVE_INTERVAL 500
99#define IDLE_INTERVAL 10000
100#define MCELSIUS 1000
101
102/* CPU Zone information */
103#define PANIC_ZONE 4
104#define WARN_ZONE 3
105#define MONITOR_ZONE 2
106#define SAFE_ZONE 1
107
108#define GET_ZONE(trip) (trip + 2)
109#define GET_TRIP(zone) (zone - 2)
110
111#define EXYNOS_ZONE_COUNT 3
112
113struct exynos_tmu_data {
114 struct exynos_tmu_platform_data *pdata;
115 struct resource *mem;
116 void __iomem *base;
117 int irq;
118 enum soc_type soc;
119 struct work_struct irq_work;
120 struct mutex lock;
121 struct clk *clk;
122 u8 temp_error1, temp_error2;
123};
124
125struct thermal_trip_point_conf {
126 int trip_val[MAX_TRIP_COUNT];
127 int trip_count;
128};
129
130struct thermal_cooling_conf {
131 struct freq_clip_table freq_data[MAX_TRIP_COUNT];
132 int freq_clip_count;
133};
134
135struct thermal_sensor_conf {
136 char name[SENSOR_NAME_LEN];
137 int (*read_temperature)(void *data);
138 struct thermal_trip_point_conf trip_data;
139 struct thermal_cooling_conf cooling_data;
140 void *private_data;
141};
142
143struct exynos_thermal_zone {
144 enum thermal_device_mode mode;
145 struct thermal_zone_device *therm_dev;
146 struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
147 unsigned int cool_dev_size;
148 struct platform_device *exynos4_dev;
149 struct thermal_sensor_conf *sensor_conf;
150 bool bind;
151};
152
153static struct exynos_thermal_zone *th_zone;
154static void exynos_unregister_thermal(void);
155static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
156
157/* Get mode callback functions for thermal zone */
158static int exynos_get_mode(struct thermal_zone_device *thermal,
159 enum thermal_device_mode *mode)
160{
161 if (th_zone)
162 *mode = th_zone->mode;
163 return 0;
164}
165
166/* Set mode callback functions for thermal zone */
167static int exynos_set_mode(struct thermal_zone_device *thermal,
168 enum thermal_device_mode mode)
169{
170 if (!th_zone->therm_dev) {
171 pr_notice("thermal zone not registered\n");
172 return 0;
173 }
174
175 mutex_lock(&th_zone->therm_dev->lock);
176
177 if (mode == THERMAL_DEVICE_ENABLED)
178 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
179 else
180 th_zone->therm_dev->polling_delay = 0;
181
182 mutex_unlock(&th_zone->therm_dev->lock);
183
184 th_zone->mode = mode;
185 thermal_zone_device_update(th_zone->therm_dev);
186 pr_info("thermal polling set for duration=%d msec\n",
187 th_zone->therm_dev->polling_delay);
188 return 0;
189}
190
191
192/* Get trip type callback functions for thermal zone */
193static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
194 enum thermal_trip_type *type)
195{
196 switch (GET_ZONE(trip)) {
197 case MONITOR_ZONE:
198 case WARN_ZONE:
199 *type = THERMAL_TRIP_ACTIVE;
200 break;
201 case PANIC_ZONE:
202 *type = THERMAL_TRIP_CRITICAL;
203 break;
204 default:
205 return -EINVAL;
206 }
207 return 0;
208}
209
210/* Get trip temperature callback functions for thermal zone */
211static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
212 unsigned long *temp)
213{
214 if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
215 return -EINVAL;
216
217 *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
218 /* convert the temperature into millicelsius */
219 *temp = *temp * MCELSIUS;
220
221 return 0;
222}
223
224/* Get critical temperature callback functions for thermal zone */
225static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
226 unsigned long *temp)
227{
228 int ret;
229 /* Panic zone */
230 ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
231 return ret;
232}
233
234static int exynos_get_frequency_level(unsigned int cpu, unsigned int freq)
235{
236 int i = 0, ret = -EINVAL;
237 struct cpufreq_frequency_table *table = NULL;
238#ifdef CONFIG_CPU_FREQ
239 table = cpufreq_frequency_get_table(cpu);
240#endif
241 if (!table)
242 return ret;
243
244 while (table[i].frequency != CPUFREQ_TABLE_END) {
245 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
246 continue;
247 if (table[i].frequency == freq)
248 return i;
249 i++;
250 }
251 return ret;
252}
253
254/* Bind callback functions for thermal zone */
255static int exynos_bind(struct thermal_zone_device *thermal,
256 struct thermal_cooling_device *cdev)
257{
258 int ret = 0, i, tab_size, level;
259 struct freq_clip_table *tab_ptr, *clip_data;
260 struct thermal_sensor_conf *data = th_zone->sensor_conf;
261
262 tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
263 tab_size = data->cooling_data.freq_clip_count;
264
265 if (tab_ptr == NULL || tab_size == 0)
266 return -EINVAL;
267
268 /* find the cooling device registered*/
269 for (i = 0; i < th_zone->cool_dev_size; i++)
270 if (cdev == th_zone->cool_dev[i])
271 break;
272
273 /* No matching cooling device */
274 if (i == th_zone->cool_dev_size)
275 return 0;
276
277 /* Bind the thermal zone to the cpufreq cooling device */
278 for (i = 0; i < tab_size; i++) {
279 clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
280 level = exynos_get_frequency_level(0, clip_data->freq_clip_max);
281 if (level < 0)
282 return 0;
283 switch (GET_ZONE(i)) {
284 case MONITOR_ZONE:
285 case WARN_ZONE:
286 if (thermal_zone_bind_cooling_device(thermal, i, cdev,
287 level, level)) {
288 pr_err("error binding cdev inst %d\n", i);
289 ret = -EINVAL;
290 }
291 th_zone->bind = true;
292 break;
293 default:
294 ret = -EINVAL;
295 }
296 }
297
298 return ret;
299}
300
301/* Unbind callback functions for thermal zone */
302static int exynos_unbind(struct thermal_zone_device *thermal,
303 struct thermal_cooling_device *cdev)
304{
305 int ret = 0, i, tab_size;
306 struct thermal_sensor_conf *data = th_zone->sensor_conf;
307
308 if (th_zone->bind == false)
309 return 0;
310
311 tab_size = data->cooling_data.freq_clip_count;
312
313 if (tab_size == 0)
314 return -EINVAL;
315
316 /* find the cooling device registered*/
317 for (i = 0; i < th_zone->cool_dev_size; i++)
318 if (cdev == th_zone->cool_dev[i])
319 break;
320
321 /* No matching cooling device */
322 if (i == th_zone->cool_dev_size)
323 return 0;
324
325 /* Bind the thermal zone to the cpufreq cooling device */
326 for (i = 0; i < tab_size; i++) {
327 switch (GET_ZONE(i)) {
328 case MONITOR_ZONE:
329 case WARN_ZONE:
330 if (thermal_zone_unbind_cooling_device(thermal, i,
331 cdev)) {
332 pr_err("error unbinding cdev inst=%d\n", i);
333 ret = -EINVAL;
334 }
335 th_zone->bind = false;
336 break;
337 default:
338 ret = -EINVAL;
339 }
340 }
341 return ret;
342}
343
344/* Get temperature callback functions for thermal zone */
345static int exynos_get_temp(struct thermal_zone_device *thermal,
346 unsigned long *temp)
347{
348 void *data;
349
350 if (!th_zone->sensor_conf) {
351 pr_info("Temperature sensor not initialised\n");
352 return -EINVAL;
353 }
354 data = th_zone->sensor_conf->private_data;
355 *temp = th_zone->sensor_conf->read_temperature(data);
356 /* convert the temperature into millicelsius */
357 *temp = *temp * MCELSIUS;
358 return 0;
359}
360
361/* Get the temperature trend */
362static int exynos_get_trend(struct thermal_zone_device *thermal,
363 int trip, enum thermal_trend *trend)
364{
365 if (thermal->temperature >= trip)
366 *trend = THERMAL_TREND_RAISING;
367 else
368 *trend = THERMAL_TREND_DROPPING;
369
370 return 0;
371}
372/* Operation callback functions for thermal zone */
373static struct thermal_zone_device_ops const exynos_dev_ops = {
374 .bind = exynos_bind,
375 .unbind = exynos_unbind,
376 .get_temp = exynos_get_temp,
377 .get_trend = exynos_get_trend,
378 .get_mode = exynos_get_mode,
379 .set_mode = exynos_set_mode,
380 .get_trip_type = exynos_get_trip_type,
381 .get_trip_temp = exynos_get_trip_temp,
382 .get_crit_temp = exynos_get_crit_temp,
383};
384
385/*
386 * This function may be called from interrupt based temperature sensor
387 * when threshold is changed.
388 */
389static void exynos_report_trigger(void)
390{
391 unsigned int i;
392 char data[10];
393 char *envp[] = { data, NULL };
394
395 if (!th_zone || !th_zone->therm_dev)
396 return;
397 if (th_zone->bind == false) {
398 for (i = 0; i < th_zone->cool_dev_size; i++) {
399 if (!th_zone->cool_dev[i])
400 continue;
401 exynos_bind(th_zone->therm_dev,
402 th_zone->cool_dev[i]);
403 }
404 }
405
406 thermal_zone_device_update(th_zone->therm_dev);
407
408 mutex_lock(&th_zone->therm_dev->lock);
409 /* Find the level for which trip happened */
410 for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
411 if (th_zone->therm_dev->last_temperature <
412 th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
413 break;
414 }
415
416 if (th_zone->mode == THERMAL_DEVICE_ENABLED) {
417 if (i > 0)
418 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
419 else
420 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
421 }
422
423 snprintf(data, sizeof(data), "%u", i);
424 kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
425 mutex_unlock(&th_zone->therm_dev->lock);
426}
427
428/* Register with the in-kernel thermal management */
429static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
430{
431 int ret;
432 struct cpumask mask_val;
433
434 if (!sensor_conf || !sensor_conf->read_temperature) {
435 pr_err("Temperature sensor not initialised\n");
436 return -EINVAL;
437 }
438
439 th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
440 if (!th_zone)
441 return -ENOMEM;
442
443 th_zone->sensor_conf = sensor_conf;
444 cpumask_set_cpu(0, &mask_val);
445 th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
446 if (IS_ERR(th_zone->cool_dev[0])) {
447 pr_err("Failed to register cpufreq cooling device\n");
448 ret = -EINVAL;
449 goto err_unregister;
450 }
451 th_zone->cool_dev_size++;
452
453 th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
454 EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
455 IDLE_INTERVAL);
456
457 if (IS_ERR(th_zone->therm_dev)) {
458 pr_err("Failed to register thermal zone device\n");
459 ret = -EINVAL;
460 goto err_unregister;
461 }
462 th_zone->mode = THERMAL_DEVICE_ENABLED;
463
464 pr_info("Exynos: Kernel Thermal management registered\n");
465
466 return 0;
467
468err_unregister:
469 exynos_unregister_thermal();
470 return ret;
471}
472
473/* Un-Register with the in-kernel thermal management */
474static void exynos_unregister_thermal(void)
475{
476 int i;
477
478 if (!th_zone)
479 return;
480
481 if (th_zone->therm_dev)
482 thermal_zone_device_unregister(th_zone->therm_dev);
483
484 for (i = 0; i < th_zone->cool_dev_size; i++) {
485 if (th_zone->cool_dev[i])
486 cpufreq_cooling_unregister(th_zone->cool_dev[i]);
487 }
488
489 kfree(th_zone);
490 pr_info("Exynos: Kernel Thermal management unregistered\n");
491}
492
493/*
494 * TMU treats temperature as a mapped temperature code.
495 * The temperature is converted differently depending on the calibration type.
496 */
497static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
498{
499 struct exynos_tmu_platform_data *pdata = data->pdata;
500 int temp_code;
501
502 if (data->soc == SOC_ARCH_EXYNOS4210)
503 /* temp should range between 25 and 125 */
504 if (temp < 25 || temp > 125) {
505 temp_code = -EINVAL;
506 goto out;
507 }
508
509 switch (pdata->cal_type) {
510 case TYPE_TWO_POINT_TRIMMING:
511 temp_code = (temp - 25) *
512 (data->temp_error2 - data->temp_error1) /
513 (85 - 25) + data->temp_error1;
514 break;
515 case TYPE_ONE_POINT_TRIMMING:
516 temp_code = temp + data->temp_error1 - 25;
517 break;
518 default:
519 temp_code = temp + EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
520 break;
521 }
522out:
523 return temp_code;
524}
525
526/*
527 * Calculate a temperature value from a temperature code.
528 * The unit of the temperature is degree Celsius.
529 */
530static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
531{
532 struct exynos_tmu_platform_data *pdata = data->pdata;
533 int temp;
534
535 if (data->soc == SOC_ARCH_EXYNOS4210)
536 /* temp_code should range between 75 and 175 */
537 if (temp_code < 75 || temp_code > 175) {
538 temp = -ENODATA;
539 goto out;
540 }
541
542 switch (pdata->cal_type) {
543 case TYPE_TWO_POINT_TRIMMING:
544 temp = (temp_code - data->temp_error1) * (85 - 25) /
545 (data->temp_error2 - data->temp_error1) + 25;
546 break;
547 case TYPE_ONE_POINT_TRIMMING:
548 temp = temp_code - data->temp_error1 + 25;
549 break;
550 default:
551 temp = temp_code - EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
552 break;
553 }
554out:
555 return temp;
556}
557
558static int exynos_tmu_initialize(struct platform_device *pdev)
559{
560 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
561 struct exynos_tmu_platform_data *pdata = data->pdata;
562 unsigned int status, trim_info, rising_threshold;
563 int ret = 0, threshold_code;
564
565 mutex_lock(&data->lock);
566 clk_enable(data->clk);
567
568 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
569 if (!status) {
570 ret = -EBUSY;
571 goto out;
572 }
573
574 if (data->soc == SOC_ARCH_EXYNOS) {
575 __raw_writel(EXYNOS_TRIMINFO_RELOAD,
576 data->base + EXYNOS_TMU_TRIMINFO_CON);
577 }
578 /* Save trimming info in order to perform calibration */
579 trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
580 data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
581 data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
582
583 if ((EFUSE_MIN_VALUE > data->temp_error1) ||
584 (data->temp_error1 > EFUSE_MAX_VALUE) ||
585 (data->temp_error2 != 0))
586 data->temp_error1 = pdata->efuse_value;
587
588 if (data->soc == SOC_ARCH_EXYNOS4210) {
589 /* Write temperature code for threshold */
590 threshold_code = temp_to_code(data, pdata->threshold);
591 if (threshold_code < 0) {
592 ret = threshold_code;
593 goto out;
594 }
595 writeb(threshold_code,
596 data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
597
598 writeb(pdata->trigger_levels[0],
599 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0);
600 writeb(pdata->trigger_levels[1],
601 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL1);
602 writeb(pdata->trigger_levels[2],
603 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL2);
604 writeb(pdata->trigger_levels[3],
605 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL3);
606
607 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
608 data->base + EXYNOS_TMU_REG_INTCLEAR);
609 } else if (data->soc == SOC_ARCH_EXYNOS) {
610 /* Write temperature code for threshold */
611 threshold_code = temp_to_code(data, pdata->trigger_levels[0]);
612 if (threshold_code < 0) {
613 ret = threshold_code;
614 goto out;
615 }
616 rising_threshold = threshold_code;
617 threshold_code = temp_to_code(data, pdata->trigger_levels[1]);
618 if (threshold_code < 0) {
619 ret = threshold_code;
620 goto out;
621 }
622 rising_threshold |= (threshold_code << 8);
623 threshold_code = temp_to_code(data, pdata->trigger_levels[2]);
624 if (threshold_code < 0) {
625 ret = threshold_code;
626 goto out;
627 }
628 rising_threshold |= (threshold_code << 16);
629
630 writel(rising_threshold,
631 data->base + EXYNOS_THD_TEMP_RISE);
632 writel(0, data->base + EXYNOS_THD_TEMP_FALL);
633
634 writel(EXYNOS_TMU_CLEAR_RISE_INT|EXYNOS_TMU_CLEAR_FALL_INT,
635 data->base + EXYNOS_TMU_REG_INTCLEAR);
636 }
637out:
638 clk_disable(data->clk);
639 mutex_unlock(&data->lock);
640
641 return ret;
642}
643
644static void exynos_tmu_control(struct platform_device *pdev, bool on)
645{
646 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
647 struct exynos_tmu_platform_data *pdata = data->pdata;
648 unsigned int con, interrupt_en;
649
650 mutex_lock(&data->lock);
651 clk_enable(data->clk);
652
653 con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
654 pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
655
656 if (data->soc == SOC_ARCH_EXYNOS) {
657 con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
658 con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
659 }
660
661 if (on) {
662 con |= EXYNOS_TMU_CORE_ON;
663 interrupt_en = pdata->trigger_level3_en << 12 |
664 pdata->trigger_level2_en << 8 |
665 pdata->trigger_level1_en << 4 |
666 pdata->trigger_level0_en;
667 } else {
668 con |= EXYNOS_TMU_CORE_OFF;
669 interrupt_en = 0; /* Disable all interrupts */
670 }
671 writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
672 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
673
674 clk_disable(data->clk);
675 mutex_unlock(&data->lock);
676}
677
678static int exynos_tmu_read(struct exynos_tmu_data *data)
679{
680 u8 temp_code;
681 int temp;
682
683 mutex_lock(&data->lock);
684 clk_enable(data->clk);
685
686 temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
687 temp = code_to_temp(data, temp_code);
688
689 clk_disable(data->clk);
690 mutex_unlock(&data->lock);
691
692 return temp;
693}
694
695static void exynos_tmu_work(struct work_struct *work)
696{
697 struct exynos_tmu_data *data = container_of(work,
698 struct exynos_tmu_data, irq_work);
699
700 mutex_lock(&data->lock);
701 clk_enable(data->clk);
702
703
704 if (data->soc == SOC_ARCH_EXYNOS)
705 writel(EXYNOS_TMU_CLEAR_RISE_INT,
706 data->base + EXYNOS_TMU_REG_INTCLEAR);
707 else
708 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
709 data->base + EXYNOS_TMU_REG_INTCLEAR);
710
711 clk_disable(data->clk);
712 mutex_unlock(&data->lock);
713 exynos_report_trigger();
714 enable_irq(data->irq);
715}
716
717static irqreturn_t exynos_tmu_irq(int irq, void *id)
718{
719 struct exynos_tmu_data *data = id;
720
721 disable_irq_nosync(irq);
722 schedule_work(&data->irq_work);
723
724 return IRQ_HANDLED;
725}
726static struct thermal_sensor_conf exynos_sensor_conf = {
727 .name = "exynos-therm",
728 .read_temperature = (int (*)(void *))exynos_tmu_read,
729};
730
731#if defined(CONFIG_CPU_EXYNOS4210)
732static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
733 .threshold = 80,
734 .trigger_levels[0] = 5,
735 .trigger_levels[1] = 20,
736 .trigger_levels[2] = 30,
737 .trigger_level0_en = 1,
738 .trigger_level1_en = 1,
739 .trigger_level2_en = 1,
740 .trigger_level3_en = 0,
741 .gain = 15,
742 .reference_voltage = 7,
743 .cal_type = TYPE_ONE_POINT_TRIMMING,
744 .freq_tab[0] = {
745 .freq_clip_max = 800 * 1000,
746 .temp_level = 85,
747 },
748 .freq_tab[1] = {
749 .freq_clip_max = 200 * 1000,
750 .temp_level = 100,
751 },
752 .freq_tab_count = 2,
753 .type = SOC_ARCH_EXYNOS4210,
754};
755#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
756#else
757#define EXYNOS4210_TMU_DRV_DATA (NULL)
758#endif
759
760#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
761static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
762 .trigger_levels[0] = 85,
763 .trigger_levels[1] = 103,
764 .trigger_levels[2] = 110,
765 .trigger_level0_en = 1,
766 .trigger_level1_en = 1,
767 .trigger_level2_en = 1,
768 .trigger_level3_en = 0,
769 .gain = 8,
770 .reference_voltage = 16,
771 .noise_cancel_mode = 4,
772 .cal_type = TYPE_ONE_POINT_TRIMMING,
773 .efuse_value = 55,
774 .freq_tab[0] = {
775 .freq_clip_max = 800 * 1000,
776 .temp_level = 85,
777 },
778 .freq_tab[1] = {
779 .freq_clip_max = 200 * 1000,
780 .temp_level = 103,
781 },
782 .freq_tab_count = 2,
783 .type = SOC_ARCH_EXYNOS,
784};
785#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
786#else
787#define EXYNOS_TMU_DRV_DATA (NULL)
788#endif
789
790#ifdef CONFIG_OF
791static const struct of_device_id exynos_tmu_match[] = {
792 {
793 .compatible = "samsung,exynos4210-tmu",
794 .data = (void *)EXYNOS4210_TMU_DRV_DATA,
795 },
796 {
797 .compatible = "samsung,exynos5250-tmu",
798 .data = (void *)EXYNOS_TMU_DRV_DATA,
799 },
800 {},
801};
802MODULE_DEVICE_TABLE(of, exynos_tmu_match);
803#else
804#define exynos_tmu_match NULL
805#endif
806
807static struct platform_device_id exynos_tmu_driver_ids[] = {
808 {
809 .name = "exynos4210-tmu",
810 .driver_data = (kernel_ulong_t)EXYNOS4210_TMU_DRV_DATA,
811 },
812 {
813 .name = "exynos5250-tmu",
814 .driver_data = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
815 },
816 { },
817};
818MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
819
820static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
821 struct platform_device *pdev)
822{
823#ifdef CONFIG_OF
824 if (pdev->dev.of_node) {
825 const struct of_device_id *match;
826 match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
827 if (!match)
828 return NULL;
829 return (struct exynos_tmu_platform_data *) match->data;
830 }
831#endif
832 return (struct exynos_tmu_platform_data *)
833 platform_get_device_id(pdev)->driver_data;
834}
835static int exynos_tmu_probe(struct platform_device *pdev)
836{
837 struct exynos_tmu_data *data;
838 struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
839 int ret, i;
840
841 if (!pdata)
842 pdata = exynos_get_driver_data(pdev);
843
844 if (!pdata) {
845 dev_err(&pdev->dev, "No platform init data supplied.\n");
846 return -ENODEV;
847 }
848 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
849 GFP_KERNEL);
850 if (!data) {
851 dev_err(&pdev->dev, "Failed to allocate driver structure\n");
852 return -ENOMEM;
853 }
854
855 data->irq = platform_get_irq(pdev, 0);
856 if (data->irq < 0) {
857 dev_err(&pdev->dev, "Failed to get platform irq\n");
858 return data->irq;
859 }
860
861 INIT_WORK(&data->irq_work, exynos_tmu_work);
862
863 data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
864 if (!data->mem) {
865 dev_err(&pdev->dev, "Failed to get platform resource\n");
866 return -ENOENT;
867 }
868
869 data->base = devm_request_and_ioremap(&pdev->dev, data->mem);
870 if (!data->base) {
871 dev_err(&pdev->dev, "Failed to ioremap memory\n");
872 return -ENODEV;
873 }
874
875 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
876 IRQF_TRIGGER_RISING, "exynos-tmu", data);
877 if (ret) {
878 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
879 return ret;
880 }
881
882 data->clk = clk_get(NULL, "tmu_apbif");
883 if (IS_ERR(data->clk)) {
884 dev_err(&pdev->dev, "Failed to get clock\n");
885 return PTR_ERR(data->clk);
886 }
887
888 if (pdata->type == SOC_ARCH_EXYNOS ||
889 pdata->type == SOC_ARCH_EXYNOS4210)
890 data->soc = pdata->type;
891 else {
892 ret = -EINVAL;
893 dev_err(&pdev->dev, "Platform not supported\n");
894 goto err_clk;
895 }
896
897 data->pdata = pdata;
898 platform_set_drvdata(pdev, data);
899 mutex_init(&data->lock);
900
901 ret = exynos_tmu_initialize(pdev);
902 if (ret) {
903 dev_err(&pdev->dev, "Failed to initialize TMU\n");
904 goto err_clk;
905 }
906
907 exynos_tmu_control(pdev, true);
908
909 /* Register the sensor with thermal management interface */
910 (&exynos_sensor_conf)->private_data = data;
911 exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en +
912 pdata->trigger_level1_en + pdata->trigger_level2_en +
913 pdata->trigger_level3_en;
914
915 for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
916 exynos_sensor_conf.trip_data.trip_val[i] =
917 pdata->threshold + pdata->trigger_levels[i];
918
919 exynos_sensor_conf.cooling_data.freq_clip_count =
920 pdata->freq_tab_count;
921 for (i = 0; i < pdata->freq_tab_count; i++) {
922 exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
923 pdata->freq_tab[i].freq_clip_max;
924 exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
925 pdata->freq_tab[i].temp_level;
926 }
927
928 ret = exynos_register_thermal(&exynos_sensor_conf);
929 if (ret) {
930 dev_err(&pdev->dev, "Failed to register thermal interface\n");
931 goto err_clk;
932 }
933 return 0;
934err_clk:
935 platform_set_drvdata(pdev, NULL);
936 clk_put(data->clk);
937 return ret;
938}
939
940static int exynos_tmu_remove(struct platform_device *pdev)
941{
942 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
943
944 exynos_tmu_control(pdev, false);
945
946 exynos_unregister_thermal();
947
948 clk_put(data->clk);
949
950 platform_set_drvdata(pdev, NULL);
951
952 return 0;
953}
954
955#ifdef CONFIG_PM_SLEEP
956static int exynos_tmu_suspend(struct device *dev)
957{
958 exynos_tmu_control(to_platform_device(dev), false);
959
960 return 0;
961}
962
963static int exynos_tmu_resume(struct device *dev)
964{
965 struct platform_device *pdev = to_platform_device(dev);
966
967 exynos_tmu_initialize(pdev);
968 exynos_tmu_control(pdev, true);
969
970 return 0;
971}
972
973static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
974 exynos_tmu_suspend, exynos_tmu_resume);
975#define EXYNOS_TMU_PM (&exynos_tmu_pm)
976#else
977#define EXYNOS_TMU_PM NULL
978#endif
979
980static struct platform_driver exynos_tmu_driver = {
981 .driver = {
982 .name = "exynos-tmu",
983 .owner = THIS_MODULE,
984 .pm = EXYNOS_TMU_PM,
985 .of_match_table = exynos_tmu_match,
986 },
987 .probe = exynos_tmu_probe,
988 .remove = exynos_tmu_remove,
989 .id_table = exynos_tmu_driver_ids,
990};
991
992module_platform_driver(exynos_tmu_driver);
993
994MODULE_DESCRIPTION("EXYNOS TMU Driver");
995MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
996MODULE_LICENSE("GPL");
997MODULE_ALIAS("platform:exynos-tmu");
diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
deleted file mode 100644
index 792479f2b64..00000000000
--- a/drivers/thermal/fair_share.c
+++ /dev/null
@@ -1,133 +0,0 @@
1/*
2 * fair_share.c - A simple weight based Thermal governor
3 *
4 * Copyright (C) 2012 Intel Corp
5 * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/module.h>
28#include <linux/thermal.h>
29
30#include "thermal_core.h"
31
32/**
33 * get_trip_level: - obtains the current trip level for a zone
34 * @tz: thermal zone device
35 */
36static int get_trip_level(struct thermal_zone_device *tz)
37{
38 int count = 0;
39 unsigned long trip_temp;
40
41 if (tz->trips == 0 || !tz->ops->get_trip_temp)
42 return 0;
43
44 for (count = 0; count < tz->trips; count++) {
45 tz->ops->get_trip_temp(tz, count, &trip_temp);
46 if (tz->temperature < trip_temp)
47 break;
48 }
49 return count;
50}
51
52static long get_target_state(struct thermal_zone_device *tz,
53 struct thermal_cooling_device *cdev, int weight, int level)
54{
55 unsigned long max_state;
56
57 cdev->ops->get_max_state(cdev, &max_state);
58
59 return (long)(weight * level * max_state) / (100 * tz->trips);
60}
61
62/**
63 * fair_share_throttle - throttles devices asscciated with the given zone
64 * @tz - thermal_zone_device
65 *
66 * Throttling Logic: This uses three parameters to calculate the new
67 * throttle state of the cooling devices associated with the given zone.
68 *
69 * Parameters used for Throttling:
70 * P1. max_state: Maximum throttle state exposed by the cooling device.
71 * P2. weight[i]/100:
72 * How 'effective' the 'i'th device is, in cooling the given zone.
73 * P3. cur_trip_level/max_no_of_trips:
74 * This describes the extent to which the devices should be throttled.
75 * We do not want to throttle too much when we trip a lower temperature,
76 * whereas the throttling is at full swing if we trip critical levels.
77 * (Heavily assumes the trip points are in ascending order)
78 * new_state of cooling device = P3 * P2 * P1
79 */
80static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
81{
82 const struct thermal_zone_params *tzp;
83 struct thermal_cooling_device *cdev;
84 struct thermal_instance *instance;
85 int i;
86 int cur_trip_level = get_trip_level(tz);
87
88 if (!tz->tzp || !tz->tzp->tbp)
89 return -EINVAL;
90
91 tzp = tz->tzp;
92
93 for (i = 0; i < tzp->num_tbps; i++) {
94 if (!tzp->tbp[i].cdev)
95 continue;
96
97 cdev = tzp->tbp[i].cdev;
98 instance = get_thermal_instance(tz, cdev, trip);
99 if (!instance)
100 continue;
101
102 instance->target = get_target_state(tz, cdev,
103 tzp->tbp[i].weight, cur_trip_level);
104
105 instance->cdev->updated = false;
106 thermal_cdev_update(cdev);
107 }
108 return 0;
109}
110
111static struct thermal_governor thermal_gov_fair_share = {
112 .name = "fair_share",
113 .throttle = fair_share_throttle,
114 .owner = THIS_MODULE,
115};
116
117static int __init thermal_gov_fair_share_init(void)
118{
119 return thermal_register_governor(&thermal_gov_fair_share);
120}
121
122static void __exit thermal_gov_fair_share_exit(void)
123{
124 thermal_unregister_governor(&thermal_gov_fair_share);
125}
126
127/* This should load after thermal framework */
128fs_initcall(thermal_gov_fair_share_init);
129module_exit(thermal_gov_fair_share_exit);
130
131MODULE_AUTHOR("Durgadoss R");
132MODULE_DESCRIPTION("A simple weight based thermal throttling governor");
133MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
deleted file mode 100644
index 90db951725d..00000000000
--- a/drivers/thermal/rcar_thermal.c
+++ /dev/null
@@ -1,249 +0,0 @@
1/*
2 * R-Car THS/TSC thermal sensor driver
3 *
4 * Copyright (C) 2012 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
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 as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20#include <linux/delay.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26#include <linux/spinlock.h>
27#include <linux/thermal.h>
28
29#define THSCR 0x2c
30#define THSSR 0x30
31
32/* THSCR */
33#define CPTAP 0xf
34
35/* THSSR */
36#define CTEMP 0x3f
37
38
39struct rcar_thermal_priv {
40 void __iomem *base;
41 struct device *dev;
42 spinlock_t lock;
43 u32 comp;
44};
45
46#define MCELSIUS(temp) ((temp) * 1000)
47#define rcar_zone_to_priv(zone) (zone->devdata)
48
49/*
50 * basic functions
51 */
52static u32 rcar_thermal_read(struct rcar_thermal_priv *priv, u32 reg)
53{
54 unsigned long flags;
55 u32 ret;
56
57 spin_lock_irqsave(&priv->lock, flags);
58
59 ret = ioread32(priv->base + reg);
60
61 spin_unlock_irqrestore(&priv->lock, flags);
62
63 return ret;
64}
65
66#if 0 /* no user at this point */
67static void rcar_thermal_write(struct rcar_thermal_priv *priv,
68 u32 reg, u32 data)
69{
70 unsigned long flags;
71
72 spin_lock_irqsave(&priv->lock, flags);
73
74 iowrite32(data, priv->base + reg);
75
76 spin_unlock_irqrestore(&priv->lock, flags);
77}
78#endif
79
80static void rcar_thermal_bset(struct rcar_thermal_priv *priv, u32 reg,
81 u32 mask, u32 data)
82{
83 unsigned long flags;
84 u32 val;
85
86 spin_lock_irqsave(&priv->lock, flags);
87
88 val = ioread32(priv->base + reg);
89 val &= ~mask;
90 val |= (data & mask);
91 iowrite32(val, priv->base + reg);
92
93 spin_unlock_irqrestore(&priv->lock, flags);
94}
95
96/*
97 * zone device functions
98 */
99static int rcar_thermal_get_temp(struct thermal_zone_device *zone,
100 unsigned long *temp)
101{
102 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
103 int val, min, max, tmp;
104
105 tmp = -200; /* default */
106 while (1) {
107 if (priv->comp < 1 || priv->comp > 12) {
108 dev_err(priv->dev,
109 "THSSR invalid data (%d)\n", priv->comp);
110 priv->comp = 4; /* for next thermal */
111 return -EINVAL;
112 }
113
114 /*
115 * THS comparator offset and the reference temperature
116 *
117 * Comparator | reference | Temperature field
118 * offset | temperature | measurement
119 * | (degrees C) | (degrees C)
120 * -------------+---------------+-------------------
121 * 1 | -45 | -45 to -30
122 * 2 | -30 | -30 to -15
123 * 3 | -15 | -15 to 0
124 * 4 | 0 | 0 to +15
125 * 5 | +15 | +15 to +30
126 * 6 | +30 | +30 to +45
127 * 7 | +45 | +45 to +60
128 * 8 | +60 | +60 to +75
129 * 9 | +75 | +75 to +90
130 * 10 | +90 | +90 to +105
131 * 11 | +105 | +105 to +120
132 * 12 | +120 | +120 to +135
133 */
134
135 /* calculate thermal limitation */
136 min = (priv->comp * 15) - 60;
137 max = min + 15;
138
139 /*
140 * we need to wait 300us after changing comparator offset
141 * to get stable temperature.
142 * see "Usage Notes" on datasheet
143 */
144 rcar_thermal_bset(priv, THSCR, CPTAP, priv->comp);
145 udelay(300);
146
147 /* calculate current temperature */
148 val = rcar_thermal_read(priv, THSSR) & CTEMP;
149 val = (val * 5) - 65;
150
151 dev_dbg(priv->dev, "comp/min/max/val = %d/%d/%d/%d\n",
152 priv->comp, min, max, val);
153
154 /*
155 * If val is same as min/max, then,
156 * it should try again on next comparator.
157 * But the val might be correct temperature.
158 * Keep it on "tmp" and compare with next val.
159 */
160 if (tmp == val)
161 break;
162
163 if (val <= min) {
164 tmp = min;
165 priv->comp--; /* try again */
166 } else if (val >= max) {
167 tmp = max;
168 priv->comp++; /* try again */
169 } else {
170 tmp = val;
171 break;
172 }
173 }
174
175 *temp = MCELSIUS(tmp);
176 return 0;
177}
178
179static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
180 .get_temp = rcar_thermal_get_temp,
181};
182
183/*
184 * platform functions
185 */
186static int rcar_thermal_probe(struct platform_device *pdev)
187{
188 struct thermal_zone_device *zone;
189 struct rcar_thermal_priv *priv;
190 struct resource *res;
191
192 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
193 if (!res) {
194 dev_err(&pdev->dev, "Could not get platform resource\n");
195 return -ENODEV;
196 }
197
198 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
199 if (!priv) {
200 dev_err(&pdev->dev, "Could not allocate priv\n");
201 return -ENOMEM;
202 }
203
204 priv->comp = 4; /* basic setup */
205 priv->dev = &pdev->dev;
206 spin_lock_init(&priv->lock);
207 priv->base = devm_ioremap_nocache(&pdev->dev,
208 res->start, resource_size(res));
209 if (!priv->base) {
210 dev_err(&pdev->dev, "Unable to ioremap thermal register\n");
211 return -ENOMEM;
212 }
213
214 zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,
215 &rcar_thermal_zone_ops, NULL, 0, 0);
216 if (IS_ERR(zone)) {
217 dev_err(&pdev->dev, "thermal zone device is NULL\n");
218 return PTR_ERR(zone);
219 }
220
221 platform_set_drvdata(pdev, zone);
222
223 dev_info(&pdev->dev, "proved\n");
224
225 return 0;
226}
227
228static int rcar_thermal_remove(struct platform_device *pdev)
229{
230 struct thermal_zone_device *zone = platform_get_drvdata(pdev);
231
232 thermal_zone_device_unregister(zone);
233 platform_set_drvdata(pdev, NULL);
234
235 return 0;
236}
237
238static struct platform_driver rcar_thermal_driver = {
239 .driver = {
240 .name = "rcar_thermal",
241 },
242 .probe = rcar_thermal_probe,
243 .remove = rcar_thermal_remove,
244};
245module_platform_driver(rcar_thermal_driver);
246
247MODULE_LICENSE("GPL");
248MODULE_DESCRIPTION("R-Car THS/TSC thermal sensor driver");
249MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
deleted file mode 100644
index 6b2d8b21aae..00000000000
--- a/drivers/thermal/spear_thermal.c
+++ /dev/null
@@ -1,212 +0,0 @@
1/*
2 * SPEAr thermal driver.
3 *
4 * Copyright (C) 2011-2012 ST Microelectronics
5 * Author: Vincenzo Frascino <vincenzo.frascino@st.com>
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 */
17
18#include <linux/clk.h>
19#include <linux/device.h>
20#include <linux/err.h>
21#include <linux/io.h>
22#include <linux/kernel.h>
23#include <linux/of.h>
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/thermal.h>
27
28#define MD_FACTOR 1000
29
30/* SPEAr Thermal Sensor Dev Structure */
31struct spear_thermal_dev {
32 /* pointer to base address of the thermal sensor */
33 void __iomem *thermal_base;
34 /* clk structure */
35 struct clk *clk;
36 /* pointer to thermal flags */
37 unsigned int flags;
38};
39
40static inline int thermal_get_temp(struct thermal_zone_device *thermal,
41 unsigned long *temp)
42{
43 struct spear_thermal_dev *stdev = thermal->devdata;
44
45 /*
46 * Data are ready to be read after 628 usec from POWERDOWN signal
47 * (PDN) = 1
48 */
49 *temp = (readl_relaxed(stdev->thermal_base) & 0x7F) * MD_FACTOR;
50 return 0;
51}
52
53static struct thermal_zone_device_ops ops = {
54 .get_temp = thermal_get_temp,
55};
56
57#ifdef CONFIG_PM
58static int spear_thermal_suspend(struct device *dev)
59{
60 struct platform_device *pdev = to_platform_device(dev);
61 struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
62 struct spear_thermal_dev *stdev = spear_thermal->devdata;
63 unsigned int actual_mask = 0;
64
65 /* Disable SPEAr Thermal Sensor */
66 actual_mask = readl_relaxed(stdev->thermal_base);
67 writel_relaxed(actual_mask & ~stdev->flags, stdev->thermal_base);
68
69 clk_disable(stdev->clk);
70 dev_info(dev, "Suspended.\n");
71
72 return 0;
73}
74
75static int spear_thermal_resume(struct device *dev)
76{
77 struct platform_device *pdev = to_platform_device(dev);
78 struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
79 struct spear_thermal_dev *stdev = spear_thermal->devdata;
80 unsigned int actual_mask = 0;
81 int ret = 0;
82
83 ret = clk_enable(stdev->clk);
84 if (ret) {
85 dev_err(&pdev->dev, "Can't enable clock\n");
86 return ret;
87 }
88
89 /* Enable SPEAr Thermal Sensor */
90 actual_mask = readl_relaxed(stdev->thermal_base);
91 writel_relaxed(actual_mask | stdev->flags, stdev->thermal_base);
92
93 dev_info(dev, "Resumed.\n");
94
95 return 0;
96}
97#endif
98
99static SIMPLE_DEV_PM_OPS(spear_thermal_pm_ops, spear_thermal_suspend,
100 spear_thermal_resume);
101
102static int spear_thermal_probe(struct platform_device *pdev)
103{
104 struct thermal_zone_device *spear_thermal = NULL;
105 struct spear_thermal_dev *stdev;
106 struct device_node *np = pdev->dev.of_node;
107 struct resource *stres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
108 int ret = 0, val;
109
110 if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) {
111 dev_err(&pdev->dev, "Failed: DT Pdata not passed\n");
112 return -EINVAL;
113 }
114
115 if (!stres) {
116 dev_err(&pdev->dev, "memory resource missing\n");
117 return -ENODEV;
118 }
119
120 stdev = devm_kzalloc(&pdev->dev, sizeof(*stdev), GFP_KERNEL);
121 if (!stdev) {
122 dev_err(&pdev->dev, "kzalloc fail\n");
123 return -ENOMEM;
124 }
125
126 /* Enable thermal sensor */
127 stdev->thermal_base = devm_ioremap(&pdev->dev, stres->start,
128 resource_size(stres));
129 if (!stdev->thermal_base) {
130 dev_err(&pdev->dev, "ioremap failed\n");
131 return -ENOMEM;
132 }
133
134 stdev->clk = clk_get(&pdev->dev, NULL);
135 if (IS_ERR(stdev->clk)) {
136 dev_err(&pdev->dev, "Can't get clock\n");
137 return PTR_ERR(stdev->clk);
138 }
139
140 ret = clk_enable(stdev->clk);
141 if (ret) {
142 dev_err(&pdev->dev, "Can't enable clock\n");
143 goto put_clk;
144 }
145
146 stdev->flags = val;
147 writel_relaxed(stdev->flags, stdev->thermal_base);
148
149 spear_thermal = thermal_zone_device_register("spear_thermal", 0, 0,
150 stdev, &ops, NULL, 0, 0);
151 if (IS_ERR(spear_thermal)) {
152 dev_err(&pdev->dev, "thermal zone device is NULL\n");
153 ret = PTR_ERR(spear_thermal);
154 goto disable_clk;
155 }
156
157 platform_set_drvdata(pdev, spear_thermal);
158
159 dev_info(&spear_thermal->device, "Thermal Sensor Loaded at: 0x%p.\n",
160 stdev->thermal_base);
161
162 return 0;
163
164disable_clk:
165 clk_disable(stdev->clk);
166put_clk:
167 clk_put(stdev->clk);
168
169 return ret;
170}
171
172static int spear_thermal_exit(struct platform_device *pdev)
173{
174 unsigned int actual_mask = 0;
175 struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
176 struct spear_thermal_dev *stdev = spear_thermal->devdata;
177
178 thermal_zone_device_unregister(spear_thermal);
179 platform_set_drvdata(pdev, NULL);
180
181 /* Disable SPEAr Thermal Sensor */
182 actual_mask = readl_relaxed(stdev->thermal_base);
183 writel_relaxed(actual_mask & ~stdev->flags, stdev->thermal_base);
184
185 clk_disable(stdev->clk);
186 clk_put(stdev->clk);
187
188 return 0;
189}
190
191static const struct of_device_id spear_thermal_id_table[] = {
192 { .compatible = "st,thermal-spear1340" },
193 {}
194};
195MODULE_DEVICE_TABLE(of, spear_thermal_id_table);
196
197static struct platform_driver spear_thermal_driver = {
198 .probe = spear_thermal_probe,
199 .remove = spear_thermal_exit,
200 .driver = {
201 .name = "spear_thermal",
202 .owner = THIS_MODULE,
203 .pm = &spear_thermal_pm_ops,
204 .of_match_table = of_match_ptr(spear_thermal_id_table),
205 },
206};
207
208module_platform_driver(spear_thermal_driver);
209
210MODULE_AUTHOR("Vincenzo Frascino <vincenzo.frascino@st.com>");
211MODULE_DESCRIPTION("SPEAr thermal driver");
212MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
deleted file mode 100644
index 0cd5e9fbab1..00000000000
--- a/drivers/thermal/step_wise.c
+++ /dev/null
@@ -1,194 +0,0 @@
1/*
2 * step_wise.c - A step-by-step Thermal throttling governor
3 *
4 * Copyright (C) 2012 Intel Corp
5 * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/module.h>
28#include <linux/thermal.h>
29
30#include "thermal_core.h"
31
32/*
33 * If the temperature is higher than a trip point,
34 * a. if the trend is THERMAL_TREND_RAISING, use higher cooling
35 * state for this trip point
36 * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
37 * state for this trip point
38 */
39static unsigned long get_target_state(struct thermal_instance *instance,
40 enum thermal_trend trend)
41{
42 struct thermal_cooling_device *cdev = instance->cdev;
43 unsigned long cur_state;
44
45 cdev->ops->get_cur_state(cdev, &cur_state);
46
47 if (trend == THERMAL_TREND_RAISING) {
48 cur_state = cur_state < instance->upper ?
49 (cur_state + 1) : instance->upper;
50 } else if (trend == THERMAL_TREND_DROPPING) {
51 cur_state = cur_state > instance->lower ?
52 (cur_state - 1) : instance->lower;
53 }
54
55 return cur_state;
56}
57
58static void update_passive_instance(struct thermal_zone_device *tz,
59 enum thermal_trip_type type, int value)
60{
61 /*
62 * If value is +1, activate a passive instance.
63 * If value is -1, deactivate a passive instance.
64 */
65 if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE)
66 tz->passive += value;
67}
68
69static void update_instance_for_throttle(struct thermal_zone_device *tz,
70 int trip, enum thermal_trip_type trip_type,
71 enum thermal_trend trend)
72{
73 struct thermal_instance *instance;
74
75 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
76 if (instance->trip != trip)
77 continue;
78
79 instance->target = get_target_state(instance, trend);
80
81 /* Activate a passive thermal instance */
82 if (instance->target == THERMAL_NO_TARGET)
83 update_passive_instance(tz, trip_type, 1);
84
85 instance->cdev->updated = false; /* cdev needs update */
86 }
87}
88
89static void update_instance_for_dethrottle(struct thermal_zone_device *tz,
90 int trip, enum thermal_trip_type trip_type)
91{
92 struct thermal_instance *instance;
93 struct thermal_cooling_device *cdev;
94 unsigned long cur_state;
95
96 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
97 if (instance->trip != trip ||
98 instance->target == THERMAL_NO_TARGET)
99 continue;
100
101 cdev = instance->cdev;
102 cdev->ops->get_cur_state(cdev, &cur_state);
103
104 instance->target = cur_state > instance->lower ?
105 (cur_state - 1) : THERMAL_NO_TARGET;
106
107 /* Deactivate a passive thermal instance */
108 if (instance->target == THERMAL_NO_TARGET)
109 update_passive_instance(tz, trip_type, -1);
110
111 cdev->updated = false; /* cdev needs update */
112 }
113}
114
115static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
116{
117 long trip_temp;
118 enum thermal_trip_type trip_type;
119 enum thermal_trend trend;
120
121 if (trip == THERMAL_TRIPS_NONE) {
122 trip_temp = tz->forced_passive;
123 trip_type = THERMAL_TRIPS_NONE;
124 } else {
125 tz->ops->get_trip_temp(tz, trip, &trip_temp);
126 tz->ops->get_trip_type(tz, trip, &trip_type);
127 }
128
129 trend = get_tz_trend(tz, trip);
130
131 mutex_lock(&tz->lock);
132
133 if (tz->temperature >= trip_temp)
134 update_instance_for_throttle(tz, trip, trip_type, trend);
135 else
136 update_instance_for_dethrottle(tz, trip, trip_type);
137
138 mutex_unlock(&tz->lock);
139}
140
141/**
142 * step_wise_throttle - throttles devices asscciated with the given zone
143 * @tz - thermal_zone_device
144 * @trip - the trip point
145 * @trip_type - type of the trip point
146 *
147 * Throttling Logic: This uses the trend of the thermal zone to throttle.
148 * If the thermal zone is 'heating up' this throttles all the cooling
149 * devices associated with the zone and its particular trip point, by one
150 * step. If the zone is 'cooling down' it brings back the performance of
151 * the devices by one step.
152 */
153static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
154{
155 struct thermal_instance *instance;
156
157 thermal_zone_trip_update(tz, trip);
158
159 if (tz->forced_passive)
160 thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE);
161
162 mutex_lock(&tz->lock);
163
164 list_for_each_entry(instance, &tz->thermal_instances, tz_node)
165 thermal_cdev_update(instance->cdev);
166
167 mutex_unlock(&tz->lock);
168
169 return 0;
170}
171
172static struct thermal_governor thermal_gov_step_wise = {
173 .name = "step_wise",
174 .throttle = step_wise_throttle,
175 .owner = THIS_MODULE,
176};
177
178static int __init thermal_gov_step_wise_init(void)
179{
180 return thermal_register_governor(&thermal_gov_step_wise);
181}
182
183static void __exit thermal_gov_step_wise_exit(void)
184{
185 thermal_unregister_governor(&thermal_gov_step_wise);
186}
187
188/* This should load after thermal framework */
189fs_initcall(thermal_gov_step_wise_init);
190module_exit(thermal_gov_step_wise_exit);
191
192MODULE_AUTHOR("Durgadoss R");
193MODULE_DESCRIPTION("A step-by-step thermal throttling governor");
194MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
deleted file mode 100644
index 0d3205a1811..00000000000
--- a/drivers/thermal/thermal_core.h
+++ /dev/null
@@ -1,53 +0,0 @@
1/*
2 * thermal_core.h
3 *
4 * Copyright (C) 2012 Intel Corp
5 * Author: Durgadoss R <durgadoss.r@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 *
21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 */
23
24#ifndef __THERMAL_CORE_H__
25#define __THERMAL_CORE_H__
26
27#include <linux/device.h>
28#include <linux/thermal.h>
29
30/* Initial state of a cooling device during binding */
31#define THERMAL_NO_TARGET -1UL
32
33/*
34 * This structure is used to describe the behavior of
35 * a certain cooling device on a certain trip point
36 * in a certain thermal zone
37 */
38struct thermal_instance {
39 int id;
40 char name[THERMAL_NAME_LENGTH];
41 struct thermal_zone_device *tz;
42 struct thermal_cooling_device *cdev;
43 int trip;
44 unsigned long upper; /* Highest cooling state for this trip point */
45 unsigned long lower; /* Lowest cooling state for this trip point */
46 unsigned long target; /* expected cooling state */
47 char attr_name[THERMAL_NAME_LENGTH];
48 struct device_attribute attr;
49 struct list_head tz_node; /* node in tz->thermal_instances */
50 struct list_head cdev_node; /* node in cdev->thermal_instances */
51};
52
53#endif /* __THERMAL_CORE_H__ */
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 8c8ce806180..708f8e92771 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -23,8 +23,6 @@
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */ 24 */
25 25
26#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
28#include <linux/module.h> 26#include <linux/module.h>
29#include <linux/device.h> 27#include <linux/device.h>
30#include <linux/err.h> 28#include <linux/err.h>
@@ -37,104 +35,38 @@
37#include <net/netlink.h> 35#include <net/netlink.h>
38#include <net/genetlink.h> 36#include <net/genetlink.h>
39 37
40#include "thermal_core.h"
41
42MODULE_AUTHOR("Zhang Rui"); 38MODULE_AUTHOR("Zhang Rui");
43MODULE_DESCRIPTION("Generic thermal management sysfs support"); 39MODULE_DESCRIPTION("Generic thermal management sysfs support");
44MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
45 41
42#define PREFIX "Thermal: "
43
44struct thermal_cooling_device_instance {
45 int id;
46 char name[THERMAL_NAME_LENGTH];
47 struct thermal_zone_device *tz;
48 struct thermal_cooling_device *cdev;
49 int trip;
50 char attr_name[THERMAL_NAME_LENGTH];
51 struct device_attribute attr;
52 struct list_head node;
53};
54
46static DEFINE_IDR(thermal_tz_idr); 55static DEFINE_IDR(thermal_tz_idr);
47static DEFINE_IDR(thermal_cdev_idr); 56static DEFINE_IDR(thermal_cdev_idr);
48static DEFINE_MUTEX(thermal_idr_lock); 57static DEFINE_MUTEX(thermal_idr_lock);
49 58
50static LIST_HEAD(thermal_tz_list); 59static LIST_HEAD(thermal_tz_list);
51static LIST_HEAD(thermal_cdev_list); 60static LIST_HEAD(thermal_cdev_list);
52static LIST_HEAD(thermal_governor_list);
53
54static DEFINE_MUTEX(thermal_list_lock); 61static DEFINE_MUTEX(thermal_list_lock);
55static DEFINE_MUTEX(thermal_governor_lock);
56 62
57static struct thermal_governor *__find_governor(const char *name) 63static unsigned int thermal_event_seqnum;
58{
59 struct thermal_governor *pos;
60
61 list_for_each_entry(pos, &thermal_governor_list, governor_list)
62 if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
63 return pos;
64
65 return NULL;
66}
67
68int thermal_register_governor(struct thermal_governor *governor)
69{
70 int err;
71 const char *name;
72 struct thermal_zone_device *pos;
73
74 if (!governor)
75 return -EINVAL;
76
77 mutex_lock(&thermal_governor_lock);
78
79 err = -EBUSY;
80 if (__find_governor(governor->name) == NULL) {
81 err = 0;
82 list_add(&governor->governor_list, &thermal_governor_list);
83 }
84
85 mutex_lock(&thermal_list_lock);
86
87 list_for_each_entry(pos, &thermal_tz_list, node) {
88 if (pos->governor)
89 continue;
90 if (pos->tzp)
91 name = pos->tzp->governor_name;
92 else
93 name = DEFAULT_THERMAL_GOVERNOR;
94 if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
95 pos->governor = governor;
96 }
97
98 mutex_unlock(&thermal_list_lock);
99 mutex_unlock(&thermal_governor_lock);
100
101 return err;
102}
103EXPORT_SYMBOL_GPL(thermal_register_governor);
104
105void thermal_unregister_governor(struct thermal_governor *governor)
106{
107 struct thermal_zone_device *pos;
108
109 if (!governor)
110 return;
111
112 mutex_lock(&thermal_governor_lock);
113
114 if (__find_governor(governor->name) == NULL)
115 goto exit;
116
117 mutex_lock(&thermal_list_lock);
118
119 list_for_each_entry(pos, &thermal_tz_list, node) {
120 if (!strnicmp(pos->governor->name, governor->name,
121 THERMAL_NAME_LENGTH))
122 pos->governor = NULL;
123 }
124
125 mutex_unlock(&thermal_list_lock);
126 list_del(&governor->governor_list);
127exit:
128 mutex_unlock(&thermal_governor_lock);
129 return;
130}
131EXPORT_SYMBOL_GPL(thermal_unregister_governor);
132 64
133static int get_idr(struct idr *idr, struct mutex *lock, int *id) 65static int get_idr(struct idr *idr, struct mutex *lock, int *id)
134{ 66{
135 int err; 67 int err;
136 68
137again: 69 again:
138 if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0)) 70 if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
139 return -ENOMEM; 71 return -ENOMEM;
140 72
@@ -148,7 +80,7 @@ again:
148 else if (unlikely(err)) 80 else if (unlikely(err))
149 return err; 81 return err;
150 82
151 *id = *id & MAX_IDR_MASK; 83 *id = *id & MAX_ID_MASK;
152 return 0; 84 return 0;
153} 85}
154 86
@@ -161,262 +93,6 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
161 mutex_unlock(lock); 93 mutex_unlock(lock);
162} 94}
163 95
164int get_tz_trend(struct thermal_zone_device *tz, int trip)
165{
166 enum thermal_trend trend;
167
168 if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
169 if (tz->temperature > tz->last_temperature)
170 trend = THERMAL_TREND_RAISING;
171 else if (tz->temperature < tz->last_temperature)
172 trend = THERMAL_TREND_DROPPING;
173 else
174 trend = THERMAL_TREND_STABLE;
175 }
176
177 return trend;
178}
179EXPORT_SYMBOL(get_tz_trend);
180
181struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz,
182 struct thermal_cooling_device *cdev, int trip)
183{
184 struct thermal_instance *pos = NULL;
185 struct thermal_instance *target_instance = NULL;
186
187 mutex_lock(&tz->lock);
188 mutex_lock(&cdev->lock);
189
190 list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
191 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
192 target_instance = pos;
193 break;
194 }
195 }
196
197 mutex_unlock(&cdev->lock);
198 mutex_unlock(&tz->lock);
199
200 return target_instance;
201}
202EXPORT_SYMBOL(get_thermal_instance);
203
204static void print_bind_err_msg(struct thermal_zone_device *tz,
205 struct thermal_cooling_device *cdev, int ret)
206{
207 dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
208 tz->type, cdev->type, ret);
209}
210
211static void __bind(struct thermal_zone_device *tz, int mask,
212 struct thermal_cooling_device *cdev)
213{
214 int i, ret;
215
216 for (i = 0; i < tz->trips; i++) {
217 if (mask & (1 << i)) {
218 ret = thermal_zone_bind_cooling_device(tz, i, cdev,
219 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
220 if (ret)
221 print_bind_err_msg(tz, cdev, ret);
222 }
223 }
224}
225
226static void __unbind(struct thermal_zone_device *tz, int mask,
227 struct thermal_cooling_device *cdev)
228{
229 int i;
230
231 for (i = 0; i < tz->trips; i++)
232 if (mask & (1 << i))
233 thermal_zone_unbind_cooling_device(tz, i, cdev);
234}
235
236static void bind_cdev(struct thermal_cooling_device *cdev)
237{
238 int i, ret;
239 const struct thermal_zone_params *tzp;
240 struct thermal_zone_device *pos = NULL;
241
242 mutex_lock(&thermal_list_lock);
243
244 list_for_each_entry(pos, &thermal_tz_list, node) {
245 if (!pos->tzp && !pos->ops->bind)
246 continue;
247
248 if (!pos->tzp && pos->ops->bind) {
249 ret = pos->ops->bind(pos, cdev);
250 if (ret)
251 print_bind_err_msg(pos, cdev, ret);
252 }
253
254 tzp = pos->tzp;
255 if (!tzp || !tzp->tbp)
256 continue;
257
258 for (i = 0; i < tzp->num_tbps; i++) {
259 if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
260 continue;
261 if (tzp->tbp[i].match(pos, cdev))
262 continue;
263 tzp->tbp[i].cdev = cdev;
264 __bind(pos, tzp->tbp[i].trip_mask, cdev);
265 }
266 }
267
268 mutex_unlock(&thermal_list_lock);
269}
270
271static void bind_tz(struct thermal_zone_device *tz)
272{
273 int i, ret;
274 struct thermal_cooling_device *pos = NULL;
275 const struct thermal_zone_params *tzp = tz->tzp;
276
277 if (!tzp && !tz->ops->bind)
278 return;
279
280 mutex_lock(&thermal_list_lock);
281
282 /* If there is no platform data, try to use ops->bind */
283 if (!tzp && tz->ops->bind) {
284 list_for_each_entry(pos, &thermal_cdev_list, node) {
285 ret = tz->ops->bind(tz, pos);
286 if (ret)
287 print_bind_err_msg(tz, pos, ret);
288 }
289 goto exit;
290 }
291
292 if (!tzp || !tzp->tbp)
293 goto exit;
294
295 list_for_each_entry(pos, &thermal_cdev_list, node) {
296 for (i = 0; i < tzp->num_tbps; i++) {
297 if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
298 continue;
299 if (tzp->tbp[i].match(tz, pos))
300 continue;
301 tzp->tbp[i].cdev = pos;
302 __bind(tz, tzp->tbp[i].trip_mask, pos);
303 }
304 }
305exit:
306 mutex_unlock(&thermal_list_lock);
307}
308
309static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
310 int delay)
311{
312 if (delay > 1000)
313 mod_delayed_work(system_freezable_wq, &tz->poll_queue,
314 round_jiffies(msecs_to_jiffies(delay)));
315 else if (delay)
316 mod_delayed_work(system_freezable_wq, &tz->poll_queue,
317 msecs_to_jiffies(delay));
318 else
319 cancel_delayed_work(&tz->poll_queue);
320}
321
322static void monitor_thermal_zone(struct thermal_zone_device *tz)
323{
324 mutex_lock(&tz->lock);
325
326 if (tz->passive)
327 thermal_zone_device_set_polling(tz, tz->passive_delay);
328 else if (tz->polling_delay)
329 thermal_zone_device_set_polling(tz, tz->polling_delay);
330 else
331 thermal_zone_device_set_polling(tz, 0);
332
333 mutex_unlock(&tz->lock);
334}
335
336static void handle_non_critical_trips(struct thermal_zone_device *tz,
337 int trip, enum thermal_trip_type trip_type)
338{
339 if (tz->governor)
340 tz->governor->throttle(tz, trip);
341}
342
343static void handle_critical_trips(struct thermal_zone_device *tz,
344 int trip, enum thermal_trip_type trip_type)
345{
346 long trip_temp;
347
348 tz->ops->get_trip_temp(tz, trip, &trip_temp);
349
350 /* If we have not crossed the trip_temp, we do not care. */
351 if (tz->temperature < trip_temp)
352 return;
353
354 if (tz->ops->notify)
355 tz->ops->notify(tz, trip, trip_type);
356
357 if (trip_type == THERMAL_TRIP_CRITICAL) {
358 pr_emerg("Critical temperature reached(%d C),shutting down\n",
359 tz->temperature / 1000);
360 orderly_poweroff(true);
361 }
362}
363
364static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
365{
366 enum thermal_trip_type type;
367
368 tz->ops->get_trip_type(tz, trip, &type);
369
370 if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
371 handle_critical_trips(tz, trip, type);
372 else
373 handle_non_critical_trips(tz, trip, type);
374 /*
375 * Alright, we handled this trip successfully.
376 * So, start monitoring again.
377 */
378 monitor_thermal_zone(tz);
379}
380
381static void update_temperature(struct thermal_zone_device *tz)
382{
383 long temp;
384 int ret;
385
386 mutex_lock(&tz->lock);
387
388 ret = tz->ops->get_temp(tz, &temp);
389 if (ret) {
390 pr_warn("failed to read out thermal zone %d\n", tz->id);
391 goto exit;
392 }
393
394 tz->last_temperature = tz->temperature;
395 tz->temperature = temp;
396
397exit:
398 mutex_unlock(&tz->lock);
399}
400
401void thermal_zone_device_update(struct thermal_zone_device *tz)
402{
403 int count;
404
405 update_temperature(tz);
406
407 for (count = 0; count < tz->trips; count++)
408 handle_thermal_trip(tz, count);
409}
410EXPORT_SYMBOL(thermal_zone_device_update);
411
412static void thermal_zone_device_check(struct work_struct *work)
413{
414 struct thermal_zone_device *tz = container_of(work, struct
415 thermal_zone_device,
416 poll_queue.work);
417 thermal_zone_device_update(tz);
418}
419
420/* sys I/F for thermal zone */ 96/* sys I/F for thermal zone */
421 97
422#define to_thermal_zone(_dev) \ 98#define to_thermal_zone(_dev) \
@@ -476,9 +152,9 @@ mode_store(struct device *dev, struct device_attribute *attr,
476 if (!tz->ops->set_mode) 152 if (!tz->ops->set_mode)
477 return -EPERM; 153 return -EPERM;
478 154
479 if (!strncmp(buf, "enabled", sizeof("enabled") - 1)) 155 if (!strncmp(buf, "enabled", sizeof("enabled")))
480 result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED); 156 result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
481 else if (!strncmp(buf, "disabled", sizeof("disabled") - 1)) 157 else if (!strncmp(buf, "disabled", sizeof("disabled")))
482 result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED); 158 result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
483 else 159 else
484 result = -EINVAL; 160 result = -EINVAL;
@@ -522,28 +198,6 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
522} 198}
523 199
524static ssize_t 200static ssize_t
525trip_point_temp_store(struct device *dev, struct device_attribute *attr,
526 const char *buf, size_t count)
527{
528 struct thermal_zone_device *tz = to_thermal_zone(dev);
529 int trip, ret;
530 unsigned long temperature;
531
532 if (!tz->ops->set_trip_temp)
533 return -EPERM;
534
535 if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
536 return -EINVAL;
537
538 if (kstrtoul(buf, 10, &temperature))
539 return -EINVAL;
540
541 ret = tz->ops->set_trip_temp(tz, trip, temperature);
542
543 return ret ? ret : count;
544}
545
546static ssize_t
547trip_point_temp_show(struct device *dev, struct device_attribute *attr, 201trip_point_temp_show(struct device *dev, struct device_attribute *attr,
548 char *buf) 202 char *buf)
549{ 203{
@@ -566,52 +220,6 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
566} 220}
567 221
568static ssize_t 222static ssize_t
569trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
570 const char *buf, size_t count)
571{
572 struct thermal_zone_device *tz = to_thermal_zone(dev);
573 int trip, ret;
574 unsigned long temperature;
575
576 if (!tz->ops->set_trip_hyst)
577 return -EPERM;
578
579 if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
580 return -EINVAL;
581
582 if (kstrtoul(buf, 10, &temperature))
583 return -EINVAL;
584
585 /*
586 * We are not doing any check on the 'temperature' value
587 * here. The driver implementing 'set_trip_hyst' has to
588 * take care of this.
589 */
590 ret = tz->ops->set_trip_hyst(tz, trip, temperature);
591
592 return ret ? ret : count;
593}
594
595static ssize_t
596trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
597 char *buf)
598{
599 struct thermal_zone_device *tz = to_thermal_zone(dev);
600 int trip, ret;
601 unsigned long temperature;
602
603 if (!tz->ops->get_trip_hyst)
604 return -EPERM;
605
606 if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
607 return -EINVAL;
608
609 ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
610
611 return ret ? ret : sprintf(buf, "%ld\n", temperature);
612}
613
614static ssize_t
615passive_store(struct device *dev, struct device_attribute *attr, 223passive_store(struct device *dev, struct device_attribute *attr,
616 const char *buf, size_t count) 224 const char *buf, size_t count)
617{ 225{
@@ -634,9 +242,8 @@ passive_store(struct device *dev, struct device_attribute *attr,
634 if (!strncmp("Processor", cdev->type, 242 if (!strncmp("Processor", cdev->type,
635 sizeof("Processor"))) 243 sizeof("Processor")))
636 thermal_zone_bind_cooling_device(tz, 244 thermal_zone_bind_cooling_device(tz,
637 THERMAL_TRIPS_NONE, cdev, 245 THERMAL_TRIPS_NONE,
638 THERMAL_NO_LIMIT, 246 cdev);
639 THERMAL_NO_LIMIT);
640 } 247 }
641 mutex_unlock(&thermal_list_lock); 248 mutex_unlock(&thermal_list_lock);
642 if (!tz->passive_delay) 249 if (!tz->passive_delay)
@@ -654,6 +261,9 @@ passive_store(struct device *dev, struct device_attribute *attr,
654 tz->passive_delay = 0; 261 tz->passive_delay = 0;
655 } 262 }
656 263
264 tz->tc1 = 1;
265 tz->tc2 = 1;
266
657 tz->forced_passive = state; 267 tz->forced_passive = state;
658 268
659 thermal_zone_device_update(tz); 269 thermal_zone_device_update(tz);
@@ -670,41 +280,54 @@ passive_show(struct device *dev, struct device_attribute *attr,
670 return sprintf(buf, "%d\n", tz->forced_passive); 280 return sprintf(buf, "%d\n", tz->forced_passive);
671} 281}
672 282
673static ssize_t
674policy_store(struct device *dev, struct device_attribute *attr,
675 const char *buf, size_t count)
676{
677 int ret = -EINVAL;
678 struct thermal_zone_device *tz = to_thermal_zone(dev);
679 struct thermal_governor *gov;
680
681 mutex_lock(&thermal_governor_lock);
682
683 gov = __find_governor(buf);
684 if (!gov)
685 goto exit;
686
687 tz->governor = gov;
688 ret = count;
689
690exit:
691 mutex_unlock(&thermal_governor_lock);
692 return ret;
693}
694
695static ssize_t
696policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
697{
698 struct thermal_zone_device *tz = to_thermal_zone(dev);
699
700 return sprintf(buf, "%s\n", tz->governor->name);
701}
702
703static DEVICE_ATTR(type, 0444, type_show, NULL); 283static DEVICE_ATTR(type, 0444, type_show, NULL);
704static DEVICE_ATTR(temp, 0444, temp_show, NULL); 284static DEVICE_ATTR(temp, 0444, temp_show, NULL);
705static DEVICE_ATTR(mode, 0644, mode_show, mode_store); 285static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
706static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); 286static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, \
707static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store); 287 passive_store);
288
289static struct device_attribute trip_point_attrs[] = {
290 __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
291 __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
292 __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
293 __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
294 __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
295 __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
296 __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
297 __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
298 __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
299 __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
300 __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
301 __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
302 __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
303 __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
304 __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
305 __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
306 __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
307 __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
308 __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
309 __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
310 __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL),
311 __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL),
312 __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL),
313 __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL),
314};
315
316#define TRIP_POINT_ATTR_ADD(_dev, _index, result) \
317do { \
318 result = device_create_file(_dev, \
319 &trip_point_attrs[_index * 2]); \
320 if (result) \
321 break; \
322 result = device_create_file(_dev, \
323 &trip_point_attrs[_index * 2 + 1]); \
324} while (0)
325
326#define TRIP_POINT_ATTR_REMOVE(_dev, _index) \
327do { \
328 device_remove_file(_dev, &trip_point_attrs[_index * 2]); \
329 device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \
330} while (0)
708 331
709/* sys I/F for cooling device */ 332/* sys I/F for cooling device */
710#define to_cooling_device(_dev) \ 333#define to_cooling_device(_dev) \
@@ -780,10 +403,10 @@ static ssize_t
780thermal_cooling_device_trip_point_show(struct device *dev, 403thermal_cooling_device_trip_point_show(struct device *dev,
781 struct device_attribute *attr, char *buf) 404 struct device_attribute *attr, char *buf)
782{ 405{
783 struct thermal_instance *instance; 406 struct thermal_cooling_device_instance *instance;
784 407
785 instance = 408 instance =
786 container_of(attr, struct thermal_instance, attr); 409 container_of(attr, struct thermal_cooling_device_instance, attr);
787 410
788 if (instance->trip == THERMAL_TRIPS_NONE) 411 if (instance->trip == THERMAL_TRIPS_NONE)
789 return sprintf(buf, "-1\n"); 412 return sprintf(buf, "-1\n");
@@ -945,7 +568,7 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
945 temp->tz = tz; 568 temp->tz = tz;
946 hwmon->count++; 569 hwmon->count++;
947 570
948 snprintf(temp->temp_input.name, sizeof(temp->temp_input.name), 571 snprintf(temp->temp_input.name, THERMAL_NAME_LENGTH,
949 "temp%d_input", hwmon->count); 572 "temp%d_input", hwmon->count);
950 temp->temp_input.attr.attr.name = temp->temp_input.name; 573 temp->temp_input.attr.attr.name = temp->temp_input.name;
951 temp->temp_input.attr.attr.mode = 0444; 574 temp->temp_input.attr.attr.mode = 0444;
@@ -958,8 +581,7 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
958 if (tz->ops->get_crit_temp) { 581 if (tz->ops->get_crit_temp) {
959 unsigned long temperature; 582 unsigned long temperature;
960 if (!tz->ops->get_crit_temp(tz, &temperature)) { 583 if (!tz->ops->get_crit_temp(tz, &temperature)) {
961 snprintf(temp->temp_crit.name, 584 snprintf(temp->temp_crit.name, THERMAL_NAME_LENGTH,
962 sizeof(temp->temp_crit.name),
963 "temp%d_crit", hwmon->count); 585 "temp%d_crit", hwmon->count);
964 temp->temp_crit.attr.attr.name = temp->temp_crit.name; 586 temp->temp_crit.attr.attr.name = temp->temp_crit.name;
965 temp->temp_crit.attr.attr.mode = 0444; 587 temp->temp_crit.attr.attr.mode = 0444;
@@ -1047,6 +669,98 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
1047} 669}
1048#endif 670#endif
1049 671
672static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
673 int delay)
674{
675 cancel_delayed_work(&(tz->poll_queue));
676
677 if (!delay)
678 return;
679
680 if (delay > 1000)
681 schedule_delayed_work(&(tz->poll_queue),
682 round_jiffies(msecs_to_jiffies(delay)));
683 else
684 schedule_delayed_work(&(tz->poll_queue),
685 msecs_to_jiffies(delay));
686}
687
688static void thermal_zone_device_passive(struct thermal_zone_device *tz,
689 int temp, int trip_temp, int trip)
690{
691 int trend = 0;
692 struct thermal_cooling_device_instance *instance;
693 struct thermal_cooling_device *cdev;
694 long state, max_state;
695
696 /*
697 * Above Trip?
698 * -----------
699 * Calculate the thermal trend (using the passive cooling equation)
700 * and modify the performance limit for all passive cooling devices
701 * accordingly. Note that we assume symmetry.
702 */
703 if (temp >= trip_temp) {
704 tz->passive = true;
705
706 trend = (tz->tc1 * (temp - tz->last_temperature)) +
707 (tz->tc2 * (temp - trip_temp));
708
709 /* Heating up? */
710 if (trend > 0) {
711 list_for_each_entry(instance, &tz->cooling_devices,
712 node) {
713 if (instance->trip != trip)
714 continue;
715 cdev = instance->cdev;
716 cdev->ops->get_cur_state(cdev, &state);
717 cdev->ops->get_max_state(cdev, &max_state);
718 if (state++ < max_state)
719 cdev->ops->set_cur_state(cdev, state);
720 }
721 } else if (trend < 0) { /* Cooling off? */
722 list_for_each_entry(instance, &tz->cooling_devices,
723 node) {
724 if (instance->trip != trip)
725 continue;
726 cdev = instance->cdev;
727 cdev->ops->get_cur_state(cdev, &state);
728 cdev->ops->get_max_state(cdev, &max_state);
729 if (state > 0)
730 cdev->ops->set_cur_state(cdev, --state);
731 }
732 }
733 return;
734 }
735
736 /*
737 * Below Trip?
738 * -----------
739 * Implement passive cooling hysteresis to slowly increase performance
740 * and avoid thrashing around the passive trip point. Note that we
741 * assume symmetry.
742 */
743 list_for_each_entry(instance, &tz->cooling_devices, node) {
744 if (instance->trip != trip)
745 continue;
746 cdev = instance->cdev;
747 cdev->ops->get_cur_state(cdev, &state);
748 cdev->ops->get_max_state(cdev, &max_state);
749 if (state > 0)
750 cdev->ops->set_cur_state(cdev, --state);
751 if (state == 0)
752 tz->passive = false;
753 }
754}
755
756static void thermal_zone_device_check(struct work_struct *work)
757{
758 struct thermal_zone_device *tz = container_of(work, struct
759 thermal_zone_device,
760 poll_queue.work);
761 thermal_zone_device_update(tz);
762}
763
1050/** 764/**
1051 * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone 765 * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
1052 * @tz: thermal zone device 766 * @tz: thermal zone device
@@ -1058,14 +772,12 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
1058 */ 772 */
1059int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, 773int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
1060 int trip, 774 int trip,
1061 struct thermal_cooling_device *cdev, 775 struct thermal_cooling_device *cdev)
1062 unsigned long upper, unsigned long lower)
1063{ 776{
1064 struct thermal_instance *dev; 777 struct thermal_cooling_device_instance *dev;
1065 struct thermal_instance *pos; 778 struct thermal_cooling_device_instance *pos;
1066 struct thermal_zone_device *pos1; 779 struct thermal_zone_device *pos1;
1067 struct thermal_cooling_device *pos2; 780 struct thermal_cooling_device *pos2;
1068 unsigned long max_state;
1069 int result; 781 int result;
1070 782
1071 if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) 783 if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
@@ -1083,26 +795,13 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
1083 if (tz != pos1 || cdev != pos2) 795 if (tz != pos1 || cdev != pos2)
1084 return -EINVAL; 796 return -EINVAL;
1085 797
1086 cdev->ops->get_max_state(cdev, &max_state);
1087
1088 /* lower default 0, upper default max_state */
1089 lower = lower == THERMAL_NO_LIMIT ? 0 : lower;
1090 upper = upper == THERMAL_NO_LIMIT ? max_state : upper;
1091
1092 if (lower > upper || upper > max_state)
1093 return -EINVAL;
1094
1095 dev = 798 dev =
1096 kzalloc(sizeof(struct thermal_instance), GFP_KERNEL); 799 kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
1097 if (!dev) 800 if (!dev)
1098 return -ENOMEM; 801 return -ENOMEM;
1099 dev->tz = tz; 802 dev->tz = tz;
1100 dev->cdev = cdev; 803 dev->cdev = cdev;
1101 dev->trip = trip; 804 dev->trip = trip;
1102 dev->upper = upper;
1103 dev->lower = lower;
1104 dev->target = THERMAL_NO_TARGET;
1105
1106 result = get_idr(&tz->idr, &tz->lock, &dev->id); 805 result = get_idr(&tz->idr, &tz->lock, &dev->id);
1107 if (result) 806 if (result)
1108 goto free_mem; 807 goto free_mem;
@@ -1123,31 +822,28 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
1123 goto remove_symbol_link; 822 goto remove_symbol_link;
1124 823
1125 mutex_lock(&tz->lock); 824 mutex_lock(&tz->lock);
1126 mutex_lock(&cdev->lock); 825 list_for_each_entry(pos, &tz->cooling_devices, node)
1127 list_for_each_entry(pos, &tz->thermal_instances, tz_node)
1128 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { 826 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
1129 result = -EEXIST; 827 result = -EEXIST;
1130 break; 828 break;
1131 } 829 }
1132 if (!result) { 830 if (!result)
1133 list_add_tail(&dev->tz_node, &tz->thermal_instances); 831 list_add_tail(&dev->node, &tz->cooling_devices);
1134 list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
1135 }
1136 mutex_unlock(&cdev->lock);
1137 mutex_unlock(&tz->lock); 832 mutex_unlock(&tz->lock);
1138 833
1139 if (!result) 834 if (!result)
1140 return 0; 835 return 0;
1141 836
1142 device_remove_file(&tz->device, &dev->attr); 837 device_remove_file(&tz->device, &dev->attr);
1143remove_symbol_link: 838 remove_symbol_link:
1144 sysfs_remove_link(&tz->device.kobj, dev->name); 839 sysfs_remove_link(&tz->device.kobj, dev->name);
1145release_idr: 840 release_idr:
1146 release_idr(&tz->idr, &tz->lock, dev->id); 841 release_idr(&tz->idr, &tz->lock, dev->id);
1147free_mem: 842 free_mem:
1148 kfree(dev); 843 kfree(dev);
1149 return result; 844 return result;
1150} 845}
846
1151EXPORT_SYMBOL(thermal_zone_bind_cooling_device); 847EXPORT_SYMBOL(thermal_zone_bind_cooling_device);
1152 848
1153/** 849/**
@@ -1163,31 +859,28 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
1163 int trip, 859 int trip,
1164 struct thermal_cooling_device *cdev) 860 struct thermal_cooling_device *cdev)
1165{ 861{
1166 struct thermal_instance *pos, *next; 862 struct thermal_cooling_device_instance *pos, *next;
1167 863
1168 mutex_lock(&tz->lock); 864 mutex_lock(&tz->lock);
1169 mutex_lock(&cdev->lock); 865 list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
1170 list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) {
1171 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { 866 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
1172 list_del(&pos->tz_node); 867 list_del(&pos->node);
1173 list_del(&pos->cdev_node);
1174 mutex_unlock(&cdev->lock);
1175 mutex_unlock(&tz->lock); 868 mutex_unlock(&tz->lock);
1176 goto unbind; 869 goto unbind;
1177 } 870 }
1178 } 871 }
1179 mutex_unlock(&cdev->lock);
1180 mutex_unlock(&tz->lock); 872 mutex_unlock(&tz->lock);
1181 873
1182 return -ENODEV; 874 return -ENODEV;
1183 875
1184unbind: 876 unbind:
1185 device_remove_file(&tz->device, &pos->attr); 877 device_remove_file(&tz->device, &pos->attr);
1186 sysfs_remove_link(&tz->device.kobj, pos->name); 878 sysfs_remove_link(&tz->device.kobj, pos->name);
1187 release_idr(&tz->idr, &tz->lock, pos->id); 879 release_idr(&tz->idr, &tz->lock, pos->id);
1188 kfree(pos); 880 kfree(pos);
1189 return 0; 881 return 0;
1190} 882}
883
1191EXPORT_SYMBOL(thermal_zone_unbind_cooling_device); 884EXPORT_SYMBOL(thermal_zone_unbind_cooling_device);
1192 885
1193static void thermal_release(struct device *dev) 886static void thermal_release(struct device *dev)
@@ -1195,8 +888,7 @@ static void thermal_release(struct device *dev)
1195 struct thermal_zone_device *tz; 888 struct thermal_zone_device *tz;
1196 struct thermal_cooling_device *cdev; 889 struct thermal_cooling_device *cdev;
1197 890
1198 if (!strncmp(dev_name(dev), "thermal_zone", 891 if (!strncmp(dev_name(dev), "thermal_zone", sizeof "thermal_zone" - 1)) {
1199 sizeof("thermal_zone") - 1)) {
1200 tz = to_thermal_zone(dev); 892 tz = to_thermal_zone(dev);
1201 kfree(tz); 893 kfree(tz);
1202 } else { 894 } else {
@@ -1216,14 +908,14 @@ static struct class thermal_class = {
1216 * @devdata: device private data. 908 * @devdata: device private data.
1217 * @ops: standard thermal cooling devices callbacks. 909 * @ops: standard thermal cooling devices callbacks.
1218 */ 910 */
1219struct thermal_cooling_device * 911struct thermal_cooling_device *thermal_cooling_device_register(
1220thermal_cooling_device_register(char *type, void *devdata, 912 char *type, void *devdata, const struct thermal_cooling_device_ops *ops)
1221 const struct thermal_cooling_device_ops *ops)
1222{ 913{
1223 struct thermal_cooling_device *cdev; 914 struct thermal_cooling_device *cdev;
915 struct thermal_zone_device *pos;
1224 int result; 916 int result;
1225 917
1226 if (type && strlen(type) >= THERMAL_NAME_LENGTH) 918 if (strlen(type) >= THERMAL_NAME_LENGTH)
1227 return ERR_PTR(-EINVAL); 919 return ERR_PTR(-EINVAL);
1228 920
1229 if (!ops || !ops->get_max_state || !ops->get_cur_state || 921 if (!ops || !ops->get_max_state || !ops->get_cur_state ||
@@ -1240,11 +932,8 @@ thermal_cooling_device_register(char *type, void *devdata,
1240 return ERR_PTR(result); 932 return ERR_PTR(result);
1241 } 933 }
1242 934
1243 strcpy(cdev->type, type ? : ""); 935 strcpy(cdev->type, type);
1244 mutex_init(&cdev->lock);
1245 INIT_LIST_HEAD(&cdev->thermal_instances);
1246 cdev->ops = ops; 936 cdev->ops = ops;
1247 cdev->updated = true;
1248 cdev->device.class = &thermal_class; 937 cdev->device.class = &thermal_class;
1249 cdev->devdata = devdata; 938 cdev->devdata = devdata;
1250 dev_set_name(&cdev->device, "cooling_device%d", cdev->id); 939 dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
@@ -1270,21 +959,27 @@ thermal_cooling_device_register(char *type, void *devdata,
1270 if (result) 959 if (result)
1271 goto unregister; 960 goto unregister;
1272 961
1273 /* Add 'this' new cdev to the global cdev list */
1274 mutex_lock(&thermal_list_lock); 962 mutex_lock(&thermal_list_lock);
1275 list_add(&cdev->node, &thermal_cdev_list); 963 list_add(&cdev->node, &thermal_cdev_list);
1276 mutex_unlock(&thermal_list_lock); 964 list_for_each_entry(pos, &thermal_tz_list, node) {
965 if (!pos->ops->bind)
966 continue;
967 result = pos->ops->bind(pos, cdev);
968 if (result)
969 break;
1277 970
1278 /* Update binding information for 'this' new cdev */ 971 }
1279 bind_cdev(cdev); 972 mutex_unlock(&thermal_list_lock);
1280 973
1281 return cdev; 974 if (!result)
975 return cdev;
1282 976
1283unregister: 977 unregister:
1284 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); 978 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
1285 device_unregister(&cdev->device); 979 device_unregister(&cdev->device);
1286 return ERR_PTR(result); 980 return ERR_PTR(result);
1287} 981}
982
1288EXPORT_SYMBOL(thermal_cooling_device_register); 983EXPORT_SYMBOL(thermal_cooling_device_register);
1289 984
1290/** 985/**
@@ -1294,10 +989,10 @@ EXPORT_SYMBOL(thermal_cooling_device_register);
1294 * thermal_cooling_device_unregister() must be called when the device is no 989 * thermal_cooling_device_unregister() must be called when the device is no
1295 * longer needed. 990 * longer needed.
1296 */ 991 */
1297void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) 992void thermal_cooling_device_unregister(struct
993 thermal_cooling_device
994 *cdev)
1298{ 995{
1299 int i;
1300 const struct thermal_zone_params *tzp;
1301 struct thermal_zone_device *tz; 996 struct thermal_zone_device *tz;
1302 struct thermal_cooling_device *pos = NULL; 997 struct thermal_cooling_device *pos = NULL;
1303 998
@@ -1314,28 +1009,12 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
1314 return; 1009 return;
1315 } 1010 }
1316 list_del(&cdev->node); 1011 list_del(&cdev->node);
1317
1318 /* Unbind all thermal zones associated with 'this' cdev */
1319 list_for_each_entry(tz, &thermal_tz_list, node) { 1012 list_for_each_entry(tz, &thermal_tz_list, node) {
1320 if (tz->ops->unbind) { 1013 if (!tz->ops->unbind)
1321 tz->ops->unbind(tz, cdev);
1322 continue;
1323 }
1324
1325 if (!tz->tzp || !tz->tzp->tbp)
1326 continue; 1014 continue;
1327 1015 tz->ops->unbind(tz, cdev);
1328 tzp = tz->tzp;
1329 for (i = 0; i < tzp->num_tbps; i++) {
1330 if (tzp->tbp[i].cdev == cdev) {
1331 __unbind(tz, tzp->tbp[i].trip_mask, cdev);
1332 tzp->tbp[i].cdev = NULL;
1333 }
1334 }
1335 } 1016 }
1336
1337 mutex_unlock(&thermal_list_lock); 1017 mutex_unlock(&thermal_list_lock);
1338
1339 if (cdev->type[0]) 1018 if (cdev->type[0])
1340 device_remove_file(&cdev->device, &dev_attr_cdev_type); 1019 device_remove_file(&cdev->device, &dev_attr_cdev_type);
1341 device_remove_file(&cdev->device, &dev_attr_max_state); 1020 device_remove_file(&cdev->device, &dev_attr_max_state);
@@ -1345,160 +1024,101 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
1345 device_unregister(&cdev->device); 1024 device_unregister(&cdev->device);
1346 return; 1025 return;
1347} 1026}
1348EXPORT_SYMBOL(thermal_cooling_device_unregister);
1349
1350void thermal_cdev_update(struct thermal_cooling_device *cdev)
1351{
1352 struct thermal_instance *instance;
1353 unsigned long target = 0;
1354
1355 /* cooling device is updated*/
1356 if (cdev->updated)
1357 return;
1358 1027
1359 mutex_lock(&cdev->lock); 1028EXPORT_SYMBOL(thermal_cooling_device_unregister);
1360 /* Make sure cdev enters the deepest cooling state */
1361 list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
1362 if (instance->target == THERMAL_NO_TARGET)
1363 continue;
1364 if (instance->target > target)
1365 target = instance->target;
1366 }
1367 mutex_unlock(&cdev->lock);
1368 cdev->ops->set_cur_state(cdev, target);
1369 cdev->updated = true;
1370}
1371EXPORT_SYMBOL(thermal_cdev_update);
1372 1029
1373/** 1030/**
1374 * notify_thermal_framework - Sensor drivers use this API to notify framework 1031 * thermal_zone_device_update - force an update of a thermal zone's state
1375 * @tz: thermal zone device 1032 * @ttz: the thermal zone to update
1376 * @trip: indicates which trip point has been crossed
1377 *
1378 * This function handles the trip events from sensor drivers. It starts
1379 * throttling the cooling devices according to the policy configured.
1380 * For CRITICAL and HOT trip points, this notifies the respective drivers,
1381 * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
1382 * The throttling policy is based on the configured platform data; if no
1383 * platform data is provided, this uses the step_wise throttling policy.
1384 */ 1033 */
1385void notify_thermal_framework(struct thermal_zone_device *tz, int trip)
1386{
1387 handle_thermal_trip(tz, trip);
1388}
1389EXPORT_SYMBOL(notify_thermal_framework);
1390 1034
1391/** 1035void thermal_zone_device_update(struct thermal_zone_device *tz)
1392 * create_trip_attrs - create attributes for trip points
1393 * @tz: the thermal zone device
1394 * @mask: Writeable trip point bitmap.
1395 */
1396static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
1397{ 1036{
1398 int indx; 1037 int count, ret = 0;
1399 int size = sizeof(struct thermal_attr) * tz->trips; 1038 long temp, trip_temp;
1039 enum thermal_trip_type trip_type;
1040 struct thermal_cooling_device_instance *instance;
1041 struct thermal_cooling_device *cdev;
1400 1042
1401 tz->trip_type_attrs = kzalloc(size, GFP_KERNEL); 1043 mutex_lock(&tz->lock);
1402 if (!tz->trip_type_attrs)
1403 return -ENOMEM;
1404 1044
1405 tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL); 1045 if (tz->ops->get_temp(tz, &temp)) {
1406 if (!tz->trip_temp_attrs) { 1046 /* get_temp failed - retry it later */
1407 kfree(tz->trip_type_attrs); 1047 printk(KERN_WARNING PREFIX "failed to read out thermal zone "
1408 return -ENOMEM; 1048 "%d\n", tz->id);
1049 goto leave;
1409 } 1050 }
1410 1051
1411 if (tz->ops->get_trip_hyst) { 1052 for (count = 0; count < tz->trips; count++) {
1412 tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL); 1053 tz->ops->get_trip_type(tz, count, &trip_type);
1413 if (!tz->trip_hyst_attrs) { 1054 tz->ops->get_trip_temp(tz, count, &trip_temp);
1414 kfree(tz->trip_type_attrs); 1055
1415 kfree(tz->trip_temp_attrs); 1056 switch (trip_type) {
1416 return -ENOMEM; 1057 case THERMAL_TRIP_CRITICAL:
1058 if (temp >= trip_temp) {
1059 if (tz->ops->notify)
1060 ret = tz->ops->notify(tz, count,
1061 trip_type);
1062 if (!ret) {
1063 printk(KERN_EMERG
1064 "Critical temperature reached (%ld C), shutting down.\n",
1065 temp/1000);
1066 orderly_poweroff(true);
1067 }
1068 }
1069 break;
1070 case THERMAL_TRIP_HOT:
1071 if (temp >= trip_temp)
1072 if (tz->ops->notify)
1073 tz->ops->notify(tz, count, trip_type);
1074 break;
1075 case THERMAL_TRIP_ACTIVE:
1076 list_for_each_entry(instance, &tz->cooling_devices,
1077 node) {
1078 if (instance->trip != count)
1079 continue;
1080
1081 cdev = instance->cdev;
1082
1083 if (temp >= trip_temp)
1084 cdev->ops->set_cur_state(cdev, 1);
1085 else
1086 cdev->ops->set_cur_state(cdev, 0);
1087 }
1088 break;
1089 case THERMAL_TRIP_PASSIVE:
1090 if (temp >= trip_temp || tz->passive)
1091 thermal_zone_device_passive(tz, temp,
1092 trip_temp, count);
1093 break;
1417 } 1094 }
1418 } 1095 }
1419 1096
1097 if (tz->forced_passive)
1098 thermal_zone_device_passive(tz, temp, tz->forced_passive,
1099 THERMAL_TRIPS_NONE);
1420 1100
1421 for (indx = 0; indx < tz->trips; indx++) { 1101 tz->last_temperature = temp;
1422 /* create trip type attribute */
1423 snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
1424 "trip_point_%d_type", indx);
1425
1426 sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
1427 tz->trip_type_attrs[indx].attr.attr.name =
1428 tz->trip_type_attrs[indx].name;
1429 tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
1430 tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
1431
1432 device_create_file(&tz->device,
1433 &tz->trip_type_attrs[indx].attr);
1434
1435 /* create trip temp attribute */
1436 snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
1437 "trip_point_%d_temp", indx);
1438
1439 sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
1440 tz->trip_temp_attrs[indx].attr.attr.name =
1441 tz->trip_temp_attrs[indx].name;
1442 tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
1443 tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
1444 if (mask & (1 << indx)) {
1445 tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
1446 tz->trip_temp_attrs[indx].attr.store =
1447 trip_point_temp_store;
1448 }
1449
1450 device_create_file(&tz->device,
1451 &tz->trip_temp_attrs[indx].attr);
1452 1102
1453 /* create Optional trip hyst attribute */ 1103 leave:
1454 if (!tz->ops->get_trip_hyst) 1104 if (tz->passive)
1455 continue; 1105 thermal_zone_device_set_polling(tz, tz->passive_delay);
1456 snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH, 1106 else if (tz->polling_delay)
1457 "trip_point_%d_hyst", indx); 1107 thermal_zone_device_set_polling(tz, tz->polling_delay);
1458 1108 else
1459 sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr); 1109 thermal_zone_device_set_polling(tz, 0);
1460 tz->trip_hyst_attrs[indx].attr.attr.name = 1110 mutex_unlock(&tz->lock);
1461 tz->trip_hyst_attrs[indx].name;
1462 tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
1463 tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
1464 if (tz->ops->set_trip_hyst) {
1465 tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
1466 tz->trip_hyst_attrs[indx].attr.store =
1467 trip_point_hyst_store;
1468 }
1469
1470 device_create_file(&tz->device,
1471 &tz->trip_hyst_attrs[indx].attr);
1472 }
1473 return 0;
1474}
1475
1476static void remove_trip_attrs(struct thermal_zone_device *tz)
1477{
1478 int indx;
1479
1480 for (indx = 0; indx < tz->trips; indx++) {
1481 device_remove_file(&tz->device,
1482 &tz->trip_type_attrs[indx].attr);
1483 device_remove_file(&tz->device,
1484 &tz->trip_temp_attrs[indx].attr);
1485 if (tz->ops->get_trip_hyst)
1486 device_remove_file(&tz->device,
1487 &tz->trip_hyst_attrs[indx].attr);
1488 }
1489 kfree(tz->trip_type_attrs);
1490 kfree(tz->trip_temp_attrs);
1491 kfree(tz->trip_hyst_attrs);
1492} 1111}
1112EXPORT_SYMBOL(thermal_zone_device_update);
1493 1113
1494/** 1114/**
1495 * thermal_zone_device_register - register a new thermal zone device 1115 * thermal_zone_device_register - register a new thermal zone device
1496 * @type: the thermal zone device type 1116 * @type: the thermal zone device type
1497 * @trips: the number of trip points the thermal zone support 1117 * @trips: the number of trip points the thermal zone support
1498 * @mask: a bit string indicating the writeablility of trip points
1499 * @devdata: private device data 1118 * @devdata: private device data
1500 * @ops: standard thermal zone device callbacks 1119 * @ops: standard thermal zone device callbacks
1501 * @tzp: thermal zone platform parameters 1120 * @tc1: thermal coefficient 1 for passive calculations
1121 * @tc2: thermal coefficient 2 for passive calculations
1502 * @passive_delay: number of milliseconds to wait between polls when 1122 * @passive_delay: number of milliseconds to wait between polls when
1503 * performing passive cooling 1123 * performing passive cooling
1504 * @polling_delay: number of milliseconds to wait between polls when checking 1124 * @polling_delay: number of milliseconds to wait between polls when checking
@@ -1506,24 +1126,25 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
1506 * driven systems) 1126 * driven systems)
1507 * 1127 *
1508 * thermal_zone_device_unregister() must be called when the device is no 1128 * thermal_zone_device_unregister() must be called when the device is no
1509 * longer needed. The passive cooling depends on the .get_trend() return value. 1129 * longer needed. The passive cooling formula uses tc1 and tc2 as described in
1130 * section 11.1.5.1 of the ACPI specification 3.0.
1510 */ 1131 */
1511struct thermal_zone_device *thermal_zone_device_register(const char *type, 1132struct thermal_zone_device *thermal_zone_device_register(char *type,
1512 int trips, int mask, void *devdata, 1133 int trips, void *devdata,
1513 const struct thermal_zone_device_ops *ops, 1134 const struct thermal_zone_device_ops *ops,
1514 const struct thermal_zone_params *tzp, 1135 int tc1, int tc2, int passive_delay, int polling_delay)
1515 int passive_delay, int polling_delay)
1516{ 1136{
1517 struct thermal_zone_device *tz; 1137 struct thermal_zone_device *tz;
1138 struct thermal_cooling_device *pos;
1518 enum thermal_trip_type trip_type; 1139 enum thermal_trip_type trip_type;
1519 int result; 1140 int result;
1520 int count; 1141 int count;
1521 int passive = 0; 1142 int passive = 0;
1522 1143
1523 if (type && strlen(type) >= THERMAL_NAME_LENGTH) 1144 if (strlen(type) >= THERMAL_NAME_LENGTH)
1524 return ERR_PTR(-EINVAL); 1145 return ERR_PTR(-EINVAL);
1525 1146
1526 if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) 1147 if (trips > THERMAL_MAX_TRIPS || trips < 0)
1527 return ERR_PTR(-EINVAL); 1148 return ERR_PTR(-EINVAL);
1528 1149
1529 if (!ops || !ops->get_temp) 1150 if (!ops || !ops->get_temp)
@@ -1533,7 +1154,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1533 if (!tz) 1154 if (!tz)
1534 return ERR_PTR(-ENOMEM); 1155 return ERR_PTR(-ENOMEM);
1535 1156
1536 INIT_LIST_HEAD(&tz->thermal_instances); 1157 INIT_LIST_HEAD(&tz->cooling_devices);
1537 idr_init(&tz->idr); 1158 idr_init(&tz->idr);
1538 mutex_init(&tz->lock); 1159 mutex_init(&tz->lock);
1539 result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); 1160 result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
@@ -1542,12 +1163,13 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1542 return ERR_PTR(result); 1163 return ERR_PTR(result);
1543 } 1164 }
1544 1165
1545 strcpy(tz->type, type ? : ""); 1166 strcpy(tz->type, type);
1546 tz->ops = ops; 1167 tz->ops = ops;
1547 tz->tzp = tzp;
1548 tz->device.class = &thermal_class; 1168 tz->device.class = &thermal_class;
1549 tz->devdata = devdata; 1169 tz->devdata = devdata;
1550 tz->trips = trips; 1170 tz->trips = trips;
1171 tz->tc1 = tc1;
1172 tz->tc2 = tc2;
1551 tz->passive_delay = passive_delay; 1173 tz->passive_delay = passive_delay;
1552 tz->polling_delay = polling_delay; 1174 tz->polling_delay = polling_delay;
1553 1175
@@ -1576,48 +1198,36 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1576 goto unregister; 1198 goto unregister;
1577 } 1199 }
1578 1200
1579 result = create_trip_attrs(tz, mask);
1580 if (result)
1581 goto unregister;
1582
1583 for (count = 0; count < trips; count++) { 1201 for (count = 0; count < trips; count++) {
1202 TRIP_POINT_ATTR_ADD(&tz->device, count, result);
1203 if (result)
1204 goto unregister;
1584 tz->ops->get_trip_type(tz, count, &trip_type); 1205 tz->ops->get_trip_type(tz, count, &trip_type);
1585 if (trip_type == THERMAL_TRIP_PASSIVE) 1206 if (trip_type == THERMAL_TRIP_PASSIVE)
1586 passive = 1; 1207 passive = 1;
1587 } 1208 }
1588 1209
1589 if (!passive) { 1210 if (!passive)
1590 result = device_create_file(&tz->device, &dev_attr_passive); 1211 result = device_create_file(&tz->device,
1591 if (result) 1212 &dev_attr_passive);
1592 goto unregister;
1593 }
1594 1213
1595 /* Create policy attribute */
1596 result = device_create_file(&tz->device, &dev_attr_policy);
1597 if (result) 1214 if (result)
1598 goto unregister; 1215 goto unregister;
1599 1216
1600 /* Update 'this' zone's governor information */
1601 mutex_lock(&thermal_governor_lock);
1602
1603 if (tz->tzp)
1604 tz->governor = __find_governor(tz->tzp->governor_name);
1605 else
1606 tz->governor = __find_governor(DEFAULT_THERMAL_GOVERNOR);
1607
1608 mutex_unlock(&thermal_governor_lock);
1609
1610 result = thermal_add_hwmon_sysfs(tz); 1217 result = thermal_add_hwmon_sysfs(tz);
1611 if (result) 1218 if (result)
1612 goto unregister; 1219 goto unregister;
1613 1220
1614 mutex_lock(&thermal_list_lock); 1221 mutex_lock(&thermal_list_lock);
1615 list_add_tail(&tz->node, &thermal_tz_list); 1222 list_add_tail(&tz->node, &thermal_tz_list);
1223 if (ops->bind)
1224 list_for_each_entry(pos, &thermal_cdev_list, node) {
1225 result = ops->bind(tz, pos);
1226 if (result)
1227 break;
1228 }
1616 mutex_unlock(&thermal_list_lock); 1229 mutex_unlock(&thermal_list_lock);
1617 1230
1618 /* Bind cooling devices for this zone */
1619 bind_tz(tz);
1620
1621 INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); 1231 INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
1622 1232
1623 thermal_zone_device_update(tz); 1233 thermal_zone_device_update(tz);
@@ -1625,11 +1235,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1625 if (!result) 1235 if (!result)
1626 return tz; 1236 return tz;
1627 1237
1628unregister: 1238 unregister:
1629 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); 1239 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
1630 device_unregister(&tz->device); 1240 device_unregister(&tz->device);
1631 return ERR_PTR(result); 1241 return ERR_PTR(result);
1632} 1242}
1243
1633EXPORT_SYMBOL(thermal_zone_device_register); 1244EXPORT_SYMBOL(thermal_zone_device_register);
1634 1245
1635/** 1246/**
@@ -1638,16 +1249,13 @@ EXPORT_SYMBOL(thermal_zone_device_register);
1638 */ 1249 */
1639void thermal_zone_device_unregister(struct thermal_zone_device *tz) 1250void thermal_zone_device_unregister(struct thermal_zone_device *tz)
1640{ 1251{
1641 int i;
1642 const struct thermal_zone_params *tzp;
1643 struct thermal_cooling_device *cdev; 1252 struct thermal_cooling_device *cdev;
1644 struct thermal_zone_device *pos = NULL; 1253 struct thermal_zone_device *pos = NULL;
1254 int count;
1645 1255
1646 if (!tz) 1256 if (!tz)
1647 return; 1257 return;
1648 1258
1649 tzp = tz->tzp;
1650
1651 mutex_lock(&thermal_list_lock); 1259 mutex_lock(&thermal_list_lock);
1652 list_for_each_entry(pos, &thermal_tz_list, node) 1260 list_for_each_entry(pos, &thermal_tz_list, node)
1653 if (pos == tz) 1261 if (pos == tz)
@@ -1658,25 +1266,9 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
1658 return; 1266 return;
1659 } 1267 }
1660 list_del(&tz->node); 1268 list_del(&tz->node);
1661 1269 if (tz->ops->unbind)
1662 /* Unbind all cdevs associated with 'this' thermal zone */ 1270 list_for_each_entry(cdev, &thermal_cdev_list, node)
1663 list_for_each_entry(cdev, &thermal_cdev_list, node) { 1271 tz->ops->unbind(tz, cdev);
1664 if (tz->ops->unbind) {
1665 tz->ops->unbind(tz, cdev);
1666 continue;
1667 }
1668
1669 if (!tzp || !tzp->tbp)
1670 break;
1671
1672 for (i = 0; i < tzp->num_tbps; i++) {
1673 if (tzp->tbp[i].cdev == cdev) {
1674 __unbind(tz, tzp->tbp[i].trip_mask, cdev);
1675 tzp->tbp[i].cdev = NULL;
1676 }
1677 }
1678 }
1679
1680 mutex_unlock(&thermal_list_lock); 1272 mutex_unlock(&thermal_list_lock);
1681 1273
1682 thermal_zone_device_set_polling(tz, 0); 1274 thermal_zone_device_set_polling(tz, 0);
@@ -1686,9 +1278,9 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
1686 device_remove_file(&tz->device, &dev_attr_temp); 1278 device_remove_file(&tz->device, &dev_attr_temp);
1687 if (tz->ops->get_mode) 1279 if (tz->ops->get_mode)
1688 device_remove_file(&tz->device, &dev_attr_mode); 1280 device_remove_file(&tz->device, &dev_attr_mode);
1689 device_remove_file(&tz->device, &dev_attr_policy); 1281
1690 remove_trip_attrs(tz); 1282 for (count = 0; count < tz->trips; count++)
1691 tz->governor = NULL; 1283 TRIP_POINT_ATTR_REMOVE(&tz->device, count);
1692 1284
1693 thermal_remove_hwmon_sysfs(tz); 1285 thermal_remove_hwmon_sysfs(tz);
1694 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); 1286 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
@@ -1697,6 +1289,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
1697 device_unregister(&tz->device); 1289 device_unregister(&tz->device);
1698 return; 1290 return;
1699} 1291}
1292
1700EXPORT_SYMBOL(thermal_zone_device_unregister); 1293EXPORT_SYMBOL(thermal_zone_device_unregister);
1701 1294
1702#ifdef CONFIG_NET 1295#ifdef CONFIG_NET
@@ -1711,7 +1304,7 @@ static struct genl_multicast_group thermal_event_mcgrp = {
1711 .name = THERMAL_GENL_MCAST_GROUP_NAME, 1304 .name = THERMAL_GENL_MCAST_GROUP_NAME,
1712}; 1305};
1713 1306
1714int thermal_generate_netlink_event(u32 orig, enum events event) 1307int generate_netlink_event(u32 orig, enum events event)
1715{ 1308{
1716 struct sk_buff *skb; 1309 struct sk_buff *skb;
1717 struct nlattr *attr; 1310 struct nlattr *attr;
@@ -1719,11 +1312,10 @@ int thermal_generate_netlink_event(u32 orig, enum events event)
1719 void *msg_header; 1312 void *msg_header;
1720 int size; 1313 int size;
1721 int result; 1314 int result;
1722 static unsigned int thermal_event_seqnum;
1723 1315
1724 /* allocate memory */ 1316 /* allocate memory */
1725 size = nla_total_size(sizeof(struct thermal_genl_event)) + 1317 size = nla_total_size(sizeof(struct thermal_genl_event)) + \
1726 nla_total_size(0); 1318 nla_total_size(0);
1727 1319
1728 skb = genlmsg_new(size, GFP_ATOMIC); 1320 skb = genlmsg_new(size, GFP_ATOMIC);
1729 if (!skb) 1321 if (!skb)
@@ -1739,8 +1331,8 @@ int thermal_generate_netlink_event(u32 orig, enum events event)
1739 } 1331 }
1740 1332
1741 /* fill the data */ 1333 /* fill the data */
1742 attr = nla_reserve(skb, THERMAL_GENL_ATTR_EVENT, 1334 attr = nla_reserve(skb, THERMAL_GENL_ATTR_EVENT, \
1743 sizeof(struct thermal_genl_event)); 1335 sizeof(struct thermal_genl_event));
1744 1336
1745 if (!attr) { 1337 if (!attr) {
1746 nlmsg_free(skb); 1338 nlmsg_free(skb);
@@ -1767,11 +1359,11 @@ int thermal_generate_netlink_event(u32 orig, enum events event)
1767 1359
1768 result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC); 1360 result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC);
1769 if (result) 1361 if (result)
1770 pr_info("failed to send netlink event:%d\n", result); 1362 printk(KERN_INFO "failed to send netlink event:%d", result);
1771 1363
1772 return result; 1364 return result;
1773} 1365}
1774EXPORT_SYMBOL(thermal_generate_netlink_event); 1366EXPORT_SYMBOL(generate_netlink_event);
1775 1367
1776static int genetlink_init(void) 1368static int genetlink_init(void)
1777{ 1369{
diff --git a/drivers/thermal/user_space.c b/drivers/thermal/user_space.c
deleted file mode 100644
index 6bbb380b6d1..00000000000
--- a/drivers/thermal/user_space.c
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 * user_space.c - A simple user space Thermal events notifier
3 *
4 * Copyright (C) 2012 Intel Corp
5 * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/module.h>
28#include <linux/thermal.h>
29
30#include "thermal_core.h"
31
32/**
33 * notify_user_space - Notifies user space about thermal events
34 * @tz - thermal_zone_device
35 *
36 * This function notifies the user space through UEvents.
37 */
38static int notify_user_space(struct thermal_zone_device *tz, int trip)
39{
40 mutex_lock(&tz->lock);
41 kobject_uevent(&tz->device.kobj, KOBJ_CHANGE);
42 mutex_unlock(&tz->lock);
43 return 0;
44}
45
46static struct thermal_governor thermal_gov_user_space = {
47 .name = "user_space",
48 .throttle = notify_user_space,
49 .owner = THIS_MODULE,
50};
51
52static int __init thermal_gov_user_space_init(void)
53{
54 return thermal_register_governor(&thermal_gov_user_space);
55}
56
57static void __exit thermal_gov_user_space_exit(void)
58{
59 thermal_unregister_governor(&thermal_gov_user_space);
60}
61
62/* This should load after thermal framework */
63fs_initcall(thermal_gov_user_space_init);
64module_exit(thermal_gov_user_space_exit);
65
66MODULE_AUTHOR("Durgadoss R");
67MODULE_DESCRIPTION("A user space Thermal notifier");
68MODULE_LICENSE("GPL");