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