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