2 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
5 * Mikko Perttunen <mperttunen@nvidia.com>
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
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>
25 #include <linux/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/reset.h>
29 #include <linux/thermal.h>
31 #include <dt-bindings/thermal/tegra124-soctherm.h>
35 #define SENSOR_CONFIG0 0
36 #define SENSOR_CONFIG0_STOP BIT(0)
37 #define SENSOR_CONFIG0_CPTR_OVER BIT(2)
38 #define SENSOR_CONFIG0_OVER BIT(3)
39 #define SENSOR_CONFIG0_TCALC_OVER BIT(4)
40 #define SENSOR_CONFIG0_TALL_MASK (0xfffff << 8)
41 #define SENSOR_CONFIG0_TALL_SHIFT 8
43 #define SENSOR_CONFIG1 4
44 #define SENSOR_CONFIG1_TSAMPLE_MASK 0x3ff
45 #define SENSOR_CONFIG1_TSAMPLE_SHIFT 0
46 #define SENSOR_CONFIG1_TIDDQ_EN_MASK (0x3f << 15)
47 #define SENSOR_CONFIG1_TIDDQ_EN_SHIFT 15
48 #define SENSOR_CONFIG1_TEN_COUNT_MASK (0x3f << 24)
49 #define SENSOR_CONFIG1_TEN_COUNT_SHIFT 24
50 #define SENSOR_CONFIG1_TEMP_ENABLE BIT(31)
53 * SENSOR_CONFIG2 is defined in soctherm.h
54 * because, it will be used by tegra_soctherm_fuse.c
57 #define SENSOR_STATUS0 0xc
58 #define SENSOR_STATUS0_VALID_MASK BIT(31)
59 #define SENSOR_STATUS0_CAPTURE_MASK 0xffff
61 #define SENSOR_STATUS1 0x10
62 #define SENSOR_STATUS1_TEMP_VALID_MASK BIT(31)
63 #define SENSOR_STATUS1_TEMP_MASK 0xffff
65 #define READBACK_VALUE_MASK 0xff00
66 #define READBACK_VALUE_SHIFT 8
67 #define READBACK_ADD_HALF BIT(7)
68 #define READBACK_NEGATE BIT(0)
70 /* get val from register(r) mask bits(m) */
71 #define REG_GET_MASK(r, m) (((r) & (m)) >> (ffs(m) - 1))
72 /* set val(v) to mask bits(m) of register(r) */
73 #define REG_SET_MASK(r, m, v) (((r) & ~(m)) | \
74 (((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1)))
76 static const int min_low_temp
= -127000;
77 static const int max_high_temp
= 127000;
79 struct tegra_thermctl_zone
{
82 struct thermal_zone_device
*tz
;
83 const struct tegra_tsensor_group
*sg
;
86 struct tegra_soctherm
{
87 struct reset_control
*reset
;
88 struct clk
*clock_tsensor
;
89 struct clk
*clock_soctherm
;
91 struct thermal_zone_device
**thermctl_tzs
;
94 struct tegra_soctherm_soc
*soc
;
96 struct dentry
*debugfs_dir
;
99 static void enable_tsensor(struct tegra_soctherm
*tegra
, unsigned int i
)
101 const struct tegra_tsensor
*sensor
= &tegra
->soc
->tsensors
[i
];
102 void __iomem
*base
= tegra
->regs
+ sensor
->base
;
105 val
= sensor
->config
->tall
<< SENSOR_CONFIG0_TALL_SHIFT
;
106 writel(val
, base
+ SENSOR_CONFIG0
);
108 val
= (sensor
->config
->tsample
- 1) << SENSOR_CONFIG1_TSAMPLE_SHIFT
;
109 val
|= sensor
->config
->tiddq_en
<< SENSOR_CONFIG1_TIDDQ_EN_SHIFT
;
110 val
|= sensor
->config
->ten_count
<< SENSOR_CONFIG1_TEN_COUNT_SHIFT
;
111 val
|= SENSOR_CONFIG1_TEMP_ENABLE
;
112 writel(val
, base
+ SENSOR_CONFIG1
);
114 writel(tegra
->calib
[i
], base
+ SENSOR_CONFIG2
);
118 * Translate from soctherm readback format to millicelsius.
119 * The soctherm readback format in bits is as follows:
121 * where T's contain the temperature in Celsius,
122 * H denotes an addition of 0.5 Celsius and N denotes negation
123 * of the final value.
125 static int translate_temp(u16 val
)
129 t
= ((val
& READBACK_VALUE_MASK
) >> READBACK_VALUE_SHIFT
) * 1000;
130 if (val
& READBACK_ADD_HALF
)
132 if (val
& READBACK_NEGATE
)
138 static int tegra_thermctl_get_temp(void *data
, int *out_temp
)
140 struct tegra_thermctl_zone
*zone
= data
;
143 val
= readl(zone
->reg
);
144 val
= REG_GET_MASK(val
, zone
->sg
->sensor_temp_mask
);
145 *out_temp
= translate_temp(val
);
151 thermtrip_program(struct device
*dev
, const struct tegra_tsensor_group
*sg
,
154 static int tegra_thermctl_set_trip_temp(void *data
, int trip
, int temp
)
156 struct tegra_thermctl_zone
*zone
= data
;
157 struct thermal_zone_device
*tz
= zone
->tz
;
158 const struct tegra_tsensor_group
*sg
= zone
->sg
;
159 struct device
*dev
= zone
->dev
;
160 enum thermal_trip_type type
;
166 ret
= tz
->ops
->get_trip_type(tz
, trip
, &type
);
170 if (type
!= THERMAL_TRIP_CRITICAL
)
173 return thermtrip_program(dev
, sg
, temp
);
176 static const struct thermal_zone_of_device_ops tegra_of_thermal_ops
= {
177 .get_temp
= tegra_thermctl_get_temp
,
178 .set_trip_temp
= tegra_thermctl_set_trip_temp
,
182 * enforce_temp_range() - check and enforce temperature range [min, max]
183 * @trip_temp: the trip temperature to check
185 * Checks and enforces the permitted temperature range that SOC_THERM
186 * HW can support This is
187 * done while taking care of precision.
189 * Return: The precision adjusted capped temperature in millicelsius.
191 static int enforce_temp_range(struct device
*dev
, int trip_temp
)
195 temp
= clamp_val(trip_temp
, min_low_temp
, max_high_temp
);
196 if (temp
!= trip_temp
)
197 dev_info(dev
, "soctherm: trip temperature %d forced to %d\n",
203 * thermtrip_program() - Configures the hardware to shut down the
204 * system if a given sensor group reaches a given temperature
205 * @dev: ptr to the struct device for the SOC_THERM IP block
206 * @sg: pointer to the sensor group to set the thermtrip temperature for
207 * @trip_temp: the temperature in millicelsius to trigger the thermal trip at
209 * Sets the thermal trip threshold of the given sensor group to be the
210 * @trip_temp. If this threshold is crossed, the hardware will shut
213 * Note that, although @trip_temp is specified in millicelsius, the
214 * hardware is programmed in degrees Celsius.
216 * Return: 0 upon success, or %-EINVAL upon failure.
218 static int thermtrip_program(struct device
*dev
,
219 const struct tegra_tsensor_group
*sg
,
222 struct tegra_soctherm
*ts
= dev_get_drvdata(dev
);
226 if (!sg
|| !sg
->thermtrip_threshold_mask
)
229 temp
= enforce_temp_range(dev
, trip_temp
) / ts
->soc
->thresh_grain
;
231 r
= readl(ts
->regs
+ THERMCTL_THERMTRIP_CTL
);
232 r
= REG_SET_MASK(r
, sg
->thermtrip_threshold_mask
, temp
);
233 r
= REG_SET_MASK(r
, sg
->thermtrip_enable_mask
, 1);
234 r
= REG_SET_MASK(r
, sg
->thermtrip_any_en_mask
, 0);
235 writel(r
, ts
->regs
+ THERMCTL_THERMTRIP_CTL
);
241 * tegra_soctherm_set_hwtrips() - set HW trip point from DT data
242 * @dev: struct device * of the SOC_THERM instance
244 * Configure the SOC_THERM HW trip points, setting "THERMTRIP"
245 * trip points , using "critical" type trip_temp from thermal
247 * After they have been configured, THERMTRIP will take action
248 * when the configured SoC thermal sensor group reaches a
249 * certain temperature.
251 * Return: 0 upon success, or a negative error code on failure.
252 * "Success" does not mean that trips was enabled; it could also
253 * mean that no node was found in DT.
254 * THERMTRIP has been enabled successfully when a message similar to
255 * this one appears on the serial console:
256 * "thermtrip: will shut down when sensor group XXX reaches YYYYYY mC"
258 static int tegra_soctherm_set_hwtrips(struct device
*dev
,
259 const struct tegra_tsensor_group
*sg
,
260 struct thermal_zone_device
*tz
)
265 ret
= tz
->ops
->get_crit_temp(tz
, &temperature
);
267 dev_warn(dev
, "thermtrip: %s: missing critical temperature\n",
272 ret
= thermtrip_program(dev
, sg
, temperature
);
274 dev_err(dev
, "thermtrip: %s: error during enable\n",
280 "thermtrip: will shut down when %s reaches %d mC\n",
281 sg
->name
, temperature
);
286 #ifdef CONFIG_DEBUG_FS
287 static int regs_show(struct seq_file
*s
, void *data
)
289 struct platform_device
*pdev
= s
->private;
290 struct tegra_soctherm
*ts
= platform_get_drvdata(pdev
);
291 const struct tegra_tsensor
*tsensors
= ts
->soc
->tsensors
;
292 const struct tegra_tsensor_group
**ttgs
= ts
->soc
->ttgs
;
296 seq_puts(s
, "-----TSENSE (convert HW)-----\n");
298 for (i
= 0; i
< ts
->soc
->num_tsensors
; i
++) {
299 r
= readl(ts
->regs
+ tsensors
[i
].base
+ SENSOR_CONFIG1
);
300 state
= REG_GET_MASK(r
, SENSOR_CONFIG1_TEMP_ENABLE
);
302 seq_printf(s
, "%s: ", tsensors
[i
].name
);
303 seq_printf(s
, "En(%d) ", state
);
310 state
= REG_GET_MASK(r
, SENSOR_CONFIG1_TIDDQ_EN_MASK
);
311 seq_printf(s
, "tiddq(%d) ", state
);
312 state
= REG_GET_MASK(r
, SENSOR_CONFIG1_TEN_COUNT_MASK
);
313 seq_printf(s
, "ten_count(%d) ", state
);
314 state
= REG_GET_MASK(r
, SENSOR_CONFIG1_TSAMPLE_MASK
);
315 seq_printf(s
, "tsample(%d) ", state
+ 1);
317 r
= readl(ts
->regs
+ tsensors
[i
].base
+ SENSOR_STATUS1
);
318 state
= REG_GET_MASK(r
, SENSOR_STATUS1_TEMP_VALID_MASK
);
319 seq_printf(s
, "Temp(%d/", state
);
320 state
= REG_GET_MASK(r
, SENSOR_STATUS1_TEMP_MASK
);
321 seq_printf(s
, "%d) ", translate_temp(state
));
323 r
= readl(ts
->regs
+ tsensors
[i
].base
+ SENSOR_STATUS0
);
324 state
= REG_GET_MASK(r
, SENSOR_STATUS0_VALID_MASK
);
325 seq_printf(s
, "Capture(%d/", state
);
326 state
= REG_GET_MASK(r
, SENSOR_STATUS0_CAPTURE_MASK
);
327 seq_printf(s
, "%d) ", state
);
329 r
= readl(ts
->regs
+ tsensors
[i
].base
+ SENSOR_CONFIG0
);
330 state
= REG_GET_MASK(r
, SENSOR_CONFIG0_STOP
);
331 seq_printf(s
, "Stop(%d) ", state
);
332 state
= REG_GET_MASK(r
, SENSOR_CONFIG0_TALL_MASK
);
333 seq_printf(s
, "Tall(%d) ", state
);
334 state
= REG_GET_MASK(r
, SENSOR_CONFIG0_TCALC_OVER
);
335 seq_printf(s
, "Over(%d/", state
);
336 state
= REG_GET_MASK(r
, SENSOR_CONFIG0_OVER
);
337 seq_printf(s
, "%d/", state
);
338 state
= REG_GET_MASK(r
, SENSOR_CONFIG0_CPTR_OVER
);
339 seq_printf(s
, "%d) ", state
);
341 r
= readl(ts
->regs
+ tsensors
[i
].base
+ SENSOR_CONFIG2
);
342 state
= REG_GET_MASK(r
, SENSOR_CONFIG2_THERMA_MASK
);
343 seq_printf(s
, "Therm_A/B(%d/", state
);
344 state
= REG_GET_MASK(r
, SENSOR_CONFIG2_THERMB_MASK
);
345 seq_printf(s
, "%d)\n", (s16
)state
);
348 r
= readl(ts
->regs
+ SENSOR_PDIV
);
349 seq_printf(s
, "PDIV: 0x%x\n", r
);
351 r
= readl(ts
->regs
+ SENSOR_HOTSPOT_OFF
);
352 seq_printf(s
, "HOTSPOT: 0x%x\n", r
);
355 seq_puts(s
, "-----SOC_THERM-----\n");
357 r
= readl(ts
->regs
+ SENSOR_TEMP1
);
358 state
= REG_GET_MASK(r
, SENSOR_TEMP1_CPU_TEMP_MASK
);
359 seq_printf(s
, "Temperatures: CPU(%d) ", translate_temp(state
));
360 state
= REG_GET_MASK(r
, SENSOR_TEMP1_GPU_TEMP_MASK
);
361 seq_printf(s
, " GPU(%d) ", translate_temp(state
));
362 r
= readl(ts
->regs
+ SENSOR_TEMP2
);
363 state
= REG_GET_MASK(r
, SENSOR_TEMP2_PLLX_TEMP_MASK
);
364 seq_printf(s
, " PLLX(%d) ", translate_temp(state
));
365 state
= REG_GET_MASK(r
, SENSOR_TEMP2_MEM_TEMP_MASK
);
366 seq_printf(s
, " MEM(%d)\n", translate_temp(state
));
368 r
= readl(ts
->regs
+ THERMCTL_THERMTRIP_CTL
);
369 state
= REG_GET_MASK(r
, ttgs
[0]->thermtrip_any_en_mask
);
370 seq_printf(s
, "Thermtrip Any En(%d)\n", state
);
371 for (i
= 0; i
< ts
->soc
->num_ttgs
; i
++) {
372 state
= REG_GET_MASK(r
, ttgs
[i
]->thermtrip_enable_mask
);
373 seq_printf(s
, " %s En(%d) ", ttgs
[i
]->name
, state
);
374 state
= REG_GET_MASK(r
, ttgs
[i
]->thermtrip_threshold_mask
);
375 state
*= ts
->soc
->thresh_grain
;
376 seq_printf(s
, "Thresh(%d)\n", state
);
382 static int regs_open(struct inode
*inode
, struct file
*file
)
384 return single_open(file
, regs_show
, inode
->i_private
);
387 static const struct file_operations regs_fops
= {
391 .release
= single_release
,
394 static void soctherm_debug_init(struct platform_device
*pdev
)
396 struct tegra_soctherm
*tegra
= platform_get_drvdata(pdev
);
397 struct dentry
*root
, *file
;
399 root
= debugfs_create_dir("soctherm", NULL
);
401 dev_err(&pdev
->dev
, "failed to create debugfs directory\n");
405 tegra
->debugfs_dir
= root
;
407 file
= debugfs_create_file("reg_contents", 0644, root
,
410 dev_err(&pdev
->dev
, "failed to create debugfs file\n");
411 debugfs_remove_recursive(tegra
->debugfs_dir
);
412 tegra
->debugfs_dir
= NULL
;
416 static inline void soctherm_debug_init(struct platform_device
*pdev
) {}
419 static int soctherm_clk_enable(struct platform_device
*pdev
, bool enable
)
421 struct tegra_soctherm
*tegra
= platform_get_drvdata(pdev
);
424 if (!tegra
->clock_soctherm
|| !tegra
->clock_tsensor
)
427 reset_control_assert(tegra
->reset
);
430 err
= clk_prepare_enable(tegra
->clock_soctherm
);
432 reset_control_deassert(tegra
->reset
);
436 err
= clk_prepare_enable(tegra
->clock_tsensor
);
438 clk_disable_unprepare(tegra
->clock_soctherm
);
439 reset_control_deassert(tegra
->reset
);
443 clk_disable_unprepare(tegra
->clock_tsensor
);
444 clk_disable_unprepare(tegra
->clock_soctherm
);
447 reset_control_deassert(tegra
->reset
);
452 static void soctherm_init(struct platform_device
*pdev
)
454 struct tegra_soctherm
*tegra
= platform_get_drvdata(pdev
);
455 const struct tegra_tsensor_group
**ttgs
= tegra
->soc
->ttgs
;
459 /* Initialize raw sensors */
460 for (i
= 0; i
< tegra
->soc
->num_tsensors
; ++i
)
461 enable_tsensor(tegra
, i
);
463 /* program pdiv and hotspot offsets per THERM */
464 pdiv
= readl(tegra
->regs
+ SENSOR_PDIV
);
465 hotspot
= readl(tegra
->regs
+ SENSOR_HOTSPOT_OFF
);
466 for (i
= 0; i
< tegra
->soc
->num_ttgs
; ++i
) {
467 pdiv
= REG_SET_MASK(pdiv
, ttgs
[i
]->pdiv_mask
,
469 /* hotspot offset from PLLX, doesn't need to configure PLLX */
470 if (ttgs
[i
]->id
== TEGRA124_SOCTHERM_SENSOR_PLLX
)
472 hotspot
= REG_SET_MASK(hotspot
,
473 ttgs
[i
]->pllx_hotspot_mask
,
474 ttgs
[i
]->pllx_hotspot_diff
);
476 writel(pdiv
, tegra
->regs
+ SENSOR_PDIV
);
477 writel(hotspot
, tegra
->regs
+ SENSOR_HOTSPOT_OFF
);
480 static const struct of_device_id tegra_soctherm_of_match
[] = {
481 #ifdef CONFIG_ARCH_TEGRA_124_SOC
483 .compatible
= "nvidia,tegra124-soctherm",
484 .data
= &tegra124_soctherm
,
487 #ifdef CONFIG_ARCH_TEGRA_132_SOC
489 .compatible
= "nvidia,tegra132-soctherm",
490 .data
= &tegra132_soctherm
,
493 #ifdef CONFIG_ARCH_TEGRA_210_SOC
495 .compatible
= "nvidia,tegra210-soctherm",
496 .data
= &tegra210_soctherm
,
501 MODULE_DEVICE_TABLE(of
, tegra_soctherm_of_match
);
503 static int tegra_soctherm_probe(struct platform_device
*pdev
)
505 const struct of_device_id
*match
;
506 struct tegra_soctherm
*tegra
;
507 struct thermal_zone_device
*z
;
508 struct tsensor_shared_calib shared_calib
;
509 struct resource
*res
;
510 struct tegra_soctherm_soc
*soc
;
514 match
= of_match_node(tegra_soctherm_of_match
, pdev
->dev
.of_node
);
518 soc
= (struct tegra_soctherm_soc
*)match
->data
;
519 if (soc
->num_ttgs
> TEGRA124_SOCTHERM_SENSOR_NUM
)
522 tegra
= devm_kzalloc(&pdev
->dev
, sizeof(*tegra
), GFP_KERNEL
);
526 dev_set_drvdata(&pdev
->dev
, tegra
);
530 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
531 tegra
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
532 if (IS_ERR(tegra
->regs
))
533 return PTR_ERR(tegra
->regs
);
535 tegra
->reset
= devm_reset_control_get(&pdev
->dev
, "soctherm");
536 if (IS_ERR(tegra
->reset
)) {
537 dev_err(&pdev
->dev
, "can't get soctherm reset\n");
538 return PTR_ERR(tegra
->reset
);
541 tegra
->clock_tsensor
= devm_clk_get(&pdev
->dev
, "tsensor");
542 if (IS_ERR(tegra
->clock_tsensor
)) {
543 dev_err(&pdev
->dev
, "can't get tsensor clock\n");
544 return PTR_ERR(tegra
->clock_tsensor
);
547 tegra
->clock_soctherm
= devm_clk_get(&pdev
->dev
, "soctherm");
548 if (IS_ERR(tegra
->clock_soctherm
)) {
549 dev_err(&pdev
->dev
, "can't get soctherm clock\n");
550 return PTR_ERR(tegra
->clock_soctherm
);
553 tegra
->calib
= devm_kzalloc(&pdev
->dev
,
554 sizeof(u32
) * soc
->num_tsensors
,
559 /* calculate shared calibration data */
560 err
= tegra_calc_shared_calib(soc
->tfuse
, &shared_calib
);
564 /* calculate tsensor calibaration data */
565 for (i
= 0; i
< soc
->num_tsensors
; ++i
) {
566 err
= tegra_calc_tsensor_calib(&soc
->tsensors
[i
],
573 tegra
->thermctl_tzs
= devm_kzalloc(&pdev
->dev
,
574 sizeof(*z
) * soc
->num_ttgs
,
576 if (!tegra
->thermctl_tzs
)
579 err
= soctherm_clk_enable(pdev
, true);
585 for (i
= 0; i
< soc
->num_ttgs
; ++i
) {
586 struct tegra_thermctl_zone
*zone
=
587 devm_kzalloc(&pdev
->dev
, sizeof(*zone
), GFP_KERNEL
);
593 zone
->reg
= tegra
->regs
+ soc
->ttgs
[i
]->sensor_temp_offset
;
594 zone
->dev
= &pdev
->dev
;
595 zone
->sg
= soc
->ttgs
[i
];
597 z
= devm_thermal_zone_of_sensor_register(&pdev
->dev
,
598 soc
->ttgs
[i
]->id
, zone
,
599 &tegra_of_thermal_ops
);
602 dev_err(&pdev
->dev
, "failed to register sensor: %d\n",
608 tegra
->thermctl_tzs
[soc
->ttgs
[i
]->id
] = z
;
610 /* Configure hw trip points */
611 tegra_soctherm_set_hwtrips(&pdev
->dev
, soc
->ttgs
[i
], z
);
614 soctherm_debug_init(pdev
);
619 soctherm_clk_enable(pdev
, false);
624 static int tegra_soctherm_remove(struct platform_device
*pdev
)
626 struct tegra_soctherm
*tegra
= platform_get_drvdata(pdev
);
628 debugfs_remove_recursive(tegra
->debugfs_dir
);
630 soctherm_clk_enable(pdev
, false);
635 static int __maybe_unused
soctherm_suspend(struct device
*dev
)
637 struct platform_device
*pdev
= to_platform_device(dev
);
639 soctherm_clk_enable(pdev
, false);
644 static int __maybe_unused
soctherm_resume(struct device
*dev
)
646 struct platform_device
*pdev
= to_platform_device(dev
);
647 struct tegra_soctherm
*tegra
= platform_get_drvdata(pdev
);
648 struct tegra_soctherm_soc
*soc
= tegra
->soc
;
651 err
= soctherm_clk_enable(pdev
, true);
654 "Resume failed: enable clocks failed\n");
660 for (i
= 0; i
< soc
->num_ttgs
; ++i
) {
661 struct thermal_zone_device
*tz
;
663 tz
= tegra
->thermctl_tzs
[soc
->ttgs
[i
]->id
];
664 tegra_soctherm_set_hwtrips(dev
, soc
->ttgs
[i
], tz
);
670 static SIMPLE_DEV_PM_OPS(tegra_soctherm_pm
, soctherm_suspend
, soctherm_resume
);
672 static struct platform_driver tegra_soctherm_driver
= {
673 .probe
= tegra_soctherm_probe
,
674 .remove
= tegra_soctherm_remove
,
676 .name
= "tegra_soctherm",
677 .pm
= &tegra_soctherm_pm
,
678 .of_match_table
= tegra_soctherm_of_match
,
681 module_platform_driver(tegra_soctherm_driver
);
683 MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
684 MODULE_DESCRIPTION("NVIDIA Tegra SOCTHERM thermal management driver");
685 MODULE_LICENSE("GPL v2");