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