* Util/helpers:
*/
+int msm_clk_bulk_get(struct device *dev, struct clk_bulk_data **bulk)
+{
+ struct property *prop;
+ const char *name;
+ struct clk_bulk_data *local;
+ int i = 0, ret, count;
+
+ count = of_property_count_strings(dev->of_node, "clock-names");
+ if (count < 1)
+ return 0;
+
+ local = devm_kcalloc(dev, sizeof(struct clk_bulk_data *),
+ count, GFP_KERNEL);
+ if (!local)
+ return -ENOMEM;
+
+ of_property_for_each_string(dev->of_node, "clock-names", prop, name) {
+ local[i].id = devm_kstrdup(dev, name, GFP_KERNEL);
+ if (!local[i].id) {
+ devm_kfree(dev, local);
+ return -ENOMEM;
+ }
+
+ i++;
+ }
+
+ ret = devm_clk_bulk_get(dev, count, local);
+
+ if (ret) {
+ for (i = 0; i < count; i++)
+ devm_kfree(dev, (void *) local[i].id);
+ devm_kfree(dev, local);
+
+ return ret;
+ }
+
+ *bulk = local;
+ return count;
+}
+
+struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
+ const char *name)
+{
+ int i;
+ char n[32];
+
+ snprintf(n, sizeof(n), "%s_clk", name);
+
+ for (i = 0; bulk && i < count; i++) {
+ if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n))
+ return bulk[i].clk;
+ }
+
+
+ return NULL;
+}
+
struct clk *msm_clk_get(struct platform_device *pdev, const char *name)
{
struct clk *clk;
static int enable_clk(struct msm_gpu *gpu)
{
- int i;
-
if (gpu->core_clk && gpu->fast_rate)
clk_set_rate(gpu->core_clk, gpu->fast_rate);
if (gpu->rbbmtimer_clk)
clk_set_rate(gpu->rbbmtimer_clk, 19200000);
- for (i = gpu->nr_clocks - 1; i >= 0; i--)
- if (gpu->grp_clks[i])
- clk_prepare(gpu->grp_clks[i]);
-
- for (i = gpu->nr_clocks - 1; i >= 0; i--)
- if (gpu->grp_clks[i])
- clk_enable(gpu->grp_clks[i]);
-
- return 0;
+ return clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks);
}
static int disable_clk(struct msm_gpu *gpu)
{
- int i;
-
- for (i = gpu->nr_clocks - 1; i >= 0; i--)
- if (gpu->grp_clks[i])
- clk_disable(gpu->grp_clks[i]);
-
- for (i = gpu->nr_clocks - 1; i >= 0; i--)
- if (gpu->grp_clks[i])
- clk_unprepare(gpu->grp_clks[i]);
+ clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks);
/*
* Set the clock to a deliberately low rate. On older targets the clock
return gpu->funcs->irq(gpu);
}
-static struct clk *get_clock(struct device *dev, const char *name)
-{
- struct clk *clk = devm_clk_get(dev, name);
-
- return IS_ERR(clk) ? NULL : clk;
-}
-
static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu)
{
- struct device *dev = &pdev->dev;
- struct property *prop;
- const char *name;
- int i = 0;
+ int ret = msm_clk_bulk_get(&pdev->dev, &gpu->grp_clks);
- gpu->nr_clocks = of_property_count_strings(dev->of_node, "clock-names");
- if (gpu->nr_clocks < 1) {
+ if (ret < 1) {
gpu->nr_clocks = 0;
- return 0;
- }
-
- gpu->grp_clks = devm_kcalloc(dev, sizeof(struct clk *), gpu->nr_clocks,
- GFP_KERNEL);
- if (!gpu->grp_clks) {
- gpu->nr_clocks = 0;
- return -ENOMEM;
+ return ret;
}
- of_property_for_each_string(dev->of_node, "clock-names", prop, name) {
- gpu->grp_clks[i] = get_clock(dev, name);
+ gpu->nr_clocks = ret;
- /* Remember the key clocks that we need to control later */
- if (!strcmp(name, "core") || !strcmp(name, "core_clk"))
- gpu->core_clk = gpu->grp_clks[i];
- else if (!strcmp(name, "rbbmtimer") || !strcmp(name, "rbbmtimer_clk"))
- gpu->rbbmtimer_clk = gpu->grp_clks[i];
+ gpu->core_clk = msm_clk_bulk_get_clock(gpu->grp_clks,
+ gpu->nr_clocks, "core");
- ++i;
- }
+ gpu->rbbmtimer_clk = msm_clk_bulk_get_clock(gpu->grp_clks,
+ gpu->nr_clocks, "rbbmtimer");
return 0;
}