53ad580fd1fd77c22061b6c59c816d0167e55b0b
[linux-2.6.git] / arch / arm / mach-tegra / tegra3_thermal.c
1 /*
2  * arch/arm/mach-tegra/tegra3_thermal.c
3  *
4  * Copyright (C) 2010-2012 NVIDIA Corporation.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/cpufreq.h>
19 #include <linux/delay.h>
20 #include <linux/mutex.h>
21 #include <linux/init.h>
22 #include <linux/err.h>
23 #include <linux/clk.h>
24 #include <linux/debugfs.h>
25 #include <linux/seq_file.h>
26 #include <linux/uaccess.h>
27 #include <linux/thermal.h>
28 #include <linux/module.h>
29 #include <mach/thermal.h>
30 #include <mach/edp.h>
31 #include <linux/slab.h>
32 #include <linux/suspend.h>
33
34 #include "clock.h"
35 #include "cpu-tegra.h"
36 #include "dvfs.h"
37
38 static struct tegra_thermal_data *therm;
39 static LIST_HEAD(tegra_therm_list);
40 static DEFINE_MUTEX(tegra_therm_mutex);
41
42 static struct balanced_throttle *throttle_list;
43 static int throttle_list_size;
44
45 #ifdef CONFIG_TEGRA_EDP_LIMITS
46 static long edp_thermal_zone_val;
47 #endif
48
49 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
50 static int skin_devs_bitmap;
51 static struct therm_est_subdevice *skin_devs[THERMAL_DEVICE_MAX];
52 static int skin_devs_count;
53 #endif
54 static bool tegra_thermal_suspend;
55
56 #ifdef CONFIG_DEBUG_FS
57 static struct dentry *thermal_debugfs_root;
58 #endif
59
60 static inline long dev2tj(struct tegra_thermal_device *dev,
61                                 long dev_temp)
62 {
63         return dev_temp + dev->offset;
64 }
65
66 static inline long tj2dev(struct tegra_thermal_device *dev,
67                                 long tj_temp)
68 {
69         return tj_temp - dev->offset;
70 }
71
72 static int tegra_thermal_get_temp_unlocked(long *tj_temp, bool offsetted)
73 {
74         struct tegra_thermal_device *dev = NULL;
75         int ret = 0;
76
77         list_for_each_entry(dev, &tegra_therm_list, node)
78                 if (dev->id == therm->throttle_edp_device_id)
79                         break;
80
81         if (dev) {
82                 dev->get_temp(dev->data, tj_temp);
83                 if (offsetted)
84                         *tj_temp = dev2tj(dev, *tj_temp);
85         } else {
86                 *tj_temp = 0xdeadbeef;
87                 ret = -1;
88         }
89
90         return ret;
91 }
92
93 static int tegra_thermal_zone_bind(struct thermal_zone_device *thz,
94                                 struct thermal_cooling_device *cdevice) {
95
96         struct balanced_throttle *bthrot = cdevice->devdata;
97         struct tegra_thermal_device *device = thz->devdata;
98
99         if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) &&
100                 (device->id == therm->throttle_edp_device_id))
101                 return thermal_zone_bind_cooling_device(thz, 0, cdevice);
102
103 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
104         if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) &&
105                 (device->id == therm->skin_device_id))
106                 return thermal_zone_bind_cooling_device(thz, 0, cdevice);
107 #endif
108
109         return 0;
110 }
111
112 static int tegra_thermal_zone_unbind(struct thermal_zone_device *thz,
113                                 struct thermal_cooling_device *cdevice) {
114         struct balanced_throttle *bthrot = cdevice->devdata;
115         struct tegra_thermal_device *device = thz->devdata;
116
117         if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) &&
118                 (device->id == therm->throttle_edp_device_id))
119                 return thermal_zone_unbind_cooling_device(thz, 0, cdevice);
120
121 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
122         if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) &&
123                 (device->id == therm->skin_device_id))
124                 return thermal_zone_unbind_cooling_device(thz, 0, cdevice);
125 #endif
126
127         return 0;
128 }
129
130 static int tegra_thermal_zone_get_temp(struct thermal_zone_device *thz,
131                                         unsigned long *temp)
132 {
133         struct tegra_thermal_device *device = thz->devdata;
134
135         if (!tegra_thermal_suspend)
136                 device->get_temp(device->data, temp);
137
138         return 0;
139 }
140
141 static int tegra_thermal_zone_get_trip_type(
142                         struct thermal_zone_device *thermal,
143                         int trip,
144                         enum thermal_trip_type *type) {
145         if (trip != 0)
146                 return -EINVAL;
147
148         *type = THERMAL_TRIP_PASSIVE;
149
150         return 0;
151 }
152
153 static int tegra_thermal_zone_get_trip_temp(struct thermal_zone_device *thz,
154                                         int trip,
155                                         unsigned long *temp) {
156         struct tegra_thermal_device *device = thz->devdata;
157
158         if (trip != 0)
159                 return -EINVAL;
160
161         if (device->id == therm->throttle_edp_device_id)
162                 *temp = therm->temp_throttle;
163 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
164         else if (device->id == therm->skin_device_id)
165                 *temp = therm->temp_throttle_skin;
166 #endif
167         else
168                 return -EINVAL;
169
170         return 0;
171 }
172
173 static struct thermal_zone_device_ops tegra_thermal_zone_ops = {
174         .bind = tegra_thermal_zone_bind,
175         .unbind = tegra_thermal_zone_unbind,
176         .get_temp = tegra_thermal_zone_get_temp,
177         .get_trip_type = tegra_thermal_zone_get_trip_type,
178         .get_trip_temp = tegra_thermal_zone_get_trip_temp,
179 };
180
181 static int tegra_thermal_pm_notify(struct notifier_block *nb,
182                                 unsigned long event, void *data)
183 {
184         switch (event) {
185         case PM_SUSPEND_PREPARE:
186                 tegra_thermal_suspend = true;
187                 break;
188         case PM_POST_SUSPEND:
189                 tegra_thermal_suspend = false;
190                 break;
191         }
192
193         return NOTIFY_OK;
194 };
195
196 static struct notifier_block tegra_thermal_nb = {
197         .notifier_call = tegra_thermal_pm_notify,
198 };
199
200 static void tegra_thermal_alert_unlocked(void *data)
201 {
202         struct tegra_thermal_device *device = data;
203         long temp_tj;
204         long lo_limit_throttle_tj, hi_limit_throttle_tj;
205         long lo_limit_edp_tj = 0, hi_limit_edp_tj = 0;
206         long temp_low_dev, temp_low_tj;
207         int lo_limit_tj = 0, hi_limit_tj = 0;
208 #ifdef CONFIG_TEGRA_EDP_LIMITS
209         const struct tegra_edp_limits *z;
210         int zones_sz;
211         int i;
212 #endif
213
214         if (device->thz) {
215                 if ((!device->thz->passive) && (!tegra_thermal_suspend))
216                         thermal_zone_device_update(device->thz);
217         }
218
219
220         /* Convert all temps to tj and then do all work/logic in terms of
221            tj in order to avoid confusion */
222         if (tegra_thermal_get_temp_unlocked(&temp_tj, true))
223                 return;
224         device->get_temp_low(device, &temp_low_dev);
225         temp_low_tj = dev2tj(device, temp_low_dev);
226
227         lo_limit_throttle_tj = temp_low_tj;
228         hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown);
229
230         hi_limit_throttle_tj = dev2tj(device, therm->temp_throttle);
231
232         if (temp_tj > dev2tj(device, therm->temp_throttle)) {
233                 lo_limit_throttle_tj = dev2tj(device, therm->temp_throttle);
234                 hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown);
235         }
236
237 #ifdef CONFIG_TEGRA_EDP_LIMITS
238         tegra_get_cpu_edp_limits(&z, &zones_sz);
239
240 /* edp table based off of tdiode measurements */
241 #define EDP_TEMP_TJ(_index) (z[_index].temperature * 1000 + therm->edp_offset)
242
243         if (temp_tj < EDP_TEMP_TJ(0)) {
244                 lo_limit_edp_tj = temp_low_tj;
245                 hi_limit_edp_tj = EDP_TEMP_TJ(0);
246         } else if (temp_tj >= EDP_TEMP_TJ(zones_sz-1)) {
247                 lo_limit_edp_tj = EDP_TEMP_TJ(zones_sz-1) -
248                                         therm->hysteresis_edp;
249                 hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown);
250         } else {
251                 for (i = 0; (i + 1) < zones_sz; i++) {
252                         if ((temp_tj >= EDP_TEMP_TJ(i)) &&
253                                 (temp_tj < EDP_TEMP_TJ(i+1))) {
254                                 lo_limit_edp_tj = EDP_TEMP_TJ(i) -
255                                                         therm->hysteresis_edp;
256                                 hi_limit_edp_tj = EDP_TEMP_TJ(i+1);
257                                 break;
258                         }
259                 }
260         }
261 #undef EDP_TEMP_TJ
262 #else
263         lo_limit_edp_tj = temp_low_tj;
264         hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown);
265 #endif
266
267         /* Get smallest window size */
268         lo_limit_tj = max(lo_limit_throttle_tj, lo_limit_edp_tj);
269         hi_limit_tj = min(hi_limit_throttle_tj, hi_limit_edp_tj);
270
271         device->set_limits(device->data,
272                                 tj2dev(device, lo_limit_tj),
273                                 tj2dev(device, hi_limit_tj));
274
275 #ifdef CONFIG_TEGRA_EDP_LIMITS
276         /* inform edp governor */
277         if (edp_thermal_zone_val != temp_tj) {
278                 long temp_edp = (temp_tj - therm->edp_offset) / 1000;
279                 tegra_edp_update_thermal_zone(temp_edp);
280                 edp_thermal_zone_val = temp_tj;
281         }
282 #endif
283 }
284
285 /* Make sure this function remains stateless */
286 static void tegra_thermal_alert(void *data)
287 {
288         mutex_lock(&tegra_therm_mutex);
289         tegra_thermal_alert_unlocked(data);
290         mutex_unlock(&tegra_therm_mutex);
291 }
292
293 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
294 static void tegra_skin_thermal_alert(void *data)
295 {
296         struct tegra_thermal_device *dev = data;
297
298         if (!dev->thz->passive)
299                 thermal_zone_device_update(dev->thz);
300 }
301
302 static int tegra_skin_device_register(struct tegra_thermal_device *device)
303 {
304         int i;
305         struct therm_est_subdevice *skin_dev =
306                 kzalloc(sizeof(struct therm_est_subdevice), GFP_KERNEL);
307
308         for (i = 0; i < therm->skin_devs_size; i++) {
309                 if (therm->skin_devs[i].id == device->id) {
310                         memcpy(skin_dev->coeffs,
311                                 therm->skin_devs[i].coeffs,
312                                 sizeof(skin_devs[i]->coeffs));
313                         break;
314                 }
315         }
316
317         skin_dev->dev_data = device->data;
318         skin_dev->get_temp = device->get_temp;
319
320         skin_devs[skin_devs_count++] = skin_dev;
321
322         /* Create skin thermal device */
323         if (skin_devs_count == therm->skin_devs_size) {
324                 struct tegra_thermal_device *thermal_skin_device;
325                 struct therm_estimator *skin_estimator;
326
327                 skin_estimator = therm_est_register(
328                                         skin_devs,
329                                         skin_devs_count,
330                                         therm->skin_temp_offset,
331                                         therm->skin_period);
332                 thermal_skin_device = kzalloc(sizeof(struct tegra_thermal_device),
333                                                         GFP_KERNEL);
334                 thermal_skin_device->name = "skin_pred";
335                 thermal_skin_device->id = THERMAL_DEVICE_ID_SKIN;
336                 thermal_skin_device->data = skin_estimator;
337                 thermal_skin_device->get_temp =
338                         (int (*)(void *, long *)) therm_est_get_temp;
339                 thermal_skin_device->set_limits =
340                         (int (*)(void *, long, long)) therm_est_set_limits;
341                 thermal_skin_device->set_alert =
342                         (int (*)(void *, void (*)(void *), void *))
343                                 therm_est_set_alert;
344
345                 tegra_thermal_device_register(thermal_skin_device);
346         }
347
348         return 0;
349 }
350 #endif
351
352 int tegra_thermal_device_register(struct tegra_thermal_device *device)
353 {
354         struct tegra_thermal_device *dev;
355         struct thermal_zone_device *thz;
356         int t1 = 0, t2 = 0, pdelay = 0;
357         bool create_thz = false;
358
359         mutex_lock(&tegra_therm_mutex);
360         list_for_each_entry(dev, &tegra_therm_list, node) {
361                 if (dev->id == device->id) {
362                         mutex_unlock(&tegra_therm_mutex);
363                         return -EINVAL;
364                 }
365         }
366
367         if (device->id == therm->throttle_edp_device_id) {
368                 t1 = therm->tc1;
369                 t2 = therm->tc2;
370                 pdelay = therm->passive_delay;
371                 create_thz = true;
372         }
373
374 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
375         if (device->id == therm->skin_device_id) {
376                 t1 = 0;
377                 t2 = 1;
378                 pdelay = 5000;
379                 create_thz = true;
380         }
381 #endif
382
383         if (create_thz) {
384                 thz = thermal_zone_device_register(
385                                                 device->name,
386                                                 1, /* trips */
387                                                 device,
388                                                 &tegra_thermal_zone_ops,
389                                                 t1, /* dT/dt */
390                                                 t2, /* throttle */
391                                                 pdelay,
392                                                 0); /* polling delay */
393                 if (IS_ERR_OR_NULL(thz))
394                         return -ENODEV;
395
396                 device->thz = thz;
397         }
398
399         list_add(&device->node, &tegra_therm_list);
400         mutex_unlock(&tegra_therm_mutex);
401
402         if (device->id == therm->shutdown_device_id) {
403                 device->set_shutdown_temp(device->data, therm->temp_shutdown);
404         }
405
406 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
407         if (device->id == therm->skin_device_id) {
408                 if (create_thz)
409                         device->set_alert(device->data,
410                                 tegra_skin_thermal_alert,
411                                 device);
412                 device->set_limits(device->data, 0, therm->temp_throttle_skin);
413         }
414 #endif
415
416         if (device->id == therm->throttle_edp_device_id) {
417                 device->set_alert(device->data, tegra_thermal_alert, device);
418
419                 /* initialize limits */
420                 tegra_thermal_alert(device);
421         }
422
423 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
424         if ((therm->skin_device_id == THERMAL_DEVICE_ID_SKIN) &&
425                 device->id && skin_devs_bitmap)
426                 tegra_skin_device_register(device);
427 #endif
428
429         return 0;
430 }
431
432 /* This needs to be inialized later hand */
433 static int __init throttle_list_init(void)
434 {
435         int i;
436         for (i = 0; i < throttle_list_size; i++)
437                 if (balanced_throttle_register(&throttle_list[i]))
438                         return -ENODEV;
439
440         return 0;
441 }
442 late_initcall(throttle_list_init);
443
444 int __init tegra_thermal_init(struct tegra_thermal_data *data,
445                                 struct balanced_throttle *tlist,
446                                 int tlist_size)
447 {
448         therm = data;
449 #ifdef CONFIG_DEBUG_FS
450         thermal_debugfs_root = debugfs_create_dir("tegra_thermal", 0);
451 #endif
452
453 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
454         {
455                 int i;
456                 for (i = 0; i < therm->skin_devs_size; i++)
457                         skin_devs_bitmap |= therm->skin_devs[i].id;
458         }
459 #endif
460
461         throttle_list = tlist;
462         throttle_list_size = tlist_size;
463
464         register_pm_notifier(&tegra_thermal_nb);
465
466         return 0;
467 }
468
469 int tegra_thermal_exit(void)
470 {
471         struct tegra_thermal_device *dev;
472         mutex_lock(&tegra_therm_mutex);
473         list_for_each_entry(dev, &tegra_therm_list, node) {
474                 thermal_zone_device_unregister(dev->thz);
475         }
476         mutex_unlock(&tegra_therm_mutex);
477
478         return 0;
479 }
480
481 #ifdef CONFIG_DEBUG_FS
482 static int tegra_thermal_temp_tj_get(void *data, u64 *val)
483 {
484         long temp_tj;
485
486         mutex_lock(&tegra_therm_mutex);
487         if (tegra_thermal_get_temp_unlocked(&temp_tj, false))
488                 temp_tj = -1;
489         mutex_unlock(&tegra_therm_mutex);
490
491         *val = (u64)temp_tj;
492
493         return 0;
494 }
495
496 DEFINE_SIMPLE_ATTRIBUTE(temp_tj_fops,
497                         tegra_thermal_temp_tj_get,
498                         NULL,
499                         "%llu\n");
500
501 static int __init temp_tj_debug_init(void)
502 {
503         debugfs_create_file("temp_tj", 0644, thermal_debugfs_root,
504                 NULL, &temp_tj_fops);
505         return 0;
506 }
507 late_initcall(temp_tj_debug_init);
508
509
510 #define TEGRA_THERM_DEBUGFS(_name, _device_id, throttle, shutdown) \
511         static int tegra_thermal_##_name##_set(void *data, u64 val) \
512         { \
513                 struct tegra_thermal_device *dev; \
514                 mutex_lock(&tegra_therm_mutex); \
515                 therm->_name = val; \
516                 list_for_each_entry(dev, &tegra_therm_list, node) \
517                         if (dev->id == therm->_device_id) \
518                                 break; \
519                 if (dev) { \
520                         if (throttle) \
521                                 tegra_thermal_alert_unlocked(dev); \
522                         if (shutdown) \
523                                 dev->set_shutdown_temp(dev->data, \
524                                                         therm->temp_shutdown); \
525                 } \
526                 mutex_unlock(&tegra_therm_mutex); \
527                 return 0; \
528         } \
529         static int tegra_thermal_##_name##_get(void *data, u64 *val) \
530         { \
531                 *val = (u64)therm->_name; \
532                 return 0; \
533         } \
534         DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, \
535                                 tegra_thermal_##_name##_get, \
536                                 tegra_thermal_##_name##_set, \
537                                 "%llu\n"); \
538         static int __init _name##_debug_init(void) \
539         { \
540                 debugfs_create_file(#_name, 0644, thermal_debugfs_root, \
541                         NULL, &_name##_fops); \
542                 return 0; \
543         } \
544         late_initcall(_name##_debug_init);
545
546
547 TEGRA_THERM_DEBUGFS(temp_shutdown, shutdown_device_id, false, true);
548 TEGRA_THERM_DEBUGFS(temp_throttle, throttle_edp_device_id, true, false);
549 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
550 TEGRA_THERM_DEBUGFS(temp_throttle_skin, skin_device_id, false, false);
551 #endif
552
553 #define THERM_DEBUGFS(_name) \
554         static int tegra_thermal_##_name##_set(void *data, u64 val) \
555         { \
556                 struct tegra_thermal_device *dev; \
557                 mutex_lock(&tegra_therm_mutex); \
558                 list_for_each_entry(dev, &tegra_therm_list, node) \
559                         if (dev->id == therm->throttle_edp_device_id) \
560                                 break; \
561                 if (dev) \
562                         dev->thz->_name = val; \
563                 mutex_unlock(&tegra_therm_mutex); \
564                 return 0; \
565         } \
566         static int tegra_thermal_##_name##_get(void *data, u64 *val) \
567         { \
568                 struct tegra_thermal_device *dev; \
569                 mutex_lock(&tegra_therm_mutex); \
570                 list_for_each_entry(dev, &tegra_therm_list, node) \
571                         if (dev->id == therm->throttle_edp_device_id) \
572                                 break; \
573                 if (dev) \
574                         *val = (u64)dev->thz->_name; \
575                 mutex_unlock(&tegra_therm_mutex); \
576                 return 0; \
577         } \
578         DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, \
579                         tegra_thermal_##_name##_get, \
580                         tegra_thermal_##_name##_set, \
581                         "%llu\n"); \
582         static int __init _name##_debug_init(void) \
583         { \
584                 debugfs_create_file(#_name, 0644, thermal_debugfs_root, \
585                         NULL, &_name##_fops); \
586                 return 0; \
587         } \
588         late_initcall(_name##_debug_init);
589
590
591 THERM_DEBUGFS(tc1);
592 THERM_DEBUGFS(tc2);
593 THERM_DEBUGFS(passive_delay);
594 #endif