Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal into thermal-soc

Zhang Rui c75960aa 049e6dde

+985 -35
+14
Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt
··· 10 10 11 11 Required properties: 12 12 - compatible : Should be: 13 + - "ti,omap34xx-bandgap" : for OMAP34xx bandgap 14 + - "ti,omap36xx-bandgap" : for OMAP36xx bandgap 13 15 - "ti,omap4430-bandgap" : for OMAP4430 bandgap 14 16 - "ti,omap4460-bandgap" : for OMAP4460 bandgap 15 17 - "ti,omap4470-bandgap" : for OMAP4470 bandgap ··· 27 25 soc to soc, apart of depending on available features. 28 26 29 27 Example: 28 + OMAP34xx: 29 + bandgap { 30 + reg = <0x48002524 0x4>; 31 + compatible = "ti,omap34xx-bandgap"; 32 + }; 33 + 34 + OMAP36xx: 35 + bandgap { 36 + reg = <0x48002524 0x4>; 37 + compatible = "ti,omap36xx-bandgap"; 38 + }; 39 + 30 40 OMAP4430: 31 41 bandgap { 32 42 reg = <0x4a002260 0x4 0x4a00232C 0x4>;
+2 -2
drivers/base/power/opp.c
··· 217 217 } 218 218 219 219 /** 220 - * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an available opp 220 + * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp 221 221 * @opp: opp for which voltage has to be returned for 222 222 * 223 223 * Return: voltage in micro volt corresponding to the opp, else ··· 239 239 opp_rcu_lockdep_assert(); 240 240 241 241 tmp_opp = rcu_dereference(opp); 242 - if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available) 242 + if (IS_ERR_OR_NULL(tmp_opp)) 243 243 pr_err("%s: Invalid parameters\n", __func__); 244 244 else 245 245 v = tmp_opp->u_volt;
+14
drivers/thermal/Kconfig
··· 147 147 device that is configured to use this cooling mechanism will be 148 148 controlled to reduce clock frequency whenever temperature is high. 149 149 150 + config DEVFREQ_THERMAL 151 + bool "Generic device cooling support" 152 + depends on PM_DEVFREQ 153 + depends on PM_OPP 154 + help 155 + This implements the generic devfreq cooling mechanism through 156 + frequency reduction for devices using devfreq. 157 + 158 + This will throttle the device by limiting the maximum allowed DVFS 159 + frequency corresponding to the cooling level. 160 + 161 + In order to use the power extensions of the cooling device, 162 + devfreq should use the simple_ondemand governor. 163 + 150 164 If you want this support, you should say Y here. 151 165 152 166 config THERMAL_EMULATION
+3
drivers/thermal/Makefile
··· 22 22 # clock cooling 23 23 thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o 24 24 25 + # devfreq cooling 26 + thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o 27 + 25 28 # platform thermal drivers 26 29 obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o 27 30 obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
+3 -3
drivers/thermal/armada_thermal.c
··· 224 224 .is_valid_shift = 10, 225 225 .temp_shift = 0, 226 226 .temp_mask = 0x3ff, 227 - .coef_b = 2931108200UL, 228 - .coef_m = 5000000UL, 229 - .coef_div = 10502, 227 + .coef_b = 1172499100UL, 228 + .coef_m = 2000096UL, 229 + .coef_div = 4201, 230 230 .inverted = true, 231 231 }; 232 232
+569
drivers/thermal/devfreq_cooling.c
··· 1 + /* 2 + * devfreq_cooling: Thermal cooling device implementation for devices using 3 + * devfreq 4 + * 5 + * Copyright (C) 2014-2015 ARM Limited 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + * 11 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12 + * kind, whether express or implied; without even the implied warranty 13 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * TODO: 17 + * - If OPPs are added or removed after devfreq cooling has 18 + * registered, the devfreq cooling won't react to it. 19 + */ 20 + 21 + #include <linux/devfreq.h> 22 + #include <linux/devfreq_cooling.h> 23 + #include <linux/export.h> 24 + #include <linux/slab.h> 25 + #include <linux/pm_opp.h> 26 + #include <linux/thermal.h> 27 + 28 + #include <trace/events/thermal.h> 29 + 30 + static DEFINE_MUTEX(devfreq_lock); 31 + static DEFINE_IDR(devfreq_idr); 32 + 33 + /** 34 + * struct devfreq_cooling_device - Devfreq cooling device 35 + * @id: unique integer value corresponding to each 36 + * devfreq_cooling_device registered. 37 + * @cdev: Pointer to associated thermal cooling device. 38 + * @devfreq: Pointer to associated devfreq device. 39 + * @cooling_state: Current cooling state. 40 + * @power_table: Pointer to table with maximum power draw for each 41 + * cooling state. State is the index into the table, and 42 + * the power is in mW. 43 + * @freq_table: Pointer to a table with the frequencies sorted in descending 44 + * order. You can index the table by cooling device state 45 + * @freq_table_size: Size of the @freq_table and @power_table 46 + * @power_ops: Pointer to devfreq_cooling_power, used to generate the 47 + * @power_table. 48 + */ 49 + struct devfreq_cooling_device { 50 + int id; 51 + struct thermal_cooling_device *cdev; 52 + struct devfreq *devfreq; 53 + unsigned long cooling_state; 54 + u32 *power_table; 55 + u32 *freq_table; 56 + size_t freq_table_size; 57 + struct devfreq_cooling_power *power_ops; 58 + }; 59 + 60 + /** 61 + * get_idr - function to get a unique id. 62 + * @idr: struct idr * handle used to create a id. 63 + * @id: int * value generated by this function. 64 + * 65 + * This function will populate @id with an unique 66 + * id, using the idr API. 67 + * 68 + * Return: 0 on success, an error code on failure. 69 + */ 70 + static int get_idr(struct idr *idr, int *id) 71 + { 72 + int ret; 73 + 74 + mutex_lock(&devfreq_lock); 75 + ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL); 76 + mutex_unlock(&devfreq_lock); 77 + if (unlikely(ret < 0)) 78 + return ret; 79 + *id = ret; 80 + 81 + return 0; 82 + } 83 + 84 + /** 85 + * release_idr - function to free the unique id. 86 + * @idr: struct idr * handle used for creating the id. 87 + * @id: int value representing the unique id. 88 + */ 89 + static void release_idr(struct idr *idr, int id) 90 + { 91 + mutex_lock(&devfreq_lock); 92 + idr_remove(idr, id); 93 + mutex_unlock(&devfreq_lock); 94 + } 95 + 96 + /** 97 + * partition_enable_opps() - disable all opps above a given state 98 + * @dfc: Pointer to devfreq we are operating on 99 + * @cdev_state: cooling device state we're setting 100 + * 101 + * Go through the OPPs of the device, enabling all OPPs until 102 + * @cdev_state and disabling those frequencies above it. 103 + */ 104 + static int partition_enable_opps(struct devfreq_cooling_device *dfc, 105 + unsigned long cdev_state) 106 + { 107 + int i; 108 + struct device *dev = dfc->devfreq->dev.parent; 109 + 110 + for (i = 0; i < dfc->freq_table_size; i++) { 111 + struct dev_pm_opp *opp; 112 + int ret = 0; 113 + unsigned int freq = dfc->freq_table[i]; 114 + bool want_enable = i >= cdev_state ? true : false; 115 + 116 + rcu_read_lock(); 117 + opp = dev_pm_opp_find_freq_exact(dev, freq, !want_enable); 118 + rcu_read_unlock(); 119 + 120 + if (PTR_ERR(opp) == -ERANGE) 121 + continue; 122 + else if (IS_ERR(opp)) 123 + return PTR_ERR(opp); 124 + 125 + if (want_enable) 126 + ret = dev_pm_opp_enable(dev, freq); 127 + else 128 + ret = dev_pm_opp_disable(dev, freq); 129 + 130 + if (ret) 131 + return ret; 132 + } 133 + 134 + return 0; 135 + } 136 + 137 + static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev, 138 + unsigned long *state) 139 + { 140 + struct devfreq_cooling_device *dfc = cdev->devdata; 141 + 142 + *state = dfc->freq_table_size - 1; 143 + 144 + return 0; 145 + } 146 + 147 + static int devfreq_cooling_get_cur_state(struct thermal_cooling_device *cdev, 148 + unsigned long *state) 149 + { 150 + struct devfreq_cooling_device *dfc = cdev->devdata; 151 + 152 + *state = dfc->cooling_state; 153 + 154 + return 0; 155 + } 156 + 157 + static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev, 158 + unsigned long state) 159 + { 160 + struct devfreq_cooling_device *dfc = cdev->devdata; 161 + struct devfreq *df = dfc->devfreq; 162 + struct device *dev = df->dev.parent; 163 + int ret; 164 + 165 + if (state == dfc->cooling_state) 166 + return 0; 167 + 168 + dev_dbg(dev, "Setting cooling state %lu\n", state); 169 + 170 + if (state >= dfc->freq_table_size) 171 + return -EINVAL; 172 + 173 + ret = partition_enable_opps(dfc, state); 174 + if (ret) 175 + return ret; 176 + 177 + dfc->cooling_state = state; 178 + 179 + return 0; 180 + } 181 + 182 + /** 183 + * freq_get_state() - get the cooling state corresponding to a frequency 184 + * @dfc: Pointer to devfreq cooling device 185 + * @freq: frequency in Hz 186 + * 187 + * Return: the cooling state associated with the @freq, or 188 + * THERMAL_CSTATE_INVALID if it wasn't found. 189 + */ 190 + static unsigned long 191 + freq_get_state(struct devfreq_cooling_device *dfc, unsigned long freq) 192 + { 193 + int i; 194 + 195 + for (i = 0; i < dfc->freq_table_size; i++) { 196 + if (dfc->freq_table[i] == freq) 197 + return i; 198 + } 199 + 200 + return THERMAL_CSTATE_INVALID; 201 + } 202 + 203 + /** 204 + * get_static_power() - calculate the static power 205 + * @dfc: Pointer to devfreq cooling device 206 + * @freq: Frequency in Hz 207 + * 208 + * Calculate the static power in milliwatts using the supplied 209 + * get_static_power(). The current voltage is calculated using the 210 + * OPP library. If no get_static_power() was supplied, assume the 211 + * static power is negligible. 212 + */ 213 + static unsigned long 214 + get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq) 215 + { 216 + struct devfreq *df = dfc->devfreq; 217 + struct device *dev = df->dev.parent; 218 + unsigned long voltage; 219 + struct dev_pm_opp *opp; 220 + 221 + if (!dfc->power_ops->get_static_power) 222 + return 0; 223 + 224 + rcu_read_lock(); 225 + 226 + opp = dev_pm_opp_find_freq_exact(dev, freq, true); 227 + if (IS_ERR(opp) && (PTR_ERR(opp) == -ERANGE)) 228 + opp = dev_pm_opp_find_freq_exact(dev, freq, false); 229 + 230 + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ 231 + 232 + rcu_read_unlock(); 233 + 234 + if (voltage == 0) { 235 + dev_warn_ratelimited(dev, 236 + "Failed to get voltage for frequency %lu: %ld\n", 237 + freq, IS_ERR(opp) ? PTR_ERR(opp) : 0); 238 + return 0; 239 + } 240 + 241 + return dfc->power_ops->get_static_power(voltage); 242 + } 243 + 244 + /** 245 + * get_dynamic_power - calculate the dynamic power 246 + * @dfc: Pointer to devfreq cooling device 247 + * @freq: Frequency in Hz 248 + * @voltage: Voltage in millivolts 249 + * 250 + * Calculate the dynamic power in milliwatts consumed by the device at 251 + * frequency @freq and voltage @voltage. If the get_dynamic_power() 252 + * was supplied as part of the devfreq_cooling_power struct, then that 253 + * function is used. Otherwise, a simple power model (Pdyn = Coeff * 254 + * Voltage^2 * Frequency) is used. 255 + */ 256 + static unsigned long 257 + get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq, 258 + unsigned long voltage) 259 + { 260 + unsigned long power; 261 + u32 freq_mhz; 262 + struct devfreq_cooling_power *dfc_power = dfc->power_ops; 263 + 264 + if (dfc_power->get_dynamic_power) 265 + return dfc_power->get_dynamic_power(freq, voltage); 266 + 267 + freq_mhz = freq / 1000000; 268 + power = (u64)dfc_power->dyn_power_coeff * freq_mhz * voltage * voltage; 269 + do_div(power, 1000000000); 270 + 271 + return power; 272 + } 273 + 274 + static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev, 275 + struct thermal_zone_device *tz, 276 + u32 *power) 277 + { 278 + struct devfreq_cooling_device *dfc = cdev->devdata; 279 + struct devfreq *df = dfc->devfreq; 280 + struct devfreq_dev_status *status = &df->last_status; 281 + unsigned long state; 282 + unsigned long freq = status->current_frequency; 283 + u32 dyn_power, static_power; 284 + 285 + /* Get dynamic power for state */ 286 + state = freq_get_state(dfc, freq); 287 + if (state == THERMAL_CSTATE_INVALID) 288 + return -EAGAIN; 289 + 290 + dyn_power = dfc->power_table[state]; 291 + 292 + /* Scale dynamic power for utilization */ 293 + dyn_power = (dyn_power * status->busy_time) / status->total_time; 294 + 295 + /* Get static power */ 296 + static_power = get_static_power(dfc, freq); 297 + 298 + trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power, 299 + static_power); 300 + 301 + *power = dyn_power + static_power; 302 + 303 + return 0; 304 + } 305 + 306 + static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, 307 + struct thermal_zone_device *tz, 308 + unsigned long state, 309 + u32 *power) 310 + { 311 + struct devfreq_cooling_device *dfc = cdev->devdata; 312 + unsigned long freq; 313 + u32 static_power; 314 + 315 + if (state < 0 || state >= dfc->freq_table_size) 316 + return -EINVAL; 317 + 318 + freq = dfc->freq_table[state]; 319 + static_power = get_static_power(dfc, freq); 320 + 321 + *power = dfc->power_table[state] + static_power; 322 + return 0; 323 + } 324 + 325 + static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev, 326 + struct thermal_zone_device *tz, 327 + u32 power, unsigned long *state) 328 + { 329 + struct devfreq_cooling_device *dfc = cdev->devdata; 330 + struct devfreq *df = dfc->devfreq; 331 + struct devfreq_dev_status *status = &df->last_status; 332 + unsigned long freq = status->current_frequency; 333 + unsigned long busy_time; 334 + s32 dyn_power; 335 + u32 static_power; 336 + int i; 337 + 338 + static_power = get_static_power(dfc, freq); 339 + 340 + dyn_power = power - static_power; 341 + dyn_power = dyn_power > 0 ? dyn_power : 0; 342 + 343 + /* Scale dynamic power for utilization */ 344 + busy_time = status->busy_time ?: 1; 345 + dyn_power = (dyn_power * status->total_time) / busy_time; 346 + 347 + /* 348 + * Find the first cooling state that is within the power 349 + * budget for dynamic power. 350 + */ 351 + for (i = 0; i < dfc->freq_table_size - 1; i++) 352 + if (dyn_power >= dfc->power_table[i]) 353 + break; 354 + 355 + *state = i; 356 + trace_thermal_power_devfreq_limit(cdev, freq, *state, power); 357 + return 0; 358 + } 359 + 360 + static struct thermal_cooling_device_ops devfreq_cooling_ops = { 361 + .get_max_state = devfreq_cooling_get_max_state, 362 + .get_cur_state = devfreq_cooling_get_cur_state, 363 + .set_cur_state = devfreq_cooling_set_cur_state, 364 + }; 365 + 366 + /** 367 + * devfreq_cooling_gen_tables() - Generate power and freq tables. 368 + * @dfc: Pointer to devfreq cooling device. 369 + * 370 + * Generate power and frequency tables: the power table hold the 371 + * device's maximum power usage at each cooling state (OPP). The 372 + * static and dynamic power using the appropriate voltage and 373 + * frequency for the state, is acquired from the struct 374 + * devfreq_cooling_power, and summed to make the maximum power draw. 375 + * 376 + * The frequency table holds the frequencies in descending order. 377 + * That way its indexed by cooling device state. 378 + * 379 + * The tables are malloced, and pointers put in dfc. They must be 380 + * freed when unregistering the devfreq cooling device. 381 + * 382 + * Return: 0 on success, negative error code on failure. 383 + */ 384 + static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc) 385 + { 386 + struct devfreq *df = dfc->devfreq; 387 + struct device *dev = df->dev.parent; 388 + int ret, num_opps; 389 + unsigned long freq; 390 + u32 *power_table = NULL; 391 + u32 *freq_table; 392 + int i; 393 + 394 + num_opps = dev_pm_opp_get_opp_count(dev); 395 + 396 + if (dfc->power_ops) { 397 + power_table = kcalloc(num_opps, sizeof(*power_table), 398 + GFP_KERNEL); 399 + if (!power_table) 400 + ret = -ENOMEM; 401 + } 402 + 403 + freq_table = kcalloc(num_opps, sizeof(*freq_table), 404 + GFP_KERNEL); 405 + if (!freq_table) { 406 + ret = -ENOMEM; 407 + goto free_power_table; 408 + } 409 + 410 + for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) { 411 + unsigned long power_dyn, voltage; 412 + struct dev_pm_opp *opp; 413 + 414 + rcu_read_lock(); 415 + 416 + opp = dev_pm_opp_find_freq_floor(dev, &freq); 417 + if (IS_ERR(opp)) { 418 + rcu_read_unlock(); 419 + ret = PTR_ERR(opp); 420 + goto free_tables; 421 + } 422 + 423 + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ 424 + 425 + rcu_read_unlock(); 426 + 427 + if (dfc->power_ops) { 428 + power_dyn = get_dynamic_power(dfc, freq, voltage); 429 + 430 + dev_dbg(dev, "Dynamic power table: %lu MHz @ %lu mV: %lu = %lu mW\n", 431 + freq / 1000000, voltage, power_dyn, power_dyn); 432 + 433 + power_table[i] = power_dyn; 434 + } 435 + 436 + freq_table[i] = freq; 437 + } 438 + 439 + if (dfc->power_ops) 440 + dfc->power_table = power_table; 441 + 442 + dfc->freq_table = freq_table; 443 + dfc->freq_table_size = num_opps; 444 + 445 + return 0; 446 + 447 + free_tables: 448 + kfree(freq_table); 449 + free_power_table: 450 + kfree(power_table); 451 + 452 + return ret; 453 + } 454 + 455 + /** 456 + * of_devfreq_cooling_register_power() - Register devfreq cooling device, 457 + * with OF and power information. 458 + * @np: Pointer to OF device_node. 459 + * @df: Pointer to devfreq device. 460 + * @dfc_power: Pointer to devfreq_cooling_power. 461 + * 462 + * Register a devfreq cooling device. The available OPPs must be 463 + * registered on the device. 464 + * 465 + * If @dfc_power is provided, the cooling device is registered with the 466 + * power extensions. For the power extensions to work correctly, 467 + * devfreq should use the simple_ondemand governor, other governors 468 + * are not currently supported. 469 + */ 470 + struct devfreq_cooling_device * 471 + of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, 472 + struct devfreq_cooling_power *dfc_power) 473 + { 474 + struct thermal_cooling_device *cdev; 475 + struct devfreq_cooling_device *dfc; 476 + char dev_name[THERMAL_NAME_LENGTH]; 477 + int err; 478 + 479 + dfc = kzalloc(sizeof(*dfc), GFP_KERNEL); 480 + if (!dfc) 481 + return ERR_PTR(-ENOMEM); 482 + 483 + dfc->devfreq = df; 484 + 485 + if (dfc_power) { 486 + dfc->power_ops = dfc_power; 487 + 488 + devfreq_cooling_ops.get_requested_power = 489 + devfreq_cooling_get_requested_power; 490 + devfreq_cooling_ops.state2power = devfreq_cooling_state2power; 491 + devfreq_cooling_ops.power2state = devfreq_cooling_power2state; 492 + } 493 + 494 + err = devfreq_cooling_gen_tables(dfc); 495 + if (err) 496 + goto free_dfc; 497 + 498 + err = get_idr(&devfreq_idr, &dfc->id); 499 + if (err) 500 + goto free_tables; 501 + 502 + snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id); 503 + 504 + cdev = thermal_of_cooling_device_register(np, dev_name, dfc, 505 + &devfreq_cooling_ops); 506 + if (IS_ERR(cdev)) { 507 + err = PTR_ERR(cdev); 508 + dev_err(df->dev.parent, 509 + "Failed to register devfreq cooling device (%d)\n", 510 + err); 511 + goto release_idr; 512 + } 513 + 514 + dfc->cdev = cdev; 515 + 516 + return dfc; 517 + 518 + release_idr: 519 + release_idr(&devfreq_idr, dfc->id); 520 + free_tables: 521 + kfree(dfc->power_table); 522 + kfree(dfc->freq_table); 523 + free_dfc: 524 + kfree(dfc); 525 + 526 + return ERR_PTR(err); 527 + } 528 + EXPORT_SYMBOL_GPL(of_devfreq_cooling_register_power); 529 + 530 + /** 531 + * of_devfreq_cooling_register() - Register devfreq cooling device, 532 + * with OF information. 533 + * @np: Pointer to OF device_node. 534 + * @df: Pointer to devfreq device. 535 + */ 536 + struct devfreq_cooling_device * 537 + of_devfreq_cooling_register(struct device_node *np, struct devfreq *df) 538 + { 539 + return of_devfreq_cooling_register_power(np, df, NULL); 540 + } 541 + EXPORT_SYMBOL_GPL(of_devfreq_cooling_register); 542 + 543 + /** 544 + * devfreq_cooling_register() - Register devfreq cooling device. 545 + * @df: Pointer to devfreq device. 546 + */ 547 + struct devfreq_cooling_device *devfreq_cooling_register(struct devfreq *df) 548 + { 549 + return of_devfreq_cooling_register(NULL, df); 550 + } 551 + EXPORT_SYMBOL_GPL(devfreq_cooling_register); 552 + 553 + /** 554 + * devfreq_cooling_unregister() - Unregister devfreq cooling device. 555 + * @dfc: Pointer to devfreq cooling device to unregister. 556 + */ 557 + void devfreq_cooling_unregister(struct devfreq_cooling_device *dfc) 558 + { 559 + if (!dfc) 560 + return; 561 + 562 + thermal_cooling_device_unregister(dfc->cdev); 563 + release_idr(&devfreq_idr, dfc->id); 564 + kfree(dfc->power_table); 565 + kfree(dfc->freq_table); 566 + 567 + kfree(dfc); 568 + } 569 + EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
+12 -9
drivers/thermal/imx_thermal.c
··· 288 288 if (trip == IMX_TRIP_CRITICAL) 289 289 return -EPERM; 290 290 291 - if (temp > IMX_TEMP_PASSIVE) 291 + if (temp < 0 || temp > IMX_TEMP_PASSIVE) 292 292 return -EINVAL; 293 293 294 294 data->temp_passive = temp; ··· 487 487 if (data->irq < 0) 488 488 return data->irq; 489 489 490 - ret = devm_request_threaded_irq(&pdev->dev, data->irq, 491 - imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, 492 - 0, "imx_thermal", data); 493 - if (ret < 0) { 494 - dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); 495 - return ret; 496 - } 497 - 498 490 platform_set_drvdata(pdev, data); 499 491 500 492 ret = imx_get_sensor_data(pdev); ··· 562 570 563 571 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); 564 572 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); 573 + 574 + ret = devm_request_threaded_irq(&pdev->dev, data->irq, 575 + imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, 576 + 0, "imx_thermal", data); 577 + if (ret < 0) { 578 + dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); 579 + clk_disable_unprepare(data->thermal_clk); 580 + thermal_zone_device_unregister(data->tz); 581 + cpufreq_cooling_unregister(data->cdev); 582 + return ret; 583 + } 565 584 566 585 data->irq_enabled = true; 567 586 data->mode = THERMAL_DEVICE_ENABLED;
+17 -21
drivers/thermal/rockchip_thermal.c
··· 106 106 #define TSADCV2_AUTO_PERIOD_HT 0x6c 107 107 108 108 #define TSADCV2_AUTO_EN BIT(0) 109 - #define TSADCV2_AUTO_DISABLE ~BIT(0) 110 109 #define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn)) 111 110 #define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8) 112 - #define TSADCV2_AUTO_TSHUT_POLARITY_LOW ~BIT(8) 113 111 114 112 #define TSADCV2_INT_SRC_EN(chn) BIT(chn) 115 113 #define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn)) 116 114 #define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn)) 117 115 118 - #define TSADCV2_INT_PD_CLEAR ~BIT(8) 116 + #define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8) 119 117 120 118 #define TSADCV2_DATA_MASK 0xfff 121 119 #define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4 ··· 122 124 #define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* msec */ 123 125 124 126 struct tsadc_table { 125 - unsigned long code; 127 + u32 code; 126 128 long temp; 127 129 }; 128 130 ··· 162 164 {3452, 115000}, 163 165 {3437, 120000}, 164 166 {3421, 125000}, 165 - {0, 125000}, 166 167 }; 167 168 168 169 static u32 rk_tsadcv2_temp_to_code(long temp) ··· 188 191 return 0; 189 192 } 190 193 191 - static int rk_tsadcv2_code_to_temp(u32 code) 194 + static int rk_tsadcv2_code_to_temp(u32 code, int *temp) 192 195 { 193 - unsigned int low = 0; 196 + unsigned int low = 1; 194 197 unsigned int high = ARRAY_SIZE(v2_code_table) - 1; 195 198 unsigned int mid = (low + high) / 2; 196 199 unsigned int num; 197 200 unsigned long denom; 198 201 199 - /* Invalid code, return -EAGAIN */ 200 - if (code > TSADCV2_DATA_MASK) 201 - return -EAGAIN; 202 + BUILD_BUG_ON(ARRAY_SIZE(v2_code_table) < 2); 202 203 203 - while (low <= high && mid) { 204 + code &= TSADCV2_DATA_MASK; 205 + if (code < v2_code_table[high].code) 206 + return -EAGAIN; /* Incorrect reading */ 207 + 208 + while (low <= high) { 204 209 if (code >= v2_code_table[mid].code && 205 210 code < v2_code_table[mid - 1].code) 206 211 break; ··· 222 223 num = v2_code_table[mid].temp - v2_code_table[mid - 1].temp; 223 224 num *= v2_code_table[mid - 1].code - code; 224 225 denom = v2_code_table[mid - 1].code - v2_code_table[mid].code; 225 - return v2_code_table[mid - 1].temp + (num / denom); 226 + *temp = v2_code_table[mid - 1].temp + (num / denom); 227 + 228 + return 0; 226 229 } 227 230 228 231 /** ··· 242 241 enum tshut_polarity tshut_polarity) 243 242 { 244 243 if (tshut_polarity == TSHUT_HIGH_ACTIVE) 245 - writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_HIGH), 244 + writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH, 246 245 regs + TSADCV2_AUTO_CON); 247 246 else 248 - writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_LOW), 247 + writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, 249 248 regs + TSADCV2_AUTO_CON); 250 249 251 250 writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD); ··· 262 261 u32 val; 263 262 264 263 val = readl_relaxed(regs + TSADCV2_INT_PD); 265 - writel_relaxed(val & TSADCV2_INT_PD_CLEAR, regs + TSADCV2_INT_PD); 264 + writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD); 266 265 } 267 266 268 267 static void rk_tsadcv2_control(void __iomem *regs, bool enable) ··· 282 281 { 283 282 u32 val; 284 283 285 - /* the A/D value of the channel last conversion need some time */ 286 284 val = readl_relaxed(regs + TSADCV2_DATA(chn)); 287 - if (val == 0) 288 - return -EAGAIN; 289 285 290 - *temp = rk_tsadcv2_code_to_temp(val); 291 - 292 - return 0; 286 + return rk_tsadcv2_code_to_temp(val, temp); 293 287 } 294 288 295 289 static void rk_tsadcv2_tshut_temp(int chn, void __iomem *regs, long temp)
+15
drivers/thermal/ti-soc-thermal/Kconfig
··· 19 19 This includes trip points definitions, extrapolation rules and 20 20 CPU cooling device bindings. 21 21 22 + config OMAP3_THERMAL 23 + bool "Texas Instruments OMAP3 thermal support" 24 + depends on TI_SOC_THERMAL 25 + depends on ARCH_OMAP3 || COMPILE_TEST 26 + help 27 + If you say yes here you get thermal support for the Texas Instruments 28 + OMAP3 SoC family. The current chips supported are: 29 + - OMAP3430 30 + 31 + OMAP3 chips normally don't need thermal management, and sensors in 32 + this generation are not accurate, nor they are very close to 33 + the important hotspots. 34 + 35 + Say 'N' here. 36 + 22 37 config OMAP4_THERMAL 23 38 bool "Texas Instruments OMAP4 thermal support" 24 39 depends on TI_SOC_THERMAL
+1
drivers/thermal/ti-soc-thermal/Makefile
··· 2 2 ti-soc-thermal-y := ti-bandgap.o 3 3 ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o 4 4 ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o 5 + ti-soc-thermal-$(CONFIG_OMAP3_THERMAL) += omap3-thermal-data.o 5 6 ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o 6 7 ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o
+176
drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
··· 1 + /* 2 + * OMAP3 thermal driver. 3 + * 4 + * Copyright (C) 2011-2012 Texas Instruments Inc. 5 + * Copyright (C) 2014 Pavel Machek <pavel@ucw.cz> 6 + * 7 + * This software is licensed under the terms of the GNU General Public 8 + * License version 2, as published by the Free Software Foundation, and 9 + * may be copied, distributed, and modified under those terms. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * Note 17 + * http://www.ti.com/lit/er/sprz278f/sprz278f.pdf "Advisory 18 + * 3.1.1.186 MMC OCP Clock Not Gated When Thermal Sensor Is Used" 19 + * 20 + * Also TI says: 21 + * Just be careful when you try to make thermal policy like decisions 22 + * based on this sensor. Placement of the sensor w.r.t the actual logic 23 + * generating heat has to be a factor as well. If you are just looking 24 + * for an approximation temperature (thermometerish kind), you might be 25 + * ok with this. I am not sure we'd find any TI data around this.. just a 26 + * heads up. 27 + */ 28 + 29 + #include "ti-thermal.h" 30 + #include "ti-bandgap.h" 31 + 32 + /* 33 + * OMAP34XX has one instance of thermal sensor for MPU 34 + * need to describe the individual bit fields 35 + */ 36 + static struct temp_sensor_registers 37 + omap34xx_mpu_temp_sensor_registers = { 38 + .temp_sensor_ctrl = 0, 39 + .bgap_soc_mask = BIT(8), 40 + .bgap_eocz_mask = BIT(7), 41 + .bgap_dtemp_mask = 0x7f, 42 + 43 + .bgap_mode_ctrl = 0, 44 + .mode_ctrl_mask = BIT(9), 45 + }; 46 + 47 + /* Thresholds and limits for OMAP34XX MPU temperature sensor */ 48 + static struct temp_sensor_data omap34xx_mpu_temp_sensor_data = { 49 + .min_freq = 32768, 50 + .max_freq = 32768, 51 + .max_temp = 125000, 52 + .min_temp = -40000, 53 + .hyst_val = 5000, 54 + }; 55 + 56 + /* 57 + * Temperature values in milli degree celsius 58 + */ 59 + static const int 60 + omap34xx_adc_to_temp[128] = { 61 + -40000, -40000, -40000, -40000, -40000, -39000, -38000, -36000, 62 + -34000, -32000, -31000, -29000, -28000, -26000, -25000, -24000, 63 + -22000, -21000, -19000, -18000, -17000, -15000, -14000, -12000, 64 + -11000, -9000, -8000, -7000, -5000, -4000, -2000, -1000, 0000, 65 + 1000, 3000, 4000, 5000, 7000, 8000, 10000, 11000, 13000, 14000, 66 + 15000, 17000, 18000, 20000, 21000, 22000, 24000, 25000, 27000, 67 + 28000, 30000, 31000, 32000, 34000, 35000, 37000, 38000, 39000, 68 + 41000, 42000, 44000, 45000, 47000, 48000, 49000, 51000, 52000, 69 + 53000, 55000, 56000, 58000, 59000, 60000, 62000, 63000, 65000, 70 + 66000, 67000, 69000, 70000, 72000, 73000, 74000, 76000, 77000, 71 + 79000, 80000, 81000, 83000, 84000, 85000, 87000, 88000, 89000, 72 + 91000, 92000, 94000, 95000, 96000, 98000, 99000, 100000, 73 + 102000, 103000, 105000, 106000, 107000, 109000, 110000, 111000, 74 + 113000, 114000, 116000, 117000, 118000, 120000, 121000, 122000, 75 + 124000, 124000, 125000, 125000, 125000, 125000, 125000 76 + }; 77 + 78 + /* OMAP34XX data */ 79 + const struct ti_bandgap_data omap34xx_data = { 80 + .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE, 81 + .fclock_name = "ts_fck", 82 + .div_ck_name = "ts_fck", 83 + .conv_table = omap34xx_adc_to_temp, 84 + .adc_start_val = 0, 85 + .adc_end_val = 127, 86 + .expose_sensor = ti_thermal_expose_sensor, 87 + .remove_sensor = ti_thermal_remove_sensor, 88 + 89 + .sensors = { 90 + { 91 + .registers = &omap34xx_mpu_temp_sensor_registers, 92 + .ts_data = &omap34xx_mpu_temp_sensor_data, 93 + .domain = "cpu", 94 + .slope = 0, 95 + .constant = 20000, 96 + .slope_pcb = 0, 97 + .constant_pcb = 20000, 98 + .register_cooling = NULL, 99 + .unregister_cooling = NULL, 100 + }, 101 + }, 102 + .sensor_count = 1, 103 + }; 104 + 105 + /* 106 + * OMAP36XX has one instance of thermal sensor for MPU 107 + * need to describe the individual bit fields 108 + */ 109 + static struct temp_sensor_registers 110 + omap36xx_mpu_temp_sensor_registers = { 111 + .temp_sensor_ctrl = 0, 112 + .bgap_soc_mask = BIT(9), 113 + .bgap_eocz_mask = BIT(8), 114 + .bgap_dtemp_mask = 0xFF, 115 + 116 + .bgap_mode_ctrl = 0, 117 + .mode_ctrl_mask = BIT(10), 118 + }; 119 + 120 + /* Thresholds and limits for OMAP36XX MPU temperature sensor */ 121 + static struct temp_sensor_data omap36xx_mpu_temp_sensor_data = { 122 + .min_freq = 32768, 123 + .max_freq = 32768, 124 + .max_temp = 125000, 125 + .min_temp = -40000, 126 + .hyst_val = 5000, 127 + }; 128 + 129 + /* 130 + * Temperature values in milli degree celsius 131 + */ 132 + static const int 133 + omap36xx_adc_to_temp[128] = { 134 + -40000, -40000, -40000, -40000, -40000, -40000, -40000, -40000, 135 + -40000, -40000, -40000, -40000, -40000, -38000, -35000, -34000, 136 + -32000, -30000, -28000, -26000, -24000, -22000, -20000, -18500, 137 + -17000, -15000, -13500, -12000, -10000, -8000, -6500, -5000, -3500, 138 + -1500, 0, 2000, 3500, 5000, 6500, 8500, 10000, 12000, 13500, 139 + 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28500, 30000, 140 + 32000, 33500, 35000, 37000, 38500, 40000, 42000, 43500, 45000, 141 + 47000, 48500, 50000, 52000, 53500, 55000, 57000, 58500, 60000, 142 + 62000, 64000, 66000, 68000, 70000, 71500, 73500, 75000, 77000, 143 + 78500, 80000, 82000, 83500, 85000, 87000, 88500, 90000, 92000, 144 + 93500, 95000, 97000, 98500, 100000, 102000, 103500, 105000, 107000, 145 + 109000, 111000, 113000, 115000, 117000, 118500, 120000, 122000, 146 + 123500, 125000, 125000, 125000, 125000, 125000, 125000, 125000, 147 + 125000, 125000, 125000, 125000, 125000, 125000, 125000, 125000, 148 + 125000, 125000, 125000, 125000, 125000, 125000, 125000 149 + }; 150 + 151 + /* OMAP36XX data */ 152 + const struct ti_bandgap_data omap36xx_data = { 153 + .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE, 154 + .fclock_name = "ts_fck", 155 + .div_ck_name = "ts_fck", 156 + .conv_table = omap36xx_adc_to_temp, 157 + .adc_start_val = 0, 158 + .adc_end_val = 127, 159 + .expose_sensor = ti_thermal_expose_sensor, 160 + .remove_sensor = ti_thermal_remove_sensor, 161 + 162 + .sensors = { 163 + { 164 + .registers = &omap36xx_mpu_temp_sensor_registers, 165 + .ts_data = &omap36xx_mpu_temp_sensor_data, 166 + .domain = "cpu", 167 + .slope = 0, 168 + .constant = 20000, 169 + .slope_pcb = 0, 170 + .constant_pcb = 20000, 171 + .register_cooling = NULL, 172 + .unregister_cooling = NULL, 173 + }, 174 + }, 175 + .sensor_count = 1, 176 + };
+14
drivers/thermal/ti-soc-thermal/ti-bandgap.c
··· 1274 1274 } 1275 1275 bgp->dev = &pdev->dev; 1276 1276 1277 + if (TI_BANDGAP_HAS(bgp, UNRELIABLE)) 1278 + dev_warn(&pdev->dev, 1279 + "This OMAP thermal sensor is unreliable. You've been warned\n"); 1280 + 1277 1281 if (TI_BANDGAP_HAS(bgp, TSHUT)) { 1278 1282 ret = ti_bandgap_tshut_init(bgp, pdev); 1279 1283 if (ret) { ··· 1583 1579 #endif 1584 1580 1585 1581 static const struct of_device_id of_ti_bandgap_match[] = { 1582 + #ifdef CONFIG_OMAP3_THERMAL 1583 + { 1584 + .compatible = "ti,omap34xx-bandgap", 1585 + .data = (void *)&omap34xx_data, 1586 + }, 1587 + { 1588 + .compatible = "ti,omap36xx-bandgap", 1589 + .data = (void *)&omap36xx_data, 1590 + }, 1591 + #endif 1586 1592 #ifdef CONFIG_OMAP4_THERMAL 1587 1593 { 1588 1594 .compatible = "ti,omap4430-bandgap",
+11
drivers/thermal/ti-soc-thermal/ti-bandgap.h
··· 322 322 * has Errata 814 323 323 * TI_BANDGAP_FEATURE_ERRATA_813 - used to workaorund when the bandgap device 324 324 * has Errata 813 325 + * TI_BANDGAP_FEATURE_UNRELIABLE - used when the sensor readings are too 326 + * inaccurate. 325 327 * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a 326 328 * specific feature (above) or not. Return non-zero, if yes. 327 329 */ ··· 339 337 #define TI_BANDGAP_FEATURE_HISTORY_BUFFER BIT(9) 340 338 #define TI_BANDGAP_FEATURE_ERRATA_814 BIT(10) 341 339 #define TI_BANDGAP_FEATURE_ERRATA_813 BIT(11) 340 + #define TI_BANDGAP_FEATURE_UNRELIABLE BIT(12) 342 341 #define TI_BANDGAP_HAS(b, f) \ 343 342 ((b)->conf->features & TI_BANDGAP_FEATURE_ ## f) 344 343 ··· 392 389 int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data); 393 390 void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id); 394 391 int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend); 392 + 393 + #ifdef CONFIG_OMAP3_THERMAL 394 + extern const struct ti_bandgap_data omap34xx_data; 395 + extern const struct ti_bandgap_data omap36xx_data; 396 + #else 397 + #define omap34xx_data NULL 398 + #define omap36xx_data NULL 399 + #endif 395 400 396 401 #ifdef CONFIG_OMAP4_THERMAL 397 402 extern const struct ti_bandgap_data omap4430_data;
+81
include/linux/devfreq_cooling.h
··· 1 + /* 2 + * devfreq_cooling: Thermal cooling device implementation for devices using 3 + * devfreq 4 + * 5 + * Copyright (C) 2014-2015 ARM Limited 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + * 11 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12 + * kind, whether express or implied; without even the implied warranty 13 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + 17 + #ifndef __DEVFREQ_COOLING_H__ 18 + #define __DEVFREQ_COOLING_H__ 19 + 20 + #include <linux/devfreq.h> 21 + #include <linux/thermal.h> 22 + 23 + #ifdef CONFIG_DEVFREQ_THERMAL 24 + 25 + /** 26 + * struct devfreq_cooling_power - Devfreq cooling power ops 27 + * @get_static_power: Take voltage, in mV, and return the static power 28 + * in mW. If NULL, the static power is assumed 29 + * to be 0. 30 + * @get_dynamic_power: Take voltage, in mV, and frequency, in HZ, and 31 + * return the dynamic power draw in mW. If NULL, 32 + * a simple power model is used. 33 + * @dyn_power_coeff: Coefficient for the simple dynamic power model in 34 + * mW/(MHz mV mV). 35 + * If get_dynamic_power() is NULL, then the 36 + * dynamic power is calculated as 37 + * @dyn_power_coeff * frequency * voltage^2 38 + */ 39 + struct devfreq_cooling_power { 40 + unsigned long (*get_static_power)(unsigned long voltage); 41 + unsigned long (*get_dynamic_power)(unsigned long freq, 42 + unsigned long voltage); 43 + unsigned long dyn_power_coeff; 44 + }; 45 + 46 + struct devfreq_cooling_device * 47 + of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, 48 + struct devfreq_cooling_power *dfc_power); 49 + struct devfreq_cooling_device * 50 + of_devfreq_cooling_register(struct device_node *np, struct devfreq *df); 51 + struct devfreq_cooling_device *devfreq_cooling_register(struct devfreq *df); 52 + void devfreq_cooling_unregister(struct devfreq_cooling_device *dfc); 53 + 54 + #else /* !CONFIG_DEVFREQ_THERMAL */ 55 + 56 + struct devfreq_cooling_device * 57 + of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, 58 + struct devfreq_cooling_power *dfc_power) 59 + { 60 + return ERR_PTR(-EINVAL); 61 + } 62 + 63 + static inline struct devfreq_cooling_device * 64 + of_devfreq_cooling_register(struct device_node *np, struct devfreq *df) 65 + { 66 + return ERR_PTR(-EINVAL); 67 + } 68 + 69 + static inline struct devfreq_cooling_device * 70 + devfreq_cooling_register(struct devfreq *df) 71 + { 72 + return ERR_PTR(-EINVAL); 73 + } 74 + 75 + static inline void 76 + devfreq_cooling_unregister(struct devfreq_cooling_device *dfc) 77 + { 78 + } 79 + 80 + #endif /* CONFIG_DEVFREQ_THERMAL */ 81 + #endif /* __DEVFREQ_COOLING_H__ */
+53
include/trace/events/thermal.h
··· 4 4 #if !defined(_TRACE_THERMAL_H) || defined(TRACE_HEADER_MULTI_READ) 5 5 #define _TRACE_THERMAL_H 6 6 7 + #include <linux/devfreq.h> 7 8 #include <linux/thermal.h> 8 9 #include <linux/tracepoint.h> 9 10 ··· 136 135 __entry->power) 137 136 ); 138 137 138 + TRACE_EVENT(thermal_power_devfreq_get_power, 139 + TP_PROTO(struct thermal_cooling_device *cdev, 140 + struct devfreq_dev_status *status, unsigned long freq, 141 + u32 dynamic_power, u32 static_power), 142 + 143 + TP_ARGS(cdev, status, freq, dynamic_power, static_power), 144 + 145 + TP_STRUCT__entry( 146 + __string(type, cdev->type ) 147 + __field(unsigned long, freq ) 148 + __field(u32, load ) 149 + __field(u32, dynamic_power ) 150 + __field(u32, static_power ) 151 + ), 152 + 153 + TP_fast_assign( 154 + __assign_str(type, cdev->type); 155 + __entry->freq = freq; 156 + __entry->load = (100 * status->busy_time) / status->total_time; 157 + __entry->dynamic_power = dynamic_power; 158 + __entry->static_power = static_power; 159 + ), 160 + 161 + TP_printk("type=%s freq=%lu load=%u dynamic_power=%u static_power=%u", 162 + __get_str(type), __entry->freq, 163 + __entry->load, __entry->dynamic_power, __entry->static_power) 164 + ); 165 + 166 + TRACE_EVENT(thermal_power_devfreq_limit, 167 + TP_PROTO(struct thermal_cooling_device *cdev, unsigned long freq, 168 + unsigned long cdev_state, u32 power), 169 + 170 + TP_ARGS(cdev, freq, cdev_state, power), 171 + 172 + TP_STRUCT__entry( 173 + __string(type, cdev->type) 174 + __field(unsigned int, freq ) 175 + __field(unsigned long, cdev_state) 176 + __field(u32, power ) 177 + ), 178 + 179 + TP_fast_assign( 180 + __assign_str(type, cdev->type); 181 + __entry->freq = freq; 182 + __entry->cdev_state = cdev_state; 183 + __entry->power = power; 184 + ), 185 + 186 + TP_printk("type=%s freq=%u cdev_state=%lu power=%u", 187 + __get_str(type), __entry->freq, __entry->cdev_state, 188 + __entry->power) 189 + ); 139 190 #endif /* _TRACE_THERMAL_H */ 140 191 141 192 /* This part must be outside protection */