From 937337ff1b345d79c7f8d38c7e2a2fbe175e9d13 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Wed, 5 May 2021 00:09:22 -0700 Subject: [PATCH 1/2] interconnect: qcom: Add support for enabling BCMs needed for QoS Some QoS blocks require voting for BCMs before their registers can be accessed, since they require clocks and regulators controlled by BCM. Change-Id: Ic93d224c7dc56c8e56d527179a0c2d1e888e3822 Signed-off-by: Mike Tipton Signed-off-by: Odelu Kukatla --- drivers/interconnect/qcom/icc-rpmh.c | 78 ++++++++++++++++++++++++++++ drivers/interconnect/qcom/icc-rpmh.h | 4 +- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index 367b70810db5..2d7d5f2b7341 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -177,4 +177,82 @@ int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev) } EXPORT_SYMBOL(qcom_icc_bcm_init); +static bool bcm_needs_qos_proxy(struct qcom_icc_bcm *bcm) +{ + int i; + + if (bcm->voter_idx == 0) + for (i = 0; i < bcm->num_nodes; i++) + if (bcm->nodes[i]->qosbox) + return true; + + return false; +} + +/** + * qcom_icc_enable_qos_deps - enable clocks and BCMs required for QoS + * @qp: interconnect provider associated with masters whose QoS to be set + * + * Return: 0 on success, or an error code otherwise + */ +int qcom_icc_enable_qos_deps(struct qcom_icc_provider *qp) +{ + struct qcom_icc_bcm *bcm; + struct bcm_voter *voter; + bool keepalive; + int ret, i; + + for (i = 0; i < qp->num_bcms; i++) { + bcm = qp->bcms[i]; + if (bcm_needs_qos_proxy(bcm)) { + keepalive = bcm->keepalive; + bcm->keepalive = true; + + voter = qp->voters[bcm->voter_idx]; + qcom_icc_bcm_voter_add(voter, bcm); + ret = qcom_icc_bcm_voter_commit(voter); + + bcm->keepalive = keepalive; + + if (ret) { + dev_err(qp->dev, "failed to vote BW to %s for QoS\n", + bcm->name); + return ret; + } + } + } + + ret = clk_bulk_prepare_enable(qp->num_clks, qp->clks); + if (ret) { + dev_err(qp->dev, "failed to enable clocks for QoS\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(qcom_icc_enable_qos_deps); + +/** + * qcom_icc_disable_qos_deps - disable clocks and BCMs + * @qp: interconnect provider associated with masters whose QoS to be set + */ +void qcom_icc_disable_qos_deps(struct qcom_icc_provider *qp) +{ + struct qcom_icc_bcm *bcm; + struct bcm_voter *voter; + int i; + + clk_bulk_disable_unprepare(qp->num_clks, qp->clks); + + for (i = 0; i < qp->num_bcms; i++) { + bcm = qp->bcms[i]; + if (bcm_needs_qos_proxy(bcm)) { + voter = qp->voters[bcm->voter_idx]; + qcom_icc_bcm_voter_add(voter, bcm); + qcom_icc_bcm_voter_commit(voter); + } + } +} +EXPORT_SYMBOL(qcom_icc_disable_qos_deps); + MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h index c4d255ffe365..ce0e9a5fb5fb 100644 --- a/drivers/interconnect/qcom/icc-rpmh.h +++ b/drivers/interconnect/qcom/icc-rpmh.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. * */ @@ -149,5 +149,7 @@ int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, int qcom_icc_set(struct icc_node *src, struct icc_node *dst); int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev); void qcom_icc_pre_aggregate(struct icc_node *node); +int qcom_icc_enable_qos_deps(struct qcom_icc_provider *qp); +void qcom_icc_disable_qos_deps(struct qcom_icc_provider *qp); #endif From d813843cc0b003e3ec24bc67cfc59446d6a80b42 Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Thu, 10 Jun 2021 15:49:50 +0530 Subject: [PATCH 2/2] interconnect: qcom: Enable BCMs needed for QoS configuration for Shima Some QoS blocks require voting for BCMs before their registers can be accessed, since they require clocks and regulators controlled by BCM. Vote for these BCMs before configuring QoS during probe. Change-Id: I6aaf8a963f4ace12eb639b61ae0ae45ac045d849 Signed-off-by: Odelu Kukatla --- drivers/interconnect/qcom/shima.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/interconnect/qcom/shima.c b/drivers/interconnect/qcom/shima.c index ad6c4bb014ce..f372f4515d28 100644 --- a/drivers/interconnect/qcom/shima.c +++ b/drivers/interconnect/qcom/shima.c @@ -2548,12 +2548,12 @@ static int qnoc_probe(struct platform_device *pdev) if (qp->num_clks < 0) return qp->num_clks; - ret = clk_bulk_prepare_enable(qp->num_clks, qp->clks); + for (i = 0; i < qp->num_bcms; i++) + qcom_icc_bcm_init(qp->bcms[i], &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "failed to enable clocks\n"); + ret = qcom_icc_enable_qos_deps(qp); + if (ret) return ret; - } for (i = 0; i < num_nodes; i++) { size_t j; @@ -2589,11 +2589,7 @@ static int qnoc_probe(struct platform_device *pdev) } data->num_nodes = num_nodes; - clk_bulk_disable_unprepare(qp->num_clks, qp->clks); - - for (i = 0; i < qp->num_bcms; i++) - qcom_icc_bcm_init(qp->bcms[i], &pdev->dev); - + qcom_icc_disable_qos_deps(qp); platform_set_drvdata(pdev, qp); dev_info(&pdev->dev, "Registered SHIMA ICC\n"); @@ -2609,6 +2605,7 @@ err: icc_node_destroy(node->id); } + qcom_icc_disable_qos_deps(qp); clk_bulk_put_all(qp->num_clks, qp->clks); icc_provider_del(provider);