1702f26f6962d6126867cccbd4e5c6a5508eabaf
[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 --- a/drivers/clk/qcom/common.c
27 +++ b/drivers/clk/qcom/common.c
28 @@ -8,6 +8,7 @@
29 #include <linux/regmap.h>
30 #include <linux/platform_device.h>
31 #include <linux/clk-provider.h>
32 +#include <linux/interconnect-clk.h>
33 #include <linux/reset-controller.h>
34 #include <linux/of.h>
35
36 @@ -252,6 +253,38 @@ static struct clk_hw *qcom_cc_clk_hw_get
37 return cc->rclks[idx] ? &cc->rclks[idx]->hw : NULL;
38 }
39
40 +static int qcom_cc_icc_register(struct device *dev,
41 + const struct qcom_cc_desc *desc)
42 +{
43 + struct icc_clk_data *icd;
44 + struct clk_hw *hws;
45 + int i;
46 +
47 + if (!IS_ENABLED(CONFIG_INTERCONNECT_CLK))
48 + return 0;
49 +
50 + if (!desc->icc_hws)
51 + return 0;
52 +
53 + icd = devm_kcalloc(dev, desc->num_icc_hws, sizeof(*icd), GFP_KERNEL);
54 + if (!icd)
55 + return -ENOMEM;
56 +
57 + for (i = 0; i < desc->num_icc_hws; i++) {
58 + icd[i].master_id = desc->icc_hws[i].master_id;
59 + icd[i].slave_id = desc->icc_hws[i].slave_id;
60 + hws = &desc->clks[desc->icc_hws[i].clk_id]->hw;
61 + icd[i].clk = devm_clk_hw_get_clk(dev, hws, "icc");
62 + if (!icd[i].clk)
63 + return dev_err_probe(dev, -ENOENT,
64 + "(%d) clock entry is null\n", i);
65 + icd[i].name = clk_hw_get_name(hws);
66 + }
67 +
68 + return devm_icc_clk_register(dev, desc->icc_first_node_id,
69 + desc->num_icc_hws, icd);
70 +}
71 +
72 int qcom_cc_really_probe(struct device *dev,
73 const struct qcom_cc_desc *desc, struct regmap *regmap)
74 {
75 @@ -320,7 +353,7 @@ int qcom_cc_really_probe(struct device *
76 if (ret)
77 return ret;
78
79 - return 0;
80 + return qcom_cc_icc_register(dev, desc);
81 }
82 EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
83
84 --- a/drivers/clk/qcom/common.h
85 +++ b/drivers/clk/qcom/common.h
86 @@ -19,6 +19,12 @@ struct clk_hw;
87 #define PLL_VOTE_FSM_ENA BIT(20)
88 #define PLL_VOTE_FSM_RESET BIT(21)
89
90 +struct qcom_icc_hws_data {
91 + int master_id;
92 + int slave_id;
93 + int clk_id;
94 +};
95 +
96 struct qcom_cc_desc {
97 const struct regmap_config *config;
98 struct clk_regmap **clks;
99 @@ -29,6 +35,9 @@ struct qcom_cc_desc {
100 size_t num_gdscs;
101 struct clk_hw **clk_hws;
102 size_t num_clk_hws;
103 + struct qcom_icc_hws_data *icc_hws;
104 + size_t num_icc_hws;
105 + unsigned int icc_first_node_id;
106 };
107
108 /**