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