summaryrefslogtreecommitdiff
path: root/drivers/clk/qcom/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/qcom/common.c')
-rw-r--r--drivers/clk/qcom/common.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index 75f09e6e057e..9e3380fd7181 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>
@@ -21,6 +22,7 @@ struct qcom_cc {
struct qcom_reset_controller reset;
struct clk_regmap **rclks;
size_t num_rclks;
+ struct dev_pm_domain_list *pd_list;
};
const
@@ -41,6 +43,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 +228,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 +252,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;
@@ -251,6 +300,10 @@ int qcom_cc_really_probe(struct platform_device *pdev,
if (!cc)
return -ENOMEM;
+ ret = devm_pm_domain_attach_list(dev, NULL, &cc->pd_list);
+ if (ret < 0 && ret != -EEXIST)
+ return ret;
+
reset = &cc->reset;
reset->rcdev.of_node = dev->of_node;
reset->rcdev.ops = &qcom_reset_ops;
@@ -270,6 +323,7 @@ int qcom_cc_really_probe(struct platform_device *pdev,
scd->dev = dev;
scd->scs = desc->gdscs;
scd->num = desc->num_gdscs;
+ scd->pd_list = cc->pd_list;
ret = gdsc_register(scd, &reset->rcdev, regmap);
if (ret)
return ret;
@@ -303,7 +357,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 +369,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 +387,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");