int i = 0;
if (!clk_dvfs_node)
- return -1;
+ return -EINVAL;
clk_dvfs_node->min_rate = 0;
clk_dvfs_node->max_rate = 0;
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;
}
pd = clk_dvfs_node->pd;
if (!pd)
- return ;
+ return;
pd->cur_volt = dvfs_pd_get_newvolt_byclk(pd, clk_dvfs_node);
}
{
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);
}
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;
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
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;
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);
int clk_disable_dvfs(struct dvfs_node *clk_dvfs_node)
{
+ int volt_new;
+
if (!clk_dvfs_node)
return -EINVAL;
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");
}
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;
#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);
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)
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);
.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,
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);
}