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

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull thermal management updates from Zhang Rui:

- Fix a problem where orderly_shutdown() is called for multiple times
due to multiple critical overheating events raised in a short period
by platform thermal driver. (Keerthy)

- Introduce a backup thermal shutdown mechanism, which invokes
kernel_power_off()/emergency_restart() directly, after
orderly_shutdown() being issued for certain amount of time(specified
via Kconfig). This is useful in certain conditions that userspace may
be unable to power off the system in a clean manner and leaves the
system in a critical state, like in the middle of driver probing
phase. (Keerthy)

- Introduce a new interface in thermal devfreq_cooling code so that the
driver can provide more precise data regarding actual power to the
thermal governor every time the power budget is calculated. (Lukasz
Luba)

- Introduce BCM 2835 soc thermal driver and northstar thermal driver,
within a new sub-folder. (Rafał Miłecki)

- Introduce DA9062/61 thermal driver. (Steve Twiss)

- Remove non-DT booting on TI-SoC driver. Also add support to fetching
coefficients from DT. (Keerthy)

- Refactorf RCAR Gen3 thermal driver. (Niklas Söderlund)

- Small fix on MTK and intel-soc-dts thermal driver. (Dawei Chien,
Brian Bian)

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (25 commits)
thermal: core: Add a back up thermal shutdown mechanism
thermal: core: Allow orderly_poweroff to be called only once
Thermal: Intel SoC DTS: Change interrupt request behavior
trace: thermal: add another parameter 'power' to the tracing function
thermal: devfreq_cooling: add new interface for direct power read
thermal: devfreq_cooling: refactor code and add get_voltage function
thermal: mt8173: minor mtk_thermal.c cleanups
thermal: bcm2835: move to the broadcom subdirectory
thermal: broadcom: ns: specify myself as MODULE_AUTHOR
thermal: da9062/61: Thermal junction temperature monitoring driver
Documentation: devicetree: thermal: da9062/61 TJUNC temperature binding
thermal: broadcom: add Northstar thermal driver
dt-bindings: thermal: add support for Broadcom's Northstar thermal
thermal: bcm2835: add thermal driver for bcm2835 SoC
dt-bindings: Add thermal zone to bcm2835-thermal example
thermal: rcar_gen3_thermal: add suspend and resume support
thermal: rcar_gen3_thermal: store device match data in private structure
thermal: rcar_gen3_thermal: enable hardware interrupts for trip points
thermal: rcar_gen3_thermal: record and check number of TSCs found
thermal: rcar_gen3_thermal: check that TSC exists before memory allocation
...

+1305 -266
+28 -4
Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
··· 3 3 Required parameters: 4 4 ------------------- 5 5 6 - compatible: should be one of: "brcm,bcm2835-thermal", 7 - "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal" 8 - reg: Address range of the thermal registers. 9 - clocks: Phandle of the clock used by the thermal sensor. 6 + compatible: should be one of: "brcm,bcm2835-thermal", 7 + "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal" 8 + reg: Address range of the thermal registers. 9 + clocks: Phandle of the clock used by the thermal sensor. 10 + #thermal-sensor-cells: should be 0 (see thermal.txt) 10 11 11 12 Example: 13 + 14 + thermal-zones { 15 + cpu_thermal: cpu-thermal { 16 + polling-delay-passive = <0>; 17 + polling-delay = <1000>; 18 + 19 + thermal-sensors = <&thermal>; 20 + 21 + trips { 22 + cpu-crit { 23 + temperature = <80000>; 24 + hysteresis = <0>; 25 + type = "critical"; 26 + }; 27 + }; 28 + 29 + coefficients = <(-538) 407000>; 30 + 31 + cooling-maps { 32 + }; 33 + }; 34 + }; 12 35 13 36 thermal: thermal@7e212000 { 14 37 compatible = "brcm,bcm2835-thermal"; 15 38 reg = <0x7e212000 0x8>; 16 39 clocks = <&clocks BCM2835_CLOCK_TSENS>; 40 + #thermal-sensor-cells = <0>; 17 41 };
+37
Documentation/devicetree/bindings/thermal/brcm,ns-thermal
··· 1 + * Broadcom Northstar Thermal 2 + 3 + This binding describes thermal sensor that is part of Northstar's DMU (Device 4 + Management Unit). 5 + 6 + Required properties: 7 + - compatible : Must be "brcm,ns-thermal" 8 + - reg : iomem address range of PVTMON registers 9 + - #thermal-sensor-cells : Should be <0> 10 + 11 + Example: 12 + 13 + thermal: thermal@1800c2c0 { 14 + compatible = "brcm,ns-thermal"; 15 + reg = <0x1800c2c0 0x10>; 16 + #thermal-sensor-cells = <0>; 17 + }; 18 + 19 + thermal-zones { 20 + cpu_thermal: cpu-thermal { 21 + polling-delay-passive = <0>; 22 + polling-delay = <1000>; 23 + coefficients = <(-556) 418000>; 24 + thermal-sensors = <&thermal>; 25 + 26 + trips { 27 + cpu-crit { 28 + temperature = <125000>; 29 + hysteresis = <0>; 30 + type = "critical"; 31 + }; 32 + }; 33 + 34 + cooling-maps { 35 + }; 36 + }; 37 + };
+36
Documentation/devicetree/bindings/thermal/da9062-thermal.txt
··· 1 + * Dialog DA9062/61 TJUNC Thermal Module 2 + 3 + This module is part of the DA9061/DA9062. For more details about entire 4 + DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt 5 + 6 + Junction temperature thermal module uses an interrupt signal to identify 7 + high THERMAL_TRIP_HOT temperatures for the PMIC device. 8 + 9 + Required properties: 10 + 11 + - compatible: should be one of the following valid compatible string lines: 12 + "dlg,da9061-thermal", "dlg,da9062-thermal" 13 + "dlg,da9062-thermal" 14 + 15 + Optional properties: 16 + 17 + - polling-delay-passive : Specify the polling period, measured in 18 + milliseconds, between thermal zone device update checks. 19 + 20 + Example: DA9062 21 + 22 + pmic0: da9062@58 { 23 + thermal { 24 + compatible = "dlg,da9062-thermal"; 25 + polling-delay-passive = <3000>; 26 + }; 27 + }; 28 + 29 + Example: DA9061 using a fall-back compatible for the DA9062 onkey driver 30 + 31 + pmic0: da9061@58 { 32 + thermal { 33 + compatible = "dlg,da9061-thermal", "dlg,da9062-thermal"; 34 + polling-delay-passive = <3000>; 35 + }; 36 + };
+21
Documentation/thermal/sysfs-api.txt
··· 582 582 This function serves as an arbitrator to set the state of a cooling 583 583 device. It sets the cooling device to the deepest cooling state if 584 584 possible. 585 + 586 + 6. thermal_emergency_poweroff: 587 + 588 + On an event of critical trip temperature crossing. Thermal framework 589 + allows the system to shutdown gracefully by calling orderly_poweroff(). 590 + In the event of a failure of orderly_poweroff() to shut down the system 591 + we are in danger of keeping the system alive at undesirably high 592 + temperatures. To mitigate this high risk scenario we program a work 593 + queue to fire after a pre-determined number of seconds to start 594 + an emergency shutdown of the device using the kernel_power_off() 595 + function. In case kernel_power_off() fails then finally 596 + emergency_restart() is called in the worst case. 597 + 598 + The delay should be carefully profiled so as to give adequate time for 599 + orderly_poweroff(). In case of failure of an orderly_poweroff() the 600 + emergency poweroff kicks in after the delay has elapsed and shuts down 601 + the system. 602 + 603 + If set to 0 emergency poweroff will not be supported. So a carefully 604 + profiled non-zero positive value is a must for emergerncy poweroff to be 605 + triggered.
+32
drivers/thermal/Kconfig
··· 15 15 16 16 if THERMAL 17 17 18 + config THERMAL_EMERGENCY_POWEROFF_DELAY_MS 19 + int "Emergency poweroff delay in milli-seconds" 20 + depends on THERMAL 21 + default 0 22 + help 23 + Thermal subsystem will issue a graceful shutdown when 24 + critical temperatures are reached using orderly_poweroff(). In 25 + case of failure of an orderly_poweroff(), the thermal emergency 26 + poweroff kicks in after a delay has elapsed and shuts down the system. 27 + This config is number of milliseconds to delay before emergency 28 + poweroff kicks in. Similarly to the critical trip point, 29 + the delay should be carefully profiled so as to give adequate 30 + time for orderly_poweroff() to finish on regular execution. 31 + If set to 0 emergency poweroff will not be supported. 32 + 33 + In doubt, leave as 0. 34 + 18 35 config THERMAL_HWMON 19 36 bool 20 37 prompt "Expose thermal sensors as hwmon device" ··· 308 291 Enable this option if you want to have support for thermal management 309 292 controller present in Armada 370 and Armada XP SoC. 310 293 294 + config DA9062_THERMAL 295 + tristate "DA9062/DA9061 Dialog Semiconductor thermal driver" 296 + depends on MFD_DA9062 || COMPILE_TEST 297 + depends on OF 298 + help 299 + Enable this for the Dialog Semiconductor thermal sensor driver. 300 + This will report PMIC junction over-temperature for one thermal trip 301 + zone. 302 + Compatible with the DA9062 and DA9061 PMICs. 303 + 311 304 config INTEL_POWERCLAMP 312 305 tristate "Intel PowerClamp idle injection driver" 313 306 depends on THERMAL ··· 406 379 help 407 380 Enable this option if you want to have support for thermal management 408 381 controller present in Mediatek SoCs 382 + 383 + menu "Broadcom thermal drivers" 384 + depends on ARCH_BCM || COMPILE_TEST 385 + source "drivers/thermal/broadcom/Kconfig" 386 + endmenu 409 387 410 388 menu "Texas Instruments thermal drivers" 411 389 depends on ARCH_HAS_BANDGAP || COMPILE_TEST
+2
drivers/thermal/Makefile
··· 27 27 thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o 28 28 29 29 # platform thermal drivers 30 + obj-y += broadcom/ 30 31 obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o 31 32 obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 32 33 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o ··· 42 41 obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o 43 42 obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o 44 43 obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o 44 + obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o 45 45 obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 46 46 obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o 47 47 obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
+16
drivers/thermal/broadcom/Kconfig
··· 1 + config BCM2835_THERMAL 2 + tristate "Thermal sensors on bcm2835 SoC" 3 + depends on ARCH_BCM2835 || COMPILE_TEST 4 + depends on HAS_IOMEM 5 + depends on THERMAL_OF 6 + help 7 + Support for thermal sensors on Broadcom bcm2835 SoCs. 8 + 9 + config BCM_NS_THERMAL 10 + tristate "Northstar thermal driver" 11 + depends on ARCH_BCM_IPROC || COMPILE_TEST 12 + help 13 + Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081, 14 + BCM4709 and BCM47094. It contains DMU (Device Management Unit) block 15 + with a thermal sensor that allows checking CPU temperature. This 16 + driver provides support for it.
+2
drivers/thermal/broadcom/Makefile
··· 1 + obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o 2 + obj-$(CONFIG_BCM_NS_THERMAL) += ns-thermal.o
+314
drivers/thermal/broadcom/bcm2835_thermal.c
··· 1 + /* 2 + * Driver for Broadcom BCM2835 SoC temperature sensor 3 + * 4 + * Copyright (C) 2016 Martin Sperl 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 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 + 17 + #include <linux/clk.h> 18 + #include <linux/debugfs.h> 19 + #include <linux/device.h> 20 + #include <linux/err.h> 21 + #include <linux/io.h> 22 + #include <linux/kernel.h> 23 + #include <linux/module.h> 24 + #include <linux/of.h> 25 + #include <linux/of_address.h> 26 + #include <linux/of_device.h> 27 + #include <linux/platform_device.h> 28 + #include <linux/thermal.h> 29 + 30 + #define BCM2835_TS_TSENSCTL 0x00 31 + #define BCM2835_TS_TSENSSTAT 0x04 32 + 33 + #define BCM2835_TS_TSENSCTL_PRWDW BIT(0) 34 + #define BCM2835_TS_TSENSCTL_RSTB BIT(1) 35 + 36 + /* 37 + * bandgap reference voltage in 6 mV increments 38 + * 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV 39 + */ 40 + #define BCM2835_TS_TSENSCTL_CTRL_BITS 3 41 + #define BCM2835_TS_TSENSCTL_CTRL_SHIFT 2 42 + #define BCM2835_TS_TSENSCTL_CTRL_MASK \ 43 + GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS + \ 44 + BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \ 45 + BCM2835_TS_TSENSCTL_CTRL_SHIFT) 46 + #define BCM2835_TS_TSENSCTL_CTRL_DEFAULT 1 47 + #define BCM2835_TS_TSENSCTL_EN_INT BIT(5) 48 + #define BCM2835_TS_TSENSCTL_DIRECT BIT(6) 49 + #define BCM2835_TS_TSENSCTL_CLR_INT BIT(7) 50 + #define BCM2835_TS_TSENSCTL_THOLD_SHIFT 8 51 + #define BCM2835_TS_TSENSCTL_THOLD_BITS 10 52 + #define BCM2835_TS_TSENSCTL_THOLD_MASK \ 53 + GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS + \ 54 + BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \ 55 + BCM2835_TS_TSENSCTL_THOLD_SHIFT) 56 + /* 57 + * time how long the block to be asserted in reset 58 + * which based on a clock counter (TSENS clock assumed) 59 + */ 60 + #define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT 18 61 + #define BCM2835_TS_TSENSCTL_RSTDELAY_BITS 8 62 + #define BCM2835_TS_TSENSCTL_REGULEN BIT(26) 63 + 64 + #define BCM2835_TS_TSENSSTAT_DATA_BITS 10 65 + #define BCM2835_TS_TSENSSTAT_DATA_SHIFT 0 66 + #define BCM2835_TS_TSENSSTAT_DATA_MASK \ 67 + GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS + \ 68 + BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \ 69 + BCM2835_TS_TSENSSTAT_DATA_SHIFT) 70 + #define BCM2835_TS_TSENSSTAT_VALID BIT(10) 71 + #define BCM2835_TS_TSENSSTAT_INTERRUPT BIT(11) 72 + 73 + struct bcm2835_thermal_data { 74 + struct thermal_zone_device *tz; 75 + void __iomem *regs; 76 + struct clk *clk; 77 + struct dentry *debugfsdir; 78 + }; 79 + 80 + static int bcm2835_thermal_adc2temp(u32 adc, int offset, int slope) 81 + { 82 + return offset + slope * adc; 83 + } 84 + 85 + static int bcm2835_thermal_temp2adc(int temp, int offset, int slope) 86 + { 87 + temp -= offset; 88 + temp /= slope; 89 + 90 + if (temp < 0) 91 + temp = 0; 92 + if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS)) 93 + temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1; 94 + 95 + return temp; 96 + } 97 + 98 + static int bcm2835_thermal_get_temp(void *d, int *temp) 99 + { 100 + struct bcm2835_thermal_data *data = d; 101 + u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT); 102 + 103 + if (!(val & BCM2835_TS_TSENSSTAT_VALID)) 104 + return -EIO; 105 + 106 + val &= BCM2835_TS_TSENSSTAT_DATA_MASK; 107 + 108 + *temp = bcm2835_thermal_adc2temp( 109 + val, 110 + thermal_zone_get_offset(data->tz), 111 + thermal_zone_get_slope(data->tz)); 112 + 113 + return 0; 114 + } 115 + 116 + static const struct debugfs_reg32 bcm2835_thermal_regs[] = { 117 + { 118 + .name = "ctl", 119 + .offset = 0 120 + }, 121 + { 122 + .name = "stat", 123 + .offset = 4 124 + } 125 + }; 126 + 127 + static void bcm2835_thermal_debugfs(struct platform_device *pdev) 128 + { 129 + struct thermal_zone_device *tz = platform_get_drvdata(pdev); 130 + struct bcm2835_thermal_data *data = tz->devdata; 131 + struct debugfs_regset32 *regset; 132 + 133 + data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL); 134 + if (!data->debugfsdir) 135 + return; 136 + 137 + regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL); 138 + if (!regset) 139 + return; 140 + 141 + regset->regs = bcm2835_thermal_regs; 142 + regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs); 143 + regset->base = data->regs; 144 + 145 + debugfs_create_regset32("regset", 0444, data->debugfsdir, regset); 146 + } 147 + 148 + static struct thermal_zone_of_device_ops bcm2835_thermal_ops = { 149 + .get_temp = bcm2835_thermal_get_temp, 150 + }; 151 + 152 + /* 153 + * Note: as per Raspberry Foundation FAQ 154 + * (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature) 155 + * the recommended temperature range for the SoC -40C to +85C 156 + * so the trip limit is set to 80C. 157 + * this applies to all the BCM283X SoC 158 + */ 159 + 160 + static const struct of_device_id bcm2835_thermal_of_match_table[] = { 161 + { 162 + .compatible = "brcm,bcm2835-thermal", 163 + }, 164 + { 165 + .compatible = "brcm,bcm2836-thermal", 166 + }, 167 + { 168 + .compatible = "brcm,bcm2837-thermal", 169 + }, 170 + {}, 171 + }; 172 + MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table); 173 + 174 + static int bcm2835_thermal_probe(struct platform_device *pdev) 175 + { 176 + const struct of_device_id *match; 177 + struct thermal_zone_device *tz; 178 + struct bcm2835_thermal_data *data; 179 + struct resource *res; 180 + int err = 0; 181 + u32 val; 182 + unsigned long rate; 183 + 184 + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 185 + if (!data) 186 + return -ENOMEM; 187 + 188 + match = of_match_device(bcm2835_thermal_of_match_table, 189 + &pdev->dev); 190 + if (!match) 191 + return -EINVAL; 192 + 193 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 194 + data->regs = devm_ioremap_resource(&pdev->dev, res); 195 + if (IS_ERR(data->regs)) { 196 + err = PTR_ERR(data->regs); 197 + dev_err(&pdev->dev, "Could not get registers: %d\n", err); 198 + return err; 199 + } 200 + 201 + data->clk = devm_clk_get(&pdev->dev, NULL); 202 + if (IS_ERR(data->clk)) { 203 + err = PTR_ERR(data->clk); 204 + if (err != -EPROBE_DEFER) 205 + dev_err(&pdev->dev, "Could not get clk: %d\n", err); 206 + return err; 207 + } 208 + 209 + err = clk_prepare_enable(data->clk); 210 + if (err) 211 + return err; 212 + 213 + rate = clk_get_rate(data->clk); 214 + if ((rate < 1920000) || (rate > 5000000)) 215 + dev_warn(&pdev->dev, 216 + "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n", 217 + data->clk, data->clk); 218 + 219 + /* register of thermal sensor and get info from DT */ 220 + tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data, 221 + &bcm2835_thermal_ops); 222 + if (IS_ERR(tz)) { 223 + err = PTR_ERR(tz); 224 + dev_err(&pdev->dev, 225 + "Failed to register the thermal device: %d\n", 226 + err); 227 + goto err_clk; 228 + } 229 + 230 + /* 231 + * right now the FW does set up the HW-block, so we are not 232 + * touching the configuration registers. 233 + * But if the HW is not enabled, then set it up 234 + * using "sane" values used by the firmware right now. 235 + */ 236 + val = readl(data->regs + BCM2835_TS_TSENSCTL); 237 + if (!(val & BCM2835_TS_TSENSCTL_RSTB)) { 238 + int trip_temp, offset, slope; 239 + 240 + slope = thermal_zone_get_slope(tz); 241 + offset = thermal_zone_get_offset(tz); 242 + /* 243 + * For now we deal only with critical, otherwise 244 + * would need to iterate 245 + */ 246 + err = tz->ops->get_trip_temp(tz, 0, &trip_temp); 247 + if (err < 0) { 248 + err = PTR_ERR(tz); 249 + dev_err(&pdev->dev, 250 + "Not able to read trip_temp: %d\n", 251 + err); 252 + goto err_tz; 253 + } 254 + 255 + /* set bandgap reference voltage and enable voltage regulator */ 256 + val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT << 257 + BCM2835_TS_TSENSCTL_CTRL_SHIFT) | 258 + BCM2835_TS_TSENSCTL_REGULEN; 259 + 260 + /* use the recommended reset duration */ 261 + val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT); 262 + 263 + /* trip_adc value from info */ 264 + val |= bcm2835_thermal_temp2adc(trip_temp, 265 + offset, 266 + slope) 267 + << BCM2835_TS_TSENSCTL_THOLD_SHIFT; 268 + 269 + /* write the value back to the register as 2 steps */ 270 + writel(val, data->regs + BCM2835_TS_TSENSCTL); 271 + val |= BCM2835_TS_TSENSCTL_RSTB; 272 + writel(val, data->regs + BCM2835_TS_TSENSCTL); 273 + } 274 + 275 + data->tz = tz; 276 + 277 + platform_set_drvdata(pdev, tz); 278 + 279 + bcm2835_thermal_debugfs(pdev); 280 + 281 + return 0; 282 + err_tz: 283 + thermal_zone_of_sensor_unregister(&pdev->dev, tz); 284 + err_clk: 285 + clk_disable_unprepare(data->clk); 286 + 287 + return err; 288 + } 289 + 290 + static int bcm2835_thermal_remove(struct platform_device *pdev) 291 + { 292 + struct thermal_zone_device *tz = platform_get_drvdata(pdev); 293 + struct bcm2835_thermal_data *data = tz->devdata; 294 + 295 + debugfs_remove_recursive(data->debugfsdir); 296 + thermal_zone_of_sensor_unregister(&pdev->dev, tz); 297 + clk_disable_unprepare(data->clk); 298 + 299 + return 0; 300 + } 301 + 302 + static struct platform_driver bcm2835_thermal_driver = { 303 + .probe = bcm2835_thermal_probe, 304 + .remove = bcm2835_thermal_remove, 305 + .driver = { 306 + .name = "bcm2835_thermal", 307 + .of_match_table = bcm2835_thermal_of_match_table, 308 + }, 309 + }; 310 + module_platform_driver(bcm2835_thermal_driver); 311 + 312 + MODULE_AUTHOR("Martin Sperl"); 313 + MODULE_DESCRIPTION("Thermal driver for bcm2835 chip"); 314 + MODULE_LICENSE("GPL");
+106
drivers/thermal/broadcom/ns-thermal.c
··· 1 + /* 2 + * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl> 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #include <linux/module.h> 10 + #include <linux/of_address.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/thermal.h> 13 + 14 + #define PVTMON_CONTROL0 0x00 15 + #define PVTMON_CONTROL0_SEL_MASK 0x0000000e 16 + #define PVTMON_CONTROL0_SEL_TEMP_MONITOR 0x00000000 17 + #define PVTMON_CONTROL0_SEL_TEST_MODE 0x0000000e 18 + #define PVTMON_STATUS 0x08 19 + 20 + struct ns_thermal { 21 + struct thermal_zone_device *tz; 22 + void __iomem *pvtmon; 23 + }; 24 + 25 + static int ns_thermal_get_temp(void *data, int *temp) 26 + { 27 + struct ns_thermal *ns_thermal = data; 28 + int offset = thermal_zone_get_offset(ns_thermal->tz); 29 + int slope = thermal_zone_get_slope(ns_thermal->tz); 30 + u32 val; 31 + 32 + val = readl(ns_thermal->pvtmon + PVTMON_CONTROL0); 33 + if ((val & PVTMON_CONTROL0_SEL_MASK) != PVTMON_CONTROL0_SEL_TEMP_MONITOR) { 34 + /* Clear current mode selection */ 35 + val &= ~PVTMON_CONTROL0_SEL_MASK; 36 + 37 + /* Set temp monitor mode (it's the default actually) */ 38 + val |= PVTMON_CONTROL0_SEL_TEMP_MONITOR; 39 + 40 + writel(val, ns_thermal->pvtmon + PVTMON_CONTROL0); 41 + } 42 + 43 + val = readl(ns_thermal->pvtmon + PVTMON_STATUS); 44 + *temp = slope * val + offset; 45 + 46 + return 0; 47 + } 48 + 49 + static const struct thermal_zone_of_device_ops ns_thermal_ops = { 50 + .get_temp = ns_thermal_get_temp, 51 + }; 52 + 53 + static int ns_thermal_probe(struct platform_device *pdev) 54 + { 55 + struct device *dev = &pdev->dev; 56 + struct ns_thermal *ns_thermal; 57 + 58 + ns_thermal = devm_kzalloc(dev, sizeof(*ns_thermal), GFP_KERNEL); 59 + if (!ns_thermal) 60 + return -ENOMEM; 61 + 62 + ns_thermal->pvtmon = of_iomap(dev_of_node(dev), 0); 63 + if (WARN_ON(!ns_thermal->pvtmon)) 64 + return -ENOENT; 65 + 66 + ns_thermal->tz = devm_thermal_zone_of_sensor_register(dev, 0, 67 + ns_thermal, 68 + &ns_thermal_ops); 69 + if (IS_ERR(ns_thermal->tz)) { 70 + iounmap(ns_thermal->pvtmon); 71 + return PTR_ERR(ns_thermal->tz); 72 + } 73 + 74 + platform_set_drvdata(pdev, ns_thermal); 75 + 76 + return 0; 77 + } 78 + 79 + static int ns_thermal_remove(struct platform_device *pdev) 80 + { 81 + struct ns_thermal *ns_thermal = platform_get_drvdata(pdev); 82 + 83 + iounmap(ns_thermal->pvtmon); 84 + 85 + return 0; 86 + } 87 + 88 + static const struct of_device_id ns_thermal_of_match[] = { 89 + { .compatible = "brcm,ns-thermal", }, 90 + {}, 91 + }; 92 + MODULE_DEVICE_TABLE(of, ns_thermal_of_match); 93 + 94 + static struct platform_driver ns_thermal_driver = { 95 + .probe = ns_thermal_probe, 96 + .remove = ns_thermal_remove, 97 + .driver = { 98 + .name = "ns-thermal", 99 + .of_match_table = ns_thermal_of_match, 100 + }, 101 + }; 102 + module_platform_driver(ns_thermal_driver); 103 + 104 + MODULE_AUTHOR("Rafał Miłecki <rafal@milecki.pl>"); 105 + MODULE_DESCRIPTION("Northstar thermal driver"); 106 + MODULE_LICENSE("GPL v2");
+315
drivers/thermal/da9062-thermal.c
··· 1 + /* 2 + * Thermal device driver for DA9062 and DA9061 3 + * Copyright (C) 2017 Dialog Semiconductor 4 + * 5 + * This program is free software; you can redistribute it and/or 6 + * modify it under the terms of the GNU General Public License 7 + * as published by the Free Software Foundation; either version 2 8 + * of the License, or (at your option) any later version. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + */ 15 + 16 + /* When over-temperature is reached, an interrupt from the device will be 17 + * triggered. Following this event the interrupt will be disabled and 18 + * periodic transmission of uevents (HOT trip point) should define the 19 + * first level of temperature supervision. It is expected that any final 20 + * implementation of the thermal driver will include a .notify() function 21 + * to implement these uevents to userspace. 22 + * 23 + * These uevents are intended to indicate non-invasive temperature control 24 + * of the system, where the necessary measures for cooling are the 25 + * responsibility of the host software. Once the temperature falls again, 26 + * the IRQ is re-enabled so the start of a new over-temperature event can 27 + * be detected without constant software monitoring. 28 + */ 29 + 30 + #include <linux/errno.h> 31 + #include <linux/interrupt.h> 32 + #include <linux/module.h> 33 + #include <linux/of.h> 34 + #include <linux/platform_device.h> 35 + #include <linux/regmap.h> 36 + #include <linux/thermal.h> 37 + #include <linux/workqueue.h> 38 + 39 + #include <linux/mfd/da9062/core.h> 40 + #include <linux/mfd/da9062/registers.h> 41 + 42 + /* Minimum, maximum and default polling millisecond periods are provided 43 + * here as an example. It is expected that any final implementation to also 44 + * include a modification of these settings to match the required 45 + * application. 46 + */ 47 + #define DA9062_DEFAULT_POLLING_MS_PERIOD 3000 48 + #define DA9062_MAX_POLLING_MS_PERIOD 10000 49 + #define DA9062_MIN_POLLING_MS_PERIOD 1000 50 + 51 + #define DA9062_MILLI_CELSIUS(t) ((t) * 1000) 52 + 53 + struct da9062_thermal_config { 54 + const char *name; 55 + }; 56 + 57 + struct da9062_thermal { 58 + struct da9062 *hw; 59 + struct delayed_work work; 60 + struct thermal_zone_device *zone; 61 + enum thermal_device_mode mode; 62 + struct mutex lock; /* protection for da9062_thermal temperature */ 63 + int temperature; 64 + int irq; 65 + const struct da9062_thermal_config *config; 66 + struct device *dev; 67 + }; 68 + 69 + static void da9062_thermal_poll_on(struct work_struct *work) 70 + { 71 + struct da9062_thermal *thermal = container_of(work, 72 + struct da9062_thermal, 73 + work.work); 74 + unsigned long delay; 75 + unsigned int val; 76 + int ret; 77 + 78 + /* clear E_TEMP */ 79 + ret = regmap_write(thermal->hw->regmap, 80 + DA9062AA_EVENT_B, 81 + DA9062AA_E_TEMP_MASK); 82 + if (ret < 0) { 83 + dev_err(thermal->dev, 84 + "Cannot clear the TJUNC temperature status\n"); 85 + goto err_enable_irq; 86 + } 87 + 88 + /* Now read E_TEMP again: it is acting like a status bit. 89 + * If over-temperature, then this status will be true. 90 + * If not over-temperature, this status will be false. 91 + */ 92 + ret = regmap_read(thermal->hw->regmap, 93 + DA9062AA_EVENT_B, 94 + &val); 95 + if (ret < 0) { 96 + dev_err(thermal->dev, 97 + "Cannot check the TJUNC temperature status\n"); 98 + goto err_enable_irq; 99 + } 100 + 101 + if (val & DA9062AA_E_TEMP_MASK) { 102 + mutex_lock(&thermal->lock); 103 + thermal->temperature = DA9062_MILLI_CELSIUS(125); 104 + mutex_unlock(&thermal->lock); 105 + thermal_zone_device_update(thermal->zone, 106 + THERMAL_EVENT_UNSPECIFIED); 107 + 108 + delay = msecs_to_jiffies(thermal->zone->passive_delay); 109 + schedule_delayed_work(&thermal->work, delay); 110 + return; 111 + } 112 + 113 + mutex_lock(&thermal->lock); 114 + thermal->temperature = DA9062_MILLI_CELSIUS(0); 115 + mutex_unlock(&thermal->lock); 116 + thermal_zone_device_update(thermal->zone, 117 + THERMAL_EVENT_UNSPECIFIED); 118 + 119 + err_enable_irq: 120 + enable_irq(thermal->irq); 121 + } 122 + 123 + static irqreturn_t da9062_thermal_irq_handler(int irq, void *data) 124 + { 125 + struct da9062_thermal *thermal = data; 126 + 127 + disable_irq_nosync(thermal->irq); 128 + schedule_delayed_work(&thermal->work, 0); 129 + 130 + return IRQ_HANDLED; 131 + } 132 + 133 + static int da9062_thermal_get_mode(struct thermal_zone_device *z, 134 + enum thermal_device_mode *mode) 135 + { 136 + struct da9062_thermal *thermal = z->devdata; 137 + *mode = thermal->mode; 138 + return 0; 139 + } 140 + 141 + static int da9062_thermal_get_trip_type(struct thermal_zone_device *z, 142 + int trip, 143 + enum thermal_trip_type *type) 144 + { 145 + struct da9062_thermal *thermal = z->devdata; 146 + 147 + switch (trip) { 148 + case 0: 149 + *type = THERMAL_TRIP_HOT; 150 + break; 151 + default: 152 + dev_err(thermal->dev, 153 + "Driver does not support more than 1 trip-wire\n"); 154 + return -EINVAL; 155 + } 156 + 157 + return 0; 158 + } 159 + 160 + static int da9062_thermal_get_trip_temp(struct thermal_zone_device *z, 161 + int trip, 162 + int *temp) 163 + { 164 + struct da9062_thermal *thermal = z->devdata; 165 + 166 + switch (trip) { 167 + case 0: 168 + *temp = DA9062_MILLI_CELSIUS(125); 169 + break; 170 + default: 171 + dev_err(thermal->dev, 172 + "Driver does not support more than 1 trip-wire\n"); 173 + return -EINVAL; 174 + } 175 + 176 + return 0; 177 + } 178 + 179 + static int da9062_thermal_get_temp(struct thermal_zone_device *z, 180 + int *temp) 181 + { 182 + struct da9062_thermal *thermal = z->devdata; 183 + 184 + mutex_lock(&thermal->lock); 185 + *temp = thermal->temperature; 186 + mutex_unlock(&thermal->lock); 187 + 188 + return 0; 189 + } 190 + 191 + static struct thermal_zone_device_ops da9062_thermal_ops = { 192 + .get_temp = da9062_thermal_get_temp, 193 + .get_mode = da9062_thermal_get_mode, 194 + .get_trip_type = da9062_thermal_get_trip_type, 195 + .get_trip_temp = da9062_thermal_get_trip_temp, 196 + }; 197 + 198 + static const struct da9062_thermal_config da9062_config = { 199 + .name = "da9062-thermal", 200 + }; 201 + 202 + static const struct of_device_id da9062_compatible_reg_id_table[] = { 203 + { .compatible = "dlg,da9062-thermal", .data = &da9062_config }, 204 + { }, 205 + }; 206 + 207 + MODULE_DEVICE_TABLE(of, da9062_compatible_reg_id_table); 208 + 209 + static int da9062_thermal_probe(struct platform_device *pdev) 210 + { 211 + struct da9062 *chip = dev_get_drvdata(pdev->dev.parent); 212 + struct da9062_thermal *thermal; 213 + unsigned int pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD; 214 + const struct of_device_id *match; 215 + int ret = 0; 216 + 217 + match = of_match_node(da9062_compatible_reg_id_table, 218 + pdev->dev.of_node); 219 + if (!match) 220 + return -ENXIO; 221 + 222 + if (pdev->dev.of_node) { 223 + if (!of_property_read_u32(pdev->dev.of_node, 224 + "polling-delay-passive", 225 + &pp_tmp)) { 226 + if (pp_tmp < DA9062_MIN_POLLING_MS_PERIOD || 227 + pp_tmp > DA9062_MAX_POLLING_MS_PERIOD) { 228 + dev_warn(&pdev->dev, 229 + "Out-of-range polling period %d ms\n", 230 + pp_tmp); 231 + pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD; 232 + } 233 + } 234 + } 235 + 236 + thermal = devm_kzalloc(&pdev->dev, sizeof(struct da9062_thermal), 237 + GFP_KERNEL); 238 + if (!thermal) { 239 + ret = -ENOMEM; 240 + goto err; 241 + } 242 + 243 + thermal->config = match->data; 244 + thermal->hw = chip; 245 + thermal->mode = THERMAL_DEVICE_ENABLED; 246 + thermal->dev = &pdev->dev; 247 + 248 + INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on); 249 + mutex_init(&thermal->lock); 250 + 251 + thermal->zone = thermal_zone_device_register(thermal->config->name, 252 + 1, 0, thermal, 253 + &da9062_thermal_ops, NULL, pp_tmp, 254 + 0); 255 + if (IS_ERR(thermal->zone)) { 256 + dev_err(&pdev->dev, "Cannot register thermal zone device\n"); 257 + ret = PTR_ERR(thermal->zone); 258 + goto err; 259 + } 260 + 261 + dev_dbg(&pdev->dev, 262 + "TJUNC temperature polling period set at %d ms\n", 263 + thermal->zone->passive_delay); 264 + 265 + ret = platform_get_irq_byname(pdev, "THERMAL"); 266 + if (ret < 0) { 267 + dev_err(&pdev->dev, "Failed to get platform IRQ.\n"); 268 + goto err_zone; 269 + } 270 + thermal->irq = ret; 271 + 272 + ret = request_threaded_irq(thermal->irq, NULL, 273 + da9062_thermal_irq_handler, 274 + IRQF_TRIGGER_LOW | IRQF_ONESHOT, 275 + "THERMAL", thermal); 276 + if (ret) { 277 + dev_err(&pdev->dev, 278 + "Failed to request thermal device IRQ.\n"); 279 + goto err_zone; 280 + } 281 + 282 + platform_set_drvdata(pdev, thermal); 283 + return 0; 284 + 285 + err_zone: 286 + thermal_zone_device_unregister(thermal->zone); 287 + err: 288 + return ret; 289 + } 290 + 291 + static int da9062_thermal_remove(struct platform_device *pdev) 292 + { 293 + struct da9062_thermal *thermal = platform_get_drvdata(pdev); 294 + 295 + free_irq(thermal->irq, thermal); 296 + cancel_delayed_work_sync(&thermal->work); 297 + thermal_zone_device_unregister(thermal->zone); 298 + return 0; 299 + } 300 + 301 + static struct platform_driver da9062_thermal_driver = { 302 + .probe = da9062_thermal_probe, 303 + .remove = da9062_thermal_remove, 304 + .driver = { 305 + .name = "da9062-thermal", 306 + .of_match_table = da9062_compatible_reg_id_table, 307 + }, 308 + }; 309 + 310 + module_platform_driver(da9062_thermal_driver); 311 + 312 + MODULE_AUTHOR("Steve Twiss"); 313 + MODULE_DESCRIPTION("Thermal TJUNC device driver for Dialog DA9062 and DA9061"); 314 + MODULE_LICENSE("GPL"); 315 + MODULE_ALIAS("platform:da9062-thermal");
+111 -41
drivers/thermal/devfreq_cooling.c
··· 28 28 29 29 #include <trace/events/thermal.h> 30 30 31 + #define SCALE_ERROR_MITIGATION 100 32 + 31 33 static DEFINE_IDA(devfreq_ida); 32 34 33 35 /** ··· 47 45 * @freq_table_size: Size of the @freq_table and @power_table 48 46 * @power_ops: Pointer to devfreq_cooling_power, used to generate the 49 47 * @power_table. 48 + * @res_util: Resource utilization scaling factor for the power. 49 + * It is multiplied by 100 to minimize the error. It is used 50 + * for estimation of the power budget instead of using 51 + * 'utilization' (which is 'busy_time / 'total_time'). 52 + * The 'res_util' range is from 100 to (power_table[state] * 100) 53 + * for the corresponding 'state'. 50 54 */ 51 55 struct devfreq_cooling_device { 52 56 int id; ··· 63 55 u32 *freq_table; 64 56 size_t freq_table_size; 65 57 struct devfreq_cooling_power *power_ops; 58 + u32 res_util; 59 + int capped_state; 66 60 }; 67 61 68 62 /** ··· 174 164 return THERMAL_CSTATE_INVALID; 175 165 } 176 166 177 - /** 178 - * get_static_power() - calculate the static power 179 - * @dfc: Pointer to devfreq cooling device 180 - * @freq: Frequency in Hz 181 - * 182 - * Calculate the static power in milliwatts using the supplied 183 - * get_static_power(). The current voltage is calculated using the 184 - * OPP library. If no get_static_power() was supplied, assume the 185 - * static power is negligible. 186 - */ 187 - static unsigned long 188 - get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq) 167 + static unsigned long get_voltage(struct devfreq *df, unsigned long freq) 189 168 { 190 - struct devfreq *df = dfc->devfreq; 191 169 struct device *dev = df->dev.parent; 192 170 unsigned long voltage; 193 171 struct dev_pm_opp *opp; 194 - 195 - if (!dfc->power_ops->get_static_power) 196 - return 0; 197 172 198 173 opp = dev_pm_opp_find_freq_exact(dev, freq, true); 199 174 if (PTR_ERR(opp) == -ERANGE) ··· 197 202 dev_err_ratelimited(dev, 198 203 "Failed to get voltage for frequency %lu\n", 199 204 freq); 200 - return 0; 201 205 } 206 + 207 + return voltage; 208 + } 209 + 210 + /** 211 + * get_static_power() - calculate the static power 212 + * @dfc: Pointer to devfreq cooling device 213 + * @freq: Frequency in Hz 214 + * 215 + * Calculate the static power in milliwatts using the supplied 216 + * get_static_power(). The current voltage is calculated using the 217 + * OPP library. If no get_static_power() was supplied, assume the 218 + * static power is negligible. 219 + */ 220 + static unsigned long 221 + get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq) 222 + { 223 + struct devfreq *df = dfc->devfreq; 224 + unsigned long voltage; 225 + 226 + if (!dfc->power_ops->get_static_power) 227 + return 0; 228 + 229 + voltage = get_voltage(df, freq); 230 + 231 + if (voltage == 0) 232 + return 0; 202 233 203 234 return dfc->power_ops->get_static_power(df, voltage); 204 235 } ··· 260 239 return power; 261 240 } 262 241 242 + 243 + static inline unsigned long get_total_power(struct devfreq_cooling_device *dfc, 244 + unsigned long freq, 245 + unsigned long voltage) 246 + { 247 + return get_static_power(dfc, freq) + get_dynamic_power(dfc, freq, 248 + voltage); 249 + } 250 + 251 + 263 252 static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev, 264 253 struct thermal_zone_device *tz, 265 254 u32 *power) ··· 279 248 struct devfreq_dev_status *status = &df->last_status; 280 249 unsigned long state; 281 250 unsigned long freq = status->current_frequency; 282 - u32 dyn_power, static_power; 251 + unsigned long voltage; 252 + u32 dyn_power = 0; 253 + u32 static_power = 0; 254 + int res; 283 255 284 - /* Get dynamic power for state */ 285 256 state = freq_get_state(dfc, freq); 286 - if (state == THERMAL_CSTATE_INVALID) 287 - return -EAGAIN; 257 + if (state == THERMAL_CSTATE_INVALID) { 258 + res = -EAGAIN; 259 + goto fail; 260 + } 288 261 289 - dyn_power = dfc->power_table[state]; 262 + if (dfc->power_ops->get_real_power) { 263 + voltage = get_voltage(df, freq); 264 + if (voltage == 0) { 265 + res = -EINVAL; 266 + goto fail; 267 + } 290 268 291 - /* Scale dynamic power for utilization */ 292 - dyn_power = (dyn_power * status->busy_time) / status->total_time; 269 + res = dfc->power_ops->get_real_power(df, power, freq, voltage); 270 + if (!res) { 271 + state = dfc->capped_state; 272 + dfc->res_util = dfc->power_table[state]; 273 + dfc->res_util *= SCALE_ERROR_MITIGATION; 293 274 294 - /* Get static power */ 295 - static_power = get_static_power(dfc, freq); 275 + if (*power > 1) 276 + dfc->res_util /= *power; 277 + } else { 278 + goto fail; 279 + } 280 + } else { 281 + dyn_power = dfc->power_table[state]; 282 + 283 + /* Scale dynamic power for utilization */ 284 + dyn_power *= status->busy_time; 285 + dyn_power /= status->total_time; 286 + /* Get static power */ 287 + static_power = get_static_power(dfc, freq); 288 + 289 + *power = dyn_power + static_power; 290 + } 296 291 297 292 trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power, 298 - static_power); 299 - 300 - *power = dyn_power + static_power; 293 + static_power, *power); 301 294 302 295 return 0; 296 + fail: 297 + /* It is safe to set max in this case */ 298 + dfc->res_util = SCALE_ERROR_MITIGATION; 299 + return res; 303 300 } 304 301 305 302 static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, ··· 360 301 unsigned long busy_time; 361 302 s32 dyn_power; 362 303 u32 static_power; 304 + s32 est_power; 363 305 int i; 364 306 365 - static_power = get_static_power(dfc, freq); 307 + if (dfc->power_ops->get_real_power) { 308 + /* Scale for resource utilization */ 309 + est_power = power * dfc->res_util; 310 + est_power /= SCALE_ERROR_MITIGATION; 311 + } else { 312 + static_power = get_static_power(dfc, freq); 366 313 367 - dyn_power = power - static_power; 368 - dyn_power = dyn_power > 0 ? dyn_power : 0; 314 + dyn_power = power - static_power; 315 + dyn_power = dyn_power > 0 ? dyn_power : 0; 369 316 370 - /* Scale dynamic power for utilization */ 371 - busy_time = status->busy_time ?: 1; 372 - dyn_power = (dyn_power * status->total_time) / busy_time; 317 + /* Scale dynamic power for utilization */ 318 + busy_time = status->busy_time ?: 1; 319 + est_power = (dyn_power * status->total_time) / busy_time; 320 + } 373 321 374 322 /* 375 323 * Find the first cooling state that is within the power 376 324 * budget for dynamic power. 377 325 */ 378 326 for (i = 0; i < dfc->freq_table_size - 1; i++) 379 - if (dyn_power >= dfc->power_table[i]) 327 + if (est_power >= dfc->power_table[i]) 380 328 break; 381 329 382 330 *state = i; 331 + dfc->capped_state = i; 383 332 trace_thermal_power_devfreq_limit(cdev, freq, *state, power); 384 333 return 0; 385 334 } ··· 443 376 } 444 377 445 378 for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) { 446 - unsigned long power_dyn, voltage; 379 + unsigned long power, voltage; 447 380 struct dev_pm_opp *opp; 448 381 449 382 opp = dev_pm_opp_find_freq_floor(dev, &freq); ··· 456 389 dev_pm_opp_put(opp); 457 390 458 391 if (dfc->power_ops) { 459 - power_dyn = get_dynamic_power(dfc, freq, voltage); 392 + if (dfc->power_ops->get_real_power) 393 + power = get_total_power(dfc, freq, voltage); 394 + else 395 + power = get_dynamic_power(dfc, freq, voltage); 460 396 461 - dev_dbg(dev, "Dynamic power table: %lu MHz @ %lu mV: %lu = %lu mW\n", 462 - freq / 1000000, voltage, power_dyn, power_dyn); 397 + dev_dbg(dev, "Power table: %lu MHz @ %lu mV: %lu = %lu mW\n", 398 + freq / 1000000, voltage, power, power); 463 399 464 - power_table[i] = power_dyn; 400 + power_table[i] = power; 465 401 } 466 402 467 403 freq_table[i] = freq;
+6 -3
drivers/thermal/intel_soc_dts_thermal.c
··· 73 73 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 74 74 "soc_dts", soc_dts); 75 75 if (err) { 76 - pr_err("request_threaded_irq ret %d\n", err); 77 - goto error_irq; 76 + /* 77 + * Do not just error out because the user space thermal 78 + * daemon such as DPTF may use polling instead of being 79 + * interrupt driven. 80 + */ 81 + pr_warn("request_threaded_irq ret %d\n", err); 78 82 } 79 83 } 80 84 ··· 92 88 error_trips: 93 89 if (soc_dts_thres_irq) 94 90 free_irq(soc_dts_thres_irq, soc_dts); 95 - error_irq: 96 91 intel_soc_dts_iosf_exit(soc_dts); 97 92 98 93 return err;
+1 -1
drivers/thermal/mtk_thermal.c
··· 191 191 }; 192 192 193 193 static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = { 194 - TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR2 194 + TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3 195 195 }; 196 196 197 197 static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
+184 -15
drivers/thermal/rcar_gen3_thermal.c
··· 20 20 #include <linux/interrupt.h> 21 21 #include <linux/io.h> 22 22 #include <linux/module.h> 23 - #include <linux/mutex.h> 24 23 #include <linux/of_device.h> 25 24 #include <linux/platform_device.h> 26 25 #include <linux/pm_runtime.h> 26 + #include <linux/spinlock.h> 27 27 #include <linux/thermal.h> 28 + 29 + #include "thermal_core.h" 28 30 29 31 /* Register offsets */ 30 32 #define REG_GEN3_IRQSTR 0x04 ··· 42 40 #define REG_GEN3_THCODE1 0x50 43 41 #define REG_GEN3_THCODE2 0x54 44 42 #define REG_GEN3_THCODE3 0x58 43 + 44 + /* IRQ{STR,MSK,EN} bits */ 45 + #define IRQ_TEMP1 BIT(0) 46 + #define IRQ_TEMP2 BIT(1) 47 + #define IRQ_TEMP3 BIT(2) 48 + #define IRQ_TEMPD1 BIT(3) 49 + #define IRQ_TEMPD2 BIT(4) 50 + #define IRQ_TEMPD3 BIT(5) 45 51 46 52 /* CTSR bits */ 47 53 #define CTSR_PONM BIT(8) ··· 82 72 void __iomem *base; 83 73 struct thermal_zone_device *zone; 84 74 struct equation_coefs coef; 85 - struct mutex lock; 75 + int low; 76 + int high; 86 77 }; 87 78 88 79 struct rcar_gen3_thermal_priv { 89 80 struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM]; 81 + unsigned int num_tscs; 82 + spinlock_t lock; /* Protect interrupts on and off */ 83 + const struct rcar_gen3_thermal_data *data; 90 84 }; 91 85 92 86 struct rcar_gen3_thermal_data { ··· 128 114 129 115 #define FIXPT_SHIFT 7 130 116 #define FIXPT_INT(_x) ((_x) << FIXPT_SHIFT) 117 + #define INT_FIXPT(_x) ((_x) >> FIXPT_SHIFT) 131 118 #define FIXPT_DIV(_a, _b) DIV_ROUND_CLOSEST(((_a) << FIXPT_SHIFT), (_b)) 132 119 #define FIXPT_TO_MCELSIUS(_x) ((_x) * 1000 >> FIXPT_SHIFT) 133 120 ··· 178 163 u32 reg; 179 164 180 165 /* Read register and convert to mili Celsius */ 181 - mutex_lock(&tsc->lock); 182 - 183 166 reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK; 184 167 185 168 val1 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, tsc->coef.a1); 186 169 val2 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b2, tsc->coef.a2); 187 170 mcelsius = FIXPT_TO_MCELSIUS((val1 + val2) / 2); 188 - 189 - mutex_unlock(&tsc->lock); 190 171 191 172 /* Make sure we are inside specifications */ 192 173 if ((mcelsius < MCELSIUS(-40)) || (mcelsius > MCELSIUS(125))) ··· 194 183 return 0; 195 184 } 196 185 186 + static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc, 187 + int mcelsius) 188 + { 189 + int celsius, val1, val2; 190 + 191 + celsius = DIV_ROUND_CLOSEST(mcelsius, 1000); 192 + val1 = celsius * tsc->coef.a1 + tsc->coef.b1; 193 + val2 = celsius * tsc->coef.a2 + tsc->coef.b2; 194 + 195 + return INT_FIXPT((val1 + val2) / 2); 196 + } 197 + 198 + static int rcar_gen3_thermal_set_trips(void *devdata, int low, int high) 199 + { 200 + struct rcar_gen3_thermal_tsc *tsc = devdata; 201 + 202 + low = clamp_val(low, -40000, 125000); 203 + high = clamp_val(high, -40000, 125000); 204 + 205 + rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1, 206 + rcar_gen3_thermal_mcelsius_to_temp(tsc, low)); 207 + 208 + rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP2, 209 + rcar_gen3_thermal_mcelsius_to_temp(tsc, high)); 210 + 211 + tsc->low = low; 212 + tsc->high = high; 213 + 214 + return 0; 215 + } 216 + 197 217 static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = { 198 218 .get_temp = rcar_gen3_thermal_get_temp, 219 + .set_trips = rcar_gen3_thermal_set_trips, 199 220 }; 221 + 222 + static void rcar_thermal_irq_set(struct rcar_gen3_thermal_priv *priv, bool on) 223 + { 224 + unsigned int i; 225 + u32 val = on ? IRQ_TEMPD1 | IRQ_TEMP2 : 0; 226 + 227 + for (i = 0; i < priv->num_tscs; i++) 228 + rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQMSK, val); 229 + } 230 + 231 + static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data) 232 + { 233 + struct rcar_gen3_thermal_priv *priv = data; 234 + u32 status; 235 + int i, ret = IRQ_HANDLED; 236 + 237 + spin_lock(&priv->lock); 238 + for (i = 0; i < priv->num_tscs; i++) { 239 + status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR); 240 + rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0); 241 + if (status) 242 + ret = IRQ_WAKE_THREAD; 243 + } 244 + 245 + if (ret == IRQ_WAKE_THREAD) 246 + rcar_thermal_irq_set(priv, false); 247 + 248 + spin_unlock(&priv->lock); 249 + 250 + return ret; 251 + } 252 + 253 + static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data) 254 + { 255 + struct rcar_gen3_thermal_priv *priv = data; 256 + unsigned long flags; 257 + int i; 258 + 259 + for (i = 0; i < priv->num_tscs; i++) 260 + thermal_zone_device_update(priv->tscs[i]->zone, 261 + THERMAL_EVENT_UNSPECIFIED); 262 + 263 + spin_lock_irqsave(&priv->lock, flags); 264 + rcar_thermal_irq_set(priv, true); 265 + spin_unlock_irqrestore(&priv->lock, flags); 266 + 267 + return IRQ_HANDLED; 268 + } 200 269 201 270 static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc) 202 271 { ··· 286 195 usleep_range(1000, 2000); 287 196 288 197 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_PONM); 198 + 289 199 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); 200 + rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0); 201 + rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2); 202 + 290 203 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 291 204 CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN); 292 205 ··· 314 219 usleep_range(1000, 2000); 315 220 316 221 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); 222 + rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0); 223 + rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2); 224 + 317 225 reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR); 318 226 reg_val |= THCTR_THSST; 319 227 rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val); 228 + 229 + usleep_range(1000, 2000); 320 230 } 321 231 322 232 static const struct rcar_gen3_thermal_data r8a7795_data = { ··· 355 255 struct device *dev = &pdev->dev; 356 256 struct resource *res; 357 257 struct thermal_zone_device *zone; 358 - int ret, i; 359 - const struct rcar_gen3_thermal_data *match_data = 360 - of_device_get_match_data(dev); 258 + int ret, irq, i; 259 + char *irqname; 361 260 362 261 /* default values if FUSEs are missing */ 363 262 /* TODO: Read values from hardware on supported platforms */ ··· 371 272 if (!priv) 372 273 return -ENOMEM; 373 274 275 + priv->data = of_device_get_match_data(dev); 276 + 277 + spin_lock_init(&priv->lock); 278 + 374 279 platform_set_drvdata(pdev, priv); 280 + 281 + /* 282 + * Request 2 (of the 3 possible) IRQs, the driver only needs to 283 + * to trigger on the low and high trip points of the current 284 + * temp window at this point. 285 + */ 286 + for (i = 0; i < 2; i++) { 287 + irq = platform_get_irq(pdev, i); 288 + if (irq < 0) 289 + return irq; 290 + 291 + irqname = devm_kasprintf(dev, GFP_KERNEL, "%s:ch%d", 292 + dev_name(dev), i); 293 + if (!irqname) 294 + return -ENOMEM; 295 + 296 + ret = devm_request_threaded_irq(dev, irq, rcar_gen3_thermal_irq, 297 + rcar_gen3_thermal_irq_thread, 298 + IRQF_SHARED, irqname, priv); 299 + if (ret) 300 + return ret; 301 + } 375 302 376 303 pm_runtime_enable(dev); 377 304 pm_runtime_get_sync(dev); ··· 405 280 for (i = 0; i < TSC_MAX_NUM; i++) { 406 281 struct rcar_gen3_thermal_tsc *tsc; 407 282 283 + res = platform_get_resource(pdev, IORESOURCE_MEM, i); 284 + if (!res) 285 + break; 286 + 408 287 tsc = devm_kzalloc(dev, sizeof(*tsc), GFP_KERNEL); 409 288 if (!tsc) { 410 289 ret = -ENOMEM; 411 290 goto error_unregister; 412 291 } 413 - 414 - res = platform_get_resource(pdev, IORESOURCE_MEM, i); 415 - if (!res) 416 - break; 417 292 418 293 tsc->base = devm_ioremap_resource(dev, res); 419 294 if (IS_ERR(tsc->base)) { ··· 422 297 } 423 298 424 299 priv->tscs[i] = tsc; 425 - mutex_init(&tsc->lock); 426 300 427 - match_data->thermal_init(tsc); 301 + priv->data->thermal_init(tsc); 428 302 rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]); 429 303 430 304 zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, ··· 434 310 goto error_unregister; 435 311 } 436 312 tsc->zone = zone; 313 + 314 + ret = of_thermal_get_ntrips(tsc->zone); 315 + if (ret < 0) 316 + goto error_unregister; 317 + 318 + dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret); 437 319 } 320 + 321 + priv->num_tscs = i; 322 + 323 + if (!priv->num_tscs) { 324 + ret = -ENODEV; 325 + goto error_unregister; 326 + } 327 + 328 + rcar_thermal_irq_set(priv, true); 438 329 439 330 return 0; 440 331 ··· 459 320 return ret; 460 321 } 461 322 323 + static int __maybe_unused rcar_gen3_thermal_suspend(struct device *dev) 324 + { 325 + struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev); 326 + 327 + rcar_thermal_irq_set(priv, false); 328 + 329 + return 0; 330 + } 331 + 332 + static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev) 333 + { 334 + struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev); 335 + unsigned int i; 336 + 337 + for (i = 0; i < priv->num_tscs; i++) { 338 + struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; 339 + 340 + priv->data->thermal_init(tsc); 341 + rcar_gen3_thermal_set_trips(tsc, tsc->low, tsc->high); 342 + } 343 + 344 + rcar_thermal_irq_set(priv, true); 345 + 346 + return 0; 347 + } 348 + 349 + static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, rcar_gen3_thermal_suspend, 350 + rcar_gen3_thermal_resume); 351 + 462 352 static struct platform_driver rcar_gen3_thermal_driver = { 463 353 .driver = { 464 354 .name = "rcar_gen3_thermal", 355 + .pm = &rcar_gen3_thermal_pm_ops, 465 356 .of_match_table = rcar_gen3_thermal_dt_ids, 466 357 }, 467 358 .probe = rcar_gen3_thermal_probe,
+63 -1
drivers/thermal/thermal_core.c
··· 45 45 46 46 static DEFINE_MUTEX(thermal_list_lock); 47 47 static DEFINE_MUTEX(thermal_governor_lock); 48 + static DEFINE_MUTEX(poweroff_lock); 48 49 49 50 static atomic_t in_suspend; 51 + static bool power_off_triggered; 50 52 51 53 static struct thermal_governor *def_governor; 52 54 ··· 324 322 def_governor->throttle(tz, trip); 325 323 } 326 324 325 + /** 326 + * thermal_emergency_poweroff_func - emergency poweroff work after a known delay 327 + * @work: work_struct associated with the emergency poweroff function 328 + * 329 + * This function is called in very critical situations to force 330 + * a kernel poweroff after a configurable timeout value. 331 + */ 332 + static void thermal_emergency_poweroff_func(struct work_struct *work) 333 + { 334 + /* 335 + * We have reached here after the emergency thermal shutdown 336 + * Waiting period has expired. This means orderly_poweroff has 337 + * not been able to shut off the system for some reason. 338 + * Try to shut down the system immediately using kernel_power_off 339 + * if populated 340 + */ 341 + WARN(1, "Attempting kernel_power_off: Temperature too high\n"); 342 + kernel_power_off(); 343 + 344 + /* 345 + * Worst of the worst case trigger emergency restart 346 + */ 347 + WARN(1, "Attempting emergency_restart: Temperature too high\n"); 348 + emergency_restart(); 349 + } 350 + 351 + static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work, 352 + thermal_emergency_poweroff_func); 353 + 354 + /** 355 + * thermal_emergency_poweroff - Trigger an emergency system poweroff 356 + * 357 + * This may be called from any critical situation to trigger a system shutdown 358 + * after a known period of time. By default this is not scheduled. 359 + */ 360 + void thermal_emergency_poweroff(void) 361 + { 362 + int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS; 363 + /* 364 + * poweroff_delay_ms must be a carefully profiled positive value. 365 + * Its a must for thermal_emergency_poweroff_work to be scheduled 366 + */ 367 + if (poweroff_delay_ms <= 0) 368 + return; 369 + schedule_delayed_work(&thermal_emergency_poweroff_work, 370 + msecs_to_jiffies(poweroff_delay_ms)); 371 + } 372 + 327 373 static void handle_critical_trips(struct thermal_zone_device *tz, 328 374 int trip, enum thermal_trip_type trip_type) 329 375 { ··· 392 342 dev_emerg(&tz->device, 393 343 "critical temperature reached(%d C),shutting down\n", 394 344 tz->temperature / 1000); 395 - orderly_poweroff(true); 345 + mutex_lock(&poweroff_lock); 346 + if (!power_off_triggered) { 347 + /* 348 + * Queue a backup emergency shutdown in the event of 349 + * orderly_poweroff failure 350 + */ 351 + thermal_emergency_poweroff(); 352 + orderly_poweroff(true); 353 + power_off_triggered = true; 354 + } 355 + mutex_unlock(&poweroff_lock); 396 356 } 397 357 } 398 358 ··· 1523 1463 { 1524 1464 int result; 1525 1465 1466 + mutex_init(&poweroff_lock); 1526 1467 result = thermal_register_governors(); 1527 1468 if (result) 1528 1469 goto error; ··· 1558 1497 ida_destroy(&thermal_cdev_ida); 1559 1498 mutex_destroy(&thermal_list_lock); 1560 1499 mutex_destroy(&thermal_governor_lock); 1500 + mutex_destroy(&poweroff_lock); 1561 1501 return result; 1562 1502 } 1563 1503
-10
drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
··· 410 410 .domain = "cpu", 411 411 .register_cooling = ti_thermal_register_cpu_cooling, 412 412 .unregister_cooling = ti_thermal_unregister_cpu_cooling, 413 - .slope = DRA752_GRADIENT_SLOPE, 414 - .constant = DRA752_GRADIENT_CONST, 415 413 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 416 414 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 417 415 }, ··· 417 419 .registers = &dra752_gpu_temp_sensor_registers, 418 420 .ts_data = &dra752_gpu_temp_sensor_data, 419 421 .domain = "gpu", 420 - .slope = DRA752_GRADIENT_SLOPE, 421 - .constant = DRA752_GRADIENT_CONST, 422 422 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 423 423 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 424 424 }, ··· 424 428 .registers = &dra752_core_temp_sensor_registers, 425 429 .ts_data = &dra752_core_temp_sensor_data, 426 430 .domain = "core", 427 - .slope = DRA752_GRADIENT_SLOPE, 428 - .constant = DRA752_GRADIENT_CONST, 429 431 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 430 432 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 431 433 }, ··· 431 437 .registers = &dra752_dspeve_temp_sensor_registers, 432 438 .ts_data = &dra752_dspeve_temp_sensor_data, 433 439 .domain = "dspeve", 434 - .slope = DRA752_GRADIENT_SLOPE, 435 - .constant = DRA752_GRADIENT_CONST, 436 440 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 437 441 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 438 442 }, ··· 438 446 .registers = &dra752_iva_temp_sensor_registers, 439 447 .ts_data = &dra752_iva_temp_sensor_data, 440 448 .domain = "iva", 441 - .slope = DRA752_GRADIENT_SLOPE, 442 - .constant = DRA752_GRADIENT_CONST, 443 449 .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 444 450 .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 445 451 },
-4
drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
··· 91 91 .registers = &omap34xx_mpu_temp_sensor_registers, 92 92 .ts_data = &omap34xx_mpu_temp_sensor_data, 93 93 .domain = "cpu", 94 - .slope = 0, 95 - .constant = 20000, 96 94 .slope_pcb = 0, 97 95 .constant_pcb = 20000, 98 96 .register_cooling = NULL, ··· 162 164 .registers = &omap36xx_mpu_temp_sensor_registers, 163 165 .ts_data = &omap36xx_mpu_temp_sensor_data, 164 166 .domain = "cpu", 165 - .slope = 0, 166 - .constant = 20000, 167 167 .slope_pcb = 0, 168 168 .constant_pcb = 20000, 169 169 .register_cooling = NULL,
-6
drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
··· 82 82 .registers = &omap4430_mpu_temp_sensor_registers, 83 83 .ts_data = &omap4430_mpu_temp_sensor_data, 84 84 .domain = "cpu", 85 - .slope = OMAP_GRADIENT_SLOPE_4430, 86 - .constant = OMAP_GRADIENT_CONST_4430, 87 85 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4430, 88 86 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4430, 89 87 .register_cooling = ti_thermal_register_cpu_cooling, ··· 220 222 .registers = &omap4460_mpu_temp_sensor_registers, 221 223 .ts_data = &omap4460_mpu_temp_sensor_data, 222 224 .domain = "cpu", 223 - .slope = OMAP_GRADIENT_SLOPE_4460, 224 - .constant = OMAP_GRADIENT_CONST_4460, 225 225 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460, 226 226 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460, 227 227 .register_cooling = ti_thermal_register_cpu_cooling, ··· 251 255 .registers = &omap4460_mpu_temp_sensor_registers, 252 256 .ts_data = &omap4460_mpu_temp_sensor_data, 253 257 .domain = "cpu", 254 - .slope = OMAP_GRADIENT_SLOPE_4470, 255 - .constant = OMAP_GRADIENT_CONST_4470, 256 258 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470, 257 259 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470, 258 260 .register_cooling = ti_thermal_register_cpu_cooling,
-4
drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
··· 336 336 .domain = "cpu", 337 337 .register_cooling = ti_thermal_register_cpu_cooling, 338 338 .unregister_cooling = ti_thermal_unregister_cpu_cooling, 339 - .slope = OMAP_GRADIENT_SLOPE_5430_CPU, 340 - .constant = OMAP_GRADIENT_CONST_5430_CPU, 341 339 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU, 342 340 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU, 343 341 }, ··· 343 345 .registers = &omap5430_gpu_temp_sensor_registers, 344 346 .ts_data = &omap5430_gpu_temp_sensor_data, 345 347 .domain = "gpu", 346 - .slope = OMAP_GRADIENT_SLOPE_5430_GPU, 347 - .constant = OMAP_GRADIENT_CONST_5430_GPU, 348 348 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU, 349 349 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU, 350 350 },
-4
drivers/thermal/ti-soc-thermal/ti-bandgap.h
··· 254 254 * @ts_data: pointer to struct with thresholds, limits of temperature sensor 255 255 * @registers: pointer to the list of register offsets and bitfields 256 256 * @domain: the name of the domain where the sensor is located 257 - * @slope: sensor gradient slope info for hotspot extrapolation equation 258 - * @constant: sensor gradient const info for hotspot extrapolation equation 259 257 * @slope_pcb: sensor gradient slope info for hotspot extrapolation equation 260 258 * with no external influence 261 259 * @constant_pcb: sensor gradient const info for hotspot extrapolation equation ··· 272 274 struct temp_sensor_registers *registers; 273 275 char *domain; 274 276 /* for hotspot extrapolation */ 275 - const int slope; 276 - const int constant; 277 277 const int slope_pcb; 278 278 const int constant_pcb; 279 279 int (*register_cooling)(struct ti_bandgap *bgp, int id);
+5 -153
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
··· 96 96 return ret; 97 97 98 98 /* Default constants */ 99 - slope = s->slope; 100 - constant = s->constant; 99 + slope = thermal_zone_get_slope(data->ti_thermal); 100 + constant = thermal_zone_get_offset(data->ti_thermal); 101 101 102 102 pcb_tz = data->pcb_tz; 103 103 /* In case pcb zone is available, use the extrapolation rule with it */ ··· 126 126 return __ti_thermal_get_temp(data, temp); 127 127 } 128 128 129 - /* Bind callback functions for thermal zone */ 130 - static int ti_thermal_bind(struct thermal_zone_device *thermal, 131 - struct thermal_cooling_device *cdev) 132 - { 133 - struct ti_thermal_data *data = thermal->devdata; 134 - int id; 135 - 136 - if (!data || IS_ERR(data)) 137 - return -ENODEV; 138 - 139 - /* check if this is the cooling device we registered */ 140 - if (data->cool_dev != cdev) 141 - return 0; 142 - 143 - id = data->sensor_id; 144 - 145 - /* Simple thing, two trips, one passive another critical */ 146 - return thermal_zone_bind_cooling_device(thermal, 0, cdev, 147 - /* bind with min and max states defined by cpu_cooling */ 148 - THERMAL_NO_LIMIT, 149 - THERMAL_NO_LIMIT, 150 - THERMAL_WEIGHT_DEFAULT); 151 - } 152 - 153 - /* Unbind callback functions for thermal zone */ 154 - static int ti_thermal_unbind(struct thermal_zone_device *thermal, 155 - struct thermal_cooling_device *cdev) 156 - { 157 - struct ti_thermal_data *data = thermal->devdata; 158 - 159 - if (!data || IS_ERR(data)) 160 - return -ENODEV; 161 - 162 - /* check if this is the cooling device we registered */ 163 - if (data->cool_dev != cdev) 164 - return 0; 165 - 166 - /* Simple thing, two trips, one passive another critical */ 167 - return thermal_zone_unbind_cooling_device(thermal, 0, cdev); 168 - } 169 - 170 - /* Get mode callback functions for thermal zone */ 171 - static int ti_thermal_get_mode(struct thermal_zone_device *thermal, 172 - enum thermal_device_mode *mode) 173 - { 174 - struct ti_thermal_data *data = thermal->devdata; 175 - 176 - if (data) 177 - *mode = data->mode; 178 - 179 - return 0; 180 - } 181 - 182 - /* Set mode callback functions for thermal zone */ 183 - static int ti_thermal_set_mode(struct thermal_zone_device *thermal, 184 - enum thermal_device_mode mode) 185 - { 186 - struct ti_thermal_data *data = thermal->devdata; 187 - struct ti_bandgap *bgp; 188 - 189 - bgp = data->bgp; 190 - 191 - if (!data->ti_thermal) { 192 - dev_notice(&thermal->device, "thermal zone not registered\n"); 193 - return 0; 194 - } 195 - 196 - mutex_lock(&data->ti_thermal->lock); 197 - 198 - if (mode == THERMAL_DEVICE_ENABLED) 199 - data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; 200 - else 201 - data->ti_thermal->polling_delay = 0; 202 - 203 - mutex_unlock(&data->ti_thermal->lock); 204 - 205 - data->mode = mode; 206 - ti_bandgap_write_update_interval(bgp, data->sensor_id, 207 - data->ti_thermal->polling_delay); 208 - thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED); 209 - dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n", 210 - data->ti_thermal->polling_delay); 211 - 212 - return 0; 213 - } 214 - 215 - /* Get trip type callback functions for thermal zone */ 216 - static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal, 217 - int trip, enum thermal_trip_type *type) 218 - { 219 - if (!ti_thermal_is_valid_trip(trip)) 220 - return -EINVAL; 221 - 222 - if (trip + 1 == OMAP_TRIP_NUMBER) 223 - *type = THERMAL_TRIP_CRITICAL; 224 - else 225 - *type = THERMAL_TRIP_PASSIVE; 226 - 227 - return 0; 228 - } 229 - 230 - /* Get trip temperature callback functions for thermal zone */ 231 - static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal, 232 - int trip, int *temp) 233 - { 234 - if (!ti_thermal_is_valid_trip(trip)) 235 - return -EINVAL; 236 - 237 - *temp = ti_thermal_get_trip_value(trip); 238 - 239 - return 0; 240 - } 241 - 242 129 static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend) 243 130 { 244 131 struct ti_thermal_data *data = p; ··· 149 262 return 0; 150 263 } 151 264 152 - /* Get the temperature trend callback functions for thermal zone */ 153 - static int ti_thermal_get_trend(struct thermal_zone_device *thermal, 154 - int trip, enum thermal_trend *trend) 155 - { 156 - return __ti_thermal_get_trend(thermal->devdata, trip, trend); 157 - } 158 - 159 - /* Get critical temperature callback functions for thermal zone */ 160 - static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal, 161 - int *temp) 162 - { 163 - /* shutdown zone */ 164 - return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp); 165 - } 166 - 167 265 static const struct thermal_zone_of_device_ops ti_of_thermal_ops = { 168 266 .get_temp = __ti_thermal_get_temp, 169 267 .get_trend = __ti_thermal_get_trend, 170 - }; 171 - 172 - static struct thermal_zone_device_ops ti_thermal_ops = { 173 - .get_temp = ti_thermal_get_temp, 174 - .get_trend = ti_thermal_get_trend, 175 - .bind = ti_thermal_bind, 176 - .unbind = ti_thermal_unbind, 177 - .get_mode = ti_thermal_get_mode, 178 - .set_mode = ti_thermal_set_mode, 179 - .get_trip_type = ti_thermal_get_trip_type, 180 - .get_trip_temp = ti_thermal_get_trip_temp, 181 - .get_crit_temp = ti_thermal_get_crit_temp, 182 268 }; 183 269 184 270 static struct ti_thermal_data ··· 191 331 data->ti_thermal = devm_thermal_zone_of_sensor_register(bgp->dev, id, 192 332 data, &ti_of_thermal_ops); 193 333 if (IS_ERR(data->ti_thermal)) { 194 - /* Create thermal zone */ 195 - data->ti_thermal = thermal_zone_device_register(domain, 196 - OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, 197 - NULL, FAST_TEMP_MONITORING_RATE, 198 - FAST_TEMP_MONITORING_RATE); 199 - if (IS_ERR(data->ti_thermal)) { 200 - dev_err(bgp->dev, "thermal zone device is NULL\n"); 201 - return PTR_ERR(data->ti_thermal); 202 - } 203 - data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; 204 - data->our_zone = true; 334 + dev_err(bgp->dev, "thermal zone device is NULL\n"); 335 + return PTR_ERR(data->ti_thermal); 205 336 } 337 + 206 338 ti_bandgap_set_sensor_data(bgp, id, data); 207 339 ti_bandgap_write_update_interval(bgp, data->sensor_id, 208 340 data->ti_thermal->polling_delay);
-16
drivers/thermal/ti-soc-thermal/ti-thermal.h
··· 25 25 26 26 #include "ti-bandgap.h" 27 27 28 - /* sensors gradient and offsets */ 29 - #define OMAP_GRADIENT_SLOPE_4430 0 30 - #define OMAP_GRADIENT_CONST_4430 20000 31 - #define OMAP_GRADIENT_SLOPE_4460 348 32 - #define OMAP_GRADIENT_CONST_4460 -9301 33 - #define OMAP_GRADIENT_SLOPE_4470 308 34 - #define OMAP_GRADIENT_CONST_4470 -7896 35 - 36 - #define OMAP_GRADIENT_SLOPE_5430_CPU 65 37 - #define OMAP_GRADIENT_CONST_5430_CPU -1791 38 - #define OMAP_GRADIENT_SLOPE_5430_GPU 117 39 - #define OMAP_GRADIENT_CONST_5430_GPU -2992 40 - 41 - #define DRA752_GRADIENT_SLOPE 0 42 - #define DRA752_GRADIENT_CONST 2000 43 - 44 28 /* PCB sensor calculation constants */ 45 29 #define OMAP_GRADIENT_SLOPE_W_PCB_4430 0 46 30 #define OMAP_GRADIENT_CONST_W_PCB_4430 20000
+19
include/linux/devfreq_cooling.h
··· 34 34 * If get_dynamic_power() is NULL, then the 35 35 * dynamic power is calculated as 36 36 * @dyn_power_coeff * frequency * voltage^2 37 + * @get_real_power: When this is set, the framework uses it to ask the 38 + * device driver for the actual power. 39 + * Some devices have more sophisticated methods 40 + * (like power counters) to approximate the actual power 41 + * that they use. 42 + * This function provides more accurate data to the 43 + * thermal governor. When the driver does not provide 44 + * such function, framework just uses pre-calculated 45 + * table and scale the power by 'utilization' 46 + * (based on 'busy_time' and 'total_time' taken from 47 + * devfreq 'last_status'). 48 + * The value returned by this function must be lower 49 + * or equal than the maximum power value 50 + * for the current state 51 + * (which can be found in power_table[state]). 52 + * When this interface is used, the power_table holds 53 + * max total (static + dynamic) power value for each OPP. 37 54 */ 38 55 struct devfreq_cooling_power { 39 56 unsigned long (*get_static_power)(struct devfreq *devfreq, ··· 58 41 unsigned long (*get_dynamic_power)(struct devfreq *devfreq, 59 42 unsigned long freq, 60 43 unsigned long voltage); 44 + int (*get_real_power)(struct devfreq *df, u32 *power, 45 + unsigned long freq, unsigned long voltage); 61 46 unsigned long dyn_power_coeff; 62 47 }; 63 48
+7 -4
include/trace/events/thermal.h
··· 151 151 TRACE_EVENT(thermal_power_devfreq_get_power, 152 152 TP_PROTO(struct thermal_cooling_device *cdev, 153 153 struct devfreq_dev_status *status, unsigned long freq, 154 - u32 dynamic_power, u32 static_power), 154 + u32 dynamic_power, u32 static_power, u32 power), 155 155 156 - TP_ARGS(cdev, status, freq, dynamic_power, static_power), 156 + TP_ARGS(cdev, status, freq, dynamic_power, static_power, power), 157 157 158 158 TP_STRUCT__entry( 159 159 __string(type, cdev->type ) ··· 161 161 __field(u32, load ) 162 162 __field(u32, dynamic_power ) 163 163 __field(u32, static_power ) 164 + __field(u32, power) 164 165 ), 165 166 166 167 TP_fast_assign( ··· 170 169 __entry->load = (100 * status->busy_time) / status->total_time; 171 170 __entry->dynamic_power = dynamic_power; 172 171 __entry->static_power = static_power; 172 + __entry->power = power; 173 173 ), 174 174 175 - TP_printk("type=%s freq=%lu load=%u dynamic_power=%u static_power=%u", 175 + TP_printk("type=%s freq=%lu load=%u dynamic_power=%u static_power=%u power=%u", 176 176 __get_str(type), __entry->freq, 177 - __entry->load, __entry->dynamic_power, __entry->static_power) 177 + __entry->load, __entry->dynamic_power, __entry->static_power, 178 + __entry->power) 178 179 ); 179 180 180 181 TRACE_EVENT(thermal_power_devfreq_limit,