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