Thermal: Update thermal zone device register
[linux-2.6.git] / arch / arm / mach-tegra / tegra11_soctherm.c
1 /*
2  * arch/arm/mach-tegra/tegra11_soctherm.c
3  *
4  * Copyright (C) 2011-2012 NVIDIA Corporation
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  */
20
21 #include <linux/debugfs.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/list.h>
25 #include <linux/spinlock.h>
26 #include <linux/delay.h>
27 #include <linux/err.h>
28 #include <linux/io.h>
29 #include <linux/clk.h>
30 #include <linux/cpufreq.h>
31 #include <linux/seq_file.h>
32 #include <linux/irq.h>
33 #include <linux/interrupt.h>
34 #include <linux/delay.h>
35 #include <linux/slab.h>
36 #include <linux/suspend.h>
37
38 #include <mach/tegra_fuse.h>
39 #include <mach/iomap.h>
40
41 #include "tegra11_soctherm.h"
42
43 #define CTL_LVL0_CPU0                   0x0
44 #define CTL_LVL0_CPU0_UP_THRESH_SHIFT   17
45 #define CTL_LVL0_CPU0_UP_THRESH_MASK    0xff
46 #define CTL_LVL0_CPU0_DN_THRESH_SHIFT   9
47 #define CTL_LVL0_CPU0_DN_THRESH_MASK    0xff
48 #define CTL_LVL0_CPU0_EN_SHIFT          8
49 #define CTL_LVL0_CPU0_EN_MASK           0x1
50 #define CTL_LVL0_CPU0_CPU_THROT_SHIFT   5
51 #define CTL_LVL0_CPU0_CPU_THROT_MASK    0x3
52 #define CTL_LVL0_CPU0_MEM_THROT_SHIFT   2
53 #define CTL_LVL0_CPU0_MEM_THROT_MASK    0x1
54 #define CTL_LVL0_CPU0_STATUS_SHIFT      0
55 #define CTL_LVL0_CPU0_STATUS_MASK       0x3
56
57 #define CTL_LVL_OFFSET          0x20
58 #define CTL_LVL_CPU0(lvl)       (CTL_LVL0_CPU0 + (lvl * CTL_LVL_OFFSET))
59
60 #define THERMTRIP                       0x80
61 #define THERMTRIP_ANY_EN_SHIFT          28
62 #define THERMTRIP_ANY_EN_MASK           0x1
63 #define THERMTRIP_MEM_EN_SHIFT          27
64 #define THERMTRIP_MEM_EN_MASK           0x1
65 #define THERMTRIP_GPU_EN_SHIFT          26
66 #define THERMTRIP_GPU_EN_MASK           0x1
67 #define THERMTRIP_CPU_EN_SHIFT          25
68 #define THERMTRIP_CPU_EN_MASK           0x1
69 #define THERMTRIP_TSENSE_EN_SHIFT       24
70 #define THERMTRIP_TSENSE_EN_MASK        0x1
71 #define THERMTRIP_GPUMEM_THRESH_SHIFT   16
72 #define THERMTRIP_GPUMEM_THRESH_MASK    0xff
73 #define THERMTRIP_CPU_THRESH_SHIFT      8
74 #define THERMTRIP_CPU_THRESH_MASK       0xff
75 #define THERMTRIP_TSENSE_THRESH_SHIFT   0
76 #define THERMTRIP_TSENSE_THRESH_MASK    0xff
77
78 #define TS_CPU0_CONFIG0                         0xc0
79 #define TS_CPU0_CONFIG0_TALL_SHIFT              8
80 #define TS_CPU0_CONFIG0_TALL_MASK               0xfffff
81 #define TS_CPU0_CONFIG0_TCALC_OVER_SHIFT        4
82 #define TS_CPU0_CONFIG0_TCALC_OVER_MASK         0x1
83 #define TS_CPU0_CONFIG0_OVER_SHIFT              3
84 #define TS_CPU0_CONFIG0_OVER_MASK               0x1
85 #define TS_CPU0_CONFIG0_CPTR_OVER_SHIFT         2
86 #define TS_CPU0_CONFIG0_CPTR_OVER_MASK          0x1
87 #define TS_CPU0_CONFIG0_STOP_SHIFT              0
88 #define TS_CPU0_CONFIG0_STOP_MASK               0x1
89
90 #define TS_CPU0_CONFIG1                 0xc4
91 #define TS_CPU0_CONFIG1_EN_SHIFT        31
92 #define TS_CPU0_CONFIG1_EN_MASK         0x1
93 #define TS_CPU0_CONFIG1_TIDDQ_SHIFT     15
94 #define TS_CPU0_CONFIG1_TIDDQ_MASK      0x3f
95 #define TS_CPU0_CONFIG1_TEN_COUNT_SHIFT 24
96 #define TS_CPU0_CONFIG1_TEN_COUNT_MASK  0x3f
97 #define TS_CPU0_CONFIG1_TSAMPLE_SHIFT   0
98 #define TS_CPU0_CONFIG1_TSAMPLE_MASK    0x3ff
99
100 #define TS_CPU0_CONFIG2                 0xc8
101 #define TS_CPU0_CONFIG2_THERM_A_SHIFT   16
102 #define TS_CPU0_CONFIG2_THERM_A_MASK    0xffff
103 #define TS_CPU0_CONFIG2_THERM_B_SHIFT   0
104 #define TS_CPU0_CONFIG2_THERM_B_MASK    0xffff
105
106 #define TS_CPU0_STATUS0                 0xcc
107 #define TS_CPU0_STATUS0_VALID_SHIFT     31
108 #define TS_CPU0_STATUS0_VALID_MASK      0x1
109 #define TS_CPU0_STATUS0_CAPTURE_SHIFT   0
110 #define TS_CPU0_STATUS0_CAPTURE_MASK    0xffff
111
112 #define TS_CPU0_STATUS1                         0xd0
113 #define TS_CPU0_STATUS1_TEMP_VALID_SHIFT        31
114 #define TS_CPU0_STATUS1_TEMP_VALID_MASK         0x1
115 #define TS_CPU0_STATUS1_TEMP_SHIFT              0
116 #define TS_CPU0_STATUS1_TEMP_MASK               0xffff
117
118 #define TS_CPU0_STATUS2                 0xd4
119
120 #define TS_CONFIG_STATUS_OFFSET         0x20
121
122 #define TS_MEM0_CONFIG0                 0x140
123 #define TS_MEM0_CONFIG0_TALL_SHIFT      8
124 #define TS_MEM0_CONFIG0_TALL_MASK       0xfffff
125
126 #define TS_MEM0_CONFIG1                 0x144
127 #define TS_MEM0_CONFIG1_EN_SHIFT        31
128 #define TS_MEM0_CONFIG1_EN_MASK         0x1
129 #define TS_MEM0_CONFIG1_TIDDQ_SHIFT     15
130 #define TS_MEM0_CONFIG1_TIDDQ_MASK      0x3f
131 #define TS_MEM0_CONFIG1_TEN_COUNT_SHIFT 24
132 #define TS_MEM0_CONFIG1_TEN_COUNT_MASK  0x3f
133 #define TS_MEM0_CONFIG1_TSAMPLE_SHIFT   0
134 #define TS_MEM0_CONFIG1_TSAMPLE_MASK    0x3ff
135
136 #define TS_MEM0_CONFIG2                 0x148
137 #define TS_MEM0_CONFIG2_THERM_A_SHIFT   16
138 #define TS_MEM0_CONFIG2_THERM_A_MASK    0xffff
139 #define TS_MEM0_CONFIG2_THERM_B_SHIFT   0
140 #define TS_MEM0_CONFIG2_THERM_B_MASK    0xffff
141
142 #define TS_MEM0_STATUS0                 0x14c
143 #define TS_MEM0_STATUS0_CAPTURE_SHIFT   0
144 #define TS_MEM0_STATUS0_CAPTURE_MASK    0xffff
145
146 #define TS_MEM0_STATUS1                         0x150
147 #define TS_MEM0_STATUS1_TEMP_VALID_SHIFT        31
148 #define TS_MEM0_STATUS1_TEMP_VALID_MASK         0x1
149 #define TS_MEM0_STATUS1_TEMP_SHIFT              0
150 #define TS_MEM0_STATUS1_TEMP_MASK               0xffff
151
152
153 #define TS_MEM0_STATUS2                 0x154
154
155 #define TS_PDIV                         0x1c0
156 #define TS_PDIV_CPU_SHIFT               12
157 #define TS_PDIV_CPU_MASK                0xf
158 #define TS_PDIV_GPU_SHIFT               8
159 #define TS_PDIV_GPU_MASK                0xf
160 #define TS_PDIV_MEM_SHIFT               4
161 #define TS_PDIV_MEM_MASK                0xf
162 #define TS_PDIV_PLLX_SHIFT              0
163 #define TS_PDIV_PLLX_MASK               0xf
164
165 #define TS_TEMP1                        0x1c8
166 #define TS_TEMP1_CPU_TEMP_SHIFT         16
167 #define TS_TEMP1_CPU_TEMP_MASK          0xffff
168 #define TS_TEMP1_GPU_TEMP_SHIFT         0
169 #define TS_TEMP1_GPU_TEMP_MASK          0xffff
170
171 #define TS_TEMP2                        0x1cc
172 #define TS_TEMP2_MEM_TEMP_SHIFT         16
173 #define TS_TEMP2_MEM_TEMP_MASK          0xffff
174 #define TS_TEMP2_PLLX_TEMP_SHIFT        0
175 #define TS_TEMP2_PLLX_TEMP_MASK         0xffff
176
177 #define UP_STATS_L0             0x10
178 #define DN_STATS_L0             0x14
179
180 #define INTR_STATUS                     0x84
181 #define INTR_STATUS_MD0_SHIFT           25
182 #define INTR_STATUS_MD0_MASK            0x1
183 #define INTR_STATUS_MU0_SHIFT           24
184 #define INTR_STATUS_MU0_MASK            0x1
185
186 #define INTR_EN                 0x88
187 #define INTR_EN_MU0_SHIFT       24
188 #define INTR_EN_MD0_SHIFT       25
189 #define INTR_EN_CU0_SHIFT       8
190 #define INTR_EN_CD0_SHIFT       9
191
192 #define INTR_DIS                0x8c
193 #define LOCK_CTL                0x90
194 #define STATS_CTL               0x94
195
196 #define THROT_GLOBAL_CFG                0x400
197
198 #define CPU_PSKIP_STATUS                        0x418
199 #define CPU_PSKIP_STATUS_M_SHIFT                12
200 #define CPU_PSKIP_STATUS_M_MASK                 0xff
201 #define CPU_PSKIP_STATUS_N_SHIFT                4
202 #define CPU_PSKIP_STATUS_N_MASK                 0xff
203 #define CPU_PSKIP_STATUS_ENABLED_SHIFT          0
204 #define CPU_PSKIP_STATUS_ENABLED_MASK           0x1
205
206 #define THROT_PRIORITY_LOCK                     0x424
207 #define THROT_PRIORITY_LOCK_PRIORITY_SHIFT      0
208 #define THROT_PRIORITY_LOCK_PRIORITY_MASK       0xff
209
210 #define THROT_STATUS                            0x428
211 #define THROT_STATUS_BREACH_SHIFT               12
212 #define THROT_STATUS_BREACH_MASK                0x1
213 #define THROT_STATUS_STATE_SHIFT                4
214 #define THROT_STATUS_STATE_MASK                 0xff
215 #define THROT_STATUS_ENABLED_SHIFT              0
216 #define THROT_STATUS_ENABLED_MASK               0x1
217
218 #define THROT_PSKIP_CTRL_LITE_CPU                       0x430
219 #define THROT_PSKIP_CTRL_ENABLE_SHIFT           31
220 #define THROT_PSKIP_CTRL_ENABLE_MASK            0x1
221 #define THROT_PSKIP_CTRL_DIVIDEND_SHIFT 8
222 #define THROT_PSKIP_CTRL_DIVIDEND_MASK          0xff
223 #define THROT_PSKIP_CTRL_DIVISOR_SHIFT          0
224 #define THROT_PSKIP_CTRL_DIVISOR_MASK           0xff
225
226 #define THROT_PSKIP_RAMP_LITE_CPU                       0x434
227 #define THROT_PSKIP_RAMP_DURATION_SHIFT 8
228 #define THROT_PSKIP_RAMP_DURATION_MASK          0xffff
229 #define THROT_PSKIP_RAMP_STEP_SHIFT             0
230 #define THROT_PSKIP_RAMP_STEP_MASK              0xff
231
232 #define THROT_LITE_PRIORITY                     0x444
233 #define THROT_LITE_PRIORITY_PRIORITY_SHIFT      0
234 #define THROT_LITE_PRIORITY_PRIORITY_MASK       0xff
235
236 #define THROT_OFFSET                            0x30
237
238 #define FUSE_BASE_CP_SHIFT      0
239 #define FUSE_BASE_CP_MASK       0x3ff
240 #define FUSE_BASE_FT_SHIFT      16
241 #define FUSE_BASE_FT_MASK       0x7ff
242 #define FUSE_SHIFT_CP_SHIFT     10
243 #define FUSE_SHIFT_CP_MASK      0x3f
244 #define FUSE_SHIFT_FT_SHIFT     27
245 #define FUSE_SHIFT_FT_MASK      0x1f
246
247 #define FUSE_TSENSOR_CALIB_FT_SHIFT     13
248 #define FUSE_TSENSOR_CALIB_FT_MASK      0x1fff
249 #define FUSE_TSENSOR_CALIB_CP_SHIFT     0
250 #define FUSE_TSENSOR_CALIB_CP_MASK      0x1fff
251
252 #define THROT_PSKIP_CTRL(throt, dev)            (THROT_PSKIP_CTRL_LITE_CPU + \
253                                                 (THROT_OFFSET * throt) + \
254                                                 (8 * dev))
255 #define THROT_PSKIP_RAMP(throt, dev)            (THROT_PSKIP_RAMP_LITE_CPU + \
256                                                 (THROT_OFFSET * throt) + \
257                                                 (8 * dev))
258
259 #define PSKIP_CTRL_OC1_CPU                      0x490
260
261 #define REG_SET(r,_name,val) \
262         ((r)&~(_name##_MASK<<_name##_SHIFT))|(((val)&_name##_MASK)<<_name##_SHIFT)
263
264 #define REG_GET(r,_name) \
265         (((r)&(_name##_MASK<<_name##_SHIFT))>>_name##_SHIFT)
266
267 static void __iomem *reg_soctherm_base = IO_ADDRESS(TEGRA_SOCTHERM_BASE);
268 static void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
269 static void __iomem *clk_reset_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
270
271 #define clk_reset_writel(value, reg) \
272         __raw_writel(value, (u32)clk_reset_base + (reg))
273 #define clk_reset_readl(reg) __raw_readl((u32)clk_reset_base + (reg))
274
275 #define pmc_writel(value, reg) __raw_writel(value, (u32)pmc_base + (reg))
276 #define pmc_readl(reg) __raw_readl((u32)pmc_base + (reg))
277
278 #define soctherm_writel(value, reg) \
279         __raw_writel(value, (u32)reg_soctherm_base + (reg))
280 #define soctherm_readl(reg) \
281         __raw_readl((u32)reg_soctherm_base + (reg))
282
283 static struct soctherm_platform_data plat_data;
284 #ifdef CONFIG_THERMAL
285 static struct thermal_zone_device *thz[THERM_SIZE];
286 #endif
287 static struct workqueue_struct *workqueue;
288 static struct work_struct work;
289
290 static char *therm_names[] = {
291         [THERM_CPU] = "CPU",
292         [THERM_MEM] = "MEM",
293         [THERM_GPU] = "GPU",
294         [THERM_PLL] = "PLL",
295 };
296
297 static char *sensor_names[] = {
298         [TSENSE_CPU0] = "cpu0",
299         [TSENSE_CPU1] = "cpu1",
300         [TSENSE_CPU2] = "cpu2",
301         [TSENSE_CPU3] = "cpu3",
302         [TSENSE_MEM0] = "mem0",
303         [TSENSE_MEM1] = "mem1",
304         [TSENSE_GPU]  = "gpu0",
305         [TSENSE_PLLX] = "pllx",
306 };
307
308 static int sensor2tsensorcalib[] = {
309         [TSENSE_CPU0] = 0,
310         [TSENSE_CPU1] = 1,
311         [TSENSE_CPU2] = 2,
312         [TSENSE_CPU3] = 3,
313         [TSENSE_MEM0] = 5,
314         [TSENSE_MEM1] = 6,
315         [TSENSE_GPU] = 4,
316         [TSENSE_PLLX] = 7,
317 };
318
319 static inline long temp_translate(int readback)
320 {
321         int abs = readback >> 8;
322         int lsb = (readback & 0x80) >> 7;
323         int sign = readback & 0x1;
324
325         return (abs * 1000 + lsb * 500) * (sign * -2 + 1);
326 }
327
328 #ifdef CONFIG_THERMAL
329 static int soctherm_set_limits(enum soctherm_therm_id therm,
330                                 long lo_limit, long hi_limit)
331 {
332         u32 r = soctherm_readl(CTL_LVL0_CPU0);
333         r = REG_SET(r, CTL_LVL0_CPU0_DN_THRESH, lo_limit);
334         r = REG_SET(r, CTL_LVL0_CPU0_UP_THRESH, hi_limit);
335         soctherm_writel(r, CTL_LVL0_CPU0);
336
337         soctherm_writel(1<<INTR_EN_CU0_SHIFT, INTR_EN);
338         soctherm_writel(1<<INTR_EN_CD0_SHIFT, INTR_EN);
339
340         return 0;
341 }
342
343 static void soctherm_update(void)
344 {
345         struct thermal_zone_device *dev = thz[THERM_CPU];
346         long temp, trip_temp, low_temp = 0, high_temp = 128000;
347         int count;
348
349         if (!dev)
350                 return;
351
352         if (!dev->passive)
353                 thermal_zone_device_update(dev);
354
355         dev->ops->get_temp(dev, &temp);
356
357         for (count = 0; count < dev->trips; count++) {
358                 dev->ops->get_trip_temp(dev, count, &trip_temp);
359
360                 if ((trip_temp >= temp) && (trip_temp < high_temp))
361                         high_temp = trip_temp;
362
363                 if ((trip_temp < temp) && (trip_temp > low_temp))
364                         low_temp = trip_temp;
365         }
366
367         soctherm_set_limits(THERM_CPU, low_temp/1000, high_temp/1000);
368 }
369
370 static int soctherm_bind(struct thermal_zone_device *thz,
371                                 struct thermal_cooling_device *cdevice)
372 {
373         int index = ((int)thz->devdata) - TSENSE_SIZE;
374
375         if (index < 0)
376                 return 0;
377
378         if (plat_data.therm[index].cdev == cdevice)
379                 return thermal_zone_bind_cooling_device(thz, 0, cdevice,
380                                                         THERMAL_NO_LIMIT,
381                                                         THERMAL_NO_LIMIT);
382
383         return 0;
384 }
385
386 static int soctherm_unbind(struct thermal_zone_device *thz,
387                                 struct thermal_cooling_device *cdevice)
388 {
389         int index = ((int)thz->devdata) - TSENSE_SIZE;
390
391         if (index < 0)
392                 return 0;
393
394         if (plat_data.therm[index].cdev == cdevice)
395                 return thermal_zone_unbind_cooling_device(thz, 0, cdevice);
396
397         return 0;
398 }
399
400 static int soctherm_get_temp(struct thermal_zone_device *thz,
401                                         unsigned long *temp)
402 {
403         int index = (int)thz->devdata;
404         u32 r;
405
406         if (index < TSENSE_SIZE) {
407                 r = soctherm_readl(TS_CPU0_STATUS1 +
408                                         index * TS_CONFIG_STATUS_OFFSET);
409                 *temp = temp_translate(REG_GET(r, TS_CPU0_STATUS1_TEMP));
410         } else {
411                 index -= TSENSE_SIZE;
412
413                 if (index == THERM_CPU || index == THERM_GPU)
414                         r = soctherm_readl(TS_TEMP1);
415                 else
416                         r = soctherm_readl(TS_TEMP2);
417
418                 if (index == THERM_CPU || index == THERM_MEM)
419                         *temp = temp_translate(REG_GET(r, TS_TEMP1_CPU_TEMP));
420                 else
421                         *temp = temp_translate(REG_GET(r, TS_TEMP1_GPU_TEMP));
422         }
423
424         return 0;
425 }
426
427 static int soctherm_get_trip_type(struct thermal_zone_device *thz,
428                                         int trip,
429                                         enum thermal_trip_type *type) {
430         int index = ((int)thz->devdata) - TSENSE_SIZE;
431
432         if (index < 0 || !plat_data.therm[index].cdev)
433                 return -EINVAL;
434
435         *type = THERMAL_TRIP_PASSIVE;
436         return 0;
437 }
438
439 static int soctherm_get_trip_temp(struct thermal_zone_device *thz,
440                                         int trip,
441                                         unsigned long *temp) {
442         int index = ((int)thz->devdata) - TSENSE_SIZE;
443
444         if (index < 0 || !plat_data.therm[index].cdev)
445                 return -EINVAL;
446
447         *temp = plat_data.therm[index].trip_temp;
448         return 0;
449 }
450
451 static int soctherm_set_trip_temp(struct thermal_zone_device *thz,
452                                         int trip,
453                                         unsigned long temp)
454 {
455         int index = ((int)thz->devdata) - TSENSE_SIZE;
456         if (index < 0 || !plat_data.therm[index].cdev)
457                 return -EINVAL;
458
459         plat_data.therm[index].trip_temp = temp;
460
461         soctherm_update();
462
463         return 0;
464 }
465
466 static struct thermal_zone_device_ops soctherm_ops = {
467         .bind = soctherm_bind,
468         .unbind = soctherm_unbind,
469         .get_temp = soctherm_get_temp,
470         .get_trip_type = soctherm_get_trip_type,
471         .get_trip_temp = soctherm_get_trip_temp,
472         .set_trip_temp = soctherm_set_trip_temp,
473 };
474
475 static int __init soctherm_thermal_init(void)
476 {
477         char name[64];
478         int i;
479
480 #if 0
481         for (i = 0; i < TSENSE_SIZE; i++) {
482                 if (plat_data.sensor_data[i].enable) {
483                         /* Let's avoid this for now */
484                         sprintf(name, "%s-tsensor", sensor_names[i]);
485                         /* Create a thermal zone device for each sensor */
486                         thermal_zone_device_register(
487                                         name,
488                                         0,
489                                         0,
490                                         (void *)i,
491                                         &soctherm_ops,
492                                         NULL,
493                                         0, 0, 0, 0);
494                 }
495         }
496 #endif
497
498         for (i = 0; i < THERM_SIZE; i++) {
499                 sprintf(name, "%s-therm", therm_names[i]);
500                 thz[i] = thermal_zone_device_register(
501                                         name,
502                                         plat_data.therm[i].cdev ? 1 : 0,
503                                         plat_data.therm[i].cdev ? 0x1 : 0,
504                                         (void *)TSENSE_SIZE + i,
505                                         &soctherm_ops,
506                                         NULL,
507                                         plat_data.therm[i].passive_delay,
508                                         0);
509         }
510
511         return 0;
512 }
513 module_init(soctherm_thermal_init);
514
515 #else
516 static void soctherm_update(void)
517 {
518 }
519 #endif
520
521 static void soctherm_work_func(struct work_struct *work)
522 {
523         soctherm_update();
524 }
525
526 static irqreturn_t soctherm_isr(int irq, void *arg_data)
527 {
528         u32 r;
529
530         queue_work(workqueue, &work);
531
532         r = soctherm_readl(INTR_STATUS);
533         soctherm_writel(r, INTR_STATUS);
534
535         return IRQ_HANDLED;
536 }
537
538 void tegra11_soctherm_throttle_program(enum soctherm_throttle_id throttle,
539                                         struct soctherm_throttle *data)
540 {
541         u32 r;
542         int i;
543         struct soctherm_throttle_dev *dev;
544
545         for (i = 0; i < THROTTLE_DEV_SIZE; i++) {
546                 dev = &data->devs[i];
547
548                 r = soctherm_readl(THROT_PSKIP_CTRL(throttle, i));
549                 r = REG_SET(r, THROT_PSKIP_CTRL_ENABLE, dev->enable);
550                 r = REG_SET(r, THROT_PSKIP_CTRL_DIVIDEND, dev->dividend);
551                 r = REG_SET(r, THROT_PSKIP_CTRL_DIVISOR, dev->divisor);
552                 soctherm_writel(r, THROT_PSKIP_CTRL(throttle, i));
553
554                 r = soctherm_readl(THROT_PSKIP_RAMP(throttle, i));
555                 r = REG_SET(r, THROT_PSKIP_RAMP_DURATION, dev->duration);
556                 r = REG_SET(r, THROT_PSKIP_RAMP_STEP, dev->step);
557                 soctherm_writel(r, THROT_PSKIP_RAMP(throttle, i));
558         }
559
560         r = soctherm_readl(THROT_PRIORITY_LOCK);
561         if (r < data->priority) {
562                 r = REG_SET(0, THROT_PRIORITY_LOCK_PRIORITY, data->priority);
563                 soctherm_writel(r, THROT_PRIORITY_LOCK);
564         }
565
566         r = REG_SET(0, THROT_LITE_PRIORITY_PRIORITY, data->priority);
567         soctherm_writel(r, THROT_LITE_PRIORITY + THROT_OFFSET * throttle);
568 }
569
570 static void __init soctherm_tsense_program(enum soctherm_sense sensor,
571                                                 struct soctherm_sensor *data)
572 {
573         u32 r;
574         int offset = sensor * TS_CONFIG_STATUS_OFFSET;
575
576         r = REG_SET(0, TS_CPU0_CONFIG0_TALL, data->tall);
577         soctherm_writel(r, TS_CPU0_CONFIG0 + offset);
578
579         r = REG_SET(0, TS_CPU0_CONFIG1_TIDDQ, data->tiddq);
580         r = REG_SET(r, TS_CPU0_CONFIG1_EN, data->enable);
581         r = REG_SET(r, TS_CPU0_CONFIG1_TEN_COUNT, data->ten_count);
582         r = REG_SET(r, TS_CPU0_CONFIG1_TSAMPLE, data->tsample);
583         soctherm_writel(r, TS_CPU0_CONFIG1 + offset);
584 }
585
586 static int soctherm_clk_enable(bool enable)
587 {
588         struct clk *soctherm_clk;
589         struct clk *pllp_clk;
590         struct clk *ts_clk;
591         struct clk *clk_m;
592         unsigned long soctherm_clk_rate, ts_clk_rate;
593
594         soctherm_clk = clk_get_sys("soc_therm", NULL);
595         if (IS_ERR(soctherm_clk))
596                 return -1;
597
598         ts_clk = clk_get_sys("tegra-tsensor", NULL);
599         if (IS_ERR(ts_clk))
600                 return -1;
601
602         if (enable) {
603                 pllp_clk = clk_get_sys(NULL, "pll_p");
604                 if (IS_ERR(pllp_clk))
605                         return -1;
606
607                 clk_m = clk_get_sys(NULL, "clk_m");
608                 if (IS_ERR(clk_m))
609                         return -1;
610
611                 clk_enable(soctherm_clk);
612                 soctherm_clk_rate = plat_data.soctherm_clk_rate;
613                 if (clk_get_parent(soctherm_clk) != pllp_clk)
614                         if (clk_set_parent(soctherm_clk, pllp_clk))
615                                 return -1;
616                 if (clk_get_rate(pllp_clk) != soctherm_clk_rate)
617                         if (clk_set_rate(soctherm_clk, soctherm_clk_rate))
618                                 return -1;
619
620                 clk_enable(ts_clk);
621                 ts_clk_rate = plat_data.tsensor_clk_rate;
622                 if (clk_get_parent(ts_clk) != clk_m)
623                         if (clk_set_parent(ts_clk, clk_m))
624                                 return -1;
625                 if (clk_get_rate(clk_m) != ts_clk_rate)
626                         if (clk_set_rate(ts_clk, ts_clk_rate))
627                                 return -1;
628         } else {
629                 clk_disable(soctherm_clk);
630                 clk_disable(ts_clk);
631                 clk_put(soctherm_clk);
632                 clk_put(ts_clk);
633         }
634
635         return 0;
636 }
637
638 static int soctherm_fuse_read_tsensor(enum soctherm_sense sensor)
639 {
640         u32 calib;
641         u32 fuse_base_cp;
642         u32 fuse_base_ft;
643         s32 fuse_shift_cp;
644         s32 fuse_shift_ft;
645         s32 actual_cp;
646         s32 actual_ft;
647         s32 delta_T;
648
649         s32 fuse_tsensor_ft;
650         s32 fuse_tsensor_cp;
651         s32 actual_tsensor_ft;
652         s32 actual_tsensor_cp;
653         s32 delta_count;
654         s16 therm_a;
655         s16 therm_b;
656
657         u8 pdiv;
658         int tsample;
659
660         u32 r;
661
662         tegra_fuse_get_vsensor_calib(&calib);
663         fuse_base_cp = REG_GET(calib, FUSE_BASE_CP);
664         fuse_base_ft = REG_GET(calib, FUSE_BASE_FT);
665         fuse_shift_cp = REG_GET(calib, FUSE_SHIFT_CP);
666         fuse_shift_ft = REG_GET(calib, FUSE_SHIFT_FT);
667
668         /* Make signed */
669         fuse_shift_cp <<= 26;
670         fuse_shift_cp >>= 26;
671         fuse_shift_ft <<= 27;
672         fuse_shift_ft >>= 27;
673
674         actual_cp = 25000 + (fuse_shift_cp * 500);
675         actual_ft = 90000 + (fuse_shift_ft * 500);
676         actual_cp /= 500;
677         actual_ft /= 500;
678         delta_T = actual_ft - actual_cp;
679
680         tegra_fuse_get_tsensor_calib(sensor2tsensorcalib[sensor], &calib);
681         fuse_tsensor_ft = REG_GET(calib, FUSE_TSENSOR_CALIB_FT);
682         fuse_tsensor_cp = REG_GET(calib, FUSE_TSENSOR_CALIB_CP);
683
684         /* Make signed */
685         fuse_tsensor_ft <<= 19;
686         fuse_tsensor_ft >>= 19;
687         fuse_tsensor_cp <<= 19;
688         fuse_tsensor_cp >>= 19;
689
690         actual_tsensor_ft = fuse_base_ft * 32 + fuse_tsensor_ft;
691         actual_tsensor_cp = fuse_base_cp * 64 + fuse_tsensor_cp;
692
693         pdiv = plat_data.sensor_data[sensor].pdiv;
694         tsample = plat_data.sensor_data[sensor].tsample;
695
696         actual_tsensor_ft = actual_tsensor_ft / pdiv * 10 / 5 * tsample / 131;
697         actual_tsensor_cp = actual_tsensor_cp / pdiv * 10 / 5 * tsample / 131;
698
699         delta_count = actual_tsensor_ft - actual_tsensor_cp;
700
701         therm_a = ((delta_T << 8) / delta_count) << 5;
702         therm_b = (actual_tsensor_ft / delta_count * actual_cp) -
703                         (actual_tsensor_cp / delta_count * actual_ft);
704
705         r = REG_SET(0, TS_CPU0_CONFIG2_THERM_A, therm_a);
706         r = REG_SET(r, TS_CPU0_CONFIG2_THERM_B, therm_b);
707         soctherm_writel(r, TS_CPU0_CONFIG2 + sensor * TS_CONFIG_STATUS_OFFSET);
708
709         return 0;
710 }
711
712 static int soctherm_init_platform_data(void)
713 {
714         struct soctherm_therm *therm;
715         int i;
716         u32 r;
717         u32 reg_off;
718
719         therm = plat_data.therm;
720
721         /* Can only thermtrip with either GPU or MEM but not both */
722         if (therm[THERM_GPU].thermtrip && therm[THERM_MEM].thermtrip)
723                 return -EINVAL;
724
725         if (soctherm_clk_enable(true) < 0)
726                 BUG();
727
728         /* Pdiv */
729         r = soctherm_readl(TS_PDIV);
730         r = REG_SET(r, TS_PDIV_CPU, plat_data.sensor_data[TSENSE_CPU0].pdiv);
731         r = REG_SET(r, TS_PDIV_GPU, plat_data.sensor_data[TSENSE_GPU].pdiv);
732         r = REG_SET(r, TS_PDIV_MEM, plat_data.sensor_data[TSENSE_MEM0].pdiv);
733         r = REG_SET(r, TS_PDIV_PLLX, plat_data.sensor_data[TSENSE_PLLX].pdiv);
734         soctherm_writel(r, TS_PDIV);
735
736         /* Thermal Sensing programming */
737         for (i = 0; i < TSENSE_SIZE; i++) {
738                 if (plat_data.sensor_data[i].enable) {
739                         soctherm_tsense_program(i, &plat_data.sensor_data[i]);
740                         soctherm_fuse_read_tsensor(i);
741                 }
742         }
743
744         for (i = 0; i < THERM_SIZE; i++) {
745                 if (plat_data.therm[i].hw_backstop) {
746                         reg_off = CTL_LVL_CPU0(1) + i * 4;
747                         r = soctherm_readl(reg_off);
748                         r = REG_SET(r, CTL_LVL0_CPU0_UP_THRESH,
749                                         plat_data.therm[i].hw_backstop);
750                         r = REG_SET(r, CTL_LVL0_CPU0_DN_THRESH,
751                                         plat_data.therm[i].hw_backstop - 2);
752                         r = REG_SET(r, CTL_LVL0_CPU0_EN, 1);
753                         /* Heavy throttling */
754                         r = REG_SET(r, CTL_LVL0_CPU0_CPU_THROT, 2);
755                         soctherm_writel(r, reg_off);
756                 }
757         }
758
759         /* Enable Level 0 */
760         r = soctherm_readl(CTL_LVL0_CPU0);
761         r = REG_SET(r, CTL_LVL0_CPU0_EN, !!therm[THERM_CPU].trip_temp);
762         soctherm_writel(r, CTL_LVL0_CPU0);
763
764         /* Thermtrip */
765         r = REG_SET(0, THERMTRIP_CPU_EN, !!therm[THERM_CPU].thermtrip);
766         r = REG_SET(r, THERMTRIP_GPU_EN, !!therm[THERM_GPU].thermtrip);
767         r = REG_SET(r, THERMTRIP_MEM_EN, !!therm[THERM_MEM].thermtrip);
768         r = REG_SET(r, THERMTRIP_TSENSE_EN, !!therm[THERM_PLL].thermtrip);
769         r = REG_SET(r, THERMTRIP_CPU_THRESH, therm[THERM_CPU].thermtrip);
770         r = REG_SET(r, THERMTRIP_GPUMEM_THRESH, therm[THERM_GPU].thermtrip |
771                                                 therm[THERM_MEM].thermtrip);
772         r = REG_SET(r, THERMTRIP_TSENSE_THRESH, therm[THERM_PLL].thermtrip);
773         soctherm_writel(r, THERMTRIP);
774
775         /* Enable PMC to shutdown */
776         r = pmc_readl(0x1b0);
777         r |= 0x2;
778         pmc_writel(r, 0x1b0);
779
780         /* Throttling */
781         for (i = 0; i < THROTTLE_SIZE; i++)
782                 tegra11_soctherm_throttle_program(i, &plat_data.throttle[i]);
783
784         r = clk_reset_readl(0x24);
785         r |= (1 << 30);
786         clk_reset_writel(r, 0x24);
787
788         return 0;
789 }
790
791 static int soctherm_suspend(void)
792 {
793         soctherm_clk_enable(false);
794         disable_irq(INT_THERMAL);
795         cancel_work_sync(&work);
796
797         return 0;
798 }
799
800 static int soctherm_resume(void)
801 {
802         soctherm_clk_enable(true);
803         enable_irq(INT_THERMAL);
804         soctherm_init_platform_data();
805         soctherm_update();
806
807         return 0;
808 }
809
810 static int soctherm_pm_notify(struct notifier_block *nb,
811                                 unsigned long event, void *data)
812 {
813         switch (event) {
814         case PM_SUSPEND_PREPARE:
815                 soctherm_suspend();
816                 break;
817         case PM_POST_SUSPEND:
818                 soctherm_resume();
819                 break;
820         }
821
822         return NOTIFY_OK;
823 }
824
825 static struct notifier_block soctherm_nb = {
826         .notifier_call = soctherm_pm_notify,
827 };
828
829 int __init tegra11_soctherm_init(struct soctherm_platform_data *data)
830 {
831         int err;
832
833         register_pm_notifier(&soctherm_nb);
834
835         memcpy(&plat_data, data, sizeof(struct soctherm_platform_data));
836
837         if (soctherm_clk_enable(true) < 0)
838                 BUG();
839
840         soctherm_init_platform_data();
841
842         /* enable interrupts */
843         workqueue = create_singlethread_workqueue("soctherm");
844         INIT_WORK(&work, soctherm_work_func);
845
846         err = request_irq(INT_THERMAL, soctherm_isr, 0, "soctherm", NULL);
847         if (err < 0)
848                 return -1;
849
850         soctherm_update();
851
852         return 0;
853 }
854
855
856 #ifdef CONFIG_DEBUG_FS
857 static int cpu0_show(struct seq_file *s, void *data)
858 {
859         u32 r;
860         int offset = TSENSE_PLLX * TS_CONFIG_STATUS_OFFSET;
861
862         r = soctherm_readl(TS_CPU0_CONFIG0 + offset);
863         r = REG_SET(r, TS_CPU0_CONFIG0_TCALC_OVER, 1);
864         r = REG_SET(r, TS_CPU0_CONFIG0_OVER, 1);
865         r = REG_SET(r, TS_CPU0_CONFIG0_CPTR_OVER, 1);
866         soctherm_writel(r, TS_CPU0_CONFIG0 + offset);
867
868         return 0;
869 }
870
871 static int regs_show(struct seq_file *s, void *data)
872 {
873         u32 r;
874         u32 state;
875         int i, level;
876
877         seq_printf(s, "-----TSENSE-----\n");
878         for (i = 0; i < TSENSE_SIZE; i++) {
879                 seq_printf(s, "%s: ", sensor_names[i]);
880
881                 r = soctherm_readl(TS_CPU0_STATUS0 +
882                                         i * TS_CONFIG_STATUS_OFFSET);
883                 state = REG_GET(r, TS_CPU0_STATUS0_VALID);
884                 seq_printf(s, "Capture(%d/", state);
885                 state = REG_GET(r, TS_CPU0_STATUS0_CAPTURE);
886                 seq_printf(s, "%d) ", state);
887
888
889                 r = soctherm_readl(TS_CPU0_STATUS1 +
890                                         i * TS_CONFIG_STATUS_OFFSET);
891                 state = REG_GET(r, TS_CPU0_STATUS1_TEMP_VALID);
892                 seq_printf(s, "Temp(%d/", state);
893                 state = REG_GET(r, TS_CPU0_STATUS1_TEMP);
894                 seq_printf(s, "%ld) ", temp_translate(state));
895
896
897                 r = soctherm_readl(TS_CPU0_CONFIG0 +
898                                         i * TS_CONFIG_STATUS_OFFSET);
899                 state = REG_GET(r, TS_CPU0_CONFIG0_TALL);
900                 seq_printf(s, "Tall(%d) ", state);
901                 state = REG_GET(r, TS_CPU0_CONFIG0_TCALC_OVER);
902                 seq_printf(s, "Over(%d/", state);
903                 state = REG_GET(r, TS_CPU0_CONFIG0_OVER);
904                 seq_printf(s, "%d/", state);
905                 state = REG_GET(r, TS_CPU0_CONFIG0_CPTR_OVER);
906                 seq_printf(s, "%d) ", state);
907
908                 r = soctherm_readl(TS_CPU0_CONFIG1 +
909                                         i * TS_CONFIG_STATUS_OFFSET);
910                 state = REG_GET(r, TS_CPU0_CONFIG1_EN);
911                 seq_printf(s, "En(%d) ", state);
912                 state = REG_GET(r, TS_CPU0_CONFIG1_TIDDQ);
913                 seq_printf(s, "tiddq(%d) ", state);
914                 state = REG_GET(r, TS_CPU0_CONFIG1_TEN_COUNT);
915                 seq_printf(s, "ten_count(%d) ", state);
916                 state = REG_GET(r, TS_CPU0_CONFIG1_TSAMPLE);
917                 seq_printf(s, "tsample(%d) ", state);
918
919                 r = soctherm_readl(TS_CPU0_CONFIG2 +
920                                         i * TS_CONFIG_STATUS_OFFSET);
921                 state = REG_GET(r, TS_CPU0_CONFIG2_THERM_A);
922                 seq_printf(s, "Therm_A/B(%d/", state);
923                 state = REG_GET(r, TS_CPU0_CONFIG2_THERM_B);
924                 seq_printf(s, "%d)\n", state);
925         }
926
927         r = soctherm_readl(TS_PDIV);
928         seq_printf(s, "PDIV: 0x%x\n", r);
929
930         seq_printf(s, "\n");
931         seq_printf(s, "-----SOC_THERM-----\n");
932
933         r = soctherm_readl(TS_TEMP1);
934         state = REG_GET(r, TS_TEMP1_CPU_TEMP);
935         seq_printf(s, "Temperature: CPU(%ld) ", temp_translate(state));
936         state = REG_GET(r, TS_TEMP1_GPU_TEMP);
937         seq_printf(s, " GPU(%ld) ", temp_translate(state));
938         r = soctherm_readl(TS_TEMP2);
939         state = REG_GET(r, TS_TEMP2_MEM_TEMP);
940         seq_printf(s, " MEM(%ld) ", temp_translate(state));
941         state = REG_GET(r, TS_TEMP2_PLLX_TEMP);
942         seq_printf(s, " PLLX(%ld)\n\n", temp_translate(state));
943
944         for (i = 0; i < THERM_SIZE; i++) {
945                 seq_printf(s, "%s:\n", therm_names[i]);
946
947                 for (level = 0; level < 4; level++) {
948                         r = soctherm_readl(CTL_LVL_CPU0(level) + i * 4);
949                         state = REG_GET(r, CTL_LVL0_CPU0_UP_THRESH);
950                         seq_printf(s, "    Up/Dn(%d/", state);
951                         state = REG_GET(r, CTL_LVL0_CPU0_DN_THRESH);
952                         seq_printf(s, "%d) ", state);
953                         state = REG_GET(r, CTL_LVL0_CPU0_EN);
954                         seq_printf(s, "En(%d) ", state);
955                         state = REG_GET(r, CTL_LVL0_CPU0_STATUS);
956                         seq_printf(s, "Status(%s)\n", state == 0 ? "below" :
957                                                 state == 1 ? "in" :
958                                                 state == 2 ? "res" :
959                                                         "above");
960                 }
961         }
962
963         r = soctherm_readl(INTR_STATUS);
964         state = REG_GET(r, INTR_STATUS_MD0);
965         seq_printf(s, "MD0: %d\n", state);
966         state = REG_GET(r, INTR_STATUS_MU0);
967         seq_printf(s, "MU0: %d\n", state);
968
969         r = soctherm_readl(THERMTRIP);
970         state = REG_GET(r, THERMTRIP_CPU_THRESH);
971         seq_printf(s, "THERMTRIP_CPU_THRESH: %d ", state);
972         state = REG_GET(r, THERMTRIP_CPU_EN);
973         seq_printf(s, "%d\n", state);
974
975
976         seq_printf(s, "\n-----THROTTLE-----\n");
977
978         r = soctherm_readl(THROT_GLOBAL_CFG);
979         seq_printf(s, "GLOBAL CONFIG: 0x%x\n", r);
980
981         r = soctherm_readl(THROT_STATUS);
982         state = REG_GET(r, THROT_STATUS_BREACH);
983         seq_printf(s, "THROT STATUS: breach(%d) ", state);
984         state = REG_GET(r, THROT_STATUS_STATE);
985         seq_printf(s, "state(%d) ", state);
986         state = REG_GET(r, THROT_STATUS_ENABLED);
987         seq_printf(s, "enabled(%d)\n", state);
988
989         r = soctherm_readl(CPU_PSKIP_STATUS);
990         state = REG_GET(r, CPU_PSKIP_STATUS_M);
991         seq_printf(s, "CPU PSKIP: M(%d) ", state);
992         state = REG_GET(r, CPU_PSKIP_STATUS_N);
993         seq_printf(s, "N(%d) ", state);
994         state = REG_GET(r, CPU_PSKIP_STATUS_ENABLED);
995         seq_printf(s, "enabled(%d)\n", state);
996
997         r = soctherm_readl(THROT_PSKIP_CTRL(THROTTLE_HEAVY, THROTTLE_DEV_CPU));
998         state = REG_GET(r, THROT_PSKIP_CTRL_ENABLE);
999         seq_printf(s, "CPU PSKIP HEAVY: enabled(%d) ", state);
1000         state = REG_GET(r, THROT_PSKIP_CTRL_DIVIDEND);
1001         seq_printf(s, "dividend(%d) ", state);
1002         state = REG_GET(r, THROT_PSKIP_CTRL_DIVISOR);
1003         seq_printf(s, "divisor(%d) ", state);
1004
1005         r = soctherm_readl(THROT_PSKIP_RAMP(THROTTLE_HEAVY, THROTTLE_DEV_CPU));
1006         state = REG_GET(r, THROT_PSKIP_RAMP_DURATION);
1007         seq_printf(s, "duration(%d) ", state);
1008         state = REG_GET(r, THROT_PSKIP_RAMP_STEP);
1009         seq_printf(s, "step(%d)\n", state);
1010
1011         return 0;
1012 }
1013
1014 static int regs_open(struct inode *inode, struct file *file)
1015 {
1016         return single_open(file, regs_show, inode->i_private);
1017 }
1018
1019 static const struct file_operations regs_fops = {
1020         .open           = regs_open,
1021         .read           = seq_read,
1022         .llseek         = seq_lseek,
1023         .release        = single_release,
1024 };
1025
1026 static int cpu0_open(struct inode *inode, struct file *file)
1027 {
1028         return single_open(file, cpu0_show, inode->i_private);
1029 }
1030
1031 static const struct file_operations cpu0_fops = {
1032         .open           = cpu0_open,
1033         .read           = seq_read,
1034         .llseek         = seq_lseek,
1035         .release        = single_release,
1036 };
1037
1038 static int __init soctherm_debug_init(void)
1039 {
1040         struct dentry *tegra_soctherm_root;
1041
1042         tegra_soctherm_root = debugfs_create_dir("tegra_soctherm", 0);
1043         debugfs_create_file("regs", 0644, tegra_soctherm_root,
1044                                 NULL, &regs_fops);
1045         debugfs_create_file("cpu0", 0644, tegra_soctherm_root,
1046                                 NULL, &cpu0_fops);
1047
1048         return 0;
1049 }
1050 late_initcall(soctherm_debug_init);
1051 #endif