]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/thermal/samsung/exynos_tmu.c
thermal: exynos: add ->tmu_clear_irqs method
[mirror_ubuntu-hirsute-kernel.git] / drivers / thermal / samsung / exynos_tmu.c
CommitLineData
9d97e5c8 1/*
59dfa54c 2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
9d97e5c8
DK
3 *
4 * Copyright (C) 2011 Samsung Electronics
5 * Donggeun Kim <dg77.kim@samsung.com>
c48cbba6 6 * Amit Daniel Kachhap <amit.kachhap@linaro.org>
9d97e5c8
DK
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
9d97e5c8 24#include <linux/clk.h>
9d97e5c8 25#include <linux/io.h>
1b678641
ADK
26#include <linux/interrupt.h>
27#include <linux/module.h>
f22d9c03 28#include <linux/of.h>
cebe7373
ADK
29#include <linux/of_address.h>
30#include <linux/of_irq.h>
1b678641 31#include <linux/platform_device.h>
498d22f6 32#include <linux/regulator/consumer.h>
1b678641
ADK
33
34#include "exynos_thermal_common.h"
0c1836a6 35#include "exynos_tmu.h"
e6b7991e 36#include "exynos_tmu_data.h"
f22d9c03 37
cebe7373
ADK
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.
9025d563 44 * @base_second: base address of the common registers of the TMU controller.
cebe7373
ADK
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.
14a11dc7 50 * @clk_sec: pointer to the clock structure for accessing the base_second.
cebe7373
ADK
51 * @temp_error1: fused value of the first point trim.
52 * @temp_error2: fused value of the second point trim.
498d22f6 53 * @regulator: pointer to the TMU regulator structure.
cebe7373 54 * @reg_conf: pointer to structure to register with core thermal.
72d1100b 55 * @tmu_initialize: SoC specific TMU initialization method
37f9034f 56 * @tmu_control: SoC specific TMU control method
b79985ca 57 * @tmu_read: SoC specific TMU temperature read method
285d994a 58 * @tmu_set_emulation: SoC specific TMU emulation setting method
a7331f72 59 * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
cebe7373 60 */
f22d9c03 61struct exynos_tmu_data {
cebe7373 62 int id;
f22d9c03 63 struct exynos_tmu_platform_data *pdata;
9d97e5c8 64 void __iomem *base;
9025d563 65 void __iomem *base_second;
9d97e5c8 66 int irq;
f22d9c03 67 enum soc_type soc;
9d97e5c8
DK
68 struct work_struct irq_work;
69 struct mutex lock;
14a11dc7 70 struct clk *clk, *clk_sec;
9d97e5c8 71 u8 temp_error1, temp_error2;
498d22f6 72 struct regulator *regulator;
cebe7373 73 struct thermal_sensor_conf *reg_conf;
72d1100b 74 int (*tmu_initialize)(struct platform_device *pdev);
37f9034f 75 void (*tmu_control)(struct platform_device *pdev, bool on);
b79985ca 76 int (*tmu_read)(struct exynos_tmu_data *data);
285d994a
BZ
77 void (*tmu_set_emulation)(struct exynos_tmu_data *data,
78 unsigned long temp);
a7331f72 79 void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
9d97e5c8
DK
80};
81
82/*
83 * TMU treats temperature as a mapped temperature code.
84 * The temperature is converted differently depending on the calibration type.
85 */
f22d9c03 86static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
9d97e5c8 87{
f22d9c03 88 struct exynos_tmu_platform_data *pdata = data->pdata;
9d97e5c8
DK
89 int temp_code;
90
9d97e5c8
DK
91 switch (pdata->cal_type) {
92 case TYPE_TWO_POINT_TRIMMING:
bb34b4c8
ADK
93 temp_code = (temp - pdata->first_point_trim) *
94 (data->temp_error2 - data->temp_error1) /
95 (pdata->second_point_trim - pdata->first_point_trim) +
96 data->temp_error1;
9d97e5c8
DK
97 break;
98 case TYPE_ONE_POINT_TRIMMING:
bb34b4c8 99 temp_code = temp + data->temp_error1 - pdata->first_point_trim;
9d97e5c8
DK
100 break;
101 default:
bb34b4c8 102 temp_code = temp + pdata->default_temp_offset;
9d97e5c8
DK
103 break;
104 }
ddb31d43 105
9d97e5c8
DK
106 return temp_code;
107}
108
109/*
110 * Calculate a temperature value from a temperature code.
111 * The unit of the temperature is degree Celsius.
112 */
f22d9c03 113static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
9d97e5c8 114{
f22d9c03 115 struct exynos_tmu_platform_data *pdata = data->pdata;
9d97e5c8
DK
116 int temp;
117
9d97e5c8
DK
118 switch (pdata->cal_type) {
119 case TYPE_TWO_POINT_TRIMMING:
bb34b4c8
ADK
120 temp = (temp_code - data->temp_error1) *
121 (pdata->second_point_trim - pdata->first_point_trim) /
122 (data->temp_error2 - data->temp_error1) +
123 pdata->first_point_trim;
9d97e5c8
DK
124 break;
125 case TYPE_ONE_POINT_TRIMMING:
bb34b4c8 126 temp = temp_code - data->temp_error1 + pdata->first_point_trim;
9d97e5c8
DK
127 break;
128 default:
bb34b4c8 129 temp = temp_code - pdata->default_temp_offset;
9d97e5c8
DK
130 break;
131 }
ddb31d43 132
9d97e5c8
DK
133 return temp;
134}
135
8328a4b1
BZ
136static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
137{
138 struct exynos_tmu_platform_data *pdata = data->pdata;
139
140 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
141 data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
142 EXYNOS_TMU_TEMP_MASK);
143
144 if (!data->temp_error1 ||
145 (pdata->min_efuse_value > data->temp_error1) ||
146 (data->temp_error1 > pdata->max_efuse_value))
147 data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
148
149 if (!data->temp_error2)
150 data->temp_error2 =
151 (pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
152 EXYNOS_TMU_TEMP_MASK;
153}
154
fe87789c
BZ
155static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling)
156{
157 struct exynos_tmu_platform_data *pdata = data->pdata;
158 int i;
159
160 for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
161 u8 temp = pdata->trigger_levels[i];
162
163 if (falling)
164 temp -= pdata->threshold_falling;
165 else
166 threshold &= ~(0xff << 8 * i);
167
168 threshold |= temp_to_code(data, temp) << 8 * i;
169 }
170
171 return threshold;
172}
173
f22d9c03 174static int exynos_tmu_initialize(struct platform_device *pdev)
9d97e5c8 175{
f22d9c03 176 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
72d1100b 177 int ret;
9d97e5c8
DK
178
179 mutex_lock(&data->lock);
180 clk_enable(data->clk);
14a11dc7
NKC
181 if (!IS_ERR(data->clk_sec))
182 clk_enable(data->clk_sec);
72d1100b 183 ret = data->tmu_initialize(pdev);
9d97e5c8
DK
184 clk_disable(data->clk);
185 mutex_unlock(&data->lock);
14a11dc7
NKC
186 if (!IS_ERR(data->clk_sec))
187 clk_disable(data->clk_sec);
9d97e5c8
DK
188
189 return ret;
190}
191
d00671c3 192static u32 get_con_reg(struct exynos_tmu_data *data, u32 con)
9d97e5c8 193{
f22d9c03 194 struct exynos_tmu_platform_data *pdata = data->pdata;
f22d9c03 195
86f5362e 196 if (pdata->test_mux)
bfb2b88c 197 con |= (pdata->test_mux << EXYNOS4412_MUX_ADDR_SHIFT);
86f5362e 198
99d67fb9
BZ
199 con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT);
200 con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
d0a0ce3e 201
99d67fb9
BZ
202 con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
203 con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
d0a0ce3e
ADK
204
205 if (pdata->noise_cancel_mode) {
b9504a6a
BZ
206 con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT);
207 con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
f22d9c03
ADK
208 }
209
d00671c3
BZ
210 return con;
211}
212
213static void exynos_tmu_control(struct platform_device *pdev, bool on)
214{
215 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
d00671c3
BZ
216
217 mutex_lock(&data->lock);
218 clk_enable(data->clk);
37f9034f 219 data->tmu_control(pdev, on);
9d97e5c8
DK
220 clk_disable(data->clk);
221 mutex_unlock(&data->lock);
222}
223
72d1100b
BZ
224static int exynos4210_tmu_initialize(struct platform_device *pdev)
225{
226 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
227 struct exynos_tmu_platform_data *pdata = data->pdata;
228 unsigned int status;
229 int ret = 0, threshold_code, i;
230
231 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
232 if (!status) {
233 ret = -EBUSY;
234 goto out;
235 }
236
237 sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
238
239 /* Write temperature code for threshold */
240 threshold_code = temp_to_code(data, pdata->threshold);
241 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
242
243 for (i = 0; i < pdata->non_hw_trigger_levels; i++)
244 writeb(pdata->trigger_levels[i], data->base +
245 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
246
a7331f72 247 data->tmu_clear_irqs(data);
72d1100b
BZ
248out:
249 return ret;
250}
251
252static int exynos4412_tmu_initialize(struct platform_device *pdev)
253{
254 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
255 struct exynos_tmu_platform_data *pdata = data->pdata;
256 unsigned int status, trim_info, con, ctrl, rising_threshold;
257 int ret = 0, threshold_code, i;
258
259 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
260 if (!status) {
261 ret = -EBUSY;
262 goto out;
263 }
264
265 if (data->soc == SOC_ARCH_EXYNOS3250 ||
266 data->soc == SOC_ARCH_EXYNOS4412 ||
267 data->soc == SOC_ARCH_EXYNOS5250) {
268 if (data->soc == SOC_ARCH_EXYNOS3250) {
269 ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON1);
270 ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
271 writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON1);
272 }
273 ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON2);
274 ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
275 writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON2);
276 }
277
278 /* On exynos5420 the triminfo register is in the shared space */
279 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
280 trim_info = readl(data->base_second + EXYNOS_TMU_REG_TRIMINFO);
281 else
282 trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
283
284 sanitize_temp_error(data, trim_info);
285
286 /* Write temperature code for rising and falling threshold */
287 rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE);
288 rising_threshold = get_th_reg(data, rising_threshold, false);
289 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
290 writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL);
291
a7331f72 292 data->tmu_clear_irqs(data);
72d1100b
BZ
293
294 /* if last threshold limit is also present */
295 i = pdata->max_trigger_level - 1;
296 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
297 threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
298 /* 1-4 level to be assigned in th0 reg */
299 rising_threshold &= ~(0xff << 8 * i);
300 rising_threshold |= threshold_code << 8 * i;
301 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
302 con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
303 con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
304 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
305 }
306out:
307 return ret;
308}
309
310static int exynos5440_tmu_initialize(struct platform_device *pdev)
311{
312 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
313 struct exynos_tmu_platform_data *pdata = data->pdata;
314 unsigned int trim_info = 0, con, rising_threshold;
315 int ret = 0, threshold_code, i;
316
317 /*
318 * For exynos5440 soc triminfo value is swapped between TMU0 and
319 * TMU2, so the below logic is needed.
320 */
321 switch (data->id) {
322 case 0:
323 trim_info = readl(data->base + EXYNOS5440_EFUSE_SWAP_OFFSET +
324 EXYNOS5440_TMU_S0_7_TRIM);
325 break;
326 case 1:
327 trim_info = readl(data->base + EXYNOS5440_TMU_S0_7_TRIM);
328 break;
329 case 2:
330 trim_info = readl(data->base - EXYNOS5440_EFUSE_SWAP_OFFSET +
331 EXYNOS5440_TMU_S0_7_TRIM);
332 }
333 sanitize_temp_error(data, trim_info);
334
335 /* Write temperature code for rising and falling threshold */
336 rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0);
337 rising_threshold = get_th_reg(data, rising_threshold, false);
338 writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0);
339 writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1);
340
a7331f72 341 data->tmu_clear_irqs(data);
72d1100b
BZ
342
343 /* if last threshold limit is also present */
344 i = pdata->max_trigger_level - 1;
345 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
346 threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
347 /* 5th level to be assigned in th2 reg */
348 rising_threshold =
349 threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;
350 writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH2);
351 con = readl(data->base + EXYNOS5440_TMU_S0_7_CTRL);
352 con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
353 writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
354 }
355 /* Clear the PMIN in the common TMU register */
356 if (!data->id)
357 writel(0, data->base_second + EXYNOS5440_TMU_PMIN);
358 return ret;
359}
360
37f9034f
BZ
361static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
362{
363 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
364 struct exynos_tmu_platform_data *pdata = data->pdata;
365 unsigned int con, interrupt_en;
366
367 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
368
369 if (on) {
370 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
371 interrupt_en =
372 pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
373 pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
374 pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
375 pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
376 if (TMU_SUPPORTS(pdata, FALLING_TRIP))
377 interrupt_en |=
378 interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
379 } else {
380 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
381 interrupt_en = 0; /* Disable all interrupts */
382 }
383 writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
384 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
385}
386
387static void exynos5440_tmu_control(struct platform_device *pdev, bool on)
388{
389 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
390 struct exynos_tmu_platform_data *pdata = data->pdata;
391 unsigned int con, interrupt_en;
392
393 con = get_con_reg(data, readl(data->base + EXYNOS5440_TMU_S0_7_CTRL));
394
395 if (on) {
396 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
397 interrupt_en =
398 pdata->trigger_enable[3] << EXYNOS5440_TMU_INTEN_RISE3_SHIFT |
399 pdata->trigger_enable[2] << EXYNOS5440_TMU_INTEN_RISE2_SHIFT |
400 pdata->trigger_enable[1] << EXYNOS5440_TMU_INTEN_RISE1_SHIFT |
401 pdata->trigger_enable[0] << EXYNOS5440_TMU_INTEN_RISE0_SHIFT;
402 if (TMU_SUPPORTS(pdata, FALLING_TRIP))
403 interrupt_en |=
404 interrupt_en << EXYNOS5440_TMU_INTEN_FALL0_SHIFT;
405 } else {
406 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
407 interrupt_en = 0; /* Disable all interrupts */
408 }
409 writel(interrupt_en, data->base + EXYNOS5440_TMU_S0_7_IRQEN);
410 writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
411}
412
f22d9c03 413static int exynos_tmu_read(struct exynos_tmu_data *data)
9d97e5c8 414{
b79985ca 415 int ret;
9d97e5c8
DK
416
417 mutex_lock(&data->lock);
418 clk_enable(data->clk);
b79985ca
BZ
419 ret = data->tmu_read(data);
420 if (ret >= 0)
421 ret = code_to_temp(data, ret);
9d97e5c8
DK
422 clk_disable(data->clk);
423 mutex_unlock(&data->lock);
424
b79985ca 425 return ret;
9d97e5c8
DK
426}
427
bffd1f8a 428#ifdef CONFIG_THERMAL_EMULATION
154013ea
BZ
429static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
430 unsigned long temp)
431{
432 struct exynos_tmu_platform_data *pdata = data->pdata;
433
434 if (temp) {
435 temp /= MCELSIUS;
436
437 if (TMU_SUPPORTS(pdata, EMUL_TIME)) {
438 val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
439 val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
440 }
441 val &= ~(EXYNOS_EMUL_DATA_MASK << EXYNOS_EMUL_DATA_SHIFT);
442 val |= (temp_to_code(data, temp) << EXYNOS_EMUL_DATA_SHIFT) |
443 EXYNOS_EMUL_ENABLE;
444 } else {
445 val &= ~EXYNOS_EMUL_ENABLE;
446 }
447
448 return val;
449}
450
285d994a
BZ
451static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
452 unsigned long temp)
453{
454 unsigned int val;
455 u32 emul_con;
456
457 if (data->soc == SOC_ARCH_EXYNOS5260)
458 emul_con = EXYNOS5260_EMUL_CON;
459 else
460 emul_con = EXYNOS_EMUL_CON;
461
462 val = readl(data->base + emul_con);
463 val = get_emul_con_reg(data, val, temp);
464 writel(val, data->base + emul_con);
465}
466
467static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
468 unsigned long temp)
469{
470 unsigned int val;
471
472 val = readl(data->base + EXYNOS5440_TMU_S0_7_DEBUG);
473 val = get_emul_con_reg(data, val, temp);
474 writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG);
475}
476
bffd1f8a
ADK
477static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
478{
479 struct exynos_tmu_data *data = drv_data;
b8d582b9 480 struct exynos_tmu_platform_data *pdata = data->pdata;
bffd1f8a
ADK
481 int ret = -EINVAL;
482
f4dae753 483 if (!TMU_SUPPORTS(pdata, EMULATION))
bffd1f8a
ADK
484 goto out;
485
486 if (temp && temp < MCELSIUS)
487 goto out;
488
489 mutex_lock(&data->lock);
490 clk_enable(data->clk);
285d994a 491 data->tmu_set_emulation(data, temp);
bffd1f8a
ADK
492 clk_disable(data->clk);
493 mutex_unlock(&data->lock);
494 return 0;
495out:
496 return ret;
497}
498#else
285d994a
BZ
499#define exynos4412_tmu_set_emulation NULL
500#define exynos5440_tmu_set_emulation NULL
bffd1f8a
ADK
501static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
502 { return -EINVAL; }
503#endif/*CONFIG_THERMAL_EMULATION*/
504
b79985ca
BZ
505static int exynos4210_tmu_read(struct exynos_tmu_data *data)
506{
507 int ret = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
508
509 /* "temp_code" should range between 75 and 175 */
510 return (ret < 75 || ret > 175) ? -ENODATA : ret;
511}
512
513static int exynos4412_tmu_read(struct exynos_tmu_data *data)
514{
515 return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
516}
517
518static int exynos5440_tmu_read(struct exynos_tmu_data *data)
519{
520 return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP);
521}
522
f22d9c03 523static void exynos_tmu_work(struct work_struct *work)
9d97e5c8 524{
f22d9c03
ADK
525 struct exynos_tmu_data *data = container_of(work,
526 struct exynos_tmu_data, irq_work);
b835ced1 527 unsigned int val_type;
a0395eee 528
14a11dc7
NKC
529 if (!IS_ERR(data->clk_sec))
530 clk_enable(data->clk_sec);
a0395eee 531 /* Find which sensor generated this interrupt */
421d5d12
BZ
532 if (data->soc == SOC_ARCH_EXYNOS5440) {
533 val_type = readl(data->base_second + EXYNOS5440_TMU_IRQ_STATUS);
a0395eee
ADK
534 if (!((val_type >> data->id) & 0x1))
535 goto out;
536 }
14a11dc7
NKC
537 if (!IS_ERR(data->clk_sec))
538 clk_disable(data->clk_sec);
9d97e5c8 539
cebe7373 540 exynos_report_trigger(data->reg_conf);
9d97e5c8
DK
541 mutex_lock(&data->lock);
542 clk_enable(data->clk);
b8d582b9 543
a4463c4f 544 /* TODO: take action based on particular interrupt */
a7331f72 545 data->tmu_clear_irqs(data);
b8d582b9 546
9d97e5c8
DK
547 clk_disable(data->clk);
548 mutex_unlock(&data->lock);
a0395eee 549out:
f22d9c03 550 enable_irq(data->irq);
9d97e5c8
DK
551}
552
a7331f72
BZ
553static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data)
554{
555 unsigned int val_irq;
556 u32 tmu_intstat, tmu_intclear;
557
558 if (data->soc == SOC_ARCH_EXYNOS5260) {
559 tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
560 tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR;
561 } else {
562 tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
563 tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
564 }
565
566 val_irq = readl(data->base + tmu_intstat);
567 /*
568 * Clear the interrupts. Please note that the documentation for
569 * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
570 * states that INTCLEAR register has a different placing of bits
571 * responsible for FALL IRQs than INTSTAT register. Exynos5420
572 * and Exynos5440 documentation is correct (Exynos4210 doesn't
573 * support FALL IRQs at all).
574 */
575 writel(val_irq, data->base + tmu_intclear);
576}
577
578static void exynos5440_tmu_clear_irqs(struct exynos_tmu_data *data)
579{
580 unsigned int val_irq;
581
582 val_irq = readl(data->base + EXYNOS5440_TMU_S0_7_IRQ);
583 /* clear the interrupts */
584 writel(val_irq, data->base + EXYNOS5440_TMU_S0_7_IRQ);
585}
586
f22d9c03 587static irqreturn_t exynos_tmu_irq(int irq, void *id)
9d97e5c8 588{
f22d9c03 589 struct exynos_tmu_data *data = id;
9d97e5c8
DK
590
591 disable_irq_nosync(irq);
592 schedule_work(&data->irq_work);
593
594 return IRQ_HANDLED;
595}
17be868e 596
17be868e 597static const struct of_device_id exynos_tmu_match[] = {
1fe56dc1
CC
598 {
599 .compatible = "samsung,exynos3250-tmu",
600 .data = (void *)EXYNOS3250_TMU_DRV_DATA,
601 },
17be868e
ADK
602 {
603 .compatible = "samsung,exynos4210-tmu",
604 .data = (void *)EXYNOS4210_TMU_DRV_DATA,
605 },
b6cee53c
SK
606 {
607 .compatible = "samsung,exynos4412-tmu",
14ddfaec 608 .data = (void *)EXYNOS4412_TMU_DRV_DATA,
b6cee53c 609 },
17be868e
ADK
610 {
611 .compatible = "samsung,exynos5250-tmu",
e6b7991e 612 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
17be868e 613 },
923488a5
NKC
614 {
615 .compatible = "samsung,exynos5260-tmu",
616 .data = (void *)EXYNOS5260_TMU_DRV_DATA,
617 },
14a11dc7
NKC
618 {
619 .compatible = "samsung,exynos5420-tmu",
620 .data = (void *)EXYNOS5420_TMU_DRV_DATA,
621 },
622 {
623 .compatible = "samsung,exynos5420-tmu-ext-triminfo",
624 .data = (void *)EXYNOS5420_TMU_DRV_DATA,
625 },
90542546
ADK
626 {
627 .compatible = "samsung,exynos5440-tmu",
628 .data = (void *)EXYNOS5440_TMU_DRV_DATA,
629 },
17be868e
ADK
630 {},
631};
632MODULE_DEVICE_TABLE(of, exynos_tmu_match);
17be868e 633
17be868e 634static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
cebe7373 635 struct platform_device *pdev, int id)
17be868e 636{
cebe7373
ADK
637 struct exynos_tmu_init_data *data_table;
638 struct exynos_tmu_platform_data *tmu_data;
73b5b1d7
SK
639 const struct of_device_id *match;
640
641 match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
642 if (!match)
643 return NULL;
644 data_table = (struct exynos_tmu_init_data *) match->data;
645 if (!data_table || id >= data_table->tmu_count)
646 return NULL;
647 tmu_data = data_table->tmu_data;
648 return (struct exynos_tmu_platform_data *) (tmu_data + id);
7e0b55e6 649}
bbf63be4 650
cebe7373 651static int exynos_map_dt_data(struct platform_device *pdev)
9d97e5c8 652{
cebe7373
ADK
653 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
654 struct exynos_tmu_platform_data *pdata;
655 struct resource res;
498d22f6 656 int ret;
cebe7373 657
73b5b1d7 658 if (!data || !pdev->dev.of_node)
cebe7373 659 return -ENODEV;
9d97e5c8 660
498d22f6
ADK
661 /*
662 * Try enabling the regulator if found
663 * TODO: Add regulator as an SOC feature, so that regulator enable
664 * is a compulsory call.
665 */
666 data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
667 if (!IS_ERR(data->regulator)) {
668 ret = regulator_enable(data->regulator);
669 if (ret) {
670 dev_err(&pdev->dev, "failed to enable vtmu\n");
671 return ret;
672 }
673 } else {
674 dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
675 }
676
cebe7373
ADK
677 data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
678 if (data->id < 0)
679 data->id = 0;
17be868e 680
cebe7373
ADK
681 data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
682 if (data->irq <= 0) {
683 dev_err(&pdev->dev, "failed to get IRQ\n");
684 return -ENODEV;
685 }
686
687 if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
688 dev_err(&pdev->dev, "failed to get Resource 0\n");
689 return -ENODEV;
690 }
691
692 data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
693 if (!data->base) {
694 dev_err(&pdev->dev, "Failed to ioremap memory\n");
695 return -EADDRNOTAVAIL;
696 }
697
698 pdata = exynos_get_driver_data(pdev, data->id);
9d97e5c8
DK
699 if (!pdata) {
700 dev_err(&pdev->dev, "No platform init data supplied.\n");
701 return -ENODEV;
702 }
cebe7373 703 data->pdata = pdata;
d9b6ee14
ADK
704 /*
705 * Check if the TMU shares some registers and then try to map the
706 * memory of common registers.
707 */
9025d563 708 if (!TMU_SUPPORTS(pdata, ADDRESS_MULTIPLE))
d9b6ee14
ADK
709 return 0;
710
711 if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
712 dev_err(&pdev->dev, "failed to get Resource 1\n");
713 return -ENODEV;
714 }
715
9025d563 716 data->base_second = devm_ioremap(&pdev->dev, res.start,
d9b6ee14 717 resource_size(&res));
9025d563 718 if (!data->base_second) {
d9b6ee14
ADK
719 dev_err(&pdev->dev, "Failed to ioremap memory\n");
720 return -ENOMEM;
721 }
cebe7373
ADK
722
723 return 0;
724}
725
726static int exynos_tmu_probe(struct platform_device *pdev)
727{
728 struct exynos_tmu_data *data;
729 struct exynos_tmu_platform_data *pdata;
730 struct thermal_sensor_conf *sensor_conf;
731 int ret, i;
732
79e093c3
ADK
733 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
734 GFP_KERNEL);
2a9675b3 735 if (!data)
9d97e5c8 736 return -ENOMEM;
9d97e5c8 737
cebe7373
ADK
738 platform_set_drvdata(pdev, data);
739 mutex_init(&data->lock);
9d97e5c8 740
cebe7373
ADK
741 ret = exynos_map_dt_data(pdev);
742 if (ret)
743 return ret;
9d97e5c8 744
cebe7373 745 pdata = data->pdata;
9d97e5c8 746
cebe7373 747 INIT_WORK(&data->irq_work, exynos_tmu_work);
9d97e5c8 748
2a16279c 749 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
9d97e5c8 750 if (IS_ERR(data->clk)) {
9d97e5c8 751 dev_err(&pdev->dev, "Failed to get clock\n");
79e093c3 752 return PTR_ERR(data->clk);
9d97e5c8
DK
753 }
754
14a11dc7
NKC
755 data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif");
756 if (IS_ERR(data->clk_sec)) {
757 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) {
758 dev_err(&pdev->dev, "Failed to get triminfo clock\n");
759 return PTR_ERR(data->clk_sec);
760 }
761 } else {
762 ret = clk_prepare(data->clk_sec);
763 if (ret) {
764 dev_err(&pdev->dev, "Failed to get clock\n");
765 return ret;
766 }
767 }
768
2a16279c 769 ret = clk_prepare(data->clk);
14a11dc7
NKC
770 if (ret) {
771 dev_err(&pdev->dev, "Failed to get clock\n");
772 goto err_clk_sec;
773 }
2a16279c 774
72d1100b
BZ
775 data->soc = pdata->type;
776
777 switch (data->soc) {
778 case SOC_ARCH_EXYNOS4210:
779 data->tmu_initialize = exynos4210_tmu_initialize;
37f9034f 780 data->tmu_control = exynos4210_tmu_control;
b79985ca 781 data->tmu_read = exynos4210_tmu_read;
a7331f72 782 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
72d1100b
BZ
783 break;
784 case SOC_ARCH_EXYNOS3250:
785 case SOC_ARCH_EXYNOS4412:
786 case SOC_ARCH_EXYNOS5250:
787 case SOC_ARCH_EXYNOS5260:
788 case SOC_ARCH_EXYNOS5420:
789 case SOC_ARCH_EXYNOS5420_TRIMINFO:
790 data->tmu_initialize = exynos4412_tmu_initialize;
37f9034f 791 data->tmu_control = exynos4210_tmu_control;
b79985ca 792 data->tmu_read = exynos4412_tmu_read;
285d994a 793 data->tmu_set_emulation = exynos4412_tmu_set_emulation;
a7331f72 794 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
72d1100b
BZ
795 break;
796 case SOC_ARCH_EXYNOS5440:
797 data->tmu_initialize = exynos5440_tmu_initialize;
37f9034f 798 data->tmu_control = exynos5440_tmu_control;
b79985ca 799 data->tmu_read = exynos5440_tmu_read;
285d994a 800 data->tmu_set_emulation = exynos5440_tmu_set_emulation;
a7331f72 801 data->tmu_clear_irqs = exynos5440_tmu_clear_irqs;
72d1100b
BZ
802 break;
803 default:
f22d9c03
ADK
804 ret = -EINVAL;
805 dev_err(&pdev->dev, "Platform not supported\n");
806 goto err_clk;
807 }
808
f22d9c03 809 ret = exynos_tmu_initialize(pdev);
9d97e5c8
DK
810 if (ret) {
811 dev_err(&pdev->dev, "Failed to initialize TMU\n");
812 goto err_clk;
813 }
814
f22d9c03 815 exynos_tmu_control(pdev, true);
9d97e5c8 816
cebe7373
ADK
817 /* Allocate a structure to register with the exynos core thermal */
818 sensor_conf = devm_kzalloc(&pdev->dev,
819 sizeof(struct thermal_sensor_conf), GFP_KERNEL);
820 if (!sensor_conf) {
cebe7373
ADK
821 ret = -ENOMEM;
822 goto err_clk;
823 }
824 sprintf(sensor_conf->name, "therm_zone%d", data->id);
825 sensor_conf->read_temperature = (int (*)(void *))exynos_tmu_read;
826 sensor_conf->write_emul_temp =
827 (int (*)(void *, unsigned long))exynos_tmu_set_emulation;
828 sensor_conf->driver_data = data;
829 sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
bb34b4c8
ADK
830 pdata->trigger_enable[1] + pdata->trigger_enable[2]+
831 pdata->trigger_enable[3];
7e0b55e6 832
cebe7373
ADK
833 for (i = 0; i < sensor_conf->trip_data.trip_count; i++) {
834 sensor_conf->trip_data.trip_val[i] =
7e0b55e6 835 pdata->threshold + pdata->trigger_levels[i];
cebe7373 836 sensor_conf->trip_data.trip_type[i] =
5c3cf552
ADK
837 pdata->trigger_type[i];
838 }
7e0b55e6 839
cebe7373 840 sensor_conf->trip_data.trigger_falling = pdata->threshold_falling;
4f0a6847 841
cebe7373 842 sensor_conf->cooling_data.freq_clip_count = pdata->freq_tab_count;
7e0b55e6 843 for (i = 0; i < pdata->freq_tab_count; i++) {
cebe7373 844 sensor_conf->cooling_data.freq_data[i].freq_clip_max =
7e0b55e6 845 pdata->freq_tab[i].freq_clip_max;
cebe7373 846 sensor_conf->cooling_data.freq_data[i].temp_level =
7e0b55e6
ADK
847 pdata->freq_tab[i].temp_level;
848 }
cebe7373
ADK
849 sensor_conf->dev = &pdev->dev;
850 /* Register the sensor with thermal management interface */
851 ret = exynos_register_thermal(sensor_conf);
7e0b55e6
ADK
852 if (ret) {
853 dev_err(&pdev->dev, "Failed to register thermal interface\n");
854 goto err_clk;
855 }
cebe7373
ADK
856 data->reg_conf = sensor_conf;
857
858 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
859 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
860 if (ret) {
861 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
862 goto err_clk;
863 }
bbf63be4 864
9d97e5c8 865 return 0;
9d97e5c8 866err_clk:
2a16279c 867 clk_unprepare(data->clk);
14a11dc7
NKC
868err_clk_sec:
869 if (!IS_ERR(data->clk_sec))
870 clk_unprepare(data->clk_sec);
9d97e5c8
DK
871 return ret;
872}
873
4eab7a9e 874static int exynos_tmu_remove(struct platform_device *pdev)
9d97e5c8 875{
f22d9c03 876 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
9d97e5c8 877
cebe7373 878 exynos_unregister_thermal(data->reg_conf);
7e0b55e6 879
4215688e
BZ
880 exynos_tmu_control(pdev, false);
881
2a16279c 882 clk_unprepare(data->clk);
14a11dc7
NKC
883 if (!IS_ERR(data->clk_sec))
884 clk_unprepare(data->clk_sec);
9d97e5c8 885
498d22f6
ADK
886 if (!IS_ERR(data->regulator))
887 regulator_disable(data->regulator);
888
9d97e5c8
DK
889 return 0;
890}
891
08cd6753 892#ifdef CONFIG_PM_SLEEP
f22d9c03 893static int exynos_tmu_suspend(struct device *dev)
9d97e5c8 894{
f22d9c03 895 exynos_tmu_control(to_platform_device(dev), false);
9d97e5c8
DK
896
897 return 0;
898}
899
f22d9c03 900static int exynos_tmu_resume(struct device *dev)
9d97e5c8 901{
08cd6753
RW
902 struct platform_device *pdev = to_platform_device(dev);
903
f22d9c03
ADK
904 exynos_tmu_initialize(pdev);
905 exynos_tmu_control(pdev, true);
9d97e5c8
DK
906
907 return 0;
908}
08cd6753 909
f22d9c03
ADK
910static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
911 exynos_tmu_suspend, exynos_tmu_resume);
912#define EXYNOS_TMU_PM (&exynos_tmu_pm)
9d97e5c8 913#else
f22d9c03 914#define EXYNOS_TMU_PM NULL
9d97e5c8
DK
915#endif
916
f22d9c03 917static struct platform_driver exynos_tmu_driver = {
9d97e5c8 918 .driver = {
f22d9c03 919 .name = "exynos-tmu",
9d97e5c8 920 .owner = THIS_MODULE,
f22d9c03 921 .pm = EXYNOS_TMU_PM,
73b5b1d7 922 .of_match_table = exynos_tmu_match,
9d97e5c8 923 },
f22d9c03 924 .probe = exynos_tmu_probe,
4eab7a9e 925 .remove = exynos_tmu_remove,
9d97e5c8
DK
926};
927
f22d9c03 928module_platform_driver(exynos_tmu_driver);
9d97e5c8 929
f22d9c03 930MODULE_DESCRIPTION("EXYNOS TMU Driver");
9d97e5c8
DK
931MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
932MODULE_LICENSE("GPL");
f22d9c03 933MODULE_ALIAS("platform:exynos-tmu");