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>
This commit is contained in:
Varadarajan Narayanan
2024-04-30 12:12:12 +05:30
committed by Bjorn Andersson
parent d315311361
commit 8737ec830e
2 changed files with 43 additions and 1 deletions

View File

@@ -8,6 +8,7 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/interconnect-clk.h>
#include <linux/reset-controller.h> #include <linux/reset-controller.h>
#include <linux/of.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; 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, int qcom_cc_really_probe(struct device *dev,
const struct qcom_cc_desc *desc, struct regmap *regmap) const struct qcom_cc_desc *desc, struct regmap *regmap)
{ {
@@ -320,7 +353,7 @@ int qcom_cc_really_probe(struct device *dev,
if (ret) if (ret)
return ret; return ret;
return 0; return qcom_cc_icc_register(dev, desc);
} }
EXPORT_SYMBOL_GPL(qcom_cc_really_probe); EXPORT_SYMBOL_GPL(qcom_cc_really_probe);

View File

@@ -19,6 +19,12 @@ struct clk_hw;
#define PLL_VOTE_FSM_ENA BIT(20) #define PLL_VOTE_FSM_ENA BIT(20)
#define PLL_VOTE_FSM_RESET BIT(21) #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 { struct qcom_cc_desc {
const struct regmap_config *config; const struct regmap_config *config;
struct clk_regmap **clks; struct clk_regmap **clks;
@@ -29,6 +35,9 @@ struct qcom_cc_desc {
size_t num_gdscs; size_t num_gdscs;
struct clk_hw **clk_hws; struct clk_hw **clk_hws;
size_t num_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;
}; };
/** /**