Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+660 -116
+1
Documentation/admin-guide/thermal/index.rst
··· 6 6 :maxdepth: 1 7 7 8 8 intel_powerclamp 9 + intel_thermal_throttle
+91
Documentation/admin-guide/thermal/intel_thermal_throttle.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: <isonum.txt> 3 + 4 + ======================================= 5 + Intel thermal throttle events reporting 6 + ======================================= 7 + 8 + :Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> 9 + 10 + Introduction 11 + ------------ 12 + 13 + Intel processors have built in automatic and adaptive thermal monitoring 14 + mechanisms that force the processor to reduce its power consumption in order 15 + to operate within predetermined temperature limits. 16 + 17 + Refer to section "THERMAL MONITORING AND PROTECTION" in the "Intel® 64 and 18 + IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B, 3C, & 3D): 19 + System Programming Guide" for more details. 20 + 21 + In general, there are two mechanisms to control the core temperature of the 22 + processor. They are called "Thermal Monitor 1 (TM1) and Thermal Monitor 2 (TM2)". 23 + 24 + The status of the temperature sensor that triggers the thermal monitor (TM1/TM2) 25 + is indicated through the "thermal status flag" and "thermal status log flag" in 26 + MSR_IA32_THERM_STATUS for core level and MSR_IA32_PACKAGE_THERM_STATUS for 27 + package level. 28 + 29 + Thermal Status flag, bit 0 — When set, indicates that the processor core 30 + temperature is currently at the trip temperature of the thermal monitor and that 31 + the processor power consumption is being reduced via either TM1 or TM2, depending 32 + on which is enabled. When clear, the flag indicates that the core temperature is 33 + below the thermal monitor trip temperature. This flag is read only. 34 + 35 + Thermal Status Log flag, bit 1 — When set, indicates that the thermal sensor has 36 + tripped since the last power-up or reset or since the last time that software 37 + cleared this flag. This flag is a sticky bit; once set it remains set until 38 + cleared by software or until a power-up or reset of the processor. The default 39 + state is clear. 40 + 41 + It is possible that when user reads MSR_IA32_THERM_STATUS or 42 + MSR_IA32_PACKAGE_THERM_STATUS, TM1/TM2 is not active. In this case, 43 + "Thermal Status flag" will read "0" and the "Thermal Status Log flag" will be set 44 + to show any previous "TM1/TM2" activation. But since it needs to be cleared by 45 + the software, it can't show the number of occurrences of "TM1/TM2" activations. 46 + 47 + Hence, Linux provides counters of how many times the "Thermal Status flag" was 48 + set. Also presents how long the "Thermal Status flag" was active in milliseconds. 49 + Using these counters, users can check if the performance was limited because of 50 + thermal events. It is recommended to read from sysfs instead of directly reading 51 + MSRs as the "Thermal Status Log flag" is reset by the driver to implement rate 52 + control. 53 + 54 + Sysfs Interface 55 + --------------- 56 + 57 + Thermal throttling events are presented for each CPU under 58 + "/sys/devices/system/cpu/cpuX/thermal_throttle/", where "X" is the CPU number. 59 + 60 + All these counters are read-only. They can't be reset to 0. So, they can potentially 61 + overflow after reaching the maximum 64 bit unsigned integer. 62 + 63 + ``core_throttle_count`` 64 + Shows the number of times "Thermal Status flag" changed from 0 to 1 for this 65 + CPU since OS boot and thermal vector is initialized. This is a 64 bit counter. 66 + 67 + ``package_throttle_count`` 68 + Shows the number of times "Thermal Status flag" changed from 0 to 1 for the 69 + package containing this CPU since OS boot and thermal vector is initialized. 70 + Package status is broadcast to all CPUs; all CPUs in the package increment 71 + this count. This is a 64-bit counter. 72 + 73 + ``core_throttle_max_time_ms`` 74 + Shows the maximum amount of time for which "Thermal Status flag" has been 75 + set to 1 for this CPU at the core level since OS boot and thermal vector 76 + is initialized. 77 + 78 + ``package_throttle_max_time_ms`` 79 + Shows the maximum amount of time for which "Thermal Status flag" has been 80 + set to 1 for the package containing this CPU since OS boot and thermal 81 + vector is initialized. 82 + 83 + ``core_throttle_total_time_ms`` 84 + Shows the cumulative time for which "Thermal Status flag" has been 85 + set to 1 for this CPU for core level since OS boot and thermal vector 86 + is initialized. 87 + 88 + ``package_throttle_total_time_ms`` 89 + Shows the cumulative time for which "Thermal Status flag" has been set 90 + to 1 for the package containing this CPU since OS boot and thermal vector 91 + is initialized.
+87
Documentation/devicetree/bindings/thermal/fsl,imx91-tmu.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/thermal/fsl,imx91-tmu.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: NXP i.MX91 Thermal 8 + 9 + maintainers: 10 + - Pengfei Li <pengfei.li_1@nxp.com> 11 + 12 + description: 13 + i.MX91 features a new temperature sensor. It includes programmable 14 + temperature threshold comparators for both normal and privileged 15 + accesses and allows a programmable measurement frequency for the 16 + Periodic One-Shot Measurement mode. Additionally, it provides 17 + status registers for indicating the end of measurement and threshold 18 + violation events. 19 + 20 + properties: 21 + compatible: 22 + items: 23 + - const: fsl,imx91-tmu 24 + 25 + reg: 26 + maxItems: 1 27 + 28 + clocks: 29 + maxItems: 1 30 + 31 + interrupts: 32 + items: 33 + - description: Comparator 1 irq 34 + - description: Comparator 2 irq 35 + - description: Data ready irq 36 + 37 + interrupt-names: 38 + items: 39 + - const: thr1 40 + - const: thr2 41 + - const: ready 42 + 43 + nvmem-cells: 44 + items: 45 + - description: Phandle to the trim control 1 provided by ocotp 46 + - description: Phandle to the trim control 2 provided by ocotp 47 + 48 + nvmem-cell-names: 49 + items: 50 + - const: trim1 51 + - const: trim2 52 + 53 + "#thermal-sensor-cells": 54 + const: 0 55 + 56 + required: 57 + - compatible 58 + - reg 59 + - clocks 60 + - interrupts 61 + - interrupt-names 62 + 63 + allOf: 64 + - $ref: thermal-sensor.yaml 65 + 66 + unevaluatedProperties: false 67 + 68 + examples: 69 + - | 70 + #include <dt-bindings/interrupt-controller/arm-gic.h> 71 + #include <dt-bindings/clock/imx93-clock.h> 72 + 73 + thermal-sensor@44482000 { 74 + compatible = "fsl,imx91-tmu"; 75 + reg = <0x44482000 0x1000>; 76 + #thermal-sensor-cells = <0>; 77 + clocks = <&clk IMX93_CLK_TMC_GATE>; 78 + interrupt-parent = <&gic>; 79 + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>, 80 + <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>, 81 + <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; 82 + interrupt-names = "thr1", "thr2", "ready"; 83 + nvmem-cells = <&tmu_trim1>, <&tmu_trim2>; 84 + nvmem-cell-names = "trim1", "trim2"; 85 + }; 86 + 87 + ...
+8 -1
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
··· 36 36 - qcom,msm8974-tsens 37 37 - const: qcom,tsens-v0_1 38 38 39 + - description: 40 + v1 of TSENS without RPM which requires to be explicitly reset 41 + and enabled in the driver. 42 + enum: 43 + - qcom,ipq5018-tsens 44 + 39 45 - description: v1 of TSENS 40 46 items: 41 47 - enum: 42 - - qcom,ipq5018-tsens 43 48 - qcom,msm8937-tsens 44 49 - qcom,msm8956-tsens 45 50 - qcom,msm8976-tsens ··· 55 50 items: 56 51 - enum: 57 52 - qcom,glymur-tsens 53 + - qcom,kaanapali-tsens 58 54 - qcom,milos-tsens 59 55 - qcom,msm8953-tsens 60 56 - qcom,msm8996-tsens 61 57 - qcom,msm8998-tsens 62 58 - qcom,qcm2290-tsens 59 + - qcom,qcs8300-tsens 63 60 - qcom,qcs615-tsens 64 61 - qcom,sa8255p-tsens 65 62 - qcom,sa8775p-tsens
+5 -1
Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml
··· 16 16 17 17 properties: 18 18 compatible: 19 - const: renesas,r9a09g047-tsu 19 + oneOf: 20 + - const: renesas,r9a09g047-tsu # RZ/G3E 21 + - items: 22 + - const: renesas,r9a09g057-tsu # RZ/V2H 23 + - const: renesas,r9a09g047-tsu # RZ/G3E 20 24 21 25 reg: 22 26 maxItems: 1
+23
Documentation/driver-api/thermal/intel_dptf.rst
··· 409 409 Limit 1 from being exhausted. 410 410 411 411 4 – Unknown: Can't classify. 412 + 413 + On processors starting from Panther Lake additional hints are provided. 414 + The hardware analyzes workload residencies over an extended period to 415 + determine whether the workload classification tends toward idle/battery 416 + life states or sustained/performance states. Based on this long-term 417 + analysis, it classifies: 418 + 419 + Power Classification: If the workload exhibits more idle or battery life 420 + residencies, it is classified as "power". 421 + 422 + Performance Classification: If the workload exhibits more sustained or 423 + performance residencies, it is classified as "performance". 424 + 425 + This approach enables applications to ignore short-term workload 426 + fluctuations and instead respond to longer-term power vs. performance 427 + trends. 428 + 429 + Residency thresholds for this classification are CPU generation-specific. 430 + Classification is reported via bit 4 of the workload_type_index: 431 + 432 + Bit 4 = 1: Power classification 433 + 434 + Bit 4 = 0: Performance classification
-1
drivers/acpi/dptf/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 - obj-$(CONFIG_ACPI) += int340x_thermal.o 3 2 obj-$(CONFIG_DPTF_POWER) += dptf_power.o 4 3 obj-$(CONFIG_DPTF_PCH_FIVR) += dptf_pch_fivr.o
+2
drivers/acpi/dptf/dptf_power.c
··· 240 240 {"INTC10D9", 0}, 241 241 {"INTC1100", 0}, 242 242 {"INTC1101", 0}, 243 + {"INTC10F7", 0}, 244 + {"INTC10F8", 0}, 243 245 {"", 0}, 244 246 }; 245 247 MODULE_DEVICE_TABLE(acpi, int3407_device_ids);
-94
drivers/acpi/dptf/int340x_thermal.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * ACPI support for int340x thermal drivers 4 - * 5 - * Copyright (C) 2014, Intel Corporation 6 - * Authors: Zhang Rui <rui.zhang@intel.com> 7 - */ 8 - 9 - #include <linux/acpi.h> 10 - #include <linux/module.h> 11 - 12 - #include "../internal.h" 13 - 14 - #define INT3401_DEVICE 0X01 15 - static const struct acpi_device_id int340x_thermal_device_ids[] = { 16 - {"INT3400"}, 17 - {"INT3401", INT3401_DEVICE}, 18 - {"INT3402"}, 19 - {"INT3403"}, 20 - {"INT3404"}, 21 - {"INT3406"}, 22 - {"INT3407"}, 23 - {"INT3408"}, 24 - {"INT3409"}, 25 - {"INT340A"}, 26 - {"INT340B"}, 27 - {"INT3532"}, 28 - {"INTC1040"}, 29 - {"INTC1041"}, 30 - {"INTC1042"}, 31 - {"INTC1043"}, 32 - {"INTC1044"}, 33 - {"INTC1045"}, 34 - {"INTC1046"}, 35 - {"INTC1047"}, 36 - {"INTC1048"}, 37 - {"INTC1049"}, 38 - {"INTC1050"}, 39 - {"INTC1060"}, 40 - {"INTC1061"}, 41 - {"INTC1062"}, 42 - {"INTC1063"}, 43 - {"INTC1064"}, 44 - {"INTC1065"}, 45 - {"INTC1066"}, 46 - {"INTC1068"}, 47 - {"INTC1069"}, 48 - {"INTC106A"}, 49 - {"INTC106B"}, 50 - {"INTC106C"}, 51 - {"INTC106D"}, 52 - {"INTC10A0"}, 53 - {"INTC10A1"}, 54 - {"INTC10A2"}, 55 - {"INTC10A3"}, 56 - {"INTC10A4"}, 57 - {"INTC10A5"}, 58 - {"INTC10D4"}, 59 - {"INTC10D5"}, 60 - {"INTC10D6"}, 61 - {"INTC10D7"}, 62 - {"INTC10D8"}, 63 - {"INTC10D9"}, 64 - {"INTC10FC"}, 65 - {"INTC10FD"}, 66 - {"INTC10FE"}, 67 - {"INTC10FF"}, 68 - {"INTC1100"}, 69 - {"INTC1101"}, 70 - {"INTC1102"}, 71 - {""}, 72 - }; 73 - 74 - static int int340x_thermal_handler_attach(struct acpi_device *adev, 75 - const struct acpi_device_id *id) 76 - { 77 - if (IS_ENABLED(CONFIG_INT340X_THERMAL)) 78 - acpi_create_platform_device(adev, NULL); 79 - /* Intel SoC DTS thermal driver needs INT3401 to set IRQ descriptor */ 80 - else if (IS_ENABLED(CONFIG_INTEL_SOC_DTS_THERMAL) && 81 - id->driver_data == INT3401_DEVICE) 82 - acpi_create_platform_device(adev, NULL); 83 - return 1; 84 - } 85 - 86 - static struct acpi_scan_handler int340x_thermal_handler = { 87 - .ids = int340x_thermal_device_ids, 88 - .attach = int340x_thermal_handler_attach, 89 - }; 90 - 91 - void __init acpi_int340x_thermal_init(void) 92 - { 93 - acpi_scan_add_handler(&int340x_thermal_handler); 94 - }
+1
drivers/acpi/fan.h
··· 22 22 {"INTC10A2", }, /* Fan for Raptor Lake generation */ \ 23 23 {"INTC10D6", }, /* Fan for Panther Lake generation */ \ 24 24 {"INTC10FE", }, /* Fan for Wildcat Lake generation */ \ 25 + {"INTC10F5", }, /* Fan for Nova Lake generation */ \ 25 26 {"PNP0C0B", } /* Generic ACPI fan */ 26 27 27 28 #define ACPI_FPS_NAME_LEN 20
-1
drivers/acpi/internal.h
··· 27 27 void acpi_processor_init(void); 28 28 void acpi_platform_init(void); 29 29 void acpi_pnp_init(void); 30 - void acpi_int340x_thermal_init(void); 31 30 int acpi_sysfs_init(void); 32 31 void acpi_gpe_apply_masked_gpes(void); 33 32 void acpi_container_init(void);
-1
drivers/acpi/scan.c
··· 2711 2711 acpi_watchdog_init(); 2712 2712 acpi_pnp_init(); 2713 2713 acpi_power_resources_init(); 2714 - acpi_int340x_thermal_init(); 2715 2714 acpi_init_lpit(); 2716 2715 2717 2716 acpi_scan_add_handler(&generic_device_handler);
+10
drivers/thermal/Kconfig
··· 296 296 cpufreq is used as the cooling device to throttle CPUs when the passive 297 297 trip is crossed. 298 298 299 + config IMX91_THERMAL 300 + tristate "Temperature sensor driver for NXP i.MX91 SoC" 301 + depends on ARCH_MXC || COMPILE_TEST 302 + depends on OF 303 + help 304 + Include one sensor and six comparators. Each of them compares the 305 + temperature value (from the sensor) against the programmable 306 + threshold values. The direction of the comparison is configurable 307 + (greater / lesser than). 308 + 299 309 config K3_THERMAL 300 310 tristate "Texas Instruments K3 thermal support" 301 311 depends on ARCH_K3 || COMPILE_TEST
+1
drivers/thermal/Makefile
··· 51 51 obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o 52 52 obj-$(CONFIG_IMX_SC_THERMAL) += imx_sc_thermal.o 53 53 obj-$(CONFIG_IMX8MM_THERMAL) += imx8mm_thermal.o 54 + obj-$(CONFIG_IMX91_THERMAL) += imx91_thermal.o 54 55 obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o 55 56 obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o 56 57 obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o
+384
drivers/thermal/imx91_thermal.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2025 NXP. 4 + */ 5 + 6 + #include <linux/bitfield.h> 7 + #include <linux/clk.h> 8 + #include <linux/err.h> 9 + #include <linux/interrupt.h> 10 + #include <linux/iopoll.h> 11 + #include <linux/nvmem-consumer.h> 12 + #include <linux/module.h> 13 + #include <linux/of.h> 14 + #include <linux/of_device.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/pm_runtime.h> 17 + #include <linux/thermal.h> 18 + #include <linux/units.h> 19 + 20 + #define REG_SET 0x4 21 + #define REG_CLR 0x8 22 + #define REG_TOG 0xc 23 + 24 + #define IMX91_TMU_CTRL0 0x0 25 + #define IMX91_TMU_CTRL0_THR1_IE BIT(9) 26 + #define IMX91_TMU_CTRL0_THR1_MASK GENMASK(3, 2) 27 + #define IMX91_TMU_CTRL0_CLR_FLT1 BIT(21) 28 + 29 + #define IMX91_TMU_THR_MODE_LE 0 30 + #define IMX91_TMU_THR_MODE_GE 1 31 + 32 + #define IMX91_TMU_STAT0 0x10 33 + #define IMX91_TMU_STAT0_THR1_IF BIT(9) 34 + #define IMX91_TMU_STAT0_THR1_STAT BIT(13) 35 + #define IMX91_TMU_STAT0_DRDY0_IF_MASK BIT(16) 36 + 37 + #define IMX91_TMU_DATA0 0x20 38 + 39 + #define IMX91_TMU_CTRL1 0x200 40 + #define IMX91_TMU_CTRL1_EN BIT(31) 41 + #define IMX91_TMU_CTRL1_START BIT(30) 42 + #define IMX91_TMU_CTRL1_STOP BIT(29) 43 + #define IMX91_TMU_CTRL1_RES_MASK GENMASK(19, 18) 44 + #define IMX91_TMU_CTRL1_MEAS_MODE_MASK GENMASK(25, 24) 45 + #define IMX91_TMU_CTRL1_MEAS_MODE_SINGLE 0 46 + #define IMX91_TMU_CTRL1_MEAS_MODE_CONTINUES 1 47 + #define IMX91_TMU_CTRL1_MEAS_MODE_PERIODIC 2 48 + 49 + #define IMX91_TMU_THR_CTRL01 0x30 50 + #define IMX91_TMU_THR_CTRL01_THR1_MASK GENMASK(31, 16) 51 + 52 + #define IMX91_TMU_REF_DIV 0x280 53 + #define IMX91_TMU_DIV_EN BIT(31) 54 + #define IMX91_TMU_DIV_MASK GENMASK(23, 16) 55 + #define IMX91_TMU_DIV_MAX 255 56 + 57 + #define IMX91_TMU_PUD_ST_CTRL 0x2b0 58 + #define IMX91_TMU_PUDL_MASK GENMASK(23, 16) 59 + 60 + #define IMX91_TMU_TRIM1 0x2e0 61 + #define IMX91_TMU_TRIM2 0x2f0 62 + 63 + #define IMX91_TMU_TEMP_LOW_LIMIT -40000 64 + #define IMX91_TMU_TEMP_HIGH_LIMIT 125000 65 + 66 + #define IMX91_TMU_DEFAULT_TRIM1_CONFIG 0xb561bc2d 67 + #define IMX91_TMU_DEFAULT_TRIM2_CONFIG 0x65d4 68 + 69 + #define IMX91_TMU_PERIOD_CTRL 0x270 70 + #define IMX91_TMU_PERIOD_CTRL_MEAS_MASK GENMASK(23, 0) 71 + 72 + #define IMX91_TMP_FRAC 64 73 + 74 + struct imx91_tmu { 75 + void __iomem *base; 76 + struct clk *clk; 77 + struct device *dev; 78 + struct thermal_zone_device *tzd; 79 + }; 80 + 81 + static void imx91_tmu_start(struct imx91_tmu *tmu, bool start) 82 + { 83 + u32 val = start ? IMX91_TMU_CTRL1_START : IMX91_TMU_CTRL1_STOP; 84 + 85 + writel_relaxed(val, tmu->base + IMX91_TMU_CTRL1 + REG_SET); 86 + } 87 + 88 + static void imx91_tmu_enable(struct imx91_tmu *tmu, bool enable) 89 + { 90 + u32 reg = IMX91_TMU_CTRL1; 91 + 92 + reg += enable ? REG_SET : REG_CLR; 93 + 94 + writel_relaxed(IMX91_TMU_CTRL1_EN, tmu->base + reg); 95 + } 96 + 97 + static int imx91_tmu_to_mcelsius(int x) 98 + { 99 + return x * MILLIDEGREE_PER_DEGREE / IMX91_TMP_FRAC; 100 + } 101 + 102 + static int imx91_tmu_from_mcelsius(int x) 103 + { 104 + return x * IMX91_TMP_FRAC / MILLIDEGREE_PER_DEGREE; 105 + } 106 + 107 + static int imx91_tmu_get_temp(struct thermal_zone_device *tz, int *temp) 108 + { 109 + struct imx91_tmu *tmu = thermal_zone_device_priv(tz); 110 + s16 data; 111 + 112 + /* DATA0 is 16bit signed number */ 113 + data = readw_relaxed(tmu->base + IMX91_TMU_DATA0); 114 + *temp = imx91_tmu_to_mcelsius(data); 115 + 116 + return 0; 117 + } 118 + 119 + static int imx91_tmu_set_trips(struct thermal_zone_device *tz, int low, int high) 120 + { 121 + struct imx91_tmu *tmu = thermal_zone_device_priv(tz); 122 + int val; 123 + 124 + if (high >= IMX91_TMU_TEMP_HIGH_LIMIT) 125 + return -EINVAL; 126 + 127 + writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR); 128 + 129 + /* Comparator1 for temperature threshold */ 130 + writel_relaxed(IMX91_TMU_THR_CTRL01_THR1_MASK, tmu->base + IMX91_TMU_THR_CTRL01 + REG_CLR); 131 + val = FIELD_PREP(IMX91_TMU_THR_CTRL01_THR1_MASK, imx91_tmu_from_mcelsius(high)); 132 + 133 + writel_relaxed(val, tmu->base + IMX91_TMU_THR_CTRL01 + REG_SET); 134 + 135 + writel_relaxed(IMX91_TMU_STAT0_THR1_IF, tmu->base + IMX91_TMU_STAT0 + REG_CLR); 136 + 137 + writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_SET); 138 + 139 + return 0; 140 + } 141 + 142 + static int imx91_init_from_nvmem_cells(struct imx91_tmu *tmu) 143 + { 144 + struct device *dev = tmu->dev; 145 + u32 trim1, trim2; 146 + int ret; 147 + 148 + ret = nvmem_cell_read_u32(dev, "trim1", &trim1); 149 + if (ret) 150 + return ret; 151 + 152 + ret = nvmem_cell_read_u32(dev, "trim2", &trim2); 153 + if (ret) 154 + return ret; 155 + 156 + if (trim1 == 0 || trim2 == 0) 157 + return -EINVAL; 158 + 159 + writel_relaxed(trim1, tmu->base + IMX91_TMU_TRIM1); 160 + writel_relaxed(trim2, tmu->base + IMX91_TMU_TRIM2); 161 + 162 + return 0; 163 + } 164 + 165 + static void imx91_tmu_action_remove(void *data) 166 + { 167 + struct imx91_tmu *tmu = data; 168 + 169 + /* disable tmu */ 170 + imx91_tmu_enable(tmu, false); 171 + } 172 + 173 + static irqreturn_t imx91_tmu_alarm_irq(int irq, void *data) 174 + { 175 + struct imx91_tmu *tmu = data; 176 + u32 val; 177 + 178 + val = readl_relaxed(tmu->base + IMX91_TMU_STAT0); 179 + 180 + /* Check if comparison interrupt occurred */ 181 + if (val & IMX91_TMU_STAT0_THR1_IF) { 182 + /* Clear irq flag and disable interrupt until reconfigured */ 183 + writel(IMX91_TMU_STAT0_THR1_IF, tmu->base + IMX91_TMU_STAT0 + REG_CLR); 184 + writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR); 185 + 186 + return IRQ_WAKE_THREAD; 187 + } 188 + 189 + return IRQ_NONE; 190 + } 191 + 192 + static irqreturn_t imx91_tmu_alarm_irq_thread(int irq, void *data) 193 + { 194 + struct imx91_tmu *tmu = data; 195 + 196 + thermal_zone_device_update(tmu->tzd, THERMAL_EVENT_UNSPECIFIED); 197 + 198 + return IRQ_HANDLED; 199 + } 200 + 201 + static int imx91_tmu_change_mode(struct thermal_zone_device *tz, enum thermal_device_mode mode) 202 + { 203 + struct imx91_tmu *tmu = thermal_zone_device_priv(tz); 204 + int ret; 205 + 206 + if (mode == THERMAL_DEVICE_ENABLED) { 207 + ret = pm_runtime_get(tmu->dev); 208 + if (ret < 0) 209 + return ret; 210 + 211 + writel_relaxed(IMX91_TMU_CTRL0_THR1_IE | IMX91_TMU_CTRL0_THR1_MASK, 212 + tmu->base + IMX91_TMU_CTRL0 + REG_CLR); 213 + 214 + writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL0_THR1_MASK, IMX91_TMU_THR_MODE_GE), 215 + tmu->base + IMX91_TMU_CTRL0 + REG_SET); 216 + imx91_tmu_start(tmu, true); 217 + } else { 218 + writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR); 219 + imx91_tmu_start(tmu, false); 220 + pm_runtime_put(tmu->dev); 221 + } 222 + 223 + return 0; 224 + } 225 + 226 + static struct thermal_zone_device_ops tmu_tz_ops = { 227 + .get_temp = imx91_tmu_get_temp, 228 + .change_mode = imx91_tmu_change_mode, 229 + .set_trips = imx91_tmu_set_trips, 230 + }; 231 + 232 + static int imx91_tmu_probe(struct platform_device *pdev) 233 + { 234 + struct device *dev = &pdev->dev; 235 + struct imx91_tmu *tmu; 236 + unsigned long rate; 237 + int irq, ret; 238 + u32 div; 239 + 240 + tmu = devm_kzalloc(dev, sizeof(struct imx91_tmu), GFP_KERNEL); 241 + if (!tmu) 242 + return -ENOMEM; 243 + 244 + tmu->dev = dev; 245 + 246 + tmu->base = devm_platform_ioremap_resource(pdev, 0); 247 + if (IS_ERR(tmu->base)) 248 + return dev_err_probe(dev, PTR_ERR(tmu->base), "failed to get io resource"); 249 + 250 + tmu->clk = devm_clk_get_enabled(dev, NULL); 251 + if (IS_ERR(tmu->clk)) 252 + return dev_err_probe(dev, PTR_ERR(tmu->clk), "failed to get tmu clock\n"); 253 + 254 + platform_set_drvdata(pdev, tmu); 255 + 256 + /* disable the monitor during initialization */ 257 + imx91_tmu_enable(tmu, false); 258 + imx91_tmu_start(tmu, false); 259 + 260 + ret = imx91_init_from_nvmem_cells(tmu); 261 + if (ret) { 262 + dev_warn(dev, "can't get trim value, use default settings\n"); 263 + 264 + writel_relaxed(IMX91_TMU_DEFAULT_TRIM1_CONFIG, tmu->base + IMX91_TMU_TRIM1); 265 + writel_relaxed(IMX91_TMU_DEFAULT_TRIM2_CONFIG, tmu->base + IMX91_TMU_TRIM2); 266 + } 267 + 268 + /* The typical conv clk is 4MHz, the output freq is 'rate / (div + 1)' */ 269 + rate = clk_get_rate(tmu->clk); 270 + div = (rate / (4 * HZ_PER_MHZ)) - 1; 271 + if (div > IMX91_TMU_DIV_MAX) 272 + return dev_err_probe(dev, -EINVAL, "clock divider exceed hardware limitation"); 273 + 274 + /* Set divider value and enable divider */ 275 + writel_relaxed(IMX91_TMU_DIV_EN | FIELD_PREP(IMX91_TMU_DIV_MASK, div), 276 + tmu->base + IMX91_TMU_REF_DIV); 277 + 278 + /* Set max power up delay: 'Tpud(ms) = 0xFF * 1000 / 4000000' */ 279 + writel_relaxed(FIELD_PREP(IMX91_TMU_PUDL_MASK, 100U), tmu->base + IMX91_TMU_PUD_ST_CTRL); 280 + 281 + /* 282 + * Set resolution mode 283 + * 00b - Conversion time = 0.59325 ms 284 + * 01b - Conversion time = 1.10525 ms 285 + * 10b - Conversion time = 2.12925 ms 286 + * 11b - Conversion time = 4.17725 ms 287 + */ 288 + writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL1_RES_MASK, 0x3), 289 + tmu->base + IMX91_TMU_CTRL1 + REG_CLR); 290 + writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL1_RES_MASK, 0x1), 291 + tmu->base + IMX91_TMU_CTRL1 + REG_SET); 292 + 293 + writel_relaxed(IMX91_TMU_CTRL1_MEAS_MODE_MASK, tmu->base + IMX91_TMU_CTRL1 + REG_CLR); 294 + writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL1_MEAS_MODE_MASK, 295 + IMX91_TMU_CTRL1_MEAS_MODE_PERIODIC), 296 + tmu->base + IMX91_TMU_CTRL1 + REG_SET); 297 + 298 + /* 299 + * Set Periodic Measurement Frequency to 25Hz: 300 + * tMEAS_FREQ = tCONV_CLK * PERIOD_CTRL[MEAS_FREQ] 301 + */ 302 + writel_relaxed(FIELD_PREP(IMX91_TMU_PERIOD_CTRL_MEAS_MASK, 4 * HZ_PER_MHZ / 25), 303 + tmu->base + IMX91_TMU_PERIOD_CTRL); 304 + 305 + imx91_tmu_enable(tmu, true); 306 + ret = devm_add_action(dev, imx91_tmu_action_remove, tmu); 307 + if (ret) 308 + return dev_err_probe(dev, ret, "Failure to add action imx91_tmu_action_remove()\n"); 309 + 310 + pm_runtime_set_active(dev); 311 + pm_runtime_get_noresume(dev); 312 + ret = devm_pm_runtime_enable(dev); 313 + if (ret) 314 + return ret; 315 + 316 + tmu->tzd = devm_thermal_of_zone_register(dev, 0, tmu, &tmu_tz_ops); 317 + if (IS_ERR(tmu->tzd)) 318 + return dev_err_probe(dev, PTR_ERR(tmu->tzd), 319 + "failed to register thermal zone sensor\n"); 320 + 321 + irq = platform_get_irq(pdev, 0); 322 + if (irq < 0) 323 + return irq; 324 + 325 + ret = devm_request_threaded_irq(dev, irq, imx91_tmu_alarm_irq, 326 + imx91_tmu_alarm_irq_thread, 327 + IRQF_ONESHOT, "imx91_thermal", tmu); 328 + 329 + if (ret < 0) 330 + return dev_err_probe(dev, ret, "failed to request alarm irq\n"); 331 + 332 + pm_runtime_put(dev); 333 + 334 + return 0; 335 + } 336 + 337 + static int imx91_tmu_runtime_suspend(struct device *dev) 338 + { 339 + struct imx91_tmu *tmu = dev_get_drvdata(dev); 340 + 341 + /* disable tmu */ 342 + imx91_tmu_enable(tmu, false); 343 + 344 + clk_disable_unprepare(tmu->clk); 345 + 346 + return 0; 347 + } 348 + 349 + static int imx91_tmu_runtime_resume(struct device *dev) 350 + { 351 + struct imx91_tmu *tmu = dev_get_drvdata(dev); 352 + int ret; 353 + 354 + ret = clk_prepare_enable(tmu->clk); 355 + if (ret) 356 + return ret; 357 + 358 + imx91_tmu_enable(tmu, true); 359 + 360 + return 0; 361 + } 362 + 363 + static DEFINE_RUNTIME_DEV_PM_OPS(imx91_tmu_pm_ops, imx91_tmu_runtime_suspend, 364 + imx91_tmu_runtime_resume, NULL); 365 + 366 + static const struct of_device_id imx91_tmu_table[] = { 367 + { .compatible = "fsl,imx91-tmu", }, 368 + { }, 369 + }; 370 + MODULE_DEVICE_TABLE(of, imx91_tmu_table); 371 + 372 + static struct platform_driver imx91_tmu = { 373 + .driver = { 374 + .name = "imx91_thermal", 375 + .pm = pm_ptr(&imx91_tmu_pm_ops), 376 + .of_match_table = imx91_tmu_table, 377 + }, 378 + .probe = imx91_tmu_probe, 379 + }; 380 + module_platform_driver(imx91_tmu); 381 + 382 + MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>"); 383 + MODULE_DESCRIPTION("i.MX91 Thermal Monitor Unit driver"); 384 + MODULE_LICENSE("GPL");
+2 -1
drivers/thermal/intel/Kconfig
··· 44 44 45 45 config INTEL_SOC_DTS_THERMAL 46 46 tristate "Intel SoCs DTS thermal driver" 47 - depends on X86 && PCI && ACPI 47 + depends on X86_64 && PCI && ACPI && NET 48 + select INT340X_THERMAL 48 49 select INTEL_SOC_DTS_IOSF_CORE 49 50 help 50 51 Enable this to register Intel SoCs (e.g. Bay Trail) platform digital
+8 -5
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
··· 16 16 #define INT3400_ODVP_CHANGED 0x88 17 17 #define INT3400_KEEP_ALIVE 0xA0 18 18 #define INT3400_FAKE_TEMP (20 * 1000) /* faked temp sensor with 20C */ 19 + /* UUID prefix length for comparison - sufficient for all UUIDs */ 20 + #define INT3400_UUID_PREFIX_LEN 7 19 21 20 22 enum int3400_thermal_uuid { 21 23 INT3400_THERMAL_ACTIVE = 0, ··· 114 112 int length = 0; 115 113 116 114 if (!priv->uuid_bitmap) 117 - return sprintf(buf, "UNKNOWN\n"); 115 + return sysfs_emit(buf, "UNKNOWN\n"); 118 116 119 117 for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) { 120 118 if (priv->uuid_bitmap & (1 << i)) ··· 131 129 int i, length = 0; 132 130 133 131 if (priv->current_uuid_index >= 0) 134 - return sprintf(buf, "%s\n", 132 + return sysfs_emit(buf, "%s\n", 135 133 int3400_thermal_uuids[priv->current_uuid_index]); 136 134 137 135 for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) { ··· 142 140 if (length) 143 141 return length; 144 142 145 - return sprintf(buf, "INVALID\n"); 143 + return sysfs_emit(buf, "INVALID\n"); 146 144 } 147 145 148 146 static int int3400_thermal_run_osc(acpi_handle handle, char *uuid_str, int *enable) ··· 201 199 202 200 for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; ++i) { 203 201 if (!strncmp(buf, int3400_thermal_uuids[i], 204 - sizeof(int3400_thermal_uuids[i]) - 1)) { 202 + INT3400_UUID_PREFIX_LEN)) { 205 203 /* 206 204 * If we have a list of supported UUIDs, make sure 207 205 * this one is supported. ··· 342 340 343 341 odvp_attr = container_of(attr, struct odvp_attr, attr); 344 342 345 - return sprintf(buf, "%d\n", odvp_attr->priv->odvp[odvp_attr->odvp]); 343 + return sysfs_emit(buf, "%d\n", odvp_attr->priv->odvp[odvp_attr->odvp]); 346 344 } 347 345 348 346 static void cleanup_odvp(struct int3400_thermal_priv *priv) ··· 693 691 {"INTC10A0", 0}, 694 692 {"INTC10D4", 0}, 695 693 {"INTC10FC", 0}, 694 + {"INTC10F3", 0}, 696 695 {} 697 696 }; 698 697
+1
drivers/thermal/intel/int340x_thermal/int3403_thermal.c
··· 277 277 {"INTC10A1", 0}, 278 278 {"INTC10D5", 0}, 279 279 {"INTC10FD", 0}, 280 + {"INTC10F4", 0}, 280 281 {"", 0}, 281 282 }; 282 283 MODULE_DEVICE_TABLE(acpi, int3403_device_ids);
+2
drivers/thermal/intel/int340x_thermal/processor_thermal_device.h
··· 27 27 #define PCI_DEVICE_ID_INTEL_JSL_THERMAL 0x4E03 28 28 #define PCI_DEVICE_ID_INTEL_LNLM_THERMAL 0x641D 29 29 #define PCI_DEVICE_ID_INTEL_MTLP_THERMAL 0x7D03 30 + #define PCI_DEVICE_ID_INTEL_NVL_H_THERMAL 0xD703 31 + #define PCI_DEVICE_ID_INTEL_NVL_S_THERMAL 0xAD03 30 32 #define PCI_DEVICE_ID_INTEL_RPL_THERMAL 0xA71D 31 33 #define PCI_DEVICE_ID_INTEL_SKL_THERMAL 0x1903 32 34 #define PCI_DEVICE_ID_INTEL_TGL_THERMAL 0x9A03
+10
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
··· 504 504 PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DLVR | 505 505 PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_HINT | 506 506 PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC) }, 507 + { PCI_DEVICE_DATA(INTEL, NVL_H_THERMAL, PROC_THERMAL_FEATURE_RAPL | 508 + PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS | 509 + PROC_THERMAL_FEATURE_MSI_SUPPORT | PROC_THERMAL_FEATURE_WT_HINT | 510 + PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC | 511 + PROC_THERMAL_FEATURE_SOC_POWER_SLIDER) }, 512 + { PCI_DEVICE_DATA(INTEL, NVL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL | 513 + PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS | 514 + PROC_THERMAL_FEATURE_MSI_SUPPORT | PROC_THERMAL_FEATURE_WT_HINT | 515 + PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC | 516 + PROC_THERMAL_FEATURE_SOC_POWER_SLIDER) }, 507 517 { }, 508 518 }; 509 519
+15
drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
··· 87 87 {NULL, 0, NULL}, 88 88 }; 89 89 90 + static const struct mmio_reg nvl_dlvr_mmio_regs[] = { 91 + { 0, 0x19208, 5, 0x1F, 0}, /* dlvr_spread_spectrum_pct */ 92 + { 0, 0x19208, 1, 0x1, 5}, /* dlvr_control_mode */ 93 + { 0, 0x19208, 1, 0x1, 6}, /* dlvr_control_lock */ 94 + { 0, 0x19208, 1, 0x1, 7}, /* dlvr_rfim_enable */ 95 + { 0, 0x19208, 12, 0xFFF, 8}, /* dlvr_freq_select */ 96 + { 1, 0x19210, 2, 0x3, 30}, /* dlvr_hardware_rev */ 97 + { 1, 0x19210, 16, 0xFFFF, 0}, /* dlvr_freq_mhz */ 98 + { 1, 0x19210, 1, 0x1, 16}, /* dlvr_pll_busy */ 99 + }; 100 + 90 101 static int match_mapping_table(const struct mapping_table *table, const char *attr_name, 91 102 bool match_int_value, const u32 value, const char *value_str, 92 103 char **result_str, u32 *result_int) ··· 456 445 case PCI_DEVICE_ID_INTEL_WCL_THERMAL: 457 446 dlvr_mmio_regs_table = lnl_dlvr_mmio_regs; 458 447 dlvr_mapping = lnl_dlvr_mapping; 448 + break; 449 + case PCI_DEVICE_ID_INTEL_NVL_H_THERMAL: 450 + case PCI_DEVICE_ID_INTEL_NVL_S_THERMAL: 451 + dlvr_mmio_regs_table = nvl_dlvr_mmio_regs; 459 452 break; 460 453 default: 461 454 dlvr_mmio_regs_table = dlvr_mmio_regs;
+5 -5
drivers/thermal/renesas/rcar_gen3_thermal.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * R-Car Gen3 THS thermal sensor driver 3 + * R-Car Gen3, Gen4 and RZ/G2 THS thermal sensor driver 4 4 * Based on rcar_thermal.c and work from Hien Dang and Khiem Nguyen. 5 5 * 6 6 * Copyright (C) 2016 Renesas Electronics Corporation. ··· 601 601 return ret; 602 602 } 603 603 604 - static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev) 604 + static int rcar_gen3_thermal_resume(struct device *dev) 605 605 { 606 606 struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev); 607 607 unsigned int i; ··· 615 615 return 0; 616 616 } 617 617 618 - static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, NULL, 619 - rcar_gen3_thermal_resume); 618 + static DEFINE_SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, NULL, 619 + rcar_gen3_thermal_resume); 620 620 621 621 static struct platform_driver rcar_gen3_thermal_driver = { 622 622 .driver = { 623 623 .name = "rcar_gen3_thermal", 624 - .pm = &rcar_gen3_thermal_pm_ops, 624 + .pm = pm_sleep_ptr(&rcar_gen3_thermal_pm_ops), 625 625 .of_match_table = rcar_gen3_thermal_dt_ids, 626 626 }, 627 627 .probe = rcar_gen3_thermal_probe,
+3 -5
drivers/thermal/renesas/rcar_thermal.c
··· 534 534 return ret; 535 535 } 536 536 537 - #ifdef CONFIG_PM_SLEEP 538 537 static int rcar_thermal_suspend(struct device *dev) 539 538 { 540 539 struct rcar_thermal_common *common = dev_get_drvdata(dev); ··· 566 567 567 568 return 0; 568 569 } 569 - #endif 570 570 571 - static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend, 572 - rcar_thermal_resume); 571 + static DEFINE_SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend, 572 + rcar_thermal_resume); 573 573 574 574 static struct platform_driver rcar_thermal_driver = { 575 575 .driver = { 576 576 .name = "rcar_thermal", 577 - .pm = &rcar_thermal_pm_ops, 577 + .pm = pm_sleep_ptr(&rcar_thermal_pm_ops), 578 578 .of_match_table = rcar_thermal_dt_ids, 579 579 }, 580 580 .probe = rcar_thermal_probe,
+1 -1
tools/thermal/thermal-engine/thermal-engine.c
··· 374 374 } 375 375 376 376 if (options.daemonize && daemon(0, 0)) { 377 - ERROR("Failed to daemonize: %p\n"); 377 + ERROR("Failed to daemonize: %m\n"); 378 378 return THERMAL_ENGINE_DAEMON_ERROR; 379 379 } 380 380