[go: nahoru, domu]

exynos_tmu.c revision 9c7a87f146a642447db29327bcedfbe2163da172
1/*
2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
3 *
4 *  Copyright (C) 2011 Samsung Electronics
5 *  Donggeun Kim <dg77.kim@samsung.com>
6 *  Amit Daniel Kachhap <amit.kachhap@linaro.org>
7 *
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.
12 *
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.
17 *
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
21 *
22 */
23
24#include <linux/clk.h>
25#include <linux/io.h>
26#include <linux/interrupt.h>
27#include <linux/module.h>
28#include <linux/of.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>
33
34#include "exynos_thermal_common.h"
35#include "exynos_tmu.h"
36#include "exynos_tmu_data.h"
37
38/**
39 * struct exynos_tmu_data : A structure to hold the private data of the TMU
40	driver
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.
55 */
56struct exynos_tmu_data {
57	int id;
58	struct exynos_tmu_platform_data *pdata;
59	void __iomem *base;
60	void __iomem *base_second;
61	int irq;
62	enum soc_type soc;
63	struct work_struct irq_work;
64	struct mutex lock;
65	struct clk *clk, *clk_sec;
66	u8 temp_error1, temp_error2;
67	struct regulator *regulator;
68	struct thermal_sensor_conf *reg_conf;
69};
70
71/*
72 * TMU treats temperature as a mapped temperature code.
73 * The temperature is converted differently depending on the calibration type.
74 */
75static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
76{
77	struct exynos_tmu_platform_data *pdata = data->pdata;
78	int temp_code;
79
80	switch (pdata->cal_type) {
81	case TYPE_TWO_POINT_TRIMMING:
82		temp_code = (temp - pdata->first_point_trim) *
83			(data->temp_error2 - data->temp_error1) /
84			(pdata->second_point_trim - pdata->first_point_trim) +
85			data->temp_error1;
86		break;
87	case TYPE_ONE_POINT_TRIMMING:
88		temp_code = temp + data->temp_error1 - pdata->first_point_trim;
89		break;
90	default:
91		temp_code = temp + pdata->default_temp_offset;
92		break;
93	}
94
95	return temp_code;
96}
97
98/*
99 * Calculate a temperature value from a temperature code.
100 * The unit of the temperature is degree Celsius.
101 */
102static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
103{
104	struct exynos_tmu_platform_data *pdata = data->pdata;
105	int temp;
106
107	switch (pdata->cal_type) {
108	case TYPE_TWO_POINT_TRIMMING:
109		temp = (temp_code - data->temp_error1) *
110			(pdata->second_point_trim - pdata->first_point_trim) /
111			(data->temp_error2 - data->temp_error1) +
112			pdata->first_point_trim;
113		break;
114	case TYPE_ONE_POINT_TRIMMING:
115		temp = temp_code - data->temp_error1 + pdata->first_point_trim;
116		break;
117	default:
118		temp = temp_code - pdata->default_temp_offset;
119		break;
120	}
121
122	return temp;
123}
124
125static int exynos_tmu_initialize(struct platform_device *pdev)
126{
127	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
128	struct exynos_tmu_platform_data *pdata = data->pdata;
129	const struct exynos_tmu_registers *reg = pdata->registers;
130	unsigned int status, trim_info = 0, con;
131	unsigned int rising_threshold = 0, falling_threshold = 0;
132	int ret = 0, threshold_code, i;
133
134	mutex_lock(&data->lock);
135	clk_enable(data->clk);
136	if (!IS_ERR(data->clk_sec))
137		clk_enable(data->clk_sec);
138
139	if (TMU_SUPPORTS(pdata, READY_STATUS)) {
140		status = readb(data->base + reg->tmu_status);
141		if (!status) {
142			ret = -EBUSY;
143			goto out;
144		}
145	}
146
147	if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
148		__raw_writel(1, data->base + reg->triminfo_ctrl);
149
150	/* Save trimming info in order to perform calibration */
151	if (data->soc == SOC_ARCH_EXYNOS5440) {
152		/*
153		 * For exynos5440 soc triminfo value is swapped between TMU0 and
154		 * TMU2, so the below logic is needed.
155		 */
156		switch (data->id) {
157		case 0:
158			trim_info = readl(data->base +
159			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
160			break;
161		case 1:
162			trim_info = readl(data->base + reg->triminfo_data);
163			break;
164		case 2:
165			trim_info = readl(data->base -
166			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
167		}
168	} else {
169		/* On exynos5420 the triminfo register is in the shared space */
170		if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
171			trim_info = readl(data->base_second +
172							reg->triminfo_data);
173		else
174			trim_info = readl(data->base + reg->triminfo_data);
175	}
176	data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
177	data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
178				EXYNOS_TMU_TEMP_MASK);
179
180	if (!data->temp_error1 ||
181		(pdata->min_efuse_value > data->temp_error1) ||
182		(data->temp_error1 > pdata->max_efuse_value))
183		data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
184
185	if (!data->temp_error2)
186		data->temp_error2 =
187			(pdata->efuse_value >> reg->triminfo_85_shift) &
188			EXYNOS_TMU_TEMP_MASK;
189
190	rising_threshold = readl(data->base + reg->threshold_th0);
191
192	if (data->soc == SOC_ARCH_EXYNOS4210) {
193		/* Write temperature code for threshold */
194		threshold_code = temp_to_code(data, pdata->threshold);
195		writeb(threshold_code,
196			data->base + reg->threshold_temp);
197		for (i = 0; i < pdata->non_hw_trigger_levels; i++)
198			writeb(pdata->trigger_levels[i], data->base +
199			reg->threshold_th0 + i * sizeof(reg->threshold_th0));
200
201		writel(reg->intclr_rise_mask, data->base + reg->tmu_intclear);
202	} else {
203		/* Write temperature code for rising and falling threshold */
204		for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
205			threshold_code = temp_to_code(data,
206						pdata->trigger_levels[i]);
207			rising_threshold &= ~(0xff << 8 * i);
208			rising_threshold |= threshold_code << 8 * i;
209			if (pdata->threshold_falling) {
210				threshold_code = temp_to_code(data,
211						pdata->trigger_levels[i] -
212						pdata->threshold_falling);
213				falling_threshold |= threshold_code << 8 * i;
214			}
215		}
216
217		writel(rising_threshold,
218				data->base + reg->threshold_th0);
219		writel(falling_threshold,
220				data->base + reg->threshold_th1);
221
222		writel((reg->intclr_rise_mask << reg->intclr_rise_shift) |
223			(reg->intclr_fall_mask << reg->intclr_fall_shift),
224				data->base + reg->tmu_intclear);
225
226		/* if last threshold limit is also present */
227		i = pdata->max_trigger_level - 1;
228		if (pdata->trigger_levels[i] &&
229				(pdata->trigger_type[i] == HW_TRIP)) {
230			threshold_code = temp_to_code(data,
231						pdata->trigger_levels[i]);
232			if (i == EXYNOS_MAX_TRIGGER_PER_REG - 1) {
233				/* 1-4 level to be assigned in th0 reg */
234				rising_threshold &= ~(0xff << 8 * i);
235				rising_threshold |= threshold_code << 8 * i;
236				writel(rising_threshold,
237					data->base + reg->threshold_th0);
238			} else if (i == EXYNOS_MAX_TRIGGER_PER_REG) {
239				/* 5th level to be assigned in th2 reg */
240				rising_threshold =
241				threshold_code << reg->threshold_th3_l0_shift;
242				writel(rising_threshold,
243					data->base + reg->threshold_th2);
244			}
245			con = readl(data->base + reg->tmu_ctrl);
246			con |= (1 << reg->therm_trip_en_shift);
247			writel(con, data->base + reg->tmu_ctrl);
248		}
249	}
250	/*Clear the PMIN in the common TMU register*/
251	if (reg->tmu_pmin && !data->id)
252		writel(0, data->base_second + reg->tmu_pmin);
253out:
254	clk_disable(data->clk);
255	mutex_unlock(&data->lock);
256	if (!IS_ERR(data->clk_sec))
257		clk_disable(data->clk_sec);
258
259	return ret;
260}
261
262static void exynos_tmu_control(struct platform_device *pdev, bool on)
263{
264	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
265	struct exynos_tmu_platform_data *pdata = data->pdata;
266	const struct exynos_tmu_registers *reg = pdata->registers;
267	unsigned int con, interrupt_en;
268
269	mutex_lock(&data->lock);
270	clk_enable(data->clk);
271
272	con = readl(data->base + reg->tmu_ctrl);
273
274	if (pdata->test_mux)
275		con |= (pdata->test_mux << reg->test_mux_addr_shift);
276
277	con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
278	con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
279
280	con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
281	con |= (pdata->gain << reg->buf_slope_sel_shift);
282
283	if (pdata->noise_cancel_mode) {
284		con &= ~(reg->therm_trip_mode_mask <<
285					reg->therm_trip_mode_shift);
286		con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
287	}
288
289	if (on) {
290		con |= (1 << reg->core_en_shift);
291		interrupt_en =
292			pdata->trigger_enable[3] << reg->inten_rise3_shift |
293			pdata->trigger_enable[2] << reg->inten_rise2_shift |
294			pdata->trigger_enable[1] << reg->inten_rise1_shift |
295			pdata->trigger_enable[0] << reg->inten_rise0_shift;
296		if (TMU_SUPPORTS(pdata, FALLING_TRIP))
297			interrupt_en |=
298				interrupt_en << reg->inten_fall0_shift;
299	} else {
300		con &= ~(1 << reg->core_en_shift);
301		interrupt_en = 0; /* Disable all interrupts */
302	}
303	writel(interrupt_en, data->base + reg->tmu_inten);
304	writel(con, data->base + reg->tmu_ctrl);
305
306	clk_disable(data->clk);
307	mutex_unlock(&data->lock);
308}
309
310static int exynos_tmu_read(struct exynos_tmu_data *data)
311{
312	struct exynos_tmu_platform_data *pdata = data->pdata;
313	const struct exynos_tmu_registers *reg = pdata->registers;
314	u8 temp_code;
315	int temp;
316
317	mutex_lock(&data->lock);
318	clk_enable(data->clk);
319
320	temp_code = readb(data->base + reg->tmu_cur_temp);
321
322	if (data->soc == SOC_ARCH_EXYNOS4210)
323		/* temp_code should range between 75 and 175 */
324		if (temp_code < 75 || temp_code > 175) {
325			temp = -ENODATA;
326			goto out;
327		}
328
329	temp = code_to_temp(data, temp_code);
330out:
331	clk_disable(data->clk);
332	mutex_unlock(&data->lock);
333
334	return temp;
335}
336
337#ifdef CONFIG_THERMAL_EMULATION
338static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
339{
340	struct exynos_tmu_data *data = drv_data;
341	struct exynos_tmu_platform_data *pdata = data->pdata;
342	const struct exynos_tmu_registers *reg = pdata->registers;
343	unsigned int val;
344	int ret = -EINVAL;
345
346	if (!TMU_SUPPORTS(pdata, EMULATION))
347		goto out;
348
349	if (temp && temp < MCELSIUS)
350		goto out;
351
352	mutex_lock(&data->lock);
353	clk_enable(data->clk);
354
355	val = readl(data->base + reg->emul_con);
356
357	if (temp) {
358		temp /= MCELSIUS;
359
360		if (TMU_SUPPORTS(pdata, EMUL_TIME)) {
361			val &= ~(EXYNOS_EMUL_TIME_MASK << reg->emul_time_shift);
362			val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
363		}
364		val &= ~(EXYNOS_EMUL_DATA_MASK << reg->emul_temp_shift);
365		val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
366			EXYNOS_EMUL_ENABLE;
367	} else {
368		val &= ~EXYNOS_EMUL_ENABLE;
369	}
370
371	writel(val, data->base + reg->emul_con);
372
373	clk_disable(data->clk);
374	mutex_unlock(&data->lock);
375	return 0;
376out:
377	return ret;
378}
379#else
380static int exynos_tmu_set_emulation(void *drv_data,	unsigned long temp)
381	{ return -EINVAL; }
382#endif/*CONFIG_THERMAL_EMULATION*/
383
384static void exynos_tmu_work(struct work_struct *work)
385{
386	struct exynos_tmu_data *data = container_of(work,
387			struct exynos_tmu_data, irq_work);
388	struct exynos_tmu_platform_data *pdata = data->pdata;
389	const struct exynos_tmu_registers *reg = pdata->registers;
390	unsigned int val_irq, val_type;
391
392	if (!IS_ERR(data->clk_sec))
393		clk_enable(data->clk_sec);
394	/* Find which sensor generated this interrupt */
395	if (reg->tmu_irqstatus) {
396		val_type = readl(data->base_second + reg->tmu_irqstatus);
397		if (!((val_type >> data->id) & 0x1))
398			goto out;
399	}
400	if (!IS_ERR(data->clk_sec))
401		clk_disable(data->clk_sec);
402
403	exynos_report_trigger(data->reg_conf);
404	mutex_lock(&data->lock);
405	clk_enable(data->clk);
406
407	/* TODO: take action based on particular interrupt */
408	val_irq = readl(data->base + reg->tmu_intstat);
409	/* clear the interrupts */
410	writel(val_irq, data->base + reg->tmu_intclear);
411
412	clk_disable(data->clk);
413	mutex_unlock(&data->lock);
414out:
415	enable_irq(data->irq);
416}
417
418static irqreturn_t exynos_tmu_irq(int irq, void *id)
419{
420	struct exynos_tmu_data *data = id;
421
422	disable_irq_nosync(irq);
423	schedule_work(&data->irq_work);
424
425	return IRQ_HANDLED;
426}
427
428static const struct of_device_id exynos_tmu_match[] = {
429	{
430		.compatible = "samsung,exynos3250-tmu",
431		.data = (void *)EXYNOS3250_TMU_DRV_DATA,
432	},
433	{
434		.compatible = "samsung,exynos4210-tmu",
435		.data = (void *)EXYNOS4210_TMU_DRV_DATA,
436	},
437	{
438		.compatible = "samsung,exynos4412-tmu",
439		.data = (void *)EXYNOS4412_TMU_DRV_DATA,
440	},
441	{
442		.compatible = "samsung,exynos5250-tmu",
443		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
444	},
445	{
446		.compatible = "samsung,exynos5260-tmu",
447		.data = (void *)EXYNOS5260_TMU_DRV_DATA,
448	},
449	{
450		.compatible = "samsung,exynos5420-tmu",
451		.data = (void *)EXYNOS5420_TMU_DRV_DATA,
452	},
453	{
454		.compatible = "samsung,exynos5420-tmu-ext-triminfo",
455		.data = (void *)EXYNOS5420_TMU_DRV_DATA,
456	},
457	{
458		.compatible = "samsung,exynos5440-tmu",
459		.data = (void *)EXYNOS5440_TMU_DRV_DATA,
460	},
461	{},
462};
463MODULE_DEVICE_TABLE(of, exynos_tmu_match);
464
465static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
466			struct platform_device *pdev, int id)
467{
468	struct  exynos_tmu_init_data *data_table;
469	struct exynos_tmu_platform_data *tmu_data;
470	const struct of_device_id *match;
471
472	match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
473	if (!match)
474		return NULL;
475	data_table = (struct exynos_tmu_init_data *) match->data;
476	if (!data_table || id >= data_table->tmu_count)
477		return NULL;
478	tmu_data = data_table->tmu_data;
479	return (struct exynos_tmu_platform_data *) (tmu_data + id);
480}
481
482static int exynos_map_dt_data(struct platform_device *pdev)
483{
484	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
485	struct exynos_tmu_platform_data *pdata;
486	struct resource res;
487	int ret;
488
489	if (!data || !pdev->dev.of_node)
490		return -ENODEV;
491
492	/*
493	 * Try enabling the regulator if found
494	 * TODO: Add regulator as an SOC feature, so that regulator enable
495	 * is a compulsory call.
496	 */
497	data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
498	if (!IS_ERR(data->regulator)) {
499		ret = regulator_enable(data->regulator);
500		if (ret) {
501			dev_err(&pdev->dev, "failed to enable vtmu\n");
502			return ret;
503		}
504	} else {
505		dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
506	}
507
508	data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
509	if (data->id < 0)
510		data->id = 0;
511
512	data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
513	if (data->irq <= 0) {
514		dev_err(&pdev->dev, "failed to get IRQ\n");
515		return -ENODEV;
516	}
517
518	if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
519		dev_err(&pdev->dev, "failed to get Resource 0\n");
520		return -ENODEV;
521	}
522
523	data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
524	if (!data->base) {
525		dev_err(&pdev->dev, "Failed to ioremap memory\n");
526		return -EADDRNOTAVAIL;
527	}
528
529	pdata = exynos_get_driver_data(pdev, data->id);
530	if (!pdata) {
531		dev_err(&pdev->dev, "No platform init data supplied.\n");
532		return -ENODEV;
533	}
534	data->pdata = pdata;
535	/*
536	 * Check if the TMU shares some registers and then try to map the
537	 * memory of common registers.
538	 */
539	if (!TMU_SUPPORTS(pdata, ADDRESS_MULTIPLE))
540		return 0;
541
542	if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
543		dev_err(&pdev->dev, "failed to get Resource 1\n");
544		return -ENODEV;
545	}
546
547	data->base_second = devm_ioremap(&pdev->dev, res.start,
548					resource_size(&res));
549	if (!data->base_second) {
550		dev_err(&pdev->dev, "Failed to ioremap memory\n");
551		return -ENOMEM;
552	}
553
554	return 0;
555}
556
557static int exynos_tmu_probe(struct platform_device *pdev)
558{
559	struct exynos_tmu_data *data;
560	struct exynos_tmu_platform_data *pdata;
561	struct thermal_sensor_conf *sensor_conf;
562	int ret, i;
563
564	data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
565					GFP_KERNEL);
566	if (!data)
567		return -ENOMEM;
568
569	platform_set_drvdata(pdev, data);
570	mutex_init(&data->lock);
571
572	ret = exynos_map_dt_data(pdev);
573	if (ret)
574		return ret;
575
576	pdata = data->pdata;
577
578	INIT_WORK(&data->irq_work, exynos_tmu_work);
579
580	data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
581	if (IS_ERR(data->clk)) {
582		dev_err(&pdev->dev, "Failed to get clock\n");
583		return  PTR_ERR(data->clk);
584	}
585
586	data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif");
587	if (IS_ERR(data->clk_sec)) {
588		if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) {
589			dev_err(&pdev->dev, "Failed to get triminfo clock\n");
590			return PTR_ERR(data->clk_sec);
591		}
592	} else {
593		ret = clk_prepare(data->clk_sec);
594		if (ret) {
595			dev_err(&pdev->dev, "Failed to get clock\n");
596			return ret;
597		}
598	}
599
600	ret = clk_prepare(data->clk);
601	if (ret) {
602		dev_err(&pdev->dev, "Failed to get clock\n");
603		goto err_clk_sec;
604	}
605
606	if (pdata->type == SOC_ARCH_EXYNOS3250 ||
607	    pdata->type == SOC_ARCH_EXYNOS4210 ||
608	    pdata->type == SOC_ARCH_EXYNOS4412 ||
609	    pdata->type == SOC_ARCH_EXYNOS5250 ||
610	    pdata->type == SOC_ARCH_EXYNOS5260 ||
611	    pdata->type == SOC_ARCH_EXYNOS5420_TRIMINFO ||
612	    pdata->type == SOC_ARCH_EXYNOS5440)
613		data->soc = pdata->type;
614	else {
615		ret = -EINVAL;
616		dev_err(&pdev->dev, "Platform not supported\n");
617		goto err_clk;
618	}
619
620	ret = exynos_tmu_initialize(pdev);
621	if (ret) {
622		dev_err(&pdev->dev, "Failed to initialize TMU\n");
623		goto err_clk;
624	}
625
626	exynos_tmu_control(pdev, true);
627
628	/* Allocate a structure to register with the exynos core thermal */
629	sensor_conf = devm_kzalloc(&pdev->dev,
630				sizeof(struct thermal_sensor_conf), GFP_KERNEL);
631	if (!sensor_conf) {
632		ret = -ENOMEM;
633		goto err_clk;
634	}
635	sprintf(sensor_conf->name, "therm_zone%d", data->id);
636	sensor_conf->read_temperature = (int (*)(void *))exynos_tmu_read;
637	sensor_conf->write_emul_temp =
638		(int (*)(void *, unsigned long))exynos_tmu_set_emulation;
639	sensor_conf->driver_data = data;
640	sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
641			pdata->trigger_enable[1] + pdata->trigger_enable[2]+
642			pdata->trigger_enable[3];
643
644	for (i = 0; i < sensor_conf->trip_data.trip_count; i++) {
645		sensor_conf->trip_data.trip_val[i] =
646			pdata->threshold + pdata->trigger_levels[i];
647		sensor_conf->trip_data.trip_type[i] =
648					pdata->trigger_type[i];
649	}
650
651	sensor_conf->trip_data.trigger_falling = pdata->threshold_falling;
652
653	sensor_conf->cooling_data.freq_clip_count = pdata->freq_tab_count;
654	for (i = 0; i < pdata->freq_tab_count; i++) {
655		sensor_conf->cooling_data.freq_data[i].freq_clip_max =
656					pdata->freq_tab[i].freq_clip_max;
657		sensor_conf->cooling_data.freq_data[i].temp_level =
658					pdata->freq_tab[i].temp_level;
659	}
660	sensor_conf->dev = &pdev->dev;
661	/* Register the sensor with thermal management interface */
662	ret = exynos_register_thermal(sensor_conf);
663	if (ret) {
664		dev_err(&pdev->dev, "Failed to register thermal interface\n");
665		goto err_clk;
666	}
667	data->reg_conf = sensor_conf;
668
669	ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
670		IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
671	if (ret) {
672		dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
673		goto err_clk;
674	}
675
676	return 0;
677err_clk:
678	clk_unprepare(data->clk);
679err_clk_sec:
680	if (!IS_ERR(data->clk_sec))
681		clk_unprepare(data->clk_sec);
682	return ret;
683}
684
685static int exynos_tmu_remove(struct platform_device *pdev)
686{
687	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
688
689	exynos_unregister_thermal(data->reg_conf);
690
691	exynos_tmu_control(pdev, false);
692
693	clk_unprepare(data->clk);
694	if (!IS_ERR(data->clk_sec))
695		clk_unprepare(data->clk_sec);
696
697	if (!IS_ERR(data->regulator))
698		regulator_disable(data->regulator);
699
700	return 0;
701}
702
703#ifdef CONFIG_PM_SLEEP
704static int exynos_tmu_suspend(struct device *dev)
705{
706	exynos_tmu_control(to_platform_device(dev), false);
707
708	return 0;
709}
710
711static int exynos_tmu_resume(struct device *dev)
712{
713	struct platform_device *pdev = to_platform_device(dev);
714
715	exynos_tmu_initialize(pdev);
716	exynos_tmu_control(pdev, true);
717
718	return 0;
719}
720
721static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
722			 exynos_tmu_suspend, exynos_tmu_resume);
723#define EXYNOS_TMU_PM	(&exynos_tmu_pm)
724#else
725#define EXYNOS_TMU_PM	NULL
726#endif
727
728static struct platform_driver exynos_tmu_driver = {
729	.driver = {
730		.name   = "exynos-tmu",
731		.owner  = THIS_MODULE,
732		.pm     = EXYNOS_TMU_PM,
733		.of_match_table = exynos_tmu_match,
734	},
735	.probe = exynos_tmu_probe,
736	.remove	= exynos_tmu_remove,
737};
738
739module_platform_driver(exynos_tmu_driver);
740
741MODULE_DESCRIPTION("EXYNOS TMU Driver");
742MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
743MODULE_LICENSE("GPL");
744MODULE_ALIAS("platform:exynos-tmu");
745