dvfs support list regulator volt
authorxxx <xxx@rock-chips.com>
Thu, 21 Feb 2013 09:17:49 +0000 (17:17 +0800)
committerxxx <xxx@rock-chips.com>
Thu, 21 Feb 2013 09:17:49 +0000 (17:17 +0800)
arch/arm/plat-rk/dvfs.c
arch/arm/plat-rk/include/plat/dvfs.h

index ce9e6a3e642e526085d6f9d863c4d793335f5513..a9901daef16fff837861ae62a56583cae8c955c6 100755 (executable)
@@ -40,6 +40,9 @@ static int dump_dbg_map(char *buf);
 #define get_volt_up_delay(new_volt, old_volt)  \\r
        ((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 9) : 0)\r
 \r
+\r
+\r
+/**************************************vd regulator functions***************************************/\r
 int dvfs_regulator_set_voltage_readback(struct regulator *regulator, int min_uV, int max_uV)\r
 {\r
        int ret = 0, read_back = 0;\r
@@ -70,6 +73,104 @@ void clk_enable_dvfs_regulator_check(struct vd_node *vd)
        vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;\r
 }\r
 \r
+static void dvfs_get_vd_regulator_volt_list(struct vd_node *vd)\r
+{\r
+       unsigned i,selector=dvfs_regulator_count_voltages(vd->regulator);\r
+       int sel_volt=0;\r
+       \r
+       if(selector>VD_VOL_LIST_CNT)\r
+               selector=VD_VOL_LIST_CNT;\r
+       \r
+       mutex_unlock(&mutex);\r
+       for (i = 0; i<selector; i++) {\r
+               sel_volt=dvfs_regulator_list_voltage(vd->regulator,i);\r
+               if(sel_volt<=0)\r
+               {       \r
+                       DVFS_WARNING("%s : selector=%u,but volt <=0\n",vd->name,i);\r
+                       break;\r
+               }\r
+               vd->volt_list[i]=sel_volt;      \r
+               printk("%s:selector=%u,volt %d\n",vd->name,i,sel_volt);\r
+       }\r
+       vd->n_voltages=selector;\r
+       mutex_unlock(&mutex);\r
+}\r
+\r
+// >= volt\r
+static int vd_regulator_round_volt_max(struct vd_node *vd, int volt)\r
+{\r
+       int sel_volt;\r
+       unsigned i;\r
+       \r
+       for (i = 0; i<vd->n_voltages; i++) {\r
+               sel_volt=vd->volt_list[i];\r
+               if(sel_volt<=0)\r
+               {       \r
+                       DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n",__FUNCTION__,i);\r
+                       return -1;\r
+               }\r
+               if(sel_volt>=volt)\r
+                return sel_volt;       \r
+       }\r
+       return -1;\r
+}\r
+// >=volt\r
+static int vd_regulator_round_volt_min(struct vd_node *vd, int volt)\r
+{\r
+       int sel_volt;\r
+       unsigned i;\r
+       \r
+       for (i = 0; i<vd->n_voltages; i++) {\r
+               sel_volt=vd->volt_list[i];\r
+               if(sel_volt<=0)\r
+               {       \r
+                       DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n",__FUNCTION__,i);\r
+                       return -1;\r
+               }\r
+               if(sel_volt>volt)\r
+               {\r
+                       if(i>0)\r
+                               return vd->volt_list[i-1];\r
+                       else\r
+                               return -1;\r
+               }       \r
+       }\r
+       return -1;\r
+}\r
+\r
+// >=volt\r
+int vd_regulator_round_volt(struct vd_node *vd, int volt,int flags)\r
+{\r
+       if(!vd->n_voltages)\r
+               return -1;\r
+       if(flags==VD_LIST_RELATION_L)\r
+               return vd_regulator_round_volt_min(vd,volt);\r
+       else\r
+               return vd_regulator_round_volt_max(vd,volt);    \r
+}\r
+EXPORT_SYMBOL(vd_regulator_round_volt);\r
+\r
+\r
+static void dvfs_table_round_volt(struct clk_node  *dvfs_clk)\r
+{\r
+       int i,test_volt;\r
+\r
+       if(!dvfs_clk->dvfs_table||!dvfs_clk->vd||IS_ERR_OR_NULL(dvfs_clk->vd->regulator))\r
+               return;\r
+       mutex_lock(&mutex);\r
+       for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
+\r
+               test_volt=vd_regulator_round_volt(dvfs_clk->vd,dvfs_clk->dvfs_table[i].index,VD_LIST_RELATION_H);\r
+               if(test_volt<=0)\r
+               {       \r
+                       DVFS_WARNING("clk %s:round_volt : is %d,but list <=0\n",dvfs_clk->name,dvfs_clk->dvfs_table[i].index);\r
+                       break;\r
+               }\r
+               printk("clk %s:round_volt %d to %d\n",dvfs_clk->name,dvfs_clk->dvfs_table[i].index,test_volt);\r
+               dvfs_clk->dvfs_table[i].index=test_volt;                \r
+       }\r
+       mutex_unlock(&mutex);\r
+}\r
 struct regulator *dvfs_get_regulator(char *regulator_name) \r
 {\r
        struct vd_node *vd;\r
@@ -81,6 +182,7 @@ struct regulator *dvfs_get_regulator(char *regulator_name)
        return NULL;\r
 }\r
 \r
+/**************************************dvfs clocks functions***************************************/\r
 int dvfs_clk_enable_limit(struct clk *clk, unsigned int min_rate, unsigned max_rate)\r
 {\r
        struct clk_node *dvfs_clk;\r
@@ -134,6 +236,38 @@ int dvfs_set_rate(struct clk *clk, unsigned long rate)
        return ret;\r
 }\r
 \r
+static void dvfs_table_round_clk_rate(struct clk_node  *dvfs_clk)\r
+{\r
+       int i;\r
+       long temp_rate;\r
+       int rate;\r
+       int flags;\r
+       \r
+       if(!dvfs_clk->dvfs_table||dvfs_clk->clk==NULL||is_suport_round_rate(dvfs_clk->clk)<0)\r
+               return;\r
+       \r
+       mutex_lock(&mutex);\r
+       for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
+               //ddr rate = real rate+flags\r
+               flags=dvfs_clk->dvfs_table[i].frequency%1000;\r
+               rate=(dvfs_clk->dvfs_table[i].frequency/1000)*1000;\r
+               temp_rate=clk_round_rate(dvfs_clk->clk,rate*1000);\r
+               if(temp_rate<=0)\r
+               {       \r
+                       DVFS_WARNING("clk %s:round_clk_rate : is %d,but round <=0",dvfs_clk->name,dvfs_clk->dvfs_table[i].frequency);\r
+                       break;\r
+               }\r
+               temp_rate=(temp_rate/1000)+flags;\r
+               \r
+               printk("clk %s round_clk_rate %d to %d\n",\r
+                       dvfs_clk->name,dvfs_clk->dvfs_table[i].frequency,(int)(temp_rate));\r
+               \r
+               dvfs_clk->dvfs_table[i].frequency=temp_rate;            \r
+       }\r
+       mutex_unlock(&mutex);\r
+}\r
+\r
+/***************************************************************************************************/\r
 static int dvfs_clk_get_ref_volt_depend(struct depend_list *depend, int rate_khz,\r
                struct cpufreq_frequency_table *clk_fv)\r
 {\r
@@ -251,6 +385,7 @@ void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callba
        dvfs_clk->clk_dvfs_target = clk_dvfs_target;\r
 }\r
 \r
+/************************************************ freq volt table************************************/\r
 struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk) \r
 {\r
        struct clk_node *info = clk_get_dvfs_info(clk);\r
@@ -302,6 +437,8 @@ int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *ta
        DVFS_DBG("%s,clk %s,limit max=%lu,min=%lu\n",__FUNCTION__,info->name,info->max_rate,info->min_rate);\r
 \r
        mutex_unlock(&mutex);\r
+       dvfs_table_round_clk_rate(info);\r
+       dvfs_table_round_volt(info);\r
        return 0;\r
 }\r
 EXPORT_SYMBOL(dvfs_set_freq_volt_table);\r
@@ -359,8 +496,6 @@ int dvfs_set_arm_logic_volt(struct dvfs_arm_table *dvfs_cpu_logic_table,
 }\r
 \r
 \r
-\r
-\r
 int clk_enable_dvfs(struct clk *clk)\r
 {\r
        struct clk_node *dvfs_clk;\r
@@ -383,6 +518,7 @@ int clk_enable_dvfs(struct clk *clk)
                        if (!IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {\r
                                // DVFS_DBG("dvfs_regulator_get(%s)\n",dvfs_clk->vd->regulator_name);\r
                                clk_enable_dvfs_regulator_check(dvfs_clk->vd);\r
+                               dvfs_get_vd_regulator_volt_list(dvfs_clk->vd);\r
                        } else {\r
                                //dvfs_clk->vd->regulator = NULL;\r
                                dvfs_clk->enable_dvfs = 0;\r
@@ -394,6 +530,8 @@ int clk_enable_dvfs(struct clk *clk)
                        // DVFS_DBG("%s(%s) vd volt=%u\n",__func__,dvfs_clk->name,dvfs_clk->vd->cur_volt);\r
                }\r
 \r
+               dvfs_table_round_clk_rate(dvfs_clk);\r
+               dvfs_table_round_volt(dvfs_clk);\r
                dvfs_clk->set_freq = dvfs_clk_get_rate_kz(clk);\r
                // DVFS_DBG("%s ,%s get freq%u!\n",__func__,dvfs_clk->name,dvfs_clk->set_freq);\r
 \r
index d9f546dd329d1b4f2bd59fad01377d40d2633878..2aa6a09b3bbf8badbda90832641ba78ce068537c 100755 (executable)
@@ -36,6 +36,9 @@ typedef int (*clk_dvfs_target_callback)(struct clk *clk, unsigned long rate,
  * @dvfs_mutex:                Lock\r
  * @vd_dvfs_target:    Callback function       \r
  */\r
+ #define VD_VOL_LIST_CNT (200)\r
+ #define VD_LIST_RELATION_L 0\r
+ #define VD_LIST_RELATION_H 1\r
 \r
 struct vd_node {\r
        char                    *name;\r
@@ -48,6 +51,8 @@ struct vd_node {
        struct list_head        req_volt_list;\r
        //struct mutex          dvfs_mutex;\r
        vd_dvfs_target_callback vd_dvfs_target;\r
+       unsigned n_voltages;\r
+       int volt_list[VD_VOL_LIST_CNT];\r
 };\r
 \r
 /**\r
@@ -166,6 +171,8 @@ struct dvfs_arm_table {
 #define dvfs_regulator_put(regu) regulator_put((regu))\r
 #define dvfs_regulator_set_voltage(regu,min_uV,max_uV) regulator_set_voltage((regu),(min_uV),(max_uV))\r
 #define dvfs_regulator_get_voltage(regu) regulator_get_voltage((regu))\r
+#define dvfs_regulator_list_voltage(regu,selector) regulator_list_voltage((regu),(selector))\r
+#define dvfs_regulator_count_voltages(regu) regulator_count_voltages((regu))\r
 \r
 #define dvfs_clk_get(a,b) clk_get((a),(b))\r
 #define dvfs_clk_get_rate_kz(a) (clk_get_rate((a))/1000)\r
@@ -201,8 +208,8 @@ int rk_regist_vd(struct vd_node *vd);
 int rk_regist_pd(struct pd_node_lookup *pd_lookup);\r
 int rk_regist_clk(struct clk_node *dvfs_clk);\r
 int rk_regist_depends(struct depend_lookup *dep_node);\r
-struct clk_node *dvfs_get_dvfs_clk_byname(char *name) ;\r
-\r
+struct clk_node *dvfs_get_dvfs_clk_byname(char *name);\r
+int vd_regulator_round_volt(struct vd_node *vd, int volt,int flags);\r
 \r
 /******************************************************************************/\r
 \r