drivers: skin: Skin prediction algorithm
[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
33 #include "clock.h"
34 #include "cpu-tegra.h"
35 #include "dvfs.h"
36
37 static struct tegra_thermal_data *therm;
38 static LIST_HEAD(tegra_therm_list);
39 static DEFINE_MUTEX(tegra_therm_mutex);
40
41 static struct balanced_throttle *throttle_list;
42 static int throttle_list_size;
43
44 #ifdef CONFIG_TEGRA_EDP_LIMITS
45 static long edp_thermal_zone_val;
46 #endif
47
48 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
49 static int skin_devs_bitmap;
50 static struct therm_est_subdevice *skin_devs[THERMAL_DEVICE_MAX];
51 static int skin_devs_count;
52 #endif
53
54 #ifdef CONFIG_DEBUG_FS
55 static struct dentry *thermal_debugfs_root;
56 #endif
57
58 static inline long dev2tj(struct tegra_thermal_device *dev,
59                                 long dev_temp)
60 {
61         return dev_temp + dev->offset;
62 }
63
64 static inline long tj2dev(struct tegra_thermal_device *dev,
65                                 long tj_temp)
66 {
67         return tj_temp - dev->offset;
68 }
69
70 static int tegra_thermal_get_temp_unlocked(long *tj_temp, bool offsetted)
71 {
72         struct tegra_thermal_device *dev = NULL;
73         int ret = 0;
74
75 #if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE)
76         list_for_each_entry(dev, &tegra_therm_list, node)
77                 if (dev->id == therm->throttle_edp_device_id)
78                         break;
79 #endif
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                 ret = -1;
87         }
88
89         return ret;
90 }
91
92 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
93
94 static int tegra_thermal_zone_bind(struct thermal_zone_device *thz,
95                                 struct thermal_cooling_device *cdevice) {
96
97         struct balanced_throttle *bthrot = cdevice->devdata;
98         struct tegra_thermal_device *device = thz->devdata;
99
100         if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) &&
101                 (device->id == therm->throttle_edp_device_id))
102                 return thermal_zone_bind_cooling_device(thz, 0, cdevice);
103
104 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
105         if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) &&
106                 (device->id == therm->throttle_edp_device_id))
107                 return thermal_zone_bind_cooling_device(thz, 0, cdevice);
108 #endif
109
110         return 0;
111 }
112
113 static int tegra_thermal_zone_unbind(struct thermal_zone_device *thz,
114                                 struct thermal_cooling_device *cdevice) {
115         struct balanced_throttle *bthrot = cdevice->devdata;
116         struct tegra_thermal_device *device = thz->devdata;
117
118         if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) &&
119                 (device->id == therm->throttle_edp_device_id))
120                 return thermal_zone_unbind_cooling_device(thz, 0, cdevice);
121
122 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
123         if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) &&
124                 (device->id == therm->skin_device_id))
125                 return thermal_zone_unbind_cooling_device(thz, 0, cdevice);
126 #endif
127
128         return 0;
129 }
130
131 static int tegra_thermal_zone_get_temp(struct thermal_zone_device *thz,
132                                         unsigned long *temp)
133 {
134         struct tegra_thermal_device *device = thz->devdata;
135
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 #endif
181
182 static void tegra_thermal_alert_unlocked(void *data)
183 {
184         struct tegra_thermal_device *device = data;
185         long temp_tj;
186         long lo_limit_throttle_tj, hi_limit_throttle_tj;
187         long lo_limit_edp_tj = 0, hi_limit_edp_tj = 0;
188         long temp_low_dev, temp_low_tj;
189         int lo_limit_tj = 0, hi_limit_tj = 0;
190 #ifdef CONFIG_TEGRA_EDP_LIMITS
191         const struct tegra_edp_limits *z;
192         int zones_sz;
193         int i;
194 #endif
195
196 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
197         if (device->thz) {
198                 if (!device->thz->passive)
199                         thermal_zone_device_update(device->thz);
200         }
201 #endif
202
203         /* Convert all temps to tj and then do all work/logic in terms of
204            tj in order to avoid confusion */
205         if (tegra_thermal_get_temp_unlocked(&temp_tj, true))
206                 return;
207         device->get_temp_low(device, &temp_low_dev);
208         temp_low_tj = dev2tj(device, temp_low_dev);
209
210         lo_limit_throttle_tj = temp_low_tj;
211         hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown);
212
213 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
214         hi_limit_throttle_tj = dev2tj(device, therm->temp_throttle);
215
216         if (temp_tj > dev2tj(device, therm->temp_throttle)) {
217                 lo_limit_throttle_tj = dev2tj(device, therm->temp_throttle);
218                 hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown);
219         }
220 #endif
221
222 #ifdef CONFIG_TEGRA_EDP_LIMITS
223         tegra_get_cpu_edp_limits(&z, &zones_sz);
224
225 /* edp table based off of tdiode measurements */
226 #define EDP_TEMP_TJ(_index) (z[_index].temperature * 1000 + therm->edp_offset)
227
228         if (temp_tj < EDP_TEMP_TJ(0)) {
229                 lo_limit_edp_tj = temp_low_tj;
230                 hi_limit_edp_tj = EDP_TEMP_TJ(0);
231         } else if (temp_tj >= EDP_TEMP_TJ(zones_sz-1)) {
232                 lo_limit_edp_tj = EDP_TEMP_TJ(zones_sz-1) -
233                                         therm->hysteresis_edp;
234                 hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown);
235         } else {
236                 for (i = 0; (i + 1) < zones_sz; i++) {
237                         if ((temp_tj >= EDP_TEMP_TJ(i)) &&
238                                 (temp_tj < EDP_TEMP_TJ(i+1))) {
239                                 lo_limit_edp_tj = EDP_TEMP_TJ(i) -
240                                                         therm->hysteresis_edp;
241                                 hi_limit_edp_tj = EDP_TEMP_TJ(i+1);
242                                 break;
243                         }
244                 }
245         }
246 #undef EDP_TEMP_TJ
247 #else
248         lo_limit_edp_tj = temp_low_tj;
249         hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown);
250 #endif
251
252         /* Get smallest window size */
253         lo_limit_tj = max(lo_limit_throttle_tj, lo_limit_edp_tj);
254         hi_limit_tj = min(hi_limit_throttle_tj, hi_limit_edp_tj);
255
256         device->set_limits(device->data,
257                                 tj2dev(device, lo_limit_tj),
258                                 tj2dev(device, hi_limit_tj));
259
260 #ifdef CONFIG_TEGRA_EDP_LIMITS
261         /* inform edp governor */
262         if (edp_thermal_zone_val != temp_tj) {
263                 long temp_edp = (dev2tj(device, temp_tj) - therm->edp_offset) / 1000;
264                 tegra_edp_update_thermal_zone(temp_edp);
265                 edp_thermal_zone_val = temp_edp;
266         }
267 #endif
268 }
269
270 /* Make sure this function remains stateless */
271 void tegra_thermal_alert(void *data)
272 {
273         mutex_lock(&tegra_therm_mutex);
274         tegra_thermal_alert_unlocked(data);
275         mutex_unlock(&tegra_therm_mutex);
276 }
277
278 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
279 static int tegra_skin_device_register(struct tegra_thermal_device *device)
280 {
281         int i;
282         struct therm_est_subdevice *skin_dev =
283                 kzalloc(sizeof(struct therm_est_subdevice), GFP_KERNEL);
284
285         for (i = 0; i < therm->skin_devs_size; i++) {
286                 if (therm->skin_devs[i].id == device->id) {
287                         memcpy(skin_dev->coeffs,
288                                 therm->skin_devs[i].coeffs,
289                                 sizeof(skin_devs[i]->coeffs));
290                         break;
291                 }
292         }
293
294         skin_dev->dev_data = device->data;
295         skin_dev->get_temp = device->get_temp;
296
297         skin_devs[skin_devs_count++] = skin_dev;
298
299         /* Create skin thermal device */
300         if (skin_devs_count == therm->skin_devs_size) {
301                 struct tegra_thermal_device *thermal_skin_device;
302                 struct therm_estimator *skin_estimator;
303
304                 skin_estimator = therm_est_register(
305                                         skin_devs,
306                                         skin_devs_count,
307                                         therm->skin_temp_offset,
308                                         therm->skin_period);
309                 thermal_skin_device = kzalloc(sizeof(struct tegra_thermal_device),
310                                                         GFP_KERNEL);
311                 thermal_skin_device->name = "skin_pred";
312                 thermal_skin_device->id = THERMAL_DEVICE_ID_SKIN;
313                 thermal_skin_device->data = skin_estimator;
314                 thermal_skin_device->get_temp =
315                         (int (*)(void *, long *)) therm_est_get_temp;
316                 thermal_skin_device->set_limits =
317                         (int (*)(void *, long, long)) therm_est_set_limits;
318                 thermal_skin_device->set_alert =
319                         (int (*)(void *, void (*)(void *), void *))
320                                 therm_est_set_alert;
321
322                 tegra_thermal_device_register(thermal_skin_device);
323         }
324
325         return 0;
326 }
327 #endif
328
329 int tegra_thermal_device_register(struct tegra_thermal_device *device)
330 {
331         struct tegra_thermal_device *dev;
332 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
333         struct thermal_zone_device *thz;
334         int t1 = 0, t2 = 0, pdelay = 0;
335         bool create_thz = false;
336 #endif
337
338         mutex_lock(&tegra_therm_mutex);
339         list_for_each_entry(dev, &tegra_therm_list, node) {
340                 if (dev->id == device->id) {
341                         mutex_unlock(&tegra_therm_mutex);
342                         return -EINVAL;
343                 }
344         }
345
346 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
347         if (device->id == therm->throttle_edp_device_id) {
348                 t1 = therm->tc1;
349                 t2 = therm->tc2;
350                 pdelay = therm->passive_delay;
351                 create_thz = true;
352         }
353 #endif
354 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
355         if (device->id == therm->skin_device_id) {
356                 t1 = 0;
357                 t2 = 1;
358                 pdelay = 5000;
359                 create_thz = true;
360         }
361 #endif
362
363 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
364         if (create_thz) {
365                 thz = thermal_zone_device_register(
366                                                 device->name,
367                                                 1, /* trips */
368                                                 device,
369                                                 &tegra_thermal_zone_ops,
370                                                 t1, /* dT/dt */
371                                                 t2, /* throttle */
372                                                 pdelay,
373                                                 0); /* polling delay */
374                 if (IS_ERR_OR_NULL(thz))
375                         return -ENODEV;
376
377                 device->thz = thz;
378         }
379 #endif
380
381         list_add(&device->node, &tegra_therm_list);
382         mutex_unlock(&tegra_therm_mutex);
383
384         if (device->id == therm->shutdown_device_id) {
385                 device->set_shutdown_temp(device->data, therm->temp_shutdown);
386         }
387
388 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
389         if (device->id == therm->skin_device_id) {
390                 if (create_thz)
391                         device->set_alert(device->data,
392                                 (void (*)(void *))thermal_zone_device_update,
393                                 thz);
394                 device->set_limits(device->data, 0, therm->temp_throttle_skin);
395         }
396 #endif
397
398 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
399         if (device->id == therm->throttle_edp_device_id) {
400                 device->set_alert(device->data, tegra_thermal_alert, device);
401
402                 /* initialize limits */
403                 tegra_thermal_alert(device);
404         }
405 #endif
406
407 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
408         if ((therm->skin_device_id == THERMAL_DEVICE_ID_SKIN) &&
409                 device->id && skin_devs_bitmap)
410                 tegra_skin_device_register(device);
411 #endif
412
413         return 0;
414 }
415
416 /* This needs to be inialized later hand */
417 static int __init throttle_list_init(void)
418 {
419         int i;
420         for (i = 0; i < throttle_list_size; i++)
421                 if (balanced_throttle_register(&throttle_list[i]))
422                         return -ENODEV;
423
424         return 0;
425 }
426 late_initcall(throttle_list_init);
427
428 int __init tegra_thermal_init(struct tegra_thermal_data *data,
429                                 struct balanced_throttle *tlist,
430                                 int tlist_size)
431 {
432         therm = data;
433 #ifdef CONFIG_DEBUG_FS
434         thermal_debugfs_root = debugfs_create_dir("tegra_thermal", 0);
435 #endif
436
437 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
438         {
439                 int i;
440                 for (i = 0; i < therm->skin_devs_size; i++)
441                         skin_devs_bitmap |= therm->skin_devs[i].id;
442         }
443 #endif
444
445         throttle_list = tlist;
446         throttle_list_size = tlist_size;
447
448         return 0;
449 }
450
451 int tegra_thermal_exit(void)
452 {
453 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
454         struct tegra_thermal_device *dev;
455         mutex_lock(&tegra_therm_mutex);
456         list_for_each_entry(dev, &tegra_therm_list, node) {
457                 thermal_zone_device_unregister(dev->thz);
458         }
459         mutex_unlock(&tegra_therm_mutex);
460 #endif
461
462         return 0;
463 }
464
465 #ifdef CONFIG_DEBUG_FS
466 static int tegra_thermal_temp_tj_get(void *data, u64 *val)
467 {
468         long temp_tj;
469
470         mutex_lock(&tegra_therm_mutex);
471         if (tegra_thermal_get_temp_unlocked(&temp_tj, false))
472                 temp_tj = -1;
473         mutex_unlock(&tegra_therm_mutex);
474
475         *val = (u64)temp_tj;
476
477         return 0;
478 }
479
480 DEFINE_SIMPLE_ATTRIBUTE(temp_tj_fops,
481                         tegra_thermal_temp_tj_get,
482                         NULL,
483                         "%llu\n");
484
485 static int __init temp_tj_debug_init(void)
486 {
487         debugfs_create_file("temp_tj", 0644, thermal_debugfs_root,
488                 NULL, &temp_tj_fops);
489         return 0;
490 }
491 late_initcall(temp_tj_debug_init);
492
493
494 #define TEGRA_THERM_DEBUGFS(_name, _device_id, throttle, shutdown) \
495         static int tegra_thermal_##_name##_set(void *data, u64 val) \
496         { \
497                 struct tegra_thermal_device *dev; \
498                 mutex_lock(&tegra_therm_mutex); \
499                 therm->_name = val; \
500                 list_for_each_entry(dev, &tegra_therm_list, node) \
501                         if (dev->id == therm->_device_id) \
502                                 break; \
503                 if (dev) { \
504                         if (throttle) \
505                                 tegra_thermal_alert_unlocked(dev); \
506                         if (shutdown) \
507                                 dev->set_shutdown_temp(dev->data, \
508                                                         therm->temp_shutdown); \
509                 } \
510                 mutex_unlock(&tegra_therm_mutex); \
511                 return 0; \
512         } \
513         static int tegra_thermal_##_name##_get(void *data, u64 *val) \
514         { \
515                 *val = (u64)therm->_name; \
516                 return 0; \
517         } \
518         DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, \
519                                 tegra_thermal_##_name##_get, \
520                                 tegra_thermal_##_name##_set, \
521                                 "%llu\n"); \
522         static int __init _name##_debug_init(void) \
523         { \
524                 debugfs_create_file(#_name, 0644, thermal_debugfs_root, \
525                         NULL, &_name##_fops); \
526                 return 0; \
527         } \
528         late_initcall(_name##_debug_init);
529
530
531 TEGRA_THERM_DEBUGFS(temp_shutdown, shutdown_device_id, false, true);
532 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
533 TEGRA_THERM_DEBUGFS(temp_throttle, throttle_edp_device_id, true, false);
534 #endif
535 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
536 TEGRA_THERM_DEBUGFS(temp_throttle_skin, skin_device_id, false, false);
537 #endif
538
539 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
540 #define THERM_DEBUGFS(_name) \
541         static int tegra_thermal_##_name##_set(void *data, u64 val) \
542         { \
543                 struct tegra_thermal_device *dev; \
544                 mutex_lock(&tegra_therm_mutex); \
545                 list_for_each_entry(dev, &tegra_therm_list, node) \
546                         if (dev->id == therm->throttle_edp_device_id) \
547                                 break; \
548                 if (dev) \
549                         dev->thz->_name = val; \
550                 mutex_unlock(&tegra_therm_mutex); \
551                 return 0; \
552         } \
553         static int tegra_thermal_##_name##_get(void *data, u64 *val) \
554         { \
555                 struct tegra_thermal_device *dev; \
556                 mutex_lock(&tegra_therm_mutex); \
557                 list_for_each_entry(dev, &tegra_therm_list, node) \
558                         if (dev->id == therm->throttle_edp_device_id) \
559                                 break; \
560                 if (dev) \
561                         *val = (u64)dev->thz->_name; \
562                 mutex_unlock(&tegra_therm_mutex); \
563                 return 0; \
564         } \
565         DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, \
566                         tegra_thermal_##_name##_get, \
567                         tegra_thermal_##_name##_set, \
568                         "%llu\n"); \
569         static int __init _name##_debug_init(void) \
570         { \
571                 debugfs_create_file(#_name, 0644, thermal_debugfs_root, \
572                         NULL, &_name##_fops); \
573                 return 0; \
574         } \
575         late_initcall(_name##_debug_init);
576
577
578 THERM_DEBUGFS(tc1);
579 THERM_DEBUGFS(tc2);
580 THERM_DEBUGFS(passive_delay);
581 #endif
582 #endif