thermal: soctherm: enable hardware thermal throttling config
[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-2013 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/slab.h>
35 #include <linux/suspend.h>
36 #include <linux/uaccess.h>
37 #include <linux/thermal.h>
38 #include <linux/platform_data/thermal_sensors.h>
39
40 #include <mach/tegra_fuse.h>
41 #include <mach/iomap.h>
42
43 #include "tegra11_soctherm.h"
44
45 /* Min temp granularity specified as X in 2^X.
46  * -1: Hi precision option: 2^-1 = 0.5C (default)
47  *  0: Lo precision option: 2^0  = 1.0C (for use if therm_a/b overflows 16 bits)
48  */
49 static int soc_therm_precision = -1;
50
51 #define TS_TSENSE_REGS_SIZE             0x20
52 #define TS_TSENSE_REG_OFFSET(reg, ts)   ((reg) + ((ts) * TS_TSENSE_REGS_SIZE))
53
54 #define TS_THERM_LVL_REGS_SIZE          0x20
55 #define TS_THERM_GRP_REGS_SIZE          0x04
56 #define TS_THERM_REG_OFFSET(rg, lv, gr) ((rg) + ((lv) * TS_THERM_LVL_REGS_SIZE)\
57                                         + ((gr) * TS_THERM_GRP_REGS_SIZE))
58
59 #define CTL_LVL0_CPU0                   0x0
60 #define CTL_LVL0_CPU0_UP_THRESH_SHIFT   17
61 #define CTL_LVL0_CPU0_UP_THRESH_MASK    0xff
62 #define CTL_LVL0_CPU0_DN_THRESH_SHIFT   9
63 #define CTL_LVL0_CPU0_DN_THRESH_MASK    0xff
64 #define CTL_LVL0_CPU0_EN_SHIFT          8
65 #define CTL_LVL0_CPU0_EN_MASK           0x1
66 #define CTL_LVL0_CPU0_CPU_THROT_SHIFT   5
67 #define CTL_LVL0_CPU0_CPU_THROT_MASK    0x3
68 #define CTL_LVL0_CPU0_CPU_THROT_LIGHT   0x1
69 #define CTL_LVL0_CPU0_CPU_THROT_HEAVY   0x2
70 #define CTL_LVL0_CPU0_MEM_THROT_SHIFT   2
71 #define CTL_LVL0_CPU0_MEM_THROT_MASK    0x1
72 #define CTL_LVL0_CPU0_STATUS_SHIFT      0
73 #define CTL_LVL0_CPU0_STATUS_MASK       0x3
74
75 #define THERMTRIP                       0x80
76 #define THERMTRIP_ANY_EN_SHIFT          28
77 #define THERMTRIP_ANY_EN_MASK           0x1
78 #define THERMTRIP_MEM_EN_SHIFT          27
79 #define THERMTRIP_MEM_EN_MASK           0x1
80 #define THERMTRIP_GPU_EN_SHIFT          26
81 #define THERMTRIP_GPU_EN_MASK           0x1
82 #define THERMTRIP_CPU_EN_SHIFT          25
83 #define THERMTRIP_CPU_EN_MASK           0x1
84 #define THERMTRIP_TSENSE_EN_SHIFT       24
85 #define THERMTRIP_TSENSE_EN_MASK        0x1
86 #define THERMTRIP_GPUMEM_THRESH_SHIFT   16
87 #define THERMTRIP_GPUMEM_THRESH_MASK    0xff
88 #define THERMTRIP_CPU_THRESH_SHIFT      8
89 #define THERMTRIP_CPU_THRESH_MASK       0xff
90 #define THERMTRIP_TSENSE_THRESH_SHIFT   0
91 #define THERMTRIP_TSENSE_THRESH_MASK    0xff
92
93 #define TS_CPU0_CONFIG0                         0xc0
94 #define TS_CPU0_CONFIG0_TALL_SHIFT              8
95 #define TS_CPU0_CONFIG0_TALL_MASK               0xfffff
96 #define TS_CPU0_CONFIG0_TCALC_OVER_SHIFT        4
97 #define TS_CPU0_CONFIG0_TCALC_OVER_MASK         0x1
98 #define TS_CPU0_CONFIG0_OVER_SHIFT              3
99 #define TS_CPU0_CONFIG0_OVER_MASK               0x1
100 #define TS_CPU0_CONFIG0_CPTR_OVER_SHIFT         2
101 #define TS_CPU0_CONFIG0_CPTR_OVER_MASK          0x1
102 #define TS_CPU0_CONFIG0_STOP_SHIFT              0
103 #define TS_CPU0_CONFIG0_STOP_MASK               0x1
104
105 #define TS_CPU0_CONFIG1                 0xc4
106 #define TS_CPU0_CONFIG1_EN_SHIFT        31
107 #define TS_CPU0_CONFIG1_EN_MASK         0x1
108 #define TS_CPU0_CONFIG1_TIDDQ_SHIFT     15
109 #define TS_CPU0_CONFIG1_TIDDQ_MASK      0x3f
110 #define TS_CPU0_CONFIG1_TEN_COUNT_SHIFT 24
111 #define TS_CPU0_CONFIG1_TEN_COUNT_MASK  0x3f
112 #define TS_CPU0_CONFIG1_TSAMPLE_SHIFT   0
113 #define TS_CPU0_CONFIG1_TSAMPLE_MASK    0x3ff
114
115 #define TS_CPU0_CONFIG2                 0xc8
116 #define TS_CPU0_CONFIG2_THERM_A_SHIFT   16
117 #define TS_CPU0_CONFIG2_THERM_A_MASK    0xffff
118 #define TS_CPU0_CONFIG2_THERM_B_SHIFT   0
119 #define TS_CPU0_CONFIG2_THERM_B_MASK    0xffff
120
121 #define TS_CPU0_STATUS0                 0xcc
122 #define TS_CPU0_STATUS0_VALID_SHIFT     31
123 #define TS_CPU0_STATUS0_VALID_MASK      0x1
124 #define TS_CPU0_STATUS0_CAPTURE_SHIFT   0
125 #define TS_CPU0_STATUS0_CAPTURE_MASK    0xffff
126
127 #define TS_CPU0_STATUS1                         0xd0
128 #define TS_CPU0_STATUS1_TEMP_VALID_SHIFT        31
129 #define TS_CPU0_STATUS1_TEMP_VALID_MASK         0x1
130 #define TS_CPU0_STATUS1_TEMP_SHIFT              0
131 #define TS_CPU0_STATUS1_TEMP_MASK               0xffff
132
133 #define TS_CPU0_STATUS2                 0xd4
134
135 #define TS_PDIV                         0x1c0
136 #define TS_PDIV_CPU_SHIFT               12
137 #define TS_PDIV_CPU_MASK                0xf
138 #define TS_PDIV_GPU_SHIFT               8
139 #define TS_PDIV_GPU_MASK                0xf
140 #define TS_PDIV_MEM_SHIFT               4
141 #define TS_PDIV_MEM_MASK                0xf
142 #define TS_PDIV_PLLX_SHIFT              0
143 #define TS_PDIV_PLLX_MASK               0xf
144
145 #define TS_TEMP1                        0x1c8
146 #define TS_TEMP1_CPU_TEMP_SHIFT         16
147 #define TS_TEMP1_CPU_TEMP_MASK          0xffff
148 #define TS_TEMP1_GPU_TEMP_SHIFT         0
149 #define TS_TEMP1_GPU_TEMP_MASK          0xffff
150
151 #define TS_TEMP2                        0x1cc
152 #define TS_TEMP2_MEM_TEMP_SHIFT         16
153 #define TS_TEMP2_MEM_TEMP_MASK          0xffff
154 #define TS_TEMP2_PLLX_TEMP_SHIFT        0
155 #define TS_TEMP2_PLLX_TEMP_MASK         0xffff
156
157 #define INTR_STATUS                     0x84
158 #define INTR_STATUS_CD2_SHIFT           13
159 #define INTR_STATUS_CD2_MASK            0x1
160 #define INTR_STATUS_CU2_SHIFT           12
161 #define INTR_STATUS_CU2_MASK            0x1
162 #define INTR_STATUS_CD1_SHIFT           11
163 #define INTR_STATUS_CD1_MASK            0x1
164 #define INTR_STATUS_CU1_SHIFT           10
165 #define INTR_STATUS_CU1_MASK            0x1
166 #define INTR_STATUS_CD0_SHIFT           9
167 #define INTR_STATUS_CD0_MASK            0x1
168 #define INTR_STATUS_CU0_SHIFT           8
169 #define INTR_STATUS_CU0_MASK            0x1
170
171 #define INTR_EN                 0x88
172 #define INTR_EN_MU0_SHIFT       24
173 #define INTR_EN_MD0_SHIFT       25
174 #define INTR_EN_CU0_SHIFT       8
175 #define INTR_EN_CD0_SHIFT       9
176
177 #define INTR_DIS                0x8c
178 #define LOCK_CTL                0x90
179
180 #define UP_STATS_L0             0x10
181 #define DN_STATS_L0             0x14
182
183 #define STATS_CTL               0x94
184 #define STATS_CTL_CLR_DN        0x8
185 #define STATS_CTL_EN_DN         0x4
186 #define STATS_CTL_CLR_UP        0x2
187 #define STATS_CTL_EN_UP         0x1
188
189 #define THROT_GLOBAL_CFG        0x400
190
191 #define CPU_PSKIP_STATUS                        0x418
192 #define CPU_PSKIP_STATUS_M_SHIFT                12
193 #define CPU_PSKIP_STATUS_M_MASK                 0xff
194 #define CPU_PSKIP_STATUS_N_SHIFT                4
195 #define CPU_PSKIP_STATUS_N_MASK                 0xff
196 #define CPU_PSKIP_STATUS_ENABLED_SHIFT          0
197 #define CPU_PSKIP_STATUS_ENABLED_MASK           0x1
198
199 #define THROT_PRIORITY_LOCK                     0x424
200 #define THROT_PRIORITY_LOCK_PRIORITY_SHIFT      0
201 #define THROT_PRIORITY_LOCK_PRIORITY_MASK       0xff
202
203 #define THROT_STATUS                            0x428
204 #define THROT_STATUS_BREACH_SHIFT               12
205 #define THROT_STATUS_BREACH_MASK                0x1
206 #define THROT_STATUS_STATE_SHIFT                4
207 #define THROT_STATUS_STATE_MASK                 0xff
208 #define THROT_STATUS_ENABLED_SHIFT              0
209 #define THROT_STATUS_ENABLED_MASK               0x1
210
211 #define THROT_PSKIP_CTRL_LITE_CPU               0x430
212 #define THROT_PSKIP_CTRL_ENABLE_SHIFT           31
213 #define THROT_PSKIP_CTRL_ENABLE_MASK            0x1
214 #define THROT_PSKIP_CTRL_DIVIDEND_SHIFT 8
215 #define THROT_PSKIP_CTRL_DIVIDEND_MASK          0xff
216 #define THROT_PSKIP_CTRL_DIVISOR_SHIFT          0
217 #define THROT_PSKIP_CTRL_DIVISOR_MASK           0xff
218
219 #define THROT_PSKIP_RAMP_LITE_CPU               0x434
220 #define THROT_PSKIP_RAMP_DURATION_SHIFT         8
221 #define THROT_PSKIP_RAMP_DURATION_MASK          0xffff
222 #define THROT_PSKIP_RAMP_STEP_SHIFT             0
223 #define THROT_PSKIP_RAMP_STEP_MASK              0xff
224
225 #define THROT_LITE_PRIORITY                     0x444
226 #define THROT_LITE_PRIORITY_PRIORITY_SHIFT      0
227 #define THROT_LITE_PRIORITY_PRIORITY_MASK       0xff
228
229 #define THROT_OFFSET                            0x30
230
231 #define FUSE_BASE_CP_SHIFT      0
232 #define FUSE_BASE_CP_MASK       0x3ff
233 #define FUSE_BASE_FT_SHIFT      16
234 #define FUSE_BASE_FT_MASK       0x7ff
235 #define FUSE_SHIFT_CP_SHIFT     10
236 #define FUSE_SHIFT_CP_MASK      0x3f
237 #define FUSE_SHIFT_CP_BITS      6
238 #define FUSE_SHIFT_FT_SHIFT     27
239 #define FUSE_SHIFT_FT_MASK      0x1f
240 #define FUSE_SHIFT_FT_BITS      5
241
242 #define FUSE_TSENSOR_CALIB_FT_SHIFT     13
243 #define FUSE_TSENSOR_CALIB_FT_MASK      0x1fff
244 #define FUSE_TSENSOR_CALIB_CP_SHIFT     0
245 #define FUSE_TSENSOR_CALIB_CP_MASK      0x1fff
246 #define FUSE_TSENSOR_CALIB_BITS         13
247
248 #define PSKIP_CTRL_OC1_CPU                      0x490
249
250 #define THROT_PSKIP_CTRL(throt, dev)            (THROT_PSKIP_CTRL_LITE_CPU + \
251                                                 (THROT_OFFSET * throt) + \
252                                                 (8 * dev))
253 #define THROT_PSKIP_RAMP(throt, dev)            (THROT_PSKIP_RAMP_LITE_CPU + \
254                                                 (THROT_OFFSET * throt) + \
255                                                 (8 * dev))
256
257 #define REG_SET(r, _name, val)  (((r) & ~(_name##_MASK << _name##_SHIFT)) | \
258                                  (((val) & _name##_MASK) << _name##_SHIFT))
259 #define REG_GET_BIT(r, _name)   ((r) & (_name##_MASK << _name##_SHIFT))
260 #define REG_GET(r, _name)       (REG_GET_BIT(r, _name) >> _name##_SHIFT)
261 #define MAKE_SIGNED32(val, nb)  ((s32)(val) << (32 - (nb)) >> (32 - (nb)))
262
263 static void __iomem *reg_soctherm_base = IO_ADDRESS(TEGRA_SOCTHERM_BASE);
264 static void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
265 static void __iomem *clk_reset_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
266
267 #define clk_reset_writel(value, reg) \
268         __raw_writel(value, (u32)clk_reset_base + (reg))
269 #define clk_reset_readl(reg) __raw_readl((u32)clk_reset_base + (reg))
270
271 #define pmc_writel(value, reg) __raw_writel(value, (u32)pmc_base + (reg))
272 #define pmc_readl(reg) __raw_readl((u32)pmc_base + (reg))
273
274 #define soctherm_writel(value, reg) \
275         __raw_writel(value, (u32)reg_soctherm_base + (reg))
276 #define soctherm_readl(reg) \
277         __raw_readl((u32)reg_soctherm_base + (reg))
278
279 #define max4(a, b, c, d)        (max((max((a), (b))), (max((c), (d)))))
280
281 static struct soctherm_platform_data plat_data;
282
283 /*
284  * Remove this flag once this "driver" is structured as a platform driver and
285  * the board files calls platform_device_register instead of directly calling
286  * tegra11_soctherm_init(). See nvbug 1206311.
287  */
288 static bool soctherm_init_platform_done;
289
290 static struct clk *soctherm_clk;
291 static struct clk *tsensor_clk;
292
293 #ifdef CONFIG_THERMAL
294 static struct thermal_zone_device *thz[THERM_SIZE];
295 #endif
296 static struct workqueue_struct *workqueue;
297 static struct work_struct work;
298
299 static u32 fuse_calib_base_cp;
300 static u32 fuse_calib_base_ft;
301 static s32 actual_temp_cp;
302 static s32 actual_temp_ft;
303
304 static char *therm_names[] = {
305         [THERM_CPU] = "CPU",
306         [THERM_MEM] = "MEM",
307         [THERM_GPU] = "GPU",
308         [THERM_PLL] = "PLL",
309 };
310
311 static char *sensor_names[] = {
312         [TSENSE_CPU0] = "cpu0",
313         [TSENSE_CPU1] = "cpu1",
314         [TSENSE_CPU2] = "cpu2",
315         [TSENSE_CPU3] = "cpu3",
316         [TSENSE_MEM0] = "mem0",
317         [TSENSE_MEM1] = "mem1",
318         [TSENSE_GPU]  = "gpu0",
319         [TSENSE_PLLX] = "pllx",
320 };
321
322 static int sensor2tsensorcalib[] = {
323         [TSENSE_CPU0] = 0,
324         [TSENSE_CPU1] = 1,
325         [TSENSE_CPU2] = 2,
326         [TSENSE_CPU3] = 3,
327         [TSENSE_MEM0] = 5,
328         [TSENSE_MEM1] = 6,
329         [TSENSE_GPU]  = 4,
330         [TSENSE_PLLX] = 7,
331 };
332
333 static int tsensor2therm_map[] = {
334         [TSENSE_CPU0] = THERM_CPU,
335         [TSENSE_CPU1] = THERM_CPU,
336         [TSENSE_CPU2] = THERM_CPU,
337         [TSENSE_CPU3] = THERM_CPU,
338         [TSENSE_GPU]  = THERM_GPU,
339         [TSENSE_MEM0] = THERM_MEM,
340         [TSENSE_MEM1] = THERM_MEM,
341         [TSENSE_PLLX] = THERM_PLL,
342 };
343
344 static enum soctherm_throttle_dev_id therm2dev[] = {
345         [THERM_CPU] = THROTTLE_DEV_CPU,
346         [THERM_MEM] = -1,
347         [THERM_GPU] = THROTTLE_DEV_GPU,
348         [THERM_PLL] = -1,
349 };
350
351 struct soctherm_sensor sensor_defaults = {
352         .tall      = 16300,
353         .tiddq     = 1,
354         .ten_count = 1,
355         .tsample   = 163,
356         .pdiv      = 10,
357 };
358
359 static unsigned long default_soctherm_clk_rate = 136000000;
360 static unsigned long default_tsensor_clk_rate = 500000;
361
362 static struct soctherm_throttle_dev throttle_defaults[] = {
363         [THROTTLE_LIGHT] = {
364                 .dividend = 229,        /* 20% throttling */
365                 .divisor  = 255,
366                 .duration = 0xff,
367                 .step     = 0xf,
368         },
369         [THROTTLE_HEAVY] = {
370                 .dividend = 51,         /* 80% throttling */
371                 .divisor  = 255,
372                 .duration = 0xff,
373                 .step     = 0xf,
374         },
375 };
376
377 static inline s64 div64_s64_precise(s64 a, s32 b)
378 {
379         s64 r, al;
380
381         /* scale up for increased precision in division */
382         al = a << 16;
383
384         r = div64_s64((al * 2) + 1, 2 * b);
385         return r >> 16;
386 }
387
388 static inline long temp_translate(int readback)
389 {
390         int abs = readback >> 8;
391         int lsb = (readback & 0x80) >> 7;
392         int sign = readback & 0x01 ? -1 : 1;
393
394         if (soc_therm_precision == -1)
395                 return (abs * 1000 + lsb * 500) * sign;
396         else
397                 return (abs * 2000 + lsb * 1000) * sign;
398 }
399
400 #ifdef CONFIG_THERMAL
401 static inline void prog_hw_shutdown(struct thermal_trip_info *trip_state,
402                                     int therm)
403 {
404         int trip_temp;
405         u32 r;
406
407         trip_temp = trip_state->trip_temp / 1000;
408
409         r = soctherm_readl(THERMTRIP);
410         if (therm == THERM_CPU) {
411                 r = REG_SET(r, THERMTRIP_CPU_EN, 1);
412                 r = REG_SET(r, THERMTRIP_CPU_THRESH, trip_temp);
413         } else {
414                 r = REG_SET(r, THERMTRIP_GPU_EN, 1);
415                 r = REG_SET(r, THERMTRIP_GPUMEM_THRESH, trip_temp);
416         }
417         soctherm_writel(r, THERMTRIP);
418 }
419
420 static inline void prog_hw_threshold(struct thermal_trip_info *trip_state,
421                                      int therm, int throt)
422 {
423         int trip_temp;
424         u32 r, reg_off;
425
426         trip_temp = trip_state->trip_temp / 1000;
427
428         /* Hardcode LITE on level-1 and HEAVY on level-2 */
429         reg_off = TS_THERM_REG_OFFSET(CTL_LVL0_CPU0, throt + 1, therm);
430
431         r = soctherm_readl(reg_off);
432         r = REG_SET(r, CTL_LVL0_CPU0_UP_THRESH, trip_temp);
433
434         trip_state->hysteresis = trip_state->hysteresis ?: 2000;
435         trip_temp -= (trip_state->hysteresis / 1000);
436
437         r = REG_SET(r, CTL_LVL0_CPU0_DN_THRESH, trip_temp);
438         r = REG_SET(r, CTL_LVL0_CPU0_EN, 1);
439         r = REG_SET(r, CTL_LVL0_CPU0_CPU_THROT,
440                     throt == THROTTLE_HEAVY ?
441                     CTL_LVL0_CPU0_CPU_THROT_HEAVY :
442                     CTL_LVL0_CPU0_CPU_THROT_LIGHT);
443
444         soctherm_writel(r, reg_off);
445 }
446
447 static int soctherm_set_limits(enum soctherm_therm_id therm,
448                                 long lo_limit, long hi_limit)
449 {
450         u32 r = soctherm_readl(CTL_LVL0_CPU0);
451         r = REG_SET(r, CTL_LVL0_CPU0_DN_THRESH, lo_limit);
452         r = REG_SET(r, CTL_LVL0_CPU0_UP_THRESH, hi_limit);
453         soctherm_writel(r, CTL_LVL0_CPU0);
454
455         soctherm_writel(1<<INTR_EN_CU0_SHIFT, INTR_EN);
456         soctherm_writel(1<<INTR_EN_CD0_SHIFT, INTR_EN);
457         return 0;
458 }
459
460 static void soctherm_update(void)
461 {
462         long temp, trip_temp, low_temp = 0, high_temp = 128000;
463         int i, count;
464         enum thermal_trip_type trip_type;
465
466         if (!soctherm_init_platform_done)
467                 return;
468
469         for (i = 0; i < THERM_SIZE; i++) {
470                 if (!thz[i])
471                         continue;
472
473                 thermal_zone_device_update(thz[i]);
474
475                 thz[i]->ops->get_temp(thz[i], &temp);
476
477                 for (count = 0; count < thz[i]->trips; count++) {
478                         thz[i]->ops->get_trip_type(thz[i], count, &trip_type);
479                         if ((trip_type == THERMAL_TRIP_HOT) ||
480                             (trip_type == THERMAL_TRIP_CRITICAL))
481                                 continue; /* handled in HW */
482
483                         thz[i]->ops->get_trip_temp(thz[i], count, &trip_temp);
484
485                         if ((trip_temp >= temp) && (trip_temp < high_temp))
486                                 high_temp = trip_temp;
487
488                         if ((trip_temp < temp) && (trip_temp > low_temp))
489                                 low_temp = trip_temp -
490                                     plat_data.therm[i].trips[count].hysteresis;
491                 }
492         }
493
494         soctherm_set_limits(THERM_CPU, low_temp/1000, high_temp/1000);
495 }
496
497 static int soctherm_hw_action_get_max_state(struct thermal_cooling_device *cdev,
498                                             unsigned long *max_state)
499 {
500         struct thermal_trip_info *trip_state = cdev->devdata;
501
502         if (!trip_state)
503                 return 0;
504
505         *max_state = 1;
506         return 0;
507 }
508
509 static int soctherm_hw_action_get_cur_state(struct thermal_cooling_device *cdev,
510                                             unsigned long *cur_state)
511 {
512         struct thermal_trip_info *trip_state = cdev->devdata;
513         u32 pskip_m;
514
515         if (!trip_state)
516                 return 0;
517
518         *cur_state = 0;
519         if (trip_state->trip_type != THERMAL_TRIP_HOT)
520                 return 0;
521
522         pskip_m = REG_GET(soctherm_readl(CPU_PSKIP_STATUS), CPU_PSKIP_STATUS_M);
523
524         if (strnstr(trip_state->cdev_type, "heavy", THERMAL_NAME_LENGTH) &&
525             pskip_m == throttle_defaults[THROTTLE_LIGHT].dividend)
526                 return 0;
527
528         if (strnstr(trip_state->cdev_type, "light", THERMAL_NAME_LENGTH) &&
529             pskip_m == throttle_defaults[THROTTLE_HEAVY].dividend)
530                 return 0;
531
532         *cur_state =
533                 !!REG_GET(soctherm_readl(THROT_STATUS), THROT_STATUS_STATE);
534         return 0;
535 }
536
537 static int soctherm_hw_action_set_cur_state(struct thermal_cooling_device *cdev,
538                                             unsigned long cur_state)
539 {
540         return 0; /* hw sets this state */
541 }
542
543 static struct thermal_cooling_device_ops soctherm_hw_action_ops = {
544         .get_max_state = soctherm_hw_action_get_max_state,
545         .get_cur_state = soctherm_hw_action_get_cur_state,
546         .set_cur_state = soctherm_hw_action_set_cur_state,
547 };
548
549 static int soctherm_bind(struct thermal_zone_device *thz,
550                                 struct thermal_cooling_device *cdev)
551 {
552         int i, index = ((int)thz->devdata) - TSENSE_SIZE;
553         struct thermal_trip_info *trip_state;
554
555         if (index < 0)
556                 return 0;
557
558         for (i = 0; i < plat_data.therm[index].num_trips; i++) {
559                 trip_state = &plat_data.therm[index].trips[i];
560                 trip_state->hysteresis = trip_state->hysteresis ?: 2000;
561                 if (trip_state->cdev_type &&
562                     !strncmp(trip_state->cdev_type, cdev->type,
563                              THERMAL_NAME_LENGTH))
564                         thermal_zone_bind_cooling_device(thz, i, cdev,
565                                                          trip_state->upper,
566                                                          trip_state->lower);
567         }
568
569         return 0;
570 }
571
572 static int soctherm_unbind(struct thermal_zone_device *thz,
573                                 struct thermal_cooling_device *cdev)
574 {
575         int i, index = ((int)thz->devdata) - TSENSE_SIZE;
576         struct thermal_trip_info *trip_state;
577
578         if (index < 0)
579                 return 0;
580
581         for (i = 0; i < plat_data.therm[index].num_trips; i++) {
582                 trip_state = &plat_data.therm[index].trips[i];
583                 if (trip_state->cdev_type &&
584                     !strncmp(trip_state->cdev_type, cdev->type,
585                              THERMAL_NAME_LENGTH))
586                         thermal_zone_unbind_cooling_device(thz, 0, cdev);
587         }
588
589         return 0;
590 }
591
592 static int soctherm_get_temp(struct thermal_zone_device *thz,
593                                         unsigned long *temp)
594 {
595         int index = (int)thz->devdata;
596         u32 r;
597
598         if (index < TSENSE_SIZE) {
599                 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_STATUS1,
600                                                         index));
601                 *temp = temp_translate(REG_GET(r, TS_CPU0_STATUS1_TEMP));
602         } else {
603                 index -= TSENSE_SIZE;
604
605                 if (index == THERM_CPU || index == THERM_GPU)
606                         r = soctherm_readl(TS_TEMP1);
607                 else
608                         r = soctherm_readl(TS_TEMP2);
609
610                 if (index == THERM_CPU || index == THERM_MEM)
611                         *temp = temp_translate(REG_GET(r, TS_TEMP1_CPU_TEMP));
612                 else
613                         *temp = temp_translate(REG_GET(r, TS_TEMP1_GPU_TEMP));
614
615                 plat_data.therm[index].etemp = *temp;
616         }
617
618         return 0;
619 }
620
621 static int soctherm_get_trip_type(struct thermal_zone_device *thz,
622                                 int trip, enum thermal_trip_type *type)
623 {
624         int index = ((int)thz->devdata) - TSENSE_SIZE;
625         struct thermal_trip_info *trip_state;
626
627         if (index < 0)
628                 return -EINVAL;
629
630         trip_state = &plat_data.therm[index].trips[trip];
631         *type = trip_state->trip_type;
632         return 0;
633 }
634
635 static int soctherm_get_trip_temp(struct thermal_zone_device *thz,
636                                 int trip, unsigned long *temp)
637 {
638         int index = ((int)thz->devdata) - TSENSE_SIZE;
639         struct thermal_trip_info *trip_state;
640
641         if (index < 0)
642                 return -EINVAL;
643
644         trip_state = &plat_data.therm[index].trips[trip];
645         *temp = trip_state->trip_temp;
646         return 0;
647 }
648
649 static int soctherm_set_trip_temp(struct thermal_zone_device *thz,
650                                 int trip, unsigned long temp)
651 {
652         int index = ((int)thz->devdata) - TSENSE_SIZE;
653         struct thermal_trip_info *trip_state;
654
655         if (index < 0)
656                 return -EINVAL;
657
658         trip_state = &plat_data.therm[index].trips[trip];
659         trip_state->trip_temp = temp;
660
661         if (trip_state->trip_type == THERMAL_TRIP_HOT) {
662                 if (strnstr(trip_state->cdev_type,
663                                 "heavy", THERMAL_NAME_LENGTH))
664                         prog_hw_threshold(trip_state, index, THROTTLE_HEAVY);
665                 else if (strnstr(trip_state->cdev_type,
666                                 "light", THERMAL_NAME_LENGTH))
667                         prog_hw_threshold(trip_state, index, THROTTLE_LIGHT);
668         }
669
670         /* Allow SW to shutdown at 'Critical temperature reached' */
671         soctherm_update();
672
673         /* Reprogram HW thermtrip */
674         if (trip_state->trip_type == THERMAL_TRIP_CRITICAL)
675                 prog_hw_shutdown(trip_state, index);
676
677         return 0;
678 }
679
680 static int soctherm_get_trend(struct thermal_zone_device *thz,
681                                 int trip,
682                                 enum thermal_trend *trend)
683 {
684         int index = ((int)thz->devdata) - TSENSE_SIZE;
685         struct thermal_trip_info *trip_state;
686
687         if (index < 0)
688                 return -EINVAL;
689
690         trip_state = &plat_data.therm[index].trips[trip];
691
692         switch (trip_state->trip_type) {
693         case THERMAL_TRIP_ACTIVE:
694                 /* aggressive active cooling */
695                 *trend = THERMAL_TREND_RAISING;
696                 break;
697         case THERMAL_TRIP_PASSIVE:
698                 if (plat_data.therm[index].etemp > trip_state->trip_temp)
699                         *trend = THERMAL_TREND_RAISING;
700                 else
701                         *trend = THERMAL_TREND_DROPPING;
702                 break;
703         default:
704                 return -EINVAL;
705         }
706
707         return 0;
708 }
709
710 static struct thermal_zone_device_ops soctherm_ops = {
711         .bind = soctherm_bind,
712         .unbind = soctherm_unbind,
713         .get_temp = soctherm_get_temp,
714         .get_trip_type = soctherm_get_trip_type,
715         .get_trip_temp = soctherm_get_trip_temp,
716         .set_trip_temp = soctherm_set_trip_temp,
717         .get_trend = soctherm_get_trend,
718 };
719
720 static int __init soctherm_thermal_sys_init(void)
721 {
722         char name[THERMAL_NAME_LENGTH];
723         struct soctherm_therm *therm;
724         int i, j, k;
725
726         if (!soctherm_init_platform_done)
727                 return 0;
728
729
730         for (i = 0; i < TSENSE_SIZE; i++) {
731                 if (plat_data.sensor_data[i].zone_enable) {
732                         snprintf(name, THERMAL_NAME_LENGTH,
733                                  "%s-tsensor", sensor_names[i]);
734                         /* Create a thermal zone device for each sensor */
735                         thermal_zone_device_register(
736                                         name,
737                                         0,
738                                         0,
739                                         (void *)i,
740                                         &soctherm_ops,
741                                         NULL,
742                                         0,
743                                         0);
744                 }
745         }
746
747         for (i = 0; i < THERM_SIZE; i++) {
748                 therm = &plat_data.therm[i];
749                 if (!therm->zone_enable)
750                         continue;
751
752                 for (j = 0; j < therm->num_trips; j++) {
753                         switch (therm->trips[j].trip_type) {
754                         case THERMAL_TRIP_CRITICAL:
755                                 thermal_cooling_device_register(
756                                                 therm->trips[j].cdev_type,
757                                                 &therm->trips[j],
758                                                 &soctherm_hw_action_ops);
759                                 break;
760
761                         case THERMAL_TRIP_HOT:
762                                 for (k = 0; k < THROTTLE_SIZE; k++) {
763                                         if ((strnstr(therm->trips[j].cdev_type,
764                                                      "heavy",
765                                                      THERMAL_NAME_LENGTH)
766                                              && k == THROTTLE_LIGHT) ||
767                                             (strnstr(therm->trips[j].cdev_type,
768                                                      "light",
769                                                      THERMAL_NAME_LENGTH)
770                                              && k == THROTTLE_HEAVY))
771                                                 continue;
772
773                                         if (!plat_data.throttle[k].
774                                             devs[therm2dev[i]].enable)
775                                                 continue;
776
777                                         thermal_cooling_device_register(
778                                                 therm->trips[j].cdev_type,
779                                                 &therm->trips[j],
780                                                 &soctherm_hw_action_ops);
781                                 }
782                                 break;
783
784                         case THERMAL_TRIP_PASSIVE:
785                         case THERMAL_TRIP_ACTIVE:
786                                 break; /* done elsewhere */
787                         }
788                 }
789
790                 snprintf(name, THERMAL_NAME_LENGTH,
791                          "%s-therm", therm_names[i]);
792                 thz[i] = thermal_zone_device_register(
793                                         name,
794                                         therm->num_trips,
795                                         (1 << therm->num_trips) - 1,
796                                         (void *)TSENSE_SIZE + i,
797                                         &soctherm_ops,
798                                         NULL,
799                                         therm->passive_delay,
800                                         0);
801         }
802
803         soctherm_update();
804         return 0;
805 }
806 module_init(soctherm_thermal_sys_init);
807
808 #else
809 static void soctherm_update(void)
810 {
811 }
812 #endif
813
814 static void soctherm_work_func(struct work_struct *work)
815 {
816         u32 st, ex = 0;
817
818         st = soctherm_readl(INTR_STATUS);
819
820         /* deliberately clear expected interrupts handled in SW */
821         ex |= REG_GET_BIT(st, INTR_STATUS_CD0);
822         ex |= REG_GET_BIT(st, INTR_STATUS_CU0);
823         if (ex) {
824                 soctherm_writel(ex, INTR_STATUS);
825                 st &= ~ex;
826                 soctherm_update();
827         }
828
829         /* deliberately ignore expected interrupts NOT handled in SW */
830         ex |= REG_GET_BIT(st, INTR_STATUS_CD1);
831         ex |= REG_GET_BIT(st, INTR_STATUS_CU1);
832         ex |= REG_GET_BIT(st, INTR_STATUS_CD2);
833         ex |= REG_GET_BIT(st, INTR_STATUS_CU2);
834         st &= ~ex;
835
836         if (!st)
837                 return;
838
839         /* Whine about any other unexpected INTR bits still set */
840         pr_err("soctherm: Ignored unexpected INTRs 0x%08x\n", st);
841         soctherm_writel(st, INTR_STATUS);
842 }
843
844 static irqreturn_t soctherm_isr(int irq, void *arg_data)
845 {
846         u32 r;
847
848         queue_work(workqueue, &work);
849
850         r = soctherm_readl(INTR_STATUS);
851         soctherm_writel(r, INTR_DIS);
852
853         return IRQ_HANDLED;
854 }
855
856 void tegra11_soctherm_throttle_program(enum soctherm_throttle_id throttle,
857                                         struct soctherm_throttle *data)
858 {
859         u32 r;
860         int i;
861         struct soctherm_throttle_dev *dev;
862
863         for (i = 0; i < THROTTLE_DEV_SIZE; i++) {
864                 dev = &data->devs[i];
865
866                 r = soctherm_readl(THROT_PSKIP_CTRL(throttle, i));
867                 r = REG_SET(r, THROT_PSKIP_CTRL_ENABLE, dev->enable);
868                 if (!dev->enable)
869                         continue;
870
871                 r = REG_SET(r, THROT_PSKIP_CTRL_DIVIDEND,
872                         dev->dividend ?: throttle_defaults[throttle].dividend);
873                 r = REG_SET(r, THROT_PSKIP_CTRL_DIVISOR,
874                         dev->divisor ?: throttle_defaults[throttle].divisor);
875                 soctherm_writel(r, THROT_PSKIP_CTRL(throttle, i));
876
877                 r = soctherm_readl(THROT_PSKIP_RAMP(throttle, i));
878                 r = REG_SET(r, THROT_PSKIP_RAMP_DURATION,
879                         dev->duration ?: throttle_defaults[throttle].duration);
880                 r = REG_SET(r, THROT_PSKIP_RAMP_STEP,
881                         dev->step ?: throttle_defaults[throttle].step);
882                 soctherm_writel(r, THROT_PSKIP_RAMP(throttle, i));
883         }
884
885         r = soctherm_readl(THROT_PRIORITY_LOCK);
886         if (r < data->priority) {
887                 r = REG_SET(0, THROT_PRIORITY_LOCK_PRIORITY, data->priority);
888                 soctherm_writel(r, THROT_PRIORITY_LOCK);
889         }
890
891         r = REG_SET(0, THROT_LITE_PRIORITY_PRIORITY, data->priority);
892         soctherm_writel(r, THROT_LITE_PRIORITY + THROT_OFFSET * throttle);
893
894         /* initialize stats collection */
895         r = STATS_CTL_CLR_DN | STATS_CTL_EN_DN |
896                 STATS_CTL_CLR_UP | STATS_CTL_EN_UP;
897         soctherm_writel(r, STATS_CTL);
898 }
899
900 static void __init soctherm_tsense_program(enum soctherm_sense sensor,
901                                                 struct soctherm_sensor *data)
902 {
903         u32 r;
904
905         r = REG_SET(0, TS_CPU0_CONFIG0_TALL, data->tall);
906         soctherm_writel(r, TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG0, sensor));
907
908         r = REG_SET(0, TS_CPU0_CONFIG1_TIDDQ, data->tiddq);
909         r = REG_SET(r, TS_CPU0_CONFIG1_EN, 1);
910         r = REG_SET(r, TS_CPU0_CONFIG1_TEN_COUNT, data->ten_count);
911         r = REG_SET(r, TS_CPU0_CONFIG1_TSAMPLE, data->tsample);
912         soctherm_writel(r, TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG1, sensor));
913 }
914
915 static int __init soctherm_clk_init(void)
916 {
917         soctherm_clk = clk_get_sys("soc_therm", NULL);
918         tsensor_clk = clk_get_sys("tegra-tsensor", NULL);
919
920         if (IS_ERR(tsensor_clk) || IS_ERR(soctherm_clk)) {
921                 clk_put(soctherm_clk);
922                 clk_put(tsensor_clk);
923                 soctherm_clk = tsensor_clk = NULL;
924                 return -EINVAL;
925         }
926
927         /* initialize default clock rates */
928         plat_data.soctherm_clk_rate =
929                 plat_data.soctherm_clk_rate ?: default_soctherm_clk_rate;
930         plat_data.tsensor_clk_rate =
931                 plat_data.tsensor_clk_rate ?: default_tsensor_clk_rate;
932
933         if (clk_get_rate(soctherm_clk) != plat_data.soctherm_clk_rate)
934                 if (clk_set_rate(soctherm_clk, plat_data.soctherm_clk_rate))
935                         return -EINVAL;
936
937         if (clk_get_rate(tsensor_clk) != plat_data.tsensor_clk_rate)
938                 if (clk_set_rate(tsensor_clk, plat_data.tsensor_clk_rate))
939                         return -EINVAL;
940
941         return 0;
942 }
943
944 static int soctherm_clk_enable(bool enable)
945 {
946         if (soctherm_clk == NULL || tsensor_clk == NULL)
947                 return -EINVAL;
948
949         if (enable) {
950                 clk_enable(soctherm_clk);
951                 clk_enable(tsensor_clk);
952         } else {
953                 clk_disable(soctherm_clk);
954                 clk_disable(tsensor_clk);
955         }
956
957         return 0;
958 }
959
960 static void soctherm_fuse_read_vsensor(void)
961 {
962         u32 value;
963         s32 calib_cp, calib_ft;
964
965         tegra_fuse_get_vsensor_calib(&value);
966
967         /* Extract bits */
968         fuse_calib_base_cp = REG_GET(value, FUSE_BASE_CP);
969         fuse_calib_base_ft = REG_GET(value, FUSE_BASE_FT);
970
971         /* Extract bits and convert to signed 2's complement */
972         calib_cp = REG_GET(value, FUSE_SHIFT_CP);
973         calib_cp = MAKE_SIGNED32(calib_cp, FUSE_SHIFT_CP_BITS);
974
975         calib_ft = REG_GET(value, FUSE_SHIFT_FT);
976         calib_ft = MAKE_SIGNED32(calib_ft, FUSE_SHIFT_FT_BITS);
977
978         /* default: HI precision: use fuse_temp in 0.5C */
979         actual_temp_cp = 2 * 25 + calib_cp;
980         actual_temp_ft = 2 * 90 + calib_ft;
981
982         /* adjust: for LO precision: use fuse_temp in 1C */
983         if (soc_therm_precision != -1) {
984                 actual_temp_cp /= 2;
985                 actual_temp_ft /= 2;
986         }
987 }
988
989 static void soctherm_fuse_read_tsensor(enum soctherm_sense sensor)
990 {
991         u32 r, value;
992         s32 calib, delta_sens, delta_temp;
993         s16 therm_a, therm_b;
994         s32 div, mult, actual_tsensor_ft, actual_tsensor_cp;
995
996         tegra_fuse_get_tsensor_calib(sensor2tsensorcalib[sensor], &value);
997
998         /* Extract bits and convert to signed 2's complement */
999         calib = REG_GET(value, FUSE_TSENSOR_CALIB_FT);
1000         calib = MAKE_SIGNED32(calib, FUSE_TSENSOR_CALIB_BITS);
1001         actual_tsensor_ft = (fuse_calib_base_ft * 32) + calib;
1002
1003         calib = REG_GET(value, FUSE_TSENSOR_CALIB_CP);
1004         calib = MAKE_SIGNED32(calib, FUSE_TSENSOR_CALIB_BITS);
1005         actual_tsensor_cp = (fuse_calib_base_cp * 64) + calib;
1006
1007         mult = plat_data.sensor_data[sensor].pdiv * 655;
1008         div = plat_data.sensor_data[sensor].tsample * 10;
1009
1010         delta_sens = actual_tsensor_ft - actual_tsensor_cp;
1011         delta_temp = actual_temp_ft - actual_temp_cp;
1012
1013         therm_a = div64_s64_precise((s64)delta_temp * (1LL << 13) * mult,
1014                                     (s64)delta_sens * div);
1015
1016         therm_b = div64_s64_precise((((s64)actual_tsensor_ft * actual_temp_cp) -
1017                                      ((s64)actual_tsensor_cp * actual_temp_ft)),
1018                                     (s64)delta_sens);
1019
1020         r = REG_SET(0, TS_CPU0_CONFIG2_THERM_A, therm_a);
1021         r = REG_SET(r, TS_CPU0_CONFIG2_THERM_B, therm_b);
1022         soctherm_writel(r, TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG2, sensor));
1023 }
1024
1025 static int soctherm_init_platform_data(void)
1026 {
1027         struct soctherm_therm *therm;
1028         struct soctherm_sensor *s;
1029         int i, j, k;
1030         u32 r;
1031
1032         /* initialize default values for unspecified params */
1033         for (i = 0; i < TSENSE_SIZE; i++) {
1034                 therm = &plat_data.therm[tsensor2therm_map[i]];
1035                 s = &plat_data.sensor_data[i];
1036                 s->sensor_enable = s->zone_enable;
1037                 s->sensor_enable = s->sensor_enable ?: therm->zone_enable;
1038                 s->tall      = s->tall      ?: sensor_defaults.tall;
1039                 s->tiddq     = s->tiddq     ?: sensor_defaults.tiddq;
1040                 s->ten_count = s->ten_count ?: sensor_defaults.ten_count;
1041                 s->tsample   = s->tsample   ?: sensor_defaults.tsample;
1042                 s->pdiv      = s->pdiv      ?: sensor_defaults.pdiv;
1043         }
1044
1045         /* Pdiv */
1046         r = soctherm_readl(TS_PDIV);
1047         r = REG_SET(r, TS_PDIV_CPU, plat_data.sensor_data[TSENSE_CPU0].pdiv);
1048         r = REG_SET(r, TS_PDIV_GPU, plat_data.sensor_data[TSENSE_GPU].pdiv);
1049         r = REG_SET(r, TS_PDIV_MEM, plat_data.sensor_data[TSENSE_MEM0].pdiv);
1050         r = REG_SET(r, TS_PDIV_PLLX, plat_data.sensor_data[TSENSE_PLLX].pdiv);
1051         soctherm_writel(r, TS_PDIV);
1052
1053         /* Thermal Sensing programming */
1054         soctherm_fuse_read_vsensor();
1055         for (i = 0; i < TSENSE_SIZE; i++) {
1056                 if (plat_data.sensor_data[i].sensor_enable) {
1057                         soctherm_tsense_program(i, &plat_data.sensor_data[i]);
1058                         soctherm_fuse_read_tsensor(i);
1059                 }
1060         }
1061
1062         /* Sanitize HW throttle priority */
1063         for (i = 0; i < THROTTLE_SIZE; i++)
1064                 if (!plat_data.throttle[i].priority)
1065                         plat_data.throttle[i].priority = 0xE + i;
1066         if (plat_data.throttle[THROTTLE_HEAVY].priority <
1067             plat_data.throttle[THROTTLE_LIGHT].priority)
1068                 pr_err("soctherm: ERROR: Priority of HEAVY less than LIGHT\n");
1069
1070         /* Thermal HW throttle programming */
1071         for (i = 0; i < THROTTLE_SIZE; i++) {
1072                 /* Setup PSKIP parameters */
1073                 tegra11_soctherm_throttle_program(i, &plat_data.throttle[i]);
1074
1075                 /* Setup throttle thresholds per THERM */
1076                 for (j = 0; j < THERM_SIZE; j++) {
1077                         /* Check if PSKIP params are enabled */
1078                         if ((therm2dev[j] == -1) ||
1079                             (!plat_data.throttle[i].devs[therm2dev[j]].enable))
1080                                 continue;
1081
1082                         therm = &plat_data.therm[j];
1083                         for (k = 0; k < therm->num_trips; k++)
1084                                 if ((therm->trips[k].trip_type ==
1085                                      THERMAL_TRIP_HOT) &&
1086                                     strnstr(therm->trips[k].cdev_type,
1087                                             i == THROTTLE_HEAVY ? "heavy" :
1088                                             "light", THERMAL_NAME_LENGTH))
1089                                         break;
1090                         if (k < therm->num_trips)
1091                                 prog_hw_threshold(&therm->trips[k], j, i);
1092                 }
1093         }
1094
1095         /* Enable Level 0 */
1096         r = soctherm_readl(CTL_LVL0_CPU0);
1097         r = REG_SET(r, CTL_LVL0_CPU0_EN, 1);
1098         soctherm_writel(r, CTL_LVL0_CPU0);
1099
1100         /* Thermtrip */
1101         for (i = 0; i < THERM_SIZE; i++) {
1102                 therm = &plat_data.therm[i];
1103                 if (!therm->zone_enable)
1104                         continue;
1105
1106                 for (j = 0; j < therm->num_trips; j++)
1107                         if (therm->trips[j].trip_type == THERMAL_TRIP_CRITICAL)
1108                                 prog_hw_shutdown(&therm->trips[j], i);
1109         }
1110
1111         /* Enable PMC to shutdown */
1112         r = pmc_readl(0x1b0);
1113         r |= 0x2;
1114         pmc_writel(r, 0x1b0);
1115
1116         r = clk_reset_readl(0x24);
1117         r |= (1 << 30);
1118         clk_reset_writel(r, 0x24);
1119
1120         return 0;
1121 }
1122
1123 static int soctherm_suspend(void)
1124 {
1125         soctherm_writel((u32)-1, INTR_DIS);
1126         soctherm_clk_enable(false);
1127         disable_irq(INT_THERMAL);
1128         cancel_work_sync(&work);
1129
1130         return 0;
1131 }
1132
1133 static int soctherm_resume(void)
1134 {
1135         soctherm_clk_enable(true);
1136         enable_irq(INT_THERMAL);
1137         soctherm_init_platform_data();
1138         soctherm_update();
1139
1140         return 0;
1141 }
1142
1143 static int soctherm_pm_notify(struct notifier_block *nb,
1144                                 unsigned long event, void *data)
1145 {
1146         switch (event) {
1147         case PM_SUSPEND_PREPARE:
1148                 soctherm_suspend();
1149                 break;
1150         case PM_POST_SUSPEND:
1151                 soctherm_resume();
1152                 break;
1153         }
1154
1155         return NOTIFY_OK;
1156 }
1157
1158 static struct notifier_block soctherm_nb = {
1159         .notifier_call = soctherm_pm_notify,
1160 };
1161
1162 int __init tegra11_soctherm_init(struct soctherm_platform_data *data)
1163 {
1164         int err;
1165
1166         register_pm_notifier(&soctherm_nb);
1167
1168         if (!data)
1169                 return -1;
1170         plat_data = *data;
1171
1172         if (soctherm_clk_init() < 0)
1173                 return -1;
1174
1175         if (soctherm_clk_enable(true) < 0)
1176                 return -1;
1177
1178         if (soctherm_init_platform_data() < 0)
1179                 return -1;
1180
1181         soctherm_init_platform_done = true;
1182
1183         /* enable interrupts */
1184         workqueue = create_singlethread_workqueue("soctherm");
1185         INIT_WORK(&work, soctherm_work_func);
1186
1187         err = request_irq(INT_THERMAL, soctherm_isr, 0, "soctherm", NULL);
1188         if (err < 0)
1189                 return -1;
1190
1191         return 0;
1192 }
1193
1194 #ifdef CONFIG_DEBUG_FS
1195 static int regs_show(struct seq_file *s, void *data)
1196 {
1197         u32 r;
1198         u32 state;
1199         long tcpu[TSENSE_SIZE];
1200         int i, level;
1201
1202         seq_printf(s, "-----TSENSE (precision %s)-----\n",
1203                    soc_therm_precision == -1 ? "Hi" : "Lo");
1204         for (i = 0; i < TSENSE_SIZE; i++) {
1205                 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG1, i));
1206                 state = REG_GET(r, TS_CPU0_CONFIG1_EN);
1207                 if (!state)
1208                         continue;
1209
1210                 seq_printf(s, "%s: ", sensor_names[i]);
1211
1212                 seq_printf(s, "En(%d) ", state);
1213                 state = REG_GET(r, TS_CPU0_CONFIG1_TIDDQ);
1214                 seq_printf(s, "tiddq(%d) ", state);
1215                 state = REG_GET(r, TS_CPU0_CONFIG1_TEN_COUNT);
1216                 seq_printf(s, "ten_count(%d) ", state);
1217                 state = REG_GET(r, TS_CPU0_CONFIG1_TSAMPLE);
1218                 seq_printf(s, "tsample(%d) ", state);
1219
1220                 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_STATUS0, i));
1221                 state = REG_GET(r, TS_CPU0_STATUS0_VALID);
1222                 seq_printf(s, "Capture(%d/", state);
1223                 state = REG_GET(r, TS_CPU0_STATUS0_CAPTURE);
1224                 seq_printf(s, "%d) ", state);
1225
1226                 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_STATUS1, i));
1227                 state = REG_GET(r, TS_CPU0_STATUS1_TEMP_VALID);
1228                 seq_printf(s, "Temp(%d/", state);
1229                 state = REG_GET(r, TS_CPU0_STATUS1_TEMP);
1230                 seq_printf(s, "%ld) ", tcpu[i] = temp_translate(state));
1231
1232                 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG0, i));
1233                 state = REG_GET(r, TS_CPU0_CONFIG0_TALL);
1234                 seq_printf(s, "Tall(%d) ", state);
1235                 state = REG_GET(r, TS_CPU0_CONFIG0_TCALC_OVER);
1236                 seq_printf(s, "Over(%d/", state);
1237                 state = REG_GET(r, TS_CPU0_CONFIG0_OVER);
1238                 seq_printf(s, "%d/", state);
1239                 state = REG_GET(r, TS_CPU0_CONFIG0_CPTR_OVER);
1240                 seq_printf(s, "%d) ", state);
1241
1242                 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG2, i));
1243                 state = REG_GET(r, TS_CPU0_CONFIG2_THERM_A);
1244                 seq_printf(s, "Therm_A/B(%d/", state);
1245                 state = REG_GET(r, TS_CPU0_CONFIG2_THERM_B);
1246                 seq_printf(s, "%d)\n", (s16)state);
1247         }
1248
1249         r = soctherm_readl(TS_PDIV);
1250         seq_printf(s, "PDIV: 0x%x\n", r);
1251
1252         seq_printf(s, "\n");
1253         seq_printf(s, "-----SOC_THERM-----\n");
1254
1255         r = soctherm_readl(TS_TEMP1);
1256         state = REG_GET(r, TS_TEMP1_CPU_TEMP);
1257         seq_printf(s, "Temperature: CPU(%ld) [Max(%ld)%c] ",
1258                    temp_translate(state),
1259                    max4(tcpu[0], tcpu[1], tcpu[2], tcpu[3]),
1260                    max4(tcpu[0], tcpu[1], tcpu[2], tcpu[3]) ==
1261                    temp_translate(state) ? '=' : '!');
1262         state = REG_GET(r, TS_TEMP1_GPU_TEMP);
1263         seq_printf(s, " GPU(%ld) ", temp_translate(state));
1264         r = soctherm_readl(TS_TEMP2);
1265         state = REG_GET(r, TS_TEMP2_MEM_TEMP);
1266         seq_printf(s, " MEM(%ld) ", temp_translate(state));
1267         state = REG_GET(r, TS_TEMP2_PLLX_TEMP);
1268         seq_printf(s, " PLLX(%ld)\n\n", temp_translate(state));
1269
1270         for (i = 0; i < THERM_SIZE; i++) {
1271                 seq_printf(s, "%s:\n", therm_names[i]);
1272
1273                 for (level = 0; level < 4; level++) {
1274                         r = soctherm_readl(TS_THERM_REG_OFFSET(CTL_LVL0_CPU0,
1275                                                                 level, i));
1276                         state = REG_GET(r, CTL_LVL0_CPU0_UP_THRESH);
1277                         seq_printf(s, "   %d: Up/Dn(%d/", level, state);
1278                         state = REG_GET(r, CTL_LVL0_CPU0_DN_THRESH);
1279                         seq_printf(s, "%d) ", state);
1280                         state = REG_GET(r, CTL_LVL0_CPU0_EN);
1281                         seq_printf(s, "En(%d) ", state);
1282                         state = REG_GET(r, CTL_LVL0_CPU0_CPU_THROT);
1283                         seq_printf(s, "Throt");
1284                         seq_printf(s, "(%s) ", state ?
1285                                 state == CTL_LVL0_CPU0_CPU_THROT_LIGHT ? "L" :
1286                                 state == CTL_LVL0_CPU0_CPU_THROT_HEAVY ? "H" :
1287                                 "H+L" : "none");
1288                         state = REG_GET(r, CTL_LVL0_CPU0_STATUS);
1289                         seq_printf(s, "Status(%s)\n",
1290                                    state == 0 ? "LO" :
1291                                    state == 1 ? "in" :
1292                                    state == 2 ? "??" : "HI");
1293                 }
1294         }
1295
1296         r = soctherm_readl(STATS_CTL);
1297         seq_printf(s, "STATS: Up(%s) Dn(%s)\n",
1298                    r & STATS_CTL_EN_UP ? "En" : "--",
1299                    r & STATS_CTL_EN_DN ? "En" : "--");
1300         for (level = 0; level < 4; level++) {
1301                 r = soctherm_readl(TS_TSENSE_REG_OFFSET(UP_STATS_L0, level));
1302                 seq_printf(s, "  Level_%d Up(%d) ", level, r);
1303                 r = soctherm_readl(TS_TSENSE_REG_OFFSET(DN_STATS_L0, level));
1304                 seq_printf(s, "Dn(%d)\n", r);
1305         }
1306
1307         r = soctherm_readl(INTR_STATUS);
1308         state = REG_GET(r, INTR_STATUS_CD0);
1309         seq_printf(s, "CD0: %d\n", state);
1310         state = REG_GET(r, INTR_STATUS_CU0);
1311         seq_printf(s, "CU0: %d\n", state);
1312
1313         r = soctherm_readl(THERMTRIP);
1314         state = REG_GET(r, THERMTRIP_CPU_THRESH);
1315         seq_printf(s, "THERMTRIP_CPU_THRESH: %d ", state);
1316         state = REG_GET(r, THERMTRIP_CPU_EN);
1317         seq_printf(s, "%d\n", state);
1318
1319
1320         seq_printf(s, "\n-----THROTTLE-----\n");
1321
1322         r = soctherm_readl(THROT_GLOBAL_CFG);
1323         seq_printf(s, "GLOBAL CONFIG: 0x%x\n", r);
1324
1325         r = soctherm_readl(THROT_STATUS);
1326         state = REG_GET(r, THROT_STATUS_BREACH);
1327         seq_printf(s, "THROT STATUS: breach(%d) ", state);
1328         state = REG_GET(r, THROT_STATUS_STATE);
1329         seq_printf(s, "state(%d) ", state);
1330         state = REG_GET(r, THROT_STATUS_ENABLED);
1331         seq_printf(s, "enabled(%d)\n", state);
1332
1333         r = soctherm_readl(CPU_PSKIP_STATUS);
1334         state = REG_GET(r, CPU_PSKIP_STATUS_M);
1335         seq_printf(s, "CPU PSKIP: M(%d) ", state);
1336         state = REG_GET(r, CPU_PSKIP_STATUS_N);
1337         seq_printf(s, "N(%d) ", state);
1338         state = REG_GET(r, CPU_PSKIP_STATUS_ENABLED);
1339         seq_printf(s, "enabled(%d)\n", state);
1340
1341         r = soctherm_readl(THROT_PSKIP_CTRL(THROTTLE_LIGHT, THROTTLE_DEV_CPU));
1342         state = REG_GET(r, THROT_PSKIP_CTRL_ENABLE);
1343         seq_printf(s, "CPU PSKIP LIGHT: enabled(%d) ", state);
1344         state = REG_GET(r, THROT_PSKIP_CTRL_DIVIDEND);
1345         seq_printf(s, "dividend(%d) ", state);
1346         state = REG_GET(r, THROT_PSKIP_CTRL_DIVISOR);
1347         seq_printf(s, "divisor(%d) ", state);
1348         r = soctherm_readl(THROT_PSKIP_RAMP(THROTTLE_LIGHT, THROTTLE_DEV_CPU));
1349         state = REG_GET(r, THROT_PSKIP_RAMP_DURATION);
1350         seq_printf(s, "duration(%d) ", state);
1351         state = REG_GET(r, THROT_PSKIP_RAMP_STEP);
1352         seq_printf(s, "step(%d)\n", state);
1353
1354         r = soctherm_readl(THROT_PSKIP_CTRL(THROTTLE_HEAVY, THROTTLE_DEV_CPU));
1355         state = REG_GET(r, THROT_PSKIP_CTRL_ENABLE);
1356         seq_printf(s, "CPU PSKIP HEAVY: enabled(%d) ", state);
1357         state = REG_GET(r, THROT_PSKIP_CTRL_DIVIDEND);
1358         seq_printf(s, "dividend(%d) ", state);
1359         state = REG_GET(r, THROT_PSKIP_CTRL_DIVISOR);
1360         seq_printf(s, "divisor(%d) ", state);
1361         r = soctherm_readl(THROT_PSKIP_RAMP(THROTTLE_HEAVY, THROTTLE_DEV_CPU));
1362         state = REG_GET(r, THROT_PSKIP_RAMP_DURATION);
1363         seq_printf(s, "duration(%d) ", state);
1364         state = REG_GET(r, THROT_PSKIP_RAMP_STEP);
1365         seq_printf(s, "step(%d)\n", state);
1366         return 0;
1367 }
1368
1369 static int regs_open(struct inode *inode, struct file *file)
1370 {
1371         return single_open(file, regs_show, inode->i_private);
1372 }
1373
1374 static const struct file_operations regs_fops = {
1375         .open           = regs_open,
1376         .read           = seq_read,
1377         .llseek         = seq_lseek,
1378         .release        = single_release,
1379 };
1380
1381 static int __init soctherm_debug_init(void)
1382 {
1383         struct dentry *tegra_soctherm_root;
1384
1385         tegra_soctherm_root = debugfs_create_dir("tegra_soctherm", 0);
1386         debugfs_create_file("regs", 0644, tegra_soctherm_root,
1387                                 NULL, &regs_fops);
1388         return 0;
1389 }
1390 late_initcall(soctherm_debug_init);
1391 #endif