Commit 59dfa54c5edf4955e6e5469fd7cb8c0a5a813818

Authored by Amit Daniel Kachhap
Committed by Eduardo Valentin
1 parent 1b678641c2

thermal: exynos: Rename exynos_thermal.c to exynos_tmu.c

This patch renames exynos_thermal.c to exynos_tmu.c. This change is needed as
this file now just contains exynos tmu driver related codes and thermal zone
or cpufreq cooling registration related changes are not there anymore.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Acked-by: Jonghwa Lee <jonghwa3.lee@samsung.com>
Acked-by: Eduardo Valentin <eduardo.valentin@ti.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>

Showing 3 changed files with 655 additions and 655 deletions Side-by-side Diff

drivers/thermal/samsung/Makefile
1 1 #
2 2 # Samsung thermal specific Makefile
3 3 #
4   -obj-$(CONFIG_EXYNOS_THERMAL) += exynos_soc_thermal.o
5   -exynos_soc_thermal-y := exynos_thermal.o
6   -exynos_soc_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
  4 +obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
  5 +exynos_thermal-y := exynos_tmu.o
  6 +exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
drivers/thermal/samsung/exynos_thermal.c
1   -/*
2   - * exynos_thermal.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/platform_device.h>
30   -#include <linux/platform_data/exynos_thermal.h>
31   -
32   -#include "exynos_thermal_common.h"
33   -
34   -/* Exynos generic registers */
35   -#define EXYNOS_TMU_REG_TRIMINFO 0x0
36   -#define EXYNOS_TMU_REG_CONTROL 0x20
37   -#define EXYNOS_TMU_REG_STATUS 0x28
38   -#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
39   -#define EXYNOS_TMU_REG_INTEN 0x70
40   -#define EXYNOS_TMU_REG_INTSTAT 0x74
41   -#define EXYNOS_TMU_REG_INTCLEAR 0x78
42   -
43   -#define EXYNOS_TMU_TRIM_TEMP_MASK 0xff
44   -#define EXYNOS_TMU_GAIN_SHIFT 8
45   -#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
46   -#define EXYNOS_TMU_CORE_ON 3
47   -#define EXYNOS_TMU_CORE_OFF 2
48   -#define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET 50
49   -
50   -/* Exynos4210 specific registers */
51   -#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
52   -#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
53   -#define EXYNOS4210_TMU_REG_TRIG_LEVEL1 0x54
54   -#define EXYNOS4210_TMU_REG_TRIG_LEVEL2 0x58
55   -#define EXYNOS4210_TMU_REG_TRIG_LEVEL3 0x5C
56   -#define EXYNOS4210_TMU_REG_PAST_TEMP0 0x60
57   -#define EXYNOS4210_TMU_REG_PAST_TEMP1 0x64
58   -#define EXYNOS4210_TMU_REG_PAST_TEMP2 0x68
59   -#define EXYNOS4210_TMU_REG_PAST_TEMP3 0x6C
60   -
61   -#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK 0x1
62   -#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK 0x10
63   -#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK 0x100
64   -#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK 0x1000
65   -#define EXYNOS4210_TMU_INTCLEAR_VAL 0x1111
66   -
67   -/* Exynos5250 and Exynos4412 specific registers */
68   -#define EXYNOS_TMU_TRIMINFO_CON 0x14
69   -#define EXYNOS_THD_TEMP_RISE 0x50
70   -#define EXYNOS_THD_TEMP_FALL 0x54
71   -#define EXYNOS_EMUL_CON 0x80
72   -
73   -#define EXYNOS_TRIMINFO_RELOAD 0x1
74   -#define EXYNOS_TMU_CLEAR_RISE_INT 0x111
75   -#define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 12)
76   -#define EXYNOS_MUX_ADDR_VALUE 6
77   -#define EXYNOS_MUX_ADDR_SHIFT 20
78   -#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
79   -
80   -#define EFUSE_MIN_VALUE 40
81   -#define EFUSE_MAX_VALUE 100
82   -
83   -#ifdef CONFIG_THERMAL_EMULATION
84   -#define EXYNOS_EMUL_TIME 0x57F0
85   -#define EXYNOS_EMUL_TIME_SHIFT 16
86   -#define EXYNOS_EMUL_DATA_SHIFT 8
87   -#define EXYNOS_EMUL_DATA_MASK 0xFF
88   -#define EXYNOS_EMUL_ENABLE 0x1
89   -#endif /* CONFIG_THERMAL_EMULATION */
90   -
91   -struct exynos_tmu_data {
92   - struct exynos_tmu_platform_data *pdata;
93   - struct resource *mem;
94   - void __iomem *base;
95   - int irq;
96   - enum soc_type soc;
97   - struct work_struct irq_work;
98   - struct mutex lock;
99   - struct clk *clk;
100   - u8 temp_error1, temp_error2;
101   -};
102   -
103   -/*
104   - * TMU treats temperature as a mapped temperature code.
105   - * The temperature is converted differently depending on the calibration type.
106   - */
107   -static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
108   -{
109   - struct exynos_tmu_platform_data *pdata = data->pdata;
110   - int temp_code;
111   -
112   - if (data->soc == SOC_ARCH_EXYNOS4210)
113   - /* temp should range between 25 and 125 */
114   - if (temp < 25 || temp > 125) {
115   - temp_code = -EINVAL;
116   - goto out;
117   - }
118   -
119   - switch (pdata->cal_type) {
120   - case TYPE_TWO_POINT_TRIMMING:
121   - temp_code = (temp - 25) *
122   - (data->temp_error2 - data->temp_error1) /
123   - (85 - 25) + data->temp_error1;
124   - break;
125   - case TYPE_ONE_POINT_TRIMMING:
126   - temp_code = temp + data->temp_error1 - 25;
127   - break;
128   - default:
129   - temp_code = temp + EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
130   - break;
131   - }
132   -out:
133   - return temp_code;
134   -}
135   -
136   -/*
137   - * Calculate a temperature value from a temperature code.
138   - * The unit of the temperature is degree Celsius.
139   - */
140   -static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
141   -{
142   - struct exynos_tmu_platform_data *pdata = data->pdata;
143   - int temp;
144   -
145   - if (data->soc == SOC_ARCH_EXYNOS4210)
146   - /* temp_code should range between 75 and 175 */
147   - if (temp_code < 75 || temp_code > 175) {
148   - temp = -ENODATA;
149   - goto out;
150   - }
151   -
152   - switch (pdata->cal_type) {
153   - case TYPE_TWO_POINT_TRIMMING:
154   - temp = (temp_code - data->temp_error1) * (85 - 25) /
155   - (data->temp_error2 - data->temp_error1) + 25;
156   - break;
157   - case TYPE_ONE_POINT_TRIMMING:
158   - temp = temp_code - data->temp_error1 + 25;
159   - break;
160   - default:
161   - temp = temp_code - EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
162   - break;
163   - }
164   -out:
165   - return temp;
166   -}
167   -
168   -static int exynos_tmu_initialize(struct platform_device *pdev)
169   -{
170   - struct exynos_tmu_data *data = platform_get_drvdata(pdev);
171   - struct exynos_tmu_platform_data *pdata = data->pdata;
172   - unsigned int status, trim_info;
173   - unsigned int rising_threshold = 0, falling_threshold = 0;
174   - int ret = 0, threshold_code, i, trigger_levs = 0;
175   -
176   - mutex_lock(&data->lock);
177   - clk_enable(data->clk);
178   -
179   - status = readb(data->base + EXYNOS_TMU_REG_STATUS);
180   - if (!status) {
181   - ret = -EBUSY;
182   - goto out;
183   - }
184   -
185   - if (data->soc == SOC_ARCH_EXYNOS) {
186   - __raw_writel(EXYNOS_TRIMINFO_RELOAD,
187   - data->base + EXYNOS_TMU_TRIMINFO_CON);
188   - }
189   - /* Save trimming info in order to perform calibration */
190   - trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
191   - data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
192   - data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
193   -
194   - if ((EFUSE_MIN_VALUE > data->temp_error1) ||
195   - (data->temp_error1 > EFUSE_MAX_VALUE) ||
196   - (data->temp_error2 != 0))
197   - data->temp_error1 = pdata->efuse_value;
198   -
199   - /* Count trigger levels to be enabled */
200   - for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
201   - if (pdata->trigger_levels[i])
202   - trigger_levs++;
203   -
204   - if (data->soc == SOC_ARCH_EXYNOS4210) {
205   - /* Write temperature code for threshold */
206   - threshold_code = temp_to_code(data, pdata->threshold);
207   - if (threshold_code < 0) {
208   - ret = threshold_code;
209   - goto out;
210   - }
211   - writeb(threshold_code,
212   - data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
213   - for (i = 0; i < trigger_levs; i++)
214   - writeb(pdata->trigger_levels[i],
215   - data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
216   -
217   - writel(EXYNOS4210_TMU_INTCLEAR_VAL,
218   - data->base + EXYNOS_TMU_REG_INTCLEAR);
219   - } else if (data->soc == SOC_ARCH_EXYNOS) {
220   - /* Write temperature code for rising and falling threshold */
221   - for (i = 0; i < trigger_levs; i++) {
222   - threshold_code = temp_to_code(data,
223   - pdata->trigger_levels[i]);
224   - if (threshold_code < 0) {
225   - ret = threshold_code;
226   - goto out;
227   - }
228   - rising_threshold |= threshold_code << 8 * i;
229   - if (pdata->threshold_falling) {
230   - threshold_code = temp_to_code(data,
231   - pdata->trigger_levels[i] -
232   - pdata->threshold_falling);
233   - if (threshold_code > 0)
234   - falling_threshold |=
235   - threshold_code << 8 * i;
236   - }
237   - }
238   -
239   - writel(rising_threshold,
240   - data->base + EXYNOS_THD_TEMP_RISE);
241   - writel(falling_threshold,
242   - data->base + EXYNOS_THD_TEMP_FALL);
243   -
244   - writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
245   - data->base + EXYNOS_TMU_REG_INTCLEAR);
246   - }
247   -out:
248   - clk_disable(data->clk);
249   - mutex_unlock(&data->lock);
250   -
251   - return ret;
252   -}
253   -
254   -static void exynos_tmu_control(struct platform_device *pdev, bool on)
255   -{
256   - struct exynos_tmu_data *data = platform_get_drvdata(pdev);
257   - struct exynos_tmu_platform_data *pdata = data->pdata;
258   - unsigned int con, interrupt_en;
259   -
260   - mutex_lock(&data->lock);
261   - clk_enable(data->clk);
262   -
263   - con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
264   - pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
265   -
266   - if (data->soc == SOC_ARCH_EXYNOS) {
267   - con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
268   - con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
269   - }
270   -
271   - if (on) {
272   - con |= EXYNOS_TMU_CORE_ON;
273   - interrupt_en = pdata->trigger_level3_en << 12 |
274   - pdata->trigger_level2_en << 8 |
275   - pdata->trigger_level1_en << 4 |
276   - pdata->trigger_level0_en;
277   - if (pdata->threshold_falling)
278   - interrupt_en |= interrupt_en << 16;
279   - } else {
280   - con |= EXYNOS_TMU_CORE_OFF;
281   - interrupt_en = 0; /* Disable all interrupts */
282   - }
283   - writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
284   - writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
285   -
286   - clk_disable(data->clk);
287   - mutex_unlock(&data->lock);
288   -}
289   -
290   -static int exynos_tmu_read(struct exynos_tmu_data *data)
291   -{
292   - u8 temp_code;
293   - int temp;
294   -
295   - mutex_lock(&data->lock);
296   - clk_enable(data->clk);
297   -
298   - temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
299   - temp = code_to_temp(data, temp_code);
300   -
301   - clk_disable(data->clk);
302   - mutex_unlock(&data->lock);
303   -
304   - return temp;
305   -}
306   -
307   -#ifdef CONFIG_THERMAL_EMULATION
308   -static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
309   -{
310   - struct exynos_tmu_data *data = drv_data;
311   - unsigned int reg;
312   - int ret = -EINVAL;
313   -
314   - if (data->soc == SOC_ARCH_EXYNOS4210)
315   - goto out;
316   -
317   - if (temp && temp < MCELSIUS)
318   - goto out;
319   -
320   - mutex_lock(&data->lock);
321   - clk_enable(data->clk);
322   -
323   - reg = readl(data->base + EXYNOS_EMUL_CON);
324   -
325   - if (temp) {
326   - temp /= MCELSIUS;
327   -
328   - reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
329   - (temp_to_code(data, temp)
330   - << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
331   - } else {
332   - reg &= ~EXYNOS_EMUL_ENABLE;
333   - }
334   -
335   - writel(reg, data->base + EXYNOS_EMUL_CON);
336   -
337   - clk_disable(data->clk);
338   - mutex_unlock(&data->lock);
339   - return 0;
340   -out:
341   - return ret;
342   -}
343   -#else
344   -static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
345   - { return -EINVAL; }
346   -#endif/*CONFIG_THERMAL_EMULATION*/
347   -
348   -static void exynos_tmu_work(struct work_struct *work)
349   -{
350   - struct exynos_tmu_data *data = container_of(work,
351   - struct exynos_tmu_data, irq_work);
352   -
353   - exynos_report_trigger();
354   - mutex_lock(&data->lock);
355   - clk_enable(data->clk);
356   - if (data->soc == SOC_ARCH_EXYNOS)
357   - writel(EXYNOS_TMU_CLEAR_RISE_INT |
358   - EXYNOS_TMU_CLEAR_FALL_INT,
359   - data->base + EXYNOS_TMU_REG_INTCLEAR);
360   - else
361   - writel(EXYNOS4210_TMU_INTCLEAR_VAL,
362   - data->base + EXYNOS_TMU_REG_INTCLEAR);
363   - clk_disable(data->clk);
364   - mutex_unlock(&data->lock);
365   -
366   - enable_irq(data->irq);
367   -}
368   -
369   -static irqreturn_t exynos_tmu_irq(int irq, void *id)
370   -{
371   - struct exynos_tmu_data *data = id;
372   -
373   - disable_irq_nosync(irq);
374   - schedule_work(&data->irq_work);
375   -
376   - return IRQ_HANDLED;
377   -}
378   -static struct thermal_sensor_conf exynos_sensor_conf = {
379   - .name = "exynos-therm",
380   - .read_temperature = (int (*)(void *))exynos_tmu_read,
381   - .write_emul_temp = exynos_tmu_set_emulation,
382   -};
383   -
384   -#if defined(CONFIG_CPU_EXYNOS4210)
385   -static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
386   - .threshold = 80,
387   - .trigger_levels[0] = 5,
388   - .trigger_levels[1] = 20,
389   - .trigger_levels[2] = 30,
390   - .trigger_level0_en = 1,
391   - .trigger_level1_en = 1,
392   - .trigger_level2_en = 1,
393   - .trigger_level3_en = 0,
394   - .gain = 15,
395   - .reference_voltage = 7,
396   - .cal_type = TYPE_ONE_POINT_TRIMMING,
397   - .freq_tab[0] = {
398   - .freq_clip_max = 800 * 1000,
399   - .temp_level = 85,
400   - },
401   - .freq_tab[1] = {
402   - .freq_clip_max = 200 * 1000,
403   - .temp_level = 100,
404   - },
405   - .freq_tab_count = 2,
406   - .type = SOC_ARCH_EXYNOS4210,
407   -};
408   -#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
409   -#else
410   -#define EXYNOS4210_TMU_DRV_DATA (NULL)
411   -#endif
412   -
413   -#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412) || \
414   - defined(CONFIG_SOC_EXYNOS4212)
415   -static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
416   - .threshold_falling = 10,
417   - .trigger_levels[0] = 85,
418   - .trigger_levels[1] = 103,
419   - .trigger_levels[2] = 110,
420   - .trigger_level0_en = 1,
421   - .trigger_level1_en = 1,
422   - .trigger_level2_en = 1,
423   - .trigger_level3_en = 0,
424   - .gain = 8,
425   - .reference_voltage = 16,
426   - .noise_cancel_mode = 4,
427   - .cal_type = TYPE_ONE_POINT_TRIMMING,
428   - .efuse_value = 55,
429   - .freq_tab[0] = {
430   - .freq_clip_max = 800 * 1000,
431   - .temp_level = 85,
432   - },
433   - .freq_tab[1] = {
434   - .freq_clip_max = 200 * 1000,
435   - .temp_level = 103,
436   - },
437   - .freq_tab_count = 2,
438   - .type = SOC_ARCH_EXYNOS,
439   -};
440   -#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
441   -#else
442   -#define EXYNOS_TMU_DRV_DATA (NULL)
443   -#endif
444   -
445   -#ifdef CONFIG_OF
446   -static const struct of_device_id exynos_tmu_match[] = {
447   - {
448   - .compatible = "samsung,exynos4210-tmu",
449   - .data = (void *)EXYNOS4210_TMU_DRV_DATA,
450   - },
451   - {
452   - .compatible = "samsung,exynos4412-tmu",
453   - .data = (void *)EXYNOS_TMU_DRV_DATA,
454   - },
455   - {
456   - .compatible = "samsung,exynos5250-tmu",
457   - .data = (void *)EXYNOS_TMU_DRV_DATA,
458   - },
459   - {},
460   -};
461   -MODULE_DEVICE_TABLE(of, exynos_tmu_match);
462   -#endif
463   -
464   -static struct platform_device_id exynos_tmu_driver_ids[] = {
465   - {
466   - .name = "exynos4210-tmu",
467   - .driver_data = (kernel_ulong_t)EXYNOS4210_TMU_DRV_DATA,
468   - },
469   - {
470   - .name = "exynos5250-tmu",
471   - .driver_data = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
472   - },
473   - { },
474   -};
475   -MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
476   -
477   -static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
478   - struct platform_device *pdev)
479   -{
480   -#ifdef CONFIG_OF
481   - if (pdev->dev.of_node) {
482   - const struct of_device_id *match;
483   - match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
484   - if (!match)
485   - return NULL;
486   - return (struct exynos_tmu_platform_data *) match->data;
487   - }
488   -#endif
489   - return (struct exynos_tmu_platform_data *)
490   - platform_get_device_id(pdev)->driver_data;
491   -}
492   -
493   -static int exynos_tmu_probe(struct platform_device *pdev)
494   -{
495   - struct exynos_tmu_data *data;
496   - struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
497   - int ret, i;
498   -
499   - if (!pdata)
500   - pdata = exynos_get_driver_data(pdev);
501   -
502   - if (!pdata) {
503   - dev_err(&pdev->dev, "No platform init data supplied.\n");
504   - return -ENODEV;
505   - }
506   - data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
507   - GFP_KERNEL);
508   - if (!data) {
509   - dev_err(&pdev->dev, "Failed to allocate driver structure\n");
510   - return -ENOMEM;
511   - }
512   -
513   - data->irq = platform_get_irq(pdev, 0);
514   - if (data->irq < 0) {
515   - dev_err(&pdev->dev, "Failed to get platform irq\n");
516   - return data->irq;
517   - }
518   -
519   - INIT_WORK(&data->irq_work, exynos_tmu_work);
520   -
521   - data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
522   - data->base = devm_ioremap_resource(&pdev->dev, data->mem);
523   - if (IS_ERR(data->base))
524   - return PTR_ERR(data->base);
525   -
526   - ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
527   - IRQF_TRIGGER_RISING, "exynos-tmu", data);
528   - if (ret) {
529   - dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
530   - return ret;
531   - }
532   -
533   - data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
534   - if (IS_ERR(data->clk)) {
535   - dev_err(&pdev->dev, "Failed to get clock\n");
536   - return PTR_ERR(data->clk);
537   - }
538   -
539   - ret = clk_prepare(data->clk);
540   - if (ret)
541   - return ret;
542   -
543   - if (pdata->type == SOC_ARCH_EXYNOS ||
544   - pdata->type == SOC_ARCH_EXYNOS4210)
545   - data->soc = pdata->type;
546   - else {
547   - ret = -EINVAL;
548   - dev_err(&pdev->dev, "Platform not supported\n");
549   - goto err_clk;
550   - }
551   -
552   - data->pdata = pdata;
553   - platform_set_drvdata(pdev, data);
554   - mutex_init(&data->lock);
555   -
556   - ret = exynos_tmu_initialize(pdev);
557   - if (ret) {
558   - dev_err(&pdev->dev, "Failed to initialize TMU\n");
559   - goto err_clk;
560   - }
561   -
562   - exynos_tmu_control(pdev, true);
563   -
564   - /* Register the sensor with thermal management interface */
565   - (&exynos_sensor_conf)->private_data = data;
566   - exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en +
567   - pdata->trigger_level1_en + pdata->trigger_level2_en +
568   - pdata->trigger_level3_en;
569   -
570   - for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
571   - exynos_sensor_conf.trip_data.trip_val[i] =
572   - pdata->threshold + pdata->trigger_levels[i];
573   -
574   - exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
575   -
576   - exynos_sensor_conf.cooling_data.freq_clip_count =
577   - pdata->freq_tab_count;
578   - for (i = 0; i < pdata->freq_tab_count; i++) {
579   - exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
580   - pdata->freq_tab[i].freq_clip_max;
581   - exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
582   - pdata->freq_tab[i].temp_level;
583   - }
584   -
585   - ret = exynos_register_thermal(&exynos_sensor_conf);
586   - if (ret) {
587   - dev_err(&pdev->dev, "Failed to register thermal interface\n");
588   - goto err_clk;
589   - }
590   -
591   - return 0;
592   -err_clk:
593   - clk_unprepare(data->clk);
594   - return ret;
595   -}
596   -
597   -static int exynos_tmu_remove(struct platform_device *pdev)
598   -{
599   - struct exynos_tmu_data *data = platform_get_drvdata(pdev);
600   -
601   - exynos_tmu_control(pdev, false);
602   -
603   - exynos_unregister_thermal();
604   -
605   - clk_unprepare(data->clk);
606   -
607   - return 0;
608   -}
609   -
610   -#ifdef CONFIG_PM_SLEEP
611   -static int exynos_tmu_suspend(struct device *dev)
612   -{
613   - exynos_tmu_control(to_platform_device(dev), false);
614   -
615   - return 0;
616   -}
617   -
618   -static int exynos_tmu_resume(struct device *dev)
619   -{
620   - struct platform_device *pdev = to_platform_device(dev);
621   -
622   - exynos_tmu_initialize(pdev);
623   - exynos_tmu_control(pdev, true);
624   -
625   - return 0;
626   -}
627   -
628   -static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
629   - exynos_tmu_suspend, exynos_tmu_resume);
630   -#define EXYNOS_TMU_PM (&exynos_tmu_pm)
631   -#else
632   -#define EXYNOS_TMU_PM NULL
633   -#endif
634   -
635   -static struct platform_driver exynos_tmu_driver = {
636   - .driver = {
637   - .name = "exynos-tmu",
638   - .owner = THIS_MODULE,
639   - .pm = EXYNOS_TMU_PM,
640   - .of_match_table = of_match_ptr(exynos_tmu_match),
641   - },
642   - .probe = exynos_tmu_probe,
643   - .remove = exynos_tmu_remove,
644   - .id_table = exynos_tmu_driver_ids,
645   -};
646   -
647   -module_platform_driver(exynos_tmu_driver);
648   -
649   -MODULE_DESCRIPTION("EXYNOS TMU Driver");
650   -MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
651   -MODULE_LICENSE("GPL");
652   -MODULE_ALIAS("platform:exynos-tmu");
drivers/thermal/samsung/exynos_tmu.c
  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/platform_device.h>
  30 +#include <linux/platform_data/exynos_thermal.h>
  31 +
  32 +#include "exynos_thermal_common.h"
  33 +
  34 +/* Exynos generic registers */
  35 +#define EXYNOS_TMU_REG_TRIMINFO 0x0
  36 +#define EXYNOS_TMU_REG_CONTROL 0x20
  37 +#define EXYNOS_TMU_REG_STATUS 0x28
  38 +#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
  39 +#define EXYNOS_TMU_REG_INTEN 0x70
  40 +#define EXYNOS_TMU_REG_INTSTAT 0x74
  41 +#define EXYNOS_TMU_REG_INTCLEAR 0x78
  42 +
  43 +#define EXYNOS_TMU_TRIM_TEMP_MASK 0xff
  44 +#define EXYNOS_TMU_GAIN_SHIFT 8
  45 +#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
  46 +#define EXYNOS_TMU_CORE_ON 3
  47 +#define EXYNOS_TMU_CORE_OFF 2
  48 +#define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET 50
  49 +
  50 +/* Exynos4210 specific registers */
  51 +#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
  52 +#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
  53 +#define EXYNOS4210_TMU_REG_TRIG_LEVEL1 0x54
  54 +#define EXYNOS4210_TMU_REG_TRIG_LEVEL2 0x58
  55 +#define EXYNOS4210_TMU_REG_TRIG_LEVEL3 0x5C
  56 +#define EXYNOS4210_TMU_REG_PAST_TEMP0 0x60
  57 +#define EXYNOS4210_TMU_REG_PAST_TEMP1 0x64
  58 +#define EXYNOS4210_TMU_REG_PAST_TEMP2 0x68
  59 +#define EXYNOS4210_TMU_REG_PAST_TEMP3 0x6C
  60 +
  61 +#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK 0x1
  62 +#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK 0x10
  63 +#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK 0x100
  64 +#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK 0x1000
  65 +#define EXYNOS4210_TMU_INTCLEAR_VAL 0x1111
  66 +
  67 +/* Exynos5250 and Exynos4412 specific registers */
  68 +#define EXYNOS_TMU_TRIMINFO_CON 0x14
  69 +#define EXYNOS_THD_TEMP_RISE 0x50
  70 +#define EXYNOS_THD_TEMP_FALL 0x54
  71 +#define EXYNOS_EMUL_CON 0x80
  72 +
  73 +#define EXYNOS_TRIMINFO_RELOAD 0x1
  74 +#define EXYNOS_TMU_CLEAR_RISE_INT 0x111
  75 +#define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 12)
  76 +#define EXYNOS_MUX_ADDR_VALUE 6
  77 +#define EXYNOS_MUX_ADDR_SHIFT 20
  78 +#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
  79 +
  80 +#define EFUSE_MIN_VALUE 40
  81 +#define EFUSE_MAX_VALUE 100
  82 +
  83 +#ifdef CONFIG_THERMAL_EMULATION
  84 +#define EXYNOS_EMUL_TIME 0x57F0
  85 +#define EXYNOS_EMUL_TIME_SHIFT 16
  86 +#define EXYNOS_EMUL_DATA_SHIFT 8
  87 +#define EXYNOS_EMUL_DATA_MASK 0xFF
  88 +#define EXYNOS_EMUL_ENABLE 0x1
  89 +#endif /* CONFIG_THERMAL_EMULATION */
  90 +
  91 +struct exynos_tmu_data {
  92 + struct exynos_tmu_platform_data *pdata;
  93 + struct resource *mem;
  94 + void __iomem *base;
  95 + int irq;
  96 + enum soc_type soc;
  97 + struct work_struct irq_work;
  98 + struct mutex lock;
  99 + struct clk *clk;
  100 + u8 temp_error1, temp_error2;
  101 +};
  102 +
  103 +/*
  104 + * TMU treats temperature as a mapped temperature code.
  105 + * The temperature is converted differently depending on the calibration type.
  106 + */
  107 +static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
  108 +{
  109 + struct exynos_tmu_platform_data *pdata = data->pdata;
  110 + int temp_code;
  111 +
  112 + if (data->soc == SOC_ARCH_EXYNOS4210)
  113 + /* temp should range between 25 and 125 */
  114 + if (temp < 25 || temp > 125) {
  115 + temp_code = -EINVAL;
  116 + goto out;
  117 + }
  118 +
  119 + switch (pdata->cal_type) {
  120 + case TYPE_TWO_POINT_TRIMMING:
  121 + temp_code = (temp - 25) *
  122 + (data->temp_error2 - data->temp_error1) /
  123 + (85 - 25) + data->temp_error1;
  124 + break;
  125 + case TYPE_ONE_POINT_TRIMMING:
  126 + temp_code = temp + data->temp_error1 - 25;
  127 + break;
  128 + default:
  129 + temp_code = temp + EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
  130 + break;
  131 + }
  132 +out:
  133 + return temp_code;
  134 +}
  135 +
  136 +/*
  137 + * Calculate a temperature value from a temperature code.
  138 + * The unit of the temperature is degree Celsius.
  139 + */
  140 +static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
  141 +{
  142 + struct exynos_tmu_platform_data *pdata = data->pdata;
  143 + int temp;
  144 +
  145 + if (data->soc == SOC_ARCH_EXYNOS4210)
  146 + /* temp_code should range between 75 and 175 */
  147 + if (temp_code < 75 || temp_code > 175) {
  148 + temp = -ENODATA;
  149 + goto out;
  150 + }
  151 +
  152 + switch (pdata->cal_type) {
  153 + case TYPE_TWO_POINT_TRIMMING:
  154 + temp = (temp_code - data->temp_error1) * (85 - 25) /
  155 + (data->temp_error2 - data->temp_error1) + 25;
  156 + break;
  157 + case TYPE_ONE_POINT_TRIMMING:
  158 + temp = temp_code - data->temp_error1 + 25;
  159 + break;
  160 + default:
  161 + temp = temp_code - EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
  162 + break;
  163 + }
  164 +out:
  165 + return temp;
  166 +}
  167 +
  168 +static int exynos_tmu_initialize(struct platform_device *pdev)
  169 +{
  170 + struct exynos_tmu_data *data = platform_get_drvdata(pdev);
  171 + struct exynos_tmu_platform_data *pdata = data->pdata;
  172 + unsigned int status, trim_info;
  173 + unsigned int rising_threshold = 0, falling_threshold = 0;
  174 + int ret = 0, threshold_code, i, trigger_levs = 0;
  175 +
  176 + mutex_lock(&data->lock);
  177 + clk_enable(data->clk);
  178 +
  179 + status = readb(data->base + EXYNOS_TMU_REG_STATUS);
  180 + if (!status) {
  181 + ret = -EBUSY;
  182 + goto out;
  183 + }
  184 +
  185 + if (data->soc == SOC_ARCH_EXYNOS) {
  186 + __raw_writel(EXYNOS_TRIMINFO_RELOAD,
  187 + data->base + EXYNOS_TMU_TRIMINFO_CON);
  188 + }
  189 + /* Save trimming info in order to perform calibration */
  190 + trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
  191 + data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
  192 + data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
  193 +
  194 + if ((EFUSE_MIN_VALUE > data->temp_error1) ||
  195 + (data->temp_error1 > EFUSE_MAX_VALUE) ||
  196 + (data->temp_error2 != 0))
  197 + data->temp_error1 = pdata->efuse_value;
  198 +
  199 + /* Count trigger levels to be enabled */
  200 + for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
  201 + if (pdata->trigger_levels[i])
  202 + trigger_levs++;
  203 +
  204 + if (data->soc == SOC_ARCH_EXYNOS4210) {
  205 + /* Write temperature code for threshold */
  206 + threshold_code = temp_to_code(data, pdata->threshold);
  207 + if (threshold_code < 0) {
  208 + ret = threshold_code;
  209 + goto out;
  210 + }
  211 + writeb(threshold_code,
  212 + data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
  213 + for (i = 0; i < trigger_levs; i++)
  214 + writeb(pdata->trigger_levels[i],
  215 + data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
  216 +
  217 + writel(EXYNOS4210_TMU_INTCLEAR_VAL,
  218 + data->base + EXYNOS_TMU_REG_INTCLEAR);
  219 + } else if (data->soc == SOC_ARCH_EXYNOS) {
  220 + /* Write temperature code for rising and falling threshold */
  221 + for (i = 0; i < trigger_levs; i++) {
  222 + threshold_code = temp_to_code(data,
  223 + pdata->trigger_levels[i]);
  224 + if (threshold_code < 0) {
  225 + ret = threshold_code;
  226 + goto out;
  227 + }
  228 + rising_threshold |= threshold_code << 8 * i;
  229 + if (pdata->threshold_falling) {
  230 + threshold_code = temp_to_code(data,
  231 + pdata->trigger_levels[i] -
  232 + pdata->threshold_falling);
  233 + if (threshold_code > 0)
  234 + falling_threshold |=
  235 + threshold_code << 8 * i;
  236 + }
  237 + }
  238 +
  239 + writel(rising_threshold,
  240 + data->base + EXYNOS_THD_TEMP_RISE);
  241 + writel(falling_threshold,
  242 + data->base + EXYNOS_THD_TEMP_FALL);
  243 +
  244 + writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
  245 + data->base + EXYNOS_TMU_REG_INTCLEAR);
  246 + }
  247 +out:
  248 + clk_disable(data->clk);
  249 + mutex_unlock(&data->lock);
  250 +
  251 + return ret;
  252 +}
  253 +
  254 +static void exynos_tmu_control(struct platform_device *pdev, bool on)
  255 +{
  256 + struct exynos_tmu_data *data = platform_get_drvdata(pdev);
  257 + struct exynos_tmu_platform_data *pdata = data->pdata;
  258 + unsigned int con, interrupt_en;
  259 +
  260 + mutex_lock(&data->lock);
  261 + clk_enable(data->clk);
  262 +
  263 + con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
  264 + pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
  265 +
  266 + if (data->soc == SOC_ARCH_EXYNOS) {
  267 + con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
  268 + con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
  269 + }
  270 +
  271 + if (on) {
  272 + con |= EXYNOS_TMU_CORE_ON;
  273 + interrupt_en = pdata->trigger_level3_en << 12 |
  274 + pdata->trigger_level2_en << 8 |
  275 + pdata->trigger_level1_en << 4 |
  276 + pdata->trigger_level0_en;
  277 + if (pdata->threshold_falling)
  278 + interrupt_en |= interrupt_en << 16;
  279 + } else {
  280 + con |= EXYNOS_TMU_CORE_OFF;
  281 + interrupt_en = 0; /* Disable all interrupts */
  282 + }
  283 + writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
  284 + writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
  285 +
  286 + clk_disable(data->clk);
  287 + mutex_unlock(&data->lock);
  288 +}
  289 +
  290 +static int exynos_tmu_read(struct exynos_tmu_data *data)
  291 +{
  292 + u8 temp_code;
  293 + int temp;
  294 +
  295 + mutex_lock(&data->lock);
  296 + clk_enable(data->clk);
  297 +
  298 + temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
  299 + temp = code_to_temp(data, temp_code);
  300 +
  301 + clk_disable(data->clk);
  302 + mutex_unlock(&data->lock);
  303 +
  304 + return temp;
  305 +}
  306 +
  307 +#ifdef CONFIG_THERMAL_EMULATION
  308 +static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
  309 +{
  310 + struct exynos_tmu_data *data = drv_data;
  311 + unsigned int reg;
  312 + int ret = -EINVAL;
  313 +
  314 + if (data->soc == SOC_ARCH_EXYNOS4210)
  315 + goto out;
  316 +
  317 + if (temp && temp < MCELSIUS)
  318 + goto out;
  319 +
  320 + mutex_lock(&data->lock);
  321 + clk_enable(data->clk);
  322 +
  323 + reg = readl(data->base + EXYNOS_EMUL_CON);
  324 +
  325 + if (temp) {
  326 + temp /= MCELSIUS;
  327 +
  328 + reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
  329 + (temp_to_code(data, temp)
  330 + << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
  331 + } else {
  332 + reg &= ~EXYNOS_EMUL_ENABLE;
  333 + }
  334 +
  335 + writel(reg, data->base + EXYNOS_EMUL_CON);
  336 +
  337 + clk_disable(data->clk);
  338 + mutex_unlock(&data->lock);
  339 + return 0;
  340 +out:
  341 + return ret;
  342 +}
  343 +#else
  344 +static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
  345 + { return -EINVAL; }
  346 +#endif/*CONFIG_THERMAL_EMULATION*/
  347 +
  348 +static void exynos_tmu_work(struct work_struct *work)
  349 +{
  350 + struct exynos_tmu_data *data = container_of(work,
  351 + struct exynos_tmu_data, irq_work);
  352 +
  353 + exynos_report_trigger();
  354 + mutex_lock(&data->lock);
  355 + clk_enable(data->clk);
  356 + if (data->soc == SOC_ARCH_EXYNOS)
  357 + writel(EXYNOS_TMU_CLEAR_RISE_INT |
  358 + EXYNOS_TMU_CLEAR_FALL_INT,
  359 + data->base + EXYNOS_TMU_REG_INTCLEAR);
  360 + else
  361 + writel(EXYNOS4210_TMU_INTCLEAR_VAL,
  362 + data->base + EXYNOS_TMU_REG_INTCLEAR);
  363 + clk_disable(data->clk);
  364 + mutex_unlock(&data->lock);
  365 +
  366 + enable_irq(data->irq);
  367 +}
  368 +
  369 +static irqreturn_t exynos_tmu_irq(int irq, void *id)
  370 +{
  371 + struct exynos_tmu_data *data = id;
  372 +
  373 + disable_irq_nosync(irq);
  374 + schedule_work(&data->irq_work);
  375 +
  376 + return IRQ_HANDLED;
  377 +}
  378 +static struct thermal_sensor_conf exynos_sensor_conf = {
  379 + .name = "exynos-therm",
  380 + .read_temperature = (int (*)(void *))exynos_tmu_read,
  381 + .write_emul_temp = exynos_tmu_set_emulation,
  382 +};
  383 +
  384 +#if defined(CONFIG_CPU_EXYNOS4210)
  385 +static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
  386 + .threshold = 80,
  387 + .trigger_levels[0] = 5,
  388 + .trigger_levels[1] = 20,
  389 + .trigger_levels[2] = 30,
  390 + .trigger_level0_en = 1,
  391 + .trigger_level1_en = 1,
  392 + .trigger_level2_en = 1,
  393 + .trigger_level3_en = 0,
  394 + .gain = 15,
  395 + .reference_voltage = 7,
  396 + .cal_type = TYPE_ONE_POINT_TRIMMING,
  397 + .freq_tab[0] = {
  398 + .freq_clip_max = 800 * 1000,
  399 + .temp_level = 85,
  400 + },
  401 + .freq_tab[1] = {
  402 + .freq_clip_max = 200 * 1000,
  403 + .temp_level = 100,
  404 + },
  405 + .freq_tab_count = 2,
  406 + .type = SOC_ARCH_EXYNOS4210,
  407 +};
  408 +#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
  409 +#else
  410 +#define EXYNOS4210_TMU_DRV_DATA (NULL)
  411 +#endif
  412 +
  413 +#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412) || \
  414 + defined(CONFIG_SOC_EXYNOS4212)
  415 +static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
  416 + .threshold_falling = 10,
  417 + .trigger_levels[0] = 85,
  418 + .trigger_levels[1] = 103,
  419 + .trigger_levels[2] = 110,
  420 + .trigger_level0_en = 1,
  421 + .trigger_level1_en = 1,
  422 + .trigger_level2_en = 1,
  423 + .trigger_level3_en = 0,
  424 + .gain = 8,
  425 + .reference_voltage = 16,
  426 + .noise_cancel_mode = 4,
  427 + .cal_type = TYPE_ONE_POINT_TRIMMING,
  428 + .efuse_value = 55,
  429 + .freq_tab[0] = {
  430 + .freq_clip_max = 800 * 1000,
  431 + .temp_level = 85,
  432 + },
  433 + .freq_tab[1] = {
  434 + .freq_clip_max = 200 * 1000,
  435 + .temp_level = 103,
  436 + },
  437 + .freq_tab_count = 2,
  438 + .type = SOC_ARCH_EXYNOS,
  439 +};
  440 +#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
  441 +#else
  442 +#define EXYNOS_TMU_DRV_DATA (NULL)
  443 +#endif
  444 +
  445 +#ifdef CONFIG_OF
  446 +static const struct of_device_id exynos_tmu_match[] = {
  447 + {
  448 + .compatible = "samsung,exynos4210-tmu",
  449 + .data = (void *)EXYNOS4210_TMU_DRV_DATA,
  450 + },
  451 + {
  452 + .compatible = "samsung,exynos4412-tmu",
  453 + .data = (void *)EXYNOS_TMU_DRV_DATA,
  454 + },
  455 + {
  456 + .compatible = "samsung,exynos5250-tmu",
  457 + .data = (void *)EXYNOS_TMU_DRV_DATA,
  458 + },
  459 + {},
  460 +};
  461 +MODULE_DEVICE_TABLE(of, exynos_tmu_match);
  462 +#endif
  463 +
  464 +static struct platform_device_id exynos_tmu_driver_ids[] = {
  465 + {
  466 + .name = "exynos4210-tmu",
  467 + .driver_data = (kernel_ulong_t)EXYNOS4210_TMU_DRV_DATA,
  468 + },
  469 + {
  470 + .name = "exynos5250-tmu",
  471 + .driver_data = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
  472 + },
  473 + { },
  474 +};
  475 +MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
  476 +
  477 +static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
  478 + struct platform_device *pdev)
  479 +{
  480 +#ifdef CONFIG_OF
  481 + if (pdev->dev.of_node) {
  482 + const struct of_device_id *match;
  483 + match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
  484 + if (!match)
  485 + return NULL;
  486 + return (struct exynos_tmu_platform_data *) match->data;
  487 + }
  488 +#endif
  489 + return (struct exynos_tmu_platform_data *)
  490 + platform_get_device_id(pdev)->driver_data;
  491 +}
  492 +
  493 +static int exynos_tmu_probe(struct platform_device *pdev)
  494 +{
  495 + struct exynos_tmu_data *data;
  496 + struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
  497 + int ret, i;
  498 +
  499 + if (!pdata)
  500 + pdata = exynos_get_driver_data(pdev);
  501 +
  502 + if (!pdata) {
  503 + dev_err(&pdev->dev, "No platform init data supplied.\n");
  504 + return -ENODEV;
  505 + }
  506 + data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
  507 + GFP_KERNEL);
  508 + if (!data) {
  509 + dev_err(&pdev->dev, "Failed to allocate driver structure\n");
  510 + return -ENOMEM;
  511 + }
  512 +
  513 + data->irq = platform_get_irq(pdev, 0);
  514 + if (data->irq < 0) {
  515 + dev_err(&pdev->dev, "Failed to get platform irq\n");
  516 + return data->irq;
  517 + }
  518 +
  519 + INIT_WORK(&data->irq_work, exynos_tmu_work);
  520 +
  521 + data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  522 + data->base = devm_ioremap_resource(&pdev->dev, data->mem);
  523 + if (IS_ERR(data->base))
  524 + return PTR_ERR(data->base);
  525 +
  526 + ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
  527 + IRQF_TRIGGER_RISING, "exynos-tmu", data);
  528 + if (ret) {
  529 + dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
  530 + return ret;
  531 + }
  532 +
  533 + data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
  534 + if (IS_ERR(data->clk)) {
  535 + dev_err(&pdev->dev, "Failed to get clock\n");
  536 + return PTR_ERR(data->clk);
  537 + }
  538 +
  539 + ret = clk_prepare(data->clk);
  540 + if (ret)
  541 + return ret;
  542 +
  543 + if (pdata->type == SOC_ARCH_EXYNOS ||
  544 + pdata->type == SOC_ARCH_EXYNOS4210)
  545 + data->soc = pdata->type;
  546 + else {
  547 + ret = -EINVAL;
  548 + dev_err(&pdev->dev, "Platform not supported\n");
  549 + goto err_clk;
  550 + }
  551 +
  552 + data->pdata = pdata;
  553 + platform_set_drvdata(pdev, data);
  554 + mutex_init(&data->lock);
  555 +
  556 + ret = exynos_tmu_initialize(pdev);
  557 + if (ret) {
  558 + dev_err(&pdev->dev, "Failed to initialize TMU\n");
  559 + goto err_clk;
  560 + }
  561 +
  562 + exynos_tmu_control(pdev, true);
  563 +
  564 + /* Register the sensor with thermal management interface */
  565 + (&exynos_sensor_conf)->private_data = data;
  566 + exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en +
  567 + pdata->trigger_level1_en + pdata->trigger_level2_en +
  568 + pdata->trigger_level3_en;
  569 +
  570 + for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
  571 + exynos_sensor_conf.trip_data.trip_val[i] =
  572 + pdata->threshold + pdata->trigger_levels[i];
  573 +
  574 + exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
  575 +
  576 + exynos_sensor_conf.cooling_data.freq_clip_count =
  577 + pdata->freq_tab_count;
  578 + for (i = 0; i < pdata->freq_tab_count; i++) {
  579 + exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
  580 + pdata->freq_tab[i].freq_clip_max;
  581 + exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
  582 + pdata->freq_tab[i].temp_level;
  583 + }
  584 +
  585 + ret = exynos_register_thermal(&exynos_sensor_conf);
  586 + if (ret) {
  587 + dev_err(&pdev->dev, "Failed to register thermal interface\n");
  588 + goto err_clk;
  589 + }
  590 +
  591 + return 0;
  592 +err_clk:
  593 + clk_unprepare(data->clk);
  594 + return ret;
  595 +}
  596 +
  597 +static int exynos_tmu_remove(struct platform_device *pdev)
  598 +{
  599 + struct exynos_tmu_data *data = platform_get_drvdata(pdev);
  600 +
  601 + exynos_tmu_control(pdev, false);
  602 +
  603 + exynos_unregister_thermal();
  604 +
  605 + clk_unprepare(data->clk);
  606 +
  607 + return 0;
  608 +}
  609 +
  610 +#ifdef CONFIG_PM_SLEEP
  611 +static int exynos_tmu_suspend(struct device *dev)
  612 +{
  613 + exynos_tmu_control(to_platform_device(dev), false);
  614 +
  615 + return 0;
  616 +}
  617 +
  618 +static int exynos_tmu_resume(struct device *dev)
  619 +{
  620 + struct platform_device *pdev = to_platform_device(dev);
  621 +
  622 + exynos_tmu_initialize(pdev);
  623 + exynos_tmu_control(pdev, true);
  624 +
  625 + return 0;
  626 +}
  627 +
  628 +static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
  629 + exynos_tmu_suspend, exynos_tmu_resume);
  630 +#define EXYNOS_TMU_PM (&exynos_tmu_pm)
  631 +#else
  632 +#define EXYNOS_TMU_PM NULL
  633 +#endif
  634 +
  635 +static struct platform_driver exynos_tmu_driver = {
  636 + .driver = {
  637 + .name = "exynos-tmu",
  638 + .owner = THIS_MODULE,
  639 + .pm = EXYNOS_TMU_PM,
  640 + .of_match_table = of_match_ptr(exynos_tmu_match),
  641 + },
  642 + .probe = exynos_tmu_probe,
  643 + .remove = exynos_tmu_remove,
  644 + .id_table = exynos_tmu_driver_ids,
  645 +};
  646 +
  647 +module_platform_driver(exynos_tmu_driver);
  648 +
  649 +MODULE_DESCRIPTION("EXYNOS TMU Driver");
  650 +MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
  651 +MODULE_LICENSE("GPL");
  652 +MODULE_ALIAS("platform:exynos-tmu");