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