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