mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
remoteproc: qcom: pas: add support for TMD thermal cooling devices
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. Reviewed-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com> Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com> Link: https://lore.kernel.org/r/20260809-b4-qmi-tmd-v8-3-b15d47adc379@oss.qualcomm.com Signed-off-by: Bjorn Andersson <andersson@kernel.org>
This commit is contained in:
parent
2ff581c218
commit
8eef721027
|
|
@ -236,6 +236,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
|
||||
|
|
|
|||
|
|
@ -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,9 +27,11 @@
|
|||
#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/power/qcom,rpmhpd.h>
|
||||
#include <dt-bindings/thermal/qcom,pas.h>
|
||||
|
||||
#include "qcom_common.h"
|
||||
#include "qcom_pil_info.h"
|
||||
|
|
@ -39,6 +42,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;
|
||||
|
|
@ -61,6 +74,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;
|
||||
|
|
@ -127,6 +144,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,
|
||||
|
|
@ -825,6 +844,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;
|
||||
|
|
@ -948,16 +1025,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);
|
||||
|
|
@ -985,6 +1070,9 @@ static void qcom_pas_remove(struct platform_device *pdev)
|
|||
|
||||
rproc_del(pas->rproc);
|
||||
|
||||
if (pas->tmd_inst)
|
||||
qmi_tmd_exit(pas->tmd_inst);
|
||||
|
||||
qcom_q6v5_deinit(&pas->q6v5);
|
||||
qcom_pas_unassign_memory_region(pas);
|
||||
qcom_remove_glink_subdev(pas->rproc, &pas->glink_subdev);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user