drm/amd/display: disable S/G display on DCN 3.1.4
[platform/kernel/linux-starfive.git] / drivers / thermal / thermal_of.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  of-thermal.c - Generic Thermal Management device tree support.
4  *
5  *  Copyright (C) 2013 Texas Instruments
6  *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
7  */
8
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11 #include <linux/err.h>
12 #include <linux/export.h>
13 #include <linux/of_device.h>
14 #include <linux/of_platform.h>
15 #include <linux/slab.h>
16 #include <linux/thermal.h>
17 #include <linux/types.h>
18 #include <linux/string.h>
19
20 #include "thermal_core.h"
21
22 /**
23  * of_thermal_get_ntrips - function to export number of available trip
24  *                         points.
25  * @tz: pointer to a thermal zone
26  *
27  * This function is a globally visible wrapper to get number of trip points
28  * stored in the local struct __thermal_zone
29  *
30  * Return: number of available trip points, -ENODEV when data not available
31  */
32 int of_thermal_get_ntrips(struct thermal_zone_device *tz)
33 {
34         return tz->num_trips;
35 }
36 EXPORT_SYMBOL_GPL(of_thermal_get_ntrips);
37
38 /**
39  * of_thermal_is_trip_valid - function to check if trip point is valid
40  *
41  * @tz: pointer to a thermal zone
42  * @trip:       trip point to evaluate
43  *
44  * This function is responsible for checking if passed trip point is valid
45  *
46  * Return: true if trip point is valid, false otherwise
47  */
48 bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, int trip)
49 {
50         if (trip >= tz->num_trips || trip < 0)
51                 return false;
52
53         return true;
54 }
55 EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid);
56
57 /**
58  * of_thermal_get_trip_points - function to get access to a globally exported
59  *                              trip points
60  *
61  * @tz: pointer to a thermal zone
62  *
63  * This function provides a pointer to trip points table
64  *
65  * Return: pointer to trip points table, NULL otherwise
66  */
67 const struct thermal_trip *
68 of_thermal_get_trip_points(struct thermal_zone_device *tz)
69 {
70         return tz->trips;
71 }
72 EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
73
74 static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
75                                     enum thermal_trip_type *type)
76 {
77         if (trip >= tz->num_trips || trip < 0)
78                 return -EDOM;
79
80         *type = tz->trips[trip].type;
81
82         return 0;
83 }
84
85 static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
86                                     int *temp)
87 {
88         if (trip >= tz->num_trips || trip < 0)
89                 return -EDOM;
90
91         *temp = tz->trips[trip].temperature;
92
93         return 0;
94 }
95
96 static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
97                                     int *hyst)
98 {
99         if (trip >= tz->num_trips || trip < 0)
100                 return -EDOM;
101
102         *hyst = tz->trips[trip].hysteresis;
103
104         return 0;
105 }
106
107 static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
108                                     int hyst)
109 {
110         if (trip >= tz->num_trips || trip < 0)
111                 return -EDOM;
112
113         /* thermal framework should take care of data->mask & (1 << trip) */
114         tz->trips[trip].hysteresis = hyst;
115
116         return 0;
117 }
118
119 static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
120                                     int *temp)
121 {
122         int i;
123
124         for (i = 0; i < tz->num_trips; i++)
125                 if (tz->trips[i].type == THERMAL_TRIP_CRITICAL) {
126                         *temp = tz->trips[i].temperature;
127                         return 0;
128                 }
129
130         return -EINVAL;
131 }
132
133 /***   functions parsing device tree nodes   ***/
134
135 static int of_find_trip_id(struct device_node *np, struct device_node *trip)
136 {
137         struct device_node *trips;
138         struct device_node *t;
139         int i = 0;
140
141         trips = of_get_child_by_name(np, "trips");
142         if (!trips) {
143                 pr_err("Failed to find 'trips' node\n");
144                 return -EINVAL;
145         }
146
147         /*
148          * Find the trip id point associated with the cooling device map
149          */
150         for_each_child_of_node(trips, t) {
151
152                 if (t == trip)
153                         goto out;
154                 i++;
155         }
156
157         i = -ENXIO;
158 out:
159         of_node_put(trips);
160
161         return i;
162 }
163
164 /*
165  * It maps 'enum thermal_trip_type' found in include/linux/thermal.h
166  * into the device tree binding of 'trip', property type.
167  */
168 static const char * const trip_types[] = {
169         [THERMAL_TRIP_ACTIVE]   = "active",
170         [THERMAL_TRIP_PASSIVE]  = "passive",
171         [THERMAL_TRIP_HOT]      = "hot",
172         [THERMAL_TRIP_CRITICAL] = "critical",
173 };
174
175 /**
176  * thermal_of_get_trip_type - Get phy mode for given device_node
177  * @np: Pointer to the given device_node
178  * @type: Pointer to resulting trip type
179  *
180  * The function gets trip type string from property 'type',
181  * and store its index in trip_types table in @type,
182  *
183  * Return: 0 on success, or errno in error case.
184  */
185 static int thermal_of_get_trip_type(struct device_node *np,
186                                     enum thermal_trip_type *type)
187 {
188         const char *t;
189         int err, i;
190
191         err = of_property_read_string(np, "type", &t);
192         if (err < 0)
193                 return err;
194
195         for (i = 0; i < ARRAY_SIZE(trip_types); i++)
196                 if (!strcasecmp(t, trip_types[i])) {
197                         *type = i;
198                         return 0;
199                 }
200
201         return -ENODEV;
202 }
203
204 static int thermal_of_populate_trip(struct device_node *np,
205                                     struct thermal_trip *trip)
206 {
207         int prop;
208         int ret;
209
210         ret = of_property_read_u32(np, "temperature", &prop);
211         if (ret < 0) {
212                 pr_err("missing temperature property\n");
213                 return ret;
214         }
215         trip->temperature = prop;
216
217         ret = of_property_read_u32(np, "hysteresis", &prop);
218         if (ret < 0) {
219                 pr_err("missing hysteresis property\n");
220                 return ret;
221         }
222         trip->hysteresis = prop;
223
224         ret = thermal_of_get_trip_type(np, &trip->type);
225         if (ret < 0) {
226                 pr_err("wrong trip type property\n");
227                 return ret;
228         }
229
230         return 0;
231 }
232
233 static struct thermal_trip *thermal_of_trips_init(struct device_node *np, int *ntrips)
234 {
235         struct thermal_trip *tt;
236         struct device_node *trips, *trip;
237         int ret, count;
238
239         trips = of_get_child_by_name(np, "trips");
240         if (!trips) {
241                 pr_err("Failed to find 'trips' node\n");
242                 return ERR_PTR(-EINVAL);
243         }
244
245         count = of_get_child_count(trips);
246         if (!count) {
247                 pr_err("No trip point defined\n");
248                 ret = -EINVAL;
249                 goto out_of_node_put;
250         }
251
252         tt = kzalloc(sizeof(*tt) * count, GFP_KERNEL);
253         if (!tt) {
254                 ret = -ENOMEM;
255                 goto out_of_node_put;
256         }
257
258         *ntrips = count;
259
260         count = 0;
261         for_each_child_of_node(trips, trip) {
262                 ret = thermal_of_populate_trip(trip, &tt[count++]);
263                 if (ret)
264                         goto out_kfree;
265         }
266
267         of_node_put(trips);
268
269         return tt;
270
271 out_kfree:
272         kfree(tt);
273         *ntrips = 0;
274 out_of_node_put:
275         of_node_put(trips);
276
277         return ERR_PTR(ret);
278 }
279
280 static struct device_node *of_thermal_zone_find(struct device_node *sensor, int id)
281 {
282         struct device_node *np, *tz;
283         struct of_phandle_args sensor_specs;
284
285         np = of_find_node_by_name(NULL, "thermal-zones");
286         if (!np) {
287                 pr_debug("No thermal zones description\n");
288                 return ERR_PTR(-ENODEV);
289         }
290
291         /*
292          * Search for each thermal zone, a defined sensor
293          * corresponding to the one passed as parameter
294          */
295         for_each_available_child_of_node(np, tz) {
296
297                 int count, i;
298
299                 count = of_count_phandle_with_args(tz, "thermal-sensors",
300                                                    "#thermal-sensor-cells");
301                 if (count <= 0) {
302                         pr_err("%pOFn: missing thermal sensor\n", tz);
303                         tz = ERR_PTR(-EINVAL);
304                         goto out;
305                 }
306
307                 for (i = 0; i < count; i++) {
308
309                         int ret;
310
311                         ret = of_parse_phandle_with_args(tz, "thermal-sensors",
312                                                          "#thermal-sensor-cells",
313                                                          i, &sensor_specs);
314                         if (ret < 0) {
315                                 pr_err("%pOFn: Failed to read thermal-sensors cells: %d\n", tz, ret);
316                                 tz = ERR_PTR(ret);
317                                 goto out;
318                         }
319
320                         if ((sensor == sensor_specs.np) && id == (sensor_specs.args_count ?
321                                                                   sensor_specs.args[0] : 0)) {
322                                 pr_debug("sensor %pOFn id=%d belongs to %pOFn\n", sensor, id, tz);
323                                 goto out;
324                         }
325                 }
326         }
327         tz = ERR_PTR(-ENODEV);
328 out:
329         of_node_put(np);
330         return tz;
331 }
332
333 static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdelay)
334 {
335         int ret;
336
337         ret = of_property_read_u32(np, "polling-delay-passive", pdelay);
338         if (ret < 0) {
339                 pr_err("%pOFn: missing polling-delay-passive property\n", np);
340                 return ret;
341         }
342
343         ret = of_property_read_u32(np, "polling-delay", delay);
344         if (ret < 0) {
345                 pr_err("%pOFn: missing polling-delay property\n", np);
346                 return ret;
347         }
348
349         return 0;
350 }
351
352 static struct thermal_zone_params *thermal_of_parameters_init(struct device_node *np)
353 {
354         struct thermal_zone_params *tzp;
355         int coef[2];
356         int ncoef = ARRAY_SIZE(coef);
357         int prop, ret;
358
359         tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
360         if (!tzp)
361                 return ERR_PTR(-ENOMEM);
362
363         tzp->no_hwmon = true;
364
365         if (!of_property_read_u32(np, "sustainable-power", &prop))
366                 tzp->sustainable_power = prop;
367
368         /*
369          * For now, the thermal framework supports only one sensor per
370          * thermal zone. Thus, we are considering only the first two
371          * values as slope and offset.
372          */
373         ret = of_property_read_u32_array(np, "coefficients", coef, ncoef);
374         if (ret) {
375                 coef[0] = 1;
376                 coef[1] = 0;
377         }
378
379         tzp->slope = coef[0];
380         tzp->offset = coef[1];
381
382         return tzp;
383 }
384
385 static struct device_node *thermal_of_zone_get_by_name(struct thermal_zone_device *tz)
386 {
387         struct device_node *np, *tz_np;
388
389         np = of_find_node_by_name(NULL, "thermal-zones");
390         if (!np)
391                 return ERR_PTR(-ENODEV);
392
393         tz_np = of_get_child_by_name(np, tz->type);
394
395         of_node_put(np);
396
397         if (!tz_np)
398                 return ERR_PTR(-ENODEV);
399
400         return tz_np;
401 }
402
403 static int __thermal_of_unbind(struct device_node *map_np, int index, int trip_id,
404                                struct thermal_zone_device *tz, struct thermal_cooling_device *cdev)
405 {
406         struct of_phandle_args cooling_spec;
407         int ret;
408
409         ret = of_parse_phandle_with_args(map_np, "cooling-device", "#cooling-cells",
410                                          index, &cooling_spec);
411
412         of_node_put(cooling_spec.np);
413
414         if (ret < 0) {
415                 pr_err("Invalid cooling-device entry\n");
416                 return ret;
417         }
418
419         if (cooling_spec.args_count < 2) {
420                 pr_err("wrong reference to cooling device, missing limits\n");
421                 return -EINVAL;
422         }
423
424         if (cooling_spec.np != cdev->np)
425                 return 0;
426
427         ret = thermal_zone_unbind_cooling_device(tz, trip_id, cdev);
428         if (ret)
429                 pr_err("Failed to unbind '%s' with '%s': %d\n", tz->type, cdev->type, ret);
430
431         return ret;
432 }
433
434 static int __thermal_of_bind(struct device_node *map_np, int index, int trip_id,
435                              struct thermal_zone_device *tz, struct thermal_cooling_device *cdev)
436 {
437         struct of_phandle_args cooling_spec;
438         int ret, weight = THERMAL_WEIGHT_DEFAULT;
439
440         of_property_read_u32(map_np, "contribution", &weight);
441
442         ret = of_parse_phandle_with_args(map_np, "cooling-device", "#cooling-cells",
443                                          index, &cooling_spec);
444
445         of_node_put(cooling_spec.np);
446
447         if (ret < 0) {
448                 pr_err("Invalid cooling-device entry\n");
449                 return ret;
450         }
451
452         if (cooling_spec.args_count < 2) {
453                 pr_err("wrong reference to cooling device, missing limits\n");
454                 return -EINVAL;
455         }
456
457         if (cooling_spec.np != cdev->np)
458                 return 0;
459
460         ret = thermal_zone_bind_cooling_device(tz, trip_id, cdev, cooling_spec.args[1],
461                                                cooling_spec.args[0],
462                                                weight);
463         if (ret)
464                 pr_err("Failed to bind '%s' with '%s': %d\n", tz->type, cdev->type, ret);
465
466         return ret;
467 }
468
469 static int thermal_of_for_each_cooling_device(struct device_node *tz_np, struct device_node *map_np,
470                                               struct thermal_zone_device *tz, struct thermal_cooling_device *cdev,
471                                               int (*action)(struct device_node *, int, int,
472                                                             struct thermal_zone_device *, struct thermal_cooling_device *))
473 {
474         struct device_node *tr_np;
475         int count, i, trip_id;
476
477         tr_np = of_parse_phandle(map_np, "trip", 0);
478         if (!tr_np)
479                 return -ENODEV;
480
481         trip_id = of_find_trip_id(tz_np, tr_np);
482         if (trip_id < 0)
483                 return trip_id;
484
485         count = of_count_phandle_with_args(map_np, "cooling-device", "#cooling-cells");
486         if (count <= 0) {
487                 pr_err("Add a cooling_device property with at least one device\n");
488                 return -ENOENT;
489         }
490
491         /*
492          * At this point, we don't want to bail out when there is an
493          * error, we will try to bind/unbind as many as possible
494          * cooling devices
495          */
496         for (i = 0; i < count; i++)
497                 action(map_np, i, trip_id, tz, cdev);
498
499         return 0;
500 }
501
502 static int thermal_of_for_each_cooling_maps(struct thermal_zone_device *tz,
503                                             struct thermal_cooling_device *cdev,
504                                             int (*action)(struct device_node *, int, int,
505                                                           struct thermal_zone_device *, struct thermal_cooling_device *))
506 {
507         struct device_node *tz_np, *cm_np, *child;
508         int ret = 0;
509
510         tz_np = thermal_of_zone_get_by_name(tz);
511         if (IS_ERR(tz_np)) {
512                 pr_err("Failed to get node tz by name\n");
513                 return PTR_ERR(tz_np);
514         }
515
516         cm_np = of_get_child_by_name(tz_np, "cooling-maps");
517         if (!cm_np)
518                 goto out;
519
520         for_each_child_of_node(cm_np, child) {
521                 ret = thermal_of_for_each_cooling_device(tz_np, child, tz, cdev, action);
522                 if (ret)
523                         break;
524         }
525
526         of_node_put(cm_np);
527 out:
528         of_node_put(tz_np);
529
530         return ret;
531 }
532
533 static int thermal_of_bind(struct thermal_zone_device *tz,
534                            struct thermal_cooling_device *cdev)
535 {
536         return thermal_of_for_each_cooling_maps(tz, cdev, __thermal_of_bind);
537 }
538
539 static int thermal_of_unbind(struct thermal_zone_device *tz,
540                              struct thermal_cooling_device *cdev)
541 {
542         return thermal_of_for_each_cooling_maps(tz, cdev, __thermal_of_unbind);
543 }
544
545 /**
546  * thermal_of_zone_unregister - Cleanup the specific allocated ressources
547  *
548  * This function disables the thermal zone and frees the different
549  * ressources allocated specific to the thermal OF.
550  *
551  * @tz: a pointer to the thermal zone structure
552  */
553 void thermal_of_zone_unregister(struct thermal_zone_device *tz)
554 {
555         struct thermal_trip *trips = tz->trips;
556         struct thermal_zone_params *tzp = tz->tzp;
557         struct thermal_zone_device_ops *ops = tz->ops;
558
559         thermal_zone_device_disable(tz);
560         thermal_zone_device_unregister(tz);
561         kfree(trips);
562         kfree(tzp);
563         kfree(ops);
564 }
565 EXPORT_SYMBOL_GPL(thermal_of_zone_unregister);
566
567 /**
568  * thermal_of_zone_register - Register a thermal zone with device node
569  * sensor
570  *
571  * The thermal_of_zone_register() parses a device tree given a device
572  * node sensor and identifier. It searches for the thermal zone
573  * associated to the couple sensor/id and retrieves all the thermal
574  * zone properties and registers new thermal zone with those
575  * properties.
576  *
577  * @sensor: A device node pointer corresponding to the sensor in the device tree
578  * @id: An integer as sensor identifier
579  * @data: A private data to be stored in the thermal zone dedicated private area
580  * @ops: A set of thermal sensor ops
581  *
582  * Return: a valid thermal zone structure pointer on success.
583  *      - EINVAL: if the device tree thermal description is malformed
584  *      - ENOMEM: if one structure can not be allocated
585  *      - Other negative errors are returned by the underlying called functions
586  */
587 struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, int id, void *data,
588                                                      const struct thermal_zone_device_ops *ops)
589 {
590         struct thermal_zone_device *tz;
591         struct thermal_trip *trips;
592         struct thermal_zone_params *tzp;
593         struct thermal_zone_device_ops *of_ops;
594         struct device_node *np;
595         int delay, pdelay;
596         int ntrips, mask;
597         int ret;
598
599         of_ops = kmemdup(ops, sizeof(*ops), GFP_KERNEL);
600         if (!of_ops)
601                 return ERR_PTR(-ENOMEM);
602
603         np = of_thermal_zone_find(sensor, id);
604         if (IS_ERR(np)) {
605                 if (PTR_ERR(np) != -ENODEV)
606                         pr_err("Failed to find thermal zone for %pOFn id=%d\n", sensor, id);
607                 ret = PTR_ERR(np);
608                 goto out_kfree_of_ops;
609         }
610
611         trips = thermal_of_trips_init(np, &ntrips);
612         if (IS_ERR(trips)) {
613                 pr_err("Failed to find trip points for %pOFn id=%d\n", sensor, id);
614                 ret = PTR_ERR(trips);
615                 goto out_kfree_of_ops;
616         }
617
618         ret = thermal_of_monitor_init(np, &delay, &pdelay);
619         if (ret) {
620                 pr_err("Failed to initialize monitoring delays from %pOFn\n", np);
621                 goto out_kfree_trips;
622         }
623
624         tzp = thermal_of_parameters_init(np);
625         if (IS_ERR(tzp)) {
626                 ret = PTR_ERR(tzp);
627                 pr_err("Failed to initialize parameter from %pOFn: %d\n", np, ret);
628                 goto out_kfree_trips;
629         }
630
631         of_ops->get_trip_type = of_ops->get_trip_type ? : of_thermal_get_trip_type;
632         of_ops->get_trip_temp = of_ops->get_trip_temp ? : of_thermal_get_trip_temp;
633         of_ops->get_trip_hyst = of_ops->get_trip_hyst ? : of_thermal_get_trip_hyst;
634         of_ops->set_trip_hyst = of_ops->set_trip_hyst ? : of_thermal_set_trip_hyst;
635         of_ops->get_crit_temp = of_ops->get_crit_temp ? : of_thermal_get_crit_temp;
636         of_ops->bind = thermal_of_bind;
637         of_ops->unbind = thermal_of_unbind;
638
639         mask = GENMASK_ULL((ntrips) - 1, 0);
640
641         tz = thermal_zone_device_register_with_trips(np->name, trips, ntrips,
642                                                      mask, data, of_ops, tzp,
643                                                      pdelay, delay);
644         if (IS_ERR(tz)) {
645                 ret = PTR_ERR(tz);
646                 pr_err("Failed to register thermal zone %pOFn: %d\n", np, ret);
647                 goto out_kfree_tzp;
648         }
649
650         ret = thermal_zone_device_enable(tz);
651         if (ret) {
652                 pr_err("Failed to enabled thermal zone '%s', id=%d: %d\n",
653                        tz->type, tz->id, ret);
654                 thermal_of_zone_unregister(tz);
655                 return ERR_PTR(ret);
656         }
657
658         return tz;
659
660 out_kfree_tzp:
661         kfree(tzp);
662 out_kfree_trips:
663         kfree(trips);
664 out_kfree_of_ops:
665         kfree(of_ops);
666
667         return ERR_PTR(ret);
668 }
669 EXPORT_SYMBOL_GPL(thermal_of_zone_register);
670
671 static void devm_thermal_of_zone_release(struct device *dev, void *res)
672 {
673         thermal_of_zone_unregister(*(struct thermal_zone_device **)res);
674 }
675
676 static int devm_thermal_of_zone_match(struct device *dev, void *res,
677                                       void *data)
678 {
679         struct thermal_zone_device **r = res;
680
681         if (WARN_ON(!r || !*r))
682                 return 0;
683
684         return *r == data;
685 }
686
687 /**
688  * devm_thermal_of_zone_register - register a thermal tied with the sensor life cycle
689  *
690  * This function is the device version of the thermal_of_zone_register() function.
691  *
692  * @dev: a device structure pointer to sensor to be tied with the thermal zone OF life cycle
693  * @sensor_id: the sensor identifier
694  * @data: a pointer to a private data to be stored in the thermal zone 'devdata' field
695  * @ops: a pointer to the ops structure associated with the sensor
696  */
697 struct thermal_zone_device *devm_thermal_of_zone_register(struct device *dev, int sensor_id, void *data,
698                                                           const struct thermal_zone_device_ops *ops)
699 {
700         struct thermal_zone_device **ptr, *tzd;
701
702         ptr = devres_alloc(devm_thermal_of_zone_release, sizeof(*ptr),
703                            GFP_KERNEL);
704         if (!ptr)
705                 return ERR_PTR(-ENOMEM);
706
707         tzd = thermal_of_zone_register(dev->of_node, sensor_id, data, ops);
708         if (IS_ERR(tzd)) {
709                 devres_free(ptr);
710                 return tzd;
711         }
712
713         *ptr = tzd;
714         devres_add(dev, ptr);
715
716         return tzd;
717 }
718 EXPORT_SYMBOL_GPL(devm_thermal_of_zone_register);
719
720 /**
721  * devm_thermal_of_zone_unregister - Resource managed version of
722  *                              thermal_of_zone_unregister().
723  * @dev: Device for which which resource was allocated.
724  * @tz: a pointer to struct thermal_zone where the sensor is registered.
725  *
726  * This function removes the sensor callbacks and private data from the
727  * thermal zone device registered with devm_thermal_zone_of_sensor_register()
728  * API. It will also silent the zone by remove the .get_temp() and .get_trend()
729  * thermal zone device callbacks.
730  * Normally this function will not need to be called and the resource
731  * management code will ensure that the resource is freed.
732  */
733 void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz)
734 {
735         WARN_ON(devres_release(dev, devm_thermal_of_zone_release,
736                                devm_thermal_of_zone_match, tz));
737 }
738 EXPORT_SYMBOL_GPL(devm_thermal_of_zone_unregister);