* [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling
@ 2026-07-27 14:22 Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 1/9] dt-bindings: remoteproc: qcom,pas: add #cooling-cells property Gaurav Kohli
` (8 more replies)
0 siblings, 9 replies; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi, Casey Connolly,
Dmitry Baryshkov, Dipa Ramesh Mantre
This series introduces Qualcomm Messaging Interface based Thermal
Mitigation Device (QMI TMD) support to control thermal mitigation
on remote subsystems such as the Modem and CDSP.
The QMI TMD is an interface that instructs a remote subsystem to adjust
the performance level of the devices it manages, reducing power consumption
in response to critically low battery charge, overcurrent alerts, or
overheating conditions.
The series is organized as follows:
- Add a shared dt-bindings header mapping TMD device indices for use
in DT cooling-maps, ensuring a consistent binding between the thermal
zone and the QMI TMD driver.
- Extend the remoteproc PAS binding with the optional #cooling-cells
property to allow remoteproc nodes to be referenced as cooling devices.
- Add QMI TMD support in the remoteproc PAS framework, hooking into
the probe/unregister lifecycle to register and unregister cooling
devices with the thermal framework.
- Enable CDSP and Modem cooling on kodiak, lemans, talos, monaco and
hamoa platforms using the new binding.
Not all TMD endpoints advertised by the firmware are wired into kernel
thermal zones. Endpoints such as BCL (battery current limiting) and cold
temperature protection are handled from userspace via qmi and do not
require kernel thermal zone bindings.
The constants defined in this series cover only the endpoints actively
used for thermal mitigation in the kernel thermal framework on the
currently posted targets: cdsp_sw (CDSP software thermal limit), pa
(modem power amplifier), and modem.
This work revives the earlier QMI cooling series by Casey Connolly [1],
with the following key differences:
- Uses an id based API for cooling-device binding
- Integrates QMI TMD directly into the remoteproc PAS framework and
hooks into the probe/unregister lifecycle.
- Removes unused code and cleans up macro names
This series depends on cooling device id support from Daniel Lezcano [2].
[1] https://lore.kernel.org/linux-devicetree/20230905-caleb-qmi_cooling-v1-0-5aa39d4164a7@linaro.org/
[2] https://lore.kernel.org/all/20260526140802.1059293-12-daniel.lezcano@oss.qualcomm.com/
---
Changes in v6:
- Added Reviewed-by tags from Dmitry.
- Kodiak: delete MPSS cooling maps by label on non-modem boards. (Dmitry)
- Renamed qcom,qmi-tmd.h to qcom,pas.h. (Krzysztof)
- Made QCOM_QMI_TMD tristate to fix unmet dependency issue. (Sashiko)
- Removed redundant negative TMD id check in qcom_pas_setup_tmd(). (Dmitry)
- Fixed QMI_DATA_LEN type issue by using u32. (Sashiko)
- Link to v5: https://lore.kernel.org/r/20260721-b4-qmi-tmd-v5-0-99620e07f505@oss.qualcomm.com
Changes in v5:
- Added Reviewed-by tag (Daniel Lezcano)
- Squashed dt-bindings header patch into the yaml binding patch.(Krzysztof)
- Renamed constants: QCOM_CDSP_TMD_CDSP_SW -> QCOM_TMD_CDSP_SW,
QCOM_MODEM_TMD_PA -> QCOM_TMD_PA, QCOM_MODEM_TMD_MODEM ->
QCOM_TMD_MODEM.(Krzysztof)
- Replaced dev_err() with dev_err_probe() in qmi_tmd_init() (Krzysztof)
- Fixed qmi_tmd_exit() teardown order to prevent cancel_work_sync()
re-queue race.(Krzysztof)
- Removed only MPSS maps instead of entire cooling-maps node.(Dmitry)
- Added cover letter note clarifying TMD endpoint selection rationale.(Dmitry)
- Added NET dependency in Kconfig.(Julian)
- Link to v4: https://lore.kernel.org/r/20260703-qmi-tmd-v4-0-3882189c1f83@oss.qualcomm.com
Changes in v4:
- Drop the tmd-names DT property.
- Move TMD instance id and tmd device name into PAS platform data.
- Add a shared dt-bindings header to define numeric constant for TMD id.
- Add mutex documentation comments for get/set state callbacks.
- Link to v3: https://lore.kernel.org/r/20260609-qmi-tmd-v3-0-291a2ff4c634@oss.qualcomm.com
Changes in v3:
- Removed the remoteproc-cooling abstraction approach.
- Integerated QMI TMD with remoteproc core framework.
- Cleaned the macro names and removed unused code.
- Switched to index-based thermal_of_cooling_device_register() api.
- Link to v2: https://lore.kernel.org/linux-devicetree/20260127155722.2797783-1-gaurav.kohli@oss.qualcomm.com/
Changes in v2:
- Update Remoreproc thermal config to tristate and removed unnecessary NULL checks.
- Fixed dt binding file format and added generic name support for cdsp.
- Fixed memory leak and cleaned up qmi-cooling driver file.
- Corrected DT formatting errors and commit descriptions for all targets.
- Link to v1: https://lore.kernel.org/linux-devicetree/20251223123227.1317244-1-gaurav.kohli@oss.qualcomm.com/
---
---
Casey Connolly (1):
soc: qcom: Add QMI TMD support for remote thermal mitigation
Dipa Ramesh Mantre (1):
arm64: dts: qcom: hamoa: Enable CDSP cooling
Gaurav Kohli (7):
dt-bindings: remoteproc: qcom,pas: add #cooling-cells property
remoteproc: qcom: pas: add support for TMD thermal cooling devices
remoteproc: qcom_q6v5_pas: enable QMI TMD cooling support
arm64: dts: qcom: kodiak: Enable CDSP & Modem cooling
arm64: dts: qcom: lemans: Enable CDSP cooling
arm64: dts: qcom: talos: Enable CDSP cooling
arm64: dts: qcom: monaco: Enable CDSP cooling
.../bindings/remoteproc/qcom,pas-common.yaml | 9 +
MAINTAINERS | 8 +
arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 32 ++
arch/arm64/boot/dts/qcom/hamoa.dtsi | 63 +++
arch/arm64/boot/dts/qcom/kodiak.dtsi | 125 +++++
arch/arm64/boot/dts/qcom/lemans.dtsi | 125 ++++-
arch/arm64/boot/dts/qcom/monaco.dtsi | 99 ++++
.../boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts | 8 +
.../dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts | 8 +
.../boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts | 8 +
.../boot/dts/qcom/qcs6490-vicharak-axon-mini.dts | 8 +
.../boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi | 10 +
.../boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi | 9 +
arch/arm64/boot/dts/qcom/talos.dtsi | 19 +
drivers/remoteproc/Kconfig | 1 +
drivers/remoteproc/qcom_q6v5_pas.c | 117 +++-
drivers/soc/qcom/Kconfig | 12 +
drivers/soc/qcom/Makefile | 1 +
drivers/soc/qcom/qmi_tmd.c | 595 +++++++++++++++++++++
include/dt-bindings/thermal/qcom,pas.h | 20 +
include/linux/soc/qcom/qmi.h | 1 +
include/linux/soc/qcom/qmi_tmd.h | 36 ++
22 files changed, 1301 insertions(+), 13 deletions(-)
---
base-commit: 49362394dad7df66c274c867a271394c10ca2bb8
change-id: 20260715-b4-qmi-tmd-d23e8df1b282
Best regards,
--
Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v6 1/9] dt-bindings: remoteproc: qcom,pas: add #cooling-cells property
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
@ 2026-07-27 14:22 ` Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 2/9] soc: qcom: Add QMI TMD support for remote thermal mitigation Gaurav Kohli
` (7 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi
Document the optional #cooling-cells property for Qualcomm PAS
remoteproc nodes so they can be used as thermal cooling devices via
the QMI Thermal Mitigation Device (TMD) interface.
Qualcomm remote processors expose TMD endpoints that support thermal
throttling through firmware. The cooling-device specifier uses 3 cells:
<&phandle device_id min_state max_state>
where device_id selects the TMD endpoint (for example PA, modem, or
CDSP software mitigation), with constants defined in:
include/dt-bindings/thermal/qcom,pas.h
Example usage in a thermal zone:
cooling-maps {
map0 {
trip = <&cpu_alert>;
cooling-device = <&remoteproc_cdsp
QCOM_TMD_CDSP_SW
0 THERMAL_NO_LIMIT>;
};
};
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
---
.../bindings/remoteproc/qcom,pas-common.yaml | 9 +++++++++
MAINTAINERS | 1 +
include/dt-bindings/thermal/qcom,pas.h | 20 ++++++++++++++++++++
3 files changed, 30 insertions(+)
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml
index 11faf655f530..f75cab6b4ed9 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml
@@ -77,6 +77,15 @@ properties:
channels and devices related to the ADSP.
unevaluatedProperties: false
+ '#cooling-cells':
+ description: |
+ Cooling device with three cells:
+ Cell 0: Cooling device id as defined in
+ include/dt-bindings/thermal/qcom,pas.h
+ Cell 1: Minimum cooling state
+ Cell 2: Maximum cooling state
+ const: 3
+
glink-edge:
$ref: /schemas/remoteproc/qcom,glink-edge.yaml#
description:
diff --git a/MAINTAINERS b/MAINTAINERS
index dcffe9fc54f6..3f1e2bbf7099 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3423,6 +3423,7 @@ F: drivers/watchdog/gunyah_wdt.c
F: include/dt-bindings/arm/qcom,ids.h
F: include/dt-bindings/firmware/qcom,scm.h
F: include/dt-bindings/soc/qcom*
+F: include/dt-bindings/thermal/qcom,pas.h
F: include/linux/firmware/qcom
F: include/linux/soc/qcom/
F: include/soc/qcom/
diff --git a/include/dt-bindings/thermal/qcom,pas.h b/include/dt-bindings/thermal/qcom,pas.h
new file mode 100644
index 000000000000..f603bddef9a8
--- /dev/null
+++ b/include/dt-bindings/thermal/qcom,pas.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+/*
+ * Qualcomm PAS remoteproc cooling device indices
+ *
+ * These indices are used in device tree cooling-maps to reference
+ * specific TMD devices provided by PAS-managed remote processors via QMI.
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#ifndef _DT_BINDINGS_THERMAL_QCOM_PAS_H
+#define _DT_BINDINGS_THERMAL_QCOM_PAS_H
+
+/* CDSP thermal mitigation device id */
+#define QCOM_TMD_CDSP_SW 0
+
+/* Modem thermal mitigation device id */
+#define QCOM_TMD_PA 0
+#define QCOM_TMD_MODEM 1
+
+#endif /* _DT_BINDINGS_THERMAL_QCOM_PAS_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 2/9] soc: qcom: Add QMI TMD support for remote thermal mitigation
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 1/9] dt-bindings: remoteproc: qcom,pas: add #cooling-cells property Gaurav Kohli
@ 2026-07-27 14:22 ` Gaurav Kohli
2026-07-27 14:40 ` sashiko-bot
2026-07-27 14:22 ` [PATCH v6 3/9] remoteproc: qcom: pas: add support for TMD thermal cooling devices Gaurav Kohli
` (6 subsequent siblings)
8 siblings, 1 reply; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi, Casey Connolly
From: Casey Connolly <casey.connolly@linaro.org>
Add support for Qualcomm Messaging Interface (QMI) based Thermal Mitigation
Device (TMD) cooling devices provided by remote subsystems.
On Qualcomm platforms where remote processors expose mitigation controls
through the TMD QMI service, client drivers need support to discover the
service, register cooling devices for available mitigation endpoints,
and forward cooling state updates to remote subsystems.
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Co-developed-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
Co-developed-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
---
MAINTAINERS | 7 +
drivers/soc/qcom/Kconfig | 12 +
drivers/soc/qcom/Makefile | 1 +
drivers/soc/qcom/qmi_tmd.c | 595 +++++++++++++++++++++++++++++++++++++++
include/linux/soc/qcom/qmi.h | 1 +
include/linux/soc/qcom/qmi_tmd.h | 36 +++
6 files changed, 652 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 3f1e2bbf7099..7b347a84883d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22389,6 +22389,13 @@ F: Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml
F: Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
F: drivers/net/ethernet/qualcomm/ppe/
+QUALCOMM QMI (REMOTEPROC THERMAL MITIGATION) TMD
+M: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
+L: linux-arm-msm@vger.kernel.org
+L: linux-pm@vger.kernel.org
+S: Maintained
+F: drivers/soc/qcom/qmi_tmd.c
+
QUALCOMM QSEECOM DRIVER
M: Maximilian Luz <luzmaximilian@gmail.com>
L: linux-arm-msm@vger.kernel.org
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index fd4d4ecd2df0..6f87e85713ec 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -319,6 +319,18 @@ config QCOM_QMI_HELPERS
tristate
depends on NET
+config QCOM_QMI_TMD
+ tristate "Qualcomm remote subsystem TMD" if COMPILE_TEST
+ depends on NET
+ depends on ARCH_QCOM || COMPILE_TEST
+ select QRTR
+ select QCOM_QMI_HELPERS
+ help
+ This enables Qualcomm Messaging Interface (QMI) based Thermal Mitigation
+ Device (TMD) support for Qualcomm remote subsystems. It manages
+ TMD messaging and handles QMI communication with remote processors
+ to exchange mitigation state and apply thermal mitigation requests.
+
config QCOM_UBWC_CONFIG
tristate
help
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index b7f1d2a57367..4544e61c74e7 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
CFLAGS_pmic_pdcharger_ulog.o := -I$(src)
+obj-$(CONFIG_QCOM_QMI_TMD) += qmi_tmd.o
obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o
qmi_helpers-y += qmi_encdec.o qmi_interface.o
obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o
diff --git a/drivers/soc/qcom/qmi_tmd.c b/drivers/soc/qcom/qmi_tmd.c
new file mode 100644
index 000000000000..555f2aff1ac0
--- /dev/null
+++ b/drivers/soc/qcom/qmi_tmd.c
@@ -0,0 +1,595 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025, Linaro Limited
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * QMI Thermal Mitigation Device (TMD).
+ * Provides cooling device support for remote subsystems
+ * running the TMD service via QMI.
+ */
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/qmi.h>
+#include <linux/soc/qcom/qmi_tmd.h>
+#include <linux/thermal.h>
+
+#define QMI_TMD_SERVICE_VERS_V01 0x01
+
+#define QMI_TMD_SET_LEVEL_REQ 0x0021
+#define QMI_TMD_GET_DEV_LIST_REQ 0x0020
+
+#define QMI_TMD_DEV_ID_LEN_MAX 32
+#define QMI_TMD_DEV_LIST_MAX 32
+#define QMI_TMD_RESP_TIMEOUT msecs_to_jiffies(100)
+#define TMD_GET_LEVEL_REQ_MAX_LEN 36
+#define TMD_SET_LEVEL_REQ_MAX_LEN 40
+
+#define TMD_GET_DEV_LIST_REQ_MAX_LEN 0
+#define TMD_GET_DEV_LIST_RESP_MAX_LEN 1099
+
+struct tmd_dev_id {
+ char mitigation_dev_id[QMI_TMD_DEV_ID_LEN_MAX + 1];
+};
+
+static const struct qmi_elem_info tmd_dev_id_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = QMI_TMD_DEV_ID_LEN_MAX + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct tmd_dev_id,
+ mitigation_dev_id),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct tmd_dev_list {
+ struct tmd_dev_id mitigation_dev_id;
+ u8 max_mitigation_level;
+};
+
+static const struct qmi_elem_info tmd_dev_list_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct tmd_dev_id),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct tmd_dev_list,
+ mitigation_dev_id),
+ .ei_array = tmd_dev_id_ei,
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct tmd_dev_list,
+ max_mitigation_level),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct tmd_get_dev_list_req {
+ char placeholder;
+};
+
+static const struct qmi_elem_info tmd_get_dev_list_req_ei[] = {
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct tmd_get_dev_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 mitigation_device_list_valid;
+ u32 mitigation_device_list_len;
+ struct tmd_dev_list
+ mitigation_device_list[QMI_TMD_DEV_LIST_MAX];
+};
+
+static const struct qmi_elem_info tmd_get_dev_list_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct tmd_get_dev_list_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct tmd_get_dev_list_resp,
+ mitigation_device_list_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct tmd_get_dev_list_resp,
+ mitigation_device_list_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = QMI_TMD_DEV_LIST_MAX,
+ .elem_size = sizeof(struct tmd_dev_list),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct tmd_get_dev_list_resp,
+ mitigation_device_list),
+ .ei_array = tmd_dev_list_ei,
+ },
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct tmd_set_level_req {
+ struct tmd_dev_id mitigation_dev_id;
+ u8 mitigation_level;
+};
+
+static const struct qmi_elem_info tmd_set_level_req_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct tmd_dev_id),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct tmd_set_level_req,
+ mitigation_dev_id),
+ .ei_array = tmd_dev_id_ei,
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct tmd_set_level_req,
+ mitigation_level),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct tmd_set_level_resp {
+ struct qmi_response_type_v01 resp;
+};
+
+static const struct qmi_elem_info tmd_set_level_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct tmd_set_level_resp, resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+/**
+ * struct qmi_tmd - A TMD cooling device
+ * @name: The name of this tmd shared by the remote subsystem
+ * @cdev: Thermal cooling device handle
+ * @cur_state: The current mitigation state
+ * @max_state: The maximum state
+ * @qmi_tmd_cli: Parent QMI TMD client
+ */
+struct qmi_tmd {
+ const char *name;
+ struct thermal_cooling_device *cdev;
+ unsigned int cur_state;
+ unsigned int max_state;
+ struct qmi_tmd_client *qmi_tmd_cli;
+};
+
+/**
+ * struct qmi_tmd_client - QMI TMD client state
+ * @dev: Device associated with this instance
+ * @handle: QMI connection handle
+ * @mutex: Serializes QMI request/response sequences (qmi_txn_init,
+ * qmi_send_request) during DSP subsystem restart and
+ * protects @connection_active and @exiting
+ * @connection_active: Whether or not we're connected to the QMI TMD service
+ * @exiting: Whether or not teardown has started
+ * @svc_arrive_work: Work item for initialising when the TMD service starts
+ * @num_tmds: Number of tmds described in the device tree
+ * @tmds: An array of tmd structures
+ */
+struct qmi_tmd_client {
+ struct device *dev;
+ struct qmi_handle handle;
+ /* protects QMI transactions, connection_active and exiting */
+ struct mutex mutex;
+ bool connection_active;
+ bool exiting;
+ struct work_struct svc_arrive_work;
+ int num_tmds;
+ struct qmi_tmd tmds[] __counted_by(num_tmds);
+};
+
+/* Notify the remote subsystem of the requested cooling state */
+static int qmi_tmd_send_state_request(struct qmi_tmd *tmd, int state)
+{
+ struct tmd_set_level_resp resp = { 0 };
+ struct tmd_set_level_req req = { 0 };
+ struct qmi_tmd_client *qmi_tmd_cli = tmd->qmi_tmd_cli;
+ struct qmi_txn txn;
+ int ret = 0;
+
+ guard(mutex)(&qmi_tmd_cli->mutex);
+
+ if (!qmi_tmd_cli->connection_active)
+ return 0;
+
+ strscpy(req.mitigation_dev_id.mitigation_dev_id, tmd->name,
+ QMI_TMD_DEV_ID_LEN_MAX + 1);
+ req.mitigation_level = state;
+
+ ret = qmi_txn_init(&qmi_tmd_cli->handle, &txn,
+ tmd_set_level_resp_ei, &resp);
+ if (ret < 0) {
+ dev_err(qmi_tmd_cli->dev, "qmi set state %d txn init failed for %s ret %d\n",
+ state, tmd->name, ret);
+ return ret;
+ }
+
+ ret = qmi_send_request(&qmi_tmd_cli->handle, NULL, &txn,
+ QMI_TMD_SET_LEVEL_REQ,
+ TMD_SET_LEVEL_REQ_MAX_LEN,
+ tmd_set_level_req_ei, &req);
+ if (ret < 0) {
+ dev_err(qmi_tmd_cli->dev, "qmi set state %d txn send failed for %s ret %d\n",
+ state, tmd->name, ret);
+ qmi_txn_cancel(&txn);
+ return ret;
+ }
+
+ ret = qmi_txn_wait(&txn, QMI_TMD_RESP_TIMEOUT);
+ if (ret < 0) {
+ dev_err(qmi_tmd_cli->dev, "qmi set state %d txn wait failed for %s ret %d\n",
+ state, tmd->name, ret);
+ return ret;
+ }
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ dev_err(qmi_tmd_cli->dev,
+ "qmi set state %d failed for %s result %#x error %#x\n",
+ state, tmd->name,
+ resp.resp.result, resp.resp.error);
+ return -EREMOTEIO;
+ }
+
+ dev_dbg(qmi_tmd_cli->dev, "Requested state %d/%d for %s\n", state,
+ tmd->max_state, tmd->name);
+
+ return 0;
+}
+
+static int qmi_tmd_get_max_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct qmi_tmd *tmd = cdev->devdata;
+
+ *state = tmd->max_state;
+
+ return 0;
+}
+
+static int qmi_tmd_get_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct qmi_tmd *tmd = cdev->devdata;
+
+ /* cur_state is protected by thermal core's cdev->lock */
+ *state = tmd->cur_state;
+
+ return 0;
+}
+
+static int qmi_tmd_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long state)
+{
+ struct qmi_tmd *tmd = cdev->devdata;
+ int ret;
+
+ if (state > tmd->max_state)
+ return -EINVAL;
+
+ /* cur_state is protected by thermal core's cdev->lock */
+ if (tmd->cur_state == state)
+ return 0;
+
+ ret = qmi_tmd_send_state_request(tmd, state);
+ if (!ret)
+ tmd->cur_state = state;
+
+ return ret;
+}
+
+static const struct thermal_cooling_device_ops qmi_tmd_cooling_ops = {
+ .get_max_state = qmi_tmd_get_max_state,
+ .get_cur_state = qmi_tmd_get_cur_state,
+ .set_cur_state = qmi_tmd_set_cur_state,
+};
+
+static int qmi_tmd_register(struct qmi_tmd_client *qmi_tmd_cli,
+ const char *label, u8 max_state)
+{
+ struct device *dev = qmi_tmd_cli->dev;
+ struct qmi_tmd *tmd;
+ int index;
+
+ for (index = 0; index < qmi_tmd_cli->num_tmds; index++) {
+ tmd = &qmi_tmd_cli->tmds[index];
+
+ if (!strncasecmp(tmd->name, label,
+ QMI_TMD_DEV_ID_LEN_MAX + 1))
+ goto found;
+ }
+
+ dev_dbg(qmi_tmd_cli->dev,
+ "TMD '%s' available in firmware but not specified in DT\n",
+ label);
+ return 0;
+
+found:
+ tmd->max_state = max_state;
+
+ /*
+ * If the cooling device already exists then the QMI service went away and
+ * came back. So just make sure the current cooling device state is
+ * reflected on the remote side and then return.
+ */
+ if (tmd->cdev)
+ return qmi_tmd_send_state_request(tmd, tmd->cur_state);
+
+ tmd->cdev = thermal_of_cooling_device_register(dev->of_node, index,
+ label, tmd, &qmi_tmd_cooling_ops);
+ if (IS_ERR(tmd->cdev)) {
+ int ret = PTR_ERR(tmd->cdev);
+
+ tmd->cdev = NULL;
+ return ret;
+ }
+
+ return 0;
+}
+
+static void qmi_tmd_unregister(struct qmi_tmd_client *qmi_tmd_cli)
+{
+ struct qmi_tmd *tmd;
+ int index;
+
+ for (index = 0; index < qmi_tmd_cli->num_tmds; index++) {
+ tmd = &qmi_tmd_cli->tmds[index];
+
+ if (!tmd->cdev)
+ continue;
+
+ thermal_cooling_device_unregister(tmd->cdev);
+ tmd->cdev = NULL;
+ }
+}
+
+static void qmi_tmd_svc_arrive(struct work_struct *work)
+{
+ struct qmi_tmd_client *qmi_tmd_cli =
+ container_of(work, struct qmi_tmd_client, svc_arrive_work);
+
+ struct tmd_get_dev_list_req req = { 0 };
+ struct tmd_get_dev_list_resp *resp __free(kfree) = NULL;
+ int ret, i;
+ struct qmi_txn txn;
+
+ resp = kzalloc_obj(*resp, GFP_KERNEL);
+ if (!resp) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ scoped_guard(mutex, &qmi_tmd_cli->mutex) {
+ if (qmi_tmd_cli->exiting)
+ return;
+
+ ret = qmi_txn_init(&qmi_tmd_cli->handle, &txn,
+ tmd_get_dev_list_resp_ei, resp);
+ if (ret < 0)
+ goto out;
+
+ ret = qmi_send_request(&qmi_tmd_cli->handle, NULL, &txn,
+ QMI_TMD_GET_DEV_LIST_REQ,
+ TMD_GET_DEV_LIST_REQ_MAX_LEN,
+ tmd_get_dev_list_req_ei, &req);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ goto out;
+ }
+
+ ret = qmi_txn_wait(&txn, QMI_TMD_RESP_TIMEOUT);
+ if (ret < 0)
+ goto out;
+
+ if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
+ ret = -EPROTO;
+ goto out;
+ }
+
+ qmi_tmd_cli->connection_active = true;
+ }
+
+ for (i = 0; i < resp->mitigation_device_list_len; i++) {
+ struct tmd_dev_list *device =
+ &resp->mitigation_device_list[i];
+
+ ret = qmi_tmd_register(qmi_tmd_cli,
+ device->mitigation_dev_id.mitigation_dev_id,
+ device->max_mitigation_level);
+ if (ret)
+ break;
+ }
+
+out:
+ if (ret)
+ dev_err(qmi_tmd_cli->dev, "Failed to initialize TMD service: %d\n", ret);
+}
+
+static void qmi_tmd_del_server(struct qmi_handle *qmi, struct qmi_service *service)
+{
+ struct qmi_tmd_client *qmi_tmd_cli =
+ container_of(qmi, struct qmi_tmd_client, handle);
+
+ scoped_guard(mutex, &qmi_tmd_cli->mutex) {
+ qmi_tmd_cli->connection_active = false;
+ }
+}
+
+static int qmi_tmd_new_server(struct qmi_handle *qmi, struct qmi_service *service)
+{
+ struct sockaddr_qrtr sq = { AF_QIPCRTR, service->node, service->port };
+ struct qmi_tmd_client *qmi_tmd_cli;
+ int ret;
+
+ qmi_tmd_cli = container_of(qmi, struct qmi_tmd_client, handle);
+
+ scoped_guard(mutex, &qmi_tmd_cli->mutex) {
+ if (qmi_tmd_cli->exiting)
+ return 0;
+
+ ret = kernel_connect(qmi->sock, (struct sockaddr_unsized *)&sq,
+ sizeof(sq), 0);
+ }
+
+ if (ret < 0) {
+ dev_err(qmi_tmd_cli->dev, "QMI connect failed for node %u port %u: %d\n",
+ service->node, service->port, ret);
+ return ret;
+ }
+
+ queue_work(system_highpri_wq, &qmi_tmd_cli->svc_arrive_work);
+
+ return 0;
+}
+
+static const struct qmi_ops qmi_tmd_ops = {
+ .new_server = qmi_tmd_new_server,
+ .del_server = qmi_tmd_del_server,
+};
+
+/**
+ * qmi_tmd_init() - Initialize QMI TMD instance
+ * @dev: Device pointer
+ * @instance_id: QMI service instance ID for the remote subsystem
+ * @tmd_names: Array of TMD names
+ * @num_tmds: Number of TMD names
+ *
+ * Context: Must be called from probe context.
+ *
+ * Return: Pointer to qmi_tmd_client on success, ERR_PTR on failure
+ */
+struct qmi_tmd_client *qmi_tmd_init(struct device *dev,
+ unsigned int instance_id,
+ const char * const *tmd_names,
+ int num_tmds)
+{
+ struct qmi_tmd_client *qmi_tmd_cli;
+ int ret, i;
+
+ if (!dev || !tmd_names || num_tmds <= 0)
+ return ERR_PTR(-EINVAL);
+
+ qmi_tmd_cli = devm_kzalloc(dev, struct_size(qmi_tmd_cli, tmds, num_tmds), GFP_KERNEL);
+ if (!qmi_tmd_cli)
+ return ERR_PTR(-ENOMEM);
+
+ qmi_tmd_cli->dev = dev;
+ qmi_tmd_cli->num_tmds = num_tmds;
+ mutex_init(&qmi_tmd_cli->mutex);
+ INIT_WORK(&qmi_tmd_cli->svc_arrive_work, qmi_tmd_svc_arrive);
+
+ for (i = 0; i < num_tmds; i++) {
+ qmi_tmd_cli->tmds[i].name = tmd_names[i];
+ qmi_tmd_cli->tmds[i].qmi_tmd_cli = qmi_tmd_cli;
+ }
+
+ ret = qmi_handle_init(&qmi_tmd_cli->handle,
+ TMD_GET_DEV_LIST_RESP_MAX_LEN,
+ &qmi_tmd_ops, NULL);
+ if (ret < 0)
+ return ERR_PTR(dev_err_probe(dev, ret, "QMI handle init failed\n"));
+
+ ret = qmi_add_lookup(&qmi_tmd_cli->handle, QMI_SERVICE_ID_TMD,
+ QMI_TMD_SERVICE_VERS_V01, instance_id);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "QMI add lookup failed\n");
+ goto err_release_handle;
+ }
+
+ return qmi_tmd_cli;
+
+err_release_handle:
+ qmi_handle_release(&qmi_tmd_cli->handle);
+
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(qmi_tmd_init);
+
+/**
+ * qmi_tmd_exit() - Deinitialize QMI TMD instance
+ * @qmi_tmd_cli: QMI TMD client to deinitialize
+ */
+void qmi_tmd_exit(struct qmi_tmd_client *qmi_tmd_cli)
+{
+ if (!qmi_tmd_cli)
+ return;
+
+ scoped_guard(mutex, &qmi_tmd_cli->mutex) {
+ qmi_tmd_cli->exiting = true;
+ qmi_tmd_cli->connection_active = false;
+ }
+
+ qmi_handle_release(&qmi_tmd_cli->handle);
+ cancel_work_sync(&qmi_tmd_cli->svc_arrive_work);
+ qmi_tmd_unregister(qmi_tmd_cli);
+}
+EXPORT_SYMBOL_GPL(qmi_tmd_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Qualcomm QMI Thermal Mitigation support");
diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h
index b9dcb437a0be..683d27cee413 100644
--- a/include/linux/soc/qcom/qmi.h
+++ b/include/linux/soc/qcom/qmi.h
@@ -96,6 +96,7 @@ struct qmi_elem_info {
* Enumerate the IDs of the QMI services
*/
#define QMI_SERVICE_ID_TEST 0x0f /* 15 */
+#define QMI_SERVICE_ID_TMD 0x18 /* 24 */
#define QMI_SERVICE_ID_SSCTL 0x2b /* 43 */
#define QMI_SERVICE_ID_IPA 0x31 /* 49 */
#define QMI_SERVICE_ID_SERVREG_LOC 0x40 /* 64 */
diff --git a/include/linux/soc/qcom/qmi_tmd.h b/include/linux/soc/qcom/qmi_tmd.h
new file mode 100644
index 000000000000..452f51f23731
--- /dev/null
+++ b/include/linux/soc/qcom/qmi_tmd.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025, Linaro Limited
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * QMI Thermal Mitigation Device (TMD) library header.
+ */
+
+#ifndef __QMI_TMD_H__
+#define __QMI_TMD_H__
+
+struct device;
+struct qmi_tmd_client;
+
+#if IS_ENABLED(CONFIG_QCOM_QMI_TMD)
+struct qmi_tmd_client *qmi_tmd_init(struct device *dev,
+ unsigned int instance_id,
+ const char * const *tmd_names,
+ int num_tmds);
+
+void qmi_tmd_exit(struct qmi_tmd_client *tmd_cli);
+#else
+static inline struct qmi_tmd_client *qmi_tmd_init(struct device *dev,
+ unsigned int instance_id,
+ const char * const *tmd_names,
+ int num_tmds)
+{
+ return NULL;
+}
+
+static inline void qmi_tmd_exit(struct qmi_tmd_client *tmd_cli)
+{
+}
+#endif
+
+#endif /* __QMI_TMD_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 3/9] remoteproc: qcom: pas: add support for TMD thermal cooling devices
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 1/9] dt-bindings: remoteproc: qcom,pas: add #cooling-cells property Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 2/9] soc: qcom: Add QMI TMD support for remote thermal mitigation Gaurav Kohli
@ 2026-07-27 14:22 ` Gaurav Kohli
2026-07-27 14:37 ` sashiko-bot
2026-07-27 14:22 ` [PATCH v6 4/9] remoteproc: qcom_q6v5_pas: enable QMI TMD cooling support Gaurav Kohli
` (5 subsequent siblings)
8 siblings, 1 reply; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi
Register Thermal Mitigation Devices (TMDs) for PAS-managed remote
processors to enable thermal throttling through QMI.
This allows the thermal framework to request mitigation when remote
subsystems such as modem and CDSP contribute to thermal pressure.
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
---
drivers/remoteproc/Kconfig | 1 +
drivers/remoteproc/qcom_q6v5_pas.c | 90 +++++++++++++++++++++++++++++++++++++-
2 files changed, 90 insertions(+), 1 deletion(-)
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 65befdbfa5f7..152d7a53aa09 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -229,6 +229,7 @@ config QCOM_Q6V5_PAS
select QCOM_PIL_INFO
select QCOM_MDT_LOADER
select QCOM_Q6V5_COMMON
+ select QCOM_QMI_TMD if NET
select QCOM_RPROC_COMMON
select QCOM_SCM
select QCOM_PAS
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 25599d728208..07336a2d75f7 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -5,6 +5,7 @@
* Copyright (C) 2016 Linaro Ltd
* Copyright (C) 2014 Sony Mobile Communications AB
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/clk.h>
@@ -26,8 +27,10 @@
#include <linux/regulator/consumer.h>
#include <linux/remoteproc.h>
#include <linux/soc/qcom/mdt_loader.h>
+#include <linux/soc/qcom/qmi_tmd.h>
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/smem_state.h>
+#include <dt-bindings/thermal/qcom,pas.h>
#include "qcom_common.h"
#include "qcom_pil_info.h"
@@ -38,6 +41,16 @@
#define MAX_ASSIGN_COUNT 3
+/**
+ * struct tmd_name - TMD device name to cooling-device index mapping
+ * @name: TMD device name
+ * @id: Cooling-device index used as #cooling-cells cell 0 in DT
+ */
+struct tmd_name {
+ const char *name;
+ int id;
+};
+
struct qcom_pas_data {
int crash_reason_smem;
const char *firmware_name;
@@ -58,6 +71,10 @@ struct qcom_pas_data {
int ssctl_id;
unsigned int smem_host_id;
+ unsigned int tmd_instance_id;
+ const struct tmd_name *tmd_name;
+ int num_tmd;
+
int region_assign_idx;
int region_assign_count;
bool region_assign_shared;
@@ -122,6 +139,8 @@ struct qcom_pas {
struct qcom_pas_context *pas_ctx;
struct qcom_pas_context *dtb_pas_ctx;
+
+ struct qmi_tmd_client *tmd_inst;
};
static void qcom_pas_segment_dump(struct rproc *rproc,
@@ -798,6 +817,64 @@ static void qcom_pas_unassign_memory_region(struct qcom_pas *pas)
}
}
+static int qcom_pas_setup_tmd(struct qcom_pas *pas, const struct qcom_pas_data *desc)
+{
+ struct qmi_tmd_client *tmd_inst;
+ const struct tmd_name *tmd;
+ const char **tmd_names;
+ int i, ret;
+
+ if (!device_property_present(pas->dev, "#cooling-cells"))
+ return 0;
+
+ if (!desc->tmd_name || desc->num_tmd == 0)
+ return 0;
+
+ tmd_names = devm_kcalloc(pas->dev, desc->num_tmd,
+ sizeof(*tmd_names), GFP_KERNEL);
+ if (!tmd_names)
+ return -ENOMEM;
+
+ for (i = 0; i < desc->num_tmd; i++) {
+ tmd = &desc->tmd_name[i];
+
+ if (tmd->id >= desc->num_tmd) {
+ dev_err(pas->dev, "Invalid TMD id %d for '%s'\n",
+ tmd->id, tmd->name);
+ return -EINVAL;
+ }
+
+ if (tmd_names[tmd->id]) {
+ dev_err(pas->dev, "Duplicate TMD id %d for '%s'\n",
+ tmd->id, tmd->name);
+ return -EINVAL;
+ }
+
+ tmd_names[tmd->id] = tmd->name;
+ }
+
+ for (i = 0; i < desc->num_tmd; i++) {
+ if (!tmd_names[i]) {
+ dev_err(pas->dev, "Missing TMD mapping for id %d\n", i);
+ return -EINVAL;
+ }
+ }
+
+ tmd_inst = qmi_tmd_init(pas->dev, desc->tmd_instance_id, tmd_names,
+ desc->num_tmd);
+ if (IS_ERR(tmd_inst)) {
+ ret = PTR_ERR(tmd_inst);
+ if (ret == -ENODEV)
+ return 0;
+
+ return ret;
+ }
+
+ pas->tmd_inst = tmd_inst;
+
+ return 0;
+}
+
static int qcom_pas_probe(struct platform_device *pdev)
{
const struct qcom_pas_data *desc;
@@ -925,16 +1002,24 @@ static int qcom_pas_probe(struct platform_device *pdev)
if (desc->early_boot)
pas->rproc->state = RPROC_DETACHED;
- ret = rproc_add(rproc);
+ ret = qcom_pas_setup_tmd(pas, desc);
if (ret)
goto remove_ssr_sysmon;
+ ret = rproc_add(rproc);
+ if (ret)
+ goto remove_setup_tmd;
+
node = of_get_compatible_child(pdev->dev.of_node, "qcom,bam-dmux");
pas->bam_dmux = of_platform_device_create(node, NULL, &pdev->dev);
of_node_put(node);
return 0;
+remove_setup_tmd:
+ if (pas->tmd_inst)
+ qmi_tmd_exit(pas->tmd_inst);
+
remove_ssr_sysmon:
qcom_remove_ssr_subdev(rproc, &pas->ssr_subdev);
qcom_remove_sysmon_subdev(pas->sysmon);
@@ -960,6 +1045,9 @@ static void qcom_pas_remove(struct platform_device *pdev)
if (pas->bam_dmux)
of_platform_device_destroy(&pas->bam_dmux->dev, NULL);
+ if (pas->tmd_inst)
+ qmi_tmd_exit(pas->tmd_inst);
+
rproc_del(pas->rproc);
qcom_q6v5_deinit(&pas->q6v5);
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 4/9] remoteproc: qcom_q6v5_pas: enable QMI TMD cooling support
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
` (2 preceding siblings ...)
2026-07-27 14:22 ` [PATCH v6 3/9] remoteproc: qcom: pas: add support for TMD thermal cooling devices Gaurav Kohli
@ 2026-07-27 14:22 ` Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 5/9] arm64: dts: qcom: kodiak: Enable CDSP & Modem cooling Gaurav Kohli
` (4 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi
Enable Thermal Mitigation Device (TMD) support for PAS-managed CDSP and
modem remote processors on platforms that expose the QMI TMD service.
This adds per-platform TMD configuration in qcom_q6v5_pas for:
- Hamoa (X1E80100) CDSP
- Kodiak CDSP and modem
- Lemans (SA8775P) CDSP
- Talos CDSP
- Monaco CDSP
For each remoteproc, the configured TMD QMI instance ID is used to bind to
the TMD service running on that subsystem (e.g. CDSP: 0x43, modem: 0x0).
The driver then uses the corresponding TMD endpoint names ("cdsp_sw",
"pa", "modem") for cooling-device registration.
QMI TMD identifies mitigation endpoints by name, while DT thermal bindings
reference cooling devices by id. This change provides the mapping
between DT cooling indices and QMI TMD names, allowing remoteproc nodes
with #cooling-cells to act as cooling devices in the thermal framework.
With this in place, thermal policies can request mitigation from CDSP and
modem subsystems via QMI under thermal pressure.
Reviewed-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
---
drivers/remoteproc/qcom_q6v5_pas.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 07336a2d75f7..ab23c371601f 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -1061,6 +1061,15 @@ static void qcom_pas_remove(struct platform_device *pdev)
device_init_wakeup(pas->dev, false);
}
+static const struct tmd_name cdsp_tmd_name[] = {
+ { .name = "cdsp_sw", .id = QCOM_TMD_CDSP_SW },
+};
+
+static const struct tmd_name modem_tmd_name[] = {
+ { .name = "pa", .id = QCOM_TMD_PA },
+ { .name = "modem", .id = QCOM_TMD_MODEM },
+};
+
static const struct qcom_pas_data adsp_resource_init = {
.crash_reason_smem = 423,
.firmware_name = "adsp.mdt",
@@ -1218,6 +1227,9 @@ static const struct qcom_pas_data sa8775p_cdsp0_resource = {
.ssr_name = "cdsp",
.sysmon_name = "cdsp",
.ssctl_id = 0x17,
+ .tmd_instance_id = 0x43,
+ .tmd_name = cdsp_tmd_name,
+ .num_tmd = ARRAY_SIZE(cdsp_tmd_name),
};
static const struct qcom_pas_data sa8775p_cdsp1_resource = {
@@ -1236,6 +1248,9 @@ static const struct qcom_pas_data sa8775p_cdsp1_resource = {
.ssr_name = "cdsp1",
.sysmon_name = "cdsp1",
.ssctl_id = 0x20,
+ .tmd_instance_id = 0x44,
+ .tmd_name = cdsp_tmd_name,
+ .num_tmd = ARRAY_SIZE(cdsp_tmd_name),
};
static const struct qcom_pas_data sdm845_cdsp_resource_init = {
@@ -1263,6 +1278,9 @@ static const struct qcom_pas_data sm6350_cdsp_resource = {
.ssr_name = "cdsp",
.sysmon_name = "cdsp",
.ssctl_id = 0x17,
+ .tmd_instance_id = 0x43,
+ .tmd_name = cdsp_tmd_name,
+ .num_tmd = ARRAY_SIZE(cdsp_tmd_name),
};
static const struct qcom_pas_data sm8150_cdsp_resource = {
@@ -1278,6 +1296,9 @@ static const struct qcom_pas_data sm8150_cdsp_resource = {
.ssr_name = "cdsp",
.sysmon_name = "cdsp",
.ssctl_id = 0x17,
+ .tmd_instance_id = 0x43,
+ .tmd_name = cdsp_tmd_name,
+ .num_tmd = ARRAY_SIZE(cdsp_tmd_name),
};
static const struct qcom_pas_data sm8250_cdsp_resource = {
@@ -1362,6 +1383,9 @@ static const struct qcom_pas_data x1e80100_cdsp_resource = {
.ssr_name = "cdsp",
.sysmon_name = "cdsp",
.ssctl_id = 0x17,
+ .tmd_instance_id = 0x43,
+ .tmd_name = cdsp_tmd_name,
+ .num_tmd = ARRAY_SIZE(cdsp_tmd_name),
};
static const struct qcom_pas_data sm8350_cdsp_resource = {
@@ -1430,6 +1454,9 @@ static const struct qcom_pas_data mpss_resource_init = {
.ssr_name = "mpss",
.sysmon_name = "modem",
.ssctl_id = 0x12,
+ .tmd_instance_id = 0x0,
+ .tmd_name = modem_tmd_name,
+ .num_tmd = ARRAY_SIZE(modem_tmd_name),
};
static const struct qcom_pas_data sc8180x_mpss_resource = {
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 5/9] arm64: dts: qcom: kodiak: Enable CDSP & Modem cooling
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
` (3 preceding siblings ...)
2026-07-27 14:22 ` [PATCH v6 4/9] remoteproc: qcom_q6v5_pas: enable QMI TMD cooling support Gaurav Kohli
@ 2026-07-27 14:22 ` Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 6/9] arm64: dts: qcom: lemans: Enable CDSP cooling Gaurav Kohli
` (3 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi
Unlike the CPU, the CDSP/Modem does not throttle its speed automatically
when it reaches high temperatures in kodiak.
Set up CDSP cooling by throttling the cdsp when it reaches 100°C and
for modem when it reaches to 95°C.
Add polling-delay-passive so the governor periodically evaluates
the zone during passive cooling and steps up cooling levels when
temperature stabilizes below the next trip.
Since the remoteproc_mpss node doesn't exist on non modem boards, the
cooling-maps that reference it cause DT compilation errors. To fix that
remove inherited mdmss cooling-map nodes.
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/kodiak.dtsi | 125 +++++++++++++++++++++
.../boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts | 8 ++
.../dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts | 8 ++
.../boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts | 8 ++
.../boot/dts/qcom/qcs6490-vicharak-axon-mini.dts | 8 ++
.../boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi | 10 ++
.../boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi | 9 ++
7 files changed, 176 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi
index 7e73348fe0d0..53dcc5ebacd3 100644
--- a/arch/arm64/boot/dts/qcom/kodiak.dtsi
+++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi
@@ -30,6 +30,7 @@
#include <dt-bindings/sound/qcom,lpass.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/thermal/qcom,pas.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -3431,6 +3432,8 @@ remoteproc_mpss: remoteproc@4080000 {
qcom,smem-states = <&modem_smp2p_out 0>;
qcom,smem-state-names = "stop";
+ #cooling-cells = <3>;
+
status = "disabled";
glink-edge {
@@ -4803,6 +4806,8 @@ remoteproc_cdsp: remoteproc@a300000 {
qcom,smem-states = <&cdsp_smp2p_out 0>;
qcom,smem-state-names = "stop";
+ #cooling-cells = <3>;
+
status = "disabled";
glink-edge {
@@ -7732,6 +7737,8 @@ map0 {
};
nspss0-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens1 3>;
trips {
@@ -7741,15 +7748,31 @@ nspss0_alert0: trip-point0 {
type = "hot";
};
+ nspss0_alert1: trip-point1 {
+ temperature = <100000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nspss0_crit: nspss0-crit {
temperature = <110000>;
hysteresis = <0>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nspss0_alert1>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nspss1-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens1 4>;
trips {
@@ -7759,12 +7782,26 @@ nspss1_alert0: trip-point0 {
type = "hot";
};
+ nspss1_alert1: trip-point1 {
+ temperature = <100000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nspss1_crit: nspss1-crit {
temperature = <110000>;
hysteresis = <0>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nspss1_alert1>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
video-thermal {
@@ -7804,6 +7841,8 @@ ddr_crit: ddr-crit {
};
mdmss0-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens1 7>;
trips {
@@ -7813,15 +7852,37 @@ mdmss0_alert0: trip-point0 {
type = "hot";
};
+ mdmss0_alert1: trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
mdmss0_crit: mdmss0-crit {
temperature = <110000>;
hysteresis = <0>;
type = "critical";
};
};
+
+ cooling-maps {
+ mdmss0_pa_cooling_map: map0 {
+ trip = <&mdmss0_alert1>;
+ cooling-device = <&remoteproc_mpss QCOM_TMD_PA
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+
+ mdmss0_modem_cooling_map: map1 {
+ trip = <&mdmss0_alert1>;
+ cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
mdmss1-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens1 8>;
trips {
@@ -7831,15 +7892,37 @@ mdmss1_alert0: trip-point0 {
type = "hot";
};
+ mdmss1_alert1: trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
mdmss1_crit: mdmss1-crit {
temperature = <110000>;
hysteresis = <0>;
type = "critical";
};
};
+
+ cooling-maps {
+ mdmss1_pa_cooling_map: map0 {
+ trip = <&mdmss1_alert1>;
+ cooling-device = <&remoteproc_mpss QCOM_TMD_PA
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+
+ mdmss1_modem_cooling_map: map1 {
+ trip = <&mdmss1_alert1>;
+ cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
mdmss2-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens1 9>;
trips {
@@ -7849,15 +7932,37 @@ mdmss2_alert0: trip-point0 {
type = "hot";
};
+ mdmss2_alert1: trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
mdmss2_crit: mdmss2-crit {
temperature = <110000>;
hysteresis = <0>;
type = "critical";
};
};
+
+ cooling-maps {
+ mdmss2_pa_cooling_map: map0 {
+ trip = <&mdmss2_alert1>;
+ cooling-device = <&remoteproc_mpss QCOM_TMD_PA
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+
+ mdmss2_modem_cooling_map: map1 {
+ trip = <&mdmss2_alert1>;
+ cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
mdmss3-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens1 10>;
trips {
@@ -7867,12 +7972,32 @@ mdmss3_alert0: trip-point0 {
type = "hot";
};
+ mdmss3_alert1: trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
mdmss3_crit: mdmss3-crit {
temperature = <110000>;
hysteresis = <0>;
type = "critical";
};
};
+
+ cooling-maps {
+ mdmss3_pa_cooling_map: map0 {
+ trip = <&mdmss3_alert1>;
+ cooling-device = <&remoteproc_mpss QCOM_TMD_PA
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+
+ mdmss3_modem_cooling_map: map1 {
+ trip = <&mdmss3_alert1>;
+ cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
camera0-thermal {
diff --git a/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts b/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts
index 82ebd88f9aba..e3ddf47ce421 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts
@@ -24,6 +24,14 @@
/delete-node/ &adsp_mem;
/delete-node/ &cdsp_mem;
/delete-node/ &ipa_fw_mem;
+/delete-node/ &mdmss0_pa_cooling_map;
+/delete-node/ &mdmss0_modem_cooling_map;
+/delete-node/ &mdmss1_pa_cooling_map;
+/delete-node/ &mdmss1_modem_cooling_map;
+/delete-node/ &mdmss2_pa_cooling_map;
+/delete-node/ &mdmss2_modem_cooling_map;
+/delete-node/ &mdmss3_pa_cooling_map;
+/delete-node/ &mdmss3_modem_cooling_map;
/delete-node/ &mpss_mem;
/delete-node/ &remoteproc_mpss;
/delete-node/ &remoteproc_wpss;
diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts
index c8eed8ba93f5..8ce0cf23deee 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts
@@ -22,6 +22,14 @@
/delete-node/ &cdsp_mem;
/delete-node/ &ipa_fw_mem;
/delete-node/ &mpss_mem;
+/delete-node/ &mdmss0_pa_cooling_map;
+/delete-node/ &mdmss0_modem_cooling_map;
+/delete-node/ &mdmss1_pa_cooling_map;
+/delete-node/ &mdmss1_modem_cooling_map;
+/delete-node/ &mdmss2_pa_cooling_map;
+/delete-node/ &mdmss2_modem_cooling_map;
+/delete-node/ &mdmss3_pa_cooling_map;
+/delete-node/ &mdmss3_modem_cooling_map;
/delete-node/ &remoteproc_mpss;
/delete-node/ &remoteproc_wpss;
/delete-node/ &rmtfs_mem;
diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts
index d8a9a7e47bdc..abee1af19c23 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts
@@ -23,6 +23,14 @@
/delete-node/ &adsp_mem;
/delete-node/ &cdsp_mem;
/delete-node/ &ipa_fw_mem;
+/delete-node/ &mdmss0_pa_cooling_map;
+/delete-node/ &mdmss0_modem_cooling_map;
+/delete-node/ &mdmss1_pa_cooling_map;
+/delete-node/ &mdmss1_modem_cooling_map;
+/delete-node/ &mdmss2_pa_cooling_map;
+/delete-node/ &mdmss2_modem_cooling_map;
+/delete-node/ &mdmss3_pa_cooling_map;
+/delete-node/ &mdmss3_modem_cooling_map;
/delete-node/ &mpss_mem;
/delete-node/ &remoteproc_mpss;
/delete-node/ &remoteproc_wpss;
diff --git a/arch/arm64/boot/dts/qcom/qcs6490-vicharak-axon-mini.dts b/arch/arm64/boot/dts/qcom/qcs6490-vicharak-axon-mini.dts
index 4f2e0109f49b..d3f558596ca2 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-vicharak-axon-mini.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-vicharak-axon-mini.dts
@@ -25,6 +25,14 @@
/delete-node/ &cdsp_mem;
/delete-node/ &ipa_fw_mem;
/delete-node/ &mpss_mem;
+/delete-node/ &mdmss0_pa_cooling_map;
+/delete-node/ &mdmss0_modem_cooling_map;
+/delete-node/ &mdmss1_pa_cooling_map;
+/delete-node/ &mdmss1_modem_cooling_map;
+/delete-node/ &mdmss2_pa_cooling_map;
+/delete-node/ &mdmss2_modem_cooling_map;
+/delete-node/ &mdmss3_pa_cooling_map;
+/delete-node/ &mdmss3_modem_cooling_map;
/delete-node/ &remoteproc_mpss;
/delete-node/ &remoteproc_wpss;
/delete-node/ &rmtfs_mem;
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi
index ac89724ee099..891941906a46 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi
@@ -28,8 +28,18 @@ &ipa {
status = "okay";
};
+/delete-node/ &mdmss0_pa_cooling_map;
+/delete-node/ &mdmss0_modem_cooling_map;
+/delete-node/ &mdmss1_pa_cooling_map;
+/delete-node/ &mdmss1_modem_cooling_map;
+/delete-node/ &mdmss2_pa_cooling_map;
+/delete-node/ &mdmss2_modem_cooling_map;
+/delete-node/ &mdmss3_pa_cooling_map;
+/delete-node/ &mdmss3_modem_cooling_map;
+
&remoteproc_mpss {
compatible = "qcom,sc7280-mss-pil";
+ /delete-property/ #cooling-cells;
reg = <0 0x04080000 0 0x10000>, <0 0x04180000 0 0x48>;
reg-names = "qdsp6", "rmb";
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi
index 3ebc915f0dc2..296c72672ec5 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi
@@ -7,6 +7,15 @@
/* WIFI SKUs save 256M by not having modem/mba/rmtfs memory regions defined. */
+/delete-node/ &mdmss0_pa_cooling_map;
+/delete-node/ &mdmss0_modem_cooling_map;
+/delete-node/ &mdmss1_pa_cooling_map;
+/delete-node/ &mdmss1_modem_cooling_map;
+/delete-node/ &mdmss2_pa_cooling_map;
+/delete-node/ &mdmss2_modem_cooling_map;
+/delete-node/ &mdmss3_pa_cooling_map;
+/delete-node/ &mdmss3_modem_cooling_map;
+
/delete-node/ &mpss_mem;
/delete-node/ &remoteproc_mpss;
/delete-node/ &rmtfs_mem;
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 6/9] arm64: dts: qcom: lemans: Enable CDSP cooling
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
` (4 preceding siblings ...)
2026-07-27 14:22 ` [PATCH v6 5/9] arm64: dts: qcom: kodiak: Enable CDSP & Modem cooling Gaurav Kohli
@ 2026-07-27 14:22 ` Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 7/9] arm64: dts: qcom: talos: " Gaurav Kohli
` (2 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi, Dmitry Baryshkov
Unlike the CPU, the CDSP does not throttle its speed automatically
when it reaches high temperatures in lemans.
Set up CDSP cooling for both instances by throttling the cdsp, when
it reaches 105°C.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/lemans.dtsi | 125 +++++++++++++++++++++++++++++++----
1 file changed, 113 insertions(+), 12 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi
index 3b0539e27b51..2ca14300ec6d 100644
--- a/arch/arm64/boot/dts/qcom/lemans.dtsi
+++ b/arch/arm64/boot/dts/qcom/lemans.dtsi
@@ -21,6 +21,7 @@
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/soc/qcom,gpr.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
+#include <dt-bindings/thermal/qcom,pas.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -7773,6 +7774,8 @@ remoteproc_cdsp0: remoteproc@26300000 {
qcom,smem-states = <&smp2p_cdsp0_out 0>;
qcom,smem-state-names = "stop";
+ #cooling-cells = <3>;
+
status = "disabled";
glink-edge {
@@ -7912,6 +7915,8 @@ remoteproc_cdsp1: remoteproc@2a300000 {
qcom,smem-states = <&smp2p_cdsp1_out 0>;
qcom,smem-state-names = "stop";
+ #cooling-cells = <3>;
+
status = "disabled";
glink-edge {
@@ -8760,7 +8765,7 @@ nsp-0-0-0-thermal {
thermal-sensors = <&tsens2 5>;
trips {
- trip-point0 {
+ nsp_0_0_0_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -8772,6 +8777,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_0_0_alert0>;
+ cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-0-1-0-thermal {
@@ -8780,7 +8793,7 @@ nsp-0-1-0-thermal {
thermal-sensors = <&tsens2 6>;
trips {
- trip-point0 {
+ nsp_0_1_0_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -8792,6 +8805,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_1_0_alert0>;
+ cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-0-2-0-thermal {
@@ -8800,7 +8821,7 @@ nsp-0-2-0-thermal {
thermal-sensors = <&tsens2 7>;
trips {
- trip-point0 {
+ nsp_0_2_0_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -8812,6 +8833,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_2_0_alert0>;
+ cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-1-0-0-thermal {
@@ -8820,7 +8849,7 @@ nsp-1-0-0-thermal {
thermal-sensors = <&tsens2 8>;
trips {
- trip-point0 {
+ nsp_1_0_0_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -8832,6 +8861,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_1_0_0_alert0>;
+ cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-1-1-0-thermal {
@@ -8840,7 +8877,7 @@ nsp-1-1-0-thermal {
thermal-sensors = <&tsens2 9>;
trips {
- trip-point0 {
+ nsp_1_1_0_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -8852,6 +8889,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_1_1_0_alert0>;
+ cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-1-2-0-thermal {
@@ -8860,7 +8905,7 @@ nsp-1-2-0-thermal {
thermal-sensors = <&tsens2 10>;
trips {
- trip-point0 {
+ nsp_1_2_0_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -8872,6 +8917,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_1_2_0_alert0>;
+ cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
ddrss-0-thermal {
@@ -9014,7 +9067,7 @@ nsp-0-0-1-thermal {
thermal-sensors = <&tsens3 5>;
trips {
- trip-point0 {
+ nsp_0_0_1_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -9026,6 +9079,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_0_1_alert0>;
+ cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-0-1-1-thermal {
@@ -9034,7 +9095,7 @@ nsp-0-1-1-thermal {
thermal-sensors = <&tsens3 6>;
trips {
- trip-point0 {
+ nsp_0_1_1_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -9046,6 +9107,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_1_1_alert0>;
+ cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-0-2-1-thermal {
@@ -9054,7 +9123,7 @@ nsp-0-2-1-thermal {
thermal-sensors = <&tsens3 7>;
trips {
- trip-point0 {
+ nsp_0_2_1_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -9066,6 +9135,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_2_1_alert0>;
+ cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-1-0-1-thermal {
@@ -9074,7 +9151,7 @@ nsp-1-0-1-thermal {
thermal-sensors = <&tsens3 8>;
trips {
- trip-point0 {
+ nsp_1_0_1_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -9086,6 +9163,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_1_0_1_alert0>;
+ cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-1-1-1-thermal {
@@ -9094,7 +9179,7 @@ nsp-1-1-1-thermal {
thermal-sensors = <&tsens3 9>;
trips {
- trip-point0 {
+ nsp_1_1_1_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -9106,6 +9191,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_1_1_1_alert0>;
+ cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-1-2-1-thermal {
@@ -9114,7 +9207,7 @@ nsp-1-2-1-thermal {
thermal-sensors = <&tsens3 10>;
trips {
- trip-point0 {
+ nsp_1_2_1_alert0: trip-point0 {
temperature = <105000>;
hysteresis = <5000>;
type = "passive";
@@ -9126,6 +9219,14 @@ trip-point1 {
type = "passive";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_1_2_1_alert0>;
+ cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
ddrss-1-thermal {
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 7/9] arm64: dts: qcom: talos: Enable CDSP cooling
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
` (5 preceding siblings ...)
2026-07-27 14:22 ` [PATCH v6 6/9] arm64: dts: qcom: lemans: Enable CDSP cooling Gaurav Kohli
@ 2026-07-27 14:22 ` Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 8/9] arm64: dts: qcom: monaco: " Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 9/9] arm64: dts: qcom: hamoa: " Gaurav Kohli
8 siblings, 0 replies; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi, Dmitry Baryshkov
Unlike the CPU, the CDSP does not throttle its speed automatically
when it reaches high temperatures in talos.
Set up CDSP cooling by throttling the cdsp, when it reaches 105°C.
Add polling-delay-passive so the governor periodically evaluates
the zone during passive cooling and steps up cooling levels when
temperature stabilizes below the next trip.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/talos.dtsi | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi
index bdfb70ca9740..0fb7cb8e9f64 100644
--- a/arch/arm64/boot/dts/qcom/talos.dtsi
+++ b/arch/arm64/boot/dts/qcom/talos.dtsi
@@ -21,6 +21,7 @@
#include <dt-bindings/power/qcom,rpmhpd.h>
#include <dt-bindings/soc/qcom,gpr.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
+#include <dt-bindings/thermal/qcom,pas.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -3840,6 +3841,8 @@ remoteproc_cdsp: remoteproc@8300000 {
qcom,smem-states = <&cdsp_smp2p_out 0>;
qcom,smem-state-names = "stop";
+ #cooling-cells = <3>;
+
status = "disabled";
glink-edge {
@@ -5497,15 +5500,31 @@ map0 {
};
q6-hvx-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens0 10>;
trips {
+ q6_hvx_alert0: trip-point0 {
+ temperature = <105000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
q6-hvx-critical {
temperature = <115000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&q6_hvx_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
mdm-core-thermal {
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 8/9] arm64: dts: qcom: monaco: Enable CDSP cooling
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
` (6 preceding siblings ...)
2026-07-27 14:22 ` [PATCH v6 7/9] arm64: dts: qcom: talos: " Gaurav Kohli
@ 2026-07-27 14:22 ` Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 9/9] arm64: dts: qcom: hamoa: " Gaurav Kohli
8 siblings, 0 replies; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi, Dmitry Baryshkov
Unlike the CPU, the CDSP does not throttle its speed automatically
when it reaches high temperatures in monaco.
Set up CDSP cooling for both instances by throttling the cdsp, when
it reaches 115°C.
Add polling-delay-passive so the governor periodically evaluates
the zone during passive cooling and steps up cooling levels when
temperature stabilizes below the next trip.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/monaco.dtsi | 99 ++++++++++++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi
index 64fc0d592282..3f388c000fbb 100644
--- a/arch/arm64/boot/dts/qcom/monaco.dtsi
+++ b/arch/arm64/boot/dts/qcom/monaco.dtsi
@@ -22,6 +22,7 @@
#include <dt-bindings/soc/qcom,gpr.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
#include <dt-bindings/sound/qcom,q6dsp-lpass-ports.h>
+#include <dt-bindings/thermal/qcom,pas.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -7738,6 +7739,8 @@ remoteproc_cdsp: remoteproc@26300000 {
qcom,smem-states = <&smp2p_cdsp_out 0>;
qcom,smem-state-names = "stop";
+ #cooling-cells = <3>;
+
status = "disabled";
glink-edge {
@@ -8170,39 +8173,87 @@ cpu-critical {
};
nsp-0-0-0-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens2 5>;
trips {
+ nsp_0_0_0_alert0: trip-point0 {
+ temperature = <115000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp-critical {
temperature = <125000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_0_0_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-0-1-0-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens2 6>;
trips {
+ nsp_0_1_0_alert0: trip-point0 {
+ temperature = <115000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp-critical {
temperature = <125000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_1_0_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-0-2-0-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens2 7>;
trips {
+ nsp_0_2_0_alert0: trip-point0 {
+ temperature = <115000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp-critical {
temperature = <125000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_2_0_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
ddrss-0-thermal {
@@ -8290,39 +8341,87 @@ cpu-critical {
};
nsp-0-0-1-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens3 5>;
trips {
+ nsp_0_0_1_alert0: trip-point0 {
+ temperature = <115000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp-critical {
temperature = <125000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_0_1_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-0-1-1-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens3 6>;
trips {
+ nsp_0_1_1_alert0: trip-point0 {
+ temperature = <115000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp-critical {
temperature = <125000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_1_1_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
nsp-0-2-1-thermal {
+ polling-delay-passive = <200>;
+
thermal-sensors = <&tsens3 7>;
trips {
+ nsp_0_2_1_alert0: trip-point0 {
+ temperature = <115000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp-critical {
temperature = <125000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp_0_2_1_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
ddrss-1-thermal {
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 9/9] arm64: dts: qcom: hamoa: Enable CDSP cooling
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
` (7 preceding siblings ...)
2026-07-27 14:22 ` [PATCH v6 8/9] arm64: dts: qcom: monaco: " Gaurav Kohli
@ 2026-07-27 14:22 ` Gaurav Kohli
2026-07-27 14:36 ` sashiko-bot
8 siblings, 1 reply; 13+ messages in thread
From: Gaurav Kohli @ 2026-07-27 14:22 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Lezcano, Amit Kucheria,
Konrad Dybcio, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Manivannan Sadhasivam, Gaurav Kohli, Kees Cook,
Gustavo A. R. Silva, cros-qcom-dts-watchers
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
linux-pm, linux-hardening, manaf.pallikunhi, Dipa Ramesh Mantre,
Dmitry Baryshkov
From: Dipa Ramesh Mantre <dipa.mantre@oss.qualcomm.com>
Unlike the CPU, the CDSP does not throttle its speed automatically
when it reaches high temperatures in hamoa.
Set up CDSP cooling for both instances by throttling the cdsp, when
it reaches 95°C.
Add polling-delay-passive so the governor periodically evaluates
the zone during passive cooling and steps up cooling levels when
temperature stabilizes below the next trip.
Signed-off-by: Dipa Ramesh Mantre <dipa.mantre@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 32 +++++++++++++++
arch/arm64/boot/dts/qcom/hamoa.dtsi | 63 ++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts
index 9fa86bb6438e..a146be1cb5fb 100644
--- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts
+++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts
@@ -1684,4 +1684,36 @@ trip-point0 {
};
};
};
+
+ nsp0-thermal {
+ trips {
+ trip-point1 {
+ temperature = <105000>;
+ };
+ };
+ };
+
+ nsp1-thermal {
+ trips {
+ trip-point1 {
+ temperature = <105000>;
+ };
+ };
+ };
+
+ nsp2-thermal {
+ trips {
+ trip-point1 {
+ temperature = <105000>;
+ };
+ };
+ };
+
+ nsp3-thermal {
+ trips {
+ trip-point1 {
+ temperature = <105000>;
+ };
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi
index 09527dcf9576..ba453c8ca80d 100644
--- a/arch/arm64/boot/dts/qcom/hamoa.dtsi
+++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi
@@ -23,6 +23,7 @@
#include <dt-bindings/soc/qcom,gpr.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
#include <dt-bindings/sound/qcom,q6dsp-lpass-ports.h>
+#include <dt-bindings/thermal/qcom,pas.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -8971,6 +8972,8 @@ remoteproc_cdsp: remoteproc@32300000 {
status = "disabled";
+ #cooling-cells = <3>;
+
glink-edge {
interrupts-extended = <&ipcc IPCC_CLIENT_CDSP
IPCC_MPROC_SIGNAL_GLINK_QMP
@@ -9558,6 +9561,7 @@ aoss0-critical {
};
thermal_nsp0: nsp0-thermal {
+ polling-delay-passive = <200>;
thermal-sensors = <&tsens3 1>;
trips {
@@ -9567,15 +9571,30 @@ trip-point0 {
type = "hot";
};
+ nsp0_alert0: trip-point1 {
+ temperature = <95000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp0-critical {
temperature = <115000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp0_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
thermal_nsp1: nsp1-thermal {
+ polling-delay-passive = <200>;
thermal-sensors = <&tsens3 2>;
trips {
@@ -9585,15 +9604,30 @@ trip-point0 {
type = "hot";
};
+ nsp1_alert0: trip-point1 {
+ temperature = <95000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp1-critical {
temperature = <115000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp1_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
thermal_nsp2: nsp2-thermal {
+ polling-delay-passive = <200>;
thermal-sensors = <&tsens3 3>;
trips {
@@ -9603,15 +9637,30 @@ trip-point0 {
type = "hot";
};
+ nsp2_alert0: trip-point1 {
+ temperature = <95000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp2-critical {
temperature = <115000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp2_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
thermal_nsp3: nsp3-thermal {
+ polling-delay-passive = <200>;
thermal-sensors = <&tsens3 4>;
trips {
@@ -9621,12 +9670,26 @@ trip-point0 {
type = "hot";
};
+ nsp3_alert0: trip-point1 {
+ temperature = <95000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+
nsp3-critical {
temperature = <115000>;
hysteresis = <1000>;
type = "critical";
};
};
+
+ cooling-maps {
+ map0 {
+ trip = <&nsp3_alert0>;
+ cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW
+ THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
thermal_gpuss_0: gpuss-0-thermal {
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v6 9/9] arm64: dts: qcom: hamoa: Enable CDSP cooling
2026-07-27 14:22 ` [PATCH v6 9/9] arm64: dts: qcom: hamoa: " Gaurav Kohli
@ 2026-07-27 14:36 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-07-27 14:36 UTC (permalink / raw)
To: Gaurav Kohli; +Cc: conor+dt, devicetree, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The commit message claims to set up CDSP cooling for 'both instances', but the patch actually configures 4 NSP thermal zones mapping to a single CDSP instance.
--
--- Patch [9]: [PATCH v6 9/9] arm64: dts: qcom: hamoa: Enable CDSP cooling ---
commit 11f46654cec2615152b5d3c181397f2d61caf2f7
Author: Dipa Ramesh Mantre <dipa.mantre@oss.qualcomm.com>
arm64: dts: qcom: hamoa: Enable CDSP cooling
This commit enables CDSP cooling for the hamoa platform. It configures
a polling delay for passive cooling and maps thermal zones to the CDSP
cooling device to throttle it when high temperatures are reached.
> Set up CDSP cooling for both instances by throttling the cdsp, when
> it reaches 95°C.
[Severity: Medium]
This isn't a bug, but there appears to be a mismatch between the commit
message and the actual code changes. The description mentions setting up
cooling for "both instances", which implies two instances.
However, the patch actually configures four NSP thermal zones (nsp0 through
nsp3) that all map to a single remoteproc_cdsp node in
arch/arm64/boot/dts/qcom/hamoa.dtsi.
Could the commit message be updated to accurately reflect the correct
number of instances and thermal zones being configured?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260727-b4-qmi-tmd-v6-0-973cd3a226af@oss.qualcomm.com?part=9
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 3/9] remoteproc: qcom: pas: add support for TMD thermal cooling devices
2026-07-27 14:22 ` [PATCH v6 3/9] remoteproc: qcom: pas: add support for TMD thermal cooling devices Gaurav Kohli
@ 2026-07-27 14:37 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-07-27 14:37 UTC (permalink / raw)
To: Gaurav Kohli; +Cc: robh, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Incorrect teardown order of the TMD client relative to the remoteproc device in `qcom_pas_remove()`.
--
--- Patch [3]: [PATCH v6 3/9] remoteproc: qcom: pas: add support for TMD thermal cooling devices ---
commit 96a80a2d7479048c20fb270197f15552907de3de
Author: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
remoteproc: qcom: pas: add support for TMD thermal cooling devices
This commit registers Thermal Mitigation Devices (TMDs) for PAS-managed
remote processors to enable thermal throttling through QMI.
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index 25599d7282083..07336a2d75f73 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
[ ... ]
> @@ -960,6 +1045,9 @@ static void qcom_pas_remove(struct platform_device *pdev)
> if (pas->bam_dmux)
> of_platform_device_destroy(&pas->bam_dmux->dev, NULL);
>
> + if (pas->tmd_inst)
> + qmi_tmd_exit(pas->tmd_inst);
> +
> rproc_del(pas->rproc);
[Severity: Low]
Does this sequence unregister the thermal mitigation cooling device in the
wrong order?
Looking at qcom_pas_probe(), qcom_pas_setup_tmd() is called before rproc_add().
Should qmi_tmd_exit() be called after rproc_del() in qcom_pas_remove()
to maintain strict reverse-initialization ordering?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260727-b4-qmi-tmd-v6-0-973cd3a226af@oss.qualcomm.com?part=3
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 2/9] soc: qcom: Add QMI TMD support for remote thermal mitigation
2026-07-27 14:22 ` [PATCH v6 2/9] soc: qcom: Add QMI TMD support for remote thermal mitigation Gaurav Kohli
@ 2026-07-27 14:40 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-07-27 14:40 UTC (permalink / raw)
To: Gaurav Kohli; +Cc: conor+dt, robh, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unprotected read of `tmd->cur_state` during QMI reconnect can cause the remote mitigation state to permanently desynchronize from the thermal core.
- [Medium] Data race on `tmd->max_state` between the QMI worker and thermal core callbacks.
--
--- Patch [2]: [PATCH v6 2/9] soc: qcom: Add QMI TMD support for remote thermal mitigation ---
commit 8a125ac63b99f7508e9f1e7c025b0c0da679cac6
Author: Casey Connolly <casey.connolly@linaro.org>
soc: qcom: Add QMI TMD support for remote thermal mitigation
Add support for Qualcomm Messaging Interface (QMI) based Thermal Mitigation
Device (TMD) cooling devices provided by remote subsystems.
> diff --git a/drivers/soc/qcom/qmi_tmd.c b/drivers/soc/qcom/qmi_tmd.c
> new file mode 100644
> index 0000000000000..555f2aff1ac0f
> --- /dev/null
> +++ b/drivers/soc/qcom/qmi_tmd.c
[ ... ]
> +static int qmi_tmd_set_cur_state(struct thermal_cooling_device *cdev,
> + unsigned long state)
> +{
> + struct qmi_tmd *tmd = cdev->devdata;
> + int ret;
> +
> + if (state > tmd->max_state)
> + return -EINVAL;
> +
> + /* cur_state is protected by thermal core's cdev->lock */
> + if (tmd->cur_state == state)
> + return 0;
> +
> + ret = qmi_tmd_send_state_request(tmd, state);
> + if (!ret)
> + tmd->cur_state = state;
[Severity: High]
Can the remote mitigation state permanently desynchronize from the thermal
core here?
If a remote QMI subsystem restarts, it triggers qmi_tmd_svc_arrive() and
qmi_tmd_register(). Concurrently, the thermal core might update the cooling
state via qmi_tmd_set_cur_state().
In qmi_tmd_set_cur_state(), the request is sent first, and tmd->cur_state is
updated afterwards without holding qmi_tmd_cli->mutex. This creates a window
where the state has been updated on the remote device, but tmd->cur_state
does not yet reflect the new state.
Could the following sequence occur?
CPU A (thermal core)
qmi_tmd_set_cur_state()
qmi_tmd_send_state_request()
// acquires and releases mutex, sends new state
<preempted before updating tmd->cur_state>
CPU B (reconnect work)
qmi_tmd_register()
reads tmd->cur_state (which is still the old state)
qmi_tmd_send_state_request()
// acquires mutex, sends old state
CPU A (resumes)
tmd->cur_state = state;
If this happens, the remote device would be left running with the old state,
while the local thermal core tracks the new state. Should tmd->cur_state be
read and updated under the protection of a lock?
> +
> + return ret;
> +}
[ ... ]
> +static int qmi_tmd_register(struct qmi_tmd_client *qmi_tmd_cli,
> + const char *label, u8 max_state)
> +{
> + struct device *dev = qmi_tmd_cli->dev;
> + struct qmi_tmd *tmd;
> + int index;
> +
> + for (index = 0; index < qmi_tmd_cli->num_tmds; index++) {
> + tmd = &qmi_tmd_cli->tmds[index];
> +
> + if (!strncasecmp(tmd->name, label,
> + QMI_TMD_DEV_ID_LEN_MAX + 1))
> + goto found;
> + }
> +
> + dev_dbg(qmi_tmd_cli->dev,
> + "TMD '%s' available in firmware but not specified in DT\n",
> + label);
> + return 0;
> +
> +found:
> + tmd->max_state = max_state;
[Severity: Medium]
Could this write to tmd->max_state cause a data race?
This assignment in qmi_tmd_register() is executed from a workqueue when
the QMI service arrives, but it does not hold a lock. Concurrently, the
thermal core can invoke qmi_tmd_get_max_state() or qmi_tmd_set_cur_state(),
which both read tmd->max_state without holding shared locks.
While tearing might be unlikely on most architectures, could this
unsynchronized read and write trigger KCSAN warnings or lead to undefined
behavior?
> +
> + /*
> + * If the cooling device already exists then the QMI service went away and
> + * came back. So just make sure the current cooling device state is
> + * reflected on the remote side and then return.
> + */
> + if (tmd->cdev)
> + return qmi_tmd_send_state_request(tmd, tmd->cur_state);
> +
> + tmd->cdev = thermal_of_cooling_device_register(dev->of_node, index,
> + label, tmd, &qmi_tmd_cooling_ops);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260727-b4-qmi-tmd-v6-0-973cd3a226af@oss.qualcomm.com?part=2
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-07-27 14:40 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-27 14:22 [PATCH v6 0/9] Add support for Qualcomm remoteproc subsystem cooling Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 1/9] dt-bindings: remoteproc: qcom,pas: add #cooling-cells property Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 2/9] soc: qcom: Add QMI TMD support for remote thermal mitigation Gaurav Kohli
2026-07-27 14:40 ` sashiko-bot
2026-07-27 14:22 ` [PATCH v6 3/9] remoteproc: qcom: pas: add support for TMD thermal cooling devices Gaurav Kohli
2026-07-27 14:37 ` sashiko-bot
2026-07-27 14:22 ` [PATCH v6 4/9] remoteproc: qcom_q6v5_pas: enable QMI TMD cooling support Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 5/9] arm64: dts: qcom: kodiak: Enable CDSP & Modem cooling Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 6/9] arm64: dts: qcom: lemans: Enable CDSP cooling Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 7/9] arm64: dts: qcom: talos: " Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 8/9] arm64: dts: qcom: monaco: " Gaurav Kohli
2026-07-27 14:22 ` [PATCH v6 9/9] arm64: dts: qcom: hamoa: " Gaurav Kohli
2026-07-27 14:36 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox