Lines Matching +full:cooling +full:- +full:maps
1 // SPDX-License-Identifier: GPL-2.0
3 * of-thermal.c - Generic Thermal Management device tree support.
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
38 * struct __thermal_bind_param - a match between trip and cooling device
39 * @tcbp: a pointer to an array of cooling devices
42 * @usage: the percentage (from 0 to 100) of cooling contribution
53 * struct __thermal_zone - internal representation of a thermal zone
54 * @passive_delay: polling interval while passive cooling is activated
59 * @trips: an array of trip points (0..ntrips - 1)
61 * @tbps: an array of thermal bind params (0..num_tbps - 1)
76 /* cooling binding data */
90 struct __thermal_zone *data = tz->devdata; in of_thermal_get_temp()
92 if (!data->ops->get_temp) in of_thermal_get_temp()
93 return -EINVAL; in of_thermal_get_temp()
95 return data->ops->get_temp(data->sensor_data, temp); in of_thermal_get_temp()
101 struct __thermal_zone *data = tz->devdata; in of_thermal_set_trips()
103 if (!data->ops || !data->ops->set_trips) in of_thermal_set_trips()
104 return -EINVAL; in of_thermal_set_trips()
106 return data->ops->set_trips(data->sensor_data, low, high); in of_thermal_set_trips()
110 * of_thermal_get_ntrips - function to export number of available trip
117 * Return: number of available trip points, -ENODEV when data not available
121 struct __thermal_zone *data = tz->devdata; in of_thermal_get_ntrips()
124 return -ENODEV; in of_thermal_get_ntrips()
126 return data->ntrips; in of_thermal_get_ntrips()
131 * of_thermal_is_trip_valid - function to check if trip point is valid
142 struct __thermal_zone *data = tz->devdata; in of_thermal_is_trip_valid()
144 if (!data || trip >= data->ntrips || trip < 0) in of_thermal_is_trip_valid()
152 * of_thermal_get_trip_points - function to get access to a globally exported
164 struct __thermal_zone *data = tz->devdata; in of_thermal_get_trip_points()
169 return data->trips; in of_thermal_get_trip_points()
174 * of_thermal_set_emul_temp - function to set emulated temperature
187 struct __thermal_zone *data = tz->devdata; in of_thermal_set_emul_temp()
189 return data->ops->set_emul_temp(data->sensor_data, temp); in of_thermal_set_emul_temp()
195 struct __thermal_zone *data = tz->devdata; in of_thermal_get_trend()
197 if (!data->ops->get_trend) in of_thermal_get_trend()
198 return -EINVAL; in of_thermal_get_trend()
200 return data->ops->get_trend(data->sensor_data, trip, trend); in of_thermal_get_trend()
206 struct __thermal_zone *data = thermal->devdata; in of_thermal_bind()
212 return -ENODEV; in of_thermal_bind()
215 for (i = 0; i < data->num_tbps; i++) { in of_thermal_bind()
216 tbp = data->tbps + i; in of_thermal_bind()
218 for (j = 0; j < tbp->count; j++) { in of_thermal_bind()
219 tcbp = tbp->tcbp + j; in of_thermal_bind()
221 if (tcbp->cooling_device == cdev->np) { in of_thermal_bind()
225 tbp->trip_id, cdev, in of_thermal_bind()
226 tcbp->max, in of_thermal_bind()
227 tcbp->min, in of_thermal_bind()
228 tbp->usage); in of_thermal_bind()
241 struct __thermal_zone *data = thermal->devdata; in of_thermal_unbind()
247 return -ENODEV; in of_thermal_unbind()
250 for (i = 0; i < data->num_tbps; i++) { in of_thermal_unbind()
251 tbp = data->tbps + i; in of_thermal_unbind()
253 for (j = 0; j < tbp->count; j++) { in of_thermal_unbind()
254 tcbp = tbp->tcbp + j; in of_thermal_unbind()
256 if (tcbp->cooling_device == cdev->np) { in of_thermal_unbind()
260 tbp->trip_id, cdev); in of_thermal_unbind()
273 struct __thermal_zone *data = tz->devdata; in of_thermal_get_trip_type()
275 if (trip >= data->ntrips || trip < 0) in of_thermal_get_trip_type()
276 return -EDOM; in of_thermal_get_trip_type()
278 *type = data->trips[trip].type; in of_thermal_get_trip_type()
286 struct __thermal_zone *data = tz->devdata; in of_thermal_get_trip_temp()
288 if (trip >= data->ntrips || trip < 0) in of_thermal_get_trip_temp()
289 return -EDOM; in of_thermal_get_trip_temp()
291 *temp = data->trips[trip].temperature; in of_thermal_get_trip_temp()
299 struct __thermal_zone *data = tz->devdata; in of_thermal_set_trip_temp()
301 if (trip >= data->ntrips || trip < 0) in of_thermal_set_trip_temp()
302 return -EDOM; in of_thermal_set_trip_temp()
304 if (data->ops->set_trip_temp) { in of_thermal_set_trip_temp()
307 ret = data->ops->set_trip_temp(data->sensor_data, trip, temp); in of_thermal_set_trip_temp()
312 /* thermal framework should take care of data->mask & (1 << trip) */ in of_thermal_set_trip_temp()
313 data->trips[trip].temperature = temp; in of_thermal_set_trip_temp()
321 struct __thermal_zone *data = tz->devdata; in of_thermal_get_trip_hyst()
323 if (trip >= data->ntrips || trip < 0) in of_thermal_get_trip_hyst()
324 return -EDOM; in of_thermal_get_trip_hyst()
326 *hyst = data->trips[trip].hysteresis; in of_thermal_get_trip_hyst()
334 struct __thermal_zone *data = tz->devdata; in of_thermal_set_trip_hyst()
336 if (trip >= data->ntrips || trip < 0) in of_thermal_set_trip_hyst()
337 return -EDOM; in of_thermal_set_trip_hyst()
339 /* thermal framework should take care of data->mask & (1 << trip) */ in of_thermal_set_trip_hyst()
340 data->trips[trip].hysteresis = hyst; in of_thermal_set_trip_hyst()
348 struct __thermal_zone *data = tz->devdata; in of_thermal_get_crit_temp()
351 for (i = 0; i < data->ntrips; i++) in of_thermal_get_crit_temp()
352 if (data->trips[i].type == THERMAL_TRIP_CRITICAL) { in of_thermal_get_crit_temp()
353 *temp = data->trips[i].temperature; in of_thermal_get_crit_temp()
357 return -EINVAL; in of_thermal_get_crit_temp()
382 tzd = thermal_zone_get_zone_by_name(zone->name); in thermal_zone_of_add_sensor()
384 return ERR_PTR(-EPROBE_DEFER); in thermal_zone_of_add_sensor()
386 tz = tzd->devdata; in thermal_zone_of_add_sensor()
389 return ERR_PTR(-EINVAL); in thermal_zone_of_add_sensor()
391 mutex_lock(&tzd->lock); in thermal_zone_of_add_sensor()
392 tz->ops = ops; in thermal_zone_of_add_sensor()
393 tz->sensor_data = data; in thermal_zone_of_add_sensor()
395 tzd->ops->get_temp = of_thermal_get_temp; in thermal_zone_of_add_sensor()
396 tzd->ops->get_trend = of_thermal_get_trend; in thermal_zone_of_add_sensor()
402 if (ops->set_trips) in thermal_zone_of_add_sensor()
403 tzd->ops->set_trips = of_thermal_set_trips; in thermal_zone_of_add_sensor()
405 if (ops->set_emul_temp) in thermal_zone_of_add_sensor()
406 tzd->ops->set_emul_temp = of_thermal_set_emul_temp; in thermal_zone_of_add_sensor()
408 mutex_unlock(&tzd->lock); in thermal_zone_of_add_sensor()
414 * thermal_zone_of_get_sensor_id - get sensor ID from a DT thermal zone
433 "thermal-sensors", in thermal_zone_of_get_sensor_id()
434 "#thermal-sensor-cells", in thermal_zone_of_get_sensor_id()
442 return -ENODEV; in thermal_zone_of_get_sensor_id()
458 * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone
469 * @dev->of_node as temperature providers. For the zone pointing to the
479 * 01 - This function must enqueue the new sensor instead of using
482 * 02 - There must be a way to match the sensor with all thermal zones
494 struct thermal_zone_device *tzd = ERR_PTR(-ENODEV); in thermal_zone_of_sensor_register()
496 np = of_find_node_by_name(NULL, "thermal-zones"); in thermal_zone_of_sensor_register()
498 return ERR_PTR(-ENODEV); in thermal_zone_of_sensor_register()
500 if (!dev || !dev->of_node) { in thermal_zone_of_sensor_register()
502 return ERR_PTR(-ENODEV); in thermal_zone_of_sensor_register()
505 sensor_np = of_node_get(dev->of_node); in thermal_zone_of_sensor_register()
534 * thermal_zone_of_sensor_unregister - unregisters a sensor from a DT thermal zone
553 if (!dev || !tzd || !tzd->devdata) in thermal_zone_of_sensor_unregister()
556 tz = tzd->devdata; in thermal_zone_of_sensor_unregister()
565 mutex_lock(&tzd->lock); in thermal_zone_of_sensor_unregister()
566 tzd->ops->get_temp = NULL; in thermal_zone_of_sensor_unregister()
567 tzd->ops->get_trend = NULL; in thermal_zone_of_sensor_unregister()
568 tzd->ops->set_emul_temp = NULL; in thermal_zone_of_sensor_unregister()
570 tz->ops = NULL; in thermal_zone_of_sensor_unregister()
571 tz->sensor_data = NULL; in thermal_zone_of_sensor_unregister()
572 mutex_unlock(&tzd->lock); in thermal_zone_of_sensor_unregister()
594 * devm_thermal_zone_of_sensor_register - Resource managed version of
621 return ERR_PTR(-ENOMEM); in devm_thermal_zone_of_sensor_register()
637 * devm_thermal_zone_of_sensor_unregister - Resource managed version of
660 * thermal_of_populate_bind_params - parse and fill cooling map data
661 * @np: DT node containing a cooling-map node
662 * @__tbp: data structure to be filled with cooling map info
666 * This function parses a cooling-map type of node represented by
685 __tbp->usage = THERMAL_WEIGHT_DEFAULT; in thermal_of_populate_bind_params()
688 __tbp->usage = prop; in thermal_of_populate_bind_params()
693 return -ENODEV; in thermal_of_populate_bind_params()
699 __tbp->trip_id = i; in thermal_of_populate_bind_params()
704 ret = -ENODEV; in thermal_of_populate_bind_params()
708 count = of_count_phandle_with_args(np, "cooling-device", in thermal_of_populate_bind_params()
709 "#cooling-cells"); in thermal_of_populate_bind_params()
712 ret = -ENOENT; in thermal_of_populate_bind_params()
718 ret = -ENOMEM; in thermal_of_populate_bind_params()
723 ret = of_parse_phandle_with_args(np, "cooling-device", in thermal_of_populate_bind_params()
724 "#cooling-cells", i, &cooling_spec); in thermal_of_populate_bind_params()
726 pr_err("Invalid cooling-device entry\n"); in thermal_of_populate_bind_params()
736 pr_err("wrong reference to cooling device, missing limits\n"); in thermal_of_populate_bind_params()
740 __tbp->tcbp = __tcbp; in thermal_of_populate_bind_params()
741 __tbp->count = count; in thermal_of_populate_bind_params()
746 for (i = i - 1; i >= 0; i--) in thermal_of_populate_bind_params()
756 * It maps 'enum thermal_trip_type' found in include/linux/thermal.h
767 * thermal_of_get_trip_type - Get phy mode for given device_node
792 return -ENODEV; in thermal_of_get_trip_type()
796 * thermal_of_populate_trip - parse and fill one trip point data
816 trip->temperature = prop; in thermal_of_populate_trip()
823 trip->hysteresis = prop; in thermal_of_populate_trip()
825 ret = thermal_of_get_trip_type(np, &trip->type); in thermal_of_populate_trip()
831 /* Required for cooling map matching */ in thermal_of_populate_trip()
832 trip->np = np; in thermal_of_populate_trip()
839 * thermal_of_build_thermal_zone - parse and fill one thermal zone data
846 * TODO: Missing properties to parse: thermal-sensor-names
862 return ERR_PTR(-EINVAL); in thermal_of_build_thermal_zone()
867 return ERR_PTR(-ENOMEM); in thermal_of_build_thermal_zone()
869 ret = of_property_read_u32(np, "polling-delay-passive", &prop); in thermal_of_build_thermal_zone()
871 pr_err("%pOFn: missing polling-delay-passive property\n", np); in thermal_of_build_thermal_zone()
874 tz->passive_delay = prop; in thermal_of_build_thermal_zone()
876 ret = of_property_read_u32(np, "polling-delay", &prop); in thermal_of_build_thermal_zone()
878 pr_err("%pOFn: missing polling-delay property\n", np); in thermal_of_build_thermal_zone()
881 tz->polling_delay = prop; in thermal_of_build_thermal_zone()
890 tz->slope = coef[0]; in thermal_of_build_thermal_zone()
891 tz->offset = coef[1]; in thermal_of_build_thermal_zone()
893 tz->slope = 1; in thermal_of_build_thermal_zone()
894 tz->offset = 0; in thermal_of_build_thermal_zone()
904 tz->ntrips = of_get_child_count(child); in thermal_of_build_thermal_zone()
905 if (tz->ntrips == 0) /* must have at least one child */ in thermal_of_build_thermal_zone()
908 tz->trips = kcalloc(tz->ntrips, sizeof(*tz->trips), GFP_KERNEL); in thermal_of_build_thermal_zone()
909 if (!tz->trips) { in thermal_of_build_thermal_zone()
910 ret = -ENOMEM; in thermal_of_build_thermal_zone()
916 ret = thermal_of_populate_trip(gchild, &tz->trips[i++]); in thermal_of_build_thermal_zone()
923 /* cooling-maps */ in thermal_of_build_thermal_zone()
924 child = of_get_child_by_name(np, "cooling-maps"); in thermal_of_build_thermal_zone()
926 /* cooling-maps not provided */ in thermal_of_build_thermal_zone()
930 tz->num_tbps = of_get_child_count(child); in thermal_of_build_thermal_zone()
931 if (tz->num_tbps == 0) in thermal_of_build_thermal_zone()
934 tz->tbps = kcalloc(tz->num_tbps, sizeof(*tz->tbps), GFP_KERNEL); in thermal_of_build_thermal_zone()
935 if (!tz->tbps) { in thermal_of_build_thermal_zone()
936 ret = -ENOMEM; in thermal_of_build_thermal_zone()
942 ret = thermal_of_populate_bind_params(gchild, &tz->tbps[i++], in thermal_of_build_thermal_zone()
943 tz->trips, tz->ntrips); in thermal_of_build_thermal_zone()
954 for (i = i - 1; i >= 0; i--) { in thermal_of_build_thermal_zone()
955 struct __thermal_bind_params *tbp = tz->tbps + i; in thermal_of_build_thermal_zone()
958 for (j = 0; j < tbp->count; j++) in thermal_of_build_thermal_zone()
959 of_node_put(tbp->tcbp[j].cooling_device); in thermal_of_build_thermal_zone()
961 kfree(tbp->tcbp); in thermal_of_build_thermal_zone()
964 kfree(tz->tbps); in thermal_of_build_thermal_zone()
966 for (i = 0; i < tz->ntrips; i++) in thermal_of_build_thermal_zone()
967 of_node_put(tz->trips[i].np); in thermal_of_build_thermal_zone()
968 kfree(tz->trips); in thermal_of_build_thermal_zone()
982 for (i = 0; i < tz->num_tbps; i++) { in of_thermal_free_zone()
983 tbp = tz->tbps + i; in of_thermal_free_zone()
985 for (j = 0; j < tbp->count; j++) in of_thermal_free_zone()
986 of_node_put(tbp->tcbp[j].cooling_device); in of_thermal_free_zone()
988 kfree(tbp->tcbp); in of_thermal_free_zone()
991 kfree(tz->tbps); in of_thermal_free_zone()
992 for (i = 0; i < tz->ntrips; i++) in of_thermal_free_zone()
993 of_node_put(tz->trips[i].np); in of_thermal_free_zone()
994 kfree(tz->trips); in of_thermal_free_zone()
999 * of_thermal_destroy_zones - remove all zones parsed and allocated resources
1009 np = of_find_node_by_name(NULL, "thermal-zones"); in of_thermal_destroy_zones()
1018 zone = thermal_zone_get_zone_by_name(child->name); in of_thermal_destroy_zones()
1023 kfree(zone->tzp); in of_thermal_destroy_zones()
1024 kfree(zone->ops); in of_thermal_destroy_zones()
1025 of_thermal_free_zone(zone->devdata); in of_thermal_destroy_zones()
1031 * of_parse_thermal_zones - parse device tree thermal data
1036 * Cooling devices and sensor devices nodes are supposed to be parsed
1048 np = of_find_node_by_name(NULL, "thermal-zones"); in of_parse_thermal_zones()
1079 tzp->no_hwmon = true; in of_parse_thermal_zones()
1081 if (!of_property_read_u32(child, "sustainable-power", &prop)) in of_parse_thermal_zones()
1082 tzp->sustainable_power = prop; in of_parse_thermal_zones()
1084 for (i = 0; i < tz->ntrips; i++) in of_parse_thermal_zones()
1088 tzp->slope = tz->slope; in of_parse_thermal_zones()
1089 tzp->offset = tz->offset; in of_parse_thermal_zones()
1091 zone = thermal_zone_device_register(child->name, tz->ntrips, in of_parse_thermal_zones()
1094 tz->passive_delay, in of_parse_thermal_zones()
1095 tz->polling_delay); in of_parse_thermal_zones()
1117 return -ENOMEM; in of_parse_thermal_zones()