mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'thermal-v5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux
Pull thermal updates from Daniel Lezcano: - Remove duplicate error message for the amlogic driver (Tang Bin) - Fix spellos in comments for the tegra and sun8i (Bhaskar Chowdhury) - Add the missing fifth node on the rcar_gen3 sensor (Niklas Söderlund) - Remove duplicate include in ti-bandgap (Zhang Yunkai) - Assign error code in the error path in the function thermal_of_populate_bind_params() (Jia-Ju Bai) - Fix spelling mistake in a comment 'disabed' -> 'disabled' (Colin Ian King) - Use the device name instead of auto-numbering for a better identification of the cooling device (Daniel Lezcano) - Improve a bit the division accuracy in the power allocator governor (Jeson Gao) - Enable the missing third sensor on msm8976 (Konrad Dybcio) - Add QCom tsens driver co-maintainer (Thara Gopinath) - Fix memory leak and use after free errors in the core code (Daniel Lezcano) - Add the MDM9607 compatible bindings (Konrad Dybcio) - Fix trivial spello in the copyright name for Hisilicon (Hao Fang) - Fix negative index array access when converting the frequency to power in the energy model (Brian-sy Yang) - Add support for Gen2 new PMIC support for Qcom SPMI (David Collins) - Update maintainer file for CPU cooling device section (Lukasz Luba) - Fix missing put_device on error in the Qcom tsens driver (Guangqing Zhu) - Add compatible DT binding for sm8350 (Robert Foss) - Add support for the MDM9607's tsens driver (Konrad Dybcio) - Remove duplicate error messages in thermal_mmio and the bcm2835 driver (Ruiqi Gong) - Add the Thermal Temperature Cooling driver (Zhang Rui) - Remove duplicate error messages in the Hisilicon sensor driver (Ye Bin) - Use the devm_platform_ioremap_resource_byname() function instead of a couple of corresponding calls (dingsenjie) - Sort the headers alphabetically in the ti-bandgap driver (Zhen Lei) - Add missing property in the DT thermal sensor binding (Rafał Miłecki) - Remove dead code in the ti-bandgap sensor driver (Lin Ruizhe) - Convert the BRCM DT bindings to the yaml schema (Rafał Miłecki) - Replace the thermal_notify_framework() call by a call to the thermal_zone_device_update() function. Remove the function as well as the corresponding documentation (Thara Gopinath) - Add support for the ipq8064-tsens sensor along with a set of cleanups and code preparation (Ansuel Smith) - Add a lockless __thermal_cdev_update() function to improve the locking scheme in the core code and governors (Lukasz Luba) - Fix multiple cooling device notification changes (Lukasz Luba) - Remove unneeded variable initialization (Colin Ian King) * tag 'thermal-v5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (55 commits) thermal/drivers/mtk_thermal: Remove redundant initializations of several variables thermal/core/power allocator: Use the lockless __thermal_cdev_update() function thermal/core/fair share: Use the lockless __thermal_cdev_update() function thermal/core/fair share: Lock the thermal zone while looping over instances thermal/core/power_allocator: Update once cooling devices when temp is low thermal/core/power_allocator: Maintain the device statistics from going stale thermal/core: Create a helper __thermal_cdev_update() without a lock dt-bindings: thermal: tsens: Document ipq8064 bindings thermal/drivers/tsens: Add support for ipq8064-tsens thermal/drivers/tsens: Drop unused define for msm8960 thermal/drivers/tsens: Replace custom 8960 apis with generic apis thermal/drivers/tsens: Fix bug in sensor enable for msm8960 thermal/drivers/tsens: Use init_common for msm8960 thermal/drivers/tsens: Add VER_0 tsens version thermal/drivers/tsens: Convert msm8960 to reg_field thermal/drivers/tsens: Don't hardcode sensor slope Documentation: driver-api: thermal: Remove thermal_notify_framework from documentation thermal/core: Remove thermal_notify_framework iwlwifi: mvm: tt: Replace thermal_notify_framework dt-bindings: thermal: brcm,ns-thermal: Convert to the json-schema ...
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
* Broadcom Northstar Thermal
|
||||
|
||||
This binding describes thermal sensor that is part of Northstar's DMU (Device
|
||||
Management Unit).
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "brcm,ns-thermal"
|
||||
- reg : iomem address range of PVTMON registers
|
||||
- #thermal-sensor-cells : Should be <0>
|
||||
|
||||
Example:
|
||||
|
||||
thermal: thermal@1800c2c0 {
|
||||
compatible = "brcm,ns-thermal";
|
||||
reg = <0x1800c2c0 0x10>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
cpu_thermal: cpu-thermal {
|
||||
polling-delay-passive = <0>;
|
||||
polling-delay = <1000>;
|
||||
coefficients = <(-556) 418000>;
|
||||
thermal-sensors = <&thermal>;
|
||||
|
||||
trips {
|
||||
cpu-crit {
|
||||
temperature = <125000>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/thermal/brcm,ns-thermal.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom Northstar Thermal
|
||||
|
||||
maintainers:
|
||||
- Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
description:
|
||||
Thermal sensor that is part of Northstar's DMU (Device Management Unit).
|
||||
|
||||
allOf:
|
||||
- $ref: thermal-sensor.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,ns-thermal
|
||||
|
||||
reg:
|
||||
description: PVTMON registers range
|
||||
maxItems: 1
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 0
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
thermal: thermal@1800c2c0 {
|
||||
compatible = "brcm,ns-thermal";
|
||||
reg = <0x1800c2c0 0x10>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
cpu-thermal {
|
||||
polling-delay-passive = <0>;
|
||||
polling-delay = <1000>;
|
||||
coefficients = <(-556) 418000>;
|
||||
thermal-sensors = <&thermal>;
|
||||
|
||||
trips {
|
||||
cpu-crit {
|
||||
temperature = <125000>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -19,9 +19,15 @@ description: |
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: msm9860 TSENS based
|
||||
items:
|
||||
- enum:
|
||||
- qcom,ipq8064-tsens
|
||||
|
||||
- description: v0.1 of TSENS
|
||||
items:
|
||||
- enum:
|
||||
- qcom,mdm9607-tsens
|
||||
- qcom,msm8916-tsens
|
||||
- qcom,msm8939-tsens
|
||||
- qcom,msm8974-tsens
|
||||
@@ -43,6 +49,7 @@ properties:
|
||||
- qcom,sdm845-tsens
|
||||
- qcom,sm8150-tsens
|
||||
- qcom,sm8250-tsens
|
||||
- qcom,sm8350-tsens
|
||||
- const: qcom,tsens-v2
|
||||
|
||||
reg:
|
||||
@@ -73,7 +80,9 @@ properties:
|
||||
maxItems: 2
|
||||
items:
|
||||
- const: calib
|
||||
- const: calib_sel
|
||||
- enum:
|
||||
- calib_backup
|
||||
- calib_sel
|
||||
|
||||
"#qcom,sensors":
|
||||
description:
|
||||
@@ -88,12 +97,21 @@ properties:
|
||||
Number of cells required to uniquely identify the thermal sensors. Since
|
||||
we have multiple sensors this is set to 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- "#thermal-sensor-cells"
|
||||
- "#qcom,sensors"
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq8064-tsens
|
||||
- qcom,mdm9607-tsens
|
||||
- qcom,msm8916-tsens
|
||||
- qcom,msm8974-tsens
|
||||
- qcom,msm8976-tsens
|
||||
@@ -114,17 +132,42 @@ allOf:
|
||||
interrupt-names:
|
||||
minItems: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#qcom,sensors"
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- "#thermal-sensor-cells"
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,tsens-v0_1
|
||||
- qcom,tsens-v1
|
||||
- qcom,tsens-v2
|
||||
|
||||
then:
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
// Example msm9860 based SoC (ipq8064):
|
||||
gcc: clock-controller {
|
||||
|
||||
/* ... */
|
||||
|
||||
tsens: thermal-sensor {
|
||||
compatible = "qcom,ipq8064-tsens";
|
||||
|
||||
nvmem-cells = <&tsens_calib>, <&tsens_calib_backup>;
|
||||
nvmem-cell-names = "calib", "calib_backup";
|
||||
interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "uplow";
|
||||
|
||||
#qcom,sensors = <11>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
// Example 1 (legacy: for pre v1 IP):
|
||||
|
||||
@@ -28,14 +28,7 @@ properties:
|
||||
- renesas,r8a77980-thermal # R-Car V3H
|
||||
- renesas,r8a779a0-thermal # R-Car V3U
|
||||
|
||||
reg:
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
items:
|
||||
- description: TSC1 registers
|
||||
- description: TSC2 registers
|
||||
- description: TSC3 registers
|
||||
- description: TSC4 registers
|
||||
reg: true
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
@@ -71,8 +64,25 @@ if:
|
||||
enum:
|
||||
- renesas,r8a779a0-thermal
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
items:
|
||||
- description: TSC1 registers
|
||||
- description: TSC2 registers
|
||||
- description: TSC3 registers
|
||||
required:
|
||||
- interrupts
|
||||
else:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TSC0 registers
|
||||
- description: TSC1 registers
|
||||
- description: TSC2 registers
|
||||
- description: TSC3 registers
|
||||
- description: TSC4 registers
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
@@ -111,3 +121,20 @@ examples:
|
||||
};
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/r8a779a0-sysc.h>
|
||||
|
||||
tsc_r8a779a0: thermal@e6190000 {
|
||||
compatible = "renesas,r8a779a0-thermal";
|
||||
reg = <0xe6190000 0x200>,
|
||||
<0xe6198000 0x200>,
|
||||
<0xe61a0000 0x200>,
|
||||
<0xe61a8000 0x200>,
|
||||
<0xe61b0000 0x200>;
|
||||
clocks = <&cpg CPG_MOD 919>;
|
||||
power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 919>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
|
||||
@@ -36,6 +36,9 @@ properties:
|
||||
containing several internal sensors.
|
||||
enum: [0, 1]
|
||||
|
||||
required:
|
||||
- "#thermal-sensor-cells"
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
examples:
|
||||
|
||||
@@ -730,17 +730,7 @@ This function returns the thermal_instance corresponding to a given
|
||||
{thermal_zone, cooling_device, trip_point} combination. Returns NULL
|
||||
if such an instance does not exist.
|
||||
|
||||
4.3. thermal_notify_framework
|
||||
-----------------------------
|
||||
|
||||
This function handles the trip events from sensor drivers. It starts
|
||||
throttling the cooling devices according to the policy configured.
|
||||
For CRITICAL and HOT trip points, this notifies the respective drivers,
|
||||
and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
|
||||
The throttling policy is based on the configured platform data; if no
|
||||
platform data is provided, this uses the step_wise throttling policy.
|
||||
|
||||
4.4. thermal_cdev_update
|
||||
4.3. thermal_cdev_update
|
||||
------------------------
|
||||
|
||||
This function serves as an arbitrator to set the state of a cooling
|
||||
|
||||
@@ -15197,6 +15197,7 @@ F: include/linux/if_rmnet.h
|
||||
|
||||
QUALCOMM TSENS THERMAL DRIVER
|
||||
M: Amit Kucheria <amitk@kernel.org>
|
||||
M: Thara Gopinath <thara.gopinath@linaro.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
@@ -18101,7 +18102,7 @@ THERMAL/CPU_COOLING
|
||||
M: Amit Daniel Kachhap <amit.kachhap@gmail.com>
|
||||
M: Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||
M: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
M: Javi Merino <javi.merino@kernel.org>
|
||||
R: Lukasz Luba <lukasz.luba@arm.com>
|
||||
L: linux-pm@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/driver-api/thermal/cpu-cooling-api.rst
|
||||
|
||||
@@ -132,7 +132,7 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
|
||||
/* Allow mlxsw thermal zone binding to an external cooling device */
|
||||
for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
|
||||
if (strnstr(cdev->type, mlxsw_thermal_external_allowed_cdev[i],
|
||||
sizeof(cdev->type)))
|
||||
strlen(cdev->type)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,8 +146,8 @@ void iwl_mvm_temp_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
|
||||
if (mvm->tz_device.tzone) {
|
||||
struct iwl_mvm_thermal_device *tz_dev = &mvm->tz_device;
|
||||
|
||||
thermal_notify_framework(tz_dev->tzone,
|
||||
tz_dev->fw_trips_index[ths_crossed]);
|
||||
thermal_zone_device_update(tz_dev->tzone,
|
||||
THERMAL_TRIP_VIOLATED);
|
||||
}
|
||||
#endif /* CONFIG_THERMAL */
|
||||
}
|
||||
|
||||
@@ -254,10 +254,8 @@ static int amlogic_thermal_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, pdata);
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base)) {
|
||||
dev_err(dev, "failed to get io address\n");
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
}
|
||||
|
||||
pdata->regmap = devm_regmap_init_mmio(dev, base,
|
||||
pdata->data->regmap_config);
|
||||
|
||||
@@ -184,7 +184,6 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
|
||||
data->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(data->regs)) {
|
||||
err = PTR_ERR(data->regs);
|
||||
dev_err(&pdev->dev, "Could not get registers: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/cpu_cooling.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/energy_model.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -50,8 +50,6 @@ struct time_in_idle {
|
||||
|
||||
/**
|
||||
* struct cpufreq_cooling_device - data for cooling device with cpufreq
|
||||
* @id: unique integer value corresponding to each cpufreq_cooling_device
|
||||
* registered.
|
||||
* @last_load: load measured by the latest call to cpufreq_get_requested_power()
|
||||
* @cpufreq_state: integer value representing the current state of cpufreq
|
||||
* cooling devices.
|
||||
@@ -61,7 +59,6 @@ struct time_in_idle {
|
||||
* @cdev: thermal_cooling_device pointer to keep track of the
|
||||
* registered cooling device.
|
||||
* @policy: cpufreq policy.
|
||||
* @node: list_head to link all cpufreq_cooling_device together.
|
||||
* @idle_time: idle time stats
|
||||
* @qos_req: PM QoS contraint to apply
|
||||
*
|
||||
@@ -69,23 +66,17 @@ struct time_in_idle {
|
||||
* cpufreq_cooling_device.
|
||||
*/
|
||||
struct cpufreq_cooling_device {
|
||||
int id;
|
||||
u32 last_load;
|
||||
unsigned int cpufreq_state;
|
||||
unsigned int max_level;
|
||||
struct em_perf_domain *em;
|
||||
struct cpufreq_policy *policy;
|
||||
struct list_head node;
|
||||
#ifndef CONFIG_SMP
|
||||
struct time_in_idle *idle_time;
|
||||
#endif
|
||||
struct freq_qos_request qos_req;
|
||||
};
|
||||
|
||||
static DEFINE_IDA(cpufreq_ida);
|
||||
static DEFINE_MUTEX(cooling_list_lock);
|
||||
static LIST_HEAD(cpufreq_cdev_list);
|
||||
|
||||
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
|
||||
/**
|
||||
* get_level: Find the level for a particular frequency
|
||||
@@ -125,7 +116,7 @@ static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_cdev,
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = cpufreq_cdev->max_level; i >= 0; i--) {
|
||||
for (i = cpufreq_cdev->max_level; i > 0; i--) {
|
||||
if (power >= cpufreq_cdev->em->table[i].power)
|
||||
break;
|
||||
}
|
||||
@@ -528,11 +519,11 @@ __cpufreq_cooling_register(struct device_node *np,
|
||||
{
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct cpufreq_cooling_device *cpufreq_cdev;
|
||||
char dev_name[THERMAL_NAME_LENGTH];
|
||||
unsigned int i;
|
||||
struct device *dev;
|
||||
int ret;
|
||||
struct thermal_cooling_device_ops *cooling_ops;
|
||||
char *name;
|
||||
|
||||
dev = get_cpu_device(policy->cpu);
|
||||
if (unlikely(!dev)) {
|
||||
@@ -567,16 +558,6 @@ __cpufreq_cooling_register(struct device_node *np,
|
||||
/* max_level is an index, not a counter */
|
||||
cpufreq_cdev->max_level = i - 1;
|
||||
|
||||
ret = ida_simple_get(&cpufreq_ida, 0, 0, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
cdev = ERR_PTR(ret);
|
||||
goto free_idle_time;
|
||||
}
|
||||
cpufreq_cdev->id = ret;
|
||||
|
||||
snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
|
||||
cpufreq_cdev->id);
|
||||
|
||||
cooling_ops = &cpufreq_cooling_ops;
|
||||
|
||||
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
|
||||
@@ -591,7 +572,7 @@ __cpufreq_cooling_register(struct device_node *np,
|
||||
pr_err("%s: unsorted frequency tables are not supported\n",
|
||||
__func__);
|
||||
cdev = ERR_PTR(-EINVAL);
|
||||
goto remove_ida;
|
||||
goto free_idle_time;
|
||||
}
|
||||
|
||||
ret = freq_qos_add_request(&policy->constraints,
|
||||
@@ -601,24 +582,25 @@ __cpufreq_cooling_register(struct device_node *np,
|
||||
pr_err("%s: Failed to add freq constraint (%d)\n", __func__,
|
||||
ret);
|
||||
cdev = ERR_PTR(ret);
|
||||
goto remove_ida;
|
||||
goto free_idle_time;
|
||||
}
|
||||
|
||||
cdev = thermal_of_cooling_device_register(np, dev_name, cpufreq_cdev,
|
||||
cooling_ops);
|
||||
if (IS_ERR(cdev))
|
||||
cdev = ERR_PTR(-ENOMEM);
|
||||
name = kasprintf(GFP_KERNEL, "cpufreq-%s", dev_name(dev));
|
||||
if (!name)
|
||||
goto remove_qos_req;
|
||||
|
||||
mutex_lock(&cooling_list_lock);
|
||||
list_add(&cpufreq_cdev->node, &cpufreq_cdev_list);
|
||||
mutex_unlock(&cooling_list_lock);
|
||||
cdev = thermal_of_cooling_device_register(np, name, cpufreq_cdev,
|
||||
cooling_ops);
|
||||
kfree(name);
|
||||
|
||||
if (IS_ERR(cdev))
|
||||
goto remove_qos_req;
|
||||
|
||||
return cdev;
|
||||
|
||||
remove_qos_req:
|
||||
freq_qos_remove_request(&cpufreq_cdev->qos_req);
|
||||
remove_ida:
|
||||
ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
|
||||
free_idle_time:
|
||||
free_idle_time(cpufreq_cdev);
|
||||
free_cdev:
|
||||
@@ -706,13 +688,8 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
||||
|
||||
cpufreq_cdev = cdev->devdata;
|
||||
|
||||
mutex_lock(&cooling_list_lock);
|
||||
list_del(&cpufreq_cdev->node);
|
||||
mutex_unlock(&cooling_list_lock);
|
||||
|
||||
thermal_cooling_device_unregister(cdev);
|
||||
freq_qos_remove_request(&cpufreq_cdev->qos_req);
|
||||
ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
|
||||
free_idle_time(cpufreq_cdev);
|
||||
kfree(cpufreq_cdev);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
#include <linux/cpu_cooling.h>
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/idle_inject.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/thermal.h>
|
||||
@@ -26,8 +26,6 @@ struct cpuidle_cooling_device {
|
||||
unsigned long state;
|
||||
};
|
||||
|
||||
static DEFINE_IDA(cpuidle_ida);
|
||||
|
||||
/**
|
||||
* cpuidle_cooling_runtime - Running time computation
|
||||
* @idle_duration_us: CPU idle time to inject in microseconds
|
||||
@@ -174,10 +172,11 @@ static int __cpuidle_cooling_register(struct device_node *np,
|
||||
struct idle_inject_device *ii_dev;
|
||||
struct cpuidle_cooling_device *idle_cdev;
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct device *dev;
|
||||
unsigned int idle_duration_us = TICK_USEC;
|
||||
unsigned int latency_us = UINT_MAX;
|
||||
char dev_name[THERMAL_NAME_LENGTH];
|
||||
int id, ret;
|
||||
char *name;
|
||||
int ret;
|
||||
|
||||
idle_cdev = kzalloc(sizeof(*idle_cdev), GFP_KERNEL);
|
||||
if (!idle_cdev) {
|
||||
@@ -185,16 +184,10 @@ static int __cpuidle_cooling_register(struct device_node *np,
|
||||
goto out;
|
||||
}
|
||||
|
||||
id = ida_simple_get(&cpuidle_ida, 0, 0, GFP_KERNEL);
|
||||
if (id < 0) {
|
||||
ret = id;
|
||||
goto out_kfree;
|
||||
}
|
||||
|
||||
ii_dev = idle_inject_register(drv->cpumask);
|
||||
if (!ii_dev) {
|
||||
ret = -EINVAL;
|
||||
goto out_id;
|
||||
goto out_kfree;
|
||||
}
|
||||
|
||||
of_property_read_u32(np, "duration-us", &idle_duration_us);
|
||||
@@ -205,24 +198,32 @@ static int __cpuidle_cooling_register(struct device_node *np,
|
||||
|
||||
idle_cdev->ii_dev = ii_dev;
|
||||
|
||||
snprintf(dev_name, sizeof(dev_name), "thermal-idle-%d", id);
|
||||
dev = get_cpu_device(cpumask_first(drv->cpumask));
|
||||
|
||||
cdev = thermal_of_cooling_device_register(np, dev_name, idle_cdev,
|
||||
&cpuidle_cooling_ops);
|
||||
if (IS_ERR(cdev)) {
|
||||
ret = PTR_ERR(cdev);
|
||||
name = kasprintf(GFP_KERNEL, "idle-%s", dev_name(dev));
|
||||
if (!name) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unregister;
|
||||
}
|
||||
|
||||
cdev = thermal_of_cooling_device_register(np, name, idle_cdev,
|
||||
&cpuidle_cooling_ops);
|
||||
if (IS_ERR(cdev)) {
|
||||
ret = PTR_ERR(cdev);
|
||||
goto out_kfree_name;
|
||||
}
|
||||
|
||||
pr_debug("%s: Idle injection set with idle duration=%u, latency=%u\n",
|
||||
dev_name, idle_duration_us, latency_us);
|
||||
name, idle_duration_us, latency_us);
|
||||
|
||||
kfree(name);
|
||||
|
||||
return 0;
|
||||
|
||||
out_kfree_name:
|
||||
kfree(name);
|
||||
out_unregister:
|
||||
idle_inject_unregister(ii_dev);
|
||||
out_id:
|
||||
ida_simple_remove(&cpuidle_ida, id);
|
||||
out_kfree:
|
||||
kfree(idle_cdev);
|
||||
out:
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <linux/devfreq_cooling.h>
|
||||
#include <linux/energy_model.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/pm_qos.h>
|
||||
@@ -25,11 +24,8 @@
|
||||
#define HZ_PER_KHZ 1000
|
||||
#define SCALE_ERROR_MITIGATION 100
|
||||
|
||||
static DEFINE_IDA(devfreq_ida);
|
||||
|
||||
/**
|
||||
* struct devfreq_cooling_device - Devfreq cooling device
|
||||
* @id: unique integer value corresponding to each
|
||||
* devfreq_cooling_device registered.
|
||||
* @cdev: Pointer to associated thermal cooling device.
|
||||
* @devfreq: Pointer to associated devfreq device.
|
||||
@@ -51,7 +47,6 @@ static DEFINE_IDA(devfreq_ida);
|
||||
* @em_pd: Energy Model for the associated Devfreq device
|
||||
*/
|
||||
struct devfreq_cooling_device {
|
||||
int id;
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct devfreq *devfreq;
|
||||
unsigned long cooling_state;
|
||||
@@ -363,7 +358,7 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct device *dev = df->dev.parent;
|
||||
struct devfreq_cooling_device *dfc;
|
||||
char dev_name[THERMAL_NAME_LENGTH];
|
||||
char *name;
|
||||
int err, num_opps;
|
||||
|
||||
dfc = kzalloc(sizeof(*dfc), GFP_KERNEL);
|
||||
@@ -407,30 +402,27 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
|
||||
if (err < 0)
|
||||
goto free_table;
|
||||
|
||||
err = ida_simple_get(&devfreq_ida, 0, 0, GFP_KERNEL);
|
||||
if (err < 0)
|
||||
err = -ENOMEM;
|
||||
name = kasprintf(GFP_KERNEL, "devfreq-%s", dev_name(dev));
|
||||
if (!name)
|
||||
goto remove_qos_req;
|
||||
|
||||
dfc->id = err;
|
||||
|
||||
snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id);
|
||||
|
||||
cdev = thermal_of_cooling_device_register(np, dev_name, dfc,
|
||||
cdev = thermal_of_cooling_device_register(np, name, dfc,
|
||||
&devfreq_cooling_ops);
|
||||
kfree(name);
|
||||
|
||||
if (IS_ERR(cdev)) {
|
||||
err = PTR_ERR(cdev);
|
||||
dev_err(dev,
|
||||
"Failed to register devfreq cooling device (%d)\n",
|
||||
err);
|
||||
goto release_ida;
|
||||
goto remove_qos_req;
|
||||
}
|
||||
|
||||
dfc->cdev = cdev;
|
||||
|
||||
return cdev;
|
||||
|
||||
release_ida:
|
||||
ida_simple_remove(&devfreq_ida, dfc->id);
|
||||
remove_qos_req:
|
||||
dev_pm_qos_remove_request(&dfc->req_max_freq);
|
||||
free_table:
|
||||
@@ -527,7 +519,6 @@ void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
||||
dev = dfc->devfreq->dev.parent;
|
||||
|
||||
thermal_cooling_device_unregister(dfc->cdev);
|
||||
ida_simple_remove(&devfreq_ida, dfc->id);
|
||||
dev_pm_qos_remove_request(&dfc->req_max_freq);
|
||||
|
||||
em_dev_unregister_perf_domain(dev);
|
||||
|
||||
@@ -82,6 +82,8 @@ static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
|
||||
int total_instance = 0;
|
||||
int cur_trip_level = get_trip_level(tz);
|
||||
|
||||
mutex_lock(&tz->lock);
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
if (instance->trip != trip)
|
||||
continue;
|
||||
@@ -105,11 +107,12 @@ static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
|
||||
instance->target = get_target_state(tz, cdev, percentage,
|
||||
cur_trip_level);
|
||||
|
||||
mutex_lock(&instance->cdev->lock);
|
||||
instance->cdev->updated = false;
|
||||
mutex_unlock(&instance->cdev->lock);
|
||||
thermal_cdev_update(cdev);
|
||||
mutex_lock(&cdev->lock);
|
||||
__thermal_cdev_update(cdev);
|
||||
mutex_unlock(&cdev->lock);
|
||||
}
|
||||
|
||||
mutex_unlock(&tz->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -301,9 +301,8 @@ power_actor_set_power(struct thermal_cooling_device *cdev,
|
||||
|
||||
instance->target = clamp_val(state, instance->lower, instance->upper);
|
||||
mutex_lock(&cdev->lock);
|
||||
cdev->updated = false;
|
||||
__thermal_cdev_update(cdev);
|
||||
mutex_unlock(&cdev->lock);
|
||||
thermal_cdev_update(cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -374,9 +373,11 @@ static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
|
||||
*/
|
||||
extra_power = min(extra_power, capped_extra_power);
|
||||
if (capped_extra_power > 0)
|
||||
for (i = 0; i < num_actors; i++)
|
||||
granted_power[i] += (extra_actor_power[i] *
|
||||
extra_power) / capped_extra_power;
|
||||
for (i = 0; i < num_actors; i++) {
|
||||
u64 extra_range = (u64)extra_actor_power[i] * extra_power;
|
||||
granted_power[i] += DIV_ROUND_CLOSEST_ULL(extra_range,
|
||||
capped_extra_power);
|
||||
}
|
||||
}
|
||||
|
||||
static int allocate_power(struct thermal_zone_device *tz,
|
||||
@@ -569,22 +570,33 @@ static void reset_pid_controller(struct power_allocator_params *params)
|
||||
params->prev_err = 0;
|
||||
}
|
||||
|
||||
static void allow_maximum_power(struct thermal_zone_device *tz)
|
||||
static void allow_maximum_power(struct thermal_zone_device *tz, bool update)
|
||||
{
|
||||
struct thermal_instance *instance;
|
||||
struct power_allocator_params *params = tz->governor_data;
|
||||
u32 req_power;
|
||||
|
||||
mutex_lock(&tz->lock);
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
struct thermal_cooling_device *cdev = instance->cdev;
|
||||
|
||||
if ((instance->trip != params->trip_max_desired_temperature) ||
|
||||
(!cdev_is_power_actor(instance->cdev)))
|
||||
continue;
|
||||
|
||||
instance->target = 0;
|
||||
mutex_lock(&instance->cdev->lock);
|
||||
instance->cdev->updated = false;
|
||||
/*
|
||||
* Call for updating the cooling devices local stats and avoid
|
||||
* periods of dozen of seconds when those have not been
|
||||
* maintained.
|
||||
*/
|
||||
cdev->ops->get_requested_power(cdev, &req_power);
|
||||
|
||||
if (update)
|
||||
__thermal_cdev_update(instance->cdev);
|
||||
|
||||
mutex_unlock(&instance->cdev->lock);
|
||||
thermal_cdev_update(instance->cdev);
|
||||
}
|
||||
mutex_unlock(&tz->lock);
|
||||
}
|
||||
@@ -698,6 +710,7 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
|
||||
int ret;
|
||||
int switch_on_temp, control_temp;
|
||||
struct power_allocator_params *params = tz->governor_data;
|
||||
bool update;
|
||||
|
||||
/*
|
||||
* We get called for every trip point but we only need to do
|
||||
@@ -709,9 +722,10 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
|
||||
ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
|
||||
&switch_on_temp);
|
||||
if (!ret && (tz->temperature < switch_on_temp)) {
|
||||
update = (tz->last_temperature >= switch_on_temp);
|
||||
tz->passive = 0;
|
||||
reset_pid_controller(params);
|
||||
allow_maximum_power(tz);
|
||||
allow_maximum_power(tz, update);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Hisilicon thermal sensor driver
|
||||
* HiSilicon thermal sensor driver
|
||||
*
|
||||
* Copyright (c) 2014-2015 Hisilicon Limited.
|
||||
* Copyright (c) 2014-2015 HiSilicon Limited.
|
||||
* Copyright (c) 2014-2015 Linaro Limited.
|
||||
*
|
||||
* Xinwei Kong <kong.kongxinwei@hisilicon.com>
|
||||
@@ -572,10 +572,8 @@ static int hisi_thermal_probe(struct platform_device *pdev)
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(data->regs)) {
|
||||
dev_err(dev, "failed to get io address\n");
|
||||
if (IS_ERR(data->regs))
|
||||
return PTR_ERR(data->regs);
|
||||
}
|
||||
|
||||
ret = data->ops->probe(data);
|
||||
if (ret)
|
||||
@@ -672,5 +670,5 @@ module_platform_driver(hisi_thermal_driver);
|
||||
|
||||
MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
|
||||
MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");
|
||||
MODULE_DESCRIPTION("Hisilicon thermal driver");
|
||||
MODULE_DESCRIPTION("HiSilicon thermal driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -79,3 +79,14 @@ config INTEL_PCH_THERMAL
|
||||
Enable this to support thermal reporting on certain intel PCHs.
|
||||
Thermal reporting device will provide temperature reading,
|
||||
programmable trip points and other information.
|
||||
|
||||
config INTEL_TCC_COOLING
|
||||
tristate "Intel TCC offset cooling Driver"
|
||||
depends on X86
|
||||
help
|
||||
Enable this to support system cooling by adjusting the effective TCC
|
||||
activation temperature via the TCC Offset register, which is widely
|
||||
supported on modern Intel platforms.
|
||||
Note that, on different platforms, the behavior might be different
|
||||
on how fast the setting takes effect, and how much the CPU frequency
|
||||
is reduced.
|
||||
|
||||
@@ -10,4 +10,5 @@ obj-$(CONFIG_INTEL_QUARK_DTS_THERMAL) += intel_quark_dts_thermal.o
|
||||
obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
|
||||
obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
|
||||
obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
|
||||
obj-$(CONFIG_INTEL_TCC_COOLING) += intel_tcc_cooling.o
|
||||
obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o
|
||||
|
||||
129
drivers/thermal/intel/intel_tcc_cooling.c
Normal file
129
drivers/thermal/intel/intel_tcc_cooling.c
Normal file
@@ -0,0 +1,129 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* cooling device driver that activates the processor throttling by
|
||||
* programming the TCC Offset register.
|
||||
* Copyright (c) 2021, Intel Corporation.
|
||||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
#define TCC_SHIFT 24
|
||||
#define TCC_MASK (0x3fULL<<24)
|
||||
#define TCC_PROGRAMMABLE BIT(30)
|
||||
|
||||
static struct thermal_cooling_device *tcc_cdev;
|
||||
|
||||
static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long
|
||||
*state)
|
||||
{
|
||||
*state = TCC_MASK >> TCC_SHIFT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcc_offset_update(int tcc)
|
||||
{
|
||||
u64 val;
|
||||
int err;
|
||||
|
||||
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val &= ~TCC_MASK;
|
||||
val |= tcc << TCC_SHIFT;
|
||||
|
||||
err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcc_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
|
||||
*state)
|
||||
{
|
||||
u64 val;
|
||||
int err;
|
||||
|
||||
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*state = (val & TCC_MASK) >> TCC_SHIFT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcc_set_cur_state(struct thermal_cooling_device *cdev, unsigned long
|
||||
state)
|
||||
{
|
||||
return tcc_offset_update(state);
|
||||
}
|
||||
|
||||
static const struct thermal_cooling_device_ops tcc_cooling_ops = {
|
||||
.get_max_state = tcc_get_max_state,
|
||||
.get_cur_state = tcc_get_cur_state,
|
||||
.set_cur_state = tcc_set_cur_state,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id tcc_ids[] __initconst = {
|
||||
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, NULL),
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(x86cpu, tcc_ids);
|
||||
|
||||
static int __init tcc_cooling_init(void)
|
||||
{
|
||||
int ret;
|
||||
u64 val;
|
||||
const struct x86_cpu_id *id;
|
||||
|
||||
int err;
|
||||
|
||||
id = x86_match_cpu(tcc_ids);
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
|
||||
err = rdmsrl_safe(MSR_PLATFORM_INFO, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!(val & TCC_PROGRAMMABLE))
|
||||
return -ENODEV;
|
||||
|
||||
pr_info("Programmable TCC Offset detected\n");
|
||||
|
||||
tcc_cdev =
|
||||
thermal_cooling_device_register("TCC Offset", NULL,
|
||||
&tcc_cooling_ops);
|
||||
if (IS_ERR(tcc_cdev)) {
|
||||
ret = PTR_ERR(tcc_cdev);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(tcc_cooling_init)
|
||||
|
||||
static void __exit tcc_cooling_exit(void)
|
||||
{
|
||||
thermal_cooling_device_unregister(tcc_cdev);
|
||||
}
|
||||
|
||||
module_exit(tcc_cooling_exit)
|
||||
|
||||
MODULE_DESCRIPTION("TCC offset cooling device Driver");
|
||||
MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user