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 tag 'thermal-v5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux

Pull thermal updates from Daniel Lezcano:

- Add upper and lower limits clamps for the cooling device state in the
power allocator governor (Michael Kao)

- Add upper and lower limits support for the power allocator governor
(Lukasz Luba)

- Optimize conditions testing for the trip points (Bernard Zhao)

- Replace spin_lock_irqsave by spin_lock in hard IRQ on the rcar driver
(Tian Tao)

- Add MT8516 dt-bindings and device reset optional support (Fabien
Parent)

- Add a quiescent period to cool down the PCH when entering S0iX
(Sumeet Pawnikar)

- Use bitmap API instead of re-inventing the wheel on sun8i (Yangtao
Li)

- Remove useless NULL check in the hwmon driver (Bernard Zhao)

- Update the current state in the cpufreq cooling device only if the
frequency change is effective (Zhuguangqing)

- Improve the schema validation for the rcar DT bindings (Geert
Uytterhoeven)

- Fix the user time unit in the documentation (Viresh Kumar)

- Add PCI ids for Lewisburg PCH (Andres Freund)

- Add hwmon support on amlogic (Martin Blumenstingl)

- Fix build failure for PCH entering on in S0iX (Randy Dunlap)

- Improve the k_* coefficient for the power allocator governor (Lukasz
Luba)

- Fix missing const on a sysfs attribute (Rikard Falkeborn)

- Remove broken interrupt support on rcar to be replaced by a new one
(Niklas Söderlund)

- Improve the error code handling at init time on imx8mm (Fabio
Estevam)

- Compute interval validity once instead at each temperature reading
iteration on acerhdf (Daniel Lezcano)

- Add r8a779a0 support (Niklas Söderlund)

- Add PCI ids for AlderLake PCH and mmio refactoring (Srinivas
Pandruvada)

- Add RFIM and mailbox support on int340x (Srinivas Pandruvada)

- Use macro for temperature calculation on PCH (Sumeet Pawnikar)

- Simplify return conditions at probe time on Broadcom (Zheng Yongjun)

- Fix workload name on PCH (Srinivas Pandruvada)

- Migrate the devfreq cooling device code to the energy model API
(Lukasz Luba)

- Emit a warning if the thermal_zone_device_update is called without
the .get_temp() ops (Daniel Lezcano)

- Add critical and hot ops for the thermal zone (Daniel Lezcano)

- Remove notification usage when critical is reached on rcar (Daniel
Lezcano)

- Fix devfreq build when ENERGY_MODEL is not set (Lukasz Luba)

* tag 'thermal-v5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (45 commits)
thermal/drivers/devfreq_cooling: Fix the build when !ENERGY_MODEL
thermal/drivers/rcar: Remove notification usage
thermal/core: Add critical and hot ops
thermal/core: Emit a warning if the thermal zone is updated without ops
drm/panfrost: Register devfreq cooling and attempt to add Energy Model
thermal: devfreq_cooling: remove old power model and use EM
thermal: devfreq_cooling: add new registration functions with Energy Model
thermal: devfreq_cooling: use a copy of device status
thermal: devfreq_cooling: change tracing function and arguments
thermal: int340x: processor_thermal: Correct workload type name
thermal: broadcom: simplify the return expression of bcm2711_thermal_probe()
thermal: intel: pch: use macro for temperature calculation
thermal: int340x: processor_thermal: Add mailbox driver
thermal: int340x: processor_thermal: Add RFIM driver
thermal: int340x: processor_thermal: Add AlderLake PCI device id
thermal: int340x: processor_thermal: Refactor MMIO interface
thermal: rcar_gen3_thermal: Add r8a779a0 support
dt-bindings: thermal: rcar-gen3-thermal: Add r8a779a0 support
platform/x86/drivers/acerhdf: Check the interval value when it is set
platform/x86/drivers/acerhdf: Use module_param_cb to set/get polling interval
...

+1290 -811
+2 -1
Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
··· 14 14 - "mediatek,mt2712-thermal" : For MT2712 family of SoCs 15 15 - "mediatek,mt7622-thermal" : For MT7622 SoC 16 16 - "mediatek,mt8183-thermal" : For MT8183 family of SoCs 17 + - "mediatek,mt8516-thermal", "mediatek,mt2701-thermal : For MT8516 family of SoCs 17 18 - reg: Address range of the thermal controller 18 19 - interrupts: IRQ for the thermal controller 19 20 - clocks, clock-names: Clocks needed for the thermal controller. required 20 21 clocks are: 21 22 "therm": Main clock needed for register access 22 23 "auxadc": The AUXADC clock 23 - - resets: Reference to the reset controller controlling the thermal controller. 24 24 - mediatek,auxadc: A phandle to the AUXADC which the thermal controller uses 25 25 - mediatek,apmixedsys: A phandle to the APMIXEDSYS controller. 26 26 - #thermal-sensor-cells : Should be 0. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. 27 27 28 28 Optional properties: 29 + - resets: Reference to the reset controller controlling the thermal controller. 29 30 - nvmem-cells: A phandle to the calibration data provided by a nvmem device. If 30 31 unspecified default values shall be used. 31 32 - nvmem-cell-names: Should be "calibration-data"
+15 -2
Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml
··· 26 26 - renesas,r8a77961-thermal # R-Car M3-W+ 27 27 - renesas,r8a77965-thermal # R-Car M3-N 28 28 - renesas,r8a77980-thermal # R-Car V3H 29 + - renesas,r8a779a0-thermal # R-Car V3U 30 + 29 31 reg: 30 32 minItems: 2 31 - maxItems: 3 33 + maxItems: 4 32 34 items: 33 35 - description: TSC1 registers 34 36 - description: TSC2 registers 35 37 - description: TSC3 registers 38 + - description: TSC4 registers 36 39 37 40 interrupts: 38 41 items: ··· 58 55 required: 59 56 - compatible 60 57 - reg 61 - - interrupts 62 58 - clocks 63 59 - power-domains 64 60 - resets 65 61 - "#thermal-sensor-cells" 62 + 63 + if: 64 + not: 65 + properties: 66 + compatible: 67 + contains: 68 + enum: 69 + - renesas,r8a779a0-thermal 70 + then: 71 + required: 72 + - interrupts 66 73 67 74 additionalProperties: false 68 75
+29 -19
Documentation/devicetree/bindings/thermal/rcar-thermal.yaml
··· 62 62 "#thermal-sensor-cells": 63 63 const: 0 64 64 65 - if: 66 - properties: 67 - compatible: 68 - contains: 69 - enum: 70 - - renesas,thermal-r8a73a4 # R-Mobile APE6 71 - - renesas,thermal-r8a7779 # R-Car H1 72 - then: 73 - required: 74 - - compatible 75 - - reg 76 - else: 77 - required: 78 - - compatible 79 - - reg 80 - - interrupts 81 - - clocks 82 - - power-domains 83 - - resets 65 + required: 66 + - compatible 67 + - reg 68 + 69 + allOf: 70 + - if: 71 + not: 72 + properties: 73 + compatible: 74 + contains: 75 + enum: 76 + - renesas,thermal-r8a73a4 # R-Mobile APE6 77 + - renesas,thermal-r8a7779 # R-Car H1 78 + then: 79 + required: 80 + - resets 81 + - '#thermal-sensor-cells' 82 + 83 + - if: 84 + not: 85 + properties: 86 + compatible: 87 + contains: 88 + const: renesas,thermal-r8a7779 # R-Car H1 89 + then: 90 + required: 91 + - interrupts 92 + - clocks 93 + - power-domains 84 94 85 95 additionalProperties: false 86 96
+1 -2
Documentation/driver-api/thermal/sysfs-api.rst
··· 654 654 The amount of time spent by the cooling device in various cooling 655 655 states. The output will have "<state> <time>" pair in each line, which 656 656 will mean this cooling device spent <time> msec of time at <state>. 657 - Output will have one line for each of the supported states. usertime 658 - units here is 10mS (similar to other time exported in /proc). 657 + Output will have one line for each of the supported states. 659 658 RO, Required 660 659 661 660
+1 -1
drivers/gpu/drm/panfrost/panfrost_devfreq.c
··· 138 138 } 139 139 pfdevfreq->devfreq = devfreq; 140 140 141 - cooling = of_devfreq_cooling_register(dev->of_node, devfreq); 141 + cooling = devfreq_cooling_em_register(devfreq, NULL); 142 142 if (IS_ERR(cooling)) 143 143 DRM_DEV_INFO(dev, "Failed to register cooling device\n"); 144 144 else
+25 -5
drivers/platform/x86/acerhdf.c
··· 84 84 85 85 module_param(kernelmode, uint, 0); 86 86 MODULE_PARM_DESC(kernelmode, "Kernel mode fan control on / off"); 87 - module_param(interval, uint, 0600); 88 - MODULE_PARM_DESC(interval, "Polling interval of temperature check"); 89 87 module_param(fanon, uint, 0600); 90 88 MODULE_PARM_DESC(fanon, "Turn the fan on above this temperature"); 91 89 module_param(fanoff, uint, 0600); ··· 334 336 } 335 337 if (verbose) 336 338 pr_notice("interval changed to: %d\n", interval); 337 - thermal->polling_delay = interval*1000; 339 + 340 + if (thermal) 341 + thermal->polling_delay = interval*1000; 342 + 338 343 prev_interval = interval; 339 344 } 340 345 } ··· 351 350 static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, int *t) 352 351 { 353 352 int temp, err = 0; 354 - 355 - acerhdf_check_param(thermal); 356 353 357 354 err = acerhdf_get_temp(&temp); 358 355 if (err) ··· 823 824 824 825 module_init(acerhdf_init); 825 826 module_exit(acerhdf_exit); 827 + 828 + static int interval_set_uint(const char *val, const struct kernel_param *kp) 829 + { 830 + int ret; 831 + 832 + ret = param_set_uint(val, kp); 833 + if (ret) 834 + return ret; 835 + 836 + acerhdf_check_param(thz_dev); 837 + 838 + return 0; 839 + } 840 + 841 + static const struct kernel_param_ops interval_ops = { 842 + .set = interval_set_uint, 843 + .get = param_get_uint, 844 + }; 845 + 846 + module_param_cb(interval, &interval_ops, &interval, 0600); 847 + MODULE_PARM_DESC(interval, "Polling interval of temperature check");
+4
drivers/thermal/amlogic_thermal.c
··· 29 29 #include <linux/thermal.h> 30 30 31 31 #include "thermal_core.h" 32 + #include "thermal_hwmon.h" 32 33 33 34 #define TSENSOR_CFG_REG1 0x4 34 35 #define TSENSOR_CFG_REG1_RSET_VBG BIT(12) ··· 287 286 dev_err(dev, "Failed to register tsensor: %d\n", ret); 288 287 return ret; 289 288 } 289 + 290 + if (devm_thermal_add_hwmon_sysfs(pdata->tzd)) 291 + dev_warn(&pdev->dev, "Failed to add hwmon sysfs attributes\n"); 290 292 291 293 ret = amlogic_thermal_initialize(pdata); 292 294 if (ret)
+1 -5
drivers/thermal/broadcom/bcm2711_thermal.c
··· 102 102 priv->thermal = thermal; 103 103 104 104 thermal->tzp->no_hwmon = false; 105 - ret = thermal_add_hwmon_sysfs(thermal); 106 - if (ret) 107 - return ret; 108 - 109 - return 0; 105 + return thermal_add_hwmon_sysfs(thermal); 110 106 } 111 107 112 108 static struct platform_driver bcm2711_thermal_driver = {
+1 -3
drivers/thermal/cpufreq_cooling.c
··· 438 438 if (cpufreq_cdev->cpufreq_state == state) 439 439 return 0; 440 440 441 - cpufreq_cdev->cpufreq_state = state; 442 - 443 441 frequency = get_state_freq(cpufreq_cdev, state); 444 442 445 443 ret = freq_qos_update_request(&cpufreq_cdev->qos_req, frequency); 446 - 447 444 if (ret > 0) { 445 + cpufreq_cdev->cpufreq_state = state; 448 446 cpus = cpufreq_cdev->policy->cpus; 449 447 max_capacity = arch_scale_cpu_capacity(cpumask_first(cpus)); 450 448 capacity = frequency * max_capacity;
+176 -212
drivers/thermal/devfreq_cooling.c
··· 12 12 13 13 #include <linux/devfreq.h> 14 14 #include <linux/devfreq_cooling.h> 15 + #include <linux/energy_model.h> 15 16 #include <linux/export.h> 16 17 #include <linux/idr.h> 17 18 #include <linux/slab.h> ··· 34 33 * @cdev: Pointer to associated thermal cooling device. 35 34 * @devfreq: Pointer to associated devfreq device. 36 35 * @cooling_state: Current cooling state. 37 - * @power_table: Pointer to table with maximum power draw for each 38 - * cooling state. State is the index into the table, and 39 - * the power is in mW. 40 36 * @freq_table: Pointer to a table with the frequencies sorted in descending 41 37 * order. You can index the table by cooling device state 42 - * @freq_table_size: Size of the @freq_table and @power_table 43 - * @power_ops: Pointer to devfreq_cooling_power, used to generate the 44 - * @power_table. 38 + * @max_state: It is the last index, that is, one less than the number of the 39 + * OPPs 40 + * @power_ops: Pointer to devfreq_cooling_power, a more precised model. 45 41 * @res_util: Resource utilization scaling factor for the power. 46 42 * It is multiplied by 100 to minimize the error. It is used 47 43 * for estimation of the power budget instead of using 48 - * 'utilization' (which is 'busy_time / 'total_time'). 49 - * The 'res_util' range is from 100 to (power_table[state] * 100) 50 - * for the corresponding 'state'. 44 + * 'utilization' (which is 'busy_time' / 'total_time'). 45 + * The 'res_util' range is from 100 to power * 100 for the 46 + * corresponding 'state'. 51 47 * @capped_state: index to cooling state with in dynamic power budget 52 48 * @req_max_freq: PM QoS request for limiting the maximum frequency 53 49 * of the devfreq device. 50 + * @em_pd: Energy Model for the associated Devfreq device 54 51 */ 55 52 struct devfreq_cooling_device { 56 53 int id; 57 54 struct thermal_cooling_device *cdev; 58 55 struct devfreq *devfreq; 59 56 unsigned long cooling_state; 60 - u32 *power_table; 61 57 u32 *freq_table; 62 - size_t freq_table_size; 58 + size_t max_state; 63 59 struct devfreq_cooling_power *power_ops; 64 60 u32 res_util; 65 61 int capped_state; 66 62 struct dev_pm_qos_request req_max_freq; 63 + struct em_perf_domain *em_pd; 67 64 }; 68 65 69 66 static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev, ··· 69 70 { 70 71 struct devfreq_cooling_device *dfc = cdev->devdata; 71 72 72 - *state = dfc->freq_table_size - 1; 73 + *state = dfc->max_state; 73 74 74 75 return 0; 75 76 } ··· 91 92 struct devfreq *df = dfc->devfreq; 92 93 struct device *dev = df->dev.parent; 93 94 unsigned long freq; 95 + int perf_idx; 94 96 95 97 if (state == dfc->cooling_state) 96 98 return 0; 97 99 98 100 dev_dbg(dev, "Setting cooling state %lu\n", state); 99 101 100 - if (state >= dfc->freq_table_size) 102 + if (state > dfc->max_state) 101 103 return -EINVAL; 102 104 103 - freq = dfc->freq_table[state]; 105 + if (dfc->em_pd) { 106 + perf_idx = dfc->max_state - state; 107 + freq = dfc->em_pd->table[perf_idx].frequency * 1000; 108 + } else { 109 + freq = dfc->freq_table[state]; 110 + } 104 111 105 112 dev_pm_qos_update_request(&dfc->req_max_freq, 106 113 DIV_ROUND_UP(freq, HZ_PER_KHZ)); ··· 117 112 } 118 113 119 114 /** 120 - * freq_get_state() - get the cooling state corresponding to a frequency 121 - * @dfc: Pointer to devfreq cooling device 122 - * @freq: frequency in Hz 115 + * get_perf_idx() - get the performance index corresponding to a frequency 116 + * @em_pd: Pointer to device's Energy Model 117 + * @freq: frequency in kHz 123 118 * 124 - * Return: the cooling state associated with the @freq, or 125 - * THERMAL_CSTATE_INVALID if it wasn't found. 119 + * Return: the performance index associated with the @freq, or 120 + * -EINVAL if it wasn't found. 126 121 */ 127 - static unsigned long 128 - freq_get_state(struct devfreq_cooling_device *dfc, unsigned long freq) 122 + static int get_perf_idx(struct em_perf_domain *em_pd, unsigned long freq) 129 123 { 130 124 int i; 131 125 132 - for (i = 0; i < dfc->freq_table_size; i++) { 133 - if (dfc->freq_table[i] == freq) 126 + for (i = 0; i < em_pd->nr_perf_states; i++) { 127 + if (em_pd->table[i].frequency == freq) 134 128 return i; 135 129 } 136 130 137 - return THERMAL_CSTATE_INVALID; 131 + return -EINVAL; 138 132 } 139 133 140 134 static unsigned long get_voltage(struct devfreq *df, unsigned long freq) ··· 164 160 return voltage; 165 161 } 166 162 167 - /** 168 - * get_static_power() - calculate the static power 169 - * @dfc: Pointer to devfreq cooling device 170 - * @freq: Frequency in Hz 171 - * 172 - * Calculate the static power in milliwatts using the supplied 173 - * get_static_power(). The current voltage is calculated using the 174 - * OPP library. If no get_static_power() was supplied, assume the 175 - * static power is negligible. 176 - */ 177 - static unsigned long 178 - get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq) 163 + static void _normalize_load(struct devfreq_dev_status *status) 179 164 { 180 - struct devfreq *df = dfc->devfreq; 181 - unsigned long voltage; 165 + if (status->total_time > 0xfffff) { 166 + status->total_time >>= 10; 167 + status->busy_time >>= 10; 168 + } 182 169 183 - if (!dfc->power_ops->get_static_power) 184 - return 0; 170 + status->busy_time <<= 10; 171 + status->busy_time /= status->total_time ? : 1; 185 172 186 - voltage = get_voltage(df, freq); 187 - 188 - if (voltage == 0) 189 - return 0; 190 - 191 - return dfc->power_ops->get_static_power(df, voltage); 173 + status->busy_time = status->busy_time ? : 1; 174 + status->total_time = 1024; 192 175 } 193 - 194 - /** 195 - * get_dynamic_power - calculate the dynamic power 196 - * @dfc: Pointer to devfreq cooling device 197 - * @freq: Frequency in Hz 198 - * @voltage: Voltage in millivolts 199 - * 200 - * Calculate the dynamic power in milliwatts consumed by the device at 201 - * frequency @freq and voltage @voltage. If the get_dynamic_power() 202 - * was supplied as part of the devfreq_cooling_power struct, then that 203 - * function is used. Otherwise, a simple power model (Pdyn = Coeff * 204 - * Voltage^2 * Frequency) is used. 205 - */ 206 - static unsigned long 207 - get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq, 208 - unsigned long voltage) 209 - { 210 - u64 power; 211 - u32 freq_mhz; 212 - struct devfreq_cooling_power *dfc_power = dfc->power_ops; 213 - 214 - if (dfc_power->get_dynamic_power) 215 - return dfc_power->get_dynamic_power(dfc->devfreq, freq, 216 - voltage); 217 - 218 - freq_mhz = freq / 1000000; 219 - power = (u64)dfc_power->dyn_power_coeff * freq_mhz * voltage * voltage; 220 - do_div(power, 1000000000); 221 - 222 - return power; 223 - } 224 - 225 - 226 - static inline unsigned long get_total_power(struct devfreq_cooling_device *dfc, 227 - unsigned long freq, 228 - unsigned long voltage) 229 - { 230 - return get_static_power(dfc, freq) + get_dynamic_power(dfc, freq, 231 - voltage); 232 - } 233 - 234 176 235 177 static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev, 236 178 u32 *power) 237 179 { 238 180 struct devfreq_cooling_device *dfc = cdev->devdata; 239 181 struct devfreq *df = dfc->devfreq; 240 - struct devfreq_dev_status *status = &df->last_status; 182 + struct devfreq_dev_status status; 241 183 unsigned long state; 242 - unsigned long freq = status->current_frequency; 184 + unsigned long freq; 243 185 unsigned long voltage; 244 - u32 dyn_power = 0; 245 - u32 static_power = 0; 246 - int res; 186 + int res, perf_idx; 247 187 248 - state = freq_get_state(dfc, freq); 249 - if (state == THERMAL_CSTATE_INVALID) { 250 - res = -EAGAIN; 251 - goto fail; 252 - } 188 + mutex_lock(&df->lock); 189 + status = df->last_status; 190 + mutex_unlock(&df->lock); 253 191 254 - if (dfc->power_ops->get_real_power) { 192 + freq = status.current_frequency; 193 + 194 + if (dfc->power_ops && dfc->power_ops->get_real_power) { 255 195 voltage = get_voltage(df, freq); 256 196 if (voltage == 0) { 257 197 res = -EINVAL; ··· 205 257 res = dfc->power_ops->get_real_power(df, power, freq, voltage); 206 258 if (!res) { 207 259 state = dfc->capped_state; 208 - dfc->res_util = dfc->power_table[state]; 260 + dfc->res_util = dfc->em_pd->table[state].power; 209 261 dfc->res_util *= SCALE_ERROR_MITIGATION; 210 262 211 263 if (*power > 1) ··· 214 266 goto fail; 215 267 } 216 268 } else { 217 - dyn_power = dfc->power_table[state]; 269 + /* Energy Model frequencies are in kHz */ 270 + perf_idx = get_perf_idx(dfc->em_pd, freq / 1000); 271 + if (perf_idx < 0) { 272 + res = -EAGAIN; 273 + goto fail; 274 + } 218 275 219 - /* Scale dynamic power for utilization */ 220 - dyn_power *= status->busy_time; 221 - dyn_power /= status->total_time; 222 - /* Get static power */ 223 - static_power = get_static_power(dfc, freq); 276 + _normalize_load(&status); 224 277 225 - *power = dyn_power + static_power; 278 + /* Scale power for utilization */ 279 + *power = dfc->em_pd->table[perf_idx].power; 280 + *power *= status.busy_time; 281 + *power >>= 10; 226 282 } 227 283 228 - trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power, 229 - static_power, *power); 284 + trace_thermal_power_devfreq_get_power(cdev, &status, freq, *power); 230 285 231 286 return 0; 232 287 fail: ··· 239 288 } 240 289 241 290 static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, 242 - unsigned long state, 243 - u32 *power) 291 + unsigned long state, u32 *power) 244 292 { 245 293 struct devfreq_cooling_device *dfc = cdev->devdata; 246 - unsigned long freq; 247 - u32 static_power; 294 + int perf_idx; 248 295 249 - if (state >= dfc->freq_table_size) 296 + if (state > dfc->max_state) 250 297 return -EINVAL; 251 298 252 - freq = dfc->freq_table[state]; 253 - static_power = get_static_power(dfc, freq); 299 + perf_idx = dfc->max_state - state; 300 + *power = dfc->em_pd->table[perf_idx].power; 254 301 255 - *power = dfc->power_table[state] + static_power; 256 302 return 0; 257 303 } 258 304 ··· 258 310 { 259 311 struct devfreq_cooling_device *dfc = cdev->devdata; 260 312 struct devfreq *df = dfc->devfreq; 261 - struct devfreq_dev_status *status = &df->last_status; 262 - unsigned long freq = status->current_frequency; 263 - unsigned long busy_time; 264 - s32 dyn_power; 265 - u32 static_power; 313 + struct devfreq_dev_status status; 314 + unsigned long freq; 266 315 s32 est_power; 267 316 int i; 268 317 269 - if (dfc->power_ops->get_real_power) { 318 + mutex_lock(&df->lock); 319 + status = df->last_status; 320 + mutex_unlock(&df->lock); 321 + 322 + freq = status.current_frequency; 323 + 324 + if (dfc->power_ops && dfc->power_ops->get_real_power) { 270 325 /* Scale for resource utilization */ 271 326 est_power = power * dfc->res_util; 272 327 est_power /= SCALE_ERROR_MITIGATION; 273 328 } else { 274 - static_power = get_static_power(dfc, freq); 275 - 276 - dyn_power = power - static_power; 277 - dyn_power = dyn_power > 0 ? dyn_power : 0; 278 - 279 329 /* Scale dynamic power for utilization */ 280 - busy_time = status->busy_time ?: 1; 281 - est_power = (dyn_power * status->total_time) / busy_time; 330 + _normalize_load(&status); 331 + est_power = power << 10; 332 + est_power /= status.busy_time; 282 333 } 283 334 284 335 /* 285 336 * Find the first cooling state that is within the power 286 - * budget for dynamic power. 337 + * budget. The EM power table is sorted ascending. 287 338 */ 288 - for (i = 0; i < dfc->freq_table_size - 1; i++) 289 - if (est_power >= dfc->power_table[i]) 339 + for (i = dfc->max_state; i > 0; i--) 340 + if (est_power >= dfc->em_pd->table[i].power) 290 341 break; 291 342 292 - *state = i; 293 - dfc->capped_state = i; 343 + *state = dfc->max_state - i; 344 + dfc->capped_state = *state; 345 + 294 346 trace_thermal_power_devfreq_limit(cdev, freq, *state, power); 295 347 return 0; 296 348 } ··· 302 354 }; 303 355 304 356 /** 305 - * devfreq_cooling_gen_tables() - Generate power and freq tables. 306 - * @dfc: Pointer to devfreq cooling device. 357 + * devfreq_cooling_gen_tables() - Generate frequency table. 358 + * @dfc: Pointer to devfreq cooling device. 359 + * @num_opps: Number of OPPs 307 360 * 308 - * Generate power and frequency tables: the power table hold the 309 - * device's maximum power usage at each cooling state (OPP). The 310 - * static and dynamic power using the appropriate voltage and 311 - * frequency for the state, is acquired from the struct 312 - * devfreq_cooling_power, and summed to make the maximum power draw. 313 - * 314 - * The frequency table holds the frequencies in descending order. 315 - * That way its indexed by cooling device state. 316 - * 317 - * The tables are malloced, and pointers put in dfc. They must be 318 - * freed when unregistering the devfreq cooling device. 361 + * Generate frequency table which holds the frequencies in descending 362 + * order. That way its indexed by cooling device state. This is for 363 + * compatibility with drivers which do not register Energy Model. 319 364 * 320 365 * Return: 0 on success, negative error code on failure. 321 366 */ 322 - static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc) 367 + static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc, 368 + int num_opps) 323 369 { 324 370 struct devfreq *df = dfc->devfreq; 325 371 struct device *dev = df->dev.parent; 326 - int ret, num_opps; 327 372 unsigned long freq; 328 - u32 *power_table = NULL; 329 - u32 *freq_table; 330 373 int i; 331 374 332 - num_opps = dev_pm_opp_get_opp_count(dev); 333 - 334 - if (dfc->power_ops) { 335 - power_table = kcalloc(num_opps, sizeof(*power_table), 336 - GFP_KERNEL); 337 - if (!power_table) 338 - return -ENOMEM; 339 - } 340 - 341 - freq_table = kcalloc(num_opps, sizeof(*freq_table), 375 + dfc->freq_table = kcalloc(num_opps, sizeof(*dfc->freq_table), 342 376 GFP_KERNEL); 343 - if (!freq_table) { 344 - ret = -ENOMEM; 345 - goto free_power_table; 346 - } 377 + if (!dfc->freq_table) 378 + return -ENOMEM; 347 379 348 380 for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) { 349 - unsigned long power, voltage; 350 381 struct dev_pm_opp *opp; 351 382 352 383 opp = dev_pm_opp_find_freq_floor(dev, &freq); 353 384 if (IS_ERR(opp)) { 354 - ret = PTR_ERR(opp); 355 - goto free_tables; 385 + kfree(dfc->freq_table); 386 + return PTR_ERR(opp); 356 387 } 357 388 358 - voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ 359 389 dev_pm_opp_put(opp); 360 - 361 - if (dfc->power_ops) { 362 - if (dfc->power_ops->get_real_power) 363 - power = get_total_power(dfc, freq, voltage); 364 - else 365 - power = get_dynamic_power(dfc, freq, voltage); 366 - 367 - dev_dbg(dev, "Power table: %lu MHz @ %lu mV: %lu = %lu mW\n", 368 - freq / 1000000, voltage, power, power); 369 - 370 - power_table[i] = power; 371 - } 372 - 373 - freq_table[i] = freq; 390 + dfc->freq_table[i] = freq; 374 391 } 375 392 376 - if (dfc->power_ops) 377 - dfc->power_table = power_table; 378 - 379 - dfc->freq_table = freq_table; 380 - dfc->freq_table_size = num_opps; 381 - 382 393 return 0; 383 - 384 - free_tables: 385 - kfree(freq_table); 386 - free_power_table: 387 - kfree(power_table); 388 - 389 - return ret; 390 394 } 391 395 392 396 /** ··· 361 461 struct devfreq_cooling_power *dfc_power) 362 462 { 363 463 struct thermal_cooling_device *cdev; 464 + struct device *dev = df->dev.parent; 364 465 struct devfreq_cooling_device *dfc; 365 466 char dev_name[THERMAL_NAME_LENGTH]; 366 - int err; 467 + int err, num_opps; 367 468 368 469 dfc = kzalloc(sizeof(*dfc), GFP_KERNEL); 369 470 if (!dfc) ··· 372 471 373 472 dfc->devfreq = df; 374 473 375 - if (dfc_power) { 376 - dfc->power_ops = dfc_power; 377 - 474 + dfc->em_pd = em_pd_get(dev); 475 + if (dfc->em_pd) { 378 476 devfreq_cooling_ops.get_requested_power = 379 477 devfreq_cooling_get_requested_power; 380 478 devfreq_cooling_ops.state2power = devfreq_cooling_state2power; 381 479 devfreq_cooling_ops.power2state = devfreq_cooling_power2state; 480 + 481 + dfc->power_ops = dfc_power; 482 + 483 + num_opps = em_pd_nr_perf_states(dfc->em_pd); 484 + } else { 485 + /* Backward compatibility for drivers which do not use IPA */ 486 + dev_dbg(dev, "missing EM for cooling device\n"); 487 + 488 + num_opps = dev_pm_opp_get_opp_count(dev); 489 + 490 + err = devfreq_cooling_gen_tables(dfc, num_opps); 491 + if (err) 492 + goto free_dfc; 382 493 } 383 494 384 - err = devfreq_cooling_gen_tables(dfc); 385 - if (err) 495 + if (num_opps <= 0) { 496 + err = -EINVAL; 386 497 goto free_dfc; 498 + } 387 499 388 - err = dev_pm_qos_add_request(df->dev.parent, &dfc->req_max_freq, 500 + /* max_state is an index, not a counter */ 501 + dfc->max_state = num_opps - 1; 502 + 503 + err = dev_pm_qos_add_request(dev, &dfc->req_max_freq, 389 504 DEV_PM_QOS_MAX_FREQUENCY, 390 505 PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); 391 506 if (err < 0) 392 - goto free_tables; 507 + goto free_table; 393 508 394 509 err = ida_simple_get(&devfreq_ida, 0, 0, GFP_KERNEL); 395 510 if (err < 0) 396 511 goto remove_qos_req; 512 + 397 513 dfc->id = err; 398 514 399 515 snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id); ··· 419 501 &devfreq_cooling_ops); 420 502 if (IS_ERR(cdev)) { 421 503 err = PTR_ERR(cdev); 422 - dev_err(df->dev.parent, 504 + dev_err(dev, 423 505 "Failed to register devfreq cooling device (%d)\n", 424 506 err); 425 507 goto release_ida; ··· 431 513 432 514 release_ida: 433 515 ida_simple_remove(&devfreq_ida, dfc->id); 434 - 435 516 remove_qos_req: 436 517 dev_pm_qos_remove_request(&dfc->req_max_freq); 437 - 438 - free_tables: 439 - kfree(dfc->power_table); 518 + free_table: 440 519 kfree(dfc->freq_table); 441 520 free_dfc: 442 521 kfree(dfc); ··· 466 551 EXPORT_SYMBOL_GPL(devfreq_cooling_register); 467 552 468 553 /** 554 + * devfreq_cooling_em_register_power() - Register devfreq cooling device with 555 + * power information and automatically register Energy Model (EM) 556 + * @df: Pointer to devfreq device. 557 + * @dfc_power: Pointer to devfreq_cooling_power. 558 + * 559 + * Register a devfreq cooling device and automatically register EM. The 560 + * available OPPs must be registered for the device. 561 + * 562 + * If @dfc_power is provided, the cooling device is registered with the 563 + * power extensions. It is using the simple Energy Model which requires 564 + * "dynamic-power-coefficient" a devicetree property. To not break drivers 565 + * which miss that DT property, the function won't bail out when the EM 566 + * registration failed. The cooling device will be registered if everything 567 + * else is OK. 568 + */ 569 + struct thermal_cooling_device * 570 + devfreq_cooling_em_register(struct devfreq *df, 571 + struct devfreq_cooling_power *dfc_power) 572 + { 573 + struct thermal_cooling_device *cdev; 574 + struct device *dev; 575 + int ret; 576 + 577 + if (IS_ERR_OR_NULL(df)) 578 + return ERR_PTR(-EINVAL); 579 + 580 + dev = df->dev.parent; 581 + 582 + ret = dev_pm_opp_of_register_em(dev, NULL); 583 + if (ret) 584 + dev_dbg(dev, "Unable to register EM for devfreq cooling device (%d)\n", 585 + ret); 586 + 587 + cdev = of_devfreq_cooling_register_power(dev->of_node, df, dfc_power); 588 + 589 + if (IS_ERR_OR_NULL(cdev)) 590 + em_dev_unregister_perf_domain(dev); 591 + 592 + return cdev; 593 + } 594 + EXPORT_SYMBOL_GPL(devfreq_cooling_em_register); 595 + 596 + /** 469 597 * devfreq_cooling_unregister() - Unregister devfreq cooling device. 470 598 * @cdev: Pointer to devfreq cooling device to unregister. 599 + * 600 + * Unregisters devfreq cooling device and related Energy Model if it was 601 + * present. 471 602 */ 472 603 void devfreq_cooling_unregister(struct thermal_cooling_device *cdev) 473 604 { 474 605 struct devfreq_cooling_device *dfc; 606 + struct device *dev; 475 607 476 - if (!cdev) 608 + if (IS_ERR_OR_NULL(cdev)) 477 609 return; 478 610 479 611 dfc = cdev->devdata; 612 + dev = dfc->devfreq->dev.parent; 480 613 481 614 thermal_cooling_device_unregister(dfc->cdev); 482 615 ida_simple_remove(&devfreq_ida, dfc->id); 483 616 dev_pm_qos_remove_request(&dfc->req_max_freq); 484 - kfree(dfc->power_table); 485 - kfree(dfc->freq_table); 486 617 618 + em_dev_unregister_perf_domain(dev); 619 + 620 + kfree(dfc->freq_table); 487 621 kfree(dfc); 488 622 } 489 623 EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
+87 -29
drivers/thermal/gov_power_allocator.c
··· 63 63 * @trip_max_desired_temperature: last passive trip point of the thermal 64 64 * zone. The temperature we are 65 65 * controlling for. 66 + * @sustainable_power: Sustainable power (heat) that this thermal zone can 67 + * dissipate 66 68 */ 67 69 struct power_allocator_params { 68 70 bool allocated_tzp; ··· 72 70 s32 prev_err; 73 71 int trip_switch_on; 74 72 int trip_max_desired_temperature; 73 + u32 sustainable_power; 75 74 }; 76 75 77 76 /** ··· 99 96 if (instance->trip != params->trip_max_desired_temperature) 100 97 continue; 101 98 102 - if (power_actor_get_min_power(cdev, &min_power)) 99 + if (!cdev_is_power_actor(cdev)) 100 + continue; 101 + 102 + if (cdev->ops->state2power(cdev, instance->upper, &min_power)) 103 103 continue; 104 104 105 105 sustainable_power += min_power; ··· 117 111 * @sustainable_power: sustainable power for the thermal zone 118 112 * @trip_switch_on: trip point number for the switch on temperature 119 113 * @control_temp: target temperature for the power allocator governor 120 - * @force: whether to force the update of the constants 121 114 * 122 115 * This function is used to update the estimation of the PID 123 116 * controller constants in struct thermal_zone_parameters. 124 - * Sustainable power is provided in case it was estimated. The 125 - * estimated sustainable_power should not be stored in the 126 - * thermal_zone_parameters so it has to be passed explicitly to this 127 - * function. 128 - * 129 - * If @force is not set, the values in the thermal zone's parameters 130 - * are preserved if they are not zero. If @force is set, the values 131 - * in thermal zone's parameters are overwritten. 132 117 */ 133 118 static void estimate_pid_constants(struct thermal_zone_device *tz, 134 119 u32 sustainable_power, int trip_switch_on, 135 - int control_temp, bool force) 120 + int control_temp) 136 121 { 137 122 int ret; 138 123 int switch_on_temp; 139 124 u32 temperature_threshold; 125 + s32 k_i; 140 126 141 127 ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp); 142 128 if (ret) ··· 146 148 if (!temperature_threshold) 147 149 return; 148 150 149 - if (!tz->tzp->k_po || force) 150 - tz->tzp->k_po = int_to_frac(sustainable_power) / 151 - temperature_threshold; 151 + tz->tzp->k_po = int_to_frac(sustainable_power) / 152 + temperature_threshold; 152 153 153 - if (!tz->tzp->k_pu || force) 154 - tz->tzp->k_pu = int_to_frac(2 * sustainable_power) / 155 - temperature_threshold; 154 + tz->tzp->k_pu = int_to_frac(2 * sustainable_power) / 155 + temperature_threshold; 156 156 157 - if (!tz->tzp->k_i || force) 158 - tz->tzp->k_i = int_to_frac(10) / 1000; 157 + k_i = tz->tzp->k_pu / 10; 158 + tz->tzp->k_i = k_i > 0 ? k_i : 1; 159 + 159 160 /* 160 161 * The default for k_d and integral_cutoff is 0, so we can 161 162 * leave them as they are. 162 163 */ 164 + } 165 + 166 + /** 167 + * get_sustainable_power() - Get the right sustainable power 168 + * @tz: thermal zone for which to estimate the constants 169 + * @params: parameters for the power allocator governor 170 + * @control_temp: target temperature for the power allocator governor 171 + * 172 + * This function is used for getting the proper sustainable power value based 173 + * on variables which might be updated by the user sysfs interface. If that 174 + * happen the new value is going to be estimated and updated. It is also used 175 + * after thermal zone binding, where the initial values where set to 0. 176 + */ 177 + static u32 get_sustainable_power(struct thermal_zone_device *tz, 178 + struct power_allocator_params *params, 179 + int control_temp) 180 + { 181 + u32 sustainable_power; 182 + 183 + if (!tz->tzp->sustainable_power) 184 + sustainable_power = estimate_sustainable_power(tz); 185 + else 186 + sustainable_power = tz->tzp->sustainable_power; 187 + 188 + /* Check if it's init value 0 or there was update via sysfs */ 189 + if (sustainable_power != params->sustainable_power) { 190 + estimate_pid_constants(tz, sustainable_power, 191 + params->trip_switch_on, control_temp); 192 + 193 + /* Do the estimation only once and make available in sysfs */ 194 + tz->tzp->sustainable_power = sustainable_power; 195 + params->sustainable_power = sustainable_power; 196 + } 197 + 198 + return sustainable_power; 163 199 } 164 200 165 201 /** ··· 225 193 226 194 max_power_frac = int_to_frac(max_allocatable_power); 227 195 228 - if (tz->tzp->sustainable_power) { 229 - sustainable_power = tz->tzp->sustainable_power; 230 - } else { 231 - sustainable_power = estimate_sustainable_power(tz); 232 - estimate_pid_constants(tz, sustainable_power, 233 - params->trip_switch_on, control_temp, 234 - true); 235 - } 196 + sustainable_power = get_sustainable_power(tz, params, control_temp); 236 197 237 198 err = control_temp - tz->temperature; 238 199 err = int_to_frac(err); ··· 274 249 frac_to_int(d), power_range); 275 250 276 251 return power_range; 252 + } 253 + 254 + /** 255 + * power_actor_set_power() - limit the maximum power a cooling device consumes 256 + * @cdev: pointer to &thermal_cooling_device 257 + * @instance: thermal instance to update 258 + * @power: the power in milliwatts 259 + * 260 + * Set the cooling device to consume at most @power milliwatts. The limit is 261 + * expected to be a cap at the maximum power consumption. 262 + * 263 + * Return: 0 on success, -EINVAL if the cooling device does not 264 + * implement the power actor API or -E* for other failures. 265 + */ 266 + static int 267 + power_actor_set_power(struct thermal_cooling_device *cdev, 268 + struct thermal_instance *instance, u32 power) 269 + { 270 + unsigned long state; 271 + int ret; 272 + 273 + ret = cdev->ops->power2state(cdev, power, &state); 274 + if (ret) 275 + return ret; 276 + 277 + instance->target = clamp_val(state, instance->lower, instance->upper); 278 + mutex_lock(&cdev->lock); 279 + cdev->updated = false; 280 + mutex_unlock(&cdev->lock); 281 + thermal_cdev_update(cdev); 282 + 283 + return 0; 277 284 } 278 285 279 286 /** ··· 455 398 456 399 weighted_req_power[i] = frac_to_int(weight * req_power[i]); 457 400 458 - if (power_actor_get_max_power(cdev, &max_power[i])) 401 + if (cdev->ops->state2power(cdev, instance->lower, 402 + &max_power[i])) 459 403 continue; 460 404 461 405 total_req_power += req_power[i]; ··· 630 572 if (!ret) 631 573 estimate_pid_constants(tz, tz->tzp->sustainable_power, 632 574 params->trip_switch_on, 633 - control_temp, false); 575 + control_temp); 634 576 } 635 577 636 578 reset_pid_controller(params);
+6 -1
drivers/thermal/imx8mm_thermal.c
··· 166 166 &tmu->sensors[i], 167 167 &tmu_tz_ops); 168 168 if (IS_ERR(tmu->sensors[i].tzd)) { 169 + ret = PTR_ERR(tmu->sensors[i].tzd); 169 170 dev_err(&pdev->dev, 170 171 "failed to register thermal zone sensor[%d]: %d\n", 171 172 i, ret); 172 - return PTR_ERR(tmu->sensors[i].tzd); 173 + goto disable_clk; 173 174 } 174 175 tmu->sensors[i].hw_id = i; 175 176 } ··· 185 184 imx8mm_tmu_enable(tmu, true); 186 185 187 186 return 0; 187 + 188 + disable_clk: 189 + clk_disable_unprepare(tmu->clk); 190 + return ret; 188 191 } 189 192 190 193 static int imx8mm_tmu_remove(struct platform_device *pdev)
+2 -4
drivers/thermal/intel/int340x_thermal/Kconfig
··· 10 10 select ACPI_THERMAL_REL 11 11 select ACPI_FAN 12 12 select INTEL_SOC_DTS_IOSF_CORE 13 + select PROC_THERMAL_MMIO_RAPL if X86_64 && POWERCAP 13 14 help 14 15 Newer laptops and tablets that use ACPI may have thermal sensors and 15 16 other devices with thermal control capabilities outside the core ··· 42 41 power consumed by display device. 43 42 44 43 config PROC_THERMAL_MMIO_RAPL 45 - bool 46 - depends on 64BIT 47 - depends on POWERCAP 44 + tristate 48 45 select INTEL_RAPL_CORE 49 - default y 50 46 endif
+3
drivers/thermal/intel/int340x_thermal/Makefile
··· 4 4 obj-$(CONFIG_INT340X_THERMAL) += int3402_thermal.o 5 5 obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o 6 6 obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device.o 7 + obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o 8 + obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o 9 + obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o 7 10 obj-$(CONFIG_INT3406_THERMAL) += int3406_thermal.o 8 11 obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o
+92 -214
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
··· 12 12 #include <linux/acpi.h> 13 13 #include <linux/thermal.h> 14 14 #include <linux/cpuhotplug.h> 15 - #include <linux/intel_rapl.h> 16 15 #include "int340x_thermal_zone.h" 16 + #include "processor_thermal_device.h" 17 17 #include "../intel_soc_dts_iosf.h" 18 18 19 - /* Broadwell-U/HSB thermal reporting device */ 20 - #define PCI_DEVICE_ID_PROC_BDW_THERMAL 0x1603 21 - #define PCI_DEVICE_ID_PROC_HSB_THERMAL 0x0A03 22 - 23 - /* Skylake thermal reporting device */ 24 - #define PCI_DEVICE_ID_PROC_SKL_THERMAL 0x1903 25 - 26 - /* CannonLake thermal reporting device */ 27 - #define PCI_DEVICE_ID_PROC_CNL_THERMAL 0x5a03 28 - #define PCI_DEVICE_ID_PROC_CFL_THERMAL 0x3E83 29 - 30 - /* Braswell thermal reporting device */ 31 - #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC 32 - 33 - /* Broxton thermal reporting device */ 34 - #define PCI_DEVICE_ID_PROC_BXT0_THERMAL 0x0A8C 35 - #define PCI_DEVICE_ID_PROC_BXT1_THERMAL 0x1A8C 36 - #define PCI_DEVICE_ID_PROC_BXTX_THERMAL 0x4A8C 37 - #define PCI_DEVICE_ID_PROC_BXTP_THERMAL 0x5A8C 38 - 39 - /* GeminiLake thermal reporting device */ 40 - #define PCI_DEVICE_ID_PROC_GLK_THERMAL 0x318C 41 - 42 - /* IceLake thermal reporting device */ 43 - #define PCI_DEVICE_ID_PROC_ICL_THERMAL 0x8a03 44 - 45 - /* JasperLake thermal reporting device */ 46 - #define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4E03 47 - 48 - /* TigerLake thermal reporting device */ 49 - #define PCI_DEVICE_ID_PROC_TGL_THERMAL 0x9A03 50 - 51 19 #define DRV_NAME "proc_thermal" 52 - 53 - struct power_config { 54 - u32 index; 55 - u32 min_uw; 56 - u32 max_uw; 57 - u32 tmin_us; 58 - u32 tmax_us; 59 - u32 step_uw; 60 - }; 61 - 62 - struct proc_thermal_device { 63 - struct device *dev; 64 - struct acpi_device *adev; 65 - struct power_config power_limits[2]; 66 - struct int34x_thermal_zone *int340x_zone; 67 - struct intel_soc_dts_sensors *soc_dts; 68 - void __iomem *mmio_base; 69 - }; 70 20 71 21 enum proc_thermal_emum_mode_type { 72 22 PROC_THERMAL_NONE, 73 23 PROC_THERMAL_PCI, 74 24 PROC_THERMAL_PLATFORM_DEV 75 - }; 76 - 77 - struct rapl_mmio_regs { 78 - u64 reg_unit; 79 - u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX]; 80 - int limits[RAPL_DOMAIN_MAX]; 81 25 }; 82 26 83 27 /* ··· 405 461 return IRQ_HANDLED; 406 462 } 407 463 408 - #ifdef CONFIG_PROC_THERMAL_MMIO_RAPL 409 - 410 464 #define MCHBAR 0 411 465 412 - /* RAPL Support via MMIO interface */ 413 - static struct rapl_if_priv rapl_mmio_priv; 414 - 415 - static int rapl_mmio_cpu_online(unsigned int cpu) 466 + static int proc_thermal_set_mmio_base(struct pci_dev *pdev, 467 + struct proc_thermal_device *proc_priv) 416 468 { 417 - struct rapl_package *rp; 418 - 419 - /* mmio rapl supports package 0 only for now */ 420 - if (topology_physical_package_id(cpu)) 421 - return 0; 422 - 423 - rp = rapl_find_package_domain(cpu, &rapl_mmio_priv); 424 - if (!rp) { 425 - rp = rapl_add_package(cpu, &rapl_mmio_priv); 426 - if (IS_ERR(rp)) 427 - return PTR_ERR(rp); 428 - } 429 - cpumask_set_cpu(cpu, &rp->cpumask); 430 - return 0; 431 - } 432 - 433 - static int rapl_mmio_cpu_down_prep(unsigned int cpu) 434 - { 435 - struct rapl_package *rp; 436 - int lead_cpu; 437 - 438 - rp = rapl_find_package_domain(cpu, &rapl_mmio_priv); 439 - if (!rp) 440 - return 0; 441 - 442 - cpumask_clear_cpu(cpu, &rp->cpumask); 443 - lead_cpu = cpumask_first(&rp->cpumask); 444 - if (lead_cpu >= nr_cpu_ids) 445 - rapl_remove_package(rp); 446 - else if (rp->lead_cpu == cpu) 447 - rp->lead_cpu = lead_cpu; 448 - return 0; 449 - } 450 - 451 - static int rapl_mmio_read_raw(int cpu, struct reg_action *ra) 452 - { 453 - if (!ra->reg) 454 - return -EINVAL; 455 - 456 - ra->value = readq((void __iomem *)ra->reg); 457 - ra->value &= ra->mask; 458 - return 0; 459 - } 460 - 461 - static int rapl_mmio_write_raw(int cpu, struct reg_action *ra) 462 - { 463 - u64 val; 464 - 465 - if (!ra->reg) 466 - return -EINVAL; 467 - 468 - val = readq((void __iomem *)ra->reg); 469 - val &= ~ra->mask; 470 - val |= ra->value; 471 - writeq(val, (void __iomem *)ra->reg); 472 - return 0; 473 - } 474 - 475 - static int proc_thermal_rapl_add(struct pci_dev *pdev, 476 - struct proc_thermal_device *proc_priv, 477 - struct rapl_mmio_regs *rapl_regs) 478 - { 479 - enum rapl_domain_reg_id reg; 480 - enum rapl_domain_type domain; 481 469 int ret; 482 - 483 - if (!rapl_regs) 484 - return 0; 485 470 486 471 ret = pcim_iomap_regions(pdev, 1 << MCHBAR, DRV_NAME); 487 472 if (ret) { ··· 420 547 421 548 proc_priv->mmio_base = pcim_iomap_table(pdev)[MCHBAR]; 422 549 423 - for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) { 424 - for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++) 425 - if (rapl_regs->regs[domain][reg]) 426 - rapl_mmio_priv.regs[domain][reg] = 427 - (u64)proc_priv->mmio_base + 428 - rapl_regs->regs[domain][reg]; 429 - rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain]; 430 - } 431 - rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit; 432 - 433 - rapl_mmio_priv.read_raw = rapl_mmio_read_raw; 434 - rapl_mmio_priv.write_raw = rapl_mmio_write_raw; 435 - 436 - rapl_mmio_priv.control_type = powercap_register_control_type(NULL, "intel-rapl-mmio", NULL); 437 - if (IS_ERR(rapl_mmio_priv.control_type)) { 438 - pr_debug("failed to register powercap control_type.\n"); 439 - return PTR_ERR(rapl_mmio_priv.control_type); 440 - } 441 - 442 - ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online", 443 - rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep); 444 - if (ret < 0) { 445 - powercap_unregister_control_type(rapl_mmio_priv.control_type); 446 - rapl_mmio_priv.control_type = NULL; 447 - return ret; 448 - } 449 - rapl_mmio_priv.pcap_rapl_online = ret; 450 - 451 550 return 0; 452 551 } 453 552 454 - static void proc_thermal_rapl_remove(void) 455 - { 456 - if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type)) 457 - return; 458 - 459 - cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online); 460 - powercap_unregister_control_type(rapl_mmio_priv.control_type); 461 - } 462 - 463 - static const struct rapl_mmio_regs rapl_mmio_hsw = { 464 - .reg_unit = 0x5938, 465 - .regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930}, 466 - .regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0}, 467 - .limits[RAPL_DOMAIN_PACKAGE] = 2, 468 - .limits[RAPL_DOMAIN_DRAM] = 2, 469 - }; 470 - 471 - #else 472 - 473 - static int proc_thermal_rapl_add(struct pci_dev *pdev, 553 + static int proc_thermal_mmio_add(struct pci_dev *pdev, 474 554 struct proc_thermal_device *proc_priv, 475 - struct rapl_mmio_regs *rapl_regs) 555 + kernel_ulong_t feature_mask) 476 556 { 477 - return 0; 478 - } 479 - static void proc_thermal_rapl_remove(void) {} 480 - static const struct rapl_mmio_regs rapl_mmio_hsw; 557 + int ret; 481 558 482 - #endif /* CONFIG_MMIO_RAPL */ 559 + proc_priv->mmio_feature_mask = feature_mask; 560 + 561 + if (feature_mask) { 562 + ret = proc_thermal_set_mmio_base(pdev, proc_priv); 563 + if (ret) 564 + return ret; 565 + } 566 + 567 + if (feature_mask & PROC_THERMAL_FEATURE_RAPL) { 568 + ret = proc_thermal_rapl_add(pdev, proc_priv); 569 + if (ret) { 570 + dev_err(&pdev->dev, "failed to add RAPL MMIO interface\n"); 571 + return ret; 572 + } 573 + } 574 + 575 + if (feature_mask & PROC_THERMAL_FEATURE_FIVR || 576 + feature_mask & PROC_THERMAL_FEATURE_DVFS) { 577 + ret = proc_thermal_rfim_add(pdev, proc_priv); 578 + if (ret) { 579 + dev_err(&pdev->dev, "failed to add RFIM interface\n"); 580 + goto err_rem_rapl; 581 + } 582 + } 583 + 584 + if (feature_mask & PROC_THERMAL_FEATURE_MBOX) { 585 + ret = proc_thermal_mbox_add(pdev, proc_priv); 586 + if (ret) { 587 + dev_err(&pdev->dev, "failed to add MBOX interface\n"); 588 + goto err_rem_rfim; 589 + } 590 + } 591 + 592 + return 0; 593 + 594 + err_rem_rfim: 595 + proc_thermal_rfim_remove(pdev); 596 + err_rem_rapl: 597 + proc_thermal_rapl_remove(); 598 + 599 + return ret; 600 + } 601 + 602 + static void proc_thermal_mmio_remove(struct pci_dev *pdev) 603 + { 604 + struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); 605 + 606 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_RAPL) 607 + proc_thermal_rapl_remove(); 608 + 609 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR || 610 + proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) 611 + proc_thermal_rfim_remove(pdev); 612 + 613 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MBOX) 614 + proc_thermal_mbox_remove(pdev); 615 + } 483 616 484 617 static int proc_thermal_pci_probe(struct pci_dev *pdev, 485 618 const struct pci_device_id *id) ··· 508 629 if (ret) 509 630 return ret; 510 631 511 - ret = proc_thermal_rapl_add(pdev, proc_priv, 512 - (struct rapl_mmio_regs *)id->driver_data); 513 - if (ret) { 514 - dev_err(&pdev->dev, "failed to add RAPL MMIO interface\n"); 515 - proc_thermal_remove(proc_priv); 516 - return ret; 517 - } 518 - 519 632 pci_set_drvdata(pdev, proc_priv); 520 633 proc_thermal_emum_mode = PROC_THERMAL_PCI; 521 634 522 - if (pdev->device == PCI_DEVICE_ID_PROC_BSW_THERMAL) { 635 + if (pdev->device == PCI_DEVICE_ID_INTEL_BSW_THERMAL) { 523 636 /* 524 637 * Enumerate additional DTS sensors available via IOSF. 525 638 * But we are not treating as a failure condition, if ··· 547 676 return ret; 548 677 549 678 ret = sysfs_create_group(&pdev->dev.kobj, &power_limit_attribute_group); 550 - if (ret) 679 + if (ret) { 551 680 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr); 681 + return ret; 682 + } 552 683 553 - return ret; 684 + ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); 685 + if (ret) { 686 + proc_thermal_remove(proc_priv); 687 + return ret; 688 + } 689 + 690 + return 0; 554 691 } 555 692 556 693 static void proc_thermal_pci_remove(struct pci_dev *pdev) ··· 572 693 pci_disable_msi(pdev); 573 694 } 574 695 } 575 - proc_thermal_rapl_remove(); 696 + 697 + proc_thermal_mmio_remove(pdev); 576 698 proc_thermal_remove(proc_priv); 577 699 } 578 700 ··· 596 716 static SIMPLE_DEV_PM_OPS(proc_thermal_pm, NULL, proc_thermal_resume); 597 717 598 718 static const struct pci_device_id proc_thermal_pci_ids[] = { 599 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BDW_THERMAL)}, 600 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_HSB_THERMAL)}, 601 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_SKL_THERMAL), 602 - .driver_data = (kernel_ulong_t)&rapl_mmio_hsw, }, 603 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BSW_THERMAL)}, 604 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT0_THERMAL)}, 605 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT1_THERMAL)}, 606 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTX_THERMAL)}, 607 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTP_THERMAL)}, 608 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CNL_THERMAL)}, 609 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CFL_THERMAL)}, 610 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_GLK_THERMAL)}, 611 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_ICL_THERMAL), 612 - .driver_data = (kernel_ulong_t)&rapl_mmio_hsw, }, 613 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_JSL_THERMAL)}, 614 - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_TGL_THERMAL), 615 - .driver_data = (kernel_ulong_t)&rapl_mmio_hsw, }, 616 - { 0, }, 719 + { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, 720 + { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) }, 721 + { PCI_DEVICE_DATA(INTEL, BSW_THERMAL, 0) }, 722 + { PCI_DEVICE_DATA(INTEL, BXT0_THERMAL, 0) }, 723 + { PCI_DEVICE_DATA(INTEL, BXT1_THERMAL, 0) }, 724 + { PCI_DEVICE_DATA(INTEL, BXTX_THERMAL, 0) }, 725 + { PCI_DEVICE_DATA(INTEL, BXTP_THERMAL, 0) }, 726 + { PCI_DEVICE_DATA(INTEL, CNL_THERMAL, 0) }, 727 + { PCI_DEVICE_DATA(INTEL, CFL_THERMAL, 0) }, 728 + { PCI_DEVICE_DATA(INTEL, GLK_THERMAL, 0) }, 729 + { PCI_DEVICE_DATA(INTEL, HSB_THERMAL, 0) }, 730 + { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, 731 + { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) }, 732 + { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, 733 + { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_MBOX) }, 734 + { }, 617 735 }; 618 736 619 737 MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids);
+82
drivers/thermal/intel/int340x_thermal/processor_thermal_device.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * processor_thermal_device.h 4 + * Copyright (c) 2020, Intel Corporation. 5 + */ 6 + 7 + #ifndef __PROCESSOR_THERMAL_DEVICE_H__ 8 + #define __PROCESSOR_THERMAL_DEVICE_H__ 9 + 10 + #include <linux/intel_rapl.h> 11 + 12 + #define PCI_DEVICE_ID_INTEL_ADL_THERMAL 0x461d 13 + #define PCI_DEVICE_ID_INTEL_BDW_THERMAL 0x1603 14 + #define PCI_DEVICE_ID_INTEL_BSW_THERMAL 0x22DC 15 + 16 + #define PCI_DEVICE_ID_INTEL_BXT0_THERMAL 0x0A8C 17 + #define PCI_DEVICE_ID_INTEL_BXT1_THERMAL 0x1A8C 18 + #define PCI_DEVICE_ID_INTEL_BXTX_THERMAL 0x4A8C 19 + #define PCI_DEVICE_ID_INTEL_BXTP_THERMAL 0x5A8C 20 + 21 + #define PCI_DEVICE_ID_INTEL_CNL_THERMAL 0x5a03 22 + #define PCI_DEVICE_ID_INTEL_CFL_THERMAL 0x3E83 23 + #define PCI_DEVICE_ID_INTEL_GLK_THERMAL 0x318C 24 + #define PCI_DEVICE_ID_INTEL_HSB_THERMAL 0x0A03 25 + #define PCI_DEVICE_ID_INTEL_ICL_THERMAL 0x8a03 26 + #define PCI_DEVICE_ID_INTEL_JSL_THERMAL 0x4E03 27 + #define PCI_DEVICE_ID_INTEL_SKL_THERMAL 0x1903 28 + #define PCI_DEVICE_ID_INTEL_TGL_THERMAL 0x9A03 29 + 30 + struct power_config { 31 + u32 index; 32 + u32 min_uw; 33 + u32 max_uw; 34 + u32 tmin_us; 35 + u32 tmax_us; 36 + u32 step_uw; 37 + }; 38 + 39 + struct proc_thermal_device { 40 + struct device *dev; 41 + struct acpi_device *adev; 42 + struct power_config power_limits[2]; 43 + struct int34x_thermal_zone *int340x_zone; 44 + struct intel_soc_dts_sensors *soc_dts; 45 + u32 mmio_feature_mask; 46 + void __iomem *mmio_base; 47 + }; 48 + 49 + struct rapl_mmio_regs { 50 + u64 reg_unit; 51 + u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX]; 52 + int limits[RAPL_DOMAIN_MAX]; 53 + }; 54 + 55 + #define PROC_THERMAL_FEATURE_NONE 0x00 56 + #define PROC_THERMAL_FEATURE_RAPL 0x01 57 + #define PROC_THERMAL_FEATURE_FIVR 0x02 58 + #define PROC_THERMAL_FEATURE_DVFS 0x04 59 + #define PROC_THERMAL_FEATURE_MBOX 0x08 60 + 61 + #if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) 62 + int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 63 + void proc_thermal_rapl_remove(void); 64 + #else 65 + static int __maybe_unused proc_thermal_rapl_add(struct pci_dev *pdev, 66 + struct proc_thermal_device *proc_priv) 67 + { 68 + return 0; 69 + } 70 + 71 + static void __maybe_unused proc_thermal_rapl_remove(void) 72 + { 73 + } 74 + #endif 75 + 76 + int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 77 + void proc_thermal_rfim_remove(struct pci_dev *pdev); 78 + 79 + int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 80 + void proc_thermal_mbox_remove(struct pci_dev *pdev); 81 + 82 + #endif
+212
drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * processor thermal device mailbox driver for Workload type hints 4 + * Copyright (c) 2020, Intel Corporation. 5 + */ 6 + 7 + #include <linux/kernel.h> 8 + #include <linux/module.h> 9 + #include <linux/pci.h> 10 + #include "processor_thermal_device.h" 11 + 12 + #define MBOX_CMD_WORKLOAD_TYPE_READ 0x0E 13 + #define MBOX_CMD_WORKLOAD_TYPE_WRITE 0x0F 14 + 15 + #define MBOX_OFFSET_DATA 0x5810 16 + #define MBOX_OFFSET_INTERFACE 0x5818 17 + 18 + #define MBOX_BUSY_BIT 31 19 + #define MBOX_RETRY_COUNT 100 20 + 21 + #define MBOX_DATA_BIT_VALID 31 22 + #define MBOX_DATA_BIT_AC_DC 30 23 + 24 + static DEFINE_MUTEX(mbox_lock); 25 + 26 + static int send_mbox_cmd(struct pci_dev *pdev, u8 cmd_id, u32 cmd_data, u8 *cmd_resp) 27 + { 28 + struct proc_thermal_device *proc_priv; 29 + u32 retries, data; 30 + int ret; 31 + 32 + mutex_lock(&mbox_lock); 33 + proc_priv = pci_get_drvdata(pdev); 34 + 35 + /* Poll for rb bit == 0 */ 36 + retries = MBOX_RETRY_COUNT; 37 + do { 38 + data = readl((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); 39 + if (data & BIT_ULL(MBOX_BUSY_BIT)) { 40 + ret = -EBUSY; 41 + continue; 42 + } 43 + ret = 0; 44 + break; 45 + } while (--retries); 46 + 47 + if (ret) 48 + goto unlock_mbox; 49 + 50 + if (cmd_id == MBOX_CMD_WORKLOAD_TYPE_WRITE) 51 + writel(cmd_data, (void __iomem *) ((proc_priv->mmio_base + MBOX_OFFSET_DATA))); 52 + 53 + /* Write command register */ 54 + data = BIT_ULL(MBOX_BUSY_BIT) | cmd_id; 55 + writel(data, (void __iomem *) ((proc_priv->mmio_base + MBOX_OFFSET_INTERFACE))); 56 + 57 + /* Poll for rb bit == 0 */ 58 + retries = MBOX_RETRY_COUNT; 59 + do { 60 + data = readl((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); 61 + if (data & BIT_ULL(MBOX_BUSY_BIT)) { 62 + ret = -EBUSY; 63 + continue; 64 + } 65 + 66 + if (data) { 67 + ret = -ENXIO; 68 + goto unlock_mbox; 69 + } 70 + 71 + if (cmd_id == MBOX_CMD_WORKLOAD_TYPE_READ) { 72 + data = readl((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_DATA)); 73 + *cmd_resp = data & 0xff; 74 + } 75 + 76 + ret = 0; 77 + break; 78 + } while (--retries); 79 + 80 + unlock_mbox: 81 + mutex_unlock(&mbox_lock); 82 + return ret; 83 + } 84 + 85 + /* List of workload types */ 86 + static const char * const workload_types[] = { 87 + "none", 88 + "idle", 89 + "semi_active", 90 + "bursty", 91 + "sustained", 92 + "battery_life", 93 + NULL 94 + }; 95 + 96 + 97 + static ssize_t workload_available_types_show(struct device *dev, 98 + struct device_attribute *attr, 99 + char *buf) 100 + { 101 + int i = 0; 102 + int ret = 0; 103 + 104 + while (workload_types[i] != NULL) 105 + ret += sprintf(&buf[ret], "%s ", workload_types[i++]); 106 + 107 + ret += sprintf(&buf[ret], "\n"); 108 + 109 + return ret; 110 + } 111 + 112 + static DEVICE_ATTR_RO(workload_available_types); 113 + 114 + static ssize_t workload_type_store(struct device *dev, 115 + struct device_attribute *attr, 116 + const char *buf, size_t count) 117 + { 118 + struct pci_dev *pdev = to_pci_dev(dev); 119 + char str_preference[15]; 120 + u32 data = 0; 121 + ssize_t ret; 122 + 123 + ret = sscanf(buf, "%14s", str_preference); 124 + if (ret != 1) 125 + return -EINVAL; 126 + 127 + ret = match_string(workload_types, -1, str_preference); 128 + if (ret < 0) 129 + return ret; 130 + 131 + ret &= 0xff; 132 + 133 + if (ret) 134 + data = BIT(MBOX_DATA_BIT_VALID) | BIT(MBOX_DATA_BIT_AC_DC); 135 + 136 + data |= ret; 137 + 138 + ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data, NULL); 139 + if (ret) 140 + return false; 141 + 142 + return count; 143 + } 144 + 145 + static ssize_t workload_type_show(struct device *dev, 146 + struct device_attribute *attr, 147 + char *buf) 148 + { 149 + struct pci_dev *pdev = to_pci_dev(dev); 150 + u8 cmd_resp; 151 + int ret; 152 + 153 + ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, 0, &cmd_resp); 154 + if (ret) 155 + return false; 156 + 157 + cmd_resp &= 0xff; 158 + 159 + if (cmd_resp > ARRAY_SIZE(workload_types) - 1) 160 + return -EINVAL; 161 + 162 + return sprintf(buf, "%s\n", workload_types[cmd_resp]); 163 + } 164 + 165 + static DEVICE_ATTR_RW(workload_type); 166 + 167 + static struct attribute *workload_req_attrs[] = { 168 + &dev_attr_workload_available_types.attr, 169 + &dev_attr_workload_type.attr, 170 + NULL 171 + }; 172 + 173 + static const struct attribute_group workload_req_attribute_group = { 174 + .attrs = workload_req_attrs, 175 + .name = "workload_request" 176 + }; 177 + 178 + 179 + 180 + static bool workload_req_created; 181 + 182 + int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 183 + { 184 + u8 cmd_resp; 185 + int ret; 186 + 187 + /* Check if there is a mailbox support, if fails return success */ 188 + ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, 0, &cmd_resp); 189 + if (ret) 190 + return 0; 191 + 192 + ret = sysfs_create_group(&pdev->dev.kobj, &workload_req_attribute_group); 193 + if (ret) 194 + return ret; 195 + 196 + workload_req_created = true; 197 + 198 + return 0; 199 + } 200 + EXPORT_SYMBOL_GPL(proc_thermal_mbox_add); 201 + 202 + void proc_thermal_mbox_remove(struct pci_dev *pdev) 203 + { 204 + if (workload_req_created) 205 + sysfs_remove_group(&pdev->dev.kobj, &workload_req_attribute_group); 206 + 207 + workload_req_created = false; 208 + 209 + } 210 + EXPORT_SYMBOL_GPL(proc_thermal_mbox_remove); 211 + 212 + MODULE_LICENSE("GPL v2");
+134
drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * processor thermal device RFIM control 4 + * Copyright (c) 2020, Intel Corporation. 5 + */ 6 + 7 + #include <linux/kernel.h> 8 + #include <linux/module.h> 9 + #include <linux/pci.h> 10 + #include "processor_thermal_device.h" 11 + 12 + static struct rapl_if_priv rapl_mmio_priv; 13 + 14 + static const struct rapl_mmio_regs rapl_mmio_default = { 15 + .reg_unit = 0x5938, 16 + .regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930}, 17 + .regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0}, 18 + .limits[RAPL_DOMAIN_PACKAGE] = 2, 19 + .limits[RAPL_DOMAIN_DRAM] = 2, 20 + }; 21 + 22 + static int rapl_mmio_cpu_online(unsigned int cpu) 23 + { 24 + struct rapl_package *rp; 25 + 26 + /* mmio rapl supports package 0 only for now */ 27 + if (topology_physical_package_id(cpu)) 28 + return 0; 29 + 30 + rp = rapl_find_package_domain(cpu, &rapl_mmio_priv); 31 + if (!rp) { 32 + rp = rapl_add_package(cpu, &rapl_mmio_priv); 33 + if (IS_ERR(rp)) 34 + return PTR_ERR(rp); 35 + } 36 + cpumask_set_cpu(cpu, &rp->cpumask); 37 + return 0; 38 + } 39 + 40 + static int rapl_mmio_cpu_down_prep(unsigned int cpu) 41 + { 42 + struct rapl_package *rp; 43 + int lead_cpu; 44 + 45 + rp = rapl_find_package_domain(cpu, &rapl_mmio_priv); 46 + if (!rp) 47 + return 0; 48 + 49 + cpumask_clear_cpu(cpu, &rp->cpumask); 50 + lead_cpu = cpumask_first(&rp->cpumask); 51 + if (lead_cpu >= nr_cpu_ids) 52 + rapl_remove_package(rp); 53 + else if (rp->lead_cpu == cpu) 54 + rp->lead_cpu = lead_cpu; 55 + return 0; 56 + } 57 + 58 + static int rapl_mmio_read_raw(int cpu, struct reg_action *ra) 59 + { 60 + if (!ra->reg) 61 + return -EINVAL; 62 + 63 + ra->value = readq((void __iomem *)ra->reg); 64 + ra->value &= ra->mask; 65 + return 0; 66 + } 67 + 68 + static int rapl_mmio_write_raw(int cpu, struct reg_action *ra) 69 + { 70 + u64 val; 71 + 72 + if (!ra->reg) 73 + return -EINVAL; 74 + 75 + val = readq((void __iomem *)ra->reg); 76 + val &= ~ra->mask; 77 + val |= ra->value; 78 + writeq(val, (void __iomem *)ra->reg); 79 + return 0; 80 + } 81 + 82 + int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 83 + { 84 + const struct rapl_mmio_regs *rapl_regs = &rapl_mmio_default; 85 + enum rapl_domain_reg_id reg; 86 + enum rapl_domain_type domain; 87 + int ret; 88 + 89 + if (!rapl_regs) 90 + return 0; 91 + 92 + for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) { 93 + for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++) 94 + if (rapl_regs->regs[domain][reg]) 95 + rapl_mmio_priv.regs[domain][reg] = 96 + (u64)proc_priv->mmio_base + 97 + rapl_regs->regs[domain][reg]; 98 + rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain]; 99 + } 100 + rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit; 101 + 102 + rapl_mmio_priv.read_raw = rapl_mmio_read_raw; 103 + rapl_mmio_priv.write_raw = rapl_mmio_write_raw; 104 + 105 + rapl_mmio_priv.control_type = powercap_register_control_type(NULL, "intel-rapl-mmio", NULL); 106 + if (IS_ERR(rapl_mmio_priv.control_type)) { 107 + pr_debug("failed to register powercap control_type.\n"); 108 + return PTR_ERR(rapl_mmio_priv.control_type); 109 + } 110 + 111 + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online", 112 + rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep); 113 + if (ret < 0) { 114 + powercap_unregister_control_type(rapl_mmio_priv.control_type); 115 + rapl_mmio_priv.control_type = NULL; 116 + return ret; 117 + } 118 + rapl_mmio_priv.pcap_rapl_online = ret; 119 + 120 + return 0; 121 + } 122 + EXPORT_SYMBOL_GPL(proc_thermal_rapl_add); 123 + 124 + void proc_thermal_rapl_remove(void) 125 + { 126 + if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type)) 127 + return; 128 + 129 + cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online); 130 + powercap_unregister_control_type(rapl_mmio_priv.control_type); 131 + } 132 + EXPORT_SYMBOL_GPL(proc_thermal_rapl_remove); 133 + 134 + MODULE_LICENSE("GPL v2");
+244
drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * processor thermal device RFIM control 4 + * Copyright (c) 2020, Intel Corporation. 5 + */ 6 + 7 + #include <linux/kernel.h> 8 + #include <linux/module.h> 9 + #include <linux/pci.h> 10 + #include "processor_thermal_device.h" 11 + 12 + struct mmio_reg { 13 + int read_only; 14 + u32 offset; 15 + int bits; 16 + u16 mask; 17 + u16 shift; 18 + }; 19 + 20 + /* These will represent sysfs attribute names */ 21 + static const char * const fivr_strings[] = { 22 + "vco_ref_code_lo", 23 + "vco_ref_code_hi", 24 + "spread_spectrum_pct", 25 + "spread_spectrum_clk_enable", 26 + "rfi_vco_ref_code", 27 + "fivr_fffc_rev", 28 + NULL 29 + }; 30 + 31 + static const struct mmio_reg tgl_fivr_mmio_regs[] = { 32 + { 0, 0x5A18, 3, 0x7, 12}, /* vco_ref_code_lo */ 33 + { 0, 0x5A18, 8, 0xFF, 16}, /* vco_ref_code_hi */ 34 + { 0, 0x5A08, 8, 0xFF, 0}, /* spread_spectrum_pct */ 35 + { 0, 0x5A08, 1, 0x1, 8}, /* spread_spectrum_clk_enable */ 36 + { 1, 0x5A10, 12, 0xFFF, 0}, /* rfi_vco_ref_code */ 37 + { 1, 0x5A14, 2, 0x3, 1}, /* fivr_fffc_rev */ 38 + }; 39 + 40 + /* These will represent sysfs attribute names */ 41 + static const char * const dvfs_strings[] = { 42 + "rfi_restriction_run_busy", 43 + "rfi_restriction_err_code", 44 + "rfi_restriction_data_rate", 45 + "rfi_restriction_data_rate_base", 46 + "ddr_data_rate_point_0", 47 + "ddr_data_rate_point_1", 48 + "ddr_data_rate_point_2", 49 + "ddr_data_rate_point_3", 50 + "rfi_disable", 51 + NULL 52 + }; 53 + 54 + static const struct mmio_reg adl_dvfs_mmio_regs[] = { 55 + { 0, 0x5A38, 1, 0x1, 31}, /* rfi_restriction_run_busy */ 56 + { 0, 0x5A38, 7, 0x7F, 24}, /* rfi_restriction_err_code */ 57 + { 0, 0x5A38, 8, 0xFF, 16}, /* rfi_restriction_data_rate */ 58 + { 0, 0x5A38, 16, 0xFFFF, 0}, /* rfi_restriction_data_rate_base */ 59 + { 0, 0x5A30, 10, 0x3FF, 0}, /* ddr_data_rate_point_0 */ 60 + { 0, 0x5A30, 10, 0x3FF, 10}, /* ddr_data_rate_point_1 */ 61 + { 0, 0x5A30, 10, 0x3FF, 20}, /* ddr_data_rate_point_2 */ 62 + { 0, 0x5A30, 10, 0x3FF, 30}, /* ddr_data_rate_point_3 */ 63 + { 0, 0x5A40, 1, 0x1, 0}, /* rfi_disable */ 64 + }; 65 + 66 + #define RFIM_SHOW(suffix, table)\ 67 + static ssize_t suffix##_show(struct device *dev,\ 68 + struct device_attribute *attr,\ 69 + char *buf)\ 70 + {\ 71 + struct proc_thermal_device *proc_priv;\ 72 + struct pci_dev *pdev = to_pci_dev(dev);\ 73 + const struct mmio_reg *mmio_regs;\ 74 + const char **match_strs;\ 75 + u32 reg_val;\ 76 + int ret;\ 77 + \ 78 + proc_priv = pci_get_drvdata(pdev);\ 79 + if (table) {\ 80 + match_strs = (const char **)dvfs_strings;\ 81 + mmio_regs = adl_dvfs_mmio_regs;\ 82 + } else { \ 83 + match_strs = (const char **)fivr_strings;\ 84 + mmio_regs = tgl_fivr_mmio_regs;\ 85 + } \ 86 + \ 87 + ret = match_string(match_strs, -1, attr->attr.name);\ 88 + if (ret < 0)\ 89 + return ret;\ 90 + reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\ 91 + ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\ 92 + return sprintf(buf, "%u\n", ret);\ 93 + } 94 + 95 + #define RFIM_STORE(suffix, table)\ 96 + static ssize_t suffix##_store(struct device *dev,\ 97 + struct device_attribute *attr,\ 98 + const char *buf, size_t count)\ 99 + {\ 100 + struct proc_thermal_device *proc_priv;\ 101 + struct pci_dev *pdev = to_pci_dev(dev);\ 102 + unsigned int input;\ 103 + const char **match_strs;\ 104 + const struct mmio_reg *mmio_regs;\ 105 + int ret, err;\ 106 + u32 reg_val;\ 107 + u32 mask;\ 108 + \ 109 + proc_priv = pci_get_drvdata(pdev);\ 110 + if (table) {\ 111 + match_strs = (const char **)dvfs_strings;\ 112 + mmio_regs = adl_dvfs_mmio_regs;\ 113 + } else { \ 114 + match_strs = (const char **)fivr_strings;\ 115 + mmio_regs = tgl_fivr_mmio_regs;\ 116 + } \ 117 + \ 118 + ret = match_string(match_strs, -1, attr->attr.name);\ 119 + if (ret < 0)\ 120 + return ret;\ 121 + if (mmio_regs[ret].read_only)\ 122 + return -EPERM;\ 123 + err = kstrtouint(buf, 10, &input);\ 124 + if (err)\ 125 + return err;\ 126 + mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\ 127 + reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\ 128 + reg_val &= ~mask;\ 129 + reg_val |= (input << mmio_regs[ret].shift);\ 130 + writel(reg_val, (void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\ 131 + return count;\ 132 + } 133 + 134 + RFIM_SHOW(vco_ref_code_lo, 0) 135 + RFIM_SHOW(vco_ref_code_hi, 0) 136 + RFIM_SHOW(spread_spectrum_pct, 0) 137 + RFIM_SHOW(spread_spectrum_clk_enable, 0) 138 + RFIM_SHOW(rfi_vco_ref_code, 0) 139 + RFIM_SHOW(fivr_fffc_rev, 0) 140 + 141 + RFIM_STORE(vco_ref_code_lo, 0) 142 + RFIM_STORE(vco_ref_code_hi, 0) 143 + RFIM_STORE(spread_spectrum_pct, 0) 144 + RFIM_STORE(spread_spectrum_clk_enable, 0) 145 + RFIM_STORE(rfi_vco_ref_code, 0) 146 + RFIM_STORE(fivr_fffc_rev, 0) 147 + 148 + static DEVICE_ATTR_RW(vco_ref_code_lo); 149 + static DEVICE_ATTR_RW(vco_ref_code_hi); 150 + static DEVICE_ATTR_RW(spread_spectrum_pct); 151 + static DEVICE_ATTR_RW(spread_spectrum_clk_enable); 152 + static DEVICE_ATTR_RW(rfi_vco_ref_code); 153 + static DEVICE_ATTR_RW(fivr_fffc_rev); 154 + 155 + static struct attribute *fivr_attrs[] = { 156 + &dev_attr_vco_ref_code_lo.attr, 157 + &dev_attr_vco_ref_code_hi.attr, 158 + &dev_attr_spread_spectrum_pct.attr, 159 + &dev_attr_spread_spectrum_clk_enable.attr, 160 + &dev_attr_rfi_vco_ref_code.attr, 161 + &dev_attr_fivr_fffc_rev.attr, 162 + NULL 163 + }; 164 + 165 + static const struct attribute_group fivr_attribute_group = { 166 + .attrs = fivr_attrs, 167 + .name = "fivr" 168 + }; 169 + 170 + RFIM_SHOW(rfi_restriction_run_busy, 1) 171 + RFIM_SHOW(rfi_restriction_err_code, 1) 172 + RFIM_SHOW(rfi_restriction_data_rate, 1) 173 + RFIM_SHOW(ddr_data_rate_point_0, 1) 174 + RFIM_SHOW(ddr_data_rate_point_1, 1) 175 + RFIM_SHOW(ddr_data_rate_point_2, 1) 176 + RFIM_SHOW(ddr_data_rate_point_3, 1) 177 + RFIM_SHOW(rfi_disable, 1) 178 + 179 + RFIM_STORE(rfi_restriction_run_busy, 1) 180 + RFIM_STORE(rfi_restriction_err_code, 1) 181 + RFIM_STORE(rfi_restriction_data_rate, 1) 182 + RFIM_STORE(rfi_disable, 1) 183 + 184 + static DEVICE_ATTR_RW(rfi_restriction_run_busy); 185 + static DEVICE_ATTR_RW(rfi_restriction_err_code); 186 + static DEVICE_ATTR_RW(rfi_restriction_data_rate); 187 + static DEVICE_ATTR_RO(ddr_data_rate_point_0); 188 + static DEVICE_ATTR_RO(ddr_data_rate_point_1); 189 + static DEVICE_ATTR_RO(ddr_data_rate_point_2); 190 + static DEVICE_ATTR_RO(ddr_data_rate_point_3); 191 + static DEVICE_ATTR_RW(rfi_disable); 192 + 193 + static struct attribute *dvfs_attrs[] = { 194 + &dev_attr_rfi_restriction_run_busy.attr, 195 + &dev_attr_rfi_restriction_err_code.attr, 196 + &dev_attr_rfi_restriction_data_rate.attr, 197 + &dev_attr_ddr_data_rate_point_0.attr, 198 + &dev_attr_ddr_data_rate_point_1.attr, 199 + &dev_attr_ddr_data_rate_point_2.attr, 200 + &dev_attr_ddr_data_rate_point_3.attr, 201 + &dev_attr_rfi_disable.attr, 202 + NULL 203 + }; 204 + 205 + static const struct attribute_group dvfs_attribute_group = { 206 + .attrs = dvfs_attrs, 207 + .name = "dvfs" 208 + }; 209 + 210 + int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 211 + { 212 + int ret; 213 + 214 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) { 215 + ret = sysfs_create_group(&pdev->dev.kobj, &fivr_attribute_group); 216 + if (ret) 217 + return ret; 218 + } 219 + 220 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) { 221 + ret = sysfs_create_group(&pdev->dev.kobj, &dvfs_attribute_group); 222 + if (ret && proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) { 223 + sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group); 224 + return ret; 225 + } 226 + } 227 + 228 + return 0; 229 + } 230 + EXPORT_SYMBOL_GPL(proc_thermal_rfim_add); 231 + 232 + void proc_thermal_rfim_remove(struct pci_dev *pdev) 233 + { 234 + struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); 235 + 236 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) 237 + sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group); 238 + 239 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) 240 + sysfs_remove_group(&pdev->dev.kobj, &dvfs_attribute_group); 241 + } 242 + EXPORT_SYMBOL_GPL(proc_thermal_rfim_remove); 243 + 244 + MODULE_LICENSE("GPL v2");
+87 -18
drivers/thermal/intel/intel_pch_thermal.c
··· 7 7 * Tushar Dave <tushar.n.dave@intel.com> 8 8 */ 9 9 10 + #include <linux/acpi.h> 11 + #include <linux/delay.h> 10 12 #include <linux/module.h> 11 - #include <linux/types.h> 12 13 #include <linux/init.h> 13 14 #include <linux/pci.h> 14 - #include <linux/acpi.h> 15 - #include <linux/thermal.h> 16 - #include <linux/units.h> 17 15 #include <linux/pm.h> 16 + #include <linux/suspend.h> 17 + #include <linux/thermal.h> 18 + #include <linux/types.h> 19 + #include <linux/units.h> 18 20 19 21 /* Intel PCH thermal Device IDs */ 20 22 #define PCH_THERMAL_DID_HSW_1 0x9C24 /* Haswell PCH */ ··· 28 26 #define PCH_THERMAL_DID_CNL_H 0xA379 /* CNL-H PCH */ 29 27 #define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */ 30 28 #define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */ 29 + #define PCH_THERMAL_DID_LWB 0xA1B1 /* Lewisburg PCH */ 31 30 32 31 /* Wildcat Point-LP PCH Thermal registers */ 33 32 #define WPT_TEMP 0x0000 /* Temperature */ ··· 38 35 #define WPT_TSREL 0x0A /* Thermal Sensor Report Enable and Lock */ 39 36 #define WPT_TSMIC 0x0C /* Thermal Sensor SMI Control */ 40 37 #define WPT_CTT 0x0010 /* Catastrophic Trip Point */ 38 + #define WPT_TSPM 0x001C /* Thermal Sensor Power Management */ 41 39 #define WPT_TAHV 0x0014 /* Thermal Alert High Value */ 42 40 #define WPT_TALV 0x0018 /* Thermal Alert Low Value */ 43 41 #define WPT_TL 0x00000040 /* Throttle Value */ ··· 58 54 #define WPT_TL_TOL 0x000001FF /* T0 Level */ 59 55 #define WPT_TL_T1L 0x1ff00000 /* T1 Level */ 60 56 #define WPT_TL_TTEN 0x20000000 /* TT Enable */ 57 + 58 + /* Resolution of 1/2 degree C and an offset of -50C */ 59 + #define PCH_TEMP_OFFSET (-50) 60 + #define GET_WPT_TEMP(x) ((x) * MILLIDEGREE_PER_DEGREE / 2 + WPT_TEMP_OFFSET) 61 + #define WPT_TEMP_OFFSET (PCH_TEMP_OFFSET * MILLIDEGREE_PER_DEGREE) 62 + #define GET_PCH_TEMP(x) (((x) / 2) + PCH_TEMP_OFFSET) 63 + 64 + /* Amount of time for each cooling delay, 100ms by default for now */ 65 + static unsigned int delay_timeout = 100; 66 + module_param(delay_timeout, int, 0644); 67 + MODULE_PARM_DESC(delay_timeout, "amount of time delay for each iteration."); 68 + 69 + /* Number of iterations for cooling delay, 10 counts by default for now */ 70 + static unsigned int delay_cnt = 10; 71 + module_param(delay_cnt, int, 0644); 72 + MODULE_PARM_DESC(delay_cnt, "total number of iterations for time delay."); 61 73 62 74 static char driver_name[] = "Intel PCH thermal driver"; 63 75 ··· 167 147 trip_temp = readw(ptd->hw_base + WPT_CTT); 168 148 trip_temp &= 0x1FF; 169 149 if (trip_temp) { 170 - /* Resolution of 1/2 degree C and an offset of -50C */ 171 - ptd->crt_temp = trip_temp * 1000 / 2 - 50000; 150 + ptd->crt_temp = GET_WPT_TEMP(trip_temp); 172 151 ptd->crt_trip_id = 0; 173 152 ++(*nr_trips); 174 153 } ··· 176 157 trip_temp = readw(ptd->hw_base + WPT_PHL); 177 158 trip_temp &= 0x1FF; 178 159 if (trip_temp) { 179 - /* Resolution of 1/2 degree C and an offset of -50C */ 180 - ptd->hot_temp = trip_temp * 1000 / 2 - 50000; 160 + ptd->hot_temp = GET_WPT_TEMP(trip_temp); 181 161 ptd->hot_trip_id = *nr_trips; 182 162 ++(*nr_trips); 183 163 } ··· 188 170 189 171 static int pch_wpt_get_temp(struct pch_thermal_device *ptd, int *temp) 190 172 { 191 - u16 wpt_temp; 192 - 193 - wpt_temp = WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP); 194 - 195 - /* Resolution of 1/2 degree C and an offset of -50C */ 196 - *temp = (wpt_temp * 1000 / 2 - 50000); 173 + *temp = GET_WPT_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP)); 197 174 198 175 return 0; 199 176 } ··· 196 183 static int pch_wpt_suspend(struct pch_thermal_device *ptd) 197 184 { 198 185 u8 tsel; 186 + u8 pch_delay_cnt = 1; 187 + u16 pch_thr_temp, pch_cur_temp; 199 188 200 - if (ptd->bios_enabled) 189 + /* Shutdown the thermal sensor if it is not enabled by BIOS */ 190 + if (!ptd->bios_enabled) { 191 + tsel = readb(ptd->hw_base + WPT_TSEL); 192 + writeb(tsel & 0xFE, ptd->hw_base + WPT_TSEL); 193 + return 0; 194 + } 195 + 196 + /* Do not check temperature if it is not a S0ix capable platform */ 197 + #ifdef CONFIG_ACPI 198 + if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) 199 + return 0; 200 + #else 201 + return 0; 202 + #endif 203 + 204 + /* Do not check temperature if it is not s2idle */ 205 + if (pm_suspend_via_firmware()) 201 206 return 0; 202 207 203 - tsel = readb(ptd->hw_base + WPT_TSEL); 208 + /* Get the PCH temperature threshold value */ 209 + pch_thr_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TSPM)); 204 210 205 - writeb(tsel & 0xFE, ptd->hw_base + WPT_TSEL); 211 + /* Get the PCH current temperature value */ 212 + pch_cur_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP)); 213 + 214 + /* 215 + * If current PCH temperature is higher than configured PCH threshold 216 + * value, run some delay loop with sleep to let the current temperature 217 + * go down below the threshold value which helps to allow system enter 218 + * lower power S0ix suspend state. Even after delay loop if PCH current 219 + * temperature stays above threshold, notify the warning message 220 + * which helps to indentify the reason why S0ix entry was rejected. 221 + */ 222 + while (pch_delay_cnt <= delay_cnt) { 223 + if (pch_cur_temp <= pch_thr_temp) 224 + break; 225 + 226 + dev_warn(&ptd->pdev->dev, 227 + "CPU-PCH current temp [%dC] higher than the threshold temp [%dC], sleep %d times for %d ms duration\n", 228 + pch_cur_temp, pch_thr_temp, pch_delay_cnt, delay_timeout); 229 + msleep(delay_timeout); 230 + /* Read the PCH current temperature for next cycle. */ 231 + pch_cur_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP)); 232 + pch_delay_cnt++; 233 + } 234 + 235 + if (pch_cur_temp > pch_thr_temp) 236 + dev_warn(&ptd->pdev->dev, 237 + "CPU-PCH is hot [%dC] even after delay, continue to suspend. S0ix might fail\n", 238 + pch_cur_temp); 239 + else 240 + dev_info(&ptd->pdev->dev, 241 + "CPU-PCH is cool [%dC], continue to suspend\n", pch_cur_temp); 206 242 207 243 return 0; 208 244 } ··· 338 276 board_skl, 339 277 board_cnl, 340 278 board_cml, 279 + board_lwb, 341 280 }; 342 281 343 282 static const struct board_info { ··· 364 301 [board_cml] = { 365 302 .name = "pch_cometlake", 366 303 .ops = &pch_dev_ops_wpt, 367 - } 304 + }, 305 + [board_lwb] = { 306 + .name = "pch_lewisburg", 307 + .ops = &pch_dev_ops_wpt, 308 + }, 368 309 }; 369 310 370 311 static int intel_pch_thermal_probe(struct pci_dev *pdev, ··· 482 415 .driver_data = board_cnl, }, 483 416 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CML_H), 484 417 .driver_data = board_cml, }, 418 + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_LWB), 419 + .driver_data = board_lwb, }, 485 420 { 0, }, 486 421 }; 487 422 MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id);
+1 -1
drivers/thermal/mtk_thermal.c
··· 1052 1052 return -EINVAL; 1053 1053 } 1054 1054 1055 - ret = device_reset(&pdev->dev); 1055 + ret = device_reset_optional(&pdev->dev); 1056 1056 if (ret) 1057 1057 return ret; 1058 1058
+8 -107
drivers/thermal/rcar_gen3_thermal.c
··· 60 60 #define MCELSIUS(temp) ((temp) * 1000) 61 61 #define GEN3_FUSE_MASK 0xFFF 62 62 63 - #define TSC_MAX_NUM 3 63 + #define TSC_MAX_NUM 4 64 64 65 65 /* default THCODE values if FUSEs are missing */ 66 66 static const int thcodes[TSC_MAX_NUM][3] = { 67 67 { 3397, 2800, 2221 }, 68 68 { 3393, 2795, 2216 }, 69 69 { 3389, 2805, 2237 }, 70 + { 3415, 2694, 2195 }, 70 71 }; 71 72 72 73 /* Structure for thermal temperature calculation */ ··· 189 188 return 0; 190 189 } 191 190 192 - static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc, 193 - int mcelsius) 194 - { 195 - int celsius, val; 196 - 197 - celsius = DIV_ROUND_CLOSEST(mcelsius, 1000); 198 - if (celsius <= INT_FIXPT(tsc->tj_t)) 199 - val = celsius * tsc->coef.a1 + tsc->coef.b1; 200 - else 201 - val = celsius * tsc->coef.a2 + tsc->coef.b2; 202 - 203 - return INT_FIXPT(val); 204 - } 205 - 206 - static int rcar_gen3_thermal_update_range(struct rcar_gen3_thermal_tsc *tsc) 207 - { 208 - int temperature, low, high; 209 - 210 - rcar_gen3_thermal_get_temp(tsc, &temperature); 211 - 212 - low = temperature - MCELSIUS(1); 213 - high = temperature + MCELSIUS(1); 214 - 215 - rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1, 216 - rcar_gen3_thermal_mcelsius_to_temp(tsc, low)); 217 - 218 - rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP2, 219 - rcar_gen3_thermal_mcelsius_to_temp(tsc, high)); 220 - 221 - return 0; 222 - } 223 - 224 191 static const struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = { 225 192 .get_temp = rcar_gen3_thermal_get_temp, 226 193 }; 227 - 228 - static void rcar_thermal_irq_set(struct rcar_gen3_thermal_priv *priv, bool on) 229 - { 230 - unsigned int i; 231 - u32 val = on ? IRQ_TEMPD1 | IRQ_TEMP2 : 0; 232 - 233 - for (i = 0; i < priv->num_tscs; i++) 234 - rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQMSK, val); 235 - } 236 - 237 - static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data) 238 - { 239 - struct rcar_gen3_thermal_priv *priv = data; 240 - u32 status; 241 - int i; 242 - 243 - for (i = 0; i < priv->num_tscs; i++) { 244 - status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR); 245 - rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0); 246 - if (status) { 247 - rcar_gen3_thermal_update_range(priv->tscs[i]); 248 - thermal_zone_device_update(priv->tscs[i]->zone, 249 - THERMAL_EVENT_UNSPECIFIED); 250 - } 251 - } 252 - 253 - return IRQ_HANDLED; 254 - } 255 194 256 195 static const struct soc_device_attribute r8a7795es1[] = { 257 196 { .soc_id = "r8a7795", .revision = "ES1.*" }, ··· 209 268 210 269 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); 211 270 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0); 212 - rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2); 213 271 214 272 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 215 273 CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN); ··· 234 294 235 295 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0); 236 296 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0); 237 - rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2); 238 297 239 298 reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR); 240 299 reg_val |= THCTR_THSST; ··· 277 338 .compatible = "renesas,r8a77980-thermal", 278 339 .data = &rcar_gen3_ths_tj_1, 279 340 }, 341 + { 342 + .compatible = "renesas,r8a779a0-thermal", 343 + .data = &rcar_gen3_ths_tj_1, 344 + }, 280 345 {}, 281 346 }; 282 347 MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); ··· 288 345 static int rcar_gen3_thermal_remove(struct platform_device *pdev) 289 346 { 290 347 struct device *dev = &pdev->dev; 291 - struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev); 292 - 293 - rcar_thermal_irq_set(priv, false); 294 348 295 349 pm_runtime_put(dev); 296 350 pm_runtime_disable(dev); ··· 309 369 const int *rcar_gen3_ths_tj_1 = of_device_get_match_data(dev); 310 370 struct resource *res; 311 371 struct thermal_zone_device *zone; 312 - int ret, irq, i; 313 - char *irqname; 372 + int ret, i; 314 373 315 374 /* default values if FUSEs are missing */ 316 375 /* TODO: Read values from hardware on supported platforms */ ··· 324 385 priv->thermal_init = rcar_gen3_thermal_init_r8a7795es1; 325 386 326 387 platform_set_drvdata(pdev, priv); 327 - 328 - /* 329 - * Request 2 (of the 3 possible) IRQs, the driver only needs to 330 - * to trigger on the low and high trip points of the current 331 - * temp window at this point. 332 - */ 333 - for (i = 0; i < 2; i++) { 334 - irq = platform_get_irq(pdev, i); 335 - if (irq < 0) 336 - return irq; 337 - 338 - irqname = devm_kasprintf(dev, GFP_KERNEL, "%s:ch%d", 339 - dev_name(dev), i); 340 - if (!irqname) 341 - return -ENOMEM; 342 - 343 - ret = devm_request_threaded_irq(dev, irq, NULL, 344 - rcar_gen3_thermal_irq, 345 - IRQF_ONESHOT, irqname, priv); 346 - if (ret) 347 - return ret; 348 - } 349 388 350 389 pm_runtime_enable(dev); 351 390 pm_runtime_get_sync(dev); ··· 376 459 if (ret < 0) 377 460 goto error_unregister; 378 461 379 - rcar_gen3_thermal_update_range(tsc); 380 - 381 462 dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret); 382 463 } 383 464 ··· 386 471 goto error_unregister; 387 472 } 388 473 389 - rcar_thermal_irq_set(priv, true); 390 - 391 474 return 0; 392 475 393 476 error_unregister: 394 477 rcar_gen3_thermal_remove(pdev); 395 478 396 479 return ret; 397 - } 398 - 399 - static int __maybe_unused rcar_gen3_thermal_suspend(struct device *dev) 400 - { 401 - struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev); 402 - 403 - rcar_thermal_irq_set(priv, false); 404 - 405 - return 0; 406 480 } 407 481 408 482 static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev) ··· 403 499 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; 404 500 405 501 priv->thermal_init(tsc); 406 - rcar_gen3_thermal_update_range(tsc); 407 502 } 408 - 409 - rcar_thermal_irq_set(priv, true); 410 503 411 504 return 0; 412 505 } 413 506 414 - static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, rcar_gen3_thermal_suspend, 507 + static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, NULL, 415 508 rcar_gen3_thermal_resume); 416 509 417 510 static struct platform_driver rcar_gen3_thermal_driver = {
+2 -22
drivers/thermal/rcar_thermal.c
··· 323 323 return 0; 324 324 } 325 325 326 - static int rcar_thermal_notify(struct thermal_zone_device *zone, 327 - int trip, enum thermal_trip_type type) 328 - { 329 - struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); 330 - struct device *dev = rcar_priv_to_dev(priv); 331 - 332 - switch (type) { 333 - case THERMAL_TRIP_CRITICAL: 334 - /* FIXME */ 335 - dev_warn(dev, "Thermal reached to critical temperature\n"); 336 - break; 337 - default: 338 - break; 339 - } 340 - 341 - return 0; 342 - } 343 - 344 326 static const struct thermal_zone_of_device_ops rcar_thermal_zone_of_ops = { 345 327 .get_temp = rcar_thermal_of_get_temp, 346 328 }; ··· 331 349 .get_temp = rcar_thermal_get_temp, 332 350 .get_trip_type = rcar_thermal_get_trip_type, 333 351 .get_trip_temp = rcar_thermal_get_trip_temp, 334 - .notify = rcar_thermal_notify, 335 352 }; 336 353 337 354 /* ··· 390 409 { 391 410 struct rcar_thermal_common *common = data; 392 411 struct rcar_thermal_priv *priv; 393 - unsigned long flags; 394 412 u32 status, mask; 395 413 396 - spin_lock_irqsave(&common->lock, flags); 414 + spin_lock(&common->lock); 397 415 398 416 mask = rcar_thermal_common_read(common, INTMSK); 399 417 status = rcar_thermal_common_read(common, STR); 400 418 rcar_thermal_common_write(common, STR, 0x000F0F0F & mask); 401 419 402 - spin_unlock_irqrestore(&common->lock, flags); 420 + spin_unlock(&common->lock); 403 421 404 422 status = status & ~mask; 405 423
+17 -16
drivers/thermal/sun8i_thermal.c
··· 8 8 * Based on the work of Josef Gajdusek <atx@atx.name> 9 9 */ 10 10 11 + #include <linux/bitmap.h> 11 12 #include <linux/clk.h> 12 13 #include <linux/device.h> 13 14 #include <linux/interrupt.h> ··· 75 74 int (*calibrate)(struct ths_device *tmdev, 76 75 u16 *caldata, int callen); 77 76 int (*init)(struct ths_device *tmdev); 78 - int (*irq_ack)(struct ths_device *tmdev); 77 + unsigned long (*irq_ack)(struct ths_device *tmdev); 79 78 int (*calc_temp)(struct ths_device *tmdev, 80 79 int id, int reg); 81 80 }; ··· 147 146 .max_register = 0xfc, 148 147 }; 149 148 150 - static int sun8i_h3_irq_ack(struct ths_device *tmdev) 149 + static unsigned long sun8i_h3_irq_ack(struct ths_device *tmdev) 151 150 { 152 - int i, state, ret = 0; 151 + unsigned long irq_bitmap = 0; 152 + int i, state; 153 153 154 154 regmap_read(tmdev->regmap, SUN8I_THS_IS, &state); 155 155 ··· 158 156 if (state & SUN8I_THS_DATA_IRQ_STS(i)) { 159 157 regmap_write(tmdev->regmap, SUN8I_THS_IS, 160 158 SUN8I_THS_DATA_IRQ_STS(i)); 161 - ret |= BIT(i); 159 + bitmap_set(&irq_bitmap, i, 1); 162 160 } 163 161 } 164 162 165 - return ret; 163 + return irq_bitmap; 166 164 } 167 165 168 - static int sun50i_h6_irq_ack(struct ths_device *tmdev) 166 + static unsigned long sun50i_h6_irq_ack(struct ths_device *tmdev) 169 167 { 170 - int i, state, ret = 0; 168 + unsigned long irq_bitmap = 0; 169 + int i, state; 171 170 172 171 regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, &state); 173 172 ··· 176 173 if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) { 177 174 regmap_write(tmdev->regmap, SUN50I_H6_THS_DIS, 178 175 SUN50I_H6_THS_DATA_IRQ_STS(i)); 179 - ret |= BIT(i); 176 + bitmap_set(&irq_bitmap, i, 1); 180 177 } 181 178 } 182 179 183 - return ret; 180 + return irq_bitmap; 184 181 } 185 182 186 183 static irqreturn_t sun8i_irq_thread(int irq, void *data) 187 184 { 188 185 struct ths_device *tmdev = data; 189 - int i, state; 186 + unsigned long irq_bitmap = tmdev->chip->irq_ack(tmdev); 187 + int i; 190 188 191 - state = tmdev->chip->irq_ack(tmdev); 192 - 193 - for (i = 0; i < tmdev->chip->sensor_num; i++) { 194 - if (state & BIT(i)) 195 - thermal_zone_device_update(tmdev->sensor[i].tzd, 196 - THERMAL_EVENT_UNSPECIFIED); 189 + for_each_set_bit(i, &irq_bitmap, tmdev->chip->sensor_num) { 190 + thermal_zone_device_update(tmdev->sensor[i].tzd, 191 + THERMAL_EVENT_UNSPECIFIED); 197 192 } 198 193 199 194 return IRQ_HANDLED;
+32 -111
drivers/thermal/thermal_core.c
··· 380 380 msecs_to_jiffies(poweroff_delay_ms)); 381 381 } 382 382 383 + void thermal_zone_device_critical(struct thermal_zone_device *tz) 384 + { 385 + dev_emerg(&tz->device, "%s: critical temperature reached, " 386 + "shutting down\n", tz->type); 387 + 388 + mutex_lock(&poweroff_lock); 389 + if (!power_off_triggered) { 390 + /* 391 + * Queue a backup emergency shutdown in the event of 392 + * orderly_poweroff failure 393 + */ 394 + thermal_emergency_poweroff(); 395 + orderly_poweroff(true); 396 + power_off_triggered = true; 397 + } 398 + mutex_unlock(&poweroff_lock); 399 + } 400 + EXPORT_SYMBOL(thermal_zone_device_critical); 401 + 383 402 static void handle_critical_trips(struct thermal_zone_device *tz, 384 403 int trip, enum thermal_trip_type trip_type) 385 404 { ··· 415 396 if (tz->ops->notify) 416 397 tz->ops->notify(tz, trip, trip_type); 417 398 418 - if (trip_type == THERMAL_TRIP_CRITICAL) { 419 - dev_emerg(&tz->device, 420 - "critical temperature reached (%d C), shutting down\n", 421 - tz->temperature / 1000); 422 - mutex_lock(&poweroff_lock); 423 - if (!power_off_triggered) { 424 - /* 425 - * Queue a backup emergency shutdown in the event of 426 - * orderly_poweroff failure 427 - */ 428 - thermal_emergency_poweroff(); 429 - orderly_poweroff(true); 430 - power_off_triggered = true; 431 - } 432 - mutex_unlock(&poweroff_lock); 433 - } 399 + if (trip_type == THERMAL_TRIP_HOT && tz->ops->hot) 400 + tz->ops->hot(tz); 401 + else if (trip_type == THERMAL_TRIP_CRITICAL) 402 + tz->ops->critical(tz); 434 403 } 435 404 436 405 static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) ··· 560 553 if (atomic_read(&in_suspend)) 561 554 return; 562 555 563 - if (!tz->ops->get_temp) 556 + if (WARN_ONCE(!tz->ops->get_temp, "'%s' must not be called without " 557 + "'get_temp' ops set\n", __func__)) 564 558 return; 565 559 566 560 update_temperature(tz); ··· 599 591 thermal_zone_device, 600 592 poll_queue.work); 601 593 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 602 - } 603 - 604 - /* 605 - * Power actor section: interface to power actors to estimate power 606 - * 607 - * Set of functions used to interact to cooling devices that know 608 - * how to estimate their devices power consumption. 609 - */ 610 - 611 - /** 612 - * power_actor_get_max_power() - get the maximum power that a cdev can consume 613 - * @cdev: pointer to &thermal_cooling_device 614 - * @max_power: pointer in which to store the maximum power 615 - * 616 - * Calculate the maximum power consumption in milliwats that the 617 - * cooling device can currently consume and store it in @max_power. 618 - * 619 - * Return: 0 on success, -EINVAL if @cdev doesn't support the 620 - * power_actor API or -E* on other error. 621 - */ 622 - int power_actor_get_max_power(struct thermal_cooling_device *cdev, 623 - u32 *max_power) 624 - { 625 - if (!cdev_is_power_actor(cdev)) 626 - return -EINVAL; 627 - 628 - return cdev->ops->state2power(cdev, 0, max_power); 629 - } 630 - 631 - /** 632 - * power_actor_get_min_power() - get the mainimum power that a cdev can consume 633 - * @cdev: pointer to &thermal_cooling_device 634 - * @min_power: pointer in which to store the minimum power 635 - * 636 - * Calculate the minimum power consumption in milliwatts that the 637 - * cooling device can currently consume and store it in @min_power. 638 - * 639 - * Return: 0 on success, -EINVAL if @cdev doesn't support the 640 - * power_actor API or -E* on other error. 641 - */ 642 - int power_actor_get_min_power(struct thermal_cooling_device *cdev, 643 - u32 *min_power) 644 - { 645 - unsigned long max_state; 646 - int ret; 647 - 648 - if (!cdev_is_power_actor(cdev)) 649 - return -EINVAL; 650 - 651 - ret = cdev->ops->get_max_state(cdev, &max_state); 652 - if (ret) 653 - return ret; 654 - 655 - return cdev->ops->state2power(cdev, max_state, min_power); 656 - } 657 - 658 - /** 659 - * power_actor_set_power() - limit the maximum power a cooling device consumes 660 - * @cdev: pointer to &thermal_cooling_device 661 - * @instance: thermal instance to update 662 - * @power: the power in milliwatts 663 - * 664 - * Set the cooling device to consume at most @power milliwatts. The limit is 665 - * expected to be a cap at the maximum power consumption. 666 - * 667 - * Return: 0 on success, -EINVAL if the cooling device does not 668 - * implement the power actor API or -E* for other failures. 669 - */ 670 - int power_actor_set_power(struct thermal_cooling_device *cdev, 671 - struct thermal_instance *instance, u32 power) 672 - { 673 - unsigned long state; 674 - int ret; 675 - 676 - if (!cdev_is_power_actor(cdev)) 677 - return -EINVAL; 678 - 679 - ret = cdev->ops->power2state(cdev, power, &state); 680 - if (ret) 681 - return ret; 682 - 683 - instance->target = state; 684 - mutex_lock(&cdev->lock); 685 - cdev->updated = false; 686 - mutex_unlock(&cdev->lock); 687 - thermal_cdev_update(cdev); 688 - 689 - return 0; 690 594 } 691 595 692 596 void thermal_zone_device_rebind_exception(struct thermal_zone_device *tz, ··· 1343 1423 1344 1424 tz->id = id; 1345 1425 strlcpy(tz->type, type, sizeof(tz->type)); 1426 + 1427 + if (!ops->critical) 1428 + ops->critical = thermal_zone_device_critical; 1429 + 1346 1430 tz->ops = ops; 1347 1431 tz->tzp = tzp; 1348 1432 tz->device.class = &thermal_class; ··· 1370 1446 goto release_device; 1371 1447 1372 1448 for (count = 0; count < trips; count++) { 1373 - if (tz->ops->get_trip_type(tz, count, &trip_type)) 1374 - set_bit(count, &tz->trips_disabled); 1375 - if (tz->ops->get_trip_temp(tz, count, &trip_temp)) 1376 - set_bit(count, &tz->trips_disabled); 1377 - /* Check for bogus trip points */ 1378 - if (trip_temp == 0) 1449 + if (tz->ops->get_trip_type(tz, count, &trip_type) || 1450 + tz->ops->get_trip_temp(tz, count, &trip_temp) || 1451 + !trip_temp) 1379 1452 set_bit(count, &tz->trips_disabled); 1380 1453 } 1381 1454
-6
drivers/thermal/thermal_core.h
··· 65 65 cdev->ops->power2state; 66 66 } 67 67 68 - int power_actor_get_max_power(struct thermal_cooling_device *cdev, 69 - u32 *max_power); 70 - int power_actor_get_min_power(struct thermal_cooling_device *cdev, 71 - u32 *min_power); 72 - int power_actor_set_power(struct thermal_cooling_device *cdev, 73 - struct thermal_instance *ti, u32 power); 74 68 /** 75 69 * struct thermal_trip - representation of a point in temperature domain 76 70 * @np: pointer to struct device_node that this trip point was created from
+1 -2
drivers/thermal/thermal_hwmon.c
··· 206 206 if (new_hwmon_device) 207 207 hwmon_device_unregister(hwmon->device); 208 208 free_mem: 209 - if (new_hwmon_device) 210 - kfree(hwmon); 209 + kfree(hwmon); 211 210 212 211 return result; 213 212 }
+3 -3
drivers/thermal/thermal_sysfs.c
··· 425 425 NULL, 426 426 }; 427 427 428 - static struct attribute_group thermal_zone_attribute_group = { 428 + static const struct attribute_group thermal_zone_attribute_group = { 429 429 .attrs = thermal_zone_dev_attrs, 430 430 }; 431 431 ··· 434 434 NULL, 435 435 }; 436 436 437 - static struct attribute_group thermal_zone_mode_attribute_group = { 437 + static const struct attribute_group thermal_zone_mode_attribute_group = { 438 438 .attrs = thermal_zone_mode_attrs, 439 439 }; 440 440 ··· 468 468 return 0; 469 469 } 470 470 471 - static struct attribute_group thermal_zone_passive_attribute_group = { 471 + static const struct attribute_group thermal_zone_passive_attribute_group = { 472 472 .attrs = thermal_zone_passive_attrs, 473 473 .is_visible = thermal_zone_passive_is_visible, 474 474 };
+10 -17
include/linux/devfreq_cooling.h
··· 16 16 17 17 /** 18 18 * struct devfreq_cooling_power - Devfreq cooling power ops 19 - * @get_static_power: Take voltage, in mV, and return the static power 20 - * in mW. If NULL, the static power is assumed 21 - * to be 0. 22 - * @get_dynamic_power: Take voltage, in mV, and frequency, in HZ, and 23 - * return the dynamic power draw in mW. If NULL, 24 - * a simple power model is used. 25 - * @dyn_power_coeff: Coefficient for the simple dynamic power model in 26 - * mW/(MHz mV mV). 27 - * If get_dynamic_power() is NULL, then the 28 - * dynamic power is calculated as 29 - * @dyn_power_coeff * frequency * voltage^2 30 19 * @get_real_power: When this is set, the framework uses it to ask the 31 20 * device driver for the actual power. 32 21 * Some devices have more sophisticated methods ··· 35 46 * max total (static + dynamic) power value for each OPP. 36 47 */ 37 48 struct devfreq_cooling_power { 38 - unsigned long (*get_static_power)(struct devfreq *devfreq, 39 - unsigned long voltage); 40 - unsigned long (*get_dynamic_power)(struct devfreq *devfreq, 41 - unsigned long freq, 42 - unsigned long voltage); 43 49 int (*get_real_power)(struct devfreq *df, u32 *power, 44 50 unsigned long freq, unsigned long voltage); 45 - unsigned long dyn_power_coeff; 46 51 }; 47 52 48 53 #ifdef CONFIG_DEVFREQ_THERMAL ··· 48 65 of_devfreq_cooling_register(struct device_node *np, struct devfreq *df); 49 66 struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df); 50 67 void devfreq_cooling_unregister(struct thermal_cooling_device *dfc); 68 + struct thermal_cooling_device * 69 + devfreq_cooling_em_register(struct devfreq *df, 70 + struct devfreq_cooling_power *dfc_power); 51 71 52 72 #else /* !CONFIG_DEVFREQ_THERMAL */ 53 73 ··· 69 83 70 84 static inline struct thermal_cooling_device * 71 85 devfreq_cooling_register(struct devfreq *df) 86 + { 87 + return ERR_PTR(-EINVAL); 88 + } 89 + 90 + static inline struct thermal_cooling_device * 91 + devfreq_cooling_em_register(struct devfreq *df, 92 + struct devfreq_cooling_power *dfc_power) 72 93 { 73 94 return ERR_PTR(-EINVAL); 74 95 }
+3
include/linux/thermal.h
··· 79 79 enum thermal_trend *); 80 80 int (*notify) (struct thermal_zone_device *, int, 81 81 enum thermal_trip_type); 82 + void (*hot)(struct thermal_zone_device *); 83 + void (*critical)(struct thermal_zone_device *); 82 84 }; 83 85 84 86 struct thermal_cooling_device_ops { ··· 401 399 void thermal_notify_framework(struct thermal_zone_device *, int); 402 400 int thermal_zone_device_enable(struct thermal_zone_device *tz); 403 401 int thermal_zone_device_disable(struct thermal_zone_device *tz); 402 + void thermal_zone_device_critical(struct thermal_zone_device *tz); 404 403 #else 405 404 static inline struct thermal_zone_device *thermal_zone_device_register( 406 405 const char *type, int trips, int mask, void *devdata,
+9 -10
include/trace/events/thermal.h
··· 153 153 TRACE_EVENT(thermal_power_devfreq_get_power, 154 154 TP_PROTO(struct thermal_cooling_device *cdev, 155 155 struct devfreq_dev_status *status, unsigned long freq, 156 - u32 dynamic_power, u32 static_power, u32 power), 156 + u32 power), 157 157 158 - TP_ARGS(cdev, status, freq, dynamic_power, static_power, power), 158 + TP_ARGS(cdev, status, freq, power), 159 159 160 160 TP_STRUCT__entry( 161 161 __string(type, cdev->type ) 162 162 __field(unsigned long, freq ) 163 - __field(u32, load ) 164 - __field(u32, dynamic_power ) 165 - __field(u32, static_power ) 163 + __field(u32, busy_time) 164 + __field(u32, total_time) 166 165 __field(u32, power) 167 166 ), 168 167 169 168 TP_fast_assign( 170 169 __assign_str(type, cdev->type); 171 170 __entry->freq = freq; 172 - __entry->load = (100 * status->busy_time) / status->total_time; 173 - __entry->dynamic_power = dynamic_power; 174 - __entry->static_power = static_power; 171 + __entry->busy_time = status->busy_time; 172 + __entry->total_time = status->total_time; 175 173 __entry->power = power; 176 174 ), 177 175 178 - TP_printk("type=%s freq=%lu load=%u dynamic_power=%u static_power=%u power=%u", 176 + TP_printk("type=%s freq=%lu load=%u power=%u", 179 177 __get_str(type), __entry->freq, 180 - __entry->load, __entry->dynamic_power, __entry->static_power, 178 + __entry->total_time == 0 ? 0 : 179 + (100 * __entry->busy_time) / __entry->total_time, 181 180 __entry->power) 182 181 ); 183 182