dvfs: add aclk_vio1 dvfs node to keep log volt greater than 1.0V when pd_vio is enable

This commit is contained in:
陈亮
2014-05-10 23:52:12 -07:00
parent 83f21e6978
commit 7c7430e205
3 changed files with 58 additions and 49 deletions

View File

@@ -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";
};
};

View 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;

View 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);
}