1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/debugfs.h>
19#include <linux/bitops.h>
20#include <linux/clk.h>
21#include <linux/delay.h>
22#include <linux/err.h>
23#include <linux/interrupt.h>
24#include <linux/io.h>
25#include <linux/module.h>
26#include <linux/of.h>
27#include <linux/platform_device.h>
28#include <linux/reset.h>
29#include <linux/thermal.h>
30
31#include <dt-bindings/thermal/tegra124-soctherm.h>
32
33#include "../thermal_core.h"
34#include "soctherm.h"
35
36#define SENSOR_CONFIG0 0
37#define SENSOR_CONFIG0_STOP BIT(0)
38#define SENSOR_CONFIG0_CPTR_OVER BIT(2)
39#define SENSOR_CONFIG0_OVER BIT(3)
40#define SENSOR_CONFIG0_TCALC_OVER BIT(4)
41#define SENSOR_CONFIG0_TALL_MASK (0xfffff << 8)
42#define SENSOR_CONFIG0_TALL_SHIFT 8
43
44#define SENSOR_CONFIG1 4
45#define SENSOR_CONFIG1_TSAMPLE_MASK 0x3ff
46#define SENSOR_CONFIG1_TSAMPLE_SHIFT 0
47#define SENSOR_CONFIG1_TIDDQ_EN_MASK (0x3f << 15)
48#define SENSOR_CONFIG1_TIDDQ_EN_SHIFT 15
49#define SENSOR_CONFIG1_TEN_COUNT_MASK (0x3f << 24)
50#define SENSOR_CONFIG1_TEN_COUNT_SHIFT 24
51#define SENSOR_CONFIG1_TEMP_ENABLE BIT(31)
52
53
54
55
56
57
58#define SENSOR_STATUS0 0xc
59#define SENSOR_STATUS0_VALID_MASK BIT(31)
60#define SENSOR_STATUS0_CAPTURE_MASK 0xffff
61
62#define SENSOR_STATUS1 0x10
63#define SENSOR_STATUS1_TEMP_VALID_MASK BIT(31)
64#define SENSOR_STATUS1_TEMP_MASK 0xffff
65
66#define READBACK_VALUE_MASK 0xff00
67#define READBACK_VALUE_SHIFT 8
68#define READBACK_ADD_HALF BIT(7)
69#define READBACK_NEGATE BIT(0)
70
71
72
73
74
75#define THERMCTL_LVL0_CPU0_EN_MASK BIT(8)
76#define THERMCTL_LVL0_CPU0_CPU_THROT_MASK (0x3 << 5)
77#define THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT 0x1
78#define THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY 0x2
79#define THERMCTL_LVL0_CPU0_GPU_THROT_MASK (0x3 << 3)
80#define THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT 0x1
81#define THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY 0x2
82#define THERMCTL_LVL0_CPU0_MEM_THROT_MASK BIT(2)
83#define THERMCTL_LVL0_CPU0_STATUS_MASK 0x3
84
85#define THERMCTL_LVL0_UP_STATS 0x10
86#define THERMCTL_LVL0_DN_STATS 0x14
87
88#define THERMCTL_STATS_CTL 0x94
89#define STATS_CTL_CLR_DN 0x8
90#define STATS_CTL_EN_DN 0x4
91#define STATS_CTL_CLR_UP 0x2
92#define STATS_CTL_EN_UP 0x1
93
94#define THROT_GLOBAL_CFG 0x400
95#define THROT_GLOBAL_ENB_MASK BIT(0)
96
97#define CPU_PSKIP_STATUS 0x418
98#define XPU_PSKIP_STATUS_M_MASK (0xff << 12)
99#define XPU_PSKIP_STATUS_N_MASK (0xff << 4)
100#define XPU_PSKIP_STATUS_SW_OVERRIDE_MASK BIT(1)
101#define XPU_PSKIP_STATUS_ENABLED_MASK BIT(0)
102
103#define THROT_PRIORITY_LOCK 0x424
104#define THROT_PRIORITY_LOCK_PRIORITY_MASK 0xff
105
106#define THROT_STATUS 0x428
107#define THROT_STATUS_BREACH_MASK BIT(12)
108#define THROT_STATUS_STATE_MASK (0xff << 4)
109#define THROT_STATUS_ENABLED_MASK BIT(0)
110
111#define THROT_PSKIP_CTRL_LITE_CPU 0x430
112#define THROT_PSKIP_CTRL_ENABLE_MASK BIT(31)
113#define THROT_PSKIP_CTRL_DIVIDEND_MASK (0xff << 8)
114#define THROT_PSKIP_CTRL_DIVISOR_MASK 0xff
115#define THROT_PSKIP_CTRL_VECT_GPU_MASK (0x7 << 16)
116#define THROT_PSKIP_CTRL_VECT_CPU_MASK (0x7 << 8)
117#define THROT_PSKIP_CTRL_VECT2_CPU_MASK 0x7
118
119#define THROT_VECT_NONE 0x0
120#define THROT_VECT_LOW 0x1
121#define THROT_VECT_MED 0x3
122#define THROT_VECT_HIGH 0x7
123
124#define THROT_PSKIP_RAMP_LITE_CPU 0x434
125#define THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK BIT(31)
126#define THROT_PSKIP_RAMP_DURATION_MASK (0xffff << 8)
127#define THROT_PSKIP_RAMP_STEP_MASK 0xff
128
129#define THROT_PRIORITY_LITE 0x444
130#define THROT_PRIORITY_LITE_PRIO_MASK 0xff
131
132#define THROT_DELAY_LITE 0x448
133#define THROT_DELAY_LITE_DELAY_MASK 0xff
134
135
136#define CAR_SUPER_CCLKG_DIVIDER 0x36c
137#define CDIVG_USE_THERM_CONTROLS_MASK BIT(30)
138
139
140#define CCROC_SUPER_CCLKG_DIVIDER 0x024
141
142#define CCROC_GLOBAL_CFG 0x148
143
144#define CCROC_THROT_PSKIP_RAMP_CPU 0x150
145#define CCROC_THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK BIT(31)
146#define CCROC_THROT_PSKIP_RAMP_DURATION_MASK (0xffff << 8)
147#define CCROC_THROT_PSKIP_RAMP_STEP_MASK 0xff
148
149#define CCROC_THROT_PSKIP_CTRL_CPU 0x154
150#define CCROC_THROT_PSKIP_CTRL_ENB_MASK BIT(31)
151#define CCROC_THROT_PSKIP_CTRL_DIVIDEND_MASK (0xff << 8)
152#define CCROC_THROT_PSKIP_CTRL_DIVISOR_MASK 0xff
153
154
155#define REG_GET_MASK(r, m) (((r) & (m)) >> (ffs(m) - 1))
156
157#define REG_SET_MASK(r, m, v) (((r) & ~(m)) | \
158 (((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1)))
159
160
161#define THROT_DEPTH_DIVIDEND(depth) ((256 * (100 - (depth)) / 100) - 1)
162
163
164#define THROT_OFFSET 0x30
165#define THROT_PSKIP_CTRL(throt, dev) (THROT_PSKIP_CTRL_LITE_CPU + \
166 (THROT_OFFSET * throt) + (8 * dev))
167#define THROT_PSKIP_RAMP(throt, dev) (THROT_PSKIP_RAMP_LITE_CPU + \
168 (THROT_OFFSET * throt) + (8 * dev))
169
170
171#define THROT_PRIORITY_CTRL(throt) (THROT_PRIORITY_LITE + \
172 (THROT_OFFSET * throt))
173#define THROT_DELAY_CTRL(throt) (THROT_DELAY_LITE + \
174 (THROT_OFFSET * throt))
175
176
177#define CCROC_THROT_OFFSET 0x0c
178#define CCROC_THROT_PSKIP_CTRL_CPU_REG(vect) (CCROC_THROT_PSKIP_CTRL_CPU + \
179 (CCROC_THROT_OFFSET * vect))
180#define CCROC_THROT_PSKIP_RAMP_CPU_REG(vect) (CCROC_THROT_PSKIP_RAMP_CPU + \
181 (CCROC_THROT_OFFSET * vect))
182
183
184#define THERMCTL_LVL_REGS_SIZE 0x20
185#define THERMCTL_LVL_REG(rg, lv) ((rg) + ((lv) * THERMCTL_LVL_REGS_SIZE))
186
187static const int min_low_temp = -127000;
188static const int max_high_temp = 127000;
189
190enum soctherm_throttle_id {
191 THROTTLE_LIGHT = 0,
192 THROTTLE_HEAVY,
193 THROTTLE_SIZE,
194};
195
196enum soctherm_throttle_dev_id {
197 THROTTLE_DEV_CPU = 0,
198 THROTTLE_DEV_GPU,
199 THROTTLE_DEV_SIZE,
200};
201
202static const char *const throt_names[] = {
203 [THROTTLE_LIGHT] = "light",
204 [THROTTLE_HEAVY] = "heavy",
205};
206
207struct tegra_soctherm;
208struct tegra_thermctl_zone {
209 void __iomem *reg;
210 struct device *dev;
211 struct tegra_soctherm *ts;
212 struct thermal_zone_device *tz;
213 const struct tegra_tsensor_group *sg;
214};
215
216struct soctherm_throt_cfg {
217 const char *name;
218 unsigned int id;
219 u8 priority;
220 u8 cpu_throt_level;
221 u32 cpu_throt_depth;
222 struct thermal_cooling_device *cdev;
223 bool init;
224};
225
226struct tegra_soctherm {
227 struct reset_control *reset;
228 struct clk *clock_tsensor;
229 struct clk *clock_soctherm;
230 void __iomem *regs;
231 void __iomem *clk_regs;
232 void __iomem *ccroc_regs;
233
234 u32 *calib;
235 struct thermal_zone_device **thermctl_tzs;
236 struct tegra_soctherm_soc *soc;
237
238 struct soctherm_throt_cfg throt_cfgs[THROTTLE_SIZE];
239
240 struct dentry *debugfs_dir;
241};
242
243
244
245
246
247
248
249
250
251static inline void clk_writel(struct tegra_soctherm *ts, u32 value, u32 reg)
252{
253 writel(value, (ts->clk_regs + reg));
254}
255
256
257
258
259
260
261
262
263static inline u32 clk_readl(struct tegra_soctherm *ts, u32 reg)
264{
265 return readl(ts->clk_regs + reg);
266}
267
268
269
270
271
272
273
274
275
276static inline void ccroc_writel(struct tegra_soctherm *ts, u32 value, u32 reg)
277{
278 writel(value, (ts->ccroc_regs + reg));
279}
280
281
282
283
284
285
286
287
288static inline u32 ccroc_readl(struct tegra_soctherm *ts, u32 reg)
289{
290 return readl(ts->ccroc_regs + reg);
291}
292
293static void enable_tsensor(struct tegra_soctherm *tegra, unsigned int i)
294{
295 const struct tegra_tsensor *sensor = &tegra->soc->tsensors[i];
296 void __iomem *base = tegra->regs + sensor->base;
297 unsigned int val;
298
299 val = sensor->config->tall << SENSOR_CONFIG0_TALL_SHIFT;
300 writel(val, base + SENSOR_CONFIG0);
301
302 val = (sensor->config->tsample - 1) << SENSOR_CONFIG1_TSAMPLE_SHIFT;
303 val |= sensor->config->tiddq_en << SENSOR_CONFIG1_TIDDQ_EN_SHIFT;
304 val |= sensor->config->ten_count << SENSOR_CONFIG1_TEN_COUNT_SHIFT;
305 val |= SENSOR_CONFIG1_TEMP_ENABLE;
306 writel(val, base + SENSOR_CONFIG1);
307
308 writel(tegra->calib[i], base + SENSOR_CONFIG2);
309}
310
311
312
313
314
315
316
317
318
319static int translate_temp(u16 val)
320{
321 int t;
322
323 t = ((val & READBACK_VALUE_MASK) >> READBACK_VALUE_SHIFT) * 1000;
324 if (val & READBACK_ADD_HALF)
325 t += 500;
326 if (val & READBACK_NEGATE)
327 t *= -1;
328
329 return t;
330}
331
332static int tegra_thermctl_get_temp(void *data, int *out_temp)
333{
334 struct tegra_thermctl_zone *zone = data;
335 u32 val;
336
337 val = readl(zone->reg);
338 val = REG_GET_MASK(val, zone->sg->sensor_temp_mask);
339 *out_temp = translate_temp(val);
340
341 return 0;
342}
343
344static int
345thermtrip_program(struct device *dev, const struct tegra_tsensor_group *sg,
346 int trip_temp);
347static int
348throttrip_program(struct device *dev, const struct tegra_tsensor_group *sg,
349 struct soctherm_throt_cfg *stc, int trip_temp);
350static struct soctherm_throt_cfg *
351find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name);
352
353static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
354{
355 struct tegra_thermctl_zone *zone = data;
356 struct thermal_zone_device *tz = zone->tz;
357 struct tegra_soctherm *ts = zone->ts;
358 const struct tegra_tsensor_group *sg = zone->sg;
359 struct device *dev = zone->dev;
360 enum thermal_trip_type type;
361 int ret;
362
363 if (!tz)
364 return -EINVAL;
365
366 ret = tz->ops->get_trip_type(tz, trip, &type);
367 if (ret)
368 return ret;
369
370 if (type == THERMAL_TRIP_CRITICAL) {
371 return thermtrip_program(dev, sg, temp);
372 } else if (type == THERMAL_TRIP_HOT) {
373 int i;
374
375 for (i = 0; i < THROTTLE_SIZE; i++) {
376 struct thermal_cooling_device *cdev;
377 struct soctherm_throt_cfg *stc;
378
379 if (!ts->throt_cfgs[i].init)
380 continue;
381
382 cdev = ts->throt_cfgs[i].cdev;
383 if (get_thermal_instance(tz, cdev, trip))
384 stc = find_throttle_cfg_by_name(ts, cdev->type);
385 else
386 continue;
387
388 return throttrip_program(dev, sg, stc, temp);
389 }
390 }
391
392 return 0;
393}
394
395static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
396 .get_temp = tegra_thermctl_get_temp,
397 .set_trip_temp = tegra_thermctl_set_trip_temp,
398};
399
400
401
402
403
404
405
406
407
408
409
410static int enforce_temp_range(struct device *dev, int trip_temp)
411{
412 int temp;
413
414 temp = clamp_val(trip_temp, min_low_temp, max_high_temp);
415 if (temp != trip_temp)
416 dev_info(dev, "soctherm: trip temperature %d forced to %d\n",
417 trip_temp, temp);
418 return temp;
419}
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437static int thermtrip_program(struct device *dev,
438 const struct tegra_tsensor_group *sg,
439 int trip_temp)
440{
441 struct tegra_soctherm *ts = dev_get_drvdata(dev);
442 int temp;
443 u32 r;
444
445 if (!sg || !sg->thermtrip_threshold_mask)
446 return -EINVAL;
447
448 temp = enforce_temp_range(dev, trip_temp) / ts->soc->thresh_grain;
449
450 r = readl(ts->regs + THERMCTL_THERMTRIP_CTL);
451 r = REG_SET_MASK(r, sg->thermtrip_threshold_mask, temp);
452 r = REG_SET_MASK(r, sg->thermtrip_enable_mask, 1);
453 r = REG_SET_MASK(r, sg->thermtrip_any_en_mask, 0);
454 writel(r, ts->regs + THERMCTL_THERMTRIP_CTL);
455
456 return 0;
457}
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476static int throttrip_program(struct device *dev,
477 const struct tegra_tsensor_group *sg,
478 struct soctherm_throt_cfg *stc,
479 int trip_temp)
480{
481 struct tegra_soctherm *ts = dev_get_drvdata(dev);
482 int temp, cpu_throt, gpu_throt;
483 unsigned int throt;
484 u32 r, reg_off;
485
486 if (!dev || !sg || !stc || !stc->init)
487 return -EINVAL;
488
489 temp = enforce_temp_range(dev, trip_temp) / ts->soc->thresh_grain;
490
491
492 throt = stc->id;
493 reg_off = THERMCTL_LVL_REG(sg->thermctl_lvl0_offset, throt + 1);
494
495 if (throt == THROTTLE_LIGHT) {
496 cpu_throt = THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT;
497 gpu_throt = THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT;
498 } else {
499 cpu_throt = THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY;
500 gpu_throt = THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY;
501 if (throt != THROTTLE_HEAVY)
502 dev_warn(dev,
503 "invalid throt id %d - assuming HEAVY",
504 throt);
505 }
506
507 r = readl(ts->regs + reg_off);
508 r = REG_SET_MASK(r, sg->thermctl_lvl0_up_thresh_mask, temp);
509 r = REG_SET_MASK(r, sg->thermctl_lvl0_dn_thresh_mask, temp);
510 r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_CPU_THROT_MASK, cpu_throt);
511 r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_GPU_THROT_MASK, gpu_throt);
512 r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 1);
513 writel(r, ts->regs + reg_off);
514
515 return 0;
516}
517
518static struct soctherm_throt_cfg *
519find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name)
520{
521 unsigned int i;
522
523 for (i = 0; ts->throt_cfgs[i].name; i++)
524 if (!strcmp(ts->throt_cfgs[i].name, name))
525 return &ts->throt_cfgs[i];
526
527 return NULL;
528}
529
530static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp)
531{
532 int ntrips, i, ret;
533 enum thermal_trip_type type;
534
535 ntrips = of_thermal_get_ntrips(tz);
536 if (ntrips <= 0)
537 return -EINVAL;
538
539 for (i = 0; i < ntrips; i++) {
540 ret = tz->ops->get_trip_type(tz, i, &type);
541 if (ret)
542 return -EINVAL;
543 if (type == THERMAL_TRIP_HOT) {
544 ret = tz->ops->get_trip_temp(tz, i, temp);
545 if (!ret)
546 *trip = i;
547
548 return ret;
549 }
550 }
551
552 return -EINVAL;
553}
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576static int tegra_soctherm_set_hwtrips(struct device *dev,
577 const struct tegra_tsensor_group *sg,
578 struct thermal_zone_device *tz)
579{
580 struct tegra_soctherm *ts = dev_get_drvdata(dev);
581 struct soctherm_throt_cfg *stc;
582 int i, trip, temperature;
583 int ret;
584
585 ret = tz->ops->get_crit_temp(tz, &temperature);
586 if (ret) {
587 dev_warn(dev, "thermtrip: %s: missing critical temperature\n",
588 sg->name);
589 goto set_throttle;
590 }
591
592 ret = thermtrip_program(dev, sg, temperature);
593 if (ret) {
594 dev_err(dev, "thermtrip: %s: error during enable\n",
595 sg->name);
596 return ret;
597 }
598
599 dev_info(dev,
600 "thermtrip: will shut down when %s reaches %d mC\n",
601 sg->name, temperature);
602
603set_throttle:
604 ret = get_hot_temp(tz, &trip, &temperature);
605 if (ret) {
606 dev_warn(dev, "throttrip: %s: missing hot temperature\n",
607 sg->name);
608 return 0;
609 }
610
611 for (i = 0; i < THROTTLE_SIZE; i++) {
612 struct thermal_cooling_device *cdev;
613
614 if (!ts->throt_cfgs[i].init)
615 continue;
616
617 cdev = ts->throt_cfgs[i].cdev;
618 if (get_thermal_instance(tz, cdev, trip))
619 stc = find_throttle_cfg_by_name(ts, cdev->type);
620 else
621 continue;
622
623 ret = throttrip_program(dev, sg, stc, temperature);
624 if (ret) {
625 dev_err(dev, "throttrip: %s: error during enable\n",
626 sg->name);
627 return ret;
628 }
629
630 dev_info(dev,
631 "throttrip: will throttle when %s reaches %d mC\n",
632 sg->name, temperature);
633 break;
634 }
635
636 if (i == THROTTLE_SIZE)
637 dev_warn(dev, "throttrip: %s: missing throttle cdev\n",
638 sg->name);
639
640 return 0;
641}
642
643#ifdef CONFIG_DEBUG_FS
644static int regs_show(struct seq_file *s, void *data)
645{
646 struct platform_device *pdev = s->private;
647 struct tegra_soctherm *ts = platform_get_drvdata(pdev);
648 const struct tegra_tsensor *tsensors = ts->soc->tsensors;
649 const struct tegra_tsensor_group **ttgs = ts->soc->ttgs;
650 u32 r, state;
651 int i, level;
652
653 seq_puts(s, "-----TSENSE (convert HW)-----\n");
654
655 for (i = 0; i < ts->soc->num_tsensors; i++) {
656 r = readl(ts->regs + tsensors[i].base + SENSOR_CONFIG1);
657 state = REG_GET_MASK(r, SENSOR_CONFIG1_TEMP_ENABLE);
658
659 seq_printf(s, "%s: ", tsensors[i].name);
660 seq_printf(s, "En(%d) ", state);
661
662 if (!state) {
663 seq_puts(s, "\n");
664 continue;
665 }
666
667 state = REG_GET_MASK(r, SENSOR_CONFIG1_TIDDQ_EN_MASK);
668 seq_printf(s, "tiddq(%d) ", state);
669 state = REG_GET_MASK(r, SENSOR_CONFIG1_TEN_COUNT_MASK);
670 seq_printf(s, "ten_count(%d) ", state);
671 state = REG_GET_MASK(r, SENSOR_CONFIG1_TSAMPLE_MASK);
672 seq_printf(s, "tsample(%d) ", state + 1);
673
674 r = readl(ts->regs + tsensors[i].base + SENSOR_STATUS1);
675 state = REG_GET_MASK(r, SENSOR_STATUS1_TEMP_VALID_MASK);
676 seq_printf(s, "Temp(%d/", state);
677 state = REG_GET_MASK(r, SENSOR_STATUS1_TEMP_MASK);
678 seq_printf(s, "%d) ", translate_temp(state));
679
680 r = readl(ts->regs + tsensors[i].base + SENSOR_STATUS0);
681 state = REG_GET_MASK(r, SENSOR_STATUS0_VALID_MASK);
682 seq_printf(s, "Capture(%d/", state);
683 state = REG_GET_MASK(r, SENSOR_STATUS0_CAPTURE_MASK);
684 seq_printf(s, "%d) ", state);
685
686 r = readl(ts->regs + tsensors[i].base + SENSOR_CONFIG0);
687 state = REG_GET_MASK(r, SENSOR_CONFIG0_STOP);
688 seq_printf(s, "Stop(%d) ", state);
689 state = REG_GET_MASK(r, SENSOR_CONFIG0_TALL_MASK);
690 seq_printf(s, "Tall(%d) ", state);
691 state = REG_GET_MASK(r, SENSOR_CONFIG0_TCALC_OVER);
692 seq_printf(s, "Over(%d/", state);
693 state = REG_GET_MASK(r, SENSOR_CONFIG0_OVER);
694 seq_printf(s, "%d/", state);
695 state = REG_GET_MASK(r, SENSOR_CONFIG0_CPTR_OVER);
696 seq_printf(s, "%d) ", state);
697
698 r = readl(ts->regs + tsensors[i].base + SENSOR_CONFIG2);
699 state = REG_GET_MASK(r, SENSOR_CONFIG2_THERMA_MASK);
700 seq_printf(s, "Therm_A/B(%d/", state);
701 state = REG_GET_MASK(r, SENSOR_CONFIG2_THERMB_MASK);
702 seq_printf(s, "%d)\n", (s16)state);
703 }
704
705 r = readl(ts->regs + SENSOR_PDIV);
706 seq_printf(s, "PDIV: 0x%x\n", r);
707
708 r = readl(ts->regs + SENSOR_HOTSPOT_OFF);
709 seq_printf(s, "HOTSPOT: 0x%x\n", r);
710
711 seq_puts(s, "\n");
712 seq_puts(s, "-----SOC_THERM-----\n");
713
714 r = readl(ts->regs + SENSOR_TEMP1);
715 state = REG_GET_MASK(r, SENSOR_TEMP1_CPU_TEMP_MASK);
716 seq_printf(s, "Temperatures: CPU(%d) ", translate_temp(state));
717 state = REG_GET_MASK(r, SENSOR_TEMP1_GPU_TEMP_MASK);
718 seq_printf(s, " GPU(%d) ", translate_temp(state));
719 r = readl(ts->regs + SENSOR_TEMP2);
720 state = REG_GET_MASK(r, SENSOR_TEMP2_PLLX_TEMP_MASK);
721 seq_printf(s, " PLLX(%d) ", translate_temp(state));
722 state = REG_GET_MASK(r, SENSOR_TEMP2_MEM_TEMP_MASK);
723 seq_printf(s, " MEM(%d)\n", translate_temp(state));
724
725 for (i = 0; i < ts->soc->num_ttgs; i++) {
726 seq_printf(s, "%s:\n", ttgs[i]->name);
727 for (level = 0; level < 4; level++) {
728 s32 v;
729 u32 mask;
730 u16 off = ttgs[i]->thermctl_lvl0_offset;
731
732 r = readl(ts->regs + THERMCTL_LVL_REG(off, level));
733
734 mask = ttgs[i]->thermctl_lvl0_up_thresh_mask;
735 state = REG_GET_MASK(r, mask);
736 v = sign_extend32(state, ts->soc->bptt - 1);
737 v *= ts->soc->thresh_grain;
738 seq_printf(s, " %d: Up/Dn(%d /", level, v);
739
740 mask = ttgs[i]->thermctl_lvl0_dn_thresh_mask;
741 state = REG_GET_MASK(r, mask);
742 v = sign_extend32(state, ts->soc->bptt - 1);
743 v *= ts->soc->thresh_grain;
744 seq_printf(s, "%d ) ", v);
745
746 mask = THERMCTL_LVL0_CPU0_EN_MASK;
747 state = REG_GET_MASK(r, mask);
748 seq_printf(s, "En(%d) ", state);
749
750 mask = THERMCTL_LVL0_CPU0_CPU_THROT_MASK;
751 state = REG_GET_MASK(r, mask);
752 seq_puts(s, "CPU Throt");
753 if (!state)
754 seq_printf(s, "(%s) ", "none");
755 else if (state == THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT)
756 seq_printf(s, "(%s) ", "L");
757 else if (state == THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY)
758 seq_printf(s, "(%s) ", "H");
759 else
760 seq_printf(s, "(%s) ", "H+L");
761
762 mask = THERMCTL_LVL0_CPU0_GPU_THROT_MASK;
763 state = REG_GET_MASK(r, mask);
764 seq_puts(s, "GPU Throt");
765 if (!state)
766 seq_printf(s, "(%s) ", "none");
767 else if (state == THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT)
768 seq_printf(s, "(%s) ", "L");
769 else if (state == THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY)
770 seq_printf(s, "(%s) ", "H");
771 else
772 seq_printf(s, "(%s) ", "H+L");
773
774 mask = THERMCTL_LVL0_CPU0_STATUS_MASK;
775 state = REG_GET_MASK(r, mask);
776 seq_printf(s, "Status(%s)\n",
777 state == 0 ? "LO" :
778 state == 1 ? "In" :
779 state == 2 ? "Res" : "HI");
780 }
781 }
782
783 r = readl(ts->regs + THERMCTL_STATS_CTL);
784 seq_printf(s, "STATS: Up(%s) Dn(%s)\n",
785 r & STATS_CTL_EN_UP ? "En" : "--",
786 r & STATS_CTL_EN_DN ? "En" : "--");
787
788 for (level = 0; level < 4; level++) {
789 u16 off;
790
791 off = THERMCTL_LVL0_UP_STATS;
792 r = readl(ts->regs + THERMCTL_LVL_REG(off, level));
793 seq_printf(s, " Level_%d Up(%d) ", level, r);
794
795 off = THERMCTL_LVL0_DN_STATS;
796 r = readl(ts->regs + THERMCTL_LVL_REG(off, level));
797 seq_printf(s, "Dn(%d)\n", r);
798 }
799
800 r = readl(ts->regs + THERMCTL_THERMTRIP_CTL);
801 state = REG_GET_MASK(r, ttgs[0]->thermtrip_any_en_mask);
802 seq_printf(s, "Thermtrip Any En(%d)\n", state);
803 for (i = 0; i < ts->soc->num_ttgs; i++) {
804 state = REG_GET_MASK(r, ttgs[i]->thermtrip_enable_mask);
805 seq_printf(s, " %s En(%d) ", ttgs[i]->name, state);
806 state = REG_GET_MASK(r, ttgs[i]->thermtrip_threshold_mask);
807 state *= ts->soc->thresh_grain;
808 seq_printf(s, "Thresh(%d)\n", state);
809 }
810
811 r = readl(ts->regs + THROT_GLOBAL_CFG);
812 seq_puts(s, "\n");
813 seq_printf(s, "GLOBAL THROTTLE CONFIG: 0x%08x\n", r);
814
815 seq_puts(s, "---------------------------------------------------\n");
816 r = readl(ts->regs + THROT_STATUS);
817 state = REG_GET_MASK(r, THROT_STATUS_BREACH_MASK);
818 seq_printf(s, "THROT STATUS: breach(%d) ", state);
819 state = REG_GET_MASK(r, THROT_STATUS_STATE_MASK);
820 seq_printf(s, "state(%d) ", state);
821 state = REG_GET_MASK(r, THROT_STATUS_ENABLED_MASK);
822 seq_printf(s, "enabled(%d)\n", state);
823
824 r = readl(ts->regs + CPU_PSKIP_STATUS);
825 if (ts->soc->use_ccroc) {
826 state = REG_GET_MASK(r, XPU_PSKIP_STATUS_ENABLED_MASK);
827 seq_printf(s, "CPU PSKIP STATUS: enabled(%d)\n", state);
828 } else {
829 state = REG_GET_MASK(r, XPU_PSKIP_STATUS_M_MASK);
830 seq_printf(s, "CPU PSKIP STATUS: M(%d) ", state);
831 state = REG_GET_MASK(r, XPU_PSKIP_STATUS_N_MASK);
832 seq_printf(s, "N(%d) ", state);
833 state = REG_GET_MASK(r, XPU_PSKIP_STATUS_ENABLED_MASK);
834 seq_printf(s, "enabled(%d)\n", state);
835 }
836
837 return 0;
838}
839
840static int regs_open(struct inode *inode, struct file *file)
841{
842 return single_open(file, regs_show, inode->i_private);
843}
844
845static const struct file_operations regs_fops = {
846 .open = regs_open,
847 .read = seq_read,
848 .llseek = seq_lseek,
849 .release = single_release,
850};
851
852static void soctherm_debug_init(struct platform_device *pdev)
853{
854 struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
855 struct dentry *root, *file;
856
857 root = debugfs_create_dir("soctherm", NULL);
858 if (!root) {
859 dev_err(&pdev->dev, "failed to create debugfs directory\n");
860 return;
861 }
862
863 tegra->debugfs_dir = root;
864
865 file = debugfs_create_file("reg_contents", 0644, root,
866 pdev, ®s_fops);
867 if (!file) {
868 dev_err(&pdev->dev, "failed to create debugfs file\n");
869 debugfs_remove_recursive(tegra->debugfs_dir);
870 tegra->debugfs_dir = NULL;
871 }
872}
873#else
874static inline void soctherm_debug_init(struct platform_device *pdev) {}
875#endif
876
877static int soctherm_clk_enable(struct platform_device *pdev, bool enable)
878{
879 struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
880 int err;
881
882 if (!tegra->clock_soctherm || !tegra->clock_tsensor)
883 return -EINVAL;
884
885 reset_control_assert(tegra->reset);
886
887 if (enable) {
888 err = clk_prepare_enable(tegra->clock_soctherm);
889 if (err) {
890 reset_control_deassert(tegra->reset);
891 return err;
892 }
893
894 err = clk_prepare_enable(tegra->clock_tsensor);
895 if (err) {
896 clk_disable_unprepare(tegra->clock_soctherm);
897 reset_control_deassert(tegra->reset);
898 return err;
899 }
900 } else {
901 clk_disable_unprepare(tegra->clock_tsensor);
902 clk_disable_unprepare(tegra->clock_soctherm);
903 }
904
905 reset_control_deassert(tegra->reset);
906
907 return 0;
908}
909
910static int throt_get_cdev_max_state(struct thermal_cooling_device *cdev,
911 unsigned long *max_state)
912{
913 *max_state = 1;
914 return 0;
915}
916
917static int throt_get_cdev_cur_state(struct thermal_cooling_device *cdev,
918 unsigned long *cur_state)
919{
920 struct tegra_soctherm *ts = cdev->devdata;
921 u32 r;
922
923 r = readl(ts->regs + THROT_STATUS);
924 if (REG_GET_MASK(r, THROT_STATUS_STATE_MASK))
925 *cur_state = 1;
926 else
927 *cur_state = 0;
928
929 return 0;
930}
931
932static int throt_set_cdev_state(struct thermal_cooling_device *cdev,
933 unsigned long cur_state)
934{
935 return 0;
936}
937
938static struct thermal_cooling_device_ops throt_cooling_ops = {
939 .get_max_state = throt_get_cdev_max_state,
940 .get_cur_state = throt_get_cdev_cur_state,
941 .set_cur_state = throt_set_cdev_state,
942};
943
944
945
946
947
948static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
949{
950 struct device *dev = &pdev->dev;
951 struct tegra_soctherm *ts = dev_get_drvdata(dev);
952 struct device_node *np_stc, *np_stcc;
953 const char *name;
954 u32 val;
955 int i, r;
956
957 for (i = 0; i < THROTTLE_SIZE; i++) {
958 ts->throt_cfgs[i].name = throt_names[i];
959 ts->throt_cfgs[i].id = i;
960 ts->throt_cfgs[i].init = false;
961 }
962
963 np_stc = of_get_child_by_name(dev->of_node, "throttle-cfgs");
964 if (!np_stc) {
965 dev_info(dev,
966 "throttle-cfg: no throttle-cfgs - not enabling\n");
967 return;
968 }
969
970 for_each_child_of_node(np_stc, np_stcc) {
971 struct soctherm_throt_cfg *stc;
972 struct thermal_cooling_device *tcd;
973
974 name = np_stcc->name;
975 stc = find_throttle_cfg_by_name(ts, name);
976 if (!stc) {
977 dev_err(dev,
978 "throttle-cfg: could not find %s\n", name);
979 continue;
980 }
981
982 r = of_property_read_u32(np_stcc, "nvidia,priority", &val);
983 if (r) {
984 dev_info(dev,
985 "throttle-cfg: %s: missing priority\n", name);
986 continue;
987 }
988 stc->priority = val;
989
990 if (ts->soc->use_ccroc) {
991 r = of_property_read_u32(np_stcc,
992 "nvidia,cpu-throt-level",
993 &val);
994 if (r) {
995 dev_info(dev,
996 "throttle-cfg: %s: missing cpu-throt-level\n",
997 name);
998 continue;
999 }
1000 stc->cpu_throt_level = val;
1001 } else {
1002 r = of_property_read_u32(np_stcc,
1003 "nvidia,cpu-throt-percent",
1004 &val);
1005 if (r) {
1006 dev_info(dev,
1007 "throttle-cfg: %s: missing cpu-throt-percent\n",
1008 name);
1009 continue;
1010 }
1011 stc->cpu_throt_depth = val;
1012 }
1013
1014 tcd = thermal_of_cooling_device_register(np_stcc,
1015 (char *)name, ts,
1016 &throt_cooling_ops);
1017 of_node_put(np_stcc);
1018 if (IS_ERR_OR_NULL(tcd)) {
1019 dev_err(dev,
1020 "throttle-cfg: %s: failed to register cooling device\n",
1021 name);
1022 continue;
1023 }
1024
1025 stc->cdev = tcd;
1026 stc->init = true;
1027 }
1028
1029 of_node_put(np_stc);
1030}
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043static void throttlectl_cpu_level_cfg(struct tegra_soctherm *ts, int level)
1044{
1045 u8 depth, dividend;
1046 u32 r;
1047
1048 switch (level) {
1049 case TEGRA_SOCTHERM_THROT_LEVEL_LOW:
1050 depth = 50;
1051 break;
1052 case TEGRA_SOCTHERM_THROT_LEVEL_MED:
1053 depth = 75;
1054 break;
1055 case TEGRA_SOCTHERM_THROT_LEVEL_HIGH:
1056 depth = 80;
1057 break;
1058 case TEGRA_SOCTHERM_THROT_LEVEL_NONE:
1059 return;
1060 default:
1061 return;
1062 }
1063
1064 dividend = THROT_DEPTH_DIVIDEND(depth);
1065
1066
1067 r = ccroc_readl(ts, CCROC_THROT_PSKIP_RAMP_CPU_REG(level));
1068 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_RAMP_DURATION_MASK, 0xff);
1069 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_RAMP_STEP_MASK, 0xf);
1070 ccroc_writel(ts, r, CCROC_THROT_PSKIP_RAMP_CPU_REG(level));
1071
1072 r = ccroc_readl(ts, CCROC_THROT_PSKIP_CTRL_CPU_REG(level));
1073 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_ENB_MASK, 1);
1074 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_DIVIDEND_MASK, dividend);
1075 r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_DIVISOR_MASK, 0xff);
1076 ccroc_writel(ts, r, CCROC_THROT_PSKIP_CTRL_CPU_REG(level));
1077}
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090static void throttlectl_cpu_level_select(struct tegra_soctherm *ts,
1091 enum soctherm_throttle_id throt)
1092{
1093 u32 r, throt_vect;
1094
1095
1096 switch (ts->throt_cfgs[throt].cpu_throt_level) {
1097 case TEGRA_SOCTHERM_THROT_LEVEL_LOW:
1098 throt_vect = THROT_VECT_LOW;
1099 break;
1100 case TEGRA_SOCTHERM_THROT_LEVEL_MED:
1101 throt_vect = THROT_VECT_MED;
1102 break;
1103 case TEGRA_SOCTHERM_THROT_LEVEL_HIGH:
1104 throt_vect = THROT_VECT_HIGH;
1105 break;
1106 default:
1107 throt_vect = THROT_VECT_NONE;
1108 break;
1109 }
1110
1111 r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
1112 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);
1113 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT_CPU_MASK, throt_vect);
1114 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT2_CPU_MASK, throt_vect);
1115 writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
1116
1117
1118 r = REG_SET_MASK(0, THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK, 1);
1119 writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
1120}
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133static void throttlectl_cpu_mn(struct tegra_soctherm *ts,
1134 enum soctherm_throttle_id throt)
1135{
1136 u32 r;
1137 int depth;
1138 u8 dividend;
1139
1140 depth = ts->throt_cfgs[throt].cpu_throt_depth;
1141 dividend = THROT_DEPTH_DIVIDEND(depth);
1142
1143 r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
1144 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);
1145 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_DIVIDEND_MASK, dividend);
1146 r = REG_SET_MASK(r, THROT_PSKIP_CTRL_DIVISOR_MASK, 0xff);
1147 writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
1148
1149 r = readl(ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
1150 r = REG_SET_MASK(r, THROT_PSKIP_RAMP_DURATION_MASK, 0xff);
1151 r = REG_SET_MASK(r, THROT_PSKIP_RAMP_STEP_MASK, 0xf);
1152 writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
1153}
1154
1155
1156
1157
1158
1159
1160
1161
1162static void soctherm_throttle_program(struct tegra_soctherm *ts,
1163 enum soctherm_throttle_id throt)
1164{
1165 u32 r;
1166 struct soctherm_throt_cfg stc = ts->throt_cfgs[throt];
1167
1168 if (!stc.init)
1169 return;
1170
1171
1172 if (ts->soc->use_ccroc)
1173 throttlectl_cpu_level_select(ts, throt);
1174 else
1175 throttlectl_cpu_mn(ts, throt);
1176
1177 r = REG_SET_MASK(0, THROT_PRIORITY_LITE_PRIO_MASK, stc.priority);
1178 writel(r, ts->regs + THROT_PRIORITY_CTRL(throt));
1179
1180 r = REG_SET_MASK(0, THROT_DELAY_LITE_DELAY_MASK, 0);
1181 writel(r, ts->regs + THROT_DELAY_CTRL(throt));
1182
1183 r = readl(ts->regs + THROT_PRIORITY_LOCK);
1184 r = REG_GET_MASK(r, THROT_PRIORITY_LOCK_PRIORITY_MASK);
1185 if (r >= stc.priority)
1186 return;
1187 r = REG_SET_MASK(0, THROT_PRIORITY_LOCK_PRIORITY_MASK,
1188 stc.priority);
1189 writel(r, ts->regs + THROT_PRIORITY_LOCK);
1190}
1191
1192static void tegra_soctherm_throttle(struct device *dev)
1193{
1194 struct tegra_soctherm *ts = dev_get_drvdata(dev);
1195 u32 v;
1196 int i;
1197
1198
1199 if (ts->soc->use_ccroc) {
1200 throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_LOW);
1201 throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_MED);
1202 throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_HIGH);
1203 }
1204
1205
1206 for (i = 0; i < THROTTLE_SIZE; i++)
1207 soctherm_throttle_program(ts, i);
1208
1209 v = REG_SET_MASK(0, THROT_GLOBAL_ENB_MASK, 1);
1210 if (ts->soc->use_ccroc) {
1211 ccroc_writel(ts, v, CCROC_GLOBAL_CFG);
1212
1213 v = ccroc_readl(ts, CCROC_SUPER_CCLKG_DIVIDER);
1214 v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);
1215 ccroc_writel(ts, v, CCROC_SUPER_CCLKG_DIVIDER);
1216 } else {
1217 writel(v, ts->regs + THROT_GLOBAL_CFG);
1218
1219 v = clk_readl(ts, CAR_SUPER_CCLKG_DIVIDER);
1220 v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);
1221 clk_writel(ts, v, CAR_SUPER_CCLKG_DIVIDER);
1222 }
1223
1224
1225 v = STATS_CTL_CLR_DN | STATS_CTL_EN_DN |
1226 STATS_CTL_CLR_UP | STATS_CTL_EN_UP;
1227 writel(v, ts->regs + THERMCTL_STATS_CTL);
1228}
1229
1230static void soctherm_init(struct platform_device *pdev)
1231{
1232 struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
1233 const struct tegra_tsensor_group **ttgs = tegra->soc->ttgs;
1234 int i;
1235 u32 pdiv, hotspot;
1236
1237
1238 for (i = 0; i < tegra->soc->num_tsensors; ++i)
1239 enable_tsensor(tegra, i);
1240
1241
1242 pdiv = readl(tegra->regs + SENSOR_PDIV);
1243 hotspot = readl(tegra->regs + SENSOR_HOTSPOT_OFF);
1244 for (i = 0; i < tegra->soc->num_ttgs; ++i) {
1245 pdiv = REG_SET_MASK(pdiv, ttgs[i]->pdiv_mask,
1246 ttgs[i]->pdiv);
1247
1248 if (ttgs[i]->id == TEGRA124_SOCTHERM_SENSOR_PLLX)
1249 continue;
1250 hotspot = REG_SET_MASK(hotspot,
1251 ttgs[i]->pllx_hotspot_mask,
1252 ttgs[i]->pllx_hotspot_diff);
1253 }
1254 writel(pdiv, tegra->regs + SENSOR_PDIV);
1255 writel(hotspot, tegra->regs + SENSOR_HOTSPOT_OFF);
1256
1257
1258 tegra_soctherm_throttle(&pdev->dev);
1259}
1260
1261static const struct of_device_id tegra_soctherm_of_match[] = {
1262#ifdef CONFIG_ARCH_TEGRA_124_SOC
1263 {
1264 .compatible = "nvidia,tegra124-soctherm",
1265 .data = &tegra124_soctherm,
1266 },
1267#endif
1268#ifdef CONFIG_ARCH_TEGRA_132_SOC
1269 {
1270 .compatible = "nvidia,tegra132-soctherm",
1271 .data = &tegra132_soctherm,
1272 },
1273#endif
1274#ifdef CONFIG_ARCH_TEGRA_210_SOC
1275 {
1276 .compatible = "nvidia,tegra210-soctherm",
1277 .data = &tegra210_soctherm,
1278 },
1279#endif
1280 { },
1281};
1282MODULE_DEVICE_TABLE(of, tegra_soctherm_of_match);
1283
1284static int tegra_soctherm_probe(struct platform_device *pdev)
1285{
1286 const struct of_device_id *match;
1287 struct tegra_soctherm *tegra;
1288 struct thermal_zone_device *z;
1289 struct tsensor_shared_calib shared_calib;
1290 struct resource *res;
1291 struct tegra_soctherm_soc *soc;
1292 unsigned int i;
1293 int err;
1294
1295 match = of_match_node(tegra_soctherm_of_match, pdev->dev.of_node);
1296 if (!match)
1297 return -ENODEV;
1298
1299 soc = (struct tegra_soctherm_soc *)match->data;
1300 if (soc->num_ttgs > TEGRA124_SOCTHERM_SENSOR_NUM)
1301 return -EINVAL;
1302
1303 tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
1304 if (!tegra)
1305 return -ENOMEM;
1306
1307 dev_set_drvdata(&pdev->dev, tegra);
1308
1309 tegra->soc = soc;
1310
1311 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1312 "soctherm-reg");
1313 tegra->regs = devm_ioremap_resource(&pdev->dev, res);
1314 if (IS_ERR(tegra->regs)) {
1315 dev_err(&pdev->dev, "can't get soctherm registers");
1316 return PTR_ERR(tegra->regs);
1317 }
1318
1319 if (!tegra->soc->use_ccroc) {
1320 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1321 "car-reg");
1322 tegra->clk_regs = devm_ioremap_resource(&pdev->dev, res);
1323 if (IS_ERR(tegra->clk_regs)) {
1324 dev_err(&pdev->dev, "can't get car clk registers");
1325 return PTR_ERR(tegra->clk_regs);
1326 }
1327 } else {
1328 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1329 "ccroc-reg");
1330 tegra->ccroc_regs = devm_ioremap_resource(&pdev->dev, res);
1331 if (IS_ERR(tegra->ccroc_regs)) {
1332 dev_err(&pdev->dev, "can't get ccroc registers");
1333 return PTR_ERR(tegra->ccroc_regs);
1334 }
1335 }
1336
1337 tegra->reset = devm_reset_control_get(&pdev->dev, "soctherm");
1338 if (IS_ERR(tegra->reset)) {
1339 dev_err(&pdev->dev, "can't get soctherm reset\n");
1340 return PTR_ERR(tegra->reset);
1341 }
1342
1343 tegra->clock_tsensor = devm_clk_get(&pdev->dev, "tsensor");
1344 if (IS_ERR(tegra->clock_tsensor)) {
1345 dev_err(&pdev->dev, "can't get tsensor clock\n");
1346 return PTR_ERR(tegra->clock_tsensor);
1347 }
1348
1349 tegra->clock_soctherm = devm_clk_get(&pdev->dev, "soctherm");
1350 if (IS_ERR(tegra->clock_soctherm)) {
1351 dev_err(&pdev->dev, "can't get soctherm clock\n");
1352 return PTR_ERR(tegra->clock_soctherm);
1353 }
1354
1355 tegra->calib = devm_kzalloc(&pdev->dev,
1356 sizeof(u32) * soc->num_tsensors,
1357 GFP_KERNEL);
1358 if (!tegra->calib)
1359 return -ENOMEM;
1360
1361
1362 err = tegra_calc_shared_calib(soc->tfuse, &shared_calib);
1363 if (err)
1364 return err;
1365
1366
1367 for (i = 0; i < soc->num_tsensors; ++i) {
1368 err = tegra_calc_tsensor_calib(&soc->tsensors[i],
1369 &shared_calib,
1370 &tegra->calib[i]);
1371 if (err)
1372 return err;
1373 }
1374
1375 tegra->thermctl_tzs = devm_kzalloc(&pdev->dev,
1376 sizeof(*z) * soc->num_ttgs,
1377 GFP_KERNEL);
1378 if (!tegra->thermctl_tzs)
1379 return -ENOMEM;
1380
1381 err = soctherm_clk_enable(pdev, true);
1382 if (err)
1383 return err;
1384
1385 soctherm_init_hw_throt_cdev(pdev);
1386
1387 soctherm_init(pdev);
1388
1389 for (i = 0; i < soc->num_ttgs; ++i) {
1390 struct tegra_thermctl_zone *zone =
1391 devm_kzalloc(&pdev->dev, sizeof(*zone), GFP_KERNEL);
1392 if (!zone) {
1393 err = -ENOMEM;
1394 goto disable_clocks;
1395 }
1396
1397 zone->reg = tegra->regs + soc->ttgs[i]->sensor_temp_offset;
1398 zone->dev = &pdev->dev;
1399 zone->sg = soc->ttgs[i];
1400 zone->ts = tegra;
1401
1402 z = devm_thermal_zone_of_sensor_register(&pdev->dev,
1403 soc->ttgs[i]->id, zone,
1404 &tegra_of_thermal_ops);
1405 if (IS_ERR(z)) {
1406 err = PTR_ERR(z);
1407 dev_err(&pdev->dev, "failed to register sensor: %d\n",
1408 err);
1409 goto disable_clocks;
1410 }
1411
1412 zone->tz = z;
1413 tegra->thermctl_tzs[soc->ttgs[i]->id] = z;
1414
1415
1416 err = tegra_soctherm_set_hwtrips(&pdev->dev, soc->ttgs[i], z);
1417 if (err)
1418 goto disable_clocks;
1419 }
1420
1421 soctherm_debug_init(pdev);
1422
1423 return 0;
1424
1425disable_clocks:
1426 soctherm_clk_enable(pdev, false);
1427
1428 return err;
1429}
1430
1431static int tegra_soctherm_remove(struct platform_device *pdev)
1432{
1433 struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
1434
1435 debugfs_remove_recursive(tegra->debugfs_dir);
1436
1437 soctherm_clk_enable(pdev, false);
1438
1439 return 0;
1440}
1441
1442static int __maybe_unused soctherm_suspend(struct device *dev)
1443{
1444 struct platform_device *pdev = to_platform_device(dev);
1445
1446 soctherm_clk_enable(pdev, false);
1447
1448 return 0;
1449}
1450
1451static int __maybe_unused soctherm_resume(struct device *dev)
1452{
1453 struct platform_device *pdev = to_platform_device(dev);
1454 struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
1455 struct tegra_soctherm_soc *soc = tegra->soc;
1456 int err, i;
1457
1458 err = soctherm_clk_enable(pdev, true);
1459 if (err) {
1460 dev_err(&pdev->dev,
1461 "Resume failed: enable clocks failed\n");
1462 return err;
1463 }
1464
1465 soctherm_init(pdev);
1466
1467 for (i = 0; i < soc->num_ttgs; ++i) {
1468 struct thermal_zone_device *tz;
1469
1470 tz = tegra->thermctl_tzs[soc->ttgs[i]->id];
1471 err = tegra_soctherm_set_hwtrips(dev, soc->ttgs[i], tz);
1472 if (err) {
1473 dev_err(&pdev->dev,
1474 "Resume failed: set hwtrips failed\n");
1475 return err;
1476 }
1477 }
1478
1479 return 0;
1480}
1481
1482static SIMPLE_DEV_PM_OPS(tegra_soctherm_pm, soctherm_suspend, soctherm_resume);
1483
1484static struct platform_driver tegra_soctherm_driver = {
1485 .probe = tegra_soctherm_probe,
1486 .remove = tegra_soctherm_remove,
1487 .driver = {
1488 .name = "tegra_soctherm",
1489 .pm = &tegra_soctherm_pm,
1490 .of_match_table = tegra_soctherm_of_match,
1491 },
1492};
1493module_platform_driver(tegra_soctherm_driver);
1494
1495MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
1496MODULE_DESCRIPTION("NVIDIA Tegra SOCTHERM thermal management driver");
1497MODULE_LICENSE("GPL v2");
1498