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