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