summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHyungwoo Yang <hyungwooy@nvidia.com>2012-12-17 14:58:35 -0500
committerNicolin Chen <nicolinc@nvidia.com>2017-08-14 21:38:52 -0400
commitddac309b0749be578488f33d070f42e6a37dfabc (patch)
tree02b6b35aac64dc7ad3a8a73fd2c778181ffc5556
parent7b3c2f179e9a4847e834e79b45b69ffdf429fd14 (diff)
drivers: misc: therm_est: support new thermal framework
Modified thermal estimator to make it compatible with new thermal framework which is backported from kernel 3.7 Bug 1158323 Change-Id: Idad7c07f9da5f68e75d71f0031e4f80f107a22d9 Signed-off-by: Hyungwoo Yang <hyungwooy@nvidia.com> Reviewed-on: http://git-master/r/172470
-rw-r--r--drivers/misc/therm_est.c89
-rw-r--r--include/linux/therm_est.h9
2 files changed, 73 insertions, 25 deletions
diff --git a/drivers/misc/therm_est.c b/drivers/misc/therm_est.c
index 8e6ace29f..654b0f675 100644
--- a/drivers/misc/therm_est.c
+++ b/drivers/misc/therm_est.c
@@ -31,6 +31,7 @@
31#include <linux/thermal.h> 31#include <linux/thermal.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/hwmon-sysfs.h> 33#include <linux/hwmon-sysfs.h>
34#include <linux/suspend.h>
34 35
35struct therm_estimator { 36struct therm_estimator {
36 long cur_temp; 37 long cur_temp;
@@ -42,8 +43,11 @@ struct therm_estimator {
42 int ndevs; 43 int ndevs;
43 struct therm_est_subdevice *devs; 44 struct therm_est_subdevice *devs;
44 struct thermal_zone_device *thz; 45 struct thermal_zone_device *thz;
45 struct thermal_cooling_device *cdev; 46 char *cdev_type;
46 long trip_temp; 47 long trip_temp;
48#ifdef CONFIG_PM
49 struct notifier_block pm_nb;
50#endif
47}; 51};
48 52
49static void therm_est_work_func(struct work_struct *work) 53static void therm_est_work_func(struct work_struct *work)
@@ -88,8 +92,9 @@ static int therm_est_bind(struct thermal_zone_device *thz,
88{ 92{
89 struct therm_estimator *est = thz->devdata; 93 struct therm_estimator *est = thz->devdata;
90 94
91 if (cdev == est->cdev) 95 if (!strcmp(cdev->type, est->cdev_type))
92 thermal_zone_bind_cooling_device(thz, 0, cdev); 96 thermal_zone_bind_cooling_device(thz, 0, cdev,
97 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
93 98
94 return 0; 99 return 0;
95} 100}
@@ -99,7 +104,7 @@ static int therm_est_unbind(struct thermal_zone_device *thz,
99{ 104{
100 struct therm_estimator *est = thz->devdata; 105 struct therm_estimator *est = thz->devdata;
101 106
102 if (cdev == est->cdev) 107 if (!strcmp(cdev->type, est->cdev_type))
103 thermal_zone_unbind_cooling_device(thz, 0, cdev); 108 thermal_zone_unbind_cooling_device(thz, 0, cdev);
104 109
105 return 0; 110 return 0;
@@ -233,7 +238,7 @@ static ssize_t set_offset(struct device *dev,
233} 238}
234 239
235static ssize_t show_temps(struct device *dev, 240static ssize_t show_temps(struct device *dev,
236 struct device_attrbite *da, 241 struct device_attribute *da,
237 char *buf) 242 char *buf)
238{ 243{
239 struct therm_estimator *est = dev_get_drvdata(dev); 244 struct therm_estimator *est = dev_get_drvdata(dev);
@@ -262,12 +267,54 @@ static struct sensor_device_attribute therm_est_nodes[] = {
262 SENSOR_ATTR(temps, S_IRUGO, show_temps, 0, 0), 267 SENSOR_ATTR(temps, S_IRUGO, show_temps, 0, 0),
263}; 268};
264 269
265static int __devinit therm_est_probe(struct platform_device *pdev) 270static int therm_est_init_history(struct therm_estimator *est)
266{ 271{
267 int i, j; 272 int i, j;
273 struct therm_est_subdevice *dev;
268 long temp; 274 long temp;
275
276 for (i = 0; i < est->ndevs; i++) {
277 dev = &est->devs[i];
278
279 if (dev->get_temp(dev->dev_data, &temp))
280 return -EINVAL;
281
282 for (j = 0; j < HIST_LEN; j++)
283 dev->hist[j] = temp;
284 }
285
286 return 0;
287}
288
289#ifdef CONFIG_PM
290static int therm_est_pm_notify(struct notifier_block *nb,
291 unsigned long event, void *data)
292{
293 struct therm_estimator *est = container_of(
294 nb,
295 struct therm_estimator,
296 pm_nb);
297
298 switch (event) {
299 case PM_SUSPEND_PREPARE:
300 cancel_delayed_work_sync(&est->therm_est_work);
301 break;
302 case PM_POST_SUSPEND:
303 therm_est_init_history(est);
304 queue_delayed_work(est->workqueue,
305 &est->therm_est_work,
306 msecs_to_jiffies(est->polling_period));
307 break;
308 }
309
310 return NOTIFY_OK;
311}
312#endif
313
314static int __devinit therm_est_probe(struct platform_device *pdev)
315{
316 int i;
269 struct therm_estimator *est; 317 struct therm_estimator *est;
270 struct therm_est_subdevice *dev;
271 struct therm_est_data *data; 318 struct therm_est_data *data;
272 319
273 est = kzalloc(sizeof(struct therm_estimator), GFP_KERNEL); 320 est = kzalloc(sizeof(struct therm_estimator), GFP_KERNEL);
@@ -284,33 +331,28 @@ static int __devinit therm_est_probe(struct platform_device *pdev)
284 est->polling_period = data->polling_period; 331 est->polling_period = data->polling_period;
285 332
286 /* initialize history */ 333 /* initialize history */
287 for (i = 0; i < data->ndevs; i++) { 334 therm_est_init_history(est);
288 dev = &est->devs[i];
289 335
290 if (dev->get_temp(dev->dev_data, &temp)) 336 est->workqueue = alloc_workqueue(dev_name(&pdev->dev),
291 goto err;
292
293 for (j = 0; j < HIST_LEN; j++)
294 dev->hist[j] = temp;
295 }
296
297 est->workqueue = alloc_workqueue("therm_est",
298 WQ_HIGHPRI | WQ_UNBOUND, 1); 337 WQ_HIGHPRI | WQ_UNBOUND, 1);
338 if (!est->workqueue)
339 goto err;
340
299 INIT_DELAYED_WORK(&est->therm_est_work, therm_est_work_func); 341 INIT_DELAYED_WORK(&est->therm_est_work, therm_est_work_func);
300 342
301 queue_delayed_work(est->workqueue, 343 queue_delayed_work(est->workqueue,
302 &est->therm_est_work, 344 &est->therm_est_work,
303 msecs_to_jiffies(est->polling_period)); 345 msecs_to_jiffies(est->polling_period));
304 346
305 est->cdev = data->cdev;
306 est->trip_temp = data->trip_temp; 347 est->trip_temp = data->trip_temp;
348 est->cdev_type = data->cdev_type;
307 349
308 est->thz = thermal_zone_device_register("therm_est", 350 est->thz = thermal_zone_device_register(dev_name(&pdev->dev),
309 1, 351 1,
352 0x1,
310 est, 353 est,
311 &therm_est_ops, 354 &therm_est_ops,
312 data->tc1, 355 NULL,
313 data->tc2,
314 data->passive_delay, 356 data->passive_delay,
315 0); 357 0);
316 if (IS_ERR_OR_NULL(est->thz)) 358 if (IS_ERR_OR_NULL(est->thz))
@@ -319,6 +361,11 @@ static int __devinit therm_est_probe(struct platform_device *pdev)
319 for (i = 0; i < ARRAY_SIZE(therm_est_nodes); i++) 361 for (i = 0; i < ARRAY_SIZE(therm_est_nodes); i++)
320 device_create_file(&pdev->dev, &therm_est_nodes[i].dev_attr); 362 device_create_file(&pdev->dev, &therm_est_nodes[i].dev_attr);
321 363
364#ifdef CONFIG_PM
365 est->pm_nb.notifier_call = therm_est_pm_notify,
366 register_pm_notifier(&est->pm_nb);
367#endif
368
322 return 0; 369 return 0;
323err: 370err:
324 kfree(est); 371 kfree(est);
diff --git a/include/linux/therm_est.h b/include/linux/therm_est.h
index 29bdf8ba6..8d48ed1db 100644
--- a/include/linux/therm_est.h
+++ b/include/linux/therm_est.h
@@ -31,12 +31,13 @@ struct therm_est_subdevice {
31}; 31};
32 32
33struct therm_est_data { 33struct therm_est_data {
34 /* trip point info : there's only 1 trip point */
35 char *cdev_type; /* cooling device for this trip */
36 long trip_temp;
37
38 /* zone parameters */
34 long toffset; 39 long toffset;
35 long polling_period; 40 long polling_period;
36 struct thermal_cooling_device *cdev;
37 long trip_temp;
38 int tc1;
39 int tc2;
40 int passive_delay; 41 int passive_delay;
41 int ndevs; 42 int ndevs;
42 struct therm_est_subdevice devs[]; 43 struct therm_est_subdevice devs[];