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