drivers:misc: Setup gamepad_reset gpio only on loki
[linux-3.10.git] / drivers / misc / therm_fan_est.c
1 /*
2  * drivers/misc/therm_fan_est.c
3  *
4  * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 #include <linux/platform_device.h>
18 #include <linux/kernel.h>
19 #include <linux/cpufreq.h>
20 #include <linux/delay.h>
21 #include <linux/mutex.h>
22 #include <linux/init.h>
23 #include <linux/err.h>
24 #include <linux/clk.h>
25 #include <linux/debugfs.h>
26 #include <linux/seq_file.h>
27 #include <linux/uaccess.h>
28 #include <linux/slab.h>
29 #include <linux/syscalls.h>
30 #include <linux/therm_est.h>
31 #include <linux/thermal.h>
32 #include <linux/module.h>
33 #include <linux/hwmon-sysfs.h>
34
35 #define DEFERRED_RESUME_TIME 3000
36 #define DEBUG 0
37 struct therm_fan_estimator {
38         long cur_temp;
39 #if DEBUG
40         long cur_temp_debug;
41 #endif
42         long polling_period;
43         struct workqueue_struct *workqueue;
44         struct delayed_work therm_fan_est_work;
45         long toffset;
46         int ntemp;
47         int ndevs;
48         struct therm_fan_est_subdevice *devs;
49         struct thermal_zone_device *thz;
50         int current_trip_index;
51         const char *cdev_type;
52         int active_trip_temps[MAX_ACTIVE_STATES];
53         int active_hysteresis[MAX_ACTIVE_STATES];
54         int active_trip_temps_hyst[(MAX_ACTIVE_STATES << 1) + 1];
55         struct thermal_zone_params *tzp;
56         int num_resources;
57         int trip_length;
58         const char *name;
59 };
60
61
62 static void fan_set_trip_temp_hyst(struct therm_fan_estimator *est, int trip,
63                                                         unsigned long hyst_temp,
64                                                         unsigned long trip_temp)
65 {
66         est->active_hysteresis[trip] = hyst_temp;
67         est->active_trip_temps[trip] = trip_temp;
68         est->active_trip_temps_hyst[(trip << 1)] = trip_temp;
69         est->active_trip_temps_hyst[((trip - 1) << 1) + 1] =
70                                                 trip_temp - hyst_temp;
71 }
72
73 static void therm_fan_est_work_func(struct work_struct *work)
74 {
75         int i, j, index, trip_index, sum = 0;
76         long temp = 0;
77         struct delayed_work *dwork = container_of(work,
78                                         struct delayed_work, work);
79         struct therm_fan_estimator *est = container_of(
80                                         dwork,
81                                         struct therm_fan_estimator,
82                                         therm_fan_est_work);
83         for (i = 0; i < est->ndevs; i++) {
84                 if (est->devs[i].get_temp(est->devs[i].dev_data, &temp))
85                         continue;
86                 est->devs[i].hist[(est->ntemp % HIST_LEN)] = temp;
87         }
88
89         for (i = 0; i < est->ndevs; i++) {
90                 for (j = 0; j < HIST_LEN; j++) {
91                         index = (est->ntemp - j + HIST_LEN) % HIST_LEN;
92                         sum += est->devs[i].hist[index] *
93                                 est->devs[i].coeffs[j];
94                 }
95         }
96 #if !DEBUG
97         est->cur_temp = sum / 100 + est->toffset;
98 #else
99         est->cur_temp = est->cur_temp_debug;
100 #endif
101         for (trip_index = 0;
102                 trip_index < ((MAX_ACTIVE_STATES << 1) + 1); trip_index++) {
103                 if (est->cur_temp < est->active_trip_temps_hyst[trip_index])
104                         break;
105         }
106         if (est->current_trip_index != (trip_index - 1)) {
107                 if (!((trip_index - 1) % 2) || (!est->current_trip_index) ||
108                         ((trip_index - est->current_trip_index) >= 2) ||
109                         ((trip_index - est->current_trip_index) <= -2)) {
110                         pr_debug("%s, cur_temp:%ld, cur_trip_index:%d\n",
111                         __func__, est->cur_temp, est->current_trip_index);
112                         thermal_zone_device_update(est->thz);
113                 }
114                 est->current_trip_index = trip_index - 1;
115         }
116
117         est->ntemp++;
118         queue_delayed_work(est->workqueue, &est->therm_fan_est_work,
119                                 msecs_to_jiffies(est->polling_period));
120 }
121
122 static int therm_fan_est_bind(struct thermal_zone_device *thz,
123                                 struct thermal_cooling_device *cdev)
124 {
125         int i;
126         struct therm_fan_estimator *est = thz->devdata;
127         if (!strcmp(cdev->type, est->cdev_type)) {
128                 for (i = 0; i < MAX_ACTIVE_STATES; i++)
129                         thermal_zone_bind_cooling_device(thz, i, cdev, i, i);
130         }
131
132         return 0;
133 }
134
135 static int therm_fan_est_unbind(struct thermal_zone_device *thz,
136                                 struct thermal_cooling_device *cdev)
137 {
138         int i;
139         struct therm_fan_estimator *est = thz->devdata;
140         if (!strcmp(cdev->type, est->cdev_type)) {
141                 for (i = 0; i < MAX_ACTIVE_STATES; i++)
142                         thermal_zone_unbind_cooling_device(thz, i, cdev);
143         }
144
145         return 0;
146 }
147
148 static int therm_fan_est_get_trip_type(struct thermal_zone_device *thz,
149                                         int trip,
150                                         enum thermal_trip_type *type)
151 {
152         *type = THERMAL_TRIP_ACTIVE;
153         return 0;
154 }
155
156 static int therm_fan_est_get_trip_temp(struct thermal_zone_device *thz,
157                                         int trip, long *temp)
158 {
159         struct therm_fan_estimator *est = thz->devdata;
160
161         if (est->current_trip_index == 0)
162                 *temp = 0;
163
164         if (trip * 2 <= est->current_trip_index) /* tripped then lower */
165                 *temp = est->active_trip_temps_hyst[trip * 2 - 1];
166         else /* not tripped, then upper */
167                 *temp = est->active_trip_temps_hyst[trip * 2];
168
169         return 0;
170 }
171
172 static int therm_fan_est_set_trip_temp(struct thermal_zone_device *thz,
173                                         int trip, long temp)
174 {
175         struct therm_fan_estimator *est = thz->devdata;
176
177         /*Need trip 0 to remain as it is*/
178         if (((temp - est->active_hysteresis[trip]) < 0) || (trip <= 0))
179                 return -EINVAL;
180
181         fan_set_trip_temp_hyst(est, trip, est->active_hysteresis[trip], temp);
182         return 0;
183 }
184
185 static int therm_fan_est_get_temp(struct thermal_zone_device *thz, long *temp)
186 {
187         struct therm_fan_estimator *est = thz->devdata;
188
189         *temp = est->cur_temp;
190         return 0;
191 }
192
193 static int therm_fan_est_set_trip_hyst(struct thermal_zone_device *thz,
194                                 int trip, long hyst_temp)
195 {
196         struct therm_fan_estimator *est = thz->devdata;
197
198         /*Need trip 0 to remain as it is*/
199         if ((est->active_trip_temps[trip] - hyst_temp) < 0 || trip <= 0)
200                 return -EINVAL;
201
202         fan_set_trip_temp_hyst(est, trip,
203                         hyst_temp, est->active_trip_temps[trip]);
204         return 0;
205 }
206
207 static int therm_fan_est_get_trip_hyst(struct thermal_zone_device *thz,
208                                 int trip, long *temp)
209 {
210         struct therm_fan_estimator *est = thz->devdata;
211
212         *temp = est->active_hysteresis[trip];
213         return 0;
214 }
215
216 static struct thermal_zone_device_ops therm_fan_est_ops = {
217         .bind = therm_fan_est_bind,
218         .unbind = therm_fan_est_unbind,
219         .get_trip_type = therm_fan_est_get_trip_type,
220         .get_trip_temp = therm_fan_est_get_trip_temp,
221         .get_temp = therm_fan_est_get_temp,
222         .set_trip_temp = therm_fan_est_set_trip_temp,
223         .get_trip_hyst = therm_fan_est_get_trip_hyst,
224         .set_trip_hyst = therm_fan_est_set_trip_hyst,
225 };
226
227 static ssize_t show_coeff(struct device *dev,
228                                 struct device_attribute *da,
229                                 char *buf)
230 {
231         struct therm_fan_estimator *est = dev_get_drvdata(dev);
232         ssize_t len, total_len = 0;
233         int i, j;
234
235         for (i = 0; i < est->ndevs; i++) {
236                 len = snprintf(buf + total_len, PAGE_SIZE, "[%d]", i);
237                 total_len += len;
238                 for (j = 0; j < HIST_LEN; j++) {
239                         len = snprintf(buf + total_len, PAGE_SIZE, " %d",
240                                         est->devs[i].coeffs[j]);
241                         total_len += len;
242                 }
243                 len = snprintf(buf + total_len, PAGE_SIZE, "\n");
244                 total_len += len;
245         }
246         return strlen(buf);
247 }
248
249 static ssize_t set_coeff(struct device *dev,
250                                 struct device_attribute *da,
251                                 const char *buf, size_t count)
252 {
253         struct therm_fan_estimator *est = dev_get_drvdata(dev);
254         int devid, scount;
255         long coeff[20];
256
257         if (HIST_LEN > 20)
258                 return -EINVAL;
259
260         scount = sscanf(buf, "[%d] %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld " \
261                         "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
262                         &devid, &coeff[0], &coeff[1], &coeff[2], &coeff[3],
263                         &coeff[4], &coeff[5], &coeff[6], &coeff[7], &coeff[8],
264                         &coeff[9], &coeff[10], &coeff[11], &coeff[12],
265                         &coeff[13], &coeff[14], &coeff[15], &coeff[16],
266                         &coeff[17], &coeff[18], &coeff[19]);
267
268         if (scount != HIST_LEN + 1)
269                 return -1;
270
271         if (devid < 0 || devid >= est->ndevs)
272                 return -EINVAL;
273
274         /* This has obvious locking issues but don't worry about it */
275         memcpy(est->devs[devid].coeffs, coeff, sizeof(long) * HIST_LEN);
276
277         return count;
278 }
279
280 static ssize_t show_offset(struct device *dev,
281                                 struct device_attribute *da,
282                                 char *buf)
283 {
284         struct therm_fan_estimator *est = dev_get_drvdata(dev);
285
286         snprintf(buf, PAGE_SIZE, "%ld\n", est->toffset);
287         return strlen(buf);
288 }
289
290 static ssize_t set_offset(struct device *dev,
291                                 struct device_attribute *da,
292                                 const char *buf, size_t count)
293 {
294         struct therm_fan_estimator *est = dev_get_drvdata(dev);
295         int offset;
296
297         if (kstrtoint(buf, 0, &offset))
298                 return -EINVAL;
299
300         est->toffset = offset;
301
302         return count;
303 }
304
305 static ssize_t show_temps(struct device *dev,
306                                 struct device_attribute *da,
307                                 char *buf)
308 {
309         struct therm_fan_estimator *est = dev_get_drvdata(dev);
310         ssize_t total_len = 0;
311         int i, j;
312         int index;
313
314         /* This has obvious locking issues but don't worry about it */
315         for (i = 0; i < est->ndevs; i++) {
316                 total_len += snprintf(buf + total_len, PAGE_SIZE, "[%d]", i);
317                 for (j = 0; j < HIST_LEN; j++) {
318                         index = (est->ntemp - j + HIST_LEN) % HIST_LEN;
319                         total_len += snprintf(buf + total_len,
320                                                 PAGE_SIZE,
321                                                 " %d",
322                                                 est->devs[i].hist[index]);
323                 }
324                 total_len += snprintf(buf + total_len, PAGE_SIZE, "\n");
325         }
326         return strlen(buf);
327 }
328
329 #if DEBUG
330 static ssize_t set_temps(struct device *dev,
331                                 struct device_attribute *da,
332                                 const char *buf, size_t count)
333 {
334         struct therm_fan_estimator *est = dev_get_drvdata(dev);
335         int temp;
336
337         if (kstrtoint(buf, 0, &temp))
338                 return -EINVAL;
339
340         est->cur_temp_debug = temp;
341
342         return count;
343 }
344 #endif
345
346 static struct sensor_device_attribute therm_fan_est_nodes[] = {
347         SENSOR_ATTR(coeff, S_IRUGO | S_IWUSR, show_coeff, set_coeff, 0),
348         SENSOR_ATTR(offset, S_IRUGO | S_IWUSR, show_offset, set_offset, 0),
349 #if DEBUG
350         SENSOR_ATTR(temps, S_IRUGO | S_IWUSR, show_temps, set_temps, 0),
351 #else
352         SENSOR_ATTR(temps, S_IRUGO, show_temps, 0, 0),
353 #endif
354 };
355
356
357 static int fan_est_match(struct thermal_zone_device *thz, void *data)
358 {
359         return (strcmp((char *)data, thz->type) == 0);
360 }
361
362 static int fan_est_get_temp_func(const char *data, long *temp)
363 {
364         struct thermal_zone_device *thz;
365
366         thz = thermal_zone_device_find((void *)data, fan_est_match);
367
368         if (!thz || thz->ops->get_temp == NULL || thz->ops->get_temp(thz, temp))
369                 *temp = 25000;
370
371         return 0;
372 }
373
374
375 static int therm_fan_est_probe(struct platform_device *pdev)
376 {
377         int i, j;
378         long temp;
379         int err = 0;
380         int of_err = 0;
381         struct therm_fan_estimator *est_data;
382         struct therm_fan_est_subdevice *subdevs;
383         struct therm_fan_est_subdevice *dev;
384         struct thermal_zone_params *tzp;
385         struct device_node *node = NULL;
386         struct device_node *data_node = NULL;
387         int child_count = 0;
388         struct device_node *child = NULL;
389         const char *gov_name;
390         u32 value;
391
392         pr_info("THERMAL EST start of therm_fan_est_probe.\n");
393         if (!pdev)
394                 return -EINVAL;
395
396         node = pdev->dev.of_node;
397         if (!node) {
398                 pr_err("THERMAL EST: dev of_node NULL\n");
399                 return -EINVAL;
400         }
401
402         data_node = of_parse_phandle(node, "shared_data", 0);
403         if (!data_node) {
404                 pr_err("THERMAL EST shared data node parsing failed\n");
405                 return -EINVAL;
406         }
407
408         child_count = of_get_child_count(data_node);
409         of_err |= of_property_read_u32(data_node, "ndevs", &value);
410         if (of_err) {
411                 pr_err("THERMAL EST: missing ndevs\n");
412                 return -ENXIO;
413         }
414         if (child_count != (int)value) {
415                 pr_err("THERMAL EST: ndevs count mismatch\n");
416                 return -EINVAL;
417         }
418
419         est_data = devm_kzalloc(&pdev->dev,
420                                 sizeof(struct therm_fan_estimator), GFP_KERNEL);
421         if (IS_ERR_OR_NULL(est_data))
422                 return -ENOMEM;
423
424         est_data->ndevs = child_count;
425         pr_info("THERMAL EST: found %d subdevs\n", est_data->ndevs);
426
427         of_err |= of_property_read_string(node, "name", &est_data->name);
428         if (of_err) {
429                 pr_err("THERMAL EST: name is missing\n");
430                 err = -ENXIO;
431                 goto free_est;
432         }
433         pr_info("THERMAL EST name: %s.\n", est_data->name);
434
435         of_err |= of_property_read_u32(node, "num_resources", &value);
436         if (of_err) {
437                 pr_err("THERMAL EST: num_resources is missing\n");
438                 err = -ENXIO;
439                 goto free_est;
440         }
441         est_data->num_resources = value;
442         pr_info("THERMAL EST num_resources: %d\n", est_data->num_resources);
443
444         of_err |= of_property_read_u32(node, "trip_length", &value);
445         if (of_err) {
446                 pr_err("THERMAL EST: missing trip length\n");
447                 err = -ENXIO;
448                 goto free_est;
449         }
450
451         est_data->trip_length = (int)value;
452         subdevs = devm_kzalloc(&pdev->dev,
453                         child_count * sizeof(struct therm_fan_est_subdevice),
454                         GFP_KERNEL);
455         if (IS_ERR_OR_NULL(subdevs)) {
456                 err = -ENOMEM;
457                 goto free_est;
458         }
459
460         /* initialize subdevs */
461         j = 0;
462         for_each_child_of_node(data_node, child) {
463                 pr_info("[THERMAL EST subdev %d]\n", j);
464                 of_err |= of_property_read_string(child, "dev_data",
465                                                 &subdevs[j].dev_data);
466                 if (of_err) {
467                         pr_err("THERMAL EST subdev[%d] dev_data missed\n", j);
468                         err = -ENXIO;
469                         goto free_subdevs;
470                 }
471                 pr_info("THERMAL EST subdev name: %s\n",
472                                 (char *)subdevs[j].dev_data);
473
474                 subdevs[j].get_temp = &fan_est_get_temp_func;
475
476                 of_err |= of_property_read_u32_array(child, "coeffs",
477                         subdevs[j].coeffs, est_data->trip_length);
478                 for (i = 0; i < est_data->trip_length; i++)
479                         pr_info("THERMAL EST index %d coeffs %d\n",
480                                 i, subdevs[j].coeffs[i]);
481                 j++;
482         }
483         est_data->devs = subdevs;
484
485         of_err |= of_property_read_u32(data_node, "toffset", &value);
486         if (of_err) {
487                 pr_err("THERMAL EST: missing toffset\n");
488                 err = -ENXIO;
489                 goto free_subdevs;
490         }
491         est_data->toffset = (long)value;
492
493         of_err |= of_property_read_u32(data_node, "polling_period", &value);
494         if (of_err) {
495                 pr_err("THERMAL EST: missing polling_period\n");
496                 err = -ENXIO;
497                 goto free_subdevs;
498         }
499         est_data->polling_period = (long)value;
500
501         of_err |= of_property_read_u32_array(node, "active_trip_temps",
502                 est_data->active_trip_temps, (size_t) est_data->trip_length);
503         if (of_err) {
504                 pr_err("THERMAL EST: active trip temps failed to parse.\n");
505                 err = -ENXIO;
506                 goto free_subdevs;
507         }
508
509         of_err |= of_property_read_u32_array(node, "active_hysteresis",
510                 est_data->active_hysteresis, (size_t) est_data->trip_length);
511         if (of_err) {
512                 pr_err("THERMAL EST: active hysteresis failed to parse.\n");
513                 err = -ENXIO;
514                 goto free_subdevs;
515         }
516
517         for (i = 0; i < est_data->trip_length; i++)
518                 pr_info("THERMAL EST index %d: trip_temp %d, hyst %d\n",
519                         i, est_data->active_trip_temps[i],
520                         est_data->active_hysteresis[i]);
521
522         est_data->active_trip_temps_hyst[0] = est_data->active_trip_temps[0];
523         for (i = 1; i < MAX_ACTIVE_STATES; i++)
524                 fan_set_trip_temp_hyst(est_data, i,
525                         est_data->active_hysteresis[i],
526                         est_data->active_trip_temps[i]);
527         for (i = 0; i < (MAX_ACTIVE_STATES << 1) + 1; i++)
528                 pr_info("THERMAL EST index %d: trip_temps_hyst %d\n",
529                         i, est_data->active_trip_temps_hyst[i]);
530
531         for (i = 0; i < est_data->ndevs; i++) {
532                 dev = &est_data->devs[i];
533                 if (dev->get_temp(dev->dev_data, &temp)) {
534                         err = -EINVAL;
535                         goto free_subdevs;
536                 }
537                 for (j = 0; j < HIST_LEN; j++)
538                         dev->hist[j] = temp;
539                 pr_info("THERMAL EST init dev[%d] temp hist to %ld\n",
540                         i, temp);
541         }
542
543         of_err |= of_property_read_string(data_node, "cdev_type",
544                                                 &est_data->cdev_type);
545         if (of_err) {
546                 pr_err("THERMAL EST: cdev_type is missing\n");
547                 err = -EINVAL;
548                 goto free_subdevs;
549         }
550         pr_info("THERMAL EST cdev_type: %s.\n", est_data->cdev_type);
551
552         tzp = devm_kzalloc(&pdev->dev, sizeof(struct thermal_zone_params),
553                                 GFP_KERNEL);
554         if (IS_ERR_OR_NULL(tzp)) {
555                 err = -ENOMEM;
556                 goto free_subdevs;
557         }
558         memset(tzp, 0, sizeof(struct thermal_zone_params));
559         of_err |= of_property_read_string(data_node, "tzp_governor_name",
560                                                 &gov_name);
561         if (of_err) {
562                 pr_err("THERMAL EST: governor name is missing\n");
563                 err = -EINVAL;
564                 goto free_tzp;
565         }
566         strcpy(tzp->governor_name, gov_name);
567         pr_info("THERMAL EST governor name: %s\n", tzp->governor_name);
568         est_data->tzp = tzp;
569         est_data->thz = thermal_zone_device_register(
570                                         (char *)dev_name(&pdev->dev),
571                                         10, 0x3FF, est_data,
572                                         &therm_fan_est_ops, tzp, 0, 0);
573         if (IS_ERR_OR_NULL(est_data->thz)) {
574                 pr_err("THERMAL EST: thz register failed\n");
575                 err = -EINVAL;
576                 goto free_tzp;
577         }
578         pr_info("THERMAL EST: thz register success.\n");
579
580         /* workqueue related */
581         est_data->workqueue = alloc_workqueue(dev_name(&pdev->dev),
582                                     WQ_HIGHPRI | WQ_UNBOUND, 1);
583         if (!est_data->workqueue) {
584                 err = -ENOMEM;
585                 goto free_tzp;
586         }
587
588         est_data->current_trip_index = 0;
589         INIT_DELAYED_WORK(&est_data->therm_fan_est_work,
590                                 therm_fan_est_work_func);
591         queue_delayed_work(est_data->workqueue,
592                                 &est_data->therm_fan_est_work,
593                                 msecs_to_jiffies(est_data->polling_period));
594
595         for (i = 0; i < ARRAY_SIZE(therm_fan_est_nodes); i++)
596                 device_create_file(&pdev->dev,
597                         &therm_fan_est_nodes[i].dev_attr);
598
599         platform_set_drvdata(pdev, est_data);
600
601         pr_info("THERMAL EST: end of probe, return err: %d\n", err);
602         return err;
603
604 free_tzp:
605         devm_kfree(&pdev->dev, (void *)tzp);
606 free_subdevs:
607         devm_kfree(&pdev->dev, (void *)subdevs);
608 free_est:
609         devm_kfree(&pdev->dev, (void *)est_data);
610         return err;
611 }
612
613 static int therm_fan_est_remove(struct platform_device *pdev)
614 {
615         struct therm_fan_estimator *est = platform_get_drvdata(pdev);
616
617         if (!est)
618                 return -EINVAL;
619
620         cancel_delayed_work(&est->therm_fan_est_work);
621         destroy_workqueue(est->workqueue);
622         thermal_zone_device_unregister(est->thz);
623         devm_kfree(&pdev->dev, (void *)est->tzp);
624         devm_kfree(&pdev->dev, (void *)est->devs);
625         devm_kfree(&pdev->dev, (void *)est);
626         return 0;
627 }
628
629 #if CONFIG_PM
630 static int therm_fan_est_suspend(struct platform_device *pdev,
631                                                         pm_message_t state)
632 {
633         struct therm_fan_estimator *est = platform_get_drvdata(pdev);
634
635         if (!est)
636                 return -EINVAL;
637
638         pr_debug("therm-fan-est: %s, cur_temp:%ld", __func__, est->cur_temp);
639         cancel_delayed_work(&est->therm_fan_est_work);
640         est->current_trip_index = 0;
641
642         return 0;
643 }
644
645 static int therm_fan_est_resume(struct platform_device *pdev)
646 {
647         struct therm_fan_estimator *est = platform_get_drvdata(pdev);
648
649         if (!est)
650                 return -EINVAL;
651         pr_debug("therm-fan-est: %s, cur_temp:%ld", __func__, est->cur_temp);
652
653         queue_delayed_work(est->workqueue,
654                                 &est->therm_fan_est_work,
655                                 msecs_to_jiffies(DEFERRED_RESUME_TIME));
656         return 0;
657 }
658 #endif
659
660 static void therm_fan_est_shutdown(struct platform_device *pdev)
661 {
662         struct therm_fan_estimator *est = platform_get_drvdata(pdev);
663         pr_info("therm-fan-est: shutting down\n");
664         cancel_delayed_work_sync(&est->therm_fan_est_work);
665         destroy_workqueue(est->workqueue);
666         thermal_zone_device_unregister(est->thz);
667         devm_kfree(&pdev->dev, (void *)est->tzp);
668         devm_kfree(&pdev->dev, (void *)est->devs);
669         devm_kfree(&pdev->dev, (void *)est);
670 }
671
672 static const struct of_device_id of_thermal_est_match[] = {
673         { .compatible = "loki-thermal-est", },
674         { .compatible = "foster-thermal-est", },
675         { .compatible = "thermal-fan-est", },
676         {},
677 };
678 MODULE_DEVICE_TABLE(of, of_thermal_est_match);
679
680 static struct platform_driver therm_fan_est_driver = {
681         .driver = {
682                 .name  = "therm-fan-est-driver",
683                 .owner = THIS_MODULE,
684                 .of_match_table = of_thermal_est_match,
685         },
686         .probe  = therm_fan_est_probe,
687         .remove = therm_fan_est_remove,
688 #if CONFIG_PM
689         .suspend = therm_fan_est_suspend,
690         .resume = therm_fan_est_resume,
691 #endif
692         .shutdown = therm_fan_est_shutdown,
693 };
694
695 module_platform_driver(therm_fan_est_driver);
696
697 MODULE_DESCRIPTION("fan thermal estimator");
698 MODULE_AUTHOR("Anshul Jain <anshulj@nvidia.com>");
699 MODULE_LICENSE("GPL v2");