summaryrefslogtreecommitdiff
path: root/drivers/interconnect/qcom/icc-rpm.c
diff options
context:
space:
mode:
authorLeo Yan <leo.yan@linaro.org>2022-07-12 04:59:28 +0300
committerGeorgi Djakov <djakov@kernel.org>2022-07-12 10:03:09 +0300
commitdcbce7b0a79cc5bc16759079090e1a3aa8dfea34 (patch)
tree52158b3491d735f1b9a55db0fac7d6887b7decdd /drivers/interconnect/qcom/icc-rpm.c
parentad510e4ed2a3b6f195c2aed6fe21a311440b489b (diff)
downloadlinux-dcbce7b0a79cc5bc16759079090e1a3aa8dfea34.tar.xz
interconnect: qcom: icc-rpm: Support multiple buckets
The current interconnect rpm driver uses a single aggregate bandwidth to calculate the clock rates for both active and sleep clocks; therefore, it has no chance to separate bandwidth requests for these two kinds of clocks. This patch studies the implementation from interconnect rpmh driver to support multiple buckets. The rpmh driver provides three buckets for AMC, WAKE, and SLEEP; this driver only needs to use WAKE and SLEEP buckets, but we keep the same way with rpmh driver, this can allow us to reuse the DT binding and avoid to define duplicated data structures. This patch introduces two callbacks: qcom_icc_pre_bw_aggregate() is used to clean up bucket values before aggregate bandwidth requests, and qcom_icc_bw_aggregate() is to aggregate bandwidth for buckets. Signed-off-by: Leo Yan <leo.yan@linaro.org> Link: https://lore.kernel.org/r/20220712015929.2789881-5-leo.yan@linaro.org Signed-off-by: Georgi Djakov <djakov@kernel.org>
Diffstat (limited to 'drivers/interconnect/qcom/icc-rpm.c')
-rw-r--r--drivers/interconnect/qcom/icc-rpm.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 8c9d5cc7276c..d27b1582521f 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -254,6 +254,54 @@ static int __qcom_icc_set(struct icc_node *n, struct qcom_icc_node *qn,
return 0;
}
+/**
+ * qcom_icc_pre_bw_aggregate - cleans up values before re-aggregate requests
+ * @node: icc node to operate on
+ */
+static void qcom_icc_pre_bw_aggregate(struct icc_node *node)
+{
+ struct qcom_icc_node *qn;
+ size_t i;
+
+ qn = node->data;
+ for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
+ qn->sum_avg[i] = 0;
+ qn->max_peak[i] = 0;
+ }
+}
+
+/**
+ * qcom_icc_bw_aggregate - aggregate bw for buckets indicated by tag
+ * @node: node to aggregate
+ * @tag: tag to indicate which buckets to aggregate
+ * @avg_bw: new bw to sum aggregate
+ * @peak_bw: new bw to max aggregate
+ * @agg_avg: existing aggregate avg bw val
+ * @agg_peak: existing aggregate peak bw val
+ */
+static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
+ u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
+{
+ size_t i;
+ struct qcom_icc_node *qn;
+
+ qn = node->data;
+
+ if (!tag)
+ tag = QCOM_ICC_TAG_ALWAYS;
+
+ for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
+ if (tag & BIT(i)) {
+ qn->sum_avg[i] += avg_bw;
+ qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw);
+ }
+ }
+
+ *agg_avg += avg_bw;
+ *agg_peak = max_t(u32, *agg_peak, peak_bw);
+ return 0;
+}
+
static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
{
struct qcom_icc_provider *qp;
@@ -414,7 +462,8 @@ regmap_done:
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev;
provider->set = qcom_icc_set;
- provider->aggregate = icc_std_aggregate;
+ provider->pre_aggregate = qcom_icc_pre_bw_aggregate;
+ provider->aggregate = qcom_icc_bw_aggregate;
provider->xlate_extended = qcom_icc_xlate_extended;
provider->data = data;