return a5xx_gpu->cur_ring;
 }
 
-static int a5xx_gpu_busy(struct msm_gpu *gpu, uint64_t *value)
+static unsigned long a5xx_gpu_busy(struct msm_gpu *gpu)
 {
-       *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO,
-               REG_A5XX_RBBM_PERFCTR_RBBM_0_HI);
+       u64 busy_cycles;
+       unsigned long busy_time;
 
-       return 0;
+       busy_cycles = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO,
+                       REG_A5XX_RBBM_PERFCTR_RBBM_0_HI);
+
+       busy_time = (busy_cycles - gpu->devfreq.busy_cycles) /
+               (clk_get_rate(gpu->core_clk) / 1000000);
+
+       gpu->devfreq.busy_cycles = busy_cycles;
+
+       return busy_time;
 }
 
 static const struct adreno_gpu_funcs funcs = {
 
        if (IS_ERR(opp))
                return PTR_ERR(opp);
 
-       clk_set_rate(gpu->core_clk, *freq);
+       if (gpu->funcs->gpu_set_freq)
+               gpu->funcs->gpu_set_freq(gpu, (u64)*freq);
+       else
+               clk_set_rate(gpu->core_clk, *freq);
+
        dev_pm_opp_put(opp);
 
        return 0;
                struct devfreq_dev_status *status)
 {
        struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev));
-       u64 cycles;
-       u32 freq = ((u32) status->current_frequency) / 1000000;
        ktime_t time;
 
-       status->current_frequency = (unsigned long) clk_get_rate(gpu->core_clk);
-       gpu->funcs->gpu_busy(gpu, &cycles);
-
-       status->busy_time = ((u32) (cycles - gpu->devfreq.busy_cycles)) / freq;
+       if (gpu->funcs->gpu_get_freq)
+               status->current_frequency = gpu->funcs->gpu_get_freq(gpu);
+       else
+               status->current_frequency = clk_get_rate(gpu->core_clk);
 
-       gpu->devfreq.busy_cycles = cycles;
+       status->busy_time = gpu->funcs->gpu_busy(gpu);
 
        time = ktime_get();
        status->total_time = ktime_us_delta(time, gpu->devfreq.time);
 {
        struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev));
 
-       *freq = (unsigned long) clk_get_rate(gpu->core_clk);
+       if (gpu->funcs->gpu_get_freq)
+               *freq = gpu->funcs->gpu_get_freq(gpu);
+       else
+               *freq = clk_get_rate(gpu->core_clk);
 
        return 0;
 }
 static void msm_devfreq_init(struct msm_gpu *gpu)
 {
        /* We need target support to do devfreq */
-       if (!gpu->funcs->gpu_busy || !gpu->core_clk)
+       if (!gpu->funcs->gpu_busy)
                return;
 
        msm_devfreq_profile.initial_freq = gpu->fast_rate;
        return 0;
 }
 
+void msm_gpu_resume_devfreq(struct msm_gpu *gpu)
+{
+       gpu->devfreq.busy_cycles = 0;
+       gpu->devfreq.time = ktime_get();
+
+       devfreq_resume_device(gpu->devfreq.devfreq);
+}
+
 int msm_gpu_pm_resume(struct msm_gpu *gpu)
 {
        int ret;
        if (ret)
                return ret;
 
-       if (gpu->devfreq.devfreq) {
-               gpu->devfreq.busy_cycles = 0;
-               gpu->devfreq.time = ktime_get();
-
-               devfreq_resume_device(gpu->devfreq.devfreq);
-       }
+       msm_gpu_resume_devfreq(gpu);
 
        gpu->needs_hw_init = true;
 
 
        DBG("%s", gpu->name);
 
-       if (gpu->devfreq.devfreq)
-               devfreq_suspend_device(gpu->devfreq.devfreq);
+       devfreq_suspend_device(gpu->devfreq.devfreq);
 
        ret = disable_axi(gpu);
        if (ret)
 
        /* for generation specific debugfs: */
        int (*debugfs_init)(struct msm_gpu *gpu, struct drm_minor *minor);
 #endif
-       int (*gpu_busy)(struct msm_gpu *gpu, uint64_t *value);
+       unsigned long (*gpu_busy)(struct msm_gpu *gpu);
        struct msm_gpu_state *(*gpu_state_get)(struct msm_gpu *gpu);
        int (*gpu_state_put)(struct msm_gpu_state *state);
+       unsigned long (*gpu_get_freq)(struct msm_gpu *gpu);
+       void (*gpu_set_freq)(struct msm_gpu *gpu, unsigned long freq);
 };
 
 struct msm_gpu {
 
 int msm_gpu_pm_suspend(struct msm_gpu *gpu);
 int msm_gpu_pm_resume(struct msm_gpu *gpu);
+void msm_gpu_resume_devfreq(struct msm_gpu *gpu);
 
 int msm_gpu_hw_init(struct msm_gpu *gpu);