Blame view

drivers/thermal/samsung/exynos_thermal_common.c 11.4 KB
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  /*
   * exynos_thermal_common.c - Samsung EXYNOS common thermal file
   *
   *  Copyright (C) 2013 Samsung Electronics
   *  Amit Daniel Kachhap <amit.daniel@samsung.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   *
   */
  
  #include <linux/cpu_cooling.h>
  #include <linux/err.h>
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  #include <linux/slab.h>
  #include <linux/thermal.h>
  
  #include "exynos_thermal_common.h"
  
  struct exynos_thermal_zone {
  	enum thermal_device_mode mode;
  	struct thermal_zone_device *therm_dev;
  	struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
  	unsigned int cool_dev_size;
  	struct platform_device *exynos4_dev;
  	struct thermal_sensor_conf *sensor_conf;
  	bool bind;
  };
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
39
40
41
42
  /* Get mode callback functions for thermal zone */
  static int exynos_get_mode(struct thermal_zone_device *thermal,
  			enum thermal_device_mode *mode)
  {
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
43
  	struct exynos_thermal_zone *th_zone = thermal->devdata;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
44
45
46
47
48
49
50
51
52
  	if (th_zone)
  		*mode = th_zone->mode;
  	return 0;
  }
  
  /* Set mode callback functions for thermal zone */
  static int exynos_set_mode(struct thermal_zone_device *thermal,
  			enum thermal_device_mode mode)
  {
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
53
54
  	struct exynos_thermal_zone *th_zone = thermal->devdata;
  	if (!th_zone) {
91ff81cf4   Sachin Kamat   thermal: exynos: ...
55
  		dev_err(&thermal->device,
c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
56
57
  			"thermal zone not registered
  ");
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
58
59
  		return 0;
  	}
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
60
  	mutex_lock(&thermal->lock);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
61
62
63
  
  	if (mode == THERMAL_DEVICE_ENABLED &&
  		!th_zone->sensor_conf->trip_data.trigger_falling)
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
64
  		thermal->polling_delay = IDLE_INTERVAL;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
65
  	else
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
66
  		thermal->polling_delay = 0;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
67

4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
68
  	mutex_unlock(&thermal->lock);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
69
70
  
  	th_zone->mode = mode;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
71
  	thermal_zone_device_update(thermal);
c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
72
73
74
75
  	dev_dbg(th_zone->sensor_conf->dev,
  		"thermal polling set for duration=%d msec
  ",
  		thermal->polling_delay);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
76
77
78
79
80
81
82
83
  	return 0;
  }
  
  
  /* Get trip type callback functions for thermal zone */
  static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
  				 enum thermal_trip_type *type)
  {
5c3cf5527   Amit Daniel Kachhap   thermal: exynos: ...
84
85
86
87
88
89
90
91
92
93
  	struct exynos_thermal_zone *th_zone = thermal->devdata;
  	int max_trip = th_zone->sensor_conf->trip_data.trip_count;
  	int trip_type;
  
  	if (trip < 0 || trip >= max_trip)
  		return -EINVAL;
  
  	trip_type = th_zone->sensor_conf->trip_data.trip_type[trip];
  
  	if (trip_type == SW_TRIP)
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
94
  		*type = THERMAL_TRIP_CRITICAL;
5c3cf5527   Amit Daniel Kachhap   thermal: exynos: ...
95
96
97
98
99
  	else if (trip_type == THROTTLE_ACTIVE)
  		*type = THERMAL_TRIP_ACTIVE;
  	else if (trip_type == THROTTLE_PASSIVE)
  		*type = THERMAL_TRIP_PASSIVE;
  	else
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
100
  		return -EINVAL;
5c3cf5527   Amit Daniel Kachhap   thermal: exynos: ...
101

1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
102
103
104
105
106
107
108
  	return 0;
  }
  
  /* Get trip temperature callback functions for thermal zone */
  static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
  				unsigned long *temp)
  {
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
109
  	struct exynos_thermal_zone *th_zone = thermal->devdata;
5c3cf5527   Amit Daniel Kachhap   thermal: exynos: ...
110
  	int max_trip = th_zone->sensor_conf->trip_data.trip_count;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
111

5c3cf5527   Amit Daniel Kachhap   thermal: exynos: ...
112
  	if (trip < 0 || trip >= max_trip)
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
113
114
115
116
117
118
119
120
121
122
123
124
125
  		return -EINVAL;
  
  	*temp = th_zone->sensor_conf->trip_data.trip_val[trip];
  	/* convert the temperature into millicelsius */
  	*temp = *temp * MCELSIUS;
  
  	return 0;
  }
  
  /* Get critical temperature callback functions for thermal zone */
  static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
  				unsigned long *temp)
  {
5c3cf5527   Amit Daniel Kachhap   thermal: exynos: ...
126
127
128
129
  	struct exynos_thermal_zone *th_zone = thermal->devdata;
  	int max_trip = th_zone->sensor_conf->trip_data.trip_count;
  	/* Get the temp of highest trip*/
  	return exynos_get_trip_temp(thermal, max_trip - 1, temp);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
130
131
132
133
134
135
136
137
  }
  
  /* Bind callback functions for thermal zone */
  static int exynos_bind(struct thermal_zone_device *thermal,
  			struct thermal_cooling_device *cdev)
  {
  	int ret = 0, i, tab_size, level;
  	struct freq_clip_table *tab_ptr, *clip_data;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
138
  	struct exynos_thermal_zone *th_zone = thermal->devdata;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
139
140
141
142
143
144
  	struct thermal_sensor_conf *data = th_zone->sensor_conf;
  
  	tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
  	tab_size = data->cooling_data.freq_clip_count;
  
  	if (tab_ptr == NULL || tab_size == 0)
23a3eb106   Amit Daniel Kachhap   thermal: exynos: ...
145
  		return 0;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  
  	/* find the cooling device registered*/
  	for (i = 0; i < th_zone->cool_dev_size; i++)
  		if (cdev == th_zone->cool_dev[i])
  			break;
  
  	/* No matching cooling device */
  	if (i == th_zone->cool_dev_size)
  		return 0;
  
  	/* Bind the thermal zone to the cpufreq cooling device */
  	for (i = 0; i < tab_size; i++) {
  		clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
  		level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
  		if (level == THERMAL_CSTATE_INVALID)
  			return 0;
  		switch (GET_ZONE(i)) {
  		case MONITOR_ZONE:
  		case WARN_ZONE:
  			if (thermal_zone_bind_cooling_device(thermal, i, cdev,
  								level, 0)) {
c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
167
168
169
  				dev_err(data->dev,
  					"error unbinding cdev inst=%d
  ", i);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  				ret = -EINVAL;
  			}
  			th_zone->bind = true;
  			break;
  		default:
  			ret = -EINVAL;
  		}
  	}
  
  	return ret;
  }
  
  /* Unbind callback functions for thermal zone */
  static int exynos_unbind(struct thermal_zone_device *thermal,
  			struct thermal_cooling_device *cdev)
  {
  	int ret = 0, i, tab_size;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
187
  	struct exynos_thermal_zone *th_zone = thermal->devdata;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
188
189
190
191
192
193
194
195
  	struct thermal_sensor_conf *data = th_zone->sensor_conf;
  
  	if (th_zone->bind == false)
  		return 0;
  
  	tab_size = data->cooling_data.freq_clip_count;
  
  	if (tab_size == 0)
23a3eb106   Amit Daniel Kachhap   thermal: exynos: ...
196
  		return 0;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  
  	/* find the cooling device registered*/
  	for (i = 0; i < th_zone->cool_dev_size; i++)
  		if (cdev == th_zone->cool_dev[i])
  			break;
  
  	/* No matching cooling device */
  	if (i == th_zone->cool_dev_size)
  		return 0;
  
  	/* Bind the thermal zone to the cpufreq cooling device */
  	for (i = 0; i < tab_size; i++) {
  		switch (GET_ZONE(i)) {
  		case MONITOR_ZONE:
  		case WARN_ZONE:
  			if (thermal_zone_unbind_cooling_device(thermal, i,
  								cdev)) {
c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
214
215
216
  				dev_err(data->dev,
  					"error unbinding cdev inst=%d
  ", i);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  				ret = -EINVAL;
  			}
  			th_zone->bind = false;
  			break;
  		default:
  			ret = -EINVAL;
  		}
  	}
  	return ret;
  }
  
  /* Get temperature callback functions for thermal zone */
  static int exynos_get_temp(struct thermal_zone_device *thermal,
  			unsigned long *temp)
  {
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
232
  	struct exynos_thermal_zone *th_zone = thermal->devdata;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
233
234
235
  	void *data;
  
  	if (!th_zone->sensor_conf) {
91ff81cf4   Sachin Kamat   thermal: exynos: ...
236
  		dev_err(&thermal->device,
c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
237
238
  			"Temperature sensor not initialised
  ");
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
239
240
  		return -EINVAL;
  	}
d58f0a6d8   Amit Daniel Kachhap   thermal: exynos: ...
241
  	data = th_zone->sensor_conf->driver_data;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
242
243
244
245
246
247
248
249
250
251
252
253
  	*temp = th_zone->sensor_conf->read_temperature(data);
  	/* convert the temperature into millicelsius */
  	*temp = *temp * MCELSIUS;
  	return 0;
  }
  
  /* Get temperature callback functions for thermal zone */
  static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
  						unsigned long temp)
  {
  	void *data;
  	int ret = -EINVAL;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
254
  	struct exynos_thermal_zone *th_zone = thermal->devdata;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
255
256
  
  	if (!th_zone->sensor_conf) {
91ff81cf4   Sachin Kamat   thermal: exynos: ...
257
  		dev_err(&thermal->device,
c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
258
259
  			"Temperature sensor not initialised
  ");
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
260
261
  		return -EINVAL;
  	}
d58f0a6d8   Amit Daniel Kachhap   thermal: exynos: ...
262
  	data = th_zone->sensor_conf->driver_data;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  	if (th_zone->sensor_conf->write_emul_temp)
  		ret = th_zone->sensor_conf->write_emul_temp(data, temp);
  	return ret;
  }
  
  /* Get the temperature trend */
  static int exynos_get_trend(struct thermal_zone_device *thermal,
  			int trip, enum thermal_trend *trend)
  {
  	int ret;
  	unsigned long trip_temp;
  
  	ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
  	if (ret < 0)
  		return ret;
  
  	if (thermal->temperature >= trip_temp)
  		*trend = THERMAL_TREND_RAISE_FULL;
  	else
  		*trend = THERMAL_TREND_DROP_FULL;
  
  	return 0;
  }
  /* Operation callback functions for thermal zone */
b688b5bf8   Naveen Krishna Chatradhi   thermal:samsung: ...
287
  static struct thermal_zone_device_ops exynos_dev_ops = {
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
  	.bind = exynos_bind,
  	.unbind = exynos_unbind,
  	.get_temp = exynos_get_temp,
  	.set_emul_temp = exynos_set_emul_temp,
  	.get_trend = exynos_get_trend,
  	.get_mode = exynos_get_mode,
  	.set_mode = exynos_set_mode,
  	.get_trip_type = exynos_get_trip_type,
  	.get_trip_temp = exynos_get_trip_temp,
  	.get_crit_temp = exynos_get_crit_temp,
  };
  
  /*
   * This function may be called from interrupt based temperature sensor
   * when threshold is changed.
   */
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
304
  void exynos_report_trigger(struct thermal_sensor_conf *conf)
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
305
306
307
308
  {
  	unsigned int i;
  	char data[10];
  	char *envp[] = { data, NULL };
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
309
  	struct exynos_thermal_zone *th_zone;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
310

4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
311
312
313
  	if (!conf || !conf->pzone_data) {
  		pr_err("Invalid temperature sensor configuration data
  ");
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
314
  		return;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
315
316
317
  	}
  
  	th_zone = conf->pzone_data;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
318

1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
  	if (th_zone->bind == false) {
  		for (i = 0; i < th_zone->cool_dev_size; i++) {
  			if (!th_zone->cool_dev[i])
  				continue;
  			exynos_bind(th_zone->therm_dev,
  					th_zone->cool_dev[i]);
  		}
  	}
  
  	thermal_zone_device_update(th_zone->therm_dev);
  
  	mutex_lock(&th_zone->therm_dev->lock);
  	/* Find the level for which trip happened */
  	for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
  		if (th_zone->therm_dev->last_temperature <
  			th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
  			break;
  	}
  
  	if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
  		!th_zone->sensor_conf->trip_data.trigger_falling) {
  		if (i > 0)
  			th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
  		else
  			th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
  	}
  
  	snprintf(data, sizeof(data), "%u", i);
  	kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
  	mutex_unlock(&th_zone->therm_dev->lock);
  }
  
  /* Register with the in-kernel thermal management */
  int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
  {
  	int ret;
  	struct cpumask mask_val;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
356
  	struct exynos_thermal_zone *th_zone;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
357
358
359
360
361
362
  
  	if (!sensor_conf || !sensor_conf->read_temperature) {
  		pr_err("Temperature sensor not initialised
  ");
  		return -EINVAL;
  	}
c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
363
364
  	th_zone = devm_kzalloc(sensor_conf->dev,
  				sizeof(struct exynos_thermal_zone), GFP_KERNEL);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
365
366
367
368
  	if (!th_zone)
  		return -ENOMEM;
  
  	th_zone->sensor_conf = sensor_conf;
5c3cf5527   Amit Daniel Kachhap   thermal: exynos: ...
369
370
371
372
373
374
375
376
377
378
  	/*
  	 * TODO: 1) Handle multiple cooling devices in a thermal zone
  	 *	 2) Add a flag/name in cooling info to map to specific
  	 *	 sensor
  	 */
  	if (sensor_conf->cooling_data.freq_clip_count > 0) {
  		cpumask_set_cpu(0, &mask_val);
  		th_zone->cool_dev[th_zone->cool_dev_size] =
  					cpufreq_cooling_register(&mask_val);
  		if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) {
c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
379
380
381
  			dev_err(sensor_conf->dev,
  				"Failed to register cpufreq cooling device
  ");
5c3cf5527   Amit Daniel Kachhap   thermal: exynos: ...
382
383
384
385
  			ret = -EINVAL;
  			goto err_unregister;
  		}
  		th_zone->cool_dev_size++;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
386
  	}
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
387

5c3cf5527   Amit Daniel Kachhap   thermal: exynos: ...
388
389
390
391
392
  	th_zone->therm_dev = thermal_zone_device_register(
  			sensor_conf->name, sensor_conf->trip_data.trip_count,
  			0, th_zone, &exynos_dev_ops, NULL, 0,
  			sensor_conf->trip_data.trigger_falling ? 0 :
  			IDLE_INTERVAL);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
393
394
  
  	if (IS_ERR(th_zone->therm_dev)) {
c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
395
396
397
  		dev_err(sensor_conf->dev,
  			"Failed to register thermal zone device
  ");
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
398
399
400
401
  		ret = PTR_ERR(th_zone->therm_dev);
  		goto err_unregister;
  	}
  	th_zone->mode = THERMAL_DEVICE_ENABLED;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
402
  	sensor_conf->pzone_data = th_zone;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
403

c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
404
405
406
  	dev_info(sensor_conf->dev,
  		"Exynos: Thermal zone(%s) registered
  ", sensor_conf->name);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
407
408
409
410
  
  	return 0;
  
  err_unregister:
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
411
  	exynos_unregister_thermal(sensor_conf);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
412
413
414
415
  	return ret;
  }
  
  /* Un-Register with the in-kernel thermal management */
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
416
  void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf)
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
417
418
  {
  	int i;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
419
  	struct exynos_thermal_zone *th_zone;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
420

4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
421
422
423
  	if (!sensor_conf || !sensor_conf->pzone_data) {
  		pr_err("Invalid temperature sensor configuration data
  ");
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
424
  		return;
4de0bdaa9   Amit Daniel Kachhap   thermal: exynos: ...
425
426
427
  	}
  
  	th_zone = sensor_conf->pzone_data;
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
428

d3e19567f   Markus Elfring   thermal: Exynos: ...
429
  	thermal_zone_device_unregister(th_zone->therm_dev);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
430

d3e19567f   Markus Elfring   thermal: Exynos: ...
431
432
  	for (i = 0; i < th_zone->cool_dev_size; ++i)
  		cpufreq_cooling_unregister(th_zone->cool_dev[i]);
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
433

c55930e33   Amit Daniel Kachhap   thermal: exynos: ...
434
435
436
  	dev_info(sensor_conf->dev,
  		"Exynos: Kernel Thermal management unregistered
  ");
1b678641c   Amit Daniel Kachhap   thermal: exynos: ...
437
  }