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