rk30:sdk: add logic dynamic voltage scale
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rk30 / 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 "clock.h"\r
24 #include <mach/dvfs.h>\r
25 #include <mach/clock.h>\r
26 #include <linux/regulator/consumer.h>\r
27 #include <linux/delay.h>\r
28 \r
29 #define DVFS_DBG(fmt, args...) {while(0);}\r
30 #define DVFS_ERR(fmt, args...) pr_err(fmt, ##args)\r
31 #define DVFS_LOG(fmt, args...) pr_debug(fmt, ##args)\r
32 //#define DVFS_LOG(fmt, args...) pr_err(fmt, ##args)\r
33 \r
34 #define dvfs_regulator_get(dev,id) regulator_get((dev),(id))\r
35 #define dvfs_regulator_put(regu) regulator_put((regu))\r
36 #define dvfs_regulator_set_voltage(regu,min_uV,max_uV) regulator_set_voltage((regu),(min_uV),(max_uV))\r
37 #define dvfs_regulator_get_voltage(regu) regulator_get_voltage((regu))\r
38 \r
39 #define dvfs_clk_get(a,b) clk_get((a),(b))\r
40 #define dvfs_clk_get_rate_kz(a) (clk_get_rate((a))/1000)\r
41 #define dvfs_clk_set_rate(a,b) clk_set_rate((a),(b))\r
42 #define dvfs_clk_enable(a) clk_enable((a))\r
43 #define dvfs_clk_disable(a) clk_disable((a))\r
44 \r
45 #define DVFS_MHZ (1000*1000)\r
46 #define DVFS_KHZ (1000)\r
47 \r
48 #define DVFS_V (1000*1000)\r
49 #define DVFS_MV (1000)\r
50 \r
51 \r
52 static LIST_HEAD(rk_dvfs_tree);\r
53 static DEFINE_MUTEX(mutex);\r
54 \r
55 extern int rk30_clk_notifier_register(struct clk *clk, struct notifier_block *nb);\r
56 extern int rk30_clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);\r
57 \r
58 // #define DVFS_DUMP_TREE\r
59 #ifdef DVFS_DUMP_TREE\r
60 static void dump_dbg_map(void);\r
61 #endif\r
62 \r
63 #define PD_ON   1\r
64 #define PD_OFF  0\r
65 \r
66 int is_support_dvfs(struct clk_node *dvfs_info)\r
67 {\r
68         return (dvfs_info->vd && dvfs_info->vd->vd_dvfs_target && dvfs_info->enable_dvfs);\r
69 }\r
70 \r
71 int dvfs_set_rate(struct clk *clk, unsigned long rate)\r
72 {\r
73         int ret = 0;\r
74         struct vd_node *vd;\r
75         DVFS_DBG("%s(%s(%lu))\n", __func__, clk->name, rate);\r
76         if (!clk->dvfs_info) {\r
77                 DVFS_ERR("%s :This clk do not support dvfs!\n", __func__);\r
78                 ret = -1;\r
79         } else {\r
80                 vd = clk->dvfs_info->vd;\r
81                 mutex_lock(&vd->dvfs_mutex);\r
82                 ret = vd->vd_dvfs_target(clk, rate);\r
83                 mutex_unlock(&vd->dvfs_mutex);\r
84         }\r
85         DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);\r
86         return ret;\r
87 }\r
88 \r
89 static int dvfs_clk_get_ref_volt_depend(struct depend_list *depend, int rate_khz,\r
90                 struct cpufreq_frequency_table *clk_fv)\r
91 {\r
92         int i = 0;\r
93         if (rate_khz == 0 || !depend || !depend->dep_table) {\r
94                 return -1;\r
95         }\r
96         clk_fv->frequency = rate_khz;\r
97         clk_fv->index = 0;\r
98 \r
99         for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
100                 if (depend->dep_table[i].frequency >= rate_khz) {\r
101                         clk_fv->frequency = depend->dep_table[i].frequency;\r
102                         clk_fv->index = depend->dep_table[i].index;\r
103                         return 0;\r
104                 }\r
105         }\r
106         clk_fv->frequency = 0;\r
107         clk_fv->index = 0;\r
108         return -1;\r
109 }\r
110 static int dvfs_clk_get_ref_volt(struct clk_node *dvfs_clk, int rate_khz,\r
111                 struct cpufreq_frequency_table *clk_fv)\r
112 {\r
113         int i = 0;\r
114         if (rate_khz == 0 || !dvfs_clk || !dvfs_clk->dvfs_table) {\r
115                 /* since no need */\r
116                 return -1;\r
117         }\r
118         clk_fv->frequency = rate_khz;\r
119         clk_fv->index = 0;\r
120 \r
121         for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
122                 if (dvfs_clk->dvfs_table[i].frequency >= rate_khz) {\r
123                         clk_fv->frequency = dvfs_clk->dvfs_table[i].frequency;\r
124                         clk_fv->index = dvfs_clk->dvfs_table[i].index;\r
125                         // DVFS_DBG("%s,%s rate=%ukhz(vol=%d)\n",__func__,dvfs_clk->name, \r
126                         // clk_fv->frequency, clk_fv->index);\r
127                         return 0;\r
128                 }\r
129         }\r
130         clk_fv->frequency = 0;\r
131         clk_fv->index = 0;\r
132         // DVFS_DBG("%s get corresponding voltage error! out of bound\n", dvfs_clk->name);\r
133         return -1;\r
134 }\r
135 \r
136 static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct clk_node *dvfs_clk)\r
137 {\r
138         struct clk_list *child;\r
139         int volt_max = 0;\r
140 \r
141         if (!pd || !dvfs_clk)\r
142                 return 0;\r
143 \r
144         if (dvfs_clk->set_volt >= pd->cur_volt) {\r
145                 return dvfs_clk->set_volt;\r
146         }\r
147 \r
148         list_for_each_entry(child, &pd->clk_list, node) {\r
149                 // DVFS_DBG("%s ,pd(%s),dvfs(%s),volt(%u)\n",__func__,pd->name,\r
150                 // dvfs_clk->name,dvfs_clk->set_volt);\r
151                 volt_max = max(volt_max, child->dvfs_clk->set_volt);\r
152         }\r
153         return volt_max;\r
154 }\r
155 \r
156 void dvfs_update_clk_pds_volt(struct clk_node *dvfs_clk)\r
157 {\r
158         struct pd_node   *pd;\r
159         int i;\r
160         if (!dvfs_clk)\r
161                 return;\r
162         for (i = 0; (dvfs_clk->pds[i].pd != NULL); i++) {\r
163                 pd = dvfs_clk->pds[i].pd;\r
164                 // DVFS_DBG("%s dvfs(%s),pd(%s)\n",__func__,dvfs_clk->name,pd->name);\r
165                 pd->cur_volt = dvfs_pd_get_newvolt_byclk(pd, dvfs_clk);\r
166         }\r
167 }\r
168 \r
169 static int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)\r
170 {\r
171         struct pd_node          *pd;\r
172         struct depend_list      *depend;\r
173         int     volt_max_vd = 0;\r
174         list_for_each_entry(pd, &vd->pd_list, node) {\r
175                 // DVFS_DBG("%s pd(%s,%u)\n",__func__,pd->name,pd->cur_volt);\r
176                 volt_max_vd = max(volt_max_vd, pd->cur_volt);\r
177         }\r
178 \r
179         /* some clks depend on this voltage domain */\r
180         if (!list_empty(&vd->req_volt_list)) {\r
181                 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {\r
182                         volt_max_vd = max(volt_max_vd, depend->req_volt);\r
183                 }\r
184         }\r
185         return volt_max_vd;\r
186 }\r
187 \r
188 static int dvfs_vd_get_newvolt_byclk(struct clk_node *dvfs_clk)\r
189 {\r
190         if (!dvfs_clk)\r
191                 return -1;\r
192         dvfs_update_clk_pds_volt(dvfs_clk);\r
193         return  dvfs_vd_get_newvolt_bypd(dvfs_clk->vd);\r
194 }\r
195 \r
196 void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target)\r
197 {\r
198         struct clk_node *dvfs_clk = clk_get_dvfs_info(clk);\r
199         dvfs_clk->clk_dvfs_target = clk_dvfs_target;\r
200 }\r
201 \r
202 struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk) \r
203 {\r
204         struct clk_node *info = clk_get_dvfs_info(clk);\r
205         struct cpufreq_frequency_table *table;\r
206         if (!info || !info->dvfs_table) {\r
207                 return NULL;\r
208         }\r
209         mutex_lock(&mutex);\r
210         table = info->dvfs_table;\r
211         mutex_unlock(&mutex);\r
212         return table;\r
213 }\r
214 \r
215 int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table)\r
216 {\r
217         struct clk_node *info = clk_get_dvfs_info(clk);\r
218         if (!table || !info)\r
219                 return -1;\r
220 \r
221         mutex_lock(&mutex);\r
222         info->dvfs_table = table;\r
223         mutex_unlock(&mutex);\r
224         return 0;\r
225 }\r
226 \r
227 int dvfs_set_depend_table(struct clk *clk, char *vd_name, struct cpufreq_frequency_table *table)\r
228 {\r
229         struct vd_node          *vd;\r
230         struct depend_list      *depend;\r
231         struct clk_node         *info;\r
232         info = clk_get_dvfs_info(clk);\r
233         if (!table || !info || !vd_name) {\r
234                 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! table or info or name empty\n", __func__);\r
235                 return -1;\r
236         }\r
237 \r
238         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
239                 if (0 == strcmp(vd->name, vd_name)) {\r
240                         DVFS_LOG("FOUND A MATCH\n");\r
241                         mutex_lock(&mutex);\r
242                         list_for_each_entry(depend, &info->depend_list, node2clk) {\r
243                                 if (vd == depend->dep_vd && info == depend->dvfs_clk) {\r
244                                         depend->dep_table = table;\r
245                                         break;\r
246                                 }\r
247                         }\r
248                         mutex_unlock(&mutex);\r
249 #ifdef DVFS_DUMP_TREE\r
250                         dump_dbg_map();\r
251 #endif\r
252                         return 0;\r
253                 }\r
254         }\r
255         DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! can not find vd:%s\n", __func__, vd_name);\r
256 \r
257         return 0;\r
258 }\r
259 \r
260 int clk_enable_dvfs(struct clk *clk)\r
261 {\r
262         struct regulator *regulator;\r
263         struct clk_node *dvfs_clk;\r
264         struct cpufreq_frequency_table clk_fv;\r
265         if (!clk) {\r
266                 DVFS_ERR("clk enable dvfs error\n");\r
267                 return -1;\r
268         }\r
269         dvfs_clk = clk_get_dvfs_info(clk);\r
270         if (!dvfs_clk || !dvfs_clk->vd) {\r
271                 DVFS_ERR("%s clk(%s) not support dvfs!\n", __func__, clk->name);\r
272                 return -1;\r
273         }\r
274         if (dvfs_clk->enable_dvfs == 0) {\r
275 \r
276                 if (!dvfs_clk->vd->regulator) {\r
277                         regulator = NULL;\r
278                         if (dvfs_clk->vd->regulator_name)\r
279                                 regulator = dvfs_regulator_get(NULL, dvfs_clk->vd->regulator_name);\r
280                         if (regulator) {\r
281                                 // DVFS_DBG("dvfs_regulator_get(%s)\n",dvfs_clk->vd->regulator_name);\r
282                                 dvfs_clk->vd->regulator = regulator;\r
283                         } else {\r
284                                 dvfs_clk->vd->regulator = NULL;\r
285                                 dvfs_clk->enable_dvfs = 0;\r
286                                 DVFS_ERR("%s can't get regulator in %s\n", dvfs_clk->name, __func__);\r
287                                 return -1;\r
288                         }\r
289                 } else {\r
290                         dvfs_clk->vd->cur_volt = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);\r
291                         // DVFS_DBG("%s(%s) vd volt=%u\n",__func__,dvfs_clk->name,dvfs_clk->vd->cur_volt);\r
292                 }\r
293 \r
294                 dvfs_clk->set_freq = dvfs_clk_get_rate_kz(clk);\r
295                 // DVFS_DBG("%s ,%s get freq%u!\n",__func__,dvfs_clk->name,dvfs_clk->set_freq);\r
296 \r
297                 if (dvfs_clk_get_ref_volt(dvfs_clk, dvfs_clk->set_freq, &clk_fv)) {\r
298                         dvfs_clk->enable_dvfs = 0;\r
299                         return -1;\r
300                 }\r
301                 dvfs_clk->set_volt = clk_fv.index;\r
302                 // DVFS_DBG("%s,%s,freq%u(ref vol %u)\n",__func__,dvfs_clk->name,\r
303                 //       dvfs_clk->set_freq,dvfs_clk->set_volt);\r
304 #if 0\r
305                 if (dvfs_clk->dvfs_nb) {\r
306                         // must unregister when clk disable\r
307                         rk30_clk_notifier_register(clk, dvfs_clk->dvfs_nb);\r
308                 }\r
309 #endif\r
310                 dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
311                 dvfs_clk->enable_dvfs++;\r
312         } else {\r
313                 DVFS_ERR("dvfs already enable clk enable = %d!\n", dvfs_clk->enable_dvfs);\r
314                 dvfs_clk->enable_dvfs++;\r
315         }\r
316         return 0;\r
317 }\r
318 \r
319 int clk_disable_dvfs(struct clk *clk)\r
320 {\r
321         struct clk_node *dvfs_clk;\r
322         dvfs_clk = clk->dvfs_info;\r
323         if (!dvfs_clk->enable_dvfs) {\r
324                 DVFS_DBG("clk is already closed!\n");\r
325                 return -1;\r
326         } else {\r
327                 dvfs_clk->enable_dvfs--;\r
328                 if (0 == dvfs_clk->enable_dvfs) {\r
329                         DVFS_ERR("clk closed!\n");\r
330                         rk30_clk_notifier_unregister(clk, dvfs_clk->dvfs_nb);\r
331                         DVFS_DBG("clk unregister nb!\n");\r
332                 }\r
333         }\r
334         return 0;\r
335 }\r
336 \r
337 static int rk_dvfs_clk_notifier_event(struct notifier_block *this,\r
338                 unsigned long event, void *ptr)\r
339 {\r
340         struct clk_notifier_data *noti_info;\r
341         struct clk *clk;\r
342         struct clk_node *dvfs_clk;\r
343         noti_info = (struct clk_notifier_data *)ptr;\r
344         clk = noti_info->clk;\r
345         dvfs_clk = clk->dvfs_info;\r
346 \r
347         switch (event) {\r
348                 case CLK_PRE_RATE_CHANGE:\r
349                         DVFS_DBG("%s CLK_PRE_RATE_CHANGE\n", __func__);\r
350                         break;\r
351                 case CLK_POST_RATE_CHANGE:\r
352                         DVFS_DBG("%s CLK_POST_RATE_CHANGE\n", __func__);\r
353                         break;\r
354                 case CLK_ABORT_RATE_CHANGE:\r
355                         DVFS_DBG("%s CLK_ABORT_RATE_CHANGE\n", __func__);\r
356                         break;\r
357                 case CLK_PRE_ENABLE:\r
358                         DVFS_DBG("%s CLK_PRE_ENABLE\n", __func__);\r
359                         break;\r
360                 case CLK_POST_ENABLE:\r
361                         DVFS_DBG("%s CLK_POST_ENABLE\n", __func__);\r
362                         break;\r
363                 case CLK_ABORT_ENABLE:\r
364                         DVFS_DBG("%s CLK_ABORT_ENABLE\n", __func__);\r
365                         break;\r
366                 case CLK_PRE_DISABLE:\r
367                         DVFS_DBG("%s CLK_PRE_DISABLE\n", __func__);\r
368                         break;\r
369                 case CLK_POST_DISABLE:\r
370                         DVFS_DBG("%s CLK_POST_DISABLE\n", __func__);\r
371                         dvfs_clk->set_freq = 0;\r
372                         break;\r
373                 case CLK_ABORT_DISABLE:\r
374                         DVFS_DBG("%s CLK_ABORT_DISABLE\n", __func__);\r
375 \r
376                         break;\r
377                 default:\r
378                         break;\r
379         }\r
380         return 0;\r
381 }\r
382 \r
383 static struct notifier_block rk_dvfs_clk_notifier = {\r
384         .notifier_call = rk_dvfs_clk_notifier_event,\r
385 };\r
386 \r
387 static struct clk_node *dvfs_get_dvfs_clk_byname(char *name)\r
388 {\r
389         struct vd_node *vd;\r
390         struct pd_node *pd;\r
391         struct clk_list *child;\r
392         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
393                 list_for_each_entry(pd, &vd->pd_list, node) {\r
394                         list_for_each_entry(child, &pd->clk_list, node) {\r
395                                 if (0 == strcmp(child->dvfs_clk->name, name)) {\r
396                                         return child->dvfs_clk;\r
397                                 }\r
398                         }\r
399                 }\r
400         }\r
401         return NULL;\r
402 }\r
403 static int rk_regist_vd(struct vd_node *vd)\r
404 {\r
405         if (!vd)\r
406                 return -1;\r
407         mutex_lock(&mutex);\r
408         mutex_init(&vd->dvfs_mutex);\r
409         list_add(&vd->node, &rk_dvfs_tree);\r
410         INIT_LIST_HEAD(&vd->pd_list);\r
411         INIT_LIST_HEAD(&vd->req_volt_list);\r
412 \r
413         mutex_unlock(&mutex);\r
414         return 0;\r
415 }\r
416 \r
417 static int rk_regist_pd(struct pd_node_lookup *pd_lookup)\r
418 {\r
419         struct vd_node  *vd;\r
420         struct pd_node  *pd;\r
421 \r
422         mutex_lock(&mutex);\r
423         pd = pd_lookup->pd;\r
424 \r
425         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
426                 if (vd == pd->vd) {\r
427                         list_add(&pd->node, &vd->pd_list);\r
428                         INIT_LIST_HEAD(&pd->clk_list);\r
429                         break;\r
430                 }\r
431         }\r
432         mutex_unlock(&mutex);\r
433         return 0;\r
434 }\r
435 \r
436 static int rk_regist_clk(struct clk_node *dvfs_clk)\r
437 {\r
438         struct pd_node  *pd;\r
439         struct clk_list *child;\r
440         struct clk      *clk;\r
441         int i = 0;\r
442 \r
443         if (!dvfs_clk)\r
444                 return -1;\r
445 \r
446         if (!dvfs_clk->pds)\r
447                 return -1;\r
448         mutex_lock(&mutex);\r
449         dvfs_clk->enable_dvfs = 0;\r
450         dvfs_clk->vd = dvfs_clk->pds[0].pd->vd;\r
451         for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {\r
452                 child = &(dvfs_clk->pds[i].clk_list);\r
453                 child->dvfs_clk = dvfs_clk;\r
454                 pd = dvfs_clk->pds[i].pd;\r
455                 list_add(&child->node, &pd->clk_list);\r
456         }\r
457         clk = dvfs_clk_get(NULL, dvfs_clk->name);\r
458         dvfs_clk->clk = clk;\r
459         clk_register_dvfs(dvfs_clk, clk);\r
460         INIT_LIST_HEAD(&dvfs_clk->depend_list);\r
461         mutex_unlock(&mutex);\r
462         return 0;\r
463 }\r
464 \r
465 static int rk_regist_depends(struct depend_lookup *dep_node)\r
466 {\r
467         struct depend_list      *depend_list;\r
468         struct clk_node         *dvfs_clk;\r
469 \r
470         if (!dep_node) {\r
471                 DVFS_ERR("%s : DVFS BAD depend node!\n", __func__);\r
472                 return -1;\r
473         }\r
474 \r
475         if (!dep_node->clk_name || !dep_node->dep_vd) {\r
476                 DVFS_ERR("%s : DVFS BAD depend members!\n", __func__);\r
477                 return -1;\r
478         }\r
479 \r
480         depend_list = &dep_node->dep_list;\r
481         dvfs_clk = dvfs_get_dvfs_clk_byname(dep_node->clk_name);\r
482 \r
483         mutex_lock(&mutex);\r
484 \r
485         depend_list->dvfs_clk = dvfs_clk;\r
486         depend_list->dep_vd = dep_node->dep_vd;\r
487         depend_list->dep_table = dep_node->dep_table;\r
488 \r
489         list_add(&depend_list->node2clk, &dvfs_clk->depend_list);\r
490         list_add(&depend_list->node2vd, &depend_list->dep_vd->req_volt_list);\r
491 \r
492         mutex_unlock(&mutex);\r
493         return 0;\r
494 }\r
495 \r
496 #define get_volt_up_delay(new_volt, old_volt)   \\r
497         ((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 10) : 0)\r
498 \r
499 static int dvfs_set_depend_pre(struct clk_node *dvfs_clk, unsigned long rate_old, unsigned long rate_new)\r
500 {\r
501         struct depend_list      *depend;\r
502         struct cpufreq_frequency_table  clk_fv;\r
503         int ret = -1;\r
504         int volt = 0;\r
505         struct regulator *regulator;\r
506 \r
507         if (rate_old >= rate_new) {\r
508                 return 0;\r
509         }\r
510         list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {\r
511                 ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv);\r
512                 if (ret != 0) {\r
513                         DVFS_ERR("%s LOGIC DVFS CAN NOT GET REF VOLT!, frequency too large!\n", __func__);\r
514                         return -1;\r
515                 }\r
516 \r
517                 if (!depend->dep_vd->regulator) {\r
518                         DVFS_LOG("%s regulator empty\n", __func__);\r
519                         regulator = dvfs_regulator_get(NULL, depend->dep_vd->regulator_name);\r
520                         if (!regulator) {\r
521                                 DVFS_ERR("%s get regulator err\n", __func__);\r
522                                 return -1;\r
523                         }\r
524 \r
525                         depend->dep_vd->regulator = regulator;\r
526                 }\r
527                 if (!depend->dep_vd->regulator) {\r
528                         DVFS_ERR("%s vd's(%s) regulator empty\n", __func__, depend->dep_vd->name);\r
529                         return -1;\r
530                 }\r
531 \r
532                 if (clk_fv.index == dvfs_regulator_get_voltage(depend->dep_vd->regulator)) {\r
533                         depend->req_volt = clk_fv.index;\r
534                         DVFS_LOG("%s same voltage\n", __func__);\r
535                         return 0;\r
536                 }\r
537 \r
538                 depend->req_volt = clk_fv.index;\r
539                 volt = dvfs_vd_get_newvolt_bypd(depend->dep_vd);\r
540                 DVFS_LOG("%s setting voltage = %d\n", __func__, volt);\r
541                 ret = dvfs_regulator_set_voltage(depend->dep_vd->regulator, volt, volt);\r
542                 if (0 != ret) {\r
543                         DVFS_ERR("%s set voltage = %d ERROR, ret = %d\n", __func__, volt, ret);\r
544                         return -1;\r
545                 }\r
546                 udelay(200);\r
547                 DVFS_LOG("%s set voltage = %d OK, ret = %d\n", __func__, volt, ret);\r
548                 if (ret != 0) {\r
549                         DVFS_ERR("%s err, ret = %d\n", __func__, ret);\r
550                         return -1;\r
551                 }\r
552         }\r
553 \r
554         return 0;\r
555 }\r
556 \r
557 static int dvfs_set_depend_post(struct clk_node *dvfs_clk, unsigned long rate_old, unsigned long rate_new)\r
558 {\r
559         struct depend_list      *depend;\r
560         struct cpufreq_frequency_table  clk_fv;\r
561         int ret = -1;\r
562         int volt = 0;\r
563         struct regulator *regulator;\r
564 \r
565         if (rate_old <= rate_new) \r
566                 return 0;\r
567         list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {\r
568                 ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv);\r
569                 if (ret != 0) {\r
570                         DVFS_ERR("%s LOGIC DVFS CAN NOT GET REF VOLT!, frequency too large!\n", __func__);\r
571                         return -1;\r
572                 }\r
573 \r
574                 if (!depend->dep_vd->regulator) {\r
575                         DVFS_LOG("%s regulator empty\n", __func__);\r
576                         regulator = dvfs_regulator_get(NULL, depend->dep_vd->regulator_name);\r
577                         if (!regulator) {\r
578                                 DVFS_ERR("%s get regulator err\n", __func__);\r
579                                 return -1;\r
580                         }\r
581 \r
582                         depend->dep_vd->regulator = regulator;\r
583                 }\r
584                 if (!depend->dep_vd->regulator) {\r
585                         DVFS_ERR("%s vd's(%s) regulator empty\n", __func__, depend->dep_vd->name);\r
586                         return -1;\r
587                 }\r
588 \r
589                 if (clk_fv.index == dvfs_regulator_get_voltage(depend->dep_vd->regulator)) {\r
590                         depend->req_volt = clk_fv.index;\r
591                         DVFS_LOG("%s same voltage\n", __func__);\r
592                         return 0;\r
593                 }\r
594 \r
595                 depend->req_volt = clk_fv.index;\r
596                 volt = dvfs_vd_get_newvolt_bypd(depend->dep_vd);\r
597                 DVFS_LOG("%s setting voltage = %d\n", __func__, volt);\r
598                 ret = dvfs_regulator_set_voltage(depend->dep_vd->regulator, volt, volt);\r
599                 if (0 != ret) {\r
600                         DVFS_ERR("%s set voltage = %d ERROR, ret = %d\n", __func__, volt, ret);\r
601                         return -1;\r
602                 }\r
603                 udelay(200);\r
604                 DVFS_LOG("%s set voltage = %d OK, ret = %d\n", __func__, volt, ret);\r
605                 if (ret != 0) {\r
606                         DVFS_ERR("%s err, ret = %d\n", __func__, ret);\r
607                         return -1;\r
608                 }\r
609         }\r
610 \r
611         return 0;\r
612 }\r
613 \r
614 static int flag_core_set_volt_err = 0;\r
615 int dvfs_target_core(struct clk *clk, unsigned long rate_hz)\r
616 {\r
617         struct clk_node *dvfs_clk;\r
618         unsigned int volt_new = 0, volt_old = 0, volt_clk_old = 0;\r
619         struct cpufreq_frequency_table clk_fv = {0, 0};\r
620         int ret = 0;\r
621         int flag_set_volt_correct = 0;\r
622         unsigned long rate_new, rate_old;\r
623 \r
624         if (!clk) {\r
625                 DVFS_ERR("%s is not clk\n", __func__);\r
626                 return -1;\r
627         }\r
628         dvfs_clk = clk_get_dvfs_info(clk);\r
629 \r
630         if (!dvfs_clk || dvfs_clk->vd->regulator == NULL) {\r
631                 DVFS_ERR("%s can't get dvfs regulater\n", clk->name);\r
632                 return -1;\r
633         }\r
634 \r
635         // clk_round_rate_nolock(clk, rate_hz);\r
636         rate_new = rate_hz;\r
637         rate_old = clk_get_rate(clk);\r
638 \r
639         // DVFS_DBG("dvfs(%s) round rate(%lu)(rount %lu)\n",dvfs_clk->name,rate_hz,rate_new);\r
640 \r
641         /* find the clk corresponding voltage */\r
642         if (dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {\r
643                 DVFS_ERR("%s--%s:rate%lu,Get corresponding voltage error!\n", \r
644                                 __func__, dvfs_clk->name, rate_new);\r
645                 return -1;\r
646         }\r
647         volt_old = dvfs_clk->vd->cur_volt;\r
648 \r
649         volt_clk_old = dvfs_clk->set_volt;\r
650 \r
651         dvfs_clk->set_volt = clk_fv.index;\r
652 \r
653         volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
654 \r
655         DVFS_DBG("dvfs--(%s),volt=%d(was %dmV),rate=%lu(was %lu),vd%u=(was%u)\n",\r
656                         dvfs_clk->name, clk_fv.index, dvfs_clk->set_volt, rate_new, rate_old\r
657                         , volt_new, volt_old);\r
658 \r
659         if (flag_core_set_volt_err) {\r
660                 /* It means the last time set voltage error */  \r
661                 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);\r
662                 if (flag_set_volt_correct <= 0) {\r
663                         DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload core_volt error %d!!! stop scaling\n", \r
664                                         __func__, dvfs_clk->name, volt_new, volt_old, \r
665                                         rate_new, rate_old, flag_set_volt_correct);\r
666                         return -1;\r
667                 }\r
668 \r
669                 flag_core_set_volt_err = 0;\r
670                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload core_volt! core_volt_correct = %d\n", \r
671                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
672                                 rate_new, rate_old, flag_set_volt_correct);\r
673 \r
674                 /* Reset vd's voltage */\r
675                 dvfs_clk->vd->cur_volt = flag_set_volt_correct;\r
676                 volt_old = dvfs_clk->vd->cur_volt;\r
677         }\r
678 \r
679         /* if up the voltage */\r
680         if (volt_old < volt_new) {\r
681                 if (dvfs_clk->vd->regulator) {\r
682                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
683                         if (ret < 0) {\r
684                                 flag_core_set_volt_err = 1;\r
685                                 DVFS_ERR("%s %s set voltage up err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
686                                                 __func__, dvfs_clk->name, ret, \r
687                                                 rate_new, rate_old, volt_new, volt_old);\r
688                                 return -1;\r
689                         }\r
690 \r
691                 } else {\r
692                         DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
693                         return -1;\r
694                 }\r
695 \r
696                 dvfs_clk->vd->cur_volt = volt_new;\r
697                 udelay(get_volt_up_delay(volt_new, volt_old));\r
698                 DVFS_DBG("%s %s set voltage OK up ret = %d, Vnew = %d(was %d), Rnew = %lu(was %lu)\n", \r
699                                 __func__, dvfs_clk->name, ret, volt_new, volt_old, rate_new, rate_old);\r
700         }\r
701 \r
702         if (dvfs_clk->clk_dvfs_target) {\r
703                 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);\r
704         } else {\r
705                 ret = clk_set_rate_locked(clk, rate_new);\r
706         }\r
707 \r
708         if (ret < 0) {\r
709 \r
710                 dvfs_clk->set_volt = volt_old;\r
711                 dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
712                 DVFS_ERR("set rate err\n");\r
713                 return -1;\r
714         }\r
715         dvfs_clk->set_freq      = rate_new / 1000;\r
716 \r
717         /* if down the voltage */\r
718         if (volt_old > volt_new) {\r
719                 if (dvfs_clk->vd->regulator) {\r
720                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
721                         if (ret < 0) {\r
722                                 flag_core_set_volt_err = 1;\r
723                                 DVFS_ERR("%s %s set voltage down err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
724                                                 __func__, dvfs_clk->name, ret, rate_new, rate_old, \r
725                                                 volt_new, volt_old);\r
726                                 return -1;\r
727                         }\r
728 \r
729                 } else {\r
730                         DVFS_ERR("%s down volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
731                         return -1;\r
732                 }\r
733 \r
734                 dvfs_clk->vd->cur_volt = volt_new;\r
735                 DVFS_DBG("dvfs %s set volt ok dn\n", dvfs_clk->name);\r
736 \r
737         }\r
738 \r
739         return 0;\r
740 }\r
741 \r
742 static int flag_arm_set_volt_err = 0;\r
743 int dvfs_target_cpu(struct clk *clk, unsigned long rate_hz)\r
744 {\r
745         struct clk_node *dvfs_clk;\r
746         int volt_new = 0, volt_old = 0;\r
747         struct cpufreq_frequency_table clk_fv;\r
748         int ret = 0;\r
749         int flag_set_volt_correct = 0;\r
750         unsigned long rate_new, rate_old;\r
751 \r
752 \r
753         if (!clk) {\r
754                 DVFS_ERR("%s is not clk\n", __func__);\r
755                 return -1;\r
756         }\r
757         dvfs_clk = clk_get_dvfs_info(clk);\r
758 \r
759         if (!dvfs_clk || dvfs_clk->vd->regulator == NULL) {\r
760                 DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);\r
761                 return -1;\r
762         }\r
763 \r
764         /* need round rate */\r
765         rate_new = clk_round_rate_nolock(clk, rate_hz);\r
766         DVFS_DBG("dvfs(%s) round rate (%lu)(rount %lu)\n", dvfs_clk->name, rate_hz, rate_new);\r
767 \r
768         rate_old = clk_get_rate(clk);\r
769         /* find the clk corresponding voltage */\r
770         if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {\r
771                 DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
772                 return -1;\r
773         }\r
774 \r
775         volt_old = dvfs_clk->vd->cur_volt;\r
776         volt_new = clk_fv.index;\r
777         if (flag_arm_set_volt_err) {\r
778                 /* It means the last time set voltage error */\r
779                 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);\r
780                 if (flag_set_volt_correct <= 0) {\r
781                         DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload arm_volt error %d!!! stop scaling\n", \r
782                                         __func__, dvfs_clk->name, volt_new, volt_old, \r
783                                         rate_new, rate_old, flag_set_volt_correct);\r
784                         return -1;\r
785                 }\r
786 \r
787                 flag_arm_set_volt_err = 0;\r
788                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload arm_volt! arm_volt_correct = %d\n", \r
789                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
790                                 rate_new, rate_old, flag_set_volt_correct);\r
791 \r
792                 /* Reset vd's voltage */\r
793                 dvfs_clk->vd->cur_volt = flag_set_volt_correct;\r
794                 volt_old = dvfs_clk->vd->cur_volt;\r
795         }\r
796 \r
797         /* if up the voltage */\r
798         if (volt_old < volt_new) {\r
799                 if (dvfs_clk->vd->regulator) {\r
800                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
801                         if (ret < 0) {\r
802                                 flag_arm_set_volt_err = 1;\r
803                                 DVFS_ERR("%s %s set voltage up err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
804                                                 __func__, dvfs_clk->name, ret, rate_new, rate_old, \r
805                                                 volt_new, volt_old);\r
806                                 return -1;\r
807                         }\r
808 \r
809                 } else {\r
810                         DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
811                         return -1;\r
812                 }\r
813 \r
814                 dvfs_clk->vd->cur_volt = volt_new;\r
815                 udelay(get_volt_up_delay(volt_new, volt_old));\r
816                 DVFS_DBG("%s %s set voltage OK up ret = %d, Vnew = %d(was %d), Rnew = %lu(was %lu)\n", \r
817                                 __func__, dvfs_clk->name, ret, volt_new, volt_old, rate_new, rate_old);\r
818         }\r
819         \r
820         /* depend voltage domain set up*/\r
821         if (0 != dvfs_set_depend_pre(dvfs_clk, rate_old, rate_new)) {\r
822                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), set depend pre voltage err, stop scaling\n", \r
823                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
824                                 rate_new, rate_old);\r
825                 return -1;\r
826         }\r
827 \r
828         if (dvfs_clk->clk_dvfs_target) {\r
829                 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);\r
830         } else {\r
831                 ret = clk_set_rate_locked(clk, rate_new);\r
832         }\r
833 \r
834         if (ret < 0) {\r
835                 DVFS_ERR("set rate err\n");\r
836                 return -1;\r
837         }\r
838         dvfs_clk->set_freq      = rate_new / 1000;\r
839 \r
840         DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));\r
841 \r
842         /* depend voltage domain set down*/\r
843         if (0 != dvfs_set_depend_post(dvfs_clk, rate_old, rate_new)) {\r
844                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), set depend post voltage  err, stop scaling\n", \r
845                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
846                                 rate_new, rate_old);\r
847                 return -1;\r
848         }\r
849 \r
850         /* if down the voltage */\r
851         if (volt_old > volt_new) {\r
852                 if (dvfs_clk->vd->regulator) {\r
853                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
854                         if (ret < 0) {\r
855                                 flag_arm_set_volt_err = 1;\r
856                                 DVFS_ERR("%s %s set voltage down err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
857                                                 __func__, dvfs_clk->name, ret, rate_new, rate_old, \r
858                                                 volt_new, volt_old);\r
859                                 return -1;\r
860                         }\r
861 \r
862                 } else {\r
863                         DVFS_ERR("%s down volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
864                         return -1;\r
865                 }\r
866 \r
867                 dvfs_clk->vd->cur_volt = volt_new;\r
868                 DVFS_DBG("dvfs %s set volt ok dn\n", dvfs_clk->name);\r
869 \r
870         }\r
871 \r
872         return ret;\r
873 }\r
874 \r
875 \r
876 \r
877 /*****************************init**************************/\r
878 /**\r
879  * rate must be raising sequence\r
880  */\r
881 static struct cpufreq_frequency_table cpu_dvfs_table[] = {\r
882         // {.frequency  = 48 * DVFS_KHZ, .index = 920*DVFS_MV},\r
883         // {.frequency  = 126 * DVFS_KHZ, .index        = 970 * DVFS_MV},\r
884         // {.frequency  = 252 * DVFS_KHZ, .index        = 1040 * DVFS_MV},\r
885         // {.frequency  = 504 * DVFS_KHZ, .index        = 1050 * DVFS_MV},\r
886         {.frequency     = 816 * DVFS_KHZ, .index        = 1050 * DVFS_MV},\r
887         // {.frequency  = 1008 * DVFS_KHZ, .index       = 1100 * DVFS_MV},\r
888         {.frequency     = CPUFREQ_TABLE_END},\r
889 };\r
890 \r
891 static struct cpufreq_frequency_table ddr_dvfs_table[] = {\r
892         // {.frequency = 100 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
893         {.frequency = 200 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
894         {.frequency = 300 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
895         {.frequency = 400 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
896         {.frequency = 500 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
897         {.frequency = 600 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
898         {.frequency = CPUFREQ_TABLE_END},\r
899 };\r
900 \r
901 static struct cpufreq_frequency_table gpu_dvfs_table[] = {\r
902         {.frequency = 100 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
903         {.frequency = 200 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
904         {.frequency = 300 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
905         {.frequency = 400 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
906         {.frequency = 500 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
907         {.frequency = CPUFREQ_TABLE_END},\r
908 };\r
909 \r
910 static struct cpufreq_frequency_table peri_aclk_dvfs_table[] = {\r
911         {.frequency = 100 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
912         {.frequency = 200 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
913         {.frequency = 300 * DVFS_KHZ, .index = 1070 * DVFS_MV},\r
914         {.frequency = 500 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
915         {.frequency = CPUFREQ_TABLE_END},\r
916 };\r
917 \r
918 static struct cpufreq_frequency_table dep_cpu2core_table[] = {\r
919         // {.frequency = 252 * DVFS_KHZ, .index    = 1025 * DVFS_MV},\r
920         // {.frequency = 504 * DVFS_KHZ, .index    = 1025 * DVFS_MV},\r
921         {.frequency = 816 * DVFS_KHZ, .index    = 1050 * DVFS_MV},//logic 1.050V\r
922         // {.frequency = 1008 * DVFS_KHZ,.index    = 1050 * DVFS_MV},\r
923         // {.frequency = 1200 * DVFS_KHZ,.index    = 1050 * DVFS_MV},\r
924         // {.frequency = 1272 * DVFS_KHZ,.index    = 1050 * DVFS_MV},//logic 1.050V\r
925         // {.frequency = 1416 * DVFS_KHZ,.index    = 1100 * DVFS_MV},//logic 1.100V\r
926         // {.frequency = 1512 * DVFS_KHZ,.index    = 1125 * DVFS_MV},//logic 1.125V\r
927         // {.frequency = 1608 * DVFS_KHZ,.index    = 1175 * DVFS_MV},//logic 1.175V\r
928         {.frequency     = CPUFREQ_TABLE_END},\r
929 };\r
930 \r
931 static struct vd_node vd_cpu = {\r
932         .name           = "vd_cpu",\r
933         .regulator_name = "vdd_cpu",\r
934         .vd_dvfs_target = dvfs_target_cpu,\r
935 };\r
936 \r
937 static struct vd_node vd_core = {\r
938         .name           = "vd_core",\r
939         .regulator_name = "vdd_core",\r
940         .vd_dvfs_target = dvfs_target_core,\r
941 };\r
942 \r
943 static struct vd_node vd_rtc = {\r
944         .name           = "vd_rtc",\r
945         .regulator_name = "vdd_rtc",\r
946         .vd_dvfs_target = NULL,\r
947 };\r
948 \r
949 static struct vd_node *rk30_vds[] = {&vd_cpu, &vd_core, &vd_rtc};\r
950 \r
951 static struct pd_node pd_a9_0 = {\r
952         .name                   = "pd_a9_0",\r
953         .vd                     = &vd_cpu,\r
954 };\r
955 static struct pd_node pd_a9_1 = {\r
956         .name                   = "pd_a9_1",\r
957         .vd                     = &vd_cpu,\r
958 };\r
959 static struct pd_node pd_debug = {\r
960         .name                   = "pd_debug",\r
961         .vd                     = &vd_cpu,\r
962 };\r
963 static struct pd_node pd_scu = {\r
964         .name                   = "pd_scu",\r
965         .vd                     = &vd_cpu,\r
966 };\r
967 static struct pd_node pd_video = {\r
968         .name                   = "pd_video",\r
969         .vd                     = &vd_core,\r
970 };\r
971 static struct pd_node pd_vio = {\r
972         .name                   = "pd_vio",\r
973         .vd                     = &vd_core,\r
974 };\r
975 static struct pd_node pd_gpu = {\r
976         .name                   = "pd_gpu",\r
977         .vd                     = &vd_core,\r
978 };\r
979 static struct pd_node pd_peri = {\r
980         .name                   = "pd_peri",\r
981         .vd                     = &vd_core,\r
982 };\r
983 static struct pd_node pd_cpu = {\r
984         .name                   = "pd_cpu",\r
985         .vd                     = &vd_core,\r
986 };\r
987 static struct pd_node pd_alive = {\r
988         .name                   = "pd_alive",\r
989         .vd                     = &vd_core,\r
990 };\r
991 static struct pd_node pd_rtc = {\r
992         .name                   = "pd_rtc",\r
993         .vd                     = &vd_rtc,\r
994 };\r
995 #define LOOKUP_PD(_ppd) \\r
996 {       \\r
997         .pd     = _ppd, \\r
998 }\r
999 static struct pd_node_lookup rk30_pds[] = {\r
1000         LOOKUP_PD(&pd_a9_0),\r
1001         LOOKUP_PD(&pd_a9_1),\r
1002         LOOKUP_PD(&pd_debug),\r
1003         LOOKUP_PD(&pd_scu),\r
1004         LOOKUP_PD(&pd_video),\r
1005         LOOKUP_PD(&pd_vio),\r
1006         LOOKUP_PD(&pd_gpu),\r
1007         LOOKUP_PD(&pd_peri),\r
1008         LOOKUP_PD(&pd_cpu),\r
1009         LOOKUP_PD(&pd_alive),\r
1010         LOOKUP_PD(&pd_rtc),\r
1011 };\r
1012 \r
1013 #define CLK_PDS(_ppd) \\r
1014 {       \\r
1015         .pd     = _ppd, \\r
1016 }\r
1017 \r
1018 static struct pds_list cpu_pds[] = {\r
1019         CLK_PDS(&pd_a9_0),\r
1020         CLK_PDS(&pd_a9_1),\r
1021         CLK_PDS(NULL),\r
1022 };\r
1023 \r
1024 static struct pds_list ddr_pds[] = {\r
1025         CLK_PDS(&pd_cpu),\r
1026         CLK_PDS(NULL),\r
1027 };\r
1028 \r
1029 static struct pds_list gpu_pds[] = {\r
1030         CLK_PDS(&pd_gpu),\r
1031         CLK_PDS(NULL),\r
1032 };\r
1033 \r
1034 static struct pds_list aclk_periph_pds[] = {\r
1035         CLK_PDS(&pd_peri),\r
1036         CLK_PDS(NULL),\r
1037 };\r
1038 \r
1039 #define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb) \\r
1040 { \\r
1041         .name   = _clk_name, \\r
1042         .pds = _ppds,\\r
1043         .dvfs_table = _dvfs_table,      \\r
1044         .dvfs_nb        = _dvfs_nb,     \\r
1045 }\r
1046 \r
1047 static struct clk_node rk30_clks[] = {\r
1048         RK_CLKS("cpu", cpu_pds, cpu_dvfs_table, &rk_dvfs_clk_notifier),\r
1049         RK_CLKS("ddr", ddr_pds, ddr_dvfs_table, &rk_dvfs_clk_notifier),\r
1050         RK_CLKS("gpu", gpu_pds, gpu_dvfs_table, &rk_dvfs_clk_notifier),\r
1051         RK_CLKS("aclk_periph", aclk_periph_pds, peri_aclk_dvfs_table, &rk_dvfs_clk_notifier),\r
1052 };\r
1053 \r
1054 #define RK_DEPPENDS(_clk_name, _pvd, _dep_table) \\r
1055 { \\r
1056         .clk_name       = _clk_name, \\r
1057         .dep_vd         = _pvd,\\r
1058         .dep_table      = _dep_table,   \\r
1059 }\r
1060 \r
1061 static struct depend_lookup rk30_depends[] = {\r
1062         RK_DEPPENDS("cpu", &vd_core, dep_cpu2core_table),\r
1063 };\r
1064 \r
1065 int rk30_dvfs_init(void)\r
1066 {\r
1067         int i = 0;\r
1068         for (i = 0; i < ARRAY_SIZE(rk30_vds); i++) {\r
1069                 rk_regist_vd(rk30_vds[i]);\r
1070         }\r
1071         for (i = 0; i < ARRAY_SIZE(rk30_pds); i++) {\r
1072                 rk_regist_pd(&rk30_pds[i]);\r
1073         }\r
1074         for (i = 0; i < ARRAY_SIZE(rk30_clks); i++) {\r
1075                 rk_regist_clk(&rk30_clks[i]);\r
1076         }\r
1077         for (i = 0; i < ARRAY_SIZE(rk30_depends); i++) {\r
1078                 rk_regist_depends(&rk30_depends[i]);\r
1079         }\r
1080 #ifdef DVFS_DUMP_TREE\r
1081         dump_dbg_map();\r
1082 #endif\r
1083         return 0;\r
1084 }\r
1085 \r
1086 #ifdef DVFS_DUMP_TREE\r
1087 /**\r
1088  * dump_dbg_map() : Draw all informations of dvfs while debug\r
1089  */\r
1090 static void dump_dbg_map(void)\r
1091 {\r
1092         int i;\r
1093         struct vd_node  *vd;\r
1094         struct pd_node  *pd, *clkparent;\r
1095         struct clk_list *child;\r
1096         struct clk_node *dvfs_clk;\r
1097         struct depend_list *depend;\r
1098 \r
1099         DVFS_LOG("-------------DVFS DEBUG-----------\n\n\n");\r
1100         DVFS_LOG("RK30 DVFS TREE:\n");\r
1101         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
1102                 DVFS_LOG("|\n|- voltage domain:%s\n", vd->name);\r
1103                 DVFS_LOG("|- current voltage:%d\n", vd->cur_volt);\r
1104                 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {\r
1105                         DVFS_LOG("|- request voltage:%d, clk:%s\n", depend->req_volt, depend->dvfs_clk->name);\r
1106                 }\r
1107 \r
1108                 list_for_each_entry(pd, &vd->pd_list, node) {\r
1109                         DVFS_LOG("|  |\n|  |- power domain:%s, status = %s, current volt = %d\n",\r
1110                                         pd->name, (pd->pd_status == PD_ON) ? "ON" : "OFF", pd->cur_volt);\r
1111 \r
1112                         list_for_each_entry(child, &pd->clk_list, node) {\r
1113                                 dvfs_clk = child->dvfs_clk;\r
1114                                 DVFS_LOG("|  |  |\n|  |  |- clock: %s current: rate %d, volt = %d, enable_dvfs = %s\n",\r
1115                                                 dvfs_clk->name, dvfs_clk->set_freq, dvfs_clk->set_volt, \r
1116                                                 dvfs_clk->enable_dvfs == 0 ? "DISABLE" : "ENABLE");\r
1117                                 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {\r
1118                                         clkparent = dvfs_clk->pds[i].pd;\r
1119                                         DVFS_LOG("|  |  |  |- clock parents: %s, vd_parent = %s\n", \r
1120                                                         clkparent->name, clkparent->vd->name);\r
1121                                 }\r
1122 \r
1123                                 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
1124                                         DVFS_LOG("|  |  |  |- freq = %d, volt = %d\n", \r
1125                                                         dvfs_clk->dvfs_table[i].frequency, \r
1126                                                         dvfs_clk->dvfs_table[i].index);\r
1127 \r
1128                                 }\r
1129 \r
1130                                 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {\r
1131                                         DVFS_LOG("|  |  |  |  |- DEPEND VD: %s\n", depend->dep_vd->name); \r
1132                                         for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
1133                                                 DVFS_LOG("|  |  |  |  |- freq = %d, req_volt = %d\n", \r
1134                                                                 depend->dep_table[i].frequency, \r
1135                                                                 depend->dep_table[i].index);\r
1136 \r
1137                                         }\r
1138                                 }\r
1139                         }\r
1140                 }\r
1141         }\r
1142         DVFS_LOG("-------------DVFS DEBUG END------------\n");\r
1143 }\r
1144 #endif\r
1145 \r
1146 \r
1147 \r