diff options
| author | Hyungwoo Yang <hyungwooy@nvidia.com> | 2012-12-17 14:58:35 -0500 |
|---|---|---|
| committer | Nicolin Chen <nicolinc@nvidia.com> | 2017-08-14 21:38:52 -0400 |
| commit | ddac309b0749be578488f33d070f42e6a37dfabc (patch) | |
| tree | 02b6b35aac64dc7ad3a8a73fd2c778181ffc5556 | |
| parent | 7b3c2f179e9a4847e834e79b45b69ffdf429fd14 (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.c | 89 | ||||
| -rw-r--r-- | include/linux/therm_est.h | 9 |
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 | ||
| 35 | struct therm_estimator { | 36 | struct 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 | ||
| 49 | static void therm_est_work_func(struct work_struct *work) | 53 | static 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 | ||
| 235 | static ssize_t show_temps(struct device *dev, | 240 | static 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 | ||
| 265 | static int __devinit therm_est_probe(struct platform_device *pdev) | 270 | static 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 | ||
| 290 | static 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 | |||
| 314 | static 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; |
| 323 | err: | 370 | err: |
| 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 | ||
| 33 | struct therm_est_data { | 33 | struct 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[]; |
