2 * arch/arm/mach-tegra/tegra11_soctherm.c
4 * Copyright (c) 2011-2013, NVIDIA CORPORATION. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope 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
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <linux/debugfs.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/list.h>
23 #include <linux/mutex.h>
24 #include <linux/delay.h>
25 #include <linux/err.h>
26 #include <linux/gpio.h>
28 #include <linux/clk.h>
29 #include <linux/cpufreq.h>
30 #include <linux/seq_file.h>
31 #include <linux/irq.h>
32 #include <linux/interrupt.h>
33 #include <linux/irqdomain.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 #include <linux/bug.h>
40 #include <linux/tegra-fuse.h>
44 #include "tegra3_tsensor.h"
45 #include "tegra11_soctherm.h"
46 #include "gpio-names.h"
49 static const int MAX_HIGH_TEMP = 128000;
51 /* Min temp granularity specified as X in 2^X.
52 * -1: Hi precision option: 2^-1 = 0.5C (T12x onwards)
53 * 0: Lo precision option: 2^0 = 1.0C
55 #ifdef CONFIG_ARCH_TEGRA_12x_SOC
56 static const int precision = -1; /* Use high precision on T12x */
58 static const int precision; /* default 0 -> low precision */
61 #define LOWER_PRECISION_FOR_CONV(val) ((!precision) ? ((val)*2) : (val))
62 #define LOWER_PRECISION_FOR_TEMP(val) ((!precision) ? ((val)/2) : (val))
63 #define PRECISION_IS_LOWER() ((!precision))
64 #define PRECISION_TO_STR() ((!precision) ? "Lo" : "Hi")
66 #define TS_TSENSE_REGS_SIZE 0x20
67 #define TS_TSENSE_REG_OFFSET(reg, ts) ((reg) + ((ts) * TS_TSENSE_REGS_SIZE))
69 #define TS_THERM_LVL_REGS_SIZE 0x20
70 #define TS_THERM_GRP_REGS_SIZE 0x04
71 #define TS_THERM_REG_OFFSET(rg, lv, gr) ((rg) + ((lv) * TS_THERM_LVL_REGS_SIZE)\
72 + ((gr) * TS_THERM_GRP_REGS_SIZE))
74 #define CTL_LVL0_CPU0 0x0
75 #define CTL_LVL0_CPU0_UP_THRESH_SHIFT 17
76 #define CTL_LVL0_CPU0_UP_THRESH_MASK 0xff
77 #define CTL_LVL0_CPU0_DN_THRESH_SHIFT 9
78 #define CTL_LVL0_CPU0_DN_THRESH_MASK 0xff
79 #define CTL_LVL0_CPU0_EN_SHIFT 8
80 #define CTL_LVL0_CPU0_EN_MASK 0x1
81 #define CTL_LVL0_CPU0_CPU_THROT_SHIFT 5
82 #define CTL_LVL0_CPU0_CPU_THROT_MASK 0x3
83 #define CTL_LVL0_CPU0_CPU_THROT_LIGHT 0x1
84 #define CTL_LVL0_CPU0_CPU_THROT_HEAVY 0x2
85 #define CTL_LVL0_CPU0_GPU_THROT_SHIFT 3
86 #define CTL_LVL0_CPU0_GPU_THROT_MASK 0x3
87 #define CTL_LVL0_CPU0_GPU_THROT_LIGHT 0x1
88 #define CTL_LVL0_CPU0_GPU_THROT_HEAVY 0x2
89 #define CTL_LVL0_CPU0_MEM_THROT_SHIFT 2
90 #define CTL_LVL0_CPU0_MEM_THROT_MASK 0x1
91 #define CTL_LVL0_CPU0_STATUS_SHIFT 0
92 #define CTL_LVL0_CPU0_STATUS_MASK 0x3
94 #define THERMTRIP 0x80
95 #define THERMTRIP_ANY_EN_SHIFT 28
96 #define THERMTRIP_ANY_EN_MASK 0x1
97 #define THERMTRIP_MEM_EN_SHIFT 27
98 #define THERMTRIP_MEM_EN_MASK 0x1
99 #define THERMTRIP_GPU_EN_SHIFT 26
100 #define THERMTRIP_GPU_EN_MASK 0x1
101 #define THERMTRIP_CPU_EN_SHIFT 25
102 #define THERMTRIP_CPU_EN_MASK 0x1
103 #define THERMTRIP_TSENSE_EN_SHIFT 24
104 #define THERMTRIP_TSENSE_EN_MASK 0x1
105 #define THERMTRIP_GPUMEM_THRESH_SHIFT 16
106 #define THERMTRIP_GPUMEM_THRESH_MASK 0xff
107 #define THERMTRIP_CPU_THRESH_SHIFT 8
108 #define THERMTRIP_CPU_THRESH_MASK 0xff
109 #define THERMTRIP_TSENSE_THRESH_SHIFT 0
110 #define THERMTRIP_TSENSE_THRESH_MASK 0xff
112 #define TS_CPU0_CONFIG0 0xc0
113 #define TS_CPU0_CONFIG0_TALL_SHIFT 8
114 #define TS_CPU0_CONFIG0_TALL_MASK 0xfffff
115 #define TS_CPU0_CONFIG0_TCALC_OVER_SHIFT 4
116 #define TS_CPU0_CONFIG0_TCALC_OVER_MASK 0x1
117 #define TS_CPU0_CONFIG0_OVER_SHIFT 3
118 #define TS_CPU0_CONFIG0_OVER_MASK 0x1
119 #define TS_CPU0_CONFIG0_CPTR_OVER_SHIFT 2
120 #define TS_CPU0_CONFIG0_CPTR_OVER_MASK 0x1
121 #define TS_CPU0_CONFIG0_STOP_SHIFT 0
122 #define TS_CPU0_CONFIG0_STOP_MASK 0x1
124 #define TS_CPU0_CONFIG1 0xc4
125 #define TS_CPU0_CONFIG1_EN_SHIFT 31
126 #define TS_CPU0_CONFIG1_EN_MASK 0x1
127 #define TS_CPU0_CONFIG1_TIDDQ_SHIFT 15
128 #define TS_CPU0_CONFIG1_TIDDQ_MASK 0x3f
129 #define TS_CPU0_CONFIG1_TEN_COUNT_SHIFT 24
130 #define TS_CPU0_CONFIG1_TEN_COUNT_MASK 0x3f
131 #define TS_CPU0_CONFIG1_TSAMPLE_SHIFT 0
132 #define TS_CPU0_CONFIG1_TSAMPLE_MASK 0x3ff
134 #define TS_CPU0_CONFIG2 0xc8
135 #define TS_CPU0_CONFIG2_THERM_A_SHIFT 16
136 #define TS_CPU0_CONFIG2_THERM_A_MASK 0xffff
137 #define TS_CPU0_CONFIG2_THERM_B_SHIFT 0
138 #define TS_CPU0_CONFIG2_THERM_B_MASK 0xffff
140 #define TS_CPU0_STATUS0 0xcc
141 #define TS_CPU0_STATUS0_VALID_SHIFT 31
142 #define TS_CPU0_STATUS0_VALID_MASK 0x1
143 #define TS_CPU0_STATUS0_CAPTURE_SHIFT 0
144 #define TS_CPU0_STATUS0_CAPTURE_MASK 0xffff
146 #define TS_CPU0_STATUS1 0xd0
147 #define TS_CPU0_STATUS1_TEMP_VALID_SHIFT 31
148 #define TS_CPU0_STATUS1_TEMP_VALID_MASK 0x1
149 #define TS_CPU0_STATUS1_TEMP_SHIFT 0
150 #define TS_CPU0_STATUS1_TEMP_MASK 0xffff
152 #define TS_CPU0_STATUS2 0xd4
154 #define TS_PDIV 0x1c0
155 #define TS_PDIV_CPU_SHIFT 12
156 #define TS_PDIV_CPU_MASK 0xf
157 #define TS_PDIV_GPU_SHIFT 8
158 #define TS_PDIV_GPU_MASK 0xf
159 #define TS_PDIV_MEM_SHIFT 4
160 #define TS_PDIV_MEM_MASK 0xf
161 #define TS_PDIV_PLLX_SHIFT 0
162 #define TS_PDIV_PLLX_MASK 0xf
164 #define TS_HOTSPOT_OFF 0x1c4
165 #define TS_HOTSPOT_OFF_CPU_SHIFT 16
166 #define TS_HOTSPOT_OFF_CPU_MASK 0xff
167 #define TS_HOTSPOT_OFF_GPU_SHIFT 8
168 #define TS_HOTSPOT_OFF_GPU_MASK 0xff
169 #define TS_HOTSPOT_OFF_MEM_SHIFT 0
170 #define TS_HOTSPOT_OFF_MEM_MASK 0xff
172 #define TS_TEMP1 0x1c8
173 #define TS_TEMP1_CPU_TEMP_SHIFT 16
174 #define TS_TEMP1_CPU_TEMP_MASK 0xffff
175 #define TS_TEMP1_GPU_TEMP_SHIFT 0
176 #define TS_TEMP1_GPU_TEMP_MASK 0xffff
178 #define TS_TEMP2 0x1cc
179 #define TS_TEMP2_MEM_TEMP_SHIFT 16
180 #define TS_TEMP2_MEM_TEMP_MASK 0xffff
181 #define TS_TEMP2_PLLX_TEMP_SHIFT 0
182 #define TS_TEMP2_PLLX_TEMP_MASK 0xffff
184 #define TS_TEMP_SW_OVERRIDE 0x1d8
186 #define TH_INTR_STATUS 0x84
187 #define TH_INTR_ENABLE 0x88
188 #define TH_INTR_DISABLE 0x8c
190 #define LOCK_CTL 0x90
192 #define TH_INTR_POS_MD3_SHIFT 31
193 #define TH_INTR_POS_MD3_MASK 0x1
194 #define TH_INTR_POS_MU3_SHIFT 30
195 #define TH_INTR_POS_MU3_MASK 0x1
196 #define TH_INTR_POS_MD2_SHIFT 29
197 #define TH_INTR_POS_MD2_MASK 0x1
198 #define TH_INTR_POS_MU2_SHIFT 28
199 #define TH_INTR_POS_MU2_MASK 0x1
200 #define TH_INTR_POS_MD1_SHIFT 27
201 #define TH_INTR_POS_MD1_MASK 0x1
202 #define TH_INTR_POS_MU1_SHIFT 26
203 #define TH_INTR_POS_MU1_MASK 0x1
204 #define TH_INTR_POS_MD0_SHIFT 25
205 #define TH_INTR_POS_MD0_MASK 0x1
206 #define TH_INTR_POS_MU0_SHIFT 24
207 #define TH_INTR_POS_MU0_MASK 0x1
208 #define TH_INTR_POS_GD3_SHIFT 23
209 #define TH_INTR_POS_GD3_MASK 0x1
210 #define TH_INTR_POS_GU3_SHIFT 22
211 #define TH_INTR_POS_GU3_MASK 0x1
212 #define TH_INTR_POS_GD2_SHIFT 21
213 #define TH_INTR_POS_GD2_MASK 0x1
214 #define TH_INTR_POS_GU2_SHIFT 20
215 #define TH_INTR_POS_GU2_MASK 0x1
216 #define TH_INTR_POS_GD1_SHIFT 19
217 #define TH_INTR_POS_GD1_MASK 0x1
218 #define TH_INTR_POS_GU1_SHIFT 18
219 #define TH_INTR_POS_GU1_MASK 0x1
220 #define TH_INTR_POS_GD0_SHIFT 17
221 #define TH_INTR_POS_GD0_MASK 0x1
222 #define TH_INTR_POS_GU0_SHIFT 16
223 #define TH_INTR_POS_GU0_MASK 0x1
224 #define TH_INTR_POS_CD3_SHIFT 15
225 #define TH_INTR_POS_CD3_MASK 0x1
226 #define TH_INTR_POS_CU3_SHIFT 14
227 #define TH_INTR_POS_CU3_MASK 0x1
228 #define TH_INTR_POS_CD2_SHIFT 13
229 #define TH_INTR_POS_CD2_MASK 0x1
230 #define TH_INTR_POS_CU2_SHIFT 12
231 #define TH_INTR_POS_CU2_MASK 0x1
232 #define TH_INTR_POS_CD1_SHIFT 11
233 #define TH_INTR_POS_CD1_MASK 0x1
234 #define TH_INTR_POS_CU1_SHIFT 10
235 #define TH_INTR_POS_CU1_MASK 0x1
236 #define TH_INTR_POS_CD0_SHIFT 9
237 #define TH_INTR_POS_CD0_MASK 0x1
238 #define TH_INTR_POS_CU0_SHIFT 8
239 #define TH_INTR_POS_CU0_MASK 0x1
240 #define TH_INTR_POS_PD3_SHIFT 7
241 #define TH_INTR_POS_PD3_MASK 0x1
242 #define TH_INTR_POS_PU3_SHIFT 6
243 #define TH_INTR_POS_PU3_MASK 0x1
244 #define TH_INTR_POS_PD2_SHIFT 5
245 #define TH_INTR_POS_PD2_MASK 0x1
246 #define TH_INTR_POS_PU2_SHIFT 4
247 #define TH_INTR_POS_PU2_MASK 0x1
248 #define TH_INTR_POS_PD1_SHIFT 3
249 #define TH_INTR_POS_PD1_MASK 0x1
250 #define TH_INTR_POS_PU1_SHIFT 2
251 #define TH_INTR_POS_PU1_MASK 0x1
252 #define TH_INTR_POS_PD0_SHIFT 1
253 #define TH_INTR_POS_PD0_MASK 0x1
254 #define TH_INTR_POS_PU0_SHIFT 0
255 #define TH_INTR_POS_PU0_MASK 0x1
258 #define UP_STATS_L0 0x10
259 #define DN_STATS_L0 0x14
261 #define STATS_CTL 0x94
262 #define STATS_CTL_CLR_DN 0x8
263 #define STATS_CTL_EN_DN 0x4
264 #define STATS_CTL_CLR_UP 0x2
265 #define STATS_CTL_EN_UP 0x1
267 #define THROT_GLOBAL_CFG 0x400
269 #define OC1_CFG 0x310
270 #define OC1_CFG_LONG_LATENCY_SHIFT 6
271 #define OC1_CFG_LONG_LATENCY_MASK 0x1
272 #define OC1_CFG_HW_RESTORE_SHIFT 5
273 #define OC1_CFG_HW_RESTORE_MASK 0x1
274 #define OC1_CFG_PWR_GOOD_MASK_SHIFT 4
275 #define OC1_CFG_PWR_GOOD_MASK_MASK 0x1
276 #define OC1_CFG_THROTTLE_MODE_SHIFT 2
277 #define OC1_CFG_THROTTLE_MODE_MASK 0x3
278 #define OC1_CFG_ALARM_POLARITY_SHIFT 1
279 #define OC1_CFG_ALARM_POLARITY_MASK 0x1
280 #define OC1_CFG_EN_THROTTLE_SHIFT 0
281 #define OC1_CFG_EN_THROTTLE_MASK 0x1
283 #define OC1_CNT_THRESHOLD 0x314
284 #define OC1_THRESHOLD_PERIOD 0x318
285 #define OC1_ALARM_COUNT 0x31c
286 #define OC1_FILTER 0x320
288 #define OC1_STATS 0x3a8
290 #define OC_INTR_STATUS 0x39c
291 #define OC_INTR_ENABLE 0x3a0
292 #define OC_INTR_DISABLE 0x3a4
293 #define OC_INTR_POS_OC1_SHIFT 0
294 #define OC_INTR_POS_OC1_MASK 0x1
295 #define OC_INTR_POS_OC2_SHIFT 1
296 #define OC_INTR_POS_OC2_MASK 0x1
297 #define OC_INTR_POS_OC3_SHIFT 2
298 #define OC_INTR_POS_OC3_MASK 0x1
299 #define OC_INTR_POS_OC4_SHIFT 3
300 #define OC_INTR_POS_OC4_MASK 0x1
301 #define OC_INTR_POS_OC5_SHIFT 4
302 #define OC_INTR_POS_OC5_MASK 0x1
304 #define OC_STATS_CTL 0x3c4
305 #define OC_STATS_CTL_CLR_ALL 0x2
306 #define OC_STATS_CTL_EN_ALL 0x1
308 #define CPU_PSKIP_STATUS 0x418
309 #define CPU_PSKIP_STATUS_M_SHIFT 12
310 #define CPU_PSKIP_STATUS_M_MASK 0xff
311 #define CPU_PSKIP_STATUS_N_SHIFT 4
312 #define CPU_PSKIP_STATUS_N_MASK 0xff
313 #define CPU_PSKIP_STATUS_ENABLED_SHIFT 0
314 #define CPU_PSKIP_STATUS_ENABLED_MASK 0x1
316 #define THROT_PRIORITY_LOCK 0x424
317 #define THROT_PRIORITY_LOCK_PRIORITY_SHIFT 0
318 #define THROT_PRIORITY_LOCK_PRIORITY_MASK 0xff
320 #define THROT_STATUS 0x428
321 #define THROT_STATUS_BREACH_SHIFT 12
322 #define THROT_STATUS_BREACH_MASK 0x1
323 #define THROT_STATUS_STATE_SHIFT 4
324 #define THROT_STATUS_STATE_MASK 0xff
325 #define THROT_STATUS_ENABLED_SHIFT 0
326 #define THROT_STATUS_ENABLED_MASK 0x1
328 #define THROT_PSKIP_CTRL_LITE_CPU 0x430
329 #define THROT_PSKIP_CTRL_ENABLE_SHIFT 31
330 #define THROT_PSKIP_CTRL_ENABLE_MASK 0x1
331 #define THROT_PSKIP_CTRL_DIVIDEND_SHIFT 8
332 #define THROT_PSKIP_CTRL_DIVIDEND_MASK 0xff
333 #define THROT_PSKIP_CTRL_DIVISOR_SHIFT 0
334 #define THROT_PSKIP_CTRL_DIVISOR_MASK 0xff
336 #define THROT_PSKIP_RAMP_LITE_CPU 0x434
337 #define THROT_PSKIP_RAMP_DURATION_SHIFT 8
338 #define THROT_PSKIP_RAMP_DURATION_MASK 0xffff
339 #define THROT_PSKIP_RAMP_STEP_SHIFT 0
340 #define THROT_PSKIP_RAMP_STEP_MASK 0xff
342 #define THROT_PSKIP_CTRL_LITE_GPU 0x438
343 #define THROT_PSKIP_CTRL_THROT_DEPTH_SHIFT 16
344 #define THROT_PSKIP_CTRL_THROT_DEPTH_MASK 0x7
345 #define THROT_DEPTH_NONE 0x0
346 #define THROT_DEPTH_LOW 0x1
347 #define THROT_DEPTH_MED 0x2
348 #define THROT_DEPTH_HIG 0x4
350 #define THROT_PRIORITY_LITE 0x444
351 #define THROT_PRIORITY_LITE_PRIO_SHIFT 0
352 #define THROT_PRIORITY_LITE_PRIO_MASK 0xff
354 #define THROT_DELAY_LITE 0x448
355 #define THROT_DELAY_LITE_DELAY_SHIFT 0
356 #define THROT_DELAY_LITE_DELAY_MASK 0xff
358 #define THROT_OFFSET 0x30
359 #define ALARM_OFFSET 0x14
361 #define FUSE_TSENSOR_CALIB_FT_SHIFT 13
362 #define FUSE_TSENSOR_CALIB_FT_MASK 0x1fff
363 #define FUSE_TSENSOR_CALIB_CP_SHIFT 0
364 #define FUSE_TSENSOR_CALIB_CP_MASK 0x1fff
365 #define FUSE_TSENSOR_CALIB_BITS 13
367 /* car register offsets needed for enabling HW throttling */
368 #define CAR_SUPER_CCLKG_DIVIDER 0x36c
369 #define CDIVG_USE_THERM_CONTROLS_SHIFT 30
370 #define CDIVG_USE_THERM_CONTROLS_MASK 0x1
372 /* pmc register offsets needed for powering off PMU */
373 #define PMC_SCRATCH_WRITE_SHIFT 2
374 #define PMC_SCRATCH_WRITE_MASK 0x1
375 #define PMC_ENABLE_RST_SHIFT 1
376 #define PMC_ENABLE_RST_MASK 0x1
377 #define PMC_SENSOR_CTRL 0x1B0
378 #define PMC_SCRATCH54 0x258
379 #define PMC_SCRATCH55 0x25C
381 /* scratch54 register bit fields */
382 #define PMU_OFF_DATA_SHIFT 8
383 #define PMU_OFF_DATA_MASK 0xff
384 #define PMU_OFF_ADDR_SHIFT 0
385 #define PMU_OFF_ADDR_MASK 0xff
387 /* scratch55 register bit fields */
388 #define RESET_TEGRA_SHIFT 31
389 #define RESET_TEGRA_MASK 0x1
390 #define CONTROLLER_TYPE_SHIFT 30
391 #define CONTROLLER_TYPE_MASK 0x1
392 #define I2C_CONTROLLER_ID_SHIFT 27
393 #define I2C_CONTROLLER_ID_MASK 0x7
394 #define PINMUX_SHIFT 24
395 #define PINMUX_MASK 0x7
396 #define CHECKSUM_SHIFT 16
397 #define CHECKSUM_MASK 0xff
398 #define PMU_16BIT_SUPPORT_SHIFT 15
399 #define PMU_16BIT_SUPPORT_MASK 0x1
400 #define PMU_I2C_ADDRESS_SHIFT 0
401 #define PMU_I2C_ADDRESS_MASK 0x7f
403 #define THROT_PSKIP_CTRL(throt, dev) (THROT_PSKIP_CTRL_LITE_CPU + \
404 (THROT_OFFSET * throt) + \
406 #define THROT_PSKIP_RAMP(throt, dev) (THROT_PSKIP_RAMP_LITE_CPU + \
407 (THROT_OFFSET * throt) + \
409 #define THROT_PRIORITY_CTRL(throt) (THROT_PRIORITY_LITE + \
410 (THROT_OFFSET * throt))
411 #define THROT_DELAY_CTRL(throt) (THROT_DELAY_LITE + \
412 (THROT_OFFSET * throt))
413 #define ALARM_CFG(throt) (OC1_CFG + \
414 (ALARM_OFFSET * (throt - \
416 #define ALARM_CNT_THRESHOLD(throt) (OC1_CNT_THRESHOLD + \
417 (ALARM_OFFSET * (throt - \
419 #define ALARM_THRESHOLD_PERIOD(throt) (OC1_THRESHOLD_PERIOD + \
420 (ALARM_OFFSET * (throt - \
422 #define ALARM_ALARM_COUNT(throt) (OC1_ALARM_COUNT + \
423 (ALARM_OFFSET * (throt - \
425 #define ALARM_FILTER(throt) (OC1_FILTER + \
426 (ALARM_OFFSET * (throt - \
428 #define ALARM_STATS(throt) (OC1_STATS + \
429 (4 * (throt - THROTTLE_OC1)))
431 #define THROT_DEPTH_DIVIDEND(depth) ((256 * (100 - (depth)) / 100) - 1)
432 #define THROT_DEPTH_DEFAULT (80)
433 #define THROT_DEPTH(th, dp) { \
434 (th)->depth = (dp); \
435 (th)->dividend = THROT_DEPTH_DIVIDEND(dp); \
436 (th)->divisor = 255; \
437 (th)->duration = 0xff; \
441 #define REG_SET(r, _name, val) (((r) & ~(_name##_MASK << _name##_SHIFT)) | \
442 (((val) & _name##_MASK) << _name##_SHIFT))
443 #define REG_GET_BIT(r, _name) ((r) & (_name##_MASK << _name##_SHIFT))
444 #define REG_GET(r, _name) (REG_GET_BIT(r, _name) >> _name##_SHIFT)
445 #define MAKE_SIGNED32(val, nb) ((s32)(val) << (32 - (nb)) >> (32 - (nb)))
447 static void __iomem *reg_soctherm_base = IO_ADDRESS(TEGRA_SOCTHERM_BASE);
448 static void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
449 static void __iomem *clk_reset_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
451 static DEFINE_MUTEX(soctherm_suspend_resume_lock);
453 static int soctherm_suspend(void);
454 static int soctherm_resume(void);
456 static struct soctherm_platform_data plat_data;
459 * Remove this flag once this "driver" is structured as a platform driver and
460 * the board files calls platform_device_register instead of directly calling
461 * tegra11_soctherm_init(). See nvbug 1206311.
463 static bool soctherm_init_platform_done;
464 static bool read_hw_temp = true;
465 static bool soctherm_suspended;
466 static bool soctherm_high_voltage_range = true;
467 static u32 tegra_chip_id;
469 static struct clk *soctherm_clk;
470 static struct clk *tsensor_clk;
472 static inline void soctherm_writel(u32 value, u32 reg)
474 if (!soctherm_suspended)
475 __raw_writel(value, (void *)
476 (reg_soctherm_base + reg));
479 static inline u32 soctherm_readl(u32 reg)
481 if (soctherm_suspended)
483 return __raw_readl(reg_soctherm_base + reg);
486 static inline void pmc_writel(u32 value, u32 reg)
488 __raw_writel(value, (void *)
492 static inline u32 pmc_readl(u32 reg)
494 return __raw_readl(pmc_base + reg);
497 static inline void clk_reset_writel(u32 value, u32 reg)
499 __raw_writel(value, (void *)
500 (clk_reset_base + reg));
503 static inline u32 clk_reset_readl(u32 reg)
505 return __raw_readl(clk_reset_base + reg);
508 static inline long temp_convert(int cap, int a, int b)
513 cap *= LOWER_PRECISION_FOR_CONV(500);
518 static inline u32 temp_translate_rev(long temp)
526 sign = (temp > 0 ? 1 : -1);
527 low_bit = (sign > 0 ? 0 : 1);
529 /* high precision only */
530 if (!PRECISION_IS_LOWER()) {
531 lsb = ((temp % 1000) > 0) ? 1 : 0;
532 abs = (temp - 500 * lsb) / 1000;
534 reg = ((abs << 8) | (lsb << 7) | low_bit);
539 #ifdef CONFIG_THERMAL
540 static struct thermal_zone_device *thz[THERM_SIZE];
542 struct soctherm_oc_irq_chip_data {
544 struct mutex irq_lock;
545 struct irq_chip irq_chip;
546 struct irq_domain *domain;
549 static struct soctherm_oc_irq_chip_data soc_irq_cdata;
551 static u32 fuse_calib_base_cp;
552 static u32 fuse_calib_base_ft;
553 static s32 actual_temp_cp;
554 static s32 actual_temp_ft;
556 static const char *const therm_names[] = {
563 static const char *const throt_names[] = {
564 [THROTTLE_LIGHT] = "light",
565 [THROTTLE_HEAVY] = "heavy",
566 [THROTTLE_OC1] = "oc1",
567 [THROTTLE_OC2] = "oc2",
568 [THROTTLE_OC3] = "oc3",
569 [THROTTLE_OC4] = "oc4",
570 [THROTTLE_OC5] = "oc5",
573 static const char *const throt_dev_names[] = {
574 [THROTTLE_DEV_CPU] = "CPU",
575 [THROTTLE_DEV_GPU] = "GPU",
578 static const char *const sensor_names[] = {
579 [TSENSE_CPU0] = "cpu0",
580 [TSENSE_CPU1] = "cpu1",
581 [TSENSE_CPU2] = "cpu2",
582 [TSENSE_CPU3] = "cpu3",
583 [TSENSE_MEM0] = "mem0",
584 [TSENSE_MEM1] = "mem1",
585 [TSENSE_GPU] = "gpu0",
586 [TSENSE_PLLX] = "pllx",
589 static const int sensor2tsensorcalib[] = {
600 static const int tsensor2therm_map[] = {
601 [TSENSE_CPU0] = THERM_CPU,
602 [TSENSE_CPU1] = THERM_CPU,
603 [TSENSE_CPU2] = THERM_CPU,
604 [TSENSE_CPU3] = THERM_CPU,
605 [TSENSE_GPU] = THERM_GPU,
606 [TSENSE_MEM0] = THERM_MEM,
607 [TSENSE_MEM1] = THERM_MEM,
608 [TSENSE_PLLX] = THERM_PLL,
611 static const enum soctherm_throttle_dev_id therm2dev[] = {
612 [THERM_CPU] = THROTTLE_DEV_CPU,
613 [THERM_MEM] = THROTTLE_DEV_NONE,
614 [THERM_GPU] = THROTTLE_DEV_GPU,
615 [THERM_PLL] = THROTTLE_DEV_NONE,
618 static const struct soctherm_sensor default_t11x_sensor_params = {
627 static const struct soctherm_sensor default_t14x_sensor_params = {
637 /* TODO: not the final sensor data for T124 */
638 static const struct soctherm_sensor default_t12x_sensor_params = {
648 static const unsigned long default_t11x_soctherm_clk_rate = 51000000;
649 static const unsigned long default_t11x_tsensor_clk_rate = 500000;
650 static const unsigned long default_t14x_soctherm_clk_rate = 51000000;
651 static const unsigned long default_t14x_tsensor_clk_rate = 400000;
652 /* TODO : finalize the default clk rate */
653 static const unsigned long default_t12x_soctherm_clk_rate = 51000000;
654 static const unsigned long default_t12x_tsensor_clk_rate = 400000;
656 /* SOC- OCx to theirt GPIO which is wakeup capable. This is T114 specific */
657 static int soctherm_ocx_to_wake_gpio[TEGRA_SOC_OC_IRQ_MAX] = {
658 TEGRA_GPIO_PEE3, /* TEGRA_SOC_OC_IRQ_1 */
659 TEGRA_GPIO_INVALID, /* TEGRA_SOC_OC_IRQ_2 */
660 TEGRA_GPIO_INVALID, /* TEGRA_SOC_OC_IRQ_3 */
661 TEGRA_GPIO_PJ2, /* TEGRA_SOC_OC_IRQ_4 */
662 TEGRA_GPIO_INVALID, /* TEGRA_SOC_OC_IRQ_5 */
665 static int sensor2therm_a[TSENSE_SIZE];
666 static int sensor2therm_b[TSENSE_SIZE];
668 static inline s64 div64_s64_precise(s64 a, s32 b)
672 /* scale up for increased precision in division */
675 r = div64_s64((al * 2) + 1, 2 * b);
679 static inline long temp_translate(int readback)
681 int abs = readback >> 8;
682 int lsb = (readback & 0x80) >> 7;
683 int sign = readback & 0x01 ? -1 : 1;
685 return (abs * LOWER_PRECISION_FOR_CONV(1000) +
686 lsb * LOWER_PRECISION_FOR_CONV(500)) * sign;
689 #ifdef CONFIG_THERMAL
690 static inline void prog_hw_shutdown(struct thermal_trip_info *trip_state,
696 trip_temp = LOWER_PRECISION_FOR_TEMP(trip_state->trip_temp / 1000);
698 r = soctherm_readl(THERMTRIP);
699 if (therm == THERM_CPU) {
700 r = REG_SET(r, THERMTRIP_CPU_EN, 1);
701 r = REG_SET(r, THERMTRIP_CPU_THRESH, trip_temp);
702 } else if (therm == THERM_GPU) {
703 r = REG_SET(r, THERMTRIP_GPU_EN, 1);
704 r = REG_SET(r, THERMTRIP_GPUMEM_THRESH, trip_temp);
705 } else if (therm == THERM_PLL) {
706 r = REG_SET(r, THERMTRIP_TSENSE_EN, 1);
707 r = REG_SET(r, THERMTRIP_TSENSE_THRESH, trip_temp);
708 } else if (therm == THERM_MEM) {
709 r = REG_SET(r, THERMTRIP_MEM_EN, 1);
710 r = REG_SET(r, THERMTRIP_GPUMEM_THRESH, trip_temp);
712 r = REG_SET(r, THERMTRIP_ANY_EN, 0);
713 soctherm_writel(r, THERMTRIP);
716 static inline void prog_hw_threshold(struct thermal_trip_info *trip_state,
717 int therm, int throt)
722 trip_temp = LOWER_PRECISION_FOR_TEMP(trip_state->trip_temp / 1000);
724 /* Hardcode LITE on level-1 and HEAVY on level-2 */
725 reg_off = TS_THERM_REG_OFFSET(CTL_LVL0_CPU0, throt + 1, therm);
727 r = soctherm_readl(reg_off);
728 r = REG_SET(r, CTL_LVL0_CPU0_UP_THRESH, trip_temp);
729 r = REG_SET(r, CTL_LVL0_CPU0_DN_THRESH, trip_temp);
730 r = REG_SET(r, CTL_LVL0_CPU0_EN, 1);
732 r = REG_SET(r, CTL_LVL0_CPU0_CPU_THROT,
733 throt == THROTTLE_HEAVY ?
734 CTL_LVL0_CPU0_CPU_THROT_HEAVY :
735 CTL_LVL0_CPU0_CPU_THROT_LIGHT);
736 r = REG_SET(r, CTL_LVL0_CPU0_GPU_THROT,
737 throt == THROTTLE_HEAVY ?
738 CTL_LVL0_CPU0_GPU_THROT_HEAVY :
739 CTL_LVL0_CPU0_GPU_THROT_LIGHT);
741 soctherm_writel(r, reg_off);
744 static void soctherm_set_limits(enum soctherm_therm_id therm,
745 long lo_limit, long hi_limit)
749 reg_off = TS_THERM_REG_OFFSET(CTL_LVL0_CPU0, 0, therm);
750 r = soctherm_readl(reg_off);
752 lo_limit = LOWER_PRECISION_FOR_TEMP(lo_limit);
753 hi_limit = LOWER_PRECISION_FOR_TEMP(hi_limit);
755 r = REG_SET(r, CTL_LVL0_CPU0_DN_THRESH, lo_limit);
756 r = REG_SET(r, CTL_LVL0_CPU0_UP_THRESH, hi_limit);
757 r = REG_SET(r, CTL_LVL0_CPU0_EN, 1);
758 soctherm_writel(r, reg_off);
762 r = REG_SET(0, TH_INTR_POS_CD0, 1);
763 r = REG_SET(r, TH_INTR_POS_CU0, 1);
766 r = REG_SET(0, TH_INTR_POS_GD0, 1);
767 r = REG_SET(r, TH_INTR_POS_GU0, 1);
770 r = REG_SET(0, TH_INTR_POS_PD0, 1);
771 r = REG_SET(r, TH_INTR_POS_PU0, 1);
774 r = REG_SET(0, TH_INTR_POS_MD0, 1);
775 r = REG_SET(r, TH_INTR_POS_MU0, 1);
781 soctherm_writel(r, TH_INTR_ENABLE);
784 static void soctherm_update_zone(int zn)
786 long low_temp = 0, high_temp = MAX_HIGH_TEMP;
787 long trip_temp, passive_low_temp = MAX_HIGH_TEMP, zone_temp;
788 enum thermal_trip_type trip_type;
789 struct thermal_trip_info *trip_state;
790 struct thermal_zone_device *cur_thz = thz[zn];
793 thermal_zone_device_update(cur_thz);
795 trips = cur_thz->trips;
796 for (count = 0; count < trips; count++) {
797 cur_thz->ops->get_trip_type(cur_thz, count, &trip_type);
798 if ((trip_type == THERMAL_TRIP_HOT) ||
799 (trip_type == THERMAL_TRIP_CRITICAL))
800 continue; /* handled in HW */
802 cur_thz->ops->get_trip_temp(cur_thz, count, &trip_temp);
804 trip_state = &plat_data.therm[zn].trips[count];
805 zone_temp = cur_thz->temperature;
807 if (!trip_state->tripped) { /* not tripped? update high */
808 if (trip_temp < high_temp)
809 high_temp = trip_temp;
810 } else { /* tripped? update low */
811 if (trip_type != THERMAL_TRIP_PASSIVE) {
812 /* get highest ACTIVE */
813 if (trip_temp > low_temp)
814 low_temp = trip_temp;
816 /* get lowest PASSIVE */
817 if (trip_temp < passive_low_temp)
818 passive_low_temp = trip_temp;
823 if (passive_low_temp != MAX_HIGH_TEMP)
824 low_temp = max(low_temp, passive_low_temp);
826 soctherm_set_limits(zn, low_temp/1000, high_temp/1000);
829 static void soctherm_update(void)
833 if (!soctherm_init_platform_done)
836 for (i = 0; i < THERM_SIZE; i++) {
837 if (thz[i] && thz[i]->trips)
838 soctherm_update_zone(i);
842 static int soctherm_hw_action_get_max_state(struct thermal_cooling_device *cdev,
843 unsigned long *max_state)
845 struct thermal_trip_info *trip_state = cdev->devdata;
850 *max_state = 3; /* bit 1: CPU bit 2: GPU */
854 static int soctherm_hw_action_get_cur_state(struct thermal_cooling_device *cdev,
855 unsigned long *cur_state)
857 struct thermal_trip_info *trip_state = cdev->devdata;
865 if (trip_state->trip_type != THERMAL_TRIP_HOT)
868 for (j = 0; j < THROTTLE_DEV_SIZE; j++) {
869 r = soctherm_readl(CPU_PSKIP_STATUS + (j * 4));
870 if (!REG_GET(r, CPU_PSKIP_STATUS_ENABLED))
872 if (tegra_chip_id == TEGRA_CHIPID_TEGRA12 &&
873 j == THROTTLE_DEV_GPU) {
874 for (i = THROTTLE_LIGHT; i <= THROTTLE_HEAVY; i++) {
875 if (strnstr(trip_state->cdev_type,
876 throt_names[i], THERMAL_NAME_LENGTH) &&
877 plat_data.throttle[i].devs[j].enable)
878 *cur_state |= (j + 1);
879 /* bit1: CPU bit2: GPU */
883 m = REG_GET(r, CPU_PSKIP_STATUS_M);
884 n = REG_GET(r, CPU_PSKIP_STATUS_N);
885 for (i = THROTTLE_LIGHT; i <= THROTTLE_HEAVY; i++) {
886 if (strnstr(trip_state->cdev_type,
887 throt_names[i], THERMAL_NAME_LENGTH) &&
888 plat_data.throttle[i].devs[j].enable &&
889 m == plat_data.throttle[i].devs[j].dividend &&
890 n == plat_data.throttle[i].devs[j].divisor)
891 *cur_state |= (j + 1); /* bit1: CPU bit2: GPU */
897 static int soctherm_hw_action_set_cur_state(struct thermal_cooling_device *cdev,
898 unsigned long cur_state)
900 return 0; /* hw sets this state */
903 static struct thermal_cooling_device *soctherm_hw_critical_cdev;
904 static struct thermal_cooling_device *soctherm_hw_hot_cdev;
905 static struct thermal_cooling_device_ops soctherm_hw_action_ops = {
906 .get_max_state = soctherm_hw_action_get_max_state,
907 .get_cur_state = soctherm_hw_action_get_cur_state,
908 .set_cur_state = soctherm_hw_action_set_cur_state,
911 static int soctherm_suspend_get_max_state(struct thermal_cooling_device *cdev,
912 unsigned long *max_state)
918 static int soctherm_suspend_get_cur_state(struct thermal_cooling_device *cdev,
919 unsigned long *cur_state)
921 *cur_state = !soctherm_suspended;
925 static int soctherm_suspend_set_cur_state(struct thermal_cooling_device *cdev,
926 unsigned long cur_state)
928 if (!cur_state != soctherm_suspended) {
937 static struct thermal_cooling_device_ops soctherm_suspend_ops = {
938 .get_max_state = soctherm_suspend_get_max_state,
939 .get_cur_state = soctherm_suspend_get_cur_state,
940 .set_cur_state = soctherm_suspend_set_cur_state,
943 static int soctherm_bind(struct thermal_zone_device *thz,
944 struct thermal_cooling_device *cdev)
946 int i, index = ((int)thz->devdata) - TSENSE_SIZE;
947 struct thermal_trip_info *trip_state;
948 u32 base_cp, base_ft;
949 s32 shft_cp, shft_ft;
954 /* skip binding cooling devices on improperly fused soctherm */
955 if (tegra_fuse_calib_base_get_cp(&base_cp, &shft_cp) < 0 ||
956 tegra_fuse_calib_base_get_ft(&base_ft, &shft_ft) < 0)
959 for (i = 0; i < plat_data.therm[index].num_trips; i++) {
960 trip_state = &plat_data.therm[index].trips[i];
961 if (trip_state->bound)
963 if (trip_state->cdev_type &&
964 !strncmp(trip_state->cdev_type, cdev->type,
965 THERMAL_NAME_LENGTH)) {
966 thermal_zone_bind_cooling_device(thz, i, cdev,
969 trip_state->bound = true;
976 static int soctherm_unbind(struct thermal_zone_device *thz,
977 struct thermal_cooling_device *cdev)
979 int i, index = ((int)thz->devdata) - TSENSE_SIZE;
980 struct thermal_trip_info *trip_state;
985 for (i = 0; i < plat_data.therm[index].num_trips; i++) {
986 trip_state = &plat_data.therm[index].trips[i];
987 if (!trip_state->bound)
989 if (trip_state->cdev_type &&
990 !strncmp(trip_state->cdev_type, cdev->type,
991 THERMAL_NAME_LENGTH)) {
992 thermal_zone_unbind_cooling_device(thz, 0, cdev);
993 trip_state->bound = false;
1000 static int soctherm_get_temp(struct thermal_zone_device *thz,
1001 unsigned long *temp)
1003 int index = (int)thz->devdata;
1004 u32 r, regv, shft, mask;
1005 enum soctherm_sense i, j;
1008 if (index < TSENSE_SIZE) { /* 'TSENSE_XXX' thermal zone */
1009 regv = TS_CPU0_STATUS1;
1010 shft = TS_CPU0_STATUS1_TEMP_SHIFT;
1011 mask = TS_CPU0_STATUS1_TEMP_MASK;
1014 index -= TSENSE_SIZE; /* 'THERM_XXX' thermal zone */
1019 shft = TS_TEMP1_CPU_TEMP_SHIFT;
1020 mask = TS_TEMP1_CPU_TEMP_MASK;
1027 shft = TS_TEMP1_GPU_TEMP_SHIFT;
1028 mask = TS_TEMP1_GPU_TEMP_MASK;
1034 shft = TS_TEMP2_PLLX_TEMP_SHIFT;
1035 mask = TS_TEMP2_PLLX_TEMP_MASK;
1036 i = j = TSENSE_PLLX;
1041 shft = TS_TEMP2_MEM_TEMP_SHIFT;
1042 mask = TS_TEMP2_MEM_TEMP_MASK;
1048 return 0; /* error really */
1053 r = soctherm_readl(regv);
1054 *temp = temp_translate((r & (mask << shft)) >> shft);
1056 for (tt = 0; i <= j; i++) {
1057 r = soctherm_readl(TS_TSENSE_REG_OFFSET(
1058 TS_CPU0_STATUS0, i));
1059 ti = temp_convert(REG_GET(r, TS_CPU0_STATUS0_CAPTURE),
1062 *temp = tt = max(tt, ti);
1068 static int soctherm_get_trip_type(struct thermal_zone_device *thz,
1069 int trip, enum thermal_trip_type *type)
1071 int index = ((int)thz->devdata) - TSENSE_SIZE;
1072 struct thermal_trip_info *trip_state;
1077 trip_state = &plat_data.therm[index].trips[trip];
1078 *type = trip_state->trip_type;
1082 static int soctherm_get_trip_temp(struct thermal_zone_device *thz,
1083 int trip, unsigned long *temp)
1085 int index = ((int)thz->devdata) - TSENSE_SIZE;
1086 struct thermal_trip_info *trip_state;
1087 unsigned long trip_temp, zone_temp;
1092 trip_state = &plat_data.therm[index].trips[trip];
1093 trip_temp = trip_state->trip_temp;
1094 zone_temp = thz->temperature;
1096 if (zone_temp >= trip_temp) {
1097 trip_temp -= trip_state->hysteresis;
1098 trip_state->tripped = true;
1099 } else if (trip_state->tripped) {
1100 trip_temp -= trip_state->hysteresis;
1101 if (zone_temp < trip_temp)
1102 trip_state->tripped = false;
1110 static int soctherm_set_trip_temp(struct thermal_zone_device *thz,
1111 int trip, unsigned long temp)
1113 int index = ((int)thz->devdata) - TSENSE_SIZE;
1114 struct thermal_trip_info *trip_state;
1120 trip_state = &plat_data.therm[index].trips[trip];
1122 trip_state->trip_temp = temp;
1124 rem = trip_state->trip_temp % LOWER_PRECISION_FOR_CONV(1000);
1126 pr_warn("soctherm: zone%d/trip_point%d %ld mC rounded down\n",
1127 index, trip, trip_state->trip_temp);
1128 trip_state->trip_temp -= rem;
1131 if (trip_state->trip_type == THERMAL_TRIP_HOT) {
1132 if (strnstr(trip_state->cdev_type,
1133 "heavy", THERMAL_NAME_LENGTH))
1134 prog_hw_threshold(trip_state, index, THROTTLE_HEAVY);
1135 else if (strnstr(trip_state->cdev_type,
1136 "light", THERMAL_NAME_LENGTH))
1137 prog_hw_threshold(trip_state, index, THROTTLE_LIGHT);
1140 /* Allow SW to shutdown at 'Critical temperature reached' */
1141 soctherm_update_zone(index);
1143 /* Reprogram HW thermtrip */
1144 if (trip_state->trip_type == THERMAL_TRIP_CRITICAL)
1145 prog_hw_shutdown(trip_state, index);
1150 static int soctherm_get_crit_temp(struct thermal_zone_device *thz,
1151 unsigned long *temp)
1153 int i, index = ((int)thz->devdata) - TSENSE_SIZE;
1154 struct thermal_trip_info *trip_state;
1159 for (i = 0; i < plat_data.therm[index].num_trips; i++) {
1160 trip_state = &plat_data.therm[index].trips[i];
1161 if (trip_state->trip_type != THERMAL_TRIP_CRITICAL)
1163 *temp = trip_state->trip_temp;
1170 static int soctherm_get_trend(struct thermal_zone_device *thz,
1172 enum thermal_trend *trend)
1174 int index = ((int)thz->devdata) - TSENSE_SIZE;
1175 struct thermal_trip_info *trip_state;
1181 trip_state = &plat_data.therm[index].trips[trip];
1182 thz->ops->get_trip_temp(thz, trip, &trip_temp);
1184 switch (trip_state->trip_type) {
1185 case THERMAL_TRIP_ACTIVE:
1186 /* aggressive active cooling */
1187 *trend = THERMAL_TREND_RAISING;
1189 case THERMAL_TRIP_PASSIVE:
1190 if (thz->temperature > trip_state->trip_temp)
1191 *trend = THERMAL_TREND_RAISING;
1192 else if (thz->temperature < trip_temp)
1193 *trend = THERMAL_TREND_DROPPING;
1195 *trend = THERMAL_TREND_STABLE;
1203 static struct thermal_zone_device_ops soctherm_ops = {
1204 .bind = soctherm_bind,
1205 .unbind = soctherm_unbind,
1206 .get_temp = soctherm_get_temp,
1207 .get_trip_type = soctherm_get_trip_type,
1208 .get_trip_temp = soctherm_get_trip_temp,
1209 .set_trip_temp = soctherm_set_trip_temp,
1210 .get_crit_temp = soctherm_get_crit_temp,
1211 .get_trend = soctherm_get_trend,
1214 static int __init soctherm_thermal_sys_init(void)
1216 char name[THERMAL_NAME_LENGTH];
1217 struct soctherm_therm *therm;
1221 if (!soctherm_init_platform_done)
1224 for (i = 0; i < TSENSE_SIZE; i++) {
1225 if (plat_data.sensor_data[i].zone_enable) {
1226 snprintf(name, THERMAL_NAME_LENGTH,
1227 "%s-tsensor", sensor_names[i]);
1228 /* Create a thermal zone device for each sensor */
1229 thermal_zone_device_register(
1241 for (i = 0; i < THERM_SIZE; i++) {
1242 therm = &plat_data.therm[i];
1243 if (!therm->zone_enable)
1246 for (j = 0; j < therm->num_trips; j++) {
1247 switch (therm->trips[j].trip_type) {
1248 case THERMAL_TRIP_CRITICAL:
1249 if (soctherm_hw_critical_cdev)
1251 soctherm_hw_critical_cdev =
1252 thermal_cooling_device_register(
1253 therm->trips[j].cdev_type,
1255 &soctherm_hw_action_ops);
1258 case THERMAL_TRIP_HOT:
1259 for (k = 0; k < THROTTLE_SIZE; k++) {
1260 if (!plat_data.throttle[k].
1261 devs[therm2dev[i]].enable)
1264 if ((strnstr(therm->trips[j].cdev_type,
1266 THERMAL_NAME_LENGTH)
1267 && k == THROTTLE_LIGHT) ||
1268 (strnstr(therm->trips[j].cdev_type,
1270 THERMAL_NAME_LENGTH)
1271 && k == THROTTLE_HEAVY) ||
1272 (strnstr(therm->trips[j].cdev_type,
1274 THERMAL_NAME_LENGTH)
1275 && k == THROTTLE_OC1) ||
1276 (strnstr(therm->trips[j].cdev_type,
1278 THERMAL_NAME_LENGTH)
1279 && k == THROTTLE_OC2) ||
1280 (strnstr(therm->trips[j].cdev_type,
1282 THERMAL_NAME_LENGTH)
1283 && k == THROTTLE_OC3) ||
1284 (strnstr(therm->trips[j].cdev_type,
1286 THERMAL_NAME_LENGTH)
1287 && k == THROTTLE_OC4) ||
1288 (strnstr(therm->trips[j].cdev_type,
1290 THERMAL_NAME_LENGTH)
1291 && k == THROTTLE_OC5))
1294 if (soctherm_hw_hot_cdev)
1296 soctherm_hw_hot_cdev =
1297 thermal_cooling_device_register(
1298 therm->trips[j].cdev_type,
1300 &soctherm_hw_action_ops);
1304 case THERMAL_TRIP_PASSIVE:
1305 case THERMAL_TRIP_ACTIVE:
1306 break; /* done elsewhere */
1310 snprintf(name, THERMAL_NAME_LENGTH,
1311 "%s-therm", therm_names[i]);
1312 thz[i] = thermal_zone_device_register(
1315 (1ULL << therm->num_trips) - 1,
1316 (void *)TSENSE_SIZE + i,
1319 therm->passive_delay,
1322 for (k = THROTTLE_OC1; !oc_en && k < THROTTLE_SIZE; k++) {
1323 if (therm2dev[i] == THROTTLE_DEV_NONE)
1325 if (plat_data.throttle[k].devs[therm2dev[i]].enable)
1330 /* do not enable suspend feature if any OC alarms are enabled */
1332 thermal_cooling_device_register("suspend_soctherm", 0,
1333 &soctherm_suspend_ops);
1335 pr_warn("soctherm: Suspend feature CANNOT be enabled %s\n",
1336 "when any OC alarm is enabled");
1341 module_init(soctherm_thermal_sys_init);
1344 static void soctherm_update_zone(int zn)
1347 static void soctherm_update(void)
1352 static irqreturn_t soctherm_thermal_thread_func(int irq, void *arg)
1354 u32 st, ex = 0, cp = 0, gp = 0, pl = 0;
1356 st = soctherm_readl(TH_INTR_STATUS);
1358 /* deliberately clear expected interrupts handled in SW */
1359 cp |= REG_GET_BIT(st, TH_INTR_POS_CD0);
1360 cp |= REG_GET_BIT(st, TH_INTR_POS_CU0);
1363 gp |= REG_GET_BIT(st, TH_INTR_POS_GD0);
1364 gp |= REG_GET_BIT(st, TH_INTR_POS_GU0);
1367 pl |= REG_GET_BIT(st, TH_INTR_POS_PD0);
1368 pl |= REG_GET_BIT(st, TH_INTR_POS_PU0);
1372 soctherm_writel(ex, TH_INTR_STATUS);
1375 soctherm_update_zone(THERM_CPU);
1377 soctherm_update_zone(THERM_GPU);
1379 soctherm_update_zone(THERM_PLL);
1382 /* deliberately ignore expected interrupts NOT handled in SW */
1383 ex |= REG_GET_BIT(st, TH_INTR_POS_MD0);
1384 ex |= REG_GET_BIT(st, TH_INTR_POS_MU0);
1386 ex |= REG_GET_BIT(st, TH_INTR_POS_CD1);
1387 ex |= REG_GET_BIT(st, TH_INTR_POS_CU1);
1388 ex |= REG_GET_BIT(st, TH_INTR_POS_CD2);
1389 ex |= REG_GET_BIT(st, TH_INTR_POS_CU2);
1390 ex |= REG_GET_BIT(st, TH_INTR_POS_CD3);
1391 ex |= REG_GET_BIT(st, TH_INTR_POS_CU3);
1393 ex |= REG_GET_BIT(st, TH_INTR_POS_GD1);
1394 ex |= REG_GET_BIT(st, TH_INTR_POS_GU1);
1395 ex |= REG_GET_BIT(st, TH_INTR_POS_GD2);
1396 ex |= REG_GET_BIT(st, TH_INTR_POS_GU2);
1397 ex |= REG_GET_BIT(st, TH_INTR_POS_GD3);
1398 ex |= REG_GET_BIT(st, TH_INTR_POS_GU3);
1400 ex |= REG_GET_BIT(st, TH_INTR_POS_PD1);
1401 ex |= REG_GET_BIT(st, TH_INTR_POS_PU1);
1402 ex |= REG_GET_BIT(st, TH_INTR_POS_PD2);
1403 ex |= REG_GET_BIT(st, TH_INTR_POS_PU2);
1404 ex |= REG_GET_BIT(st, TH_INTR_POS_PD3);
1405 ex |= REG_GET_BIT(st, TH_INTR_POS_PU3);
1407 ex |= REG_GET_BIT(st, TH_INTR_POS_MD1);
1408 ex |= REG_GET_BIT(st, TH_INTR_POS_MU1);
1409 ex |= REG_GET_BIT(st, TH_INTR_POS_MD2);
1410 ex |= REG_GET_BIT(st, TH_INTR_POS_MU2);
1411 ex |= REG_GET_BIT(st, TH_INTR_POS_MD3);
1412 ex |= REG_GET_BIT(st, TH_INTR_POS_MU3);
1416 /* Whine about any other unexpected INTR bits still set */
1417 pr_err("soctherm: Ignored unexpected INTRs 0x%08x\n", st);
1418 soctherm_writel(st, TH_INTR_STATUS);
1424 static inline void soctherm_oc_intr_enable(enum soctherm_throttle_id alarm,
1434 r = REG_SET(0, OC_INTR_POS_OC1, 1);
1437 r = REG_SET(0, OC_INTR_POS_OC2, 1);
1440 r = REG_SET(0, OC_INTR_POS_OC3, 1);
1443 r = REG_SET(0, OC_INTR_POS_OC4, 1);
1446 r = REG_SET(0, OC_INTR_POS_OC5, 1);
1452 soctherm_writel(r, OC_INTR_ENABLE);
1455 /* Return 0 (success) if you want to reenable OC alarm intr. */
1456 static int soctherm_handle_alarm(enum soctherm_throttle_id alarm)
1462 pr_warn("soctherm: Unexpected OC1 alarm\n");
1463 /* add OC1 alarm handling code here */
1467 pr_info("soctherm: Successfully handled OC2 alarm\n");
1468 /* TODO: add OC2 alarm handling code here */
1473 pr_warn("soctherm: Unexpected OC3 alarm\n");
1474 /* add OC3 alarm handling code here */
1478 pr_debug("soctherm: Successfully handled OC4 alarm\n");
1479 /* TODO: add OC4 alarm handling code here */
1484 pr_warn("soctherm: Unexpected OC5 alarm\n");
1485 /* add OC5 alarm handling code here */
1493 pr_err("soctherm: ERROR in handling %s alarm\n",
1494 throt_names[alarm]);
1499 static irqreturn_t soctherm_edp_thread_func(int irq, void *arg)
1501 u32 st, ex, oc1, oc2, oc3, oc4, oc5;
1503 st = soctherm_readl(OC_INTR_STATUS);
1505 /* deliberately clear expected interrupts handled in SW */
1506 oc1 = REG_GET_BIT(st, OC_INTR_POS_OC1);
1507 oc2 = REG_GET_BIT(st, OC_INTR_POS_OC2);
1508 oc3 = REG_GET_BIT(st, OC_INTR_POS_OC3);
1509 oc4 = REG_GET_BIT(st, OC_INTR_POS_OC4);
1510 oc5 = REG_GET_BIT(st, OC_INTR_POS_OC5);
1511 ex = oc1 | oc2 | oc3 | oc4 | oc5;
1514 soctherm_writel(st, OC_INTR_STATUS);
1517 if (oc1 && !soctherm_handle_alarm(THROTTLE_OC1))
1518 soctherm_oc_intr_enable(THROTTLE_OC1, true);
1520 if (oc2 && !soctherm_handle_alarm(THROTTLE_OC2))
1521 soctherm_oc_intr_enable(THROTTLE_OC2, true);
1523 if (oc3 && !soctherm_handle_alarm(THROTTLE_OC3))
1524 soctherm_oc_intr_enable(THROTTLE_OC3, true);
1526 if (oc4 && !soctherm_handle_alarm(THROTTLE_OC4))
1527 soctherm_oc_intr_enable(THROTTLE_OC4, true);
1529 if (oc5 && !soctherm_handle_alarm(THROTTLE_OC5))
1530 soctherm_oc_intr_enable(THROTTLE_OC5, true);
1532 if (oc1 && soc_irq_cdata.irq_enable & BIT(0))
1534 irq_find_mapping(soc_irq_cdata.domain, 0));
1536 if (oc2 && soc_irq_cdata.irq_enable & BIT(1))
1538 irq_find_mapping(soc_irq_cdata.domain, 1));
1540 if (oc3 && soc_irq_cdata.irq_enable & BIT(2))
1542 irq_find_mapping(soc_irq_cdata.domain, 2));
1544 if (oc4 && soc_irq_cdata.irq_enable & BIT(3))
1546 irq_find_mapping(soc_irq_cdata.domain, 3));
1548 if (oc5 && soc_irq_cdata.irq_enable & BIT(4))
1550 irq_find_mapping(soc_irq_cdata.domain, 0));
1554 pr_err("soctherm: Ignored unexpected OC ALARM 0x%08x\n", st);
1555 soctherm_writel(st, OC_INTR_STATUS);
1561 static irqreturn_t soctherm_thermal_isr(int irq, void *arg)
1565 r = soctherm_readl(TH_INTR_STATUS);
1566 soctherm_writel(r, TH_INTR_DISABLE);
1568 return IRQ_WAKE_THREAD;
1571 static irqreturn_t soctherm_edp_isr(int irq, void *arg)
1575 r = soctherm_readl(OC_INTR_STATUS);
1576 soctherm_writel(r, OC_INTR_DISABLE);
1578 return IRQ_WAKE_THREAD;
1581 static void tegra11_soctherm_throttle_program(enum soctherm_throttle_id throt)
1586 bool throt_enable = false;
1587 struct soctherm_throttle_dev *dev;
1588 struct soctherm_throttle *data = &plat_data.throttle[throt];
1590 for (i = 0; i < THROTTLE_DEV_SIZE; i++) {
1591 dev = &data->devs[i];
1594 throt_enable = true;
1596 if (i == THROTTLE_DEV_GPU && tegra_chip_id ==
1597 TEGRA_CHIPID_TEGRA12) {
1598 /* gk20a interface N:3 Mapping */
1599 if (!strcmp(dev->throttling_depth,
1600 "heavy_throttling"))
1601 gk20a_throt = THROT_DEPTH_HIG;
1602 else if (!strcmp(dev->throttling_depth,
1603 "medium_throttling"))
1604 gk20a_throt = THROT_DEPTH_MED;
1606 gk20a_throt = THROT_DEPTH_LOW;
1608 r = soctherm_readl(THROT_PSKIP_CTRL(throt, i));
1609 r = REG_SET(r, THROT_PSKIP_CTRL_ENABLE, dev->enable);
1611 r = REG_SET(r, THROT_PSKIP_CTRL_THROT_DEPTH,
1614 soctherm_writel(r, THROT_PSKIP_CTRL(throt, i));
1618 THROT_DEPTH(dev, dev->depth);
1619 } else if (!dev->dividend || !dev->divisor
1620 || !dev->duration || !dev->step) {
1621 THROT_DEPTH(dev, THROT_DEPTH_DEFAULT);
1624 r = soctherm_readl(THROT_PSKIP_CTRL(throt, i));
1625 r = REG_SET(r, THROT_PSKIP_CTRL_ENABLE, dev->enable);
1627 r = REG_SET(r, THROT_PSKIP_CTRL_DIVIDEND, dev->dividend);
1628 r = REG_SET(r, THROT_PSKIP_CTRL_DIVISOR, dev->divisor);
1629 soctherm_writel(r, THROT_PSKIP_CTRL(throt, i));
1631 r = soctherm_readl(THROT_PSKIP_RAMP(throt, i));
1632 r = REG_SET(r, THROT_PSKIP_RAMP_DURATION, dev->duration);
1633 r = REG_SET(r, THROT_PSKIP_RAMP_STEP, dev->step);
1634 soctherm_writel(r, THROT_PSKIP_RAMP(throt, i));
1637 r = REG_SET(0, THROT_PRIORITY_LITE_PRIO, data->priority);
1638 soctherm_writel(r, THROT_PRIORITY_CTRL(throt));
1640 r = REG_SET(0, THROT_DELAY_LITE_DELAY, 0);
1641 soctherm_writel(r, THROT_DELAY_CTRL(throt));
1643 r = soctherm_readl(THROT_PRIORITY_LOCK);
1644 if (r < data->priority) {
1645 r = REG_SET(0, THROT_PRIORITY_LOCK_PRIORITY, data->priority);
1646 soctherm_writel(r, THROT_PRIORITY_LOCK);
1649 if (!throt_enable || (throt < THROTTLE_OC1))
1652 /* ----- configure OC alarms ----- */
1654 if (!(data->throt_mode == BRIEF || data->throt_mode == STICKY))
1655 pr_warn("soctherm: Invalid throt_mode in %s\n",
1656 throt_names[throt]);
1658 r = soctherm_readl(ALARM_CFG(throt));
1659 r = REG_SET(r, OC1_CFG_HW_RESTORE, 1);
1660 r = REG_SET(r, OC1_CFG_PWR_GOOD_MASK, data->pgmask);
1661 r = REG_SET(r, OC1_CFG_THROTTLE_MODE, data->throt_mode);
1662 r = REG_SET(r, OC1_CFG_ALARM_POLARITY, data->polarity);
1663 r = REG_SET(r, OC1_CFG_EN_THROTTLE, 1);
1664 soctherm_writel(r, ALARM_CFG(throt));
1666 soctherm_oc_intr_enable(throt, data->intr);
1668 soctherm_writel(data->period, ALARM_THRESHOLD_PERIOD(throt)); /* usec */
1669 soctherm_writel(0xffffffff, ALARM_FILTER(throt));
1672 static void soctherm_tsense_program(enum soctherm_sense sensor,
1673 struct soctherm_sensor *data)
1677 r = REG_SET(0, TS_CPU0_CONFIG0_TALL, data->tall);
1678 soctherm_writel(r, TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG0, sensor));
1680 r = REG_SET(0, TS_CPU0_CONFIG1_TIDDQ, data->tiddq);
1681 r = REG_SET(r, TS_CPU0_CONFIG1_EN, 1);
1682 r = REG_SET(r, TS_CPU0_CONFIG1_TEN_COUNT, data->ten_count);
1683 r = REG_SET(r, TS_CPU0_CONFIG1_TSAMPLE, data->tsample - 1);
1684 soctherm_writel(r, TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG1, sensor));
1687 static int __init soctherm_clk_init(void)
1689 unsigned long default_soctherm_clk_rate;
1690 unsigned long default_tsensor_clk_rate;
1692 soctherm_clk = clk_get_sys("soc_therm", NULL);
1693 tsensor_clk = clk_get_sys("tegra-tsensor", NULL);
1695 if (IS_ERR(tsensor_clk) || IS_ERR(soctherm_clk)) {
1696 clk_put(soctherm_clk);
1697 clk_put(tsensor_clk);
1698 soctherm_clk = tsensor_clk = NULL;
1702 /* initialize default clock rates */
1703 if (tegra_chip_id == TEGRA_CHIPID_TEGRA11) {
1704 default_soctherm_clk_rate =
1705 default_t11x_soctherm_clk_rate;
1706 default_tsensor_clk_rate =
1707 default_t11x_tsensor_clk_rate;
1708 } else if (tegra_chip_id == TEGRA_CHIPID_TEGRA14) {
1709 default_soctherm_clk_rate =
1710 default_t14x_soctherm_clk_rate;
1711 default_tsensor_clk_rate =
1712 default_t14x_tsensor_clk_rate;
1713 } else if (tegra_chip_id == TEGRA_CHIPID_TEGRA12) {
1714 default_soctherm_clk_rate =
1715 default_t12x_soctherm_clk_rate;
1716 default_tsensor_clk_rate =
1717 default_t12x_tsensor_clk_rate;
1722 plat_data.soctherm_clk_rate =
1723 plat_data.soctherm_clk_rate ?: default_soctherm_clk_rate;
1724 plat_data.tsensor_clk_rate =
1725 plat_data.tsensor_clk_rate ?: default_tsensor_clk_rate;
1727 if (clk_get_rate(soctherm_clk) != plat_data.soctherm_clk_rate)
1728 if (clk_set_rate(soctherm_clk, plat_data.soctherm_clk_rate))
1731 if (clk_get_rate(tsensor_clk) != plat_data.tsensor_clk_rate)
1732 if (clk_set_rate(tsensor_clk, plat_data.tsensor_clk_rate))
1738 static int soctherm_clk_enable(bool enable)
1740 if (soctherm_clk == NULL || tsensor_clk == NULL)
1744 clk_enable(soctherm_clk);
1745 clk_enable(tsensor_clk);
1747 clk_disable(soctherm_clk);
1748 clk_disable(tsensor_clk);
1754 static int soctherm_fuse_read_calib_base(void)
1756 s32 calib_cp, calib_ft;
1757 s32 nominal_calib_cp, nominal_calib_ft;
1759 if (tegra_fuse_calib_base_get_cp(&fuse_calib_base_cp, &calib_cp) < 0 ||
1760 tegra_fuse_calib_base_get_ft(&fuse_calib_base_ft, &calib_ft) < 0) {
1761 pr_err("soctherm: ERROR: Improper CP or FT calib fuse.\n");
1765 nominal_calib_cp = 25;
1766 if (tegra_chip_id == TEGRA_CHIPID_TEGRA11)
1767 nominal_calib_ft = 90;
1768 else if (tegra_chip_id == TEGRA_CHIPID_TEGRA14)
1769 nominal_calib_ft = 105;
1770 else if (tegra_chip_id == TEGRA_CHIPID_TEGRA12)
1771 nominal_calib_ft = 105;
1775 /* use HI precision to calculate: use fuse_temp in 0.5C */
1776 actual_temp_cp = 2 * nominal_calib_cp + calib_cp;
1777 actual_temp_ft = 2 * nominal_calib_ft + calib_ft;
1782 static int t11x_fuse_corr_alpha[] = { /* scaled *1000000 */
1783 [TSENSE_CPU0] = 1196400,
1784 [TSENSE_CPU1] = 1196400,
1785 [TSENSE_CPU2] = 1196400,
1786 [TSENSE_CPU3] = 1196400,
1787 [TSENSE_GPU] = 1124500,
1788 [TSENSE_PLLX] = 1224200,
1791 static int t11x_fuse_corr_beta[] = { /* scaled *1000000 */
1792 [TSENSE_CPU0] = -13600000,
1793 [TSENSE_CPU1] = -13600000,
1794 [TSENSE_CPU2] = -13600000,
1795 [TSENSE_CPU3] = -13600000,
1796 [TSENSE_GPU] = -9793100,
1797 [TSENSE_PLLX] = -14665000,
1800 static int t14x_fuse_corr_alpha[] = { /* scaled *1000000 */
1801 [TSENSE_CPU0] = 1149000,
1802 [TSENSE_CPU1] = 1148800,
1803 [TSENSE_CPU2] = 1139100,
1804 [TSENSE_CPU3] = 1141800,
1805 [TSENSE_MEM0] = 1082300,
1806 [TSENSE_MEM1] = 1061800,
1807 [TSENSE_GPU] = 1078900,
1808 [TSENSE_PLLX] = 1125900,
1811 static int t14x_fuse_corr_beta[] = { /* scaled *1000000 */
1812 [TSENSE_CPU0] = -16753000,
1813 [TSENSE_CPU1] = -16287000,
1814 [TSENSE_CPU2] = -12552000,
1815 [TSENSE_CPU3] = -11061000,
1816 [TSENSE_MEM0] = -11061000,
1817 [TSENSE_MEM1] = -7596500,
1818 [TSENSE_GPU] = -10480000,
1819 [TSENSE_PLLX] = -14736000,
1822 static int t12x_fuse_corr_alpha[] = { /* scaled *1000000 */
1823 [TSENSE_CPU0] = 1148300,
1824 [TSENSE_CPU1] = 1126100,
1825 [TSENSE_CPU2] = 1155800,
1826 [TSENSE_CPU3] = 1134900,
1827 [TSENSE_MEM0] = 1062700,
1828 [TSENSE_MEM1] = 1084700,
1829 [TSENSE_GPU] = 1084300,
1830 [TSENSE_PLLX] = 1134500,
1833 static int t12x_fuse_corr_beta[] = { /* scaled *1000000 */
1834 [TSENSE_CPU0] = -6572300,
1835 [TSENSE_CPU1] = -5794600,
1836 [TSENSE_CPU2] = -7462800,
1837 [TSENSE_CPU3] = -6810800,
1838 [TSENSE_MEM0] = -4463200,
1839 [TSENSE_MEM1] = -5603400,
1840 [TSENSE_GPU] = -5111900,
1841 [TSENSE_PLLX] = -7410700,
1844 static int t12x_fuse_corr_alpa2[] = { /* scaled *1000000 */
1845 [TSENSE_CPU0] = 1135400,
1846 [TSENSE_CPU1] = 1122220,
1847 [TSENSE_CPU2] = 1127000,
1848 [TSENSE_CPU3] = 1110900,
1849 [TSENSE_MEM0] = 1122300,
1850 [TSENSE_MEM1] = 1145700,
1851 [TSENSE_GPU] = 1120100,
1852 [TSENSE_PLLX] = 1106500,
1855 static int t12x_fuse_corr_beta2[] = { /* scaled *1000000 */
1856 [TSENSE_CPU0] = -6266900,
1857 [TSENSE_CPU1] = -5700700,
1858 [TSENSE_CPU2] = -6768200,
1859 [TSENSE_CPU3] = -6232000,
1860 [TSENSE_MEM0] = -5936400,
1861 [TSENSE_MEM1] = -7124600,
1862 [TSENSE_GPU] = -6000500,
1863 [TSENSE_PLLX] = -6729300,
1866 static int soctherm_fuse_read_tsensor(enum soctherm_sense sensor)
1869 s32 calib, delta_sens, delta_temp;
1870 s16 therm_a, therm_b;
1871 s32 div, mult, actual_tsensor_ft, actual_tsensor_cp;
1876 fuse_rev = tegra_fuse_calib_base_get_cp(&base_cp, &shft_cp);
1880 tegra_fuse_get_tsensor_calib(sensor2tsensorcalib[sensor], &value);
1882 /* Extract bits and convert to signed 2's complement */
1883 calib = REG_GET(value, FUSE_TSENSOR_CALIB_FT);
1884 calib = MAKE_SIGNED32(calib, FUSE_TSENSOR_CALIB_BITS);
1885 actual_tsensor_ft = (fuse_calib_base_ft * 32) + calib;
1887 calib = REG_GET(value, FUSE_TSENSOR_CALIB_CP);
1888 calib = MAKE_SIGNED32(calib, FUSE_TSENSOR_CALIB_BITS);
1889 actual_tsensor_cp = (fuse_calib_base_cp * 64) + calib;
1891 mult = plat_data.sensor_data[sensor].pdiv *
1892 plat_data.sensor_data[sensor].tsamp_ATE;
1893 div = plat_data.sensor_data[sensor].tsample *
1894 plat_data.sensor_data[sensor].pdiv_ATE;
1896 /* first calculate therm_a and therm_b in Hi precision */
1897 delta_sens = actual_tsensor_ft - actual_tsensor_cp;
1898 delta_temp = actual_temp_ft - actual_temp_cp;
1900 therm_a = div64_s64_precise((s64)delta_temp * (1LL << 13) * mult,
1901 (s64)delta_sens * div);
1903 therm_b = div64_s64_precise((((s64)actual_tsensor_ft * actual_temp_cp) -
1904 ((s64)actual_tsensor_cp * actual_temp_ft)),
1907 /* FUSE corrections for Tegra when precision is set LOW */
1908 if (PRECISION_IS_LOWER()) {
1909 if (tegra_chip_id == TEGRA_CHIPID_TEGRA11) {
1910 t11x_fuse_corr_alpha[sensor] =
1911 t11x_fuse_corr_alpha[sensor] ?: 1000000;
1912 therm_a = div64_s64_precise(
1913 (s64)therm_a * t11x_fuse_corr_alpha[sensor],
1915 therm_b = div64_s64_precise(
1916 (s64)therm_b * t11x_fuse_corr_alpha[sensor] +
1917 t11x_fuse_corr_beta[sensor], (s64)1000000LL);
1918 } else if (tegra_chip_id == TEGRA_CHIPID_TEGRA14) {
1919 t14x_fuse_corr_alpha[sensor] =
1920 t14x_fuse_corr_alpha[sensor] ?: 1000000;
1921 therm_a = div64_s64_precise(
1922 (s64)therm_a * t14x_fuse_corr_alpha[sensor],
1924 therm_b = div64_s64_precise(
1925 (s64)therm_b * t14x_fuse_corr_alpha[sensor] +
1926 t14x_fuse_corr_beta[sensor], (s64)1000000LL);
1929 if (tegra_chip_id == TEGRA_CHIPID_TEGRA12) {
1930 if (fuse_rev == 0) { /* new CP1/CP2 */
1931 t12x_fuse_corr_alpa2[sensor] =
1932 t12x_fuse_corr_alpa2[sensor] ?: 1000000;
1933 therm_a = div64_s64_precise(
1934 (s64)therm_a * t12x_fuse_corr_alpa2[sensor],
1936 therm_b = div64_s64_precise(
1937 (s64)therm_b * t12x_fuse_corr_alpa2[sensor] +
1938 t12x_fuse_corr_beta2[sensor], (s64)1000000LL);
1939 } else { /* old CP/FT */
1940 t12x_fuse_corr_alpha[sensor] =
1941 t12x_fuse_corr_alpha[sensor] ?: 1000000;
1942 therm_a = div64_s64_precise(
1943 (s64)therm_a * t12x_fuse_corr_alpha[sensor],
1945 therm_b = div64_s64_precise(
1946 (s64)therm_b * t12x_fuse_corr_alpha[sensor] +
1947 t12x_fuse_corr_beta[sensor], (s64)1000000LL);
1952 therm_a = LOWER_PRECISION_FOR_TEMP(therm_a);
1953 therm_b = LOWER_PRECISION_FOR_TEMP(therm_b);
1955 sensor2therm_a[sensor] = (s16)therm_a;
1956 sensor2therm_b[sensor] = (s16)therm_b;
1958 r = REG_SET(0, TS_CPU0_CONFIG2_THERM_A, therm_a);
1959 r = REG_SET(r, TS_CPU0_CONFIG2_THERM_B, therm_b);
1960 soctherm_writel(r, TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG2, sensor));
1965 static void soctherm_therm_trip_init(struct tegra_tsensor_pmu_data *data)
1972 /* enable therm trip at PMC */
1973 val = pmc_readl(PMC_SENSOR_CTRL);
1974 val = REG_SET(val, PMC_SCRATCH_WRITE, 1);
1975 val = REG_SET(val, PMC_ENABLE_RST, 1);
1976 pmc_writel(val, PMC_SENSOR_CTRL);
1978 /* Fill scratch registers to shutdown device on therm TRIP */
1979 val = REG_SET(0, PMU_OFF_DATA, data->poweroff_reg_data);
1980 val = REG_SET(val, PMU_OFF_ADDR, data->poweroff_reg_addr);
1981 pmc_writel(val, PMC_SCRATCH54);
1983 val = REG_SET(0, RESET_TEGRA, 1);
1984 val = REG_SET(val, CONTROLLER_TYPE, data->controller_type);
1985 val = REG_SET(val, I2C_CONTROLLER_ID, data->i2c_controller_id);
1986 val = REG_SET(val, PINMUX, data->pinmux);
1987 val = REG_SET(val, PMU_16BIT_SUPPORT, data->pmu_16bit_ops);
1988 val = REG_SET(val, PMU_I2C_ADDRESS, data->pmu_i2c_addr);
1990 checksum = data->poweroff_reg_addr +
1991 data->poweroff_reg_data +
1993 ((val >> 8) & 0xFF) +
1994 ((val >> 24) & 0xFF);
1996 checksum = 0x100 - checksum;
1998 val = REG_SET(val, CHECKSUM, checksum);
1999 pmc_writel(val, PMC_SCRATCH55);
2002 static void soctherm_adjust_cpu_zone(void)
2006 unsigned long cpu_temp, pll_temp, diff;
2008 if (soctherm_suspended)
2011 if (!soctherm_high_voltage_range) {
2012 r = soctherm_readl(TS_TEMP1);
2013 cpu_temp = temp_translate(REG_GET(r, TS_TEMP1_CPU_TEMP));
2016 r = soctherm_readl(TS_TEMP2);
2017 pll_temp = temp_translate(REG_GET(r, TS_TEMP2_PLLX_TEMP));
2019 if (cpu_temp > pll_temp)
2020 diff = cpu_temp - pll_temp;
2024 /* Program hotspot offsets per CPU ~ PLL diff */
2025 r = soctherm_readl(TS_HOTSPOT_OFF);
2026 r = REG_SET(r, TS_HOTSPOT_OFF_CPU, diff / 1000);
2027 soctherm_writel(r, TS_HOTSPOT_OFF);
2029 /* Stop CPUn TSOSCs */
2030 for (cpu = 0; cpu <= TSENSE_CPU3; cpu++) {
2031 r = soctherm_readl(TS_TSENSE_REG_OFFSET
2032 (TS_CPU0_CONFIG0, cpu));
2033 r = REG_SET(r, TS_CPU0_CONFIG0_STOP, 1);
2034 soctherm_writel(r, TS_TSENSE_REG_OFFSET
2035 (TS_CPU0_CONFIG0, cpu));
2038 /* UN-Stop CPUn TSOSCs */
2039 for (cpu = 0; cpu <= TSENSE_CPU3; cpu++) {
2040 r = soctherm_readl(TS_TSENSE_REG_OFFSET
2041 (TS_CPU0_CONFIG0, cpu));
2042 r = REG_SET(r, TS_CPU0_CONFIG0_STOP, 0);
2043 soctherm_writel(r, TS_TSENSE_REG_OFFSET
2044 (TS_CPU0_CONFIG0, cpu));
2047 /* Program hotspot offsets per config */
2048 r = soctherm_readl(TS_HOTSPOT_OFF);
2049 r = REG_SET(r, TS_HOTSPOT_OFF_CPU,
2050 plat_data.therm[THERM_CPU].hotspot_offset / 1000);
2052 soctherm_writel(r, TS_HOTSPOT_OFF);
2056 static int soctherm_init_platform_data(void)
2058 struct soctherm_therm *therm;
2059 struct soctherm_sensor *s;
2060 struct soctherm_sensor sensor_defaults;
2063 long gsh = MAX_HIGH_TEMP;
2066 if (tegra_chip_id == TEGRA_CHIPID_TEGRA11)
2067 sensor_defaults = default_t11x_sensor_params;
2068 else if (tegra_chip_id == TEGRA_CHIPID_TEGRA14)
2069 sensor_defaults = default_t14x_sensor_params;
2070 else if (tegra_chip_id == TEGRA_CHIPID_TEGRA12)
2071 sensor_defaults = default_t12x_sensor_params;
2075 /* initialize default values for unspecified params */
2076 for (i = 0; i < TSENSE_SIZE; i++) {
2077 therm = &plat_data.therm[tsensor2therm_map[i]];
2078 s = &plat_data.sensor_data[i];
2079 s->sensor_enable = s->zone_enable;
2080 s->sensor_enable = s->sensor_enable ?: therm->zone_enable;
2081 s->tall = s->tall ?: sensor_defaults.tall;
2082 s->tiddq = s->tiddq ?: sensor_defaults.tiddq;
2083 s->ten_count = s->ten_count ?: sensor_defaults.ten_count;
2084 s->tsample = s->tsample ?: sensor_defaults.tsample;
2085 s->tsamp_ATE = s->tsamp_ATE ?: sensor_defaults.tsamp_ATE;
2086 s->pdiv = s->pdiv ?: sensor_defaults.pdiv;
2087 s->pdiv_ATE = s->pdiv_ATE ?: sensor_defaults.pdiv_ATE;
2091 r = soctherm_readl(TS_PDIV);
2092 r = REG_SET(r, TS_PDIV_CPU, plat_data.sensor_data[TSENSE_CPU0].pdiv);
2093 r = REG_SET(r, TS_PDIV_GPU, plat_data.sensor_data[TSENSE_GPU].pdiv);
2094 r = REG_SET(r, TS_PDIV_MEM, plat_data.sensor_data[TSENSE_MEM0].pdiv);
2095 r = REG_SET(r, TS_PDIV_PLLX, plat_data.sensor_data[TSENSE_PLLX].pdiv);
2096 soctherm_writel(r, TS_PDIV);
2098 /* Thermal Sensing programming */
2099 if (soctherm_fuse_read_calib_base() < 0)
2101 for (i = 0; i < TSENSE_SIZE; i++) {
2102 if (plat_data.sensor_data[i].sensor_enable) {
2103 soctherm_tsense_program(i, &plat_data.sensor_data[i]);
2104 if (soctherm_fuse_read_tsensor(i) < 0)
2109 soctherm_adjust_cpu_zone();
2111 /* Sanitize therm trips */
2112 for (i = 0; i < THERM_SIZE; i++) {
2113 therm = &plat_data.therm[i];
2114 if (!therm->zone_enable)
2117 for (j = 0; j < therm->num_trips; j++) {
2118 rem = therm->trips[j].trip_temp %
2119 LOWER_PRECISION_FOR_CONV(1000);
2122 "soctherm: zone%d/trip_point%d %ld mC rounded down\n",
2123 i, j, therm->trips[j].trip_temp);
2124 therm->trips[j].trip_temp -= rem;
2129 /* Program hotspot offsets per THERM */
2130 r = REG_SET(0, TS_HOTSPOT_OFF_CPU,
2131 plat_data.therm[THERM_CPU].hotspot_offset / 1000);
2132 r = REG_SET(r, TS_HOTSPOT_OFF_GPU,
2133 plat_data.therm[THERM_GPU].hotspot_offset / 1000);
2134 r = REG_SET(r, TS_HOTSPOT_OFF_MEM,
2135 plat_data.therm[THERM_MEM].hotspot_offset / 1000);
2136 soctherm_writel(r, TS_HOTSPOT_OFF);
2138 /* Sanitize HW throttle priority */
2139 for (i = 0; i < THROTTLE_SIZE; i++)
2140 if (!plat_data.throttle[i].priority)
2141 plat_data.throttle[i].priority = 0xE + i;
2142 if (plat_data.throttle[THROTTLE_HEAVY].priority <
2143 plat_data.throttle[THROTTLE_LIGHT].priority)
2144 pr_err("soctherm: ERROR: Priority of HEAVY less than LIGHT\n");
2146 /* Thermal HW throttle programming */
2147 for (i = 0; i < THROTTLE_SIZE; i++) {
2148 /* Setup PSKIP parameters */
2149 tegra11_soctherm_throttle_program(i);
2151 /* Setup throttle thresholds per THERM */
2152 for (j = 0; j < THERM_SIZE; j++) {
2153 /* Check if PSKIP params are enabled */
2154 if ((therm2dev[j] == -1) ||
2155 (!plat_data.throttle[i].devs[therm2dev[j]].enable))
2158 therm = &plat_data.therm[j];
2159 for (k = 0; k < therm->num_trips; k++)
2160 if ((therm->trips[k].trip_type ==
2161 THERMAL_TRIP_HOT) &&
2162 strnstr(therm->trips[k].cdev_type,
2163 i == THROTTLE_HEAVY ? "heavy" :
2164 "light", THERMAL_NAME_LENGTH))
2166 if (k < therm->num_trips && i <= THROTTLE_HEAVY)
2167 prog_hw_threshold(&therm->trips[k], j, i);
2171 /* initialize stats collection */
2172 r = STATS_CTL_CLR_DN | STATS_CTL_EN_DN |
2173 STATS_CTL_CLR_UP | STATS_CTL_EN_UP;
2174 soctherm_writel(r, STATS_CTL);
2175 soctherm_writel(OC_STATS_CTL_EN_ALL, OC_STATS_CTL);
2177 /* Enable PMC to shutdown */
2178 soctherm_therm_trip_init(plat_data.tshut_pmu_trip_data);
2180 r = clk_reset_readl(CAR_SUPER_CCLKG_DIVIDER);
2181 r = REG_SET(r, CDIVG_USE_THERM_CONTROLS, 1);
2182 clk_reset_writel(r, CAR_SUPER_CCLKG_DIVIDER);
2185 for (i = 0; i < THERM_SIZE; i++) {
2186 therm = &plat_data.therm[i];
2187 if (!therm->zone_enable)
2190 for (j = 0; j < therm->num_trips; j++) {
2191 if (therm->trips[j].trip_type != THERMAL_TRIP_CRITICAL)
2193 if (i == THERM_GPU) {
2194 gsh = therm->trips[j].trip_temp;
2195 } else if ((i == THERM_MEM) &&
2196 (gsh != MAX_HIGH_TEMP) &&
2197 (therm->trips[j].trip_temp != gsh)) {
2198 pr_warn("soctherm: Force TRIP temp: MEM = GPU");
2199 therm->trips[j].trip_temp = gsh;
2201 prog_hw_shutdown(&therm->trips[j], i);
2208 static void soctherm_suspend_locked(void)
2210 if (!soctherm_suspended) {
2211 soctherm_writel((u32)-1, TH_INTR_DISABLE);
2212 soctherm_writel((u32)-1, OC_INTR_DISABLE);
2213 disable_irq(INT_THERMAL);
2214 disable_irq(INT_EDP);
2215 soctherm_init_platform_done = false;
2216 soctherm_suspended = true;
2217 /* soctherm_clk_enable(false);*/
2221 static int soctherm_suspend(void)
2223 mutex_lock(&soctherm_suspend_resume_lock);
2224 soctherm_suspend_locked();
2225 mutex_unlock(&soctherm_suspend_resume_lock);
2229 static void soctherm_resume_locked(void)
2231 if (soctherm_suspended) {
2232 /* soctherm_clk_enable(true);*/
2233 soctherm_suspended = false;
2234 soctherm_init_platform_data();
2235 soctherm_init_platform_done = true;
2237 enable_irq(INT_THERMAL);
2238 enable_irq(INT_EDP);
2242 static int soctherm_resume(void)
2244 mutex_lock(&soctherm_suspend_resume_lock);
2245 soctherm_resume_locked();
2246 mutex_unlock(&soctherm_suspend_resume_lock);
2250 static int soctherm_sync(void)
2252 mutex_lock(&soctherm_suspend_resume_lock);
2254 if (soctherm_suspended) {
2255 soctherm_resume_locked();
2256 soctherm_suspend_locked();
2261 mutex_unlock(&soctherm_suspend_resume_lock);
2264 late_initcall_sync(soctherm_sync);
2266 static int soctherm_pm_notify(struct notifier_block *nb,
2267 unsigned long event, void *data)
2270 case PM_SUSPEND_PREPARE:
2273 case PM_POST_SUSPEND:
2281 static struct notifier_block soctherm_nb = {
2282 .notifier_call = soctherm_pm_notify,
2285 static void soctherm_oc_irq_lock(struct irq_data *data)
2287 struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
2289 mutex_lock(&d->irq_lock);
2291 static void soctherm_oc_irq_sync_unlock(struct irq_data *data)
2293 struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
2295 mutex_unlock(&d->irq_lock);
2297 static void soctherm_oc_irq_enable(struct irq_data *data)
2299 struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
2301 d->irq_enable |= BIT(data->hwirq);
2304 static void soctherm_oc_irq_disable(struct irq_data *data)
2306 struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
2308 d->irq_enable &= ~BIT(data->hwirq);
2311 static int soctherm_oc_irq_set_type(struct irq_data *data, unsigned int type)
2316 static int soctherm_oc_irq_set_wake(struct irq_data *data, unsigned int on)
2321 gpio = soctherm_ocx_to_wake_gpio[data->hwirq];
2322 if (!gpio_is_valid(gpio)) {
2323 pr_err("No wakeup supported for irq %lu\n", data->hwirq);
2327 gpio_irq = gpio_to_irq(gpio);
2329 pr_err("No gpio_to_irq for gpio %d\n", gpio);
2333 irq_set_irq_wake(gpio_irq, on);
2337 static int soctherm_oc_irq_map(struct irq_domain *h, unsigned int virq,
2340 struct soctherm_oc_irq_chip_data *data = h->host_data;
2342 irq_set_chip_data(virq, data);
2343 irq_set_chip(virq, &data->irq_chip);
2344 irq_set_nested_thread(virq, 1);
2345 set_irq_flags(virq, IRQF_VALID);
2349 static struct irq_domain_ops soctherm_oc_domain_ops = {
2350 .map = soctherm_oc_irq_map,
2351 .xlate = irq_domain_xlate_twocell,
2354 static int tegra11_soctherem_oc_int_init(int irq_base, int num_irqs)
2356 if (irq_base <= 0 || !num_irqs) {
2357 pr_info("%s(): OC interrupts are not enabled\n", __func__);
2361 mutex_init(&soc_irq_cdata.irq_lock);
2362 soc_irq_cdata.irq_enable = 0;
2364 soc_irq_cdata.irq_chip.name = "sco_therm_oc";
2365 soc_irq_cdata.irq_chip.irq_bus_lock = soctherm_oc_irq_lock,
2366 soc_irq_cdata.irq_chip.irq_bus_sync_unlock = soctherm_oc_irq_sync_unlock,
2367 soc_irq_cdata.irq_chip.irq_disable = soctherm_oc_irq_disable,
2368 soc_irq_cdata.irq_chip.irq_enable = soctherm_oc_irq_enable,
2369 soc_irq_cdata.irq_chip.irq_set_type = soctherm_oc_irq_set_type,
2370 soc_irq_cdata.irq_chip.irq_set_wake = soctherm_oc_irq_set_wake,
2372 irq_base = irq_alloc_descs(irq_base, 0, num_irqs, 0);
2374 pr_err("%s: Failed to allocate IRQs: %d\n", __func__, irq_base);
2378 soc_irq_cdata.domain = irq_domain_add_legacy(NULL, num_irqs,
2379 irq_base, 0, &soctherm_oc_domain_ops, &soc_irq_cdata);
2380 if (!soc_irq_cdata.domain) {
2381 pr_err("%s: Failed to create IRQ domain\n", __func__);
2384 pr_info("%s(): OC interrupts enabled successful\n", __func__);
2388 int __init tegra11_soctherm_init(struct soctherm_platform_data *data)
2392 tegra_chip_id = tegra_get_chip_id();
2393 if (!(tegra_chip_id == TEGRA_CHIPID_TEGRA11 ||
2394 tegra_chip_id == TEGRA_CHIPID_TEGRA14 ||
2395 tegra_chip_id == TEGRA_CHIPID_TEGRA12)) {
2396 pr_err("%s: Unknown chip_id %d", __func__, tegra_chip_id);
2400 register_pm_notifier(&soctherm_nb);
2406 if (soctherm_clk_init() < 0)
2409 if (soctherm_clk_enable(true) < 0)
2412 if (soctherm_init_platform_data() < 0)
2415 soctherm_init_platform_done = true;
2417 ret = tegra11_soctherem_oc_int_init(data->oc_irq_base,
2420 pr_err("soctherem_oc_int_init failed: %d\n", ret);
2424 if (request_threaded_irq(INT_THERMAL, soctherm_thermal_isr,
2425 soctherm_thermal_thread_func, IRQF_ONESHOT,
2426 "soctherm_thermal", NULL) < 0)
2429 if (request_threaded_irq(INT_EDP, soctherm_edp_isr,
2430 soctherm_edp_thread_func, IRQF_ONESHOT,
2431 "soctherm_edp", NULL) < 0)
2437 void tegra_soctherm_adjust_cpu_zone(bool high_voltage_range)
2439 if (soctherm_high_voltage_range != high_voltage_range) {
2440 soctherm_high_voltage_range = high_voltage_range;
2441 soctherm_adjust_cpu_zone();
2445 #ifdef CONFIG_DEBUG_FS
2447 static int regs_show(struct seq_file *s, void *data)
2451 int tcpu[TSENSE_SIZE];
2454 if (soctherm_suspended) {
2455 seq_printf(s, "SOC_THERM is SUSPENDED\n");
2459 seq_printf(s, "-----TSENSE (precision %s convert %s)-----\n",
2460 PRECISION_TO_STR(), read_hw_temp ? "HW" : "SW");
2461 for (i = 0; i < TSENSE_SIZE; i++) {
2462 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG1, i));
2463 state = REG_GET(r, TS_CPU0_CONFIG1_EN);
2467 seq_printf(s, "%s: ", sensor_names[i]);
2469 seq_printf(s, "En(%d) ", state);
2470 state = REG_GET(r, TS_CPU0_CONFIG1_TIDDQ);
2471 seq_printf(s, "tiddq(%d) ", state);
2472 state = REG_GET(r, TS_CPU0_CONFIG1_TEN_COUNT);
2473 seq_printf(s, "ten_count(%d) ", state);
2474 state = REG_GET(r, TS_CPU0_CONFIG1_TSAMPLE);
2475 seq_printf(s, "tsample(%d) ", state + 1);
2477 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_STATUS1, i));
2478 state = REG_GET(r, TS_CPU0_STATUS1_TEMP_VALID);
2479 seq_printf(s, "Temp(%d/", state);
2480 state = REG_GET(r, TS_CPU0_STATUS1_TEMP);
2481 seq_printf(s, "%d) ", tcpu[i] = temp_translate(state));
2483 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_STATUS0, i));
2484 state = REG_GET(r, TS_CPU0_STATUS0_VALID);
2485 seq_printf(s, "Capture(%d/", state);
2486 state = REG_GET(r, TS_CPU0_STATUS0_CAPTURE);
2487 seq_printf(s, "%d) (Converted-temp(%ld) ", state,
2488 temp_convert(state, sensor2therm_a[i],
2489 sensor2therm_b[i]));
2491 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG0, i));
2492 state = REG_GET(r, TS_CPU0_CONFIG0_TALL);
2493 seq_printf(s, "Tall(%d) ", state);
2494 state = REG_GET(r, TS_CPU0_CONFIG0_TCALC_OVER);
2495 seq_printf(s, "Over(%d/", state);
2496 state = REG_GET(r, TS_CPU0_CONFIG0_OVER);
2497 seq_printf(s, "%d/", state);
2498 state = REG_GET(r, TS_CPU0_CONFIG0_CPTR_OVER);
2499 seq_printf(s, "%d) ", state);
2501 r = soctherm_readl(TS_TSENSE_REG_OFFSET(TS_CPU0_CONFIG2, i));
2502 state = REG_GET(r, TS_CPU0_CONFIG2_THERM_A);
2503 seq_printf(s, "Therm_A/B(%d/", state);
2504 state = REG_GET(r, TS_CPU0_CONFIG2_THERM_B);
2505 seq_printf(s, "%d)\n", (s16)state);
2508 r = soctherm_readl(TS_PDIV);
2509 seq_printf(s, "PDIV: 0x%x\n", r);
2511 seq_printf(s, "\n");
2512 seq_printf(s, "-----SOC_THERM-----\n");
2514 r = soctherm_readl(TS_TEMP1);
2515 state = REG_GET(r, TS_TEMP1_CPU_TEMP);
2516 seq_printf(s, "Temperatures: CPU(%ld) ", temp_translate(state));
2517 state = REG_GET(r, TS_TEMP1_GPU_TEMP);
2518 seq_printf(s, " GPU(%ld) ", temp_translate(state));
2519 r = soctherm_readl(TS_TEMP2);
2520 state = REG_GET(r, TS_TEMP2_PLLX_TEMP);
2521 seq_printf(s, " PLLX(%ld) ", temp_translate(state));
2522 state = REG_GET(r, TS_TEMP2_MEM_TEMP);
2523 seq_printf(s, " MEM(%ld)\n", temp_translate(state));
2525 for (i = 0; i < THERM_SIZE; i++) {
2526 seq_printf(s, "%s:\n", therm_names[i]);
2527 for (level = 0; level < 4; level++) {
2528 r = soctherm_readl(TS_THERM_REG_OFFSET(CTL_LVL0_CPU0,
2530 state = REG_GET(r, CTL_LVL0_CPU0_UP_THRESH);
2531 seq_printf(s, " %d: Up/Dn(%d/", level,
2532 LOWER_PRECISION_FOR_CONV(state));
2533 state = REG_GET(r, CTL_LVL0_CPU0_DN_THRESH);
2534 seq_printf(s, "%d) ", LOWER_PRECISION_FOR_CONV(state));
2535 state = REG_GET(r, CTL_LVL0_CPU0_EN);
2536 seq_printf(s, "En(%d) ", state);
2538 state = REG_GET(r, CTL_LVL0_CPU0_CPU_THROT);
2539 seq_printf(s, "CPU Throt");
2540 seq_printf(s, "(%s) ", state ?
2541 state == CTL_LVL0_CPU0_CPU_THROT_LIGHT ? "L" :
2542 state == CTL_LVL0_CPU0_CPU_THROT_HEAVY ? "H" :
2545 state = REG_GET(r, CTL_LVL0_CPU0_GPU_THROT);
2546 seq_printf(s, "GPU Throt");
2547 seq_printf(s, "(%s) ", state ?
2548 state == CTL_LVL0_CPU0_GPU_THROT_LIGHT ? "L" :
2549 state == CTL_LVL0_CPU0_GPU_THROT_HEAVY ? "H" :
2552 state = REG_GET(r, CTL_LVL0_CPU0_STATUS);
2553 seq_printf(s, "Status(%s)\n",
2556 state == 2 ? "??" : "HI");
2560 r = soctherm_readl(STATS_CTL);
2561 seq_printf(s, "STATS: Up(%s) Dn(%s)\n",
2562 r & STATS_CTL_EN_UP ? "En" : "--",
2563 r & STATS_CTL_EN_DN ? "En" : "--");
2564 for (level = 0; level < 4; level++) {
2565 r = soctherm_readl(TS_TSENSE_REG_OFFSET(UP_STATS_L0, level));
2566 seq_printf(s, " Level_%d Up(%d) ", level, r);
2567 r = soctherm_readl(TS_TSENSE_REG_OFFSET(DN_STATS_L0, level));
2568 seq_printf(s, "Dn(%d)\n", r);
2571 r = soctherm_readl(THERMTRIP);
2572 state = REG_GET(r, THERMTRIP_ANY_EN);
2573 seq_printf(s, "ThermTRIP ANY En(%d)\n", state);
2575 state = REG_GET(r, THERMTRIP_CPU_EN);
2576 seq_printf(s, " CPU En(%d) ", state);
2577 state = REG_GET(r, THERMTRIP_CPU_THRESH);
2578 seq_printf(s, "Thresh(%d)\n", LOWER_PRECISION_FOR_CONV(state));
2580 state = REG_GET(r, THERMTRIP_GPU_EN);
2581 seq_printf(s, " GPU En(%d) ", state);
2582 state = REG_GET(r, THERMTRIP_GPUMEM_THRESH);
2583 seq_printf(s, "Thresh(%d)\n", LOWER_PRECISION_FOR_CONV(state));
2585 state = REG_GET(r, THERMTRIP_MEM_EN);
2586 seq_printf(s, " MEM En(%d) ", state);
2587 state = REG_GET(r, THERMTRIP_GPUMEM_THRESH);
2588 seq_printf(s, "Thresh(%d)\n", LOWER_PRECISION_FOR_CONV(state));
2590 state = REG_GET(r, THERMTRIP_TSENSE_EN);
2591 seq_printf(s, " PLLX En(%d) ", state);
2592 state = REG_GET(r, THERMTRIP_TSENSE_THRESH);
2593 seq_printf(s, "Thresh(%d)\n", LOWER_PRECISION_FOR_CONV(state));
2595 r = soctherm_readl(THROT_GLOBAL_CFG);
2596 seq_printf(s, "GLOBAL THROTTLE CONFIG: 0x%08x\n", r);
2598 seq_printf(s, "---------------------------------------------------\n");
2599 r = soctherm_readl(THROT_STATUS);
2600 state = REG_GET(r, THROT_STATUS_BREACH);
2601 seq_printf(s, "THROT STATUS: breach(%d) ", state);
2602 state = REG_GET(r, THROT_STATUS_STATE);
2603 seq_printf(s, "state(%d) ", state);
2604 state = REG_GET(r, THROT_STATUS_ENABLED);
2605 seq_printf(s, "enabled(%d)\n", state);
2607 r = soctherm_readl(CPU_PSKIP_STATUS);
2608 state = REG_GET(r, CPU_PSKIP_STATUS_M);
2609 seq_printf(s, "%s PSKIP STATUS: M(%d) ",
2610 throt_dev_names[0], state);
2612 state = REG_GET(r, CPU_PSKIP_STATUS_N);
2613 seq_printf(s, "N(%d) ", state);
2614 state = REG_GET(r, CPU_PSKIP_STATUS_ENABLED);
2615 seq_printf(s, "enabled(%d)\n", state);
2617 r = soctherm_readl(CPU_PSKIP_STATUS + 4);
2618 if (tegra_chip_id == TEGRA_CHIPID_TEGRA12) {
2619 state = REG_GET(r, CPU_PSKIP_STATUS_ENABLED);
2620 seq_printf(s, "%s PSKIP STATUS: ",
2621 throt_dev_names[1]);
2622 seq_printf(s, "enabled(%d)\n", state);
2624 state = REG_GET(r, CPU_PSKIP_STATUS_M);
2625 seq_printf(s, "%s PSKIP STATUS: M(%d) ",
2626 throt_dev_names[1], state);
2627 state = REG_GET(r, CPU_PSKIP_STATUS_N);
2628 seq_printf(s, "N(%d) ", state);
2629 state = REG_GET(r, CPU_PSKIP_STATUS_ENABLED);
2630 seq_printf(s, "enabled(%d)\n", state);
2633 seq_printf(s, "---------------------------------------------------\n");
2634 seq_printf(s, "THROTTLE control and PSKIP configuration:\n");
2635 seq_printf(s, "%5s %3s %2s %8s %7s %8s %4s %4s %5s ",
2636 "throt", "dev", "en", "dividend", "divisor", "duration",
2637 "step", "prio", "delay");
2638 seq_printf(s, "%2s %2s %2s %2s %2s %2s ",
2639 "LL", "HW", "PG", "MD", "01", "EN");
2640 seq_printf(s, "%8s %8s %8s %8s %8s\n",
2641 "thresh", "period", "count", "filter", "stats");
2642 for (i = 0; i < THROTTLE_SIZE; i++) {
2643 for (j = 0; j < THROTTLE_DEV_SIZE; j++) {
2644 r = soctherm_readl(THROT_PSKIP_CTRL(i, j));
2645 state = REG_GET(r, THROT_PSKIP_CTRL_ENABLE);
2646 seq_printf(s, "%5s %3s %2d ",
2647 j ? "" : throt_names[i],
2648 throt_dev_names[j], state);
2650 if (j == THROTTLE_DEV_GPU &&
2651 tegra_chip_id == TEGRA_CHIPID_TEGRA12) {
2653 THROT_PSKIP_CTRL_THROT_DEPTH);
2654 seq_printf(s, "throt depth: %d ", state);
2656 state = REG_GET(r, THROT_PSKIP_CTRL_DIVIDEND);
2657 seq_printf(s, "%8d ", state);
2658 state = REG_GET(r, THROT_PSKIP_CTRL_DIVISOR);
2659 seq_printf(s, "%7d ", state);
2660 r = soctherm_readl(THROT_PSKIP_RAMP(i, j));
2661 state = REG_GET(r, THROT_PSKIP_RAMP_DURATION);
2662 seq_printf(s, "%8d ", state);
2663 state = REG_GET(r, THROT_PSKIP_RAMP_STEP);
2664 seq_printf(s, "%4d ", state);
2668 seq_printf(s, "\n");
2672 r = soctherm_readl(THROT_PRIORITY_CTRL(i));
2673 state = REG_GET(r, THROT_PRIORITY_LITE_PRIO);
2674 seq_printf(s, "%4d ", state);
2676 r = soctherm_readl(THROT_DELAY_CTRL(i));
2677 state = REG_GET(r, THROT_DELAY_LITE_DELAY);
2678 seq_printf(s, "%5d ", state);
2680 if (i >= THROTTLE_OC1) {
2681 r = soctherm_readl(ALARM_CFG(i));
2682 state = REG_GET(r, OC1_CFG_LONG_LATENCY);
2683 seq_printf(s, "%2d ", state);
2684 state = REG_GET(r, OC1_CFG_HW_RESTORE);
2685 seq_printf(s, "%2d ", state);
2686 state = REG_GET(r, OC1_CFG_PWR_GOOD_MASK);
2687 seq_printf(s, "%2d ", state);
2688 state = REG_GET(r, OC1_CFG_THROTTLE_MODE);
2689 seq_printf(s, "%2d ", state);
2690 state = REG_GET(r, OC1_CFG_ALARM_POLARITY);
2691 seq_printf(s, "%2d ", state);
2692 state = REG_GET(r, OC1_CFG_EN_THROTTLE);
2693 seq_printf(s, "%2d ", state);
2695 r = soctherm_readl(ALARM_CNT_THRESHOLD(i));
2696 seq_printf(s, "%8d ", r);
2697 r = soctherm_readl(ALARM_THRESHOLD_PERIOD(i));
2698 seq_printf(s, "%8d ", r);
2699 r = soctherm_readl(ALARM_ALARM_COUNT(i));
2700 seq_printf(s, "%8d ", r);
2701 r = soctherm_readl(ALARM_FILTER(i));
2702 seq_printf(s, "%8d ", r);
2703 r = soctherm_readl(ALARM_STATS(i));
2704 seq_printf(s, "%8d ", r);
2706 seq_printf(s, "\n");
2712 static int temp_log_show(struct seq_file *s, void *data)
2718 bool was_suspended = false;
2721 ns = do_div(ts, 1000000000);
2722 seq_printf(s, "%6lu.%06lu", (u_long) ts, ns / 1000);
2724 if (soctherm_suspended) {
2725 mutex_lock(&soctherm_suspend_resume_lock);
2726 soctherm_resume_locked();
2727 was_suspended = true;
2730 for (i = 0; i < TSENSE_SIZE; i++) {
2731 r = soctherm_readl(TS_TSENSE_REG_OFFSET(
2732 TS_CPU0_CONFIG1, i));
2733 state = REG_GET(r, TS_CPU0_CONFIG1_EN);
2737 r = soctherm_readl(TS_TSENSE_REG_OFFSET(
2738 TS_CPU0_STATUS1, i));
2739 if (!REG_GET(r, TS_CPU0_STATUS1_TEMP_VALID)) {
2740 seq_printf(s, "\tINVALID");
2745 state = REG_GET(r, TS_CPU0_STATUS1_TEMP);
2746 seq_printf(s, "\t%ld", temp_translate(state));
2748 r = soctherm_readl(TS_TSENSE_REG_OFFSET(
2749 TS_CPU0_STATUS0, i));
2750 state = REG_GET(r, TS_CPU0_STATUS0_CAPTURE);
2751 seq_printf(s, "\t%ld", temp_convert(state,
2753 sensor2therm_b[i]));
2756 seq_printf(s, "\n");
2758 if (was_suspended) {
2759 soctherm_suspend_locked();
2760 mutex_unlock(&soctherm_suspend_resume_lock);
2765 static int regs_open(struct inode *inode, struct file *file)
2767 return single_open(file, regs_show, inode->i_private);
2770 static const struct file_operations regs_fops = {
2773 .llseek = seq_lseek,
2774 .release = single_release,
2777 static int convert_get(void *data, u64 *val)
2779 *val = !read_hw_temp;
2782 static int convert_set(void *data, u64 val)
2784 read_hw_temp = !val;
2788 static int cputemp_get(void *data, u64 *val)
2791 reg = soctherm_readl(TS_TEMP1);
2792 *val = (reg & 0xffff0000) >> 16;
2796 static int cputemp_set(void *data, u64 temp)
2798 u32 reg_val = temp_translate_rev(temp);
2799 u32 reg_orig = soctherm_readl(TS_TEMP1);
2800 reg_val = (reg_val << 16) | (reg_orig & 0xffff);
2801 soctherm_writel(reg_val, TS_TEMP1);
2805 static int gputemp_get(void *data, u64 *val)
2808 reg = soctherm_readl(TS_TEMP1);
2809 *val = (reg & 0x0000ffff);
2813 static int gputemp_set(void *data, u64 temp)
2815 u32 reg_val = temp_translate_rev(temp);
2816 u32 reg_orig = soctherm_readl(TS_TEMP1);
2817 reg_val = reg_val | (reg_orig & 0xffff0000);
2818 soctherm_writel(reg_val, TS_TEMP1);
2822 static int memtemp_get(void *data, u64 *val)
2825 reg = soctherm_readl(TS_TEMP2);
2826 *val = (reg & 0xffff0000) >> 16;
2830 static int memtemp_set(void *data, u64 temp)
2832 u32 reg_val = temp_translate_rev(temp);
2833 u32 reg_orig = soctherm_readl(TS_TEMP2);
2834 reg_val = (reg_val << 16) | (reg_orig & 0xffff);
2835 soctherm_writel(reg_val, TS_TEMP2);
2839 static int plltemp_get(void *data, u64 *val)
2842 reg = soctherm_readl(TS_TEMP2);
2843 *val = (reg & 0x0000ffff);
2847 static int plltemp_set(void *data, u64 temp)
2849 u32 reg_val = temp_translate_rev(temp);
2850 u32 reg_orig = soctherm_readl(TS_TEMP2);
2851 reg_val = reg_val | (reg_orig & 0xffff0000);
2852 soctherm_writel(reg_val, TS_TEMP2);
2856 static int tempoverride_get(void *data, u64 *val)
2858 *val = soctherm_readl(TS_TEMP_SW_OVERRIDE);
2863 static int tempoverride_set(void *data, u64 val)
2865 soctherm_writel(val, TS_TEMP_SW_OVERRIDE);
2870 DEFINE_SIMPLE_ATTRIBUTE(convert_fops, convert_get, convert_set, "%llu\n");
2872 DEFINE_SIMPLE_ATTRIBUTE(cputemp_fops, cputemp_get, cputemp_set, "%llu\n");
2874 DEFINE_SIMPLE_ATTRIBUTE(gputemp_fops, gputemp_get, gputemp_set, "%llu\n");
2876 DEFINE_SIMPLE_ATTRIBUTE(memtemp_fops, memtemp_get, memtemp_set, "%llu\n");
2878 DEFINE_SIMPLE_ATTRIBUTE(plltemp_fops, plltemp_get, plltemp_set, "%llu\n");
2880 DEFINE_SIMPLE_ATTRIBUTE(tempoverride_fops, tempoverride_get, tempoverride_set, "%llu\n");
2882 static int temp_log_open(struct inode *inode, struct file *file)
2884 return single_open(file, temp_log_show, inode->i_private);
2886 static const struct file_operations temp_log_fops = {
2887 .open = temp_log_open,
2889 .llseek = seq_lseek,
2890 .release = single_release,
2893 static int __init soctherm_debug_init(void)
2895 struct dentry *tegra_soctherm_root;
2897 tegra_soctherm_root = debugfs_create_dir("tegra_soctherm", 0);
2898 debugfs_create_file("regs", 0644, tegra_soctherm_root,
2900 debugfs_create_file("convert", 0644, tegra_soctherm_root,
2901 NULL, &convert_fops);
2902 debugfs_create_file("cputemp", 0644, tegra_soctherm_root,
2903 NULL, &cputemp_fops);
2904 debugfs_create_file("gputemp", 0644, tegra_soctherm_root,
2905 NULL, &gputemp_fops);
2906 debugfs_create_file("memtemp", 0644, tegra_soctherm_root,
2907 NULL, &memtemp_fops);
2908 debugfs_create_file("plltemp", 0644, tegra_soctherm_root,
2909 NULL, &plltemp_fops);
2910 debugfs_create_file("tempoverride", 0644, tegra_soctherm_root,
2911 NULL, &tempoverride_fops);
2912 debugfs_create_file("temp_log", 0644, tegra_soctherm_root,
2913 NULL, &temp_log_fops);
2916 late_initcall(soctherm_debug_init);