1f3b9ac8bc85dc1c64b26c2e10117b93f372e04e
[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 dvfs_set_arm_logic_volt(struct dvfs_arm_table *dvfs_cpu_logic_table, \r
261                 struct cpufreq_frequency_table *cpu_dvfs_table,\r
262                 struct cpufreq_frequency_table *dep_cpu2core_table)\r
263 {\r
264         int i = 0;\r
265         for (i = 0; dvfs_cpu_logic_table[i].frequency != CPUFREQ_TABLE_END; i++) {\r
266                 cpu_dvfs_table[i].frequency = dvfs_cpu_logic_table[i].frequency;\r
267                 cpu_dvfs_table[i].index = dvfs_cpu_logic_table[i].cpu_volt;\r
268 \r
269                 dep_cpu2core_table[i].frequency = dvfs_cpu_logic_table[i].frequency;\r
270                 dep_cpu2core_table[i].index = dvfs_cpu_logic_table[i].logic_volt;\r
271         }\r
272 \r
273         cpu_dvfs_table[i].frequency = CPUFREQ_TABLE_END;\r
274         dep_cpu2core_table[i].frequency = CPUFREQ_TABLE_END;\r
275 \r
276         dvfs_set_freq_volt_table(clk_get(NULL, "cpu"), cpu_dvfs_table);\r
277         dvfs_set_depend_table(clk_get(NULL, "cpu"), "vd_core", dep_cpu2core_table);\r
278         return 0;\r
279 }\r
280 \r
281 int clk_enable_dvfs(struct clk *clk)\r
282 {\r
283         struct regulator *regulator;\r
284         struct clk_node *dvfs_clk;\r
285         struct cpufreq_frequency_table clk_fv;\r
286         if (!clk) {\r
287                 DVFS_ERR("clk enable dvfs error\n");\r
288                 return -1;\r
289         }\r
290         dvfs_clk = clk_get_dvfs_info(clk);\r
291         if (!dvfs_clk || !dvfs_clk->vd) {\r
292                 DVFS_ERR("%s clk(%s) not support dvfs!\n", __func__, clk->name);\r
293                 return -1;\r
294         }\r
295         if (dvfs_clk->enable_dvfs == 0) {\r
296 \r
297                 if (!dvfs_clk->vd->regulator) {\r
298                         regulator = NULL;\r
299                         if (dvfs_clk->vd->regulator_name)\r
300                                 regulator = dvfs_regulator_get(NULL, dvfs_clk->vd->regulator_name);\r
301                         if (regulator) {\r
302                                 // DVFS_DBG("dvfs_regulator_get(%s)\n",dvfs_clk->vd->regulator_name);\r
303                                 dvfs_clk->vd->regulator = regulator;\r
304                         } else {\r
305                                 dvfs_clk->vd->regulator = NULL;\r
306                                 dvfs_clk->enable_dvfs = 0;\r
307                                 DVFS_ERR("%s can't get regulator in %s\n", dvfs_clk->name, __func__);\r
308                                 return -1;\r
309                         }\r
310                 } else {\r
311                         dvfs_clk->vd->cur_volt = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);\r
312                         // DVFS_DBG("%s(%s) vd volt=%u\n",__func__,dvfs_clk->name,dvfs_clk->vd->cur_volt);\r
313                 }\r
314 \r
315                 dvfs_clk->set_freq = dvfs_clk_get_rate_kz(clk);\r
316                 // DVFS_DBG("%s ,%s get freq%u!\n",__func__,dvfs_clk->name,dvfs_clk->set_freq);\r
317 \r
318                 if (dvfs_clk_get_ref_volt(dvfs_clk, dvfs_clk->set_freq, &clk_fv)) {\r
319                         dvfs_clk->enable_dvfs = 0;\r
320                         return -1;\r
321                 }\r
322                 dvfs_clk->set_volt = clk_fv.index;\r
323                 // DVFS_DBG("%s,%s,freq%u(ref vol %u)\n",__func__,dvfs_clk->name,\r
324                 //       dvfs_clk->set_freq,dvfs_clk->set_volt);\r
325 #if 0\r
326                 if (dvfs_clk->dvfs_nb) {\r
327                         // must unregister when clk disable\r
328                         rk30_clk_notifier_register(clk, dvfs_clk->dvfs_nb);\r
329                 }\r
330 #endif\r
331                 dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
332                 dvfs_clk->enable_dvfs++;\r
333         } else {\r
334                 DVFS_ERR("dvfs already enable clk enable = %d!\n", dvfs_clk->enable_dvfs);\r
335                 dvfs_clk->enable_dvfs++;\r
336         }\r
337         return 0;\r
338 }\r
339 \r
340 int clk_disable_dvfs(struct clk *clk)\r
341 {\r
342         struct clk_node *dvfs_clk;\r
343         dvfs_clk = clk->dvfs_info;\r
344         if (!dvfs_clk->enable_dvfs) {\r
345                 DVFS_DBG("clk is already closed!\n");\r
346                 return -1;\r
347         } else {\r
348                 dvfs_clk->enable_dvfs--;\r
349                 if (0 == dvfs_clk->enable_dvfs) {\r
350                         DVFS_ERR("clk closed!\n");\r
351                         rk30_clk_notifier_unregister(clk, dvfs_clk->dvfs_nb);\r
352                         DVFS_DBG("clk unregister nb!\n");\r
353                 }\r
354         }\r
355         return 0;\r
356 }\r
357 \r
358 static int rk_dvfs_clk_notifier_event(struct notifier_block *this,\r
359                 unsigned long event, void *ptr)\r
360 {\r
361         struct clk_notifier_data *noti_info;\r
362         struct clk *clk;\r
363         struct clk_node *dvfs_clk;\r
364         noti_info = (struct clk_notifier_data *)ptr;\r
365         clk = noti_info->clk;\r
366         dvfs_clk = clk->dvfs_info;\r
367 \r
368         switch (event) {\r
369                 case CLK_PRE_RATE_CHANGE:\r
370                         DVFS_DBG("%s CLK_PRE_RATE_CHANGE\n", __func__);\r
371                         break;\r
372                 case CLK_POST_RATE_CHANGE:\r
373                         DVFS_DBG("%s CLK_POST_RATE_CHANGE\n", __func__);\r
374                         break;\r
375                 case CLK_ABORT_RATE_CHANGE:\r
376                         DVFS_DBG("%s CLK_ABORT_RATE_CHANGE\n", __func__);\r
377                         break;\r
378                 case CLK_PRE_ENABLE:\r
379                         DVFS_DBG("%s CLK_PRE_ENABLE\n", __func__);\r
380                         break;\r
381                 case CLK_POST_ENABLE:\r
382                         DVFS_DBG("%s CLK_POST_ENABLE\n", __func__);\r
383                         break;\r
384                 case CLK_ABORT_ENABLE:\r
385                         DVFS_DBG("%s CLK_ABORT_ENABLE\n", __func__);\r
386                         break;\r
387                 case CLK_PRE_DISABLE:\r
388                         DVFS_DBG("%s CLK_PRE_DISABLE\n", __func__);\r
389                         break;\r
390                 case CLK_POST_DISABLE:\r
391                         DVFS_DBG("%s CLK_POST_DISABLE\n", __func__);\r
392                         dvfs_clk->set_freq = 0;\r
393                         break;\r
394                 case CLK_ABORT_DISABLE:\r
395                         DVFS_DBG("%s CLK_ABORT_DISABLE\n", __func__);\r
396 \r
397                         break;\r
398                 default:\r
399                         break;\r
400         }\r
401         return 0;\r
402 }\r
403 \r
404 static struct notifier_block rk_dvfs_clk_notifier = {\r
405         .notifier_call = rk_dvfs_clk_notifier_event,\r
406 };\r
407 \r
408 static struct clk_node *dvfs_get_dvfs_clk_byname(char *name)\r
409 {\r
410         struct vd_node *vd;\r
411         struct pd_node *pd;\r
412         struct clk_list *child;\r
413         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
414                 list_for_each_entry(pd, &vd->pd_list, node) {\r
415                         list_for_each_entry(child, &pd->clk_list, node) {\r
416                                 if (0 == strcmp(child->dvfs_clk->name, name)) {\r
417                                         return child->dvfs_clk;\r
418                                 }\r
419                         }\r
420                 }\r
421         }\r
422         return NULL;\r
423 }\r
424 static int rk_regist_vd(struct vd_node *vd)\r
425 {\r
426         if (!vd)\r
427                 return -1;\r
428         mutex_lock(&mutex);\r
429         mutex_init(&vd->dvfs_mutex);\r
430         list_add(&vd->node, &rk_dvfs_tree);\r
431         INIT_LIST_HEAD(&vd->pd_list);\r
432         INIT_LIST_HEAD(&vd->req_volt_list);\r
433 \r
434         mutex_unlock(&mutex);\r
435         return 0;\r
436 }\r
437 \r
438 static int rk_regist_pd(struct pd_node_lookup *pd_lookup)\r
439 {\r
440         struct vd_node  *vd;\r
441         struct pd_node  *pd;\r
442 \r
443         mutex_lock(&mutex);\r
444         pd = pd_lookup->pd;\r
445 \r
446         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
447                 if (vd == pd->vd) {\r
448                         list_add(&pd->node, &vd->pd_list);\r
449                         INIT_LIST_HEAD(&pd->clk_list);\r
450                         break;\r
451                 }\r
452         }\r
453         mutex_unlock(&mutex);\r
454         return 0;\r
455 }\r
456 \r
457 static int rk_regist_clk(struct clk_node *dvfs_clk)\r
458 {\r
459         struct pd_node  *pd;\r
460         struct clk_list *child;\r
461         struct clk      *clk;\r
462         int i = 0;\r
463 \r
464         if (!dvfs_clk)\r
465                 return -1;\r
466 \r
467         if (!dvfs_clk->pds)\r
468                 return -1;\r
469         mutex_lock(&mutex);\r
470         dvfs_clk->enable_dvfs = 0;\r
471         dvfs_clk->vd = dvfs_clk->pds[0].pd->vd;\r
472         for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {\r
473                 child = &(dvfs_clk->pds[i].clk_list);\r
474                 child->dvfs_clk = dvfs_clk;\r
475                 pd = dvfs_clk->pds[i].pd;\r
476                 list_add(&child->node, &pd->clk_list);\r
477         }\r
478         clk = dvfs_clk_get(NULL, dvfs_clk->name);\r
479         dvfs_clk->clk = clk;\r
480         clk_register_dvfs(dvfs_clk, clk);\r
481         INIT_LIST_HEAD(&dvfs_clk->depend_list);\r
482         mutex_unlock(&mutex);\r
483         return 0;\r
484 }\r
485 \r
486 static int rk_regist_depends(struct depend_lookup *dep_node)\r
487 {\r
488         struct depend_list      *depend_list;\r
489         struct clk_node         *dvfs_clk;\r
490 \r
491         if (!dep_node) {\r
492                 DVFS_ERR("%s : DVFS BAD depend node!\n", __func__);\r
493                 return -1;\r
494         }\r
495 \r
496         if (!dep_node->clk_name || !dep_node->dep_vd) {\r
497                 DVFS_ERR("%s : DVFS BAD depend members!\n", __func__);\r
498                 return -1;\r
499         }\r
500 \r
501         depend_list = &dep_node->dep_list;\r
502         dvfs_clk = dvfs_get_dvfs_clk_byname(dep_node->clk_name);\r
503 \r
504         mutex_lock(&mutex);\r
505 \r
506         depend_list->dvfs_clk = dvfs_clk;\r
507         depend_list->dep_vd = dep_node->dep_vd;\r
508         depend_list->dep_table = dep_node->dep_table;\r
509 \r
510         list_add(&depend_list->node2clk, &dvfs_clk->depend_list);\r
511         list_add(&depend_list->node2vd, &depend_list->dep_vd->req_volt_list);\r
512 \r
513         mutex_unlock(&mutex);\r
514         return 0;\r
515 }\r
516 \r
517 #define get_volt_up_delay(new_volt, old_volt)   \\r
518         ((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 10) : 0)\r
519 \r
520 static int dvfs_set_depend_pre(struct clk_node *dvfs_clk, unsigned long rate_old, unsigned long rate_new)\r
521 {\r
522         struct depend_list      *depend;\r
523         struct cpufreq_frequency_table  clk_fv;\r
524         int ret = -1;\r
525         int volt = 0;\r
526         struct regulator *regulator;\r
527 \r
528         if (rate_old >= rate_new) {\r
529                 return 0;\r
530         }\r
531         list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {\r
532                 ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv);\r
533                 if (ret != 0) {\r
534                         DVFS_ERR("%s LOGIC DVFS CAN NOT GET REF VOLT!, frequency too large!\n", __func__);\r
535                         return -1;\r
536                 }\r
537 \r
538                 if (!depend->dep_vd->regulator) {\r
539                         DVFS_LOG("%s regulator empty\n", __func__);\r
540                         regulator = dvfs_regulator_get(NULL, depend->dep_vd->regulator_name);\r
541                         if (!regulator) {\r
542                                 DVFS_ERR("%s get regulator err\n", __func__);\r
543                                 return -1;\r
544                         }\r
545 \r
546                         depend->dep_vd->regulator = regulator;\r
547                 }\r
548                 if (!depend->dep_vd->regulator) {\r
549                         DVFS_ERR("%s vd's(%s) regulator empty\n", __func__, depend->dep_vd->name);\r
550                         return -1;\r
551                 }\r
552 \r
553                 if (clk_fv.index == dvfs_regulator_get_voltage(depend->dep_vd->regulator)) {\r
554                         depend->req_volt = clk_fv.index;\r
555                         DVFS_LOG("%s same voltage\n", __func__);\r
556                         return 0;\r
557                 }\r
558 \r
559                 depend->req_volt = clk_fv.index;\r
560                 volt = dvfs_vd_get_newvolt_bypd(depend->dep_vd);\r
561                 DVFS_LOG("%s setting voltage = %d\n", __func__, volt);\r
562                 ret = dvfs_regulator_set_voltage(depend->dep_vd->regulator, volt, volt);\r
563                 if (0 != ret) {\r
564                         DVFS_ERR("%s set voltage = %d ERROR, ret = %d\n", __func__, volt, ret);\r
565                         return -1;\r
566                 }\r
567                 udelay(200);\r
568                 DVFS_LOG("%s set voltage = %d OK, ret = %d\n", __func__, volt, ret);\r
569                 if (ret != 0) {\r
570                         DVFS_ERR("%s err, ret = %d\n", __func__, ret);\r
571                         return -1;\r
572                 }\r
573         }\r
574 \r
575         return 0;\r
576 }\r
577 \r
578 static int dvfs_set_depend_post(struct clk_node *dvfs_clk, unsigned long rate_old, unsigned long rate_new)\r
579 {\r
580         struct depend_list      *depend;\r
581         struct cpufreq_frequency_table  clk_fv;\r
582         int ret = -1;\r
583         int volt = 0;\r
584         struct regulator *regulator;\r
585 \r
586         if (rate_old <= rate_new) \r
587                 return 0;\r
588         list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {\r
589                 ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv);\r
590                 if (ret != 0) {\r
591                         DVFS_ERR("%s LOGIC DVFS CAN NOT GET REF VOLT!, frequency too large!\n", __func__);\r
592                         return -1;\r
593                 }\r
594 \r
595                 if (!depend->dep_vd->regulator) {\r
596                         DVFS_LOG("%s regulator empty\n", __func__);\r
597                         regulator = dvfs_regulator_get(NULL, depend->dep_vd->regulator_name);\r
598                         if (!regulator) {\r
599                                 DVFS_ERR("%s get regulator err\n", __func__);\r
600                                 return -1;\r
601                         }\r
602 \r
603                         depend->dep_vd->regulator = regulator;\r
604                 }\r
605                 if (!depend->dep_vd->regulator) {\r
606                         DVFS_ERR("%s vd's(%s) regulator empty\n", __func__, depend->dep_vd->name);\r
607                         return -1;\r
608                 }\r
609 \r
610                 if (clk_fv.index == dvfs_regulator_get_voltage(depend->dep_vd->regulator)) {\r
611                         depend->req_volt = clk_fv.index;\r
612                         DVFS_LOG("%s same voltage\n", __func__);\r
613                         return 0;\r
614                 }\r
615 \r
616                 depend->req_volt = clk_fv.index;\r
617                 volt = dvfs_vd_get_newvolt_bypd(depend->dep_vd);\r
618                 DVFS_LOG("%s setting voltage = %d\n", __func__, volt);\r
619                 ret = dvfs_regulator_set_voltage(depend->dep_vd->regulator, volt, volt);\r
620                 if (0 != ret) {\r
621                         DVFS_ERR("%s set voltage = %d ERROR, ret = %d\n", __func__, volt, ret);\r
622                         return -1;\r
623                 }\r
624                 udelay(200);\r
625                 DVFS_LOG("%s set voltage = %d OK, ret = %d\n", __func__, volt, ret);\r
626                 if (ret != 0) {\r
627                         DVFS_ERR("%s err, ret = %d\n", __func__, ret);\r
628                         return -1;\r
629                 }\r
630         }\r
631 \r
632         return 0;\r
633 }\r
634 \r
635 static int flag_core_set_volt_err = 0;\r
636 int dvfs_target_core(struct clk *clk, unsigned long rate_hz)\r
637 {\r
638         struct clk_node *dvfs_clk;\r
639         unsigned int volt_new = 0, volt_old = 0, volt_clk_old = 0;\r
640         struct cpufreq_frequency_table clk_fv = {0, 0};\r
641         int ret = 0;\r
642         int flag_set_volt_correct = 0;\r
643         unsigned long rate_new, rate_old;\r
644 \r
645         if (!clk) {\r
646                 DVFS_ERR("%s is not clk\n", __func__);\r
647                 return -1;\r
648         }\r
649         dvfs_clk = clk_get_dvfs_info(clk);\r
650 \r
651         if (!dvfs_clk || dvfs_clk->vd->regulator == NULL) {\r
652                 DVFS_ERR("%s can't get dvfs regulater\n", clk->name);\r
653                 return -1;\r
654         }\r
655 \r
656         // clk_round_rate_nolock(clk, rate_hz);\r
657         rate_new = rate_hz;\r
658         rate_old = clk_get_rate(clk);\r
659 \r
660         // DVFS_DBG("dvfs(%s) round rate(%lu)(rount %lu)\n",dvfs_clk->name,rate_hz,rate_new);\r
661 \r
662         /* find the clk corresponding voltage */\r
663         if (dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {\r
664                 DVFS_ERR("%s--%s:rate%lu,Get corresponding voltage error!\n", \r
665                                 __func__, dvfs_clk->name, rate_new);\r
666                 return -1;\r
667         }\r
668         volt_old = dvfs_clk->vd->cur_volt;\r
669 \r
670         volt_clk_old = dvfs_clk->set_volt;\r
671 \r
672         dvfs_clk->set_volt = clk_fv.index;\r
673 \r
674         volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
675 \r
676         DVFS_DBG("dvfs--(%s),volt=%d(was %dmV),rate=%lu(was %lu),vd%u=(was%u)\n",\r
677                         dvfs_clk->name, clk_fv.index, dvfs_clk->set_volt, rate_new, rate_old\r
678                         , volt_new, volt_old);\r
679 \r
680         if (flag_core_set_volt_err) {\r
681                 /* It means the last time set voltage error */  \r
682                 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);\r
683                 if (flag_set_volt_correct <= 0) {\r
684                         DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload core_volt error %d!!! stop scaling\n", \r
685                                         __func__, dvfs_clk->name, volt_new, volt_old, \r
686                                         rate_new, rate_old, flag_set_volt_correct);\r
687                         return -1;\r
688                 }\r
689 \r
690                 flag_core_set_volt_err = 0;\r
691                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload core_volt! core_volt_correct = %d\n", \r
692                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
693                                 rate_new, rate_old, flag_set_volt_correct);\r
694 \r
695                 /* Reset vd's voltage */\r
696                 dvfs_clk->vd->cur_volt = flag_set_volt_correct;\r
697                 volt_old = dvfs_clk->vd->cur_volt;\r
698         }\r
699 \r
700         /* if up the voltage */\r
701         if (volt_old < volt_new) {\r
702                 if (dvfs_clk->vd->regulator) {\r
703                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
704                         if (ret < 0) {\r
705                                 flag_core_set_volt_err = 1;\r
706                                 DVFS_ERR("%s %s set voltage up err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
707                                                 __func__, dvfs_clk->name, ret, \r
708                                                 rate_new, rate_old, volt_new, volt_old);\r
709                                 return -1;\r
710                         }\r
711 \r
712                 } else {\r
713                         DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
714                         return -1;\r
715                 }\r
716 \r
717                 dvfs_clk->vd->cur_volt = volt_new;\r
718                 udelay(get_volt_up_delay(volt_new, volt_old));\r
719                 DVFS_DBG("%s %s set voltage OK up ret = %d, Vnew = %d(was %d), Rnew = %lu(was %lu)\n", \r
720                                 __func__, dvfs_clk->name, ret, volt_new, volt_old, rate_new, rate_old);\r
721         }\r
722 \r
723         if (dvfs_clk->clk_dvfs_target) {\r
724                 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);\r
725         } else {\r
726                 ret = clk_set_rate_locked(clk, rate_new);\r
727         }\r
728 \r
729         if (ret < 0) {\r
730 \r
731                 dvfs_clk->set_volt = volt_old;\r
732                 dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
733                 DVFS_ERR("set rate err\n");\r
734                 return -1;\r
735         }\r
736         dvfs_clk->set_freq      = rate_new / 1000;\r
737 \r
738         /* if down the voltage */\r
739         if (volt_old > volt_new) {\r
740                 if (dvfs_clk->vd->regulator) {\r
741                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
742                         if (ret < 0) {\r
743                                 flag_core_set_volt_err = 1;\r
744                                 DVFS_ERR("%s %s set voltage down err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
745                                                 __func__, dvfs_clk->name, ret, rate_new, rate_old, \r
746                                                 volt_new, volt_old);\r
747                                 return -1;\r
748                         }\r
749 \r
750                 } else {\r
751                         DVFS_ERR("%s down volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
752                         return -1;\r
753                 }\r
754 \r
755                 dvfs_clk->vd->cur_volt = volt_new;\r
756                 DVFS_DBG("dvfs %s set volt ok dn\n", dvfs_clk->name);\r
757 \r
758         }\r
759 \r
760         return 0;\r
761 }\r
762 \r
763 static int flag_arm_set_volt_err = 0;\r
764 int dvfs_target_cpu(struct clk *clk, unsigned long rate_hz)\r
765 {\r
766         struct clk_node *dvfs_clk;\r
767         int volt_new = 0, volt_old = 0;\r
768         struct cpufreq_frequency_table clk_fv;\r
769         int ret = 0;\r
770         int flag_set_volt_correct = 0;\r
771         unsigned long rate_new, rate_old;\r
772 \r
773 \r
774         if (!clk) {\r
775                 DVFS_ERR("%s is not clk\n", __func__);\r
776                 return -1;\r
777         }\r
778         dvfs_clk = clk_get_dvfs_info(clk);\r
779 \r
780         if (!dvfs_clk || dvfs_clk->vd->regulator == NULL) {\r
781                 DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);\r
782                 return -1;\r
783         }\r
784 \r
785         /* need round rate */\r
786         rate_new = clk_round_rate_nolock(clk, rate_hz);\r
787         DVFS_DBG("dvfs(%s) round rate (%lu)(rount %lu)\n", dvfs_clk->name, rate_hz, rate_new);\r
788 \r
789         rate_old = clk_get_rate(clk);\r
790         /* find the clk corresponding voltage */\r
791         if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {\r
792                 DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
793                 return -1;\r
794         }\r
795 \r
796         volt_old = dvfs_clk->vd->cur_volt;\r
797         volt_new = clk_fv.index;\r
798         if (flag_arm_set_volt_err) {\r
799                 /* It means the last time set voltage error */\r
800                 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);\r
801                 if (flag_set_volt_correct <= 0) {\r
802                         DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload arm_volt error %d!!! stop scaling\n", \r
803                                         __func__, dvfs_clk->name, volt_new, volt_old, \r
804                                         rate_new, rate_old, flag_set_volt_correct);\r
805                         return -1;\r
806                 }\r
807 \r
808                 flag_arm_set_volt_err = 0;\r
809                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload arm_volt! arm_volt_correct = %d\n", \r
810                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
811                                 rate_new, rate_old, flag_set_volt_correct);\r
812 \r
813                 /* Reset vd's voltage */\r
814                 dvfs_clk->vd->cur_volt = flag_set_volt_correct;\r
815                 volt_old = dvfs_clk->vd->cur_volt;\r
816         }\r
817 \r
818         /* if up the voltage */\r
819         if (volt_old < volt_new) {\r
820                 if (dvfs_clk->vd->regulator) {\r
821                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
822                         if (ret < 0) {\r
823                                 flag_arm_set_volt_err = 1;\r
824                                 DVFS_ERR("%s %s set voltage up err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
825                                                 __func__, dvfs_clk->name, ret, rate_new, rate_old, \r
826                                                 volt_new, volt_old);\r
827                                 return -1;\r
828                         }\r
829 \r
830                 } else {\r
831                         DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
832                         return -1;\r
833                 }\r
834 \r
835                 dvfs_clk->vd->cur_volt = volt_new;\r
836                 udelay(get_volt_up_delay(volt_new, volt_old));\r
837                 DVFS_DBG("%s %s set voltage OK up ret = %d, Vnew = %d(was %d), Rnew = %lu(was %lu)\n", \r
838                                 __func__, dvfs_clk->name, ret, volt_new, volt_old, rate_new, rate_old);\r
839         }\r
840         \r
841         /* depend voltage domain set up*/\r
842         if (0 != dvfs_set_depend_pre(dvfs_clk, rate_old, rate_new)) {\r
843                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), set depend pre voltage err, stop scaling\n", \r
844                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
845                                 rate_new, rate_old);\r
846                 return -1;\r
847         }\r
848 \r
849         if (dvfs_clk->clk_dvfs_target) {\r
850                 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);\r
851         } else {\r
852                 ret = clk_set_rate_locked(clk, rate_new);\r
853         }\r
854 \r
855         if (ret < 0) {\r
856                 DVFS_ERR("set rate err\n");\r
857                 return -1;\r
858         }\r
859         dvfs_clk->set_freq      = rate_new / 1000;\r
860 \r
861         DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));\r
862 \r
863         /* depend voltage domain set down*/\r
864         if (0 != dvfs_set_depend_post(dvfs_clk, rate_old, rate_new)) {\r
865                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), set depend post voltage  err, stop scaling\n", \r
866                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
867                                 rate_new, rate_old);\r
868                 return -1;\r
869         }\r
870 \r
871         /* if down the voltage */\r
872         if (volt_old > volt_new) {\r
873                 if (dvfs_clk->vd->regulator) {\r
874                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
875                         if (ret < 0) {\r
876                                 flag_arm_set_volt_err = 1;\r
877                                 DVFS_ERR("%s %s set voltage down err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
878                                                 __func__, dvfs_clk->name, ret, rate_new, rate_old, \r
879                                                 volt_new, volt_old);\r
880                                 return -1;\r
881                         }\r
882 \r
883                 } else {\r
884                         DVFS_ERR("%s down volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
885                         return -1;\r
886                 }\r
887 \r
888                 dvfs_clk->vd->cur_volt = volt_new;\r
889                 DVFS_DBG("dvfs %s set volt ok dn\n", dvfs_clk->name);\r
890 \r
891         }\r
892 \r
893         return ret;\r
894 }\r
895 \r
896 \r
897 \r
898 /*****************************init**************************/\r
899 /**\r
900  * rate must be raising sequence\r
901  */\r
902 static struct cpufreq_frequency_table cpu_dvfs_table[] = {\r
903         // {.frequency  = 48 * DVFS_KHZ, .index = 920*DVFS_MV},\r
904         // {.frequency  = 126 * DVFS_KHZ, .index        = 970 * DVFS_MV},\r
905         // {.frequency  = 252 * DVFS_KHZ, .index        = 1040 * DVFS_MV},\r
906         // {.frequency  = 504 * DVFS_KHZ, .index        = 1050 * DVFS_MV},\r
907         {.frequency     = 816 * DVFS_KHZ, .index        = 1050 * DVFS_MV},\r
908         // {.frequency  = 1008 * DVFS_KHZ, .index       = 1100 * DVFS_MV},\r
909         {.frequency     = CPUFREQ_TABLE_END},\r
910 };\r
911 \r
912 static struct cpufreq_frequency_table ddr_dvfs_table[] = {\r
913         // {.frequency = 100 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
914         {.frequency = 200 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
915         {.frequency = 300 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
916         {.frequency = 400 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
917         {.frequency = 500 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
918         {.frequency = 600 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
919         {.frequency = CPUFREQ_TABLE_END},\r
920 };\r
921 \r
922 static struct cpufreq_frequency_table gpu_dvfs_table[] = {\r
923         {.frequency = 100 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
924         {.frequency = 200 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
925         {.frequency = 300 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
926         {.frequency = 400 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
927         {.frequency = 500 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
928         {.frequency = CPUFREQ_TABLE_END},\r
929 };\r
930 \r
931 static struct cpufreq_frequency_table peri_aclk_dvfs_table[] = {\r
932         {.frequency = 100 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
933         {.frequency = 200 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
934         {.frequency = 300 * DVFS_KHZ, .index = 1070 * DVFS_MV},\r
935         {.frequency = 500 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
936         {.frequency = CPUFREQ_TABLE_END},\r
937 };\r
938 \r
939 static struct cpufreq_frequency_table dep_cpu2core_table[] = {\r
940         // {.frequency = 252 * DVFS_KHZ, .index    = 1025 * DVFS_MV},\r
941         // {.frequency = 504 * DVFS_KHZ, .index    = 1025 * DVFS_MV},\r
942         {.frequency = 816 * DVFS_KHZ, .index    = 1050 * DVFS_MV},//logic 1.050V\r
943         // {.frequency = 1008 * DVFS_KHZ,.index    = 1050 * DVFS_MV},\r
944         // {.frequency = 1200 * DVFS_KHZ,.index    = 1050 * DVFS_MV},\r
945         // {.frequency = 1272 * DVFS_KHZ,.index    = 1050 * DVFS_MV},//logic 1.050V\r
946         // {.frequency = 1416 * DVFS_KHZ,.index    = 1100 * DVFS_MV},//logic 1.100V\r
947         // {.frequency = 1512 * DVFS_KHZ,.index    = 1125 * DVFS_MV},//logic 1.125V\r
948         // {.frequency = 1608 * DVFS_KHZ,.index    = 1175 * DVFS_MV},//logic 1.175V\r
949         {.frequency     = CPUFREQ_TABLE_END},\r
950 };\r
951 \r
952 static struct vd_node vd_cpu = {\r
953         .name           = "vd_cpu",\r
954         .regulator_name = "vdd_cpu",\r
955         .vd_dvfs_target = dvfs_target_cpu,\r
956 };\r
957 \r
958 static struct vd_node vd_core = {\r
959         .name           = "vd_core",\r
960         .regulator_name = "vdd_core",\r
961         .vd_dvfs_target = dvfs_target_core,\r
962 };\r
963 \r
964 static struct vd_node vd_rtc = {\r
965         .name           = "vd_rtc",\r
966         .regulator_name = "vdd_rtc",\r
967         .vd_dvfs_target = NULL,\r
968 };\r
969 \r
970 static struct vd_node *rk30_vds[] = {&vd_cpu, &vd_core, &vd_rtc};\r
971 \r
972 static struct pd_node pd_a9_0 = {\r
973         .name                   = "pd_a9_0",\r
974         .vd                     = &vd_cpu,\r
975 };\r
976 static struct pd_node pd_a9_1 = {\r
977         .name                   = "pd_a9_1",\r
978         .vd                     = &vd_cpu,\r
979 };\r
980 static struct pd_node pd_debug = {\r
981         .name                   = "pd_debug",\r
982         .vd                     = &vd_cpu,\r
983 };\r
984 static struct pd_node pd_scu = {\r
985         .name                   = "pd_scu",\r
986         .vd                     = &vd_cpu,\r
987 };\r
988 static struct pd_node pd_video = {\r
989         .name                   = "pd_video",\r
990         .vd                     = &vd_core,\r
991 };\r
992 static struct pd_node pd_vio = {\r
993         .name                   = "pd_vio",\r
994         .vd                     = &vd_core,\r
995 };\r
996 static struct pd_node pd_gpu = {\r
997         .name                   = "pd_gpu",\r
998         .vd                     = &vd_core,\r
999 };\r
1000 static struct pd_node pd_peri = {\r
1001         .name                   = "pd_peri",\r
1002         .vd                     = &vd_core,\r
1003 };\r
1004 static struct pd_node pd_cpu = {\r
1005         .name                   = "pd_cpu",\r
1006         .vd                     = &vd_core,\r
1007 };\r
1008 static struct pd_node pd_alive = {\r
1009         .name                   = "pd_alive",\r
1010         .vd                     = &vd_core,\r
1011 };\r
1012 static struct pd_node pd_rtc = {\r
1013         .name                   = "pd_rtc",\r
1014         .vd                     = &vd_rtc,\r
1015 };\r
1016 #define LOOKUP_PD(_ppd) \\r
1017 {       \\r
1018         .pd     = _ppd, \\r
1019 }\r
1020 static struct pd_node_lookup rk30_pds[] = {\r
1021         LOOKUP_PD(&pd_a9_0),\r
1022         LOOKUP_PD(&pd_a9_1),\r
1023         LOOKUP_PD(&pd_debug),\r
1024         LOOKUP_PD(&pd_scu),\r
1025         LOOKUP_PD(&pd_video),\r
1026         LOOKUP_PD(&pd_vio),\r
1027         LOOKUP_PD(&pd_gpu),\r
1028         LOOKUP_PD(&pd_peri),\r
1029         LOOKUP_PD(&pd_cpu),\r
1030         LOOKUP_PD(&pd_alive),\r
1031         LOOKUP_PD(&pd_rtc),\r
1032 };\r
1033 \r
1034 #define CLK_PDS(_ppd) \\r
1035 {       \\r
1036         .pd     = _ppd, \\r
1037 }\r
1038 \r
1039 static struct pds_list cpu_pds[] = {\r
1040         CLK_PDS(&pd_a9_0),\r
1041         CLK_PDS(&pd_a9_1),\r
1042         CLK_PDS(NULL),\r
1043 };\r
1044 \r
1045 static struct pds_list ddr_pds[] = {\r
1046         CLK_PDS(&pd_cpu),\r
1047         CLK_PDS(NULL),\r
1048 };\r
1049 \r
1050 static struct pds_list gpu_pds[] = {\r
1051         CLK_PDS(&pd_gpu),\r
1052         CLK_PDS(NULL),\r
1053 };\r
1054 \r
1055 static struct pds_list aclk_periph_pds[] = {\r
1056         CLK_PDS(&pd_peri),\r
1057         CLK_PDS(NULL),\r
1058 };\r
1059 \r
1060 #define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb) \\r
1061 { \\r
1062         .name   = _clk_name, \\r
1063         .pds = _ppds,\\r
1064         .dvfs_table = _dvfs_table,      \\r
1065         .dvfs_nb        = _dvfs_nb,     \\r
1066 }\r
1067 \r
1068 static struct clk_node rk30_clks[] = {\r
1069         RK_CLKS("cpu", cpu_pds, cpu_dvfs_table, &rk_dvfs_clk_notifier),\r
1070         RK_CLKS("ddr", ddr_pds, ddr_dvfs_table, &rk_dvfs_clk_notifier),\r
1071         RK_CLKS("gpu", gpu_pds, gpu_dvfs_table, &rk_dvfs_clk_notifier),\r
1072         RK_CLKS("aclk_periph", aclk_periph_pds, peri_aclk_dvfs_table, &rk_dvfs_clk_notifier),\r
1073 };\r
1074 \r
1075 #define RK_DEPPENDS(_clk_name, _pvd, _dep_table) \\r
1076 { \\r
1077         .clk_name       = _clk_name, \\r
1078         .dep_vd         = _pvd,\\r
1079         .dep_table      = _dep_table,   \\r
1080 }\r
1081 \r
1082 static struct depend_lookup rk30_depends[] = {\r
1083         RK_DEPPENDS("cpu", &vd_core, dep_cpu2core_table),\r
1084 };\r
1085 \r
1086 int rk30_dvfs_init(void)\r
1087 {\r
1088         int i = 0;\r
1089         for (i = 0; i < ARRAY_SIZE(rk30_vds); i++) {\r
1090                 rk_regist_vd(rk30_vds[i]);\r
1091         }\r
1092         for (i = 0; i < ARRAY_SIZE(rk30_pds); i++) {\r
1093                 rk_regist_pd(&rk30_pds[i]);\r
1094         }\r
1095         for (i = 0; i < ARRAY_SIZE(rk30_clks); i++) {\r
1096                 rk_regist_clk(&rk30_clks[i]);\r
1097         }\r
1098         for (i = 0; i < ARRAY_SIZE(rk30_depends); i++) {\r
1099                 rk_regist_depends(&rk30_depends[i]);\r
1100         }\r
1101 #ifdef DVFS_DUMP_TREE\r
1102         dump_dbg_map();\r
1103 #endif\r
1104         return 0;\r
1105 }\r
1106 \r
1107 #ifdef DVFS_DUMP_TREE\r
1108 /**\r
1109  * dump_dbg_map() : Draw all informations of dvfs while debug\r
1110  */\r
1111 static void dump_dbg_map(void)\r
1112 {\r
1113         int i;\r
1114         struct vd_node  *vd;\r
1115         struct pd_node  *pd, *clkparent;\r
1116         struct clk_list *child;\r
1117         struct clk_node *dvfs_clk;\r
1118         struct depend_list *depend;\r
1119 \r
1120         DVFS_LOG("-------------DVFS DEBUG-----------\n\n\n");\r
1121         DVFS_LOG("RK30 DVFS TREE:\n");\r
1122         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
1123                 DVFS_LOG("|\n|- voltage domain:%s\n", vd->name);\r
1124                 DVFS_LOG("|- current voltage:%d\n", vd->cur_volt);\r
1125                 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {\r
1126                         DVFS_LOG("|- request voltage:%d, clk:%s\n", depend->req_volt, depend->dvfs_clk->name);\r
1127                 }\r
1128 \r
1129                 list_for_each_entry(pd, &vd->pd_list, node) {\r
1130                         DVFS_LOG("|  |\n|  |- power domain:%s, status = %s, current volt = %d\n",\r
1131                                         pd->name, (pd->pd_status == PD_ON) ? "ON" : "OFF", pd->cur_volt);\r
1132 \r
1133                         list_for_each_entry(child, &pd->clk_list, node) {\r
1134                                 dvfs_clk = child->dvfs_clk;\r
1135                                 DVFS_LOG("|  |  |\n|  |  |- clock: %s current: rate %d, volt = %d, enable_dvfs = %s\n",\r
1136                                                 dvfs_clk->name, dvfs_clk->set_freq, dvfs_clk->set_volt, \r
1137                                                 dvfs_clk->enable_dvfs == 0 ? "DISABLE" : "ENABLE");\r
1138                                 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {\r
1139                                         clkparent = dvfs_clk->pds[i].pd;\r
1140                                         DVFS_LOG("|  |  |  |- clock parents: %s, vd_parent = %s\n", \r
1141                                                         clkparent->name, clkparent->vd->name);\r
1142                                 }\r
1143 \r
1144                                 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
1145                                         DVFS_LOG("|  |  |  |- freq = %d, volt = %d\n", \r
1146                                                         dvfs_clk->dvfs_table[i].frequency, \r
1147                                                         dvfs_clk->dvfs_table[i].index);\r
1148 \r
1149                                 }\r
1150 \r
1151                                 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {\r
1152                                         DVFS_LOG("|  |  |  |  |- DEPEND VD: %s\n", depend->dep_vd->name); \r
1153                                         for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
1154                                                 DVFS_LOG("|  |  |  |  |- freq = %d, req_volt = %d\n", \r
1155                                                                 depend->dep_table[i].frequency, \r
1156                                                                 depend->dep_table[i].index);\r
1157 \r
1158                                         }\r
1159                                 }\r
1160                         }\r
1161                 }\r
1162         }\r
1163         DVFS_LOG("-------------DVFS DEBUG END------------\n");\r
1164 }\r
1165 #endif\r
1166 \r
1167 \r
1168 \r