msm/drm: gpu: Dynamically locate the clocks from the device tree
authorJordan Crouse <jcrouse@codeaurora.org>
Tue, 7 Mar 2017 17:02:56 +0000 (10:02 -0700)
committerRob Clark <robdclark@gmail.com>
Sat, 8 Apr 2017 10:59:37 +0000 (06:59 -0400)
Instead of using a fixed list of clock names use the clock-names
list in the device tree to discover and get the list of clocks
that we need.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_gpu.h

index f8ee148..97b9c38 100644 (file)
@@ -93,18 +93,18 @@ static int enable_clk(struct msm_gpu *gpu)
 {
        int i;
 
-       if (gpu->grp_clks[0] && gpu->fast_rate)
-               clk_set_rate(gpu->grp_clks[0], gpu->fast_rate);
+       if (gpu->core_clk && gpu->fast_rate)
+               clk_set_rate(gpu->core_clk, gpu->fast_rate);
 
        /* Set the RBBM timer rate to 19.2Mhz */
-       if (gpu->grp_clks[2])
-               clk_set_rate(gpu->grp_clks[2], 19200000);
+       if (gpu->rbbmtimer_clk)
+               clk_set_rate(gpu->rbbmtimer_clk, 19200000);
 
-       for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
+       for (i = gpu->nr_clocks - 1; i >= 0; i--)
                if (gpu->grp_clks[i])
                        clk_prepare(gpu->grp_clks[i]);
 
-       for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
+       for (i = gpu->nr_clocks - 1; i >= 0; i--)
                if (gpu->grp_clks[i])
                        clk_enable(gpu->grp_clks[i]);
 
@@ -115,11 +115,11 @@ static int disable_clk(struct msm_gpu *gpu)
 {
        int i;
 
-       for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
+       for (i = gpu->nr_clocks - 1; i >= 0; i--)
                if (gpu->grp_clks[i])
                        clk_disable(gpu->grp_clks[i]);
 
-       for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
+       for (i = gpu->nr_clocks - 1; i >= 0; i--)
                if (gpu->grp_clks[i])
                        clk_unprepare(gpu->grp_clks[i]);
 
@@ -128,10 +128,11 @@ static int disable_clk(struct msm_gpu *gpu)
         * speed had to be non zero to avoid problems. On newer targets this
         * will be rounded down to zero anyway so it all works out.
         */
-       clk_set_rate(gpu->grp_clks[0], 27000000);
+       if (gpu->core_clk)
+               clk_set_rate(gpu->core_clk, 27000000);
 
-       if (gpu->grp_clks[2])
-               clk_set_rate(gpu->grp_clks[2], 0);
+       if (gpu->rbbmtimer_clk)
+               clk_set_rate(gpu->rbbmtimer_clk, 0);
 
        return 0;
 }
@@ -519,16 +520,52 @@ static irqreturn_t irq_handler(int irq, void *data)
        return gpu->funcs->irq(gpu);
 }
 
-static const char *clk_names[] = {
-       "core", "iface", "rbbmtimer", "mem", "mem_iface", "alt_mem_iface",
-};
+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;
+
+       gpu->nr_clocks = of_property_count_strings(dev->of_node, "clock-names");
+       if (gpu->nr_clocks < 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)
+               return -ENOMEM;
+
+       of_property_for_each_string(dev->of_node, "clock-names", prop, name) {
+               gpu->grp_clks[i] = get_clock(dev, name);
+
+               /* Remember the key clocks that we need to control later */
+               if (!strcmp(name, "core"))
+                       gpu->core_clk = gpu->grp_clks[i];
+               else if (!strcmp(name, "rbbmtimer"))
+                       gpu->rbbmtimer_clk = gpu->grp_clks[i];
+
+               ++i;
+       }
+
+       return 0;
+}
 
 int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,
                const char *name, const char *ioname, const char *irqname, int ringsz)
 {
        struct iommu_domain *iommu;
-       int i, ret;
+       int ret;
 
        if (WARN_ON(gpu->num_perfcntrs > ARRAY_SIZE(gpu->last_cntrs)))
                gpu->num_perfcntrs = ARRAY_SIZE(gpu->last_cntrs);
@@ -554,7 +591,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 
        spin_lock_init(&gpu->perf_lock);
 
-       BUG_ON(ARRAY_SIZE(clk_names) != ARRAY_SIZE(gpu->grp_clks));
 
        /* Map registers: */
        gpu->mmio = msm_ioremap(pdev, ioname, name);
@@ -578,13 +614,9 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                goto fail;
        }
 
-       /* Acquire clocks: */
-       for (i = 0; i < ARRAY_SIZE(clk_names); i++) {
-               gpu->grp_clks[i] = msm_clk_get(pdev, clk_names[i]);
-               DBG("grp_clks[%s]: %p", clk_names[i], gpu->grp_clks[i]);
-               if (IS_ERR(gpu->grp_clks[i]))
-                       gpu->grp_clks[i] = NULL;
-       }
+       ret = get_clocks(pdev, gpu);
+       if (ret)
+               goto fail;
 
        gpu->ebi1_clk = msm_clk_get(pdev, "bus");
        DBG("ebi1_clk: %p", gpu->ebi1_clk);
index 44f0c34..aa32410 100644 (file)
@@ -103,7 +103,9 @@ struct msm_gpu {
 
        /* Power Control: */
        struct regulator *gpu_reg, *gpu_cx;
-       struct clk *ebi1_clk, *grp_clks[6];
+       struct clk **grp_clks;
+       int nr_clocks;
+       struct clk *ebi1_clk, *core_clk, *rbbmtimer_clk;
        uint32_t fast_rate, bus_freq;
 
 #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING