rk3188:linux3.10: add dvfs support
author陈亮 <cl@rock-chips.com>
Fri, 28 Feb 2014 08:33:02 +0000 (00:33 -0800)
committer陈亮 <cl@rock-chips.com>
Fri, 28 Feb 2014 08:33:02 +0000 (00:33 -0800)
arch/arm/mach-rockchip/dvfs.c
arch/arm/mach-rockchip/dvfs.h

index 83b959e13f70bb8a4a00225456d0749dbf3f5c3c..9701ecc78b548376222f9c434687031aa2ad6955 100644 (file)
  * GNU General Public License for more details.
  *
  */
-#include <linux/clk-provider.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
-#include <linux/cpufreq.h>
 #include <linux/regulator/consumer.h>
 #include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/hrtimer.h>
 #include <linux/stat.h>
 #include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/clk-private.h>
 #include <linux/opp.h>
-
 #include "dvfs.h"
 
 #define MHz    (1000 * 1000)
 static LIST_HEAD(rk_dvfs_tree);
-static DEFINE_MUTEX(mutex);
 static DEFINE_MUTEX(rk_dvfs_mutex);
 
-int dump_dbg_map(char *buf);
-
-#define PD_ON  1
-#define PD_OFF 0
-#define DVFS_STR_DISABLE(on) ((on)?"enable":"disable")
-
-#define get_volt_up_delay(new_volt, old_volt)  \
-       ((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 9) : 0)
-/**************************************vd regulator functions***************************************/
-static void dvfs_volt_up_delay(struct vd_node *vd,int new_volt, int old_volt)
+static void dvfs_volt_up_delay(struct vd_node *vd, int new_volt, int old_volt)
 {
        int u_time;
-       if(new_volt<=old_volt)
+       
+       if(new_volt <= old_volt)
                return;
-       if(vd->volt_time_flag>0)        
-               u_time=regulator_set_voltage_time(vd->regulator,old_volt,new_volt);
+       if(vd->volt_time_flag > 0)      
+               u_time = regulator_set_voltage_time(vd->regulator, old_volt, new_volt);
        else
-               u_time=-1;              
-       if(u_time<0)// regulator is not suported time,useing default time
-       {
+               u_time = -1;            
+       if(u_time < 0) {// regulator is not suported time,useing default time
                DVFS_DBG("%s:vd %s is not suported getting delay time,so we use default\n",
-                               __FUNCTION__,vd->name);
-               u_time=((new_volt) - (old_volt)) >> 9;
+                               __func__, vd->name);
+               u_time = ((new_volt) - (old_volt)) >> 9;
        }
-       DVFS_DBG("%s:vd %s volt %d to %d delay %d us\n",__FUNCTION__,vd->name,
-               old_volt,new_volt,u_time);
+       
+       DVFS_DBG("%s: vd %s volt %d to %d delay %d us\n", 
+               __func__, vd->name, old_volt, new_volt, u_time);
+       
        if (u_time >= 1000) {
                mdelay(u_time / 1000);
                udelay(u_time % 1000);
-               DVFS_ERR("regulator set vol delay is larger 1ms,old is %d,new is %d\n",old_volt,new_volt);
+               DVFS_WARNING("%s: regulator set vol delay is larger 1ms,old is %d,new is %d\n",
+                       __func__, old_volt, new_volt);
        } else if (u_time) {
                udelay(u_time);
        }                       
 }
 
-int dvfs_regulator_set_voltage_readback(struct regulator *regulator, int min_uV, int max_uV)
+static int dvfs_regulator_set_voltage_readback(struct regulator *regulator, int min_uV, int max_uV)
 {
        int ret = 0, read_back = 0;
+       
        ret = dvfs_regulator_set_voltage(regulator, max_uV, max_uV);
        if (ret < 0) {
-               DVFS_ERR("%s now read back to check voltage\n", __func__);
+               DVFS_ERR("%s: now read back to check voltage\n", __func__);
 
                /* read back to judge if it is already effect */
                mdelay(2);
                read_back = dvfs_regulator_get_voltage(regulator);
                if (read_back == max_uV) {
-                       DVFS_ERR("%s set ERROR but already effected, volt=%d\n", __func__, read_back);
+                       DVFS_ERR("%s: set ERROR but already effected, volt=%d\n", __func__, read_back);
                        ret = 0;
                } else {
-                       DVFS_ERR("%s set ERROR AND NOT effected, volt=%d\n", __func__, read_back);
+                       DVFS_ERR("%s: set ERROR AND NOT effected, volt=%d\n", __func__, read_back);
                }
        }
+       
        return ret;
 }
+
+static int dvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new)
+{
+       int ret = 0;
+       
+       DVFS_DBG("%s: volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);
+       
+       if (IS_ERR_OR_NULL(vd_clk)) {
+               DVFS_ERR("%s: vd_node error\n", __func__);
+               return -EINVAL;
+       }
+
+       if (!IS_ERR_OR_NULL(vd_clk->regulator)) {
+               ret = dvfs_regulator_set_voltage_readback(vd_clk->regulator, volt_new, volt_new);
+               dvfs_volt_up_delay(vd_clk,volt_new, vd_clk->cur_volt);
+               if (ret < 0) {
+                       vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
+                       DVFS_ERR("%s: %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
+                                       __func__, vd_clk->name, ret, volt_new, vd_clk->cur_volt);
+                       return -EAGAIN;
+               }
+
+       } else {
+               DVFS_ERR("%s: invalid regulator\n", __func__);
+               return -EINVAL;
+       }
+
+       vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
+       vd_clk->cur_volt = volt_new;
+
+       return 0;
+
+}
+
+static int dvfs_reset_volt(struct vd_node *dvfs_vd)
+{
+       int flag_set_volt_correct = 0;
+       if (!IS_ERR_OR_NULL(dvfs_vd->regulator))
+               flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_vd->regulator);
+       else {
+               DVFS_ERR("%s: invalid regulator\n", __func__);
+               return -EINVAL;
+       }
+       if (flag_set_volt_correct <= 0) {
+               DVFS_ERR("%s (vd:%s), try to reload volt ,by it is error again(%d)!!! stop scaling\n",
+                               __func__, dvfs_vd->name, flag_set_volt_correct);
+               return -EAGAIN;
+       }
+       dvfs_vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
+       DVFS_WARNING("%s:vd(%s) try to reload volt = %d\n",
+                       __func__, dvfs_vd->name, flag_set_volt_correct);
+
+       /* Reset vd's voltage */
+       dvfs_vd->cur_volt = flag_set_volt_correct;
+
+       return dvfs_vd->cur_volt;
+}
+
+
 // for clk enable case to get vd regulator info
-void clk_enable_dvfs_regulator_check(struct vd_node *vd)
+static void clk_enable_dvfs_regulator_check(struct vd_node *vd)
 {
        vd->cur_volt = dvfs_regulator_get_voltage(vd->regulator);
-       if(vd->cur_volt<=0)
-       {
+       if(vd->cur_volt <= 0){
                vd->volt_set_flag = DVFS_SET_VOLT_FAILURE;
        }
        vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
@@ -104,146 +146,143 @@ void clk_enable_dvfs_regulator_check(struct vd_node *vd)
 
 static void dvfs_get_vd_regulator_volt_list(struct vd_node *vd)
 {
-       unsigned i,selector=dvfs_regulator_count_voltages(vd->regulator);
-       int sel_volt=0;
-       
-       if(selector>VD_VOL_LIST_CNT)
-               selector=VD_VOL_LIST_CNT;
+       unsigned int i, selector = dvfs_regulator_count_voltages(vd->regulator);
+       int n = 0, sel_volt = 0;
        
-       mutex_lock(&mutex);
-       for (i = 0; i<selector; i++) {
-               sel_volt=dvfs_regulator_list_voltage(vd->regulator,i);
-               if(sel_volt<=0)
-               {       
-                       DVFS_WARNING("%s : selector=%u,but volt <=0\n",vd->name,i);
-                       break;
+       if(selector > VD_VOL_LIST_CNT)
+               selector = VD_VOL_LIST_CNT;
+
+       for (i = 0; i < selector; i++) {
+               sel_volt = dvfs_regulator_list_voltage(vd->regulator, i);
+               if(sel_volt <= 0){      
+                       //DVFS_WARNING("%s: vd(%s) list volt selector=%u, but volt(%d) <=0\n",
+                       //      __func__, vd->name, i, sel_volt);
+                       continue;
                }
-               vd->volt_list[i]=sel_volt;      
-               DVFS_DBG("%s:selector=%u,volt %d\n",vd->name,i,sel_volt);
+               vd->volt_list[n++] = sel_volt;  
+               DVFS_DBG("%s: vd(%s) list volt selector=%u, n=%d, volt=%d\n", 
+                       __func__, vd->name, i, n, sel_volt);
        }
-       vd->n_voltages=selector;
-       mutex_unlock(&mutex);
+       
+       vd->n_voltages = n;
 }
 
 // >= volt
 static int vd_regulator_round_volt_max(struct vd_node *vd, int volt)
 {
        int sel_volt;
-       unsigned i;
+       int i;
        
-       for (i = 0; i<vd->n_voltages; i++) {
-               sel_volt=vd->volt_list[i];
-               if(sel_volt<=0)
-               {       
-                       DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n",__FUNCTION__,i);
-                       return -1;
+       for (i = 0; i < vd->n_voltages; i++) {
+               sel_volt = vd->volt_list[i];
+               if(sel_volt <= 0){      
+                       DVFS_WARNING("%s: selector=%u, but volt <=0\n", 
+                               __func__, i);
+                       continue;
                }
-               if(sel_volt>=volt)
-                return sel_volt;       
+               if(sel_volt >= volt)
+                       return sel_volt;        
        }
-       return -1;
+       return -EINVAL;
 }
+
 // >=volt
 static int vd_regulator_round_volt_min(struct vd_node *vd, int volt)
 {
        int sel_volt;
-       unsigned i;
+       int i;
        
-       for (i = 0; i<vd->n_voltages; i++) {
-               sel_volt=vd->volt_list[i];
-               if(sel_volt<=0)
-               {       
-                       DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n",__FUNCTION__,i);
-                       return -1;
+       for (i = 0; i < vd->n_voltages; i++) {
+               sel_volt = vd->volt_list[i];
+               if(sel_volt <= 0){      
+                       DVFS_WARNING("%s: selector=%u, but volt <=0\n", 
+                               __func__, i);
+                       continue;
                }
-               if(sel_volt>volt)
-               {
-                       if(i>0)
+               if(sel_volt > volt){
+                       if(i > 0)
                                return vd->volt_list[i-1];
                        else
-                               return -1;
+                               return -EINVAL;
                }       
        }
-       return -1;
+       
+       return -EINVAL;
 }
 
 // >=volt
-int vd_regulator_round_volt(struct vd_node *vd, int volt,int flags)
+static int vd_regulator_round_volt(struct vd_node *vd, int volt, int flags)
 {
        if(!vd->n_voltages)
-               return -1;
-       if(flags==VD_LIST_RELATION_L)
-               return vd_regulator_round_volt_min(vd,volt);
+               return -EINVAL;
+       if(flags == VD_LIST_RELATION_L)
+               return vd_regulator_round_volt_min(vd, volt);
        else
-               return vd_regulator_round_volt_max(vd,volt);    
+               return vd_regulator_round_volt_max(vd, volt);   
 }
-EXPORT_SYMBOL(vd_regulator_round_volt);
-
 
-static void dvfs_table_round_volt(struct dvfs_node  *clk_dvfs_node)
+static void dvfs_table_round_volt(struct dvfs_node *clk_dvfs_node)
 {
-       int i,test_volt;
+       int i, test_volt;
 
-       if(!clk_dvfs_node->dvfs_table||!clk_dvfs_node->vd||IS_ERR_OR_NULL(clk_dvfs_node->vd->regulator))
+       if(!clk_dvfs_node->dvfs_table || !clk_dvfs_node->vd || 
+               IS_ERR_OR_NULL(clk_dvfs_node->vd->regulator))
                return;
-       mutex_lock(&mutex);
+
        for (i = 0; (clk_dvfs_node->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
 
-               test_volt=vd_regulator_round_volt(clk_dvfs_node->vd,clk_dvfs_node->dvfs_table[i].index,VD_LIST_RELATION_H);
-               if(test_volt<=0)
+               test_volt = vd_regulator_round_volt(clk_dvfs_node->vd, clk_dvfs_node->dvfs_table[i].index, VD_LIST_RELATION_H);
+               if(test_volt <= 0)
                {       
-                       DVFS_WARNING("clk %s:round_volt : is %d,but list <=0\n",clk_dvfs_node->name,clk_dvfs_node->dvfs_table[i].index);
+                       DVFS_WARNING("%s: clk(%s) round volt(%d) but list <=0\n",
+                               __func__, clk_dvfs_node->name, clk_dvfs_node->dvfs_table[i].index);
                        break;
                }
-               DVFS_DBG("clk %s:round_volt %d to %d\n",clk_dvfs_node->name,clk_dvfs_node->dvfs_table[i].index,test_volt);
+               DVFS_DBG("clk %s:round_volt %d to %d\n",
+                       clk_dvfs_node->name, clk_dvfs_node->dvfs_table[i].index, test_volt);
+               
                clk_dvfs_node->dvfs_table[i].index=test_volt;           
        }
-       mutex_unlock(&mutex);
 }
-void dvfs_vd_get_regulator_volt_time_info(struct vd_node *vd)
+
+static void dvfs_vd_get_regulator_volt_time_info(struct vd_node *vd)
 {
-       if(vd->volt_time_flag<=0)// check regulator support get uping vol timer
-       {
-               vd->volt_time_flag=dvfs_regulator_set_voltage_time(vd->regulator,vd->cur_volt,vd->cur_volt+200*1000);
-               if(vd->volt_time_flag<0)
-               {
-                       DVFS_DBG("%s,vd %s volt_time is no support\n",__FUNCTION__,vd->name);
+       if(vd->volt_time_flag <= 0){// check regulator support get uping vol timer
+               vd->volt_time_flag = dvfs_regulator_set_voltage_time(vd->regulator, vd->cur_volt, vd->cur_volt+200*1000);
+               if(vd->volt_time_flag < 0){
+                       DVFS_DBG("%s,vd %s volt_time is no support\n",
+                               __func__, vd->name);
                }
-               else
-               {
-                       DVFS_DBG("%s,vd %s volt_time is support,up 200mv need delay %d us\n",__FUNCTION__,vd->name,vd->volt_time_flag);
-
+               else{
+                       DVFS_DBG("%s,vd %s volt_time is support,up 200mv need delay %d us\n",
+                               __func__, vd->name, vd->volt_time_flag);
                }       
        }
 }
-
-void dvfs_vd_get_regulator_mode_info(struct vd_node *vd)
+#if 0
+static void dvfs_vd_get_regulator_mode_info(struct vd_node *vd)
 {
        //REGULATOR_MODE_FAST
-       if(vd->mode_flag<=0)// check regulator support get uping vol timer
-       {
-               vd->mode_flag=dvfs_regulator_get_mode(vd->regulator);
-               if(vd->mode_flag==REGULATOR_MODE_FAST||vd->mode_flag==REGULATOR_MODE_NORMAL
-                       ||vd->mode_flag==REGULATOR_MODE_IDLE||vd->mode_flag==REGULATOR_MODE_STANDBY)
-               {
-                       if(dvfs_regulator_set_mode(vd->regulator,vd->mode_flag)<0)
-                       {
-                               vd->mode_flag=0;// check again
-                       }
+       if(vd->mode_flag <= 0){// check regulator support get uping vol timer{
+               vd->mode_flag = dvfs_regulator_get_mode(vd->regulator);
+               if(vd->mode_flag==REGULATOR_MODE_FAST || vd->mode_flag==REGULATOR_MODE_NORMAL
+                       || vd->mode_flag == REGULATOR_MODE_IDLE || vd->mode_flag==REGULATOR_MODE_STANDBY){
                        
+                       if(dvfs_regulator_set_mode(vd->regulator, vd->mode_flag) < 0){
+                               vd->mode_flag = 0;// check again
+                       }
                }
-               if(vd->mode_flag>0)
-               {
-                       DVFS_DBG("%s,vd %s mode(now is %d) support\n",__FUNCTION__,vd->name,vd->mode_flag);
+               if(vd->mode_flag > 0){
+                       DVFS_DBG("%s,vd %s mode(now is %d) support\n",
+                               __func__, vd->name, vd->mode_flag);
                }
-               else
-               {
-                       DVFS_DBG("%s,vd %s mode is not support now check\n",__FUNCTION__,vd->name);
-
+               else{
+                       DVFS_DBG("%s,vd %s mode is not support now check\n",
+                               __func__, vd->name);
                }
-               
        }
 }
+
 struct regulator *dvfs_get_regulator1(char *regulator_name) 
 {
        struct vd_node *vd;
@@ -254,10 +293,10 @@ struct regulator *dvfs_get_regulator1(char *regulator_name)
        }
        return NULL;
 }
+#endif
 
-int dvfs_get_rate_range(struct clk *clk)
+static int dvfs_get_rate_range(struct dvfs_node *clk_dvfs_node)
 {
-       struct dvfs_node *clk_dvfs_node = clk_get_dvfs_info(clk);
        struct cpufreq_frequency_table *table;
        int i = 0;
 
@@ -280,122 +319,22 @@ int dvfs_get_rate_range(struct clk *clk)
        return 0;
 }
 
-/**************************************dvfs clocks functions***************************************/
-int clk_dvfs_enable_limit(struct clk *clk, unsigned int min_rate, unsigned max_rate)
-{
-       struct dvfs_node *clk_dvfs_node;
-       u32 rate = 0, ret = 0;
-       clk_dvfs_node = clk_get_dvfs_info(clk);
-       
-       if (IS_ERR_OR_NULL(clk_dvfs_node)) {
-               DVFS_ERR("%s: can not get dvfs clk(%s)\n", __func__, __clk_get_name(clk));
-               return -1;
-
-       }
-
-       if (clk_dvfs_node->vd && clk_dvfs_node->vd->vd_dvfs_target){
-               mutex_lock(&rk_dvfs_mutex);
-               
-               dvfs_get_rate_range(clk);
-               clk_dvfs_node->freq_limit_en = 1;
-               clk_dvfs_node->min_rate = min_rate > clk_dvfs_node->min_rate ? min_rate : clk_dvfs_node->min_rate;
-               clk_dvfs_node->max_rate = max_rate < clk_dvfs_node->max_rate ? max_rate : clk_dvfs_node->max_rate;
-               if (clk_dvfs_node->last_set_rate == 0)
-                       rate = clk_get_rate(clk);
-               else
-                       rate = clk_dvfs_node->last_set_rate;
-               ret = clk_dvfs_node->vd->vd_dvfs_target(clk->hw, rate, rate);
-               clk_dvfs_node->last_set_rate = rate;
-
-               mutex_unlock(&rk_dvfs_mutex);
-
-       }
-
-       DVFS_DBG("%s: clk(%s) last_set_rate=%u; [min_rate, max_rate]=[%u, %u]\n",
-                       __func__, __clk_get_name(clk), clk_dvfs_node->last_set_rate, clk_dvfs_node->min_rate, clk_dvfs_node->max_rate);
-
-       return 0;
-}
-
-int clk_dvfs_disable_limit(struct clk *clk)
-{
-       struct dvfs_node *clk_dvfs_node;
-       u32 ret = 0;
-       clk_dvfs_node = clk_get_dvfs_info(clk);
-       if (IS_ERR_OR_NULL(clk_dvfs_node)) {
-               DVFS_ERR("%s: can not get dvfs clk(%s)\n", __func__, __clk_get_name(clk));
-               return -1;
-
-       }
-
-       if (clk_dvfs_node->vd && clk_dvfs_node->vd->vd_dvfs_target){
-               mutex_lock(&rk_dvfs_mutex);
-               /* To reset clk_dvfs_node->min_rate/max_rate */
-               dvfs_get_rate_range(clk);
-
-               clk_dvfs_node->freq_limit_en = 0;
-               ret = clk_dvfs_node->vd->vd_dvfs_target(clk->hw, clk_dvfs_node->last_set_rate, clk_dvfs_node->last_set_rate);
-
-               mutex_unlock(&rk_dvfs_mutex);
-       }
-
-       DVFS_DBG("%s: clk(%s) last_set_rate=%u; [min_rate, max_rate]=[%u, %u]\n",
-                       __func__, __clk_get_name(clk), clk_dvfs_node->last_set_rate, clk_dvfs_node->min_rate, clk_dvfs_node->max_rate);
-       return 0;
-}
-
-int dvfs_vd_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-                           unsigned long parent_rate)
-{
-       int ret = -1;
-       struct dvfs_node *dvfs_info = clk_get_dvfs_info(hw->clk);
-       
-       DVFS_DBG("%s(%s(%lu))\n", __func__, dvfs_info->name, rate);
-       
-       #if 0 // judge by reference func in rk
-       if (dvfs_support_clk_set_rate(dvfs_info)==false) {
-               DVFS_ERR("dvfs func:%s is not support!\n", __func__);
-               return ret;
-       }
-       #endif
-       
-       if (dvfs_info->vd && dvfs_info->vd->vd_dvfs_target) {
-               // mutex_lock(&vd->dvfs_mutex);
-               mutex_lock(&rk_dvfs_mutex);
-               ret = dvfs_info->vd->vd_dvfs_target(hw, rate, rate);
-               dvfs_info->last_set_rate = rate;
-               mutex_unlock(&rk_dvfs_mutex);
-               // mutex_unlock(&vd->dvfs_mutex);
-       } else {
-               //DVFS_WARNING("%s(%s),vd is no target callback\n", __func__, __clk_get_name(clk));     
-               return -1;
-       }
-               
-       //DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);
-       return ret;
-}
-EXPORT_SYMBOL(dvfs_vd_clk_set_rate);
-
 static void dvfs_table_round_clk_rate(struct dvfs_node  *clk_dvfs_node)
 {
-       int i;
-       unsigned long temp_rate;
-       int rate;
-       int flags;
+       int i, rate, temp_rate, flags;
        
-       if(!clk_dvfs_node->dvfs_table||clk_dvfs_node->clk==NULL)//||is_suport_round_rate(clk_dvfs_node->clk)<0)
+       if(!clk_dvfs_node || !clk_dvfs_node->dvfs_table || !clk_dvfs_node->clk)
                return;
-       
-       mutex_lock(&mutex);
+
        for (i = 0; (clk_dvfs_node->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
                //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);
-               if(temp_rate<=0)
-               {       
-                       DVFS_WARNING("clk %s:round_clk_rate : is %d,but round <=0",clk_dvfs_node->name,clk_dvfs_node->dvfs_table[i].frequency);
-                       break;
+               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);
+               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);
+                       continue;
                }
                
                /* Set rate unit as MHZ */
@@ -405,14 +344,13 @@ static void dvfs_table_round_clk_rate(struct dvfs_node  *clk_dvfs_node)
                temp_rate = (temp_rate / 1000) + flags;
                
                DVFS_DBG("clk %s round_clk_rate %d to %d\n",
-                       clk_dvfs_node->name,clk_dvfs_node->dvfs_table[i].frequency,(int)(temp_rate));
+                       clk_dvfs_node->name,clk_dvfs_node->dvfs_table[i].frequency, temp_rate);
                
-               clk_dvfs_node->dvfs_table[i].frequency=temp_rate;               
+               clk_dvfs_node->dvfs_table[i].frequency = temp_rate;             
        }
-       mutex_unlock(&mutex);
 }
 
-int clk_dvfs_node_get_ref_volt(struct dvfs_node *clk_dvfs_node, int rate_khz,
+static int clk_dvfs_node_get_ref_volt(struct dvfs_node *clk_dvfs_node, int rate_khz,
                struct cpufreq_frequency_table *clk_fv)
 {
        int i = 0;
@@ -441,7 +379,6 @@ int clk_dvfs_node_get_ref_volt(struct dvfs_node *clk_dvfs_node, int rate_khz,
 
 static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct dvfs_node *clk_dvfs_node)
 {
-       struct clk_list *child;
        int volt_max = 0;
 
        if (!pd || !clk_dvfs_node)
@@ -451,15 +388,15 @@ static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct dvfs_node *clk_d
                return clk_dvfs_node->set_volt;
        }
 
-       list_for_each_entry(child, &pd->clk_list, node) {
+       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, child->clk_dvfs_node->set_volt);
+               volt_max = max(volt_max, clk_dvfs_node->set_volt);
        }
        return volt_max;
 }
 
-void dvfs_update_clk_pds_volt(struct dvfs_node *clk_dvfs_node)
+static void dvfs_update_clk_pds_volt(struct dvfs_node *clk_dvfs_node)
 {
        struct pd_node *pd;
        
@@ -478,7 +415,7 @@ void dvfs_update_clk_pds_volt(struct dvfs_node *clk_dvfs_node)
        }*/
 }
 
-int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)
+static int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)
 {
        int volt_max_vd = 0;
        struct pd_node *pd;
@@ -501,7 +438,7 @@ int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)
        return volt_max_vd;
 }
 
-int dvfs_vd_get_newvolt_byclk(struct dvfs_node *clk_dvfs_node)
+static int dvfs_vd_get_newvolt_byclk(struct dvfs_node *clk_dvfs_node)
 {
        if (!clk_dvfs_node)
                return -1;
@@ -509,118 +446,181 @@ int dvfs_vd_get_newvolt_byclk(struct dvfs_node *clk_dvfs_node)
        return  dvfs_vd_get_newvolt_bypd(clk_dvfs_node->vd);
 }
 
-void clk_dvfs_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target)
+int dvfs_clk_enable_limit(struct dvfs_node *clk_dvfs_node, unsigned int min_rate, unsigned max_rate)
 {
-       struct dvfs_node *clk_dvfs_node = clk_get_dvfs_info(clk);
-       if (IS_ERR_OR_NULL(clk_dvfs_node)) {
-               DVFS_ERR("%s %s get clk_dvfs_node err\n", __func__, clk->name);
-               return ;
+       u32 rate = 0, ret = 0;
+
+       if (!clk_dvfs_node)
+               return -EINVAL;
+       
+       if (clk_dvfs_node->vd && clk_dvfs_node->vd->vd_dvfs_target){
+               mutex_lock(&clk_dvfs_node->vd->mutex);
+               
+               /* To reset clk_dvfs_node->min_rate/max_rate */
+               dvfs_get_rate_range(clk_dvfs_node);
+               clk_dvfs_node->freq_limit_en = 1;
+               clk_dvfs_node->min_rate = min_rate > clk_dvfs_node->min_rate ? min_rate : clk_dvfs_node->min_rate;
+               clk_dvfs_node->max_rate = max_rate < clk_dvfs_node->max_rate ? max_rate : clk_dvfs_node->max_rate;
+               if (clk_dvfs_node->last_set_rate == 0)
+                       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);
+
+               mutex_unlock(&clk_dvfs_node->vd->mutex);
+
+       }
+
+       DVFS_DBG("%s:clk(%s) last_set_rate=%u; [min_rate, max_rate]=[%u, %u]\n",
+                       __func__, __clk_get_name(clk_dvfs_node->clk), clk_dvfs_node->last_set_rate, 
+                       clk_dvfs_node->min_rate, clk_dvfs_node->max_rate);
+
+       return 0;
+}
+EXPORT_SYMBOL(dvfs_clk_enable_limit);
+
+int dvfs_clk_disable_limit(struct dvfs_node *clk_dvfs_node)
+{
+       u32 ret = 0;
+
+       if (!clk_dvfs_node)
+               return -EINVAL;
+       
+       if (clk_dvfs_node->vd && clk_dvfs_node->vd->vd_dvfs_target){
+               mutex_lock(&clk_dvfs_node->vd->mutex);
+               
+               /* To reset clk_dvfs_node->min_rate/max_rate */
+               dvfs_get_rate_range(clk_dvfs_node);
+               clk_dvfs_node->freq_limit_en = 0;
+               ret = clk_dvfs_node->vd->vd_dvfs_target(clk_dvfs_node, clk_dvfs_node->last_set_rate);
+
+               mutex_unlock(&clk_dvfs_node->vd->mutex);
        }
+
+       DVFS_DBG("%s: clk(%s) last_set_rate=%u; [min_rate, max_rate]=[%u, %u]\n",
+                       __func__, __clk_get_name(clk_dvfs_node->clk), clk_dvfs_node->last_set_rate, clk_dvfs_node->min_rate, clk_dvfs_node->max_rate);
+       return 0;
+}
+EXPORT_SYMBOL(dvfs_clk_disable_limit);
+
+
+int dvfs_clk_register_set_rate_callback(struct dvfs_node *clk_dvfs_node, clk_set_rate_callback clk_dvfs_target)
+{
+       if (!clk_dvfs_node)
+               return -EINVAL;
+                       
+       mutex_lock(&clk_dvfs_node->vd->mutex);
        clk_dvfs_node->clk_dvfs_target = clk_dvfs_target;
+       mutex_unlock(&clk_dvfs_node->vd->mutex);
+
+       return 0;
 }
+EXPORT_SYMBOL(dvfs_clk_register_set_rate_callback);
 
-/************************************************ freq volt table************************************/
-struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk) 
+struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct dvfs_node *clk_dvfs_node) 
 {
-       struct dvfs_node *info = clk_get_dvfs_info(clk);
        struct cpufreq_frequency_table *table;
-       if (!info || !info->dvfs_table) {
+
+       if (!clk_dvfs_node)
                return NULL;
-       }
-       mutex_lock(&mutex);
-       table = info->dvfs_table;
-       mutex_unlock(&mutex);
+
+       mutex_lock(&clk_dvfs_node->vd->mutex);
+       table = clk_dvfs_node->dvfs_table;
+       mutex_unlock(&clk_dvfs_node->vd->mutex);
+       
        return table;
 }
 EXPORT_SYMBOL(dvfs_get_freq_volt_table);
 
-int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table)
+int dvfs_set_freq_volt_table(struct dvfs_node *clk_dvfs_node, struct cpufreq_frequency_table *table)
 {
-       struct dvfs_node *info = clk_get_dvfs_info(clk);
-
-       if (!info)
-               return -1;      
-       if (!table)
-       {               
-               info->min_rate=0;       
-               info->max_rate=0;       
-               return -1;
-       }
+       if (!clk_dvfs_node)
+               return -EINVAL;
 
-       mutex_lock(&mutex);
-       info->dvfs_table = table;
-       dvfs_get_rate_range(clk);
-       mutex_unlock(&mutex);
+       if (IS_ERR_OR_NULL(table)){
+               DVFS_ERR("%s:invalid table!\n", __func__);
+               return -EINVAL;
+       }
+       
+       mutex_lock(&clk_dvfs_node->vd->mutex);
+       clk_dvfs_node->dvfs_table = table;
+       dvfs_get_rate_range(clk_dvfs_node);
+       dvfs_table_round_clk_rate(clk_dvfs_node);
+       dvfs_table_round_volt(clk_dvfs_node);
+       mutex_unlock(&clk_dvfs_node->vd->mutex);
 
-       dvfs_table_round_clk_rate(info);
-       dvfs_table_round_volt(info);
        return 0;
 }
 EXPORT_SYMBOL(dvfs_set_freq_volt_table);
 
-int clk_enable_dvfs(struct clk *clk)
+int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node)
 {
-       struct dvfs_node *clk_dvfs_node;
        struct cpufreq_frequency_table clk_fv;
-       
-       if (!clk) {
-               DVFS_ERR("clk enable dvfs error\n");
+
+       if (!clk_dvfs_node)
                return -EINVAL;
-       }
        
-       clk_dvfs_node = clk_get_dvfs_info(clk);
-       if (!clk_dvfs_node || !clk_dvfs_node->vd) {
-               DVFS_ERR("%s clk(%s) not support dvfs!\n", __func__, __clk_get_name(clk));
+       DVFS_DBG("%s: dvfs clk(%s) enable dvfs!\n", 
+               __func__, __clk_get_name(clk_dvfs_node->clk));
+
+       if (!clk_dvfs_node->vd) {
+               DVFS_ERR("%s: dvfs node(%s) has no vd node!\n", 
+                       __func__, clk_dvfs_node->name);
                return -EINVAL;
        }
-       if (clk_dvfs_node->enable_dvfs == 0) {
+       mutex_lock(&clk_dvfs_node->vd->mutex);
+       if (clk_dvfs_node->enable_count == 0) {
                if (IS_ERR_OR_NULL(clk_dvfs_node->vd->regulator)) {
-                       //regulator = NULL;
                        if (clk_dvfs_node->vd->regulator_name)
                                clk_dvfs_node->vd->regulator = dvfs_regulator_get(NULL, clk_dvfs_node->vd->regulator_name);
                        if (!IS_ERR_OR_NULL(clk_dvfs_node->vd->regulator)) {
-                               // DVFS_DBG("dvfs_regulator_get(%s)\n",clk_dvfs_node->vd->regulator_name);
+                               DVFS_DBG("%s: vd(%s) get regulator(%s) ok\n",
+                                       __func__, clk_dvfs_node->vd->name, clk_dvfs_node->vd->regulator_name);
                                clk_enable_dvfs_regulator_check(clk_dvfs_node->vd);
                                dvfs_get_vd_regulator_volt_list(clk_dvfs_node->vd);
                                dvfs_vd_get_regulator_volt_time_info(clk_dvfs_node->vd);
-                               //dvfs_vd_get_regulator_mode_info(clk_dvfs_node->vd);
                        } else {
-                               //clk_dvfs_node->vd->regulator = NULL;
-                               clk_dvfs_node->enable_dvfs = 0;
-                               DVFS_ERR("%s can't get regulator in %s\n", clk_dvfs_node->name, __func__);
+                               clk_dvfs_node->enable_count = 0;
+                               DVFS_ERR("%s: vd(%s) can't get regulator(%s)!\n", 
+                                       __func__, clk_dvfs_node->vd->name, clk_dvfs_node->vd->regulator_name);
+                               mutex_unlock(&clk_dvfs_node->vd->mutex);
                                return -ENXIO;
                        }
                } else {
-                            clk_enable_dvfs_regulator_check(clk_dvfs_node->vd);
-                       // DVFS_DBG("%s(%s) vd volt=%u\n",__func__,clk_dvfs_node->name,clk_dvfs_node->vd->cur_volt);
+                       clk_enable_dvfs_regulator_check(clk_dvfs_node->vd);
                }
+               
+               DVFS_DBG("%s: vd(%s) cur volt=%d\n",
+                       __func__, clk_dvfs_node->name, clk_dvfs_node->vd->cur_volt);
 
                dvfs_table_round_clk_rate(clk_dvfs_node);
-
-               mutex_lock(&mutex);
-               dvfs_get_rate_range(clk);
-               mutex_unlock(&mutex);
-               
+               dvfs_get_rate_range(clk_dvfs_node);
+               clk_dvfs_node->freq_limit_en = 1;
                dvfs_table_round_volt(clk_dvfs_node);
-               clk_dvfs_node->set_freq = clk_dvfs_node_get_rate_kz(clk);
-               DVFS_DBG("%s ,%s get freq %u!\n", __func__, clk_dvfs_node->name, clk_dvfs_node->set_freq);
+               clk_dvfs_node->set_freq = clk_dvfs_node_get_rate_kz(clk_dvfs_node->clk);
+               
+               DVFS_DBG("%s: %s get freq %u!\n", 
+                       __func__, clk_dvfs_node->name, clk_dvfs_node->set_freq);
 
                if (clk_dvfs_node_get_ref_volt(clk_dvfs_node, clk_dvfs_node->set_freq, &clk_fv)) {
                        if (clk_dvfs_node->dvfs_table[0].frequency == CPUFREQ_TABLE_END) {
-                               DVFS_ERR("%s table empty\n", __func__);
-                               clk_dvfs_node->enable_dvfs = 0;
-                               return -1;
+                               DVFS_ERR("%s: table empty\n", __func__);
+                               clk_dvfs_node->enable_count = 0;
+                               mutex_unlock(&clk_dvfs_node->vd->mutex);
+                               return -EINVAL;
                        } else {
-                               DVFS_WARNING("%s table all value are smaller than default, use default, just enable dvfs\n", __func__);
-                               clk_dvfs_node->enable_dvfs++;
+                               DVFS_WARNING("%s: clk(%s) freq table all value are smaller than default(%d), use default, just enable dvfs\n", 
+                                       __func__, clk_dvfs_node->name, clk_dvfs_node->set_freq);
+                               clk_dvfs_node->enable_count++;
+                               mutex_unlock(&clk_dvfs_node->vd->mutex);
                                return 0;
                        }
                }
 
                clk_dvfs_node->set_volt = clk_fv.index;
                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);
+               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
                if (clk_dvfs_node->dvfs_nb) {
                        // must unregister when clk disable
@@ -644,420 +644,104 @@ int clk_enable_dvfs(struct clk *clk)
                        mutex_unlock(&rk_dvfs_mutex);
                }
 #endif
-               clk_dvfs_node->enable_dvfs++;
+               clk_dvfs_node->enable_count++;
        } else {
-               DVFS_ERR("dvfs already enable clk enable = %d!\n", clk_dvfs_node->enable_dvfs);
-               clk_dvfs_node->enable_dvfs++;
+               DVFS_DBG("%s: dvfs already enable clk enable = %d!\n",
+                       __func__, clk_dvfs_node->enable_count);
+               clk_dvfs_node->enable_count++;
        }
+
+       mutex_unlock(&clk_dvfs_node->vd->mutex);
+       
        return 0;
 }
+EXPORT_SYMBOL(clk_enable_dvfs);
 
-int clk_disable_dvfs(struct clk *clk)
+int clk_disable_dvfs(struct dvfs_node *clk_dvfs_node)
 {
-       struct dvfs_node *clk_dvfs_node;
-       clk_dvfs_node = clk_get_dvfs_info(clk);
-       if (!clk_dvfs_node->enable_dvfs) {
-               DVFS_DBG("clk is already closed!\n");
-               return -1;
+       if (!clk_dvfs_node)
+               return -EINVAL;
+
+       DVFS_DBG("%s:dvfs clk(%s) disable dvfs!\n", 
+               __func__, __clk_get_name(clk_dvfs_node->clk));
+
+       mutex_lock(&clk_dvfs_node->vd->mutex);
+       if (!clk_dvfs_node->enable_count) {
+               DVFS_WARNING("%s:clk(%s) is already closed!\n", 
+                       __func__, __clk_get_name(clk_dvfs_node->clk));
+               return 0;
        } else {
-               clk_dvfs_node->enable_dvfs--;
-               if (0 == clk_dvfs_node->enable_dvfs) {
-                       DVFS_ERR("clk closed!\n");
+               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));
 #if 0
                        clk_notifier_unregister(clk, clk_dvfs_node->dvfs_nb);
                        DVFS_DBG("clk unregister nb!\n");
 #endif
                }
        }
+       mutex_unlock(&clk_dvfs_node->vd->mutex);
        return 0;
 }
-struct dvfs_node *dvfs_get_clk_dvfs_node_byname(char *name) 
+EXPORT_SYMBOL(clk_disable_dvfs);
+
+static int dvfs_target(struct dvfs_node *clk_dvfs_node, unsigned long rate)
 {
-       struct vd_node *vd;
-       struct pd_node *pd;
-       struct clk_list *child;
-       list_for_each_entry(vd, &rk_dvfs_tree, node) {
-               list_for_each_entry(pd, &vd->pd_list, node) {
-                       list_for_each_entry(child, &pd->clk_list, node) {
-                               if (0 == strcmp(child->clk_dvfs_node->name, name)) {
-                                       return child->clk_dvfs_node;
-                               }
-                       }
-               }
+       struct cpufreq_frequency_table clk_fv;
+       unsigned long old_rate = 0, new_rate = 0, volt_new = 0, clk_volt_store = 0;
+       struct clk *clk = clk_dvfs_node->clk;
+       int ret;
+
+       if (!clk)
+               return -EINVAL;
+
+       if (!clk_dvfs_node->enable_count){
+               DVFS_WARNING("%s:dvfs(%s) is disable\n", 
+                       __func__, clk_dvfs_node->name);
+               return 0;
        }
-       return NULL;
-}
-int rk_regist_vd(struct vd_node *vd)
-{
-       if (!vd)
-               return -EINVAL;
-       mutex_lock(&mutex);
-       //mutex_init(&vd->dvfs_mutex);
-       list_add(&vd->node, &rk_dvfs_tree);
-       INIT_LIST_HEAD(&vd->pd_list);
-       INIT_LIST_HEAD(&vd->req_volt_list);
-       vd->mode_flag=0;
-       vd->volt_time_flag=0;
-       vd->n_voltages=0;
-       mutex_unlock(&mutex);
-       return 0;
-}
-
-int rk_regist_pd(struct pd_node *pd)
-{
-       struct vd_node  *vd;
-
-       vd = pd->vd;
-       if (!vd)
-               return -EINVAL;
-       
-       mutex_lock(&mutex);
-       
-       list_add(&pd->node, &vd->pd_list);
-       INIT_LIST_HEAD(&pd->clk_list);  
-
-       mutex_unlock(&mutex);
-
-       return 0;
-}
-
-int rk_regist_clk(struct dvfs_node *clk_dvfs_node)
-{
-       struct pd_node  *pd;
-       struct clk_list *child;
-
-       pd = clk_dvfs_node->pd;
-       if (!pd)
-               return -EINVAL;
-       
-       mutex_lock(&mutex);
-
-       child = &clk_dvfs_node->clk_list;
-       child->clk_dvfs_node = clk_dvfs_node;
-       list_add(&child->node, &pd->clk_list);
-       
-       mutex_unlock(&mutex);
-       
-       return 0;
-}
-
-int correct_volt(int *volt_clk, int *volt_dep, int clk_biger_than_dep, int dep_biger_than_clk)
-{
-       int up_boundary = 0, low_boundary = 0;
-
-       up_boundary = *volt_clk + dep_biger_than_clk;
-       low_boundary = *volt_clk - clk_biger_than_dep;
-
-       if (*volt_dep < low_boundary || *volt_dep > up_boundary) {
-
-               if (*volt_dep < low_boundary) {
-                       *volt_dep = low_boundary;
-
-               } else if (*volt_dep > up_boundary) {
-                       *volt_clk = *volt_dep - dep_biger_than_clk;
-               }
-       }
-
-       return 0;
-}
-
-int dvfs_scale_volt(struct vd_node *vd_clk, struct vd_node *vd_dep,
-               int volt_old, int volt_new, int volt_dep_old, int volt_dep_new, int clk_biger_than_dep, int dep_biger_than_clk)
-{
-       struct regulator *regulator, *regulator_dep;
-       int volt = 0, volt_dep = 0, step = 0, step_dep = 0;
-       int volt_tmp = 0, volt_dep_tmp = 0;
-       int volt_pre = 0, volt_dep_pre = 0;
-       int ret = 0;
-
-       DVFS_DBG("ENTER %s, volt=%d(old=%d), volt_dep=%d(dep_old=%d)\n", __func__, volt_new, volt_old, volt_dep_new, volt_dep_old);
-       regulator = vd_clk->regulator;
-       regulator_dep = vd_dep->regulator;
-
-       if (IS_ERR_OR_NULL(regulator) || IS_ERR(regulator_dep)) {
-               DVFS_ERR("%s clk_dvfs_node->vd->regulator or depend->dep_vd->regulator == NULL\n", __func__);
-               return -1;
-       }
-
-       volt = volt_old;
-       volt_dep = volt_dep_old;
-
-       step = volt_new - volt_old > 0 ? 1 : (-1);
-       step_dep = volt_dep_new - volt_dep_old > 0 ? 1 : (-1);
-
-       DVFS_DBG("step=%d step_dep=%d %d\n", step, step_dep, step * step_dep);
-
-       DVFS_DBG("Volt_new=%d(old=%d), volt_dep_new=%d(dep_old=%d)\n",
-                       volt_new, volt_old, volt_dep_new, volt_dep_old);
-       do {
-               volt_pre = volt;
-               volt_dep_pre = volt_dep;
-               if (step * step_dep < 0) {
-                       // target is between volt_old and volt_dep_old, just
-                       // need one step
-                       DVFS_DBG("step * step_dep < 0\n");
-                       volt = volt_new;
-                       volt_dep = volt_dep_new;
-
-               } else if (step > 0) {
-                       // up voltage
-                       DVFS_DBG("step > 0\n");
-                       volt_tmp = volt_dep + clk_biger_than_dep;
-                       volt_dep_tmp = volt + dep_biger_than_clk;
-
-                       volt = volt_tmp > volt_new ? volt_new : volt_tmp;
-                       volt_dep = volt_dep_tmp > volt_dep_new ? volt_dep_new : volt_dep_tmp;
-
-               } else if (step < 0) {
-                       // down voltage
-                       DVFS_DBG("step < 0\n");
-
-                       volt_tmp = volt_dep - dep_biger_than_clk;
-                       volt_dep_tmp = volt - clk_biger_than_dep;
-
-                       volt = volt_tmp < volt_new ? volt_new : volt_tmp;
-                       volt_dep = volt_dep_tmp < volt_dep_new ? volt_dep_new : volt_dep_tmp;
-
-               } else {
-                       DVFS_ERR("Oops, some bugs here:Volt_new=%d(old=%d), volt_dep_new=%d(dep_old=%d)\n",
-                                       volt_new, volt_old, volt_dep_new, volt_dep_old);
-                       goto fail;
-               }
-
-               if (vd_clk->cur_volt != volt) {
-                       DVFS_DBG("\t\t%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt);
-                       ret = dvfs_regulator_set_voltage_readback(regulator, volt, volt);
-                       //udelay(get_volt_up_delay(volt, volt_pre));
-                       dvfs_volt_up_delay(vd_clk,volt, volt_pre);
-                       if (ret < 0) {
-                               DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
-                                               __func__, vd_clk->name, ret, volt_new, volt_old);
-                               goto fail;
-                       }
-                       vd_clk->cur_volt = volt;
-               }
-               if (vd_dep->cur_volt != volt_dep) {
-                       DVFS_DBG("\t\t%s:%d->%d\n", vd_dep->name, vd_dep->cur_volt, volt_dep);
-                       ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep, volt_dep);
-                       //udelay(get_volt_up_delay(volt_dep, volt_dep_pre));
-                       dvfs_volt_up_delay(vd_dep,volt_dep, volt_dep_pre);
-                       if (ret < 0) {
-                               DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
-                                               __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);
-                               goto fail;
-                       }
-                       vd_dep->cur_volt = volt_dep;
-               }
-
-               DVFS_DBG("\t\tNOW:Volt=%d, volt_dep=%d\n", volt, volt_dep);
-
-       } while (volt != volt_new || volt_dep != volt_dep_new);
-
-       vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
-       vd_clk->cur_volt = volt_new;
-
-       return 0;
-fail:
-       DVFS_ERR("+++++++++++++++++FAIL AREA\n");
-       vd_clk->cur_volt = volt_old;
-       vd_dep->cur_volt = volt_dep_old;
-       vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
-       ret = dvfs_regulator_set_voltage_readback(regulator, volt_old, volt_old);
-       if (ret < 0) {
-               vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
-               DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",
-                               __func__, vd_clk->name, ret, volt_new, volt_old);
-       }
-
-       ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_old, volt_dep_old);
-       if (ret < 0) {
-               vd_dep->volt_set_flag = DVFS_SET_VOLT_FAILURE;
-               DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",
-                               __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);
-       }
-
-       return -1;
-}
-
-int dvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new)
-{
-       int ret = 0;
        
-       DVFS_DBG("ENTER %s, volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);
-       
-       if (IS_ERR_OR_NULL(vd_clk)) {
-               DVFS_ERR("%s vd_node error\n", __func__);
-               return -EINVAL;
-       }
-
-       if (!IS_ERR_OR_NULL(vd_clk->regulator)) {
-               ret = dvfs_regulator_set_voltage_readback(vd_clk->regulator, volt_new, volt_new);
-               //udelay(get_volt_up_delay(volt_new, vd_clk->cur_volt));
-               dvfs_volt_up_delay(vd_clk,volt_new, vd_clk->cur_volt);
+       if (clk_dvfs_node->vd->volt_set_flag == DVFS_SET_VOLT_FAILURE) {
+               /* It means the last time set voltage error */
+               ret = dvfs_reset_volt(clk_dvfs_node->vd);
                if (ret < 0) {
-                       vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
-                       DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
-                                       __func__, vd_clk->name, ret, volt_new, vd_clk->cur_volt);
-                       return -1;
+                       return -EAGAIN;
                }
-
-       } else {
-               DVFS_ERR("%s up volt clk_dvfs_node->vd->regulator == NULL\n", __func__);
-               return -1;
        }
 
-       vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
-       vd_clk->cur_volt = volt_new;
-
-       return 0;
-
-}
-
-int dvfs_scale_volt_bystep(struct vd_node *vd_clk, struct vd_node *vd_dep, int volt_new, int volt_dep_new,
-               int cur_clk_biger_than_dep, int cur_dep_biger_than_clk, int new_clk_biger_than_dep, int new_dep_biger_than_clk)
-{
-
-       struct regulator *regulator, *regulator_dep;
-       int volt_new_corrected = 0, volt_dep_new_corrected = 0;
-       int volt_old = 0, volt_dep_old = 0;
-       int ret = 0;
-
-       volt_old = vd_clk->cur_volt;
-       volt_dep_old = vd_dep->cur_volt;
-
-       DVFS_DBG("ENTER %s, volt=%d(old=%d) vd_dep=%d(dep_old=%d)\n", __func__,
-                       volt_new, volt_old, volt_dep_new, volt_dep_old);
-       DVFS_DBG("ENTER %s, VOLT_DIFF: clk_cur=%d(clk_new=%d) dep_cur=%d(dep_new=%d)\n", __func__,
-                       cur_clk_biger_than_dep, new_clk_biger_than_dep, 
-                       cur_dep_biger_than_clk, new_dep_biger_than_clk);
-
-       volt_new_corrected = volt_new;
-       volt_dep_new_corrected = volt_dep_new;
-       correct_volt(&volt_new_corrected, &volt_dep_new_corrected, cur_clk_biger_than_dep, cur_dep_biger_than_clk);
-       ret = dvfs_scale_volt(vd_clk, vd_dep, volt_old, volt_new_corrected, volt_dep_old, volt_dep_new_corrected,
-                       cur_clk_biger_than_dep, cur_dep_biger_than_clk);
-       if (ret < 0) {
-               vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
-               DVFS_ERR("set volt error\n");
-               return -1;
-       }
-
-       if (cur_clk_biger_than_dep != new_clk_biger_than_dep || cur_dep_biger_than_clk != new_dep_biger_than_clk) {
-               regulator = vd_clk->regulator;
-               regulator_dep = vd_dep->regulator;
-
-               volt_new_corrected = volt_new;
-               volt_dep_new_corrected = volt_dep_new;
-               correct_volt(&volt_new_corrected, &volt_dep_new_corrected, new_clk_biger_than_dep, new_dep_biger_than_clk);
-
-               if (vd_clk->cur_volt != volt_new_corrected) {
-                       DVFS_DBG("%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt_new_corrected);
-                       ret = dvfs_regulator_set_voltage_readback(regulator, volt_new_corrected, volt_new_corrected);
-                       //udelay(get_volt_up_delay(volt_new_corrected, vd_clk->cur_volt));
-                       dvfs_volt_up_delay(vd_clk,volt_new_corrected, vd_clk->cur_volt);
-                       if (ret < 0) {
-                               DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
-                                               __func__, vd_clk->name, ret, volt_new_corrected, vd_clk->cur_volt);
-                               return -1;
-                       }
-                       vd_clk->cur_volt = volt_new_corrected;
-               }
-               if (vd_dep->cur_volt != volt_dep_new_corrected) {
-                       DVFS_DBG("%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt_dep_new_corrected);
-                       ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_new_corrected, volt_dep_new_corrected);
-                       //udelay(get_volt_up_delay(volt_dep_new_corrected, vd_dep->cur_volt));
-                       dvfs_volt_up_delay(vd_dep,volt_dep_new_corrected, vd_dep->cur_volt);
-                       if (ret < 0) {
-                               DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
-                                               __func__, vd_dep->name, ret, volt_dep_new_corrected, vd_dep->cur_volt);
-                               return -1;
-                       }
-                       vd_dep->cur_volt = volt_dep_new_corrected;
+       /* Check limit rate */
+       //if (clk_dvfs_node->freq_limit_en) {
+               if (rate < clk_dvfs_node->min_rate) {
+                       rate = clk_dvfs_node->min_rate;
+               } else if (rate > clk_dvfs_node->max_rate) {
+                       rate = clk_dvfs_node->max_rate;
                }
-       }
-
-       return 0;
-}
-
-int dvfs_reset_volt(struct vd_node *dvfs_vd)
-{
-       int flag_set_volt_correct = 0;
-       if (!IS_ERR_OR_NULL(dvfs_vd->regulator))
-               flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_vd->regulator);
-       else {
-               DVFS_ERR("dvfs regulator is ERROR\n");
-               return -1;
-       }
-       if (flag_set_volt_correct <= 0) {
-               DVFS_ERR("%s (vd:%s), try to reload volt ,by it is error again(%d)!!! stop scaling\n",
-                               __func__, dvfs_vd->name, flag_set_volt_correct);
-               return -1;
-       }
-       dvfs_vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
-       DVFS_WARNING("%s (vd:%s), try to reload volt = %d\n",
-                       __func__, dvfs_vd->name, flag_set_volt_correct);
-
-       /* Reset vd's voltage */
-       dvfs_vd->cur_volt = flag_set_volt_correct;
-
-       return dvfs_vd->cur_volt;
-}
-
-
-/*********************************************************************************/
-int dvfs_target(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate)
-{
-       struct cpufreq_frequency_table clk_fv;
-       const struct clk_ops *origin_clk_ops;
-       struct clk *clk = hw->clk;
-       struct dvfs_node *clk_dvfs_node;
-       unsigned long old_rate = 0, volt_new = 0, clk_volt_store = 0;
-       int ret = 0;
-
-       if (!clk) {
-               DVFS_ERR("%s is not a clk\n", __func__);
-               return -EINVAL;
-       }
+       //}
 
+       new_rate = clk_round_rate(clk, rate);
        old_rate = clk_get_rate(clk);
-       if (rate == old_rate)
+       if (new_rate == old_rate)
                return 0;
-       
-       clk_dvfs_node = clk_get_dvfs_info(clk);
-       if (IS_ERR_OR_NULL(clk_dvfs_node))
-               return PTR_ERR(clk_dvfs_node);
-       
-       DVFS_DBG("enter %s: clk(%s) new_rate = %lu Hz, old_rate =  %lu Hz\n", 
-               __func__, clk_dvfs_node->name, rate, old_rate);
-
-       if (!clk_dvfs_node->enable_dvfs){
-               DVFS_WARNING("dvfs(%s) is disable\n", clk_dvfs_node->name);
-               return 0;
-       }
 
-       origin_clk_ops = clk_dvfs_node->origin_clk_ops;
-       
-       if (clk_dvfs_node->vd->volt_set_flag == DVFS_SET_VOLT_FAILURE) {
-               /* It means the last time set voltage error */
-               ret = dvfs_reset_volt(clk_dvfs_node->vd);
-               if (ret < 0) {
-                       return -EAGAIN;
-               }
-       }
+       DVFS_DBG("enter %s: clk(%s) new_rate = %lu Hz, old_rate =  %lu Hz\n", 
+               __func__, clk_dvfs_node->name, rate, old_rate); 
 
        /* find the clk corresponding voltage */
-       ret = clk_dvfs_node_get_ref_volt(clk_dvfs_node, rate / 1000, &clk_fv);
-       if (ret) 
+       ret = clk_dvfs_node_get_ref_volt(clk_dvfs_node, new_rate / 1000, &clk_fv);
+       if (ret) {
+               DVFS_ERR("%s:dvfs clk(%s) rate %luhz is larger,not support\n",
+                       __func__, clk_dvfs_node->name, new_rate);
                return ret;
+       }
        clk_volt_store = clk_dvfs_node->set_volt;
        clk_dvfs_node->set_volt = clk_fv.index;
        volt_new = dvfs_vd_get_newvolt_byclk(clk_dvfs_node);
-       DVFS_DBG("%s %s new rate=%lu(was=%lu),new volt=%lu,(was=%d)\n",
-               __func__, clk_dvfs_node->name, rate, old_rate, volt_new,clk_dvfs_node->vd->cur_volt);
+       DVFS_DBG("%s:%s new rate=%lu(was=%lu),new volt=%lu,(was=%d)\n",
+               __func__, clk_dvfs_node->name, new_rate, old_rate, volt_new,clk_dvfs_node->vd->cur_volt);
 
        /* if up the rate */
-       if (rate > old_rate) {
+       if (new_rate > old_rate) {
                ret = dvfs_scale_volt_direct(clk_dvfs_node->vd, volt_new);
                if (ret)
                        goto fail_roll_back;
@@ -1065,26 +749,30 @@ int dvfs_target(struct clk_hw *hw, unsigned long rate,
 
        /* scale rate */
        if (clk_dvfs_node->clk_dvfs_target) {
-               ret = clk_dvfs_node->clk_dvfs_target(hw, rate, origin_clk_ops->set_rate);
+               ret = clk_dvfs_node->clk_dvfs_target(clk, new_rate);
        } else {
-               ret = origin_clk_ops->set_rate(hw, rate, clk->parent->rate);
+               ret = clk_set_rate(clk, new_rate);
        }
 
        if (ret) {
-               DVFS_ERR("%s set rate err\n", __func__);
+               DVFS_ERR("%s:clk(%s) set rate err\n", 
+                       __func__, __clk_get_name(clk));
                goto fail_roll_back;
        }
-       clk_dvfs_node->set_freq = rate / 1000;
+       clk_dvfs_node->set_freq = new_rate / 1000;
 
-       DVFS_DBG("dvfs %s set rate %lu ok\n", clk_dvfs_node->name, clk_get_rate(clk));
+       DVFS_DBG("%s:dvfs clk(%s) set rate %lu ok\n", 
+               __func__, clk_dvfs_node->name, clk_get_rate(clk));
 
        /* if down the rate */
-       if (rate < old_rate) {
+       if (new_rate < old_rate) {
                ret = dvfs_scale_volt_direct(clk_dvfs_node->vd, volt_new);
                if (ret)
                        goto out;
        }
-
+       
+       clk_dvfs_node->last_set_rate = new_rate;
+       
        return 0;
 fail_roll_back:
        clk_dvfs_node->set_volt = clk_volt_store;
@@ -1092,71 +780,159 @@ out:
        return ret;
 }
 
+unsigned long dvfs_clk_get_rate(struct dvfs_node *clk_dvfs_node)
+{
+       return clk_get_rate(clk_dvfs_node->clk);
+}
+EXPORT_SYMBOL_GPL(dvfs_clk_get_rate);
 
-static long _clk_dvfs_node_round_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long *prate)
+int dvfs_clk_enable(struct dvfs_node *clk_dvfs_node)
 {
-       struct clk *clk = hw->clk;
-       struct dvfs_node *dvfs_node = clk_get_dvfs_info(clk);
+       return clk_enable(clk_dvfs_node->clk);
+}
+EXPORT_SYMBOL_GPL(dvfs_clk_enable);
 
-       if (rate < dvfs_node->min_rate) {
-               rate = dvfs_node->min_rate;
-       } else if (rate > dvfs_node->max_rate) {
-               rate = dvfs_node->max_rate;
-       }
+void dvfs_clk_disable(struct dvfs_node *clk_dvfs_node)
+{
+       return clk_disable(clk_dvfs_node->clk);
+}
+EXPORT_SYMBOL_GPL(dvfs_clk_disable);
 
-       return dvfs_node->origin_clk_ops->round_rate(hw, rate, prate);
+struct dvfs_node *clk_get_dvfs_node(char *clk_name)
+{
+       struct vd_node *vd;
+       struct pd_node *pd;
+       struct dvfs_node *clk_dvfs_node;
+
+       mutex_lock(&rk_dvfs_mutex);
+       list_for_each_entry(vd, &rk_dvfs_tree, node) {
+               mutex_lock(&vd->mutex);
+               list_for_each_entry(pd, &vd->pd_list, node) {
+                       list_for_each_entry(clk_dvfs_node, &pd->clk_list, node) {
+                               if (0 == strcmp(clk_dvfs_node->name, clk_name)) {
+                                       mutex_unlock(&vd->mutex);
+                                       mutex_unlock(&rk_dvfs_mutex);
+                                       return clk_dvfs_node;
+                               }
+                       }
+               }
+               mutex_unlock(&vd->mutex);
+       }
+       mutex_unlock(&rk_dvfs_mutex);
+       
+       return NULL;    
 }
+EXPORT_SYMBOL_GPL(clk_get_dvfs_node);
 
-static int _clk_dvfs_node_enable(struct clk_hw *hw)
+void clk_put_dvfs_node(struct dvfs_node *clk_dvfs_node)
 {
-       struct clk *clk = hw->clk;
-       struct dvfs_node *dvfs_node = clk_get_dvfs_info(clk);   
+       return;
+}
+EXPORT_SYMBOL_GPL(clk_put_dvfs_node);
 
-       return dvfs_node->origin_clk_ops->enable(hw);
+int dvfs_clk_prepare_enable(struct dvfs_node *clk_dvfs_node)
+{
+       return clk_prepare_enable(clk_dvfs_node->clk);
 }
+EXPORT_SYMBOL_GPL(dvfs_clk_prepare_enable);
 
 
-static void _clk_dvfs_node_disable(struct clk_hw *hw)
+void dvfs_clk_disable_unprepare(struct dvfs_node *clk_dvfs_node)
 {
-       struct clk *clk = hw->clk;
-       struct dvfs_node *dvfs_node = clk_get_dvfs_info(clk);   
+       clk_disable_unprepare(clk_dvfs_node->clk);
+}
+EXPORT_SYMBOL_GPL(dvfs_clk_disable_unprepare);
 
-       dvfs_node->origin_clk_ops->disable(hw); 
+int dvfs_clk_set_rate(struct dvfs_node *clk_dvfs_node, unsigned long rate)
+{
+       int ret = -EINVAL;
+       
+       if (!clk_dvfs_node)
+               return -EINVAL;
+       
+       DVFS_DBG("%s:dvfs node(%s) set rate(%lu)\n", 
+               __func__, clk_dvfs_node->name, rate);
+       
+       #if 0 // judge by reference func in rk
+       if (dvfs_support_clk_set_rate(dvfs_info)==false) {
+               DVFS_ERR("dvfs func:%s is not support!\n", __func__);
+               return ret;
+       }
+       #endif
+
+       if (clk_dvfs_node->vd && clk_dvfs_node->vd->vd_dvfs_target) {
+               mutex_lock(&clk_dvfs_node->vd->mutex);
+               ret = clk_dvfs_node->vd->vd_dvfs_target(clk_dvfs_node, rate);
+               mutex_unlock(&clk_dvfs_node->vd->mutex);
+       } else {
+               DVFS_ERR("%s:dvfs node(%s) has no vd node or target callback!\n", 
+                       __func__, clk_dvfs_node->name);
+       }
+               
+       return ret;     
 }
+EXPORT_SYMBOL_GPL(dvfs_clk_set_rate);
 
 
+int rk_regist_vd(struct vd_node *vd)
+{
+       if (!vd)
+               return -EINVAL;
 
-static int _clk_register_dvfs(struct clk *clk, struct dvfs_node *dvfs_node)
+       vd->mode_flag=0;
+       vd->volt_time_flag=0;
+       vd->n_voltages=0;
+       INIT_LIST_HEAD(&vd->pd_list);
+       mutex_lock(&rk_dvfs_mutex);
+       list_add(&vd->node, &rk_dvfs_tree);
+       mutex_unlock(&rk_dvfs_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rk_regist_vd);
+
+int rk_regist_pd(struct pd_node *pd)
 {
-       struct clk_ops  *ops;
+       struct vd_node  *vd;
+
+       if (!pd)
+               return -EINVAL;
 
-       if (IS_ERR(clk) || IS_ERR(dvfs_node))
+       vd = pd->vd;
+       if (!vd)
                return -EINVAL;
 
-       //mutex_lock(&mutex);
+       INIT_LIST_HEAD(&pd->clk_list);
+       mutex_lock(&vd->mutex);
+       list_add(&pd->node, &vd->pd_list);
+       mutex_unlock(&vd->mutex);
+       
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rk_regist_pd);
 
-       dvfs_node->clk = clk;
-       dvfs_node->origin_clk_ops = clk->ops;
+int rk_regist_clk(struct dvfs_node *clk_dvfs_node)
+{
+       struct vd_node  *vd;
+       struct pd_node  *pd;
 
-       ops = kzalloc(sizeof(struct clk_ops), GFP_KERNEL);
-       if (!ops)
-               return -ENOMEM;
-       *ops = *(clk->ops);
-       ops->set_rate = dvfs_vd_clk_set_rate;
-       ops->round_rate = _clk_dvfs_node_round_rate;
-       ops->enable = _clk_dvfs_node_enable;
-       ops->disable = _clk_dvfs_node_disable;
-       
-       clk->ops = ops;
-       clk->private_data = dvfs_node;
+       if (!clk_dvfs_node)
+               return -EINVAL;
+
+       vd = clk_dvfs_node->vd;
+       pd = clk_dvfs_node->pd;
+       if (!vd || !pd)
+               return -EINVAL;
 
-       //mutex_unlock(&mutex);
+       mutex_lock(&vd->mutex);
+       list_add(&clk_dvfs_node->node, &pd->clk_list);
+       mutex_unlock(&vd->mutex);
        
        return 0;
 }
+EXPORT_SYMBOL_GPL(rk_regist_clk);
 
-static int _rk_convert_cpufreq_table(struct dvfs_node *dvfs_node)
+static int rk_convert_cpufreq_table(struct dvfs_node *dvfs_node)
 {
        struct opp *opp;
        struct device *dev;
@@ -1175,8 +951,6 @@ static int _rk_convert_cpufreq_table(struct dvfs_node *dvfs_node)
        return 0;
 }
 
-
-
 int of_dvfs_init(void)
 {
        struct vd_node *vd;
@@ -1186,7 +960,7 @@ int of_dvfs_init(void)
        struct clk *clk;
        int ret;
 
-       printk("%s\n", __func__);
+       DVFS_DBG("%s\n", __func__);
 
        dvfs_dev_node = of_find_node_by_name(NULL, "dvfs");
        if (IS_ERR_OR_NULL(dvfs_dev_node)) {
@@ -1199,10 +973,11 @@ int of_dvfs_init(void)
                if (!vd)
                        return -ENOMEM;
 
+               mutex_init(&vd->mutex);
                vd->name = vd_dev_node->name;
                ret = of_property_read_string(vd_dev_node, "regulator_name", &vd->regulator_name);
                if (ret) {
-                       DVFS_ERR("%s vd(%s) get regulator_name err, ret:%d\n", 
+                       DVFS_ERR("%s:vd(%s) get regulator_name err, ret:%d\n", 
                                __func__, vd_dev_node->name, ret);
                        kfree(vd);
                        continue;
@@ -1221,12 +996,12 @@ int of_dvfs_init(void)
                vd->vd_dvfs_target = dvfs_target;
                ret = rk_regist_vd(vd);
                if (ret){
-                       DVFS_ERR("%s vd(%s) register err:%d\n", __func__, vd->name, ret);
+                       DVFS_ERR("%s:vd(%s) register err:%d\n", __func__, vd->name, ret);
                        kfree(vd);
                        continue;
                }
 
-               DVFS_DBG("%s vd(%s) register ok, regulator name:%s,suspend volt:%d\n", 
+               DVFS_DBG("%s:vd(%s) register ok, regulator name:%s,suspend volt:%d\n", 
                        __func__, vd->name, vd->regulator_name, vd->suspend_volt);
                
                for_each_available_child_of_node(vd_dev_node, pd_dev_node) {            
@@ -1239,11 +1014,11 @@ int of_dvfs_init(void)
                        
                        ret = rk_regist_pd(pd);
                        if (ret){
-                               DVFS_ERR("%s pd(%s) register err:%d\n", __func__, pd->name, ret);
+                               DVFS_ERR("%s:pd(%s) register err:%d\n", __func__, pd->name, ret);
                                kfree(pd);
                                continue;
                        }
-                       DVFS_DBG("%s pd(%s) register ok, parent vd:%s\n", 
+                       DVFS_DBG("%s:pd(%s) register ok, parent vd:%s\n", 
                                __func__, pd->name, vd->name);                  
                        for_each_available_child_of_node(pd_dev_node, clk_dev_node) {
                                dvfs_node = kzalloc(sizeof(struct dvfs_node), GFP_KERNEL);
@@ -1256,18 +1031,18 @@ int of_dvfs_init(void)
                                dvfs_node->dev.of_node = clk_dev_node;
                                ret = of_init_opp_table(&dvfs_node->dev);
                                if (ret) {
-                                       DVFS_ERR("%s clk(%s) get opp table err:%d\n", __func__, dvfs_node->name, ret);
+                                       DVFS_ERR("%s:clk(%s) get opp table err:%d\n", __func__, dvfs_node->name, ret);
                                        kfree(dvfs_node);
                                        continue;
                                }
                                
                                ret = opp_init_cpufreq_table(&dvfs_node->dev, &dvfs_node->dvfs_table);
                                if (ret) {
-                                       DVFS_ERR("%s clk(%s) get cpufreq table err:%d\n", __func__, dvfs_node->name, ret);
+                                       DVFS_ERR("%s:clk(%s) get cpufreq table err:%d\n", __func__, dvfs_node->name, ret);
                                        kfree(dvfs_node);
                                        continue;
                                }
-                               ret = _rk_convert_cpufreq_table(dvfs_node);
+                               ret = rk_convert_cpufreq_table(dvfs_node);
                                if (ret) {
                                        kfree(dvfs_node);
                                        continue;
@@ -1275,22 +1050,20 @@ int of_dvfs_init(void)
                                
                                clk = clk_get(NULL, clk_dev_node->name);
                                if (IS_ERR(clk)){
-                                       DVFS_ERR("%s get clk(%s) err:%ld\n", __func__, dvfs_node->name, PTR_ERR(clk));
+                                       DVFS_ERR("%s:get clk(%s) err:%ld\n", __func__, dvfs_node->name, PTR_ERR(clk));
                                        kfree(dvfs_node);
                                        continue;
                                        
                                }
-
-                               _clk_register_dvfs(clk, dvfs_node);
-                               clk_put(clk);
                                
+                               dvfs_node->clk = clk;
                                ret = rk_regist_clk(dvfs_node);
                                if (ret){
-                                       DVFS_ERR("%s dvfs_node(%s) register err:%d\n", __func__, dvfs_node->name, ret);
+                                       DVFS_ERR("%s:dvfs_node(%s) register err:%d\n", __func__, dvfs_node->name, ret);
                                        return ret;
                                }
 
-                               DVFS_DBG("%s dvfs_node(%s) register ok, parent pd:%s\n", 
+                               DVFS_DBG("%s:dvfs_node(%s) register ok, parent pd:%s\n", 
                                        __func__, clk_dev_node->name, pd->name);        
 
                        }
@@ -1304,46 +1077,36 @@ int of_dvfs_init(void)
 /**
  * dump_dbg_map() : Draw all informations of dvfs while debug
  */
-int dump_dbg_map(char *buf)
+static int dump_dbg_map(char *buf)
 {
        int i;
        struct vd_node  *vd;
-       struct pd_node  *pd; //*clkparent;
-       struct clk_list *child;
+       struct pd_node  *pd;
        struct dvfs_node        *clk_dvfs_node;
-       //struct depend_list *depend;
        char *s = buf;
+       
        mutex_lock(&rk_dvfs_mutex);
-
        printk( "-------------DVFS TREE-----------\n\n\n");
        printk( "DVFS TREE:\n");
+
        list_for_each_entry(vd, &rk_dvfs_tree, node) {
+               mutex_lock(&vd->mutex);
                printk( "|\n|- voltage domain:%s\n", vd->name);
                printk( "|- current voltage:%d\n", vd->cur_volt);
-               //list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
-               //      printk( "|- request voltage:%d, clk:%s\n", depend->req_volt, depend->clk_dvfs_node->name);
-               //}
 
                list_for_each_entry(pd, &vd->pd_list, node) {
                        printk( "|  |\n|  |- power domain:%s, status = %s, current volt = %d\n",
-                                       pd->name, (pd->pd_status == PD_ON) ? "ON" : "OFF", pd->cur_volt);
+                                       pd->name, (pd->pd_status == 1) ? "ON" : "OFF", pd->cur_volt);
 
-                       list_for_each_entry(child, &pd->clk_list, node) {
-                               clk_dvfs_node = child->clk_dvfs_node;
+                       list_for_each_entry(clk_dvfs_node, &pd->clk_list, node) {
                                printk( "|  |  |\n|  |  |- clock: %s current: rate %d, volt = %d,"
                                                " enable_dvfs = %s\n",
                                                clk_dvfs_node->name, clk_dvfs_node->set_freq, clk_dvfs_node->set_volt,
-                                               clk_dvfs_node->enable_dvfs == 0 ? "DISABLE" : "ENABLE");
+                                               clk_dvfs_node->enable_count == 0 ? "DISABLE" : "ENABLE");
                                printk( "|  |  |- clk limit:[%u, %u]; last set rate = %u\n",
                                                clk_dvfs_node->min_rate, clk_dvfs_node->max_rate,
                                                clk_dvfs_node->last_set_rate);
 
-                               /*for (i = 0; clk_dvfs_node->pds[i].pd != NULL; i++) {
-                                       clkparent = clk_dvfs_node->pds[i].pd;
-                                       printk( "|  |  |  |- clock parents: %s, vd_parent = %s\n",
-                                                       clkparent->name, clkparent->vd->name);
-                               }*/
-
                                for (i = 0; (clk_dvfs_node->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
                                        printk( "|  |  |  |- freq = %d, volt = %d\n",
                                                        clk_dvfs_node->dvfs_table[i].frequency,
@@ -1352,10 +1115,12 @@ int dump_dbg_map(char *buf)
                                }
                        }
                }
+               mutex_unlock(&vd->mutex);
        }
-       printk( "-------------DVFS TREE END------------\n");
        
+       printk( "-------------DVFS TREE END------------\n");
        mutex_unlock(&rk_dvfs_mutex);
+       
        return s - buf;
 }
 /*******************************AVS AREA****************************************/
@@ -1383,18 +1148,6 @@ struct init_avs_st {
 
 static struct init_avs_st init_avs_paramet[init_avs_st_num];
 
-void avs_board_init(struct avs_ctr_st *data)
-{
-       
-       avs_ctr_data=data;
-}
-void avs_init(void)
-{
-       memset(&init_avs_paramet[0].is_set, 0, sizeof(init_avs_paramet));
-       if(avs_ctr_data&&avs_ctr_data->avs_init)
-               avs_ctr_data->avs_init();
-       avs_init_val_get(0, 1200000,"board_init");
-}
 static u8 rk_get_avs_val(void)
 {
        
@@ -1405,7 +1158,7 @@ static u8 rk_get_avs_val(void)
        return 0;
 
 }
-/******************************int val get**************************************/
+
 void avs_init_val_get(int index, int vol, char *s)
 {
        int i;
@@ -1422,6 +1175,20 @@ void avs_init_val_get(int index, int vol, char *s)
        }
        printk("\n");
 }
+
+void avs_board_init(struct avs_ctr_st *data)
+{
+       
+       avs_ctr_data=data;
+}
+void avs_init(void)
+{
+       memset(&init_avs_paramet[0].is_set, 0, sizeof(init_avs_paramet));
+       if(avs_ctr_data&&avs_ctr_data->avs_init)
+               avs_ctr_data->avs_init();
+       avs_init_val_get(0, 1200000,"board_init");
+}
+
 int avs_set_scal_val(u8 avs_base)
 {
        return 0;
index 0af28cc82c1b8aafcbde42e4d4f5fff88a188a2c..9155786f572d429164acadf05d0c6882d02adcbc 100644 (file)
 #define _RK30_DVFS_H_
 
 #include <linux/device.h>
-#include <linux/clk-private.h>
+#include <linux/clk-provider.h>
 
-typedef int (*dvfs_set_rate_callback)(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate);
-typedef int (*clk_dvfs_target_callback)(struct clk_hw *hw, unsigned long rate,
-                                        dvfs_set_rate_callback set_rate);
-typedef int (*clk_dvfs_node_disable_callback)(struct clk *clk,int on);
+struct dvfs_node;
+typedef int (*dvfs_set_rate_callback)(struct dvfs_node *clk_dvfs_node, unsigned long rate);
+typedef int (*clk_set_rate_callback)(struct clk *clk, unsigned long rate);
 
 /**
  * struct vd_node:     To Store All Voltage Domains' info
@@ -51,11 +49,9 @@ struct vd_node {
        struct regulator        *regulator;
        struct list_head        node;
        struct list_head        pd_list;
-       struct list_head        req_volt_list;
-       //struct mutex          dvfs_mutex;
-       clk_dvfs_node_disable_callback  vd_clk_disable_target;
-       dvfs_set_rate_callback      vd_dvfs_target;
-       unsigned n_voltages;
+       struct mutex            mutex;
+       dvfs_set_rate_callback  vd_dvfs_target;
+       unsigned int            n_voltages;
        int volt_list[VD_VOL_LIST_CNT];
 };
 
@@ -78,10 +74,6 @@ struct pd_node {
        struct list_head        clk_list;
 };
 
-struct clk_list{
-       struct dvfs_node                *clk_dvfs_node;
-       struct list_head        node;
-};
 /**
  * struct dvfs_node:   To Store All dvfs clocks' info
  * @name:              Dvfs clock's Name
@@ -100,7 +92,7 @@ struct dvfs_node {
        const char              *name;
        int                     set_freq;       //KHZ
        int                     set_volt;       //MV
-       int                     enable_dvfs;
+       int                     enable_count;
        int                     freq_limit_en;  //sign if use limit frequency
        unsigned int            min_rate;       //limit min frequency
        unsigned int            max_rate;       //limit max frequency
@@ -108,21 +100,22 @@ struct dvfs_node {
        struct clk              *clk;
        struct pd_node          *pd;
        struct vd_node          *vd;
-       struct clk_list         clk_list;
+       struct list_head        node;
        struct notifier_block   *dvfs_nb;
        struct cpufreq_frequency_table  *dvfs_table;
-       struct clk_disable_ctr          *disable_ctr;
-       const struct clk_ops            *origin_clk_ops;
-       clk_dvfs_target_callback        clk_dvfs_target;
+       struct cpufreq_frequency_table  *condition_freq_table;
+       clk_set_rate_callback   clk_dvfs_target;
 };
 
+
+
 #define DVFS_MHZ (1000*1000)
 #define DVFS_KHZ (1000)
 
 #define DVFS_V (1000*1000)
 #define DVFS_MV (1000)
 #if 0
-#define DVFS_DBG(fmt, args...) printk(KERN_DEBUG "DVFS DBG:\t"fmt, ##args)
+#define DVFS_DBG(fmt, args...) printk(KERN_INFO "DVFS DBG:\t"fmt, ##args)
 #else
 #define DVFS_DBG(fmt, args...) {while(0);}
 #endif
@@ -131,12 +124,9 @@ struct dvfs_node {
 #define DVFS_LOG(fmt, args...) printk(KERN_DEBUG "DVFS LOG:\t"fmt, ##args)
 #define DVFS_WARNING(fmt, args...) printk(KERN_WARNING "DVFS WARNING:\t"fmt, ##args)
 
-
-
 #define DVFS_SET_VOLT_FAILURE  1
 #define DVFS_SET_VOLT_SUCCESS  0
 
-
 #define dvfs_regulator_get(dev,id) regulator_get((dev),(id))
 #define dvfs_regulator_put(regu) regulator_put((regu))
 #define dvfs_regulator_set_voltage(regu,min_uV,max_uV) regulator_set_voltage((regu),(min_uV),(max_uV))
@@ -151,9 +141,6 @@ struct dvfs_node {
 #define clk_dvfs_node_get_rate_kz(a) (clk_get_rate((a))/1000)
 #define clk_dvfs_node_set_rate(a,b) clk_set_rate((a),(b))
 
-
-
-
 typedef void (*avs_init_fn)(void);
 typedef u8 (*avs_get_val_fn)(void);
 struct avs_ctr_st {
@@ -162,70 +149,47 @@ struct avs_ctr_st {
 };
 
 #ifdef CONFIG_DVFS
-int of_dvfs_init(void);
-int clk_dvfs_node_get_ref_volt(struct dvfs_node *clk_dvfs_node, int rate_khz,
-               struct cpufreq_frequency_table *clk_fv);
-int dvfs_reset_volt(struct vd_node *dvfs_vd);
-int dvfs_vd_get_newvolt_byclk(struct dvfs_node *clk_dvfs_node);
-int dvfs_vd_get_newvolt_bypd(struct vd_node *vd);
-int dvfs_scale_volt_bystep(struct vd_node *vd_clk, struct vd_node *vd_dep, int volt_new, int volt_dep_new,
-               int cur_clk_biger_than_dep, int cur_dep_biger_than_clk, int new_clk_biger_than_dep, int new_dep_biger_than_clk);
+struct dvfs_node *clk_get_dvfs_node(char *clk_name);
+void clk_put_dvfs_node(struct dvfs_node *clk_dvfs_node);
+unsigned long dvfs_clk_get_rate(struct dvfs_node *clk_dvfs_node);
+int dvfs_clk_set_rate(struct dvfs_node *clk_dvfs_node, unsigned long rate);
+int dvfs_clk_enable(struct dvfs_node *clk_dvfs_node);
+void dvfs_clk_disable(struct dvfs_node *clk_dvfs_node);
+int dvfs_clk_prepare_enable(struct dvfs_node *clk_dvfs_node);
+void dvfs_clk_disable_unprepare(struct dvfs_node *clk_dvfs_node);
+int dvfs_set_freq_volt_table(struct dvfs_node *clk_dvfs_node, struct cpufreq_frequency_table *table);
+int dvfs_clk_register_set_rate_callback(struct dvfs_node *clk_dvfs_node, clk_set_rate_callback clk_dvfs_target);
+int dvfs_clk_enable_limit(struct dvfs_node *clk_dvfs_node, unsigned int min_rate, unsigned max_rate);
+int dvfs_clk_disable_limit(struct dvfs_node *clk_dvfs_node);
+int clk_disable_dvfs(struct dvfs_node *clk_dvfs_node);
+int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node);
+struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct dvfs_node *clk_dvfs_node);
 int rk_regist_vd(struct vd_node *vd);
 int rk_regist_pd(struct pd_node *pd);
 int rk_regist_clk(struct dvfs_node *clk_dvfs_node);
-struct dvfs_node *dvfs_get_clk_dvfs_node_byname(char *name);
-int vd_regulator_round_volt(struct vd_node *vd, int volt,int flags);
-/*********************************if not define dvfs ,the following function is need defined func{}******************************/
-int dvfs_vd_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-                           unsigned long parent_rate);
-int clk_enable_dvfs(struct clk *clk);
-int clk_disable_dvfs(struct clk *clk);
-void clk_dvfs_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target);
-struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk);
-int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table);
-struct regulator* dvfs_get_regulator(char *regulator_name);
-int clk_dvfs_enable_limit(struct clk *clk, unsigned int min_rate, unsigned max_rate);
-int clk_dvfs_disable_limit(struct clk *clk);
-int dvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new);
-/******************************** inline *******************************/
-static inline struct dvfs_node *clk_get_dvfs_info(struct clk *clk)
-{
-    return clk->private_data;
-}
-static inline bool dvfs_support_clk_set_rate(struct dvfs_node *dvfs_info)
-{
-       return (dvfs_info&&dvfs_info->enable_dvfs);
-}
-static inline bool dvfs_support_clk_disable(struct dvfs_node *dvfs_info)
-{
-       return (dvfs_info&&dvfs_info->disable_ctr&&dvfs_info->enable_dvfs);
-}
-/********************************avs*******************************/
-void avs_init(void);
-void avs_init_val_get(int index,int vol,char *s);
-int avs_set_scal_val(u8 avs_base);
-void avs_board_init(struct avs_ctr_st *data);
+int of_dvfs_init(void);
 
 #else
+
+static inline struct dvfs_node *clk_get_dvfs_node(char *clk_name){ return NULL; };
+static inline void clk_put_dvfs_node(struct dvfs_node *clk_dvfs_node){ return; };
+static inline unsigned long dvfs_clk_get_rate(struct dvfs_node *clk_dvfs_node){ return 0; };
+static inline int dvfs_clk_set_rate(struct dvfs_node *clk_dvfs_node, unsigned long rate){ return 0; };
+static inline int dvfs_clk_enable(struct dvfs_node *clk_dvfs_node){ return 0; };
+static inline void dvfs_clk_disable(struct dvfs_node *clk_dvfs_node){ };
+static inline int dvfs_clk_prepare_enable(struct dvfs_node *clk_dvfs_node){ return 0; };
+static inline void dvfs_clk_disable_unprepare(struct dvfs_node *clk_dvfs_node){ };
+static inline int dvfs_set_freq_volt_table(struct dvfs_node *clk_dvfs_node, struct cpufreq_frequency_table *table){ return 0; };
+static inline int dvfs_clk_register_set_rate_callback(struct dvfs_node *clk_dvfs_node, clk_set_rate_callback clk_dvfs_target){ return 0; };
+static inline int dvfs_clk_enable_limit(struct dvfs_node *clk_dvfs_node, unsigned int min_rate, unsigned max_rate){ return 0; };
+static inline int dvfs_clk_disable_limit(struct dvfs_node *clk_dvfs_node){ return 0; };
+static inline int clk_disable_dvfs(struct dvfs_node *clk_dvfs_node){ return 0; };
+static inline int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node){ return 0; };
+static inline struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct dvfs_node *clk_dvfs_node){ return NULL; };
+static inline int rk_regist_vd(struct vd_node *vd){ return 0; };
+static inline int rk_regist_pd(struct pd_node *pd){ return 0; };
+static inline int rk_regist_clk(struct dvfs_node *clk_dvfs_node){ return 0; };
 static inline int of_dvfs_init(void){ return 0; };
-static inline bool dvfs_support_clk_set_rate(struct dvfs_node *dvfs_info) { return 0; }
-static inline bool dvfs_support_clk_disable(struct dvfs_node *dvfs_info) { return 0; }
-static inline int dvfs_vd_clk_set_rate(struct clk *clk, unsigned long rate) { return 0; }
-static inline int dvfs_vd_clk_disable(struct clk *clk, int on) { return 0; }
-static inline int clk_enable_dvfs(struct clk *clk) { return 0; }
-static inline int clk_disable_dvfs(struct clk *clk) { return 0; }
-static inline void clk_dvfs_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target) {}
-static inline struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk) { return NULL; }
-static inline int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table) { return 0; }
-static inline struct regulator* dvfs_get_regulator(char *regulator_name){ return NULL; }
-static inline int clk_dvfs_enable_limit(struct clk *clk, unsigned int min_rate, unsigned max_rate){ return 0; }
-static inline int clk_dvfs_disable_limit(struct clk *clk){ return 0; };
-static inline int dvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new){ return 0; };
-
-static inline void avs_init(void){};
-static inline void avs_init_val_get(int index, int vol, char *s){};
-static inline int avs_set_scal_val(u8 avs_base){ return 0; };
-static inline void avs_board_init(struct avs_ctr_st *data){ return 0; };
 #endif
 
 #endif