Linux Audio

Check our new training course

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