root/drivers/thermal/of-thermal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. of_thermal_get_temp
  2. of_thermal_set_trips
  3. of_thermal_get_ntrips
  4. of_thermal_is_trip_valid
  5. of_thermal_get_trip_points
  6. of_thermal_set_emul_temp
  7. of_thermal_get_trend
  8. of_thermal_bind
  9. of_thermal_unbind
  10. of_thermal_get_mode
  11. of_thermal_set_mode
  12. of_thermal_get_trip_type
  13. of_thermal_get_trip_temp
  14. of_thermal_set_trip_temp
  15. of_thermal_get_trip_hyst
  16. of_thermal_set_trip_hyst
  17. of_thermal_get_crit_temp
  18. thermal_zone_of_add_sensor
  19. thermal_zone_of_sensor_register
  20. thermal_zone_of_sensor_unregister
  21. devm_thermal_zone_of_sensor_release
  22. devm_thermal_zone_of_sensor_match
  23. devm_thermal_zone_of_sensor_register
  24. devm_thermal_zone_of_sensor_unregister
  25. thermal_of_populate_bind_params
  26. thermal_of_get_trip_type
  27. thermal_of_populate_trip
  28. thermal_of_build_thermal_zone
  29. of_thermal_free_zone
  30. of_parse_thermal_zones
  31. of_thermal_destroy_zones

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

/* [<][>][^][v][top][bottom][index][help] */