ddrfreq: separate ddr from clk frame to fix dead lock and advance performance
author陈亮 <cl@rock-chips.com>
Wed, 21 May 2014 09:11:06 +0000 (02:11 -0700)
committer陈亮 <cl@rock-chips.com>
Wed, 21 May 2014 09:11:06 +0000 (02:11 -0700)
arch/arm/mach-rockchip/ddr_freq.c
arch/arm/mach-rockchip/dvfs.c

index 9daf0b5833efd4db4b5903569b5861e6ac3c5013..6284eac31677a0fbe0b86161dd4727c9063c2fb8 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/io.h>
 #include <linux/rockchip/grf.h>
 #include <linux/rockchip/iomap.h>
+#include <linux/clk-private.h>
 #include "../../../drivers/clk/rockchip/clk-pd.h"
 
 extern int rockchip_cpufreq_reboot_limit_freq(void);
@@ -734,6 +735,20 @@ int of_init_ddr_freq_table(void)
        return 0;
 }
 
+static int ddrfreq_scale_rate_for_dvfs(struct clk *clk, unsigned long rate)
+{
+       unsigned long real_rate;
+
+       real_rate = ddr_change_freq(rate/MHZ);
+       real_rate *= MHZ;
+       if (!real_rate)
+               return -EAGAIN;
+
+       clk->parent->rate = clk->rate = real_rate;
+
+       return 0;
+}
+
 #if defined(CONFIG_RK_PM_TESTS)
 static void ddrfreq_tst_init(void);
 #endif
@@ -758,6 +773,8 @@ static int ddrfreq_init(void)
                return -EINVAL;
        }
        clk_enable_dvfs(ddr.clk_dvfs_node);
+
+       dvfs_clk_register_set_rate_callback(ddr.clk_dvfs_node, ddrfreq_scale_rate_for_dvfs);
        
        init_waitqueue_head(&ddr.wait);
        INIT_LIST_HEAD(&ddr.video_info_list);
index aa24b246fa9482df04baf1d2e8bac468d86f5105..e2922a141d2143f9560a296905265a3866124b1b 100644 (file)
@@ -341,7 +341,7 @@ static void dvfs_table_round_clk_rate(struct dvfs_node  *clk_dvfs_node)
                //ddr rate = real rate+flags
                flags = clk_dvfs_node->dvfs_table[i].frequency%1000;
                rate = (clk_dvfs_node->dvfs_table[i].frequency/1000)*1000;
-               temp_rate = clk_round_rate(clk_dvfs_node->clk, rate*1000);
+               temp_rate = __clk_round_rate(clk_dvfs_node->clk, rate*1000);
                if(temp_rate <= 0){     
                        DVFS_WARNING("%s: clk(%s) rate %d round return %d\n",
                                __func__, clk_dvfs_node->name, clk_dvfs_node->dvfs_table[i].frequency, temp_rate);
@@ -564,7 +564,7 @@ int dvfs_clk_enable_limit(struct dvfs_node *clk_dvfs_node, unsigned int min_rate
                }
 
                if (clk_dvfs_node->last_set_rate == 0)
-                       rate = clk_get_rate(clk_dvfs_node->clk);
+                       rate = __clk_get_rate(clk_dvfs_node->clk);
                else
                        rate = clk_dvfs_node->last_set_rate;
                ret = clk_dvfs_node->vd->vd_dvfs_target(clk_dvfs_node, rate);
@@ -865,8 +865,8 @@ static int dvfs_target(struct dvfs_node *clk_dvfs_node, unsigned long rate)
        }
 
        rate = dvfs_get_limit_rate(clk_dvfs_node, rate);
-       new_rate = clk_round_rate(clk, rate);
-       old_rate = clk_get_rate(clk);
+       new_rate = __clk_round_rate(clk, rate);
+       old_rate = __clk_get_rate(clk);
        if (new_rate == old_rate)
                return 0;
 
@@ -908,7 +908,7 @@ static int dvfs_target(struct dvfs_node *clk_dvfs_node, unsigned long rate)
        clk_dvfs_node->set_freq = new_rate / 1000;
 
        DVFS_DBG("%s:dvfs clk(%s) set rate %lu ok\n", 
-               __func__, clk_dvfs_node->name, clk_get_rate(clk));
+               __func__, clk_dvfs_node->name, __clk_get_rate(clk));
 
        /* if down the rate */
        if (new_rate < old_rate) {
@@ -926,7 +926,7 @@ out:
 
 unsigned long dvfs_clk_get_rate(struct dvfs_node *clk_dvfs_node)
 {
-       return clk_get_rate(clk_dvfs_node->clk);
+       return __clk_get_rate(clk_dvfs_node->clk);
 }
 EXPORT_SYMBOL_GPL(dvfs_clk_get_rate);