aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukasz Majewski <l.majewski@samsung.com>2015-01-23 07:10:09 -0500
committerEduardo Valentin <edubezval@gmail.com>2015-01-24 16:40:49 -0500
commit1fd2273f966a095ff825cb20304878fdf14a6b45 (patch)
tree971e578a9c873fda4c58caa12e506debaef2f4d9
parent3b6a1a805f342472a0e68e2a0eb1decaadf7fa02 (diff)
thermal: exynos: Remove exynos_thermal_common.[c|h] files
After defining all necessary Exynos data in the device tree and heavy reusage of the of-thermal.c those files can be removed. Signed-off-by: Lukasz Majewski <l.majewski@samsung.com> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.c445
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.h106
2 files changed, 0 insertions, 551 deletions
diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
deleted file mode 100644
index 00aa68862a52..000000000000
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ /dev/null
@@ -1,445 +0,0 @@
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 struct exynos_thermal_zone *th_zone = thermal->devdata;
137 struct thermal_sensor_conf *data = th_zone->sensor_conf;
138 struct device_node *child, *gchild, *np;
139 struct of_phandle_args cooling_spec;
140 unsigned long max, state = 0;
141 int ret = 0, i = 0;
142
143 /*
144 * Below code is necessary to skip binding when cpufreq's
145 * frequency table is not yet initialized.
146 */
147 cdev->ops->get_max_state(cdev, &state);
148 if (!state && !th_zone->cool_dev_size) {
149 th_zone->cool_dev_size = 1;
150 th_zone->cool_dev[0] = cdev;
151 th_zone->bind = false;
152 return 0;
153 }
154
155 np = of_find_node_by_path("/thermal-zones/cpu-thermal");
156 if (!np) {
157 pr_err("failed to find thmerla-zones/cpu-thermal node\n");
158 return -ENOENT;
159 }
160
161 child = of_get_child_by_name(np, "cooling-maps");
162
163 for_each_child_of_node(child, gchild) {
164 ret = of_parse_phandle_with_args(gchild, "cooling-device",
165 "#cooling-cells",
166 0, &cooling_spec);
167 if (ret < 0) {
168 pr_err("missing cooling_device property\n");
169 goto end;
170 }
171
172 if (cooling_spec.args_count < 2) {
173 ret = -EINVAL;
174 goto end;
175 }
176
177 max = cooling_spec.args[0];
178 if (thermal_zone_bind_cooling_device(thermal, i, cdev,
179 max, 0)) {
180 dev_err(data->dev,
181 "thermal error unbinding cdev inst=%d\n", i);
182
183 ret = -EINVAL;
184 goto end;
185 }
186 i++;
187 }
188 th_zone->bind = true;
189end:
190 of_node_put(child);
191 of_node_put(np);
192
193 return ret;
194}
195
196/* Unbind callback functions for thermal zone */
197static int exynos_unbind(struct thermal_zone_device *thermal,
198 struct thermal_cooling_device *cdev)
199{
200 int ret = 0, i;
201 struct exynos_thermal_zone *th_zone = thermal->devdata;
202 struct thermal_sensor_conf *data = th_zone->sensor_conf;
203 struct device_node *child, *gchild, *np;
204
205 if (th_zone->bind == false || !th_zone->cool_dev_size)
206 return 0;
207
208 /* find the cooling device registered*/
209 for (i = 0; i < th_zone->cool_dev_size; i++)
210 if (cdev == th_zone->cool_dev[i])
211 break;
212
213 /* No matching cooling device */
214 if (i == th_zone->cool_dev_size)
215 return 0;
216
217 np = of_find_node_by_path("/thermal-zones/cpu-thermal");
218 if (!np) {
219 pr_err("failed to find thmerla-zones/cpu-thermal node\n");
220 return -ENOENT;
221 }
222
223 child = of_get_child_by_name(np, "cooling-maps");
224
225 i = 0;
226 for_each_child_of_node(child, gchild) {
227 if (thermal_zone_unbind_cooling_device(thermal, i,
228 cdev)) {
229 dev_err(data->dev,
230 "error unbinding cdev inst=%d\n", i);
231 ret = -EINVAL;
232 goto end;
233 }
234 i++;
235 }
236 th_zone->bind = false;
237end:
238 of_node_put(child);
239 of_node_put(np);
240
241 return ret;
242}
243
244/* Get temperature callback functions for thermal zone */
245static int exynos_get_temp(struct thermal_zone_device *thermal,
246 unsigned long *temp)
247{
248 struct exynos_thermal_zone *th_zone = thermal->devdata;
249 void *data;
250
251 if (!th_zone->sensor_conf) {
252 dev_err(&thermal->device,
253 "Temperature sensor not initialised\n");
254 return -EINVAL;
255 }
256 data = th_zone->sensor_conf->driver_data;
257 *temp = th_zone->sensor_conf->read_temperature(data);
258 /* convert the temperature into millicelsius */
259 *temp = *temp * MCELSIUS;
260 return 0;
261}
262
263/* Get temperature callback functions for thermal zone */
264static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
265 unsigned long temp)
266{
267 void *data;
268 int ret = -EINVAL;
269 struct exynos_thermal_zone *th_zone = thermal->devdata;
270
271 if (!th_zone->sensor_conf) {
272 dev_err(&thermal->device,
273 "Temperature sensor not initialised\n");
274 return -EINVAL;
275 }
276 data = th_zone->sensor_conf->driver_data;
277 if (th_zone->sensor_conf->write_emul_temp)
278 ret = th_zone->sensor_conf->write_emul_temp(data, temp);
279 return ret;
280}
281
282/* Get the temperature trend */
283static int exynos_get_trend(struct thermal_zone_device *thermal,
284 int trip, enum thermal_trend *trend)
285{
286 int ret;
287 unsigned long trip_temp;
288
289 ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
290 if (ret < 0)
291 return ret;
292
293 if (thermal->temperature >= trip_temp)
294 *trend = THERMAL_TREND_RAISE_FULL;
295 else
296 *trend = THERMAL_TREND_DROP_FULL;
297
298 return 0;
299}
300/* Operation callback functions for thermal zone */
301static struct thermal_zone_device_ops exynos_dev_ops = {
302 .bind = exynos_bind,
303 .unbind = exynos_unbind,
304 .get_temp = exynos_get_temp,
305 .set_emul_temp = exynos_set_emul_temp,
306 .get_trend = exynos_get_trend,
307 .get_mode = exynos_get_mode,
308 .set_mode = exynos_set_mode,
309 .get_trip_type = exynos_get_trip_type,
310 .get_trip_temp = exynos_get_trip_temp,
311 .get_crit_temp = exynos_get_crit_temp,
312};
313
314/*
315 * This function may be called from interrupt based temperature sensor
316 * when threshold is changed.
317 */
318void exynos_report_trigger(struct thermal_sensor_conf *conf)
319{
320 unsigned int i;
321 char data[10];
322 char *envp[] = { data, NULL };
323 struct exynos_thermal_zone *th_zone;
324
325 if (!conf || !conf->pzone_data) {
326 pr_err("Invalid temperature sensor configuration data\n");
327 return;
328 }
329
330 th_zone = conf->pzone_data;
331
332 if (th_zone->bind == false) {
333 for (i = 0; i < th_zone->cool_dev_size; i++) {
334 if (!th_zone->cool_dev[i])
335 continue;
336 exynos_bind(th_zone->therm_dev,
337 th_zone->cool_dev[i]);
338 }
339 }
340
341 thermal_zone_device_update(th_zone->therm_dev);
342
343 mutex_lock(&th_zone->therm_dev->lock);
344 /* Find the level for which trip happened */
345 for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
346 if (th_zone->therm_dev->last_temperature <
347 th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
348 break;
349 }
350
351 if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
352 !th_zone->sensor_conf->trip_data.trigger_falling) {
353 if (i > 0)
354 th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
355 else
356 th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
357 }
358
359 snprintf(data, sizeof(data), "%u", i);
360 kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
361 mutex_unlock(&th_zone->therm_dev->lock);
362}
363
364/* Register with the in-kernel thermal management */
365int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
366{
367 int ret;
368 struct exynos_thermal_zone *th_zone;
369
370 if (!sensor_conf || !sensor_conf->read_temperature) {
371 pr_err("Temperature sensor not initialised\n");
372 return -EINVAL;
373 }
374
375 th_zone = devm_kzalloc(sensor_conf->dev,
376 sizeof(struct exynos_thermal_zone), GFP_KERNEL);
377 if (!th_zone)
378 return -ENOMEM;
379
380 th_zone->sensor_conf = sensor_conf;
381 /*
382 * TODO: 1) Handle multiple cooling devices in a thermal zone
383 * 2) Add a flag/name in cooling info to map to specific
384 * sensor
385 */
386 if (sensor_conf->cooling_data.freq_clip_count > 0) {
387 th_zone->cool_dev[th_zone->cool_dev_size] =
388 cpufreq_cooling_register(cpu_present_mask);
389 if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) {
390 ret = PTR_ERR(th_zone->cool_dev[th_zone->cool_dev_size]);
391 if (ret != -EPROBE_DEFER)
392 dev_err(sensor_conf->dev,
393 "Failed to register cpufreq cooling device: %d\n",
394 ret);
395 goto err_unregister;
396 }
397 th_zone->cool_dev_size++;
398 }
399
400 th_zone->therm_dev = thermal_zone_device_register(
401 sensor_conf->name, sensor_conf->trip_data.trip_count,
402 0, th_zone, &exynos_dev_ops, NULL, 0,
403 sensor_conf->trip_data.trigger_falling ? 0 :
404 IDLE_INTERVAL);
405
406 if (IS_ERR(th_zone->therm_dev)) {
407 dev_err(sensor_conf->dev,
408 "Failed to register thermal zone device\n");
409 ret = PTR_ERR(th_zone->therm_dev);
410 goto err_unregister;
411 }
412 th_zone->mode = THERMAL_DEVICE_ENABLED;
413 sensor_conf->pzone_data = th_zone;
414
415 dev_info(sensor_conf->dev,
416 "Exynos: Thermal zone(%s) registered\n", sensor_conf->name);
417
418 return 0;
419
420err_unregister:
421 exynos_unregister_thermal(sensor_conf);
422 return ret;
423}
424
425/* Un-Register with the in-kernel thermal management */
426void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf)
427{
428 int i;
429 struct exynos_thermal_zone *th_zone;
430
431 if (!sensor_conf || !sensor_conf->pzone_data) {
432 pr_err("Invalid temperature sensor configuration data\n");
433 return;
434 }
435
436 th_zone = sensor_conf->pzone_data;
437
438 thermal_zone_device_unregister(th_zone->therm_dev);
439
440 for (i = 0; i < th_zone->cool_dev_size; ++i)
441 cpufreq_cooling_unregister(th_zone->cool_dev[i]);
442
443 dev_info(sensor_conf->dev,
444 "Exynos: Kernel Thermal management unregistered\n");
445}
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
deleted file mode 100644
index cd4471925cdd..000000000000
--- a/drivers/thermal/samsung/exynos_thermal_common.h
+++ /dev/null
@@ -1,106 +0,0 @@
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
31#define ACTIVE_INTERVAL 500
32#define IDLE_INTERVAL 10000
33#define MCELSIUS 1000
34
35/* CPU Zone information */
36#define PANIC_ZONE 4
37#define WARN_ZONE 3
38#define MONITOR_ZONE 2
39#define SAFE_ZONE 1
40
41#define GET_ZONE(trip) (trip + 2)
42#define GET_TRIP(zone) (zone - 2)
43
44enum trigger_type {
45 THROTTLE_ACTIVE = 1,
46 THROTTLE_PASSIVE,
47 SW_TRIP,
48 HW_TRIP,
49};
50
51/**
52 * struct freq_clip_table
53 * @freq_clip_max: maximum frequency allowed for this cooling state.
54 * @temp_level: Temperature level at which the temperature clipping will
55 * happen.
56 * @mask_val: cpumask of the allowed cpu's where the clipping will take place.
57 *
58 * This structure is required to be filled and passed to the
59 * cpufreq_cooling_unregister function.
60 */
61struct freq_clip_table {
62 unsigned int freq_clip_max;
63 unsigned int temp_level;
64 const struct cpumask *mask_val;
65};
66
67struct thermal_trip_point_conf {
68 int trip_val[MAX_TRIP_COUNT];
69 int trip_type[MAX_TRIP_COUNT];
70 int trip_count;
71 unsigned char trigger_falling;
72};
73
74struct thermal_cooling_conf {
75 struct freq_clip_table freq_data[MAX_TRIP_COUNT];
76 int freq_clip_count;
77};
78
79struct thermal_sensor_conf {
80 char name[SENSOR_NAME_LEN];
81 int (*read_temperature)(void *data);
82 int (*write_emul_temp)(void *drv_data, unsigned long temp);
83 struct thermal_trip_point_conf trip_data;
84 struct thermal_cooling_conf cooling_data;
85 void *driver_data;
86 void *pzone_data;
87 struct device *dev;
88};
89
90/*Functions used exynos based thermal sensor driver*/
91#ifdef CONFIG_EXYNOS_THERMAL_CORE
92void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf);
93int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
94void exynos_report_trigger(struct thermal_sensor_conf *sensor_conf);
95#else
96static inline void
97exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf) { return; }
98
99static inline int
100exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) { return 0; }
101
102static inline void
103exynos_report_trigger(struct thermal_sensor_conf *sensor_conf) { return; }
104
105#endif /* CONFIG_EXYNOS_THERMAL_CORE */
106#endif /* _EXYNOS_THERMAL_COMMON_H */