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