1 // SPDX-License-Identifier: GPL-2.0
3 * of-thermal.c - Generic Thermal Management device tree support.
5 * Copyright (C) 2013 Texas Instruments
6 * Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #include <linux/thermal.h>
12 #include <linux/slab.h>
13 #include <linux/types.h>
14 #include <linux/of_device.h>
15 #include <linux/of_platform.h>
16 #include <linux/err.h>
17 #include <linux/export.h>
18 #include <linux/string.h>
20 #include "thermal_core.h"
22 /*** Private data structures to represent thermal device tree data ***/
25 * struct __thermal_cooling_bind_param - a cooling device for a trip point
26 * @cooling_device: a pointer to identify the referred cooling device
27 * @min: minimum cooling state used at this trip point
28 * @max: maximum cooling state used at this trip point
31 struct __thermal_cooling_bind_param
{
32 struct device_node
*cooling_device
;
38 * struct __thermal_bind_param - a match between trip and cooling device
39 * @tcbp: a pointer to an array of cooling devices
40 * @count: number of elements in array
41 * @trip_id: the trip point index
42 * @usage: the percentage (from 0 to 100) of cooling contribution
45 struct __thermal_bind_params
{
46 struct __thermal_cooling_bind_param
*tcbp
;
53 * struct __thermal_zone - internal representation of a thermal zone
54 * @mode: current thermal zone device mode (enabled/disabled)
55 * @passive_delay: polling interval while passive cooling is activated
56 * @polling_delay: zone polling interval
57 * @slope: slope of the temperature adjustment curve
58 * @offset: offset of the temperature adjustment curve
59 * @ntrips: number of trip points
60 * @trips: an array of trip points (0..ntrips - 1)
61 * @num_tbps: number of thermal bind params
62 * @tbps: an array of thermal bind params (0..num_tbps - 1)
63 * @sensor_data: sensor private data used while reading temperature and trend
64 * @ops: set of callbacks to handle the thermal zone based on DT
67 struct __thermal_zone
{
68 enum thermal_device_mode mode
;
76 struct thermal_trip
*trips
;
78 /* cooling binding data */
80 struct __thermal_bind_params
*tbps
;
82 /* sensor interface */
84 const struct thermal_zone_of_device_ops
*ops
;
87 /*** DT thermal zone device callbacks ***/
89 static int of_thermal_get_temp(struct thermal_zone_device
*tz
,
92 struct __thermal_zone
*data
= tz
->devdata
;
94 if (!data
->ops
->get_temp
)
97 return data
->ops
->get_temp(data
->sensor_data
, temp
);
100 static int of_thermal_set_trips(struct thermal_zone_device
*tz
,
103 struct __thermal_zone
*data
= tz
->devdata
;
105 if (!data
->ops
|| !data
->ops
->set_trips
)
108 return data
->ops
->set_trips(data
->sensor_data
, low
, high
);
112 * of_thermal_get_ntrips - function to export number of available trip
114 * @tz: pointer to a thermal zone
116 * This function is a globally visible wrapper to get number of trip points
117 * stored in the local struct __thermal_zone
119 * Return: number of available trip points, -ENODEV when data not available
121 int of_thermal_get_ntrips(struct thermal_zone_device
*tz
)
123 struct __thermal_zone
*data
= tz
->devdata
;
125 if (!data
|| IS_ERR(data
))
130 EXPORT_SYMBOL_GPL(of_thermal_get_ntrips
);
133 * of_thermal_is_trip_valid - function to check if trip point is valid
135 * @tz: pointer to a thermal zone
136 * @trip: trip point to evaluate
138 * This function is responsible for checking if passed trip point is valid
140 * Return: true if trip point is valid, false otherwise
142 bool of_thermal_is_trip_valid(struct thermal_zone_device
*tz
, int trip
)
144 struct __thermal_zone
*data
= tz
->devdata
;
146 if (!data
|| trip
>= data
->ntrips
|| trip
< 0)
151 EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid
);
154 * of_thermal_get_trip_points - function to get access to a globally exported
157 * @tz: pointer to a thermal zone
159 * This function provides a pointer to trip points table
161 * Return: pointer to trip points table, NULL otherwise
163 const struct thermal_trip
*
164 of_thermal_get_trip_points(struct thermal_zone_device
*tz
)
166 struct __thermal_zone
*data
= tz
->devdata
;
173 EXPORT_SYMBOL_GPL(of_thermal_get_trip_points
);
176 * of_thermal_set_emul_temp - function to set emulated temperature
178 * @tz: pointer to a thermal zone
179 * @temp: temperature to set
181 * This function gives the ability to set emulated value of temperature,
182 * which is handy for debugging
184 * Return: zero on success, error code otherwise
186 static int of_thermal_set_emul_temp(struct thermal_zone_device
*tz
,
189 struct __thermal_zone
*data
= tz
->devdata
;
191 return data
->ops
->set_emul_temp(data
->sensor_data
, temp
);
194 static int of_thermal_get_trend(struct thermal_zone_device
*tz
, int trip
,
195 enum thermal_trend
*trend
)
197 struct __thermal_zone
*data
= tz
->devdata
;
199 if (!data
->ops
->get_trend
)
202 return data
->ops
->get_trend(data
->sensor_data
, trip
, trend
);
205 static int of_thermal_bind(struct thermal_zone_device
*thermal
,
206 struct thermal_cooling_device
*cdev
)
208 struct __thermal_zone
*data
= thermal
->devdata
;
209 struct __thermal_bind_params
*tbp
;
210 struct __thermal_cooling_bind_param
*tcbp
;
213 if (!data
|| IS_ERR(data
))
216 /* find where to bind */
217 for (i
= 0; i
< data
->num_tbps
; i
++) {
218 tbp
= data
->tbps
+ i
;
220 for (j
= 0; j
< tbp
->count
; j
++) {
221 tcbp
= tbp
->tcbp
+ j
;
223 if (tcbp
->cooling_device
== cdev
->np
) {
226 ret
= thermal_zone_bind_cooling_device(thermal
,
240 static int of_thermal_unbind(struct thermal_zone_device
*thermal
,
241 struct thermal_cooling_device
*cdev
)
243 struct __thermal_zone
*data
= thermal
->devdata
;
244 struct __thermal_bind_params
*tbp
;
245 struct __thermal_cooling_bind_param
*tcbp
;
248 if (!data
|| IS_ERR(data
))
251 /* find where to unbind */
252 for (i
= 0; i
< data
->num_tbps
; i
++) {
253 tbp
= data
->tbps
+ i
;
255 for (j
= 0; j
< tbp
->count
; j
++) {
256 tcbp
= tbp
->tcbp
+ j
;
258 if (tcbp
->cooling_device
== cdev
->np
) {
261 ret
= thermal_zone_unbind_cooling_device(thermal
,
272 static int of_thermal_get_mode(struct thermal_zone_device
*tz
,
273 enum thermal_device_mode
*mode
)
275 struct __thermal_zone
*data
= tz
->devdata
;
282 static int of_thermal_set_mode(struct thermal_zone_device
*tz
,
283 enum thermal_device_mode mode
)
285 struct __thermal_zone
*data
= tz
->devdata
;
287 mutex_lock(&tz
->lock
);
289 if (mode
== THERMAL_DEVICE_ENABLED
) {
290 tz
->polling_delay
= data
->polling_delay
;
291 tz
->passive_delay
= data
->passive_delay
;
293 tz
->polling_delay
= 0;
294 tz
->passive_delay
= 0;
297 mutex_unlock(&tz
->lock
);
300 thermal_zone_device_update(tz
, THERMAL_EVENT_UNSPECIFIED
);
305 static int of_thermal_get_trip_type(struct thermal_zone_device
*tz
, int trip
,
306 enum thermal_trip_type
*type
)
308 struct __thermal_zone
*data
= tz
->devdata
;
310 if (trip
>= data
->ntrips
|| trip
< 0)
313 *type
= data
->trips
[trip
].type
;
318 static int of_thermal_get_trip_temp(struct thermal_zone_device
*tz
, int trip
,
321 struct __thermal_zone
*data
= tz
->devdata
;
323 if (trip
>= data
->ntrips
|| trip
< 0)
326 *temp
= data
->trips
[trip
].temperature
;
331 static int of_thermal_set_trip_temp(struct thermal_zone_device
*tz
, int trip
,
334 struct __thermal_zone
*data
= tz
->devdata
;
336 if (trip
>= data
->ntrips
|| trip
< 0)
339 if (data
->ops
->set_trip_temp
) {
342 ret
= data
->ops
->set_trip_temp(data
->sensor_data
, trip
, temp
);
347 /* thermal framework should take care of data->mask & (1 << trip) */
348 data
->trips
[trip
].temperature
= temp
;
353 static int of_thermal_get_trip_hyst(struct thermal_zone_device
*tz
, int trip
,
356 struct __thermal_zone
*data
= tz
->devdata
;
358 if (trip
>= data
->ntrips
|| trip
< 0)
361 *hyst
= data
->trips
[trip
].hysteresis
;
366 static int of_thermal_set_trip_hyst(struct thermal_zone_device
*tz
, int trip
,
369 struct __thermal_zone
*data
= tz
->devdata
;
371 if (trip
>= data
->ntrips
|| trip
< 0)
374 /* thermal framework should take care of data->mask & (1 << trip) */
375 data
->trips
[trip
].hysteresis
= hyst
;
380 static int of_thermal_get_crit_temp(struct thermal_zone_device
*tz
,
383 struct __thermal_zone
*data
= tz
->devdata
;
386 for (i
= 0; i
< data
->ntrips
; i
++)
387 if (data
->trips
[i
].type
== THERMAL_TRIP_CRITICAL
) {
388 *temp
= data
->trips
[i
].temperature
;
395 static struct thermal_zone_device_ops of_thermal_ops
= {
396 .get_mode
= of_thermal_get_mode
,
397 .set_mode
= of_thermal_set_mode
,
399 .get_trip_type
= of_thermal_get_trip_type
,
400 .get_trip_temp
= of_thermal_get_trip_temp
,
401 .set_trip_temp
= of_thermal_set_trip_temp
,
402 .get_trip_hyst
= of_thermal_get_trip_hyst
,
403 .set_trip_hyst
= of_thermal_set_trip_hyst
,
404 .get_crit_temp
= of_thermal_get_crit_temp
,
406 .bind
= of_thermal_bind
,
407 .unbind
= of_thermal_unbind
,
412 static struct thermal_zone_device
*
413 thermal_zone_of_add_sensor(struct device_node
*zone
,
414 struct device_node
*sensor
, void *data
,
415 const struct thermal_zone_of_device_ops
*ops
)
417 struct thermal_zone_device
*tzd
;
418 struct __thermal_zone
*tz
;
420 tzd
= thermal_zone_get_zone_by_name(zone
->name
);
422 return ERR_PTR(-EPROBE_DEFER
);
427 return ERR_PTR(-EINVAL
);
429 mutex_lock(&tzd
->lock
);
431 tz
->sensor_data
= data
;
433 tzd
->ops
->get_temp
= of_thermal_get_temp
;
434 tzd
->ops
->get_trend
= of_thermal_get_trend
;
437 * The thermal zone core will calculate the window if they have set the
438 * optional set_trips pointer.
441 tzd
->ops
->set_trips
= of_thermal_set_trips
;
443 if (ops
->set_emul_temp
)
444 tzd
->ops
->set_emul_temp
= of_thermal_set_emul_temp
;
446 mutex_unlock(&tzd
->lock
);
452 * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone
453 * @dev: a valid struct device pointer of a sensor device. Must contain
454 * a valid .of_node, for the sensor node.
455 * @sensor_id: a sensor identifier, in case the sensor IP has more
457 * @data: a private pointer (owned by the caller) that will be passed
458 * back, when a temperature reading is needed.
459 * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
461 * This function will search the list of thermal zones described in device
462 * tree and look for the zone that refer to the sensor device pointed by
463 * @dev->of_node as temperature providers. For the zone pointing to the
464 * sensor node, the sensor will be added to the DT thermal zone device.
466 * The thermal zone temperature is provided by the @get_temp function
467 * pointer. When called, it will have the private pointer @data back.
469 * The thermal zone temperature trend is provided by the @get_trend function
470 * pointer. When called, it will have the private pointer @data back.
473 * 01 - This function must enqueue the new sensor instead of using
474 * it as the only source of temperature values.
476 * 02 - There must be a way to match the sensor with all thermal zones
479 * Return: On success returns a valid struct thermal_zone_device,
480 * otherwise, it returns a corresponding ERR_PTR(). Caller must
481 * check the return value with help of IS_ERR() helper.
483 struct thermal_zone_device
*
484 thermal_zone_of_sensor_register(struct device
*dev
, int sensor_id
, void *data
,
485 const struct thermal_zone_of_device_ops
*ops
)
487 struct device_node
*np
, *child
, *sensor_np
;
488 struct thermal_zone_device
*tzd
= ERR_PTR(-ENODEV
);
490 np
= of_find_node_by_name(NULL
, "thermal-zones");
492 return ERR_PTR(-ENODEV
);
494 if (!dev
|| !dev
->of_node
) {
496 return ERR_PTR(-ENODEV
);
499 sensor_np
= of_node_get(dev
->of_node
);
501 for_each_available_child_of_node(np
, child
) {
502 struct of_phandle_args sensor_specs
;
505 /* For now, thermal framework supports only 1 sensor per zone */
506 ret
= of_parse_phandle_with_args(child
, "thermal-sensors",
507 "#thermal-sensor-cells",
512 if (sensor_specs
.args_count
>= 1) {
513 id
= sensor_specs
.args
[0];
514 WARN(sensor_specs
.args_count
> 1,
515 "%pOFn: too many cells in sensor specifier %d\n",
516 sensor_specs
.np
, sensor_specs
.args_count
);
521 if (sensor_specs
.np
== sensor_np
&& id
== sensor_id
) {
522 tzd
= thermal_zone_of_add_sensor(child
, sensor_np
,
525 tzd
->ops
->set_mode(tzd
, THERMAL_DEVICE_ENABLED
);
527 of_node_put(sensor_specs
.np
);
531 of_node_put(sensor_specs
.np
);
534 of_node_put(sensor_np
);
539 EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register
);
542 * thermal_zone_of_sensor_unregister - unregisters a sensor from a DT thermal zone
543 * @dev: a valid struct device pointer of a sensor device. Must contain
544 * a valid .of_node, for the sensor node.
545 * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
547 * This function removes the sensor callbacks and private data from the
548 * thermal zone device registered with thermal_zone_of_sensor_register()
549 * API. It will also silent the zone by remove the .get_temp() and .get_trend()
550 * thermal zone device callbacks.
552 * TODO: When the support to several sensors per zone is added, this
553 * function must search the sensor list based on @dev parameter.
556 void thermal_zone_of_sensor_unregister(struct device
*dev
,
557 struct thermal_zone_device
*tzd
)
559 struct __thermal_zone
*tz
;
561 if (!dev
|| !tzd
|| !tzd
->devdata
)
566 /* no __thermal_zone, nothing to be done */
570 mutex_lock(&tzd
->lock
);
571 tzd
->ops
->get_temp
= NULL
;
572 tzd
->ops
->get_trend
= NULL
;
573 tzd
->ops
->set_emul_temp
= NULL
;
576 tz
->sensor_data
= NULL
;
577 mutex_unlock(&tzd
->lock
);
579 EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister
);
581 static void devm_thermal_zone_of_sensor_release(struct device
*dev
, void *res
)
583 thermal_zone_of_sensor_unregister(dev
,
584 *(struct thermal_zone_device
**)res
);
587 static int devm_thermal_zone_of_sensor_match(struct device
*dev
, void *res
,
590 struct thermal_zone_device
**r
= res
;
592 if (WARN_ON(!r
|| !*r
))
599 * devm_thermal_zone_of_sensor_register - Resource managed version of
600 * thermal_zone_of_sensor_register()
601 * @dev: a valid struct device pointer of a sensor device. Must contain
602 * a valid .of_node, for the sensor node.
603 * @sensor_id: a sensor identifier, in case the sensor IP has more
605 * @data: a private pointer (owned by the caller) that will be passed
606 * back, when a temperature reading is needed.
607 * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
609 * Refer thermal_zone_of_sensor_register() for more details.
611 * Return: On success returns a valid struct thermal_zone_device,
612 * otherwise, it returns a corresponding ERR_PTR(). Caller must
613 * check the return value with help of IS_ERR() helper.
614 * Registered thermal_zone_device device will automatically be
615 * released when device is unbounded.
617 struct thermal_zone_device
*devm_thermal_zone_of_sensor_register(
618 struct device
*dev
, int sensor_id
,
619 void *data
, const struct thermal_zone_of_device_ops
*ops
)
621 struct thermal_zone_device
**ptr
, *tzd
;
623 ptr
= devres_alloc(devm_thermal_zone_of_sensor_release
, sizeof(*ptr
),
626 return ERR_PTR(-ENOMEM
);
628 tzd
= thermal_zone_of_sensor_register(dev
, sensor_id
, data
, ops
);
635 devres_add(dev
, ptr
);
639 EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_register
);
642 * devm_thermal_zone_of_sensor_unregister - Resource managed version of
643 * thermal_zone_of_sensor_unregister().
644 * @dev: Device for which which resource was allocated.
645 * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
647 * This function removes the sensor callbacks and private data from the
648 * thermal zone device registered with devm_thermal_zone_of_sensor_register()
649 * API. It will also silent the zone by remove the .get_temp() and .get_trend()
650 * thermal zone device callbacks.
651 * Normally this function will not need to be called and the resource
652 * management code will ensure that the resource is freed.
654 void devm_thermal_zone_of_sensor_unregister(struct device
*dev
,
655 struct thermal_zone_device
*tzd
)
657 WARN_ON(devres_release(dev
, devm_thermal_zone_of_sensor_release
,
658 devm_thermal_zone_of_sensor_match
, tzd
));
660 EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister
);
662 /*** functions parsing device tree nodes ***/
665 * thermal_of_populate_bind_params - parse and fill cooling map data
666 * @np: DT node containing a cooling-map node
667 * @__tbp: data structure to be filled with cooling map info
668 * @trips: array of thermal zone trip points
669 * @ntrips: number of trip points inside trips.
671 * This function parses a cooling-map type of node represented by
672 * @np parameter and fills the read data into @__tbp data structure.
673 * It needs the already parsed array of trip points of the thermal zone
676 * Return: 0 on success, proper error code otherwise
678 static int thermal_of_populate_bind_params(struct device_node
*np
,
679 struct __thermal_bind_params
*__tbp
,
680 struct thermal_trip
*trips
,
683 struct of_phandle_args cooling_spec
;
684 struct __thermal_cooling_bind_param
*__tcbp
;
685 struct device_node
*trip
;
689 /* Default weight. Usage is optional */
690 __tbp
->usage
= THERMAL_WEIGHT_DEFAULT
;
691 ret
= of_property_read_u32(np
, "contribution", &prop
);
695 trip
= of_parse_phandle(np
, "trip", 0);
697 pr_err("missing trip property\n");
701 /* match using device_node */
702 for (i
= 0; i
< ntrips
; i
++)
703 if (trip
== trips
[i
].np
) {
713 count
= of_count_phandle_with_args(np
, "cooling-device",
716 pr_err("Add a cooling_device property with at least one device\n");
720 __tcbp
= kcalloc(count
, sizeof(*__tcbp
), GFP_KERNEL
);
724 for (i
= 0; i
< count
; i
++) {
725 ret
= of_parse_phandle_with_args(np
, "cooling-device",
726 "#cooling-cells", i
, &cooling_spec
);
728 pr_err("Invalid cooling-device entry\n");
732 __tcbp
[i
].cooling_device
= cooling_spec
.np
;
734 if (cooling_spec
.args_count
>= 2) { /* at least min and max */
735 __tcbp
[i
].min
= cooling_spec
.args
[0];
736 __tcbp
[i
].max
= cooling_spec
.args
[1];
738 pr_err("wrong reference to cooling device, missing limits\n");
742 __tbp
->tcbp
= __tcbp
;
743 __tbp
->count
= count
;
748 for (i
= i
- 1; i
>= 0; i
--)
749 of_node_put(__tcbp
[i
].cooling_device
);
758 * It maps 'enum thermal_trip_type' found in include/linux/thermal.h
759 * into the device tree binding of 'trip', property type.
761 static const char * const trip_types
[] = {
762 [THERMAL_TRIP_ACTIVE
] = "active",
763 [THERMAL_TRIP_PASSIVE
] = "passive",
764 [THERMAL_TRIP_HOT
] = "hot",
765 [THERMAL_TRIP_CRITICAL
] = "critical",
769 * thermal_of_get_trip_type - Get phy mode for given device_node
770 * @np: Pointer to the given device_node
771 * @type: Pointer to resulting trip type
773 * The function gets trip type string from property 'type',
774 * and store its index in trip_types table in @type,
776 * Return: 0 on success, or errno in error case.
778 static int thermal_of_get_trip_type(struct device_node
*np
,
779 enum thermal_trip_type
*type
)
784 err
= of_property_read_string(np
, "type", &t
);
788 for (i
= 0; i
< ARRAY_SIZE(trip_types
); i
++)
789 if (!strcasecmp(t
, trip_types
[i
])) {
798 * thermal_of_populate_trip - parse and fill one trip point data
799 * @np: DT node containing a trip point node
800 * @trip: trip point data structure to be filled up
802 * This function parses a trip point type of node represented by
803 * @np parameter and fills the read data into @trip data structure.
805 * Return: 0 on success, proper error code otherwise
807 static int thermal_of_populate_trip(struct device_node
*np
,
808 struct thermal_trip
*trip
)
813 ret
= of_property_read_u32(np
, "temperature", &prop
);
815 pr_err("missing temperature property\n");
818 trip
->temperature
= prop
;
820 ret
= of_property_read_u32(np
, "hysteresis", &prop
);
822 pr_err("missing hysteresis property\n");
825 trip
->hysteresis
= prop
;
827 ret
= thermal_of_get_trip_type(np
, &trip
->type
);
829 pr_err("wrong trip type property\n");
833 /* Required for cooling map matching */
841 * thermal_of_build_thermal_zone - parse and fill one thermal zone data
842 * @np: DT node containing a thermal zone node
844 * This function parses a thermal zone type of node represented by
845 * @np parameter and fills the read data into a __thermal_zone data structure
846 * and return this pointer.
848 * TODO: Missing properties to parse: thermal-sensor-names
850 * Return: On success returns a valid struct __thermal_zone,
851 * otherwise, it returns a corresponding ERR_PTR(). Caller must
852 * check the return value with help of IS_ERR() helper.
854 static struct __thermal_zone
855 __init
*thermal_of_build_thermal_zone(struct device_node
*np
)
857 struct device_node
*child
= NULL
, *gchild
;
858 struct __thermal_zone
*tz
;
863 pr_err("no thermal zone np\n");
864 return ERR_PTR(-EINVAL
);
867 tz
= kzalloc(sizeof(*tz
), GFP_KERNEL
);
869 return ERR_PTR(-ENOMEM
);
871 ret
= of_property_read_u32(np
, "polling-delay-passive", &prop
);
873 pr_err("%pOFn: missing polling-delay-passive property\n", np
);
876 tz
->passive_delay
= prop
;
878 ret
= of_property_read_u32(np
, "polling-delay", &prop
);
880 pr_err("%pOFn: missing polling-delay property\n", np
);
883 tz
->polling_delay
= prop
;
886 * REVIST: for now, the thermal framework supports only
887 * one sensor per thermal zone. Thus, we are considering
888 * only the first two values as slope and offset.
890 ret
= of_property_read_u32_array(np
, "coefficients", coef
, 2);
893 tz
->offset
= coef
[1];
900 child
= of_get_child_by_name(np
, "trips");
902 /* No trips provided */
906 tz
->ntrips
= of_get_child_count(child
);
907 if (tz
->ntrips
== 0) /* must have at least one child */
910 tz
->trips
= kcalloc(tz
->ntrips
, sizeof(*tz
->trips
), GFP_KERNEL
);
917 for_each_child_of_node(child
, gchild
) {
918 ret
= thermal_of_populate_trip(gchild
, &tz
->trips
[i
++]);
926 child
= of_get_child_by_name(np
, "cooling-maps");
928 /* cooling-maps not provided */
932 tz
->num_tbps
= of_get_child_count(child
);
933 if (tz
->num_tbps
== 0)
936 tz
->tbps
= kcalloc(tz
->num_tbps
, sizeof(*tz
->tbps
), GFP_KERNEL
);
943 for_each_child_of_node(child
, gchild
) {
944 ret
= thermal_of_populate_bind_params(gchild
, &tz
->tbps
[i
++],
945 tz
->trips
, tz
->ntrips
);
952 tz
->mode
= THERMAL_DEVICE_DISABLED
;
957 for (i
= i
- 1; i
>= 0; i
--) {
958 struct __thermal_bind_params
*tbp
= tz
->tbps
+ i
;
961 for (j
= 0; j
< tbp
->count
; j
++)
962 of_node_put(tbp
->tcbp
[j
].cooling_device
);
969 for (i
= 0; i
< tz
->ntrips
; i
++)
970 of_node_put(tz
->trips
[i
].np
);
980 static __init
void of_thermal_free_zone(struct __thermal_zone
*tz
)
982 struct __thermal_bind_params
*tbp
;
985 for (i
= 0; i
< tz
->num_tbps
; i
++) {
988 for (j
= 0; j
< tbp
->count
; j
++)
989 of_node_put(tbp
->tcbp
[j
].cooling_device
);
995 for (i
= 0; i
< tz
->ntrips
; i
++)
996 of_node_put(tz
->trips
[i
].np
);
1002 * of_thermal_destroy_zones - remove all zones parsed and allocated resources
1004 * Finds all zones parsed and added to the thermal framework and remove them
1005 * from the system, together with their resources.
1008 static __init
void of_thermal_destroy_zones(void)
1010 struct device_node
*np
, *child
;
1012 np
= of_find_node_by_name(NULL
, "thermal-zones");
1014 pr_debug("unable to find thermal zones\n");
1018 for_each_available_child_of_node(np
, child
) {
1019 struct thermal_zone_device
*zone
;
1021 zone
= thermal_zone_get_zone_by_name(child
->name
);
1025 thermal_zone_device_unregister(zone
);
1028 of_thermal_free_zone(zone
->devdata
);
1034 * of_parse_thermal_zones - parse device tree thermal data
1036 * Initialization function that can be called by machine initialization
1037 * code to parse thermal data and populate the thermal framework
1038 * with hardware thermal zones info. This function only parses thermal zones.
1039 * Cooling devices and sensor devices nodes are supposed to be parsed
1040 * by their respective drivers.
1042 * Return: 0 on success, proper error code otherwise
1045 int __init
of_parse_thermal_zones(void)
1047 struct device_node
*np
, *child
;
1048 struct __thermal_zone
*tz
;
1049 struct thermal_zone_device_ops
*ops
;
1051 np
= of_find_node_by_name(NULL
, "thermal-zones");
1053 pr_debug("unable to find thermal zones\n");
1054 return 0; /* Run successfully on systems without thermal DT */
1057 for_each_available_child_of_node(np
, child
) {
1058 struct thermal_zone_device
*zone
;
1059 struct thermal_zone_params
*tzp
;
1063 tz
= thermal_of_build_thermal_zone(child
);
1065 pr_err("failed to build thermal zone %pOFn: %ld\n",
1071 ops
= kmemdup(&of_thermal_ops
, sizeof(*ops
), GFP_KERNEL
);
1075 tzp
= kzalloc(sizeof(*tzp
), GFP_KERNEL
);
1081 /* No hwmon because there might be hwmon drivers registering */
1082 tzp
->no_hwmon
= true;
1084 if (!of_property_read_u32(child
, "sustainable-power", &prop
))
1085 tzp
->sustainable_power
= prop
;
1087 for (i
= 0; i
< tz
->ntrips
; i
++)
1090 /* these two are left for temperature drivers to use */
1091 tzp
->slope
= tz
->slope
;
1092 tzp
->offset
= tz
->offset
;
1094 zone
= thermal_zone_device_register(child
->name
, tz
->ntrips
,
1100 pr_err("Failed to build %pOFn zone %ld\n", child
,
1104 of_thermal_free_zone(tz
);
1105 /* attempting to build remaining zones still */
1115 of_thermal_free_zone(tz
);
1117 /* no memory available, so free what we have built */
1118 of_thermal_destroy_zones();