2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
4 * Copyright (C) 2011 Samsung Electronics
5 * Donggeun Kim <dg77.kim@samsung.com>
6 * Amit Daniel Kachhap <amit.kachhap@linaro.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <linux/clk.h>
26 #include <linux/interrupt.h>
27 #include <linux/module.h>
29 #include <linux/of_address.h>
30 #include <linux/of_irq.h>
31 #include <linux/platform_device.h>
32 #include <linux/regulator/consumer.h>
34 #include "exynos_thermal_common.h"
35 #include "exynos_tmu.h"
36 #include "exynos_tmu_data.h"
39 * struct exynos_tmu_data : A structure to hold the private data of the TMU
41 * @id: identifier of the one instance of the TMU controller.
42 * @pdata: pointer to the tmu platform/configuration data
43 * @base: base address of the single instance of the TMU controller.
44 * @base_second: base address of the common registers of the TMU controller.
45 * @irq: irq number of the TMU controller.
46 * @soc: id of the SOC type.
47 * @irq_work: pointer to the irq work structure.
48 * @lock: lock to implement synchronization.
49 * @clk: pointer to the clock structure.
50 * @clk_sec: pointer to the clock structure for accessing the base_second.
51 * @temp_error1: fused value of the first point trim.
52 * @temp_error2: fused value of the second point trim.
53 * @regulator: pointer to the TMU regulator structure.
54 * @reg_conf: pointer to structure to register with core thermal.
56 struct exynos_tmu_data
{
58 struct exynos_tmu_platform_data
*pdata
;
60 void __iomem
*base_second
;
63 struct work_struct irq_work
;
65 struct clk
*clk
, *clk_sec
;
66 u8 temp_error1
, temp_error2
;
67 struct regulator
*regulator
;
68 struct thermal_sensor_conf
*reg_conf
;
72 * TMU treats temperature as a mapped temperature code.
73 * The temperature is converted differently depending on the calibration type.
75 static int temp_to_code(struct exynos_tmu_data
*data
, u8 temp
)
77 struct exynos_tmu_platform_data
*pdata
= data
->pdata
;
80 if (pdata
->cal_mode
== HW_MODE
)
83 if (data
->soc
== SOC_ARCH_EXYNOS4210
)
84 /* temp should range between 25 and 125 */
85 if (temp
< 25 || temp
> 125) {
90 switch (pdata
->cal_type
) {
91 case TYPE_TWO_POINT_TRIMMING
:
92 temp_code
= (temp
- pdata
->first_point_trim
) *
93 (data
->temp_error2
- data
->temp_error1
) /
94 (pdata
->second_point_trim
- pdata
->first_point_trim
) +
97 case TYPE_ONE_POINT_TRIMMING
:
98 temp_code
= temp
+ data
->temp_error1
- pdata
->first_point_trim
;
101 temp_code
= temp
+ pdata
->default_temp_offset
;
109 * Calculate a temperature value from a temperature code.
110 * The unit of the temperature is degree Celsius.
112 static int code_to_temp(struct exynos_tmu_data
*data
, u8 temp_code
)
114 struct exynos_tmu_platform_data
*pdata
= data
->pdata
;
117 if (pdata
->cal_mode
== HW_MODE
)
120 if (data
->soc
== SOC_ARCH_EXYNOS4210
)
121 /* temp_code should range between 75 and 175 */
122 if (temp_code
< 75 || temp_code
> 175) {
127 switch (pdata
->cal_type
) {
128 case TYPE_TWO_POINT_TRIMMING
:
129 temp
= (temp_code
- data
->temp_error1
) *
130 (pdata
->second_point_trim
- pdata
->first_point_trim
) /
131 (data
->temp_error2
- data
->temp_error1
) +
132 pdata
->first_point_trim
;
134 case TYPE_ONE_POINT_TRIMMING
:
135 temp
= temp_code
- data
->temp_error1
+ pdata
->first_point_trim
;
138 temp
= temp_code
- pdata
->default_temp_offset
;
145 static int exynos_tmu_initialize(struct platform_device
*pdev
)
147 struct exynos_tmu_data
*data
= platform_get_drvdata(pdev
);
148 struct exynos_tmu_platform_data
*pdata
= data
->pdata
;
149 const struct exynos_tmu_registers
*reg
= pdata
->registers
;
150 unsigned int status
, trim_info
= 0, con
;
151 unsigned int rising_threshold
= 0, falling_threshold
= 0;
152 int ret
= 0, threshold_code
, i
, trigger_levs
= 0;
154 mutex_lock(&data
->lock
);
155 clk_enable(data
->clk
);
156 if (!IS_ERR(data
->clk_sec
))
157 clk_enable(data
->clk_sec
);
159 if (TMU_SUPPORTS(pdata
, READY_STATUS
)) {
160 status
= readb(data
->base
+ reg
->tmu_status
);
167 if (TMU_SUPPORTS(pdata
, TRIM_RELOAD
))
168 __raw_writel(1, data
->base
+ reg
->triminfo_ctrl
);
170 if (pdata
->cal_mode
== HW_MODE
)
171 goto skip_calib_data
;
173 /* Save trimming info in order to perform calibration */
174 if (data
->soc
== SOC_ARCH_EXYNOS5440
) {
176 * For exynos5440 soc triminfo value is swapped between TMU0 and
177 * TMU2, so the below logic is needed.
181 trim_info
= readl(data
->base
+
182 EXYNOS5440_EFUSE_SWAP_OFFSET
+ reg
->triminfo_data
);
185 trim_info
= readl(data
->base
+ reg
->triminfo_data
);
188 trim_info
= readl(data
->base
-
189 EXYNOS5440_EFUSE_SWAP_OFFSET
+ reg
->triminfo_data
);
192 /* On exynos5420 the triminfo register is in the shared space */
193 if (data
->soc
== SOC_ARCH_EXYNOS5420_TRIMINFO
)
194 trim_info
= readl(data
->base_second
+
197 trim_info
= readl(data
->base
+ reg
->triminfo_data
);
199 data
->temp_error1
= trim_info
& EXYNOS_TMU_TEMP_MASK
;
200 data
->temp_error2
= ((trim_info
>> reg
->triminfo_85_shift
) &
201 EXYNOS_TMU_TEMP_MASK
);
203 if (!data
->temp_error1
||
204 (pdata
->min_efuse_value
> data
->temp_error1
) ||
205 (data
->temp_error1
> pdata
->max_efuse_value
))
206 data
->temp_error1
= pdata
->efuse_value
& EXYNOS_TMU_TEMP_MASK
;
208 if (!data
->temp_error2
)
210 (pdata
->efuse_value
>> reg
->triminfo_85_shift
) &
211 EXYNOS_TMU_TEMP_MASK
;
214 if (pdata
->max_trigger_level
> MAX_THRESHOLD_LEVS
) {
215 dev_err(&pdev
->dev
, "Invalid max trigger level\n");
220 for (i
= 0; i
< pdata
->max_trigger_level
; i
++) {
221 if (!pdata
->trigger_levels
[i
])
224 if ((pdata
->trigger_type
[i
] == HW_TRIP
) &&
225 (!pdata
->trigger_levels
[pdata
->max_trigger_level
- 1])) {
226 dev_err(&pdev
->dev
, "Invalid hw trigger level\n");
231 /* Count trigger levels except the HW trip*/
232 if (!(pdata
->trigger_type
[i
] == HW_TRIP
))
236 rising_threshold
= readl(data
->base
+ reg
->threshold_th0
);
238 if (data
->soc
== SOC_ARCH_EXYNOS4210
) {
239 /* Write temperature code for threshold */
240 threshold_code
= temp_to_code(data
, pdata
->threshold
);
241 if (threshold_code
< 0) {
242 ret
= threshold_code
;
245 writeb(threshold_code
,
246 data
->base
+ reg
->threshold_temp
);
247 for (i
= 0; i
< trigger_levs
; i
++)
248 writeb(pdata
->trigger_levels
[i
], data
->base
+
249 reg
->threshold_th0
+ i
* sizeof(reg
->threshold_th0
));
251 writel(reg
->intclr_rise_mask
, data
->base
+ reg
->tmu_intclear
);
253 /* Write temperature code for rising and falling threshold */
255 i
< trigger_levs
&& i
< EXYNOS_MAX_TRIGGER_PER_REG
; i
++) {
256 threshold_code
= temp_to_code(data
,
257 pdata
->trigger_levels
[i
]);
258 if (threshold_code
< 0) {
259 ret
= threshold_code
;
262 rising_threshold
&= ~(0xff << 8 * i
);
263 rising_threshold
|= threshold_code
<< 8 * i
;
264 if (pdata
->threshold_falling
) {
265 threshold_code
= temp_to_code(data
,
266 pdata
->trigger_levels
[i
] -
267 pdata
->threshold_falling
);
268 if (threshold_code
> 0)
270 threshold_code
<< 8 * i
;
274 writel(rising_threshold
,
275 data
->base
+ reg
->threshold_th0
);
276 writel(falling_threshold
,
277 data
->base
+ reg
->threshold_th1
);
279 writel((reg
->intclr_rise_mask
<< reg
->intclr_rise_shift
) |
280 (reg
->intclr_fall_mask
<< reg
->intclr_fall_shift
),
281 data
->base
+ reg
->tmu_intclear
);
283 /* if last threshold limit is also present */
284 i
= pdata
->max_trigger_level
- 1;
285 if (pdata
->trigger_levels
[i
] &&
286 (pdata
->trigger_type
[i
] == HW_TRIP
)) {
287 threshold_code
= temp_to_code(data
,
288 pdata
->trigger_levels
[i
]);
289 if (threshold_code
< 0) {
290 ret
= threshold_code
;
293 if (i
== EXYNOS_MAX_TRIGGER_PER_REG
- 1) {
294 /* 1-4 level to be assigned in th0 reg */
295 rising_threshold
&= ~(0xff << 8 * i
);
296 rising_threshold
|= threshold_code
<< 8 * i
;
297 writel(rising_threshold
,
298 data
->base
+ reg
->threshold_th0
);
299 } else if (i
== EXYNOS_MAX_TRIGGER_PER_REG
) {
300 /* 5th level to be assigned in th2 reg */
302 threshold_code
<< reg
->threshold_th3_l0_shift
;
303 writel(rising_threshold
,
304 data
->base
+ reg
->threshold_th2
);
306 con
= readl(data
->base
+ reg
->tmu_ctrl
);
307 con
|= (1 << reg
->therm_trip_en_shift
);
308 writel(con
, data
->base
+ reg
->tmu_ctrl
);
311 /*Clear the PMIN in the common TMU register*/
312 if (reg
->tmu_pmin
&& !data
->id
)
313 writel(0, data
->base_second
+ reg
->tmu_pmin
);
315 clk_disable(data
->clk
);
316 mutex_unlock(&data
->lock
);
317 if (!IS_ERR(data
->clk_sec
))
318 clk_disable(data
->clk_sec
);
323 static void exynos_tmu_control(struct platform_device
*pdev
, bool on
)
325 struct exynos_tmu_data
*data
= platform_get_drvdata(pdev
);
326 struct exynos_tmu_platform_data
*pdata
= data
->pdata
;
327 const struct exynos_tmu_registers
*reg
= pdata
->registers
;
328 unsigned int con
, interrupt_en
, cal_val
;
330 mutex_lock(&data
->lock
);
331 clk_enable(data
->clk
);
333 con
= readl(data
->base
+ reg
->tmu_ctrl
);
336 con
|= (pdata
->test_mux
<< reg
->test_mux_addr_shift
);
338 if (pdata
->reference_voltage
) {
339 con
&= ~(reg
->buf_vref_sel_mask
<< reg
->buf_vref_sel_shift
);
340 con
|= pdata
->reference_voltage
<< reg
->buf_vref_sel_shift
;
344 con
&= ~(reg
->buf_slope_sel_mask
<< reg
->buf_slope_sel_shift
);
345 con
|= (pdata
->gain
<< reg
->buf_slope_sel_shift
);
348 if (pdata
->noise_cancel_mode
) {
349 con
&= ~(reg
->therm_trip_mode_mask
<<
350 reg
->therm_trip_mode_shift
);
351 con
|= (pdata
->noise_cancel_mode
<< reg
->therm_trip_mode_shift
);
354 if (pdata
->cal_mode
== HW_MODE
) {
355 con
&= ~(reg
->calib_mode_mask
<< reg
->calib_mode_shift
);
357 switch (pdata
->cal_type
) {
358 case TYPE_TWO_POINT_TRIMMING
:
361 case TYPE_ONE_POINT_TRIMMING_85
:
364 case TYPE_ONE_POINT_TRIMMING_25
:
370 dev_err(&pdev
->dev
, "Invalid calibration type, using none\n");
372 con
|= cal_val
<< reg
->calib_mode_shift
;
376 con
|= (1 << reg
->core_en_shift
);
378 pdata
->trigger_enable
[3] << reg
->inten_rise3_shift
|
379 pdata
->trigger_enable
[2] << reg
->inten_rise2_shift
|
380 pdata
->trigger_enable
[1] << reg
->inten_rise1_shift
|
381 pdata
->trigger_enable
[0] << reg
->inten_rise0_shift
;
382 if (TMU_SUPPORTS(pdata
, FALLING_TRIP
))
384 interrupt_en
<< reg
->inten_fall0_shift
;
386 con
&= ~(1 << reg
->core_en_shift
);
387 interrupt_en
= 0; /* Disable all interrupts */
389 writel(interrupt_en
, data
->base
+ reg
->tmu_inten
);
390 writel(con
, data
->base
+ reg
->tmu_ctrl
);
392 clk_disable(data
->clk
);
393 mutex_unlock(&data
->lock
);
396 static int exynos_tmu_read(struct exynos_tmu_data
*data
)
398 struct exynos_tmu_platform_data
*pdata
= data
->pdata
;
399 const struct exynos_tmu_registers
*reg
= pdata
->registers
;
403 mutex_lock(&data
->lock
);
404 clk_enable(data
->clk
);
406 temp_code
= readb(data
->base
+ reg
->tmu_cur_temp
);
407 temp
= code_to_temp(data
, temp_code
);
409 clk_disable(data
->clk
);
410 mutex_unlock(&data
->lock
);
415 #ifdef CONFIG_THERMAL_EMULATION
416 static int exynos_tmu_set_emulation(void *drv_data
, unsigned long temp
)
418 struct exynos_tmu_data
*data
= drv_data
;
419 struct exynos_tmu_platform_data
*pdata
= data
->pdata
;
420 const struct exynos_tmu_registers
*reg
= pdata
->registers
;
424 if (!TMU_SUPPORTS(pdata
, EMULATION
))
427 if (temp
&& temp
< MCELSIUS
)
430 mutex_lock(&data
->lock
);
431 clk_enable(data
->clk
);
433 val
= readl(data
->base
+ reg
->emul_con
);
438 if (TMU_SUPPORTS(pdata
, EMUL_TIME
)) {
439 val
&= ~(EXYNOS_EMUL_TIME_MASK
<< reg
->emul_time_shift
);
440 val
|= (EXYNOS_EMUL_TIME
<< reg
->emul_time_shift
);
442 val
&= ~(EXYNOS_EMUL_DATA_MASK
<< reg
->emul_temp_shift
);
443 val
|= (temp_to_code(data
, temp
) << reg
->emul_temp_shift
) |
446 val
&= ~EXYNOS_EMUL_ENABLE
;
449 writel(val
, data
->base
+ reg
->emul_con
);
451 clk_disable(data
->clk
);
452 mutex_unlock(&data
->lock
);
458 static int exynos_tmu_set_emulation(void *drv_data
, unsigned long temp
)
460 #endif/*CONFIG_THERMAL_EMULATION*/
462 static void exynos_tmu_work(struct work_struct
*work
)
464 struct exynos_tmu_data
*data
= container_of(work
,
465 struct exynos_tmu_data
, irq_work
);
466 struct exynos_tmu_platform_data
*pdata
= data
->pdata
;
467 const struct exynos_tmu_registers
*reg
= pdata
->registers
;
468 unsigned int val_irq
, val_type
;
470 if (!IS_ERR(data
->clk_sec
))
471 clk_enable(data
->clk_sec
);
472 /* Find which sensor generated this interrupt */
473 if (reg
->tmu_irqstatus
) {
474 val_type
= readl(data
->base_second
+ reg
->tmu_irqstatus
);
475 if (!((val_type
>> data
->id
) & 0x1))
478 if (!IS_ERR(data
->clk_sec
))
479 clk_disable(data
->clk_sec
);
481 exynos_report_trigger(data
->reg_conf
);
482 mutex_lock(&data
->lock
);
483 clk_enable(data
->clk
);
485 /* TODO: take action based on particular interrupt */
486 val_irq
= readl(data
->base
+ reg
->tmu_intstat
);
487 /* clear the interrupts */
488 writel(val_irq
, data
->base
+ reg
->tmu_intclear
);
490 clk_disable(data
->clk
);
491 mutex_unlock(&data
->lock
);
493 enable_irq(data
->irq
);
496 static irqreturn_t
exynos_tmu_irq(int irq
, void *id
)
498 struct exynos_tmu_data
*data
= id
;
500 disable_irq_nosync(irq
);
501 schedule_work(&data
->irq_work
);
506 static const struct of_device_id exynos_tmu_match
[] = {
508 .compatible
= "samsung,exynos3250-tmu",
509 .data
= (void *)EXYNOS3250_TMU_DRV_DATA
,
512 .compatible
= "samsung,exynos4210-tmu",
513 .data
= (void *)EXYNOS4210_TMU_DRV_DATA
,
516 .compatible
= "samsung,exynos4412-tmu",
517 .data
= (void *)EXYNOS4412_TMU_DRV_DATA
,
520 .compatible
= "samsung,exynos5250-tmu",
521 .data
= (void *)EXYNOS5250_TMU_DRV_DATA
,
524 .compatible
= "samsung,exynos5260-tmu",
525 .data
= (void *)EXYNOS5260_TMU_DRV_DATA
,
528 .compatible
= "samsung,exynos5420-tmu",
529 .data
= (void *)EXYNOS5420_TMU_DRV_DATA
,
532 .compatible
= "samsung,exynos5420-tmu-ext-triminfo",
533 .data
= (void *)EXYNOS5420_TMU_DRV_DATA
,
536 .compatible
= "samsung,exynos5440-tmu",
537 .data
= (void *)EXYNOS5440_TMU_DRV_DATA
,
541 MODULE_DEVICE_TABLE(of
, exynos_tmu_match
);
543 static inline struct exynos_tmu_platform_data
*exynos_get_driver_data(
544 struct platform_device
*pdev
, int id
)
546 struct exynos_tmu_init_data
*data_table
;
547 struct exynos_tmu_platform_data
*tmu_data
;
548 const struct of_device_id
*match
;
550 match
= of_match_node(exynos_tmu_match
, pdev
->dev
.of_node
);
553 data_table
= (struct exynos_tmu_init_data
*) match
->data
;
554 if (!data_table
|| id
>= data_table
->tmu_count
)
556 tmu_data
= data_table
->tmu_data
;
557 return (struct exynos_tmu_platform_data
*) (tmu_data
+ id
);
560 static int exynos_map_dt_data(struct platform_device
*pdev
)
562 struct exynos_tmu_data
*data
= platform_get_drvdata(pdev
);
563 struct exynos_tmu_platform_data
*pdata
;
567 if (!data
|| !pdev
->dev
.of_node
)
571 * Try enabling the regulator if found
572 * TODO: Add regulator as an SOC feature, so that regulator enable
573 * is a compulsory call.
575 data
->regulator
= devm_regulator_get(&pdev
->dev
, "vtmu");
576 if (!IS_ERR(data
->regulator
)) {
577 ret
= regulator_enable(data
->regulator
);
579 dev_err(&pdev
->dev
, "failed to enable vtmu\n");
583 dev_info(&pdev
->dev
, "Regulator node (vtmu) not found\n");
586 data
->id
= of_alias_get_id(pdev
->dev
.of_node
, "tmuctrl");
590 data
->irq
= irq_of_parse_and_map(pdev
->dev
.of_node
, 0);
591 if (data
->irq
<= 0) {
592 dev_err(&pdev
->dev
, "failed to get IRQ\n");
596 if (of_address_to_resource(pdev
->dev
.of_node
, 0, &res
)) {
597 dev_err(&pdev
->dev
, "failed to get Resource 0\n");
601 data
->base
= devm_ioremap(&pdev
->dev
, res
.start
, resource_size(&res
));
603 dev_err(&pdev
->dev
, "Failed to ioremap memory\n");
604 return -EADDRNOTAVAIL
;
607 pdata
= exynos_get_driver_data(pdev
, data
->id
);
609 dev_err(&pdev
->dev
, "No platform init data supplied.\n");
614 * Check if the TMU shares some registers and then try to map the
615 * memory of common registers.
617 if (!TMU_SUPPORTS(pdata
, ADDRESS_MULTIPLE
))
620 if (of_address_to_resource(pdev
->dev
.of_node
, 1, &res
)) {
621 dev_err(&pdev
->dev
, "failed to get Resource 1\n");
625 data
->base_second
= devm_ioremap(&pdev
->dev
, res
.start
,
626 resource_size(&res
));
627 if (!data
->base_second
) {
628 dev_err(&pdev
->dev
, "Failed to ioremap memory\n");
635 static int exynos_tmu_probe(struct platform_device
*pdev
)
637 struct exynos_tmu_data
*data
;
638 struct exynos_tmu_platform_data
*pdata
;
639 struct thermal_sensor_conf
*sensor_conf
;
642 data
= devm_kzalloc(&pdev
->dev
, sizeof(struct exynos_tmu_data
),
647 platform_set_drvdata(pdev
, data
);
648 mutex_init(&data
->lock
);
650 ret
= exynos_map_dt_data(pdev
);
656 INIT_WORK(&data
->irq_work
, exynos_tmu_work
);
658 data
->clk
= devm_clk_get(&pdev
->dev
, "tmu_apbif");
659 if (IS_ERR(data
->clk
)) {
660 dev_err(&pdev
->dev
, "Failed to get clock\n");
661 return PTR_ERR(data
->clk
);
664 data
->clk_sec
= devm_clk_get(&pdev
->dev
, "tmu_triminfo_apbif");
665 if (IS_ERR(data
->clk_sec
)) {
666 if (data
->soc
== SOC_ARCH_EXYNOS5420_TRIMINFO
) {
667 dev_err(&pdev
->dev
, "Failed to get triminfo clock\n");
668 return PTR_ERR(data
->clk_sec
);
671 ret
= clk_prepare(data
->clk_sec
);
673 dev_err(&pdev
->dev
, "Failed to get clock\n");
678 ret
= clk_prepare(data
->clk
);
680 dev_err(&pdev
->dev
, "Failed to get clock\n");
684 if (pdata
->type
== SOC_ARCH_EXYNOS3250
||
685 pdata
->type
== SOC_ARCH_EXYNOS4210
||
686 pdata
->type
== SOC_ARCH_EXYNOS4412
||
687 pdata
->type
== SOC_ARCH_EXYNOS5250
||
688 pdata
->type
== SOC_ARCH_EXYNOS5260
||
689 pdata
->type
== SOC_ARCH_EXYNOS5420_TRIMINFO
||
690 pdata
->type
== SOC_ARCH_EXYNOS5440
)
691 data
->soc
= pdata
->type
;
694 dev_err(&pdev
->dev
, "Platform not supported\n");
698 ret
= exynos_tmu_initialize(pdev
);
700 dev_err(&pdev
->dev
, "Failed to initialize TMU\n");
704 exynos_tmu_control(pdev
, true);
706 /* Allocate a structure to register with the exynos core thermal */
707 sensor_conf
= devm_kzalloc(&pdev
->dev
,
708 sizeof(struct thermal_sensor_conf
), GFP_KERNEL
);
713 sprintf(sensor_conf
->name
, "therm_zone%d", data
->id
);
714 sensor_conf
->read_temperature
= (int (*)(void *))exynos_tmu_read
;
715 sensor_conf
->write_emul_temp
=
716 (int (*)(void *, unsigned long))exynos_tmu_set_emulation
;
717 sensor_conf
->driver_data
= data
;
718 sensor_conf
->trip_data
.trip_count
= pdata
->trigger_enable
[0] +
719 pdata
->trigger_enable
[1] + pdata
->trigger_enable
[2]+
720 pdata
->trigger_enable
[3];
722 for (i
= 0; i
< sensor_conf
->trip_data
.trip_count
; i
++) {
723 sensor_conf
->trip_data
.trip_val
[i
] =
724 pdata
->threshold
+ pdata
->trigger_levels
[i
];
725 sensor_conf
->trip_data
.trip_type
[i
] =
726 pdata
->trigger_type
[i
];
729 sensor_conf
->trip_data
.trigger_falling
= pdata
->threshold_falling
;
731 sensor_conf
->cooling_data
.freq_clip_count
= pdata
->freq_tab_count
;
732 for (i
= 0; i
< pdata
->freq_tab_count
; i
++) {
733 sensor_conf
->cooling_data
.freq_data
[i
].freq_clip_max
=
734 pdata
->freq_tab
[i
].freq_clip_max
;
735 sensor_conf
->cooling_data
.freq_data
[i
].temp_level
=
736 pdata
->freq_tab
[i
].temp_level
;
738 sensor_conf
->dev
= &pdev
->dev
;
739 /* Register the sensor with thermal management interface */
740 ret
= exynos_register_thermal(sensor_conf
);
742 dev_err(&pdev
->dev
, "Failed to register thermal interface\n");
745 data
->reg_conf
= sensor_conf
;
747 ret
= devm_request_irq(&pdev
->dev
, data
->irq
, exynos_tmu_irq
,
748 IRQF_TRIGGER_RISING
| IRQF_SHARED
, dev_name(&pdev
->dev
), data
);
750 dev_err(&pdev
->dev
, "Failed to request irq: %d\n", data
->irq
);
756 clk_unprepare(data
->clk
);
758 if (!IS_ERR(data
->clk_sec
))
759 clk_unprepare(data
->clk_sec
);
763 static int exynos_tmu_remove(struct platform_device
*pdev
)
765 struct exynos_tmu_data
*data
= platform_get_drvdata(pdev
);
767 exynos_unregister_thermal(data
->reg_conf
);
769 exynos_tmu_control(pdev
, false);
771 clk_unprepare(data
->clk
);
772 if (!IS_ERR(data
->clk_sec
))
773 clk_unprepare(data
->clk_sec
);
775 if (!IS_ERR(data
->regulator
))
776 regulator_disable(data
->regulator
);
781 #ifdef CONFIG_PM_SLEEP
782 static int exynos_tmu_suspend(struct device
*dev
)
784 exynos_tmu_control(to_platform_device(dev
), false);
789 static int exynos_tmu_resume(struct device
*dev
)
791 struct platform_device
*pdev
= to_platform_device(dev
);
793 exynos_tmu_initialize(pdev
);
794 exynos_tmu_control(pdev
, true);
799 static SIMPLE_DEV_PM_OPS(exynos_tmu_pm
,
800 exynos_tmu_suspend
, exynos_tmu_resume
);
801 #define EXYNOS_TMU_PM (&exynos_tmu_pm)
803 #define EXYNOS_TMU_PM NULL
806 static struct platform_driver exynos_tmu_driver
= {
808 .name
= "exynos-tmu",
809 .owner
= THIS_MODULE
,
811 .of_match_table
= exynos_tmu_match
,
813 .probe
= exynos_tmu_probe
,
814 .remove
= exynos_tmu_remove
,
817 module_platform_driver(exynos_tmu_driver
);
819 MODULE_DESCRIPTION("EXYNOS TMU Driver");
820 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
821 MODULE_LICENSE("GPL");
822 MODULE_ALIAS("platform:exynos-tmu");