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