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