1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * exynos_tmu.c - Samsung Exynos TMU (Thermal Management Unit)
4 *
5 *  Copyright (C) 2014 Samsung Electronics
6 *  Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
7 *  Lukasz Majewski <l.majewski@samsung.com>
8 *
9 *  Copyright (C) 2011 Samsung Electronics
10 *  Donggeun Kim <dg77.kim@samsung.com>
11 *  Amit Daniel Kachhap <amit.kachhap@linaro.org>
12 */
13
14#include <linux/clk.h>
15#include <linux/io.h>
16#include <linux/interrupt.h>
17#include <linux/module.h>
18#include <linux/of_device.h>
19#include <linux/of_address.h>
20#include <linux/of_irq.h>
21#include <linux/platform_device.h>
22#include <linux/regulator/consumer.h>
23
24#include <dt-bindings/thermal/thermal_exynos.h>
25
26#include "../thermal_core.h"
27
28/* Exynos generic registers */
29#define EXYNOS_TMU_REG_TRIMINFO		0x0
30#define EXYNOS_TMU_REG_CONTROL		0x20
31#define EXYNOS_TMU_REG_STATUS		0x28
32#define EXYNOS_TMU_REG_CURRENT_TEMP	0x40
33#define EXYNOS_TMU_REG_INTEN		0x70
34#define EXYNOS_TMU_REG_INTSTAT		0x74
35#define EXYNOS_TMU_REG_INTCLEAR		0x78
36
37#define EXYNOS_TMU_TEMP_MASK		0xff
38#define EXYNOS_TMU_REF_VOLTAGE_SHIFT	24
39#define EXYNOS_TMU_REF_VOLTAGE_MASK	0x1f
40#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK	0xf
41#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT	8
42#define EXYNOS_TMU_CORE_EN_SHIFT	0
43
44/* Exynos3250 specific registers */
45#define EXYNOS_TMU_TRIMINFO_CON1	0x10
46
47/* Exynos4210 specific registers */
48#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP	0x44
49#define EXYNOS4210_TMU_REG_TRIG_LEVEL0	0x50
50
51/* Exynos5250, Exynos4412, Exynos3250 specific registers */
52#define EXYNOS_TMU_TRIMINFO_CON2	0x14
53#define EXYNOS_THD_TEMP_RISE		0x50
54#define EXYNOS_THD_TEMP_FALL		0x54
55#define EXYNOS_EMUL_CON		0x80
56
57#define EXYNOS_TRIMINFO_RELOAD_ENABLE	1
58#define EXYNOS_TRIMINFO_25_SHIFT	0
59#define EXYNOS_TRIMINFO_85_SHIFT	8
60#define EXYNOS_TMU_TRIP_MODE_SHIFT	13
61#define EXYNOS_TMU_TRIP_MODE_MASK	0x7
62#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT	12
63
64#define EXYNOS_TMU_INTEN_RISE0_SHIFT	0
65#define EXYNOS_TMU_INTEN_FALL0_SHIFT	16
66
67#define EXYNOS_EMUL_TIME	0x57F0
68#define EXYNOS_EMUL_TIME_MASK	0xffff
69#define EXYNOS_EMUL_TIME_SHIFT	16
70#define EXYNOS_EMUL_DATA_SHIFT	8
71#define EXYNOS_EMUL_DATA_MASK	0xFF
72#define EXYNOS_EMUL_ENABLE	0x1
73
74/* Exynos5260 specific */
75#define EXYNOS5260_TMU_REG_INTEN		0xC0
76#define EXYNOS5260_TMU_REG_INTSTAT		0xC4
77#define EXYNOS5260_TMU_REG_INTCLEAR		0xC8
78#define EXYNOS5260_EMUL_CON			0x100
79
80/* Exynos4412 specific */
81#define EXYNOS4412_MUX_ADDR_VALUE          6
82#define EXYNOS4412_MUX_ADDR_SHIFT          20
83
84/* Exynos5433 specific registers */
85#define EXYNOS5433_THD_TEMP_RISE3_0		0x050
86#define EXYNOS5433_THD_TEMP_RISE7_4		0x054
87#define EXYNOS5433_THD_TEMP_FALL3_0		0x060
88#define EXYNOS5433_THD_TEMP_FALL7_4		0x064
89#define EXYNOS5433_TMU_REG_INTEN		0x0c0
90#define EXYNOS5433_TMU_REG_INTPEND		0x0c8
91#define EXYNOS5433_TMU_EMUL_CON			0x110
92#define EXYNOS5433_TMU_PD_DET_EN		0x130
93
94#define EXYNOS5433_TRIMINFO_SENSOR_ID_SHIFT	16
95#define EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT	23
96#define EXYNOS5433_TRIMINFO_SENSOR_ID_MASK	\
97			(0xf << EXYNOS5433_TRIMINFO_SENSOR_ID_SHIFT)
98#define EXYNOS5433_TRIMINFO_CALIB_SEL_MASK	BIT(23)
99
100#define EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING	0
101#define EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING	1
102
103#define EXYNOS5433_PD_DET_EN			1
104
105#define EXYNOS5433_G3D_BASE			0x10070000
106
107/* Exynos7 specific registers */
108#define EXYNOS7_THD_TEMP_RISE7_6		0x50
109#define EXYNOS7_THD_TEMP_FALL7_6		0x60
110#define EXYNOS7_TMU_REG_INTEN			0x110
111#define EXYNOS7_TMU_REG_INTPEND			0x118
112#define EXYNOS7_TMU_REG_EMUL_CON		0x160
113
114#define EXYNOS7_TMU_TEMP_MASK			0x1ff
115#define EXYNOS7_PD_DET_EN_SHIFT			23
116#define EXYNOS7_TMU_INTEN_RISE0_SHIFT		0
117#define EXYNOS7_EMUL_DATA_SHIFT			7
118#define EXYNOS7_EMUL_DATA_MASK			0x1ff
119
120#define EXYNOS_FIRST_POINT_TRIM			25
121#define EXYNOS_SECOND_POINT_TRIM		85
122
123#define EXYNOS_NOISE_CANCEL_MODE		4
124
125#define MCELSIUS	1000
126
127enum soc_type {
128	SOC_ARCH_EXYNOS3250 = 1,
129	SOC_ARCH_EXYNOS4210,
130	SOC_ARCH_EXYNOS4412,
131	SOC_ARCH_EXYNOS5250,
132	SOC_ARCH_EXYNOS5260,
133	SOC_ARCH_EXYNOS5420,
134	SOC_ARCH_EXYNOS5420_TRIMINFO,
135	SOC_ARCH_EXYNOS5433,
136	SOC_ARCH_EXYNOS7,
137};
138
139/**
140 * struct exynos_tmu_data : A structure to hold the private data of the TMU
141 *			    driver
142 * @id: identifier of the one instance of the TMU controller.
143 * @base: base address of the single instance of the TMU controller.
144 * @base_second: base address of the common registers of the TMU controller.
145 * @irq: irq number of the TMU controller.
146 * @soc: id of the SOC type.
147 * @irq_work: pointer to the irq work structure.
148 * @lock: lock to implement synchronization.
149 * @clk: pointer to the clock structure.
150 * @clk_sec: pointer to the clock structure for accessing the base_second.
151 * @sclk: pointer to the clock structure for accessing the tmu special clk.
152 * @cal_type: calibration type for temperature
153 * @efuse_value: SoC defined fuse value
154 * @min_efuse_value: minimum valid trimming data
155 * @max_efuse_value: maximum valid trimming data
156 * @temp_error1: fused value of the first point trim.
157 * @temp_error2: fused value of the second point trim.
158 * @gain: gain of amplifier in the positive-TC generator block
159 *	0 < gain <= 15
160 * @reference_voltage: reference voltage of amplifier
161 *	in the positive-TC generator block
162 *	0 < reference_voltage <= 31
163 * @regulator: pointer to the TMU regulator structure.
164 * @reg_conf: pointer to structure to register with core thermal.
165 * @tzd: pointer to thermal_zone_device structure
166 * @ntrip: number of supported trip points.
167 * @enabled: current status of TMU device
168 * @tmu_set_trip_temp: SoC specific method to set trip (rising threshold)
169 * @tmu_set_trip_hyst: SoC specific to set hysteresis (falling threshold)
170 * @tmu_initialize: SoC specific TMU initialization method
171 * @tmu_control: SoC specific TMU control method
172 * @tmu_read: SoC specific TMU temperature read method
173 * @tmu_set_emulation: SoC specific TMU emulation setting method
174 * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
175 */
176struct exynos_tmu_data {
177	int id;
178	void __iomem *base;
179	void __iomem *base_second;
180	int irq;
181	enum soc_type soc;
182	struct work_struct irq_work;
183	struct mutex lock;
184	struct clk *clk, *clk_sec, *sclk;
185	u32 cal_type;
186	u32 efuse_value;
187	u32 min_efuse_value;
188	u32 max_efuse_value;
189	u16 temp_error1, temp_error2;
190	u8 gain;
191	u8 reference_voltage;
192	struct regulator *regulator;
193	struct thermal_zone_device *tzd;
194	unsigned int ntrip;
195	bool enabled;
196
197	void (*tmu_set_trip_temp)(struct exynos_tmu_data *data, int trip,
198				 u8 temp);
199	void (*tmu_set_trip_hyst)(struct exynos_tmu_data *data, int trip,
200				 u8 temp, u8 hyst);
201	void (*tmu_initialize)(struct platform_device *pdev);
202	void (*tmu_control)(struct platform_device *pdev, bool on);
203	int (*tmu_read)(struct exynos_tmu_data *data);
204	void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp);
205	void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
206};
207
208/*
209 * TMU treats temperature as a mapped temperature code.
210 * The temperature is converted differently depending on the calibration type.
211 */
212static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
213{
214	if (data->cal_type == TYPE_ONE_POINT_TRIMMING)
215		return temp + data->temp_error1 - EXYNOS_FIRST_POINT_TRIM;
216
217	return (temp - EXYNOS_FIRST_POINT_TRIM) *
218		(data->temp_error2 - data->temp_error1) /
219		(EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) +
220		data->temp_error1;
221}
222
223/*
224 * Calculate a temperature value from a temperature code.
225 * The unit of the temperature is degree Celsius.
226 */
227static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code)
228{
229	if (data->cal_type == TYPE_ONE_POINT_TRIMMING)
230		return temp_code - data->temp_error1 + EXYNOS_FIRST_POINT_TRIM;
231
232	return (temp_code - data->temp_error1) *
233		(EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) /
234		(data->temp_error2 - data->temp_error1) +
235		EXYNOS_FIRST_POINT_TRIM;
236}
237
238static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
239{
240	u16 tmu_temp_mask =
241		(data->soc == SOC_ARCH_EXYNOS7) ? EXYNOS7_TMU_TEMP_MASK
242						: EXYNOS_TMU_TEMP_MASK;
243
244	data->temp_error1 = trim_info & tmu_temp_mask;
245	data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
246				EXYNOS_TMU_TEMP_MASK);
247
248	if (!data->temp_error1 ||
249	    (data->min_efuse_value > data->temp_error1) ||
250	    (data->temp_error1 > data->max_efuse_value))
251		data->temp_error1 = data->efuse_value & EXYNOS_TMU_TEMP_MASK;
252
253	if (!data->temp_error2)
254		data->temp_error2 =
255			(data->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
256			EXYNOS_TMU_TEMP_MASK;
257}
258
259static int exynos_tmu_initialize(struct platform_device *pdev)
260{
261	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
262	struct thermal_zone_device *tzd = data->tzd;
263	const struct thermal_trip * const trips =
264		of_thermal_get_trip_points(tzd);
265	unsigned int status;
266	int ret = 0, temp, hyst;
267
268	if (!trips) {
269		dev_err(&pdev->dev,
270			"Cannot get trip points from device tree!\n");
271		return -ENODEV;
272	}
273
274	if (data->soc != SOC_ARCH_EXYNOS5433) /* FIXME */
275		ret = tzd->ops->get_crit_temp(tzd, &temp);
276	if (ret) {
277		dev_err(&pdev->dev,
278			"No CRITICAL trip point defined in device tree!\n");
279		goto out;
280	}
281
282	if (of_thermal_get_ntrips(tzd) > data->ntrip) {
283		dev_info(&pdev->dev,
284			 "More trip points than supported by this TMU.\n");
285		dev_info(&pdev->dev,
286			 "%d trip points should be configured in polling mode.\n",
287			 (of_thermal_get_ntrips(tzd) - data->ntrip));
288	}
289
290	mutex_lock(&data->lock);
291	clk_enable(data->clk);
292	if (!IS_ERR(data->clk_sec))
293		clk_enable(data->clk_sec);
294
295	status = readb(data->base + EXYNOS_TMU_REG_STATUS);
296	if (!status) {
297		ret = -EBUSY;
298	} else {
299		int i, ntrips =
300			min_t(int, of_thermal_get_ntrips(tzd), data->ntrip);
301
302		data->tmu_initialize(pdev);
303
304		/* Write temperature code for rising and falling threshold */
305		for (i = 0; i < ntrips; i++) {
306			/* Write temperature code for rising threshold */
307			ret = tzd->ops->get_trip_temp(tzd, i, &temp);
308			if (ret)
309				goto err;
310			temp /= MCELSIUS;
311			data->tmu_set_trip_temp(data, i, temp);
312
313			/* Write temperature code for falling threshold */
314			ret = tzd->ops->get_trip_hyst(tzd, i, &hyst);
315			if (ret)
316				goto err;
317			hyst /= MCELSIUS;
318			data->tmu_set_trip_hyst(data, i, temp, hyst);
319		}
320
321		data->tmu_clear_irqs(data);
322	}
323err:
324	clk_disable(data->clk);
325	mutex_unlock(&data->lock);
326	if (!IS_ERR(data->clk_sec))
327		clk_disable(data->clk_sec);
328out:
329	return ret;
330}
331
332static u32 get_con_reg(struct exynos_tmu_data *data, u32 con)
333{
334	if (data->soc == SOC_ARCH_EXYNOS4412 ||
335	    data->soc == SOC_ARCH_EXYNOS3250)
336		con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT);
337
338	con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT);
339	con |= data->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
340
341	con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
342	con |= (data->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
343
344	con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT);
345	con |= (EXYNOS_NOISE_CANCEL_MODE << EXYNOS_TMU_TRIP_MODE_SHIFT);
346
347	return con;
348}
349
350static void exynos_tmu_control(struct platform_device *pdev, bool on)
351{
352	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
353
354	mutex_lock(&data->lock);
355	clk_enable(data->clk);
356	data->tmu_control(pdev, on);
357	data->enabled = on;
358	clk_disable(data->clk);
359	mutex_unlock(&data->lock);
360}
361
362static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data,
363					 int trip, u8 temp)
364{
365	const struct thermal_trip * const trips =
366		of_thermal_get_trip_points(data->tzd);
367	u8 ref, th_code;
368
369	ref = trips[0].temperature / MCELSIUS;
370
371	if (trip == 0) {
372		th_code = temp_to_code(data, ref);
373		writeb(th_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
374	}
375
376	temp -= ref;
377	writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip * 4);
378}
379
380/* failing thresholds are not supported on Exynos4210 */
381static void exynos4210_tmu_set_trip_hyst(struct exynos_tmu_data *data,
382					 int trip, u8 temp, u8 hyst)
383{
384}
385
386static void exynos4210_tmu_initialize(struct platform_device *pdev)
387{
388	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
389
390	sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
391}
392
393static void exynos4412_tmu_set_trip_temp(struct exynos_tmu_data *data,
394					 int trip, u8 temp)
395{
396	u32 th, con;
397
398	th = readl(data->base + EXYNOS_THD_TEMP_RISE);
399	th &= ~(0xff << 8 * trip);
400	th |= temp_to_code(data, temp) << 8 * trip;
401	writel(th, data->base + EXYNOS_THD_TEMP_RISE);
402
403	if (trip == 3) {
404		con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
405		con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
406		writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
407	}
408}
409
410static void exynos4412_tmu_set_trip_hyst(struct exynos_tmu_data *data,
411					 int trip, u8 temp, u8 hyst)
412{
413	u32 th;
414
415	th = readl(data->base + EXYNOS_THD_TEMP_FALL);
416	th &= ~(0xff << 8 * trip);
417	if (hyst)
418		th |= temp_to_code(data, temp - hyst) << 8 * trip;
419	writel(th, data->base + EXYNOS_THD_TEMP_FALL);
420}
421
422static void exynos4412_tmu_initialize(struct platform_device *pdev)
423{
424	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
425	unsigned int trim_info, ctrl;
426
427	if (data->soc == SOC_ARCH_EXYNOS3250 ||
428	    data->soc == SOC_ARCH_EXYNOS4412 ||
429	    data->soc == SOC_ARCH_EXYNOS5250) {
430		if (data->soc == SOC_ARCH_EXYNOS3250) {
431			ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON1);
432			ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
433			writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON1);
434		}
435		ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON2);
436		ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
437		writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON2);
438	}
439
440	/* On exynos5420 the triminfo register is in the shared space */
441	if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
442		trim_info = readl(data->base_second + EXYNOS_TMU_REG_TRIMINFO);
443	else
444		trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
445
446	sanitize_temp_error(data, trim_info);
447}
448
449static void exynos5433_tmu_set_trip_temp(struct exynos_tmu_data *data,
450					 int trip, u8 temp)
451{
452	unsigned int reg_off, j;
453	u32 th;
454
455	if (trip > 3) {
456		reg_off = EXYNOS5433_THD_TEMP_RISE7_4;
457		j = trip - 4;
458	} else {
459		reg_off = EXYNOS5433_THD_TEMP_RISE3_0;
460		j = trip;
461	}
462
463	th = readl(data->base + reg_off);
464	th &= ~(0xff << j * 8);
465	th |= (temp_to_code(data, temp) << j * 8);
466	writel(th, data->base + reg_off);
467}
468
469static void exynos5433_tmu_set_trip_hyst(struct exynos_tmu_data *data,
470					 int trip, u8 temp, u8 hyst)
471{
472	unsigned int reg_off, j;
473	u32 th;
474
475	if (trip > 3) {
476		reg_off = EXYNOS5433_THD_TEMP_FALL7_4;
477		j = trip - 4;
478	} else {
479		reg_off = EXYNOS5433_THD_TEMP_FALL3_0;
480		j = trip;
481	}
482
483	th = readl(data->base + reg_off);
484	th &= ~(0xff << j * 8);
485	th |= (temp_to_code(data, temp - hyst) << j * 8);
486	writel(th, data->base + reg_off);
487}
488
489static void exynos5433_tmu_initialize(struct platform_device *pdev)
490{
491	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
492	unsigned int trim_info;
493	int sensor_id, cal_type;
494
495	trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
496	sanitize_temp_error(data, trim_info);
497
498	/* Read the temperature sensor id */
499	sensor_id = (trim_info & EXYNOS5433_TRIMINFO_SENSOR_ID_MASK)
500				>> EXYNOS5433_TRIMINFO_SENSOR_ID_SHIFT;
501	dev_info(&pdev->dev, "Temperature sensor ID: 0x%x\n", sensor_id);
502
503	/* Read the calibration mode */
504	writel(trim_info, data->base + EXYNOS_TMU_REG_TRIMINFO);
505	cal_type = (trim_info & EXYNOS5433_TRIMINFO_CALIB_SEL_MASK)
506				>> EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT;
507
508	switch (cal_type) {
509	case EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING:
510		data->cal_type = TYPE_TWO_POINT_TRIMMING;
511		break;
512	case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING:
513	default:
514		data->cal_type = TYPE_ONE_POINT_TRIMMING;
515		break;
516	}
517
518	dev_info(&pdev->dev, "Calibration type is %d-point calibration\n",
519			cal_type ?  2 : 1);
520}
521
522static void exynos7_tmu_set_trip_temp(struct exynos_tmu_data *data,
523				      int trip, u8 temp)
524{
525	unsigned int reg_off, bit_off;
526	u32 th;
527
528	reg_off = ((7 - trip) / 2) * 4;
529	bit_off = ((8 - trip) % 2);
530
531	th = readl(data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
532	th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
533	th |= temp_to_code(data, temp) << (16 * bit_off);
534	writel(th, data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
535}
536
537static void exynos7_tmu_set_trip_hyst(struct exynos_tmu_data *data,
538				      int trip, u8 temp, u8 hyst)
539{
540	unsigned int reg_off, bit_off;
541	u32 th;
542
543	reg_off = ((7 - trip) / 2) * 4;
544	bit_off = ((8 - trip) % 2);
545
546	th = readl(data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
547	th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
548	th |= temp_to_code(data, temp - hyst) << (16 * bit_off);
549	writel(th, data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
550}
551
552static void exynos7_tmu_initialize(struct platform_device *pdev)
553{
554	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
555	unsigned int trim_info;
556
557	trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
558	sanitize_temp_error(data, trim_info);
559}
560
561static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
562{
563	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
564	struct thermal_zone_device *tz = data->tzd;
565	unsigned int con, interrupt_en = 0, i;
566
567	con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
568
569	if (on) {
570		for (i = 0; i < data->ntrip; i++) {
571			if (!of_thermal_is_trip_valid(tz, i))
572				continue;
573
574			interrupt_en |=
575				(1 << (EXYNOS_TMU_INTEN_RISE0_SHIFT + i * 4));
576		}
577
578		if (data->soc != SOC_ARCH_EXYNOS4210)
579			interrupt_en |=
580				interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
581
582		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
583	} else {
584		con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
585	}
586
587	writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
588	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
589}
590
591static void exynos5433_tmu_control(struct platform_device *pdev, bool on)
592{
593	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
594	struct thermal_zone_device *tz = data->tzd;
595	unsigned int con, interrupt_en = 0, pd_det_en, i;
596
597	con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
598
599	if (on) {
600		for (i = 0; i < data->ntrip; i++) {
601			if (!of_thermal_is_trip_valid(tz, i))
602				continue;
603
604			interrupt_en |=
605				(1 << (EXYNOS7_TMU_INTEN_RISE0_SHIFT + i));
606		}
607
608		interrupt_en |=
609			interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
610
611		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
612	} else
613		con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
614
615	pd_det_en = on ? EXYNOS5433_PD_DET_EN : 0;
616
617	writel(pd_det_en, data->base + EXYNOS5433_TMU_PD_DET_EN);
618	writel(interrupt_en, data->base + EXYNOS5433_TMU_REG_INTEN);
619	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
620}
621
622static void exynos7_tmu_control(struct platform_device *pdev, bool on)
623{
624	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
625	struct thermal_zone_device *tz = data->tzd;
626	unsigned int con, interrupt_en = 0, i;
627
628	con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
629
630	if (on) {
631		for (i = 0; i < data->ntrip; i++) {
632			if (!of_thermal_is_trip_valid(tz, i))
633				continue;
634
635			interrupt_en |=
636				(1 << (EXYNOS7_TMU_INTEN_RISE0_SHIFT + i));
637		}
638
639		interrupt_en |=
640			interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
641
642		con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
643		con |= (1 << EXYNOS7_PD_DET_EN_SHIFT);
644	} else {
645		con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
646		con &= ~(1 << EXYNOS7_PD_DET_EN_SHIFT);
647	}
648
649	writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN);
650	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
651}
652
653static int exynos_get_temp(void *p, int *temp)
654{
655	struct exynos_tmu_data *data = p;
656	int value, ret = 0;
657
658	if (!data || !data->tmu_read)
659		return -EINVAL;
660	else if (!data->enabled)
661		/*
662		 * Called too early, probably
663		 * from thermal_zone_of_sensor_register().
664		 */
665		return -EAGAIN;
666
667	mutex_lock(&data->lock);
668	clk_enable(data->clk);
669
670	value = data->tmu_read(data);
671	if (value < 0)
672		ret = value;
673	else
674		*temp = code_to_temp(data, value) * MCELSIUS;
675
676	clk_disable(data->clk);
677	mutex_unlock(&data->lock);
678
679	return ret;
680}
681
682#ifdef CONFIG_THERMAL_EMULATION
683static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
684			    int temp)
685{
686	if (temp) {
687		temp /= MCELSIUS;
688
689		val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
690		val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
691		if (data->soc == SOC_ARCH_EXYNOS7) {
692			val &= ~(EXYNOS7_EMUL_DATA_MASK <<
693				EXYNOS7_EMUL_DATA_SHIFT);
694			val |= (temp_to_code(data, temp) <<
695				EXYNOS7_EMUL_DATA_SHIFT) |
696				EXYNOS_EMUL_ENABLE;
697		} else {
698			val &= ~(EXYNOS_EMUL_DATA_MASK <<
699				EXYNOS_EMUL_DATA_SHIFT);
700			val |= (temp_to_code(data, temp) <<
701				EXYNOS_EMUL_DATA_SHIFT) |
702				EXYNOS_EMUL_ENABLE;
703		}
704	} else {
705		val &= ~EXYNOS_EMUL_ENABLE;
706	}
707
708	return val;
709}
710
711static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
712					 int temp)
713{
714	unsigned int val;
715	u32 emul_con;
716
717	if (data->soc == SOC_ARCH_EXYNOS5260)
718		emul_con = EXYNOS5260_EMUL_CON;
719	else if (data->soc == SOC_ARCH_EXYNOS5433)
720		emul_con = EXYNOS5433_TMU_EMUL_CON;
721	else if (data->soc == SOC_ARCH_EXYNOS7)
722		emul_con = EXYNOS7_TMU_REG_EMUL_CON;
723	else
724		emul_con = EXYNOS_EMUL_CON;
725
726	val = readl(data->base + emul_con);
727	val = get_emul_con_reg(data, val, temp);
728	writel(val, data->base + emul_con);
729}
730
731static int exynos_tmu_set_emulation(void *drv_data, int temp)
732{
733	struct exynos_tmu_data *data = drv_data;
734	int ret = -EINVAL;
735
736	if (data->soc == SOC_ARCH_EXYNOS4210)
737		goto out;
738
739	if (temp && temp < MCELSIUS)
740		goto out;
741
742	mutex_lock(&data->lock);
743	clk_enable(data->clk);
744	data->tmu_set_emulation(data, temp);
745	clk_disable(data->clk);
746	mutex_unlock(&data->lock);
747	return 0;
748out:
749	return ret;
750}
751#else
752#define exynos4412_tmu_set_emulation NULL
753static int exynos_tmu_set_emulation(void *drv_data, int temp)
754	{ return -EINVAL; }
755#endif /* CONFIG_THERMAL_EMULATION */
756
757static int exynos4210_tmu_read(struct exynos_tmu_data *data)
758{
759	int ret = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
760
761	/* "temp_code" should range between 75 and 175 */
762	return (ret < 75 || ret > 175) ? -ENODATA : ret;
763}
764
765static int exynos4412_tmu_read(struct exynos_tmu_data *data)
766{
767	return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
768}
769
770static int exynos7_tmu_read(struct exynos_tmu_data *data)
771{
772	return readw(data->base + EXYNOS_TMU_REG_CURRENT_TEMP) &
773		EXYNOS7_TMU_TEMP_MASK;
774}
775
776static void exynos_tmu_work(struct work_struct *work)
777{
778	struct exynos_tmu_data *data = container_of(work,
779			struct exynos_tmu_data, irq_work);
780
781	thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED);
782
783	mutex_lock(&data->lock);
784	clk_enable(data->clk);
785
786	/* TODO: take action based on particular interrupt */
787	data->tmu_clear_irqs(data);
788
789	clk_disable(data->clk);
790	mutex_unlock(&data->lock);
791	enable_irq(data->irq);
792}
793
794static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data)
795{
796	unsigned int val_irq;
797	u32 tmu_intstat, tmu_intclear;
798
799	if (data->soc == SOC_ARCH_EXYNOS5260) {
800		tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
801		tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR;
802	} else if (data->soc == SOC_ARCH_EXYNOS7) {
803		tmu_intstat = EXYNOS7_TMU_REG_INTPEND;
804		tmu_intclear = EXYNOS7_TMU_REG_INTPEND;
805	} else if (data->soc == SOC_ARCH_EXYNOS5433) {
806		tmu_intstat = EXYNOS5433_TMU_REG_INTPEND;
807		tmu_intclear = EXYNOS5433_TMU_REG_INTPEND;
808	} else {
809		tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
810		tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
811	}
812
813	val_irq = readl(data->base + tmu_intstat);
814	/*
815	 * Clear the interrupts.  Please note that the documentation for
816	 * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
817	 * states that INTCLEAR register has a different placing of bits
818	 * responsible for FALL IRQs than INTSTAT register.  Exynos5420
819	 * and Exynos5440 documentation is correct (Exynos4210 doesn't
820	 * support FALL IRQs at all).
821	 */
822	writel(val_irq, data->base + tmu_intclear);
823}
824
825static irqreturn_t exynos_tmu_irq(int irq, void *id)
826{
827	struct exynos_tmu_data *data = id;
828
829	disable_irq_nosync(irq);
830	schedule_work(&data->irq_work);
831
832	return IRQ_HANDLED;
833}
834
835static const struct of_device_id exynos_tmu_match[] = {
836	{
837		.compatible = "samsung,exynos3250-tmu",
838		.data = (const void *)SOC_ARCH_EXYNOS3250,
839	}, {
840		.compatible = "samsung,exynos4210-tmu",
841		.data = (const void *)SOC_ARCH_EXYNOS4210,
842	}, {
843		.compatible = "samsung,exynos4412-tmu",
844		.data = (const void *)SOC_ARCH_EXYNOS4412,
845	}, {
846		.compatible = "samsung,exynos5250-tmu",
847		.data = (const void *)SOC_ARCH_EXYNOS5250,
848	}, {
849		.compatible = "samsung,exynos5260-tmu",
850		.data = (const void *)SOC_ARCH_EXYNOS5260,
851	}, {
852		.compatible = "samsung,exynos5420-tmu",
853		.data = (const void *)SOC_ARCH_EXYNOS5420,
854	}, {
855		.compatible = "samsung,exynos5420-tmu-ext-triminfo",
856		.data = (const void *)SOC_ARCH_EXYNOS5420_TRIMINFO,
857	}, {
858		.compatible = "samsung,exynos5433-tmu",
859		.data = (const void *)SOC_ARCH_EXYNOS5433,
860	}, {
861		.compatible = "samsung,exynos7-tmu",
862		.data = (const void *)SOC_ARCH_EXYNOS7,
863	},
864	{ },
865};
866MODULE_DEVICE_TABLE(of, exynos_tmu_match);
867
868static int exynos_map_dt_data(struct platform_device *pdev)
869{
870	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
871	struct resource res;
872
873	if (!data || !pdev->dev.of_node)
874		return -ENODEV;
875
876	data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
877	if (data->id < 0)
878		data->id = 0;
879
880	data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
881	if (data->irq <= 0) {
882		dev_err(&pdev->dev, "failed to get IRQ\n");
883		return -ENODEV;
884	}
885
886	if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
887		dev_err(&pdev->dev, "failed to get Resource 0\n");
888		return -ENODEV;
889	}
890
891	data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
892	if (!data->base) {
893		dev_err(&pdev->dev, "Failed to ioremap memory\n");
894		return -EADDRNOTAVAIL;
895	}
896
897	data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev);
898
899	switch (data->soc) {
900	case SOC_ARCH_EXYNOS4210:
901		data->tmu_set_trip_temp = exynos4210_tmu_set_trip_temp;
902		data->tmu_set_trip_hyst = exynos4210_tmu_set_trip_hyst;
903		data->tmu_initialize = exynos4210_tmu_initialize;
904		data->tmu_control = exynos4210_tmu_control;
905		data->tmu_read = exynos4210_tmu_read;
906		data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
907		data->ntrip = 4;
908		data->gain = 15;
909		data->reference_voltage = 7;
910		data->efuse_value = 55;
911		data->min_efuse_value = 40;
912		data->max_efuse_value = 100;
913		break;
914	case SOC_ARCH_EXYNOS3250:
915	case SOC_ARCH_EXYNOS4412:
916	case SOC_ARCH_EXYNOS5250:
917	case SOC_ARCH_EXYNOS5260:
918	case SOC_ARCH_EXYNOS5420:
919	case SOC_ARCH_EXYNOS5420_TRIMINFO:
920		data->tmu_set_trip_temp = exynos4412_tmu_set_trip_temp;
921		data->tmu_set_trip_hyst = exynos4412_tmu_set_trip_hyst;
922		data->tmu_initialize = exynos4412_tmu_initialize;
923		data->tmu_control = exynos4210_tmu_control;
924		data->tmu_read = exynos4412_tmu_read;
925		data->tmu_set_emulation = exynos4412_tmu_set_emulation;
926		data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
927		data->ntrip = 4;
928		data->gain = 8;
929		data->reference_voltage = 16;
930		data->efuse_value = 55;
931		if (data->soc != SOC_ARCH_EXYNOS5420 &&
932		    data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO)
933			data->min_efuse_value = 40;
934		else
935			data->min_efuse_value = 0;
936		data->max_efuse_value = 100;
937		break;
938	case SOC_ARCH_EXYNOS5433:
939		data->tmu_set_trip_temp = exynos5433_tmu_set_trip_temp;
940		data->tmu_set_trip_hyst = exynos5433_tmu_set_trip_hyst;
941		data->tmu_initialize = exynos5433_tmu_initialize;
942		data->tmu_control = exynos5433_tmu_control;
943		data->tmu_read = exynos4412_tmu_read;
944		data->tmu_set_emulation = exynos4412_tmu_set_emulation;
945		data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
946		data->ntrip = 8;
947		data->gain = 8;
948		if (res.start == EXYNOS5433_G3D_BASE)
949			data->reference_voltage = 23;
950		else
951			data->reference_voltage = 16;
952		data->efuse_value = 75;
953		data->min_efuse_value = 40;
954		data->max_efuse_value = 150;
955		break;
956	case SOC_ARCH_EXYNOS7:
957		data->tmu_set_trip_temp = exynos7_tmu_set_trip_temp;
958		data->tmu_set_trip_hyst = exynos7_tmu_set_trip_hyst;
959		data->tmu_initialize = exynos7_tmu_initialize;
960		data->tmu_control = exynos7_tmu_control;
961		data->tmu_read = exynos7_tmu_read;
962		data->tmu_set_emulation = exynos4412_tmu_set_emulation;
963		data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
964		data->ntrip = 8;
965		data->gain = 9;
966		data->reference_voltage = 17;
967		data->efuse_value = 75;
968		data->min_efuse_value = 15;
969		data->max_efuse_value = 100;
970		break;
971	default:
972		dev_err(&pdev->dev, "Platform not supported\n");
973		return -EINVAL;
974	}
975
976	data->cal_type = TYPE_ONE_POINT_TRIMMING;
977
978	/*
979	 * Check if the TMU shares some registers and then try to map the
980	 * memory of common registers.
981	 */
982	if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO)
983		return 0;
984
985	if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
986		dev_err(&pdev->dev, "failed to get Resource 1\n");
987		return -ENODEV;
988	}
989
990	data->base_second = devm_ioremap(&pdev->dev, res.start,
991					resource_size(&res));
992	if (!data->base_second) {
993		dev_err(&pdev->dev, "Failed to ioremap memory\n");
994		return -ENOMEM;
995	}
996
997	return 0;
998}
999
1000static const struct thermal_zone_of_device_ops exynos_sensor_ops = {
1001	.get_temp = exynos_get_temp,
1002	.set_emul_temp = exynos_tmu_set_emulation,
1003};
1004
1005static int exynos_tmu_probe(struct platform_device *pdev)
1006{
1007	struct exynos_tmu_data *data;
1008	int ret;
1009
1010	data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
1011					GFP_KERNEL);
1012	if (!data)
1013		return -ENOMEM;
1014
1015	platform_set_drvdata(pdev, data);
1016	mutex_init(&data->lock);
1017
1018	/*
1019	 * Try enabling the regulator if found
1020	 * TODO: Add regulator as an SOC feature, so that regulator enable
1021	 * is a compulsory call.
1022	 */
1023	data->regulator = devm_regulator_get_optional(&pdev->dev, "vtmu");
1024	if (!IS_ERR(data->regulator)) {
1025		ret = regulator_enable(data->regulator);
1026		if (ret) {
1027			dev_err(&pdev->dev, "failed to enable vtmu\n");
1028			return ret;
1029		}
1030	} else {
1031		if (PTR_ERR(data->regulator) == -EPROBE_DEFER)
1032			return -EPROBE_DEFER;
1033		dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
1034	}
1035
1036	ret = exynos_map_dt_data(pdev);
1037	if (ret)
1038		goto err_sensor;
1039
1040	INIT_WORK(&data->irq_work, exynos_tmu_work);
1041
1042	data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
1043	if (IS_ERR(data->clk)) {
1044		dev_err(&pdev->dev, "Failed to get clock\n");
1045		ret = PTR_ERR(data->clk);
1046		goto err_sensor;
1047	}
1048
1049	data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif");
1050	if (IS_ERR(data->clk_sec)) {
1051		if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) {
1052			dev_err(&pdev->dev, "Failed to get triminfo clock\n");
1053			ret = PTR_ERR(data->clk_sec);
1054			goto err_sensor;
1055		}
1056	} else {
1057		ret = clk_prepare(data->clk_sec);
1058		if (ret) {
1059			dev_err(&pdev->dev, "Failed to get clock\n");
1060			goto err_sensor;
1061		}
1062	}
1063
1064	ret = clk_prepare(data->clk);
1065	if (ret) {
1066		dev_err(&pdev->dev, "Failed to get clock\n");
1067		goto err_clk_sec;
1068	}
1069
1070	switch (data->soc) {
1071	case SOC_ARCH_EXYNOS5433:
1072	case SOC_ARCH_EXYNOS7:
1073		data->sclk = devm_clk_get(&pdev->dev, "tmu_sclk");
1074		if (IS_ERR(data->sclk)) {
1075			dev_err(&pdev->dev, "Failed to get sclk\n");
1076			ret = PTR_ERR(data->sclk);
1077			goto err_clk;
1078		} else {
1079			ret = clk_prepare_enable(data->sclk);
1080			if (ret) {
1081				dev_err(&pdev->dev, "Failed to enable sclk\n");
1082				goto err_clk;
1083			}
1084		}
1085		break;
1086	default:
1087		break;
1088	}
1089
1090	/*
1091	 * data->tzd must be registered before calling exynos_tmu_initialize(),
1092	 * requesting irq and calling exynos_tmu_control().
1093	 */
1094	data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
1095						    &exynos_sensor_ops);
1096	if (IS_ERR(data->tzd)) {
1097		ret = PTR_ERR(data->tzd);
1098		if (ret != -EPROBE_DEFER)
1099			dev_err(&pdev->dev, "Failed to register sensor: %d\n",
1100				ret);
1101		goto err_sclk;
1102	}
1103
1104	ret = exynos_tmu_initialize(pdev);
1105	if (ret) {
1106		dev_err(&pdev->dev, "Failed to initialize TMU\n");
1107		goto err_thermal;
1108	}
1109
1110	ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
1111		IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
1112	if (ret) {
1113		dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
1114		goto err_thermal;
1115	}
1116
1117	exynos_tmu_control(pdev, true);
1118	return 0;
1119
1120err_thermal:
1121	thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd);
1122err_sclk:
1123	clk_disable_unprepare(data->sclk);
1124err_clk:
1125	clk_unprepare(data->clk);
1126err_clk_sec:
1127	if (!IS_ERR(data->clk_sec))
1128		clk_unprepare(data->clk_sec);
1129err_sensor:
1130	if (!IS_ERR(data->regulator))
1131		regulator_disable(data->regulator);
1132
1133	return ret;
1134}
1135
1136static int exynos_tmu_remove(struct platform_device *pdev)
1137{
1138	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1139	struct thermal_zone_device *tzd = data->tzd;
1140
1141	thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
1142	exynos_tmu_control(pdev, false);
1143
1144	clk_disable_unprepare(data->sclk);
1145	clk_unprepare(data->clk);
1146	if (!IS_ERR(data->clk_sec))
1147		clk_unprepare(data->clk_sec);
1148
1149	if (!IS_ERR(data->regulator))
1150		regulator_disable(data->regulator);
1151
1152	return 0;
1153}
1154
1155#ifdef CONFIG_PM_SLEEP
1156static int exynos_tmu_suspend(struct device *dev)
1157{
1158	exynos_tmu_control(to_platform_device(dev), false);
1159
1160	return 0;
1161}
1162
1163static int exynos_tmu_resume(struct device *dev)
1164{
1165	struct platform_device *pdev = to_platform_device(dev);
1166
1167	exynos_tmu_initialize(pdev);
1168	exynos_tmu_control(pdev, true);
1169
1170	return 0;
1171}
1172
1173static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
1174			 exynos_tmu_suspend, exynos_tmu_resume);
1175#define EXYNOS_TMU_PM	(&exynos_tmu_pm)
1176#else
1177#define EXYNOS_TMU_PM	NULL
1178#endif
1179
1180static struct platform_driver exynos_tmu_driver = {
1181	.driver = {
1182		.name   = "exynos-tmu",
1183		.pm     = EXYNOS_TMU_PM,
1184		.of_match_table = exynos_tmu_match,
1185	},
1186	.probe = exynos_tmu_probe,
1187	.remove	= exynos_tmu_remove,
1188};
1189
1190module_platform_driver(exynos_tmu_driver);
1191
1192MODULE_DESCRIPTION("Exynos TMU Driver");
1193MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
1194MODULE_LICENSE("GPL");
1195MODULE_ALIAS("platform:exynos-tmu");
1196