rk: freq limit resume when disable_limit
[firefly-linux-kernel-4.4.55.git] / arch / arm / plat-rk / dvfs.c
1 /* arch/arm/mach-rk30/rk30_dvfs.c\r
2  *\r
3  * Copyright (C) 2012 ROCKCHIP, Inc.\r
4  *\r
5  * This software is licensed under the terms of the GNU General Public\r
6  * License version 2, as published by the Free Software Foundation, and\r
7  * may be copied, distributed, and modified under those terms.\r
8  *\r
9  * This program is distributed in the hope that it will be useful,\r
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
12  * GNU General Public License for more details.\r
13  *\r
14  */\r
15 \r
16 #include <linux/kernel.h>\r
17 #include <linux/err.h>\r
18 #include <linux/spinlock.h>\r
19 #include <linux/list.h>\r
20 #include <linux/slab.h>\r
21 #include <linux/clk.h>\r
22 #include <linux/cpufreq.h>\r
23 #include <mach/dvfs.h>\r
24 #include <mach/clock.h>\r
25 #include <linux/regulator/consumer.h>\r
26 #include <linux/delay.h>\r
27 #include <linux/io.h>\r
28 #include <linux/hrtimer.h>\r
29 \r
30 #define MHz     (1000 * 1000)\r
31 static LIST_HEAD(rk_dvfs_tree);\r
32 static DEFINE_MUTEX(mutex);\r
33 static DEFINE_MUTEX(rk_dvfs_mutex);\r
34 \r
35 static int dump_dbg_map(char *buf);\r
36 \r
37 #define PD_ON   1\r
38 #define PD_OFF  0\r
39 #define DVFS_STR_DISABLE(on) ((on)?"enable":"disable")\r
40 \r
41 #define get_volt_up_delay(new_volt, old_volt)   \\r
42         ((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 9) : 0)\r
43 \r
44 \r
45 \r
46 /**************************************vd regulator functions***************************************/\r
47 static void dvfs_volt_up_delay(struct vd_node *vd,int new_volt, int old_volt)\r
48 {\r
49         int u_time;\r
50         if(new_volt<=old_volt)\r
51                 return;\r
52         if(vd->volt_time_flag>0)        \r
53                 u_time=regulator_set_voltage_time(vd->regulator,old_volt,new_volt);\r
54         else\r
55                 u_time=-1;              \r
56         if(u_time<0)// regulator is not suported time,useing default time\r
57         {\r
58                 DVFS_DBG("%s:vd %s is not suported getting delay time,so we use default\n",\r
59                                 __FUNCTION__,vd->name);\r
60                 u_time=((new_volt) - (old_volt)) >> 9;\r
61         }\r
62         DVFS_DBG("%s:vd %s volt %d to %d delay %d us\n",__FUNCTION__,vd->name,\r
63                 old_volt,new_volt,u_time);\r
64         if (u_time >= 1000) {\r
65                 mdelay(u_time / 1000);\r
66                 udelay(u_time % 1000);\r
67                 DVFS_ERR("regulator set vol delay is larger 1ms,old is %d,new is %d\n",old_volt,new_volt);\r
68         } else if (u_time) {\r
69                 udelay(u_time);\r
70         }                       \r
71 }\r
72 int dvfs_regulator_set_voltage_readback(struct regulator *regulator, int min_uV, int max_uV)\r
73 {\r
74         int ret = 0, read_back = 0;\r
75         ret = dvfs_regulator_set_voltage(regulator, max_uV, max_uV);\r
76         if (ret < 0) {\r
77                 DVFS_ERR("%s now read back to check voltage\n", __func__);\r
78 \r
79                 /* read back to judge if it is already effect */\r
80                 mdelay(2);\r
81                 read_back = dvfs_regulator_get_voltage(regulator);\r
82                 if (read_back == max_uV) {\r
83                         DVFS_ERR("%s set ERROR but already effected, volt=%d\n", __func__, read_back);\r
84                         ret = 0;\r
85                 } else {\r
86                         DVFS_ERR("%s set ERROR AND NOT effected, volt=%d\n", __func__, read_back);\r
87                 }\r
88         }\r
89         return ret;\r
90 }\r
91 // for clk enable case to get vd regulator info\r
92 void clk_enable_dvfs_regulator_check(struct vd_node *vd)\r
93 {\r
94         vd->cur_volt = dvfs_regulator_get_voltage(vd->regulator);\r
95         if(vd->cur_volt<=0)\r
96         {\r
97                 vd->volt_set_flag = DVFS_SET_VOLT_FAILURE;\r
98         }\r
99         vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;\r
100 }\r
101 \r
102 static void dvfs_get_vd_regulator_volt_list(struct vd_node *vd)\r
103 {\r
104         unsigned i,selector=dvfs_regulator_count_voltages(vd->regulator);\r
105         int sel_volt=0;\r
106         \r
107         if(selector>VD_VOL_LIST_CNT)\r
108                 selector=VD_VOL_LIST_CNT;\r
109         \r
110         mutex_lock(&mutex);\r
111         for (i = 0; i<selector; i++) {\r
112                 sel_volt=dvfs_regulator_list_voltage(vd->regulator,i);\r
113                 if(sel_volt<=0)\r
114                 {       \r
115                         DVFS_WARNING("%s : selector=%u,but volt <=0\n",vd->name,i);\r
116                         break;\r
117                 }\r
118                 vd->volt_list[i]=sel_volt;      \r
119                 DVFS_DBG("%s:selector=%u,volt %d\n",vd->name,i,sel_volt);\r
120         }\r
121         vd->n_voltages=selector;\r
122         mutex_unlock(&mutex);\r
123 }\r
124 \r
125 // >= volt\r
126 static int vd_regulator_round_volt_max(struct vd_node *vd, int volt)\r
127 {\r
128         int sel_volt;\r
129         unsigned i;\r
130         \r
131         for (i = 0; i<vd->n_voltages; i++) {\r
132                 sel_volt=vd->volt_list[i];\r
133                 if(sel_volt<=0)\r
134                 {       \r
135                         DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n",__FUNCTION__,i);\r
136                         return -1;\r
137                 }\r
138                 if(sel_volt>=volt)\r
139                  return sel_volt;       \r
140         }\r
141         return -1;\r
142 }\r
143 // >=volt\r
144 static int vd_regulator_round_volt_min(struct vd_node *vd, int volt)\r
145 {\r
146         int sel_volt;\r
147         unsigned i;\r
148         \r
149         for (i = 0; i<vd->n_voltages; i++) {\r
150                 sel_volt=vd->volt_list[i];\r
151                 if(sel_volt<=0)\r
152                 {       \r
153                         DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n",__FUNCTION__,i);\r
154                         return -1;\r
155                 }\r
156                 if(sel_volt>volt)\r
157                 {\r
158                         if(i>0)\r
159                                 return vd->volt_list[i-1];\r
160                         else\r
161                                 return -1;\r
162                 }       \r
163         }\r
164         return -1;\r
165 }\r
166 \r
167 // >=volt\r
168 int vd_regulator_round_volt(struct vd_node *vd, int volt,int flags)\r
169 {\r
170         if(!vd->n_voltages)\r
171                 return -1;\r
172         if(flags==VD_LIST_RELATION_L)\r
173                 return vd_regulator_round_volt_min(vd,volt);\r
174         else\r
175                 return vd_regulator_round_volt_max(vd,volt);    \r
176 }\r
177 EXPORT_SYMBOL(vd_regulator_round_volt);\r
178 \r
179 \r
180 static void dvfs_table_round_volt(struct clk_node  *dvfs_clk)\r
181 {\r
182         int i,test_volt;\r
183 \r
184         if(!dvfs_clk->dvfs_table||!dvfs_clk->vd||IS_ERR_OR_NULL(dvfs_clk->vd->regulator))\r
185                 return;\r
186         mutex_lock(&mutex);\r
187         for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
188 \r
189                 test_volt=vd_regulator_round_volt(dvfs_clk->vd,dvfs_clk->dvfs_table[i].index,VD_LIST_RELATION_H);\r
190                 if(test_volt<=0)\r
191                 {       \r
192                         DVFS_WARNING("clk %s:round_volt : is %d,but list <=0\n",dvfs_clk->name,dvfs_clk->dvfs_table[i].index);\r
193                         break;\r
194                 }\r
195                 DVFS_DBG("clk %s:round_volt %d to %d\n",dvfs_clk->name,dvfs_clk->dvfs_table[i].index,test_volt);\r
196                 dvfs_clk->dvfs_table[i].index=test_volt;                \r
197         }\r
198         mutex_unlock(&mutex);\r
199 }\r
200 void dvfs_vd_get_regulator_volt_time_info(struct vd_node *vd)\r
201 {\r
202         if(vd->volt_time_flag<=0)// check regulator support get uping vol timer\r
203         {\r
204                 vd->volt_time_flag=dvfs_regulator_set_voltage_time(vd->regulator,vd->cur_volt,vd->cur_volt+200*1000);\r
205                 if(vd->volt_time_flag<0)\r
206                 {\r
207                         DVFS_DBG("%s,vd %s volt_time is no support\n",__FUNCTION__,vd->name);\r
208                 }\r
209                 else\r
210                 {\r
211                         DVFS_DBG("%s,vd %s volt_time is support,up 200mv need delay %d us\n",__FUNCTION__,vd->name,vd->volt_time_flag);\r
212 \r
213                 }       \r
214         }\r
215 }\r
216 \r
217 void dvfs_vd_get_regulator_mode_info(struct vd_node *vd)\r
218 {\r
219         //REGULATOR_MODE_FAST\r
220         if(vd->mode_flag<=0)// check regulator support get uping vol timer\r
221         {\r
222                 vd->mode_flag=dvfs_regulator_get_mode(vd->regulator);\r
223                 if(vd->mode_flag==REGULATOR_MODE_FAST||vd->mode_flag==REGULATOR_MODE_NORMAL\r
224                         ||vd->mode_flag==REGULATOR_MODE_IDLE||vd->mode_flag==REGULATOR_MODE_STANDBY)\r
225                 {\r
226                         if(dvfs_regulator_set_mode(vd->regulator,vd->mode_flag)<0)\r
227                         {\r
228                                 vd->mode_flag=0;// check again\r
229                         }\r
230                         \r
231                 }\r
232                 if(vd->mode_flag>0)\r
233                 {\r
234                         DVFS_DBG("%s,vd %s mode(now is %d) support\n",__FUNCTION__,vd->name,vd->mode_flag);\r
235                 }\r
236                 else\r
237                 {\r
238                         DVFS_DBG("%s,vd %s mode is not support now check\n",__FUNCTION__,vd->name);\r
239 \r
240                 }\r
241                 \r
242         }\r
243 }\r
244 struct regulator *dvfs_get_regulator(char *regulator_name) \r
245 {\r
246         struct vd_node *vd;\r
247         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
248                 if (strcmp(regulator_name, vd->regulator_name) == 0) {\r
249                         return vd->regulator;\r
250                 }\r
251         }\r
252         return NULL;\r
253 }\r
254 \r
255 /**************************************dvfs clocks functions***************************************/\r
256 int dvfs_clk_enable_limit(struct clk *clk, unsigned int min_rate, unsigned max_rate)\r
257 {\r
258         struct clk_node *dvfs_clk;\r
259         u32 rate = 0, ret = 0;\r
260         dvfs_clk = clk_get_dvfs_info(clk);\r
261         if (IS_ERR_OR_NULL(dvfs_clk)) {\r
262                 DVFS_ERR("%s: can not get dvfs clk(%s)\n", __func__, clk->name);\r
263                 return -1;\r
264 \r
265         }\r
266 \r
267         if (dvfs_clk->vd && dvfs_clk->vd->vd_dvfs_target){\r
268                 mutex_lock(&rk_dvfs_mutex);\r
269 \r
270                 dvfs_clk->freq_limit_en = 1;\r
271                 dvfs_clk->min_rate = min_rate;\r
272                 dvfs_clk->max_rate = max_rate;\r
273                 rate = clk_get_rate(clk);\r
274                 ret = dvfs_clk->vd->vd_dvfs_target(clk, rate);\r
275                 clk->last_set_rate = rate;\r
276 \r
277                 mutex_unlock(&rk_dvfs_mutex);\r
278         }\r
279 \r
280         DVFS_DBG("%s: clk(%s) last_set_rate=%d; [min_rate, max_rate]=[%d, %d]\n",\r
281                         __func__, clk->name, clk->last_set_rate, dvfs_clk->min_rate, dvfs_clk->max_rate);\r
282         return 0;\r
283 }\r
284 \r
285 int dvfs_clk_disable_limit(struct clk *clk)\r
286 {\r
287         struct clk_node *dvfs_clk;\r
288         u32 ret = 0;\r
289         dvfs_clk = clk_get_dvfs_info(clk);\r
290         if (IS_ERR_OR_NULL(dvfs_clk)) {\r
291                 DVFS_ERR("%s: can not get dvfs clk(%s)\n", __func__, clk->name);\r
292                 return -1;\r
293 \r
294         }\r
295 \r
296         if (dvfs_clk->vd && dvfs_clk->vd->vd_dvfs_target){\r
297                 mutex_lock(&rk_dvfs_mutex);\r
298                 /* To reset dvfs_clk->min_rate/max_rate */\r
299                 dvfs_set_freq_volt_table(clk, dvfs_clk->dvfs_table);\r
300 \r
301                 dvfs_clk->freq_limit_en = 0;\r
302                 ret = dvfs_clk->vd->vd_dvfs_target(clk, clk->last_set_rate);\r
303 \r
304                 mutex_unlock(&rk_dvfs_mutex);\r
305         }\r
306 \r
307         DVFS_DBG("%s: clk(%s) last_set_rate=%d; [min_rate, max_rate]=[%d, %d]\n",\r
308                         __func__, clk->name, clk->last_set_rate, dvfs_clk->min_rate, dvfs_clk->max_rate);\r
309         return 0;\r
310 }\r
311 \r
312 int dvfs_vd_clk_set_rate(struct clk *clk, unsigned long rate)\r
313 {\r
314         int ret = -1;\r
315         struct clk_node *dvfs_info=clk_get_dvfs_info(clk);\r
316         \r
317         DVFS_DBG("%s(%s(%lu))\n", __func__, dvfs_info->name, rate);\r
318 \r
319         #if 0 // judge by reference func in rk\r
320         if (dvfs_support_clk_set_rate(dvfs_info)==false) {\r
321                 DVFS_ERR("dvfs func:%s is not support!\n", __func__);\r
322                 return ret;\r
323         }\r
324         #endif\r
325         \r
326         if(dvfs_info->vd&&dvfs_info->vd->vd_dvfs_target){\r
327                 // mutex_lock(&vd->dvfs_mutex);\r
328                 mutex_lock(&rk_dvfs_mutex);\r
329                 ret = dvfs_info->vd->vd_dvfs_target(clk, rate);\r
330                 mutex_unlock(&rk_dvfs_mutex);\r
331                 // mutex_unlock(&vd->dvfs_mutex);\r
332         }\r
333         else\r
334         {\r
335                 DVFS_WARNING("%s(%s),vd is no target callback\n", __func__, clk->name); \r
336                 return -1;\r
337         }\r
338         DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);\r
339         return ret;\r
340 }\r
341 EXPORT_SYMBOL(dvfs_vd_clk_set_rate);\r
342 \r
343 int dvfs_vd_clk_disable(struct clk *clk, int on)\r
344 {\r
345         int ret = -1;\r
346         struct clk_node *dvfs_info=clk_get_dvfs_info(clk);      \r
347         DVFS_DBG("%s(%s(%s,%lu))\n", __func__, dvfs_info->name, DVFS_STR_DISABLE(on),clk_get_rate(clk));\r
348 \r
349 \r
350         #if 0 // judge by reference func in rk\r
351         if (dvfs_support_clk_disable(dvfs_info)==false) {\r
352                 DVFS_ERR("dvfs func:%s is not support!\n", __func__);\r
353                 return ret;\r
354         }\r
355         #endif\r
356         \r
357         if(dvfs_info->vd&&dvfs_info->vd->vd_clk_disable_target){\r
358                 // mutex_lock(&vd->dvfs_mutex);\r
359                 mutex_lock(&rk_dvfs_mutex);\r
360                 ret = dvfs_info->vd->vd_clk_disable_target(clk, on);\r
361                 mutex_unlock(&rk_dvfs_mutex);\r
362                 // mutex_unlock(&vd->dvfs_mutex);\r
363         }\r
364         else\r
365         {\r
366                 DVFS_WARNING("%s(%s),vd is no target callback\n", __func__, clk->name); \r
367                 return -1;\r
368         }\r
369         DVFS_DBG("%s(%s(%s)),is end\n", __func__, dvfs_info->name, DVFS_STR_DISABLE(on));\r
370 \r
371         return ret;\r
372 }\r
373 \r
374 EXPORT_SYMBOL(dvfs_vd_clk_disable);\r
375 \r
376 static void dvfs_table_round_clk_rate(struct clk_node  *dvfs_clk)\r
377 {\r
378         int i;\r
379         unsigned long temp_rate;\r
380         int rate;\r
381         int flags;\r
382         \r
383         if(!dvfs_clk->dvfs_table||dvfs_clk->clk==NULL||is_suport_round_rate(dvfs_clk->clk)<0)\r
384                 return;\r
385         \r
386         mutex_lock(&mutex);\r
387         for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
388                 //ddr rate = real rate+flags\r
389                 flags=dvfs_clk->dvfs_table[i].frequency%1000;\r
390                 rate=(dvfs_clk->dvfs_table[i].frequency/1000)*1000;\r
391                 temp_rate=clk_round_rate(dvfs_clk->clk,rate*1000);\r
392                 if(temp_rate<=0)\r
393                 {       \r
394                         DVFS_WARNING("clk %s:round_clk_rate : is %d,but round <=0",dvfs_clk->name,dvfs_clk->dvfs_table[i].frequency);\r
395                         break;\r
396                 }\r
397                 \r
398                 /* Set rate unit as MHZ */\r
399                 if (temp_rate % MHz != 0)\r
400                         temp_rate = (temp_rate / MHz + 1) * MHz;\r
401 \r
402                 temp_rate = (temp_rate / 1000) + flags;\r
403                 \r
404                 DVFS_DBG("clk %s round_clk_rate %d to %d\n",\r
405                         dvfs_clk->name,dvfs_clk->dvfs_table[i].frequency,(int)(temp_rate));\r
406                 \r
407                 dvfs_clk->dvfs_table[i].frequency=temp_rate;            \r
408         }\r
409         mutex_unlock(&mutex);\r
410 }\r
411 \r
412 /***************************************************************************************************/\r
413 static int dvfs_clk_get_ref_volt_depend(struct depend_list *depend, int rate_khz,\r
414                 struct cpufreq_frequency_table *clk_fv)\r
415 {\r
416         int i = 0;\r
417         if (rate_khz == 0 || !depend || !depend->dep_table) {\r
418                 return -1;\r
419         }\r
420         clk_fv->frequency = rate_khz;\r
421         clk_fv->index = 0;\r
422 \r
423         for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
424                 if (depend->dep_table[i].frequency >= rate_khz) {\r
425                         clk_fv->frequency = depend->dep_table[i].frequency;\r
426                         clk_fv->index = depend->dep_table[i].index;\r
427                         return 0;\r
428                 }\r
429         }\r
430         clk_fv->frequency = 0;\r
431         clk_fv->index = 0;\r
432         return -1;\r
433 }\r
434 int dvfs_clk_get_ref_volt(struct clk_node *dvfs_clk, int rate_khz,\r
435                 struct cpufreq_frequency_table *clk_fv)\r
436 {\r
437         int i = 0;\r
438         if (rate_khz == 0 || !dvfs_clk || !dvfs_clk->dvfs_table) {\r
439                 /* since no need */\r
440                 return -1;\r
441         }\r
442         clk_fv->frequency = rate_khz;\r
443         clk_fv->index = 0;\r
444 \r
445         for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
446                 if (dvfs_clk->dvfs_table[i].frequency >= rate_khz) {\r
447                         clk_fv->frequency = dvfs_clk->dvfs_table[i].frequency;\r
448                         clk_fv->index = dvfs_clk->dvfs_table[i].index;\r
449                         // DVFS_DBG("%s,%s rate=%ukhz(vol=%d)\n",__func__,dvfs_clk->name,\r
450                         // clk_fv->frequency, clk_fv->index);\r
451                         return 0;\r
452                 }\r
453         }\r
454         clk_fv->frequency = 0;\r
455         clk_fv->index = 0;\r
456         // DVFS_DBG("%s get corresponding voltage error! out of bound\n", dvfs_clk->name);\r
457         return -1;\r
458 }\r
459 \r
460 static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct clk_node *dvfs_clk)\r
461 {\r
462         struct clk_list *child;\r
463         int volt_max = 0;\r
464 \r
465         if (!pd || !dvfs_clk)\r
466                 return 0;\r
467 \r
468         if (dvfs_clk->set_volt >= pd->cur_volt) {\r
469                 return dvfs_clk->set_volt;\r
470         }\r
471 \r
472         list_for_each_entry(child, &pd->clk_list, node) {\r
473                 // DVFS_DBG("%s ,pd(%s),dvfs(%s),volt(%u)\n",__func__,pd->name,\r
474                 // dvfs_clk->name,dvfs_clk->set_volt);\r
475                 volt_max = max(volt_max, child->dvfs_clk->set_volt);\r
476         }\r
477         return volt_max;\r
478 }\r
479 \r
480 void dvfs_update_clk_pds_volt(struct clk_node *dvfs_clk)\r
481 {\r
482         struct pd_node   *pd;\r
483         int i;\r
484         if (!dvfs_clk)\r
485                 return;\r
486         for (i = 0; (dvfs_clk->pds[i].pd != NULL); i++) {\r
487                 pd = dvfs_clk->pds[i].pd;\r
488                 // DVFS_DBG("%s dvfs(%s),pd(%s)\n",__func__,dvfs_clk->name,pd->name);\r
489                 pd->cur_volt = dvfs_pd_get_newvolt_byclk(pd, dvfs_clk);\r
490         }\r
491 }\r
492 \r
493 int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)\r
494 {\r
495         struct pd_node          *pd;\r
496         struct depend_list      *depend;\r
497         int     volt_max_vd = 0;\r
498         list_for_each_entry(pd, &vd->pd_list, node) {\r
499                 // DVFS_DBG("%s pd(%s,%u)\n",__func__,pd->name,pd->cur_volt);\r
500                 volt_max_vd = max(volt_max_vd, pd->cur_volt);\r
501         }\r
502 \r
503         /* some clks depend on this voltage domain */\r
504         if (!list_empty(&vd->req_volt_list)) {\r
505                 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {\r
506                         volt_max_vd = max(volt_max_vd, depend->req_volt);\r
507                 }\r
508         }\r
509         return volt_max_vd;\r
510 }\r
511 \r
512 int dvfs_vd_get_newvolt_byclk(struct clk_node *dvfs_clk)\r
513 {\r
514         if (!dvfs_clk)\r
515                 return -1;\r
516         dvfs_update_clk_pds_volt(dvfs_clk);\r
517         return  dvfs_vd_get_newvolt_bypd(dvfs_clk->vd);\r
518 }\r
519 \r
520 void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target)\r
521 {\r
522         struct clk_node *dvfs_clk = clk_get_dvfs_info(clk);\r
523         if (IS_ERR_OR_NULL(dvfs_clk)) {\r
524                 DVFS_ERR("%s %s get dvfs_clk err\n", __func__, clk->name);\r
525                 return ;\r
526         }\r
527         dvfs_clk->clk_dvfs_target = clk_dvfs_target;\r
528 }\r
529 \r
530 /************************************************ freq volt table************************************/\r
531 struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk) \r
532 {\r
533         struct clk_node *info = clk_get_dvfs_info(clk);\r
534         struct cpufreq_frequency_table *table;\r
535         if (!info || !info->dvfs_table) {\r
536                 return NULL;\r
537         }\r
538         mutex_lock(&mutex);\r
539         table = info->dvfs_table;\r
540         mutex_unlock(&mutex);\r
541         return table;\r
542 }\r
543 EXPORT_SYMBOL(dvfs_get_freq_volt_table);\r
544 \r
545 int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table)\r
546 {\r
547         struct clk_node *info = clk_get_dvfs_info(clk);\r
548         int i=0;\r
549 \r
550         if (!info)\r
551                 return -1;      \r
552         if (!table)\r
553         {               \r
554                 info->min_rate=0;       \r
555                 info->max_rate=0;       \r
556                 return -1;\r
557         }\r
558 \r
559         mutex_lock(&mutex);\r
560         info->dvfs_table = table;\r
561         if(table[0].frequency!= CPUFREQ_TABLE_END)\r
562         {\r
563 \r
564                 info->min_rate=(table[0].frequency/1000)*1000*1000;//to hz\r
565         }\r
566         else\r
567         {\r
568                 info->min_rate=0;       \r
569                 info->max_rate=0;       \r
570                 mutex_unlock(&mutex);\r
571                 return -1;\r
572         }\r
573 \r
574         for(i=0;table[i].frequency!= CPUFREQ_TABLE_END;i++)\r
575         {\r
576         \r
577         }       \r
578         info->max_rate=(table[i-1].frequency/1000)*1000*1000;\r
579 \r
580         DVFS_DBG("%s,clk %s,limit max=%lu,min=%lu\n",__FUNCTION__,info->name,info->max_rate,info->min_rate);\r
581 \r
582         mutex_unlock(&mutex);\r
583         dvfs_table_round_clk_rate(info);\r
584         dvfs_table_round_volt(info);\r
585         return 0;\r
586 }\r
587 EXPORT_SYMBOL(dvfs_set_freq_volt_table);\r
588 \r
589 int dvfs_set_depend_table(struct clk *clk, char *vd_name, struct cpufreq_frequency_table *table)\r
590 {\r
591         struct vd_node          *vd;\r
592         struct depend_list      *depend;\r
593         struct clk_node         *info;\r
594 \r
595         info = clk_get_dvfs_info(clk);\r
596         if (!table || !info || !vd_name) {\r
597                 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! table or info or name empty\n", __func__);\r
598                 return -1;\r
599         }\r
600 \r
601         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
602                 if (0 == strcmp(vd->name, vd_name)) {\r
603                         DVFS_DBG("FOUND A MATCH\n");\r
604                         mutex_lock(&mutex);\r
605                         list_for_each_entry(depend, &info->depend_list, node2clk) {\r
606                                 if (vd == depend->dep_vd && info == depend->dvfs_clk) {\r
607                                         depend->dep_table = table;\r
608                                         break;\r
609                                 }\r
610                         }\r
611                         mutex_unlock(&mutex);\r
612                         return 0;\r
613                 }\r
614         }\r
615         DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! can not find vd:%s\n", __func__, vd_name);\r
616 \r
617         return 0;\r
618 }\r
619 \r
620 int dvfs_set_arm_logic_volt(struct dvfs_arm_table *dvfs_cpu_logic_table,\r
621                 struct cpufreq_frequency_table *cpu_dvfs_table,\r
622                 struct cpufreq_frequency_table *dep_cpu2core_table)\r
623 {\r
624         int i = 0;\r
625         for (i = 0; dvfs_cpu_logic_table[i].frequency != CPUFREQ_TABLE_END; i++) {\r
626                 cpu_dvfs_table[i].frequency = dvfs_cpu_logic_table[i].frequency;\r
627                 cpu_dvfs_table[i].index = dvfs_cpu_logic_table[i].cpu_volt;\r
628 \r
629                 dep_cpu2core_table[i].frequency = dvfs_cpu_logic_table[i].frequency;\r
630                 dep_cpu2core_table[i].index = dvfs_cpu_logic_table[i].logic_volt;\r
631         }\r
632 \r
633         cpu_dvfs_table[i].frequency = CPUFREQ_TABLE_END;\r
634         dep_cpu2core_table[i].frequency = CPUFREQ_TABLE_END;\r
635 \r
636         dvfs_set_freq_volt_table(clk_get(NULL, "cpu"), cpu_dvfs_table);\r
637         dvfs_set_depend_table(clk_get(NULL, "cpu"), "vd_core", dep_cpu2core_table);\r
638         return 0;\r
639 }\r
640 \r
641 \r
642 int clk_enable_dvfs(struct clk *clk)\r
643 {\r
644         struct clk_node *dvfs_clk;\r
645         struct cpufreq_frequency_table clk_fv;\r
646         if (!clk) {\r
647                 DVFS_ERR("clk enable dvfs error\n");\r
648                 return -1;\r
649         }\r
650         dvfs_clk = clk_get_dvfs_info(clk);\r
651         if (!dvfs_clk || !dvfs_clk->vd) {\r
652                 DVFS_ERR("%s clk(%s) not support dvfs!\n", __func__, clk->name);\r
653                 return -1;\r
654         }\r
655         if (dvfs_clk->enable_dvfs == 0) {\r
656 \r
657                 if (IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {\r
658                         //regulator = NULL;\r
659                         if (dvfs_clk->vd->regulator_name)\r
660                                 dvfs_clk->vd->regulator = dvfs_regulator_get(NULL, dvfs_clk->vd->regulator_name);\r
661                         if (!IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {\r
662                                 // DVFS_DBG("dvfs_regulator_get(%s)\n",dvfs_clk->vd->regulator_name);\r
663                                 clk_enable_dvfs_regulator_check(dvfs_clk->vd);\r
664                                 dvfs_get_vd_regulator_volt_list(dvfs_clk->vd);\r
665                                 dvfs_vd_get_regulator_volt_time_info(dvfs_clk->vd);\r
666                                 //dvfs_vd_get_regulator_mode_info(dvfs_clk->vd);\r
667                         } else {\r
668                                 //dvfs_clk->vd->regulator = NULL;\r
669                                 dvfs_clk->enable_dvfs = 0;\r
670                                 DVFS_ERR("%s can't get regulator in %s\n", dvfs_clk->name, __func__);\r
671                                 return -1;\r
672                         }\r
673                 } else {\r
674                              clk_enable_dvfs_regulator_check(dvfs_clk->vd);\r
675                         // DVFS_DBG("%s(%s) vd volt=%u\n",__func__,dvfs_clk->name,dvfs_clk->vd->cur_volt);\r
676                 }\r
677 \r
678                 dvfs_table_round_clk_rate(dvfs_clk);\r
679                 dvfs_table_round_volt(dvfs_clk);\r
680                 dvfs_clk->set_freq = dvfs_clk_get_rate_kz(clk);\r
681                 // DVFS_DBG("%s ,%s get freq%u!\n",__func__,dvfs_clk->name,dvfs_clk->set_freq);\r
682 \r
683                 if (dvfs_clk_get_ref_volt(dvfs_clk, dvfs_clk->set_freq, &clk_fv)) {\r
684                         if (dvfs_clk->dvfs_table[0].frequency == CPUFREQ_TABLE_END) {\r
685                                 DVFS_ERR("%s table empty\n", __func__);\r
686                                 dvfs_clk->enable_dvfs = 0;\r
687                                 return -1;\r
688                         } else {\r
689                                 DVFS_WARNING("%s table all value are smaller than default, use default, just enable dvfs\n", __func__);\r
690                                 dvfs_clk->enable_dvfs++;\r
691                                 return 0;\r
692                         }\r
693                 }\r
694 \r
695                 dvfs_clk->set_volt = clk_fv.index;\r
696                 dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
697                 // DVFS_DBG("%s,%s,freq%u(ref vol %u)\n",__func__,dvfs_clk->name,\r
698                 //       dvfs_clk->set_freq,dvfs_clk->set_volt);\r
699 #if 0\r
700                 if (dvfs_clk->dvfs_nb) {\r
701                         // must unregister when clk disable\r
702                         clk_notifier_register(clk, dvfs_clk->dvfs_nb);\r
703                 }\r
704 #endif\r
705 \r
706 #if 0\r
707                 if(dvfs_clk->vd->cur_volt < dvfs_clk->set_volt) {\r
708                         int ret;\r
709                         mutex_lock(&rk_dvfs_mutex);\r
710                         ret = dvfs_regulator_set_voltage_readback(dvfs_clk->vd->regulator, dvfs_clk->set_volt, dvfs_clk->set_volt);\r
711                         if (ret < 0) {\r
712                                 dvfs_clk->vd->volt_set_flag = DVFS_SET_VOLT_FAILURE;\r
713                                 dvfs_clk->enable_dvfs = 0;\r
714                                 DVFS_ERR("dvfs enable clk %s,set volt error \n", dvfs_clk->name);\r
715                                 mutex_unlock(&rk_dvfs_mutex);\r
716                                 return -1;\r
717                         }\r
718                         dvfs_clk->vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;\r
719                         mutex_unlock(&rk_dvfs_mutex);\r
720                 }\r
721 #endif\r
722                 dvfs_clk->enable_dvfs++;\r
723         } else {\r
724                 DVFS_ERR("dvfs already enable clk enable = %d!\n", dvfs_clk->enable_dvfs);\r
725                 dvfs_clk->enable_dvfs++;\r
726         }\r
727         return 0;\r
728 }\r
729 \r
730 int clk_disable_dvfs(struct clk *clk)\r
731 {\r
732         struct clk_node *dvfs_clk;\r
733         dvfs_clk = clk->dvfs_info;\r
734         if (!dvfs_clk->enable_dvfs) {\r
735                 DVFS_DBG("clk is already closed!\n");\r
736                 return -1;\r
737         } else {\r
738                 dvfs_clk->enable_dvfs--;\r
739                 if (0 == dvfs_clk->enable_dvfs) {\r
740                         DVFS_ERR("clk closed!\n");\r
741 #if 0\r
742                         clk_notifier_unregister(clk, dvfs_clk->dvfs_nb);\r
743                         DVFS_DBG("clk unregister nb!\n");\r
744 #endif\r
745                 }\r
746         }\r
747         return 0;\r
748 }\r
749 struct clk_node *dvfs_get_dvfs_clk_byname(char *name) \r
750 {\r
751         struct vd_node *vd;\r
752         struct pd_node *pd;\r
753         struct clk_list *child;\r
754         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
755                 list_for_each_entry(pd, &vd->pd_list, node) {\r
756                         list_for_each_entry(child, &pd->clk_list, node) {\r
757                                 if (0 == strcmp(child->dvfs_clk->name, name)) {\r
758                                         return child->dvfs_clk;\r
759                                 }\r
760                         }\r
761                 }\r
762         }\r
763         return NULL;\r
764 }\r
765 int rk_regist_vd(struct vd_node *vd)\r
766 {\r
767         if (!vd)\r
768                 return -1;\r
769         mutex_lock(&mutex);\r
770         //mutex_init(&vd->dvfs_mutex);\r
771         list_add(&vd->node, &rk_dvfs_tree);\r
772         INIT_LIST_HEAD(&vd->pd_list);\r
773         INIT_LIST_HEAD(&vd->req_volt_list);\r
774         vd->mode_flag=0;\r
775         vd->volt_time_flag=0;\r
776         vd->n_voltages=0;\r
777         mutex_unlock(&mutex);\r
778         return 0;\r
779 }\r
780 \r
781 int rk_regist_pd(struct pd_node_lookup *pd_lookup)\r
782 {\r
783         struct vd_node  *vd;\r
784         struct pd_node  *pd;\r
785 \r
786         mutex_lock(&mutex);\r
787         pd = pd_lookup->pd;\r
788 \r
789         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
790                 if (vd == pd->vd) {\r
791                         list_add(&pd->node, &vd->pd_list);\r
792                         INIT_LIST_HEAD(&pd->clk_list);\r
793                         break;\r
794                 }\r
795         }\r
796         mutex_unlock(&mutex);\r
797         return 0;\r
798 }\r
799 \r
800 int rk_regist_clk(struct clk_node *dvfs_clk)\r
801 {\r
802         struct pd_node  *pd;\r
803         struct clk_list *child;\r
804         struct clk      *clk;\r
805         int i = 0;\r
806 \r
807         if (!dvfs_clk)\r
808                 return -1;\r
809 \r
810         if (!dvfs_clk->pds)\r
811                 return -1;\r
812         mutex_lock(&mutex);\r
813         dvfs_clk->enable_dvfs = 0;\r
814         dvfs_clk->vd = dvfs_clk->pds[0].pd->vd;\r
815         for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {\r
816                 child = &(dvfs_clk->pds[i].clk_list);\r
817                 child->dvfs_clk = dvfs_clk;\r
818                 pd = dvfs_clk->pds[i].pd;\r
819                 list_add(&child->node, &pd->clk_list);\r
820         }\r
821         clk = dvfs_clk_get(NULL, dvfs_clk->name);\r
822         dvfs_clk->clk = clk;\r
823         clk_register_dvfs(dvfs_clk, clk);\r
824         INIT_LIST_HEAD(&dvfs_clk->depend_list);\r
825         mutex_unlock(&mutex);\r
826         return 0;\r
827 }\r
828 \r
829 int rk_regist_depends(struct depend_lookup *dep_node)\r
830 {\r
831         struct depend_list      *depend_list;\r
832         struct clk_node         *dvfs_clk;\r
833 \r
834         if (!dep_node) {\r
835                 DVFS_ERR("%s : DVFS BAD depend node!\n", __func__);\r
836                 return -1;\r
837         }\r
838 \r
839         if (!dep_node->clk_name || !dep_node->dep_vd) {\r
840                 DVFS_ERR("%s : DVFS BAD depend members!\n", __func__);\r
841                 return -1;\r
842         }\r
843 \r
844         depend_list = &dep_node->dep_list;\r
845         dvfs_clk = dvfs_get_dvfs_clk_byname(dep_node->clk_name);\r
846 \r
847         mutex_lock(&mutex);\r
848 \r
849         depend_list->dvfs_clk = dvfs_clk;\r
850         depend_list->dep_vd = dep_node->dep_vd;\r
851         depend_list->dep_table = dep_node->dep_table;\r
852 \r
853         list_add(&depend_list->node2clk, &dvfs_clk->depend_list);\r
854         list_add(&depend_list->node2vd, &depend_list->dep_vd->req_volt_list);\r
855 \r
856         mutex_unlock(&mutex);\r
857         return 0;\r
858 }\r
859 \r
860 int correct_volt(int *volt_clk, int *volt_dep, int clk_biger_than_dep, int dep_biger_than_clk)\r
861 {\r
862         int up_boundary = 0, low_boundary = 0;\r
863 \r
864         up_boundary = *volt_clk + dep_biger_than_clk;\r
865         low_boundary = *volt_clk - clk_biger_than_dep;\r
866 \r
867         if (*volt_dep < low_boundary || *volt_dep > up_boundary) {\r
868 \r
869                 if (*volt_dep < low_boundary) {\r
870                         *volt_dep = low_boundary;\r
871 \r
872                 } else if (*volt_dep > up_boundary) {\r
873                         *volt_clk = *volt_dep - dep_biger_than_clk;\r
874                 }\r
875         }\r
876 \r
877         return 0;\r
878 }\r
879 \r
880 int dvfs_scale_volt(struct vd_node *vd_clk, struct vd_node *vd_dep,\r
881                 int volt_old, int volt_new, int volt_dep_old, int volt_dep_new, int clk_biger_than_dep, int dep_biger_than_clk)\r
882 {\r
883         struct regulator *regulator, *regulator_dep;\r
884         int volt = 0, volt_dep = 0, step = 0, step_dep = 0;\r
885         int volt_tmp = 0, volt_dep_tmp = 0;\r
886         int volt_pre = 0, volt_dep_pre = 0;\r
887         int ret = 0;\r
888 \r
889         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);\r
890         regulator = vd_clk->regulator;\r
891         regulator_dep = vd_dep->regulator;\r
892 \r
893         if (IS_ERR_OR_NULL(regulator) || IS_ERR(regulator_dep)) {\r
894                 DVFS_ERR("%s dvfs_clk->vd->regulator or depend->dep_vd->regulator == NULL\n", __func__);\r
895                 return -1;\r
896         }\r
897 \r
898         volt = volt_old;\r
899         volt_dep = volt_dep_old;\r
900 \r
901         step = volt_new - volt_old > 0 ? 1 : (-1);\r
902         step_dep = volt_dep_new - volt_dep_old > 0 ? 1 : (-1);\r
903 \r
904         DVFS_DBG("step=%d step_dep=%d %d\n", step, step_dep, step * step_dep);\r
905 \r
906         DVFS_DBG("Volt_new=%d(old=%d), volt_dep_new=%d(dep_old=%d)\n",\r
907                         volt_new, volt_old, volt_dep_new, volt_dep_old);\r
908         do {\r
909                 volt_pre = volt;\r
910                 volt_dep_pre = volt_dep;\r
911                 if (step * step_dep < 0) {\r
912                         // target is between volt_old and volt_dep_old, just\r
913                         // need one step\r
914                         DVFS_DBG("step * step_dep < 0\n");\r
915                         volt = volt_new;\r
916                         volt_dep = volt_dep_new;\r
917 \r
918                 } else if (step > 0) {\r
919                         // up voltage\r
920                         DVFS_DBG("step > 0\n");\r
921                         volt_tmp = volt_dep + clk_biger_than_dep;\r
922                         volt_dep_tmp = volt + dep_biger_than_clk;\r
923 \r
924                         volt = volt_tmp > volt_new ? volt_new : volt_tmp;\r
925                         volt_dep = volt_dep_tmp > volt_dep_new ? volt_dep_new : volt_dep_tmp;\r
926 \r
927                 } else if (step < 0) {\r
928                         // down voltage\r
929                         DVFS_DBG("step < 0\n");\r
930 \r
931                         volt_tmp = volt_dep - dep_biger_than_clk;\r
932                         volt_dep_tmp = volt - clk_biger_than_dep;\r
933 \r
934                         volt = volt_tmp < volt_new ? volt_new : volt_tmp;\r
935                         volt_dep = volt_dep_tmp < volt_dep_new ? volt_dep_new : volt_dep_tmp;\r
936 \r
937                 } else {\r
938                         DVFS_ERR("Oops, some bugs here:Volt_new=%d(old=%d), volt_dep_new=%d(dep_old=%d)\n",\r
939                                         volt_new, volt_old, volt_dep_new, volt_dep_old);\r
940                         goto fail;\r
941                 }\r
942 \r
943                 if (vd_clk->cur_volt != volt) {\r
944                         DVFS_DBG("\t\t%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt);\r
945                         ret = dvfs_regulator_set_voltage_readback(regulator, volt, volt);\r
946                         //udelay(get_volt_up_delay(volt, volt_pre));\r
947                         dvfs_volt_up_delay(vd_clk,volt, volt_pre);\r
948                         if (ret < 0) {\r
949                                 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",\r
950                                                 __func__, vd_clk->name, ret, volt_new, volt_old);\r
951                                 goto fail;\r
952                         }\r
953                         vd_clk->cur_volt = volt;\r
954                 }\r
955                 if (vd_dep->cur_volt != volt_dep) {\r
956                         DVFS_DBG("\t\t%s:%d->%d\n", vd_dep->name, vd_dep->cur_volt, volt_dep);\r
957                         ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep, volt_dep);\r
958                         //udelay(get_volt_up_delay(volt_dep, volt_dep_pre));\r
959                         dvfs_volt_up_delay(vd_dep,volt_dep, volt_dep_pre);\r
960                         if (ret < 0) {\r
961                                 DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",\r
962                                                 __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);\r
963                                 goto fail;\r
964                         }\r
965                         vd_dep->cur_volt = volt_dep;\r
966                 }\r
967 \r
968                 DVFS_DBG("\t\tNOW:Volt=%d, volt_dep=%d\n", volt, volt_dep);\r
969 \r
970         } while (volt != volt_new || volt_dep != volt_dep_new);\r
971 \r
972         vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;\r
973         vd_clk->cur_volt = volt_new;\r
974 \r
975         return 0;\r
976 fail:\r
977         DVFS_ERR("+++++++++++++++++FAIL AREA\n");\r
978         vd_clk->cur_volt = volt_old;\r
979         vd_dep->cur_volt = volt_dep_old;\r
980         vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;\r
981         ret = dvfs_regulator_set_voltage_readback(regulator, volt_old, volt_old);\r
982         if (ret < 0) {\r
983                 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;\r
984                 DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",\r
985                                 __func__, vd_clk->name, ret, volt_new, volt_old);\r
986         }\r
987 \r
988         ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_old, volt_dep_old);\r
989         if (ret < 0) {\r
990                 vd_dep->volt_set_flag = DVFS_SET_VOLT_FAILURE;\r
991                 DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",\r
992                                 __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);\r
993         }\r
994 \r
995         return -1;\r
996 }\r
997 \r
998 int dvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new)\r
999 {\r
1000         int ret = 0;\r
1001         DVFS_DBG("ENTER %s, volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);\r
1002         if (IS_ERR_OR_NULL(vd_clk)) {\r
1003                 DVFS_ERR("%s vd_node error\n", __func__);\r
1004                 return -1;\r
1005         }\r
1006 \r
1007         DVFS_DBG("ENTER %s, volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);\r
1008         if (!IS_ERR_OR_NULL(vd_clk->regulator)) {\r
1009                 ret = dvfs_regulator_set_voltage_readback(vd_clk->regulator, volt_new, volt_new);\r
1010                 //udelay(get_volt_up_delay(volt_new, vd_clk->cur_volt));\r
1011                 dvfs_volt_up_delay(vd_clk,volt_new, vd_clk->cur_volt);\r
1012                 if (ret < 0) {\r
1013                         vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;\r
1014                         DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",\r
1015                                         __func__, vd_clk->name, ret, volt_new, vd_clk->cur_volt);\r
1016                         return -1;\r
1017                 }\r
1018 \r
1019         } else {\r
1020                 DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
1021                 return -1;\r
1022         }\r
1023 \r
1024         vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;\r
1025         vd_clk->cur_volt = volt_new;\r
1026 \r
1027         return 0;\r
1028 \r
1029 }\r
1030 \r
1031 int dvfs_scale_volt_bystep(struct vd_node *vd_clk, struct vd_node *vd_dep, int volt_new, int volt_dep_new,\r
1032                 int cur_clk_biger_than_dep, int cur_dep_biger_than_clk, int new_clk_biger_than_dep, int new_dep_biger_than_clk)\r
1033 {\r
1034 \r
1035         struct regulator *regulator, *regulator_dep;\r
1036         int volt_new_corrected = 0, volt_dep_new_corrected = 0;\r
1037         int volt_old = 0, volt_dep_old = 0;\r
1038         int ret = 0;\r
1039 \r
1040         volt_old = vd_clk->cur_volt;\r
1041         volt_dep_old = vd_dep->cur_volt;\r
1042 \r
1043         DVFS_DBG("ENTER %s, volt=%d(old=%d) vd_dep=%d(dep_old=%d)\n", __func__,\r
1044                         volt_new, volt_old, volt_dep_new, volt_dep_old);\r
1045         DVFS_DBG("ENTER %s, VOLT_DIFF: clk_cur=%d(clk_new=%d) dep_cur=%d(dep_new=%d)\n", __func__,\r
1046                         cur_clk_biger_than_dep, new_clk_biger_than_dep, \r
1047                         cur_dep_biger_than_clk, new_dep_biger_than_clk);\r
1048 \r
1049         volt_new_corrected = volt_new;\r
1050         volt_dep_new_corrected = volt_dep_new;\r
1051         correct_volt(&volt_new_corrected, &volt_dep_new_corrected, cur_clk_biger_than_dep, cur_dep_biger_than_clk);\r
1052         ret = dvfs_scale_volt(vd_clk, vd_dep, volt_old, volt_new_corrected, volt_dep_old, volt_dep_new_corrected,\r
1053                         cur_clk_biger_than_dep, cur_dep_biger_than_clk);\r
1054         if (ret < 0) {\r
1055                 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;\r
1056                 DVFS_ERR("set volt error\n");\r
1057                 return -1;\r
1058         }\r
1059 \r
1060         if (cur_clk_biger_than_dep != new_clk_biger_than_dep || cur_dep_biger_than_clk != new_dep_biger_than_clk) {\r
1061                 regulator = vd_clk->regulator;\r
1062                 regulator_dep = vd_dep->regulator;\r
1063 \r
1064                 volt_new_corrected = volt_new;\r
1065                 volt_dep_new_corrected = volt_dep_new;\r
1066                 correct_volt(&volt_new_corrected, &volt_dep_new_corrected, new_clk_biger_than_dep, new_dep_biger_than_clk);\r
1067 \r
1068                 if (vd_clk->cur_volt != volt_new_corrected) {\r
1069                         DVFS_DBG("%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt_new_corrected);\r
1070                         ret = dvfs_regulator_set_voltage_readback(regulator, volt_new_corrected, volt_new_corrected);\r
1071                         //udelay(get_volt_up_delay(volt_new_corrected, vd_clk->cur_volt));\r
1072                         dvfs_volt_up_delay(vd_clk,volt_new_corrected, vd_clk->cur_volt);\r
1073                         if (ret < 0) {\r
1074                                 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",\r
1075                                                 __func__, vd_clk->name, ret, volt_new_corrected, vd_clk->cur_volt);\r
1076                                 return -1;\r
1077                         }\r
1078                         vd_clk->cur_volt = volt_new_corrected;\r
1079                 }\r
1080                 if (vd_dep->cur_volt != volt_dep_new_corrected) {\r
1081                         DVFS_DBG("%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt_dep_new_corrected);\r
1082                         ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_new_corrected, volt_dep_new_corrected);\r
1083                         //udelay(get_volt_up_delay(volt_dep_new_corrected, vd_dep->cur_volt));\r
1084                         dvfs_volt_up_delay(vd_dep,volt_dep_new_corrected, vd_dep->cur_volt);\r
1085                         if (ret < 0) {\r
1086                                 DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",\r
1087                                                 __func__, vd_dep->name, ret, volt_dep_new_corrected, vd_dep->cur_volt);\r
1088                                 return -1;\r
1089                         }\r
1090                         vd_dep->cur_volt = volt_dep_new_corrected;\r
1091                 }\r
1092         }\r
1093 \r
1094         return 0;\r
1095 }\r
1096 \r
1097 int dvfs_reset_volt(struct vd_node *dvfs_vd)\r
1098 {\r
1099         int flag_set_volt_correct = 0;\r
1100         if (!IS_ERR_OR_NULL(dvfs_vd->regulator))\r
1101                 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_vd->regulator);\r
1102         else {\r
1103                 DVFS_ERR("dvfs regulator is ERROR\n");\r
1104                 return -1;\r
1105         }\r
1106         if (flag_set_volt_correct <= 0) {\r
1107                 DVFS_ERR("%s (vd:%s), try to reload volt ,by it is error again(%d)!!! stop scaling\n",\r
1108                                 __func__, dvfs_vd->name, flag_set_volt_correct);\r
1109                 return -1;\r
1110         }\r
1111         dvfs_vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;\r
1112         DVFS_WARNING("%s (vd:%s), try to reload volt = %d\n",\r
1113                         __func__, dvfs_vd->name, flag_set_volt_correct);\r
1114 \r
1115         /* Reset vd's voltage */\r
1116         dvfs_vd->cur_volt = flag_set_volt_correct;\r
1117 \r
1118         return dvfs_vd->cur_volt;\r
1119 }\r
1120 \r
1121 int dvfs_get_depend_volt(struct clk_node *dvfs_clk, struct vd_node *dvfs_vd_dep, int rate_new)\r
1122 {\r
1123         struct depend_list      *depend;\r
1124         struct cpufreq_frequency_table clk_fv_dep;\r
1125         int ret = 0;\r
1126 \r
1127         DVFS_DBG("ENTER %s, rate_new=%d\n", __func__, rate_new);\r
1128         list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {\r
1129                 DVFS_DBG("--round depend clk:%s(depend:%s)\n", depend->dvfs_clk->name, depend->dep_vd->name);\r
1130                 // this place just consider ONE depend voltage domain,\r
1131                 // multi-depends must have some differece\r
1132                 clk_fv_dep.index = 0;\r
1133                 if (depend->dep_vd == dvfs_vd_dep) {\r
1134                         ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv_dep);\r
1135                         if (ret < 0) {\r
1136                                 DVFS_ERR("%s get dvfs_ref_volt_depend error\n", __func__);\r
1137                                 return -1;\r
1138                         }\r
1139                         depend->req_volt = clk_fv_dep.index;\r
1140                         return depend->req_volt;\r
1141                 }\r
1142         }\r
1143 \r
1144         DVFS_ERR("%s can not find vd node %s\n", __func__, dvfs_vd_dep->name);\r
1145         return -1;\r
1146 }\r
1147 \r
1148 /**\r
1149  * dump_dbg_map() : Draw all informations of dvfs while debug\r
1150  */\r
1151 static int dump_dbg_map(char *buf)\r
1152 {\r
1153         int i;\r
1154         struct vd_node  *vd;\r
1155         struct pd_node  *pd, *clkparent;\r
1156         struct clk_list *child;\r
1157         struct clk_node *dvfs_clk;\r
1158         struct depend_list *depend;\r
1159         char *s = buf;\r
1160         mutex_lock(&rk_dvfs_mutex);\r
1161 \r
1162         printk( "-------------DVFS TREE-----------\n\n\n");\r
1163         printk( "DVFS TREE:\n");\r
1164         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
1165                 printk( "|\n|- voltage domain:%s\n", vd->name);\r
1166                 printk( "|- current voltage:%d\n", vd->cur_volt);\r
1167                 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {\r
1168                         printk( "|- request voltage:%d, clk:%s\n", depend->req_volt, depend->dvfs_clk->name);\r
1169                 }\r
1170 \r
1171                 list_for_each_entry(pd, &vd->pd_list, node) {\r
1172                         printk( "|  |\n|  |- power domain:%s, status = %s, current volt = %d\n",\r
1173                                         pd->name, (pd->pd_status == PD_ON) ? "ON" : "OFF", pd->cur_volt);\r
1174 \r
1175                         list_for_each_entry(child, &pd->clk_list, node) {\r
1176                                 dvfs_clk = child->dvfs_clk;\r
1177                                 printk( "|  |  |\n|  |  |- clock: %s current: rate %d, volt = %d,"\r
1178                                                 " enable_dvfs = %s\n",\r
1179                                                 dvfs_clk->name, dvfs_clk->set_freq, dvfs_clk->set_volt,\r
1180                                                 dvfs_clk->enable_dvfs == 0 ? "DISABLE" : "ENABLE");\r
1181                                 printk( "|  |  |- clk limit:[%d, %d]; last set rate = %lu\n",\r
1182                                                 dvfs_clk->min_rate, dvfs_clk->max_rate,\r
1183                                                 dvfs_clk->clk->last_set_rate);\r
1184 \r
1185                                 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {\r
1186                                         clkparent = dvfs_clk->pds[i].pd;\r
1187                                         printk( "|  |  |  |- clock parents: %s, vd_parent = %s\n",\r
1188                                                         clkparent->name, clkparent->vd->name);\r
1189                                 }\r
1190 \r
1191                                 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
1192                                         printk( "|  |  |  |- freq = %d, volt = %d\n",\r
1193                                                         dvfs_clk->dvfs_table[i].frequency,\r
1194                                                         dvfs_clk->dvfs_table[i].index);\r
1195 \r
1196                                 }\r
1197 \r
1198                                 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {\r
1199                                         printk( "|  |  |  |  |- DEPEND VD: %s\n", depend->dep_vd->name);\r
1200                                         for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
1201                                                 printk( "|  |  |  |  |- freq = %d, req_volt = %d\n",\r
1202                                                                 depend->dep_table[i].frequency,\r
1203 \r
1204                                                                 depend->dep_table[i].index);\r
1205                                         }\r
1206                                 }\r
1207                         }\r
1208                 }\r
1209         }\r
1210         printk( "-------------DVFS TREE END------------\n");\r
1211         \r
1212         mutex_unlock(&rk_dvfs_mutex);\r
1213         return s - buf;\r
1214 }\r
1215 /*******************************AVS AREA****************************************/\r
1216 /*\r
1217  * To use AVS function, you must call avs_init in machine_rk30_board_init(void)(board-rk30-sdk.c)\r
1218  * And then call(vdd_log):\r
1219  *      regulator_set_voltage(dcdc, 1100000, 1100000);\r
1220  *      avs_init_val_get(1,1100000,"wm8326 init");\r
1221  *      udelay(600);\r
1222  *      avs_set_scal_val(AVS_BASE);\r
1223  * in wm831x_post_init(board-rk30-sdk-wm8326.c)\r
1224  * AVS_BASE can use 172\r
1225  */\r
1226 \r
1227 static struct avs_ctr_st *avs_ctr_data=NULL;\r
1228 #define init_avs_times 10\r
1229 #define init_avs_st_num 5\r
1230 \r
1231 struct init_avs_st {\r
1232         int is_set;\r
1233         u8 paramet[init_avs_times];\r
1234         int vol;\r
1235         char *s;\r
1236 };\r
1237 \r
1238 static struct init_avs_st init_avs_paramet[init_avs_st_num];\r
1239 \r
1240 void avs_board_init(struct avs_ctr_st *data)\r
1241 {\r
1242         \r
1243         avs_ctr_data=data;\r
1244 }\r
1245 void avs_init(void)\r
1246 {\r
1247         memset(&init_avs_paramet[0].is_set, 0, sizeof(init_avs_paramet));\r
1248         if(avs_ctr_data&&avs_ctr_data->avs_init)\r
1249                 avs_ctr_data->avs_init();\r
1250         avs_init_val_get(0, 1200000,"board_init");\r
1251 }\r
1252 static u8 rk_get_avs_val(void)\r
1253 {\r
1254         \r
1255         if(avs_ctr_data&&avs_ctr_data->avs_get_val)\r
1256         {       \r
1257                 return avs_ctr_data->avs_get_val();\r
1258         }\r
1259         return 0;\r
1260 \r
1261 }\r
1262 /******************************int val get**************************************/\r
1263 void avs_init_val_get(int index, int vol, char *s)\r
1264 {\r
1265         int i;\r
1266         if(index >= init_avs_times)\r
1267                 return;\r
1268         init_avs_paramet[index].vol = vol;\r
1269         init_avs_paramet[index].s = s;\r
1270         init_avs_paramet[index].is_set++;\r
1271         printk("DVFS MSG:\tAVS Value(index=%d): ", index);\r
1272         for(i = 0; i < init_avs_times; i++) {\r
1273                 init_avs_paramet[index].paramet[i] = rk_get_avs_val();\r
1274                 mdelay(1);\r
1275                 printk("%d ", init_avs_paramet[index].paramet[i]);\r
1276         }\r
1277         printk("\n");\r
1278 }\r
1279 int avs_set_scal_val(u8 avs_base)\r
1280 {\r
1281         return 0;\r
1282 }\r
1283 \r
1284 /*************************interface to get avs value and dvfs tree*************************/\r
1285 #define USE_NORMAL_TIME\r
1286 #ifdef USE_NORMAL_TIME\r
1287 static struct timer_list avs_timer;\r
1288 #else\r
1289 static struct hrtimer dvfs_hrtimer;\r
1290 #endif\r
1291 \r
1292 static u32 avs_dyn_start = 0;\r
1293 static u32 avs_dyn_data_cnt;\r
1294 static u8 *avs_dyn_data = NULL;\r
1295 static u32 show_line_cnt = 0;\r
1296 static u8 dly_min;\r
1297 static u8 dly_max;\r
1298 \r
1299 #define val_per_line (30)\r
1300 #define line_pre_show (30)\r
1301 #define avs_dyn_data_num (3*1000*1000)\r
1302 \r
1303 static u32 print_avs_init(char *buf)\r
1304 {\r
1305         char *s = buf;\r
1306         int i, j;\r
1307 \r
1308         for(j = 0; j < init_avs_st_num; j++) {\r
1309                 if(init_avs_paramet[j].vol <= 0)\r
1310                         continue;\r
1311                 s += sprintf(s, "%s ,vol=%d,paramet following\n",\r
1312                                 init_avs_paramet[j].s, init_avs_paramet[j].vol);\r
1313                 for(i = 0; i < init_avs_times; i++) {\r
1314                         s += sprintf(s, "%d ", init_avs_paramet[j].paramet[i]);\r
1315                 }\r
1316 \r
1317                 s += sprintf(s, "\n");\r
1318         }\r
1319         return (s - buf);\r
1320 }\r
1321 \r
1322 static ssize_t avs_init_show(struct kobject *kobj, struct kobj_attribute *attr,\r
1323                 char *buf)\r
1324 {\r
1325         return print_avs_init(buf);\r
1326 }\r
1327 \r
1328 static ssize_t avs_init_store(struct kobject *kobj, struct kobj_attribute *attr,\r
1329                 const char *buf, size_t n)\r
1330 {\r
1331 \r
1332         return n;\r
1333 }\r
1334 static ssize_t avs_now_show(struct kobject *kobj, struct kobj_attribute *attr,\r
1335                 char *buf)\r
1336 {\r
1337         return sprintf(buf, "%d\n", rk_get_avs_val());\r
1338 }\r
1339 \r
1340 static ssize_t avs_now_store(struct kobject *kobj, struct kobj_attribute *attr,\r
1341                 const char *buf, size_t n)\r
1342 {\r
1343         return n;\r
1344 }\r
1345 static ssize_t avs_dyn_show(struct kobject *kobj, struct kobj_attribute *attr,\r
1346                 char *buf)\r
1347 {\r
1348         char *s = buf;\r
1349         u32 i;\r
1350 \r
1351         if(avs_dyn_data == NULL)\r
1352                 return (s - buf);\r
1353 \r
1354         if(avs_dyn_start) {\r
1355                 int start_cnt;\r
1356                 int end_cnt;\r
1357                 end_cnt = (avs_dyn_data_cnt ? (avs_dyn_data_cnt - 1) : 0);\r
1358                 if(end_cnt > (line_pre_show * val_per_line))\r
1359                         start_cnt = end_cnt - (line_pre_show * val_per_line);\r
1360                 else\r
1361                         start_cnt = 0;\r
1362 \r
1363                 dly_min = avs_dyn_data[start_cnt];\r
1364                 dly_max = avs_dyn_data[start_cnt];\r
1365 \r
1366                 //s += sprintf(s,"data start=%d\n",i);\r
1367                 for(i = start_cnt; i <= end_cnt;) {\r
1368                         s += sprintf(s, "%d", avs_dyn_data[i]);\r
1369                         dly_min = min(dly_min, avs_dyn_data[i]);\r
1370                         dly_max = max(dly_max, avs_dyn_data[i]);\r
1371                         i++;\r
1372                         if(!(i % val_per_line)) {\r
1373                                 s += sprintf(s, "\n");\r
1374                         } else\r
1375                                 s += sprintf(s, " ");\r
1376                 }\r
1377 \r
1378                 s += sprintf(s, "\n");\r
1379 \r
1380                 s += sprintf(s, "new data is from=%d to %d\n", start_cnt, end_cnt);\r
1381                 //s += sprintf(s,"\n max=%d,min=%d,totolcnt=%d,line=%d\n",dly_max,dly_min,avs_dyn_data_cnt,show_line_cnt);\r
1382 \r
1383 \r
1384         } else {\r
1385                 if(show_line_cnt == 0) {\r
1386                         dly_min = avs_dyn_data[0];\r
1387                         dly_max = avs_dyn_data[0];\r
1388                 }\r
1389 \r
1390 \r
1391                 for(i = show_line_cnt * (line_pre_show * val_per_line); i < avs_dyn_data_cnt;) {\r
1392                         s += sprintf(s, "%d", avs_dyn_data[i]);\r
1393                         dly_min = min(dly_min, avs_dyn_data[i]);\r
1394                         dly_max = max(dly_max, avs_dyn_data[i]);\r
1395                         i++;\r
1396                         if(!(i % val_per_line)) {\r
1397                                 s += sprintf(s, "\n");\r
1398                         } else\r
1399                                 s += sprintf(s, " ");\r
1400                         if(i >= ((show_line_cnt + 1)*line_pre_show * val_per_line))\r
1401                                 break;\r
1402                 }\r
1403 \r
1404                 s += sprintf(s, "\n");\r
1405 \r
1406                 s += sprintf(s, "max=%d,min=%d,totolcnt=%d,line=%d\n",\r
1407                                 dly_max, dly_min, avs_dyn_data_cnt, show_line_cnt);\r
1408                 show_line_cnt++;\r
1409                 if(((show_line_cnt * line_pre_show)*val_per_line) >= avs_dyn_data_cnt) {\r
1410 \r
1411                         show_line_cnt = 0;\r
1412 \r
1413                         s += sprintf(s, "data is over\n");\r
1414                 }\r
1415         }\r
1416         return (s - buf);\r
1417 }\r
1418 \r
1419 static ssize_t avs_dyn_store(struct kobject *kobj, struct kobj_attribute *attr,\r
1420                 const char *buf, size_t n)\r
1421 {\r
1422         const char *pbuf;\r
1423 \r
1424         if((strncmp(buf, "start", strlen("start")) == 0)) {\r
1425                 if(avs_dyn_data == NULL)\r
1426                         avs_dyn_data = kmalloc(avs_dyn_data_num, GFP_KERNEL);\r
1427                 if(avs_dyn_data == NULL)\r
1428                         return n;\r
1429 \r
1430                 pbuf = &buf[strlen("start")];\r
1431                 avs_dyn_data_cnt = 0;\r
1432                 show_line_cnt = 0;\r
1433                 if(avs_dyn_data) {\r
1434 #ifdef USE_NORMAL_TIME\r
1435                         mod_timer(&avs_timer, jiffies + msecs_to_jiffies(5));\r
1436 #else\r
1437                         hrtimer_start(&dvfs_hrtimer, ktime_set(0, 5 * 1000 * 1000), HRTIMER_MODE_REL);\r
1438 #endif\r
1439                         avs_dyn_start = 1;\r
1440                 }\r
1441                 //sscanf(pbuf, "%d %d", &number, &voltage);\r
1442                 //DVFS_DBG("---------ldo %d %d\n", number, voltage);\r
1443 \r
1444         } else if((strncmp(buf, "stop", strlen("stop")) == 0)) {\r
1445                 pbuf = &buf[strlen("stop")];\r
1446                 avs_dyn_start = 0;\r
1447                 show_line_cnt = 0;\r
1448                 //sscanf(pbuf, "%d %d", &number, &voltage);\r
1449                 //DVFS_DBG("---------dcdc %d %d\n", number, voltage);\r
1450         }\r
1451 \r
1452 \r
1453 \r
1454         return n;\r
1455 }\r
1456 \r
1457 static ssize_t dvfs_tree_store(struct kobject *kobj, struct kobj_attribute *attr,\r
1458                 const char *buf, size_t n)\r
1459 {\r
1460         return n;\r
1461 }\r
1462 static ssize_t dvfs_tree_show(struct kobject *kobj, struct kobj_attribute *attr,\r
1463                 char *buf)\r
1464 {\r
1465         return dump_dbg_map(buf);\r
1466 \r
1467 }\r
1468 \r
1469 static void avs_timer_fn(unsigned long data)\r
1470 {\r
1471         int i;\r
1472         for(i = 0; i < 1; i++) {\r
1473                 if(avs_dyn_data_cnt >= avs_dyn_data_num)\r
1474                         return;\r
1475                 avs_dyn_data[avs_dyn_data_cnt] = rk_get_avs_val();\r
1476                 avs_dyn_data_cnt++;\r
1477         }\r
1478         if(avs_dyn_start)\r
1479                 mod_timer(&avs_timer, jiffies + msecs_to_jiffies(10));\r
1480 }\r
1481 #if 0\r
1482 struct hrtimer dvfs_hrtimer;\r
1483 static enum hrtimer_restart dvfs_hrtimer_timer_func(struct hrtimer *timer)\r
1484 {\r
1485         int i;\r
1486         for(i = 0; i < 1; i++) {\r
1487                 if(avs_dyn_data_cnt >= avs_dyn_data_num)\r
1488                         return HRTIMER_NORESTART;\r
1489                 avs_dyn_data[avs_dyn_data_cnt] = rk_get_avs_val();\r
1490                 avs_dyn_data_cnt++;\r
1491         }\r
1492         if(avs_dyn_start)\r
1493                 hrtimer_start(timer, ktime_set(0, 1 * 1000 * 1000), HRTIMER_MODE_REL);\r
1494 \r
1495 }\r
1496 #endif\r
1497 /*********************************************************************************/\r
1498 static struct kobject *dvfs_kobj;\r
1499 struct dvfs_attribute {\r
1500         struct attribute        attr;\r
1501         ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,\r
1502                         char *buf);\r
1503         ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,\r
1504                         const char *buf, size_t n);\r
1505 };\r
1506 \r
1507 static struct dvfs_attribute dvfs_attrs[] = {\r
1508         /*     node_name        permision               show_func       store_func */\r
1509 #ifdef CONFIG_RK_CLOCK_PROC\r
1510         __ATTR(dvfs_tree,       S_IRUSR | S_IRGRP | S_IWUSR,    dvfs_tree_show, dvfs_tree_store),\r
1511         __ATTR(avs_init,        S_IRUSR | S_IRGRP | S_IWUSR,    avs_init_show,  avs_init_store),\r
1512 //      __ATTR(avs_dyn,         S_IRUSR | S_IRGRP | S_IWUSR,    avs_dyn_show,   avs_dyn_store),\r
1513         __ATTR(avs_now,         S_IRUSR | S_IRGRP | S_IWUSR,    avs_now_show,   avs_now_store),\r
1514 #endif\r
1515 };\r
1516 \r
1517 static int __init dvfs_init(void)\r
1518 {\r
1519         int i, ret = 0;\r
1520 #ifdef USE_NORMAL_TIME\r
1521         init_timer(&avs_timer);\r
1522         //avs_timer.expires = jiffies+msecs_to_jiffies(1);\r
1523         avs_timer.function = avs_timer_fn;\r
1524         //mod_timer(&avs_timer,jiffies+msecs_to_jiffies(1));\r
1525 #else\r
1526         hrtimer_init(&dvfs_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);\r
1527         dvfs_hrtimer.function = dvfs_hrtimer_timer_func;\r
1528         //hrtimer_start(&dvfs_hrtimer,ktime_set(0, 5*1000*1000),HRTIMER_MODE_REL);\r
1529 #endif\r
1530 \r
1531         dvfs_kobj = kobject_create_and_add("dvfs", NULL);\r
1532         if (!dvfs_kobj)\r
1533                 return -ENOMEM;\r
1534         for (i = 0; i < ARRAY_SIZE(dvfs_attrs); i++) {\r
1535                 ret = sysfs_create_file(dvfs_kobj, &dvfs_attrs[i].attr);\r
1536                 if (ret != 0) {\r
1537                         DVFS_ERR("create index %d error\n", i);\r
1538                         return ret;\r
1539                 }\r
1540         }\r
1541 \r
1542         return ret;\r
1543 }\r
1544 subsys_initcall(dvfs_init);\r