diff options
Diffstat (limited to 'drivers/clk/qcom/common.c')
-rw-r--r-- | drivers/clk/qcom/common.c | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 75f09e6e057e..33cc1f73c69d 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> @@ -41,6 +42,24 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate) } EXPORT_SYMBOL_GPL(qcom_find_freq); +const struct freq_multi_tbl *qcom_find_freq_multi(const struct freq_multi_tbl *f, + unsigned long rate) +{ + if (!f) + return NULL; + + if (!f->freq) + return f; + + for (; f->freq; f++) + if (rate <= f->freq) + return f; + + /* Default to our fastest rate */ + return f - 1; +} +EXPORT_SYMBOL_GPL(qcom_find_freq_multi); + const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f, unsigned long rate) { @@ -208,11 +227,9 @@ EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk); static void qcom_cc_drop_protected(struct device *dev, struct qcom_cc *cc) { struct device_node *np = dev->of_node; - struct property *prop; - const __be32 *p; u32 i; - of_property_for_each_u32(np, "protected-clocks", prop, p, i) { + of_property_for_each_u32(np, "protected-clocks", i) { if (i >= cc->num_rclks) continue; @@ -234,11 +251,42 @@ static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec, return cc->rclks[idx] ? &cc->rclks[idx]->hw : NULL; } -int qcom_cc_really_probe(struct platform_device *pdev, +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) { int i, ret; - struct device *dev = &pdev->dev; struct qcom_reset_controller *reset; struct qcom_cc *cc; struct gdsc_desc *scd; @@ -303,7 +351,7 @@ int qcom_cc_really_probe(struct platform_device *pdev, if (ret) return ret; - return 0; + return qcom_cc_icc_register(dev, desc); } EXPORT_SYMBOL_GPL(qcom_cc_really_probe); @@ -315,7 +363,7 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc) if (IS_ERR(regmap)) return PTR_ERR(regmap); - return qcom_cc_really_probe(pdev, desc, regmap); + return qcom_cc_really_probe(&pdev->dev, desc, regmap); } EXPORT_SYMBOL_GPL(qcom_cc_probe); @@ -333,8 +381,9 @@ int qcom_cc_probe_by_index(struct platform_device *pdev, int index, if (IS_ERR(regmap)) return PTR_ERR(regmap); - return qcom_cc_really_probe(pdev, desc, regmap); + return qcom_cc_really_probe(&pdev->dev, desc, regmap); } EXPORT_SYMBOL_GPL(qcom_cc_probe_by_index); MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("QTI Common Clock module"); |