aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/thermal/Kconfig24
-rw-r--r--drivers/thermal/Makefile3
-rw-r--r--drivers/thermal/exynos_thermal.c1059
-rw-r--r--drivers/thermal/imx_thermal.c541
-rw-r--r--drivers/thermal/samsung/Kconfig18
-rw-r--r--drivers/thermal/samsung/Makefile7
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.c432
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.h107
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c768
-rw-r--r--drivers/thermal/samsung/exynos_tmu.h311
-rw-r--r--drivers/thermal/samsung/exynos_tmu_data.c250
-rw-r--r--drivers/thermal/samsung/exynos_tmu_data.h155
12 files changed, 2607 insertions, 1068 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index e988c81d763c..ae18f025a761 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -91,6 +91,17 @@ config THERMAL_EMULATION
91 because userland can easily disable the thermal policy by simply 91 because userland can easily disable the thermal policy by simply
92 flooding this sysfs node with low temperature values. 92 flooding this sysfs node with low temperature values.
93 93
94config IMX_THERMAL
95 tristate "Temperature sensor driver for Freescale i.MX SoCs"
96 depends on CPU_THERMAL
97 depends on MFD_SYSCON
98 depends on OF
99 help
100 Support for Temperature Monitor (TEMPMON) found on Freescale i.MX SoCs.
101 It supports one critical trip point and one passive trip point. The
102 cpufreq is used as the cooling device to throttle CPUs when the
103 passive trip is crossed.
104
94config SPEAR_THERMAL 105config SPEAR_THERMAL
95 bool "SPEAr thermal sensor driver" 106 bool "SPEAr thermal sensor driver"
96 depends on PLAT_SPEAR 107 depends on PLAT_SPEAR
@@ -114,14 +125,6 @@ config KIRKWOOD_THERMAL
114 Support for the Kirkwood thermal sensor driver into the Linux thermal 125 Support for the Kirkwood thermal sensor driver into the Linux thermal
115 framework. Only kirkwood 88F6282 and 88F6283 have this sensor. 126 framework. Only kirkwood 88F6282 and 88F6283 have this sensor.
116 127
117config EXYNOS_THERMAL
118 tristate "Temperature sensor on Samsung EXYNOS"
119 depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
120 depends on CPU_THERMAL
121 help
122 If you say yes here you get support for TMU (Thermal Management
123 Unit) on SAMSUNG EXYNOS series of SoC.
124
125config DOVE_THERMAL 128config DOVE_THERMAL
126 tristate "Temperature sensor on Marvell Dove SoCs" 129 tristate "Temperature sensor on Marvell Dove SoCs"
127 depends on ARCH_DOVE 130 depends on ARCH_DOVE
@@ -184,4 +187,9 @@ menu "Texas Instruments thermal drivers"
184source "drivers/thermal/ti-soc-thermal/Kconfig" 187source "drivers/thermal/ti-soc-thermal/Kconfig"
185endmenu 188endmenu
186 189
190menu "Samsung thermal drivers"
191depends on PLAT_SAMSUNG
192source "drivers/thermal/samsung/Kconfig"
193endmenu
194
187endif 195endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 67184a293e3f..c19df7ab2614 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -17,10 +17,11 @@ thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
17obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 17obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
18obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o 18obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
19obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o 19obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
20obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o 20obj-y += samsung/
21obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o 21obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
22obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o 22obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
23obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o 23obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
24obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
24obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o 25obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
25obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 26obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
26obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o 27obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
deleted file mode 100644
index 9af4b93c9f86..000000000000
--- a/drivers/thermal/exynos_thermal.c
+++ /dev/null
@@ -1,1059 +0,0 @@
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/module.h>
25#include <linux/err.h>
26#include <linux/kernel.h>
27#include <linux/slab.h>
28#include <linux/platform_device.h>
29#include <linux/interrupt.h>
30#include <linux/clk.h>
31#include <linux/workqueue.h>
32#include <linux/sysfs.h>
33#include <linux/kobject.h>
34#include <linux/io.h>
35#include <linux/mutex.h>
36#include <linux/platform_data/exynos_thermal.h>
37#include <linux/thermal.h>
38#include <linux/cpufreq.h>
39#include <linux/cpu_cooling.h>
40#include <linux/of.h>
41
42/* Exynos generic registers */
43#define EXYNOS_TMU_REG_TRIMINFO 0x0
44#define EXYNOS_TMU_REG_CONTROL 0x20
45#define EXYNOS_TMU_REG_STATUS 0x28
46#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
47#define EXYNOS_TMU_REG_INTEN 0x70
48#define EXYNOS_TMU_REG_INTSTAT 0x74
49#define EXYNOS_TMU_REG_INTCLEAR 0x78
50
51#define EXYNOS_TMU_TRIM_TEMP_MASK 0xff
52#define EXYNOS_TMU_GAIN_SHIFT 8
53#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
54#define EXYNOS_TMU_CORE_ON 3
55#define EXYNOS_TMU_CORE_OFF 2
56#define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET 50
57
58/* Exynos4210 specific registers */
59#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
60#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
61#define EXYNOS4210_TMU_REG_TRIG_LEVEL1 0x54
62#define EXYNOS4210_TMU_REG_TRIG_LEVEL2 0x58
63#define EXYNOS4210_TMU_REG_TRIG_LEVEL3 0x5C
64#define EXYNOS4210_TMU_REG_PAST_TEMP0 0x60
65#define EXYNOS4210_TMU_REG_PAST_TEMP1 0x64
66#define EXYNOS4210_TMU_REG_PAST_TEMP2 0x68
67#define EXYNOS4210_TMU_REG_PAST_TEMP3 0x6C
68
69#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK 0x1
70#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK 0x10
71#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK 0x100
72#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK 0x1000
73#define EXYNOS4210_TMU_INTCLEAR_VAL 0x1111
74
75/* Exynos5250 and Exynos4412 specific registers */
76#define EXYNOS_TMU_TRIMINFO_CON 0x14
77#define EXYNOS_THD_TEMP_RISE 0x50
78#define EXYNOS_THD_TEMP_FALL 0x54
79#define EXYNOS_EMUL_CON 0x80
80
81#define EXYNOS_TRIMINFO_RELOAD 0x1
82#define EXYNOS_TMU_CLEAR_RISE_INT 0x111
83#define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 12)
84#define EXYNOS_MUX_ADDR_VALUE 6
85#define EXYNOS_MUX_ADDR_SHIFT 20
86#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
87
88#define EFUSE_MIN_VALUE 40
89#define EFUSE_MAX_VALUE 100
90
91/* In-kernel thermal framework related macros & definations */
92#define SENSOR_NAME_LEN 16
93#define MAX_TRIP_COUNT 8
94#define MAX_COOLING_DEVICE 4
95#define MAX_THRESHOLD_LEVS 4
96
97#define ACTIVE_INTERVAL 500
98#define IDLE_INTERVAL 10000
99#define MCELSIUS 1000
100
101#ifdef CONFIG_THERMAL_EMULATION
102#define EXYNOS_EMUL_TIME 0x57F0
103#define EXYNOS_EMUL_TIME_SHIFT 16
104#define EXYNOS_EMUL_DATA_SHIFT 8
105#define EXYNOS_EMUL_DATA_MASK 0xFF
106#define EXYNOS_EMUL_ENABLE 0x1
107#endif /* CONFIG_THERMAL_EMULATION */
108
109/* CPU Zone information */
110#define PANIC_ZONE 4
111#define WARN_ZONE 3
112#define MONITOR_ZONE 2
113#define SAFE_ZONE 1
114
115#define GET_ZONE(trip) (trip + 2)
116#define GET_TRIP(zone) (zone - 2)
117
118#define EXYNOS_ZONE_COUNT 3
119
120struct exynos_tmu_data {
121 struct exynos_tmu_platform_data *pdata;
122 struct resource *mem;
123 void __iomem *base;
124 int irq;
125 enum soc_type soc;
126 struct work_struct irq_work;
127 struct mutex lock;
128 struct clk *clk;
129 u8 temp_error1, temp_error2;
130};
131
132struct thermal_trip_point_conf {
133 int trip_val[MAX_TRIP_COUNT];
134 int trip_count;
135 u8 trigger_falling;
136};
137
138struct thermal_cooling_conf {
139 struct freq_clip_table freq_data[MAX_TRIP_COUNT];
140 int freq_clip_count;
141};
142
143struct thermal_sensor_conf {
144 char name[SENSOR_NAME_LEN];
145 int (*read_temperature)(void *data);
146 int (*write_emul_temp)(void *drv_data, unsigned long temp);
147 struct thermal_trip_point_conf trip_data;
148 struct thermal_cooling_conf cooling_data;
149 void *private_data;
150};
151
152struct exynos_thermal_zone {
153 enum thermal_device_mode mode;
154 struct thermal_zone_device *therm_dev;
155 struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
156 unsigned int cool_dev_size;
157 struct platform_device *exynos4_dev;
158 struct thermal_sensor_conf *sensor_conf;
159 bool bind;
160};
161
162static struct exynos_thermal_zone *th_zone;
163static void exynos_unregister_thermal(void);
164static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
165
166/* Get mode callback functions for thermal zone */
167static int exynos_get_mode(struct thermal_zone_device *thermal,
168 enum thermal_device_mode *mode)
169{
170 if (th_zone)
171 *mode = th_zone->mode;
172 return 0;
173}
174
175/* Set mode callback functions for thermal zone */
176static int exynos_set_mode(struct thermal_zone_device *thermal,
177 enum thermal_device_mode mode)
178{
179 if (!th_zone->therm_dev) {
180 pr_notice("thermal zone not registered\n");
181 return 0;
182 }
183
184 mutex_lock(&th_zone->therm_dev->lock);
185
186 if (mode == THERMAL_DEVICE_ENABLED &&
187 !th_zone->sensor_conf->trip_data.trigger_falling)
188 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
189 else
190 th_zone->therm_dev->polling_delay = 0;
191
192 mutex_unlock(&th_zone->therm_dev->lock);
193
194 th_zone->mode = mode;
195 thermal_zone_device_update(th_zone->therm_dev);
196 pr_info("thermal polling set for duration=%d msec\n",
197 th_zone->therm_dev->polling_delay);
198 return 0;
199}
200
201
202/* Get trip type callback functions for thermal zone */
203static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
204 enum thermal_trip_type *type)
205{
206 switch (GET_ZONE(trip)) {
207 case MONITOR_ZONE:
208 case WARN_ZONE:
209 *type = THERMAL_TRIP_ACTIVE;
210 break;
211 case PANIC_ZONE:
212 *type = THERMAL_TRIP_CRITICAL;
213 break;
214 default:
215 return -EINVAL;
216 }
217 return 0;
218}
219
220/* Get trip temperature callback functions for thermal zone */
221static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
222 unsigned long *temp)
223{
224 if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
225 return -EINVAL;
226
227 *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
228 /* convert the temperature into millicelsius */
229 *temp = *temp * MCELSIUS;
230
231 return 0;
232}
233
234/* Get critical temperature callback functions for thermal zone */
235static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
236 unsigned long *temp)
237{
238 int ret;
239 /* Panic zone */
240 ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
241 return ret;
242}
243
244/* Bind callback functions for thermal zone */
245static int exynos_bind(struct thermal_zone_device *thermal,
246 struct thermal_cooling_device *cdev)
247{
248 int ret = 0, i, tab_size, level;
249 struct freq_clip_table *tab_ptr, *clip_data;
250 struct thermal_sensor_conf *data = th_zone->sensor_conf;
251
252 tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
253 tab_size = data->cooling_data.freq_clip_count;
254
255 if (tab_ptr == NULL || tab_size == 0)
256 return -EINVAL;
257
258 /* find the cooling device registered*/
259 for (i = 0; i < th_zone->cool_dev_size; i++)
260 if (cdev == th_zone->cool_dev[i])
261 break;
262
263 /* No matching cooling device */
264 if (i == th_zone->cool_dev_size)
265 return 0;
266
267 /* Bind the thermal zone to the cpufreq cooling device */
268 for (i = 0; i < tab_size; i++) {
269 clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
270 level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
271 if (level == THERMAL_CSTATE_INVALID)
272 return 0;
273 switch (GET_ZONE(i)) {
274 case MONITOR_ZONE:
275 case WARN_ZONE:
276 if (thermal_zone_bind_cooling_device(thermal, i, cdev,
277 level, 0)) {
278 pr_err("error binding cdev inst %d\n", i);
279 ret = -EINVAL;
280 }
281 th_zone->bind = true;
282 break;
283 default:
284 ret = -EINVAL;
285 }
286 }
287
288 return ret;
289}
290
291/* Unbind callback functions for thermal zone */
292static int exynos_unbind(struct thermal_zone_device *thermal,
293 struct thermal_cooling_device *cdev)
294{
295 int ret = 0, i, tab_size;
296 struct thermal_sensor_conf *data = th_zone->sensor_conf;
297
298 if (th_zone->bind == false)
299 return 0;
300
301 tab_size = data->cooling_data.freq_clip_count;
302
303 if (tab_size == 0)
304 return -EINVAL;
305
306 /* find the cooling device registered*/
307 for (i = 0; i < th_zone->cool_dev_size; i++)
308 if (cdev == th_zone->cool_dev[i])
309 break;
310
311 /* No matching cooling device */
312 if (i == th_zone->cool_dev_size)
313 return 0;
314
315 /* Bind the thermal zone to the cpufreq cooling device */
316 for (i = 0; i < tab_size; i++) {
317 switch (GET_ZONE(i)) {
318 case MONITOR_ZONE:
319 case WARN_ZONE:
320 if (thermal_zone_unbind_cooling_device(thermal, i,
321 cdev)) {
322 pr_err("error unbinding cdev inst=%d\n", i);
323 ret = -EINVAL;
324 }
325 th_zone->bind = false;
326 break;
327 default:
328 ret = -EINVAL;
329 }
330 }
331 return ret;
332}
333
334/* Get temperature callback functions for thermal zone */
335static int exynos_get_temp(struct thermal_zone_device *thermal,
336 unsigned long *temp)
337{
338 void *data;
339
340 if (!th_zone->sensor_conf) {
341 pr_info("Temperature sensor not initialised\n");
342 return -EINVAL;
343 }
344 data = th_zone->sensor_conf->private_data;
345 *temp = th_zone->sensor_conf->read_temperature(data);
346 /* convert the temperature into millicelsius */
347 *temp = *temp * MCELSIUS;
348 return 0;
349}
350
351/* Get temperature callback functions for thermal zone */
352static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
353 unsigned long temp)
354{
355 void *data;
356 int ret = -EINVAL;
357
358 if (!th_zone->sensor_conf) {
359 pr_info("Temperature sensor not initialised\n");
360 return -EINVAL;
361 }
362 data = th_zone->sensor_conf->private_data;
363 if (th_zone->sensor_conf->write_emul_temp)
364 ret = th_zone->sensor_conf->write_emul_temp(data, temp);
365 return ret;
366}
367
368/* Get the temperature trend */
369static int exynos_get_trend(struct thermal_zone_device *thermal,
370 int trip, enum thermal_trend *trend)
371{
372 int ret;
373 unsigned long trip_temp;
374
375 ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
376 if (ret < 0)
377 return ret;
378
379 if (thermal->temperature >= trip_temp)
380 *trend = THERMAL_TREND_RAISE_FULL;
381 else
382 *trend = THERMAL_TREND_DROP_FULL;
383
384 return 0;
385}
386/* Operation callback functions for thermal zone */
387static struct thermal_zone_device_ops const exynos_dev_ops = {
388 .bind = exynos_bind,
389 .unbind = exynos_unbind,
390 .get_temp = exynos_get_temp,
391 .set_emul_temp = exynos_set_emul_temp,
392 .get_trend = exynos_get_trend,
393 .get_mode = exynos_get_mode,
394 .set_mode = exynos_set_mode,
395 .get_trip_type = exynos_get_trip_type,
396 .get_trip_temp = exynos_get_trip_temp,
397 .get_crit_temp = exynos_get_crit_temp,
398};
399
400/*
401 * This function may be called from interrupt based temperature sensor
402 * when threshold is changed.
403 */
404static void exynos_report_trigger(void)
405{
406 unsigned int i;
407 char data[10];
408 char *envp[] = { data, NULL };
409
410 if (!th_zone || !th_zone->therm_dev)
411 return;
412 if (th_zone->bind == false) {
413 for (i = 0; i < th_zone->cool_dev_size; i++) {
414 if (!th_zone->cool_dev[i])
415 continue;
416 exynos_bind(th_zone->therm_dev,
417 th_zone->cool_dev[i]);
418 }
419 }
420
421 thermal_zone_device_update(th_zone->therm_dev);
422
423 mutex_lock(&th_zone->therm_dev->lock);
424 /* Find the level for which trip happened */
425 for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
426 if (th_zone->therm_dev->last_temperature <
427 th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
428 break;
429 }
430
431 if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
432 !th_zone->sensor_conf->trip_data.trigger_falling) {
433 if (i > 0)
434 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
435 else
436 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
437 }
438
439 snprintf(data, sizeof(data), "%u", i);
440 kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
441 mutex_unlock(&th_zone->therm_dev->lock);
442}
443
444/* Register with the in-kernel thermal management */
445static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
446{
447 int ret;
448 struct cpumask mask_val;
449
450 if (!sensor_conf || !sensor_conf->read_temperature) {
451 pr_err("Temperature sensor not initialised\n");
452 return -EINVAL;
453 }
454
455 th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
456 if (!th_zone)
457 return -ENOMEM;
458
459 th_zone->sensor_conf = sensor_conf;
460 cpumask_set_cpu(0, &mask_val);
461 th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
462 if (IS_ERR(th_zone->cool_dev[0])) {
463 pr_err("Failed to register cpufreq cooling device\n");
464 ret = -EINVAL;
465 goto err_unregister;
466 }
467 th_zone->cool_dev_size++;
468
469 th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
470 EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
471 sensor_conf->trip_data.trigger_falling ?
472 0 : IDLE_INTERVAL);
473
474 if (IS_ERR(th_zone->therm_dev)) {
475 pr_err("Failed to register thermal zone device\n");
476 ret = PTR_ERR(th_zone->therm_dev);
477 goto err_unregister;
478 }
479 th_zone->mode = THERMAL_DEVICE_ENABLED;
480
481 pr_info("Exynos: Kernel Thermal management registered\n");
482
483 return 0;
484
485err_unregister:
486 exynos_unregister_thermal();
487 return ret;
488}
489
490/* Un-Register with the in-kernel thermal management */
491static void exynos_unregister_thermal(void)
492{
493 int i;
494
495 if (!th_zone)
496 return;
497
498 if (th_zone->therm_dev)
499 thermal_zone_device_unregister(th_zone->therm_dev);
500
501 for (i = 0; i < th_zone->cool_dev_size; i++) {
502 if (th_zone->cool_dev[i])
503 cpufreq_cooling_unregister(th_zone->cool_dev[i]);
504 }
505
506 kfree(th_zone);
507 pr_info("Exynos: Kernel Thermal management unregistered\n");
508}
509
510/*
511 * TMU treats temperature as a mapped temperature code.
512 * The temperature is converted differently depending on the calibration type.
513 */
514static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
515{
516 struct exynos_tmu_platform_data *pdata = data->pdata;
517 int temp_code;
518
519 if (data->soc == SOC_ARCH_EXYNOS4210)
520 /* temp should range between 25 and 125 */
521 if (temp < 25 || temp > 125) {
522 temp_code = -EINVAL;
523 goto out;
524 }
525
526 switch (pdata->cal_type) {
527 case TYPE_TWO_POINT_TRIMMING:
528 temp_code = (temp - 25) *
529 (data->temp_error2 - data->temp_error1) /
530 (85 - 25) + data->temp_error1;
531 break;
532 case TYPE_ONE_POINT_TRIMMING:
533 temp_code = temp + data->temp_error1 - 25;
534 break;
535 default:
536 temp_code = temp + EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
537 break;
538 }
539out:
540 return temp_code;
541}
542
543/*
544 * Calculate a temperature value from a temperature code.
545 * The unit of the temperature is degree Celsius.
546 */
547static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
548{
549 struct exynos_tmu_platform_data *pdata = data->pdata;
550 int temp;
551
552 if (data->soc == SOC_ARCH_EXYNOS4210)
553 /* temp_code should range between 75 and 175 */
554 if (temp_code < 75 || temp_code > 175) {
555 temp = -ENODATA;
556 goto out;
557 }
558
559 switch (pdata->cal_type) {
560 case TYPE_TWO_POINT_TRIMMING:
561 temp = (temp_code - data->temp_error1) * (85 - 25) /
562 (data->temp_error2 - data->temp_error1) + 25;
563 break;
564 case TYPE_ONE_POINT_TRIMMING:
565 temp = temp_code - data->temp_error1 + 25;
566 break;
567 default:
568 temp = temp_code - EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
569 break;
570 }
571out:
572 return temp;
573}
574
575static int exynos_tmu_initialize(struct platform_device *pdev)
576{
577 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
578 struct exynos_tmu_platform_data *pdata = data->pdata;
579 unsigned int status, trim_info;
580 unsigned int rising_threshold = 0, falling_threshold = 0;
581 int ret = 0, threshold_code, i, trigger_levs = 0;
582
583 mutex_lock(&data->lock);
584 clk_enable(data->clk);
585
586 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
587 if (!status) {
588 ret = -EBUSY;
589 goto out;
590 }
591
592 if (data->soc == SOC_ARCH_EXYNOS) {
593 __raw_writel(EXYNOS_TRIMINFO_RELOAD,
594 data->base + EXYNOS_TMU_TRIMINFO_CON);
595 }
596 /* Save trimming info in order to perform calibration */
597 trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
598 data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
599 data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
600
601 if ((EFUSE_MIN_VALUE > data->temp_error1) ||
602 (data->temp_error1 > EFUSE_MAX_VALUE) ||
603 (data->temp_error2 != 0))
604 data->temp_error1 = pdata->efuse_value;
605
606 /* Count trigger levels to be enabled */
607 for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
608 if (pdata->trigger_levels[i])
609 trigger_levs++;
610
611 if (data->soc == SOC_ARCH_EXYNOS4210) {
612 /* Write temperature code for threshold */
613 threshold_code = temp_to_code(data, pdata->threshold);
614 if (threshold_code < 0) {
615 ret = threshold_code;
616 goto out;
617 }
618 writeb(threshold_code,
619 data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
620 for (i = 0; i < trigger_levs; i++)
621 writeb(pdata->trigger_levels[i],
622 data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
623
624 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
625 data->base + EXYNOS_TMU_REG_INTCLEAR);
626 } else if (data->soc == SOC_ARCH_EXYNOS) {
627 /* Write temperature code for rising and falling threshold */
628 for (i = 0; i < trigger_levs; i++) {
629 threshold_code = temp_to_code(data,
630 pdata->trigger_levels[i]);
631 if (threshold_code < 0) {
632 ret = threshold_code;
633 goto out;
634 }
635 rising_threshold |= threshold_code << 8 * i;
636 if (pdata->threshold_falling) {
637 threshold_code = temp_to_code(data,
638 pdata->trigger_levels[i] -
639 pdata->threshold_falling);
640 if (threshold_code > 0)
641 falling_threshold |=
642 threshold_code << 8 * i;
643 }
644 }
645
646 writel(rising_threshold,
647 data->base + EXYNOS_THD_TEMP_RISE);
648 writel(falling_threshold,
649 data->base + EXYNOS_THD_TEMP_FALL);
650
651 writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
652 data->base + EXYNOS_TMU_REG_INTCLEAR);
653 }
654out:
655 clk_disable(data->clk);
656 mutex_unlock(&data->lock);
657
658 return ret;
659}
660
661static void exynos_tmu_control(struct platform_device *pdev, bool on)
662{
663 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
664 struct exynos_tmu_platform_data *pdata = data->pdata;
665 unsigned int con, interrupt_en;
666
667 mutex_lock(&data->lock);
668 clk_enable(data->clk);
669
670 con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
671 pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
672
673 if (data->soc == SOC_ARCH_EXYNOS) {
674 con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
675 con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
676 }
677
678 if (on) {
679 con |= EXYNOS_TMU_CORE_ON;
680 interrupt_en = pdata->trigger_level3_en << 12 |
681 pdata->trigger_level2_en << 8 |
682 pdata->trigger_level1_en << 4 |
683 pdata->trigger_level0_en;
684 if (pdata->threshold_falling)
685 interrupt_en |= interrupt_en << 16;
686 } else {
687 con |= EXYNOS_TMU_CORE_OFF;
688 interrupt_en = 0; /* Disable all interrupts */
689 }
690 writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
691 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
692
693 clk_disable(data->clk);
694 mutex_unlock(&data->lock);
695}
696
697static int exynos_tmu_read(struct exynos_tmu_data *data)
698{
699 u8 temp_code;
700 int temp;
701
702 mutex_lock(&data->lock);
703 clk_enable(data->clk);
704
705 temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
706 temp = code_to_temp(data, temp_code);
707
708 clk_disable(data->clk);
709 mutex_unlock(&data->lock);
710
711 return temp;
712}
713
714#ifdef CONFIG_THERMAL_EMULATION
715static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
716{
717 struct exynos_tmu_data *data = drv_data;
718 unsigned int reg;
719 int ret = -EINVAL;
720
721 if (data->soc == SOC_ARCH_EXYNOS4210)
722 goto out;
723
724 if (temp && temp < MCELSIUS)
725 goto out;
726
727 mutex_lock(&data->lock);
728 clk_enable(data->clk);
729
730 reg = readl(data->base + EXYNOS_EMUL_CON);
731
732 if (temp) {
733 temp /= MCELSIUS;
734
735 reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
736 (temp_to_code(data, temp)
737 << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
738 } else {
739 reg &= ~EXYNOS_EMUL_ENABLE;
740 }
741
742 writel(reg, data->base + EXYNOS_EMUL_CON);
743
744 clk_disable(data->clk);
745 mutex_unlock(&data->lock);
746 return 0;
747out:
748 return ret;
749}
750#else
751static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
752 { return -EINVAL; }
753#endif/*CONFIG_THERMAL_EMULATION*/
754
755static void exynos_tmu_work(struct work_struct *work)
756{
757 struct exynos_tmu_data *data = container_of(work,
758 struct exynos_tmu_data, irq_work);
759
760 exynos_report_trigger();
761 mutex_lock(&data->lock);
762 clk_enable(data->clk);
763 if (data->soc == SOC_ARCH_EXYNOS)
764 writel(EXYNOS_TMU_CLEAR_RISE_INT |
765 EXYNOS_TMU_CLEAR_FALL_INT,
766 data->base + EXYNOS_TMU_REG_INTCLEAR);
767 else
768 writel(EXYNOS4210_TMU_INTCLEAR_VAL,
769 data->base + EXYNOS_TMU_REG_INTCLEAR);
770 clk_disable(data->clk);
771 mutex_unlock(&data->lock);
772
773 enable_irq(data->irq);
774}
775
776static irqreturn_t exynos_tmu_irq(int irq, void *id)
777{
778 struct exynos_tmu_data *data = id;
779
780 disable_irq_nosync(irq);
781 schedule_work(&data->irq_work);
782
783 return IRQ_HANDLED;
784}
785static struct thermal_sensor_conf exynos_sensor_conf = {
786 .name = "exynos-therm",
787 .read_temperature = (int (*)(void *))exynos_tmu_read,
788 .write_emul_temp = exynos_tmu_set_emulation,
789};
790
791#if defined(CONFIG_CPU_EXYNOS4210)
792static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
793 .threshold = 80,
794 .trigger_levels[0] = 5,
795 .trigger_levels[1] = 20,
796 .trigger_levels[2] = 30,
797 .trigger_level0_en = 1,
798 .trigger_level1_en = 1,
799 .trigger_level2_en = 1,
800 .trigger_level3_en = 0,
801 .gain = 15,
802 .reference_voltage = 7,
803 .cal_type = TYPE_ONE_POINT_TRIMMING,
804 .freq_tab[0] = {
805 .freq_clip_max = 800 * 1000,
806 .temp_level = 85,
807 },
808 .freq_tab[1] = {
809 .freq_clip_max = 200 * 1000,
810 .temp_level = 100,
811 },
812 .freq_tab_count = 2,
813 .type = SOC_ARCH_EXYNOS4210,
814};
815#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
816#else
817#define EXYNOS4210_TMU_DRV_DATA (NULL)
818#endif
819
820#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412) || \
821 defined(CONFIG_SOC_EXYNOS4212)
822static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
823 .threshold_falling = 10,
824 .trigger_levels[0] = 85,
825 .trigger_levels[1] = 103,
826 .trigger_levels[2] = 110,
827 .trigger_level0_en = 1,
828 .trigger_level1_en = 1,
829 .trigger_level2_en = 1,
830 .trigger_level3_en = 0,
831 .gain = 8,
832 .reference_voltage = 16,
833 .noise_cancel_mode = 4,
834 .cal_type = TYPE_ONE_POINT_TRIMMING,
835 .efuse_value = 55,
836 .freq_tab[0] = {
837 .freq_clip_max = 800 * 1000,
838 .temp_level = 85,
839 },
840 .freq_tab[1] = {
841 .freq_clip_max = 200 * 1000,
842 .temp_level = 103,
843 },
844 .freq_tab_count = 2,
845 .type = SOC_ARCH_EXYNOS,
846};
847#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
848#else
849#define EXYNOS_TMU_DRV_DATA (NULL)
850#endif
851
852#ifdef CONFIG_OF
853static const struct of_device_id exynos_tmu_match[] = {
854 {
855 .compatible = "samsung,exynos4210-tmu",
856 .data = (void *)EXYNOS4210_TMU_DRV_DATA,
857 },
858 {
859 .compatible = "samsung,exynos4412-tmu",
860 .data = (void *)EXYNOS_TMU_DRV_DATA,
861 },
862 {
863 .compatible = "samsung,exynos5250-tmu",
864 .data = (void *)EXYNOS_TMU_DRV_DATA,
865 },
866 {},
867};
868MODULE_DEVICE_TABLE(of, exynos_tmu_match);
869#endif
870
871static struct platform_device_id exynos_tmu_driver_ids[] = {
872 {
873 .name = "exynos4210-tmu",
874 .driver_data = (kernel_ulong_t)EXYNOS4210_TMU_DRV_DATA,
875 },
876 {
877 .name = "exynos5250-tmu",
878 .driver_data = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
879 },
880 { },
881};
882MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
883
884static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
885 struct platform_device *pdev)
886{
887#ifdef CONFIG_OF
888 if (pdev->dev.of_node) {
889 const struct of_device_id *match;
890 match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
891 if (!match)
892 return NULL;
893 return (struct exynos_tmu_platform_data *) match->data;
894 }
895#endif
896 return (struct exynos_tmu_platform_data *)
897 platform_get_device_id(pdev)->driver_data;
898}
899
900static int exynos_tmu_probe(struct platform_device *pdev)
901{
902 struct exynos_tmu_data *data;
903 struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
904 int ret, i;
905
906 if (!pdata)
907 pdata = exynos_get_driver_data(pdev);
908
909 if (!pdata) {
910 dev_err(&pdev->dev, "No platform init data supplied.\n");
911 return -ENODEV;
912 }
913 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
914 GFP_KERNEL);
915 if (!data) {
916 dev_err(&pdev->dev, "Failed to allocate driver structure\n");
917 return -ENOMEM;
918 }
919
920 data->irq = platform_get_irq(pdev, 0);
921 if (data->irq < 0) {
922 dev_err(&pdev->dev, "Failed to get platform irq\n");
923 return data->irq;
924 }
925
926 INIT_WORK(&data->irq_work, exynos_tmu_work);
927
928 data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
929 data->base = devm_ioremap_resource(&pdev->dev, data->mem);
930 if (IS_ERR(data->base))
931 return PTR_ERR(data->base);
932
933 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
934 IRQF_TRIGGER_RISING, "exynos-tmu", data);
935 if (ret) {
936 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
937 return ret;
938 }
939
940 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
941 if (IS_ERR(data->clk)) {
942 dev_err(&pdev->dev, "Failed to get clock\n");
943 return PTR_ERR(data->clk);
944 }
945
946 ret = clk_prepare(data->clk);
947 if (ret)
948 return ret;
949
950 if (pdata->type == SOC_ARCH_EXYNOS ||
951 pdata->type == SOC_ARCH_EXYNOS4210)
952 data->soc = pdata->type;
953 else {
954 ret = -EINVAL;
955 dev_err(&pdev->dev, "Platform not supported\n");
956 goto err_clk;
957 }
958
959 data->pdata = pdata;
960 platform_set_drvdata(pdev, data);
961 mutex_init(&data->lock);
962
963 ret = exynos_tmu_initialize(pdev);
964 if (ret) {
965 dev_err(&pdev->dev, "Failed to initialize TMU\n");
966 goto err_clk;
967 }
968
969 exynos_tmu_control(pdev, true);
970
971 /* Register the sensor with thermal management interface */
972 (&exynos_sensor_conf)->private_data = data;
973 exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en +
974 pdata->trigger_level1_en + pdata->trigger_level2_en +
975 pdata->trigger_level3_en;
976
977 for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
978 exynos_sensor_conf.trip_data.trip_val[i] =
979 pdata->threshold + pdata->trigger_levels[i];
980
981 exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
982
983 exynos_sensor_conf.cooling_data.freq_clip_count =
984 pdata->freq_tab_count;
985 for (i = 0; i < pdata->freq_tab_count; i++) {
986 exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
987 pdata->freq_tab[i].freq_clip_max;
988 exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
989 pdata->freq_tab[i].temp_level;
990 }
991
992 ret = exynos_register_thermal(&exynos_sensor_conf);
993 if (ret) {
994 dev_err(&pdev->dev, "Failed to register thermal interface\n");
995 goto err_clk;
996 }
997
998 return 0;
999err_clk:
1000 clk_unprepare(data->clk);
1001 return ret;
1002}
1003
1004static int exynos_tmu_remove(struct platform_device *pdev)
1005{
1006 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1007
1008 exynos_tmu_control(pdev, false);
1009
1010 exynos_unregister_thermal();
1011
1012 clk_unprepare(data->clk);
1013
1014 return 0;
1015}
1016
1017#ifdef CONFIG_PM_SLEEP
1018static int exynos_tmu_suspend(struct device *dev)
1019{
1020 exynos_tmu_control(to_platform_device(dev), false);
1021
1022 return 0;
1023}
1024
1025static int exynos_tmu_resume(struct device *dev)
1026{
1027 struct platform_device *pdev = to_platform_device(dev);
1028
1029 exynos_tmu_initialize(pdev);
1030 exynos_tmu_control(pdev, true);
1031
1032 return 0;
1033}
1034
1035static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
1036 exynos_tmu_suspend, exynos_tmu_resume);
1037#define EXYNOS_TMU_PM (&exynos_tmu_pm)
1038#else
1039#define EXYNOS_TMU_PM NULL
1040#endif
1041
1042static struct platform_driver exynos_tmu_driver = {
1043 .driver = {
1044 .name = "exynos-tmu",
1045 .owner = THIS_MODULE,
1046 .pm = EXYNOS_TMU_PM,
1047 .of_match_table = of_match_ptr(exynos_tmu_match),
1048 },
1049 .probe = exynos_tmu_probe,
1050 .remove = exynos_tmu_remove,
1051 .id_table = exynos_tmu_driver_ids,
1052};
1053
1054module_platform_driver(exynos_tmu_driver);
1055
1056MODULE_DESCRIPTION("EXYNOS TMU Driver");
1057MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
1058MODULE_LICENSE("GPL");
1059MODULE_ALIAS("platform:exynos-tmu");
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
new file mode 100644
index 000000000000..1d6c801c1eb9
--- /dev/null
+++ b/drivers/thermal/imx_thermal.c
@@ -0,0 +1,541 @@
1/*
2 * Copyright 2013 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
9
10#include <linux/cpu_cooling.h>
11#include <linux/cpufreq.h>
12#include <linux/delay.h>
13#include <linux/device.h>
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <linux/io.h>
17#include <linux/kernel.h>
18#include <linux/mfd/syscon.h>
19#include <linux/module.h>
20#include <linux/of.h>
21#include <linux/platform_device.h>
22#include <linux/regmap.h>
23#include <linux/slab.h>
24#include <linux/thermal.h>
25#include <linux/types.h>
26
27#define REG_SET 0x4
28#define REG_CLR 0x8
29#define REG_TOG 0xc
30
31#define MISC0 0x0150
32#define MISC0_REFTOP_SELBIASOFF (1 << 3)
33
34#define TEMPSENSE0 0x0180
35#define TEMPSENSE0_ALARM_VALUE_SHIFT 20
36#define TEMPSENSE0_ALARM_VALUE_MASK (0xfff << TEMPSENSE0_ALARM_VALUE_SHIFT)
37#define TEMPSENSE0_TEMP_CNT_SHIFT 8
38#define TEMPSENSE0_TEMP_CNT_MASK (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT)
39#define TEMPSENSE0_FINISHED (1 << 2)
40#define TEMPSENSE0_MEASURE_TEMP (1 << 1)
41#define TEMPSENSE0_POWER_DOWN (1 << 0)
42
43#define TEMPSENSE1 0x0190
44#define TEMPSENSE1_MEASURE_FREQ 0xffff
45
46#define OCOTP_ANA1 0x04e0
47
48/* The driver supports 1 passive trip point and 1 critical trip point */
49enum imx_thermal_trip {
50 IMX_TRIP_PASSIVE,
51 IMX_TRIP_CRITICAL,
52 IMX_TRIP_NUM,
53};
54
55/*
56 * It defines the temperature in millicelsius for passive trip point
57 * that will trigger cooling action when crossed.
58 */
59#define IMX_TEMP_PASSIVE 85000
60
61#define IMX_POLLING_DELAY 2000 /* millisecond */
62#define IMX_PASSIVE_DELAY 1000
63
64struct imx_thermal_data {
65 struct thermal_zone_device *tz;
66 struct thermal_cooling_device *cdev;
67 enum thermal_device_mode mode;
68 struct regmap *tempmon;
69 int c1, c2; /* See formula in imx_get_sensor_data() */
70 unsigned long temp_passive;
71 unsigned long temp_critical;
72 unsigned long alarm_temp;
73 unsigned long last_temp;
74 bool irq_enabled;
75 int irq;
76};
77
78static void imx_set_alarm_temp(struct imx_thermal_data *data,
79 signed long alarm_temp)
80{
81 struct regmap *map = data->tempmon;
82 int alarm_value;
83
84 data->alarm_temp = alarm_temp;
85 alarm_value = (alarm_temp - data->c2) / data->c1;
86 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK);
87 regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value <<
88 TEMPSENSE0_ALARM_VALUE_SHIFT);
89}
90
91static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
92{
93 struct imx_thermal_data *data = tz->devdata;
94 struct regmap *map = data->tempmon;
95 unsigned int n_meas;
96 bool wait;
97 u32 val;
98
99 if (data->mode == THERMAL_DEVICE_ENABLED) {
100 /* Check if a measurement is currently in progress */
101 regmap_read(map, TEMPSENSE0, &val);
102 wait = !(val & TEMPSENSE0_FINISHED);
103 } else {
104 /*
105 * Every time we measure the temperature, we will power on the
106 * temperature sensor, enable measurements, take a reading,
107 * disable measurements, power off the temperature sensor.
108 */
109 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
110 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
111
112 wait = true;
113 }
114
115 /*
116 * According to the temp sensor designers, it may require up to ~17us
117 * to complete a measurement.
118 */
119 if (wait)
120 usleep_range(20, 50);
121
122 regmap_read(map, TEMPSENSE0, &val);
123
124 if (data->mode != THERMAL_DEVICE_ENABLED) {
125 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
126 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
127 }
128
129 if ((val & TEMPSENSE0_FINISHED) == 0) {
130 dev_dbg(&tz->device, "temp measurement never finished\n");
131 return -EAGAIN;
132 }
133
134 n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
135
136 /* See imx_get_sensor_data() for formula derivation */
137 *temp = data->c2 + data->c1 * n_meas;
138
139 /* Update alarm value to next higher trip point */
140 if (data->alarm_temp == data->temp_passive && *temp >= data->temp_passive)
141 imx_set_alarm_temp(data, data->temp_critical);
142 if (data->alarm_temp == data->temp_critical && *temp < data->temp_passive) {
143 imx_set_alarm_temp(data, data->temp_passive);
144 dev_dbg(&tz->device, "thermal alarm off: T < %lu\n",
145 data->alarm_temp / 1000);
146 }
147
148 if (*temp != data->last_temp) {
149 dev_dbg(&tz->device, "millicelsius: %ld\n", *temp);
150 data->last_temp = *temp;
151 }
152
153 /* Reenable alarm IRQ if temperature below alarm temperature */
154 if (!data->irq_enabled && *temp < data->alarm_temp) {
155 data->irq_enabled = true;
156 enable_irq(data->irq);
157 }
158
159 return 0;
160}
161
162static int imx_get_mode(struct thermal_zone_device *tz,
163 enum thermal_device_mode *mode)
164{
165 struct imx_thermal_data *data = tz->devdata;
166
167 *mode = data->mode;
168
169 return 0;
170}
171
172static int imx_set_mode(struct thermal_zone_device *tz,
173 enum thermal_device_mode mode)
174{
175 struct imx_thermal_data *data = tz->devdata;
176 struct regmap *map = data->tempmon;
177
178 if (mode == THERMAL_DEVICE_ENABLED) {
179 tz->polling_delay = IMX_POLLING_DELAY;
180 tz->passive_delay = IMX_PASSIVE_DELAY;
181
182 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
183 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
184
185 if (!data->irq_enabled) {
186 data->irq_enabled = true;
187 enable_irq(data->irq);
188 }
189 } else {
190 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
191 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
192
193 tz->polling_delay = 0;
194 tz->passive_delay = 0;
195
196 if (data->irq_enabled) {
197 disable_irq(data->irq);
198 data->irq_enabled = false;
199 }
200 }
201
202 data->mode = mode;
203 thermal_zone_device_update(tz);
204
205 return 0;
206}
207
208static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
209 enum thermal_trip_type *type)
210{
211 *type = (trip == IMX_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE :
212 THERMAL_TRIP_CRITICAL;
213 return 0;
214}
215
216static int imx_get_crit_temp(struct thermal_zone_device *tz,
217 unsigned long *temp)
218{
219 struct imx_thermal_data *data = tz->devdata;
220
221 *temp = data->temp_critical;
222 return 0;
223}
224
225static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
226 unsigned long *temp)
227{
228 struct imx_thermal_data *data = tz->devdata;
229
230 *temp = (trip == IMX_TRIP_PASSIVE) ? data->temp_passive :
231 data->temp_critical;
232 return 0;
233}
234
235static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
236 unsigned long temp)
237{
238 struct imx_thermal_data *data = tz->devdata;
239
240 if (trip == IMX_TRIP_CRITICAL)
241 return -EPERM;
242
243 if (temp > IMX_TEMP_PASSIVE)
244 return -EINVAL;
245
246 data->temp_passive = temp;
247
248 imx_set_alarm_temp(data, temp);
249
250 return 0;
251}
252
253static int imx_bind(struct thermal_zone_device *tz,
254 struct thermal_cooling_device *cdev)
255{
256 int ret;
257
258 ret = thermal_zone_bind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev,
259 THERMAL_NO_LIMIT,
260 THERMAL_NO_LIMIT);
261 if (ret) {
262 dev_err(&tz->device,
263 "binding zone %s with cdev %s failed:%d\n",
264 tz->type, cdev->type, ret);
265 return ret;
266 }
267
268 return 0;
269}
270
271static int imx_unbind(struct thermal_zone_device *tz,
272 struct thermal_cooling_device *cdev)
273{
274 int ret;
275
276 ret = thermal_zone_unbind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev);
277 if (ret) {
278 dev_err(&tz->device,
279 "unbinding zone %s with cdev %s failed:%d\n",
280 tz->type, cdev->type, ret);
281 return ret;
282 }
283
284 return 0;
285}
286
287static const struct thermal_zone_device_ops imx_tz_ops = {
288 .bind = imx_bind,
289 .unbind = imx_unbind,
290 .get_temp = imx_get_temp,
291 .get_mode = imx_get_mode,
292 .set_mode = imx_set_mode,
293 .get_trip_type = imx_get_trip_type,
294 .get_trip_temp = imx_get_trip_temp,
295 .get_crit_temp = imx_get_crit_temp,
296 .set_trip_temp = imx_set_trip_temp,
297};
298
299static int imx_get_sensor_data(struct platform_device *pdev)
300{
301 struct imx_thermal_data *data = platform_get_drvdata(pdev);
302 struct regmap *map;
303 int t1, t2, n1, n2;
304 int ret;
305 u32 val;
306
307 map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
308 "fsl,tempmon-data");
309 if (IS_ERR(map)) {
310 ret = PTR_ERR(map);
311 dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
312 return ret;
313 }
314
315 ret = regmap_read(map, OCOTP_ANA1, &val);
316 if (ret) {
317 dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
318 return ret;
319 }
320
321 if (val == 0 || val == ~0) {
322 dev_err(&pdev->dev, "invalid sensor calibration data\n");
323 return -EINVAL;
324 }
325
326 /*
327 * Sensor data layout:
328 * [31:20] - sensor value @ 25C
329 * [19:8] - sensor value of hot
330 * [7:0] - hot temperature value
331 */
332 n1 = val >> 20;
333 n2 = (val & 0xfff00) >> 8;
334 t2 = val & 0xff;
335 t1 = 25; /* t1 always 25C */
336
337 /*
338 * Derived from linear interpolation,
339 * Tmeas = T2 + (Nmeas - N2) * (T1 - T2) / (N1 - N2)
340 * We want to reduce this down to the minimum computation necessary
341 * for each temperature read. Also, we want Tmeas in millicelsius
342 * and we don't want to lose precision from integer division. So...
343 * milli_Tmeas = 1000 * T2 + 1000 * (Nmeas - N2) * (T1 - T2) / (N1 - N2)
344 * Let constant c1 = 1000 * (T1 - T2) / (N1 - N2)
345 * milli_Tmeas = (1000 * T2) + c1 * (Nmeas - N2)
346 * milli_Tmeas = (1000 * T2) + (c1 * Nmeas) - (c1 * N2)
347 * Let constant c2 = (1000 * T2) - (c1 * N2)
348 * milli_Tmeas = c2 + (c1 * Nmeas)
349 */
350 data->c1 = 1000 * (t1 - t2) / (n1 - n2);
351 data->c2 = 1000 * t2 - data->c1 * n2;
352
353 /*
354 * Set the default passive cooling trip point to 20 °C below the
355 * maximum die temperature. Can be changed from userspace.
356 */
357 data->temp_passive = 1000 * (t2 - 20);
358
359 /*
360 * The maximum die temperature is t2, let's give 5 °C cushion
361 * for noise and possible temperature rise between measurements.
362 */
363 data->temp_critical = 1000 * (t2 - 5);
364
365 return 0;
366}
367
368static irqreturn_t imx_thermal_alarm_irq(int irq, void *dev)
369{
370 struct imx_thermal_data *data = dev;
371
372 disable_irq_nosync(irq);
373 data->irq_enabled = false;
374
375 return IRQ_WAKE_THREAD;
376}
377
378static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
379{
380 struct imx_thermal_data *data = dev;
381
382 dev_dbg(&data->tz->device, "THERMAL ALARM: T > %lu\n",
383 data->alarm_temp / 1000);
384
385 thermal_zone_device_update(data->tz);
386
387 return IRQ_HANDLED;
388}
389
390static int imx_thermal_probe(struct platform_device *pdev)
391{
392 struct imx_thermal_data *data;
393 struct cpumask clip_cpus;
394 struct regmap *map;
395 int measure_freq;
396 int ret;
397
398 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
399 if (!data)
400 return -ENOMEM;
401
402 map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
403 if (IS_ERR(map)) {
404 ret = PTR_ERR(map);
405 dev_err(&pdev->dev, "failed to get tempmon regmap: %d\n", ret);
406 return ret;
407 }
408 data->tempmon = map;
409
410 data->irq = platform_get_irq(pdev, 0);
411 if (data->irq < 0)
412 return data->irq;
413
414 ret = devm_request_threaded_irq(&pdev->dev, data->irq,
415 imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
416 0, "imx_thermal", data);
417 if (ret < 0) {
418 dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
419 return ret;
420 }
421
422 platform_set_drvdata(pdev, data);
423
424 ret = imx_get_sensor_data(pdev);
425 if (ret) {
426 dev_err(&pdev->dev, "failed to get sensor data\n");
427 return ret;
428 }
429
430 /* Make sure sensor is in known good state for measurements */
431 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
432 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
433 regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
434 regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
435 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
436
437 cpumask_set_cpu(0, &clip_cpus);
438 data->cdev = cpufreq_cooling_register(&clip_cpus);
439 if (IS_ERR(data->cdev)) {
440 ret = PTR_ERR(data->cdev);
441 dev_err(&pdev->dev,
442 "failed to register cpufreq cooling device: %d\n", ret);
443 return ret;
444 }
445
446 data->tz = thermal_zone_device_register("imx_thermal_zone",
447 IMX_TRIP_NUM,
448 BIT(IMX_TRIP_PASSIVE), data,
449 &imx_tz_ops, NULL,
450 IMX_PASSIVE_DELAY,
451 IMX_POLLING_DELAY);
452 if (IS_ERR(data->tz)) {
453 ret = PTR_ERR(data->tz);
454 dev_err(&pdev->dev,
455 "failed to register thermal zone device %d\n", ret);
456 cpufreq_cooling_unregister(data->cdev);
457 return ret;
458 }
459
460 /* Enable measurements at ~ 10 Hz */
461 regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
462 measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
463 regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
464 imx_set_alarm_temp(data, data->temp_passive);
465 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
466 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
467
468 data->irq_enabled = true;
469 data->mode = THERMAL_DEVICE_ENABLED;
470
471 return 0;
472}
473
474static int imx_thermal_remove(struct platform_device *pdev)
475{
476 struct imx_thermal_data *data = platform_get_drvdata(pdev);
477 struct regmap *map = data->tempmon;
478
479 /* Disable measurements */
480 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
481
482 thermal_zone_device_unregister(data->tz);
483 cpufreq_cooling_unregister(data->cdev);
484
485 return 0;
486}
487
488#ifdef CONFIG_PM_SLEEP
489static int imx_thermal_suspend(struct device *dev)
490{
491 struct imx_thermal_data *data = dev_get_drvdata(dev);
492 struct regmap *map = data->tempmon;
493 u32 val;
494
495 regmap_read(map, TEMPSENSE0, &val);
496 if ((val & TEMPSENSE0_POWER_DOWN) == 0) {
497 /*
498 * If a measurement is taking place, wait for a long enough
499 * time for it to finish, and then check again. If it still
500 * does not finish, something must go wrong.
501 */
502 udelay(50);
503 regmap_read(map, TEMPSENSE0, &val);
504 if ((val & TEMPSENSE0_POWER_DOWN) == 0)
505 return -ETIMEDOUT;
506 }
507
508 return 0;
509}
510
511static int imx_thermal_resume(struct device *dev)
512{
513 /* Nothing to do for now */
514 return 0;
515}
516#endif
517
518static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
519 imx_thermal_suspend, imx_thermal_resume);
520
521static const struct of_device_id of_imx_thermal_match[] = {
522 { .compatible = "fsl,imx6q-tempmon", },
523 { /* end */ }
524};
525
526static struct platform_driver imx_thermal = {
527 .driver = {
528 .name = "imx_thermal",
529 .owner = THIS_MODULE,
530 .pm = &imx_thermal_pm_ops,
531 .of_match_table = of_imx_thermal_match,
532 },
533 .probe = imx_thermal_probe,
534 .remove = imx_thermal_remove,
535};
536module_platform_driver(imx_thermal);
537
538MODULE_AUTHOR("Freescale Semiconductor, Inc.");
539MODULE_DESCRIPTION("Thermal driver for Freescale i.MX SoCs");
540MODULE_LICENSE("GPL v2");
541MODULE_ALIAS("platform:imx-thermal");
diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
new file mode 100644
index 000000000000..b653f1539148
--- /dev/null
+++ b/drivers/thermal/samsung/Kconfig
@@ -0,0 +1,18 @@
1config EXYNOS_THERMAL
2 tristate "Exynos thermal management unit driver"
3 depends on ARCH_HAS_BANDGAP
4 help
5 If you say yes here you get support for the TMU (Thermal Management
6 Unit) driver for SAMSUNG EXYNOS series of soc. This driver initialises
7 the TMU, reports temperature and handles cooling action if defined.
8 This driver uses the exynos core thermal API's and TMU configuration
9 data from the supported soc's.
10
11config EXYNOS_THERMAL_CORE
12 bool "Core thermal framework support for EXYNOS SOC's"
13 depends on EXYNOS_THERMAL
14 help
15 If you say yes here you get support for EXYNOS TMU
16 (Thermal Management Unit) common registration/unregistration
17 functions to the core thermal layer and also to use the generic
18 cpu cooling API's.
diff --git a/drivers/thermal/samsung/Makefile b/drivers/thermal/samsung/Makefile
new file mode 100644
index 000000000000..c09d83095dc2
--- /dev/null
+++ b/drivers/thermal/samsung/Makefile
@@ -0,0 +1,7 @@
1#
2# Samsung thermal specific Makefile
3#
4obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
5exynos_thermal-y := exynos_tmu.o
6exynos_thermal-y += exynos_tmu_data.o
7exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) += exynos_thermal_common.o
diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
new file mode 100644
index 000000000000..4d8e4445ea10
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -0,0 +1,432 @@
1/*
2 * exynos_thermal_common.c - Samsung EXYNOS common thermal file
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Amit Daniel Kachhap <amit.daniel@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <linux/cpu_cooling.h>
24#include <linux/err.h>
25#include <linux/slab.h>
26#include <linux/thermal.h>
27
28#include "exynos_thermal_common.h"
29
30struct exynos_thermal_zone {
31 enum thermal_device_mode mode;
32 struct thermal_zone_device *therm_dev;
33 struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
34 unsigned int cool_dev_size;
35 struct platform_device *exynos4_dev;
36 struct thermal_sensor_conf *sensor_conf;
37 bool bind;
38};
39
40/* Get mode callback functions for thermal zone */
41static int exynos_get_mode(struct thermal_zone_device *thermal,
42 enum thermal_device_mode *mode)
43{
44 struct exynos_thermal_zone *th_zone = thermal->devdata;
45 if (th_zone)
46 *mode = th_zone->mode;
47 return 0;
48}
49
50/* Set mode callback functions for thermal zone */
51static int exynos_set_mode(struct thermal_zone_device *thermal,
52 enum thermal_device_mode mode)
53{
54 struct exynos_thermal_zone *th_zone = thermal->devdata;
55 if (!th_zone) {
56 dev_err(th_zone->sensor_conf->dev,
57 "thermal zone not registered\n");
58 return 0;
59 }
60
61 mutex_lock(&thermal->lock);
62
63 if (mode == THERMAL_DEVICE_ENABLED &&
64 !th_zone->sensor_conf->trip_data.trigger_falling)
65 thermal->polling_delay = IDLE_INTERVAL;
66 else
67 thermal->polling_delay = 0;
68
69 mutex_unlock(&thermal->lock);
70
71 th_zone->mode = mode;
72 thermal_zone_device_update(thermal);
73 dev_dbg(th_zone->sensor_conf->dev,
74 "thermal polling set for duration=%d msec\n",
75 thermal->polling_delay);
76 return 0;
77}
78
79
80/* Get trip type callback functions for thermal zone */
81static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
82 enum thermal_trip_type *type)
83{
84 struct exynos_thermal_zone *th_zone = thermal->devdata;
85 int max_trip = th_zone->sensor_conf->trip_data.trip_count;
86 int trip_type;
87
88 if (trip < 0 || trip >= max_trip)
89 return -EINVAL;
90
91 trip_type = th_zone->sensor_conf->trip_data.trip_type[trip];
92
93 if (trip_type == SW_TRIP)
94 *type = THERMAL_TRIP_CRITICAL;
95 else if (trip_type == THROTTLE_ACTIVE)
96 *type = THERMAL_TRIP_ACTIVE;
97 else if (trip_type == THROTTLE_PASSIVE)
98 *type = THERMAL_TRIP_PASSIVE;
99 else
100 return -EINVAL;
101
102 return 0;
103}
104
105/* Get trip temperature callback functions for thermal zone */
106static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
107 unsigned long *temp)
108{
109 struct exynos_thermal_zone *th_zone = thermal->devdata;
110 int max_trip = th_zone->sensor_conf->trip_data.trip_count;
111
112 if (trip < 0 || trip >= max_trip)
113 return -EINVAL;
114
115 *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
116 /* convert the temperature into millicelsius */
117 *temp = *temp * MCELSIUS;
118
119 return 0;
120}
121
122/* Get critical temperature callback functions for thermal zone */
123static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
124 unsigned long *temp)
125{
126 struct exynos_thermal_zone *th_zone = thermal->devdata;
127 int max_trip = th_zone->sensor_conf->trip_data.trip_count;
128 /* Get the temp of highest trip*/
129 return exynos_get_trip_temp(thermal, max_trip - 1, temp);
130}
131
132/* Bind callback functions for thermal zone */
133static int exynos_bind(struct thermal_zone_device *thermal,
134 struct thermal_cooling_device *cdev)
135{
136 int ret = 0, i, tab_size, level;
137 struct freq_clip_table *tab_ptr, *clip_data;
138 struct exynos_thermal_zone *th_zone = thermal->devdata;
139 struct thermal_sensor_conf *data = th_zone->sensor_conf;
140
141 tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
142 tab_size = data->cooling_data.freq_clip_count;
143
144 if (tab_ptr == NULL || tab_size == 0)
145 return 0;
146
147 /* find the cooling device registered*/
148 for (i = 0; i < th_zone->cool_dev_size; i++)
149 if (cdev == th_zone->cool_dev[i])
150 break;
151
152 /* No matching cooling device */
153 if (i == th_zone->cool_dev_size)
154 return 0;
155
156 /* Bind the thermal zone to the cpufreq cooling device */
157 for (i = 0; i < tab_size; i++) {
158 clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
159 level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
160 if (level == THERMAL_CSTATE_INVALID)
161 return 0;
162 switch (GET_ZONE(i)) {
163 case MONITOR_ZONE:
164 case WARN_ZONE:
165 if (thermal_zone_bind_cooling_device(thermal, i, cdev,
166 level, 0)) {
167 dev_err(data->dev,
168 "error unbinding cdev inst=%d\n", i);
169 ret = -EINVAL;
170 }
171 th_zone->bind = true;
172 break;
173 default:
174 ret = -EINVAL;
175 }
176 }
177
178 return ret;
179}
180
181/* Unbind callback functions for thermal zone */
182static int exynos_unbind(struct thermal_zone_device *thermal,
183 struct thermal_cooling_device *cdev)
184{
185 int ret = 0, i, tab_size;
186 struct exynos_thermal_zone *th_zone = thermal->devdata;
187 struct thermal_sensor_conf *data = th_zone->sensor_conf;
188
189 if (th_zone->bind == false)
190 return 0;
191
192 tab_size = data->cooling_data.freq_clip_count;
193
194 if (tab_size == 0)
195 return 0;
196
197 /* find the cooling device registered*/
198 for (i = 0; i < th_zone->cool_dev_size; i++)
199 if (cdev == th_zone->cool_dev[i])
200 break;
201
202 /* No matching cooling device */
203 if (i == th_zone->cool_dev_size)
204 return 0;
205
206 /* Bind the thermal zone to the cpufreq cooling device */
207 for (i = 0; i < tab_size; i++) {
208 switch (GET_ZONE(i)) {
209 case MONITOR_ZONE:
210 case WARN_ZONE:
211 if (thermal_zone_unbind_cooling_device(thermal, i,
212 cdev)) {
213 dev_err(data->dev,
214 "error unbinding cdev inst=%d\n", i);
215 ret = -EINVAL;
216 }
217 th_zone->bind = false;
218 break;
219 default:
220 ret = -EINVAL;
221 }
222 }
223 return ret;
224}
225
226/* Get temperature callback functions for thermal zone */
227static int exynos_get_temp(struct thermal_zone_device *thermal,
228 unsigned long *temp)
229{
230 struct exynos_thermal_zone *th_zone = thermal->devdata;
231 void *data;
232
233 if (!th_zone->sensor_conf) {
234 dev_err(th_zone->sensor_conf->dev,
235 "Temperature sensor not initialised\n");
236 return -EINVAL;
237 }
238 data = th_zone->sensor_conf->driver_data;
239 *temp = th_zone->sensor_conf->read_temperature(data);
240 /* convert the temperature into millicelsius */
241 *temp = *temp * MCELSIUS;
242 return 0;
243}
244
245/* Get temperature callback functions for thermal zone */
246static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
247 unsigned long temp)
248{
249 void *data;
250 int ret = -EINVAL;
251 struct exynos_thermal_zone *th_zone = thermal->devdata;
252
253 if (!th_zone->sensor_conf) {
254 dev_err(th_zone->sensor_conf->dev,
255 "Temperature sensor not initialised\n");
256 return -EINVAL;
257 }
258 data = th_zone->sensor_conf->driver_data;
259 if (th_zone->sensor_conf->write_emul_temp)
260 ret = th_zone->sensor_conf->write_emul_temp(data, temp);
261 return ret;
262}
263
264/* Get the temperature trend */
265static int exynos_get_trend(struct thermal_zone_device *thermal,
266 int trip, enum thermal_trend *trend)
267{
268 int ret;
269 unsigned long trip_temp;
270
271 ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
272 if (ret < 0)
273 return ret;
274
275 if (thermal->temperature >= trip_temp)
276 *trend = THERMAL_TREND_RAISE_FULL;
277 else
278 *trend = THERMAL_TREND_DROP_FULL;
279
280 return 0;
281}
282/* Operation callback functions for thermal zone */
283static struct thermal_zone_device_ops const exynos_dev_ops = {
284 .bind = exynos_bind,
285 .unbind = exynos_unbind,
286 .get_temp = exynos_get_temp,
287 .set_emul_temp = exynos_set_emul_temp,
288 .get_trend = exynos_get_trend,
289 .get_mode = exynos_get_mode,
290 .set_mode = exynos_set_mode,
291 .get_trip_type = exynos_get_trip_type,
292 .get_trip_temp = exynos_get_trip_temp,
293 .get_crit_temp = exynos_get_crit_temp,
294};
295
296/*
297 * This function may be called from interrupt based temperature sensor
298 * when threshold is changed.
299 */
300void exynos_report_trigger(struct thermal_sensor_conf *conf)
301{
302 unsigned int i;
303 char data[10];
304 char *envp[] = { data, NULL };
305 struct exynos_thermal_zone *th_zone;
306
307 if (!conf || !conf->pzone_data) {
308 pr_err("Invalid temperature sensor configuration data\n");
309 return;
310 }
311
312 th_zone = conf->pzone_data;
313 if (th_zone->therm_dev)
314 return;
315
316 if (th_zone->bind == false) {
317 for (i = 0; i < th_zone->cool_dev_size; i++) {
318 if (!th_zone->cool_dev[i])
319 continue;
320 exynos_bind(th_zone->therm_dev,
321 th_zone->cool_dev[i]);
322 }
323 }
324
325 thermal_zone_device_update(th_zone->therm_dev);
326
327 mutex_lock(&th_zone->therm_dev->lock);
328 /* Find the level for which trip happened */
329 for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
330 if (th_zone->therm_dev->last_temperature <
331 th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
332 break;
333 }
334
335 if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
336 !th_zone->sensor_conf->trip_data.trigger_falling) {
337 if (i > 0)
338 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
339 else
340 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
341 }
342
343 snprintf(data, sizeof(data), "%u", i);
344 kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
345 mutex_unlock(&th_zone->therm_dev->lock);
346}
347
348/* Register with the in-kernel thermal management */
349int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
350{
351 int ret;
352 struct cpumask mask_val;
353 struct exynos_thermal_zone *th_zone;
354
355 if (!sensor_conf || !sensor_conf->read_temperature) {
356 pr_err("Temperature sensor not initialised\n");
357 return -EINVAL;
358 }
359
360 th_zone = devm_kzalloc(sensor_conf->dev,
361 sizeof(struct exynos_thermal_zone), GFP_KERNEL);
362 if (!th_zone)
363 return -ENOMEM;
364
365 th_zone->sensor_conf = sensor_conf;
366 /*
367 * TODO: 1) Handle multiple cooling devices in a thermal zone
368 * 2) Add a flag/name in cooling info to map to specific
369 * sensor
370 */
371 if (sensor_conf->cooling_data.freq_clip_count > 0) {
372 cpumask_set_cpu(0, &mask_val);
373 th_zone->cool_dev[th_zone->cool_dev_size] =
374 cpufreq_cooling_register(&mask_val);
375 if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) {
376 dev_err(sensor_conf->dev,
377 "Failed to register cpufreq cooling device\n");
378 ret = -EINVAL;
379 goto err_unregister;
380 }
381 th_zone->cool_dev_size++;
382 }
383
384 th_zone->therm_dev = thermal_zone_device_register(
385 sensor_conf->name, sensor_conf->trip_data.trip_count,
386 0, th_zone, &exynos_dev_ops, NULL, 0,
387 sensor_conf->trip_data.trigger_falling ? 0 :
388 IDLE_INTERVAL);
389
390 if (IS_ERR(th_zone->therm_dev)) {
391 dev_err(sensor_conf->dev,
392 "Failed to register thermal zone device\n");
393 ret = PTR_ERR(th_zone->therm_dev);
394 goto err_unregister;
395 }
396 th_zone->mode = THERMAL_DEVICE_ENABLED;
397 sensor_conf->pzone_data = th_zone;
398
399 dev_info(sensor_conf->dev,
400 "Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
401
402 return 0;
403
404err_unregister:
405 exynos_unregister_thermal(sensor_conf);
406 return ret;
407}
408
409/* Un-Register with the in-kernel thermal management */
410void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf)
411{
412 int i;
413 struct exynos_thermal_zone *th_zone;
414
415 if (!sensor_conf || !sensor_conf->pzone_data) {
416 pr_err("Invalid temperature sensor configuration data\n");
417 return;
418 }
419
420 th_zone = sensor_conf->pzone_data;
421
422 if (th_zone->therm_dev)
423 thermal_zone_device_unregister(th_zone->therm_dev);
424
425 for (i = 0; i < th_zone->cool_dev_size; i++) {
426 if (th_zone->cool_dev[i])
427 cpufreq_cooling_unregister(th_zone->cool_dev[i]);
428 }
429
430 dev_info(sensor_conf->dev,
431 "Exynos: Kernel Thermal management unregistered\n");
432}
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
new file mode 100644
index 000000000000..3eb2ed9ea3a4
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_thermal_common.h
@@ -0,0 +1,107 @@
1/*
2 * exynos_thermal_common.h - Samsung EXYNOS common header file
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Amit Daniel Kachhap <amit.daniel@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#ifndef _EXYNOS_THERMAL_COMMON_H
24#define _EXYNOS_THERMAL_COMMON_H
25
26/* In-kernel thermal framework related macros & definations */
27#define SENSOR_NAME_LEN 16
28#define MAX_TRIP_COUNT 8
29#define MAX_COOLING_DEVICE 4
30#define MAX_THRESHOLD_LEVS 5
31
32#define ACTIVE_INTERVAL 500
33#define IDLE_INTERVAL 10000
34#define MCELSIUS 1000
35
36/* CPU Zone information */
37#define PANIC_ZONE 4
38#define WARN_ZONE 3
39#define MONITOR_ZONE 2
40#define SAFE_ZONE 1
41
42#define GET_ZONE(trip) (trip + 2)
43#define GET_TRIP(zone) (zone - 2)
44
45enum trigger_type {
46 THROTTLE_ACTIVE = 1,
47 THROTTLE_PASSIVE,
48 SW_TRIP,
49 HW_TRIP,
50};
51
52/**
53 * struct freq_clip_table
54 * @freq_clip_max: maximum frequency allowed for this cooling state.
55 * @temp_level: Temperature level at which the temperature clipping will
56 * happen.
57 * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
58 *
59 * This structure is required to be filled and passed to the
60 * cpufreq_cooling_unregister function.
61 */
62struct freq_clip_table {
63 unsigned int freq_clip_max;
64 unsigned int temp_level;
65 const struct cpumask *mask_val;
66};
67
68struct thermal_trip_point_conf {
69 int trip_val[MAX_TRIP_COUNT];
70 int trip_type[MAX_TRIP_COUNT];
71 int trip_count;
72 unsigned char trigger_falling;
73};
74
75struct thermal_cooling_conf {
76 struct freq_clip_table freq_data[MAX_TRIP_COUNT];
77 int freq_clip_count;
78};
79
80struct thermal_sensor_conf {
81 char name[SENSOR_NAME_LEN];
82 int (*read_temperature)(void *data);
83 int (*write_emul_temp)(void *drv_data, unsigned long temp);
84 struct thermal_trip_point_conf trip_data;
85 struct thermal_cooling_conf cooling_data;
86 void *driver_data;
87 void *pzone_data;
88 struct device *dev;
89};
90
91/*Functions used exynos based thermal sensor driver*/
92#ifdef CONFIG_EXYNOS_THERMAL_CORE
93void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf);
94int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
95void exynos_report_trigger(struct thermal_sensor_conf *sensor_conf);
96#else
97static inline void
98exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf) { return; }
99
100static inline int
101exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
102
103static inline void
104exynos_report_trigger(struct thermal_sensor_conf *sensor_conf) { return; }
105
106#endif /* CONFIG_EXYNOS_THERMAL_CORE */
107#endif /* _EXYNOS_THERMAL_COMMON_H */
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
new file mode 100644
index 000000000000..a033dbbf979e
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -0,0 +1,768 @@
1/*
2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
3 *
4 * Copyright (C) 2011 Samsung Electronics
5 * Donggeun Kim <dg77.kim@samsung.com>
6 * Amit Daniel Kachhap <amit.kachhap@linaro.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <linux/clk.h>
25#include <linux/io.h>
26#include <linux/interrupt.h>
27#include <linux/module.h>
28#include <linux/of.h>
29#include <linux/of_address.h>
30#include <linux/of_irq.h>
31#include <linux/platform_device.h>
32#include <linux/regulator/consumer.h>
33
34#include "exynos_thermal_common.h"
35#include "exynos_tmu.h"
36#include "exynos_tmu_data.h"
37
38/**
39 * struct exynos_tmu_data : A structure to hold the private data of the TMU
40 driver
41 * @id: identifier of the one instance of the TMU controller.
42 * @pdata: pointer to the tmu platform/configuration data
43 * @base: base address of the single instance of the TMU controller.
44 * @base_common: base address of the common registers of the TMU controller.
45 * @irq: irq number of the TMU controller.
46 * @soc: id of the SOC type.
47 * @irq_work: pointer to the irq work structure.
48 * @lock: lock to implement synchronization.
49 * @clk: pointer to the clock structure.
50 * @temp_error1: fused value of the first point trim.
51 * @temp_error2: fused value of the second point trim.
52 * @regulator: pointer to the TMU regulator structure.
53 * @reg_conf: pointer to structure to register with core thermal.
54 */
55struct exynos_tmu_data {
56 int id;
57 struct exynos_tmu_platform_data *pdata;
58 void __iomem *base;
59 void __iomem *base_common;
60 int irq;
61 enum soc_type soc;
62 struct work_struct irq_work;
63 struct mutex lock;
64 struct clk *clk;
65 u8 temp_error1, temp_error2;
66 struct regulator *regulator;
67 struct thermal_sensor_conf *reg_conf;
68};
69
70/*
71 * TMU treats temperature as a mapped temperature code.
72 * The temperature is converted differently depending on the calibration type.
73 */
74static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
75{
76 struct exynos_tmu_platform_data *pdata = data->pdata;
77 int temp_code;
78
79 if (pdata->cal_mode == HW_MODE)
80 return temp;
81
82 if (data->soc == SOC_ARCH_EXYNOS4210)
83 /* temp should range between 25 and 125 */
84 if (temp < 25 || temp > 125) {
85 temp_code = -EINVAL;
86 goto out;
87 }
88
89 switch (pdata->cal_type) {
90 case TYPE_TWO_POINT_TRIMMING:
91 temp_code = (temp - pdata->first_point_trim) *
92 (data->temp_error2 - data->temp_error1) /
93 (pdata->second_point_trim - pdata->first_point_trim) +
94 data->temp_error1;
95 break;
96 case TYPE_ONE_POINT_TRIMMING:
97 temp_code = temp + data->temp_error1 - pdata->first_point_trim;
98 break;
99 default:
100 temp_code = temp + pdata->default_temp_offset;
101 break;
102 }
103out:
104 return temp_code;
105}
106
107/*
108 * Calculate a temperature value from a temperature code.
109 * The unit of the temperature is degree Celsius.
110 */
111static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
112{
113 struct exynos_tmu_platform_data *pdata = data->pdata;
114 int temp;
115
116 if (pdata->cal_mode == HW_MODE)
117 return temp_code;
118
119 if (data->soc == SOC_ARCH_EXYNOS4210)
120 /* temp_code should range between 75 and 175 */
121 if (temp_code < 75 || temp_code > 175) {
122 temp = -ENODATA;
123 goto out;
124 }
125
126 switch (pdata->cal_type) {
127 case TYPE_TWO_POINT_TRIMMING:
128 temp = (temp_code - data->temp_error1) *
129 (pdata->second_point_trim - pdata->first_point_trim) /
130 (data->temp_error2 - data->temp_error1) +
131 pdata->first_point_trim;
132 break;
133 case TYPE_ONE_POINT_TRIMMING:
134 temp = temp_code - data->temp_error1 + pdata->first_point_trim;
135 break;
136 default:
137 temp = temp_code - pdata->default_temp_offset;
138 break;
139 }
140out:
141 return temp;
142}
143
144static int exynos_tmu_initialize(struct platform_device *pdev)
145{
146 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
147 struct exynos_tmu_platform_data *pdata = data->pdata;
148 const struct exynos_tmu_registers *reg = pdata->registers;
149 unsigned int status, trim_info = 0, con;
150 unsigned int rising_threshold = 0, falling_threshold = 0;
151 int ret = 0, threshold_code, i, trigger_levs = 0;
152
153 mutex_lock(&data->lock);
154 clk_enable(data->clk);
155
156 if (TMU_SUPPORTS(pdata, READY_STATUS)) {
157 status = readb(data->base + reg->tmu_status);
158 if (!status) {
159 ret = -EBUSY;
160 goto out;
161 }
162 }
163
164 if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
165 __raw_writel(1, data->base + reg->triminfo_ctrl);
166
167 if (pdata->cal_mode == HW_MODE)
168 goto skip_calib_data;
169
170 /* Save trimming info in order to perform calibration */
171 if (data->soc == SOC_ARCH_EXYNOS5440) {
172 /*
173 * For exynos5440 soc triminfo value is swapped between TMU0 and
174 * TMU2, so the below logic is needed.
175 */
176 switch (data->id) {
177 case 0:
178 trim_info = readl(data->base +
179 EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
180 break;
181 case 1:
182 trim_info = readl(data->base + reg->triminfo_data);
183 break;
184 case 2:
185 trim_info = readl(data->base -
186 EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
187 }
188 } else {
189 trim_info = readl(data->base + reg->triminfo_data);
190 }
191 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
192 data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
193 EXYNOS_TMU_TEMP_MASK);
194
195 if (!data->temp_error1 ||
196 (pdata->min_efuse_value > data->temp_error1) ||
197 (data->temp_error1 > pdata->max_efuse_value))
198 data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
199
200 if (!data->temp_error2)
201 data->temp_error2 =
202 (pdata->efuse_value >> reg->triminfo_85_shift) &
203 EXYNOS_TMU_TEMP_MASK;
204
205skip_calib_data:
206 if (pdata->max_trigger_level > MAX_THRESHOLD_LEVS) {
207 dev_err(&pdev->dev, "Invalid max trigger level\n");
208 goto out;
209 }
210
211 for (i = 0; i < pdata->max_trigger_level; i++) {
212 if (!pdata->trigger_levels[i])
213 continue;
214
215 if ((pdata->trigger_type[i] == HW_TRIP) &&
216 (!pdata->trigger_levels[pdata->max_trigger_level - 1])) {
217 dev_err(&pdev->dev, "Invalid hw trigger level\n");
218 ret = -EINVAL;
219 goto out;
220 }
221
222 /* Count trigger levels except the HW trip*/
223 if (!(pdata->trigger_type[i] == HW_TRIP))
224 trigger_levs++;
225 }
226
227 if (data->soc == SOC_ARCH_EXYNOS4210) {
228 /* Write temperature code for threshold */
229 threshold_code = temp_to_code(data, pdata->threshold);
230 if (threshold_code < 0) {
231 ret = threshold_code;
232 goto out;
233 }
234 writeb(threshold_code,
235 data->base + reg->threshold_temp);
236 for (i = 0; i < trigger_levs; i++)
237 writeb(pdata->trigger_levels[i], data->base +
238 reg->threshold_th0 + i * sizeof(reg->threshold_th0));
239
240 writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
241 } else {
242 /* Write temperature code for rising and falling threshold */
243 for (i = 0;
244 i < trigger_levs && i < EXYNOS_MAX_TRIGGER_PER_REG; i++) {
245 threshold_code = temp_to_code(data,
246 pdata->trigger_levels[i]);
247 if (threshold_code < 0) {
248 ret = threshold_code;
249 goto out;
250 }
251 rising_threshold |= threshold_code << 8 * i;
252 if (pdata->threshold_falling) {
253 threshold_code = temp_to_code(data,
254 pdata->trigger_levels[i] -
255 pdata->threshold_falling);
256 if (threshold_code > 0)
257 falling_threshold |=
258 threshold_code << 8 * i;
259 }
260 }
261
262 writel(rising_threshold,
263 data->base + reg->threshold_th0);
264 writel(falling_threshold,
265 data->base + reg->threshold_th1);
266
267 writel((reg->inten_rise_mask << reg->inten_rise_shift) |
268 (reg->inten_fall_mask << reg->inten_fall_shift),
269 data->base + reg->tmu_intclear);
270
271 /* if last threshold limit is also present */
272 i = pdata->max_trigger_level - 1;
273 if (pdata->trigger_levels[i] &&
274 (pdata->trigger_type[i] == HW_TRIP)) {
275 threshold_code = temp_to_code(data,
276 pdata->trigger_levels[i]);
277 if (threshold_code < 0) {
278 ret = threshold_code;
279 goto out;
280 }
281 if (i == EXYNOS_MAX_TRIGGER_PER_REG - 1) {
282 /* 1-4 level to be assigned in th0 reg */
283 rising_threshold |= threshold_code << 8 * i;
284 writel(rising_threshold,
285 data->base + reg->threshold_th0);
286 } else if (i == EXYNOS_MAX_TRIGGER_PER_REG) {
287 /* 5th level to be assigned in th2 reg */
288 rising_threshold =
289 threshold_code << reg->threshold_th3_l0_shift;
290 writel(rising_threshold,
291 data->base + reg->threshold_th2);
292 }
293 con = readl(data->base + reg->tmu_ctrl);
294 con |= (1 << reg->therm_trip_en_shift);
295 writel(con, data->base + reg->tmu_ctrl);
296 }
297 }
298 /*Clear the PMIN in the common TMU register*/
299 if (reg->tmu_pmin && !data->id)
300 writel(0, data->base_common + reg->tmu_pmin);
301out:
302 clk_disable(data->clk);
303 mutex_unlock(&data->lock);
304
305 return ret;
306}
307
308static void exynos_tmu_control(struct platform_device *pdev, bool on)
309{
310 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
311 struct exynos_tmu_platform_data *pdata = data->pdata;
312 const struct exynos_tmu_registers *reg = pdata->registers;
313 unsigned int con, interrupt_en, cal_val;
314
315 mutex_lock(&data->lock);
316 clk_enable(data->clk);
317
318 con = readl(data->base + reg->tmu_ctrl);
319
320 if (pdata->reference_voltage) {
321 con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
322 con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
323 }
324
325 if (pdata->gain) {
326 con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
327 con |= (pdata->gain << reg->buf_slope_sel_shift);
328 }
329
330 if (pdata->noise_cancel_mode) {
331 con &= ~(reg->therm_trip_mode_mask <<
332 reg->therm_trip_mode_shift);
333 con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
334 }
335
336 if (pdata->cal_mode == HW_MODE) {
337 con &= ~(reg->calib_mode_mask << reg->calib_mode_shift);
338 cal_val = 0;
339 switch (pdata->cal_type) {
340 case TYPE_TWO_POINT_TRIMMING:
341 cal_val = 3;
342 break;
343 case TYPE_ONE_POINT_TRIMMING_85:
344 cal_val = 2;
345 break;
346 case TYPE_ONE_POINT_TRIMMING_25:
347 cal_val = 1;
348 break;
349 case TYPE_NONE:
350 break;
351 default:
352 dev_err(&pdev->dev, "Invalid calibration type, using none\n");
353 }
354 con |= cal_val << reg->calib_mode_shift;
355 }
356
357 if (on) {
358 con |= (1 << reg->core_en_shift);
359 interrupt_en =
360 pdata->trigger_enable[3] << reg->inten_rise3_shift |
361 pdata->trigger_enable[2] << reg->inten_rise2_shift |
362 pdata->trigger_enable[1] << reg->inten_rise1_shift |
363 pdata->trigger_enable[0] << reg->inten_rise0_shift;
364 if (TMU_SUPPORTS(pdata, FALLING_TRIP))
365 interrupt_en |=
366 interrupt_en << reg->inten_fall0_shift;
367 } else {
368 con &= ~(1 << reg->core_en_shift);
369 interrupt_en = 0; /* Disable all interrupts */
370 }
371 writel(interrupt_en, data->base + reg->tmu_inten);
372 writel(con, data->base + reg->tmu_ctrl);
373
374 clk_disable(data->clk);
375 mutex_unlock(&data->lock);
376}
377
378static int exynos_tmu_read(struct exynos_tmu_data *data)
379{
380 struct exynos_tmu_platform_data *pdata = data->pdata;
381 const struct exynos_tmu_registers *reg = pdata->registers;
382 u8 temp_code;
383 int temp;
384
385 mutex_lock(&data->lock);
386 clk_enable(data->clk);
387
388 temp_code = readb(data->base + reg->tmu_cur_temp);
389 temp = code_to_temp(data, temp_code);
390
391 clk_disable(data->clk);
392 mutex_unlock(&data->lock);
393
394 return temp;
395}
396
397#ifdef CONFIG_THERMAL_EMULATION
398static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
399{
400 struct exynos_tmu_data *data = drv_data;
401 struct exynos_tmu_platform_data *pdata = data->pdata;
402 const struct exynos_tmu_registers *reg = pdata->registers;
403 unsigned int val;
404 int ret = -EINVAL;
405
406 if (!TMU_SUPPORTS(pdata, EMULATION))
407 goto out;
408
409 if (temp && temp < MCELSIUS)
410 goto out;
411
412 mutex_lock(&data->lock);
413 clk_enable(data->clk);
414
415 val = readl(data->base + reg->emul_con);
416
417 if (temp) {
418 temp /= MCELSIUS;
419
420 if (TMU_SUPPORTS(pdata, EMUL_TIME)) {
421 val &= ~(EXYNOS_EMUL_TIME_MASK << reg->emul_time_shift);
422 val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
423 }
424 val &= ~(EXYNOS_EMUL_DATA_MASK << reg->emul_temp_shift);
425 val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
426 EXYNOS_EMUL_ENABLE;
427 } else {
428 val &= ~EXYNOS_EMUL_ENABLE;
429 }
430
431 writel(val, data->base + reg->emul_con);
432
433 clk_disable(data->clk);
434 mutex_unlock(&data->lock);
435 return 0;
436out:
437 return ret;
438}
439#else
440static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
441 { return -EINVAL; }
442#endif/*CONFIG_THERMAL_EMULATION*/
443
444static void exynos_tmu_work(struct work_struct *work)
445{
446 struct exynos_tmu_data *data = container_of(work,
447 struct exynos_tmu_data, irq_work);
448 struct exynos_tmu_platform_data *pdata = data->pdata;
449 const struct exynos_tmu_registers *reg = pdata->registers;
450 unsigned int val_irq, val_type;
451
452 /* Find which sensor generated this interrupt */
453 if (reg->tmu_irqstatus) {
454 val_type = readl(data->base_common + reg->tmu_irqstatus);
455 if (!((val_type >> data->id) & 0x1))
456 goto out;
457 }
458
459 exynos_report_trigger(data->reg_conf);
460 mutex_lock(&data->lock);
461 clk_enable(data->clk);
462
463 /* TODO: take action based on particular interrupt */
464 val_irq = readl(data->base + reg->tmu_intstat);
465 /* clear the interrupts */
466 writel(val_irq, data->base + reg->tmu_intclear);
467
468 clk_disable(data->clk);
469 mutex_unlock(&data->lock);
470out:
471 enable_irq(data->irq);
472}
473
474static irqreturn_t exynos_tmu_irq(int irq, void *id)
475{
476 struct exynos_tmu_data *data = id;
477
478 disable_irq_nosync(irq);
479 schedule_work(&data->irq_work);
480
481 return IRQ_HANDLED;
482}
483
484#ifdef CONFIG_OF
485static const struct of_device_id exynos_tmu_match[] = {
486 {
487 .compatible = "samsung,exynos4210-tmu",
488 .data = (void *)EXYNOS4210_TMU_DRV_DATA,
489 },
490 {
491 .compatible = "samsung,exynos4412-tmu",
492 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
493 },
494 {
495 .compatible = "samsung,exynos5250-tmu",
496 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
497 },
498 {
499 .compatible = "samsung,exynos5440-tmu",
500 .data = (void *)EXYNOS5440_TMU_DRV_DATA,
501 },
502 {},
503};
504MODULE_DEVICE_TABLE(of, exynos_tmu_match);
505#endif
506
507static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
508 struct platform_device *pdev, int id)
509{
510#ifdef CONFIG_OF
511 struct exynos_tmu_init_data *data_table;
512 struct exynos_tmu_platform_data *tmu_data;
513 if (pdev->dev.of_node) {
514 const struct of_device_id *match;
515 match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
516 if (!match)
517 return NULL;
518 data_table = (struct exynos_tmu_init_data *) match->data;
519 if (!data_table || id >= data_table->tmu_count)
520 return NULL;
521 tmu_data = data_table->tmu_data;
522 return (struct exynos_tmu_platform_data *) (tmu_data + id);
523 }
524#endif
525 return NULL;
526}
527
528static int exynos_map_dt_data(struct platform_device *pdev)
529{
530 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
531 struct exynos_tmu_platform_data *pdata;
532 struct resource res;
533 int ret;
534
535 if (!data)
536 return -ENODEV;
537
538 /*
539 * Try enabling the regulator if found
540 * TODO: Add regulator as an SOC feature, so that regulator enable
541 * is a compulsory call.
542 */
543 data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
544 if (!IS_ERR(data->regulator)) {
545 ret = regulator_enable(data->regulator);
546 if (ret) {
547 dev_err(&pdev->dev, "failed to enable vtmu\n");
548 return ret;
549 }
550 } else {
551 dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
552 }
553
554 data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
555 if (data->id < 0)
556 data->id = 0;
557
558 data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
559 if (data->irq <= 0) {
560 dev_err(&pdev->dev, "failed to get IRQ\n");
561 return -ENODEV;
562 }
563
564 if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
565 dev_err(&pdev->dev, "failed to get Resource 0\n");
566 return -ENODEV;
567 }
568
569 data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
570 if (!data->base) {
571 dev_err(&pdev->dev, "Failed to ioremap memory\n");
572 return -EADDRNOTAVAIL;
573 }
574
575 pdata = exynos_get_driver_data(pdev, data->id);
576 if (!pdata) {
577 dev_err(&pdev->dev, "No platform init data supplied.\n");
578 return -ENODEV;
579 }
580 data->pdata = pdata;
581 /*
582 * Check if the TMU shares some registers and then try to map the
583 * memory of common registers.
584 */
585 if (!TMU_SUPPORTS(pdata, SHARED_MEMORY))
586 return 0;
587
588 if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
589 dev_err(&pdev->dev, "failed to get Resource 1\n");
590 return -ENODEV;
591 }
592
593 data->base_common = devm_ioremap(&pdev->dev, res.start,
594 resource_size(&res));
595 if (!data->base_common) {
596 dev_err(&pdev->dev, "Failed to ioremap memory\n");
597 return -ENOMEM;
598 }
599
600 return 0;
601}
602
603static int exynos_tmu_probe(struct platform_device *pdev)
604{
605 struct exynos_tmu_data *data;
606 struct exynos_tmu_platform_data *pdata;
607 struct thermal_sensor_conf *sensor_conf;
608 int ret, i;
609
610 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
611 GFP_KERNEL);
612 if (!data) {
613 dev_err(&pdev->dev, "Failed to allocate driver structure\n");
614 return -ENOMEM;
615 }
616
617 platform_set_drvdata(pdev, data);
618 mutex_init(&data->lock);
619
620 ret = exynos_map_dt_data(pdev);
621 if (ret)
622 return ret;
623
624 pdata = data->pdata;
625
626 INIT_WORK(&data->irq_work, exynos_tmu_work);
627
628 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
629 if (IS_ERR(data->clk)) {
630 dev_err(&pdev->dev, "Failed to get clock\n");
631 return PTR_ERR(data->clk);
632 }
633
634 ret = clk_prepare(data->clk);
635 if (ret)
636 return ret;
637
638 if (pdata->type == SOC_ARCH_EXYNOS ||
639 pdata->type == SOC_ARCH_EXYNOS4210 ||
640 pdata->type == SOC_ARCH_EXYNOS5440)
641 data->soc = pdata->type;
642 else {
643 ret = -EINVAL;
644 dev_err(&pdev->dev, "Platform not supported\n");
645 goto err_clk;
646 }
647
648 ret = exynos_tmu_initialize(pdev);
649 if (ret) {
650 dev_err(&pdev->dev, "Failed to initialize TMU\n");
651 goto err_clk;
652 }
653
654 exynos_tmu_control(pdev, true);
655
656 /* Allocate a structure to register with the exynos core thermal */
657 sensor_conf = devm_kzalloc(&pdev->dev,
658 sizeof(struct thermal_sensor_conf), GFP_KERNEL);
659 if (!sensor_conf) {
660 dev_err(&pdev->dev, "Failed to allocate registration struct\n");
661 ret = -ENOMEM;
662 goto err_clk;
663 }
664 sprintf(sensor_conf->name, "therm_zone%d", data->id);
665 sensor_conf->read_temperature = (int (*)(void *))exynos_tmu_read;
666 sensor_conf->write_emul_temp =
667 (int (*)(void *, unsigned long))exynos_tmu_set_emulation;
668 sensor_conf->driver_data = data;
669 sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
670 pdata->trigger_enable[1] + pdata->trigger_enable[2]+
671 pdata->trigger_enable[3];
672
673 for (i = 0; i < sensor_conf->trip_data.trip_count; i++) {
674 sensor_conf->trip_data.trip_val[i] =
675 pdata->threshold + pdata->trigger_levels[i];
676 sensor_conf->trip_data.trip_type[i] =
677 pdata->trigger_type[i];
678 }
679
680 sensor_conf->trip_data.trigger_falling = pdata->threshold_falling;
681
682 sensor_conf->cooling_data.freq_clip_count = pdata->freq_tab_count;
683 for (i = 0; i < pdata->freq_tab_count; i++) {
684 sensor_conf->cooling_data.freq_data[i].freq_clip_max =
685 pdata->freq_tab[i].freq_clip_max;
686 sensor_conf->cooling_data.freq_data[i].temp_level =
687 pdata->freq_tab[i].temp_level;
688 }
689 sensor_conf->dev = &pdev->dev;
690 /* Register the sensor with thermal management interface */
691 ret = exynos_register_thermal(sensor_conf);
692 if (ret) {
693 dev_err(&pdev->dev, "Failed to register thermal interface\n");
694 goto err_clk;
695 }
696 data->reg_conf = sensor_conf;
697
698 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
699 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
700 if (ret) {
701 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
702 goto err_clk;
703 }
704
705 return 0;
706err_clk:
707 clk_unprepare(data->clk);
708 return ret;
709}
710
711static int exynos_tmu_remove(struct platform_device *pdev)
712{
713 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
714
715 exynos_tmu_control(pdev, false);
716
717 exynos_unregister_thermal(data->reg_conf);
718
719 clk_unprepare(data->clk);
720
721 if (!IS_ERR(data->regulator))
722 regulator_disable(data->regulator);
723
724 return 0;
725}
726
727#ifdef CONFIG_PM_SLEEP
728static int exynos_tmu_suspend(struct device *dev)
729{
730 exynos_tmu_control(to_platform_device(dev), false);
731
732 return 0;
733}
734
735static int exynos_tmu_resume(struct device *dev)
736{
737 struct platform_device *pdev = to_platform_device(dev);
738
739 exynos_tmu_initialize(pdev);
740 exynos_tmu_control(pdev, true);
741
742 return 0;
743}
744
745static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
746 exynos_tmu_suspend, exynos_tmu_resume);
747#define EXYNOS_TMU_PM (&exynos_tmu_pm)
748#else
749#define EXYNOS_TMU_PM NULL
750#endif
751
752static struct platform_driver exynos_tmu_driver = {
753 .driver = {
754 .name = "exynos-tmu",
755 .owner = THIS_MODULE,
756 .pm = EXYNOS_TMU_PM,
757 .of_match_table = of_match_ptr(exynos_tmu_match),
758 },
759 .probe = exynos_tmu_probe,
760 .remove = exynos_tmu_remove,
761};
762
763module_platform_driver(exynos_tmu_driver);
764
765MODULE_DESCRIPTION("EXYNOS TMU Driver");
766MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
767MODULE_LICENSE("GPL");
768MODULE_ALIAS("platform:exynos-tmu");
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
new file mode 100644
index 000000000000..b364c9eee701
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -0,0 +1,311 @@
1/*
2 * exynos_tmu.h - 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.daniel@samsung.com>
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#ifndef _EXYNOS_TMU_H
24#define _EXYNOS_TMU_H
25#include <linux/cpu_cooling.h>
26
27#include "exynos_thermal_common.h"
28
29enum calibration_type {
30 TYPE_ONE_POINT_TRIMMING,
31 TYPE_ONE_POINT_TRIMMING_25,
32 TYPE_ONE_POINT_TRIMMING_85,
33 TYPE_TWO_POINT_TRIMMING,
34 TYPE_NONE,
35};
36
37enum calibration_mode {
38 SW_MODE,
39 HW_MODE,
40};
41
42enum soc_type {
43 SOC_ARCH_EXYNOS4210 = 1,
44 SOC_ARCH_EXYNOS,
45 SOC_ARCH_EXYNOS5440,
46};
47
48/**
49 * EXYNOS TMU supported features.
50 * TMU_SUPPORT_EMULATION - This features is used to set user defined
51 * temperature to the TMU controller.
52 * TMU_SUPPORT_MULTI_INST - This features denotes that the soc
53 * has many instances of TMU.
54 * TMU_SUPPORT_TRIM_RELOAD - This features shows that trimming can
55 * be reloaded.
56 * TMU_SUPPORT_FALLING_TRIP - This features shows that interrupt can
57 * be registered for falling trips also.
58 * TMU_SUPPORT_READY_STATUS - This feature tells that the TMU current
59 * state(active/idle) can be checked.
60 * TMU_SUPPORT_EMUL_TIME - This features allows to set next temp emulation
61 * sample time.
62 * TMU_SUPPORT_SHARED_MEMORY - This feature tells that the different TMU
63 * sensors shares some common registers.
64 * TMU_SUPPORT - macro to compare the above features with the supplied.
65 */
66#define TMU_SUPPORT_EMULATION BIT(0)
67#define TMU_SUPPORT_MULTI_INST BIT(1)
68#define TMU_SUPPORT_TRIM_RELOAD BIT(2)
69#define TMU_SUPPORT_FALLING_TRIP BIT(3)
70#define TMU_SUPPORT_READY_STATUS BIT(4)
71#define TMU_SUPPORT_EMUL_TIME BIT(5)
72#define TMU_SUPPORT_SHARED_MEMORY BIT(6)
73
74#define TMU_SUPPORTS(a, b) (a->features & TMU_SUPPORT_ ## b)
75
76/**
77 * struct exynos_tmu_register - register descriptors to access registers and
78 * bitfields. The register validity, offsets and bitfield values may vary
79 * slightly across different exynos SOC's.
80 * @triminfo_data: register containing 2 pont trimming data
81 * @triminfo_25_shift: shift bit of the 25 C trim value in triminfo_data reg.
82 * @triminfo_85_shift: shift bit of the 85 C trim value in triminfo_data reg.
83 * @triminfo_ctrl: trim info controller register.
84 * @triminfo_reload_shift: shift of triminfo reload enable bit in triminfo_ctrl
85 reg.
86 * @tmu_ctrl: TMU main controller register.
87 * @buf_vref_sel_shift: shift bits of reference voltage in tmu_ctrl register.
88 * @buf_vref_sel_mask: mask bits of reference voltage in tmu_ctrl register.
89 * @therm_trip_mode_shift: shift bits of tripping mode in tmu_ctrl register.
90 * @therm_trip_mode_mask: mask bits of tripping mode in tmu_ctrl register.
91 * @therm_trip_en_shift: shift bits of tripping enable in tmu_ctrl register.
92 * @buf_slope_sel_shift: shift bits of amplifier gain value in tmu_ctrl
93 register.
94 * @buf_slope_sel_mask: mask bits of amplifier gain value in tmu_ctrl register.
95 * @calib_mode_shift: shift bits of calibration mode value in tmu_ctrl
96 register.
97 * @calib_mode_mask: mask bits of calibration mode value in tmu_ctrl
98 register.
99 * @therm_trip_tq_en_shift: shift bits of thermal trip enable by TQ pin in
100 tmu_ctrl register.
101 * @core_en_shift: shift bits of TMU core enable bit in tmu_ctrl register.
102 * @tmu_status: register drescribing the TMU status.
103 * @tmu_cur_temp: register containing the current temperature of the TMU.
104 * @tmu_cur_temp_shift: shift bits of current temp value in tmu_cur_temp
105 register.
106 * @threshold_temp: register containing the base threshold level.
107 * @threshold_th0: Register containing first set of rising levels.
108 * @threshold_th0_l0_shift: shift bits of level0 threshold temperature.
109 * @threshold_th0_l1_shift: shift bits of level1 threshold temperature.
110 * @threshold_th0_l2_shift: shift bits of level2 threshold temperature.
111 * @threshold_th0_l3_shift: shift bits of level3 threshold temperature.
112 * @threshold_th1: Register containing second set of rising levels.
113 * @threshold_th1_l0_shift: shift bits of level0 threshold temperature.
114 * @threshold_th1_l1_shift: shift bits of level1 threshold temperature.
115 * @threshold_th1_l2_shift: shift bits of level2 threshold temperature.
116 * @threshold_th1_l3_shift: shift bits of level3 threshold temperature.
117 * @threshold_th2: Register containing third set of rising levels.
118 * @threshold_th2_l0_shift: shift bits of level0 threshold temperature.
119 * @threshold_th3: Register containing fourth set of rising levels.
120 * @threshold_th3_l0_shift: shift bits of level0 threshold temperature.
121 * @tmu_inten: register containing the different threshold interrupt
122 enable bits.
123 * @inten_rise_shift: shift bits of all rising interrupt bits.
124 * @inten_rise_mask: mask bits of all rising interrupt bits.
125 * @inten_fall_shift: shift bits of all rising interrupt bits.
126 * @inten_fall_mask: mask bits of all rising interrupt bits.
127 * @inten_rise0_shift: shift bits of rising 0 interrupt bits.
128 * @inten_rise1_shift: shift bits of rising 1 interrupt bits.
129 * @inten_rise2_shift: shift bits of rising 2 interrupt bits.
130 * @inten_rise3_shift: shift bits of rising 3 interrupt bits.
131 * @inten_fall0_shift: shift bits of falling 0 interrupt bits.
132 * @inten_fall1_shift: shift bits of falling 1 interrupt bits.
133 * @inten_fall2_shift: shift bits of falling 2 interrupt bits.
134 * @inten_fall3_shift: shift bits of falling 3 interrupt bits.
135 * @tmu_intstat: Register containing the interrupt status values.
136 * @tmu_intclear: Register for clearing the raised interrupt status.
137 * @emul_con: TMU emulation controller register.
138 * @emul_temp_shift: shift bits of emulation temperature.
139 * @emul_time_shift: shift bits of emulation time.
140 * @emul_time_mask: mask bits of emulation time.
141 * @tmu_irqstatus: register to find which TMU generated interrupts.
142 * @tmu_pmin: register to get/set the Pmin value.
143 */
144struct exynos_tmu_registers {
145 u32 triminfo_data;
146 u32 triminfo_25_shift;
147 u32 triminfo_85_shift;
148
149 u32 triminfo_ctrl;
150 u32 triminfo_reload_shift;
151
152 u32 tmu_ctrl;
153 u32 buf_vref_sel_shift;
154 u32 buf_vref_sel_mask;
155 u32 therm_trip_mode_shift;
156 u32 therm_trip_mode_mask;
157 u32 therm_trip_en_shift;
158 u32 buf_slope_sel_shift;
159 u32 buf_slope_sel_mask;
160 u32 calib_mode_shift;
161 u32 calib_mode_mask;
162 u32 therm_trip_tq_en_shift;
163 u32 core_en_shift;
164
165 u32 tmu_status;
166
167 u32 tmu_cur_temp;
168 u32 tmu_cur_temp_shift;
169
170 u32 threshold_temp;
171
172 u32 threshold_th0;
173 u32 threshold_th0_l0_shift;
174 u32 threshold_th0_l1_shift;
175 u32 threshold_th0_l2_shift;
176 u32 threshold_th0_l3_shift;
177
178 u32 threshold_th1;
179 u32 threshold_th1_l0_shift;
180 u32 threshold_th1_l1_shift;
181 u32 threshold_th1_l2_shift;
182 u32 threshold_th1_l3_shift;
183
184 u32 threshold_th2;
185 u32 threshold_th2_l0_shift;
186
187 u32 threshold_th3;
188 u32 threshold_th3_l0_shift;
189
190 u32 tmu_inten;
191 u32 inten_rise_shift;
192 u32 inten_rise_mask;
193 u32 inten_fall_shift;
194 u32 inten_fall_mask;
195 u32 inten_rise0_shift;
196 u32 inten_rise1_shift;
197 u32 inten_rise2_shift;
198 u32 inten_rise3_shift;
199 u32 inten_fall0_shift;
200 u32 inten_fall1_shift;
201 u32 inten_fall2_shift;
202 u32 inten_fall3_shift;
203
204 u32 tmu_intstat;
205
206 u32 tmu_intclear;
207
208 u32 emul_con;
209 u32 emul_temp_shift;
210 u32 emul_time_shift;
211 u32 emul_time_mask;
212
213 u32 tmu_irqstatus;
214 u32 tmu_pmin;
215};
216
217/**
218 * struct exynos_tmu_platform_data
219 * @threshold: basic temperature for generating interrupt
220 * 25 <= threshold <= 125 [unit: degree Celsius]
221 * @threshold_falling: differntial value for setting threshold
222 * of temperature falling interrupt.
223 * @trigger_levels: array for each interrupt levels
224 * [unit: degree Celsius]
225 * 0: temperature for trigger_level0 interrupt
226 * condition for trigger_level0 interrupt:
227 * current temperature > threshold + trigger_levels[0]
228 * 1: temperature for trigger_level1 interrupt
229 * condition for trigger_level1 interrupt:
230 * current temperature > threshold + trigger_levels[1]
231 * 2: temperature for trigger_level2 interrupt
232 * condition for trigger_level2 interrupt:
233 * current temperature > threshold + trigger_levels[2]
234 * 3: temperature for trigger_level3 interrupt
235 * condition for trigger_level3 interrupt:
236 * current temperature > threshold + trigger_levels[3]
237 * @trigger_type: defines the type of trigger. Possible values are,
238 * THROTTLE_ACTIVE trigger type
239 * THROTTLE_PASSIVE trigger type
240 * SW_TRIP trigger type
241 * HW_TRIP
242 * @trigger_enable[]: array to denote which trigger levels are enabled.
243 * 1 = enable trigger_level[] interrupt,
244 * 0 = disable trigger_level[] interrupt
245 * @max_trigger_level: max trigger level supported by the TMU
246 * @gain: gain of amplifier in the positive-TC generator block
247 * 0 <= gain <= 15
248 * @reference_voltage: reference voltage of amplifier
249 * in the positive-TC generator block
250 * 0 <= reference_voltage <= 31
251 * @noise_cancel_mode: noise cancellation mode
252 * 000, 100, 101, 110 and 111 can be different modes
253 * @type: determines the type of SOC
254 * @efuse_value: platform defined fuse value
255 * @min_efuse_value: minimum valid trimming data
256 * @max_efuse_value: maximum valid trimming data
257 * @first_point_trim: temp value of the first point trimming
258 * @second_point_trim: temp value of the second point trimming
259 * @default_temp_offset: default temperature offset in case of no trimming
260 * @cal_type: calibration type for temperature
261 * @cal_mode: calibration mode for temperature
262 * @freq_clip_table: Table representing frequency reduction percentage.
263 * @freq_tab_count: Count of the above table as frequency reduction may
264 * applicable to only some of the trigger levels.
265 * @registers: Pointer to structure containing all the TMU controller registers
266 * and bitfields shifts and masks.
267 * @features: a bitfield value indicating the features supported in SOC like
268 * emulation, multi instance etc
269 *
270 * This structure is required for configuration of exynos_tmu driver.
271 */
272struct exynos_tmu_platform_data {
273 u8 threshold;
274 u8 threshold_falling;
275 u8 trigger_levels[MAX_TRIP_COUNT];
276 enum trigger_type trigger_type[MAX_TRIP_COUNT];
277 bool trigger_enable[MAX_TRIP_COUNT];
278 u8 max_trigger_level;
279 u8 gain;
280 u8 reference_voltage;
281 u8 noise_cancel_mode;
282
283 u32 efuse_value;
284 u32 min_efuse_value;
285 u32 max_efuse_value;
286 u8 first_point_trim;
287 u8 second_point_trim;
288 u8 default_temp_offset;
289
290 enum calibration_type cal_type;
291 enum calibration_mode cal_mode;
292 enum soc_type type;
293 struct freq_clip_table freq_tab[4];
294 unsigned int freq_tab_count;
295 const struct exynos_tmu_registers *registers;
296 unsigned int features;
297};
298
299/**
300 * struct exynos_tmu_init_data
301 * @tmu_count: number of TMU instances.
302 * @tmu_data: platform data of all TMU instances.
303 * This structure is required to store data for multi-instance exynos tmu
304 * driver.
305 */
306struct exynos_tmu_init_data {
307 int tmu_count;
308 struct exynos_tmu_platform_data tmu_data[];
309};
310
311#endif /* _EXYNOS_TMU_H */
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
new file mode 100644
index 000000000000..9002499c1f69
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -0,0 +1,250 @@
1/*
2 * exynos_tmu_data.c - Samsung EXYNOS tmu data file
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Amit Daniel Kachhap <amit.daniel@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include "exynos_thermal_common.h"
24#include "exynos_tmu.h"
25#include "exynos_tmu_data.h"
26
27#if defined(CONFIG_CPU_EXYNOS4210)
28static const struct exynos_tmu_registers exynos4210_tmu_registers = {
29 .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
30 .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
31 .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
32 .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
33 .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
34 .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
35 .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
36 .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
37 .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
38 .tmu_status = EXYNOS_TMU_REG_STATUS,
39 .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
40 .threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
41 .threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
42 .tmu_inten = EXYNOS_TMU_REG_INTEN,
43 .inten_rise_mask = EXYNOS4210_TMU_TRIG_LEVEL_MASK,
44 .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
45 .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
46 .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
47 .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
48 .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
49 .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
50};
51
52struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
53 .tmu_data = {
54 {
55 .threshold = 80,
56 .trigger_levels[0] = 5,
57 .trigger_levels[1] = 20,
58 .trigger_levels[2] = 30,
59 .trigger_enable[0] = true,
60 .trigger_enable[1] = true,
61 .trigger_enable[2] = true,
62 .trigger_enable[3] = false,
63 .trigger_type[0] = THROTTLE_ACTIVE,
64 .trigger_type[1] = THROTTLE_ACTIVE,
65 .trigger_type[2] = SW_TRIP,
66 .max_trigger_level = 4,
67 .gain = 15,
68 .reference_voltage = 7,
69 .cal_type = TYPE_ONE_POINT_TRIMMING,
70 .min_efuse_value = 40,
71 .max_efuse_value = 100,
72 .first_point_trim = 25,
73 .second_point_trim = 85,
74 .default_temp_offset = 50,
75 .freq_tab[0] = {
76 .freq_clip_max = 800 * 1000,
77 .temp_level = 85,
78 },
79 .freq_tab[1] = {
80 .freq_clip_max = 200 * 1000,
81 .temp_level = 100,
82 },
83 .freq_tab_count = 2,
84 .type = SOC_ARCH_EXYNOS4210,
85 .registers = &exynos4210_tmu_registers,
86 .features = TMU_SUPPORT_READY_STATUS,
87 },
88 },
89 .tmu_count = 1,
90};
91#endif
92
93#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
94static const struct exynos_tmu_registers exynos5250_tmu_registers = {
95 .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
96 .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
97 .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
98 .triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
99 .triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
100 .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
101 .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
102 .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
103 .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
104 .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
105 .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
106 .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
107 .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
108 .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
109 .tmu_status = EXYNOS_TMU_REG_STATUS,
110 .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
111 .threshold_th0 = EXYNOS_THD_TEMP_RISE,
112 .threshold_th1 = EXYNOS_THD_TEMP_FALL,
113 .tmu_inten = EXYNOS_TMU_REG_INTEN,
114 .inten_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
115 .inten_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
116 .inten_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
117 .inten_fall_shift = EXYNOS_TMU_FALL_INT_SHIFT,
118 .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
119 .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
120 .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
121 .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
122 .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
123 .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
124 .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
125 .emul_con = EXYNOS_EMUL_CON,
126 .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
127 .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
128 .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
129};
130
131#define EXYNOS5250_TMU_DATA \
132 .threshold_falling = 10, \
133 .trigger_levels[0] = 85, \
134 .trigger_levels[1] = 103, \
135 .trigger_levels[2] = 110, \
136 .trigger_levels[3] = 120, \
137 .trigger_enable[0] = true, \
138 .trigger_enable[1] = true, \
139 .trigger_enable[2] = true, \
140 .trigger_enable[3] = false, \
141 .trigger_type[0] = THROTTLE_ACTIVE, \
142 .trigger_type[1] = THROTTLE_ACTIVE, \
143 .trigger_type[2] = SW_TRIP, \
144 .trigger_type[3] = HW_TRIP, \
145 .max_trigger_level = 4, \
146 .gain = 8, \
147 .reference_voltage = 16, \
148 .noise_cancel_mode = 4, \
149 .cal_type = TYPE_ONE_POINT_TRIMMING, \
150 .efuse_value = 55, \
151 .min_efuse_value = 40, \
152 .max_efuse_value = 100, \
153 .first_point_trim = 25, \
154 .second_point_trim = 85, \
155 .default_temp_offset = 50, \
156 .freq_tab[0] = { \
157 .freq_clip_max = 800 * 1000, \
158 .temp_level = 85, \
159 }, \
160 .freq_tab[1] = { \
161 .freq_clip_max = 200 * 1000, \
162 .temp_level = 103, \
163 }, \
164 .freq_tab_count = 2, \
165 .type = SOC_ARCH_EXYNOS, \
166 .registers = &exynos5250_tmu_registers, \
167 .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
168 TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
169 TMU_SUPPORT_EMUL_TIME)
170
171struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
172 .tmu_data = {
173 { EXYNOS5250_TMU_DATA },
174 },
175 .tmu_count = 1,
176};
177#endif
178
179#if defined(CONFIG_SOC_EXYNOS5440)
180static const struct exynos_tmu_registers exynos5440_tmu_registers = {
181 .triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
182 .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
183 .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
184 .tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
185 .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
186 .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
187 .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
188 .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
189 .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
190 .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
191 .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
192 .calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT,
193 .calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK,
194 .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
195 .tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
196 .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
197 .threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
198 .threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
199 .threshold_th2 = EXYNOS5440_TMU_S0_7_TH2,
200 .threshold_th3_l0_shift = EXYNOS5440_TMU_TH_RISE4_SHIFT,
201 .tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
202 .inten_rise_mask = EXYNOS5440_TMU_RISE_INT_MASK,
203 .inten_rise_shift = EXYNOS5440_TMU_RISE_INT_SHIFT,
204 .inten_fall_mask = EXYNOS5440_TMU_FALL_INT_MASK,
205 .inten_fall_shift = EXYNOS5440_TMU_FALL_INT_SHIFT,
206 .inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
207 .inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,
208 .inten_rise2_shift = EXYNOS5440_TMU_INTEN_RISE2_SHIFT,
209 .inten_rise3_shift = EXYNOS5440_TMU_INTEN_RISE3_SHIFT,
210 .inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
211 .tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
212 .tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
213 .tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
214 .emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
215 .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
216 .tmu_pmin = EXYNOS5440_TMU_PMIN,
217};
218
219#define EXYNOS5440_TMU_DATA \
220 .trigger_levels[0] = 100, \
221 .trigger_levels[4] = 105, \
222 .trigger_enable[0] = 1, \
223 .trigger_type[0] = SW_TRIP, \
224 .trigger_type[4] = HW_TRIP, \
225 .max_trigger_level = 5, \
226 .gain = 5, \
227 .reference_voltage = 16, \
228 .noise_cancel_mode = 4, \
229 .cal_type = TYPE_ONE_POINT_TRIMMING, \
230 .cal_mode = 0, \
231 .efuse_value = 0x5b2d, \
232 .min_efuse_value = 16, \
233 .max_efuse_value = 76, \
234 .first_point_trim = 25, \
235 .second_point_trim = 70, \
236 .default_temp_offset = 25, \
237 .type = SOC_ARCH_EXYNOS5440, \
238 .registers = &exynos5440_tmu_registers, \
239 .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
240 TMU_SUPPORT_MULTI_INST | TMU_SUPPORT_SHARED_MEMORY),
241
242struct exynos_tmu_init_data const exynos5440_default_tmu_data = {
243 .tmu_data = {
244 { EXYNOS5440_TMU_DATA } ,
245 { EXYNOS5440_TMU_DATA } ,
246 { EXYNOS5440_TMU_DATA } ,
247 },
248 .tmu_count = 3,
249};
250#endif
diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
new file mode 100644
index 000000000000..dc7feb51099b
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu_data.h
@@ -0,0 +1,155 @@
1/*
2 * exynos_tmu_data.h - Samsung EXYNOS tmu data header file
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Amit Daniel Kachhap <amit.daniel@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#ifndef _EXYNOS_TMU_DATA_H
24#define _EXYNOS_TMU_DATA_H
25
26/* Exynos generic registers */
27#define EXYNOS_TMU_REG_TRIMINFO 0x0
28#define EXYNOS_TMU_REG_CONTROL 0x20
29#define EXYNOS_TMU_REG_STATUS 0x28
30#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
31#define EXYNOS_TMU_REG_INTEN 0x70
32#define EXYNOS_TMU_REG_INTSTAT 0x74
33#define EXYNOS_TMU_REG_INTCLEAR 0x78
34
35#define EXYNOS_TMU_TEMP_MASK 0xff
36#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
37#define EXYNOS_TMU_REF_VOLTAGE_MASK 0x1f
38#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK 0xf
39#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT 8
40#define EXYNOS_TMU_CORE_EN_SHIFT 0
41
42/* Exynos4210 specific registers */
43#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
44#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
45#define EXYNOS4210_TMU_REG_TRIG_LEVEL1 0x54
46#define EXYNOS4210_TMU_REG_TRIG_LEVEL2 0x58
47#define EXYNOS4210_TMU_REG_TRIG_LEVEL3 0x5C
48#define EXYNOS4210_TMU_REG_PAST_TEMP0 0x60
49#define EXYNOS4210_TMU_REG_PAST_TEMP1 0x64
50#define EXYNOS4210_TMU_REG_PAST_TEMP2 0x68
51#define EXYNOS4210_TMU_REG_PAST_TEMP3 0x6C
52
53#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK 0x1
54#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK 0x10
55#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK 0x100
56#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK 0x1000
57#define EXYNOS4210_TMU_TRIG_LEVEL_MASK 0x1111
58#define EXYNOS4210_TMU_INTCLEAR_VAL 0x1111
59
60/* Exynos5250 and Exynos4412 specific registers */
61#define EXYNOS_TMU_TRIMINFO_CON 0x14
62#define EXYNOS_THD_TEMP_RISE 0x50
63#define EXYNOS_THD_TEMP_FALL 0x54
64#define EXYNOS_EMUL_CON 0x80
65
66#define EXYNOS_TRIMINFO_RELOAD_SHIFT 1
67#define EXYNOS_TRIMINFO_25_SHIFT 0
68#define EXYNOS_TRIMINFO_85_SHIFT 8
69#define EXYNOS_TMU_RISE_INT_MASK 0x111
70#define EXYNOS_TMU_RISE_INT_SHIFT 0
71#define EXYNOS_TMU_FALL_INT_MASK 0x111
72#define EXYNOS_TMU_FALL_INT_SHIFT 12
73#define EXYNOS_TMU_CLEAR_RISE_INT 0x111
74#define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 12)
75#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
76#define EXYNOS_TMU_TRIP_MODE_MASK 0x7
77#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12
78#define EXYNOS_TMU_CALIB_MODE_SHIFT 4
79#define EXYNOS_TMU_CALIB_MODE_MASK 0x3
80
81#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
82#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
83#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
84#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
85#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
86#define EXYNOS_TMU_INTEN_FALL1_SHIFT 20
87#define EXYNOS_TMU_INTEN_FALL2_SHIFT 24
88
89#define EXYNOS_EMUL_TIME 0x57F0
90#define EXYNOS_EMUL_TIME_MASK 0xffff
91#define EXYNOS_EMUL_TIME_SHIFT 16
92#define EXYNOS_EMUL_DATA_SHIFT 8
93#define EXYNOS_EMUL_DATA_MASK 0xFF
94#define EXYNOS_EMUL_ENABLE 0x1
95
96#define EXYNOS_MAX_TRIGGER_PER_REG 4
97
98/*exynos5440 specific registers*/
99#define EXYNOS5440_TMU_S0_7_TRIM 0x000
100#define EXYNOS5440_TMU_S0_7_CTRL 0x020
101#define EXYNOS5440_TMU_S0_7_DEBUG 0x040
102#define EXYNOS5440_TMU_S0_7_STATUS 0x060
103#define EXYNOS5440_TMU_S0_7_TEMP 0x0f0
104#define EXYNOS5440_TMU_S0_7_TH0 0x110
105#define EXYNOS5440_TMU_S0_7_TH1 0x130
106#define EXYNOS5440_TMU_S0_7_TH2 0x150
107#define EXYNOS5440_TMU_S0_7_EVTEN 0x1F0
108#define EXYNOS5440_TMU_S0_7_IRQEN 0x210
109#define EXYNOS5440_TMU_S0_7_IRQ 0x230
110/* exynos5440 common registers */
111#define EXYNOS5440_TMU_IRQ_STATUS 0x000
112#define EXYNOS5440_TMU_PMIN 0x004
113#define EXYNOS5440_TMU_TEMP 0x008
114
115#define EXYNOS5440_TMU_RISE_INT_MASK 0xf
116#define EXYNOS5440_TMU_RISE_INT_SHIFT 0
117#define EXYNOS5440_TMU_FALL_INT_MASK 0xf
118#define EXYNOS5440_TMU_FALL_INT_SHIFT 4
119#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT 0
120#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT 1
121#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT 2
122#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT 3
123#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT 4
124#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT 5
125#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT 6
126#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT 7
127#define EXYNOS5440_TMU_TH_RISE0_SHIFT 0
128#define EXYNOS5440_TMU_TH_RISE1_SHIFT 8
129#define EXYNOS5440_TMU_TH_RISE2_SHIFT 16
130#define EXYNOS5440_TMU_TH_RISE3_SHIFT 24
131#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
132#define EXYNOS5440_EFUSE_SWAP_OFFSET 8
133
134#if defined(CONFIG_CPU_EXYNOS4210)
135extern struct exynos_tmu_init_data const exynos4210_default_tmu_data;
136#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
137#else
138#define EXYNOS4210_TMU_DRV_DATA (NULL)
139#endif
140
141#if (defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412))
142extern struct exynos_tmu_init_data const exynos5250_default_tmu_data;
143#define EXYNOS5250_TMU_DRV_DATA (&exynos5250_default_tmu_data)
144#else
145#define EXYNOS5250_TMU_DRV_DATA (NULL)
146#endif
147
148#if defined(CONFIG_SOC_EXYNOS5440)
149extern struct exynos_tmu_init_data const exynos5440_default_tmu_data;
150#define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data)
151#else
152#define EXYNOS5440_TMU_DRV_DATA (NULL)
153#endif
154
155#endif /*_EXYNOS_TMU_DATA_H*/