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 #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 /***   Private data structures to represent thermal device tree data ***/
20 
21 /**
22  * struct __thermal_bind_param - a match between trip and cooling device
23  * @cooling_device: a pointer to identify the referred cooling device
24  * @trip_id: the trip point index
25  * @usage: the percentage (from 0 to 100) of cooling contribution
26  * @min: minimum cooling state used at this trip point
27  * @max: maximum cooling state used at this trip point
28  */
29 
30 struct __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  * struct __thermal_zone - internal representation of a thermal zone
40  * @mode: current thermal zone device mode (enabled/disabled)
41  * @passive_delay: polling interval while passive cooling is activated
42  * @polling_delay: zone polling interval
43  * @slope: slope of the temperature adjustment curve
44  * @offset: offset of the temperature adjustment curve
45  * @ntrips: number of trip points
46  * @trips: an array of trip points (0..ntrips - 1)
47  * @num_tbps: number of thermal bind params
48  * @tbps: an array of thermal bind params (0..num_tbps - 1)
49  * @sensor_data: sensor private data used while reading temperature and trend
50  * @ops: set of callbacks to handle the thermal zone based on DT
51  */
52 
53 struct __thermal_zone {
54 	enum thermal_device_mode mode;
55 	int passive_delay;
56 	int polling_delay;
57 	int slope;
58 	int offset;
59 
60 	/* trip data */
61 	int ntrips;
62 	struct thermal_trip *trips;
63 
64 	/* cooling binding data */
65 	int num_tbps;
66 	struct __thermal_bind_params *tbps;
67 
68 	/* sensor interface */
69 	void *sensor_data;
70 	const struct thermal_zone_of_device_ops *ops;
71 };
72 
73 /***   DT thermal zone device callbacks   ***/
74 
of_thermal_get_temp(struct thermal_zone_device * tz,int * temp)75 static 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 
of_thermal_set_trips(struct thermal_zone_device * tz,int low,int high)86 static 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  * of_thermal_get_ntrips - function to export number of available trip
99  *			   points.
100  * @tz: pointer to a thermal zone
101  *
102  * This function is a globally visible wrapper to get number of trip points
103  * stored in the local struct __thermal_zone
104  *
105  * Return: number of available trip points, -ENODEV when data not available
106  */
of_thermal_get_ntrips(struct thermal_zone_device * tz)107 int 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 }
116 EXPORT_SYMBOL_GPL(of_thermal_get_ntrips);
117 
118 /**
119  * of_thermal_is_trip_valid - function to check if trip point is valid
120  *
121  * @tz:	pointer to a thermal zone
122  * @trip:	trip point to evaluate
123  *
124  * This function is responsible for checking if passed trip point is valid
125  *
126  * Return: true if trip point is valid, false otherwise
127  */
of_thermal_is_trip_valid(struct thermal_zone_device * tz,int trip)128 bool 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 }
137 EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid);
138 
139 /**
140  * of_thermal_get_trip_points - function to get access to a globally exported
141  *				trip points
142  *
143  * @tz:	pointer to a thermal zone
144  *
145  * This function provides a pointer to trip points table
146  *
147  * Return: pointer to trip points table, NULL otherwise
148  */
149 const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device * tz)150 of_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 }
159 EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
160 
161 /**
162  * of_thermal_set_emul_temp - function to set emulated temperature
163  *
164  * @tz:	pointer to a thermal zone
165  * @temp:	temperature to set
166  *
167  * This function gives the ability to set emulated value of temperature,
168  * which is handy for debugging
169  *
170  * Return: zero on success, error code otherwise
171  */
of_thermal_set_emul_temp(struct thermal_zone_device * tz,int temp)172 static 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 
of_thermal_get_trend(struct thermal_zone_device * tz,int trip,enum thermal_trend * trend)180 static 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 
of_thermal_bind(struct thermal_zone_device * thermal,struct thermal_cooling_device * cdev)191 static 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 	/* find where to bind */
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 
of_thermal_unbind(struct thermal_zone_device * thermal,struct thermal_cooling_device * cdev)220 static 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 	/* find where to unbind */
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 
of_thermal_get_mode(struct thermal_zone_device * tz,enum thermal_device_mode * mode)246 static 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 
of_thermal_set_mode(struct thermal_zone_device * tz,enum thermal_device_mode mode)256 static 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 		tz->passive_delay = data->passive_delay;
266 	} else {
267 		tz->polling_delay = 0;
268 		tz->passive_delay = 0;
269 	}
270 
271 	mutex_unlock(&tz->lock);
272 
273 	data->mode = mode;
274 	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
275 
276 	return 0;
277 }
278 
of_thermal_get_trip_type(struct thermal_zone_device * tz,int trip,enum thermal_trip_type * type)279 static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
280 				    enum thermal_trip_type *type)
281 {
282 	struct __thermal_zone *data = tz->devdata;
283 
284 	if (trip >= data->ntrips || trip < 0)
285 		return -EDOM;
286 
287 	*type = data->trips[trip].type;
288 
289 	return 0;
290 }
291 
of_thermal_get_trip_temp(struct thermal_zone_device * tz,int trip,int * temp)292 static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
293 				    int *temp)
294 {
295 	struct __thermal_zone *data = tz->devdata;
296 
297 	if (trip >= data->ntrips || trip < 0)
298 		return -EDOM;
299 
300 	*temp = data->trips[trip].temperature;
301 
302 	return 0;
303 }
304 
of_thermal_set_trip_temp(struct thermal_zone_device * tz,int trip,int temp)305 static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
306 				    int temp)
307 {
308 	struct __thermal_zone *data = tz->devdata;
309 
310 	if (trip >= data->ntrips || trip < 0)
311 		return -EDOM;
312 
313 	if (data->ops->set_trip_temp) {
314 		int ret;
315 
316 		ret = data->ops->set_trip_temp(data->sensor_data, trip, temp);
317 		if (ret)
318 			return ret;
319 	}
320 
321 	/* thermal framework should take care of data->mask & (1 << trip) */
322 	data->trips[trip].temperature = temp;
323 
324 	return 0;
325 }
326 
of_thermal_get_trip_hyst(struct thermal_zone_device * tz,int trip,int * hyst)327 static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
328 				    int *hyst)
329 {
330 	struct __thermal_zone *data = tz->devdata;
331 
332 	if (trip >= data->ntrips || trip < 0)
333 		return -EDOM;
334 
335 	*hyst = data->trips[trip].hysteresis;
336 
337 	return 0;
338 }
339 
of_thermal_set_trip_hyst(struct thermal_zone_device * tz,int trip,int hyst)340 static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
341 				    int hyst)
342 {
343 	struct __thermal_zone *data = tz->devdata;
344 
345 	if (trip >= data->ntrips || trip < 0)
346 		return -EDOM;
347 
348 	/* thermal framework should take care of data->mask & (1 << trip) */
349 	data->trips[trip].hysteresis = hyst;
350 
351 	return 0;
352 }
353 
of_thermal_get_crit_temp(struct thermal_zone_device * tz,int * temp)354 static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
355 				    int *temp)
356 {
357 	struct __thermal_zone *data = tz->devdata;
358 	int i;
359 
360 	for (i = 0; i < data->ntrips; i++)
361 		if (data->trips[i].type == THERMAL_TRIP_CRITICAL) {
362 			*temp = data->trips[i].temperature;
363 			return 0;
364 		}
365 
366 	return -EINVAL;
367 }
368 
369 static struct thermal_zone_device_ops of_thermal_ops = {
370 	.get_mode = of_thermal_get_mode,
371 	.set_mode = of_thermal_set_mode,
372 
373 	.get_trip_type = of_thermal_get_trip_type,
374 	.get_trip_temp = of_thermal_get_trip_temp,
375 	.set_trip_temp = of_thermal_set_trip_temp,
376 	.get_trip_hyst = of_thermal_get_trip_hyst,
377 	.set_trip_hyst = of_thermal_set_trip_hyst,
378 	.get_crit_temp = of_thermal_get_crit_temp,
379 
380 	.bind = of_thermal_bind,
381 	.unbind = of_thermal_unbind,
382 };
383 
384 /***   sensor API   ***/
385 
386 static struct thermal_zone_device *
thermal_zone_of_add_sensor(struct device_node * zone,struct device_node * sensor,void * data,const struct thermal_zone_of_device_ops * ops)387 thermal_zone_of_add_sensor(struct device_node *zone,
388 			   struct device_node *sensor, void *data,
389 			   const struct thermal_zone_of_device_ops *ops)
390 {
391 	struct thermal_zone_device *tzd;
392 	struct __thermal_zone *tz;
393 
394 	tzd = thermal_zone_get_zone_by_name(zone->name);
395 	if (IS_ERR(tzd))
396 		return ERR_PTR(-EPROBE_DEFER);
397 
398 	tz = tzd->devdata;
399 
400 	if (!ops)
401 		return ERR_PTR(-EINVAL);
402 
403 	mutex_lock(&tzd->lock);
404 	tz->ops = ops;
405 	tz->sensor_data = data;
406 
407 	tzd->ops->get_temp = of_thermal_get_temp;
408 	tzd->ops->get_trend = of_thermal_get_trend;
409 
410 	/*
411 	 * The thermal zone core will calculate the window if they have set the
412 	 * optional set_trips pointer.
413 	 */
414 	if (ops->set_trips)
415 		tzd->ops->set_trips = of_thermal_set_trips;
416 
417 	if (ops->set_emul_temp)
418 		tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
419 
420 	mutex_unlock(&tzd->lock);
421 
422 	return tzd;
423 }
424 
425 /**
426  * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone
427  * @dev: a valid struct device pointer of a sensor device. Must contain
428  *       a valid .of_node, for the sensor node.
429  * @sensor_id: a sensor identifier, in case the sensor IP has more
430  *             than one sensors
431  * @data: a private pointer (owned by the caller) that will be passed
432  *        back, when a temperature reading is needed.
433  * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
434  *
435  * This function will search the list of thermal zones described in device
436  * tree and look for the zone that refer to the sensor device pointed by
437  * @dev->of_node as temperature providers. For the zone pointing to the
438  * sensor node, the sensor will be added to the DT thermal zone device.
439  *
440  * The thermal zone temperature is provided by the @get_temp function
441  * pointer. When called, it will have the private pointer @data back.
442  *
443  * The thermal zone temperature trend is provided by the @get_trend function
444  * pointer. When called, it will have the private pointer @data back.
445  *
446  * TODO:
447  * 01 - This function must enqueue the new sensor instead of using
448  * it as the only source of temperature values.
449  *
450  * 02 - There must be a way to match the sensor with all thermal zones
451  * that refer to it.
452  *
453  * Return: On success returns a valid struct thermal_zone_device,
454  * otherwise, it returns a corresponding ERR_PTR(). Caller must
455  * check the return value with help of IS_ERR() helper.
456  */
457 struct thermal_zone_device *
thermal_zone_of_sensor_register(struct device * dev,int sensor_id,void * data,const struct thermal_zone_of_device_ops * ops)458 thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
459 				const struct thermal_zone_of_device_ops *ops)
460 {
461 	struct device_node *np, *child, *sensor_np;
462 	struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);
463 
464 	np = of_find_node_by_name(NULL, "thermal-zones");
465 	if (!np)
466 		return ERR_PTR(-ENODEV);
467 
468 	if (!dev || !dev->of_node) {
469 		of_node_put(np);
470 		return ERR_PTR(-EINVAL);
471 	}
472 
473 	sensor_np = of_node_get(dev->of_node);
474 
475 	for_each_available_child_of_node(np, child) {
476 		struct of_phandle_args sensor_specs;
477 		int ret, id;
478 
479 		/* For now, thermal framework supports only 1 sensor per zone */
480 		ret = of_parse_phandle_with_args(child, "thermal-sensors",
481 						 "#thermal-sensor-cells",
482 						 0, &sensor_specs);
483 		if (ret)
484 			continue;
485 
486 		if (sensor_specs.args_count >= 1) {
487 			id = sensor_specs.args[0];
488 			WARN(sensor_specs.args_count > 1,
489 			     "%s: too many cells in sensor specifier %d\n",
490 			     sensor_specs.np->name, sensor_specs.args_count);
491 		} else {
492 			id = 0;
493 		}
494 
495 		if (sensor_specs.np == sensor_np && id == sensor_id) {
496 			tzd = thermal_zone_of_add_sensor(child, sensor_np,
497 							 data, ops);
498 			if (!IS_ERR(tzd))
499 				tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);
500 
501 			of_node_put(sensor_specs.np);
502 			of_node_put(child);
503 			goto exit;
504 		}
505 		of_node_put(sensor_specs.np);
506 	}
507 exit:
508 	of_node_put(sensor_np);
509 	of_node_put(np);
510 
511 	return tzd;
512 }
513 EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register);
514 
515 /**
516  * thermal_zone_of_sensor_unregister - unregisters a sensor from a DT thermal zone
517  * @dev: a valid struct device pointer of a sensor device. Must contain
518  *       a valid .of_node, for the sensor node.
519  * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
520  *
521  * This function removes the sensor callbacks and private data from the
522  * thermal zone device registered with thermal_zone_of_sensor_register()
523  * API. It will also silent the zone by remove the .get_temp() and .get_trend()
524  * thermal zone device callbacks.
525  *
526  * TODO: When the support to several sensors per zone is added, this
527  * function must search the sensor list based on @dev parameter.
528  *
529  */
thermal_zone_of_sensor_unregister(struct device * dev,struct thermal_zone_device * tzd)530 void thermal_zone_of_sensor_unregister(struct device *dev,
531 				       struct thermal_zone_device *tzd)
532 {
533 	struct __thermal_zone *tz;
534 
535 	if (!dev || !tzd || !tzd->devdata)
536 		return;
537 
538 	tz = tzd->devdata;
539 
540 	/* no __thermal_zone, nothing to be done */
541 	if (!tz)
542 		return;
543 
544 	mutex_lock(&tzd->lock);
545 	tzd->ops->get_temp = NULL;
546 	tzd->ops->get_trend = NULL;
547 	tzd->ops->set_emul_temp = NULL;
548 
549 	tz->ops = NULL;
550 	tz->sensor_data = NULL;
551 	mutex_unlock(&tzd->lock);
552 }
553 EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
554 
devm_thermal_zone_of_sensor_release(struct device * dev,void * res)555 static void devm_thermal_zone_of_sensor_release(struct device *dev, void *res)
556 {
557 	thermal_zone_of_sensor_unregister(dev,
558 					  *(struct thermal_zone_device **)res);
559 }
560 
devm_thermal_zone_of_sensor_match(struct device * dev,void * res,void * data)561 static int devm_thermal_zone_of_sensor_match(struct device *dev, void *res,
562 					     void *data)
563 {
564 	struct thermal_zone_device **r = res;
565 
566 	if (WARN_ON(!r || !*r))
567 		return 0;
568 
569 	return *r == data;
570 }
571 
572 /**
573  * devm_thermal_zone_of_sensor_register - Resource managed version of
574  *				thermal_zone_of_sensor_register()
575  * @dev: a valid struct device pointer of a sensor device. Must contain
576  *       a valid .of_node, for the sensor node.
577  * @sensor_id: a sensor identifier, in case the sensor IP has more
578  *	       than one sensors
579  * @data: a private pointer (owned by the caller) that will be passed
580  *	  back, when a temperature reading is needed.
581  * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
582  *
583  * Refer thermal_zone_of_sensor_register() for more details.
584  *
585  * Return: On success returns a valid struct thermal_zone_device,
586  * otherwise, it returns a corresponding ERR_PTR(). Caller must
587  * check the return value with help of IS_ERR() helper.
588  * Registered thermal_zone_device device will automatically be
589  * released when device is unbounded.
590  */
devm_thermal_zone_of_sensor_register(struct device * dev,int sensor_id,void * data,const struct thermal_zone_of_device_ops * ops)591 struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
592 	struct device *dev, int sensor_id,
593 	void *data, const struct thermal_zone_of_device_ops *ops)
594 {
595 	struct thermal_zone_device **ptr, *tzd;
596 
597 	ptr = devres_alloc(devm_thermal_zone_of_sensor_release, sizeof(*ptr),
598 			   GFP_KERNEL);
599 	if (!ptr)
600 		return ERR_PTR(-ENOMEM);
601 
602 	tzd = thermal_zone_of_sensor_register(dev, sensor_id, data, ops);
603 	if (IS_ERR(tzd)) {
604 		devres_free(ptr);
605 		return tzd;
606 	}
607 
608 	*ptr = tzd;
609 	devres_add(dev, ptr);
610 
611 	return tzd;
612 }
613 EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_register);
614 
615 /**
616  * devm_thermal_zone_of_sensor_unregister - Resource managed version of
617  *				thermal_zone_of_sensor_unregister().
618  * @dev: Device for which which resource was allocated.
619  * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
620  *
621  * This function removes the sensor callbacks and private data from the
622  * thermal zone device registered with devm_thermal_zone_of_sensor_register()
623  * API. It will also silent the zone by remove the .get_temp() and .get_trend()
624  * thermal zone device callbacks.
625  * Normally this function will not need to be called and the resource
626  * management code will ensure that the resource is freed.
627  */
devm_thermal_zone_of_sensor_unregister(struct device * dev,struct thermal_zone_device * tzd)628 void devm_thermal_zone_of_sensor_unregister(struct device *dev,
629 					    struct thermal_zone_device *tzd)
630 {
631 	WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release,
632 			       devm_thermal_zone_of_sensor_match, tzd));
633 }
634 EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister);
635 
636 /***   functions parsing device tree nodes   ***/
637 
638 /**
639  * thermal_of_populate_bind_params - parse and fill cooling map data
640  * @np: DT node containing a cooling-map node
641  * @__tbp: data structure to be filled with cooling map info
642  * @trips: array of thermal zone trip points
643  * @ntrips: number of trip points inside trips.
644  *
645  * This function parses a cooling-map type of node represented by
646  * @np parameter and fills the read data into @__tbp data structure.
647  * It needs the already parsed array of trip points of the thermal zone
648  * in consideration.
649  *
650  * Return: 0 on success, proper error code otherwise
651  */
thermal_of_populate_bind_params(struct device_node * np,struct __thermal_bind_params * __tbp,struct thermal_trip * trips,int ntrips)652 static int thermal_of_populate_bind_params(struct device_node *np,
653 					   struct __thermal_bind_params *__tbp,
654 					   struct thermal_trip *trips,
655 					   int ntrips)
656 {
657 	struct of_phandle_args cooling_spec;
658 	struct device_node *trip;
659 	int ret, i;
660 	u32 prop;
661 
662 	/* Default weight. Usage is optional */
663 	__tbp->usage = THERMAL_WEIGHT_DEFAULT;
664 	ret = of_property_read_u32(np, "contribution", &prop);
665 	if (ret == 0)
666 		__tbp->usage = prop;
667 
668 	trip = of_parse_phandle(np, "trip", 0);
669 	if (!trip) {
670 		pr_err("missing trip property\n");
671 		return -ENODEV;
672 	}
673 
674 	/* match using device_node */
675 	for (i = 0; i < ntrips; i++)
676 		if (trip == trips[i].np) {
677 			__tbp->trip_id = i;
678 			break;
679 		}
680 
681 	if (i == ntrips) {
682 		ret = -ENODEV;
683 		goto end;
684 	}
685 
686 	ret = of_parse_phandle_with_args(np, "cooling-device", "#cooling-cells",
687 					 0, &cooling_spec);
688 	if (ret < 0) {
689 		pr_err("missing cooling_device property\n");
690 		goto end;
691 	}
692 	__tbp->cooling_device = cooling_spec.np;
693 	if (cooling_spec.args_count >= 2) { /* at least min and max */
694 		__tbp->min = cooling_spec.args[0];
695 		__tbp->max = cooling_spec.args[1];
696 	} else {
697 		pr_err("wrong reference to cooling device, missing limits\n");
698 	}
699 
700 end:
701 	of_node_put(trip);
702 
703 	return ret;
704 }
705 
706 /**
707  * It maps 'enum thermal_trip_type' found in include/linux/thermal.h
708  * into the device tree binding of 'trip', property type.
709  */
710 static const char * const trip_types[] = {
711 	[THERMAL_TRIP_ACTIVE]	= "active",
712 	[THERMAL_TRIP_PASSIVE]	= "passive",
713 	[THERMAL_TRIP_HOT]	= "hot",
714 	[THERMAL_TRIP_CRITICAL]	= "critical",
715 };
716 
717 /**
718  * thermal_of_get_trip_type - Get phy mode for given device_node
719  * @np:	Pointer to the given device_node
720  * @type: Pointer to resulting trip type
721  *
722  * The function gets trip type string from property 'type',
723  * and store its index in trip_types table in @type,
724  *
725  * Return: 0 on success, or errno in error case.
726  */
thermal_of_get_trip_type(struct device_node * np,enum thermal_trip_type * type)727 static int thermal_of_get_trip_type(struct device_node *np,
728 				    enum thermal_trip_type *type)
729 {
730 	const char *t;
731 	int err, i;
732 
733 	err = of_property_read_string(np, "type", &t);
734 	if (err < 0)
735 		return err;
736 
737 	for (i = 0; i < ARRAY_SIZE(trip_types); i++)
738 		if (!strcasecmp(t, trip_types[i])) {
739 			*type = i;
740 			return 0;
741 		}
742 
743 	return -ENODEV;
744 }
745 
746 /**
747  * thermal_of_populate_trip - parse and fill one trip point data
748  * @np: DT node containing a trip point node
749  * @trip: trip point data structure to be filled up
750  *
751  * This function parses a trip point type of node represented by
752  * @np parameter and fills the read data into @trip data structure.
753  *
754  * Return: 0 on success, proper error code otherwise
755  */
thermal_of_populate_trip(struct device_node * np,struct thermal_trip * trip)756 static int thermal_of_populate_trip(struct device_node *np,
757 				    struct thermal_trip *trip)
758 {
759 	int prop;
760 	int ret;
761 
762 	ret = of_property_read_u32(np, "temperature", &prop);
763 	if (ret < 0) {
764 		pr_err("missing temperature property\n");
765 		return ret;
766 	}
767 	trip->temperature = prop;
768 
769 	ret = of_property_read_u32(np, "hysteresis", &prop);
770 	if (ret < 0) {
771 		pr_err("missing hysteresis property\n");
772 		return ret;
773 	}
774 	trip->hysteresis = prop;
775 
776 	ret = thermal_of_get_trip_type(np, &trip->type);
777 	if (ret < 0) {
778 		pr_err("wrong trip type property\n");
779 		return ret;
780 	}
781 
782 	/* Required for cooling map matching */
783 	trip->np = np;
784 	of_node_get(np);
785 
786 	return 0;
787 }
788 
789 /**
790  * thermal_of_build_thermal_zone - parse and fill one thermal zone data
791  * @np: DT node containing a thermal zone node
792  *
793  * This function parses a thermal zone type of node represented by
794  * @np parameter and fills the read data into a __thermal_zone data structure
795  * and return this pointer.
796  *
797  * TODO: Missing properties to parse: thermal-sensor-names
798  *
799  * Return: On success returns a valid struct __thermal_zone,
800  * otherwise, it returns a corresponding ERR_PTR(). Caller must
801  * check the return value with help of IS_ERR() helper.
802  */
803 static struct __thermal_zone
thermal_of_build_thermal_zone(struct device_node * np)804 __init *thermal_of_build_thermal_zone(struct device_node *np)
805 {
806 	struct device_node *child = NULL, *gchild;
807 	struct __thermal_zone *tz;
808 	int ret, i;
809 	u32 prop, coef[2];
810 
811 	if (!np) {
812 		pr_err("no thermal zone np\n");
813 		return ERR_PTR(-EINVAL);
814 	}
815 
816 	tz = kzalloc(sizeof(*tz), GFP_KERNEL);
817 	if (!tz)
818 		return ERR_PTR(-ENOMEM);
819 
820 	ret = of_property_read_u32(np, "polling-delay-passive", &prop);
821 	if (ret < 0) {
822 		pr_err("missing polling-delay-passive property\n");
823 		goto free_tz;
824 	}
825 	tz->passive_delay = prop;
826 
827 	ret = of_property_read_u32(np, "polling-delay", &prop);
828 	if (ret < 0) {
829 		pr_err("missing polling-delay property\n");
830 		goto free_tz;
831 	}
832 	tz->polling_delay = prop;
833 
834 	/*
835 	 * REVIST: for now, the thermal framework supports only
836 	 * one sensor per thermal zone. Thus, we are considering
837 	 * only the first two values as slope and offset.
838 	 */
839 	ret = of_property_read_u32_array(np, "coefficients", coef, 2);
840 	if (ret == 0) {
841 		tz->slope = coef[0];
842 		tz->offset = coef[1];
843 	} else {
844 		tz->slope = 1;
845 		tz->offset = 0;
846 	}
847 
848 	/* trips */
849 	child = of_get_child_by_name(np, "trips");
850 
851 	/* No trips provided */
852 	if (!child)
853 		goto finish;
854 
855 	tz->ntrips = of_get_child_count(child);
856 	if (tz->ntrips == 0) /* must have at least one child */
857 		goto finish;
858 
859 	tz->trips = kcalloc(tz->ntrips, sizeof(*tz->trips), GFP_KERNEL);
860 	if (!tz->trips) {
861 		ret = -ENOMEM;
862 		goto free_tz;
863 	}
864 
865 	i = 0;
866 	for_each_child_of_node(child, gchild) {
867 		ret = thermal_of_populate_trip(gchild, &tz->trips[i++]);
868 		if (ret)
869 			goto free_trips;
870 	}
871 
872 	of_node_put(child);
873 
874 	/* cooling-maps */
875 	child = of_get_child_by_name(np, "cooling-maps");
876 
877 	/* cooling-maps not provided */
878 	if (!child)
879 		goto finish;
880 
881 	tz->num_tbps = of_get_child_count(child);
882 	if (tz->num_tbps == 0)
883 		goto finish;
884 
885 	tz->tbps = kcalloc(tz->num_tbps, sizeof(*tz->tbps), GFP_KERNEL);
886 	if (!tz->tbps) {
887 		ret = -ENOMEM;
888 		goto free_trips;
889 	}
890 
891 	i = 0;
892 	for_each_child_of_node(child, gchild) {
893 		ret = thermal_of_populate_bind_params(gchild, &tz->tbps[i++],
894 						      tz->trips, tz->ntrips);
895 		if (ret)
896 			goto free_tbps;
897 	}
898 
899 finish:
900 	of_node_put(child);
901 	tz->mode = THERMAL_DEVICE_DISABLED;
902 
903 	return tz;
904 
905 free_tbps:
906 	for (i = i - 1; i >= 0; i--)
907 		of_node_put(tz->tbps[i].cooling_device);
908 	kfree(tz->tbps);
909 free_trips:
910 	for (i = 0; i < tz->ntrips; i++)
911 		of_node_put(tz->trips[i].np);
912 	kfree(tz->trips);
913 	of_node_put(gchild);
914 free_tz:
915 	kfree(tz);
916 	of_node_put(child);
917 
918 	return ERR_PTR(ret);
919 }
920 
of_thermal_free_zone(struct __thermal_zone * tz)921 static inline void of_thermal_free_zone(struct __thermal_zone *tz)
922 {
923 	int i;
924 
925 	for (i = 0; i < tz->num_tbps; i++)
926 		of_node_put(tz->tbps[i].cooling_device);
927 	kfree(tz->tbps);
928 	for (i = 0; i < tz->ntrips; i++)
929 		of_node_put(tz->trips[i].np);
930 	kfree(tz->trips);
931 	kfree(tz);
932 }
933 
934 /**
935  * of_parse_thermal_zones - parse device tree thermal data
936  *
937  * Initialization function that can be called by machine initialization
938  * code to parse thermal data and populate the thermal framework
939  * with hardware thermal zones info. This function only parses thermal zones.
940  * Cooling devices and sensor devices nodes are supposed to be parsed
941  * by their respective drivers.
942  *
943  * Return: 0 on success, proper error code otherwise
944  *
945  */
of_parse_thermal_zones(void)946 int __init of_parse_thermal_zones(void)
947 {
948 	struct device_node *np, *child;
949 	struct __thermal_zone *tz;
950 	struct thermal_zone_device_ops *ops;
951 
952 	np = of_find_node_by_name(NULL, "thermal-zones");
953 	if (!np) {
954 		pr_debug("unable to find thermal zones\n");
955 		return 0; /* Run successfully on systems without thermal DT */
956 	}
957 
958 	for_each_available_child_of_node(np, child) {
959 		struct thermal_zone_device *zone;
960 		struct thermal_zone_params *tzp;
961 		int i, mask = 0;
962 		u32 prop;
963 
964 		tz = thermal_of_build_thermal_zone(child);
965 		if (IS_ERR(tz)) {
966 			pr_err("failed to build thermal zone %s: %ld\n",
967 			       child->name,
968 			       PTR_ERR(tz));
969 			continue;
970 		}
971 
972 		ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
973 		if (!ops)
974 			goto exit_free;
975 
976 		tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
977 		if (!tzp) {
978 			kfree(ops);
979 			goto exit_free;
980 		}
981 
982 		/* No hwmon because there might be hwmon drivers registering */
983 		tzp->no_hwmon = true;
984 
985 		if (!of_property_read_u32(child, "sustainable-power", &prop))
986 			tzp->sustainable_power = prop;
987 
988 		for (i = 0; i < tz->ntrips; i++)
989 			mask |= 1 << i;
990 
991 		/* these two are left for temperature drivers to use */
992 		tzp->slope = tz->slope;
993 		tzp->offset = tz->offset;
994 
995 		zone = thermal_zone_device_register(child->name, tz->ntrips,
996 						    mask, tz,
997 						    ops, tzp,
998 						    tz->passive_delay,
999 						    tz->polling_delay);
1000 		if (IS_ERR(zone)) {
1001 			pr_err("Failed to build %s zone %ld\n", child->name,
1002 			       PTR_ERR(zone));
1003 			kfree(tzp);
1004 			kfree(ops);
1005 			of_thermal_free_zone(tz);
1006 			/* attempting to build remaining zones still */
1007 		}
1008 	}
1009 	of_node_put(np);
1010 
1011 	return 0;
1012 
1013 exit_free:
1014 	of_node_put(child);
1015 	of_node_put(np);
1016 	of_thermal_free_zone(tz);
1017 
1018 	/* no memory available, so free what we have built */
1019 	of_thermal_destroy_zones();
1020 
1021 	return -ENOMEM;
1022 }
1023 
1024 /**
1025  * of_thermal_destroy_zones - remove all zones parsed and allocated resources
1026  *
1027  * Finds all zones parsed and added to the thermal framework and remove them
1028  * from the system, together with their resources.
1029  *
1030  */
of_thermal_destroy_zones(void)1031 void of_thermal_destroy_zones(void)
1032 {
1033 	struct device_node *np, *child;
1034 
1035 	np = of_find_node_by_name(NULL, "thermal-zones");
1036 	if (!np) {
1037 		pr_debug("unable to find thermal zones\n");
1038 		return;
1039 	}
1040 
1041 	for_each_available_child_of_node(np, child) {
1042 		struct thermal_zone_device *zone;
1043 
1044 		zone = thermal_zone_get_zone_by_name(child->name);
1045 		if (IS_ERR(zone))
1046 			continue;
1047 
1048 		thermal_zone_device_unregister(zone);
1049 		kfree(zone->tzp);
1050 		kfree(zone->ops);
1051 		of_thermal_free_zone(zone->devdata);
1052 	}
1053 	of_node_put(np);
1054 }
1055