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