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