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: ...@@ -10,6 +10,8 @@ maintainers:
- Vasily Khoruzhick <anarsoul@gmail.com> - Vasily Khoruzhick <anarsoul@gmail.com>
- Yangtao Li <tiny.windzz@gmail.com> - Yangtao Li <tiny.windzz@gmail.com>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
enum: enum:
...@@ -55,7 +57,6 @@ properties: ...@@ -55,7 +57,6 @@ properties:
maxItems: 1 maxItems: 1
description: phandle to device controlling temperate offset SYS_CFG register description: phandle to device controlling temperate offset SYS_CFG register
# See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
"#thermal-sensor-cells": "#thermal-sensor-cells":
enum: enum:
- 0 - 0
...@@ -135,9 +136,8 @@ required: ...@@ -135,9 +136,8 @@ required:
- compatible - compatible
- reg - reg
- interrupts - interrupts
- '#thermal-sensor-cells'
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -11,6 +11,8 @@ maintainers: ...@@ -11,6 +11,8 @@ maintainers:
description: Binding for Amlogic Thermal description: Binding for Amlogic Thermal
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
oneOf: oneOf:
...@@ -44,11 +46,11 @@ required: ...@@ -44,11 +46,11 @@ required:
- clocks - clocks
- amlogic,ao-secure - amlogic,ao-secure
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
cpu_temp: temperature-sensor@ff634800 { temperature-sensor@ff634800 {
compatible = "amlogic,g12a-cpu-thermal", compatible = "amlogic,g12a-cpu-thermal",
"amlogic,g12a-thermal"; "amlogic,g12a-thermal";
reg = <0xff634800 0x50>; reg = <0xff634800 0x50>;
......
...@@ -19,19 +19,19 @@ description: |+ ...@@ -19,19 +19,19 @@ description: |+
Refer to the bindings described in Refer to the bindings described in
Documentation/devicetree/bindings/mfd/syscon.yaml Documentation/devicetree/bindings/mfd/syscon.yaml
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
const: brcm,bcm2711-thermal const: brcm,bcm2711-thermal
# See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
"#thermal-sensor-cells": "#thermal-sensor-cells":
const: 0 const: 0
required: required:
- compatible - compatible
- '#thermal-sensor-cells'
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -42,7 +42,6 @@ additionalProperties: false ...@@ -42,7 +42,6 @@ additionalProperties: false
required: required:
- compatible - compatible
- reg - reg
- "#thermal-sensor-cells"
examples: examples:
- | - |
......
...@@ -34,7 +34,6 @@ required: ...@@ -34,7 +34,6 @@ required:
- compatible - compatible
- reg - reg
- clocks - clocks
- '#thermal-sensor-cells'
examples: examples:
- | - |
......
...@@ -28,7 +28,6 @@ properties: ...@@ -28,7 +28,6 @@ properties:
required: required:
- compatible - compatible
- '#thermal-sensor-cells'
additionalProperties: false additionalProperties: false
......
...@@ -15,6 +15,8 @@ description: ...@@ -15,6 +15,8 @@ description:
sensor resistor. The voltage read across the sensor is mapped to sensor resistor. The voltage read across the sensor is mapped to
temperature using voltage-temperature lookup table. temperature using voltage-temperature lookup table.
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
const: generic-adc-thermal const: generic-adc-thermal
...@@ -44,11 +46,10 @@ properties: ...@@ -44,11 +46,10 @@ properties:
required: required:
- compatible - compatible
- '#thermal-sensor-cells'
- io-channels - io-channels
- io-channel-names - io-channel-names
additionalProperties: false unevaluatedProperties: false
examples: 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: | ...@@ -16,6 +16,8 @@ description: |
for i.MX8MM which has ONLY 1 sensor, v2 is for i.MX8MP which has for i.MX8MM which has ONLY 1 sensor, v2 is for i.MX8MP which has
2 sensors. 2 sensors.
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
oneOf: oneOf:
...@@ -51,9 +53,8 @@ required: ...@@ -51,9 +53,8 @@ required:
- compatible - compatible
- reg - reg
- clocks - clocks
- '#thermal-sensor-cells'
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -38,7 +38,6 @@ required: ...@@ -38,7 +38,6 @@ required:
- compatible - compatible
- reg - reg
- interrupts - interrupts
- '#thermal-sensor-cells'
if: if:
properties: properties:
......
...@@ -99,7 +99,6 @@ required: ...@@ -99,7 +99,6 @@ required:
- resets - resets
- nvmem-cells - nvmem-cells
- nvmem-cell-names - nvmem-cell-names
- "#thermal-sensor-cells"
additionalProperties: false additionalProperties: false
......
...@@ -197,7 +197,6 @@ required: ...@@ -197,7 +197,6 @@ required:
- clock-names - clock-names
- resets - resets
- reset-names - reset-names
- "#thermal-sensor-cells"
allOf: allOf:
- $ref: thermal-sensor.yaml - $ref: thermal-sensor.yaml
......
...@@ -20,11 +20,7 @@ description: | ...@@ -20,11 +20,7 @@ description: |
node. See ../firmware/nvidia,tegra186-bpmp.yaml for details of the node. See ../firmware/nvidia,tegra186-bpmp.yaml for details of the
BPMP binding. BPMP binding.
This node represents a thermal sensor. See $ref: thermal-sensor.yaml#
Documentation/devicetree/bindings/thermal/thermal-sensor.yaml
for details of the core thermal binding.
properties: properties:
compatible: compatible:
...@@ -33,10 +29,6 @@ properties: ...@@ -33,10 +29,6 @@ properties:
- nvidia,tegra194-bpmp-thermal - nvidia,tegra194-bpmp-thermal
'#thermal-sensor-cells': '#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 const: 1
additionalProperties: false unevaluatedProperties: false
...@@ -27,6 +27,8 @@ description: | ...@@ -27,6 +27,8 @@ description: |
TSENSOR has two channels which monitor two different spots of the SoC. TSENSOR has two channels which monitor two different spots of the SoC.
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
const: nvidia,tegra30-tsensor const: nvidia,tegra30-tsensor
...@@ -46,19 +48,14 @@ properties: ...@@ -46,19 +48,14 @@ properties:
"#thermal-sensor-cells": "#thermal-sensor-cells":
const: 1 const: 1
assigned-clock-parents: true
assigned-clock-rates: true
assigned-clocks: true
required: required:
- compatible - compatible
- reg - reg
- clocks - clocks
- resets - resets
- interrupts - interrupts
- "#thermal-sensor-cells"
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -42,7 +42,6 @@ required: ...@@ -42,7 +42,6 @@ required:
- compatible - compatible
- reg - reg
- interrupts - interrupts
- '#thermal-sensor-cells'
additionalProperties: false additionalProperties: false
......
...@@ -8,6 +8,8 @@ title: Qualcomm's SPMI PMIC ADC HC Thermal Monitoring ...@@ -8,6 +8,8 @@ title: Qualcomm's SPMI PMIC ADC HC Thermal Monitoring
maintainers: maintainers:
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org> - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
const: qcom,spmi-adc-tm-hc const: qcom,spmi-adc-tm-hc
...@@ -20,9 +22,6 @@ properties: ...@@ -20,9 +22,6 @@ properties:
"#thermal-sensor-cells": "#thermal-sensor-cells":
const: 1 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": "#address-cells":
const: 1 const: 1
...@@ -106,9 +105,8 @@ required: ...@@ -106,9 +105,8 @@ required:
- interrupts - interrupts
- "#address-cells" - "#address-cells"
- "#size-cells" - "#size-cells"
- "#thermal-sensor-cells"
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -8,6 +8,8 @@ title: Qualcomm's SPMI PMIC ADC Thermal Monitoring ...@@ -8,6 +8,8 @@ title: Qualcomm's SPMI PMIC ADC Thermal Monitoring
maintainers: maintainers:
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org> - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
enum: enum:
...@@ -23,9 +25,6 @@ properties: ...@@ -23,9 +25,6 @@ properties:
"#thermal-sensor-cells": "#thermal-sensor-cells":
const: 1 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": "#address-cells":
const: 1 const: 1
...@@ -159,9 +158,8 @@ required: ...@@ -159,9 +158,8 @@ required:
- interrupts - interrupts
- "#address-cells" - "#address-cells"
- "#size-cells" - "#size-cells"
- "#thermal-sensor-cells"
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -67,6 +67,7 @@ properties: ...@@ -67,6 +67,7 @@ properties:
- qcom,sm8450-tsens - qcom,sm8450-tsens
- qcom,sm8550-tsens - qcom,sm8550-tsens
- qcom,sm8650-tsens - qcom,sm8650-tsens
- qcom,x1e80100-tsens
- const: qcom,tsens-v2 - const: qcom,tsens-v2
- description: v2 of TSENS with combined interrupt - description: v2 of TSENS with combined interrupt
...@@ -217,18 +218,16 @@ properties: ...@@ -217,18 +218,16 @@ properties:
"#thermal-sensor-cells": "#thermal-sensor-cells":
const: 1 const: 1
description:
Number of cells required to uniquely identify the thermal sensors. Since
we have multiple sensors this is set to 1
required: required:
- compatible - compatible
- interrupts - interrupts
- interrupt-names - interrupt-names
- "#thermal-sensor-cells"
- "#qcom,sensors" - "#qcom,sensors"
allOf: allOf:
- $ref: thermal-sensor.yaml#
- if: - if:
properties: properties:
compatible: compatible:
...@@ -292,17 +291,12 @@ allOf: ...@@ -292,17 +291,12 @@ allOf:
required: required:
- reg - reg
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
#include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
// Example msm9860 based SoC (ipq8064): thermal-sensor {
gcc: clock-controller {
/* ... */
tsens: thermal-sensor {
compatible = "qcom,ipq8064-tsens"; compatible = "qcom,ipq8064-tsens";
nvmem-cells = <&tsens_calib>, <&tsens_calib_backup>; nvmem-cells = <&tsens_calib>, <&tsens_calib_backup>;
...@@ -313,7 +307,6 @@ examples: ...@@ -313,7 +307,6 @@ examples:
#qcom,sensors = <11>; #qcom,sensors = <11>;
#thermal-sensor-cells = <1>; #thermal-sensor-cells = <1>;
}; };
};
- | - |
#include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
......
...@@ -9,6 +9,8 @@ title: Thermal Monitoring Unit (TMU) on Freescale QorIQ SoCs ...@@ -9,6 +9,8 @@ title: Thermal Monitoring Unit (TMU) on Freescale QorIQ SoCs
maintainers: maintainers:
- Anson Huang <Anson.Huang@nxp.com> - Anson Huang <Anson.Huang@nxp.com>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
description: | description: |
...@@ -68,9 +70,8 @@ required: ...@@ -68,9 +70,8 @@ required:
- interrupts - interrupts
- fsl,tmu-range - fsl,tmu-range
- fsl,tmu-calibration - fsl,tmu-calibration
- '#thermal-sensor-cells'
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -15,6 +15,8 @@ description: ...@@ -15,6 +15,8 @@ description:
maintainers: maintainers:
- Niklas Söderlund <niklas.soderlund@ragnatech.se> - Niklas Söderlund <niklas.soderlund@ragnatech.se>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
enum: enum:
...@@ -57,7 +59,6 @@ required: ...@@ -57,7 +59,6 @@ required:
- clocks - clocks
- power-domains - power-domains
- resets - resets
- "#thermal-sensor-cells"
if: if:
properties: properties:
...@@ -96,7 +97,7 @@ else: ...@@ -96,7 +97,7 @@ else:
required: required:
- interrupts - interrupts
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -9,6 +9,8 @@ title: Temperature Sensor ADC (TSADC) on Rockchip SoCs ...@@ -9,6 +9,8 @@ title: Temperature Sensor ADC (TSADC) on Rockchip SoCs
maintainers: maintainers:
- Heiko Stuebner <heiko@sntech.de> - Heiko Stuebner <heiko@sntech.de>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
enum: enum:
...@@ -76,9 +78,8 @@ required: ...@@ -76,9 +78,8 @@ required:
- clocks - clocks
- clock-names - clock-names
- resets - resets
- "#thermal-sensor-cells"
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -13,6 +13,8 @@ description: ...@@ -13,6 +13,8 @@ description:
maintainers: maintainers:
- Biju Das <biju.das.jz@bp.renesas.com> - Biju Das <biju.das.jz@bp.renesas.com>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
items: items:
...@@ -43,9 +45,8 @@ required: ...@@ -43,9 +45,8 @@ required:
- clocks - clocks
- power-domains - power-domains
- resets - resets
- "#thermal-sensor-cells"
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -61,7 +61,8 @@ properties: ...@@ -61,7 +61,8 @@ properties:
TRIMINFO at 0x10068000 contains data for TMU channel 2 TRIMINFO at 0x10068000 contains data for TMU channel 2
minItems: 1 minItems: 1
'#thermal-sensor-cells': true '#thermal-sensor-cells':
const: 0
vtmu-supply: vtmu-supply:
description: The regulator node supplying voltage to TMU. description: The regulator node supplying voltage to TMU.
......
...@@ -14,6 +14,8 @@ description: | ...@@ -14,6 +14,8 @@ description: |
maintainers: maintainers:
- Kunihiko Hayashi <hayashi.kunihiko@socionext.com> - Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
enum: enum:
...@@ -38,9 +40,8 @@ properties: ...@@ -38,9 +40,8 @@ properties:
required: required:
- compatible - compatible
- interrupts - interrupts
- "#thermal-sensor-cells"
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -11,6 +11,8 @@ maintainers: ...@@ -11,6 +11,8 @@ maintainers:
- Baolin Wang <baolin.wang7@gmail.com> - Baolin Wang <baolin.wang7@gmail.com>
- Chunyan Zhang <zhang.lyra@gmail.com> - Chunyan Zhang <zhang.lyra@gmail.com>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
const: sprd,ums512-thermal const: sprd,ums512-thermal
...@@ -77,15 +79,14 @@ required: ...@@ -77,15 +79,14 @@ required:
- clock-names - clock-names
- nvmem-cells - nvmem-cells
- nvmem-cell-names - nvmem-cell-names
- "#thermal-sensor-cells"
- "#address-cells" - "#address-cells"
- "#size-cells" - "#size-cells"
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
ap_thm0: thermal@32200000 { thermal@32200000 {
compatible = "sprd,ums512-thermal"; compatible = "sprd,ums512-thermal";
reg = <0x32200000 0x10000>; reg = <0x32200000 0x10000>;
clock-names = "enable"; clock-names = "enable";
......
...@@ -9,6 +9,8 @@ title: STMicroelectronics STM32 digital thermal sensor (DTS) ...@@ -9,6 +9,8 @@ title: STMicroelectronics STM32 digital thermal sensor (DTS)
maintainers: maintainers:
- Pascal Paillet <p.paillet@foss.st.com> - Pascal Paillet <p.paillet@foss.st.com>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
const: st,stm32-thermal const: st,stm32-thermal
...@@ -30,14 +32,13 @@ properties: ...@@ -30,14 +32,13 @@ properties:
const: 0 const: 0
required: required:
- "#thermal-sensor-cells"
- compatible - compatible
- reg - reg
- interrupts - interrupts
- clocks - clocks
- clock-names - clock-names
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -49,7 +49,10 @@ properties: ...@@ -49,7 +49,10 @@ properties:
to take when the temperature crosses those thresholds. to take when the temperature crosses those thresholds.
patternProperties: 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 type: object
description: description:
Each thermal zone node contains information about how frequently it Each thermal zone node contains information about how frequently it
...@@ -229,7 +232,6 @@ patternProperties: ...@@ -229,7 +232,6 @@ patternProperties:
required: required:
- thermal-sensors - thermal-sensors
- trips
additionalProperties: false additionalProperties: false
......
...@@ -9,6 +9,8 @@ title: Texas Instruments AM654 VTM (DTS) ...@@ -9,6 +9,8 @@ title: Texas Instruments AM654 VTM (DTS)
maintainers: maintainers:
- Keerthy <j-keerthy@ti.com> - Keerthy <j-keerthy@ti.com>
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
const: ti,am654-vtm const: ti,am654-vtm
...@@ -26,9 +28,8 @@ required: ...@@ -26,9 +28,8 @@ required:
- compatible - compatible
- reg - reg
- power-domains - power-domains
- "#thermal-sensor-cells"
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -22,6 +22,8 @@ description: | ...@@ -22,6 +22,8 @@ description: |
Temp(C) = (-9.2627e-12) * x^4 + (6.0373e-08) * x^3 + \ Temp(C) = (-9.2627e-12) * x^4 + (6.0373e-08) * x^3 + \
(-1.7058e-04) * x^2 + (3.2512e-01) * x + (-4.9003e+01) (-1.7058e-04) * x^2 + (3.2512e-01) * x + (-4.9003e+01)
$ref: thermal-sensor.yaml#
properties: properties:
compatible: compatible:
enum: enum:
...@@ -64,9 +66,8 @@ required: ...@@ -64,9 +66,8 @@ required:
- compatible - compatible
- reg - reg
- power-domains - power-domains
- "#thermal-sensor-cells"
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -19196,8 +19196,8 @@ L: linux-renesas-soc@vger.kernel.org ...@@ -19196,8 +19196,8 @@ L: linux-renesas-soc@vger.kernel.org
S: Supported S: Supported
F: Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml F: Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml
F: Documentation/devicetree/bindings/thermal/rcar-thermal.yaml F: Documentation/devicetree/bindings/thermal/rcar-thermal.yaml
F: drivers/thermal/rcar_gen3_thermal.c F: drivers/thermal/renesas/rcar_gen3_thermal.c
F: drivers/thermal/rcar_thermal.c F: drivers/thermal/renesas/rcar_thermal.c
RENESAS RIIC DRIVER RENESAS RIIC DRIVER
M: Chris Brandt <chris.brandt@renesas.com> M: Chris Brandt <chris.brandt@renesas.com>
......
...@@ -638,7 +638,7 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device, ...@@ -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, 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); struct iwl_mvm *mvm = thermal_zone_device_priv(device);
int ret; int ret;
......
...@@ -343,32 +343,6 @@ config ROCKCHIP_THERMAL ...@@ -343,32 +343,6 @@ config ROCKCHIP_THERMAL
trip point. Cpufreq is used as the cooling device and will throttle trip point. Cpufreq is used as the cooling device and will throttle
CPUs when the Temperature crosses the passive trip point. 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 config KIRKWOOD_THERMAL
tristate "Temperature sensor on Marvell Kirkwood SoCs" tristate "Temperature sensor on Marvell Kirkwood SoCs"
depends on MACH_KIRKWOOD || COMPILE_TEST depends on MACH_KIRKWOOD || COMPILE_TEST
...@@ -459,6 +433,8 @@ depends on (ARCH_STI || ARCH_STM32) && OF ...@@ -459,6 +433,8 @@ depends on (ARCH_STI || ARCH_STM32) && OF
source "drivers/thermal/st/Kconfig" source "drivers/thermal/st/Kconfig"
endmenu endmenu
source "drivers/thermal/renesas/Kconfig"
source "drivers/thermal/tegra/Kconfig" source "drivers/thermal/tegra/Kconfig"
config GENERIC_ADC_THERMAL config GENERIC_ADC_THERMAL
......
...@@ -38,9 +38,7 @@ obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o ...@@ -38,9 +38,7 @@ obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o obj-y += renesas/
obj-$(CONFIG_RCAR_GEN3_THERMAL) += rcar_gen3_thermal.o
obj-$(CONFIG_RZG2L_THERMAL) += rzg2l_thermal.o
obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
obj-y += samsung/ obj-y += samsung/
obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
......
...@@ -163,6 +163,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table); ...@@ -163,6 +163,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
static int bcm2835_thermal_probe(struct platform_device *pdev) static int bcm2835_thermal_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev;
const struct of_device_id *match; const struct of_device_id *match;
struct thermal_zone_device *tz; struct thermal_zone_device *tz;
struct bcm2835_thermal_data *data; struct bcm2835_thermal_data *data;
...@@ -170,12 +171,11 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) ...@@ -170,12 +171,11 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
u32 val; u32 val;
unsigned long rate; unsigned long rate;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
match = of_match_device(bcm2835_thermal_of_match_table, match = of_match_device(bcm2835_thermal_of_match_table, dev);
&pdev->dev);
if (!match) if (!match)
return -EINVAL; return -EINVAL;
...@@ -185,34 +185,20 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) ...@@ -185,34 +185,20 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
return err; return err;
} }
data->clk = devm_clk_get(&pdev->dev, NULL); data->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(data->clk)) { if (IS_ERR(data->clk))
err = PTR_ERR(data->clk); return dev_err_probe(dev, PTR_ERR(data->clk), "Could not get clk\n");
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;
rate = clk_get_rate(data->clk); rate = clk_get_rate(data->clk);
if ((rate < 1920000) || (rate > 5000000)) 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", "Clock %pCn running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n",
data->clk, rate); data->clk, rate);
/* register of thermal sensor and get info from DT */ /* register of thermal sensor and get info from DT */
tz = devm_thermal_of_zone_register(&pdev->dev, 0, data, tz = devm_thermal_of_zone_register(dev, 0, data, &bcm2835_thermal_ops);
&bcm2835_thermal_ops); if (IS_ERR(tz))
if (IS_ERR(tz)) { return dev_err_probe(dev, PTR_ERR(tz), "Failed to register the thermal device\n");
err = PTR_ERR(tz);
dev_err(&pdev->dev,
"Failed to register the thermal device: %d\n",
err);
goto err_clk;
}
/* /*
* right now the FW does set up the HW-block, so we are not * 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) ...@@ -233,10 +219,8 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
*/ */
err = thermal_zone_get_trip(tz, 0, &trip); err = thermal_zone_get_trip(tz, 0, &trip);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, dev_err(dev, "Not able to read trip_temp: %d\n", err);
"Not able to read trip_temp: %d\n", return err;
err);
goto err_tz;
} }
/* set bandgap reference voltage and enable voltage regulator */ /* set bandgap reference voltage and enable voltage regulator */
...@@ -269,17 +253,11 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) ...@@ -269,17 +253,11 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
*/ */
err = thermal_add_hwmon_sysfs(tz); err = thermal_add_hwmon_sysfs(tz);
if (err) if (err)
goto err_tz; return err;
bcm2835_thermal_debugfs(pdev); bcm2835_thermal_debugfs(pdev);
return 0; 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) static void bcm2835_thermal_remove(struct platform_device *pdev)
...@@ -287,7 +265,6 @@ 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); struct bcm2835_thermal_data *data = platform_get_drvdata(pdev);
debugfs_remove_recursive(data->debugfsdir); debugfs_remove_recursive(data->debugfsdir);
clk_disable_unprepare(data->clk);
} }
static struct platform_driver bcm2835_thermal_driver = { static struct platform_driver bcm2835_thermal_driver = {
......
...@@ -57,24 +57,16 @@ static void bang_bang_control(struct thermal_zone_device *tz, ...@@ -57,24 +57,16 @@ static void bang_bang_control(struct thermal_zone_device *tz,
if (instance->trip != trip) if (instance->trip != trip)
continue; continue;
if (instance->target == THERMAL_NO_TARGET) if (instance->target != 0 && instance->target != 1 &&
instance->target = 0; instance->target != THERMAL_NO_TARGET)
if (instance->target != 0 && instance->target != 1) {
pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n", pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n",
instance->target, instance->name); instance->target, instance->name);
instance->target = 1;
}
/* /*
* Enable the fan when the trip is crossed on the way up and * Enable the fan when the trip is crossed on the way up and
* disable it when the trip is crossed on the way down. * disable it when the trip is crossed on the way down.
*/ */
if (instance->target == 0 && crossed_up) instance->target = crossed_up;
instance->target = 1;
else if (instance->target == 1 && !crossed_up)
instance->target = 0;
dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target); dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target);
......
...@@ -388,15 +388,10 @@ static int hi6220_thermal_probe(struct hisi_thermal_data *data) ...@@ -388,15 +388,10 @@ static int hi6220_thermal_probe(struct hisi_thermal_data *data)
{ {
struct platform_device *pdev = data->pdev; struct platform_device *pdev = data->pdev;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int ret;
data->clk = devm_clk_get(dev, "thermal_clk"); data->clk = devm_clk_get(dev, "thermal_clk");
if (IS_ERR(data->clk)) { if (IS_ERR(data->clk))
ret = PTR_ERR(data->clk); return dev_err_probe(dev, PTR_ERR(data->clk), "failed to get thermal clk\n");
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get thermal clk: %d\n", ret);
return ret;
}
data->sensor = devm_kzalloc(dev, sizeof(*data->sensor), GFP_KERNEL); data->sensor = devm_kzalloc(dev, sizeof(*data->sensor), GFP_KERNEL);
if (!data->sensor) if (!data->sensor)
......
...@@ -331,25 +331,16 @@ static int imx_change_mode(struct thermal_zone_device *tz, ...@@ -331,25 +331,16 @@ static int imx_change_mode(struct thermal_zone_device *tz,
return 0; return 0;
} }
static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip_id, static int imx_set_trip_temp(struct thermal_zone_device *tz,
int temp) const struct thermal_trip *trip, int temp)
{ {
struct imx_thermal_data *data = thermal_zone_device_priv(tz); struct imx_thermal_data *data = thermal_zone_device_priv(tz);
struct thermal_trip trip;
int ret; int ret;
ret = pm_runtime_resume_and_get(data->dev); ret = pm_runtime_resume_and_get(data->dev);
if (ret < 0) if (ret < 0)
return ret; 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 */ /* do not allow passive to be set higher than critical */
if (temp < 0 || temp > trips[IMX_TRIP_CRITICAL].temperature) if (temp < 0 || temp > trips[IMX_TRIP_CRITICAL].temperature)
return -EINVAL; return -EINVAL;
...@@ -601,28 +592,29 @@ static inline void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data ...@@ -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) static int imx_thermal_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev;
struct imx_thermal_data *data; struct imx_thermal_data *data;
struct regmap *map; struct regmap *map;
int measure_freq; int measure_freq;
int ret; int ret;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; 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)) { if (IS_ERR(map)) {
ret = PTR_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; return ret;
} }
data->tempmon = map; data->tempmon = map;
data->socdata = of_device_get_match_data(&pdev->dev); data->socdata = of_device_get_match_data(dev);
if (!data->socdata) { if (!data->socdata) {
dev_err(&pdev->dev, "no device match found\n"); dev_err(dev, "no device match found\n");
return -ENODEV; return -ENODEV;
} }
...@@ -645,15 +637,15 @@ static int imx_thermal_probe(struct platform_device *pdev) ...@@ -645,15 +637,15 @@ static int imx_thermal_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data); 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); ret = imx_init_from_nvmem_cells(pdev);
if (ret) if (ret)
return dev_err_probe(&pdev->dev, ret, return dev_err_probe(dev, ret,
"failed to init from nvmem\n"); "failed to init from nvmem\n");
} else { } else {
ret = imx_init_from_tempmon_data(pdev); ret = imx_init_from_tempmon_data(pdev);
if (ret) { 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; return ret;
} }
} }
...@@ -673,15 +665,12 @@ static int imx_thermal_probe(struct platform_device *pdev) ...@@ -673,15 +665,12 @@ static int imx_thermal_probe(struct platform_device *pdev)
ret = imx_thermal_register_legacy_cooling(data); ret = imx_thermal_register_legacy_cooling(data);
if (ret) if (ret)
return dev_err_probe(&pdev->dev, ret, return dev_err_probe(dev, ret,
"failed to register cpufreq cooling device\n"); "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)) { if (IS_ERR(data->thermal_clk)) {
ret = PTR_ERR(data->thermal_clk); ret = dev_err_probe(dev, PTR_ERR(data->thermal_clk), "failed to get thermal clk\n");
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"failed to get thermal clk: %d\n", ret);
goto legacy_cleanup; goto legacy_cleanup;
} }
...@@ -694,7 +683,7 @@ static int imx_thermal_probe(struct platform_device *pdev) ...@@ -694,7 +683,7 @@ static int imx_thermal_probe(struct platform_device *pdev)
*/ */
ret = clk_prepare_enable(data->thermal_clk); ret = clk_prepare_enable(data->thermal_clk);
if (ret) { 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; goto legacy_cleanup;
} }
...@@ -707,12 +696,12 @@ static int imx_thermal_probe(struct platform_device *pdev) ...@@ -707,12 +696,12 @@ static int imx_thermal_probe(struct platform_device *pdev)
IMX_POLLING_DELAY); IMX_POLLING_DELAY);
if (IS_ERR(data->tz)) { if (IS_ERR(data->tz)) {
ret = PTR_ERR(data->tz); ret = PTR_ERR(data->tz);
dev_err(&pdev->dev, dev_err(dev, "failed to register thermal zone device %d\n",
"failed to register thermal zone device %d\n", ret); ret);
goto clk_disable; 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, " critical:%dC passive:%dC\n", data->temp_grade,
data->temp_max / 1000, trips[IMX_TRIP_CRITICAL].temperature / 1000, data->temp_max / 1000, trips[IMX_TRIP_CRITICAL].temperature / 1000,
trips[IMX_TRIP_PASSIVE].temperature / 1000); trips[IMX_TRIP_PASSIVE].temperature / 1000);
...@@ -736,7 +725,7 @@ static int imx_thermal_probe(struct platform_device *pdev) ...@@ -736,7 +725,7 @@ static int imx_thermal_probe(struct platform_device *pdev)
usleep_range(20, 50); usleep_range(20, 50);
/* the core was configured and enabled just before */ /* the core was configured and enabled just before */
pm_runtime_set_active(&pdev->dev); pm_runtime_set_active(dev);
pm_runtime_enable(data->dev); pm_runtime_enable(data->dev);
ret = pm_runtime_resume_and_get(data->dev); ret = pm_runtime_resume_and_get(data->dev);
...@@ -748,11 +737,11 @@ static int imx_thermal_probe(struct platform_device *pdev) ...@@ -748,11 +737,11 @@ static int imx_thermal_probe(struct platform_device *pdev)
if (ret) if (ret)
goto thermal_zone_unregister; 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, imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
0, "imx_thermal", data); 0, "imx_thermal", data);
if (ret < 0) { 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; goto thermal_zone_unregister;
} }
......
...@@ -571,7 +571,7 @@ static int int3400_thermal_probe(struct platform_device *pdev) ...@@ -571,7 +571,7 @@ static int int3400_thermal_probe(struct platform_device *pdev)
if (!adev) if (!adev)
return -ENODEV; return -ENODEV;
priv = kzalloc(sizeof(struct int3400_thermal_priv), GFP_KERNEL); priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
......
...@@ -25,17 +25,6 @@ struct int3403_sensor { ...@@ -25,17 +25,6 @@ struct int3403_sensor {
struct int34x_thermal_zone *int340x_zone; 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 int3403_cdev {
struct thermal_cooling_device *cdev; struct thermal_cooling_device *cdev;
unsigned long max_state; unsigned long max_state;
......
...@@ -39,13 +39,14 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone, ...@@ -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, 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); 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; acpi_status status;
if (trip > 9) if (trip_index > 9)
return -EINVAL; return -EINVAL;
status = acpi_execute_simple_method(d->adev->handle, name, status = acpi_execute_simple_method(d->adev->handle, name,
...@@ -62,16 +63,6 @@ static void int340x_thermal_critical(struct thermal_zone_device *zone) ...@@ -62,16 +63,6 @@ static void int340x_thermal_critical(struct thermal_zone_device *zone)
thermal_zone_device_type(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, static int int340x_thermal_read_trips(struct acpi_device *zone_adev,
struct thermal_trip *zone_trips, struct thermal_trip *zone_trips,
int trip_cnt) int trip_cnt)
...@@ -106,7 +97,7 @@ static int int340x_thermal_read_trips(struct acpi_device *zone_adev, ...@@ -106,7 +97,7 @@ static int int340x_thermal_read_trips(struct acpi_device *zone_adev,
break; break;
zone_trips[trip_cnt].type = THERMAL_TRIP_ACTIVE; 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++; trip_cnt++;
} }
...@@ -154,6 +145,7 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, ...@@ -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].type = THERMAL_TRIP_PASSIVE;
zone_trips[i].temperature = THERMAL_TEMP_INVALID; zone_trips[i].temperature = THERMAL_TEMP_INVALID;
zone_trips[i].flags |= THERMAL_TRIP_FLAG_RW_TEMP; 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); 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) ...@@ -224,7 +216,7 @@ static int int340x_update_one_trip(struct thermal_trip *trip, void *arg)
break; break;
case THERMAL_TRIP_ACTIVE: case THERMAL_TRIP_ACTIVE:
err = thermal_acpi_active_trip_temp(zone_adev, err = thermal_acpi_active_trip_temp(zone_adev,
trip_priv_to_int(trip), THERMAL_TRIP_PRIV_TO_INT(trip->priv),
&temp); &temp);
break; break;
default: default:
......
...@@ -440,7 +440,8 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device * ...@@ -440,7 +440,8 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *
proc_thermal_rapl_remove(); proc_thermal_rapl_remove();
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR || 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); proc_thermal_rfim_remove(pdev);
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR)
......
...@@ -65,6 +65,7 @@ struct rapl_mmio_regs { ...@@ -65,6 +65,7 @@ struct rapl_mmio_regs {
#define PROC_THERMAL_FEATURE_DLVR 0x10 #define PROC_THERMAL_FEATURE_DLVR 0x10
#define PROC_THERMAL_FEATURE_WT_HINT 0x20 #define PROC_THERMAL_FEATURE_WT_HINT 0x20
#define PROC_THERMAL_FEATURE_POWER_FLOOR 0x40 #define PROC_THERMAL_FEATURE_POWER_FLOOR 0x40
#define PROC_THERMAL_FEATURE_MSI_SUPPORT 0x80
#if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) #if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL)
int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 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[] = { ...@@ -63,6 +63,18 @@ static struct proc_thermal_mmio_info proc_thermal_mmio_info[] = {
{ PROC_THERMAL_MMIO_INT_STATUS_1, 0x7200, 8, 0x01 }, { 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 #define B0D4_THERMAL_NOTIFY_DELAY 1000
static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY; 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) ...@@ -146,22 +158,41 @@ static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid)
return IRQ_HANDLED; 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) static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
{ {
struct proc_thermal_pci *pci_info = devid; struct proc_thermal_pci *pci_info = devid;
struct proc_thermal_device *proc_priv; struct proc_thermal_device *proc_priv;
int ret = IRQ_NONE; int ret = IRQ_NONE, msi_id;
u32 status; u32 status;
proc_priv = pci_info->proc_priv; 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_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; ret = IRQ_WAKE_THREAD;
} }
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) { 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; ret = IRQ_WAKE_THREAD;
} }
...@@ -171,7 +202,7 @@ static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) ...@@ -171,7 +202,7 @@ static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
* interrupt before scheduling work function for thermal threshold. * interrupt before scheduling work function for thermal threshold.
*/ */
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); 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 */ /* Disable enable interrupt flag */
proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
pkg_thermal_schedule_work(&pci_info->work); pkg_thermal_schedule_work(&pci_info->work);
...@@ -194,7 +225,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) ...@@ -194,7 +225,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
return 0; 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); struct proc_thermal_pci *pci_info = thermal_zone_device_priv(tzd);
int tjmax, _temp; int tjmax, _temp;
...@@ -244,6 +276,45 @@ static struct thermal_zone_params tzone_params = { ...@@ -244,6 +276,45 @@ static struct thermal_zone_params tzone_params = {
.no_hwmon = true, .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) static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
struct proc_thermal_device *proc_priv; struct proc_thermal_device *proc_priv;
...@@ -253,7 +324,6 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ ...@@ -253,7 +324,6 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
.flags = THERMAL_TRIP_FLAG_RW_TEMP, .flags = THERMAL_TRIP_FLAG_RW_TEMP,
}; };
int irq_flag = 0, irq, ret; int irq_flag = 0, irq, ret;
bool msi_irq = false;
proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
if (!proc_priv) if (!proc_priv)
...@@ -299,27 +369,24 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ ...@@ -299,27 +369,24 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
goto err_del_legacy; goto err_del_legacy;
} }
if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) { if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MSI_SUPPORT)
/* request and enable interrupt */ use_msi = true;
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;
}
irq = pci_irq_vector(pdev, 0); if (use_msi) {
msi_irq = true; ret = proc_thermal_setup_msi(pdev, pci_info);
if (ret)
goto err_ret_tzone;
} else { } else {
irq_flag = IRQF_SHARED; irq_flag = IRQF_SHARED;
irq = pdev->irq; irq = pdev->irq;
}
ret = devm_request_threaded_irq(&pdev->dev, irq, ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler,
proc_thermal_irq_handler, proc_thermal_irq_thread_handler, proc_thermal_irq_thread_handler, irq_flag,
irq_flag, KBUILD_MODNAME, pci_info); KBUILD_MODNAME, pci_info);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq); 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); ret = thermal_zone_device_enable(pci_info->tzone);
...@@ -352,9 +419,6 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev) ...@@ -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_THRES_0, 0);
proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_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); thermal_zone_device_unregister(pci_info->tzone);
proc_thermal_mmio_remove(pdev, pci_info->proc_priv); proc_thermal_mmio_remove(pdev, pci_info->proc_priv);
if (!pci_info->no_legacy) if (!pci_info->no_legacy)
...@@ -408,7 +472,9 @@ static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, ...@@ -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[] = { static const struct pci_device_id proc_thermal_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL |
PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, 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 | { 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_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR |
PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) }, PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) },
......
...@@ -19,6 +19,12 @@ struct mmio_reg { ...@@ -19,6 +19,12 @@ struct mmio_reg {
u16 shift; u16 shift;
}; };
struct mapping_table {
const char *attr_name;
const u32 value;
const char *mapped_str;
};
/* These will represent sysfs attribute names */ /* These will represent sysfs attribute names */
static const char * const fivr_strings[] = { static const char * const fivr_strings[] = {
"vco_ref_code_lo", "vco_ref_code_lo",
...@@ -62,6 +68,78 @@ static const struct mmio_reg dlvr_mmio_regs[] = { ...@@ -62,6 +68,78 @@ static const struct mmio_reg dlvr_mmio_regs[] = {
{ 1, 0x15A10, 1, 0x1, 16}, /* dlvr_pll_busy */ { 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 */ /* These will represent sysfs attribute names */
static const char * const dvfs_strings[] = { static const char * const dvfs_strings[] = {
"rfi_restriction_run_busy", "rfi_restriction_run_busy",
...@@ -93,12 +171,14 @@ static ssize_t suffix##_show(struct device *dev,\ ...@@ -93,12 +171,14 @@ static ssize_t suffix##_show(struct device *dev,\
struct device_attribute *attr,\ struct device_attribute *attr,\
char *buf)\ char *buf)\
{\ {\
const struct mapping_table *mapping = NULL;\
struct proc_thermal_device *proc_priv;\ struct proc_thermal_device *proc_priv;\
struct pci_dev *pdev = to_pci_dev(dev);\ struct pci_dev *pdev = to_pci_dev(dev);\
const struct mmio_reg *mmio_regs;\ const struct mmio_reg *mmio_regs;\
const char **match_strs;\ const char **match_strs;\
int ret, err;\
u32 reg_val;\ u32 reg_val;\
int ret;\ char *str;\
\ \
proc_priv = pci_get_drvdata(pdev);\ proc_priv = pci_get_drvdata(pdev);\
if (table == 1) {\ if (table == 1) {\
...@@ -106,7 +186,12 @@ static ssize_t suffix##_show(struct device *dev,\ ...@@ -106,7 +186,12 @@ static ssize_t suffix##_show(struct device *dev,\
mmio_regs = adl_dvfs_mmio_regs;\ mmio_regs = adl_dvfs_mmio_regs;\
} else if (table == 2) { \ } else if (table == 2) { \
match_strs = (const char **)dlvr_strings;\ 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;\ mmio_regs = dlvr_mmio_regs;\
} \
} else {\ } else {\
match_strs = (const char **)fivr_strings;\ match_strs = (const char **)fivr_strings;\
mmio_regs = tgl_fivr_mmio_regs;\ mmio_regs = tgl_fivr_mmio_regs;\
...@@ -116,7 +201,12 @@ static ssize_t suffix##_show(struct device *dev,\ ...@@ -116,7 +201,12 @@ static ssize_t suffix##_show(struct device *dev,\
return ret;\ return ret;\
reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\ reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\ 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 sprintf(buf, "%u\n", ret);\
return err;\
} }
#define RFIM_STORE(suffix, table)\ #define RFIM_STORE(suffix, table)\
...@@ -124,6 +214,7 @@ static ssize_t suffix##_store(struct device *dev,\ ...@@ -124,6 +214,7 @@ static ssize_t suffix##_store(struct device *dev,\
struct device_attribute *attr,\ struct device_attribute *attr,\
const char *buf, size_t count)\ const char *buf, size_t count)\
{\ {\
const struct mapping_table *mapping = NULL;\
struct proc_thermal_device *proc_priv;\ struct proc_thermal_device *proc_priv;\
struct pci_dev *pdev = to_pci_dev(dev);\ struct pci_dev *pdev = to_pci_dev(dev);\
unsigned int input;\ unsigned int input;\
...@@ -139,7 +230,12 @@ static ssize_t suffix##_store(struct device *dev,\ ...@@ -139,7 +230,12 @@ static ssize_t suffix##_store(struct device *dev,\
mmio_regs = adl_dvfs_mmio_regs;\ mmio_regs = adl_dvfs_mmio_regs;\
} else if (table == 2) { \ } else if (table == 2) { \
match_strs = (const char **)dlvr_strings;\ 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;\ mmio_regs = dlvr_mmio_regs;\
} \
} else {\ } else {\
match_strs = (const char **)fivr_strings;\ match_strs = (const char **)fivr_strings;\
mmio_regs = tgl_fivr_mmio_regs;\ mmio_regs = tgl_fivr_mmio_regs;\
...@@ -150,9 +246,14 @@ static ssize_t suffix##_store(struct device *dev,\ ...@@ -150,9 +246,14 @@ static ssize_t suffix##_store(struct device *dev,\
return ret;\ return ret;\
if (mmio_regs[ret].read_only)\ if (mmio_regs[ret].read_only)\
return -EPERM;\ 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);\ err = kstrtouint(buf, 10, &input);\
if (err)\ if (err)\
return err;\ return err;\
} \
mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\ 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 = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
reg_val &= ~mask;\ reg_val &= ~mask;\
......
...@@ -401,10 +401,10 @@ static void hfi_disable(void) ...@@ -401,10 +401,10 @@ static void hfi_disable(void)
* intel_hfi_online() - Enable HFI on @cpu * intel_hfi_online() - Enable HFI on @cpu
* @cpu: CPU in which the HFI will be enabled * @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 * Enable the HFI to be used in @cpu. The HFI is enabled at the package
* level. The first CPU in the die/package to come online does the full HFI * level. The first CPU in the package to come online does the full HFI
* initialization. Subsequent CPUs will just link themselves to the 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 * 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 * 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) ...@@ -414,31 +414,31 @@ void intel_hfi_online(unsigned int cpu)
{ {
struct hfi_instance *hfi_instance; struct hfi_instance *hfi_instance;
struct hfi_cpu_info *info; struct hfi_cpu_info *info;
u16 die_id; u16 pkg_id;
/* Nothing to do if hfi_instances are missing. */ /* Nothing to do if hfi_instances are missing. */
if (!hfi_instances) if (!hfi_instances)
return; 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. * matter whether the instance has been initialized.
*/ */
info = &per_cpu(hfi_cpu_info, cpu); 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; hfi_instance = info->hfi_instance;
if (!hfi_instance) { if (!hfi_instance) {
if (die_id >= max_hfi_instances) if (pkg_id >= max_hfi_instances)
return; return;
hfi_instance = &hfi_instances[die_id]; hfi_instance = &hfi_instances[pkg_id];
info->hfi_instance = hfi_instance; info->hfi_instance = hfi_instance;
} }
init_hfi_cpu_index(info); 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 * 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 * do is to add @cpu to this instance's cpumask and enable the instance
* if needed. * if needed.
...@@ -504,7 +504,7 @@ void intel_hfi_online(unsigned int cpu) ...@@ -504,7 +504,7 @@ void intel_hfi_online(unsigned int cpu)
* *
* On some processors, hardware remembers previous programming settings even * On some processors, hardware remembers previous programming settings even
* after being reprogrammed. Thus, keep HFI enabled even if all CPUs in the * 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) void intel_hfi_offline(unsigned int cpu)
{ {
...@@ -674,9 +674,13 @@ void __init intel_hfi_init(void) ...@@ -674,9 +674,13 @@ void __init intel_hfi_init(void)
if (hfi_parse_features()) if (hfi_parse_features())
return; return;
/* There is one HFI instance per die/package. */ /*
max_hfi_instances = topology_max_packages() * * Note: HFI resources are managed at the physical package scope.
topology_max_dies_per_package(); * 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 * This allocation may fail. CPU hotplug callbacks must check
......
...@@ -298,6 +298,11 @@ static int intel_pch_thermal_suspend_noirq(struct device *device) ...@@ -298,6 +298,11 @@ static int intel_pch_thermal_suspend_noirq(struct device *device)
/* Get the PCH current temperature value */ /* Get the PCH current temperature value */
pch_cur_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP)); 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 * If current PCH temperature is higher than configured PCH threshold
* value, run some delay loop with sleep to let the current temperature * value, run some delay loop with sleep to let the current temperature
......
...@@ -195,7 +195,7 @@ static int get_trip_temp(int trip) ...@@ -195,7 +195,7 @@ static int get_trip_temp(int trip)
} }
static int update_trip_temp(struct soc_sensor_entry *aux_entry, static int update_trip_temp(struct soc_sensor_entry *aux_entry,
int trip, int temp) int trip_index, int temp)
{ {
u32 out; u32 out;
u32 temp_out; u32 temp_out;
...@@ -230,9 +230,9 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry, ...@@ -230,9 +230,9 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry,
*/ */
temp_out = temp + QRK_DTS_TEMP_BASE; temp_out = temp + QRK_DTS_TEMP_BASE;
out = (store_ptps & ~(QRK_DTS_MASK_TP_THRES << 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) << 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, ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
QRK_DTS_REG_OFFSET_PTPS, out); QRK_DTS_REG_OFFSET_PTPS, out);
...@@ -242,10 +242,26 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry, ...@@ -242,10 +242,26 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry,
return ret; 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) 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, 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, ...@@ -129,18 +129,20 @@ static int update_trip_temp(struct intel_soc_dts_sensors *sensors,
return status; 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) int temp)
{ {
struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd); struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
struct intel_soc_dts_sensors *sensors = dts->sensors; struct intel_soc_dts_sensors *sensors = dts->sensors;
unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
int status; int status;
if (temp > sensors->tj_max) if (temp > sensors->tj_max)
return -EINVAL; return -EINVAL;
mutex_lock(&sensors->dts_update_lock); 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); mutex_unlock(&sensors->dts_update_lock);
return status; return status;
...@@ -293,11 +295,12 @@ static void dts_trips_reset(struct intel_soc_dts_sensors *sensors, int dts_index ...@@ -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, 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->type = type;
trip->flags = flags; trip->flags = flags;
trip->temperature = temp; trip->temperature = temp;
trip->priv = THERMAL_INT_TO_TRIP_PRIV(index);
} }
struct intel_soc_dts_sensors * struct intel_soc_dts_sensors *
...@@ -332,7 +335,7 @@ intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type, ...@@ -332,7 +335,7 @@ intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type,
sensors->soc_dts[i].sensors = sensors; sensors->soc_dts[i].sensors = sensors;
set_trip(&trips[i][0], THERMAL_TRIP_PASSIVE, 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); ret = update_trip_temp(sensors, 0, 0);
if (ret) if (ret)
...@@ -340,10 +343,10 @@ intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type, ...@@ -340,10 +343,10 @@ intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type,
if (critical_trip) { if (critical_trip) {
temp = sensors->tj_max - crit_offset; 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 { } else {
set_trip(&trips[i][1], THERMAL_TRIP_PASSIVE, set_trip(&trips[i][1], THERMAL_TRIP_PASSIVE,
THERMAL_TRIP_FLAG_RW_TEMP, 0); THERMAL_TRIP_FLAG_RW_TEMP, 0, 1);
temp = 0; temp = 0;
} }
......
...@@ -36,7 +36,7 @@ static irqreturn_t soc_irq_thread_fn(int irq, void *dev_data) ...@@ -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[] = { 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); MODULE_DEVICE_TABLE(x86cpu, soc_thermal_ids);
......
...@@ -6,8 +6,170 @@ ...@@ -6,8 +6,170 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/intel_tcc.h> #include <linux/intel_tcc.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <asm/msr.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 * intel_tcc_get_tjmax() - returns the default TCC activation Temperature
* @cpu: cpu that the MSR should be run on, nagative value means any cpu. * @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) ...@@ -56,7 +218,7 @@ int intel_tcc_get_offset(int cpu)
if (err) if (err)
return 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); EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, INTEL_TCC);
...@@ -76,7 +238,10 @@ int intel_tcc_set_offset(int cpu, int offset) ...@@ -76,7 +238,10 @@ int intel_tcc_set_offset(int cpu, int offset)
u32 low, high; u32 low, high;
int err; 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; return -EINVAL;
if (cpu < 0) if (cpu < 0)
...@@ -90,7 +255,7 @@ int intel_tcc_set_offset(int cpu, int offset) ...@@ -90,7 +255,7 @@ int intel_tcc_set_offset(int cpu, int offset)
if (low & BIT(31)) if (low & BIT(31))
return -EPERM; return -EPERM;
low &= ~(0x3f << 24); low &= ~(intel_tcc_temp_masks.tcc_offset << 24);
low |= offset << 24; low |= offset << 24;
if (cpu < 0) if (cpu < 0)
...@@ -113,8 +278,8 @@ EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC); ...@@ -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) 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 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS;
u32 low, high, mask;
int tjmax, err; int tjmax, err;
tjmax = intel_tcc_get_tjmax(cpu); tjmax = intel_tcc_get_tjmax(cpu);
...@@ -132,7 +297,9 @@ int intel_tcc_get_temp(int cpu, int *temp, bool pkg) ...@@ -132,7 +297,9 @@ int intel_tcc_get_temp(int cpu, int *temp, bool pkg)
if (!(low & BIT(31))) if (!(low & BIT(31)))
return -ENODATA; return -ENODATA;
*temp = tjmax - ((low >> 16) & 0x7f); mask = get_temp_mask(pkg);
*temp = tjmax - ((low >> 16) & mask);
return 0; return 0;
} }
......
...@@ -20,7 +20,7 @@ static struct thermal_cooling_device *tcc_cdev; ...@@ -20,7 +20,7 @@ static struct thermal_cooling_device *tcc_cdev;
static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long
*state) *state)
{ {
*state = 0x3f; *state = intel_tcc_get_offset_mask();
return 0; return 0;
} }
...@@ -49,21 +49,21 @@ static const struct thermal_cooling_device_ops tcc_cooling_ops = { ...@@ -49,21 +49,21 @@ static const struct thermal_cooling_device_ops tcc_cooling_ops = {
}; };
static const struct x86_cpu_id tcc_ids[] __initconst = { static const struct x86_cpu_id tcc_ids[] __initconst = {
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, NULL), X86_MATCH_VFM(INTEL_SKYLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, NULL), X86_MATCH_VFM(INTEL_SKYLAKE_L, NULL),
X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, NULL), X86_MATCH_VFM(INTEL_KABYLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, NULL), X86_MATCH_VFM(INTEL_KABYLAKE_L, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE, NULL), X86_MATCH_VFM(INTEL_ICELAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, NULL), X86_MATCH_VFM(INTEL_ICELAKE_L, NULL),
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, NULL), X86_MATCH_VFM(INTEL_TIGERLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL), X86_MATCH_VFM(INTEL_TIGERLAKE_L, NULL),
X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, NULL), X86_MATCH_VFM(INTEL_COMETLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL), X86_MATCH_VFM(INTEL_ALDERLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL), X86_MATCH_VFM(INTEL_ALDERLAKE_L, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT, NULL), X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, NULL),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL), X86_MATCH_VFM(INTEL_RAPTORLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL), X86_MATCH_VFM(INTEL_RAPTORLAKE_P, NULL),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, 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) ...@@ -119,9 +119,11 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
} }
static int 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); 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; u32 l, h, mask, shift, intr;
int tj_max, val, ret; int tj_max, val, ret;
...@@ -132,7 +134,7 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) ...@@ -132,7 +134,7 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
val = (tj_max - temp)/1000; 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; return -EINVAL;
ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, 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) ...@@ -140,7 +142,7 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (trip) { if (trip_index) {
mask = THERM_MASK_THRESHOLD1; mask = THERM_MASK_THRESHOLD1;
shift = THERM_SHIFT_THRESHOLD1; shift = THERM_SHIFT_THRESHOLD1;
intr = THERM_INT_THRESHOLD1_ENABLE; intr = THERM_INT_THRESHOLD1_ENABLE;
...@@ -296,6 +298,7 @@ static int pkg_temp_thermal_trips_init(int cpu, int tj_max, ...@@ -296,6 +298,7 @@ static int pkg_temp_thermal_trips_init(int cpu, int tj_max,
trips[i].type = THERMAL_TRIP_PASSIVE; trips[i].type = THERMAL_TRIP_PASSIVE;
trips[i].flags |= THERMAL_TRIP_FLAG_RW_TEMP; 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", pr_debug("%s: cpu=%d, trip=%d, temp=%d\n",
__func__, cpu, i, trips[i].temperature); __func__, cpu, i, trips[i].temperature);
......
...@@ -178,6 +178,7 @@ struct k3_j72xx_bandgap { ...@@ -178,6 +178,7 @@ struct k3_j72xx_bandgap {
void __iomem *base; void __iomem *base;
void __iomem *cfg2_base; void __iomem *cfg2_base;
struct k3_thermal_data *ts_data[K3_VTM_MAX_NUM_TS]; struct k3_thermal_data *ts_data[K3_VTM_MAX_NUM_TS];
int cnt;
}; };
/* common data structures */ /* common data structures */
...@@ -338,24 +339,52 @@ static void print_look_up_table(struct device *dev, int *ref_table) ...@@ -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]); 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 { struct k3_j72xx_bandgap_data {
const bool has_errata_i2128; const bool has_errata_i2128;
}; };
static int k3_j72xx_bandgap_probe(struct platform_device *pdev) static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
{ {
int ret = 0, cnt, val, id; const struct k3_j72xx_bandgap_data *driver_data;
int high_max, low_temp; struct thermal_zone_device *ti_thermal;
struct resource *res;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
bool workaround_needed = false;
struct k3_j72xx_bandgap *bgp; struct k3_j72xx_bandgap *bgp;
struct k3_thermal_data *data; 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; struct err_values err_vals;
void __iomem *fuse_base; void __iomem *fuse_base;
int ret = 0, val, id;
struct resource *res;
int *ref_table;
const s64 golden_factors[] = { const s64 golden_factors[] = {
-490019999999999936, -490019999999999936,
...@@ -422,10 +451,10 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev) ...@@ -422,10 +451,10 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
/* Get the sensor count in the VTM */ /* Get the sensor count in the VTM */
val = readl(bgp->base + K3_VTM_DEVINFO_PWR0_OFFSET); val = readl(bgp->base + K3_VTM_DEVINFO_PWR0_OFFSET);
cnt = val & K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK; bgp->cnt = val & K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK;
cnt >>= __ffs(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) { if (!data) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_alloc; goto err_alloc;
...@@ -449,8 +478,8 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev) ...@@ -449,8 +478,8 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
else else
init_table(3, ref_table, pvt_wa_factors); init_table(3, ref_table, pvt_wa_factors);
/* Register the thermal sensors */ /* Precompute the derived table & fill each thermal sensor struct */
for (id = 0; id < cnt; id++) { for (id = 0; id < bgp->cnt; id++) {
data[id].bgp = bgp; data[id].bgp = bgp;
data[id].ctrl_offset = K3_VTM_TMPSENS0_CTRL_OFFSET + id * 0x20; data[id].ctrl_offset = K3_VTM_TMPSENS0_CTRL_OFFSET + id * 0x20;
data[id].stat_offset = data[id].ctrl_offset + data[id].stat_offset = data[id].ctrl_offset +
...@@ -470,13 +499,13 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev) ...@@ -470,13 +499,13 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
else if (id == 0 && !workaround_needed) else if (id == 0 && !workaround_needed)
memcpy(derived_table, ref_table, TABLE_SIZE * 4); 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]; 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], ti_thermal = devm_thermal_of_zone_register(bgp->dev, id, &data[id],
&k3_of_thermal_ops); &k3_of_thermal_ops);
if (IS_ERR(ti_thermal)) { if (IS_ERR(ti_thermal)) {
...@@ -486,21 +515,7 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev) ...@@ -486,21 +515,7 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
} }
} }
/* platform_set_drvdata(pdev, bgp);
* 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);
print_look_up_table(dev, ref_table); print_look_up_table(dev, ref_table);
/* /*
...@@ -527,6 +542,35 @@ static void k3_j72xx_bandgap_remove(struct platform_device *pdev) ...@@ -527,6 +542,35 @@ static void k3_j72xx_bandgap_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); 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 = { static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j721e_data = {
.has_errata_i2128 = true, .has_errata_i2128 = true,
}; };
...@@ -554,6 +598,7 @@ static struct platform_driver k3_j72xx_bandgap_sensor_driver = { ...@@ -554,6 +598,7 @@ static struct platform_driver k3_j72xx_bandgap_sensor_driver = {
.driver = { .driver = {
.name = "k3-j72xx-soc-thermal", .name = "k3-j72xx-soc-thermal",
.of_match_table = of_k3_j72xx_bandgap_match, .of_match_table = of_k3_j72xx_bandgap_match,
.pm = pm_sleep_ptr(&k3_j72xx_bandgap_pm_ops),
}, },
}; };
......
...@@ -128,6 +128,7 @@ struct lvts_data { ...@@ -128,6 +128,7 @@ struct lvts_data {
int temp_factor; int temp_factor;
int temp_offset; int temp_offset;
int gt_calib_bit_offset; int gt_calib_bit_offset;
unsigned int def_calibration;
}; };
struct lvts_sensor { struct lvts_sensor {
...@@ -689,6 +690,10 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl ...@@ -689,6 +690,10 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl
size_t calib_len) size_t calib_len)
{ {
int i; 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) { lvts_for_each_valid_sensor(i, lvts_ctrl_data) {
const struct lvts_sensor_data *sensor = const struct lvts_sensor_data *sensor =
...@@ -699,10 +704,17 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl ...@@ -699,10 +704,17 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl
sensor->cal_offsets[2] >= calib_len) sensor->cal_offsets[2] >= calib_len)
return -EINVAL; return -EINVAL;
if (gt) {
lvts_ctrl->calibration[i] = lvts_ctrl->calibration[i] =
(efuse_calibration[sensor->cal_offsets[0]] << 0) + (efuse_calibration[sensor->cal_offsets[0]] << 0) +
(efuse_calibration[sensor->cal_offsets[1]] << 8) + (efuse_calibration[sensor->cal_offsets[1]] << 8) +
(efuse_calibration[sensor->cal_offsets[2]] << 16); (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; return 0;
...@@ -770,14 +782,13 @@ static int lvts_golden_temp_init(struct device *dev, u8 *calib, ...@@ -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; gt = (((u32 *)calib)[0] >> lvts_data->gt_calib_bit_offset) & 0xff;
/* A zero value for gt means that device has invalid efuse data */ /* A zero value for gt means that device has invalid efuse data */
if (!gt) if (gt && gt < LVTS_GOLDEN_TEMP_MAX)
return -ENODATA;
if (gt < LVTS_GOLDEN_TEMP_MAX)
golden_temp = gt; golden_temp = gt;
golden_temp_offset = golden_temp * 500 + lvts_data->temp_offset; golden_temp_offset = golden_temp * 500 + lvts_data->temp_offset;
dev_info(dev, "%sgolden temp=%d\n", gt ? "" : "fake ", golden_temp);
return 0; return 0;
} }
...@@ -1440,7 +1451,7 @@ static const struct lvts_ctrl_data mt8186_lvts_data_ctrl[] = { ...@@ -1440,7 +1451,7 @@ static const struct lvts_ctrl_data mt8186_lvts_data_ctrl[] = {
.cal_offsets = { 29, 30, 31 } }, .cal_offsets = { 29, 30, 31 } },
{ .dt_id = MT8186_ADSP, { .dt_id = MT8186_ADSP,
.cal_offsets = { 34, 35, 28 } }, .cal_offsets = { 34, 35, 28 } },
{ .dt_id = MT8186_MFG, { .dt_id = MT8186_GPU,
.cal_offsets = { 39, 32, 33 } } .cal_offsets = { 39, 32, 33 } }
}, },
VALID_SENSOR_MAP(1, 1, 1, 0), VALID_SENSOR_MAP(1, 1, 1, 0),
...@@ -1488,11 +1499,11 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = { ...@@ -1488,11 +1499,11 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = {
}, },
{ {
.lvts_sensor = { .lvts_sensor = {
{ .dt_id = MT8188_AP_GPU1, { .dt_id = MT8188_AP_GPU0,
.cal_offsets = { 43, 44, 45 } }, .cal_offsets = { 43, 44, 45 } },
{ .dt_id = MT8188_AP_GPU2, { .dt_id = MT8188_AP_GPU1,
.cal_offsets = { 46, 47, 48 } }, .cal_offsets = { 46, 47, 48 } },
{ .dt_id = MT8188_AP_SOC1, { .dt_id = MT8188_AP_ADSP,
.cal_offsets = { 49, 50, 51 } }, .cal_offsets = { 49, 50, 51 } },
}, },
VALID_SENSOR_MAP(1, 1, 1, 0), VALID_SENSOR_MAP(1, 1, 1, 0),
...@@ -1500,9 +1511,9 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = { ...@@ -1500,9 +1511,9 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = {
}, },
{ {
.lvts_sensor = { .lvts_sensor = {
{ .dt_id = MT8188_AP_SOC2, { .dt_id = MT8188_AP_VDO,
.cal_offsets = { 52, 53, 54 } }, .cal_offsets = { 52, 53, 54 } },
{ .dt_id = MT8188_AP_SOC3, { .dt_id = MT8188_AP_INFRA,
.cal_offsets = { 55, 56, 57 } }, .cal_offsets = { 55, 56, 57 } },
}, },
VALID_SENSOR_MAP(1, 1, 0, 0), VALID_SENSOR_MAP(1, 1, 0, 0),
...@@ -1701,6 +1712,7 @@ static const struct lvts_data mt8186_lvts_data = { ...@@ -1701,6 +1712,7 @@ static const struct lvts_data mt8186_lvts_data = {
.temp_factor = LVTS_COEFF_A_MT7988, .temp_factor = LVTS_COEFF_A_MT7988,
.temp_offset = LVTS_COEFF_B_MT7988, .temp_offset = LVTS_COEFF_B_MT7988,
.gt_calib_bit_offset = 24, .gt_calib_bit_offset = 24,
.def_calibration = 19000,
}; };
static const struct lvts_data mt8188_lvts_mcu_data = { static const struct lvts_data mt8188_lvts_mcu_data = {
...@@ -1709,6 +1721,7 @@ 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_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195, .temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 20, .gt_calib_bit_offset = 20,
.def_calibration = 35000,
}; };
static const struct lvts_data mt8188_lvts_ap_data = { static const struct lvts_data mt8188_lvts_ap_data = {
...@@ -1717,6 +1730,7 @@ 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_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195, .temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 20, .gt_calib_bit_offset = 20,
.def_calibration = 35000,
}; };
static const struct lvts_data mt8192_lvts_mcu_data = { static const struct lvts_data mt8192_lvts_mcu_data = {
...@@ -1725,6 +1739,7 @@ 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_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195, .temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 24, .gt_calib_bit_offset = 24,
.def_calibration = 35000,
}; };
static const struct lvts_data mt8192_lvts_ap_data = { static const struct lvts_data mt8192_lvts_ap_data = {
...@@ -1733,6 +1748,7 @@ 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_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195, .temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 24, .gt_calib_bit_offset = 24,
.def_calibration = 35000,
}; };
static const struct lvts_data mt8195_lvts_mcu_data = { static const struct lvts_data mt8195_lvts_mcu_data = {
...@@ -1741,6 +1757,7 @@ 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_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195, .temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 24, .gt_calib_bit_offset = 24,
.def_calibration = 35000,
}; };
static const struct lvts_data mt8195_lvts_ap_data = { static const struct lvts_data mt8195_lvts_ap_data = {
...@@ -1749,6 +1766,7 @@ 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_factor = LVTS_COEFF_A_MT8195,
.temp_offset = LVTS_COEFF_B_MT8195, .temp_offset = LVTS_COEFF_B_MT8195,
.gt_calib_bit_offset = 24, .gt_calib_bit_offset = 24,
.def_calibration = 35000,
}; };
static const struct of_device_id lvts_of_match[] = { 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, ...@@ -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, channel->iio = devm_fwnode_iio_channel_get_by_name(adc_tm->dev,
of_fwnode_handle(node), NULL); of_fwnode_handle(node), NULL);
if (IS_ERR(channel->iio)) { if (IS_ERR(channel->iio))
ret = PTR_ERR(channel->iio); return dev_err_probe(dev, PTR_ERR(channel->iio), "%s: error getting channel\n",
if (ret != -EPROBE_DEFER) name);
dev_err(dev, "%s: error getting channel: %d\n", name, ret);
return ret;
}
ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2); ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2);
if (!ret) { if (!ret) {
......
...@@ -261,17 +261,13 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip, ...@@ -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); 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 qpnp_tm_chip *chip = thermal_zone_device_priv(tz);
struct thermal_trip trip;
int ret; int ret;
ret = __thermal_zone_get_trip(chip->tz_dev, trip_id, &trip); if (trip->type != THERMAL_TRIP_CRITICAL)
if (ret)
return ret;
if (trip.type != THERMAL_TRIP_CRITICAL)
return 0; return 0;
mutex_lock(&chip->lock); mutex_lock(&chip->lock);
......
...@@ -1336,11 +1336,9 @@ static int tsens_probe(struct platform_device *pdev) ...@@ -1336,11 +1336,9 @@ static int tsens_probe(struct platform_device *pdev)
if (priv->ops->calibrate) { if (priv->ops->calibrate) {
ret = priv->ops->calibrate(priv); ret = priv->ops->calibrate(priv);
if (ret < 0) { if (ret < 0)
if (ret != -EPROBE_DEFER) return dev_err_probe(dev, ret, "%s: calibration failed\n",
dev_err(dev, "%s: calibration failed\n", __func__); __func__);
return ret;
}
} }
ret = tsens_register(priv); 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 @@ ...@@ -16,7 +16,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/thermal.h> #include <linux/thermal.h>
#include "thermal_hwmon.h" #include "../thermal_hwmon.h"
/* Register offsets */ /* Register offsets */
#define REG_GEN3_IRQSTR 0x04 #define REG_GEN3_IRQSTR 0x04
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/thermal.h> #include <linux/thermal.h>
#include "thermal_hwmon.h" #include "../thermal_hwmon.h"
#define IDLE_INTERVAL 5000 #define IDLE_INTERVAL 5000
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <linux/thermal.h> #include <linux/thermal.h>
#include <linux/units.h> #include <linux/units.h>
#include "thermal_hwmon.h" #include "../thermal_hwmon.h"
#define CTEMP_MASK 0xFFF #define CTEMP_MASK 0xFFF
......
...@@ -1004,11 +1004,11 @@ static const struct thermal_zone_device_ops exynos_sensor_ops = { ...@@ -1004,11 +1004,11 @@ static const struct thermal_zone_device_ops exynos_sensor_ops = {
static int exynos_tmu_probe(struct platform_device *pdev) static int exynos_tmu_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev;
struct exynos_tmu_data *data; struct exynos_tmu_data *data;
int ret; int ret;
data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data), data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
...@@ -1020,7 +1020,7 @@ static int exynos_tmu_probe(struct platform_device *pdev) ...@@ -1020,7 +1020,7 @@ static int exynos_tmu_probe(struct platform_device *pdev)
* TODO: Add regulator as an SOC feature, so that regulator enable * TODO: Add regulator as an SOC feature, so that regulator enable
* is a compulsory call. * is a compulsory call.
*/ */
ret = devm_regulator_get_enable_optional(&pdev->dev, "vtmu"); ret = devm_regulator_get_enable_optional(dev, "vtmu");
switch (ret) { switch (ret) {
case 0: case 0:
case -ENODEV: case -ENODEV:
...@@ -1028,8 +1028,7 @@ static int exynos_tmu_probe(struct platform_device *pdev) ...@@ -1028,8 +1028,7 @@ static int exynos_tmu_probe(struct platform_device *pdev)
case -EPROBE_DEFER: case -EPROBE_DEFER:
return -EPROBE_DEFER; return -EPROBE_DEFER;
default: default:
dev_err(&pdev->dev, "Failed to get enabled regulator: %d\n", dev_err(dev, "Failed to get enabled regulator: %d\n", ret);
ret);
return ret; return ret;
} }
...@@ -1037,44 +1036,40 @@ static int exynos_tmu_probe(struct platform_device *pdev) ...@@ -1037,44 +1036,40 @@ static int exynos_tmu_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
data->clk = devm_clk_get(&pdev->dev, "tmu_apbif"); data->clk = devm_clk_get(dev, "tmu_apbif");
if (IS_ERR(data->clk)) { if (IS_ERR(data->clk))
dev_err(&pdev->dev, "Failed to get clock\n"); return dev_err_probe(dev, PTR_ERR(data->clk), "Failed to get clock\n");
return PTR_ERR(data->clk);
}
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 (IS_ERR(data->clk_sec)) {
if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) { if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
dev_err(&pdev->dev, "Failed to get triminfo clock\n"); return dev_err_probe(dev, PTR_ERR(data->clk_sec),
return PTR_ERR(data->clk_sec); "Failed to get triminfo clock\n");
}
} else { } else {
ret = clk_prepare(data->clk_sec); ret = clk_prepare(data->clk_sec);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to get clock\n"); dev_err(dev, "Failed to get clock\n");
return ret; return ret;
} }
} }
ret = clk_prepare(data->clk); ret = clk_prepare(data->clk);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to get clock\n"); dev_err(dev, "Failed to get clock\n");
goto err_clk_sec; goto err_clk_sec;
} }
switch (data->soc) { switch (data->soc) {
case SOC_ARCH_EXYNOS5433: case SOC_ARCH_EXYNOS5433:
case SOC_ARCH_EXYNOS7: 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)) { if (IS_ERR(data->sclk)) {
dev_err(&pdev->dev, "Failed to get sclk\n"); ret = dev_err_probe(dev, PTR_ERR(data->sclk), "Failed to get sclk\n");
ret = PTR_ERR(data->sclk);
goto err_clk; goto err_clk;
} else { } else {
ret = clk_prepare_enable(data->sclk); ret = clk_prepare_enable(data->sclk);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to enable sclk\n"); dev_err(dev, "Failed to enable sclk\n");
goto err_clk; goto err_clk;
} }
} }
...@@ -1085,33 +1080,30 @@ static int exynos_tmu_probe(struct platform_device *pdev) ...@@ -1085,33 +1080,30 @@ static int exynos_tmu_probe(struct platform_device *pdev)
ret = exynos_tmu_initialize(pdev); ret = exynos_tmu_initialize(pdev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to initialize TMU\n"); dev_err(dev, "Failed to initialize TMU\n");
goto err_sclk; 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); &exynos_sensor_ops);
if (IS_ERR(data->tzd)) { if (IS_ERR(data->tzd)) {
ret = PTR_ERR(data->tzd); ret = dev_err_probe(dev, PTR_ERR(data->tzd), "Failed to register sensor\n");
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "Failed to register sensor: %d\n",
ret);
goto err_sclk; goto err_sclk;
} }
ret = exynos_thermal_zone_configure(pdev); ret = exynos_thermal_zone_configure(pdev);
if (ret) { 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; 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, exynos_tmu_threaded_irq,
IRQF_TRIGGER_RISING IRQF_TRIGGER_RISING
| IRQF_SHARED | IRQF_ONESHOT, | IRQF_SHARED | IRQF_ONESHOT,
dev_name(&pdev->dev), data); dev_name(dev), data);
if (ret) { 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; goto err_sclk;
} }
......
...@@ -142,15 +142,6 @@ static const struct st_thermal_sensor_ops st_mmap_sensor_ops = { ...@@ -142,15 +142,6 @@ static const struct st_thermal_sensor_ops st_mmap_sensor_ops = {
.enable_irq = st_mmap_enable_irq, .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 */ /* Compatible device data stih407 thermal sensor */
static const struct st_thermal_compat_data st_407_cdata = { static const struct st_thermal_compat_data st_407_cdata = {
.reg_fields = st_mmap_thermal_regfields, .reg_fields = st_mmap_thermal_regfields,
...@@ -161,7 +152,6 @@ static const struct st_thermal_compat_data st_407_cdata = { ...@@ -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[] = { 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 }, { .compatible = "st,stih407-thermal", .data = &st_407_cdata },
{ /* sentinel */ } { /* sentinel */ }
}; };
......
...@@ -582,23 +582,18 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id) ...@@ -582,23 +582,18 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id)
return temp; 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_thermctl_zone *zone = thermal_zone_device_priv(tz);
struct tegra_soctherm *ts = zone->ts; struct tegra_soctherm *ts = zone->ts;
struct thermal_trip trip;
const struct tegra_tsensor_group *sg = zone->sg; const struct tegra_tsensor_group *sg = zone->sg;
struct device *dev = zone->dev; struct device *dev = zone->dev;
int ret;
if (!tz) if (!tz)
return -EINVAL; return -EINVAL;
ret = __thermal_zone_get_trip(tz, trip_id, &trip); if (trip->type == THERMAL_TRIP_CRITICAL) {
if (ret)
return ret;
if (trip.type == THERMAL_TRIP_CRITICAL) {
/* /*
* If thermtrips property is set in DT, * If thermtrips property is set in DT,
* doesn't need to program critical type trip to HW, * 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 ...@@ -609,7 +604,7 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip
else else
return 0; return 0;
} else if (trip.type == THERMAL_TRIP_HOT) { } else if (trip->type == THERMAL_TRIP_HOT) {
int i; int i;
for (i = 0; i < THROTTLE_SIZE; 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 ...@@ -620,7 +615,7 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip
continue; continue;
cdev = ts->throt_cfgs[i].cdev; 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); stc = find_throttle_cfg_by_name(ts, cdev->type);
else else
continue; continue;
......
...@@ -117,44 +117,41 @@ static int gadc_thermal_read_linear_lookup_table(struct device *dev, ...@@ -117,44 +117,41 @@ static int gadc_thermal_read_linear_lookup_table(struct device *dev,
static int gadc_thermal_probe(struct platform_device *pdev) static int gadc_thermal_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev;
struct gadc_thermal_info *gti; struct gadc_thermal_info *gti;
int ret; int ret;
if (!pdev->dev.of_node) { if (!dev->of_node) {
dev_err(&pdev->dev, "Only DT based supported\n"); dev_err(dev, "Only DT based supported\n");
return -ENODEV; return -ENODEV;
} }
gti = devm_kzalloc(&pdev->dev, sizeof(*gti), GFP_KERNEL); gti = devm_kzalloc(dev, sizeof(*gti), GFP_KERNEL);
if (!gti) if (!gti)
return -ENOMEM; return -ENOMEM;
gti->channel = devm_iio_channel_get(&pdev->dev, "sensor-channel"); gti->channel = devm_iio_channel_get(dev, "sensor-channel");
if (IS_ERR(gti->channel)) { if (IS_ERR(gti->channel))
ret = PTR_ERR(gti->channel); return dev_err_probe(dev, PTR_ERR(gti->channel), "IIO channel not found\n");
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "IIO channel not found: %d\n", ret);
return ret;
}
ret = gadc_thermal_read_linear_lookup_table(&pdev->dev, gti); ret = gadc_thermal_read_linear_lookup_table(dev, gti);
if (ret < 0) if (ret < 0)
return ret; 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); &gadc_thermal_ops);
if (IS_ERR(gti->tz_dev)) { if (IS_ERR(gti->tz_dev)) {
ret = PTR_ERR(gti->tz_dev); ret = PTR_ERR(gti->tz_dev);
if (ret != -EPROBE_DEFER) if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, dev_err(dev,
"Thermal zone sensor register failed: %d\n", "Thermal zone sensor register failed: %d\n",
ret); ret);
return ret; return ret;
} }
devm_thermal_add_hwmon_sysfs(&pdev->dev, gti->tz_dev); devm_thermal_add_hwmon_sysfs(dev, gti->tz_dev);
return 0; return 0;
} }
......
...@@ -465,6 +465,9 @@ static void thermal_governor_trip_crossed(struct thermal_governor *governor, ...@@ -465,6 +465,9 @@ static void thermal_governor_trip_crossed(struct thermal_governor *governor,
const struct thermal_trip *trip, const struct thermal_trip *trip,
bool crossed_up) bool crossed_up)
{ {
if (trip->type == THERMAL_TRIP_HOT || trip->type == THERMAL_TRIP_CRITICAL)
return;
if (governor->trip_crossed) if (governor->trip_crossed)
governor->trip_crossed(tz, trip, crossed_up); governor->trip_crossed(tz, trip, crossed_up);
} }
...@@ -513,13 +516,13 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, ...@@ -513,13 +516,13 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
if (tz->temperature == THERMAL_TEMP_INVALID) if (tz->temperature == THERMAL_TEMP_INVALID)
goto monitor; goto monitor;
__thermal_zone_set_trips(tz);
tz->notify_event = event; tz->notify_event = event;
for_each_trip_desc(tz, td) for_each_trip_desc(tz, td)
handle_thermal_trip(tz, td, &way_up_list, &way_down_list); 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_sort(NULL, &way_up_list, thermal_trip_notify_cmp);
list_for_each_entry(td, &way_up_list, notify_list_node) list_for_each_entry(td, &way_up_list, notify_list_node)
thermal_trip_crossed(tz, &td->trip, governor, true); thermal_trip_crossed(tz, &td->trip, governor, true);
...@@ -1127,7 +1130,7 @@ static void thermal_cooling_device_release(struct device *dev, void *res) ...@@ -1127,7 +1130,7 @@ static void thermal_cooling_device_release(struct device *dev, void *res)
struct thermal_cooling_device * struct thermal_cooling_device *
devm_thermal_of_cooling_device_register(struct device *dev, devm_thermal_of_cooling_device_register(struct device *dev,
struct device_node *np, struct device_node *np,
char *type, void *devdata, const char *type, void *devdata,
const struct thermal_cooling_device_ops *ops) const struct thermal_cooling_device_ops *ops)
{ {
struct thermal_cooling_device **ptr, *tcd; struct thermal_cooling_device **ptr, *tcd;
...@@ -1354,7 +1357,8 @@ thermal_zone_device_register_with_trips(const char *type, ...@@ -1354,7 +1357,8 @@ thermal_zone_device_register_with_trips(const char *type,
int num_trips, void *devdata, int num_trips, void *devdata,
const struct thermal_zone_device_ops *ops, const struct thermal_zone_device_ops *ops,
const struct thermal_zone_params *tzp, 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; const struct thermal_trip *trip = trips;
struct thermal_zone_device *tz; struct thermal_zone_device *tz;
...@@ -1387,6 +1391,14 @@ thermal_zone_device_register_with_trips(const char *type, ...@@ -1387,6 +1391,14 @@ thermal_zone_device_register_with_trips(const char *type,
if (num_trips > 0 && !trips) if (num_trips > 0 && !trips)
return ERR_PTR(-EINVAL); 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) if (!thermal_class)
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
...@@ -1650,6 +1662,7 @@ static void thermal_zone_device_resume(struct work_struct *work) ...@@ -1650,6 +1662,7 @@ static void thermal_zone_device_resume(struct work_struct *work)
tz->suspended = false; tz->suspended = false;
thermal_debug_tz_resume(tz);
thermal_zone_device_init(tz); thermal_zone_device_init(tz);
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
......
...@@ -250,7 +250,9 @@ void thermal_governor_update_tz(struct thermal_zone_device *tz, ...@@ -250,7 +250,9 @@ void thermal_governor_update_tz(struct thermal_zone_device *tz,
#define trip_to_trip_desc(__trip) \ #define trip_to_trip_desc(__trip) \
container_of(__trip, struct thermal_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, int thermal_zone_trip_id(const struct thermal_zone_device *tz,
const struct thermal_trip *trip); const struct thermal_trip *trip);
void thermal_zone_trip_updated(struct thermal_zone_device *tz, void thermal_zone_trip_updated(struct thermal_zone_device *tz,
......
...@@ -94,7 +94,6 @@ struct cdev_record { ...@@ -94,7 +94,6 @@ struct cdev_record {
* @trip_temp: trip temperature at mitigation start * @trip_temp: trip temperature at mitigation start
* @trip_hyst: trip hysteresis at mitigation start * @trip_hyst: trip hysteresis at mitigation start
* @count: the number of times the zone temperature was above the trip point * @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 * @min: minimum recorded temperature above the trip point
* @avg: average temperature above the trip point * @avg: average temperature above the trip point
*/ */
...@@ -104,7 +103,6 @@ struct trip_stats { ...@@ -104,7 +103,6 @@ struct trip_stats {
int trip_temp; int trip_temp;
int trip_hyst; int trip_hyst;
int count; int count;
int max;
int min; int min;
int avg; int avg;
}; };
...@@ -122,12 +120,14 @@ struct trip_stats { ...@@ -122,12 +120,14 @@ struct trip_stats {
* @timestamp: first trip point crossed the way up * @timestamp: first trip point crossed the way up
* @duration: total duration of the mitigation episode * @duration: total duration of the mitigation episode
* @node: a list element to be added to the list of tz events * @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 * @trip_stats: per trip point statistics, flexible array
*/ */
struct tz_episode { struct tz_episode {
ktime_t timestamp; ktime_t timestamp;
ktime_t duration; ktime_t duration;
struct list_head node; struct list_head node;
int max_temp;
struct trip_stats trip_stats[]; struct trip_stats trip_stats[];
}; };
...@@ -561,10 +561,11 @@ static struct tz_episode *thermal_debugfs_tz_event_alloc(struct thermal_zone_dev ...@@ -561,10 +561,11 @@ static struct tz_episode *thermal_debugfs_tz_event_alloc(struct thermal_zone_dev
INIT_LIST_HEAD(&tze->node); INIT_LIST_HEAD(&tze->node);
tze->timestamp = now; tze->timestamp = now;
tze->duration = KTIME_MIN; tze->duration = KTIME_MIN;
tze->max_temp = INT_MIN;
for (i = 0; i < tz->num_trips; i++) { 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].min = INT_MAX;
tze->trip_stats[i].max = INT_MIN;
} }
return tze; return tze;
...@@ -573,20 +574,20 @@ static struct tz_episode *thermal_debugfs_tz_event_alloc(struct thermal_zone_dev ...@@ -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, void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
const struct thermal_trip *trip) const struct thermal_trip *trip)
{ {
struct tz_episode *tze;
struct tz_debugfs *tz_dbg;
struct thermal_debugfs *thermal_dbg = tz->debugfs; struct thermal_debugfs *thermal_dbg = tz->debugfs;
int trip_id = thermal_zone_trip_id(tz, trip); int trip_id = thermal_zone_trip_id(tz, trip);
ktime_t now = ktime_get(); ktime_t now = ktime_get();
struct trip_stats *trip_stats; struct trip_stats *trip_stats;
struct tz_debugfs *tz_dbg;
struct tz_episode *tze;
if (!thermal_dbg) if (!thermal_dbg)
return; return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg; tz_dbg = &thermal_dbg->tz_dbg;
mutex_lock(&thermal_dbg->lock);
/* /*
* The mitigation is starting. A mitigation can contain * The mitigation is starting. A mitigation can contain
* several episodes where each of them is related to a * 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, ...@@ -653,23 +654,33 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
mutex_unlock(&thermal_dbg->lock); 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, void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,
const struct thermal_trip *trip) const struct thermal_trip *trip)
{ {
struct thermal_debugfs *thermal_dbg = tz->debugfs; 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_episode *tze;
struct tz_debugfs *tz_dbg; struct tz_debugfs *tz_dbg;
ktime_t delta, now = ktime_get();
int trip_id = thermal_zone_trip_id(tz, trip);
int i; int i;
if (!thermal_dbg) if (!thermal_dbg)
return; return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg; tz_dbg = &thermal_dbg->tz_dbg;
mutex_lock(&thermal_dbg->lock);
/* /*
* The temperature crosses the way down but there was not * The temperature crosses the way down but there was not
* mitigation detected before. That may happen when the * mitigation detected before. That may happen when the
...@@ -695,13 +706,7 @@ void thermal_debug_tz_trip_down(struct thermal_zone_device *tz, ...@@ -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); tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node);
delta = ktime_sub(now, tze->trip_stats[trip_id].timestamp); tz_episode_close_trip(tze, trip_id, now);
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;
/* /*
* This event closes the mitigation as we are crossing the * 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) ...@@ -724,20 +729,22 @@ void thermal_debug_update_trip_stats(struct thermal_zone_device *tz)
if (!thermal_dbg) if (!thermal_dbg)
return; return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg; tz_dbg = &thermal_dbg->tz_dbg;
mutex_lock(&thermal_dbg->lock);
if (!tz_dbg->nr_trips) if (!tz_dbg->nr_trips)
goto out; goto out;
tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node); 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++) { for (i = 0; i < tz_dbg->nr_trips; i++) {
int trip_id = tz_dbg->trips_crossed[i]; int trip_id = tz_dbg->trips_crossed[i];
struct trip_stats *trip_stats = &tze->trip_stats[trip_id]; 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->min = min(trip_stats->min, tz->temperature);
trip_stats->avg += (tz->temperature - trip_stats->avg) / trip_stats->avg += (tz->temperature - trip_stats->avg) /
++trip_stats->count; ++trip_stats->count;
...@@ -777,7 +784,6 @@ static int tze_seq_show(struct seq_file *s, void *v) ...@@ -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_zone_device *tz = thermal_dbg->tz_dbg.tz;
struct thermal_trip_desc *td; struct thermal_trip_desc *td;
struct tz_episode *tze; struct tz_episode *tze;
const char *type;
u64 duration_ms; u64 duration_ms;
int trip_id; int trip_id;
char c; char c;
...@@ -793,10 +799,10 @@ static int tze_seq_show(struct seq_file *s, void *v) ...@@ -793,10 +799,10 @@ static int tze_seq_show(struct seq_file *s, void *v)
c = '='; c = '=';
} }
seq_printf(s, ",-Mitigation at %lluus, duration%c%llums\n", seq_printf(s, ",-Mitigation at %llums, duration%c%llums, max. temp=%dm°C\n",
ktime_to_us(tze->timestamp), c, duration_ms); 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) { for_each_trip_desc(tz, td) {
const struct thermal_trip *trip = &td->trip; const struct thermal_trip *trip = &td->trip;
...@@ -814,16 +820,9 @@ static int tze_seq_show(struct seq_file *s, void *v) ...@@ -814,16 +820,9 @@ static int tze_seq_show(struct seq_file *s, void *v)
trip_stats = &tze->trip_stats[trip_id]; trip_stats = &tze->trip_stats[trip_id];
/* Skip trips without any stats. */ /* Skip trips without any stats. */
if (trip_stats->min > trip_stats->max) if (trip_stats->trip_temp == THERMAL_TEMP_INVALID)
continue; 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) { if (trip_stats->timestamp != KTIME_MAX) {
/* Mitigation in progress. */ /* Mitigation in progress. */
ktime_t delta = ktime_sub(ktime_get(), ktime_t delta = ktime_sub(ktime_get(),
...@@ -837,15 +836,14 @@ static int tze_seq_show(struct seq_file *s, void *v) ...@@ -837,15 +836,14 @@ static int tze_seq_show(struct seq_file *s, void *v)
c = ' '; 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, 4 , trip_id,
8, type, 8, thermal_trip_type_name(trip->type),
9, trip_stats->trip_temp, 9, trip_stats->trip_temp,
9, trip_stats->trip_hyst, 9, trip_stats->trip_hyst,
c, 10, duration_ms, c, 11, duration_ms,
9, trip_stats->avg, 9, trip_stats->avg,
9, trip_stats->min, 9, trip_stats->min);
9, trip_stats->max);
} }
return 0; return 0;
...@@ -922,3 +920,39 @@ void thermal_debug_tz_remove(struct thermal_zone_device *tz) ...@@ -922,3 +920,39 @@ void thermal_debug_tz_remove(struct thermal_zone_device *tz)
thermal_debugfs_remove_id(thermal_dbg); thermal_debugfs_remove_id(thermal_dbg);
kfree(trips_crossed); 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); ...@@ -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_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_add(struct thermal_zone_device *tz);
void thermal_debug_tz_remove(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, void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
const struct thermal_trip *trip); const struct thermal_trip *trip);
void thermal_debug_tz_trip_down(struct thermal_zone_device *tz, 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_ ...@@ -20,6 +21,7 @@ static inline void thermal_debug_cdev_state_update(const struct thermal_cooling_
int state) {} int state) {}
static inline void thermal_debug_tz_add(struct thermal_zone_device *tz) {} 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_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, static inline void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
const struct thermal_trip *trip) {}; const struct thermal_trip *trip) {};
static inline void thermal_debug_tz_trip_down(struct thermal_zone_device *tz, 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 ...@@ -39,30 +39,53 @@ int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip
return trend; 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 * struct thermal_instance *
get_thermal_instance(struct thermal_zone_device *tz, get_thermal_instance(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev, int trip_index) struct thermal_cooling_device *cdev, int trip_index)
{ {
struct thermal_instance *pos = NULL; struct thermal_instance *ti;
struct thermal_instance *target_instance = NULL;
const struct thermal_trip *trip;
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
mutex_lock(&cdev->lock); mutex_lock(&cdev->lock);
trip = &tz->trips[trip_index].trip; ti = get_instance(tz, cdev, &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;
}
}
mutex_unlock(&cdev->lock); mutex_unlock(&cdev->lock);
mutex_unlock(&tz->lock); mutex_unlock(&tz->lock);
return target_instance; return ti;
} }
EXPORT_SYMBOL(get_thermal_instance); EXPORT_SYMBOL(get_thermal_instance);
......
...@@ -88,18 +88,7 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr, ...@@ -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) if (sscanf(attr->attr.name, "trip_point_%d_type", &trip_id) != 1)
return -EINVAL; return -EINVAL;
switch (tz->trips[trip_id].trip.type) { return sprintf(buf, "%s\n", thermal_trip_type_name(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");
}
} }
static ssize_t static ssize_t
...@@ -124,7 +113,7 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, ...@@ -124,7 +113,7 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
if (temp != trip->temperature) { if (temp != trip->temperature) {
if (tz->ops.set_trip_temp) { 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) if (ret)
goto unlock; goto unlock;
} }
...@@ -150,7 +139,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, ...@@ -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) if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1)
return -EINVAL; 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 static ssize_t
...@@ -174,7 +163,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr, ...@@ -174,7 +163,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
trip = &tz->trips[trip_id].trip; trip = &tz->trips[trip_id].trip;
if (hyst != trip->hysteresis) { if (hyst != trip->hysteresis) {
trip->hysteresis = hyst; WRITE_ONCE(trip->hysteresis, hyst);
thermal_zone_trip_updated(tz, trip); thermal_zone_trip_updated(tz, trip);
} }
...@@ -194,7 +183,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr, ...@@ -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) if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1)
return -EINVAL; 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 static ssize_t
......
...@@ -9,6 +9,21 @@ ...@@ -9,6 +9,21 @@
*/ */
#include "thermal_core.h" #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 for_each_thermal_trip(struct thermal_zone_device *tz,
int (*cb)(struct thermal_trip *, void *), int (*cb)(struct thermal_trip *, void *),
void *data) void *data)
...@@ -47,7 +62,7 @@ int thermal_zone_get_num_trips(struct thermal_zone_device *tz) ...@@ -47,7 +62,7 @@ int thermal_zone_get_num_trips(struct thermal_zone_device *tz)
EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips); 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 * @tz: a pointer to a thermal zone device structure
* *
* The function computes the next temperature boundaries by browsing * The function computes the next temperature boundaries by browsing
...@@ -61,7 +76,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips); ...@@ -61,7 +76,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);
* *
* It does not return a value * 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; const struct thermal_trip_desc *td;
int low = -INT_MAX, high = INT_MAX; int low = -INT_MAX, high = INT_MAX;
...@@ -73,17 +88,11 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz) ...@@ -73,17 +88,11 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz)
return; return;
for_each_trip_desc(tz, td) { for_each_trip_desc(tz, td) {
const struct thermal_trip *trip = &td->trip; if (td->threshold < tz->temperature && td->threshold > low)
int trip_low; low = td->threshold;
trip_low = trip->temperature - trip->hysteresis;
if (trip_low < tz->temperature && trip_low > low) if (td->threshold > tz->temperature && td->threshold < high)
low = trip_low; high = td->threshold;
if (trip->temperature > tz->temperature &&
trip->temperature < high)
high = trip->temperature;
} }
/* No need to change trip points */ /* No need to change trip points */
...@@ -105,27 +114,17 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz) ...@@ -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); 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, int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip) struct thermal_trip *trip)
{ {
int ret; if (!tz || !trip || trip_id < 0 || trip_id >= tz->num_trips)
return -EINVAL;
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
ret = __thermal_zone_get_trip(tz, trip_id, trip); *trip = tz->trips[trip_id].trip;
mutex_unlock(&tz->lock); mutex_unlock(&tz->lock);
return ret; return 0;
} }
EXPORT_SYMBOL_GPL(thermal_zone_get_trip); EXPORT_SYMBOL_GPL(thermal_zone_get_trip);
...@@ -152,7 +151,7 @@ void thermal_zone_set_trip_temp(struct thermal_zone_device *tz, ...@@ -152,7 +151,7 @@ void thermal_zone_set_trip_temp(struct thermal_zone_device *tz,
if (trip->temperature == temp) if (trip->temperature == temp)
return; return;
trip->temperature = temp; WRITE_ONCE(trip->temperature, temp);
thermal_notify_tz_trip_change(tz, trip); thermal_notify_tz_trip_change(tz, trip);
if (temp == THERMAL_TEMP_INVALID) { if (temp == THERMAL_TEMP_INVALID) {
......
...@@ -239,13 +239,34 @@ static irqreturn_t uniphier_tm_alarm_irq_thread(int irq, void *_tdev) ...@@ -239,13 +239,34 @@ static irqreturn_t uniphier_tm_alarm_irq_thread(int irq, void *_tdev)
return IRQ_HANDLED; 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) 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 device *dev = &pdev->dev;
struct regmap *regmap; struct regmap *regmap;
struct device_node *parent; struct device_node *parent;
struct uniphier_tm_dev *tdev; struct uniphier_tm_dev *tdev;
int i, ret, irq, crit_temp = INT_MAX; int ret, irq;
tdev = devm_kzalloc(dev, sizeof(*tdev), GFP_KERNEL); tdev = devm_kzalloc(dev, sizeof(*tdev), GFP_KERNEL);
if (!tdev) if (!tdev)
...@@ -293,20 +314,10 @@ static int uniphier_tm_probe(struct platform_device *pdev) ...@@ -293,20 +314,10 @@ static int uniphier_tm_probe(struct platform_device *pdev)
} }
/* set alert temperatures */ /* set alert temperatures */
for (i = 0; i < thermal_zone_get_num_trips(tdev->tz_dev); i++) { twd.tdev = tdev;
struct thermal_trip trip; 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 (twd.crit_temp > CRITICAL_TEMP_LIMIT) {
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) {
dev_err(dev, "critical trip is over limit(>%d), or not set\n", dev_err(dev, "critical trip is over limit(>%d), or not set\n",
CRITICAL_TEMP_LIMIT); CRITICAL_TEMP_LIMIT);
return -EINVAL; return -EINVAL;
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#define MT8186_BIG_CPU1 5 #define MT8186_BIG_CPU1 5
#define MT8186_NNA 6 #define MT8186_NNA 6
#define MT8186_ADSP 7 #define MT8186_ADSP 7
#define MT8186_MFG 8 #define MT8186_GPU 8
#define MT8188_MCU_LITTLE_CPU0 0 #define MT8188_MCU_LITTLE_CPU0 0
#define MT8188_MCU_LITTLE_CPU1 1 #define MT8188_MCU_LITTLE_CPU1 1
...@@ -34,11 +34,11 @@ ...@@ -34,11 +34,11 @@
#define MT8188_MCU_BIG_CPU1 5 #define MT8188_MCU_BIG_CPU1 5
#define MT8188_AP_APU 0 #define MT8188_AP_APU 0
#define MT8188_AP_GPU1 1 #define MT8188_AP_GPU0 1
#define MT8188_AP_GPU2 2 #define MT8188_AP_GPU1 2
#define MT8188_AP_SOC1 3 #define MT8188_AP_ADSP 3
#define MT8188_AP_SOC2 4 #define MT8188_AP_VDO 4
#define MT8188_AP_SOC3 5 #define MT8188_AP_INFRA 5
#define MT8188_AP_CAM1 6 #define MT8188_AP_CAM1 6
#define MT8188_AP_CAM2 7 #define MT8188_AP_CAM2 7
......
...@@ -14,5 +14,6 @@ int intel_tcc_get_tjmax(int cpu); ...@@ -14,5 +14,6 @@ int intel_tcc_get_tjmax(int cpu);
int intel_tcc_get_offset(int cpu); int intel_tcc_get_offset(int cpu);
int intel_tcc_set_offset(int cpu, int offset); int intel_tcc_set_offset(int cpu, int offset);
int intel_tcc_get_temp(int cpu, int *temp, bool pkg); int intel_tcc_get_temp(int cpu, int *temp, bool pkg);
u32 intel_tcc_get_offset_mask(void);
#endif /* __INTEL_TCC_H__ */ #endif /* __INTEL_TCC_H__ */
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
static inline bool soc_intel_is_##soc(void) \ static inline bool soc_intel_is_##soc(void) \
{ \ { \
static const struct x86_cpu_id soc##_cpu_ids[] = { \ 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; \ const struct x86_cpu_id *id; \
...@@ -31,11 +31,11 @@ static inline bool soc_intel_is_##soc(void) \ ...@@ -31,11 +31,11 @@ static inline bool soc_intel_is_##soc(void) \
return false; \ return false; \
} }
SOC_INTEL_IS_CPU(byt, ATOM_SILVERMONT); SOC_INTEL_IS_CPU(byt, INTEL_ATOM_SILVERMONT);
SOC_INTEL_IS_CPU(cht, ATOM_AIRMONT); SOC_INTEL_IS_CPU(cht, INTEL_ATOM_AIRMONT);
SOC_INTEL_IS_CPU(apl, ATOM_GOLDMONT); SOC_INTEL_IS_CPU(apl, INTEL_ATOM_GOLDMONT);
SOC_INTEL_IS_CPU(glk, ATOM_GOLDMONT_PLUS); SOC_INTEL_IS_CPU(glk, INTEL_ATOM_GOLDMONT_PLUS);
SOC_INTEL_IS_CPU(cml, KABYLAKE_L); SOC_INTEL_IS_CPU(cml, INTEL_KABYLAKE_L);
#undef SOC_INTEL_IS_CPU #undef SOC_INTEL_IS_CPU
......
...@@ -79,6 +79,9 @@ struct thermal_trip { ...@@ -79,6 +79,9 @@ struct thermal_trip {
#define THERMAL_TRIP_FLAG_RW (THERMAL_TRIP_FLAG_RW_TEMP | \ #define THERMAL_TRIP_FLAG_RW (THERMAL_TRIP_FLAG_RW_TEMP | \
THERMAL_TRIP_FLAG_RW_HYST) 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;
struct thermal_zone_device_ops { struct thermal_zone_device_ops {
...@@ -90,7 +93,8 @@ struct thermal_zone_device_ops { ...@@ -90,7 +93,8 @@ struct thermal_zone_device_ops {
int (*set_trips) (struct thermal_zone_device *, int, int); int (*set_trips) (struct thermal_zone_device *, int, int);
int (*change_mode) (struct thermal_zone_device *, int (*change_mode) (struct thermal_zone_device *,
enum thermal_device_mode); 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 (*get_crit_temp) (struct thermal_zone_device *, int *);
int (*set_emul_temp) (struct thermal_zone_device *, int); int (*set_emul_temp) (struct thermal_zone_device *, int);
int (*get_trend) (struct thermal_zone_device *, int (*get_trend) (struct thermal_zone_device *,
...@@ -198,8 +202,6 @@ static inline void devm_thermal_of_zone_unregister(struct device *dev, ...@@ -198,8 +202,6 @@ static inline void devm_thermal_of_zone_unregister(struct device *dev,
} }
#endif #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, int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip); struct thermal_trip *trip);
int for_each_thermal_trip(struct thermal_zone_device *tz, int for_each_thermal_trip(struct thermal_zone_device *tz,
...@@ -221,7 +223,8 @@ struct thermal_zone_device *thermal_zone_device_register_with_trips( ...@@ -221,7 +223,8 @@ struct thermal_zone_device *thermal_zone_device_register_with_trips(
int num_trips, void *devdata, int num_trips, void *devdata,
const struct thermal_zone_device_ops *ops, const struct thermal_zone_device_ops *ops,
const struct thermal_zone_params *tzp, 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( struct thermal_zone_device *thermal_tripless_zone_device_register(
const char *type, const char *type,
...@@ -261,7 +264,7 @@ thermal_of_cooling_device_register(struct device_node *np, const char *, void *, ...@@ -261,7 +264,7 @@ thermal_of_cooling_device_register(struct device_node *np, const char *, void *,
struct thermal_cooling_device * struct thermal_cooling_device *
devm_thermal_of_cooling_device_register(struct device *dev, devm_thermal_of_cooling_device_register(struct device *dev,
struct device_node *np, struct device_node *np,
char *type, void *devdata, const char *type, void *devdata,
const struct thermal_cooling_device_ops *ops); const struct thermal_cooling_device_ops *ops);
void thermal_cooling_device_update(struct thermal_cooling_device *); void thermal_cooling_device_update(struct thermal_cooling_device *);
void thermal_cooling_device_unregister(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); ...@@ -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_temp(struct thermal_zone_device *tz, int *temp);
int thermal_zone_get_slope(struct thermal_zone_device *tz); int thermal_zone_get_slope(struct thermal_zone_device *tz);
int thermal_zone_get_offset(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_enable(struct thermal_zone_device *tz);
int thermal_zone_device_disable(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, ...@@ -305,7 +311,7 @@ thermal_of_cooling_device_register(struct device_node *np,
static inline struct thermal_cooling_device * static inline struct thermal_cooling_device *
devm_thermal_of_cooling_device_register(struct device *dev, devm_thermal_of_cooling_device_register(struct device *dev,
struct device_node *np, struct device_node *np,
char *type, void *devdata, const char *type, void *devdata,
const struct thermal_cooling_device_ops *ops) const struct thermal_cooling_device_ops *ops)
{ {
return ERR_PTR(-ENODEV); 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