Linux Audio

Check our new training course

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