dvfs: add aclk_vio1 dvfs node to keep log volt greater than 1.0V when pd_vio is enable
author陈亮 <cl@rock-chips.com>
Sun, 11 May 2014 06:52:12 +0000 (23:52 -0700)
committer陈亮 <cl@rock-chips.com>
Sun, 11 May 2014 06:52:40 +0000 (23:52 -0700)
arch/arm/boot/dts/rk3288.dtsi
arch/arm/mach-rockchip/dvfs.c
drivers/cpufreq/rockchip-cpufreq.c

index ff5d7e5fd3de60880b961795c8963d9c39a84297..e46522692c0ac0a49ae54f9d53e5fda851dfcd61 100755 (executable)
                                };
                        };
 
-                       pd_vpu {
-                               clk_ddr_vepu_table: clk_vepu {
+                       pd_vio {
+                               aclk_vio1_dvfs_table: aclk_vio1 {
                                        operating-points = <
                                                /* KHz    uV */
-                                               200000 1300000
-                                               300000 1300000
-                                               400000 1300000
+                                               100000 1000000
+                                               500000 1000000
                                                >;
-                                       status = "disabled";
+                                       status = "okay";
                                };
                        };
                };
                                                300000 1200000
                                                400000 1200000
                                                >;
-                                       //temp-channel=<2>;
-                                       temp-limit = <
-                                               /*temp    freq*/
-                                               50      600000
-                                               70      500000
-                                               80      400000
-                                               100     300000
-                                               >;
                                        status = "okay";
                                };
                        };
index c37fbca59a058d894f265707c9748f035ab6d84f..aa24b246fa9482df04baf1d2e8bac468d86f5105 100644 (file)
@@ -312,7 +312,7 @@ static int dvfs_get_rate_range(struct dvfs_node *clk_dvfs_node)
        int i = 0;
 
        if (!clk_dvfs_node)
-               return -1;
+               return -EINVAL;
 
        clk_dvfs_node->min_rate = 0;
        clk_dvfs_node->max_rate = 0;
@@ -385,24 +385,20 @@ static int clk_dvfs_node_get_ref_volt(struct dvfs_node *clk_dvfs_node, int rate_
        clk_fv->frequency = 0;
        clk_fv->index = 0;
        //DVFS_DBG("%s get corresponding voltage error! out of bound\n", clk_dvfs_node->name);
-       return -1;
+       return -EINVAL;
 }
 
 static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct dvfs_node *clk_dvfs_node)
 {
        int volt_max = 0;
 
-       if (!pd || !clk_dvfs_node)
-               return 0;
-
-       if (clk_dvfs_node->set_volt >= pd->cur_volt) {
+       if (clk_dvfs_node->enable_count && (clk_dvfs_node->set_volt >= pd->cur_volt)) {
                return clk_dvfs_node->set_volt;
        }
 
        list_for_each_entry(clk_dvfs_node, &pd->clk_list, node) {
-               // DVFS_DBG("%s ,pd(%s),dvfs(%s),volt(%u)\n",__func__,pd->name,
-               // clk_dvfs_node->name,clk_dvfs_node->set_volt);
-               volt_max = max(volt_max, clk_dvfs_node->set_volt);
+               if (clk_dvfs_node->enable_count)
+                       volt_max = max(volt_max, clk_dvfs_node->set_volt);
        }
        return volt_max;
 }
@@ -416,7 +412,7 @@ static void dvfs_update_clk_pds_volt(struct dvfs_node *clk_dvfs_node)
        
        pd = clk_dvfs_node->pd;
        if (!pd)
-               return ;
+               return;
        
        pd->cur_volt = dvfs_pd_get_newvolt_byclk(pd, clk_dvfs_node);
 }
@@ -425,29 +421,22 @@ static int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)
 {
        int volt_max_vd = 0;
        struct pd_node *pd;
-       //struct depend_list    *depend;
 
        if (!vd)
                return -EINVAL;
        
        list_for_each_entry(pd, &vd->pd_list, node) {
-               // DVFS_DBG("%s pd(%s,%u)\n",__func__,pd->name,pd->cur_volt);
                volt_max_vd = max(volt_max_vd, pd->cur_volt);
        }
 
-       /* some clks depend on this voltage domain */
-/*     if (!list_empty(&vd->req_volt_list)) {
-               list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
-                       volt_max_vd = max(volt_max_vd, depend->req_volt);
-               }
-       }*/
        return volt_max_vd;
 }
 
 static int dvfs_vd_get_newvolt_byclk(struct dvfs_node *clk_dvfs_node)
 {
        if (!clk_dvfs_node)
-               return -1;
+               return -EINVAL;
+
        dvfs_update_clk_pds_volt(clk_dvfs_node);
        return  dvfs_vd_get_newvolt_bypd(clk_dvfs_node->vd);
 }
@@ -692,6 +681,7 @@ EXPORT_SYMBOL(dvfs_set_freq_volt_table);
 int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node)
 {
        struct cpufreq_frequency_table clk_fv;
+       int volt_new;
 
        if (!clk_dvfs_node)
                return -EINVAL;
@@ -753,9 +743,9 @@ int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node)
                                return 0;
                        }
                }
-
+               clk_dvfs_node->enable_count++;
                clk_dvfs_node->set_volt = clk_fv.index;
-               dvfs_vd_get_newvolt_byclk(clk_dvfs_node);
+               volt_new = dvfs_vd_get_newvolt_byclk(clk_dvfs_node);
                DVFS_DBG("%s: %s, freq %u(ref vol %u)\n",
                        __func__, clk_dvfs_node->name, clk_dvfs_node->set_freq, clk_dvfs_node->set_volt);
 #if 0
@@ -764,9 +754,10 @@ int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node)
                        clk_notifier_register(clk, clk_dvfs_node->dvfs_nb);
                }
 #endif
-               if(clk_dvfs_node->vd->cur_volt < clk_dvfs_node->set_volt) {
+               if(clk_dvfs_node->vd->cur_volt != volt_new) {
                        int ret;
-                       ret = dvfs_regulator_set_voltage_readback(clk_dvfs_node->vd->regulator, clk_dvfs_node->set_volt, clk_dvfs_node->set_volt);
+                       ret = dvfs_regulator_set_voltage_readback(clk_dvfs_node->vd->regulator, volt_new, volt_new);
+                       dvfs_volt_up_delay(clk_dvfs_node->vd,volt_new, clk_dvfs_node->vd->cur_volt);
                        if (ret < 0) {
                                clk_dvfs_node->vd->volt_set_flag = DVFS_SET_VOLT_FAILURE;
                                clk_dvfs_node->enable_count = 0;
@@ -774,11 +765,10 @@ int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node)
                                mutex_unlock(&clk_dvfs_node->vd->mutex);
                                return -EAGAIN;
                        }
-                       clk_dvfs_node->vd->cur_volt = clk_dvfs_node->set_volt;
+                       clk_dvfs_node->vd->cur_volt = volt_new;
                        clk_dvfs_node->vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
                }
 
-               clk_dvfs_node->enable_count++;
        } else {
                DVFS_DBG("%s: dvfs already enable clk enable = %d!\n",
                        __func__, clk_dvfs_node->enable_count);
@@ -793,6 +783,8 @@ EXPORT_SYMBOL(clk_enable_dvfs);
 
 int clk_disable_dvfs(struct dvfs_node *clk_dvfs_node)
 {
+       int volt_new;
+
        if (!clk_dvfs_node)
                return -EINVAL;
 
@@ -803,12 +795,16 @@ int clk_disable_dvfs(struct dvfs_node *clk_dvfs_node)
        if (!clk_dvfs_node->enable_count) {
                DVFS_WARNING("%s:clk(%s) is already closed!\n", 
                        __func__, __clk_get_name(clk_dvfs_node->clk));
+               mutex_unlock(&clk_dvfs_node->vd->mutex);
                return 0;
        } else {
                clk_dvfs_node->enable_count--;
                if (0 == clk_dvfs_node->enable_count) {
                        DVFS_DBG("%s:dvfs clk(%s) disable dvfs ok!\n",
                                __func__, __clk_get_name(clk_dvfs_node->clk));
+                       volt_new = dvfs_vd_get_newvolt_byclk(clk_dvfs_node);
+                       dvfs_scale_volt_direct(clk_dvfs_node->vd, volt_new);
+
 #if 0
                        clk_notifier_unregister(clk, clk_dvfs_node->dvfs_nb);
                        DVFS_DBG("clk unregister nb!\n");
@@ -820,9 +816,6 @@ int clk_disable_dvfs(struct dvfs_node *clk_dvfs_node)
 }
 EXPORT_SYMBOL(clk_disable_dvfs);
 
-
-
-
 static unsigned long dvfs_get_limit_rate(struct dvfs_node *clk_dvfs_node, unsigned long rate)
 {
        unsigned long limit_rate;
index c32af92321714fa07de86d4228ffb2c0999e6aea..1f40586c8c6338eecfb6c0e8566cae8570b364bf 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/cpu.h>
 #include <asm/unistd.h>
 #include <asm/uaccess.h>
+#include "../../../drivers/clk/rockchip/clk-pd.h"
 
 extern void dvfs_disable_temp_limit(void);
 
@@ -75,7 +76,7 @@ static DEFINE_MUTEX(cpufreq_mutex);
 static bool gpu_is_mali400;
 struct dvfs_node *clk_cpu_dvfs_node = NULL;
 struct dvfs_node *clk_gpu_dvfs_node = NULL;
-struct dvfs_node *clk_vepu_dvfs_node = NULL;
+struct dvfs_node *aclk_vio1_dvfs_node = NULL;
 struct dvfs_node *clk_ddr_dvfs_node = NULL;
 /*******************************************************/
 static unsigned int cpufreq_get_rate(unsigned int cpu)
@@ -182,11 +183,6 @@ static int cpufreq_init_cpu0(struct cpufreq_policy *policy)
                        dvfs_clk_enable_limit(clk_gpu_dvfs_node, 133000000, 600000000); 
        }
 
-       clk_vepu_dvfs_node = clk_get_dvfs_node("clk_vepu");
-       if (clk_vepu_dvfs_node){
-               clk_enable_dvfs(clk_vepu_dvfs_node);
-       }
-
        clk_ddr_dvfs_node = clk_get_dvfs_node("clk_ddr");
        if (clk_ddr_dvfs_node){
                clk_enable_dvfs(clk_ddr_dvfs_node);
@@ -414,6 +410,26 @@ static struct notifier_block cpufreq_reboot_notifier = {
        .notifier_call = cpufreq_reboot_notifier_event,
 };
 
+static int clk_pd_vio_notifier_call(struct notifier_block *nb, unsigned long event, void *ptr)
+{
+       switch (event) {
+       case RK_CLK_PD_PRE_ENABLE:
+               if (aclk_vio1_dvfs_node)
+                       clk_enable_dvfs(aclk_vio1_dvfs_node);
+               break;
+       case RK_CLK_PD_POST_DISABLE:
+               if (aclk_vio1_dvfs_node)
+                       clk_disable_dvfs(aclk_vio1_dvfs_node);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block clk_pd_vio_notifier = {
+       .notifier_call = clk_pd_vio_notifier_call,
+};
+
+
 static struct cpufreq_driver cpufreq_driver = {
        .flags = CPUFREQ_CONST_LOOPS,
        .verify = cpufreq_verify,
@@ -427,8 +443,17 @@ static struct cpufreq_driver cpufreq_driver = {
 
 static int __init cpufreq_driver_init(void)
 {
+       struct clk *clk;
+
+       clk = clk_get(NULL, "pd_vio");
+       if (clk) {
+               rk_clk_pd_notifier_register(clk, &clk_pd_vio_notifier);
+               aclk_vio1_dvfs_node = clk_get_dvfs_node("aclk_vio1");
+               if (aclk_vio1_dvfs_node && __clk_is_enabled(clk)){
+                       clk_enable_dvfs(aclk_vio1_dvfs_node);
+               }
+       }
        register_pm_notifier(&cpufreq_pm_notifier);
-       //register_reboot_notifier(&cpufreq_reboot_notifier);
        return cpufreq_register_driver(&cpufreq_driver);
 }