summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVaradarajan Narayanan <quic_varada@quicinc.com>2024-04-30 09:42:12 +0300
committerBjorn Andersson <andersson@kernel.org>2024-07-08 19:40:57 +0300
commit8737ec830ee32162858af7c1504169b05b313ab1 (patch)
tree28bbb90980375335185cbef28428ca359775ec71
parentd3153113619216e87038a20bebf82582f9be10e7 (diff)
downloadlinux-8737ec830ee32162858af7c1504169b05b313ab1.tar.xz
clk: qcom: common: Add interconnect clocks support
Unlike MSM platforms that manage NoC related clocks and scaling from RPM, IPQ SoCs dont involve RPM in managing NoC related clocks and there is no NoC scaling. However, there is a requirement to enable some NoC interface clocks for accessing the peripheral controllers present on these NoCs. Though exposing these as normal clocks would work, having a minimalistic interconnect driver to handle these clocks would make it consistent with other Qualcomm platforms resulting in common code paths. This is similar to msm8996-cbf's usage of icc-clk framework. Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com> Link: https://lore.kernel.org/r/20240430064214.2030013-5-quic_varada@quicinc.com Signed-off-by: Bjorn Andersson <andersson@kernel.org>
-rw-r--r--drivers/clk/qcom/common.c35
-rw-r--r--drivers/clk/qcom/common.h9
2 files changed, 43 insertions, 1 deletions
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index c92e10c60322..ea3788ba46f7 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -8,6 +8,7 @@
#include <linux/regmap.h>
#include <linux/platform_device.h>
#include <linux/clk-provider.h>
+#include <linux/interconnect-clk.h>
#include <linux/reset-controller.h>
#include <linux/of.h>
@@ -252,6 +253,38 @@ static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec,
return cc->rclks[idx] ? &cc->rclks[idx]->hw : NULL;
}
+static int qcom_cc_icc_register(struct device *dev,
+ const struct qcom_cc_desc *desc)
+{
+ struct icc_clk_data *icd;
+ struct clk_hw *hws;
+ int i;
+
+ if (!IS_ENABLED(CONFIG_INTERCONNECT_CLK))
+ return 0;
+
+ if (!desc->icc_hws)
+ return 0;
+
+ icd = devm_kcalloc(dev, desc->num_icc_hws, sizeof(*icd), GFP_KERNEL);
+ if (!icd)
+ return -ENOMEM;
+
+ for (i = 0; i < desc->num_icc_hws; i++) {
+ icd[i].master_id = desc->icc_hws[i].master_id;
+ icd[i].slave_id = desc->icc_hws[i].slave_id;
+ hws = &desc->clks[desc->icc_hws[i].clk_id]->hw;
+ icd[i].clk = devm_clk_hw_get_clk(dev, hws, "icc");
+ if (!icd[i].clk)
+ return dev_err_probe(dev, -ENOENT,
+ "(%d) clock entry is null\n", i);
+ icd[i].name = clk_hw_get_name(hws);
+ }
+
+ return devm_icc_clk_register(dev, desc->icc_first_node_id,
+ desc->num_icc_hws, icd);
+}
+
int qcom_cc_really_probe(struct device *dev,
const struct qcom_cc_desc *desc, struct regmap *regmap)
{
@@ -320,7 +353,7 @@ int qcom_cc_really_probe(struct device *dev,
if (ret)
return ret;
- return 0;
+ return qcom_cc_icc_register(dev, desc);
}
EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index d048bdeeba10..7e57f8fe8ea6 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -19,6 +19,12 @@ struct clk_hw;
#define PLL_VOTE_FSM_ENA BIT(20)
#define PLL_VOTE_FSM_RESET BIT(21)
+struct qcom_icc_hws_data {
+ int master_id;
+ int slave_id;
+ int clk_id;
+};
+
struct qcom_cc_desc {
const struct regmap_config *config;
struct clk_regmap **clks;
@@ -29,6 +35,9 @@ struct qcom_cc_desc {
size_t num_gdscs;
struct clk_hw **clk_hws;
size_t num_clk_hws;
+ struct qcom_icc_hws_data *icc_hws;
+ size_t num_icc_hws;
+ unsigned int icc_first_node_id;
};
/**