Commit 15114e8f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'thermal-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control updates from Rafael Wysocki:
 "These add some new hardware support (notably, the Lunar Lake platform
  support in int340x and X1E80100 temperature sensor), continue to
  rework the thermal driver interface to eliminate trip point IDs from
  it, update DT bindings for a number of platforms and simplify probe in
  a number of thermal drivers, address issues and clean up code.

  Specifics:

   - Add DLVR and MSI interrupt support for the Lunar Lake platform to
     the int340x thermal driver (Srinivas Pandruvada)

   - Enable workload type hints (WLT) support and power floor interrupt
     support for the Lunar Lake platform in int340x ((Srinivas
     Pandruvada)

   - Switch Intel thermal drivers to new Intel CPU model defines (Tony
     Luck)

   - Clean up the int3400 and int3403 drivers (Erick Archer and David
     Alan Gilbert)

   - Improve intel_pch_thermal kernel log messages printed during
     suspend to idle (Zhang Rui)

   - Make the intel_tcc_cooling driver use a model-specific bitmask for
     TCC offset (Ricardo Neri)

   - Redesign the .set_trip_temp() thermal zone callback to take a trip
     pointer instead of a trip ID and update its users (Rafael Wysocki)

   - Avoid using invalid combinations of polling_delay and passive_delay
     thermal zone parameters (Rafael Wysocki)

   - Update a cooling device registration function to take a const
     argument (Krzysztof Kozlowski)

   - Make the uniphier thermal driver use thermal_zone_for_each_trip()
     for walking trip points (Rafael Wysocki)

   - Fix and clean up several minor shortcomings in thermal debug
     (Rafael Wysocki)

   - Rename __thermal_zone_set_trips() to thermal_zone_set_trips() and
     make it use trip thresholds (Rafael Wysocki)

   - Use READ_ONCE() for lockless access to trip temperature and
     hysteresis (Rafael Wysocki)

   - Drop unnecessary cooling device target state checks from the
     Bang-Bang thermal governor (Rafael Wysocki)

   - Avoid invoking thermal governor .trip_crossed() callback for
     critical and hot trip points (Rafael Wysocki)

   - Group all Renesas drivers inside a dedicated sub directory and add
     the missing dependency to OF (Niklas Söderlund)

   - Add suspend/resume support on k3_j72xx_bandgap and take the
     opportunity to remove an unneeded delay in the init time code path
     (Théo Lebrun)

   - Fix thermal zone definition for MT8186 and MT8188 (Julien Panis)

   - Convert hisilicon-thermal.txt to dt-schema (Abdulrasaq Lawani)

   - Add DT bindings for the X1E80100 temperature sensor (Abel Vesa)

   - Fix the thermal zone node name regular expression in the DT schema
     (Krzysztof Kozlowski)

   - Avoid failing thermal control initialization by using default
     values on some platforms where calibration data is missing (Chen-Yu
     Tsai)

   - Fix the sensor cell size in DT for the Exynos platform (Krzysztof
     Kozlowski)

   - Bring the common definition of '#thermal-sensor-cells' property in
     order to simplify the bindings on all the platforms where this
     change makes sense and do some minor cleanups (Krzysztof Kozlowski)

   - Fix a race between removal and clock disable in the broadcom
     thermal driver (Krzysztof Kozlowski)

   - Drop 'trips' DT node as required from the thermal zone bindings in
     order to fix the remaining warnings appearing for thermal zones
     without trip points (Rob Herring)

   - Simplify all the drivers where dev_err_probe() can apply (Krzysztof
     Kozlowski)

   - Clean up code related to stih416 as this platform is not described
     anywhere (Raphael Gallais-Pou)"

* tag 'thermal-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (81 commits)
  thermal/drivers/sti: Cleanup code related to stih416
  thermal/drivers/generic-adc: Simplify with dev_err_probe()
  thermal/drivers/generic-adc: Simplify probe() with local dev variable
  thermal/drivers/qcom-tsens: Simplify with dev_err_probe()
  thermal/drivers/qcom-spmi-adc-tm5: Simplify with dev_err_probe()
  thermal/drivers/imx: Simplify with dev_err_probe()
  thermal/drivers/imx: Simplify probe() with local dev variable
  thermal/drivers/hisi: Simplify with dev_err_probe()
  thermal/drivers/exynos: Simplify with dev_err_probe()
  thermal/drivers/exynos: Simplify probe() with local dev variable
  thermal/drivers/broadcom: Simplify with dev_err_probe()
  thermal/drivers/broadcom: Simplify probe() with local dev variable
  thermal/drivers/broadcom: Fix race between removal and clock disable
  dt-bindings: thermal: Drop 'trips' node as required
  dt-bindings: thermal: qoriq: reference thermal-sensor schema
  dt-bindings: thermal: cleanup examples indentation
  dt-bindings: thermal: simplify few bindings
  dt-bindings: thermal: ti,j72xx: reference thermal-sensor schema
  dt-bindings: thermal: ti,am654: reference thermal-sensor schema
  dt-bindings: thermal: st,stm32: reference thermal-sensor schema
  ...
parents 42b5a015 281cfec5
......@@ -10,6 +10,8 @@ maintainers:
- Vasily Khoruzhick <anarsoul@gmail.com>
- Yangtao Li <tiny.windzz@gmail.com>
$ref: thermal-sensor.yaml#
properties:
compatible:
enum:
......@@ -55,7 +57,6 @@ properties:
maxItems: 1
description: phandle to device controlling temperate offset SYS_CFG register
# See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
"#thermal-sensor-cells":
enum:
- 0
......@@ -135,9 +136,8 @@ required:
- compatible
- reg
- interrupts
- '#thermal-sensor-cells'
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -11,6 +11,8 @@ maintainers:
description: Binding for Amlogic Thermal
$ref: thermal-sensor.yaml#
properties:
compatible:
oneOf:
......@@ -44,11 +46,11 @@ required:
- clocks
- amlogic,ao-secure
additionalProperties: false
unevaluatedProperties: false
examples:
- |
cpu_temp: temperature-sensor@ff634800 {
temperature-sensor@ff634800 {
compatible = "amlogic,g12a-cpu-thermal",
"amlogic,g12a-thermal";
reg = <0xff634800 0x50>;
......
......@@ -19,19 +19,19 @@ description: |+
Refer to the bindings described in
Documentation/devicetree/bindings/mfd/syscon.yaml
$ref: thermal-sensor.yaml#
properties:
compatible:
const: brcm,bcm2711-thermal
# See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
"#thermal-sensor-cells":
const: 0
required:
- compatible
- '#thermal-sensor-cells'
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -42,7 +42,6 @@ additionalProperties: false
required:
- compatible
- reg
- "#thermal-sensor-cells"
examples:
- |
......
......@@ -34,7 +34,6 @@ required:
- compatible
- reg
- clocks
- '#thermal-sensor-cells'
examples:
- |
......
......@@ -28,7 +28,6 @@ properties:
required:
- compatible
- '#thermal-sensor-cells'
additionalProperties: false
......
......@@ -15,6 +15,8 @@ description:
sensor resistor. The voltage read across the sensor is mapped to
temperature using voltage-temperature lookup table.
$ref: thermal-sensor.yaml#
properties:
compatible:
const: generic-adc-thermal
......@@ -44,11 +46,10 @@ properties:
required:
- compatible
- '#thermal-sensor-cells'
- io-channels
- io-channel-names
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/thermal/hisilicon,tsensor.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Temperature Sensor on HiSilicon SoCs
maintainers:
- Abdulrasaq Lawani <abdulrasaqolawani@gmail.com>
allOf:
- $ref: thermal-sensor.yaml
properties:
compatible:
enum:
- hisilicon,tsensor
- hisilicon,hi3660-tsensor
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: thermal_clk
interrupts:
maxItems: 1
'#thermal-sensor-cells':
const: 1
required:
- compatible
- reg
- interrupts
- '#thermal-sensor-cells'
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/hi6220-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
temperature-sensor@f7030700 {
compatible = "hisilicon,tsensor";
reg = <0xf7030700 0x1000>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sys_ctrl HI6220_TSENSOR_CLK>;
clock-names = "thermal_clk";
#thermal-sensor-cells = <1>;
};
* Temperature Sensor on hisilicon SoCs
** Required properties :
- compatible: "hisilicon,tsensor".
- reg: physical base address of thermal sensor and length of memory mapped
region.
- interrupt: The interrupt number to the cpu. Defines the interrupt used
by /SOCTHERM/tsensor.
- clock-names: Input clock name, should be 'thermal_clk'.
- clocks: phandles for clock specified in "clock-names" property.
- #thermal-sensor-cells: Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description.
Example :
for Hi6220:
tsensor: tsensor@0,f7030700 {
compatible = "hisilicon,tsensor";
reg = <0x0 0xf7030700 0x0 0x1000>;
interrupts = <0 7 0x4>;
clocks = <&sys_ctrl HI6220_TSENSOR_CLK>;
clock-names = "thermal_clk";
#thermal-sensor-cells = <1>;
}
for Hi3660:
tsensor: tsensor@fff30000 {
compatible = "hisilicon,hi3660-tsensor";
reg = <0x0 0xfff30000 0x0 0x1000>;
interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
#thermal-sensor-cells = <1>;
};
......@@ -16,6 +16,8 @@ description: |
for i.MX8MM which has ONLY 1 sensor, v2 is for i.MX8MP which has
2 sensors.
$ref: thermal-sensor.yaml#
properties:
compatible:
oneOf:
......@@ -51,9 +53,8 @@ required:
- compatible
- reg
- clocks
- '#thermal-sensor-cells'
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -38,7 +38,6 @@ required:
- compatible
- reg
- interrupts
- '#thermal-sensor-cells'
if:
properties:
......
......@@ -99,7 +99,6 @@ required:
- resets
- nvmem-cells
- nvmem-cell-names
- "#thermal-sensor-cells"
additionalProperties: false
......
......@@ -197,7 +197,6 @@ required:
- clock-names
- resets
- reset-names
- "#thermal-sensor-cells"
allOf:
- $ref: thermal-sensor.yaml
......
......@@ -20,11 +20,7 @@ description: |
node. See ../firmware/nvidia,tegra186-bpmp.yaml for details of the
BPMP binding.
This node represents a thermal sensor. See
Documentation/devicetree/bindings/thermal/thermal-sensor.yaml
for details of the core thermal binding.
$ref: thermal-sensor.yaml#
properties:
compatible:
......@@ -33,10 +29,6 @@ properties:
- nvidia,tegra194-bpmp-thermal
'#thermal-sensor-cells':
$ref: /schemas/types.yaml#/definitions/uint32
description: Number of cells needed in the phandle specifier to
identify a given sensor. Must be 1 and the single cell specifies
the sensor index.
const: 1
additionalProperties: false
unevaluatedProperties: false
......@@ -27,6 +27,8 @@ description: |
TSENSOR has two channels which monitor two different spots of the SoC.
$ref: thermal-sensor.yaml#
properties:
compatible:
const: nvidia,tegra30-tsensor
......@@ -46,19 +48,14 @@ properties:
"#thermal-sensor-cells":
const: 1
assigned-clock-parents: true
assigned-clock-rates: true
assigned-clocks: true
required:
- compatible
- reg
- clocks
- resets
- interrupts
- "#thermal-sensor-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -42,7 +42,6 @@ required:
- compatible
- reg
- interrupts
- '#thermal-sensor-cells'
additionalProperties: false
......
......@@ -8,6 +8,8 @@ title: Qualcomm's SPMI PMIC ADC HC Thermal Monitoring
maintainers:
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
$ref: thermal-sensor.yaml#
properties:
compatible:
const: qcom,spmi-adc-tm-hc
......@@ -20,9 +22,6 @@ properties:
"#thermal-sensor-cells":
const: 1
description:
Number of cells required to uniquely identify the thermal sensors. Since
we have multiple sensors this is set to 1
"#address-cells":
const: 1
......@@ -106,9 +105,8 @@ required:
- interrupts
- "#address-cells"
- "#size-cells"
- "#thermal-sensor-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -8,6 +8,8 @@ title: Qualcomm's SPMI PMIC ADC Thermal Monitoring
maintainers:
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
$ref: thermal-sensor.yaml#
properties:
compatible:
enum:
......@@ -23,9 +25,6 @@ properties:
"#thermal-sensor-cells":
const: 1
description:
Number of cells required to uniquely identify the thermal sensors. Since
we have multiple sensors this is set to 1
"#address-cells":
const: 1
......@@ -159,9 +158,8 @@ required:
- interrupts
- "#address-cells"
- "#size-cells"
- "#thermal-sensor-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -67,6 +67,7 @@ properties:
- qcom,sm8450-tsens
- qcom,sm8550-tsens
- qcom,sm8650-tsens
- qcom,x1e80100-tsens
- const: qcom,tsens-v2
- description: v2 of TSENS with combined interrupt
......@@ -217,18 +218,16 @@ properties:
"#thermal-sensor-cells":
const: 1
description:
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:
- $ref: thermal-sensor.yaml#
- if:
properties:
compatible:
......@@ -292,17 +291,12 @@ allOf:
required:
- reg
additionalProperties: false
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
// Example msm9860 based SoC (ipq8064):
gcc: clock-controller {
/* ... */
tsens: thermal-sensor {
thermal-sensor {
compatible = "qcom,ipq8064-tsens";
nvmem-cells = <&tsens_calib>, <&tsens_calib_backup>;
......@@ -313,7 +307,6 @@ examples:
#qcom,sensors = <11>;
#thermal-sensor-cells = <1>;
};
};
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
......
......@@ -9,6 +9,8 @@ title: Thermal Monitoring Unit (TMU) on Freescale QorIQ SoCs
maintainers:
- Anson Huang <Anson.Huang@nxp.com>
$ref: thermal-sensor.yaml#
properties:
compatible:
description: |
......@@ -68,9 +70,8 @@ required:
- interrupts
- fsl,tmu-range
- fsl,tmu-calibration
- '#thermal-sensor-cells'
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -15,6 +15,8 @@ description:
maintainers:
- Niklas Söderlund <niklas.soderlund@ragnatech.se>
$ref: thermal-sensor.yaml#
properties:
compatible:
enum:
......@@ -57,7 +59,6 @@ required:
- clocks
- power-domains
- resets
- "#thermal-sensor-cells"
if:
properties:
......@@ -96,7 +97,7 @@ else:
required:
- interrupts
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -9,6 +9,8 @@ title: Temperature Sensor ADC (TSADC) on Rockchip SoCs
maintainers:
- Heiko Stuebner <heiko@sntech.de>
$ref: thermal-sensor.yaml#
properties:
compatible:
enum:
......@@ -76,9 +78,8 @@ required:
- clocks
- clock-names
- resets
- "#thermal-sensor-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -13,6 +13,8 @@ description:
maintainers:
- Biju Das <biju.das.jz@bp.renesas.com>
$ref: thermal-sensor.yaml#
properties:
compatible:
items:
......@@ -43,9 +45,8 @@ required:
- clocks
- power-domains
- resets
- "#thermal-sensor-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -61,7 +61,8 @@ properties:
TRIMINFO at 0x10068000 contains data for TMU channel 2
minItems: 1
'#thermal-sensor-cells': true
'#thermal-sensor-cells':
const: 0
vtmu-supply:
description: The regulator node supplying voltage to TMU.
......
......@@ -14,6 +14,8 @@ description: |
maintainers:
- Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
$ref: thermal-sensor.yaml#
properties:
compatible:
enum:
......@@ -38,9 +40,8 @@ properties:
required:
- compatible
- interrupts
- "#thermal-sensor-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -11,6 +11,8 @@ maintainers:
- Baolin Wang <baolin.wang7@gmail.com>
- Chunyan Zhang <zhang.lyra@gmail.com>
$ref: thermal-sensor.yaml#
properties:
compatible:
const: sprd,ums512-thermal
......@@ -77,15 +79,14 @@ required:
- clock-names
- nvmem-cells
- nvmem-cell-names
- "#thermal-sensor-cells"
- "#address-cells"
- "#size-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |
ap_thm0: thermal@32200000 {
thermal@32200000 {
compatible = "sprd,ums512-thermal";
reg = <0x32200000 0x10000>;
clock-names = "enable";
......
......@@ -9,6 +9,8 @@ title: STMicroelectronics STM32 digital thermal sensor (DTS)
maintainers:
- Pascal Paillet <p.paillet@foss.st.com>
$ref: thermal-sensor.yaml#
properties:
compatible:
const: st,stm32-thermal
......@@ -30,14 +32,13 @@ properties:
const: 0
required:
- "#thermal-sensor-cells"
- compatible
- reg
- interrupts
- clocks
- clock-names
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -49,7 +49,10 @@ properties:
to take when the temperature crosses those thresholds.
patternProperties:
"^[a-zA-Z][a-zA-Z0-9\\-]{1,12}-thermal$":
# Node name is limited in size due to Linux kernel requirements - 19
# characters in total (see THERMAL_NAME_LENGTH, including terminating NUL
# byte):
"^[a-zA-Z][a-zA-Z0-9\\-]{1,10}-thermal$":
type: object
description:
Each thermal zone node contains information about how frequently it
......@@ -229,7 +232,6 @@ patternProperties:
required:
- thermal-sensors
- trips
additionalProperties: false
......
......@@ -9,6 +9,8 @@ title: Texas Instruments AM654 VTM (DTS)
maintainers:
- Keerthy <j-keerthy@ti.com>
$ref: thermal-sensor.yaml#
properties:
compatible:
const: ti,am654-vtm
......@@ -26,9 +28,8 @@ required:
- compatible
- reg
- power-domains
- "#thermal-sensor-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -22,6 +22,8 @@ description: |
Temp(C) = (-9.2627e-12) * x^4 + (6.0373e-08) * x^3 + \
(-1.7058e-04) * x^2 + (3.2512e-01) * x + (-4.9003e+01)
$ref: thermal-sensor.yaml#
properties:
compatible:
enum:
......@@ -64,9 +66,8 @@ required:
- compatible
- reg
- power-domains
- "#thermal-sensor-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -19196,8 +19196,8 @@ L: linux-renesas-soc@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml
F: Documentation/devicetree/bindings/thermal/rcar-thermal.yaml
F: drivers/thermal/rcar_gen3_thermal.c
F: drivers/thermal/rcar_thermal.c
F: drivers/thermal/renesas/rcar_gen3_thermal.c
F: drivers/thermal/renesas/rcar_thermal.c
RENESAS RIIC DRIVER
M: Chris Brandt <chris.brandt@renesas.com>
......
......@@ -638,7 +638,7 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device,
}
static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
int trip, int temp)
const struct thermal_trip *trip, int temp)
{
struct iwl_mvm *mvm = thermal_zone_device_priv(device);
int ret;
......
......@@ -343,32 +343,6 @@ config ROCKCHIP_THERMAL
trip point. Cpufreq is used as the cooling device and will throttle
CPUs when the Temperature crosses the passive trip point.
config RCAR_THERMAL
tristate "Renesas R-Car thermal driver"
depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
help
Enable this to plug the R-Car thermal sensor driver into the Linux
thermal framework.
config RCAR_GEN3_THERMAL
tristate "Renesas R-Car Gen3 and RZ/G2 thermal driver"
depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
depends on OF
help
Enable this to plug the R-Car Gen3 or RZ/G2 thermal sensor driver into
the Linux thermal framework.
config RZG2L_THERMAL
tristate "Renesas RZ/G2L thermal driver"
depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
depends on OF
help
Enable this to plug the RZ/G2L thermal sensor driver into the Linux
thermal framework.
config KIRKWOOD_THERMAL
tristate "Temperature sensor on Marvell Kirkwood SoCs"
depends on MACH_KIRKWOOD || COMPILE_TEST
......@@ -459,6 +433,8 @@ depends on (ARCH_STI || ARCH_STM32) && OF
source "drivers/thermal/st/Kconfig"
endmenu
source "drivers/thermal/renesas/Kconfig"
source "drivers/thermal/tegra/Kconfig"
config GENERIC_ADC_THERMAL
......
......@@ -38,9 +38,7 @@ obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
obj-$(CONFIG_RCAR_GEN3_THERMAL) += rcar_gen3_thermal.o
obj-$(CONFIG_RZG2L_THERMAL) += rzg2l_thermal.o
obj-y += renesas/
obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
obj-y += samsung/
obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
......
......@@ -163,6 +163,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
static int bcm2835_thermal_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *match;
struct thermal_zone_device *tz;
struct bcm2835_thermal_data *data;
......@@ -170,12 +171,11 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
u32 val;
unsigned long rate;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
match = of_match_device(bcm2835_thermal_of_match_table,
&pdev->dev);
match = of_match_device(bcm2835_thermal_of_match_table, dev);
if (!match)
return -EINVAL;
......@@ -185,34 +185,20 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
return err;
}
data->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->clk)) {
err = PTR_ERR(data->clk);
if (err != -EPROBE_DEFER)
dev_err(&pdev->dev, "Could not get clk: %d\n", err);
return err;
}
err = clk_prepare_enable(data->clk);
if (err)
return err;
data->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(data->clk))
return dev_err_probe(dev, PTR_ERR(data->clk), "Could not get clk\n");
rate = clk_get_rate(data->clk);
if ((rate < 1920000) || (rate > 5000000))
dev_warn(&pdev->dev,
dev_warn(dev,
"Clock %pCn running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n",
data->clk, rate);
/* register of thermal sensor and get info from DT */
tz = devm_thermal_of_zone_register(&pdev->dev, 0, data,
&bcm2835_thermal_ops);
if (IS_ERR(tz)) {
err = PTR_ERR(tz);
dev_err(&pdev->dev,
"Failed to register the thermal device: %d\n",
err);
goto err_clk;
}
tz = devm_thermal_of_zone_register(dev, 0, data, &bcm2835_thermal_ops);
if (IS_ERR(tz))
return dev_err_probe(dev, PTR_ERR(tz), "Failed to register the thermal device\n");
/*
* right now the FW does set up the HW-block, so we are not
......@@ -233,10 +219,8 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
*/
err = thermal_zone_get_trip(tz, 0, &trip);
if (err < 0) {
dev_err(&pdev->dev,
"Not able to read trip_temp: %d\n",
err);
goto err_tz;
dev_err(dev, "Not able to read trip_temp: %d\n", err);
return err;
}
/* set bandgap reference voltage and enable voltage regulator */
......@@ -269,17 +253,11 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
*/
err = thermal_add_hwmon_sysfs(tz);
if (err)
goto err_tz;
return err;
bcm2835_thermal_debugfs(pdev);
return 0;
err_tz:
devm_thermal_of_zone_unregister(&pdev->dev, tz);
err_clk:
clk_disable_unprepare(data->clk);
return err;
}
static void bcm2835_thermal_remove(struct platform_device *pdev)
......@@ -287,7 +265,6 @@ static void bcm2835_thermal_remove(struct platform_device *pdev)
struct bcm2835_thermal_data *data = platform_get_drvdata(pdev);
debugfs_remove_recursive(data->debugfsdir);
clk_disable_unprepare(data->clk);
}
static struct platform_driver bcm2835_thermal_driver = {
......
......@@ -57,24 +57,16 @@ static void bang_bang_control(struct thermal_zone_device *tz,
if (instance->trip != trip)
continue;
if (instance->target == THERMAL_NO_TARGET)
instance->target = 0;
if (instance->target != 0 && instance->target != 1) {
if (instance->target != 0 && instance->target != 1 &&
instance->target != THERMAL_NO_TARGET)
pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n",
instance->target, instance->name);
instance->target = 1;
}
/*
* Enable the fan when the trip is crossed on the way up and
* disable it when the trip is crossed on the way down.
*/
if (instance->target == 0 && crossed_up)
instance->target = 1;
else if (instance->target == 1 && !crossed_up)
instance->target = 0;
instance->target = crossed_up;
dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target);
......
......@@ -388,15 +388,10 @@ static int hi6220_thermal_probe(struct hisi_thermal_data *data)
{
struct platform_device *pdev = data->pdev;
struct device *dev = &pdev->dev;
int ret;
data->clk = devm_clk_get(dev, "thermal_clk");
if (IS_ERR(data->clk)) {
ret = PTR_ERR(data->clk);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get thermal clk: %d\n", ret);
return ret;
}
if (IS_ERR(data->clk))
return dev_err_probe(dev, PTR_ERR(data->clk), "failed to get thermal clk\n");
data->sensor = devm_kzalloc(dev, sizeof(*data->sensor), GFP_KERNEL);
if (!data->sensor)
......
......@@ -331,25 +331,16 @@ static int imx_change_mode(struct thermal_zone_device *tz,
return 0;
}
static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip_id,
int temp)
static int imx_set_trip_temp(struct thermal_zone_device *tz,
const struct thermal_trip *trip, int temp)
{
struct imx_thermal_data *data = thermal_zone_device_priv(tz);
struct thermal_trip trip;
int ret;
ret = pm_runtime_resume_and_get(data->dev);
if (ret < 0)
return ret;
ret = __thermal_zone_get_trip(tz, trip_id, &trip);
if (ret)
return ret;
/* do not allow changing critical threshold */
if (trip.type == THERMAL_TRIP_CRITICAL)
return -EPERM;
/* do not allow passive to be set higher than critical */
if (temp < 0 || temp > trips[IMX_TRIP_CRITICAL].temperature)
return -EINVAL;
......@@ -601,28 +592,29 @@ static inline void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data
static int imx_thermal_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct imx_thermal_data *data;
struct regmap *map;
int measure_freq;
int ret;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->dev = &pdev->dev;
data->dev = dev;
map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
map = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,tempmon");
if (IS_ERR(map)) {
ret = PTR_ERR(map);
dev_err(&pdev->dev, "failed to get tempmon regmap: %d\n", ret);
dev_err(dev, "failed to get tempmon regmap: %d\n", ret);
return ret;
}
data->tempmon = map;
data->socdata = of_device_get_match_data(&pdev->dev);
data->socdata = of_device_get_match_data(dev);
if (!data->socdata) {
dev_err(&pdev->dev, "no device match found\n");
dev_err(dev, "no device match found\n");
return -ENODEV;
}
......@@ -645,15 +637,15 @@ static int imx_thermal_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
if (of_property_present(pdev->dev.of_node, "nvmem-cells")) {
if (of_property_present(dev->of_node, "nvmem-cells")) {
ret = imx_init_from_nvmem_cells(pdev);
if (ret)
return dev_err_probe(&pdev->dev, ret,
return dev_err_probe(dev, ret,
"failed to init from nvmem\n");
} else {
ret = imx_init_from_tempmon_data(pdev);
if (ret) {
dev_err(&pdev->dev, "failed to init from fsl,tempmon-data\n");
dev_err(dev, "failed to init from fsl,tempmon-data\n");
return ret;
}
}
......@@ -673,15 +665,12 @@ static int imx_thermal_probe(struct platform_device *pdev)
ret = imx_thermal_register_legacy_cooling(data);
if (ret)
return dev_err_probe(&pdev->dev, ret,
return dev_err_probe(dev, ret,
"failed to register cpufreq cooling device\n");
data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
data->thermal_clk = devm_clk_get(dev, NULL);
if (IS_ERR(data->thermal_clk)) {
ret = PTR_ERR(data->thermal_clk);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"failed to get thermal clk: %d\n", ret);
ret = dev_err_probe(dev, PTR_ERR(data->thermal_clk), "failed to get thermal clk\n");
goto legacy_cleanup;
}
......@@ -694,7 +683,7 @@ static int imx_thermal_probe(struct platform_device *pdev)
*/
ret = clk_prepare_enable(data->thermal_clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
dev_err(dev, "failed to enable thermal clk: %d\n", ret);
goto legacy_cleanup;
}
......@@ -707,12 +696,12 @@ static int imx_thermal_probe(struct platform_device *pdev)
IMX_POLLING_DELAY);
if (IS_ERR(data->tz)) {
ret = PTR_ERR(data->tz);
dev_err(&pdev->dev,
"failed to register thermal zone device %d\n", ret);
dev_err(dev, "failed to register thermal zone device %d\n",
ret);
goto clk_disable;
}
dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC"
dev_info(dev, "%s CPU temperature grade - max:%dC"
" critical:%dC passive:%dC\n", data->temp_grade,
data->temp_max / 1000, trips[IMX_TRIP_CRITICAL].temperature / 1000,
trips[IMX_TRIP_PASSIVE].temperature / 1000);
......@@ -736,7 +725,7 @@ static int imx_thermal_probe(struct platform_device *pdev)
usleep_range(20, 50);
/* the core was configured and enabled just before */
pm_runtime_set_active(&pdev->dev);
pm_runtime_set_active(dev);
pm_runtime_enable(data->dev);
ret = pm_runtime_resume_and_get(data->dev);
......@@ -748,11 +737,11 @@ static int imx_thermal_probe(struct platform_device *pdev)
if (ret)
goto thermal_zone_unregister;
ret = devm_request_threaded_irq(&pdev->dev, data->irq,
ret = devm_request_threaded_irq(dev, data->irq,
imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
0, "imx_thermal", data);
if (ret < 0) {
dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
dev_err(dev, "failed to request alarm irq: %d\n", ret);
goto thermal_zone_unregister;
}
......
......@@ -571,7 +571,7 @@ static int int3400_thermal_probe(struct platform_device *pdev)
if (!adev)
return -ENODEV;
priv = kzalloc(sizeof(struct int3400_thermal_priv), GFP_KERNEL);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
......
......@@ -25,17 +25,6 @@ struct int3403_sensor {
struct int34x_thermal_zone *int340x_zone;
};
struct int3403_performance_state {
u64 performance;
u64 power;
u64 latency;
u64 linear;
u64 control;
u64 raw_performace;
char *raw_unit;
int reserved;
};
struct int3403_cdev {
struct thermal_cooling_device *cdev;
unsigned long max_state;
......
......@@ -39,13 +39,14 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
}
static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
int trip, int temp)
const struct thermal_trip *trip, int temp)
{
struct int34x_thermal_zone *d = thermal_zone_device_priv(zone);
char name[] = {'P', 'A', 'T', '0' + trip, '\0'};
unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
char name[] = {'P', 'A', 'T', '0' + trip_index, '\0'};
acpi_status status;
if (trip > 9)
if (trip_index > 9)
return -EINVAL;
status = acpi_execute_simple_method(d->adev->handle, name,
......@@ -62,16 +63,6 @@ static void int340x_thermal_critical(struct thermal_zone_device *zone)
thermal_zone_device_type(zone));
}
static inline void *int_to_trip_priv(int i)
{
return (void *)(long)i;
}
static inline int trip_priv_to_int(const struct thermal_trip *trip)
{
return (long)trip->priv;
}
static int int340x_thermal_read_trips(struct acpi_device *zone_adev,
struct thermal_trip *zone_trips,
int trip_cnt)
......@@ -106,7 +97,7 @@ static int int340x_thermal_read_trips(struct acpi_device *zone_adev,
break;
zone_trips[trip_cnt].type = THERMAL_TRIP_ACTIVE;
zone_trips[trip_cnt].priv = int_to_trip_priv(i);
zone_trips[trip_cnt].priv = THERMAL_INT_TO_TRIP_PRIV(i);
trip_cnt++;
}
......@@ -154,6 +145,7 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
zone_trips[i].type = THERMAL_TRIP_PASSIVE;
zone_trips[i].temperature = THERMAL_TEMP_INVALID;
zone_trips[i].flags |= THERMAL_TRIP_FLAG_RW_TEMP;
zone_trips[i].priv = THERMAL_INT_TO_TRIP_PRIV(i);
}
trip_cnt = int340x_thermal_read_trips(adev, zone_trips, trip_cnt);
......@@ -224,7 +216,7 @@ static int int340x_update_one_trip(struct thermal_trip *trip, void *arg)
break;
case THERMAL_TRIP_ACTIVE:
err = thermal_acpi_active_trip_temp(zone_adev,
trip_priv_to_int(trip),
THERMAL_TRIP_PRIV_TO_INT(trip->priv),
&temp);
break;
default:
......
......@@ -440,7 +440,8 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *
proc_thermal_rapl_remove();
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR ||
proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS)
proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS ||
proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR)
proc_thermal_rfim_remove(pdev);
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR)
......
......@@ -65,6 +65,7 @@ struct rapl_mmio_regs {
#define PROC_THERMAL_FEATURE_DLVR 0x10
#define PROC_THERMAL_FEATURE_WT_HINT 0x20
#define PROC_THERMAL_FEATURE_POWER_FLOOR 0x40
#define PROC_THERMAL_FEATURE_MSI_SUPPORT 0x80
#if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL)
int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
......
......@@ -63,6 +63,18 @@ static struct proc_thermal_mmio_info proc_thermal_mmio_info[] = {
{ PROC_THERMAL_MMIO_INT_STATUS_1, 0x7200, 8, 0x01 },
};
/* List of supported MSI IDs (sources) */
enum proc_thermal_msi_ids {
PKG_THERMAL,
DDR_THERMAL,
THERM_POWER_FLOOR,
WORKLOAD_CHANGE,
MSI_THERMAL_MAX
};
/* Stores IRQ associated with a MSI ID */
static int proc_thermal_msi_map[MSI_THERMAL_MAX];
#define B0D4_THERMAL_NOTIFY_DELAY 1000
static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY;
......@@ -146,22 +158,41 @@ static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid)
return IRQ_HANDLED;
}
static int proc_thermal_match_msi_irq(int irq)
{
int i;
if (!use_msi)
goto msi_fail;
for (i = 0; i < MSI_THERMAL_MAX; i++) {
if (proc_thermal_msi_map[i] == irq)
return i;
}
msi_fail:
return -EOPNOTSUPP;
}
static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
{
struct proc_thermal_pci *pci_info = devid;
struct proc_thermal_device *proc_priv;
int ret = IRQ_NONE;
int ret = IRQ_NONE, msi_id;
u32 status;
proc_priv = pci_info->proc_priv;
msi_id = proc_thermal_match_msi_irq(irq);
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) {
if (proc_thermal_check_wt_intr(pci_info->proc_priv))
if (msi_id == WORKLOAD_CHANGE || proc_thermal_check_wt_intr(pci_info->proc_priv))
ret = IRQ_WAKE_THREAD;
}
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) {
if (proc_thermal_check_power_floor_intr(pci_info->proc_priv))
if (msi_id == THERM_POWER_FLOOR ||
proc_thermal_check_power_floor_intr(pci_info->proc_priv))
ret = IRQ_WAKE_THREAD;
}
......@@ -171,7 +202,7 @@ static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
* interrupt before scheduling work function for thermal threshold.
*/
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status);
if (status) {
if (msi_id == PKG_THERMAL || status) {
/* Disable enable interrupt flag */
proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
pkg_thermal_schedule_work(&pci_info->work);
......@@ -194,7 +225,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
return 0;
}
static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
static int sys_set_trip_temp(struct thermal_zone_device *tzd,
const struct thermal_trip *trip, int temp)
{
struct proc_thermal_pci *pci_info = thermal_zone_device_priv(tzd);
int tjmax, _temp;
......@@ -244,6 +276,45 @@ static struct thermal_zone_params tzone_params = {
.no_hwmon = true,
};
static bool msi_irq;
static int proc_thermal_setup_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info)
{
int ret, i, irq;
ret = pci_alloc_irq_vectors(pdev, 1, MSI_THERMAL_MAX, PCI_IRQ_MSI | PCI_IRQ_MSIX);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to allocate vectors!\n");
return ret;
}
dev_info(&pdev->dev, "msi enabled:%d msix enabled:%d\n", pdev->msi_enabled,
pdev->msix_enabled);
for (i = 0; i < MSI_THERMAL_MAX; i++) {
irq = pci_irq_vector(pdev, i);
ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler,
proc_thermal_irq_thread_handler,
0, KBUILD_MODNAME, pci_info);
if (ret) {
dev_err(&pdev->dev, "Request IRQ %d failed\n", irq);
goto err_free_msi_vectors;
}
proc_thermal_msi_map[i] = irq;
}
msi_irq = true;
return 0;
err_free_msi_vectors:
pci_free_irq_vectors(pdev);
return ret;
}
static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct proc_thermal_device *proc_priv;
......@@ -253,7 +324,6 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
.flags = THERMAL_TRIP_FLAG_RW_TEMP,
};
int irq_flag = 0, irq, ret;
bool msi_irq = false;
proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
if (!proc_priv)
......@@ -299,27 +369,24 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
goto err_del_legacy;
}
if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) {
/* request and enable interrupt */
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to allocate vectors!\n");
goto err_ret_tzone;
}
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MSI_SUPPORT)
use_msi = true;
irq = pci_irq_vector(pdev, 0);
msi_irq = true;
if (use_msi) {
ret = proc_thermal_setup_msi(pdev, pci_info);
if (ret)
goto err_ret_tzone;
} else {
irq_flag = IRQF_SHARED;
irq = pdev->irq;
}
ret = devm_request_threaded_irq(&pdev->dev, irq,
proc_thermal_irq_handler, proc_thermal_irq_thread_handler,
irq_flag, KBUILD_MODNAME, pci_info);
ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler,
proc_thermal_irq_thread_handler, irq_flag,
KBUILD_MODNAME, pci_info);
if (ret) {
dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq);
goto err_free_vectors;
goto err_ret_tzone;
}
}
ret = thermal_zone_device_enable(pci_info->tzone);
......@@ -352,9 +419,6 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev)
proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0);
proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
devm_free_irq(&pdev->dev, pdev->irq, pci_info);
pci_free_irq_vectors(pdev);
thermal_zone_device_unregister(pci_info->tzone);
proc_thermal_mmio_remove(pdev, pci_info->proc_priv);
if (!pci_info->no_legacy)
......@@ -408,7 +472,9 @@ static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
static const struct pci_device_id proc_thermal_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL |
PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) },
{ PCI_DEVICE_DATA(INTEL, LNLM_THERMAL, PROC_THERMAL_FEATURE_RAPL) },
{ PCI_DEVICE_DATA(INTEL, LNLM_THERMAL, PROC_THERMAL_FEATURE_MSI_SUPPORT |
PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DLVR |
PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) },
{ PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL |
PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR |
PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) },
......
......@@ -19,6 +19,12 @@ struct mmio_reg {
u16 shift;
};
struct mapping_table {
const char *attr_name;
const u32 value;
const char *mapped_str;
};
/* These will represent sysfs attribute names */
static const char * const fivr_strings[] = {
"vco_ref_code_lo",
......@@ -62,6 +68,78 @@ static const struct mmio_reg dlvr_mmio_regs[] = {
{ 1, 0x15A10, 1, 0x1, 16}, /* dlvr_pll_busy */
};
static const struct mmio_reg lnl_dlvr_mmio_regs[] = {
{ 0, 0x5A08, 5, 0x1F, 0}, /* dlvr_spread_spectrum_pct */
{ 0, 0x5A08, 1, 0x1, 5}, /* dlvr_control_mode */
{ 0, 0x5A08, 1, 0x1, 6}, /* dlvr_control_lock */
{ 0, 0x5A08, 1, 0x1, 7}, /* dlvr_rfim_enable */
{ 0, 0x5A08, 2, 0x3, 8}, /* dlvr_freq_select */
{ 1, 0x5A10, 2, 0x3, 30}, /* dlvr_hardware_rev */
{ 1, 0x5A10, 2, 0x3, 0}, /* dlvr_freq_mhz */
{ 1, 0x5A10, 1, 0x1, 23}, /* dlvr_pll_busy */
};
static const struct mapping_table lnl_dlvr_mapping[] = {
{"dlvr_freq_select", 0, "2227.2"},
{"dlvr_freq_select", 1, "2140"},
{"dlvr_freq_mhz", 0, "2227.2"},
{"dlvr_freq_mhz", 1, "2140"},
{NULL, 0, NULL},
};
static int match_mapping_table(const struct mapping_table *table, const char *attr_name,
bool match_int_value, const u32 value, const char *value_str,
char **result_str, u32 *result_int)
{
bool attr_matched = false;
int i = 0;
if (!table)
return -EOPNOTSUPP;
while (table[i].attr_name) {
if (strncmp(table[i].attr_name, attr_name, strlen(attr_name)))
goto match_next;
attr_matched = true;
if (match_int_value) {
if (table[i].value != value)
goto match_next;
*result_str = (char *)table[i].mapped_str;
return 0;
}
if (strncmp(table[i].mapped_str, value_str, strlen(table[i].mapped_str)))
goto match_next;
*result_int = table[i].value;
return 0;
match_next:
i++;
}
/* If attribute name is matched, then the user space value is invalid */
if (attr_matched)
return -EINVAL;
return -EOPNOTSUPP;
}
static int get_mapped_string(const struct mapping_table *table, const char *attr_name,
u32 value, char **result)
{
return match_mapping_table(table, attr_name, true, value, NULL, result, NULL);
}
static int get_mapped_value(const struct mapping_table *table, const char *attr_name,
const char *value, unsigned int *result)
{
return match_mapping_table(table, attr_name, false, 0, value, NULL, result);
}
/* These will represent sysfs attribute names */
static const char * const dvfs_strings[] = {
"rfi_restriction_run_busy",
......@@ -93,12 +171,14 @@ static ssize_t suffix##_show(struct device *dev,\
struct device_attribute *attr,\
char *buf)\
{\
const struct mapping_table *mapping = NULL;\
struct proc_thermal_device *proc_priv;\
struct pci_dev *pdev = to_pci_dev(dev);\
const struct mmio_reg *mmio_regs;\
const char **match_strs;\
int ret, err;\
u32 reg_val;\
int ret;\
char *str;\
\
proc_priv = pci_get_drvdata(pdev);\
if (table == 1) {\
......@@ -106,7 +186,12 @@ static ssize_t suffix##_show(struct device *dev,\
mmio_regs = adl_dvfs_mmio_regs;\
} else if (table == 2) { \
match_strs = (const char **)dlvr_strings;\
if (pdev->device == PCI_DEVICE_ID_INTEL_LNLM_THERMAL) {\
mmio_regs = lnl_dlvr_mmio_regs;\
mapping = lnl_dlvr_mapping;\
} else {\
mmio_regs = dlvr_mmio_regs;\
} \
} else {\
match_strs = (const char **)fivr_strings;\
mmio_regs = tgl_fivr_mmio_regs;\
......@@ -116,7 +201,12 @@ static ssize_t suffix##_show(struct device *dev,\
return ret;\
reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\
err = get_mapped_string(mapping, attr->attr.name, ret, &str);\
if (!err)\
return sprintf(buf, "%s\n", str);\
if (err == -EOPNOTSUPP)\
return sprintf(buf, "%u\n", ret);\
return err;\
}
#define RFIM_STORE(suffix, table)\
......@@ -124,6 +214,7 @@ static ssize_t suffix##_store(struct device *dev,\
struct device_attribute *attr,\
const char *buf, size_t count)\
{\
const struct mapping_table *mapping = NULL;\
struct proc_thermal_device *proc_priv;\
struct pci_dev *pdev = to_pci_dev(dev);\
unsigned int input;\
......@@ -139,7 +230,12 @@ static ssize_t suffix##_store(struct device *dev,\
mmio_regs = adl_dvfs_mmio_regs;\
} else if (table == 2) { \
match_strs = (const char **)dlvr_strings;\
if (pdev->device == PCI_DEVICE_ID_INTEL_LNLM_THERMAL) {\
mmio_regs = lnl_dlvr_mmio_regs;\
mapping = lnl_dlvr_mapping;\
} else {\
mmio_regs = dlvr_mmio_regs;\
} \
} else {\
match_strs = (const char **)fivr_strings;\
mmio_regs = tgl_fivr_mmio_regs;\
......@@ -150,9 +246,14 @@ static ssize_t suffix##_store(struct device *dev,\
return ret;\
if (mmio_regs[ret].read_only)\
return -EPERM;\
err = get_mapped_value(mapping, attr->attr.name, buf, &input);\
if (err == -EINVAL)\
return err;\
if (err == -EOPNOTSUPP) {\
err = kstrtouint(buf, 10, &input);\
if (err)\
return err;\
} \
mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\
reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
reg_val &= ~mask;\
......
......@@ -401,10 +401,10 @@ static void hfi_disable(void)
* intel_hfi_online() - Enable HFI on @cpu
* @cpu: CPU in which the HFI will be enabled
*
* Enable the HFI to be used in @cpu. The HFI is enabled at the die/package
* level. The first CPU in the die/package to come online does the full HFI
* Enable the HFI to be used in @cpu. The HFI is enabled at the package
* level. The first CPU in the package to come online does the full HFI
* initialization. Subsequent CPUs will just link themselves to the HFI
* instance of their die/package.
* instance of their package.
*
* This function is called before enabling the thermal vector in the local APIC
* in order to ensure that @cpu has an associated HFI instance when it receives
......@@ -414,31 +414,31 @@ void intel_hfi_online(unsigned int cpu)
{
struct hfi_instance *hfi_instance;
struct hfi_cpu_info *info;
u16 die_id;
u16 pkg_id;
/* Nothing to do if hfi_instances are missing. */
if (!hfi_instances)
return;
/*
* Link @cpu to the HFI instance of its package/die. It does not
* Link @cpu to the HFI instance of its package. It does not
* matter whether the instance has been initialized.
*/
info = &per_cpu(hfi_cpu_info, cpu);
die_id = topology_logical_die_id(cpu);
pkg_id = topology_logical_package_id(cpu);
hfi_instance = info->hfi_instance;
if (!hfi_instance) {
if (die_id >= max_hfi_instances)
if (pkg_id >= max_hfi_instances)
return;
hfi_instance = &hfi_instances[die_id];
hfi_instance = &hfi_instances[pkg_id];
info->hfi_instance = hfi_instance;
}
init_hfi_cpu_index(info);
/*
* Now check if the HFI instance of the package/die of @cpu has been
* Now check if the HFI instance of the package of @cpu has been
* initialized (by checking its header). In such case, all we have to
* do is to add @cpu to this instance's cpumask and enable the instance
* if needed.
......@@ -504,7 +504,7 @@ void intel_hfi_online(unsigned int cpu)
*
* On some processors, hardware remembers previous programming settings even
* after being reprogrammed. Thus, keep HFI enabled even if all CPUs in the
* die/package of @cpu are offline. See note in intel_hfi_online().
* package of @cpu are offline. See note in intel_hfi_online().
*/
void intel_hfi_offline(unsigned int cpu)
{
......@@ -674,9 +674,13 @@ void __init intel_hfi_init(void)
if (hfi_parse_features())
return;
/* There is one HFI instance per die/package. */
max_hfi_instances = topology_max_packages() *
topology_max_dies_per_package();
/*
* Note: HFI resources are managed at the physical package scope.
* There could be platforms that enumerate packages as Linux dies.
* Special handling would be needed if this happens on an HFI-capable
* platform.
*/
max_hfi_instances = topology_max_packages();
/*
* This allocation may fail. CPU hotplug callbacks must check
......
......@@ -298,6 +298,11 @@ static int intel_pch_thermal_suspend_noirq(struct device *device)
/* Get the PCH current temperature value */
pch_cur_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP));
if (pch_cur_temp >= pch_thr_temp)
dev_warn(&ptd->pdev->dev,
"CPU-PCH current temp [%dC] higher than the threshold temp [%dC], S0ix might fail. Start cooling...\n",
pch_cur_temp, pch_thr_temp);
/*
* If current PCH temperature is higher than configured PCH threshold
* value, run some delay loop with sleep to let the current temperature
......
......@@ -195,7 +195,7 @@ static int get_trip_temp(int trip)
}
static int update_trip_temp(struct soc_sensor_entry *aux_entry,
int trip, int temp)
int trip_index, int temp)
{
u32 out;
u32 temp_out;
......@@ -230,9 +230,9 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry,
*/
temp_out = temp + QRK_DTS_TEMP_BASE;
out = (store_ptps & ~(QRK_DTS_MASK_TP_THRES <<
(trip * QRK_DTS_SHIFT_TP)));
(trip_index * QRK_DTS_SHIFT_TP)));
out |= (temp_out & QRK_DTS_MASK_TP_THRES) <<
(trip * QRK_DTS_SHIFT_TP);
(trip_index * QRK_DTS_SHIFT_TP);
ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
QRK_DTS_REG_OFFSET_PTPS, out);
......@@ -242,10 +242,26 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry,
return ret;
}
static inline int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
static inline int sys_set_trip_temp(struct thermal_zone_device *tzd,
const struct thermal_trip *trip,
int temp)
{
return update_trip_temp(thermal_zone_device_priv(tzd), trip, temp);
unsigned int trip_index;
switch (trip->type) {
case THERMAL_TRIP_HOT:
trip_index = QRK_DTS_ID_TP_HOT;
break;
case THERMAL_TRIP_CRITICAL:
trip_index = QRK_DTS_ID_TP_CRITICAL;
break;
default:
return -EINVAL;
}
return update_trip_temp(thermal_zone_device_priv(tzd), trip_index, temp);
}
static int sys_get_curr_temp(struct thermal_zone_device *tzd,
......
......@@ -129,18 +129,20 @@ static int update_trip_temp(struct intel_soc_dts_sensors *sensors,
return status;
}
static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
static int sys_set_trip_temp(struct thermal_zone_device *tzd,
const struct thermal_trip *trip,
int temp)
{
struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
struct intel_soc_dts_sensors *sensors = dts->sensors;
unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
int status;
if (temp > sensors->tj_max)
return -EINVAL;
mutex_lock(&sensors->dts_update_lock);
status = update_trip_temp(sensors, trip, temp);
status = update_trip_temp(sensors, trip_index, temp);
mutex_unlock(&sensors->dts_update_lock);
return status;
......@@ -293,11 +295,12 @@ static void dts_trips_reset(struct intel_soc_dts_sensors *sensors, int dts_index
}
static void set_trip(struct thermal_trip *trip, enum thermal_trip_type type,
u8 flags, int temp)
u8 flags, int temp, unsigned int index)
{
trip->type = type;
trip->flags = flags;
trip->temperature = temp;
trip->priv = THERMAL_INT_TO_TRIP_PRIV(index);
}
struct intel_soc_dts_sensors *
......@@ -332,7 +335,7 @@ intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type,
sensors->soc_dts[i].sensors = sensors;
set_trip(&trips[i][0], THERMAL_TRIP_PASSIVE,
THERMAL_TRIP_FLAG_RW_TEMP, 0);
THERMAL_TRIP_FLAG_RW_TEMP, 0, 0);
ret = update_trip_temp(sensors, 0, 0);
if (ret)
......@@ -340,10 +343,10 @@ intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type,
if (critical_trip) {
temp = sensors->tj_max - crit_offset;
set_trip(&trips[i][1], THERMAL_TRIP_CRITICAL, 0, temp);
set_trip(&trips[i][1], THERMAL_TRIP_CRITICAL, 0, temp, 1);
} else {
set_trip(&trips[i][1], THERMAL_TRIP_PASSIVE,
THERMAL_TRIP_FLAG_RW_TEMP, 0);
THERMAL_TRIP_FLAG_RW_TEMP, 0, 1);
temp = 0;
}
......
......@@ -36,7 +36,7 @@ static irqreturn_t soc_irq_thread_fn(int irq, void *dev_data)
}
static const struct x86_cpu_id soc_thermal_ids[] = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, BYT_SOC_DTS_APIC_IRQ),
X86_MATCH_VFM(INTEL_ATOM_SILVERMONT, BYT_SOC_DTS_APIC_IRQ),
{}
};
MODULE_DEVICE_TABLE(x86cpu, soc_thermal_ids);
......
......@@ -6,8 +6,170 @@
#include <linux/errno.h>
#include <linux/intel_tcc.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <asm/msr.h>
/**
* struct temp_masks - Bitmasks for temperature readings
* @tcc_offset: TCC offset in MSR_TEMPERATURE_TARGET
* @digital_readout: Digital readout in MSR_IA32_THERM_STATUS
* @pkg_digital_readout: Digital readout in MSR_IA32_PACKAGE_THERM_STATUS
*
* Bitmasks to extract the fields of the MSR_TEMPERATURE and IA32_[PACKAGE]_
* THERM_STATUS registers for different processor models.
*
* The bitmask of TjMax is not included in this structure. It is always 0xff.
*/
struct temp_masks {
u32 tcc_offset;
u32 digital_readout;
u32 pkg_digital_readout;
};
#define TCC_MODEL_TEMP_MASKS(model, _tcc_offset, _digital_readout, \
_pkg_digital_readout) \
static const struct temp_masks temp_##model __initconst = { \
.tcc_offset = _tcc_offset, \
.digital_readout = _digital_readout, \
.pkg_digital_readout = _pkg_digital_readout \
}
TCC_MODEL_TEMP_MASKS(nehalem, 0, 0x7f, 0x7f);
TCC_MODEL_TEMP_MASKS(haswell_x, 0xf, 0x7f, 0x7f);
TCC_MODEL_TEMP_MASKS(broadwell, 0x3f, 0x7f, 0x7f);
TCC_MODEL_TEMP_MASKS(goldmont, 0x7f, 0x7f, 0x7f);
TCC_MODEL_TEMP_MASKS(tigerlake, 0x3f, 0xff, 0xff);
TCC_MODEL_TEMP_MASKS(sapphirerapids, 0x3f, 0x7f, 0xff);
/* Use these masks for processors not included in @tcc_cpu_ids. */
static struct temp_masks intel_tcc_temp_masks __ro_after_init = {
.tcc_offset = 0x7f,
.digital_readout = 0xff,
.pkg_digital_readout = 0xff,
};
static const struct x86_cpu_id intel_tcc_cpu_ids[] __initconst = {
X86_MATCH_VFM(INTEL_CORE_YONAH, &temp_nehalem),
X86_MATCH_VFM(INTEL_CORE2_MEROM, &temp_nehalem),
X86_MATCH_VFM(INTEL_CORE2_MEROM_L, &temp_nehalem),
X86_MATCH_VFM(INTEL_CORE2_PENRYN, &temp_nehalem),
X86_MATCH_VFM(INTEL_CORE2_DUNNINGTON, &temp_nehalem),
X86_MATCH_VFM(INTEL_NEHALEM, &temp_nehalem),
X86_MATCH_VFM(INTEL_NEHALEM_G, &temp_nehalem),
X86_MATCH_VFM(INTEL_NEHALEM_EP, &temp_nehalem),
X86_MATCH_VFM(INTEL_NEHALEM_EX, &temp_nehalem),
X86_MATCH_VFM(INTEL_WESTMERE, &temp_nehalem),
X86_MATCH_VFM(INTEL_WESTMERE_EP, &temp_nehalem),
X86_MATCH_VFM(INTEL_WESTMERE_EX, &temp_nehalem),
X86_MATCH_VFM(INTEL_SANDYBRIDGE, &temp_nehalem),
X86_MATCH_VFM(INTEL_SANDYBRIDGE_X, &temp_nehalem),
X86_MATCH_VFM(INTEL_IVYBRIDGE, &temp_nehalem),
X86_MATCH_VFM(INTEL_IVYBRIDGE_X, &temp_haswell_x),
X86_MATCH_VFM(INTEL_HASWELL, &temp_nehalem),
X86_MATCH_VFM(INTEL_HASWELL_X, &temp_haswell_x),
X86_MATCH_VFM(INTEL_HASWELL_L, &temp_nehalem),
X86_MATCH_VFM(INTEL_HASWELL_G, &temp_nehalem),
X86_MATCH_VFM(INTEL_BROADWELL, &temp_broadwell),
X86_MATCH_VFM(INTEL_BROADWELL_G, &temp_broadwell),
X86_MATCH_VFM(INTEL_BROADWELL_X, &temp_haswell_x),
X86_MATCH_VFM(INTEL_BROADWELL_D, &temp_haswell_x),
X86_MATCH_VFM(INTEL_SKYLAKE_L, &temp_broadwell),
X86_MATCH_VFM(INTEL_SKYLAKE, &temp_broadwell),
X86_MATCH_VFM(INTEL_SKYLAKE_X, &temp_haswell_x),
X86_MATCH_VFM(INTEL_KABYLAKE_L, &temp_broadwell),
X86_MATCH_VFM(INTEL_KABYLAKE, &temp_broadwell),
X86_MATCH_VFM(INTEL_COMETLAKE, &temp_broadwell),
X86_MATCH_VFM(INTEL_COMETLAKE_L, &temp_broadwell),
X86_MATCH_VFM(INTEL_CANNONLAKE_L, &temp_broadwell),
X86_MATCH_VFM(INTEL_ICELAKE_X, &temp_broadwell),
X86_MATCH_VFM(INTEL_ICELAKE_D, &temp_broadwell),
X86_MATCH_VFM(INTEL_ICELAKE, &temp_broadwell),
X86_MATCH_VFM(INTEL_ICELAKE_L, &temp_broadwell),
X86_MATCH_VFM(INTEL_ICELAKE_NNPI, &temp_broadwell),
X86_MATCH_VFM(INTEL_ROCKETLAKE, &temp_broadwell),
X86_MATCH_VFM(INTEL_TIGERLAKE_L, &temp_tigerlake),
X86_MATCH_VFM(INTEL_TIGERLAKE, &temp_tigerlake),
X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, &temp_sapphirerapids),
X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X, &temp_sapphirerapids),
X86_MATCH_VFM(INTEL_LAKEFIELD, &temp_broadwell),
X86_MATCH_VFM(INTEL_ALDERLAKE, &temp_tigerlake),
X86_MATCH_VFM(INTEL_ALDERLAKE_L, &temp_tigerlake),
X86_MATCH_VFM(INTEL_RAPTORLAKE, &temp_tigerlake),
X86_MATCH_VFM(INTEL_RAPTORLAKE_P, &temp_tigerlake),
X86_MATCH_VFM(INTEL_RAPTORLAKE_S, &temp_tigerlake),
X86_MATCH_VFM(INTEL_ATOM_BONNELL, &temp_nehalem),
X86_MATCH_VFM(INTEL_ATOM_BONNELL_MID, &temp_nehalem),
X86_MATCH_VFM(INTEL_ATOM_SALTWELL, &temp_nehalem),
X86_MATCH_VFM(INTEL_ATOM_SALTWELL_MID, &temp_nehalem),
X86_MATCH_VFM(INTEL_ATOM_SILVERMONT, &temp_broadwell),
X86_MATCH_VFM(INTEL_ATOM_SILVERMONT_D, &temp_broadwell),
X86_MATCH_VFM(INTEL_ATOM_SILVERMONT_MID, &temp_broadwell),
X86_MATCH_VFM(INTEL_ATOM_AIRMONT, &temp_broadwell),
X86_MATCH_VFM(INTEL_ATOM_AIRMONT_MID, &temp_broadwell),
X86_MATCH_VFM(INTEL_ATOM_AIRMONT_NP, &temp_broadwell),
X86_MATCH_VFM(INTEL_ATOM_GOLDMONT, &temp_goldmont),
X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_D, &temp_goldmont),
X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_PLUS, &temp_goldmont),
X86_MATCH_VFM(INTEL_ATOM_TREMONT_D, &temp_broadwell),
X86_MATCH_VFM(INTEL_ATOM_TREMONT, &temp_broadwell),
X86_MATCH_VFM(INTEL_ATOM_TREMONT_L, &temp_broadwell),
X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, &temp_tigerlake),
X86_MATCH_VFM(INTEL_XEON_PHI_KNL, &temp_broadwell),
X86_MATCH_VFM(INTEL_XEON_PHI_KNM, &temp_broadwell),
{}
};
static int __init intel_tcc_init(void)
{
const struct x86_cpu_id *id;
id = x86_match_cpu(intel_tcc_cpu_ids);
if (id)
memcpy(&intel_tcc_temp_masks, (const void *)id->driver_data,
sizeof(intel_tcc_temp_masks));
return 0;
}
/*
* Use subsys_initcall to ensure temperature bitmasks are initialized before
* the drivers that use this library.
*/
subsys_initcall(intel_tcc_init);
/**
* intel_tcc_get_offset_mask() - Returns the bitmask to read TCC offset
*
* Get the model-specific bitmask to extract TCC_OFFSET from the MSR
* TEMPERATURE_TARGET register. If the mask is 0, it means the processor does
* not support TCC offset.
*
* Return: The model-specific bitmask for TCC offset.
*/
u32 intel_tcc_get_offset_mask(void)
{
return intel_tcc_temp_masks.tcc_offset;
}
EXPORT_SYMBOL_NS(intel_tcc_get_offset_mask, INTEL_TCC);
/**
* get_temp_mask() - Returns the model-specific bitmask for temperature
*
* @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor.
*
* Get the model-specific bitmask to extract the temperature reading from the
* MSR_IA32_[PACKAGE]_THERM_STATUS register.
*
* Callers must check if the thermal status registers are supported.
*
* Return: The model-specific bitmask for temperature reading
*/
static u32 get_temp_mask(bool pkg)
{
return pkg ? intel_tcc_temp_masks.pkg_digital_readout :
intel_tcc_temp_masks.digital_readout;
}
/**
* intel_tcc_get_tjmax() - returns the default TCC activation Temperature
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
......@@ -56,7 +218,7 @@ int intel_tcc_get_offset(int cpu)
if (err)
return err;
return (low >> 24) & 0x3f;
return (low >> 24) & intel_tcc_temp_masks.tcc_offset;
}
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, INTEL_TCC);
......@@ -76,7 +238,10 @@ int intel_tcc_set_offset(int cpu, int offset)
u32 low, high;
int err;
if (offset < 0 || offset > 0x3f)
if (!intel_tcc_temp_masks.tcc_offset)
return -ENODEV;
if (offset < 0 || offset > intel_tcc_temp_masks.tcc_offset)
return -EINVAL;
if (cpu < 0)
......@@ -90,7 +255,7 @@ int intel_tcc_set_offset(int cpu, int offset)
if (low & BIT(31))
return -EPERM;
low &= ~(0x3f << 24);
low &= ~(intel_tcc_temp_masks.tcc_offset << 24);
low |= offset << 24;
if (cpu < 0)
......@@ -113,8 +278,8 @@ EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
*/
int intel_tcc_get_temp(int cpu, int *temp, bool pkg)
{
u32 low, high;
u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS;
u32 low, high, mask;
int tjmax, err;
tjmax = intel_tcc_get_tjmax(cpu);
......@@ -132,7 +297,9 @@ int intel_tcc_get_temp(int cpu, int *temp, bool pkg)
if (!(low & BIT(31)))
return -ENODATA;
*temp = tjmax - ((low >> 16) & 0x7f);
mask = get_temp_mask(pkg);
*temp = tjmax - ((low >> 16) & mask);
return 0;
}
......
......@@ -20,7 +20,7 @@ static struct thermal_cooling_device *tcc_cdev;
static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long
*state)
{
*state = 0x3f;
*state = intel_tcc_get_offset_mask();
return 0;
}
......@@ -49,21 +49,21 @@ static const struct thermal_cooling_device_ops tcc_cooling_ops = {
};
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),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT, NULL),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, NULL),
X86_MATCH_VFM(INTEL_SKYLAKE, NULL),
X86_MATCH_VFM(INTEL_SKYLAKE_L, NULL),
X86_MATCH_VFM(INTEL_KABYLAKE, NULL),
X86_MATCH_VFM(INTEL_KABYLAKE_L, NULL),
X86_MATCH_VFM(INTEL_ICELAKE, NULL),
X86_MATCH_VFM(INTEL_ICELAKE_L, NULL),
X86_MATCH_VFM(INTEL_TIGERLAKE, NULL),
X86_MATCH_VFM(INTEL_TIGERLAKE_L, NULL),
X86_MATCH_VFM(INTEL_COMETLAKE, NULL),
X86_MATCH_VFM(INTEL_ALDERLAKE, NULL),
X86_MATCH_VFM(INTEL_ALDERLAKE_L, NULL),
X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, NULL),
X86_MATCH_VFM(INTEL_RAPTORLAKE, NULL),
X86_MATCH_VFM(INTEL_RAPTORLAKE_P, NULL),
X86_MATCH_VFM(INTEL_RAPTORLAKE_S, NULL),
{}
};
......
......@@ -119,9 +119,11 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
}
static int
sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
sys_set_trip_temp(struct thermal_zone_device *tzd,
const struct thermal_trip *trip, int temp)
{
struct zone_device *zonedev = thermal_zone_device_priv(tzd);
unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
u32 l, h, mask, shift, intr;
int tj_max, val, ret;
......@@ -132,7 +134,7 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
val = (tj_max - temp)/1000;
if (trip >= MAX_NUMBER_OF_TRIPS || val < 0 || val > 0x7f)
if (trip_index >= MAX_NUMBER_OF_TRIPS || val < 0 || val > 0x7f)
return -EINVAL;
ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
......@@ -140,7 +142,7 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
if (ret < 0)
return ret;
if (trip) {
if (trip_index) {
mask = THERM_MASK_THRESHOLD1;
shift = THERM_SHIFT_THRESHOLD1;
intr = THERM_INT_THRESHOLD1_ENABLE;
......@@ -296,6 +298,7 @@ static int pkg_temp_thermal_trips_init(int cpu, int tj_max,
trips[i].type = THERMAL_TRIP_PASSIVE;
trips[i].flags |= THERMAL_TRIP_FLAG_RW_TEMP;
trips[i].priv = THERMAL_INT_TO_TRIP_PRIV(i);
pr_debug("%s: cpu=%d, trip=%d, temp=%d\n",
__func__, cpu, i, trips[i].temperature);
......
......@@ -178,6 +178,7 @@ struct k3_j72xx_bandgap {
void __iomem *base;
void __iomem *cfg2_base;
struct k3_thermal_data *ts_data[K3_VTM_MAX_NUM_TS];
int cnt;
};
/* common data structures */
......@@ -338,24 +339,52 @@ static void print_look_up_table(struct device *dev, int *ref_table)
dev_dbg(dev, "%d %d %d\n", i, derived_table[i], ref_table[i]);
}
static void k3_j72xx_bandgap_init_hw(struct k3_j72xx_bandgap *bgp)
{
struct k3_thermal_data *data;
int id, high_max, low_temp;
u32 val;
for (id = 0; id < bgp->cnt; id++) {
data = bgp->ts_data[id];
val = readl(bgp->cfg2_base + data->ctrl_offset);
val |= (K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN |
K3_VTM_TMPSENS_CTRL_SOC |
K3_VTM_TMPSENS_CTRL_CLRZ | BIT(4));
writel(val, bgp->cfg2_base + data->ctrl_offset);
}
/*
* Program TSHUT thresholds
* Step 1: set the thresholds to ~123C and 105C WKUP_VTM_MISC_CTRL2
* Step 2: WKUP_VTM_TMPSENS_CTRL_j set the MAXT_OUTRG_EN bit
* This is already taken care as per of init
* Step 3: WKUP_VTM_MISC_CTRL set the ANYMAXT_OUTRG_ALERT_EN bit
*/
high_max = k3_j72xx_bandgap_temp_to_adc_code(MAX_TEMP);
low_temp = k3_j72xx_bandgap_temp_to_adc_code(COOL_DOWN_TEMP);
writel((low_temp << 16) | high_max, bgp->cfg2_base + K3_VTM_MISC_CTRL2_OFFSET);
writel(K3_VTM_ANYMAXT_OUTRG_ALERT_EN, bgp->cfg2_base + K3_VTM_MISC_CTRL_OFFSET);
}
struct k3_j72xx_bandgap_data {
const bool has_errata_i2128;
};
static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
{
int ret = 0, cnt, val, id;
int high_max, low_temp;
struct resource *res;
const struct k3_j72xx_bandgap_data *driver_data;
struct thermal_zone_device *ti_thermal;
struct device *dev = &pdev->dev;
bool workaround_needed = false;
struct k3_j72xx_bandgap *bgp;
struct k3_thermal_data *data;
bool workaround_needed = false;
const struct k3_j72xx_bandgap_data *driver_data;
struct thermal_zone_device *ti_thermal;
int *ref_table;
struct err_values err_vals;
void __iomem *fuse_base;
int ret = 0, val, id;
struct resource *res;
int *ref_table;
const s64 golden_factors[] = {
-490019999999999936,
......@@ -422,10 +451,10 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
/* Get the sensor count in the VTM */
val = readl(bgp->base + K3_VTM_DEVINFO_PWR0_OFFSET);
cnt = val & K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK;
cnt >>= __ffs(K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK);
bgp->cnt = val & K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK;
bgp->cnt >>= __ffs(K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK);
data = devm_kcalloc(bgp->dev, cnt, sizeof(*data), GFP_KERNEL);
data = devm_kcalloc(bgp->dev, bgp->cnt, sizeof(*data), GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto err_alloc;
......@@ -449,8 +478,8 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
else
init_table(3, ref_table, pvt_wa_factors);
/* Register the thermal sensors */
for (id = 0; id < cnt; id++) {
/* Precompute the derived table & fill each thermal sensor struct */
for (id = 0; id < bgp->cnt; id++) {
data[id].bgp = bgp;
data[id].ctrl_offset = K3_VTM_TMPSENS0_CTRL_OFFSET + id * 0x20;
data[id].stat_offset = data[id].ctrl_offset +
......@@ -470,13 +499,13 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
else if (id == 0 && !workaround_needed)
memcpy(derived_table, ref_table, TABLE_SIZE * 4);
val = readl(data[id].bgp->cfg2_base + data[id].ctrl_offset);
val |= (K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN |
K3_VTM_TMPSENS_CTRL_SOC |
K3_VTM_TMPSENS_CTRL_CLRZ | BIT(4));
writel(val, data[id].bgp->cfg2_base + data[id].ctrl_offset);
bgp->ts_data[id] = &data[id];
}
k3_j72xx_bandgap_init_hw(bgp);
/* Register the thermal sensors */
for (id = 0; id < bgp->cnt; id++) {
ti_thermal = devm_thermal_of_zone_register(bgp->dev, id, &data[id],
&k3_of_thermal_ops);
if (IS_ERR(ti_thermal)) {
......@@ -486,21 +515,7 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
}
}
/*
* Program TSHUT thresholds
* Step 1: set the thresholds to ~123C and 105C WKUP_VTM_MISC_CTRL2
* Step 2: WKUP_VTM_TMPSENS_CTRL_j set the MAXT_OUTRG_EN bit
* This is already taken care as per of init
* Step 3: WKUP_VTM_MISC_CTRL set the ANYMAXT_OUTRG_ALERT_EN bit
*/
high_max = k3_j72xx_bandgap_temp_to_adc_code(MAX_TEMP);
low_temp = k3_j72xx_bandgap_temp_to_adc_code(COOL_DOWN_TEMP);
writel((low_temp << 16) | high_max, data[0].bgp->cfg2_base +
K3_VTM_MISC_CTRL2_OFFSET);
mdelay(100);
writel(K3_VTM_ANYMAXT_OUTRG_ALERT_EN, data[0].bgp->cfg2_base +
K3_VTM_MISC_CTRL_OFFSET);
platform_set_drvdata(pdev, bgp);
print_look_up_table(dev, ref_table);
/*
......@@ -527,6 +542,35 @@ static void k3_j72xx_bandgap_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
}
static int k3_j72xx_bandgap_suspend(struct device *dev)
{
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
return 0;
}
static int k3_j72xx_bandgap_resume(struct device *dev)
{
struct k3_j72xx_bandgap *bgp = dev_get_drvdata(dev);
int ret;
pm_runtime_enable(dev);
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
return ret;
}
k3_j72xx_bandgap_init_hw(bgp);
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(k3_j72xx_bandgap_pm_ops,
k3_j72xx_bandgap_suspend,
k3_j72xx_bandgap_resume);
static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j721e_data = {
.has_errata_i2128 = true,
};
......@@ -554,6 +598,7 @@ static struct platform_driver k3_j72xx_bandgap_sensor_driver = {
.driver = {
.name = "k3-j72xx-soc-thermal",
.of_match_table = of_k3_j72xx_bandgap_match,
.pm = pm_sleep_ptr(&k3_j72xx_bandgap_pm_ops),
},
};
......
......@@ -128,6 +128,7 @@ struct lvts_data {
int temp_factor;
int temp_offset;
int gt_calib_bit_offset;
unsigned int def_calibration;
};
struct lvts_sensor {
......@@ -689,6 +690,10 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl
size_t calib_len)
{
int i;
u32 gt;
/* A zero value for gt means that device has invalid efuse data */
gt = (((u32 *)efuse_calibration)[0] >> lvts_ctrl->lvts_data->gt_calib_bit_offset) & 0xff;
lvts_for_each_valid_sensor(i, lvts_ctrl_data) {
const struct lvts_sensor_data *sensor =
......@@ -699,10 +704,17 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl
sensor->cal_offsets[2] >= calib_len)
return -EINVAL;
if (gt) {
lvts_ctrl->calibration[i] =
(efuse_calibration[sensor->cal_offsets[0]] << 0) +
(efuse_calibration[sensor->cal_offsets[1]] << 8) +
(efuse_calibration[sensor->cal_offsets[2]] << 16);
} else if (lvts_ctrl->lvts_data->def_calibration) {
lvts_ctrl->calibration[i] = lvts_ctrl->lvts_data->def_calibration;
} else {
dev_err(dev, "efuse contains invalid calibration data and no default given.\n");
return -ENODATA;
}
}
return 0;
......@@ -770,14 +782,13 @@ static int lvts_golden_temp_init(struct device *dev, u8 *calib,
gt = (((u32 *)calib)[0] >> lvts_data->gt_calib_bit_offset) & 0xff;
/* A zero value for gt means that device has invalid efuse data */
if (!gt)
return -ENODATA;
if (gt < LVTS_GOLDEN_TEMP_MAX)
if (gt && gt < LVTS_GOLDEN_TEMP_MAX)
golden_temp = gt;
golden_temp_offset = golden_temp * 500 + lvts_data->temp_offset;
dev_info(dev, "%sgolden temp=%d\n", gt ? "" : "fake ", golden_temp);
return 0;
}
......@@ -1440,7 +1451,7 @@ static const struct lvts_ctrl_data mt8186_lvts_data_ctrl[] = {
.cal_offsets = { 29, 30, 31 } },
{ .dt_id = MT8186_ADSP,
.cal_offsets = { 34, 35, 28 } },
{ .dt_id = MT8186_MFG,
{ .dt_id = MT8186_GPU,
.cal_offsets = { 39, 32, 33 } }
},
VALID_SENSOR_MAP(1, 1, 1, 0),
......@@ -1488,11 +1499,11 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = {
},
{
.lvts_sensor = {
{ .dt_id = MT8188_AP_GPU1,
{ .dt_id = MT8188_AP_GPU0,
.cal_offsets = { 43, 44, 45 } },
{ .dt_id = MT8188_AP_GPU2,
{ .dt_id = MT8188_AP_GPU1,
.cal_offsets = { 46, 47, 48 } },
{ .dt_id = MT8188_AP_SOC1,
{ .dt_id = MT8188_AP_ADSP,
.cal_offsets = { 49, 50, 51 } },
},
VALID_SENSOR_MAP(1, 1, 1, 0),
......@@ -1500,9 +1511,9 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = {
},
{
.lvts_sensor = {
{ .dt_id = MT8188_AP_SOC2,
{ .dt_id = MT8188_AP_VDO,
.cal_offsets = { 52, 53, 54 } },
{ .dt_id = MT8188_AP_SOC3,
{ .dt_id = MT8188_AP_INFRA,
.cal_offsets = { 55, 56, 57 } },
},
VALID_SENSOR_MAP(1, 1, 0, 0),
......@@ -1701,6 +1712,7 @@ static const struct lvts_data mt8186_lvts_data = {
.temp_factor = LVTS_COEFF_A_MT7988,
.temp_offset = LVTS_COEFF_B_MT7988,
.gt_calib_bit_offset = 24,
.def_calibration = 19000,
};
static const struct lvts_data mt8188_lvts_mcu_data = {
......@@ -1709,6 +1721,7 @@ static const struct lvts_data mt8188_lvts_mcu_data = {
.temp_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 20,
.def_calibration = 35000,
};
static const struct lvts_data mt8188_lvts_ap_data = {
......@@ -1717,6 +1730,7 @@ static const struct lvts_data mt8188_lvts_ap_data = {
.temp_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 20,
.def_calibration = 35000,
};
static const struct lvts_data mt8192_lvts_mcu_data = {
......@@ -1725,6 +1739,7 @@ static const struct lvts_data mt8192_lvts_mcu_data = {
.temp_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 24,
.def_calibration = 35000,
};
static const struct lvts_data mt8192_lvts_ap_data = {
......@@ -1733,6 +1748,7 @@ static const struct lvts_data mt8192_lvts_ap_data = {
.temp_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 24,
.def_calibration = 35000,
};
static const struct lvts_data mt8195_lvts_mcu_data = {
......@@ -1741,6 +1757,7 @@ static const struct lvts_data mt8195_lvts_mcu_data = {
.temp_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 24,
.def_calibration = 35000,
};
static const struct lvts_data mt8195_lvts_ap_data = {
......@@ -1749,6 +1766,7 @@ static const struct lvts_data mt8195_lvts_ap_data = {
.temp_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 24,
.def_calibration = 35000,
};
static const struct of_device_id lvts_of_match[] = {
......
......@@ -829,12 +829,9 @@ static int adc_tm5_get_dt_channel_data(struct adc_tm5_chip *adc_tm,
channel->iio = devm_fwnode_iio_channel_get_by_name(adc_tm->dev,
of_fwnode_handle(node), NULL);
if (IS_ERR(channel->iio)) {
ret = PTR_ERR(channel->iio);
if (ret != -EPROBE_DEFER)
dev_err(dev, "%s: error getting channel: %d\n", name, ret);
return ret;
}
if (IS_ERR(channel->iio))
return dev_err_probe(dev, PTR_ERR(channel->iio), "%s: error getting channel\n",
name);
ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2);
if (!ret) {
......
......@@ -261,17 +261,13 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip,
return qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg);
}
static int qpnp_tm_set_trip_temp(struct thermal_zone_device *tz, int trip_id, int temp)
static int qpnp_tm_set_trip_temp(struct thermal_zone_device *tz,
const struct thermal_trip *trip, int temp)
{
struct qpnp_tm_chip *chip = thermal_zone_device_priv(tz);
struct thermal_trip trip;
int ret;
ret = __thermal_zone_get_trip(chip->tz_dev, trip_id, &trip);
if (ret)
return ret;
if (trip.type != THERMAL_TRIP_CRITICAL)
if (trip->type != THERMAL_TRIP_CRITICAL)
return 0;
mutex_lock(&chip->lock);
......
......@@ -1336,11 +1336,9 @@ static int tsens_probe(struct platform_device *pdev)
if (priv->ops->calibrate) {
ret = priv->ops->calibrate(priv);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "%s: calibration failed\n", __func__);
return ret;
}
if (ret < 0)
return dev_err_probe(dev, ret, "%s: calibration failed\n",
__func__);
}
ret = tsens_register(priv);
......
# SPDX-License-Identifier: GPL-2.0-only
config RCAR_THERMAL
tristate "Renesas R-Car thermal driver"
depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
depends on OF
help
Enable this to plug the R-Car thermal sensor driver into the Linux
thermal framework.
config RCAR_GEN3_THERMAL
tristate "Renesas R-Car Gen3 and RZ/G2 thermal driver"
depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
depends on OF
help
Enable this to plug the R-Car Gen3 or RZ/G2 thermal sensor driver into
the Linux thermal framework.
config RZG2L_THERMAL
tristate "Renesas RZ/G2L thermal driver"
depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
depends on OF
help
Enable this to plug the RZ/G2L thermal sensor driver into the Linux
thermal framework.
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_RCAR_GEN3_THERMAL) += rcar_gen3_thermal.o
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
obj-$(CONFIG_RZG2L_THERMAL) += rzg2l_thermal.o
......@@ -16,7 +16,7 @@
#include <linux/pm_runtime.h>
#include <linux/thermal.h>
#include "thermal_hwmon.h"
#include "../thermal_hwmon.h"
/* Register offsets */
#define REG_GEN3_IRQSTR 0x04
......
......@@ -19,7 +19,7 @@
#include <linux/spinlock.h>
#include <linux/thermal.h>
#include "thermal_hwmon.h"
#include "../thermal_hwmon.h"
#define IDLE_INTERVAL 5000
......
......@@ -17,7 +17,7 @@
#include <linux/thermal.h>
#include <linux/units.h>
#include "thermal_hwmon.h"
#include "../thermal_hwmon.h"
#define CTEMP_MASK 0xFFF
......
......@@ -1004,11 +1004,11 @@ static const struct thermal_zone_device_ops exynos_sensor_ops = {
static int exynos_tmu_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct exynos_tmu_data *data;
int ret;
data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
GFP_KERNEL);
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
......@@ -1020,7 +1020,7 @@ static int exynos_tmu_probe(struct platform_device *pdev)
* TODO: Add regulator as an SOC feature, so that regulator enable
* is a compulsory call.
*/
ret = devm_regulator_get_enable_optional(&pdev->dev, "vtmu");
ret = devm_regulator_get_enable_optional(dev, "vtmu");
switch (ret) {
case 0:
case -ENODEV:
......@@ -1028,8 +1028,7 @@ static int exynos_tmu_probe(struct platform_device *pdev)
case -EPROBE_DEFER:
return -EPROBE_DEFER;
default:
dev_err(&pdev->dev, "Failed to get enabled regulator: %d\n",
ret);
dev_err(dev, "Failed to get enabled regulator: %d\n", ret);
return ret;
}
......@@ -1037,44 +1036,40 @@ static int exynos_tmu_probe(struct platform_device *pdev)
if (ret)
return ret;
data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
if (IS_ERR(data->clk)) {
dev_err(&pdev->dev, "Failed to get clock\n");
return PTR_ERR(data->clk);
}
data->clk = devm_clk_get(dev, "tmu_apbif");
if (IS_ERR(data->clk))
return dev_err_probe(dev, PTR_ERR(data->clk), "Failed to get clock\n");
data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif");
data->clk_sec = devm_clk_get(dev, "tmu_triminfo_apbif");
if (IS_ERR(data->clk_sec)) {
if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) {
dev_err(&pdev->dev, "Failed to get triminfo clock\n");
return PTR_ERR(data->clk_sec);
}
if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
return dev_err_probe(dev, PTR_ERR(data->clk_sec),
"Failed to get triminfo clock\n");
} else {
ret = clk_prepare(data->clk_sec);
if (ret) {
dev_err(&pdev->dev, "Failed to get clock\n");
dev_err(dev, "Failed to get clock\n");
return ret;
}
}
ret = clk_prepare(data->clk);
if (ret) {
dev_err(&pdev->dev, "Failed to get clock\n");
dev_err(dev, "Failed to get clock\n");
goto err_clk_sec;
}
switch (data->soc) {
case SOC_ARCH_EXYNOS5433:
case SOC_ARCH_EXYNOS7:
data->sclk = devm_clk_get(&pdev->dev, "tmu_sclk");
data->sclk = devm_clk_get(dev, "tmu_sclk");
if (IS_ERR(data->sclk)) {
dev_err(&pdev->dev, "Failed to get sclk\n");
ret = PTR_ERR(data->sclk);
ret = dev_err_probe(dev, PTR_ERR(data->sclk), "Failed to get sclk\n");
goto err_clk;
} else {
ret = clk_prepare_enable(data->sclk);
if (ret) {
dev_err(&pdev->dev, "Failed to enable sclk\n");
dev_err(dev, "Failed to enable sclk\n");
goto err_clk;
}
}
......@@ -1085,33 +1080,30 @@ static int exynos_tmu_probe(struct platform_device *pdev)
ret = exynos_tmu_initialize(pdev);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize TMU\n");
dev_err(dev, "Failed to initialize TMU\n");
goto err_sclk;
}
data->tzd = devm_thermal_of_zone_register(&pdev->dev, 0, data,
data->tzd = devm_thermal_of_zone_register(dev, 0, data,
&exynos_sensor_ops);
if (IS_ERR(data->tzd)) {
ret = PTR_ERR(data->tzd);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "Failed to register sensor: %d\n",
ret);
ret = dev_err_probe(dev, PTR_ERR(data->tzd), "Failed to register sensor\n");
goto err_sclk;
}
ret = exynos_thermal_zone_configure(pdev);
if (ret) {
dev_err(&pdev->dev, "Failed to configure the thermal zone\n");
dev_err(dev, "Failed to configure the thermal zone\n");
goto err_sclk;
}
ret = devm_request_threaded_irq(&pdev->dev, data->irq, NULL,
ret = devm_request_threaded_irq(dev, data->irq, NULL,
exynos_tmu_threaded_irq,
IRQF_TRIGGER_RISING
| IRQF_SHARED | IRQF_ONESHOT,
dev_name(&pdev->dev), data);
dev_name(dev), data);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
dev_err(dev, "Failed to request irq: %d\n", data->irq);
goto err_sclk;
}
......
......@@ -142,15 +142,6 @@ static const struct st_thermal_sensor_ops st_mmap_sensor_ops = {
.enable_irq = st_mmap_enable_irq,
};
/* Compatible device data stih416 mpe thermal sensor */
static const struct st_thermal_compat_data st_416mpe_cdata = {
.reg_fields = st_mmap_thermal_regfields,
.ops = &st_mmap_sensor_ops,
.calibration_val = 14,
.temp_adjust_val = -95,
.crit_temp = 120,
};
/* Compatible device data stih407 thermal sensor */
static const struct st_thermal_compat_data st_407_cdata = {
.reg_fields = st_mmap_thermal_regfields,
......@@ -161,7 +152,6 @@ static const struct st_thermal_compat_data st_407_cdata = {
};
static const struct of_device_id st_mmap_thermal_of_match[] = {
{ .compatible = "st,stih416-mpe-thermal", .data = &st_416mpe_cdata },
{ .compatible = "st,stih407-thermal", .data = &st_407_cdata },
{ /* sentinel */ }
};
......
......@@ -582,23 +582,18 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id)
return temp;
}
static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip_id, int temp)
static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz,
const struct thermal_trip *trip, int temp)
{
struct tegra_thermctl_zone *zone = thermal_zone_device_priv(tz);
struct tegra_soctherm *ts = zone->ts;
struct thermal_trip trip;
const struct tegra_tsensor_group *sg = zone->sg;
struct device *dev = zone->dev;
int ret;
if (!tz)
return -EINVAL;
ret = __thermal_zone_get_trip(tz, trip_id, &trip);
if (ret)
return ret;
if (trip.type == THERMAL_TRIP_CRITICAL) {
if (trip->type == THERMAL_TRIP_CRITICAL) {
/*
* If thermtrips property is set in DT,
* doesn't need to program critical type trip to HW,
......@@ -609,7 +604,7 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip
else
return 0;
} else if (trip.type == THERMAL_TRIP_HOT) {
} else if (trip->type == THERMAL_TRIP_HOT) {
int i;
for (i = 0; i < THROTTLE_SIZE; i++) {
......@@ -620,7 +615,7 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip
continue;
cdev = ts->throt_cfgs[i].cdev;
if (get_thermal_instance(tz, cdev, trip_id))
if (thermal_trip_is_bound_to_cdev(tz, trip, cdev))
stc = find_throttle_cfg_by_name(ts, cdev->type);
else
continue;
......
......@@ -117,44 +117,41 @@ static int gadc_thermal_read_linear_lookup_table(struct device *dev,
static int gadc_thermal_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct gadc_thermal_info *gti;
int ret;
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "Only DT based supported\n");
if (!dev->of_node) {
dev_err(dev, "Only DT based supported\n");
return -ENODEV;
}
gti = devm_kzalloc(&pdev->dev, sizeof(*gti), GFP_KERNEL);
gti = devm_kzalloc(dev, sizeof(*gti), GFP_KERNEL);
if (!gti)
return -ENOMEM;
gti->channel = devm_iio_channel_get(&pdev->dev, "sensor-channel");
if (IS_ERR(gti->channel)) {
ret = PTR_ERR(gti->channel);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "IIO channel not found: %d\n", ret);
return ret;
}
gti->channel = devm_iio_channel_get(dev, "sensor-channel");
if (IS_ERR(gti->channel))
return dev_err_probe(dev, PTR_ERR(gti->channel), "IIO channel not found\n");
ret = gadc_thermal_read_linear_lookup_table(&pdev->dev, gti);
ret = gadc_thermal_read_linear_lookup_table(dev, gti);
if (ret < 0)
return ret;
gti->dev = &pdev->dev;
gti->dev = dev;
gti->tz_dev = devm_thermal_of_zone_register(&pdev->dev, 0, gti,
gti->tz_dev = devm_thermal_of_zone_register(dev, 0, gti,
&gadc_thermal_ops);
if (IS_ERR(gti->tz_dev)) {
ret = PTR_ERR(gti->tz_dev);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
dev_err(dev,
"Thermal zone sensor register failed: %d\n",
ret);
return ret;
}
devm_thermal_add_hwmon_sysfs(&pdev->dev, gti->tz_dev);
devm_thermal_add_hwmon_sysfs(dev, gti->tz_dev);
return 0;
}
......
......@@ -465,6 +465,9 @@ static void thermal_governor_trip_crossed(struct thermal_governor *governor,
const struct thermal_trip *trip,
bool crossed_up)
{
if (trip->type == THERMAL_TRIP_HOT || trip->type == THERMAL_TRIP_CRITICAL)
return;
if (governor->trip_crossed)
governor->trip_crossed(tz, trip, crossed_up);
}
......@@ -513,13 +516,13 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
if (tz->temperature == THERMAL_TEMP_INVALID)
goto monitor;
__thermal_zone_set_trips(tz);
tz->notify_event = event;
for_each_trip_desc(tz, td)
handle_thermal_trip(tz, td, &way_up_list, &way_down_list);
thermal_zone_set_trips(tz);
list_sort(NULL, &way_up_list, thermal_trip_notify_cmp);
list_for_each_entry(td, &way_up_list, notify_list_node)
thermal_trip_crossed(tz, &td->trip, governor, true);
......@@ -1127,7 +1130,7 @@ static void thermal_cooling_device_release(struct device *dev, void *res)
struct thermal_cooling_device *
devm_thermal_of_cooling_device_register(struct device *dev,
struct device_node *np,
char *type, void *devdata,
const char *type, void *devdata,
const struct thermal_cooling_device_ops *ops)
{
struct thermal_cooling_device **ptr, *tcd;
......@@ -1354,7 +1357,8 @@ thermal_zone_device_register_with_trips(const char *type,
int num_trips, void *devdata,
const struct thermal_zone_device_ops *ops,
const struct thermal_zone_params *tzp,
int passive_delay, int polling_delay)
unsigned int passive_delay,
unsigned int polling_delay)
{
const struct thermal_trip *trip = trips;
struct thermal_zone_device *tz;
......@@ -1387,6 +1391,14 @@ thermal_zone_device_register_with_trips(const char *type,
if (num_trips > 0 && !trips)
return ERR_PTR(-EINVAL);
if (polling_delay) {
if (passive_delay > polling_delay)
return ERR_PTR(-EINVAL);
if (!passive_delay)
passive_delay = polling_delay;
}
if (!thermal_class)
return ERR_PTR(-ENODEV);
......@@ -1650,6 +1662,7 @@ static void thermal_zone_device_resume(struct work_struct *work)
tz->suspended = false;
thermal_debug_tz_resume(tz);
thermal_zone_device_init(tz);
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
......
......@@ -250,7 +250,9 @@ void thermal_governor_update_tz(struct thermal_zone_device *tz,
#define trip_to_trip_desc(__trip) \
container_of(__trip, struct thermal_trip_desc, trip)
void __thermal_zone_set_trips(struct thermal_zone_device *tz);
const char *thermal_trip_type_name(enum thermal_trip_type trip_type);
void thermal_zone_set_trips(struct thermal_zone_device *tz);
int thermal_zone_trip_id(const struct thermal_zone_device *tz,
const struct thermal_trip *trip);
void thermal_zone_trip_updated(struct thermal_zone_device *tz,
......
......@@ -94,7 +94,6 @@ struct cdev_record {
* @trip_temp: trip temperature at mitigation start
* @trip_hyst: trip hysteresis at mitigation start
* @count: the number of times the zone temperature was above the trip point
* @max: maximum recorded temperature above the trip point
* @min: minimum recorded temperature above the trip point
* @avg: average temperature above the trip point
*/
......@@ -104,7 +103,6 @@ struct trip_stats {
int trip_temp;
int trip_hyst;
int count;
int max;
int min;
int avg;
};
......@@ -122,12 +120,14 @@ struct trip_stats {
* @timestamp: first trip point crossed the way up
* @duration: total duration of the mitigation episode
* @node: a list element to be added to the list of tz events
* @max_temp: maximum zone temperature during this episode
* @trip_stats: per trip point statistics, flexible array
*/
struct tz_episode {
ktime_t timestamp;
ktime_t duration;
struct list_head node;
int max_temp;
struct trip_stats trip_stats[];
};
......@@ -561,10 +561,11 @@ static struct tz_episode *thermal_debugfs_tz_event_alloc(struct thermal_zone_dev
INIT_LIST_HEAD(&tze->node);
tze->timestamp = now;
tze->duration = KTIME_MIN;
tze->max_temp = INT_MIN;
for (i = 0; i < tz->num_trips; i++) {
tze->trip_stats[i].trip_temp = THERMAL_TEMP_INVALID;
tze->trip_stats[i].min = INT_MAX;
tze->trip_stats[i].max = INT_MIN;
}
return tze;
......@@ -573,20 +574,20 @@ static struct tz_episode *thermal_debugfs_tz_event_alloc(struct thermal_zone_dev
void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
const struct thermal_trip *trip)
{
struct tz_episode *tze;
struct tz_debugfs *tz_dbg;
struct thermal_debugfs *thermal_dbg = tz->debugfs;
int trip_id = thermal_zone_trip_id(tz, trip);
ktime_t now = ktime_get();
struct trip_stats *trip_stats;
struct tz_debugfs *tz_dbg;
struct tz_episode *tze;
if (!thermal_dbg)
return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg;
mutex_lock(&thermal_dbg->lock);
/*
* The mitigation is starting. A mitigation can contain
* several episodes where each of them is related to a
......@@ -653,23 +654,33 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
mutex_unlock(&thermal_dbg->lock);
}
static void tz_episode_close_trip(struct tz_episode *tze, int trip_id, ktime_t now)
{
struct trip_stats *trip_stats = &tze->trip_stats[trip_id];
ktime_t delta = ktime_sub(now, trip_stats->timestamp);
trip_stats->duration = ktime_add(delta, trip_stats->duration);
/* Mark the end of mitigation for this trip point. */
trip_stats->timestamp = KTIME_MAX;
}
void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,
const struct thermal_trip *trip)
{
struct thermal_debugfs *thermal_dbg = tz->debugfs;
int trip_id = thermal_zone_trip_id(tz, trip);
ktime_t now = ktime_get();
struct tz_episode *tze;
struct tz_debugfs *tz_dbg;
ktime_t delta, now = ktime_get();
int trip_id = thermal_zone_trip_id(tz, trip);
int i;
if (!thermal_dbg)
return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg;
mutex_lock(&thermal_dbg->lock);
/*
* The temperature crosses the way down but there was not
* mitigation detected before. That may happen when the
......@@ -695,13 +706,7 @@ void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,
tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node);
delta = ktime_sub(now, tze->trip_stats[trip_id].timestamp);
tze->trip_stats[trip_id].duration =
ktime_add(delta, tze->trip_stats[trip_id].duration);
/* Mark the end of mitigation for this trip point. */
tze->trip_stats[trip_id].timestamp = KTIME_MAX;
tz_episode_close_trip(tze, trip_id, now);
/*
* This event closes the mitigation as we are crossing the
......@@ -724,20 +729,22 @@ void thermal_debug_update_trip_stats(struct thermal_zone_device *tz)
if (!thermal_dbg)
return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg;
mutex_lock(&thermal_dbg->lock);
if (!tz_dbg->nr_trips)
goto out;
tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node);
if (tz->temperature > tze->max_temp)
tze->max_temp = tz->temperature;
for (i = 0; i < tz_dbg->nr_trips; i++) {
int trip_id = tz_dbg->trips_crossed[i];
struct trip_stats *trip_stats = &tze->trip_stats[trip_id];
trip_stats->max = max(trip_stats->max, tz->temperature);
trip_stats->min = min(trip_stats->min, tz->temperature);
trip_stats->avg += (tz->temperature - trip_stats->avg) /
++trip_stats->count;
......@@ -777,7 +784,6 @@ static int tze_seq_show(struct seq_file *s, void *v)
struct thermal_zone_device *tz = thermal_dbg->tz_dbg.tz;
struct thermal_trip_desc *td;
struct tz_episode *tze;
const char *type;
u64 duration_ms;
int trip_id;
char c;
......@@ -793,10 +799,10 @@ static int tze_seq_show(struct seq_file *s, void *v)
c = '=';
}
seq_printf(s, ",-Mitigation at %lluus, duration%c%llums\n",
ktime_to_us(tze->timestamp), c, duration_ms);
seq_printf(s, ",-Mitigation at %llums, duration%c%llums, max. temp=%dm°C\n",
ktime_to_ms(tze->timestamp), c, duration_ms, tze->max_temp);
seq_printf(s, "| trip | type | temp(°mC) | hyst(°mC) | duration | avg(°mC) | min(°mC) | max(°mC) |\n");
seq_printf(s, "| trip | type | temp(m°C) | hyst(m°C) | duration(ms) | avg(m°C) | min(m°C) |\n");
for_each_trip_desc(tz, td) {
const struct thermal_trip *trip = &td->trip;
......@@ -814,16 +820,9 @@ static int tze_seq_show(struct seq_file *s, void *v)
trip_stats = &tze->trip_stats[trip_id];
/* Skip trips without any stats. */
if (trip_stats->min > trip_stats->max)
if (trip_stats->trip_temp == THERMAL_TEMP_INVALID)
continue;
if (trip->type == THERMAL_TRIP_PASSIVE)
type = "passive";
else if (trip->type == THERMAL_TRIP_ACTIVE)
type = "active";
else
type = "hot";
if (trip_stats->timestamp != KTIME_MAX) {
/* Mitigation in progress. */
ktime_t delta = ktime_sub(ktime_get(),
......@@ -837,15 +836,14 @@ static int tze_seq_show(struct seq_file *s, void *v)
c = ' ';
}
seq_printf(s, "| %*d | %*s | %*d | %*d | %c%*lld | %*d | %*d | %*d |\n",
seq_printf(s, "| %*d | %*s | %*d | %*d | %c%*lld | %*d | %*d |\n",
4 , trip_id,
8, type,
8, thermal_trip_type_name(trip->type),
9, trip_stats->trip_temp,
9, trip_stats->trip_hyst,
c, 10, duration_ms,
c, 11, duration_ms,
9, trip_stats->avg,
9, trip_stats->min,
9, trip_stats->max);
9, trip_stats->min);
}
return 0;
......@@ -922,3 +920,39 @@ void thermal_debug_tz_remove(struct thermal_zone_device *tz)
thermal_debugfs_remove_id(thermal_dbg);
kfree(trips_crossed);
}
void thermal_debug_tz_resume(struct thermal_zone_device *tz)
{
struct thermal_debugfs *thermal_dbg = tz->debugfs;
ktime_t now = ktime_get();
struct tz_debugfs *tz_dbg;
struct tz_episode *tze;
int i;
if (!thermal_dbg)
return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg;
if (!tz_dbg->nr_trips)
goto out;
/*
* A mitigation episode was in progress before the preceding system
* suspend transition, so close it because the zone handling is starting
* over from scratch.
*/
tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node);
for (i = 0; i < tz_dbg->nr_trips; i++)
tz_episode_close_trip(tze, tz_dbg->trips_crossed[i], now);
tze->duration = ktime_sub(now, tze->timestamp);
tz_dbg->nr_trips = 0;
out:
mutex_unlock(&thermal_dbg->lock);
}
......@@ -7,6 +7,7 @@ void thermal_debug_cdev_remove(struct thermal_cooling_device *cdev);
void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev, int state);
void thermal_debug_tz_add(struct thermal_zone_device *tz);
void thermal_debug_tz_remove(struct thermal_zone_device *tz);
void thermal_debug_tz_resume(struct thermal_zone_device *tz);
void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
const struct thermal_trip *trip);
void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,
......@@ -20,6 +21,7 @@ static inline void thermal_debug_cdev_state_update(const struct thermal_cooling_
int state) {}
static inline void thermal_debug_tz_add(struct thermal_zone_device *tz) {}
static inline void thermal_debug_tz_remove(struct thermal_zone_device *tz) {}
static inline void thermal_debug_tz_resume(struct thermal_zone_device *tz) {}
static inline void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
const struct thermal_trip *trip) {};
static inline void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,
......
......@@ -39,30 +39,53 @@ int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip
return trend;
}
static struct thermal_instance *get_instance(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev,
const struct thermal_trip *trip)
{
struct thermal_instance *ti;
list_for_each_entry(ti, &tz->thermal_instances, tz_node) {
if (ti->trip == trip && ti->cdev == cdev)
return ti;
}
return NULL;
}
bool thermal_trip_is_bound_to_cdev(struct thermal_zone_device *tz,
const struct thermal_trip *trip,
struct thermal_cooling_device *cdev)
{
bool ret;
mutex_lock(&tz->lock);
mutex_lock(&cdev->lock);
ret = !!get_instance(tz, cdev, trip);
mutex_unlock(&cdev->lock);
mutex_unlock(&tz->lock);
return ret;
}
EXPORT_SYMBOL_GPL(thermal_trip_is_bound_to_cdev);
struct thermal_instance *
get_thermal_instance(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev, int trip_index)
{
struct thermal_instance *pos = NULL;
struct thermal_instance *target_instance = NULL;
const struct thermal_trip *trip;
struct thermal_instance *ti;
mutex_lock(&tz->lock);
mutex_lock(&cdev->lock);
trip = &tz->trips[trip_index].trip;
list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
target_instance = pos;
break;
}
}
ti = get_instance(tz, cdev, &tz->trips[trip_index].trip);
mutex_unlock(&cdev->lock);
mutex_unlock(&tz->lock);
return target_instance;
return ti;
}
EXPORT_SYMBOL(get_thermal_instance);
......
......@@ -88,18 +88,7 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
if (sscanf(attr->attr.name, "trip_point_%d_type", &trip_id) != 1)
return -EINVAL;
switch (tz->trips[trip_id].trip.type) {
case THERMAL_TRIP_CRITICAL:
return sprintf(buf, "critical\n");
case THERMAL_TRIP_HOT:
return sprintf(buf, "hot\n");
case THERMAL_TRIP_PASSIVE:
return sprintf(buf, "passive\n");
case THERMAL_TRIP_ACTIVE:
return sprintf(buf, "active\n");
default:
return sprintf(buf, "unknown\n");
}
return sprintf(buf, "%s\n", thermal_trip_type_name(tz->trips[trip_id].trip.type));
}
static ssize_t
......@@ -124,7 +113,7 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
if (temp != trip->temperature) {
if (tz->ops.set_trip_temp) {
ret = tz->ops.set_trip_temp(tz, trip_id, temp);
ret = tz->ops.set_trip_temp(tz, trip, temp);
if (ret)
goto unlock;
}
......@@ -150,7 +139,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1)
return -EINVAL;
return sprintf(buf, "%d\n", tz->trips[trip_id].trip.temperature);
return sprintf(buf, "%d\n", READ_ONCE(tz->trips[trip_id].trip.temperature));
}
static ssize_t
......@@ -174,7 +163,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
trip = &tz->trips[trip_id].trip;
if (hyst != trip->hysteresis) {
trip->hysteresis = hyst;
WRITE_ONCE(trip->hysteresis, hyst);
thermal_zone_trip_updated(tz, trip);
}
......@@ -194,7 +183,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1)
return -EINVAL;
return sprintf(buf, "%d\n", tz->trips[trip_id].trip.hysteresis);
return sprintf(buf, "%d\n", READ_ONCE(tz->trips[trip_id].trip.hysteresis));
}
static ssize_t
......
......@@ -9,6 +9,21 @@
*/
#include "thermal_core.h"
static const char *trip_type_names[] = {
[THERMAL_TRIP_ACTIVE] = "active",
[THERMAL_TRIP_PASSIVE] = "passive",
[THERMAL_TRIP_HOT] = "hot",
[THERMAL_TRIP_CRITICAL] = "critical",
};
const char *thermal_trip_type_name(enum thermal_trip_type trip_type)
{
if (trip_type < THERMAL_TRIP_ACTIVE || trip_type > THERMAL_TRIP_CRITICAL)
return "unknown";
return trip_type_names[trip_type];
}
int for_each_thermal_trip(struct thermal_zone_device *tz,
int (*cb)(struct thermal_trip *, void *),
void *data)
......@@ -47,7 +62,7 @@ int thermal_zone_get_num_trips(struct thermal_zone_device *tz)
EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);
/**
* __thermal_zone_set_trips - Computes the next trip points for the driver
* thermal_zone_set_trips - Computes the next trip points for the driver
* @tz: a pointer to a thermal zone device structure
*
* The function computes the next temperature boundaries by browsing
......@@ -61,7 +76,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);
*
* It does not return a value
*/
void __thermal_zone_set_trips(struct thermal_zone_device *tz)
void thermal_zone_set_trips(struct thermal_zone_device *tz)
{
const struct thermal_trip_desc *td;
int low = -INT_MAX, high = INT_MAX;
......@@ -73,17 +88,11 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz)
return;
for_each_trip_desc(tz, td) {
const struct thermal_trip *trip = &td->trip;
int trip_low;
trip_low = trip->temperature - trip->hysteresis;
if (td->threshold < tz->temperature && td->threshold > low)
low = td->threshold;
if (trip_low < tz->temperature && trip_low > low)
low = trip_low;
if (trip->temperature > tz->temperature &&
trip->temperature < high)
high = trip->temperature;
if (td->threshold > tz->temperature && td->threshold < high)
high = td->threshold;
}
/* No need to change trip points */
......@@ -105,27 +114,17 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz)
dev_err(&tz->device, "Failed to set trips: %d\n", ret);
}
int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip)
{
if (!tz || trip_id < 0 || trip_id >= tz->num_trips || !trip)
return -EINVAL;
*trip = tz->trips[trip_id].trip;
return 0;
}
EXPORT_SYMBOL_GPL(__thermal_zone_get_trip);
int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip)
{
int ret;
if (!tz || !trip || trip_id < 0 || trip_id >= tz->num_trips)
return -EINVAL;
mutex_lock(&tz->lock);
ret = __thermal_zone_get_trip(tz, trip_id, trip);
*trip = tz->trips[trip_id].trip;
mutex_unlock(&tz->lock);
return ret;
return 0;
}
EXPORT_SYMBOL_GPL(thermal_zone_get_trip);
......@@ -152,7 +151,7 @@ void thermal_zone_set_trip_temp(struct thermal_zone_device *tz,
if (trip->temperature == temp)
return;
trip->temperature = temp;
WRITE_ONCE(trip->temperature, temp);
thermal_notify_tz_trip_change(tz, trip);
if (temp == THERMAL_TEMP_INVALID) {
......
......@@ -239,13 +239,34 @@ static irqreturn_t uniphier_tm_alarm_irq_thread(int irq, void *_tdev)
return IRQ_HANDLED;
}
struct trip_walk_data {
struct uniphier_tm_dev *tdev;
int crit_temp;
int index;
};
static int uniphier_tm_trip_walk_cb(struct thermal_trip *trip, void *arg)
{
struct trip_walk_data *twd = arg;
if (trip->type == THERMAL_TRIP_CRITICAL &&
trip->temperature < twd->crit_temp)
twd->crit_temp = trip->temperature;
uniphier_tm_set_alert(twd->tdev, twd->index, trip->temperature);
twd->tdev->alert_en[twd->index++] = true;
return 0;
}
static int uniphier_tm_probe(struct platform_device *pdev)
{
struct trip_walk_data twd = { .crit_temp = INT_MAX, .index = 0 };
struct device *dev = &pdev->dev;
struct regmap *regmap;
struct device_node *parent;
struct uniphier_tm_dev *tdev;
int i, ret, irq, crit_temp = INT_MAX;
int ret, irq;
tdev = devm_kzalloc(dev, sizeof(*tdev), GFP_KERNEL);
if (!tdev)
......@@ -293,20 +314,10 @@ static int uniphier_tm_probe(struct platform_device *pdev)
}
/* set alert temperatures */
for (i = 0; i < thermal_zone_get_num_trips(tdev->tz_dev); i++) {
struct thermal_trip trip;
twd.tdev = tdev;
thermal_zone_for_each_trip(tdev->tz_dev, uniphier_tm_trip_walk_cb, &twd);
ret = thermal_zone_get_trip(tdev->tz_dev, i, &trip);
if (ret)
return ret;
if (trip.type == THERMAL_TRIP_CRITICAL &&
trip.temperature < crit_temp)
crit_temp = trip.temperature;
uniphier_tm_set_alert(tdev, i, trip.temperature);
tdev->alert_en[i] = true;
}
if (crit_temp > CRITICAL_TEMP_LIMIT) {
if (twd.crit_temp > CRITICAL_TEMP_LIMIT) {
dev_err(dev, "critical trip is over limit(>%d), or not set\n",
CRITICAL_TEMP_LIMIT);
return -EINVAL;
......
......@@ -24,7 +24,7 @@
#define MT8186_BIG_CPU1 5
#define MT8186_NNA 6
#define MT8186_ADSP 7
#define MT8186_MFG 8
#define MT8186_GPU 8
#define MT8188_MCU_LITTLE_CPU0 0
#define MT8188_MCU_LITTLE_CPU1 1
......@@ -34,11 +34,11 @@
#define MT8188_MCU_BIG_CPU1 5
#define MT8188_AP_APU 0
#define MT8188_AP_GPU1 1
#define MT8188_AP_GPU2 2
#define MT8188_AP_SOC1 3
#define MT8188_AP_SOC2 4
#define MT8188_AP_SOC3 5
#define MT8188_AP_GPU0 1
#define MT8188_AP_GPU1 2
#define MT8188_AP_ADSP 3
#define MT8188_AP_VDO 4
#define MT8188_AP_INFRA 5
#define MT8188_AP_CAM1 6
#define MT8188_AP_CAM2 7
......
......@@ -14,5 +14,6 @@ int intel_tcc_get_tjmax(int cpu);
int intel_tcc_get_offset(int cpu);
int intel_tcc_set_offset(int cpu, int offset);
int intel_tcc_get_temp(int cpu, int *temp, bool pkg);
u32 intel_tcc_get_offset_mask(void);
#endif /* __INTEL_TCC_H__ */
......@@ -20,7 +20,7 @@
static inline bool soc_intel_is_##soc(void) \
{ \
static const struct x86_cpu_id soc##_cpu_ids[] = { \
X86_MATCH_INTEL_FAM6_MODEL(type, NULL), \
X86_MATCH_VFM(type, NULL), \
{} \
}; \
const struct x86_cpu_id *id; \
......@@ -31,11 +31,11 @@ static inline bool soc_intel_is_##soc(void) \
return false; \
}
SOC_INTEL_IS_CPU(byt, ATOM_SILVERMONT);
SOC_INTEL_IS_CPU(cht, ATOM_AIRMONT);
SOC_INTEL_IS_CPU(apl, ATOM_GOLDMONT);
SOC_INTEL_IS_CPU(glk, ATOM_GOLDMONT_PLUS);
SOC_INTEL_IS_CPU(cml, KABYLAKE_L);
SOC_INTEL_IS_CPU(byt, INTEL_ATOM_SILVERMONT);
SOC_INTEL_IS_CPU(cht, INTEL_ATOM_AIRMONT);
SOC_INTEL_IS_CPU(apl, INTEL_ATOM_GOLDMONT);
SOC_INTEL_IS_CPU(glk, INTEL_ATOM_GOLDMONT_PLUS);
SOC_INTEL_IS_CPU(cml, INTEL_KABYLAKE_L);
#undef SOC_INTEL_IS_CPU
......
......@@ -79,6 +79,9 @@ struct thermal_trip {
#define THERMAL_TRIP_FLAG_RW (THERMAL_TRIP_FLAG_RW_TEMP | \
THERMAL_TRIP_FLAG_RW_HYST)
#define THERMAL_TRIP_PRIV_TO_INT(_val_) (uintptr_t)(_val_)
#define THERMAL_INT_TO_TRIP_PRIV(_val_) (void *)(uintptr_t)(_val_)
struct thermal_zone_device;
struct thermal_zone_device_ops {
......@@ -90,7 +93,8 @@ struct thermal_zone_device_ops {
int (*set_trips) (struct thermal_zone_device *, int, int);
int (*change_mode) (struct thermal_zone_device *,
enum thermal_device_mode);
int (*set_trip_temp) (struct thermal_zone_device *, int, int);
int (*set_trip_temp) (struct thermal_zone_device *,
const struct thermal_trip *, int);
int (*get_crit_temp) (struct thermal_zone_device *, int *);
int (*set_emul_temp) (struct thermal_zone_device *, int);
int (*get_trend) (struct thermal_zone_device *,
......@@ -198,8 +202,6 @@ static inline void devm_thermal_of_zone_unregister(struct device *dev,
}
#endif
int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip);
int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip);
int for_each_thermal_trip(struct thermal_zone_device *tz,
......@@ -221,7 +223,8 @@ struct thermal_zone_device *thermal_zone_device_register_with_trips(
int num_trips, void *devdata,
const struct thermal_zone_device_ops *ops,
const struct thermal_zone_params *tzp,
int passive_delay, int polling_delay);
unsigned int passive_delay,
unsigned int polling_delay);
struct thermal_zone_device *thermal_tripless_zone_device_register(
const char *type,
......@@ -261,7 +264,7 @@ thermal_of_cooling_device_register(struct device_node *np, const char *, void *,
struct thermal_cooling_device *
devm_thermal_of_cooling_device_register(struct device *dev,
struct device_node *np,
char *type, void *devdata,
const char *type, void *devdata,
const struct thermal_cooling_device_ops *ops);
void thermal_cooling_device_update(struct thermal_cooling_device *);
void thermal_cooling_device_unregister(struct thermal_cooling_device *);
......@@ -269,6 +272,9 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
int thermal_zone_get_slope(struct thermal_zone_device *tz);
int thermal_zone_get_offset(struct thermal_zone_device *tz);
bool thermal_trip_is_bound_to_cdev(struct thermal_zone_device *tz,
const struct thermal_trip *trip,
struct thermal_cooling_device *cdev);
int thermal_zone_device_enable(struct thermal_zone_device *tz);
int thermal_zone_device_disable(struct thermal_zone_device *tz);
......@@ -305,7 +311,7 @@ thermal_of_cooling_device_register(struct device_node *np,
static inline struct thermal_cooling_device *
devm_thermal_of_cooling_device_register(struct device *dev,
struct device_node *np,
char *type, void *devdata,
const char *type, void *devdata,
const struct thermal_cooling_device_ops *ops)
{
return ERR_PTR(-ENODEV);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment