From ddbacca26d1db5bd9c477253b0af83b028136a24 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 9 Sep 2026 18:41:57 +0200 Subject: [PATCH] interconnect: qcom: icc-rpm: Program SMD RPM auxiliary QoS ports 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 Reviewed-by: Abel Vesa Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20260909-topic-icc_rpm_smd_qol-v1-4-6dc5b5e97626@oss.qualcomm.com Signed-off-by: Georgi Djakov --- 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 fa69418818d6..407233f2d121 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,8 +180,24 @@ static int qcom_icc_noc_set_qos_priority(struct qcom_icc_provider *qp, if (rc) return rc; + 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->qos_port), + qp->qos_offset + NOC_QOS_PRIORITYn_ADDR(qos->aux_qos_port), NOC_QOS_PRIORITY_P0_MASK, qos->prio_level); } @@ -182,8 +233,17 @@ static int qcom_icc_set_noc_qos(struct icc_node *src) /* How did we get here? */ } + 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.qos_port), + qp->qos_offset + NOC_QOS_MODEn_ADDR(qn->qos.aux_qos_port), NOC_QOS_MODEn_MASK, mode); } 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; };