From 7c7430e205d09aa7fa359213f60cfd633fdb17a3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=99=88=E4=BA=AE?= Date: Sat, 10 May 2014 23:52:12 -0700 Subject: [PATCH] dvfs: add aclk_vio1 dvfs node to keep log volt greater than 1.0V when pd_vio is enable --- arch/arm/boot/dts/rk3288.dtsi | 19 +++--------- arch/arm/mach-rockchip/dvfs.c | 49 +++++++++++++----------------- drivers/cpufreq/rockchip-cpufreq.c | 39 +++++++++++++++++++----- 3 files changed, 58 insertions(+), 49 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index ff5d7e5fd3de..e46522692c0a 100755 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -935,15 +935,14 @@ }; }; - 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"; }; }; }; @@ -959,14 +958,6 @@ 300000 1200000 400000 1200000 >; - //temp-channel=<2>; - temp-limit = < - /*temp freq*/ - 50 600000 - 70 500000 - 80 400000 - 100 300000 - >; status = "okay"; }; }; diff --git a/arch/arm/mach-rockchip/dvfs.c b/arch/arm/mach-rockchip/dvfs.c index c37fbca59a05..aa24b246fa94 100644 --- a/arch/arm/mach-rockchip/dvfs.c +++ b/arch/arm/mach-rockchip/dvfs.c @@ -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; diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index c32af9232171..1f40586c8c63 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -32,6 +32,7 @@ #include #include #include +#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); } -- 2.34.1