summaryrefslogtreecommitdiffstats
path: root/drivers/interconnect/qcom/icc-rpm.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 17:39:57 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 17:39:57 +0000
commitdc50eab76b709d68175a358d6e23a5a3890764d3 (patch)
treec754d0390db060af0213ff994f0ac310e4cfd6e9 /drivers/interconnect/qcom/icc-rpm.c
parentAdding debian version 6.6.15-2. (diff)
downloadlinux-dc50eab76b709d68175a358d6e23a5a3890764d3.tar.xz
linux-dc50eab76b709d68175a358d6e23a5a3890764d3.zip
Merging upstream version 6.7.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/interconnect/qcom/icc-rpm.c')
-rw-r--r--drivers/interconnect/qcom/icc-rpm.c76
1 files changed, 64 insertions, 12 deletions
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index e76356f911..dbacb2a7af 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -291,6 +291,32 @@ static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
return 0;
}
+static u64 qcom_icc_calc_rate(struct qcom_icc_provider *qp, struct qcom_icc_node *qn, int ctx)
+{
+ u64 agg_avg_rate, agg_peak_rate, agg_rate;
+
+ if (qn->channels)
+ agg_avg_rate = div_u64(qn->sum_avg[ctx], qn->channels);
+ else
+ agg_avg_rate = qn->sum_avg[ctx];
+
+ if (qn->ab_coeff) {
+ agg_avg_rate = agg_avg_rate * qn->ab_coeff;
+ agg_avg_rate = div_u64(agg_avg_rate, 100);
+ }
+
+ if (qn->ib_coeff) {
+ agg_peak_rate = qn->max_peak[ctx] * 100;
+ agg_peak_rate = div_u64(agg_peak_rate, qn->ib_coeff);
+ } else {
+ agg_peak_rate = qn->max_peak[ctx];
+ }
+
+ agg_rate = max_t(u64, agg_avg_rate, agg_peak_rate);
+
+ return div_u64(agg_rate, qn->buswidth);
+}
+
/**
* qcom_icc_bus_aggregate - calculate bus clock rates by traversing all nodes
* @provider: generic interconnect provider
@@ -298,10 +324,10 @@ static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
*/
static void qcom_icc_bus_aggregate(struct icc_provider *provider, u64 *agg_clk_rate)
{
- u64 agg_avg_rate, agg_rate;
+ struct qcom_icc_provider *qp = to_qcom_provider(provider);
struct qcom_icc_node *qn;
struct icc_node *node;
- int i;
+ int ctx;
/*
* Iterate nodes on the provider, aggregate bandwidth requests for
@@ -309,16 +335,9 @@ static void qcom_icc_bus_aggregate(struct icc_provider *provider, u64 *agg_clk_r
*/
list_for_each_entry(node, &provider->nodes, node_list) {
qn = node->data;
- for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) {
- if (qn->channels)
- agg_avg_rate = div_u64(qn->sum_avg[i], qn->channels);
- else
- agg_avg_rate = qn->sum_avg[i];
-
- agg_rate = max_t(u64, agg_avg_rate, qn->max_peak[i]);
- do_div(agg_rate, qn->buswidth);
-
- agg_clk_rate[i] = max_t(u64, agg_clk_rate[i], agg_rate);
+ for (ctx = 0; ctx < QCOM_SMD_RPM_STATE_NUM; ctx++) {
+ agg_clk_rate[ctx] = max_t(u64, agg_clk_rate[ctx],
+ qcom_icc_calc_rate(qp, qn, ctx));
}
}
}
@@ -395,6 +414,33 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
qp->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE] = sleep_rate;
}
+ /* Handle the node-specific clock */
+ if (!src_qn->bus_clk_desc)
+ return 0;
+
+ active_rate = qcom_icc_calc_rate(qp, src_qn, QCOM_SMD_RPM_ACTIVE_STATE);
+ sleep_rate = qcom_icc_calc_rate(qp, src_qn, QCOM_SMD_RPM_SLEEP_STATE);
+
+ if (active_rate != src_qn->bus_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE]) {
+ ret = qcom_icc_rpm_set_bus_rate(src_qn->bus_clk_desc, QCOM_SMD_RPM_ACTIVE_STATE,
+ active_rate);
+ if (ret)
+ return ret;
+
+ /* Cache the rate after we've successfully committed it to RPM */
+ src_qn->bus_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE] = active_rate;
+ }
+
+ if (sleep_rate != src_qn->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE]) {
+ ret = qcom_icc_rpm_set_bus_rate(src_qn->bus_clk_desc, QCOM_SMD_RPM_SLEEP_STATE,
+ sleep_rate);
+ if (ret)
+ return ret;
+
+ /* Cache the rate after we've successfully committed it to RPM */
+ src_qn->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE] = sleep_rate;
+ }
+
return 0;
}
@@ -517,6 +563,12 @@ regmap_done:
for (i = 0; i < num_nodes; i++) {
size_t j;
+ if (!qnodes[i]->ab_coeff)
+ qnodes[i]->ab_coeff = qp->ab_coeff;
+
+ if (!qnodes[i]->ib_coeff)
+ qnodes[i]->ib_coeff = qp->ib_coeff;
+
node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) {
clk_bulk_disable_unprepare(qp->num_intf_clks,