mirror of https://github.com/torvalds/linux.git
Thermal control updates for 6.19-rc1
- Add Nova Lake processor thermal device to the int340x
processor_thermal driver, add DLVR support for Nova Lake to it,
add Nova Lake support to the ACPI DPTF code, document thermal
throttling on Intel platforms, and update workload type hint
interface documentation (Srinivas Pandruvada)
- Remove int340x thermal scan handler from the ACPI DPTF code
because it turned out to be unnecessary (Slawomir Rosek)
- Clean up the Intel int340x thermal driver (Kaushlendra Kumar)
- Document the RZ/V2H TSU DT bindings (Ovidiu Panait)
- Document the Kaanapali Temperature Sensor (Manaf Meethalavalappu
Pallikunhi)
- Document R-Car Gen4 and RZ/G2 support in driver comment (Marek Vasut)
- Convert to DEFINE_SIMPLE_DEV_PM_OPS() in R-Car [Gen3] (Geert
Uytterhoeven)
- Fix format string bug in thermal-engine (Malaya Kumar Rout)
- Make ipq5018 tsens standalone compatible (George Moussalem)
- Add the QCS8300 compatible for QCom Tsens (Gaurav Kohli)
- Add support for the NXP i.MX91 thermal module, including the DT
bindings (Pengfei Li)
-----BEGIN PGP SIGNATURE-----
iQFGBAABCAAwFiEEcM8Aw/RY0dgsiRUR7l+9nS/U47UFAmkpt1cSHHJqd0Byand5
c29ja2kubmV0AAoJEO5fvZ0v1OO1cikH/jW6IUXUvrTy9VEi3wGTzLAcnOuJJtQL
zKQBzrjtuGngr4xIeE+chr9Gr8+S4EfVcD17twp59I6C3T9fBZngfMxbi7VLdyd7
gIJs2IxIqfIlQwK32lBOkLM2/YHa0AYU3Dd/YHsgYOU3Y25adSvmiwoTqG3kUmXB
YnoHUobPskzV/9iKf2sptM7XBLDaBdoPHcDAM2BN4rfKhgOy/1ha7KzigJyuHHyW
V+b9KR/IlFOVct8OrvhXKT4mzsS9VZv6IJ6KrRsDsCIgVwM/fO1YTmRgfOkuRASZ
fw6vNNi+49xK0LN8zEvHKuYthBFy+7lIP+MiErMr2Fw5nuY2uXitZA8=
=OgXe
-----END PGP SIGNATURE-----
Merge tag 'thermal-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull thermal control updates from Rafael Wysocki:
"These add Nova Lake processor support to the Intel thermal drivers and
DPTF code, update thermal control documentation, simplify the ACPI
DPTF code related to thermal control, add QCS8300 compatible to the
tsens thermal DT bindings, add DT bindings for NXP i.MX91 thermal
module and add support for it to the imx91 thermal driver, update a
few other thermal drivers and fix a format string issue in a thermal
utility:
- Add Nova Lake processor thermal device to the int340x
processor_thermal driver, add DLVR support for Nova Lake to it, add
Nova Lake support to the ACPI DPTF code, document thermal
throttling on Intel platforms, and update workload type hint
interface documentation (Srinivas Pandruvada)
- Remove int340x thermal scan handler from the ACPI DPTF code because
it turned out to be unnecessary (Slawomir Rosek)
- Clean up the Intel int340x thermal driver (Kaushlendra Kumar)
- Document the RZ/V2H TSU DT bindings (Ovidiu Panait)
- Document the Kaanapali Temperature Sensor (Manaf Meethalavalappu
Pallikunhi)
- Document R-Car Gen4 and RZ/G2 support in driver comment (Marek
Vasut)
- Convert to DEFINE_SIMPLE_DEV_PM_OPS() in R-Car [Gen3] (Geert
Uytterhoeven)
- Fix format string bug in thermal-engine (Malaya Kumar Rout)
- Make ipq5018 tsens standalone compatible (George Moussalem)
- Add the QCS8300 compatible for QCom Tsens (Gaurav Kohli)
- Add support for the NXP i.MX91 thermal module, including the DT
bindings (Pengfei Li)"
* tag 'thermal-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
thermal/drivers/imx91: Add support for i.MX91 thermal monitoring unit
dt-bindings: thermal: fsl,imx91-tmu: add bindings for NXP i.MX91 thermal module
dt-bindings: thermal: tsens: Add QCS8300 compatible
dt-bindings: thermal: qcom-tsens: make ipq5018 tsens standalone compatible
tools/thermal/thermal-engine: Fix format string bug in thermal-engine
docs: driver-api/thermal/intel_dptf: Add new workload type hint
thermal/drivers/rcar_gen3: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
thermal/drivers/rcar: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
Documentation: thermal: Document thermal throttling on Intel platforms
ACPI: DPTF: Support Nova Lake
thermal: intel: int340x: Add DLVR support for Nova Lake
thermal: int340x: processor_thermal: Add Nova Lake processor thermal device
thermal: intel: int340x: Replace sprintf() with sysfs_emit()
thermal: intel: int340x: Use symbolic constant for UUID comparison
thermal/drivers/rcar_gen3: Document R-Car Gen4 and RZ/G2 support in driver comment
dt-bindings: thermal: qcom-tsens: document the Kaanapali Temperature Sensor
dt-bindings: thermal: r9a09g047-tsu: Document RZ/V2H TSU
ACPI: DPTF: Remove int340x thermal scan handler
thermal: intel: Select INT340X_THERMAL from INTEL_SOC_DTS_THERMAL
This commit is contained in:
commit
619f4edc8d
|
|
@ -6,3 +6,4 @@ Thermal Subsystem
|
|||
:maxdepth: 1
|
||||
|
||||
intel_powerclamp
|
||||
intel_thermal_throttle
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: <isonum.txt>
|
||||
|
||||
=======================================
|
||||
Intel thermal throttle events reporting
|
||||
=======================================
|
||||
|
||||
:Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Intel processors have built in automatic and adaptive thermal monitoring
|
||||
mechanisms that force the processor to reduce its power consumption in order
|
||||
to operate within predetermined temperature limits.
|
||||
|
||||
Refer to section "THERMAL MONITORING AND PROTECTION" in the "Intel® 64 and
|
||||
IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B, 3C, & 3D):
|
||||
System Programming Guide" for more details.
|
||||
|
||||
In general, there are two mechanisms to control the core temperature of the
|
||||
processor. They are called "Thermal Monitor 1 (TM1) and Thermal Monitor 2 (TM2)".
|
||||
|
||||
The status of the temperature sensor that triggers the thermal monitor (TM1/TM2)
|
||||
is indicated through the "thermal status flag" and "thermal status log flag" in
|
||||
MSR_IA32_THERM_STATUS for core level and MSR_IA32_PACKAGE_THERM_STATUS for
|
||||
package level.
|
||||
|
||||
Thermal Status flag, bit 0 — When set, indicates that the processor core
|
||||
temperature is currently at the trip temperature of the thermal monitor and that
|
||||
the processor power consumption is being reduced via either TM1 or TM2, depending
|
||||
on which is enabled. When clear, the flag indicates that the core temperature is
|
||||
below the thermal monitor trip temperature. This flag is read only.
|
||||
|
||||
Thermal Status Log flag, bit 1 — When set, indicates that the thermal sensor has
|
||||
tripped since the last power-up or reset or since the last time that software
|
||||
cleared this flag. This flag is a sticky bit; once set it remains set until
|
||||
cleared by software or until a power-up or reset of the processor. The default
|
||||
state is clear.
|
||||
|
||||
It is possible that when user reads MSR_IA32_THERM_STATUS or
|
||||
MSR_IA32_PACKAGE_THERM_STATUS, TM1/TM2 is not active. In this case,
|
||||
"Thermal Status flag" will read "0" and the "Thermal Status Log flag" will be set
|
||||
to show any previous "TM1/TM2" activation. But since it needs to be cleared by
|
||||
the software, it can't show the number of occurrences of "TM1/TM2" activations.
|
||||
|
||||
Hence, Linux provides counters of how many times the "Thermal Status flag" was
|
||||
set. Also presents how long the "Thermal Status flag" was active in milliseconds.
|
||||
Using these counters, users can check if the performance was limited because of
|
||||
thermal events. It is recommended to read from sysfs instead of directly reading
|
||||
MSRs as the "Thermal Status Log flag" is reset by the driver to implement rate
|
||||
control.
|
||||
|
||||
Sysfs Interface
|
||||
---------------
|
||||
|
||||
Thermal throttling events are presented for each CPU under
|
||||
"/sys/devices/system/cpu/cpuX/thermal_throttle/", where "X" is the CPU number.
|
||||
|
||||
All these counters are read-only. They can't be reset to 0. So, they can potentially
|
||||
overflow after reaching the maximum 64 bit unsigned integer.
|
||||
|
||||
``core_throttle_count``
|
||||
Shows the number of times "Thermal Status flag" changed from 0 to 1 for this
|
||||
CPU since OS boot and thermal vector is initialized. This is a 64 bit counter.
|
||||
|
||||
``package_throttle_count``
|
||||
Shows the number of times "Thermal Status flag" changed from 0 to 1 for the
|
||||
package containing this CPU since OS boot and thermal vector is initialized.
|
||||
Package status is broadcast to all CPUs; all CPUs in the package increment
|
||||
this count. This is a 64-bit counter.
|
||||
|
||||
``core_throttle_max_time_ms``
|
||||
Shows the maximum amount of time for which "Thermal Status flag" has been
|
||||
set to 1 for this CPU at the core level since OS boot and thermal vector
|
||||
is initialized.
|
||||
|
||||
``package_throttle_max_time_ms``
|
||||
Shows the maximum amount of time for which "Thermal Status flag" has been
|
||||
set to 1 for the package containing this CPU since OS boot and thermal
|
||||
vector is initialized.
|
||||
|
||||
``core_throttle_total_time_ms``
|
||||
Shows the cumulative time for which "Thermal Status flag" has been
|
||||
set to 1 for this CPU for core level since OS boot and thermal vector
|
||||
is initialized.
|
||||
|
||||
``package_throttle_total_time_ms``
|
||||
Shows the cumulative time for which "Thermal Status flag" has been set
|
||||
to 1 for the package containing this CPU since OS boot and thermal vector
|
||||
is initialized.
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/thermal/fsl,imx91-tmu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP i.MX91 Thermal
|
||||
|
||||
maintainers:
|
||||
- Pengfei Li <pengfei.li_1@nxp.com>
|
||||
|
||||
description:
|
||||
i.MX91 features a new temperature sensor. It includes programmable
|
||||
temperature threshold comparators for both normal and privileged
|
||||
accesses and allows a programmable measurement frequency for the
|
||||
Periodic One-Shot Measurement mode. Additionally, it provides
|
||||
status registers for indicating the end of measurement and threshold
|
||||
violation events.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: fsl,imx91-tmu
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Comparator 1 irq
|
||||
- description: Comparator 2 irq
|
||||
- description: Data ready irq
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: thr1
|
||||
- const: thr2
|
||||
- const: ready
|
||||
|
||||
nvmem-cells:
|
||||
items:
|
||||
- description: Phandle to the trim control 1 provided by ocotp
|
||||
- description: Phandle to the trim control 2 provided by ocotp
|
||||
|
||||
nvmem-cell-names:
|
||||
items:
|
||||
- const: trim1
|
||||
- const: trim2
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
allOf:
|
||||
- $ref: thermal-sensor.yaml
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/imx93-clock.h>
|
||||
|
||||
thermal-sensor@44482000 {
|
||||
compatible = "fsl,imx91-tmu";
|
||||
reg = <0x44482000 0x1000>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
clocks = <&clk IMX93_CLK_TMC_GATE>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "thr1", "thr2", "ready";
|
||||
nvmem-cells = <&tmu_trim1>, <&tmu_trim2>;
|
||||
nvmem-cell-names = "trim1", "trim2";
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -36,10 +36,15 @@ properties:
|
|||
- qcom,msm8974-tsens
|
||||
- const: qcom,tsens-v0_1
|
||||
|
||||
- description:
|
||||
v1 of TSENS without RPM which requires to be explicitly reset
|
||||
and enabled in the driver.
|
||||
enum:
|
||||
- qcom,ipq5018-tsens
|
||||
|
||||
- description: v1 of TSENS
|
||||
items:
|
||||
- enum:
|
||||
- qcom,ipq5018-tsens
|
||||
- qcom,msm8937-tsens
|
||||
- qcom,msm8956-tsens
|
||||
- qcom,msm8976-tsens
|
||||
|
|
@ -50,11 +55,13 @@ properties:
|
|||
items:
|
||||
- enum:
|
||||
- qcom,glymur-tsens
|
||||
- qcom,kaanapali-tsens
|
||||
- qcom,milos-tsens
|
||||
- qcom,msm8953-tsens
|
||||
- qcom,msm8996-tsens
|
||||
- qcom,msm8998-tsens
|
||||
- qcom,qcm2290-tsens
|
||||
- qcom,qcs8300-tsens
|
||||
- qcom,qcs615-tsens
|
||||
- qcom,sa8255p-tsens
|
||||
- qcom,sa8775p-tsens
|
||||
|
|
|
|||
|
|
@ -16,7 +16,11 @@ description:
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
const: renesas,r9a09g047-tsu
|
||||
oneOf:
|
||||
- const: renesas,r9a09g047-tsu # RZ/G3E
|
||||
- items:
|
||||
- const: renesas,r9a09g057-tsu # RZ/V2H
|
||||
- const: renesas,r9a09g047-tsu # RZ/G3E
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
|||
|
|
@ -409,3 +409,26 @@ based on the processor generation.
|
|||
Limit 1 from being exhausted.
|
||||
|
||||
4 – Unknown: Can't classify.
|
||||
|
||||
On processors starting from Panther Lake additional hints are provided.
|
||||
The hardware analyzes workload residencies over an extended period to
|
||||
determine whether the workload classification tends toward idle/battery
|
||||
life states or sustained/performance states. Based on this long-term
|
||||
analysis, it classifies:
|
||||
|
||||
Power Classification: If the workload exhibits more idle or battery life
|
||||
residencies, it is classified as "power".
|
||||
|
||||
Performance Classification: If the workload exhibits more sustained or
|
||||
performance residencies, it is classified as "performance".
|
||||
|
||||
This approach enables applications to ignore short-term workload
|
||||
fluctuations and instead respond to longer-term power vs. performance
|
||||
trends.
|
||||
|
||||
Residency thresholds for this classification are CPU generation-specific.
|
||||
Classification is reported via bit 4 of the workload_type_index:
|
||||
|
||||
Bit 4 = 1: Power classification
|
||||
|
||||
Bit 4 = 0: Performance classification
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_ACPI) += int340x_thermal.o
|
||||
obj-$(CONFIG_DPTF_POWER) += dptf_power.o
|
||||
obj-$(CONFIG_DPTF_PCH_FIVR) += dptf_pch_fivr.o
|
||||
|
|
|
|||
|
|
@ -240,6 +240,8 @@ static const struct acpi_device_id int3407_device_ids[] = {
|
|||
{"INTC10D9", 0},
|
||||
{"INTC1100", 0},
|
||||
{"INTC1101", 0},
|
||||
{"INTC10F7", 0},
|
||||
{"INTC10F8", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, int3407_device_ids);
|
||||
|
|
|
|||
|
|
@ -1,94 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* ACPI support for int340x thermal drivers
|
||||
*
|
||||
* Copyright (C) 2014, Intel Corporation
|
||||
* Authors: Zhang Rui <rui.zhang@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
#define INT3401_DEVICE 0X01
|
||||
static const struct acpi_device_id int340x_thermal_device_ids[] = {
|
||||
{"INT3400"},
|
||||
{"INT3401", INT3401_DEVICE},
|
||||
{"INT3402"},
|
||||
{"INT3403"},
|
||||
{"INT3404"},
|
||||
{"INT3406"},
|
||||
{"INT3407"},
|
||||
{"INT3408"},
|
||||
{"INT3409"},
|
||||
{"INT340A"},
|
||||
{"INT340B"},
|
||||
{"INT3532"},
|
||||
{"INTC1040"},
|
||||
{"INTC1041"},
|
||||
{"INTC1042"},
|
||||
{"INTC1043"},
|
||||
{"INTC1044"},
|
||||
{"INTC1045"},
|
||||
{"INTC1046"},
|
||||
{"INTC1047"},
|
||||
{"INTC1048"},
|
||||
{"INTC1049"},
|
||||
{"INTC1050"},
|
||||
{"INTC1060"},
|
||||
{"INTC1061"},
|
||||
{"INTC1062"},
|
||||
{"INTC1063"},
|
||||
{"INTC1064"},
|
||||
{"INTC1065"},
|
||||
{"INTC1066"},
|
||||
{"INTC1068"},
|
||||
{"INTC1069"},
|
||||
{"INTC106A"},
|
||||
{"INTC106B"},
|
||||
{"INTC106C"},
|
||||
{"INTC106D"},
|
||||
{"INTC10A0"},
|
||||
{"INTC10A1"},
|
||||
{"INTC10A2"},
|
||||
{"INTC10A3"},
|
||||
{"INTC10A4"},
|
||||
{"INTC10A5"},
|
||||
{"INTC10D4"},
|
||||
{"INTC10D5"},
|
||||
{"INTC10D6"},
|
||||
{"INTC10D7"},
|
||||
{"INTC10D8"},
|
||||
{"INTC10D9"},
|
||||
{"INTC10FC"},
|
||||
{"INTC10FD"},
|
||||
{"INTC10FE"},
|
||||
{"INTC10FF"},
|
||||
{"INTC1100"},
|
||||
{"INTC1101"},
|
||||
{"INTC1102"},
|
||||
{""},
|
||||
};
|
||||
|
||||
static int int340x_thermal_handler_attach(struct acpi_device *adev,
|
||||
const struct acpi_device_id *id)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_INT340X_THERMAL))
|
||||
acpi_create_platform_device(adev, NULL);
|
||||
/* Intel SoC DTS thermal driver needs INT3401 to set IRQ descriptor */
|
||||
else if (IS_ENABLED(CONFIG_INTEL_SOC_DTS_THERMAL) &&
|
||||
id->driver_data == INT3401_DEVICE)
|
||||
acpi_create_platform_device(adev, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct acpi_scan_handler int340x_thermal_handler = {
|
||||
.ids = int340x_thermal_device_ids,
|
||||
.attach = int340x_thermal_handler_attach,
|
||||
};
|
||||
|
||||
void __init acpi_int340x_thermal_init(void)
|
||||
{
|
||||
acpi_scan_add_handler(&int340x_thermal_handler);
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
{"INTC10A2", }, /* Fan for Raptor Lake generation */ \
|
||||
{"INTC10D6", }, /* Fan for Panther Lake generation */ \
|
||||
{"INTC10FE", }, /* Fan for Wildcat Lake generation */ \
|
||||
{"INTC10F5", }, /* Fan for Nova Lake generation */ \
|
||||
{"PNP0C0B", } /* Generic ACPI fan */
|
||||
|
||||
#define ACPI_FPS_NAME_LEN 20
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ static inline void acpi_pci_link_init(void) {}
|
|||
void acpi_processor_init(void);
|
||||
void acpi_platform_init(void);
|
||||
void acpi_pnp_init(void);
|
||||
void acpi_int340x_thermal_init(void);
|
||||
int acpi_sysfs_init(void);
|
||||
void acpi_gpe_apply_masked_gpes(void);
|
||||
void acpi_container_init(void);
|
||||
|
|
|
|||
|
|
@ -2711,7 +2711,6 @@ void __init acpi_scan_init(void)
|
|||
acpi_watchdog_init();
|
||||
acpi_pnp_init();
|
||||
acpi_power_resources_init();
|
||||
acpi_int340x_thermal_init();
|
||||
acpi_init_lpit();
|
||||
|
||||
acpi_scan_add_handler(&generic_device_handler);
|
||||
|
|
|
|||
|
|
@ -296,6 +296,16 @@ config IMX8MM_THERMAL
|
|||
cpufreq is used as the cooling device to throttle CPUs when the passive
|
||||
trip is crossed.
|
||||
|
||||
config IMX91_THERMAL
|
||||
tristate "Temperature sensor driver for NXP i.MX91 SoC"
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
Include one sensor and six comparators. Each of them compares the
|
||||
temperature value (from the sensor) against the programmable
|
||||
threshold values. The direction of the comparison is configurable
|
||||
(greater / lesser than).
|
||||
|
||||
config K3_THERMAL
|
||||
tristate "Texas Instruments K3 thermal support"
|
||||
depends on ARCH_K3 || COMPILE_TEST
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
|
|||
obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
|
||||
obj-$(CONFIG_IMX_SC_THERMAL) += imx_sc_thermal.o
|
||||
obj-$(CONFIG_IMX8MM_THERMAL) += imx8mm_thermal.o
|
||||
obj-$(CONFIG_IMX91_THERMAL) += imx91_thermal.o
|
||||
obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
|
||||
obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
|
||||
obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,384 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright 2025 NXP.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#define REG_SET 0x4
|
||||
#define REG_CLR 0x8
|
||||
#define REG_TOG 0xc
|
||||
|
||||
#define IMX91_TMU_CTRL0 0x0
|
||||
#define IMX91_TMU_CTRL0_THR1_IE BIT(9)
|
||||
#define IMX91_TMU_CTRL0_THR1_MASK GENMASK(3, 2)
|
||||
#define IMX91_TMU_CTRL0_CLR_FLT1 BIT(21)
|
||||
|
||||
#define IMX91_TMU_THR_MODE_LE 0
|
||||
#define IMX91_TMU_THR_MODE_GE 1
|
||||
|
||||
#define IMX91_TMU_STAT0 0x10
|
||||
#define IMX91_TMU_STAT0_THR1_IF BIT(9)
|
||||
#define IMX91_TMU_STAT0_THR1_STAT BIT(13)
|
||||
#define IMX91_TMU_STAT0_DRDY0_IF_MASK BIT(16)
|
||||
|
||||
#define IMX91_TMU_DATA0 0x20
|
||||
|
||||
#define IMX91_TMU_CTRL1 0x200
|
||||
#define IMX91_TMU_CTRL1_EN BIT(31)
|
||||
#define IMX91_TMU_CTRL1_START BIT(30)
|
||||
#define IMX91_TMU_CTRL1_STOP BIT(29)
|
||||
#define IMX91_TMU_CTRL1_RES_MASK GENMASK(19, 18)
|
||||
#define IMX91_TMU_CTRL1_MEAS_MODE_MASK GENMASK(25, 24)
|
||||
#define IMX91_TMU_CTRL1_MEAS_MODE_SINGLE 0
|
||||
#define IMX91_TMU_CTRL1_MEAS_MODE_CONTINUES 1
|
||||
#define IMX91_TMU_CTRL1_MEAS_MODE_PERIODIC 2
|
||||
|
||||
#define IMX91_TMU_THR_CTRL01 0x30
|
||||
#define IMX91_TMU_THR_CTRL01_THR1_MASK GENMASK(31, 16)
|
||||
|
||||
#define IMX91_TMU_REF_DIV 0x280
|
||||
#define IMX91_TMU_DIV_EN BIT(31)
|
||||
#define IMX91_TMU_DIV_MASK GENMASK(23, 16)
|
||||
#define IMX91_TMU_DIV_MAX 255
|
||||
|
||||
#define IMX91_TMU_PUD_ST_CTRL 0x2b0
|
||||
#define IMX91_TMU_PUDL_MASK GENMASK(23, 16)
|
||||
|
||||
#define IMX91_TMU_TRIM1 0x2e0
|
||||
#define IMX91_TMU_TRIM2 0x2f0
|
||||
|
||||
#define IMX91_TMU_TEMP_LOW_LIMIT -40000
|
||||
#define IMX91_TMU_TEMP_HIGH_LIMIT 125000
|
||||
|
||||
#define IMX91_TMU_DEFAULT_TRIM1_CONFIG 0xb561bc2d
|
||||
#define IMX91_TMU_DEFAULT_TRIM2_CONFIG 0x65d4
|
||||
|
||||
#define IMX91_TMU_PERIOD_CTRL 0x270
|
||||
#define IMX91_TMU_PERIOD_CTRL_MEAS_MASK GENMASK(23, 0)
|
||||
|
||||
#define IMX91_TMP_FRAC 64
|
||||
|
||||
struct imx91_tmu {
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
struct thermal_zone_device *tzd;
|
||||
};
|
||||
|
||||
static void imx91_tmu_start(struct imx91_tmu *tmu, bool start)
|
||||
{
|
||||
u32 val = start ? IMX91_TMU_CTRL1_START : IMX91_TMU_CTRL1_STOP;
|
||||
|
||||
writel_relaxed(val, tmu->base + IMX91_TMU_CTRL1 + REG_SET);
|
||||
}
|
||||
|
||||
static void imx91_tmu_enable(struct imx91_tmu *tmu, bool enable)
|
||||
{
|
||||
u32 reg = IMX91_TMU_CTRL1;
|
||||
|
||||
reg += enable ? REG_SET : REG_CLR;
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL1_EN, tmu->base + reg);
|
||||
}
|
||||
|
||||
static int imx91_tmu_to_mcelsius(int x)
|
||||
{
|
||||
return x * MILLIDEGREE_PER_DEGREE / IMX91_TMP_FRAC;
|
||||
}
|
||||
|
||||
static int imx91_tmu_from_mcelsius(int x)
|
||||
{
|
||||
return x * IMX91_TMP_FRAC / MILLIDEGREE_PER_DEGREE;
|
||||
}
|
||||
|
||||
static int imx91_tmu_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
{
|
||||
struct imx91_tmu *tmu = thermal_zone_device_priv(tz);
|
||||
s16 data;
|
||||
|
||||
/* DATA0 is 16bit signed number */
|
||||
data = readw_relaxed(tmu->base + IMX91_TMU_DATA0);
|
||||
*temp = imx91_tmu_to_mcelsius(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx91_tmu_set_trips(struct thermal_zone_device *tz, int low, int high)
|
||||
{
|
||||
struct imx91_tmu *tmu = thermal_zone_device_priv(tz);
|
||||
int val;
|
||||
|
||||
if (high >= IMX91_TMU_TEMP_HIGH_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR);
|
||||
|
||||
/* Comparator1 for temperature threshold */
|
||||
writel_relaxed(IMX91_TMU_THR_CTRL01_THR1_MASK, tmu->base + IMX91_TMU_THR_CTRL01 + REG_CLR);
|
||||
val = FIELD_PREP(IMX91_TMU_THR_CTRL01_THR1_MASK, imx91_tmu_from_mcelsius(high));
|
||||
|
||||
writel_relaxed(val, tmu->base + IMX91_TMU_THR_CTRL01 + REG_SET);
|
||||
|
||||
writel_relaxed(IMX91_TMU_STAT0_THR1_IF, tmu->base + IMX91_TMU_STAT0 + REG_CLR);
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx91_init_from_nvmem_cells(struct imx91_tmu *tmu)
|
||||
{
|
||||
struct device *dev = tmu->dev;
|
||||
u32 trim1, trim2;
|
||||
int ret;
|
||||
|
||||
ret = nvmem_cell_read_u32(dev, "trim1", &trim1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nvmem_cell_read_u32(dev, "trim2", &trim2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (trim1 == 0 || trim2 == 0)
|
||||
return -EINVAL;
|
||||
|
||||
writel_relaxed(trim1, tmu->base + IMX91_TMU_TRIM1);
|
||||
writel_relaxed(trim2, tmu->base + IMX91_TMU_TRIM2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imx91_tmu_action_remove(void *data)
|
||||
{
|
||||
struct imx91_tmu *tmu = data;
|
||||
|
||||
/* disable tmu */
|
||||
imx91_tmu_enable(tmu, false);
|
||||
}
|
||||
|
||||
static irqreturn_t imx91_tmu_alarm_irq(int irq, void *data)
|
||||
{
|
||||
struct imx91_tmu *tmu = data;
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(tmu->base + IMX91_TMU_STAT0);
|
||||
|
||||
/* Check if comparison interrupt occurred */
|
||||
if (val & IMX91_TMU_STAT0_THR1_IF) {
|
||||
/* Clear irq flag and disable interrupt until reconfigured */
|
||||
writel(IMX91_TMU_STAT0_THR1_IF, tmu->base + IMX91_TMU_STAT0 + REG_CLR);
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR);
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static irqreturn_t imx91_tmu_alarm_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct imx91_tmu *tmu = data;
|
||||
|
||||
thermal_zone_device_update(tmu->tzd, THERMAL_EVENT_UNSPECIFIED);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int imx91_tmu_change_mode(struct thermal_zone_device *tz, enum thermal_device_mode mode)
|
||||
{
|
||||
struct imx91_tmu *tmu = thermal_zone_device_priv(tz);
|
||||
int ret;
|
||||
|
||||
if (mode == THERMAL_DEVICE_ENABLED) {
|
||||
ret = pm_runtime_get(tmu->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE | IMX91_TMU_CTRL0_THR1_MASK,
|
||||
tmu->base + IMX91_TMU_CTRL0 + REG_CLR);
|
||||
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL0_THR1_MASK, IMX91_TMU_THR_MODE_GE),
|
||||
tmu->base + IMX91_TMU_CTRL0 + REG_SET);
|
||||
imx91_tmu_start(tmu, true);
|
||||
} else {
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR);
|
||||
imx91_tmu_start(tmu, false);
|
||||
pm_runtime_put(tmu->dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_zone_device_ops tmu_tz_ops = {
|
||||
.get_temp = imx91_tmu_get_temp,
|
||||
.change_mode = imx91_tmu_change_mode,
|
||||
.set_trips = imx91_tmu_set_trips,
|
||||
};
|
||||
|
||||
static int imx91_tmu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct imx91_tmu *tmu;
|
||||
unsigned long rate;
|
||||
int irq, ret;
|
||||
u32 div;
|
||||
|
||||
tmu = devm_kzalloc(dev, sizeof(struct imx91_tmu), GFP_KERNEL);
|
||||
if (!tmu)
|
||||
return -ENOMEM;
|
||||
|
||||
tmu->dev = dev;
|
||||
|
||||
tmu->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(tmu->base))
|
||||
return dev_err_probe(dev, PTR_ERR(tmu->base), "failed to get io resource");
|
||||
|
||||
tmu->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(tmu->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(tmu->clk), "failed to get tmu clock\n");
|
||||
|
||||
platform_set_drvdata(pdev, tmu);
|
||||
|
||||
/* disable the monitor during initialization */
|
||||
imx91_tmu_enable(tmu, false);
|
||||
imx91_tmu_start(tmu, false);
|
||||
|
||||
ret = imx91_init_from_nvmem_cells(tmu);
|
||||
if (ret) {
|
||||
dev_warn(dev, "can't get trim value, use default settings\n");
|
||||
|
||||
writel_relaxed(IMX91_TMU_DEFAULT_TRIM1_CONFIG, tmu->base + IMX91_TMU_TRIM1);
|
||||
writel_relaxed(IMX91_TMU_DEFAULT_TRIM2_CONFIG, tmu->base + IMX91_TMU_TRIM2);
|
||||
}
|
||||
|
||||
/* The typical conv clk is 4MHz, the output freq is 'rate / (div + 1)' */
|
||||
rate = clk_get_rate(tmu->clk);
|
||||
div = (rate / (4 * HZ_PER_MHZ)) - 1;
|
||||
if (div > IMX91_TMU_DIV_MAX)
|
||||
return dev_err_probe(dev, -EINVAL, "clock divider exceed hardware limitation");
|
||||
|
||||
/* Set divider value and enable divider */
|
||||
writel_relaxed(IMX91_TMU_DIV_EN | FIELD_PREP(IMX91_TMU_DIV_MASK, div),
|
||||
tmu->base + IMX91_TMU_REF_DIV);
|
||||
|
||||
/* Set max power up delay: 'Tpud(ms) = 0xFF * 1000 / 4000000' */
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_PUDL_MASK, 100U), tmu->base + IMX91_TMU_PUD_ST_CTRL);
|
||||
|
||||
/*
|
||||
* Set resolution mode
|
||||
* 00b - Conversion time = 0.59325 ms
|
||||
* 01b - Conversion time = 1.10525 ms
|
||||
* 10b - Conversion time = 2.12925 ms
|
||||
* 11b - Conversion time = 4.17725 ms
|
||||
*/
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL1_RES_MASK, 0x3),
|
||||
tmu->base + IMX91_TMU_CTRL1 + REG_CLR);
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL1_RES_MASK, 0x1),
|
||||
tmu->base + IMX91_TMU_CTRL1 + REG_SET);
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL1_MEAS_MODE_MASK, tmu->base + IMX91_TMU_CTRL1 + REG_CLR);
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL1_MEAS_MODE_MASK,
|
||||
IMX91_TMU_CTRL1_MEAS_MODE_PERIODIC),
|
||||
tmu->base + IMX91_TMU_CTRL1 + REG_SET);
|
||||
|
||||
/*
|
||||
* Set Periodic Measurement Frequency to 25Hz:
|
||||
* tMEAS_FREQ = tCONV_CLK * PERIOD_CTRL[MEAS_FREQ]
|
||||
*/
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_PERIOD_CTRL_MEAS_MASK, 4 * HZ_PER_MHZ / 25),
|
||||
tmu->base + IMX91_TMU_PERIOD_CTRL);
|
||||
|
||||
imx91_tmu_enable(tmu, true);
|
||||
ret = devm_add_action(dev, imx91_tmu_action_remove, tmu);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failure to add action imx91_tmu_action_remove()\n");
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_get_noresume(dev);
|
||||
ret = devm_pm_runtime_enable(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tmu->tzd = devm_thermal_of_zone_register(dev, 0, tmu, &tmu_tz_ops);
|
||||
if (IS_ERR(tmu->tzd))
|
||||
return dev_err_probe(dev, PTR_ERR(tmu->tzd),
|
||||
"failed to register thermal zone sensor\n");
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, imx91_tmu_alarm_irq,
|
||||
imx91_tmu_alarm_irq_thread,
|
||||
IRQF_ONESHOT, "imx91_thermal", tmu);
|
||||
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "failed to request alarm irq\n");
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx91_tmu_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct imx91_tmu *tmu = dev_get_drvdata(dev);
|
||||
|
||||
/* disable tmu */
|
||||
imx91_tmu_enable(tmu, false);
|
||||
|
||||
clk_disable_unprepare(tmu->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx91_tmu_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct imx91_tmu *tmu = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(tmu->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
imx91_tmu_enable(tmu, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_RUNTIME_DEV_PM_OPS(imx91_tmu_pm_ops, imx91_tmu_runtime_suspend,
|
||||
imx91_tmu_runtime_resume, NULL);
|
||||
|
||||
static const struct of_device_id imx91_tmu_table[] = {
|
||||
{ .compatible = "fsl,imx91-tmu", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx91_tmu_table);
|
||||
|
||||
static struct platform_driver imx91_tmu = {
|
||||
.driver = {
|
||||
.name = "imx91_thermal",
|
||||
.pm = pm_ptr(&imx91_tmu_pm_ops),
|
||||
.of_match_table = imx91_tmu_table,
|
||||
},
|
||||
.probe = imx91_tmu_probe,
|
||||
};
|
||||
module_platform_driver(imx91_tmu);
|
||||
|
||||
MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
|
||||
MODULE_DESCRIPTION("i.MX91 Thermal Monitor Unit driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -44,7 +44,8 @@ config INTEL_SOC_DTS_IOSF_CORE
|
|||
|
||||
config INTEL_SOC_DTS_THERMAL
|
||||
tristate "Intel SoCs DTS thermal driver"
|
||||
depends on X86 && PCI && ACPI
|
||||
depends on X86_64 && PCI && ACPI && NET
|
||||
select INT340X_THERMAL
|
||||
select INTEL_SOC_DTS_IOSF_CORE
|
||||
help
|
||||
Enable this to register Intel SoCs (e.g. Bay Trail) platform digital
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#define INT3400_ODVP_CHANGED 0x88
|
||||
#define INT3400_KEEP_ALIVE 0xA0
|
||||
#define INT3400_FAKE_TEMP (20 * 1000) /* faked temp sensor with 20C */
|
||||
/* UUID prefix length for comparison - sufficient for all UUIDs */
|
||||
#define INT3400_UUID_PREFIX_LEN 7
|
||||
|
||||
enum int3400_thermal_uuid {
|
||||
INT3400_THERMAL_ACTIVE = 0,
|
||||
|
|
@ -112,7 +114,7 @@ static ssize_t available_uuids_show(struct device *dev,
|
|||
int length = 0;
|
||||
|
||||
if (!priv->uuid_bitmap)
|
||||
return sprintf(buf, "UNKNOWN\n");
|
||||
return sysfs_emit(buf, "UNKNOWN\n");
|
||||
|
||||
for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) {
|
||||
if (priv->uuid_bitmap & (1 << i))
|
||||
|
|
@ -129,7 +131,7 @@ static ssize_t current_uuid_show(struct device *dev,
|
|||
int i, length = 0;
|
||||
|
||||
if (priv->current_uuid_index >= 0)
|
||||
return sprintf(buf, "%s\n",
|
||||
return sysfs_emit(buf, "%s\n",
|
||||
int3400_thermal_uuids[priv->current_uuid_index]);
|
||||
|
||||
for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) {
|
||||
|
|
@ -140,7 +142,7 @@ static ssize_t current_uuid_show(struct device *dev,
|
|||
if (length)
|
||||
return length;
|
||||
|
||||
return sprintf(buf, "INVALID\n");
|
||||
return sysfs_emit(buf, "INVALID\n");
|
||||
}
|
||||
|
||||
static int int3400_thermal_run_osc(acpi_handle handle, char *uuid_str, int *enable)
|
||||
|
|
@ -199,7 +201,7 @@ static ssize_t current_uuid_store(struct device *dev,
|
|||
|
||||
for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; ++i) {
|
||||
if (!strncmp(buf, int3400_thermal_uuids[i],
|
||||
sizeof(int3400_thermal_uuids[i]) - 1)) {
|
||||
INT3400_UUID_PREFIX_LEN)) {
|
||||
/*
|
||||
* If we have a list of supported UUIDs, make sure
|
||||
* this one is supported.
|
||||
|
|
@ -340,7 +342,7 @@ static ssize_t odvp_show(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
odvp_attr = container_of(attr, struct odvp_attr, attr);
|
||||
|
||||
return sprintf(buf, "%d\n", odvp_attr->priv->odvp[odvp_attr->odvp]);
|
||||
return sysfs_emit(buf, "%d\n", odvp_attr->priv->odvp[odvp_attr->odvp]);
|
||||
}
|
||||
|
||||
static void cleanup_odvp(struct int3400_thermal_priv *priv)
|
||||
|
|
@ -691,6 +693,7 @@ static const struct acpi_device_id int3400_thermal_match[] = {
|
|||
{"INTC10A0", 0},
|
||||
{"INTC10D4", 0},
|
||||
{"INTC10FC", 0},
|
||||
{"INTC10F3", 0},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -277,6 +277,7 @@ static const struct acpi_device_id int3403_device_ids[] = {
|
|||
{"INTC10A1", 0},
|
||||
{"INTC10D5", 0},
|
||||
{"INTC10FD", 0},
|
||||
{"INTC10F4", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, int3403_device_ids);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#define PCI_DEVICE_ID_INTEL_JSL_THERMAL 0x4E03
|
||||
#define PCI_DEVICE_ID_INTEL_LNLM_THERMAL 0x641D
|
||||
#define PCI_DEVICE_ID_INTEL_MTLP_THERMAL 0x7D03
|
||||
#define PCI_DEVICE_ID_INTEL_NVL_H_THERMAL 0xD703
|
||||
#define PCI_DEVICE_ID_INTEL_NVL_S_THERMAL 0xAD03
|
||||
#define PCI_DEVICE_ID_INTEL_RPL_THERMAL 0xA71D
|
||||
#define PCI_DEVICE_ID_INTEL_SKL_THERMAL 0x1903
|
||||
#define PCI_DEVICE_ID_INTEL_TGL_THERMAL 0x9A03
|
||||
|
|
|
|||
|
|
@ -504,6 +504,16 @@ static const struct pci_device_id proc_thermal_pci_ids[] = {
|
|||
PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DLVR |
|
||||
PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_HINT |
|
||||
PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC) },
|
||||
{ PCI_DEVICE_DATA(INTEL, NVL_H_THERMAL, PROC_THERMAL_FEATURE_RAPL |
|
||||
PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS |
|
||||
PROC_THERMAL_FEATURE_MSI_SUPPORT | PROC_THERMAL_FEATURE_WT_HINT |
|
||||
PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC |
|
||||
PROC_THERMAL_FEATURE_SOC_POWER_SLIDER) },
|
||||
{ PCI_DEVICE_DATA(INTEL, NVL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL |
|
||||
PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS |
|
||||
PROC_THERMAL_FEATURE_MSI_SUPPORT | PROC_THERMAL_FEATURE_WT_HINT |
|
||||
PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC |
|
||||
PROC_THERMAL_FEATURE_SOC_POWER_SLIDER) },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,17 @@ static const struct mapping_table lnl_dlvr_mapping[] = {
|
|||
{NULL, 0, NULL},
|
||||
};
|
||||
|
||||
static const struct mmio_reg nvl_dlvr_mmio_regs[] = {
|
||||
{ 0, 0x19208, 5, 0x1F, 0}, /* dlvr_spread_spectrum_pct */
|
||||
{ 0, 0x19208, 1, 0x1, 5}, /* dlvr_control_mode */
|
||||
{ 0, 0x19208, 1, 0x1, 6}, /* dlvr_control_lock */
|
||||
{ 0, 0x19208, 1, 0x1, 7}, /* dlvr_rfim_enable */
|
||||
{ 0, 0x19208, 12, 0xFFF, 8}, /* dlvr_freq_select */
|
||||
{ 1, 0x19210, 2, 0x3, 30}, /* dlvr_hardware_rev */
|
||||
{ 1, 0x19210, 16, 0xFFFF, 0}, /* dlvr_freq_mhz */
|
||||
{ 1, 0x19210, 1, 0x1, 16}, /* dlvr_pll_busy */
|
||||
};
|
||||
|
||||
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)
|
||||
|
|
@ -446,6 +457,10 @@ int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc
|
|||
dlvr_mmio_regs_table = lnl_dlvr_mmio_regs;
|
||||
dlvr_mapping = lnl_dlvr_mapping;
|
||||
break;
|
||||
case PCI_DEVICE_ID_INTEL_NVL_H_THERMAL:
|
||||
case PCI_DEVICE_ID_INTEL_NVL_S_THERMAL:
|
||||
dlvr_mmio_regs_table = nvl_dlvr_mmio_regs;
|
||||
break;
|
||||
default:
|
||||
dlvr_mmio_regs_table = dlvr_mmio_regs;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* R-Car Gen3 THS thermal sensor driver
|
||||
* R-Car Gen3, Gen4 and RZ/G2 THS thermal sensor driver
|
||||
* Based on rcar_thermal.c and work from Hien Dang and Khiem Nguyen.
|
||||
*
|
||||
* Copyright (C) 2016 Renesas Electronics Corporation.
|
||||
|
|
@ -601,7 +601,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev)
|
||||
static int rcar_gen3_thermal_resume(struct device *dev)
|
||||
{
|
||||
struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
|
||||
unsigned int i;
|
||||
|
|
@ -615,13 +615,13 @@ static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, NULL,
|
||||
rcar_gen3_thermal_resume);
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, NULL,
|
||||
rcar_gen3_thermal_resume);
|
||||
|
||||
static struct platform_driver rcar_gen3_thermal_driver = {
|
||||
.driver = {
|
||||
.name = "rcar_gen3_thermal",
|
||||
.pm = &rcar_gen3_thermal_pm_ops,
|
||||
.pm = pm_sleep_ptr(&rcar_gen3_thermal_pm_ops),
|
||||
.of_match_table = rcar_gen3_thermal_dt_ids,
|
||||
},
|
||||
.probe = rcar_gen3_thermal_probe,
|
||||
|
|
|
|||
|
|
@ -534,7 +534,6 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int rcar_thermal_suspend(struct device *dev)
|
||||
{
|
||||
struct rcar_thermal_common *common = dev_get_drvdata(dev);
|
||||
|
|
@ -567,15 +566,14 @@ static int rcar_thermal_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,
|
||||
rcar_thermal_resume);
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,
|
||||
rcar_thermal_resume);
|
||||
|
||||
static struct platform_driver rcar_thermal_driver = {
|
||||
.driver = {
|
||||
.name = "rcar_thermal",
|
||||
.pm = &rcar_thermal_pm_ops,
|
||||
.pm = pm_sleep_ptr(&rcar_thermal_pm_ops),
|
||||
.of_match_table = rcar_thermal_dt_ids,
|
||||
},
|
||||
.probe = rcar_thermal_probe,
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (options.daemonize && daemon(0, 0)) {
|
||||
ERROR("Failed to daemonize: %p\n");
|
||||
ERROR("Failed to daemonize: %m\n");
|
||||
return THERMAL_ENGINE_DAEMON_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue