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#include <linux/thermal.h>
34
35#include "thermal_core.h"
36
37
38
39
40
41
42
43
44
45
46
47
48struct __thermal_bind_params {
49 struct device_node *cooling_device;
50 unsigned int trip_id;
51 unsigned int usage;
52 unsigned long min;
53 unsigned long max;
54};
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71struct __thermal_zone {
72 enum thermal_device_mode mode;
73 int passive_delay;
74 int polling_delay;
75 int slope;
76 int offset;
77
78
79 int ntrips;
80 struct thermal_trip *trips;
81
82
83 int num_tbps;
84 struct __thermal_bind_params *tbps;
85
86
87 void *sensor_data;
88 const struct thermal_zone_of_device_ops *ops;
89};
90
91
92
93static int of_thermal_get_temp(struct thermal_zone_device *tz,
94 int *temp)
95{
96 struct __thermal_zone *data = tz->devdata;
97
98 if (!data->ops->get_temp)
99 return -EINVAL;
100
101 return data->ops->get_temp(data->sensor_data, temp);
102}
103
104static int of_thermal_set_trips(struct thermal_zone_device *tz,
105 int low, int high)
106{
107 struct __thermal_zone *data = tz->devdata;
108
109 if (!data->ops || !data->ops->set_trips)
110 return -EINVAL;
111
112 return data->ops->set_trips(data->sensor_data, low, high);
113}
114
115
116
117
118
119
120
121
122
123
124
125int of_thermal_get_ntrips(struct thermal_zone_device *tz)
126{
127 struct __thermal_zone *data = tz->devdata;
128
129 if (!data || IS_ERR(data))
130 return -ENODEV;
131
132 return data->ntrips;
133}
134EXPORT_SYMBOL_GPL(of_thermal_get_ntrips);
135
136
137
138
139
140
141
142
143
144
145
146bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, int trip)
147{
148 struct __thermal_zone *data = tz->devdata;
149
150 if (!data || trip >= data->ntrips || trip < 0)
151 return false;
152
153 return true;
154}
155EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid);
156
157
158
159
160
161
162
163
164
165
166
167const struct thermal_trip *
168of_thermal_get_trip_points(struct thermal_zone_device *tz)
169{
170 struct __thermal_zone *data = tz->devdata;
171
172 if (!data)
173 return NULL;
174
175 return data->trips;
176}
177EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
178
179
180
181
182
183
184
185
186
187
188
189
190static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
191 int temp)
192{
193 struct __thermal_zone *data = tz->devdata;
194
195 return data->ops->set_emul_temp(data->sensor_data, temp);
196}
197
198static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
199 enum thermal_trend *trend)
200{
201 struct __thermal_zone *data = tz->devdata;
202
203 if (!data->ops->get_trend)
204 return -EINVAL;
205
206 return data->ops->get_trend(data->sensor_data, trip, trend);
207}
208
209static int of_thermal_bind(struct thermal_zone_device *thermal,
210 struct thermal_cooling_device *cdev)
211{
212 struct __thermal_zone *data = thermal->devdata;
213 int i;
214
215 if (!data || IS_ERR(data))
216 return -ENODEV;
217
218
219 for (i = 0; i < data->num_tbps; i++) {
220 struct __thermal_bind_params *tbp = data->tbps + i;
221
222 if (tbp->cooling_device == cdev->np) {
223 int ret;
224
225 ret = thermal_zone_bind_cooling_device(thermal,
226 tbp->trip_id, cdev,
227 tbp->max,
228 tbp->min,
229 tbp->usage);
230 if (ret)
231 return ret;
232 }
233 }
234
235 return 0;
236}
237
238static int of_thermal_unbind(struct thermal_zone_device *thermal,
239 struct thermal_cooling_device *cdev)
240{
241 struct __thermal_zone *data = thermal->devdata;
242 int i;
243
244 if (!data || IS_ERR(data))
245 return -ENODEV;
246
247
248 for (i = 0; i < data->num_tbps; i++) {
249 struct __thermal_bind_params *tbp = data->tbps + i;
250
251 if (tbp->cooling_device == cdev->np) {
252 int ret;
253
254 ret = thermal_zone_unbind_cooling_device(thermal,
255 tbp->trip_id, cdev);
256 if (ret)
257 return ret;
258 }
259 }
260
261 return 0;
262}
263
264static int of_thermal_get_mode(struct thermal_zone_device *tz,
265 enum thermal_device_mode *mode)
266{
267 struct __thermal_zone *data = tz->devdata;
268
269 *mode = data->mode;
270
271 return 0;
272}
273
274static int of_thermal_set_mode(struct thermal_zone_device *tz,
275 enum thermal_device_mode mode)
276{
277 struct __thermal_zone *data = tz->devdata;
278
279 mutex_lock(&tz->lock);
280
281 if (mode == THERMAL_DEVICE_ENABLED)
282 tz->polling_delay = data->polling_delay;
283 else
284 tz->polling_delay = 0;
285
286 mutex_unlock(&tz->lock);
287
288 data->mode = mode;
289 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
290
291 return 0;
292}
293
294static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
295 enum thermal_trip_type *type)
296{
297 struct __thermal_zone *data = tz->devdata;
298
299 if (trip >= data->ntrips || trip < 0)
300 return -EDOM;
301
302 *type = data->trips[trip].type;
303
304 return 0;
305}
306
307static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
308 int *temp)
309{
310 struct __thermal_zone *data = tz->devdata;
311
312 if (trip >= data->ntrips || trip < 0)
313 return -EDOM;
314
315 *temp = data->trips[trip].temperature;
316
317 return 0;
318}
319
320static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
321 int temp)
322{
323 struct __thermal_zone *data = tz->devdata;
324
325 if (trip >= data->ntrips || trip < 0)
326 return -EDOM;
327
328 if (data->ops->set_trip_temp) {
329 int ret;
330
331 ret = data->ops->set_trip_temp(data->sensor_data, trip, temp);
332 if (ret)
333 return ret;
334 }
335
336
337 data->trips[trip].temperature = temp;
338
339 return 0;
340}
341
342static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
343 int *hyst)
344{
345 struct __thermal_zone *data = tz->devdata;
346
347 if (trip >= data->ntrips || trip < 0)
348 return -EDOM;
349
350 *hyst = data->trips[trip].hysteresis;
351
352 return 0;
353}
354
355static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
356 int hyst)
357{
358 struct __thermal_zone *data = tz->devdata;
359
360 if (trip >= data->ntrips || trip < 0)
361 return -EDOM;
362
363
364 data->trips[trip].hysteresis = hyst;
365
366 return 0;
367}
368
369static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
370 int *temp)
371{
372 struct __thermal_zone *data = tz->devdata;
373 int i;
374
375 for (i = 0; i < data->ntrips; i++)
376 if (data->trips[i].type == THERMAL_TRIP_CRITICAL) {
377 *temp = data->trips[i].temperature;
378 return 0;
379 }
380
381 return -EINVAL;
382}
383
384static struct thermal_zone_device_ops of_thermal_ops = {
385 .get_mode = of_thermal_get_mode,
386 .set_mode = of_thermal_set_mode,
387
388 .get_trip_type = of_thermal_get_trip_type,
389 .get_trip_temp = of_thermal_get_trip_temp,
390 .set_trip_temp = of_thermal_set_trip_temp,
391 .get_trip_hyst = of_thermal_get_trip_hyst,
392 .set_trip_hyst = of_thermal_set_trip_hyst,
393 .get_crit_temp = of_thermal_get_crit_temp,
394
395 .bind = of_thermal_bind,
396 .unbind = of_thermal_unbind,
397};
398
399
400
401static struct thermal_zone_device *
402thermal_zone_of_add_sensor(struct device_node *zone,
403 struct device_node *sensor, void *data,
404 const struct thermal_zone_of_device_ops *ops)
405{
406 struct thermal_zone_device *tzd;
407 struct __thermal_zone *tz;
408
409 tzd = thermal_zone_get_zone_by_name(zone->name);
410 if (IS_ERR(tzd))
411 return ERR_PTR(-EPROBE_DEFER);
412
413 tz = tzd->devdata;
414
415 if (!ops)
416 return ERR_PTR(-EINVAL);
417
418 mutex_lock(&tzd->lock);
419 tz->ops = ops;
420 tz->sensor_data = data;
421
422 tzd->ops->get_temp = of_thermal_get_temp;
423 tzd->ops->get_trend = of_thermal_get_trend;
424
425
426
427
428
429 if (ops->set_trips)
430 tzd->ops->set_trips = of_thermal_set_trips;
431
432 if (ops->set_emul_temp)
433 tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
434
435 mutex_unlock(&tzd->lock);
436
437 return tzd;
438}
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472struct thermal_zone_device *
473thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
474 const struct thermal_zone_of_device_ops *ops)
475{
476 struct device_node *np, *child, *sensor_np;
477 struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);
478
479 np = of_find_node_by_name(NULL, "thermal-zones");
480 if (!np)
481 return ERR_PTR(-ENODEV);
482
483 if (!dev || !dev->of_node) {
484 of_node_put(np);
485 return ERR_PTR(-EINVAL);
486 }
487
488 sensor_np = of_node_get(dev->of_node);
489
490 for_each_available_child_of_node(np, child) {
491 struct of_phandle_args sensor_specs;
492 int ret, id;
493
494
495 ret = of_parse_phandle_with_args(child, "thermal-sensors",
496 "#thermal-sensor-cells",
497 0, &sensor_specs);
498 if (ret)
499 continue;
500
501 if (sensor_specs.args_count >= 1) {
502 id = sensor_specs.args[0];
503 WARN(sensor_specs.args_count > 1,
504 "%s: too many cells in sensor specifier %d\n",
505 sensor_specs.np->name, sensor_specs.args_count);
506 } else {
507 id = 0;
508 }
509
510 if (sensor_specs.np == sensor_np && id == sensor_id) {
511 tzd = thermal_zone_of_add_sensor(child, sensor_np,
512 data, ops);
513 if (!IS_ERR(tzd))
514 tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);
515
516 of_node_put(sensor_specs.np);
517 of_node_put(child);
518 goto exit;
519 }
520 of_node_put(sensor_specs.np);
521 }
522exit:
523 of_node_put(sensor_np);
524 of_node_put(np);
525
526 return tzd;
527}
528EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register);
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545void thermal_zone_of_sensor_unregister(struct device *dev,
546 struct thermal_zone_device *tzd)
547{
548 struct __thermal_zone *tz;
549
550 if (!dev || !tzd || !tzd->devdata)
551 return;
552
553 tz = tzd->devdata;
554
555
556 if (!tz)
557 return;
558
559 mutex_lock(&tzd->lock);
560 tzd->ops->get_temp = NULL;
561 tzd->ops->get_trend = NULL;
562 tzd->ops->set_emul_temp = NULL;
563
564 tz->ops = NULL;
565 tz->sensor_data = NULL;
566 mutex_unlock(&tzd->lock);
567}
568EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
569
570static void devm_thermal_zone_of_sensor_release(struct device *dev, void *res)
571{
572 thermal_zone_of_sensor_unregister(dev,
573 *(struct thermal_zone_device **)res);
574}
575
576static int devm_thermal_zone_of_sensor_match(struct device *dev, void *res,
577 void *data)
578{
579 struct thermal_zone_device **r = res;
580
581 if (WARN_ON(!r || !*r))
582 return 0;
583
584 return *r == data;
585}
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
607 struct device *dev, int sensor_id,
608 void *data, const struct thermal_zone_of_device_ops *ops)
609{
610 struct thermal_zone_device **ptr, *tzd;
611
612 ptr = devres_alloc(devm_thermal_zone_of_sensor_release, sizeof(*ptr),
613 GFP_KERNEL);
614 if (!ptr)
615 return ERR_PTR(-ENOMEM);
616
617 tzd = thermal_zone_of_sensor_register(dev, sensor_id, data, ops);
618 if (IS_ERR(tzd)) {
619 devres_free(ptr);
620 return tzd;
621 }
622
623 *ptr = tzd;
624 devres_add(dev, ptr);
625
626 return tzd;
627}
628EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_register);
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643void devm_thermal_zone_of_sensor_unregister(struct device *dev,
644 struct thermal_zone_device *tzd)
645{
646 WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release,
647 devm_thermal_zone_of_sensor_match, tzd));
648}
649EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister);
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667static int thermal_of_populate_bind_params(struct device_node *np,
668 struct __thermal_bind_params *__tbp,
669 struct thermal_trip *trips,
670 int ntrips)
671{
672 struct of_phandle_args cooling_spec;
673 struct device_node *trip;
674 int ret, i;
675 u32 prop;
676
677
678 __tbp->usage = THERMAL_WEIGHT_DEFAULT;
679 ret = of_property_read_u32(np, "contribution", &prop);
680 if (ret == 0)
681 __tbp->usage = prop;
682
683 trip = of_parse_phandle(np, "trip", 0);
684 if (!trip) {
685 pr_err("missing trip property\n");
686 return -ENODEV;
687 }
688
689
690 for (i = 0; i < ntrips; i++)
691 if (trip == trips[i].np) {
692 __tbp->trip_id = i;
693 break;
694 }
695
696 if (i == ntrips) {
697 ret = -ENODEV;
698 goto end;
699 }
700
701 ret = of_parse_phandle_with_args(np, "cooling-device", "#cooling-cells",
702 0, &cooling_spec);
703 if (ret < 0) {
704 pr_err("missing cooling_device property\n");
705 goto end;
706 }
707 __tbp->cooling_device = cooling_spec.np;
708 if (cooling_spec.args_count >= 2) {
709 __tbp->min = cooling_spec.args[0];
710 __tbp->max = cooling_spec.args[1];
711 } else {
712 pr_err("wrong reference to cooling device, missing limits\n");
713 }
714
715end:
716 of_node_put(trip);
717
718 return ret;
719}
720
721
722
723
724
725static const char * const trip_types[] = {
726 [THERMAL_TRIP_ACTIVE] = "active",
727 [THERMAL_TRIP_PASSIVE] = "passive",
728 [THERMAL_TRIP_HOT] = "hot",
729 [THERMAL_TRIP_CRITICAL] = "critical",
730};
731
732
733
734
735
736
737
738
739
740
741
742static int thermal_of_get_trip_type(struct device_node *np,
743 enum thermal_trip_type *type)
744{
745 const char *t;
746 int err, i;
747
748 err = of_property_read_string(np, "type", &t);
749 if (err < 0)
750 return err;
751
752 for (i = 0; i < ARRAY_SIZE(trip_types); i++)
753 if (!strcasecmp(t, trip_types[i])) {
754 *type = i;
755 return 0;
756 }
757
758 return -ENODEV;
759}
760
761
762
763
764
765
766
767
768
769
770
771static int thermal_of_populate_trip(struct device_node *np,
772 struct thermal_trip *trip)
773{
774 int prop;
775 int ret;
776
777 ret = of_property_read_u32(np, "temperature", &prop);
778 if (ret < 0) {
779 pr_err("missing temperature property\n");
780 return ret;
781 }
782 trip->temperature = prop;
783
784 ret = of_property_read_u32(np, "hysteresis", &prop);
785 if (ret < 0) {
786 pr_err("missing hysteresis property\n");
787 return ret;
788 }
789 trip->hysteresis = prop;
790
791 ret = thermal_of_get_trip_type(np, &trip->type);
792 if (ret < 0) {
793 pr_err("wrong trip type property\n");
794 return ret;
795 }
796
797
798 trip->np = np;
799 of_node_get(np);
800
801 return 0;
802}
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818static struct __thermal_zone
819__init *thermal_of_build_thermal_zone(struct device_node *np)
820{
821 struct device_node *child = NULL, *gchild;
822 struct __thermal_zone *tz;
823 int ret, i;
824 u32 prop, coef[2];
825
826 if (!np) {
827 pr_err("no thermal zone np\n");
828 return ERR_PTR(-EINVAL);
829 }
830
831 tz = kzalloc(sizeof(*tz), GFP_KERNEL);
832 if (!tz)
833 return ERR_PTR(-ENOMEM);
834
835 ret = of_property_read_u32(np, "polling-delay-passive", &prop);
836 if (ret < 0) {
837 pr_err("missing polling-delay-passive property\n");
838 goto free_tz;
839 }
840 tz->passive_delay = prop;
841
842 ret = of_property_read_u32(np, "polling-delay", &prop);
843 if (ret < 0) {
844 pr_err("missing polling-delay property\n");
845 goto free_tz;
846 }
847 tz->polling_delay = prop;
848
849
850
851
852
853
854 ret = of_property_read_u32_array(np, "coefficients", coef, 2);
855 if (ret == 0) {
856 tz->slope = coef[0];
857 tz->offset = coef[1];
858 } else {
859 tz->slope = 1;
860 tz->offset = 0;
861 }
862
863
864 child = of_get_child_by_name(np, "trips");
865
866
867 if (!child)
868 goto finish;
869
870 tz->ntrips = of_get_child_count(child);
871 if (tz->ntrips == 0)
872 goto finish;
873
874 tz->trips = kzalloc(tz->ntrips * sizeof(*tz->trips), GFP_KERNEL);
875 if (!tz->trips) {
876 ret = -ENOMEM;
877 goto free_tz;
878 }
879
880 i = 0;
881 for_each_child_of_node(child, gchild) {
882 ret = thermal_of_populate_trip(gchild, &tz->trips[i++]);
883 if (ret)
884 goto free_trips;
885 }
886
887 of_node_put(child);
888
889
890 child = of_get_child_by_name(np, "cooling-maps");
891
892
893 if (!child)
894 goto finish;
895
896 tz->num_tbps = of_get_child_count(child);
897 if (tz->num_tbps == 0)
898 goto finish;
899
900 tz->tbps = kzalloc(tz->num_tbps * sizeof(*tz->tbps), GFP_KERNEL);
901 if (!tz->tbps) {
902 ret = -ENOMEM;
903 goto free_trips;
904 }
905
906 i = 0;
907 for_each_child_of_node(child, gchild) {
908 ret = thermal_of_populate_bind_params(gchild, &tz->tbps[i++],
909 tz->trips, tz->ntrips);
910 if (ret)
911 goto free_tbps;
912 }
913
914finish:
915 of_node_put(child);
916 tz->mode = THERMAL_DEVICE_DISABLED;
917
918 return tz;
919
920free_tbps:
921 for (i = i - 1; i >= 0; i--)
922 of_node_put(tz->tbps[i].cooling_device);
923 kfree(tz->tbps);
924free_trips:
925 for (i = 0; i < tz->ntrips; i++)
926 of_node_put(tz->trips[i].np);
927 kfree(tz->trips);
928 of_node_put(gchild);
929free_tz:
930 kfree(tz);
931 of_node_put(child);
932
933 return ERR_PTR(ret);
934}
935
936static inline void of_thermal_free_zone(struct __thermal_zone *tz)
937{
938 int i;
939
940 for (i = 0; i < tz->num_tbps; i++)
941 of_node_put(tz->tbps[i].cooling_device);
942 kfree(tz->tbps);
943 for (i = 0; i < tz->ntrips; i++)
944 of_node_put(tz->trips[i].np);
945 kfree(tz->trips);
946 kfree(tz);
947}
948
949
950
951
952
953
954
955
956
957
958
959
960
961int __init of_parse_thermal_zones(void)
962{
963 struct device_node *np, *child;
964 struct __thermal_zone *tz;
965 struct thermal_zone_device_ops *ops;
966
967 np = of_find_node_by_name(NULL, "thermal-zones");
968 if (!np) {
969 pr_debug("unable to find thermal zones\n");
970 return 0;
971 }
972
973 for_each_available_child_of_node(np, child) {
974 struct thermal_zone_device *zone;
975 struct thermal_zone_params *tzp;
976 int i, mask = 0;
977 u32 prop;
978
979 tz = thermal_of_build_thermal_zone(child);
980 if (IS_ERR(tz)) {
981 pr_err("failed to build thermal zone %s: %ld\n",
982 child->name,
983 PTR_ERR(tz));
984 continue;
985 }
986
987 ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
988 if (!ops)
989 goto exit_free;
990
991 tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
992 if (!tzp) {
993 kfree(ops);
994 goto exit_free;
995 }
996
997
998 tzp->no_hwmon = true;
999
1000 if (!of_property_read_u32(child, "sustainable-power", &prop))
1001 tzp->sustainable_power = prop;
1002
1003 for (i = 0; i < tz->ntrips; i++)
1004 mask |= 1 << i;
1005
1006
1007 tzp->slope = tz->slope;
1008 tzp->offset = tz->offset;
1009
1010 zone = thermal_zone_device_register(child->name, tz->ntrips,
1011 mask, tz,
1012 ops, tzp,
1013 tz->passive_delay,
1014 tz->polling_delay);
1015 if (IS_ERR(zone)) {
1016 pr_err("Failed to build %s zone %ld\n", child->name,
1017 PTR_ERR(zone));
1018 kfree(tzp);
1019 kfree(ops);
1020 of_thermal_free_zone(tz);
1021
1022 }
1023 }
1024 of_node_put(np);
1025
1026 return 0;
1027
1028exit_free:
1029 of_node_put(child);
1030 of_node_put(np);
1031 of_thermal_free_zone(tz);
1032
1033
1034 of_thermal_destroy_zones();
1035
1036 return -ENOMEM;
1037}
1038
1039
1040
1041
1042
1043
1044
1045
1046void of_thermal_destroy_zones(void)
1047{
1048 struct device_node *np, *child;
1049
1050 np = of_find_node_by_name(NULL, "thermal-zones");
1051 if (!np) {
1052 pr_debug("unable to find thermal zones\n");
1053 return;
1054 }
1055
1056 for_each_available_child_of_node(np, child) {
1057 struct thermal_zone_device *zone;
1058
1059 zone = thermal_zone_get_zone_by_name(child->name);
1060 if (IS_ERR(zone))
1061 continue;
1062
1063 thermal_zone_device_unregister(zone);
1064 kfree(zone->tzp);
1065 kfree(zone->ops);
1066 of_thermal_free_zone(zone->devdata);
1067 }
1068 of_node_put(np);
1069}
1070