[PATCH 4/6] interconnect: qcom: icc-rpm: Program SMD RPM auxiliary QoS ports
From: Konrad Dybcio
Date: Wed Sep 09 2026 - 13:59:19 EST
From: Konrad Dybcio <konrad.dybcio@xxxxxxxxxxxxxxxx>
Some SMD RPM interconnect nodes own two QoS ports. Currently, the code
only takes care of one, leaving some endpoints partially unconfigured.
Keep qos_port as the primary port and describe the optional second port
with aux_qos_port.
Assisted-by: LLM
Signed-off-by: Konrad Dybcio <konrad.dybcio@xxxxxxxxxxxxxxxx>
---
drivers/interconnect/qcom/icc-rpm.c | 82 ++++++++++++++++++++++++++++++++-----
drivers/interconnect/qcom/icc-rpm.h | 2 +
2 files changed, 73 insertions(+), 11 deletions(-)
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 5d8a41aede8b..12387de98318 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -58,15 +58,32 @@ static int qcom_icc_set_qnoc_qos(struct icc_node *src)
struct qcom_icc_qos *qos = &qn->qos;
int rc;
+ rc = regmap_update_bits(qp->regmap,
+ qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->qos_port),
+ QNOC_QOS_MCTL_DFLT_PRIO_MASK,
+ qos->areq_prio << QNOC_QOS_MCTL_DFLT_PRIO_SHIFT);
+ if (rc)
+ return rc;
+
rc = regmap_update_bits(qp->regmap,
qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->qos_port),
- QNOC_QOS_MCTL_DFLT_PRIO_MASK,
- qos->areq_prio << QNOC_QOS_MCTL_DFLT_PRIO_SHIFT);
+ QNOC_QOS_MCTL_URGFWD_EN_MASK,
+ !!qos->urg_fwd_en << QNOC_QOS_MCTL_URGFWD_EN_SHIFT);
+ if (rc)
+ return rc;
+
+ if (!qos->aux_qos_port)
+ return 0;
+
+ rc = regmap_update_bits(qp->regmap,
+ qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->aux_qos_port),
+ QNOC_QOS_MCTL_DFLT_PRIO_MASK,
+ qos->areq_prio << QNOC_QOS_MCTL_DFLT_PRIO_SHIFT);
if (rc)
return rc;
return regmap_update_bits(qp->regmap,
- qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->qos_port),
+ qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->aux_qos_port),
QNOC_QOS_MCTL_URGFWD_EN_MASK,
!!qos->urg_fwd_en << QNOC_QOS_MCTL_URGFWD_EN_SHIFT);
}
@@ -75,8 +92,9 @@ static int qcom_icc_bimc_set_qos_health(struct qcom_icc_provider *qp,
struct qcom_icc_qos *qos,
int regnum)
{
- u32 val;
u32 mask;
+ u32 val;
+ int ret;
val = qos->prio_level;
mask = M_BKE_HEALTH_CFG_PRIOLVL_MASK;
@@ -90,8 +108,17 @@ static int qcom_icc_bimc_set_qos_health(struct qcom_icc_provider *qp,
mask |= M_BKE_HEALTH_CFG_LIMITCMDS_MASK;
}
+ ret = regmap_update_bits(qp->regmap,
+ qp->qos_offset + M_BKE_HEALTH_CFG_ADDR(regnum, qos->qos_port),
+ mask, val);
+ if (ret)
+ return ret;
+
+ if (!qos->aux_qos_port)
+ return 0;
+
return regmap_update_bits(qp->regmap,
- qp->qos_offset + M_BKE_HEALTH_CFG_ADDR(regnum, qos->qos_port),
+ qp->qos_offset + M_BKE_HEALTH_CFG_ADDR(regnum, qos->aux_qos_port),
mask, val);
}
@@ -102,7 +129,7 @@ static int qcom_icc_set_bimc_qos(struct icc_node *src)
struct icc_provider *provider;
u32 mode = NOC_QOS_MODE_BYPASS;
u32 val = 0;
- int i, rc = 0;
+ int i, rc;
qn = src->data;
provider = src->provider;
@@ -116,8 +143,7 @@ static int qcom_icc_set_bimc_qos(struct icc_node *src)
*/
if (mode != NOC_QOS_MODE_BYPASS) {
for (i = 3; i >= 0; i--) {
- rc = qcom_icc_bimc_set_qos_health(qp,
- &qn->qos, i);
+ rc = qcom_icc_bimc_set_qos_health(qp, &qn->qos, i);
if (rc)
return rc;
}
@@ -126,8 +152,17 @@ static int qcom_icc_set_bimc_qos(struct icc_node *src)
val = 1;
}
+ rc = regmap_update_bits(qp->regmap,
+ qp->qos_offset + M_BKE_EN_ADDR(qn->qos.qos_port),
+ M_BKE_EN_EN_BMASK, val);
+ if (rc)
+ return rc;
+
+ if (!qn->qos.aux_qos_port)
+ return 0;
+
return regmap_update_bits(qp->regmap,
- qp->qos_offset + M_BKE_EN_ADDR(qn->qos.qos_port),
+ qp->qos_offset + M_BKE_EN_ADDR(qn->qos.aux_qos_port),
M_BKE_EN_EN_BMASK, val);
}
@@ -145,9 +180,25 @@ static int qcom_icc_noc_set_qos_priority(struct qcom_icc_provider *qp,
if (rc)
return rc;
- return regmap_update_bits(qp->regmap,
+ rc = regmap_update_bits(qp->regmap,
qp->qos_offset + NOC_QOS_PRIORITYn_ADDR(qos->qos_port),
NOC_QOS_PRIORITY_P0_MASK, qos->prio_level);
+ if (rc)
+ return rc;
+
+ if (!qos->aux_qos_port)
+ return 0;
+
+ val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT;
+ rc = regmap_update_bits(qp->regmap,
+ qp->qos_offset + NOC_QOS_PRIORITYn_ADDR(qos->aux_qos_port),
+ NOC_QOS_PRIORITY_P1_MASK, val);
+ if (rc)
+ return rc;
+
+ return regmap_update_bits(qp->regmap,
+ qp->qos_offset + NOC_QOS_PRIORITYn_ADDR(qos->aux_qos_port),
+ NOC_QOS_PRIORITY_P0_MASK, qos->prio_level);
}
static int qcom_icc_set_noc_qos(struct icc_node *src)
@@ -182,9 +233,18 @@ static int qcom_icc_set_noc_qos(struct icc_node *src)
/* How did we get here? */
}
- return regmap_update_bits(qp->regmap,
+ rc = regmap_update_bits(qp->regmap,
qp->qos_offset + NOC_QOS_MODEn_ADDR(qn->qos.qos_port),
NOC_QOS_MODEn_MASK, mode);
+ if (rc)
+ return rc;
+
+ if (!qn->qos.aux_qos_port)
+ return 0;
+
+ return regmap_update_bits(qp->regmap,
+ qp->qos_offset + NOC_QOS_MODEn_ADDR(qn->qos.aux_qos_port),
+ NOC_QOS_MODEn_MASK, mode);
}
static int qcom_icc_qos_set(struct icc_node *node)
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index cdd5f444b152..e36c378a80a3 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -77,6 +77,7 @@ struct qcom_icc_provider {
* @ap_owned: indicates if the node is owned by the AP or by the RPM
* @qos_mode: default qos mode for this node
* @qos_port: qos port number for finding qos registers of this node
+ * @aux_qos_port: optional QoS port in addition to @qos_port. Zero means "none".
* @urg_fwd_en: enable urgent forwarding
*/
struct qcom_icc_qos {
@@ -86,6 +87,7 @@ struct qcom_icc_qos {
bool ap_owned;
int qos_mode;
int qos_port;
+ u16 aux_qos_port;
bool urg_fwd_en;
};
--
2.55.0