1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <linux/thermal.h>
26#include <linux/slab.h>
27#include <linux/types.h>
28#include <linux/of_device.h>
29#include <linux/of_platform.h>
30#include <linux/err.h>
31#include <linux/export.h>
32#include <linux/string.h>
33
34#include "thermal_core.h"
35
36
37
38
39
40
41
42
43
44
45
46struct __thermal_trip {
47 struct device_node *np;
48 unsigned long int temperature;
49 unsigned long int hysteresis;
50 enum thermal_trip_type type;
51};
52
53
54
55
56
57
58
59
60
61
62struct __thermal_bind_params {
63 struct device_node *cooling_device;
64 unsigned int trip_id;
65 unsigned int usage;
66 unsigned long min;
67 unsigned long max;
68};
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84struct __thermal_zone {
85 enum thermal_device_mode mode;
86 int passive_delay;
87 int polling_delay;
88
89
90 int ntrips;
91 struct __thermal_trip *trips;
92
93
94 int num_tbps;
95 struct __thermal_bind_params *tbps;
96
97
98 void *sensor_data;
99 int (*get_temp)(void *, long *);
100 int (*get_trend)(void *, long *);
101};
102
103
104
105static int of_thermal_get_temp(struct thermal_zone_device *tz,
106 unsigned long *temp)
107{
108 struct __thermal_zone *data = tz->devdata;
109
110 if (!data->get_temp)
111 return -EINVAL;
112
113 return data->get_temp(data->sensor_data, temp);
114}
115
116static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
117 enum thermal_trend *trend)
118{
119 struct __thermal_zone *data = tz->devdata;
120 long dev_trend;
121 int r;
122
123 if (!data->get_trend)
124 return -EINVAL;
125
126 r = data->get_trend(data->sensor_data, &dev_trend);
127 if (r)
128 return r;
129
130
131 if (dev_trend > 0)
132 *trend = THERMAL_TREND_RAISING;
133 else if (dev_trend < 0)
134 *trend = THERMAL_TREND_DROPPING;
135 else
136 *trend = THERMAL_TREND_STABLE;
137
138 return 0;
139}
140
141static int of_thermal_bind(struct thermal_zone_device *thermal,
142 struct thermal_cooling_device *cdev)
143{
144 struct __thermal_zone *data = thermal->devdata;
145 int i;
146
147 if (!data || IS_ERR(data))
148 return -ENODEV;
149
150
151 for (i = 0; i < data->num_tbps; i++) {
152 struct __thermal_bind_params *tbp = data->tbps + i;
153
154 if (tbp->cooling_device == cdev->np) {
155 int ret;
156
157 ret = thermal_zone_bind_cooling_device(thermal,
158 tbp->trip_id, cdev,
159 tbp->max,
160 tbp->min);
161 if (ret)
162 return ret;
163 }
164 }
165
166 return 0;
167}
168
169static int of_thermal_unbind(struct thermal_zone_device *thermal,
170 struct thermal_cooling_device *cdev)
171{
172 struct __thermal_zone *data = thermal->devdata;
173 int i;
174
175 if (!data || IS_ERR(data))
176 return -ENODEV;
177
178
179 for (i = 0; i < data->num_tbps; i++) {
180 struct __thermal_bind_params *tbp = data->tbps + i;
181
182 if (tbp->cooling_device == cdev->np) {
183 int ret;
184
185 ret = thermal_zone_unbind_cooling_device(thermal,
186 tbp->trip_id, cdev);
187 if (ret)
188 return ret;
189 }
190 }
191
192 return 0;
193}
194
195static int of_thermal_get_mode(struct thermal_zone_device *tz,
196 enum thermal_device_mode *mode)
197{
198 struct __thermal_zone *data = tz->devdata;
199
200 *mode = data->mode;
201
202 return 0;
203}
204
205static int of_thermal_set_mode(struct thermal_zone_device *tz,
206 enum thermal_device_mode mode)
207{
208 struct __thermal_zone *data = tz->devdata;
209
210 mutex_lock(&tz->lock);
211
212 if (mode == THERMAL_DEVICE_ENABLED)
213 tz->polling_delay = data->polling_delay;
214 else
215 tz->polling_delay = 0;
216
217 mutex_unlock(&tz->lock);
218
219 data->mode = mode;
220 thermal_zone_device_update(tz);
221
222 return 0;
223}
224
225static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
226 enum thermal_trip_type *type)
227{
228 struct __thermal_zone *data = tz->devdata;
229
230 if (trip >= data->ntrips || trip < 0)
231 return -EDOM;
232
233 *type = data->trips[trip].type;
234
235 return 0;
236}
237
238static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
239 unsigned long *temp)
240{
241 struct __thermal_zone *data = tz->devdata;
242
243 if (trip >= data->ntrips || trip < 0)
244 return -EDOM;
245
246 *temp = data->trips[trip].temperature;
247
248 return 0;
249}
250
251static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
252 unsigned long temp)
253{
254 struct __thermal_zone *data = tz->devdata;
255
256 if (trip >= data->ntrips || trip < 0)
257 return -EDOM;
258
259
260 data->trips[trip].temperature = temp;
261
262 return 0;
263}
264
265static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
266 unsigned long *hyst)
267{
268 struct __thermal_zone *data = tz->devdata;
269
270 if (trip >= data->ntrips || trip < 0)
271 return -EDOM;
272
273 *hyst = data->trips[trip].hysteresis;
274
275 return 0;
276}
277
278static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
279 unsigned long hyst)
280{
281 struct __thermal_zone *data = tz->devdata;
282
283 if (trip >= data->ntrips || trip < 0)
284 return -EDOM;
285
286
287 data->trips[trip].hysteresis = hyst;
288
289 return 0;
290}
291
292static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
293 unsigned long *temp)
294{
295 struct __thermal_zone *data = tz->devdata;
296 int i;
297
298 for (i = 0; i < data->ntrips; i++)
299 if (data->trips[i].type == THERMAL_TRIP_CRITICAL) {
300 *temp = data->trips[i].temperature;
301 return 0;
302 }
303
304 return -EINVAL;
305}
306
307static struct thermal_zone_device_ops of_thermal_ops = {
308 .get_mode = of_thermal_get_mode,
309 .set_mode = of_thermal_set_mode,
310
311 .get_trip_type = of_thermal_get_trip_type,
312 .get_trip_temp = of_thermal_get_trip_temp,
313 .set_trip_temp = of_thermal_set_trip_temp,
314 .get_trip_hyst = of_thermal_get_trip_hyst,
315 .set_trip_hyst = of_thermal_set_trip_hyst,
316 .get_crit_temp = of_thermal_get_crit_temp,
317
318 .bind = of_thermal_bind,
319 .unbind = of_thermal_unbind,
320};
321
322
323
324static struct thermal_zone_device *
325thermal_zone_of_add_sensor(struct device_node *zone,
326 struct device_node *sensor, void *data,
327 int (*get_temp)(void *, long *),
328 int (*get_trend)(void *, long *))
329{
330 struct thermal_zone_device *tzd;
331 struct __thermal_zone *tz;
332
333 tzd = thermal_zone_get_zone_by_name(zone->name);
334 if (IS_ERR(tzd))
335 return ERR_PTR(-EPROBE_DEFER);
336
337 tz = tzd->devdata;
338
339 mutex_lock(&tzd->lock);
340 tz->get_temp = get_temp;
341 tz->get_trend = get_trend;
342 tz->sensor_data = data;
343
344 tzd->ops->get_temp = of_thermal_get_temp;
345 tzd->ops->get_trend = of_thermal_get_trend;
346 mutex_unlock(&tzd->lock);
347
348 return tzd;
349}
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384struct thermal_zone_device *
385thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
386 void *data, int (*get_temp)(void *, long *),
387 int (*get_trend)(void *, long *))
388{
389 struct device_node *np, *child, *sensor_np;
390
391 np = of_find_node_by_name(NULL, "thermal-zones");
392 if (!np)
393 return ERR_PTR(-ENODEV);
394
395 if (!dev || !dev->of_node)
396 return ERR_PTR(-EINVAL);
397
398 sensor_np = dev->of_node;
399
400 for_each_child_of_node(np, child) {
401 struct of_phandle_args sensor_specs;
402 int ret, id;
403
404
405 ret = of_parse_phandle_with_args(child, "thermal-sensors",
406 "#thermal-sensor-cells",
407 0, &sensor_specs);
408 if (ret)
409 continue;
410
411 if (sensor_specs.args_count >= 1) {
412 id = sensor_specs.args[0];
413 WARN(sensor_specs.args_count > 1,
414 "%s: too many cells in sensor specifier %d\n",
415 sensor_specs.np->name, sensor_specs.args_count);
416 } else {
417 id = 0;
418 }
419
420 if (sensor_specs.np == sensor_np && id == sensor_id) {
421 of_node_put(np);
422 return thermal_zone_of_add_sensor(child, sensor_np,
423 data,
424 get_temp,
425 get_trend);
426 }
427 }
428 of_node_put(np);
429
430 return ERR_PTR(-ENODEV);
431}
432EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register);
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449void thermal_zone_of_sensor_unregister(struct device *dev,
450 struct thermal_zone_device *tzd)
451{
452 struct __thermal_zone *tz;
453
454 if (!dev || !tzd || !tzd->devdata)
455 return;
456
457 tz = tzd->devdata;
458
459
460 if (!tz)
461 return;
462
463 mutex_lock(&tzd->lock);
464 tzd->ops->get_temp = NULL;
465 tzd->ops->get_trend = NULL;
466
467 tz->get_temp = NULL;
468 tz->get_trend = NULL;
469 tz->sensor_data = NULL;
470 mutex_unlock(&tzd->lock);
471}
472EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490static int thermal_of_populate_bind_params(struct device_node *np,
491 struct __thermal_bind_params *__tbp,
492 struct __thermal_trip *trips,
493 int ntrips)
494{
495 struct of_phandle_args cooling_spec;
496 struct device_node *trip;
497 int ret, i;
498 u32 prop;
499
500
501 __tbp->usage = 0;
502 ret = of_property_read_u32(np, "contribution", &prop);
503 if (ret == 0)
504 __tbp->usage = prop;
505
506 trip = of_parse_phandle(np, "trip", 0);
507 if (!trip) {
508 pr_err("missing trip property\n");
509 return -ENODEV;
510 }
511
512
513 for (i = 0; i < ntrips; i++)
514 if (trip == trips[i].np) {
515 __tbp->trip_id = i;
516 break;
517 }
518
519 if (i == ntrips) {
520 ret = -ENODEV;
521 goto end;
522 }
523
524 ret = of_parse_phandle_with_args(np, "cooling-device", "#cooling-cells",
525 0, &cooling_spec);
526 if (ret < 0) {
527 pr_err("missing cooling_device property\n");
528 goto end;
529 }
530 __tbp->cooling_device = cooling_spec.np;
531 if (cooling_spec.args_count >= 2) {
532 __tbp->min = cooling_spec.args[0];
533 __tbp->max = cooling_spec.args[1];
534 } else {
535 pr_err("wrong reference to cooling device, missing limits\n");
536 }
537
538end:
539 of_node_put(trip);
540
541 return ret;
542}
543
544
545
546
547
548static const char * const trip_types[] = {
549 [THERMAL_TRIP_ACTIVE] = "active",
550 [THERMAL_TRIP_PASSIVE] = "passive",
551 [THERMAL_TRIP_HOT] = "hot",
552 [THERMAL_TRIP_CRITICAL] = "critical",
553};
554
555
556
557
558
559
560
561
562
563
564
565static int thermal_of_get_trip_type(struct device_node *np,
566 enum thermal_trip_type *type)
567{
568 const char *t;
569 int err, i;
570
571 err = of_property_read_string(np, "type", &t);
572 if (err < 0)
573 return err;
574
575 for (i = 0; i < ARRAY_SIZE(trip_types); i++)
576 if (!strcasecmp(t, trip_types[i])) {
577 *type = i;
578 return 0;
579 }
580
581 return -ENODEV;
582}
583
584
585
586
587
588
589
590
591
592
593
594static int thermal_of_populate_trip(struct device_node *np,
595 struct __thermal_trip *trip)
596{
597 int prop;
598 int ret;
599
600 ret = of_property_read_u32(np, "temperature", &prop);
601 if (ret < 0) {
602 pr_err("missing temperature property\n");
603 return ret;
604 }
605 trip->temperature = prop;
606
607 ret = of_property_read_u32(np, "hysteresis", &prop);
608 if (ret < 0) {
609 pr_err("missing hysteresis property\n");
610 return ret;
611 }
612 trip->hysteresis = prop;
613
614 ret = thermal_of_get_trip_type(np, &trip->type);
615 if (ret < 0) {
616 pr_err("wrong trip type property\n");
617 return ret;
618 }
619
620
621 trip->np = np;
622
623 return 0;
624}
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640static struct __thermal_zone *
641thermal_of_build_thermal_zone(struct device_node *np)
642{
643 struct device_node *child = NULL, *gchild;
644 struct __thermal_zone *tz;
645 int ret, i;
646 u32 prop;
647
648 if (!np) {
649 pr_err("no thermal zone np\n");
650 return ERR_PTR(-EINVAL);
651 }
652
653 tz = kzalloc(sizeof(*tz), GFP_KERNEL);
654 if (!tz)
655 return ERR_PTR(-ENOMEM);
656
657 ret = of_property_read_u32(np, "polling-delay-passive", &prop);
658 if (ret < 0) {
659 pr_err("missing polling-delay-passive property\n");
660 goto free_tz;
661 }
662 tz->passive_delay = prop;
663
664 ret = of_property_read_u32(np, "polling-delay", &prop);
665 if (ret < 0) {
666 pr_err("missing polling-delay property\n");
667 goto free_tz;
668 }
669 tz->polling_delay = prop;
670
671
672 child = of_get_child_by_name(np, "trips");
673
674
675 if (!child)
676 goto finish;
677
678 tz->ntrips = of_get_child_count(child);
679 if (tz->ntrips == 0)
680 goto finish;
681
682 tz->trips = kzalloc(tz->ntrips * sizeof(*tz->trips), GFP_KERNEL);
683 if (!tz->trips) {
684 ret = -ENOMEM;
685 goto free_tz;
686 }
687
688 i = 0;
689 for_each_child_of_node(child, gchild) {
690 ret = thermal_of_populate_trip(gchild, &tz->trips[i++]);
691 if (ret)
692 goto free_trips;
693 }
694
695 of_node_put(child);
696
697
698 child = of_get_child_by_name(np, "cooling-maps");
699
700
701 if (!child)
702 goto finish;
703
704 tz->num_tbps = of_get_child_count(child);
705 if (tz->num_tbps == 0)
706 goto finish;
707
708 tz->tbps = kzalloc(tz->num_tbps * sizeof(*tz->tbps), GFP_KERNEL);
709 if (!tz->tbps) {
710 ret = -ENOMEM;
711 goto free_trips;
712 }
713
714 i = 0;
715 for_each_child_of_node(child, gchild) {
716 ret = thermal_of_populate_bind_params(gchild, &tz->tbps[i++],
717 tz->trips, tz->ntrips);
718 if (ret)
719 goto free_tbps;
720 }
721
722finish:
723 of_node_put(child);
724 tz->mode = THERMAL_DEVICE_DISABLED;
725
726 return tz;
727
728free_tbps:
729 kfree(tz->tbps);
730free_trips:
731 kfree(tz->trips);
732free_tz:
733 kfree(tz);
734 of_node_put(child);
735
736 return ERR_PTR(ret);
737}
738
739static inline void of_thermal_free_zone(struct __thermal_zone *tz)
740{
741 kfree(tz->tbps);
742 kfree(tz->trips);
743 kfree(tz);
744}
745
746
747
748
749
750
751
752
753
754
755
756
757
758int __init of_parse_thermal_zones(void)
759{
760 struct device_node *np, *child;
761 struct __thermal_zone *tz;
762 struct thermal_zone_device_ops *ops;
763
764 np = of_find_node_by_name(NULL, "thermal-zones");
765 if (!np) {
766 pr_debug("unable to find thermal zones\n");
767 return 0;
768 }
769
770 for_each_child_of_node(np, child) {
771 struct thermal_zone_device *zone;
772 struct thermal_zone_params *tzp;
773
774 tz = thermal_of_build_thermal_zone(child);
775 if (IS_ERR(tz)) {
776 pr_err("failed to build thermal zone %s: %ld\n",
777 child->name,
778 PTR_ERR(tz));
779 continue;
780 }
781
782 ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
783 if (!ops)
784 goto exit_free;
785
786 tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
787 if (!tzp) {
788 kfree(ops);
789 goto exit_free;
790 }
791
792
793 tzp->no_hwmon = true;
794
795 zone = thermal_zone_device_register(child->name, tz->ntrips,
796 0, tz,
797 ops, tzp,
798 tz->passive_delay,
799 tz->polling_delay);
800 if (IS_ERR(zone)) {
801 pr_err("Failed to build %s zone %ld\n", child->name,
802 PTR_ERR(zone));
803 kfree(tzp);
804 kfree(ops);
805 of_thermal_free_zone(tz);
806
807 }
808 }
809
810 return 0;
811
812exit_free:
813 of_thermal_free_zone(tz);
814
815
816 of_thermal_destroy_zones();
817
818 return -ENOMEM;
819}
820
821
822
823
824
825
826
827
828void of_thermal_destroy_zones(void)
829{
830 struct device_node *np, *child;
831
832 np = of_find_node_by_name(NULL, "thermal-zones");
833 if (!np) {
834 pr_err("unable to find thermal zones\n");
835 return;
836 }
837
838 for_each_child_of_node(np, child) {
839 struct thermal_zone_device *zone;
840
841 zone = thermal_zone_get_zone_by_name(child->name);
842 if (IS_ERR(zone))
843 continue;
844
845 thermal_zone_device_unregister(zone);
846 kfree(zone->tzp);
847 kfree(zone->ops);
848 of_thermal_free_zone(zone->devdata);
849 }
850}
851