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

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux

Pull thermal updates from Zhang Rui:

- Implement generic devfreq cooling mechanism through frequency
reduction for devices using devfreq. From Ørjan Eide and Javi
Merino.

- Introduce OMAP3 support on TI SoC thermal driver. From Pavel Mack
and Eduardo Valentin.

- A bounch of small fixes on devfreq_cooling, Exynos, IMX, Armada, and
Rockchip thermal drivers.

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (24 commits)
thermal: exynos: Directly return 0 instead of using local ret variable
thermal: exynos: Remove unneeded semicolon
thermal: exynos: Use IS_ERR() because regulator cannot be NULL
thermal: exynos: Fix first temperature read after registering sensor
thermal: exynos: Fix unbalanced regulator disable on probe failure
devfreq_cooling: return on allocation failure
thermal: rockchip: support the sleep pinctrl state to avoid glitches in s2r
dt-bindings: rockchip-thermal: Add the pinctrl states in this document
thermal: devfreq_cooling: Make power a u64
thermal: devfreq_cooling: use a thermal_cooling_device for register and unregister
thermal: underflow bug in imx_set_trip_temp()
thermal: armada: Fix possible overflow in the Armada 380 thermal sensor formula
thermal: imx: register irq handler later in probe
thermal: rockhip: fix setting thermal shutdown polarity
thermal: rockchip: fix handling of invalid readings
devfreq_cooling: add trace information
thermal: Add devfreq cooling
PM / OPP: get the voltage for all OPPs
tools/thermal: tmon: use pkg-config also for CFLAGS
linux/thermal.h: rename KELVIN_TO_CELSIUS to DECI_KELVIN_TO_CELSIUS
...

+1065 -86
+9 -2
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
··· 12 12 - resets : Must contain an entry for each entry in reset-names. 13 13 See ../reset/reset.txt for details. 14 14 - reset-names : Must include the name "tsadc-apb". 15 + - pinctrl-names : The pin control state names; 16 + - pinctrl-0 : The "init" pinctrl state, it will be set before device probe. 17 + - pinctrl-1 : The "default" pinctrl state, it will be set after reset the 18 + TSADC controller. 19 + - pinctrl-2 : The "sleep" pinctrl state, it will be in for suspend. 15 20 - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description. 16 21 - rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value. 17 22 - rockchip,hw-tshut-mode : The hardware-controlled shutdown mode 0:CRU 1:GPIO. ··· 32 27 clock-names = "tsadc", "apb_pclk"; 33 28 resets = <&cru SRST_TSADC>; 34 29 reset-names = "tsadc-apb"; 35 - pinctrl-names = "default"; 36 - pinctrl-0 = <&otp_out>; 30 + pinctrl-names = "init", "default", "sleep"; 31 + pinctrl-0 = <&otp_gpio>; 32 + pinctrl-1 = <&otp_out>; 33 + pinctrl-2 = <&otp_gpio>; 37 34 #thermal-sensor-cells = <1>; 38 35 rockchip,hw-tshut-temp = <95000>; 39 36 rockchip,hw-tshut-mode = <0>;
+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>;
+6 -6
drivers/acpi/thermal.c
··· 315 315 if (crt == -1) { 316 316 tz->trips.critical.flags.valid = 0; 317 317 } else if (crt > 0) { 318 - unsigned long crt_k = CELSIUS_TO_KELVIN(crt); 318 + unsigned long crt_k = CELSIUS_TO_DECI_KELVIN(crt); 319 319 /* 320 320 * Allow override critical threshold 321 321 */ ··· 351 351 if (psv == -1) { 352 352 status = AE_SUPPORT; 353 353 } else if (psv > 0) { 354 - tmp = CELSIUS_TO_KELVIN(psv); 354 + tmp = CELSIUS_TO_DECI_KELVIN(psv); 355 355 status = AE_OK; 356 356 } else { 357 357 status = acpi_evaluate_integer(tz->device->handle, ··· 431 431 break; 432 432 if (i == 1) 433 433 tz->trips.active[0].temperature = 434 - CELSIUS_TO_KELVIN(act); 434 + CELSIUS_TO_DECI_KELVIN(act); 435 435 else 436 436 /* 437 437 * Don't allow override higher than ··· 439 439 */ 440 440 tz->trips.active[i - 1].temperature = 441 441 (tz->trips.active[i - 2].temperature < 442 - CELSIUS_TO_KELVIN(act) ? 442 + CELSIUS_TO_DECI_KELVIN(act) ? 443 443 tz->trips.active[i - 2].temperature : 444 - CELSIUS_TO_KELVIN(act)); 444 + CELSIUS_TO_DECI_KELVIN(act)); 445 445 break; 446 446 } else { 447 447 tz->trips.active[i].temperature = tmp; ··· 1105 1105 INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn); 1106 1106 1107 1107 pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), 1108 - acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature)); 1108 + acpi_device_bid(device), DECI_KELVIN_TO_CELSIUS(tz->temperature)); 1109 1109 goto end; 1110 1110 1111 1111 free_memory:
+2 -2
drivers/base/power/opp/core.c
··· 100 100 } 101 101 102 102 /** 103 - * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an available opp 103 + * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp 104 104 * @opp: opp for which voltage has to be returned for 105 105 * 106 106 * Return: voltage in micro volt corresponding to the opp, else ··· 122 122 opp_rcu_lockdep_assert(); 123 123 124 124 tmp_opp = rcu_dereference(opp); 125 - if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available) 125 + if (IS_ERR_OR_NULL(tmp_opp)) 126 126 pr_err("%s: Invalid parameters\n", __func__); 127 127 else 128 128 v = tmp_opp->u_volt;
+1 -1
drivers/platform/x86/asus-wmi.c
··· 1320 1320 if (err < 0) 1321 1321 return err; 1322 1322 1323 - value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000; 1323 + value = DECI_KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000; 1324 1324 1325 1325 return sprintf(buf, "%d\n", value); 1326 1326 }
+4 -4
drivers/platform/x86/intel_menlow.c
··· 315 315 316 316 result = sensor_get_auxtrip(attr->handle, 0, &value); 317 317 318 - return result ? result : sprintf(buf, "%lu", KELVIN_TO_CELSIUS(value)); 318 + return result ? result : sprintf(buf, "%lu", DECI_KELVIN_TO_CELSIUS(value)); 319 319 } 320 320 321 321 static ssize_t aux1_show(struct device *dev, ··· 327 327 328 328 result = sensor_get_auxtrip(attr->handle, 1, &value); 329 329 330 - return result ? result : sprintf(buf, "%lu", KELVIN_TO_CELSIUS(value)); 330 + return result ? result : sprintf(buf, "%lu", DECI_KELVIN_TO_CELSIUS(value)); 331 331 } 332 332 333 333 static ssize_t aux0_store(struct device *dev, ··· 345 345 if (value < 0) 346 346 return -EINVAL; 347 347 348 - result = sensor_set_auxtrip(attr->handle, 0, CELSIUS_TO_KELVIN(value)); 348 + result = sensor_set_auxtrip(attr->handle, 0, CELSIUS_TO_DECI_KELVIN(value)); 349 349 return result ? result : count; 350 350 } 351 351 ··· 364 364 if (value < 0) 365 365 return -EINVAL; 366 366 367 - result = sensor_set_auxtrip(attr->handle, 1, CELSIUS_TO_KELVIN(value)); 367 + result = sensor_set_auxtrip(attr->handle, 1, CELSIUS_TO_DECI_KELVIN(value)); 368 368 return result ? result : count; 369 369 } 370 370
+17
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 ··· 289 275 tristate "X86 package temperature thermal driver" 290 276 depends on X86_THERMAL_VECTOR 291 277 select THERMAL_GOV_USER_SPACE 278 + select THERMAL_WRITABLE_TRIPS 292 279 default m 293 280 help 294 281 Enable this to register CPU digital sensor for package temperature as ··· 311 296 tristate "Intel SoCs DTS thermal driver" 312 297 depends on X86 313 298 select INTEL_SOC_DTS_IOSF_CORE 299 + select THERMAL_WRITABLE_TRIPS 314 300 help 315 301 Enable this to register Intel SoCs (e.g. Bay Trail) platform digital 316 302 temperature sensor (DTS). These SoCs have two additional DTSs in ··· 338 322 select ACPI_THERMAL_REL 339 323 select ACPI_FAN 340 324 select INTEL_SOC_DTS_IOSF_CORE 325 + select THERMAL_WRITABLE_TRIPS 341 326 help 342 327 Newer laptops and tablets that use ACPI may have thermal sensors and 343 328 other devices with thermal control capabilities outside the core
+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
+3 -5
drivers/thermal/cpu_cooling.c
··· 591 591 if (trace_thermal_power_cpu_get_power_enabled()) { 592 592 u32 ncpus = cpumask_weight(&cpufreq_device->allowed_cpus); 593 593 594 - load_cpu = devm_kcalloc(&cdev->device, ncpus, sizeof(*load_cpu), 595 - GFP_KERNEL); 594 + load_cpu = kcalloc(ncpus, sizeof(*load_cpu), GFP_KERNEL); 596 595 } 597 596 598 597 for_each_cpu(cpu, &cpufreq_device->allowed_cpus) { ··· 614 615 dynamic_power = get_dynamic_power(cpufreq_device, freq); 615 616 ret = get_static_power(cpufreq_device, tz, freq, &static_power); 616 617 if (ret) { 617 - if (load_cpu) 618 - devm_kfree(&cdev->device, load_cpu); 618 + kfree(load_cpu); 619 619 return ret; 620 620 } 621 621 ··· 623 625 &cpufreq_device->allowed_cpus, 624 626 freq, load_cpu, i, dynamic_power, static_power); 625 627 626 - devm_kfree(&cdev->device, load_cpu); 628 + kfree(load_cpu); 627 629 } 628 630 629 631 *power = static_power + dynamic_power;
+573
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 + u64 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 + return -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 thermal_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 cdev; 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 thermal_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 thermal_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 thermal_cooling_device *cdev) 558 + { 559 + struct devfreq_cooling_device *dfc; 560 + 561 + if (!cdev) 562 + return; 563 + 564 + dfc = cdev->devdata; 565 + 566 + thermal_cooling_device_unregister(dfc->cdev); 567 + release_idr(&devfreq_idr, dfc->id); 568 + kfree(dfc->power_table); 569 + kfree(dfc->freq_table); 570 + 571 + kfree(dfc); 572 + } 573 + 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;
+21 -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) ··· 638 642 clk_disable(thermal->pclk); 639 643 clk_disable(thermal->clk); 640 644 645 + pinctrl_pm_select_sleep_state(dev); 646 + 641 647 return 0; 642 648 } 643 649 ··· 675 677 676 678 for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++) 677 679 rockchip_thermal_toggle_sensor(&thermal->sensors[i], true); 680 + 681 + pinctrl_pm_select_default_state(dev); 678 682 679 683 return 0; 680 684 }
+38 -30
drivers/thermal/samsung/exynos_tmu.c
··· 548 548 default: 549 549 pdata->cal_type = TYPE_ONE_POINT_TRIMMING; 550 550 break; 551 - }; 551 + } 552 552 553 553 dev_info(&pdev->dev, "Calibration type is %d-point calibration\n", 554 554 cal_type ? 2 : 1); ··· 608 608 { 609 609 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 610 610 unsigned int trim_info = 0, con, rising_threshold; 611 - int ret = 0, threshold_code; 611 + int threshold_code; 612 612 int crit_temp = 0; 613 613 614 614 /* ··· 651 651 /* Clear the PMIN in the common TMU register */ 652 652 if (!data->id) 653 653 writel(0, data->base_second + EXYNOS5440_TMU_PMIN); 654 - return ret; 654 + 655 + return 0; 655 656 } 656 657 657 658 static int exynos7_tmu_initialize(struct platform_device *pdev) ··· 1169 1168 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 1170 1169 struct exynos_tmu_platform_data *pdata; 1171 1170 struct resource res; 1172 - int ret; 1173 1171 1174 1172 if (!data || !pdev->dev.of_node) 1175 1173 return -ENODEV; 1176 - 1177 - /* 1178 - * Try enabling the regulator if found 1179 - * TODO: Add regulator as an SOC feature, so that regulator enable 1180 - * is a compulsory call. 1181 - */ 1182 - data->regulator = devm_regulator_get(&pdev->dev, "vtmu"); 1183 - if (!IS_ERR(data->regulator)) { 1184 - ret = regulator_enable(data->regulator); 1185 - if (ret) { 1186 - dev_err(&pdev->dev, "failed to enable vtmu\n"); 1187 - return ret; 1188 - } 1189 - } else { 1190 - dev_info(&pdev->dev, "Regulator node (vtmu) not found\n"); 1191 - } 1192 1174 1193 1175 data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl"); 1194 1176 if (data->id < 0) ··· 1290 1306 platform_set_drvdata(pdev, data); 1291 1307 mutex_init(&data->lock); 1292 1308 1293 - data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data, 1294 - &exynos_sensor_ops); 1295 - if (IS_ERR(data->tzd)) { 1296 - pr_err("thermal: tz: %p ERROR\n", data->tzd); 1297 - return PTR_ERR(data->tzd); 1309 + /* 1310 + * Try enabling the regulator if found 1311 + * TODO: Add regulator as an SOC feature, so that regulator enable 1312 + * is a compulsory call. 1313 + */ 1314 + data->regulator = devm_regulator_get(&pdev->dev, "vtmu"); 1315 + if (!IS_ERR(data->regulator)) { 1316 + ret = regulator_enable(data->regulator); 1317 + if (ret) { 1318 + dev_err(&pdev->dev, "failed to enable vtmu\n"); 1319 + return ret; 1320 + } 1321 + } else { 1322 + dev_info(&pdev->dev, "Regulator node (vtmu) not found\n"); 1298 1323 } 1324 + 1299 1325 ret = exynos_map_dt_data(pdev); 1300 1326 if (ret) 1301 1327 goto err_sensor; ··· 1357 1363 break; 1358 1364 default: 1359 1365 break; 1360 - }; 1366 + } 1367 + 1368 + /* 1369 + * data->tzd must be registered before calling exynos_tmu_initialize(), 1370 + * requesting irq and calling exynos_tmu_control(). 1371 + */ 1372 + data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data, 1373 + &exynos_sensor_ops); 1374 + if (IS_ERR(data->tzd)) { 1375 + ret = PTR_ERR(data->tzd); 1376 + dev_err(&pdev->dev, "Failed to register sensor: %d\n", ret); 1377 + goto err_sclk; 1378 + } 1361 1379 1362 1380 ret = exynos_tmu_initialize(pdev); 1363 1381 if (ret) { 1364 1382 dev_err(&pdev->dev, "Failed to initialize TMU\n"); 1365 - goto err_sclk; 1383 + goto err_thermal; 1366 1384 } 1367 1385 1368 1386 ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq, 1369 1387 IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data); 1370 1388 if (ret) { 1371 1389 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq); 1372 - goto err_sclk; 1390 + goto err_thermal; 1373 1391 } 1374 1392 1375 1393 exynos_tmu_control(pdev, true); 1376 1394 return 0; 1395 + 1396 + err_thermal: 1397 + thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd); 1377 1398 err_sclk: 1378 1399 clk_disable_unprepare(data->sclk); 1379 1400 err_clk: ··· 1397 1388 if (!IS_ERR(data->clk_sec)) 1398 1389 clk_unprepare(data->clk_sec); 1399 1390 err_sensor: 1400 - if (!IS_ERR_OR_NULL(data->regulator)) 1391 + if (!IS_ERR(data->regulator)) 1401 1392 regulator_disable(data->regulator); 1402 - thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd); 1403 1393 1404 1394 return ret; 1405 1395 }
+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 thermal_cooling_device * 47 + of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, 48 + struct devfreq_cooling_power *dfc_power); 49 + struct thermal_cooling_device * 50 + of_devfreq_cooling_register(struct device_node *np, struct devfreq *df); 51 + struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df); 52 + void devfreq_cooling_unregister(struct thermal_cooling_device *dfc); 53 + 54 + #else /* !CONFIG_DEVFREQ_THERMAL */ 55 + 56 + struct thermal_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 thermal_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 thermal_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 thermal_cooling_device *dfc) 77 + { 78 + } 79 + 80 + #endif /* CONFIG_DEVFREQ_THERMAL */ 81 + #endif /* __DEVFREQ_COOLING_H__ */
+5 -3
include/linux/thermal.h
··· 44 44 #define THERMAL_WEIGHT_DEFAULT 0 45 45 46 46 /* Unit conversion macros */ 47 - #define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \ 48 - ((long)t-2732+5)/10 : ((long)t-2732-5)/10) 49 - #define CELSIUS_TO_KELVIN(t) ((t)*10+2732) 47 + #define DECI_KELVIN_TO_CELSIUS(t) ({ \ 48 + long _t = (t); \ 49 + ((_t-2732 >= 0) ? (_t-2732+5)/10 : (_t-2732-5)/10); \ 50 + }) 51 + #define CELSIUS_TO_DECI_KELVIN(t) ((t)*10+2732) 50 52 #define DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, off) (((t) - (off)) * 100) 51 53 #define DECI_KELVIN_TO_MILLICELSIUS(t) DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, 2732) 52 54 #define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off))
+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 */
+3
tools/thermal/tmon/Makefile
··· 22 22 pkg-config --libs $(STATIC) panel ncurses 2> /dev/null || \ 23 23 echo -lpanel -lncurses) 24 24 25 + CFLAGS += $(shell pkg-config --cflags $(STATIC) panelw ncursesw 2> /dev/null || \ 26 + pkg-config --cflags $(STATIC) panel ncurses 2> /dev/null) 27 + 25 28 OBJS = tmon.o tui.o sysfs.o pid.o 26 29 OBJS += 27 30