aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2013-12-19 09:08:03 -0500
committerJiri Kosina <jkosina@suse.cz>2013-12-19 09:08:32 -0500
commite23c34bb41da65f354fb7eee04300c56ee48f60c (patch)
tree549fbe449d55273b81ef104a9755109bf4ae7817 /drivers/thermal
parentb481c2cb3534c85dca625973b33eba15f9af3e4c (diff)
parent319e2e3f63c348a9b66db4667efa73178e18b17d (diff)
Merge branch 'master' into for-next
Sync with Linus' tree to be able to apply fixes on top of newer things in tree (efi-stub). Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/Kconfig41
-rw-r--r--drivers/thermal/Makefile6
-rw-r--r--drivers/thermal/cpu_cooling.c12
-rw-r--r--drivers/thermal/exynos_thermal.c1059
-rw-r--r--drivers/thermal/imx_thermal.c541
-rw-r--r--drivers/thermal/intel_powerclamp.c29
-rw-r--r--drivers/thermal/samsung/Kconfig18
-rw-r--r--drivers/thermal/samsung/Makefile7
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.c430
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.h107
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c766
-rw-r--r--drivers/thermal/samsung/exynos_tmu.h316
-rw-r--r--drivers/thermal/samsung/exynos_tmu_data.c268
-rw-r--r--drivers/thermal/samsung/exynos_tmu_data.h166
-rw-r--r--drivers/thermal/step_wise.c32
-rw-r--r--drivers/thermal/thermal_core.c317
-rw-r--r--drivers/thermal/thermal_hwmon.c269
-rw-r--r--drivers/thermal/thermal_hwmon.h49
-rw-r--r--drivers/thermal/ti-soc-thermal/dra752-thermal-data.c5
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c6
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal-common.c8
-rw-r--r--drivers/thermal/x86_pkg_temp_thermal.c14
22 files changed, 3089 insertions, 1377 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index e988c81d763c..f35a1f75b15b 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -17,8 +17,17 @@ if THERMAL
17 17
18config THERMAL_HWMON 18config THERMAL_HWMON
19 bool 19 bool
20 prompt "Expose thermal sensors as hwmon device"
20 depends on HWMON=y || HWMON=THERMAL 21 depends on HWMON=y || HWMON=THERMAL
21 default y 22 default y
23 help
24 In case a sensor is registered with the thermal
25 framework, this option will also register it
26 as a hwmon. The sensor will then have the common
27 hwmon sysfs interface.
28
29 Say 'Y' here if you want all thermal sensors to
30 have hwmon sysfs interface too.
22 31
23choice 32choice
24 prompt "Default Thermal governor" 33 prompt "Default Thermal governor"
@@ -47,7 +56,7 @@ config THERMAL_DEFAULT_GOV_USER_SPACE
47 select THERMAL_GOV_USER_SPACE 56 select THERMAL_GOV_USER_SPACE
48 help 57 help
49 Select this if you want to let the user space manage the 58 Select this if you want to let the user space manage the
50 lpatform thermals. 59 platform thermals.
51 60
52endchoice 61endchoice
53 62
@@ -60,6 +69,7 @@ config THERMAL_GOV_STEP_WISE
60 bool "Step_wise thermal governor" 69 bool "Step_wise thermal governor"
61 help 70 help
62 Enable this to manage platform thermals using a simple linear 71 Enable this to manage platform thermals using a simple linear
72 governor.
63 73
64config THERMAL_GOV_USER_SPACE 74config THERMAL_GOV_USER_SPACE
65 bool "User_space thermal governor" 75 bool "User_space thermal governor"
@@ -69,7 +79,6 @@ config THERMAL_GOV_USER_SPACE
69config CPU_THERMAL 79config CPU_THERMAL
70 bool "generic cpu cooling support" 80 bool "generic cpu cooling support"
71 depends on CPU_FREQ 81 depends on CPU_FREQ
72 select CPU_FREQ_TABLE
73 help 82 help
74 This implements the generic cpu cooling mechanism through frequency 83 This implements the generic cpu cooling mechanism through frequency
75 reduction. An ACPI version of this already exists 84 reduction. An ACPI version of this already exists
@@ -91,20 +100,31 @@ config THERMAL_EMULATION
91 because userland can easily disable the thermal policy by simply 100 because userland can easily disable the thermal policy by simply
92 flooding this sysfs node with low temperature values. 101 flooding this sysfs node with low temperature values.
93 102
103config IMX_THERMAL
104 tristate "Temperature sensor driver for Freescale i.MX SoCs"
105 depends on CPU_THERMAL
106 depends on MFD_SYSCON
107 depends on OF
108 help
109 Support for Temperature Monitor (TEMPMON) found on Freescale i.MX SoCs.
110 It supports one critical trip point and one passive trip point. The
111 cpufreq is used as the cooling device to throttle CPUs when the
112 passive trip is crossed.
113
94config SPEAR_THERMAL 114config SPEAR_THERMAL
95 bool "SPEAr thermal sensor driver" 115 bool "SPEAr thermal sensor driver"
96 depends on PLAT_SPEAR 116 depends on PLAT_SPEAR
97 depends on OF 117 depends on OF
98 help 118 help
99 Enable this to plug the SPEAr thermal sensor driver into the Linux 119 Enable this to plug the SPEAr thermal sensor driver into the Linux
100 thermal framework 120 thermal framework.
101 121
102config RCAR_THERMAL 122config RCAR_THERMAL
103 tristate "Renesas R-Car thermal driver" 123 tristate "Renesas R-Car thermal driver"
104 depends on ARCH_SHMOBILE 124 depends on ARCH_SHMOBILE
105 help 125 help
106 Enable this to plug the R-Car thermal sensor driver into the Linux 126 Enable this to plug the R-Car thermal sensor driver into the Linux
107 thermal framework 127 thermal framework.
108 128
109config KIRKWOOD_THERMAL 129config KIRKWOOD_THERMAL
110 tristate "Temperature sensor on Marvell Kirkwood SoCs" 130 tristate "Temperature sensor on Marvell Kirkwood SoCs"
@@ -114,14 +134,6 @@ config KIRKWOOD_THERMAL
114 Support for the Kirkwood thermal sensor driver into the Linux thermal 134 Support for the Kirkwood thermal sensor driver into the Linux thermal
115 framework. Only kirkwood 88F6282 and 88F6283 have this sensor. 135 framework. Only kirkwood 88F6282 and 88F6283 have this sensor.
116 136
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 137config DOVE_THERMAL
126 tristate "Temperature sensor on Marvell Dove SoCs" 138 tristate "Temperature sensor on Marvell Dove SoCs"
127 depends on ARCH_DOVE 139 depends on ARCH_DOVE
@@ -184,4 +196,9 @@ menu "Texas Instruments thermal drivers"
184source "drivers/thermal/ti-soc-thermal/Kconfig" 196source "drivers/thermal/ti-soc-thermal/Kconfig"
185endmenu 197endmenu
186 198
199menu "Samsung thermal drivers"
200depends on PLAT_SAMSUNG
201source "drivers/thermal/samsung/Kconfig"
202endmenu
203
187endif 204endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 67184a293e3f..584b36319d51 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -5,6 +5,9 @@
5obj-$(CONFIG_THERMAL) += thermal_sys.o 5obj-$(CONFIG_THERMAL) += thermal_sys.o
6thermal_sys-y += thermal_core.o 6thermal_sys-y += thermal_core.o
7 7
8# interface to/from other layers providing sensors
9thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
10
8# governors 11# governors
9thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o 12thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o
10thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o 13thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o
@@ -17,10 +20,11 @@ thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
17obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 20obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
18obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o 21obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
19obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o 22obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
20obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o 23obj-y += samsung/
21obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o 24obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
22obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o 25obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
23obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o 26obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
27obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
24obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o 28obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
25obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 29obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
26obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o 30obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 82e15dbb3ac7..02a46f23d14c 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -322,6 +322,8 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
322 322
323 if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus)) 323 if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus))
324 max_freq = notify_device->cpufreq_val; 324 max_freq = notify_device->cpufreq_val;
325 else
326 return 0;
325 327
326 /* Never exceed user_policy.max */ 328 /* Never exceed user_policy.max */
327 if (max_freq > policy->user_policy.max) 329 if (max_freq > policy->user_policy.max)
@@ -467,10 +469,10 @@ cpufreq_cooling_register(const struct cpumask *clip_cpus)
467 469
468 cool_dev = thermal_cooling_device_register(dev_name, cpufreq_dev, 470 cool_dev = thermal_cooling_device_register(dev_name, cpufreq_dev,
469 &cpufreq_cooling_ops); 471 &cpufreq_cooling_ops);
470 if (!cool_dev) { 472 if (IS_ERR(cool_dev)) {
471 release_idr(&cpufreq_idr, cpufreq_dev->id); 473 release_idr(&cpufreq_idr, cpufreq_dev->id);
472 kfree(cpufreq_dev); 474 kfree(cpufreq_dev);
473 return ERR_PTR(-EINVAL); 475 return cool_dev;
474 } 476 }
475 cpufreq_dev->cool_dev = cool_dev; 477 cpufreq_dev->cool_dev = cool_dev;
476 cpufreq_dev->cpufreq_state = 0; 478 cpufreq_dev->cpufreq_state = 0;
@@ -496,8 +498,12 @@ EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
496 */ 498 */
497void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 499void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
498{ 500{
499 struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata; 501 struct cpufreq_cooling_device *cpufreq_dev;
502
503 if (!cdev)
504 return;
500 505
506 cpufreq_dev = cdev->devdata;
501 mutex_lock(&cooling_cpufreq_lock); 507 mutex_lock(&cooling_cpufreq_lock);
502 cpufreq_dev_count--; 508 cpufreq_dev_count--;
503 509
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/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c
index b40b37cd25e0..8f181b3f842b 100644
--- a/drivers/thermal/intel_powerclamp.c
+++ b/drivers/thermal/intel_powerclamp.c
@@ -675,6 +675,11 @@ static const struct x86_cpu_id intel_powerclamp_ids[] = {
675 { X86_VENDOR_INTEL, 6, 0x2e}, 675 { X86_VENDOR_INTEL, 6, 0x2e},
676 { X86_VENDOR_INTEL, 6, 0x2f}, 676 { X86_VENDOR_INTEL, 6, 0x2f},
677 { X86_VENDOR_INTEL, 6, 0x3a}, 677 { X86_VENDOR_INTEL, 6, 0x3a},
678 { X86_VENDOR_INTEL, 6, 0x3c},
679 { X86_VENDOR_INTEL, 6, 0x3e},
680 { X86_VENDOR_INTEL, 6, 0x3f},
681 { X86_VENDOR_INTEL, 6, 0x45},
682 { X86_VENDOR_INTEL, 6, 0x46},
678 {} 683 {}
679}; 684};
680MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids); 685MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids);
@@ -758,21 +763,39 @@ static int powerclamp_init(void)
758 /* probe cpu features and ids here */ 763 /* probe cpu features and ids here */
759 retval = powerclamp_probe(); 764 retval = powerclamp_probe();
760 if (retval) 765 if (retval)
761 return retval; 766 goto exit_free;
767
762 /* set default limit, maybe adjusted during runtime based on feedback */ 768 /* set default limit, maybe adjusted during runtime based on feedback */
763 window_size = 2; 769 window_size = 2;
764 register_hotcpu_notifier(&powerclamp_cpu_notifier); 770 register_hotcpu_notifier(&powerclamp_cpu_notifier);
771
765 powerclamp_thread = alloc_percpu(struct task_struct *); 772 powerclamp_thread = alloc_percpu(struct task_struct *);
773 if (!powerclamp_thread) {
774 retval = -ENOMEM;
775 goto exit_unregister;
776 }
777
766 cooling_dev = thermal_cooling_device_register("intel_powerclamp", NULL, 778 cooling_dev = thermal_cooling_device_register("intel_powerclamp", NULL,
767 &powerclamp_cooling_ops); 779 &powerclamp_cooling_ops);
768 if (IS_ERR(cooling_dev)) 780 if (IS_ERR(cooling_dev)) {
769 return -ENODEV; 781 retval = -ENODEV;
782 goto exit_free_thread;
783 }
770 784
771 if (!duration) 785 if (!duration)
772 duration = jiffies_to_msecs(DEFAULT_DURATION_JIFFIES); 786 duration = jiffies_to_msecs(DEFAULT_DURATION_JIFFIES);
787
773 powerclamp_create_debug_files(); 788 powerclamp_create_debug_files();
774 789
775 return 0; 790 return 0;
791
792exit_free_thread:
793 free_percpu(powerclamp_thread);
794exit_unregister:
795 unregister_hotcpu_notifier(&powerclamp_cpu_notifier);
796exit_free:
797 kfree(cpu_clamping_mask);
798 return retval;
776} 799}
777module_init(powerclamp_init); 800module_init(powerclamp_init);
778 801
diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
new file mode 100644
index 000000000000..f760389a204c
--- /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 && OF
4 help
5 If you say yes here you get support for the TMU (Thermal Management
6 Unit) driver for SAMSUNG EXYNOS series of SoCs. This driver initialises
7 the TMU, reports temperature and handles cooling action if defined.
8 This driver uses the Exynos core thermal APIs and TMU configuration
9 data from the supported SoCs.
10
11config EXYNOS_THERMAL_CORE
12 bool "Core thermal framework support for EXYNOS SOCs"
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 APIs.
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..c2301da08ac7
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -0,0 +1,430 @@
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(&thermal->device,
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(&thermal->device,
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(&thermal->device,
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
314 if (th_zone->bind == false) {
315 for (i = 0; i < th_zone->cool_dev_size; i++) {
316 if (!th_zone->cool_dev[i])
317 continue;
318 exynos_bind(th_zone->therm_dev,
319 th_zone->cool_dev[i]);
320 }
321 }
322
323 thermal_zone_device_update(th_zone->therm_dev);
324
325 mutex_lock(&th_zone->therm_dev->lock);
326 /* Find the level for which trip happened */
327 for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
328 if (th_zone->therm_dev->last_temperature <
329 th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
330 break;
331 }
332
333 if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
334 !th_zone->sensor_conf->trip_data.trigger_falling) {
335 if (i > 0)
336 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
337 else
338 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
339 }
340
341 snprintf(data, sizeof(data), "%u", i);
342 kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
343 mutex_unlock(&th_zone->therm_dev->lock);
344}
345
346/* Register with the in-kernel thermal management */
347int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
348{
349 int ret;
350 struct cpumask mask_val;
351 struct exynos_thermal_zone *th_zone;
352
353 if (!sensor_conf || !sensor_conf->read_temperature) {
354 pr_err("Temperature sensor not initialised\n");
355 return -EINVAL;
356 }
357
358 th_zone = devm_kzalloc(sensor_conf->dev,
359 sizeof(struct exynos_thermal_zone), GFP_KERNEL);
360 if (!th_zone)
361 return -ENOMEM;
362
363 th_zone->sensor_conf = sensor_conf;
364 /*
365 * TODO: 1) Handle multiple cooling devices in a thermal zone
366 * 2) Add a flag/name in cooling info to map to specific
367 * sensor
368 */
369 if (sensor_conf->cooling_data.freq_clip_count > 0) {
370 cpumask_set_cpu(0, &mask_val);
371 th_zone->cool_dev[th_zone->cool_dev_size] =
372 cpufreq_cooling_register(&mask_val);
373 if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) {
374 dev_err(sensor_conf->dev,
375 "Failed to register cpufreq cooling device\n");
376 ret = -EINVAL;
377 goto err_unregister;
378 }
379 th_zone->cool_dev_size++;
380 }
381
382 th_zone->therm_dev = thermal_zone_device_register(
383 sensor_conf->name, sensor_conf->trip_data.trip_count,
384 0, th_zone, &exynos_dev_ops, NULL, 0,
385 sensor_conf->trip_data.trigger_falling ? 0 :
386 IDLE_INTERVAL);
387
388 if (IS_ERR(th_zone->therm_dev)) {
389 dev_err(sensor_conf->dev,
390 "Failed to register thermal zone device\n");
391 ret = PTR_ERR(th_zone->therm_dev);
392 goto err_unregister;
393 }
394 th_zone->mode = THERMAL_DEVICE_ENABLED;
395 sensor_conf->pzone_data = th_zone;
396
397 dev_info(sensor_conf->dev,
398 "Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
399
400 return 0;
401
402err_unregister:
403 exynos_unregister_thermal(sensor_conf);
404 return ret;
405}
406
407/* Un-Register with the in-kernel thermal management */
408void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf)
409{
410 int i;
411 struct exynos_thermal_zone *th_zone;
412
413 if (!sensor_conf || !sensor_conf->pzone_data) {
414 pr_err("Invalid temperature sensor configuration data\n");
415 return;
416 }
417
418 th_zone = sensor_conf->pzone_data;
419
420 if (th_zone->therm_dev)
421 thermal_zone_device_unregister(th_zone->therm_dev);
422
423 for (i = 0; i < th_zone->cool_dev_size; i++) {
424 if (th_zone->cool_dev[i])
425 cpufreq_cooling_unregister(th_zone->cool_dev[i]);
426 }
427
428 dev_info(sensor_conf->dev,
429 "Exynos: Kernel Thermal management unregistered\n");
430}
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..32f38b90c4f6
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -0,0 +1,766 @@
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->test_mux)
321 con |= (pdata->test_mux << reg->test_mux_addr_shift);
322
323 if (pdata->reference_voltage) {
324 con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
325 con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
326 }
327
328 if (pdata->gain) {
329 con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
330 con |= (pdata->gain << reg->buf_slope_sel_shift);
331 }
332
333 if (pdata->noise_cancel_mode) {
334 con &= ~(reg->therm_trip_mode_mask <<
335 reg->therm_trip_mode_shift);
336 con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
337 }
338
339 if (pdata->cal_mode == HW_MODE) {
340 con &= ~(reg->calib_mode_mask << reg->calib_mode_shift);
341 cal_val = 0;
342 switch (pdata->cal_type) {
343 case TYPE_TWO_POINT_TRIMMING:
344 cal_val = 3;
345 break;
346 case TYPE_ONE_POINT_TRIMMING_85:
347 cal_val = 2;
348 break;
349 case TYPE_ONE_POINT_TRIMMING_25:
350 cal_val = 1;
351 break;
352 case TYPE_NONE:
353 break;
354 default:
355 dev_err(&pdev->dev, "Invalid calibration type, using none\n");
356 }
357 con |= cal_val << reg->calib_mode_shift;
358 }
359
360 if (on) {
361 con |= (1 << reg->core_en_shift);
362 interrupt_en =
363 pdata->trigger_enable[3] << reg->inten_rise3_shift |
364 pdata->trigger_enable[2] << reg->inten_rise2_shift |
365 pdata->trigger_enable[1] << reg->inten_rise1_shift |
366 pdata->trigger_enable[0] << reg->inten_rise0_shift;
367 if (TMU_SUPPORTS(pdata, FALLING_TRIP))
368 interrupt_en |=
369 interrupt_en << reg->inten_fall0_shift;
370 } else {
371 con &= ~(1 << reg->core_en_shift);
372 interrupt_en = 0; /* Disable all interrupts */
373 }
374 writel(interrupt_en, data->base + reg->tmu_inten);
375 writel(con, data->base + reg->tmu_ctrl);
376
377 clk_disable(data->clk);
378 mutex_unlock(&data->lock);
379}
380
381static int exynos_tmu_read(struct exynos_tmu_data *data)
382{
383 struct exynos_tmu_platform_data *pdata = data->pdata;
384 const struct exynos_tmu_registers *reg = pdata->registers;
385 u8 temp_code;
386 int temp;
387
388 mutex_lock(&data->lock);
389 clk_enable(data->clk);
390
391 temp_code = readb(data->base + reg->tmu_cur_temp);
392 temp = code_to_temp(data, temp_code);
393
394 clk_disable(data->clk);
395 mutex_unlock(&data->lock);
396
397 return temp;
398}
399
400#ifdef CONFIG_THERMAL_EMULATION
401static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
402{
403 struct exynos_tmu_data *data = drv_data;
404 struct exynos_tmu_platform_data *pdata = data->pdata;
405 const struct exynos_tmu_registers *reg = pdata->registers;
406 unsigned int val;
407 int ret = -EINVAL;
408
409 if (!TMU_SUPPORTS(pdata, EMULATION))
410 goto out;
411
412 if (temp && temp < MCELSIUS)
413 goto out;
414
415 mutex_lock(&data->lock);
416 clk_enable(data->clk);
417
418 val = readl(data->base + reg->emul_con);
419
420 if (temp) {
421 temp /= MCELSIUS;
422
423 if (TMU_SUPPORTS(pdata, EMUL_TIME)) {
424 val &= ~(EXYNOS_EMUL_TIME_MASK << reg->emul_time_shift);
425 val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
426 }
427 val &= ~(EXYNOS_EMUL_DATA_MASK << reg->emul_temp_shift);
428 val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
429 EXYNOS_EMUL_ENABLE;
430 } else {
431 val &= ~EXYNOS_EMUL_ENABLE;
432 }
433
434 writel(val, data->base + reg->emul_con);
435
436 clk_disable(data->clk);
437 mutex_unlock(&data->lock);
438 return 0;
439out:
440 return ret;
441}
442#else
443static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
444 { return -EINVAL; }
445#endif/*CONFIG_THERMAL_EMULATION*/
446
447static void exynos_tmu_work(struct work_struct *work)
448{
449 struct exynos_tmu_data *data = container_of(work,
450 struct exynos_tmu_data, irq_work);
451 struct exynos_tmu_platform_data *pdata = data->pdata;
452 const struct exynos_tmu_registers *reg = pdata->registers;
453 unsigned int val_irq, val_type;
454
455 /* Find which sensor generated this interrupt */
456 if (reg->tmu_irqstatus) {
457 val_type = readl(data->base_common + reg->tmu_irqstatus);
458 if (!((val_type >> data->id) & 0x1))
459 goto out;
460 }
461
462 exynos_report_trigger(data->reg_conf);
463 mutex_lock(&data->lock);
464 clk_enable(data->clk);
465
466 /* TODO: take action based on particular interrupt */
467 val_irq = readl(data->base + reg->tmu_intstat);
468 /* clear the interrupts */
469 writel(val_irq, data->base + reg->tmu_intclear);
470
471 clk_disable(data->clk);
472 mutex_unlock(&data->lock);
473out:
474 enable_irq(data->irq);
475}
476
477static irqreturn_t exynos_tmu_irq(int irq, void *id)
478{
479 struct exynos_tmu_data *data = id;
480
481 disable_irq_nosync(irq);
482 schedule_work(&data->irq_work);
483
484 return IRQ_HANDLED;
485}
486
487static const struct of_device_id exynos_tmu_match[] = {
488 {
489 .compatible = "samsung,exynos4210-tmu",
490 .data = (void *)EXYNOS4210_TMU_DRV_DATA,
491 },
492 {
493 .compatible = "samsung,exynos4412-tmu",
494 .data = (void *)EXYNOS4412_TMU_DRV_DATA,
495 },
496 {
497 .compatible = "samsung,exynos5250-tmu",
498 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
499 },
500 {
501 .compatible = "samsung,exynos5440-tmu",
502 .data = (void *)EXYNOS5440_TMU_DRV_DATA,
503 },
504 {},
505};
506MODULE_DEVICE_TABLE(of, exynos_tmu_match);
507
508static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
509 struct platform_device *pdev, int id)
510{
511 struct exynos_tmu_init_data *data_table;
512 struct exynos_tmu_platform_data *tmu_data;
513 const struct of_device_id *match;
514
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
525static int exynos_map_dt_data(struct platform_device *pdev)
526{
527 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
528 struct exynos_tmu_platform_data *pdata;
529 struct resource res;
530 int ret;
531
532 if (!data || !pdev->dev.of_node)
533 return -ENODEV;
534
535 /*
536 * Try enabling the regulator if found
537 * TODO: Add regulator as an SOC feature, so that regulator enable
538 * is a compulsory call.
539 */
540 data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
541 if (!IS_ERR(data->regulator)) {
542 ret = regulator_enable(data->regulator);
543 if (ret) {
544 dev_err(&pdev->dev, "failed to enable vtmu\n");
545 return ret;
546 }
547 } else {
548 dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
549 }
550
551 data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
552 if (data->id < 0)
553 data->id = 0;
554
555 data->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
556 if (data->irq <= 0) {
557 dev_err(&pdev->dev, "failed to get IRQ\n");
558 return -ENODEV;
559 }
560
561 if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
562 dev_err(&pdev->dev, "failed to get Resource 0\n");
563 return -ENODEV;
564 }
565
566 data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
567 if (!data->base) {
568 dev_err(&pdev->dev, "Failed to ioremap memory\n");
569 return -EADDRNOTAVAIL;
570 }
571
572 pdata = exynos_get_driver_data(pdev, data->id);
573 if (!pdata) {
574 dev_err(&pdev->dev, "No platform init data supplied.\n");
575 return -ENODEV;
576 }
577 data->pdata = pdata;
578 /*
579 * Check if the TMU shares some registers and then try to map the
580 * memory of common registers.
581 */
582 if (!TMU_SUPPORTS(pdata, SHARED_MEMORY))
583 return 0;
584
585 if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
586 dev_err(&pdev->dev, "failed to get Resource 1\n");
587 return -ENODEV;
588 }
589
590 data->base_common = devm_ioremap(&pdev->dev, res.start,
591 resource_size(&res));
592 if (!data->base_common) {
593 dev_err(&pdev->dev, "Failed to ioremap memory\n");
594 return -ENOMEM;
595 }
596
597 return 0;
598}
599
600static int exynos_tmu_probe(struct platform_device *pdev)
601{
602 struct exynos_tmu_data *data;
603 struct exynos_tmu_platform_data *pdata;
604 struct thermal_sensor_conf *sensor_conf;
605 int ret, i;
606
607 data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
608 GFP_KERNEL);
609 if (!data) {
610 dev_err(&pdev->dev, "Failed to allocate driver structure\n");
611 return -ENOMEM;
612 }
613
614 platform_set_drvdata(pdev, data);
615 mutex_init(&data->lock);
616
617 ret = exynos_map_dt_data(pdev);
618 if (ret)
619 return ret;
620
621 pdata = data->pdata;
622
623 INIT_WORK(&data->irq_work, exynos_tmu_work);
624
625 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
626 if (IS_ERR(data->clk)) {
627 dev_err(&pdev->dev, "Failed to get clock\n");
628 return PTR_ERR(data->clk);
629 }
630
631 ret = clk_prepare(data->clk);
632 if (ret)
633 return ret;
634
635 if (pdata->type == SOC_ARCH_EXYNOS4210 ||
636 pdata->type == SOC_ARCH_EXYNOS4412 ||
637 pdata->type == SOC_ARCH_EXYNOS5250 ||
638 pdata->type == SOC_ARCH_EXYNOS5440)
639 data->soc = pdata->type;
640 else {
641 ret = -EINVAL;
642 dev_err(&pdev->dev, "Platform not supported\n");
643 goto err_clk;
644 }
645
646 ret = exynos_tmu_initialize(pdev);
647 if (ret) {
648 dev_err(&pdev->dev, "Failed to initialize TMU\n");
649 goto err_clk;
650 }
651
652 exynos_tmu_control(pdev, true);
653
654 /* Allocate a structure to register with the exynos core thermal */
655 sensor_conf = devm_kzalloc(&pdev->dev,
656 sizeof(struct thermal_sensor_conf), GFP_KERNEL);
657 if (!sensor_conf) {
658 dev_err(&pdev->dev, "Failed to allocate registration struct\n");
659 ret = -ENOMEM;
660 goto err_clk;
661 }
662 sprintf(sensor_conf->name, "therm_zone%d", data->id);
663 sensor_conf->read_temperature = (int (*)(void *))exynos_tmu_read;
664 sensor_conf->write_emul_temp =
665 (int (*)(void *, unsigned long))exynos_tmu_set_emulation;
666 sensor_conf->driver_data = data;
667 sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
668 pdata->trigger_enable[1] + pdata->trigger_enable[2]+
669 pdata->trigger_enable[3];
670
671 for (i = 0; i < sensor_conf->trip_data.trip_count; i++) {
672 sensor_conf->trip_data.trip_val[i] =
673 pdata->threshold + pdata->trigger_levels[i];
674 sensor_conf->trip_data.trip_type[i] =
675 pdata->trigger_type[i];
676 }
677
678 sensor_conf->trip_data.trigger_falling = pdata->threshold_falling;
679
680 sensor_conf->cooling_data.freq_clip_count = pdata->freq_tab_count;
681 for (i = 0; i < pdata->freq_tab_count; i++) {
682 sensor_conf->cooling_data.freq_data[i].freq_clip_max =
683 pdata->freq_tab[i].freq_clip_max;
684 sensor_conf->cooling_data.freq_data[i].temp_level =
685 pdata->freq_tab[i].temp_level;
686 }
687 sensor_conf->dev = &pdev->dev;
688 /* Register the sensor with thermal management interface */
689 ret = exynos_register_thermal(sensor_conf);
690 if (ret) {
691 dev_err(&pdev->dev, "Failed to register thermal interface\n");
692 goto err_clk;
693 }
694 data->reg_conf = sensor_conf;
695
696 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
697 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
698 if (ret) {
699 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
700 goto err_clk;
701 }
702
703 return 0;
704err_clk:
705 clk_unprepare(data->clk);
706 return ret;
707}
708
709static int exynos_tmu_remove(struct platform_device *pdev)
710{
711 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
712
713 exynos_tmu_control(pdev, false);
714
715 exynos_unregister_thermal(data->reg_conf);
716
717 clk_unprepare(data->clk);
718
719 if (!IS_ERR(data->regulator))
720 regulator_disable(data->regulator);
721
722 return 0;
723}
724
725#ifdef CONFIG_PM_SLEEP
726static int exynos_tmu_suspend(struct device *dev)
727{
728 exynos_tmu_control(to_platform_device(dev), false);
729
730 return 0;
731}
732
733static int exynos_tmu_resume(struct device *dev)
734{
735 struct platform_device *pdev = to_platform_device(dev);
736
737 exynos_tmu_initialize(pdev);
738 exynos_tmu_control(pdev, true);
739
740 return 0;
741}
742
743static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
744 exynos_tmu_suspend, exynos_tmu_resume);
745#define EXYNOS_TMU_PM (&exynos_tmu_pm)
746#else
747#define EXYNOS_TMU_PM NULL
748#endif
749
750static struct platform_driver exynos_tmu_driver = {
751 .driver = {
752 .name = "exynos-tmu",
753 .owner = THIS_MODULE,
754 .pm = EXYNOS_TMU_PM,
755 .of_match_table = exynos_tmu_match,
756 },
757 .probe = exynos_tmu_probe,
758 .remove = exynos_tmu_remove,
759};
760
761module_platform_driver(exynos_tmu_driver);
762
763MODULE_DESCRIPTION("EXYNOS TMU Driver");
764MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
765MODULE_LICENSE("GPL");
766MODULE_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..3fb65547e64c
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -0,0 +1,316 @@
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_EXYNOS4412,
45 SOC_ARCH_EXYNOS5250,
46 SOC_ARCH_EXYNOS5440,
47};
48
49/**
50 * EXYNOS TMU supported features.
51 * TMU_SUPPORT_EMULATION - This features is used to set user defined
52 * temperature to the TMU controller.
53 * TMU_SUPPORT_MULTI_INST - This features denotes that the soc
54 * has many instances of TMU.
55 * TMU_SUPPORT_TRIM_RELOAD - This features shows that trimming can
56 * be reloaded.
57 * TMU_SUPPORT_FALLING_TRIP - This features shows that interrupt can
58 * be registered for falling trips also.
59 * TMU_SUPPORT_READY_STATUS - This feature tells that the TMU current
60 * state(active/idle) can be checked.
61 * TMU_SUPPORT_EMUL_TIME - This features allows to set next temp emulation
62 * sample time.
63 * TMU_SUPPORT_SHARED_MEMORY - This feature tells that the different TMU
64 * sensors shares some common registers.
65 * TMU_SUPPORT - macro to compare the above features with the supplied.
66 */
67#define TMU_SUPPORT_EMULATION BIT(0)
68#define TMU_SUPPORT_MULTI_INST BIT(1)
69#define TMU_SUPPORT_TRIM_RELOAD BIT(2)
70#define TMU_SUPPORT_FALLING_TRIP BIT(3)
71#define TMU_SUPPORT_READY_STATUS BIT(4)
72#define TMU_SUPPORT_EMUL_TIME BIT(5)
73#define TMU_SUPPORT_SHARED_MEMORY BIT(6)
74
75#define TMU_SUPPORTS(a, b) (a->features & TMU_SUPPORT_ ## b)
76
77/**
78 * struct exynos_tmu_register - register descriptors to access registers and
79 * bitfields. The register validity, offsets and bitfield values may vary
80 * slightly across different exynos SOC's.
81 * @triminfo_data: register containing 2 pont trimming data
82 * @triminfo_25_shift: shift bit of the 25 C trim value in triminfo_data reg.
83 * @triminfo_85_shift: shift bit of the 85 C trim value in triminfo_data reg.
84 * @triminfo_ctrl: trim info controller register.
85 * @triminfo_reload_shift: shift of triminfo reload enable bit in triminfo_ctrl
86 reg.
87 * @tmu_ctrl: TMU main controller register.
88 * @test_mux_addr_shift: shift bits of test mux address.
89 * @buf_vref_sel_shift: shift bits of reference voltage in tmu_ctrl register.
90 * @buf_vref_sel_mask: mask bits of reference voltage in tmu_ctrl register.
91 * @therm_trip_mode_shift: shift bits of tripping mode in tmu_ctrl register.
92 * @therm_trip_mode_mask: mask bits of tripping mode in tmu_ctrl register.
93 * @therm_trip_en_shift: shift bits of tripping enable in tmu_ctrl register.
94 * @buf_slope_sel_shift: shift bits of amplifier gain value in tmu_ctrl
95 register.
96 * @buf_slope_sel_mask: mask bits of amplifier gain value in tmu_ctrl register.
97 * @calib_mode_shift: shift bits of calibration mode value in tmu_ctrl
98 register.
99 * @calib_mode_mask: mask bits of calibration mode value in tmu_ctrl
100 register.
101 * @therm_trip_tq_en_shift: shift bits of thermal trip enable by TQ pin in
102 tmu_ctrl register.
103 * @core_en_shift: shift bits of TMU core enable bit in tmu_ctrl register.
104 * @tmu_status: register drescribing the TMU status.
105 * @tmu_cur_temp: register containing the current temperature of the TMU.
106 * @tmu_cur_temp_shift: shift bits of current temp value in tmu_cur_temp
107 register.
108 * @threshold_temp: register containing the base threshold level.
109 * @threshold_th0: Register containing first set of rising levels.
110 * @threshold_th0_l0_shift: shift bits of level0 threshold temperature.
111 * @threshold_th0_l1_shift: shift bits of level1 threshold temperature.
112 * @threshold_th0_l2_shift: shift bits of level2 threshold temperature.
113 * @threshold_th0_l3_shift: shift bits of level3 threshold temperature.
114 * @threshold_th1: Register containing second set of rising levels.
115 * @threshold_th1_l0_shift: shift bits of level0 threshold temperature.
116 * @threshold_th1_l1_shift: shift bits of level1 threshold temperature.
117 * @threshold_th1_l2_shift: shift bits of level2 threshold temperature.
118 * @threshold_th1_l3_shift: shift bits of level3 threshold temperature.
119 * @threshold_th2: Register containing third set of rising levels.
120 * @threshold_th2_l0_shift: shift bits of level0 threshold temperature.
121 * @threshold_th3: Register containing fourth set of rising levels.
122 * @threshold_th3_l0_shift: shift bits of level0 threshold temperature.
123 * @tmu_inten: register containing the different threshold interrupt
124 enable bits.
125 * @inten_rise_shift: shift bits of all rising interrupt bits.
126 * @inten_rise_mask: mask bits of all rising interrupt bits.
127 * @inten_fall_shift: shift bits of all rising interrupt bits.
128 * @inten_fall_mask: mask bits of all rising interrupt bits.
129 * @inten_rise0_shift: shift bits of rising 0 interrupt bits.
130 * @inten_rise1_shift: shift bits of rising 1 interrupt bits.
131 * @inten_rise2_shift: shift bits of rising 2 interrupt bits.
132 * @inten_rise3_shift: shift bits of rising 3 interrupt bits.
133 * @inten_fall0_shift: shift bits of falling 0 interrupt bits.
134 * @inten_fall1_shift: shift bits of falling 1 interrupt bits.
135 * @inten_fall2_shift: shift bits of falling 2 interrupt bits.
136 * @inten_fall3_shift: shift bits of falling 3 interrupt bits.
137 * @tmu_intstat: Register containing the interrupt status values.
138 * @tmu_intclear: Register for clearing the raised interrupt status.
139 * @emul_con: TMU emulation controller register.
140 * @emul_temp_shift: shift bits of emulation temperature.
141 * @emul_time_shift: shift bits of emulation time.
142 * @emul_time_mask: mask bits of emulation time.
143 * @tmu_irqstatus: register to find which TMU generated interrupts.
144 * @tmu_pmin: register to get/set the Pmin value.
145 */
146struct exynos_tmu_registers {
147 u32 triminfo_data;
148 u32 triminfo_25_shift;
149 u32 triminfo_85_shift;
150
151 u32 triminfo_ctrl;
152 u32 triminfo_reload_shift;
153
154 u32 tmu_ctrl;
155 u32 test_mux_addr_shift;
156 u32 buf_vref_sel_shift;
157 u32 buf_vref_sel_mask;
158 u32 therm_trip_mode_shift;
159 u32 therm_trip_mode_mask;
160 u32 therm_trip_en_shift;
161 u32 buf_slope_sel_shift;
162 u32 buf_slope_sel_mask;
163 u32 calib_mode_shift;
164 u32 calib_mode_mask;
165 u32 therm_trip_tq_en_shift;
166 u32 core_en_shift;
167
168 u32 tmu_status;
169
170 u32 tmu_cur_temp;
171 u32 tmu_cur_temp_shift;
172
173 u32 threshold_temp;
174
175 u32 threshold_th0;
176 u32 threshold_th0_l0_shift;
177 u32 threshold_th0_l1_shift;
178 u32 threshold_th0_l2_shift;
179 u32 threshold_th0_l3_shift;
180
181 u32 threshold_th1;
182 u32 threshold_th1_l0_shift;
183 u32 threshold_th1_l1_shift;
184 u32 threshold_th1_l2_shift;
185 u32 threshold_th1_l3_shift;
186
187 u32 threshold_th2;
188 u32 threshold_th2_l0_shift;
189
190 u32 threshold_th3;
191 u32 threshold_th3_l0_shift;
192
193 u32 tmu_inten;
194 u32 inten_rise_shift;
195 u32 inten_rise_mask;
196 u32 inten_fall_shift;
197 u32 inten_fall_mask;
198 u32 inten_rise0_shift;
199 u32 inten_rise1_shift;
200 u32 inten_rise2_shift;
201 u32 inten_rise3_shift;
202 u32 inten_fall0_shift;
203 u32 inten_fall1_shift;
204 u32 inten_fall2_shift;
205 u32 inten_fall3_shift;
206
207 u32 tmu_intstat;
208
209 u32 tmu_intclear;
210
211 u32 emul_con;
212 u32 emul_temp_shift;
213 u32 emul_time_shift;
214 u32 emul_time_mask;
215
216 u32 tmu_irqstatus;
217 u32 tmu_pmin;
218};
219
220/**
221 * struct exynos_tmu_platform_data
222 * @threshold: basic temperature for generating interrupt
223 * 25 <= threshold <= 125 [unit: degree Celsius]
224 * @threshold_falling: differntial value for setting threshold
225 * of temperature falling interrupt.
226 * @trigger_levels: array for each interrupt levels
227 * [unit: degree Celsius]
228 * 0: temperature for trigger_level0 interrupt
229 * condition for trigger_level0 interrupt:
230 * current temperature > threshold + trigger_levels[0]
231 * 1: temperature for trigger_level1 interrupt
232 * condition for trigger_level1 interrupt:
233 * current temperature > threshold + trigger_levels[1]
234 * 2: temperature for trigger_level2 interrupt
235 * condition for trigger_level2 interrupt:
236 * current temperature > threshold + trigger_levels[2]
237 * 3: temperature for trigger_level3 interrupt
238 * condition for trigger_level3 interrupt:
239 * current temperature > threshold + trigger_levels[3]
240 * @trigger_type: defines the type of trigger. Possible values are,
241 * THROTTLE_ACTIVE trigger type
242 * THROTTLE_PASSIVE trigger type
243 * SW_TRIP trigger type
244 * HW_TRIP
245 * @trigger_enable[]: array to denote which trigger levels are enabled.
246 * 1 = enable trigger_level[] interrupt,
247 * 0 = disable trigger_level[] interrupt
248 * @max_trigger_level: max trigger level supported by the TMU
249 * @gain: gain of amplifier in the positive-TC generator block
250 * 0 <= gain <= 15
251 * @reference_voltage: reference voltage of amplifier
252 * in the positive-TC generator block
253 * 0 <= reference_voltage <= 31
254 * @noise_cancel_mode: noise cancellation mode
255 * 000, 100, 101, 110 and 111 can be different modes
256 * @type: determines the type of SOC
257 * @efuse_value: platform defined fuse value
258 * @min_efuse_value: minimum valid trimming data
259 * @max_efuse_value: maximum valid trimming data
260 * @first_point_trim: temp value of the first point trimming
261 * @second_point_trim: temp value of the second point trimming
262 * @default_temp_offset: default temperature offset in case of no trimming
263 * @test_mux; information if SoC supports test MUX
264 * @cal_type: calibration type for temperature
265 * @cal_mode: calibration mode for temperature
266 * @freq_clip_table: Table representing frequency reduction percentage.
267 * @freq_tab_count: Count of the above table as frequency reduction may
268 * applicable to only some of the trigger levels.
269 * @registers: Pointer to structure containing all the TMU controller registers
270 * and bitfields shifts and masks.
271 * @features: a bitfield value indicating the features supported in SOC like
272 * emulation, multi instance etc
273 *
274 * This structure is required for configuration of exynos_tmu driver.
275 */
276struct exynos_tmu_platform_data {
277 u8 threshold;
278 u8 threshold_falling;
279 u8 trigger_levels[MAX_TRIP_COUNT];
280 enum trigger_type trigger_type[MAX_TRIP_COUNT];
281 bool trigger_enable[MAX_TRIP_COUNT];
282 u8 max_trigger_level;
283 u8 gain;
284 u8 reference_voltage;
285 u8 noise_cancel_mode;
286
287 u32 efuse_value;
288 u32 min_efuse_value;
289 u32 max_efuse_value;
290 u8 first_point_trim;
291 u8 second_point_trim;
292 u8 default_temp_offset;
293 u8 test_mux;
294
295 enum calibration_type cal_type;
296 enum calibration_mode cal_mode;
297 enum soc_type type;
298 struct freq_clip_table freq_tab[4];
299 unsigned int freq_tab_count;
300 const struct exynos_tmu_registers *registers;
301 unsigned int features;
302};
303
304/**
305 * struct exynos_tmu_init_data
306 * @tmu_count: number of TMU instances.
307 * @tmu_data: platform data of all TMU instances.
308 * This structure is required to store data for multi-instance exynos tmu
309 * driver.
310 */
311struct exynos_tmu_init_data {
312 int tmu_count;
313 struct exynos_tmu_platform_data tmu_data[];
314};
315
316#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..073c292baa53
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -0,0 +1,268 @@
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_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
94static const struct exynos_tmu_registers exynos4412_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 .test_mux_addr_shift = EXYNOS4412_MUX_ADDR_SHIFT,
102 .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
103 .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
104 .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
105 .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
106 .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
107 .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
108 .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
109 .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
110 .tmu_status = EXYNOS_TMU_REG_STATUS,
111 .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
112 .threshold_th0 = EXYNOS_THD_TEMP_RISE,
113 .threshold_th1 = EXYNOS_THD_TEMP_FALL,
114 .tmu_inten = EXYNOS_TMU_REG_INTEN,
115 .inten_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
116 .inten_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
117 .inten_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
118 .inten_fall_shift = EXYNOS_TMU_FALL_INT_SHIFT,
119 .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
120 .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
121 .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
122 .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
123 .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
124 .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
125 .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
126 .emul_con = EXYNOS_EMUL_CON,
127 .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
128 .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
129 .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
130};
131
132#define EXYNOS4412_TMU_DATA \
133 .threshold_falling = 10, \
134 .trigger_levels[0] = 85, \
135 .trigger_levels[1] = 103, \
136 .trigger_levels[2] = 110, \
137 .trigger_levels[3] = 120, \
138 .trigger_enable[0] = true, \
139 .trigger_enable[1] = true, \
140 .trigger_enable[2] = true, \
141 .trigger_enable[3] = false, \
142 .trigger_type[0] = THROTTLE_ACTIVE, \
143 .trigger_type[1] = THROTTLE_ACTIVE, \
144 .trigger_type[2] = SW_TRIP, \
145 .trigger_type[3] = HW_TRIP, \
146 .max_trigger_level = 4, \
147 .gain = 8, \
148 .reference_voltage = 16, \
149 .noise_cancel_mode = 4, \
150 .cal_type = TYPE_ONE_POINT_TRIMMING, \
151 .efuse_value = 55, \
152 .min_efuse_value = 40, \
153 .max_efuse_value = 100, \
154 .first_point_trim = 25, \
155 .second_point_trim = 85, \
156 .default_temp_offset = 50, \
157 .freq_tab[0] = { \
158 .freq_clip_max = 800 * 1000, \
159 .temp_level = 85, \
160 }, \
161 .freq_tab[1] = { \
162 .freq_clip_max = 200 * 1000, \
163 .temp_level = 103, \
164 }, \
165 .freq_tab_count = 2, \
166 .registers = &exynos4412_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#endif
171
172#if defined(CONFIG_SOC_EXYNOS4412)
173struct exynos_tmu_init_data const exynos4412_default_tmu_data = {
174 .tmu_data = {
175 {
176 EXYNOS4412_TMU_DATA,
177 .type = SOC_ARCH_EXYNOS4412,
178 .test_mux = EXYNOS4412_MUX_ADDR_VALUE,
179 },
180 },
181 .tmu_count = 1,
182};
183#endif
184
185#if defined(CONFIG_SOC_EXYNOS5250)
186struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
187 .tmu_data = {
188 {
189 EXYNOS4412_TMU_DATA,
190 .type = SOC_ARCH_EXYNOS5250,
191 },
192 },
193 .tmu_count = 1,
194};
195#endif
196
197#if defined(CONFIG_SOC_EXYNOS5440)
198static const struct exynos_tmu_registers exynos5440_tmu_registers = {
199 .triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
200 .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
201 .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
202 .tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
203 .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
204 .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
205 .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
206 .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
207 .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
208 .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
209 .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
210 .calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT,
211 .calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK,
212 .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
213 .tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
214 .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
215 .threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
216 .threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
217 .threshold_th2 = EXYNOS5440_TMU_S0_7_TH2,
218 .threshold_th3_l0_shift = EXYNOS5440_TMU_TH_RISE4_SHIFT,
219 .tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
220 .inten_rise_mask = EXYNOS5440_TMU_RISE_INT_MASK,
221 .inten_rise_shift = EXYNOS5440_TMU_RISE_INT_SHIFT,
222 .inten_fall_mask = EXYNOS5440_TMU_FALL_INT_MASK,
223 .inten_fall_shift = EXYNOS5440_TMU_FALL_INT_SHIFT,
224 .inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
225 .inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,
226 .inten_rise2_shift = EXYNOS5440_TMU_INTEN_RISE2_SHIFT,
227 .inten_rise3_shift = EXYNOS5440_TMU_INTEN_RISE3_SHIFT,
228 .inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
229 .tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
230 .tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
231 .tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
232 .emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
233 .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
234 .tmu_pmin = EXYNOS5440_TMU_PMIN,
235};
236
237#define EXYNOS5440_TMU_DATA \
238 .trigger_levels[0] = 100, \
239 .trigger_levels[4] = 105, \
240 .trigger_enable[0] = 1, \
241 .trigger_type[0] = SW_TRIP, \
242 .trigger_type[4] = HW_TRIP, \
243 .max_trigger_level = 5, \
244 .gain = 5, \
245 .reference_voltage = 16, \
246 .noise_cancel_mode = 4, \
247 .cal_type = TYPE_ONE_POINT_TRIMMING, \
248 .cal_mode = 0, \
249 .efuse_value = 0x5b2d, \
250 .min_efuse_value = 16, \
251 .max_efuse_value = 76, \
252 .first_point_trim = 25, \
253 .second_point_trim = 70, \
254 .default_temp_offset = 25, \
255 .type = SOC_ARCH_EXYNOS5440, \
256 .registers = &exynos5440_tmu_registers, \
257 .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
258 TMU_SUPPORT_MULTI_INST | TMU_SUPPORT_SHARED_MEMORY),
259
260struct exynos_tmu_init_data const exynos5440_default_tmu_data = {
261 .tmu_data = {
262 { EXYNOS5440_TMU_DATA } ,
263 { EXYNOS5440_TMU_DATA } ,
264 { EXYNOS5440_TMU_DATA } ,
265 },
266 .tmu_count = 3,
267};
268#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..a1ea19d9e0a6
--- /dev/null
+++ b/drivers/thermal/samsung/exynos_tmu_data.h
@@ -0,0 +1,166 @@
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/* Exynos4412 specific */
99#define EXYNOS4412_MUX_ADDR_VALUE 6
100#define EXYNOS4412_MUX_ADDR_SHIFT 20
101
102/*exynos5440 specific registers*/
103#define EXYNOS5440_TMU_S0_7_TRIM 0x000
104#define EXYNOS5440_TMU_S0_7_CTRL 0x020
105#define EXYNOS5440_TMU_S0_7_DEBUG 0x040
106#define EXYNOS5440_TMU_S0_7_STATUS 0x060
107#define EXYNOS5440_TMU_S0_7_TEMP 0x0f0
108#define EXYNOS5440_TMU_S0_7_TH0 0x110
109#define EXYNOS5440_TMU_S0_7_TH1 0x130
110#define EXYNOS5440_TMU_S0_7_TH2 0x150
111#define EXYNOS5440_TMU_S0_7_EVTEN 0x1F0
112#define EXYNOS5440_TMU_S0_7_IRQEN 0x210
113#define EXYNOS5440_TMU_S0_7_IRQ 0x230
114/* exynos5440 common registers */
115#define EXYNOS5440_TMU_IRQ_STATUS 0x000
116#define EXYNOS5440_TMU_PMIN 0x004
117#define EXYNOS5440_TMU_TEMP 0x008
118
119#define EXYNOS5440_TMU_RISE_INT_MASK 0xf
120#define EXYNOS5440_TMU_RISE_INT_SHIFT 0
121#define EXYNOS5440_TMU_FALL_INT_MASK 0xf
122#define EXYNOS5440_TMU_FALL_INT_SHIFT 4
123#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT 0
124#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT 1
125#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT 2
126#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT 3
127#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT 4
128#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT 5
129#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT 6
130#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT 7
131#define EXYNOS5440_TMU_TH_RISE0_SHIFT 0
132#define EXYNOS5440_TMU_TH_RISE1_SHIFT 8
133#define EXYNOS5440_TMU_TH_RISE2_SHIFT 16
134#define EXYNOS5440_TMU_TH_RISE3_SHIFT 24
135#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
136#define EXYNOS5440_EFUSE_SWAP_OFFSET 8
137
138#if defined(CONFIG_CPU_EXYNOS4210)
139extern struct exynos_tmu_init_data const exynos4210_default_tmu_data;
140#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
141#else
142#define EXYNOS4210_TMU_DRV_DATA (NULL)
143#endif
144
145#if defined(CONFIG_SOC_EXYNOS4412)
146extern struct exynos_tmu_init_data const exynos4412_default_tmu_data;
147#define EXYNOS4412_TMU_DRV_DATA (&exynos4412_default_tmu_data)
148#else
149#define EXYNOS4412_TMU_DRV_DATA (NULL)
150#endif
151
152#if defined(CONFIG_SOC_EXYNOS5250)
153extern struct exynos_tmu_init_data const exynos5250_default_tmu_data;
154#define EXYNOS5250_TMU_DRV_DATA (&exynos5250_default_tmu_data)
155#else
156#define EXYNOS5250_TMU_DRV_DATA (NULL)
157#endif
158
159#if defined(CONFIG_SOC_EXYNOS5440)
160extern struct exynos_tmu_init_data const exynos5440_default_tmu_data;
161#define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data)
162#else
163#define EXYNOS5440_TMU_DRV_DATA (NULL)
164#endif
165
166#endif /*_EXYNOS_TMU_DATA_H*/
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
index 4d4ddae1a991..d89e781b0a18 100644
--- a/drivers/thermal/step_wise.c
+++ b/drivers/thermal/step_wise.c
@@ -51,44 +51,51 @@ static unsigned long get_target_state(struct thermal_instance *instance,
51{ 51{
52 struct thermal_cooling_device *cdev = instance->cdev; 52 struct thermal_cooling_device *cdev = instance->cdev;
53 unsigned long cur_state; 53 unsigned long cur_state;
54 unsigned long next_target;
54 55
56 /*
57 * We keep this instance the way it is by default.
58 * Otherwise, we use the current state of the
59 * cdev in use to determine the next_target.
60 */
55 cdev->ops->get_cur_state(cdev, &cur_state); 61 cdev->ops->get_cur_state(cdev, &cur_state);
62 next_target = instance->target;
56 63
57 switch (trend) { 64 switch (trend) {
58 case THERMAL_TREND_RAISING: 65 case THERMAL_TREND_RAISING:
59 if (throttle) { 66 if (throttle) {
60 cur_state = cur_state < instance->upper ? 67 next_target = cur_state < instance->upper ?
61 (cur_state + 1) : instance->upper; 68 (cur_state + 1) : instance->upper;
62 if (cur_state < instance->lower) 69 if (next_target < instance->lower)
63 cur_state = instance->lower; 70 next_target = instance->lower;
64 } 71 }
65 break; 72 break;
66 case THERMAL_TREND_RAISE_FULL: 73 case THERMAL_TREND_RAISE_FULL:
67 if (throttle) 74 if (throttle)
68 cur_state = instance->upper; 75 next_target = instance->upper;
69 break; 76 break;
70 case THERMAL_TREND_DROPPING: 77 case THERMAL_TREND_DROPPING:
71 if (cur_state == instance->lower) { 78 if (cur_state == instance->lower) {
72 if (!throttle) 79 if (!throttle)
73 cur_state = -1; 80 next_target = THERMAL_NO_TARGET;
74 } else { 81 } else {
75 cur_state -= 1; 82 next_target = cur_state - 1;
76 if (cur_state > instance->upper) 83 if (next_target > instance->upper)
77 cur_state = instance->upper; 84 next_target = instance->upper;
78 } 85 }
79 break; 86 break;
80 case THERMAL_TREND_DROP_FULL: 87 case THERMAL_TREND_DROP_FULL:
81 if (cur_state == instance->lower) { 88 if (cur_state == instance->lower) {
82 if (!throttle) 89 if (!throttle)
83 cur_state = -1; 90 next_target = THERMAL_NO_TARGET;
84 } else 91 } else
85 cur_state = instance->lower; 92 next_target = instance->lower;
86 break; 93 break;
87 default: 94 default:
88 break; 95 break;
89 } 96 }
90 97
91 return cur_state; 98 return next_target;
92} 99}
93 100
94static void update_passive_instance(struct thermal_zone_device *tz, 101static void update_passive_instance(struct thermal_zone_device *tz,
@@ -133,6 +140,9 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
133 old_target = instance->target; 140 old_target = instance->target;
134 instance->target = get_target_state(instance, trend, throttle); 141 instance->target = get_target_state(instance, trend, throttle);
135 142
143 if (old_target == instance->target)
144 continue;
145
136 /* Activate a passive thermal instance */ 146 /* Activate a passive thermal instance */
137 if (old_target == THERMAL_NO_TARGET && 147 if (old_target == THERMAL_NO_TARGET &&
138 instance->target != THERMAL_NO_TARGET) 148 instance->target != THERMAL_NO_TARGET)
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 1f02e8edb45c..f1d511a9475b 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -38,6 +38,7 @@
38#include <net/genetlink.h> 38#include <net/genetlink.h>
39 39
40#include "thermal_core.h" 40#include "thermal_core.h"
41#include "thermal_hwmon.h"
41 42
42MODULE_AUTHOR("Zhang Rui"); 43MODULE_AUTHOR("Zhang Rui");
43MODULE_DESCRIPTION("Generic thermal management sysfs support"); 44MODULE_DESCRIPTION("Generic thermal management sysfs support");
@@ -201,14 +202,23 @@ static void print_bind_err_msg(struct thermal_zone_device *tz,
201} 202}
202 203
203static void __bind(struct thermal_zone_device *tz, int mask, 204static void __bind(struct thermal_zone_device *tz, int mask,
204 struct thermal_cooling_device *cdev) 205 struct thermal_cooling_device *cdev,
206 unsigned long *limits)
205{ 207{
206 int i, ret; 208 int i, ret;
207 209
208 for (i = 0; i < tz->trips; i++) { 210 for (i = 0; i < tz->trips; i++) {
209 if (mask & (1 << i)) { 211 if (mask & (1 << i)) {
212 unsigned long upper, lower;
213
214 upper = THERMAL_NO_LIMIT;
215 lower = THERMAL_NO_LIMIT;
216 if (limits) {
217 lower = limits[i * 2];
218 upper = limits[i * 2 + 1];
219 }
210 ret = thermal_zone_bind_cooling_device(tz, i, cdev, 220 ret = thermal_zone_bind_cooling_device(tz, i, cdev,
211 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT); 221 upper, lower);
212 if (ret) 222 if (ret)
213 print_bind_err_msg(tz, cdev, ret); 223 print_bind_err_msg(tz, cdev, ret);
214 } 224 }
@@ -237,10 +247,11 @@ static void bind_cdev(struct thermal_cooling_device *cdev)
237 if (!pos->tzp && !pos->ops->bind) 247 if (!pos->tzp && !pos->ops->bind)
238 continue; 248 continue;
239 249
240 if (!pos->tzp && pos->ops->bind) { 250 if (pos->ops->bind) {
241 ret = pos->ops->bind(pos, cdev); 251 ret = pos->ops->bind(pos, cdev);
242 if (ret) 252 if (ret)
243 print_bind_err_msg(pos, cdev, ret); 253 print_bind_err_msg(pos, cdev, ret);
254 continue;
244 } 255 }
245 256
246 tzp = pos->tzp; 257 tzp = pos->tzp;
@@ -253,7 +264,8 @@ static void bind_cdev(struct thermal_cooling_device *cdev)
253 if (tzp->tbp[i].match(pos, cdev)) 264 if (tzp->tbp[i].match(pos, cdev))
254 continue; 265 continue;
255 tzp->tbp[i].cdev = cdev; 266 tzp->tbp[i].cdev = cdev;
256 __bind(pos, tzp->tbp[i].trip_mask, cdev); 267 __bind(pos, tzp->tbp[i].trip_mask, cdev,
268 tzp->tbp[i].binding_limits);
257 } 269 }
258 } 270 }
259 271
@@ -271,8 +283,8 @@ static void bind_tz(struct thermal_zone_device *tz)
271 283
272 mutex_lock(&thermal_list_lock); 284 mutex_lock(&thermal_list_lock);
273 285
274 /* If there is no platform data, try to use ops->bind */ 286 /* If there is ops->bind, try to use ops->bind */
275 if (!tzp && tz->ops->bind) { 287 if (tz->ops->bind) {
276 list_for_each_entry(pos, &thermal_cdev_list, node) { 288 list_for_each_entry(pos, &thermal_cdev_list, node) {
277 ret = tz->ops->bind(tz, pos); 289 ret = tz->ops->bind(tz, pos);
278 if (ret) 290 if (ret)
@@ -291,7 +303,8 @@ static void bind_tz(struct thermal_zone_device *tz)
291 if (tzp->tbp[i].match(tz, pos)) 303 if (tzp->tbp[i].match(tz, pos))
292 continue; 304 continue;
293 tzp->tbp[i].cdev = pos; 305 tzp->tbp[i].cdev = pos;
294 __bind(tz, tzp->tbp[i].trip_mask, pos); 306 __bind(tz, tzp->tbp[i].trip_mask, pos,
307 tzp->tbp[i].binding_limits);
295 } 308 }
296 } 309 }
297exit: 310exit:
@@ -859,260 +872,6 @@ thermal_cooling_device_trip_point_show(struct device *dev,
859 872
860/* Device management */ 873/* Device management */
861 874
862#if defined(CONFIG_THERMAL_HWMON)
863
864/* hwmon sys I/F */
865#include <linux/hwmon.h>
866
867/* thermal zone devices with the same type share one hwmon device */
868struct thermal_hwmon_device {
869 char type[THERMAL_NAME_LENGTH];
870 struct device *device;
871 int count;
872 struct list_head tz_list;
873 struct list_head node;
874};
875
876struct thermal_hwmon_attr {
877 struct device_attribute attr;
878 char name[16];
879};
880
881/* one temperature input for each thermal zone */
882struct thermal_hwmon_temp {
883 struct list_head hwmon_node;
884 struct thermal_zone_device *tz;
885 struct thermal_hwmon_attr temp_input; /* hwmon sys attr */
886 struct thermal_hwmon_attr temp_crit; /* hwmon sys attr */
887};
888
889static LIST_HEAD(thermal_hwmon_list);
890
891static ssize_t
892name_show(struct device *dev, struct device_attribute *attr, char *buf)
893{
894 struct thermal_hwmon_device *hwmon = dev_get_drvdata(dev);
895 return sprintf(buf, "%s\n", hwmon->type);
896}
897static DEVICE_ATTR(name, 0444, name_show, NULL);
898
899static ssize_t
900temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
901{
902 long temperature;
903 int ret;
904 struct thermal_hwmon_attr *hwmon_attr
905 = container_of(attr, struct thermal_hwmon_attr, attr);
906 struct thermal_hwmon_temp *temp
907 = container_of(hwmon_attr, struct thermal_hwmon_temp,
908 temp_input);
909 struct thermal_zone_device *tz = temp->tz;
910
911 ret = thermal_zone_get_temp(tz, &temperature);
912
913 if (ret)
914 return ret;
915
916 return sprintf(buf, "%ld\n", temperature);
917}
918
919static ssize_t
920temp_crit_show(struct device *dev, struct device_attribute *attr,
921 char *buf)
922{
923 struct thermal_hwmon_attr *hwmon_attr
924 = container_of(attr, struct thermal_hwmon_attr, attr);
925 struct thermal_hwmon_temp *temp
926 = container_of(hwmon_attr, struct thermal_hwmon_temp,
927 temp_crit);
928 struct thermal_zone_device *tz = temp->tz;
929 long temperature;
930 int ret;
931
932 ret = tz->ops->get_trip_temp(tz, 0, &temperature);
933 if (ret)
934 return ret;
935
936 return sprintf(buf, "%ld\n", temperature);
937}
938
939
940static struct thermal_hwmon_device *
941thermal_hwmon_lookup_by_type(const struct thermal_zone_device *tz)
942{
943 struct thermal_hwmon_device *hwmon;
944
945 mutex_lock(&thermal_list_lock);
946 list_for_each_entry(hwmon, &thermal_hwmon_list, node)
947 if (!strcmp(hwmon->type, tz->type)) {
948 mutex_unlock(&thermal_list_lock);
949 return hwmon;
950 }
951 mutex_unlock(&thermal_list_lock);
952
953 return NULL;
954}
955
956/* Find the temperature input matching a given thermal zone */
957static struct thermal_hwmon_temp *
958thermal_hwmon_lookup_temp(const struct thermal_hwmon_device *hwmon,
959 const struct thermal_zone_device *tz)
960{
961 struct thermal_hwmon_temp *temp;
962
963 mutex_lock(&thermal_list_lock);
964 list_for_each_entry(temp, &hwmon->tz_list, hwmon_node)
965 if (temp->tz == tz) {
966 mutex_unlock(&thermal_list_lock);
967 return temp;
968 }
969 mutex_unlock(&thermal_list_lock);
970
971 return NULL;
972}
973
974static int
975thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
976{
977 struct thermal_hwmon_device *hwmon;
978 struct thermal_hwmon_temp *temp;
979 int new_hwmon_device = 1;
980 int result;
981
982 hwmon = thermal_hwmon_lookup_by_type(tz);
983 if (hwmon) {
984 new_hwmon_device = 0;
985 goto register_sys_interface;
986 }
987
988 hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL);
989 if (!hwmon)
990 return -ENOMEM;
991
992 INIT_LIST_HEAD(&hwmon->tz_list);
993 strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH);
994 hwmon->device = hwmon_device_register(NULL);
995 if (IS_ERR(hwmon->device)) {
996 result = PTR_ERR(hwmon->device);
997 goto free_mem;
998 }
999 dev_set_drvdata(hwmon->device, hwmon);
1000 result = device_create_file(hwmon->device, &dev_attr_name);
1001 if (result)
1002 goto free_mem;
1003
1004 register_sys_interface:
1005 temp = kzalloc(sizeof(struct thermal_hwmon_temp), GFP_KERNEL);
1006 if (!temp) {
1007 result = -ENOMEM;
1008 goto unregister_name;
1009 }
1010
1011 temp->tz = tz;
1012 hwmon->count++;
1013
1014 snprintf(temp->temp_input.name, sizeof(temp->temp_input.name),
1015 "temp%d_input", hwmon->count);
1016 temp->temp_input.attr.attr.name = temp->temp_input.name;
1017 temp->temp_input.attr.attr.mode = 0444;
1018 temp->temp_input.attr.show = temp_input_show;
1019 sysfs_attr_init(&temp->temp_input.attr.attr);
1020 result = device_create_file(hwmon->device, &temp->temp_input.attr);
1021 if (result)
1022 goto free_temp_mem;
1023
1024 if (tz->ops->get_crit_temp) {
1025 unsigned long temperature;
1026 if (!tz->ops->get_crit_temp(tz, &temperature)) {
1027 snprintf(temp->temp_crit.name,
1028 sizeof(temp->temp_crit.name),
1029 "temp%d_crit", hwmon->count);
1030 temp->temp_crit.attr.attr.name = temp->temp_crit.name;
1031 temp->temp_crit.attr.attr.mode = 0444;
1032 temp->temp_crit.attr.show = temp_crit_show;
1033 sysfs_attr_init(&temp->temp_crit.attr.attr);
1034 result = device_create_file(hwmon->device,
1035 &temp->temp_crit.attr);
1036 if (result)
1037 goto unregister_input;
1038 }
1039 }
1040
1041 mutex_lock(&thermal_list_lock);
1042 if (new_hwmon_device)
1043 list_add_tail(&hwmon->node, &thermal_hwmon_list);
1044 list_add_tail(&temp->hwmon_node, &hwmon->tz_list);
1045 mutex_unlock(&thermal_list_lock);
1046
1047 return 0;
1048
1049 unregister_input:
1050 device_remove_file(hwmon->device, &temp->temp_input.attr);
1051 free_temp_mem:
1052 kfree(temp);
1053 unregister_name:
1054 if (new_hwmon_device) {
1055 device_remove_file(hwmon->device, &dev_attr_name);
1056 hwmon_device_unregister(hwmon->device);
1057 }
1058 free_mem:
1059 if (new_hwmon_device)
1060 kfree(hwmon);
1061
1062 return result;
1063}
1064
1065static void
1066thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
1067{
1068 struct thermal_hwmon_device *hwmon;
1069 struct thermal_hwmon_temp *temp;
1070
1071 hwmon = thermal_hwmon_lookup_by_type(tz);
1072 if (unlikely(!hwmon)) {
1073 /* Should never happen... */
1074 dev_dbg(&tz->device, "hwmon device lookup failed!\n");
1075 return;
1076 }
1077
1078 temp = thermal_hwmon_lookup_temp(hwmon, tz);
1079 if (unlikely(!temp)) {
1080 /* Should never happen... */
1081 dev_dbg(&tz->device, "temperature input lookup failed!\n");
1082 return;
1083 }
1084
1085 device_remove_file(hwmon->device, &temp->temp_input.attr);
1086 if (tz->ops->get_crit_temp)
1087 device_remove_file(hwmon->device, &temp->temp_crit.attr);
1088
1089 mutex_lock(&thermal_list_lock);
1090 list_del(&temp->hwmon_node);
1091 kfree(temp);
1092 if (!list_empty(&hwmon->tz_list)) {
1093 mutex_unlock(&thermal_list_lock);
1094 return;
1095 }
1096 list_del(&hwmon->node);
1097 mutex_unlock(&thermal_list_lock);
1098
1099 device_remove_file(hwmon->device, &dev_attr_name);
1100 hwmon_device_unregister(hwmon->device);
1101 kfree(hwmon);
1102}
1103#else
1104static int
1105thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
1106{
1107 return 0;
1108}
1109
1110static void
1111thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
1112{
1113}
1114#endif
1115
1116/** 875/**
1117 * thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone 876 * thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone
1118 * @tz: pointer to struct thermal_zone_device 877 * @tz: pointer to struct thermal_zone_device
@@ -1280,7 +1039,8 @@ static void thermal_release(struct device *dev)
1280 sizeof("thermal_zone") - 1)) { 1039 sizeof("thermal_zone") - 1)) {
1281 tz = to_thermal_zone(dev); 1040 tz = to_thermal_zone(dev);
1282 kfree(tz); 1041 kfree(tz);
1283 } else { 1042 } else if(!strncmp(dev_name(dev), "cooling_device",
1043 sizeof("cooling_device") - 1)){
1284 cdev = to_cooling_device(dev); 1044 cdev = to_cooling_device(dev);
1285 kfree(cdev); 1045 kfree(cdev);
1286 } 1046 }
@@ -1715,9 +1475,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1715 1475
1716 mutex_unlock(&thermal_governor_lock); 1476 mutex_unlock(&thermal_governor_lock);
1717 1477
1718 result = thermal_add_hwmon_sysfs(tz); 1478 if (!tz->tzp || !tz->tzp->no_hwmon) {
1719 if (result) 1479 result = thermal_add_hwmon_sysfs(tz);
1720 goto unregister; 1480 if (result)
1481 goto unregister;
1482 }
1721 1483
1722 mutex_lock(&thermal_list_lock); 1484 mutex_lock(&thermal_list_lock);
1723 list_add_tail(&tz->node, &thermal_tz_list); 1485 list_add_tail(&tz->node, &thermal_tz_list);
@@ -1846,15 +1608,17 @@ exit:
1846EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name); 1608EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
1847 1609
1848#ifdef CONFIG_NET 1610#ifdef CONFIG_NET
1611static const struct genl_multicast_group thermal_event_mcgrps[] = {
1612 { .name = THERMAL_GENL_MCAST_GROUP_NAME, },
1613};
1614
1849static struct genl_family thermal_event_genl_family = { 1615static struct genl_family thermal_event_genl_family = {
1850 .id = GENL_ID_GENERATE, 1616 .id = GENL_ID_GENERATE,
1851 .name = THERMAL_GENL_FAMILY_NAME, 1617 .name = THERMAL_GENL_FAMILY_NAME,
1852 .version = THERMAL_GENL_VERSION, 1618 .version = THERMAL_GENL_VERSION,
1853 .maxattr = THERMAL_GENL_ATTR_MAX, 1619 .maxattr = THERMAL_GENL_ATTR_MAX,
1854}; 1620 .mcgrps = thermal_event_mcgrps,
1855 1621 .n_mcgrps = ARRAY_SIZE(thermal_event_mcgrps),
1856static struct genl_multicast_group thermal_event_mcgrp = {
1857 .name = THERMAL_GENL_MCAST_GROUP_NAME,
1858}; 1622};
1859 1623
1860int thermal_generate_netlink_event(struct thermal_zone_device *tz, 1624int thermal_generate_netlink_event(struct thermal_zone_device *tz,
@@ -1915,7 +1679,8 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz,
1915 return result; 1679 return result;
1916 } 1680 }
1917 1681
1918 result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC); 1682 result = genlmsg_multicast(&thermal_event_genl_family, skb, 0,
1683 0, GFP_ATOMIC);
1919 if (result) 1684 if (result)
1920 dev_err(&tz->device, "Failed to send netlink event:%d", result); 1685 dev_err(&tz->device, "Failed to send netlink event:%d", result);
1921 1686
@@ -1925,17 +1690,7 @@ EXPORT_SYMBOL_GPL(thermal_generate_netlink_event);
1925 1690
1926static int genetlink_init(void) 1691static int genetlink_init(void)
1927{ 1692{
1928 int result; 1693 return genl_register_family(&thermal_event_genl_family);
1929
1930 result = genl_register_family(&thermal_event_genl_family);
1931 if (result)
1932 return result;
1933
1934 result = genl_register_mc_group(&thermal_event_genl_family,
1935 &thermal_event_mcgrp);
1936 if (result)
1937 genl_unregister_family(&thermal_event_genl_family);
1938 return result;
1939} 1694}
1940 1695
1941static void genetlink_exit(void) 1696static void genetlink_exit(void)
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
new file mode 100644
index 000000000000..fdb07199d9c2
--- /dev/null
+++ b/drivers/thermal/thermal_hwmon.c
@@ -0,0 +1,269 @@
1/*
2 * thermal_hwmon.c - Generic Thermal Management hwmon support.
3 *
4 * Code based on Intel thermal_core.c. Copyrights of the original code:
5 * Copyright (C) 2008 Intel Corp
6 * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
7 * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
8 *
9 * Copyright (C) 2013 Texas Instruments
10 * Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 */
28#include <linux/hwmon.h>
29#include <linux/thermal.h>
30#include <linux/slab.h>
31#include <linux/err.h>
32#include "thermal_hwmon.h"
33
34/* hwmon sys I/F */
35/* thermal zone devices with the same type share one hwmon device */
36struct thermal_hwmon_device {
37 char type[THERMAL_NAME_LENGTH];
38 struct device *device;
39 int count;
40 struct list_head tz_list;
41 struct list_head node;
42};
43
44struct thermal_hwmon_attr {
45 struct device_attribute attr;
46 char name[16];
47};
48
49/* one temperature input for each thermal zone */
50struct thermal_hwmon_temp {
51 struct list_head hwmon_node;
52 struct thermal_zone_device *tz;
53 struct thermal_hwmon_attr temp_input; /* hwmon sys attr */
54 struct thermal_hwmon_attr temp_crit; /* hwmon sys attr */
55};
56
57static LIST_HEAD(thermal_hwmon_list);
58
59static DEFINE_MUTEX(thermal_hwmon_list_lock);
60
61static ssize_t
62name_show(struct device *dev, struct device_attribute *attr, char *buf)
63{
64 struct thermal_hwmon_device *hwmon = dev_get_drvdata(dev);
65 return sprintf(buf, "%s\n", hwmon->type);
66}
67static DEVICE_ATTR(name, 0444, name_show, NULL);
68
69static ssize_t
70temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
71{
72 long temperature;
73 int ret;
74 struct thermal_hwmon_attr *hwmon_attr
75 = container_of(attr, struct thermal_hwmon_attr, attr);
76 struct thermal_hwmon_temp *temp
77 = container_of(hwmon_attr, struct thermal_hwmon_temp,
78 temp_input);
79 struct thermal_zone_device *tz = temp->tz;
80
81 ret = thermal_zone_get_temp(tz, &temperature);
82
83 if (ret)
84 return ret;
85
86 return sprintf(buf, "%ld\n", temperature);
87}
88
89static ssize_t
90temp_crit_show(struct device *dev, struct device_attribute *attr, char *buf)
91{
92 struct thermal_hwmon_attr *hwmon_attr
93 = container_of(attr, struct thermal_hwmon_attr, attr);
94 struct thermal_hwmon_temp *temp
95 = container_of(hwmon_attr, struct thermal_hwmon_temp,
96 temp_crit);
97 struct thermal_zone_device *tz = temp->tz;
98 long temperature;
99 int ret;
100
101 ret = tz->ops->get_trip_temp(tz, 0, &temperature);
102 if (ret)
103 return ret;
104
105 return sprintf(buf, "%ld\n", temperature);
106}
107
108
109static struct thermal_hwmon_device *
110thermal_hwmon_lookup_by_type(const struct thermal_zone_device *tz)
111{
112 struct thermal_hwmon_device *hwmon;
113
114 mutex_lock(&thermal_hwmon_list_lock);
115 list_for_each_entry(hwmon, &thermal_hwmon_list, node)
116 if (!strcmp(hwmon->type, tz->type)) {
117 mutex_unlock(&thermal_hwmon_list_lock);
118 return hwmon;
119 }
120 mutex_unlock(&thermal_hwmon_list_lock);
121
122 return NULL;
123}
124
125/* Find the temperature input matching a given thermal zone */
126static struct thermal_hwmon_temp *
127thermal_hwmon_lookup_temp(const struct thermal_hwmon_device *hwmon,
128 const struct thermal_zone_device *tz)
129{
130 struct thermal_hwmon_temp *temp;
131
132 mutex_lock(&thermal_hwmon_list_lock);
133 list_for_each_entry(temp, &hwmon->tz_list, hwmon_node)
134 if (temp->tz == tz) {
135 mutex_unlock(&thermal_hwmon_list_lock);
136 return temp;
137 }
138 mutex_unlock(&thermal_hwmon_list_lock);
139
140 return NULL;
141}
142
143int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
144{
145 struct thermal_hwmon_device *hwmon;
146 struct thermal_hwmon_temp *temp;
147 int new_hwmon_device = 1;
148 int result;
149
150 hwmon = thermal_hwmon_lookup_by_type(tz);
151 if (hwmon) {
152 new_hwmon_device = 0;
153 goto register_sys_interface;
154 }
155
156 hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
157 if (!hwmon)
158 return -ENOMEM;
159
160 INIT_LIST_HEAD(&hwmon->tz_list);
161 strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH);
162 hwmon->device = hwmon_device_register(NULL);
163 if (IS_ERR(hwmon->device)) {
164 result = PTR_ERR(hwmon->device);
165 goto free_mem;
166 }
167 dev_set_drvdata(hwmon->device, hwmon);
168 result = device_create_file(hwmon->device, &dev_attr_name);
169 if (result)
170 goto free_mem;
171
172 register_sys_interface:
173 temp = kzalloc(sizeof(*temp), GFP_KERNEL);
174 if (!temp) {
175 result = -ENOMEM;
176 goto unregister_name;
177 }
178
179 temp->tz = tz;
180 hwmon->count++;
181
182 snprintf(temp->temp_input.name, sizeof(temp->temp_input.name),
183 "temp%d_input", hwmon->count);
184 temp->temp_input.attr.attr.name = temp->temp_input.name;
185 temp->temp_input.attr.attr.mode = 0444;
186 temp->temp_input.attr.show = temp_input_show;
187 sysfs_attr_init(&temp->temp_input.attr.attr);
188 result = device_create_file(hwmon->device, &temp->temp_input.attr);
189 if (result)
190 goto free_temp_mem;
191
192 if (tz->ops->get_crit_temp) {
193 unsigned long temperature;
194 if (!tz->ops->get_crit_temp(tz, &temperature)) {
195 snprintf(temp->temp_crit.name,
196 sizeof(temp->temp_crit.name),
197 "temp%d_crit", hwmon->count);
198 temp->temp_crit.attr.attr.name = temp->temp_crit.name;
199 temp->temp_crit.attr.attr.mode = 0444;
200 temp->temp_crit.attr.show = temp_crit_show;
201 sysfs_attr_init(&temp->temp_crit.attr.attr);
202 result = device_create_file(hwmon->device,
203 &temp->temp_crit.attr);
204 if (result)
205 goto unregister_input;
206 }
207 }
208
209 mutex_lock(&thermal_hwmon_list_lock);
210 if (new_hwmon_device)
211 list_add_tail(&hwmon->node, &thermal_hwmon_list);
212 list_add_tail(&temp->hwmon_node, &hwmon->tz_list);
213 mutex_unlock(&thermal_hwmon_list_lock);
214
215 return 0;
216
217 unregister_input:
218 device_remove_file(hwmon->device, &temp->temp_input.attr);
219 free_temp_mem:
220 kfree(temp);
221 unregister_name:
222 if (new_hwmon_device) {
223 device_remove_file(hwmon->device, &dev_attr_name);
224 hwmon_device_unregister(hwmon->device);
225 }
226 free_mem:
227 if (new_hwmon_device)
228 kfree(hwmon);
229
230 return result;
231}
232
233void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
234{
235 struct thermal_hwmon_device *hwmon;
236 struct thermal_hwmon_temp *temp;
237
238 hwmon = thermal_hwmon_lookup_by_type(tz);
239 if (unlikely(!hwmon)) {
240 /* Should never happen... */
241 dev_dbg(&tz->device, "hwmon device lookup failed!\n");
242 return;
243 }
244
245 temp = thermal_hwmon_lookup_temp(hwmon, tz);
246 if (unlikely(!temp)) {
247 /* Should never happen... */
248 dev_dbg(&tz->device, "temperature input lookup failed!\n");
249 return;
250 }
251
252 device_remove_file(hwmon->device, &temp->temp_input.attr);
253 if (tz->ops->get_crit_temp)
254 device_remove_file(hwmon->device, &temp->temp_crit.attr);
255
256 mutex_lock(&thermal_hwmon_list_lock);
257 list_del(&temp->hwmon_node);
258 kfree(temp);
259 if (!list_empty(&hwmon->tz_list)) {
260 mutex_unlock(&thermal_hwmon_list_lock);
261 return;
262 }
263 list_del(&hwmon->node);
264 mutex_unlock(&thermal_hwmon_list_lock);
265
266 device_remove_file(hwmon->device, &dev_attr_name);
267 hwmon_device_unregister(hwmon->device);
268 kfree(hwmon);
269}
diff --git a/drivers/thermal/thermal_hwmon.h b/drivers/thermal/thermal_hwmon.h
new file mode 100644
index 000000000000..c798fdb2ae43
--- /dev/null
+++ b/drivers/thermal/thermal_hwmon.h
@@ -0,0 +1,49 @@
1/*
2 * thermal_hwmon.h - Generic Thermal Management hwmon support.
3 *
4 * Code based on Intel thermal_core.c. Copyrights of the original code:
5 * Copyright (C) 2008 Intel Corp
6 * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
7 * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
8 *
9 * Copyright (C) 2013 Texas Instruments
10 * Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 */
28#ifndef __THERMAL_HWMON_H__
29#define __THERMAL_HWMON_H__
30
31#include <linux/thermal.h>
32
33#ifdef CONFIG_THERMAL_HWMON
34int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz);
35void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz);
36#else
37static int
38thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
39{
40 return 0;
41}
42
43static void
44thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
45{
46}
47#endif
48
49#endif /* __THERMAL_HWMON_H__ */
diff --git a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
index e5d8326a54d6..a4929272074f 100644
--- a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
+++ b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
@@ -42,6 +42,7 @@ dra752_core_temp_sensor_registers = {
42 .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK, 42 .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK,
43 .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK, 43 .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK,
44 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 44 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
45 .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK,
45 .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK, 46 .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK,
46 .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK, 47 .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK,
47 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK, 48 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK,
@@ -77,6 +78,7 @@ dra752_iva_temp_sensor_registers = {
77 .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK, 78 .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK,
78 .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK, 79 .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK,
79 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 80 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
81 .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK,
80 .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK, 82 .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK,
81 .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK, 83 .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK,
82 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK, 84 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK,
@@ -112,6 +114,7 @@ dra752_mpu_temp_sensor_registers = {
112 .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK, 114 .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK,
113 .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK, 115 .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK,
114 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 116 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
117 .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK,
115 .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK, 118 .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK,
116 .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK, 119 .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK,
117 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK, 120 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK,
@@ -147,6 +150,7 @@ dra752_dspeve_temp_sensor_registers = {
147 .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK, 150 .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK,
148 .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK, 151 .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK,
149 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 152 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
153 .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK,
150 .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK, 154 .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK,
151 .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK, 155 .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK,
152 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK, 156 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK,
@@ -182,6 +186,7 @@ dra752_gpu_temp_sensor_registers = {
182 .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK, 186 .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK,
183 .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK, 187 .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK,
184 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 188 .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
189 .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK,
185 .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK, 190 .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK,
186 .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK, 191 .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK,
187 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK, 192 .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK,
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
index 9dfd47196e63..74c0e3474d6e 100644
--- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
@@ -1020,9 +1020,13 @@ int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend)
1020 1020
1021 /* Fetch the update interval */ 1021 /* Fetch the update interval */
1022 ret = ti_bandgap_read_update_interval(bgp, id, &interval); 1022 ret = ti_bandgap_read_update_interval(bgp, id, &interval);
1023 if (ret || !interval) 1023 if (ret)
1024 goto unfreeze; 1024 goto unfreeze;
1025 1025
1026 /* Set the interval to 1 ms if bandgap counter delay is not set */
1027 if (interval == 0)
1028 interval = 1;
1029
1026 *trend = (t1 - t2) / interval; 1030 *trend = (t1 - t2) / interval;
1027 1031
1028 dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n", 1032 dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n",
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 4c5f55c37349..5a47cc8c8f85 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -110,6 +110,7 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
110 } else { 110 } else {
111 dev_err(bgp->dev, 111 dev_err(bgp->dev,
112 "Failed to read PCB state. Using defaults\n"); 112 "Failed to read PCB state. Using defaults\n");
113 ret = 0;
113 } 114 }
114 } 115 }
115 *temp = ti_thermal_hotspot_temperature(tmp, slope, constant); 116 *temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
@@ -174,6 +175,9 @@ static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
174 enum thermal_device_mode mode) 175 enum thermal_device_mode mode)
175{ 176{
176 struct ti_thermal_data *data = thermal->devdata; 177 struct ti_thermal_data *data = thermal->devdata;
178 struct ti_bandgap *bgp;
179
180 bgp = data->bgp;
177 181
178 if (!data->ti_thermal) { 182 if (!data->ti_thermal) {
179 dev_notice(&thermal->device, "thermal zone not registered\n"); 183 dev_notice(&thermal->device, "thermal zone not registered\n");
@@ -190,6 +194,8 @@ static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
190 mutex_unlock(&data->ti_thermal->lock); 194 mutex_unlock(&data->ti_thermal->lock);
191 195
192 data->mode = mode; 196 data->mode = mode;
197 ti_bandgap_write_update_interval(bgp, data->sensor_id,
198 data->ti_thermal->polling_delay);
193 thermal_zone_device_update(data->ti_thermal); 199 thermal_zone_device_update(data->ti_thermal);
194 dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n", 200 dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
195 data->ti_thermal->polling_delay); 201 data->ti_thermal->polling_delay);
@@ -313,6 +319,8 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
313 } 319 }
314 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; 320 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
315 ti_bandgap_set_sensor_data(bgp, id, data); 321 ti_bandgap_set_sensor_data(bgp, id, data);
322 ti_bandgap_write_update_interval(bgp, data->sensor_id,
323 data->ti_thermal->polling_delay);
316 324
317 return 0; 325 return 0;
318} 326}
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index f36950e4134f..7722cb9d5a80 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -316,18 +316,19 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
316 int phy_id = topology_physical_package_id(cpu); 316 int phy_id = topology_physical_package_id(cpu);
317 struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu); 317 struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
318 bool notify = false; 318 bool notify = false;
319 unsigned long flags;
319 320
320 if (!phdev) 321 if (!phdev)
321 return; 322 return;
322 323
323 spin_lock(&pkg_work_lock); 324 spin_lock_irqsave(&pkg_work_lock, flags);
324 ++pkg_work_cnt; 325 ++pkg_work_cnt;
325 if (unlikely(phy_id > max_phy_id)) { 326 if (unlikely(phy_id > max_phy_id)) {
326 spin_unlock(&pkg_work_lock); 327 spin_unlock_irqrestore(&pkg_work_lock, flags);
327 return; 328 return;
328 } 329 }
329 pkg_work_scheduled[phy_id] = 0; 330 pkg_work_scheduled[phy_id] = 0;
330 spin_unlock(&pkg_work_lock); 331 spin_unlock_irqrestore(&pkg_work_lock, flags);
331 332
332 enable_pkg_thres_interrupt(); 333 enable_pkg_thres_interrupt();
333 rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val); 334 rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
@@ -397,6 +398,7 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
397 int thres_count; 398 int thres_count;
398 u32 eax, ebx, ecx, edx; 399 u32 eax, ebx, ecx, edx;
399 u8 *temp; 400 u8 *temp;
401 unsigned long flags;
400 402
401 cpuid(6, &eax, &ebx, &ecx, &edx); 403 cpuid(6, &eax, &ebx, &ecx, &edx);
402 thres_count = ebx & 0x07; 404 thres_count = ebx & 0x07;
@@ -420,19 +422,19 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
420 goto err_ret_unlock; 422 goto err_ret_unlock;
421 } 423 }
422 424
423 spin_lock(&pkg_work_lock); 425 spin_lock_irqsave(&pkg_work_lock, flags);
424 if (topology_physical_package_id(cpu) > max_phy_id) 426 if (topology_physical_package_id(cpu) > max_phy_id)
425 max_phy_id = topology_physical_package_id(cpu); 427 max_phy_id = topology_physical_package_id(cpu);
426 temp = krealloc(pkg_work_scheduled, 428 temp = krealloc(pkg_work_scheduled,
427 (max_phy_id+1) * sizeof(u8), GFP_ATOMIC); 429 (max_phy_id+1) * sizeof(u8), GFP_ATOMIC);
428 if (!temp) { 430 if (!temp) {
429 spin_unlock(&pkg_work_lock); 431 spin_unlock_irqrestore(&pkg_work_lock, flags);
430 err = -ENOMEM; 432 err = -ENOMEM;
431 goto err_ret_free; 433 goto err_ret_free;
432 } 434 }
433 pkg_work_scheduled = temp; 435 pkg_work_scheduled = temp;
434 pkg_work_scheduled[topology_physical_package_id(cpu)] = 0; 436 pkg_work_scheduled[topology_physical_package_id(cpu)] = 0;
435 spin_unlock(&pkg_work_lock); 437 spin_unlock_irqrestore(&pkg_work_lock, flags);
436 438
437 phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu); 439 phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu);
438 phy_dev_entry->first_cpu = cpu; 440 phy_dev_entry->first_cpu = cpu;