e0af1be6183ba170af39fce2db00f34813c70a96
[openwrt/staging/stintel.git] /
1 From 8737ec830ee32162858af7c1504169b05b313ab1 Mon Sep 17 00:00:00 2001
2 From: Varadarajan Narayanan <quic_varada@quicinc.com>
3 Date: Tue, 30 Apr 2024 12:12:12 +0530
4 Subject: [PATCH] clk: qcom: common: Add interconnect clocks support
5
6 Unlike MSM platforms that manage NoC related clocks and scaling
7 from RPM, IPQ SoCs dont involve RPM in managing NoC related
8 clocks and there is no NoC scaling.
9
10 However, there is a requirement to enable some NoC interface
11 clocks for accessing the peripheral controllers present on
12 these NoCs. Though exposing these as normal clocks would work,
13 having a minimalistic interconnect driver to handle these clocks
14 would make it consistent with other Qualcomm platforms resulting
15 in common code paths. This is similar to msm8996-cbf's usage of
16 icc-clk framework.
17
18 Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
19 Link: https://lore.kernel.org/r/20240430064214.2030013-5-quic_varada@quicinc.com
20 Signed-off-by: Bjorn Andersson <andersson@kernel.org>
21 ---
22 drivers/clk/qcom/common.c | 35 ++++++++++++++++++++++++++++++++++-
23 drivers/clk/qcom/common.h | 9 +++++++++
24 2 files changed, 43 insertions(+), 1 deletion(-)
25
26 diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
27 index c92e10c60322..ea3788ba46f7 100644
28 --- a/drivers/clk/qcom/common.c
29 +++ b/drivers/clk/qcom/common.c
30 @@ -8,6 +8,7 @@
31 #include <linux/regmap.h>
32 #include <linux/platform_device.h>
33 #include <linux/clk-provider.h>
34 +#include <linux/interconnect-clk.h>
35 #include <linux/reset-controller.h>
36 #include <linux/of.h>
37
38 @@ -252,6 +253,38 @@ static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec,
39 return cc->rclks[idx] ? &cc->rclks[idx]->hw : NULL;
40 }
41
42 +static int qcom_cc_icc_register(struct device *dev,
43 + const struct qcom_cc_desc *desc)
44 +{
45 + struct icc_clk_data *icd;
46 + struct clk_hw *hws;
47 + int i;
48 +
49 + if (!IS_ENABLED(CONFIG_INTERCONNECT_CLK))
50 + return 0;
51 +
52 + if (!desc->icc_hws)
53 + return 0;
54 +
55 + icd = devm_kcalloc(dev, desc->num_icc_hws, sizeof(*icd), GFP_KERNEL);
56 + if (!icd)
57 + return -ENOMEM;
58 +
59 + for (i = 0; i < desc->num_icc_hws; i++) {
60 + icd[i].master_id = desc->icc_hws[i].master_id;
61 + icd[i].slave_id = desc->icc_hws[i].slave_id;
62 + hws = &desc->clks[desc->icc_hws[i].clk_id]->hw;
63 + icd[i].clk = devm_clk_hw_get_clk(dev, hws, "icc");
64 + if (!icd[i].clk)
65 + return dev_err_probe(dev, -ENOENT,
66 + "(%d) clock entry is null\n", i);
67 + icd[i].name = clk_hw_get_name(hws);
68 + }
69 +
70 + return devm_icc_clk_register(dev, desc->icc_first_node_id,
71 + desc->num_icc_hws, icd);
72 +}
73 +
74 int qcom_cc_really_probe(struct device *dev,
75 const struct qcom_cc_desc *desc, struct regmap *regmap)
76 {
77 @@ -320,7 +353,7 @@ int qcom_cc_really_probe(struct device *dev,
78 if (ret)
79 return ret;
80
81 - return 0;
82 + return qcom_cc_icc_register(dev, desc);
83 }
84 EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
85
86 diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
87 index d048bdeeba10..7e57f8fe8ea6 100644
88 --- a/drivers/clk/qcom/common.h
89 +++ b/drivers/clk/qcom/common.h
90 @@ -19,6 +19,12 @@ struct clk_hw;
91 #define PLL_VOTE_FSM_ENA BIT(20)
92 #define PLL_VOTE_FSM_RESET BIT(21)
93
94 +struct qcom_icc_hws_data {
95 + int master_id;
96 + int slave_id;
97 + int clk_id;
98 +};
99 +
100 struct qcom_cc_desc {
101 const struct regmap_config *config;
102 struct clk_regmap **clks;
103 @@ -29,6 +35,9 @@ struct qcom_cc_desc {
104 size_t num_gdscs;
105 struct clk_hw **clk_hws;
106 size_t num_clk_hws;
107 + struct qcom_icc_hws_data *icc_hws;
108 + size_t num_icc_hws;
109 + unsigned int icc_first_node_id;
110 };
111
112 /**
113 --
114 2.45.2
115