a15998c9bd125d359c5043a875866dee5d189699
[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 JUMP_RATE 816000000\r
30 #define LOGIC_VOLT_SCALING\r
31 #define DVFS_DBG(fmt, args...) {while(0);}      //pr_debug(fmt, ##args)\r
32 #define DVFS_ERR(fmt, args...) pr_err(fmt, ##args)\r
33 #define DVFS_LOG(fmt, args...) pr_debug(fmt, ##args)//while(0)\r
34 \r
35 #define dvfs_regulator_get(dev,id) regulator_get((dev),(id))\r
36 #define dvfs_regulator_put(regu) regulator_put((regu))\r
37 #define dvfs_regulator_set_voltage(regu,min_uV,max_uV) regulator_set_voltage((regu),(min_uV),(max_uV))\r
38 #define dvfs_regulator_get_voltage(regu) regulator_get_voltage((regu))\r
39 \r
40 #define dvfs_clk_get(a,b) clk_get((a),(b))\r
41 #define dvfs_clk_get_rate_kz(a) (clk_get_rate((a))/1000)\r
42 #define dvfs_clk_set_rate(a,b) clk_set_rate((a),(b))\r
43 #define dvfs_clk_enable(a) clk_enable((a))\r
44 #define dvfs_clk_disable(a) clk_disable((a))\r
45 \r
46 #define DVFS_MHZ (1000*1000)\r
47 #define DVFS_KHZ (1000)\r
48 \r
49 #define DVFS_V (1000*1000)\r
50 #define DVFS_MV (1000)\r
51 \r
52 \r
53 static LIST_HEAD(rk_dvfs_tree);\r
54 static DEFINE_MUTEX(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 PD_ON   1\r
60 #define PD_OFF  0\r
61 \r
62 int is_support_dvfs(struct clk_node *dvfs_info)\r
63 {\r
64         return (dvfs_info->vd && dvfs_info->vd->vd_dvfs_target && dvfs_info->enable_dvfs);\r
65 }\r
66 \r
67 int dvfs_set_rate(struct clk *clk, unsigned long rate)\r
68 {\r
69         int ret = 0;\r
70         struct vd_node *vd;\r
71         DVFS_DBG("%s(%s(%lu))\n", __func__, clk->name, rate);\r
72         if (!clk->dvfs_info) {\r
73                 DVFS_ERR("%s :This clk do not support dvfs!\n", __func__);\r
74                 ret = -1;\r
75         } else {\r
76                 vd = clk->dvfs_info->vd;\r
77                 mutex_lock(&vd->dvfs_mutex);\r
78                 ret = vd->vd_dvfs_target(clk, rate);\r
79                 mutex_unlock(&vd->dvfs_mutex);\r
80         }\r
81         DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);\r
82         return ret;\r
83 }\r
84 \r
85 static int dvfs_clk_get_ref_volt(struct clk_node *dvfs_clk, int rate_khz,\r
86                 struct cpufreq_frequency_table *clk_fv)\r
87 {\r
88         int i = 0;\r
89         if (rate_khz == 0 || !dvfs_clk || !dvfs_clk->dvfs_table) {\r
90                 /* since no need*/\r
91                 return -1;\r
92         }\r
93         clk_fv->frequency = rate_khz;\r
94         clk_fv->index = 0;\r
95 \r
96         for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
97                 if (dvfs_clk->dvfs_table[i].frequency >= rate_khz) {\r
98                         clk_fv->frequency = dvfs_clk->dvfs_table[i].frequency;\r
99                         clk_fv->index = dvfs_clk->dvfs_table[i].index;\r
100                         // DVFS_DBG("%s,%s rate=%ukhz(vol=%d)\n",__func__,dvfs_clk->name, \r
101                         // clk_fv->frequency, clk_fv->index);\r
102                         return 0;\r
103                 }\r
104         }\r
105         clk_fv->frequency = 0;\r
106         clk_fv->index = 0;\r
107         // DVFS_DBG("%s get corresponding voltage error! out of bound\n", dvfs_clk->name);\r
108         return -1;\r
109 }\r
110 \r
111 static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct clk_node *dvfs_clk)\r
112 {\r
113         struct clk_list *child;\r
114         int volt_max = 0;\r
115 \r
116         if (!pd || !dvfs_clk)\r
117                 return 0;\r
118 \r
119         if (dvfs_clk->set_volt >= pd->cur_volt) {\r
120                 return dvfs_clk->set_volt;\r
121         }\r
122 \r
123         list_for_each_entry(child, &pd->clk_list, node) {\r
124                 //DVFS_DBG("%s ,pd(%s),dvfs(%s),volt(%u)\n",__func__,pd->name,\r
125                 //dvfs_clk->name,dvfs_clk->set_volt);\r
126                 volt_max = max(volt_max, child->dvfs_clk->set_volt);\r
127         }\r
128         return volt_max;\r
129 }\r
130 \r
131 void dvfs_update_clk_pds_volt(struct clk_node *dvfs_clk)\r
132 {\r
133         struct pd_node   *pd;\r
134         int i;\r
135         if (!dvfs_clk)\r
136                 return;\r
137         for (i = 0; (dvfs_clk->pds[i].pd != NULL); i++) {\r
138                 pd = dvfs_clk->pds[i].pd;\r
139                 // DVFS_DBG("%s dvfs(%s),pd(%s)\n",__func__,dvfs_clk->name,pd->name);\r
140                 pd->cur_volt = dvfs_pd_get_newvolt_byclk(pd, dvfs_clk);\r
141         }\r
142 }\r
143 \r
144 static int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)\r
145 {\r
146         struct pd_node *pd;\r
147         int     volt_max_vd = 0;\r
148         list_for_each_entry(pd, &vd->pd_list, node) {\r
149                 //DVFS_DBG("%s pd(%s,%u)\n",__func__,pd->name,pd->cur_volt);\r
150                 volt_max_vd = max(volt_max_vd, pd->cur_volt);\r
151         }\r
152         return volt_max_vd;\r
153 }\r
154 \r
155 static int dvfs_vd_get_newvolt_byclk(struct clk_node *dvfs_clk)\r
156 {\r
157         if (!dvfs_clk)\r
158                 return -1;\r
159         dvfs_update_clk_pds_volt(dvfs_clk);\r
160         return  dvfs_vd_get_newvolt_bypd(dvfs_clk->vd);\r
161 }\r
162 \r
163 void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target)\r
164 {\r
165         struct clk_node *dvfs_clk = clk_get_dvfs_info(clk);\r
166         dvfs_clk->clk_dvfs_target = clk_dvfs_target;\r
167 }\r
168 \r
169 struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk) \r
170 {\r
171         struct clk_node *info = clk_get_dvfs_info(clk);\r
172         struct cpufreq_frequency_table *table;\r
173         if (!info || !info->dvfs_table) {\r
174                 return NULL;\r
175         }\r
176         mutex_lock(&mutex);\r
177         table = info->dvfs_table;\r
178         mutex_unlock(&mutex);\r
179         return table;\r
180 }\r
181 \r
182 int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table)\r
183 {\r
184         struct clk_node *info = clk_get_dvfs_info(clk);\r
185         if (!table || !info)\r
186                 return -1;\r
187 \r
188         mutex_lock(&mutex);\r
189         info->dvfs_table = table;\r
190         mutex_unlock(&mutex);\r
191         return 0;\r
192 }\r
193 \r
194 int clk_enable_dvfs(struct clk *clk)\r
195 {\r
196         struct regulator *regulator;\r
197         struct clk_node *dvfs_clk;\r
198         struct cpufreq_frequency_table clk_fv;\r
199         if (!clk) {\r
200                 DVFS_ERR("clk enable dvfs error\n");\r
201                 return -1;\r
202         }\r
203         dvfs_clk = clk_get_dvfs_info(clk);\r
204         if (!dvfs_clk || !dvfs_clk->vd) {\r
205                 DVFS_ERR("%s clk(%s) not support dvfs!\n", __func__, clk->name);\r
206                 return -1;\r
207         }\r
208         if (dvfs_clk->enable_dvfs == 0) {\r
209 \r
210                 if (!dvfs_clk->vd->regulator) {\r
211                         regulator = NULL;\r
212                         if (dvfs_clk->vd->regulator_name)\r
213                                 regulator = dvfs_regulator_get(NULL, dvfs_clk->vd->regulator_name);\r
214                         if (regulator) {\r
215                                 //DVFS_DBG("dvfs_regulator_get(%s)\n",dvfs_clk->vd->regulator_name);\r
216                                 dvfs_clk->vd->regulator = regulator;\r
217                         } else {\r
218                                 dvfs_clk->vd->regulator = NULL;\r
219                                 dvfs_clk->enable_dvfs = 0;\r
220                                 DVFS_ERR("%s can't get regulator in %s\n", dvfs_clk->name, __func__);\r
221                                 return -1;\r
222                         }\r
223                 } else {\r
224                         dvfs_clk->vd->cur_volt = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);\r
225                         //DVFS_DBG("%s(%s) vd volt=%u\n",__func__,dvfs_clk->name,dvfs_clk->vd->cur_volt);\r
226                 }\r
227 \r
228                 dvfs_clk->set_freq = dvfs_clk_get_rate_kz(clk);\r
229                 //DVFS_DBG("%s ,%s get freq%u!\n",__func__,dvfs_clk->name,dvfs_clk->set_freq);\r
230 \r
231                 if (dvfs_clk_get_ref_volt(dvfs_clk, dvfs_clk->set_freq, &clk_fv)) {\r
232                         dvfs_clk->enable_dvfs = 0;\r
233                         return -1;\r
234                 }\r
235                 dvfs_clk->set_volt = clk_fv.index;\r
236                 //DVFS_DBG("%s,%s,freq%u(ref vol %u)\n",__func__,dvfs_clk->name,\r
237                 //       dvfs_clk->set_freq,dvfs_clk->set_volt);\r
238 #if 0\r
239                 if (dvfs_clk->dvfs_nb) {\r
240                         // must unregister when clk disable\r
241                         rk30_clk_notifier_register(clk, dvfs_clk->dvfs_nb);\r
242                 }\r
243 #endif\r
244                 dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
245                 dvfs_clk->enable_dvfs++;\r
246         } else {\r
247                 DVFS_ERR("dvfs already enable clk enable = %d!\n", dvfs_clk->enable_dvfs);\r
248                 dvfs_clk->enable_dvfs++;\r
249         }\r
250         return 0;\r
251 }\r
252 \r
253 int clk_disable_dvfs(struct clk *clk)\r
254 {\r
255         struct clk_node *dvfs_clk;\r
256         dvfs_clk = clk->dvfs_info;\r
257         if (!dvfs_clk->enable_dvfs) {\r
258                 DVFS_DBG("clk is already closed!\n");\r
259                 return -1;\r
260         } else {\r
261                 dvfs_clk->enable_dvfs--;\r
262                 if (0 == dvfs_clk->enable_dvfs) {\r
263                         DVFS_ERR("clk closed!\n");\r
264                         rk30_clk_notifier_unregister(clk, dvfs_clk->dvfs_nb);\r
265                         DVFS_DBG("clk unregister nb!\n");\r
266                 }\r
267         }\r
268         return 0;\r
269 }\r
270 \r
271 static int rk_dvfs_clk_notifier_event(struct notifier_block *this,\r
272                 unsigned long event, void *ptr)\r
273 {\r
274         struct clk_notifier_data *noti_info;\r
275         struct clk *clk;\r
276         struct clk_node *dvfs_clk;\r
277         noti_info = (struct clk_notifier_data *)ptr;\r
278         clk = noti_info->clk;\r
279         dvfs_clk = clk->dvfs_info;\r
280 \r
281         switch (event) {\r
282                 case CLK_PRE_RATE_CHANGE:\r
283                         DVFS_DBG("%s CLK_PRE_RATE_CHANGE\n", __func__);\r
284                         break;\r
285                 case CLK_POST_RATE_CHANGE:\r
286                         DVFS_DBG("%s CLK_POST_RATE_CHANGE\n", __func__);\r
287                         break;\r
288                 case CLK_ABORT_RATE_CHANGE:\r
289                         DVFS_DBG("%s CLK_ABORT_RATE_CHANGE\n", __func__);\r
290                         break;\r
291                 case CLK_PRE_ENABLE:\r
292                         DVFS_DBG("%s CLK_PRE_ENABLE\n", __func__);\r
293                         break;\r
294                 case CLK_POST_ENABLE:\r
295                         DVFS_DBG("%s CLK_POST_ENABLE\n", __func__);\r
296                         break;\r
297                 case CLK_ABORT_ENABLE:\r
298                         DVFS_DBG("%s CLK_ABORT_ENABLE\n", __func__);\r
299                         break;\r
300                 case CLK_PRE_DISABLE:\r
301                         DVFS_DBG("%s CLK_PRE_DISABLE\n", __func__);\r
302                         break;\r
303                 case CLK_POST_DISABLE:\r
304                         DVFS_DBG("%s CLK_POST_DISABLE\n", __func__);\r
305                         dvfs_clk->set_freq = 0;\r
306                         break;\r
307                 case CLK_ABORT_DISABLE:\r
308                         DVFS_DBG("%s CLK_ABORT_DISABLE\n", __func__);\r
309 \r
310                         break;\r
311                 default:\r
312                         break;\r
313         }\r
314         return 0;\r
315 }\r
316 \r
317 static struct notifier_block rk_dvfs_clk_notifier = {\r
318         .notifier_call = rk_dvfs_clk_notifier_event,\r
319 };\r
320 \r
321 static int rk_regist_vd(struct vd_node *vd)\r
322 {\r
323         if (!vd)\r
324                 return -1;\r
325         mutex_lock(&mutex);\r
326         mutex_init(&vd->dvfs_mutex);\r
327         list_add(&vd->node, &rk_dvfs_tree);\r
328         INIT_LIST_HEAD(&vd->pd_list);\r
329 \r
330         mutex_unlock(&mutex);\r
331         return 0;\r
332 }\r
333 \r
334 static int rk_regist_pd(struct pd_node_lookup *pd_lookup)\r
335 {\r
336         struct vd_node  *vd;\r
337         struct pd_node  *pd;\r
338 \r
339         mutex_lock(&mutex);\r
340         pd = pd_lookup->pd;\r
341 \r
342         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
343                 if (vd == pd->vd) {\r
344                         list_add(&pd->node, &vd->pd_list);\r
345                         INIT_LIST_HEAD(&pd->clk_list);\r
346                         break;\r
347                 }\r
348         }\r
349         mutex_unlock(&mutex);\r
350         return 0;\r
351 }\r
352 \r
353 static int rk_regist_clk(struct clk_node *dvfs_clk)\r
354 {\r
355         struct pd_node  *pd;\r
356         struct clk_list *child;\r
357         struct clk      *clk;\r
358         int i = 0;\r
359 \r
360         if (!dvfs_clk)\r
361                 return -1;\r
362 \r
363         if (!dvfs_clk->pds)\r
364                 return -1;\r
365         mutex_lock(&mutex);\r
366         dvfs_clk->enable_dvfs = 0;\r
367         dvfs_clk->vd = dvfs_clk->pds[0].pd->vd;\r
368         for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {\r
369                 child = &(dvfs_clk->pds[i].clk_list);\r
370                 child->dvfs_clk = dvfs_clk;\r
371                 pd = dvfs_clk->pds[i].pd;\r
372                 list_add(&child->node, &pd->clk_list);\r
373         }\r
374         clk = dvfs_clk_get(NULL, dvfs_clk->name);\r
375         dvfs_clk->ck = clk;\r
376         clk_register_dvfs(dvfs_clk, clk);\r
377         mutex_unlock(&mutex);\r
378         return 0;\r
379 }\r
380 \r
381 #define get_volt_up_delay(new_volt, old_volt)   \\r
382         ((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 10) : 0)\r
383 \r
384 #ifdef LOGIC_VOLT_SCALING\r
385 #define DVFS_LOGIC_VOLT_H       1175000\r
386 #define DVFS_LOGIC_VOLT_L       1025000\r
387 static int dvfs_up_volt_logic(void)\r
388 {\r
389         struct regulator *vdd_core;\r
390         int ret = 0;\r
391         DVFS_DBG("second jump > 816M\n");\r
392         vdd_core = dvfs_regulator_get(NULL, "vdd_core");\r
393         ret = dvfs_regulator_set_voltage(vdd_core, DVFS_LOGIC_VOLT_H, DVFS_LOGIC_VOLT_H);\r
394         udelay(200);\r
395         DVFS_DBG("DVFS > 816M\n");\r
396         if (ret != 0) {\r
397                 DVFS_ERR("%s err, ret = %d\n", __func__, ret);\r
398                 return -1;\r
399         }\r
400         dvfs_regulator_put(vdd_core);\r
401         return ret;\r
402 }\r
403 \r
404 static int dvfs_down_volt_logic(void)\r
405 {\r
406         struct regulator *vdd_core;\r
407         int ret = 0;\r
408         DVFS_DBG("first jump %d\n", JUMP_RATE);\r
409         vdd_core = dvfs_regulator_get(NULL, "vdd_core");\r
410         ret = dvfs_regulator_set_voltage(vdd_core, DVFS_LOGIC_VOLT_L, DVFS_LOGIC_VOLT_L);\r
411         //udelay(200);\r
412         DVFS_DBG("DVFS <= 816M\n");\r
413         if (ret != 0) {\r
414                 DVFS_ERR("%s err, ret = %d\n", __func__, ret);\r
415                 return -1;\r
416         }\r
417         dvfs_regulator_put(vdd_core);\r
418         return ret;\r
419 }\r
420 #endif\r
421 static int flag_core_set_volt_err = 0;\r
422 int dvfs_target_core(struct clk *clk, unsigned long rate_hz)\r
423 {\r
424         struct clk_node *dvfs_clk;\r
425         unsigned int volt_new = 0, volt_old = 0, volt_clk_old = 0;\r
426         struct cpufreq_frequency_table clk_fv = {0, 0};\r
427         int ret = 0;\r
428         int flag_set_volt_correct = 0;\r
429         unsigned long temp_hz;\r
430 \r
431         if (!clk) {\r
432                 DVFS_ERR("%s is not clk\n", __func__);\r
433                 return -1;\r
434         }\r
435         dvfs_clk = clk_get_dvfs_info(clk);\r
436 \r
437         if (!dvfs_clk || dvfs_clk->vd->regulator == NULL) {\r
438                 DVFS_ERR("%s can't get dvfs regulater\n", clk->name);\r
439                 return -1;\r
440         }\r
441 \r
442         temp_hz = rate_hz;//clk_round_rate_nolock(clk, rate_hz);\r
443 \r
444         //DVFS_DBG("dvfs(%s) round rate(%lu)(rount %lu)\n",dvfs_clk->name,rate_hz,temp_hz);\r
445 \r
446         /* find the clk corresponding voltage */\r
447         if (dvfs_clk_get_ref_volt(dvfs_clk, temp_hz / 1000, &clk_fv)) {\r
448                 DVFS_ERR("%s--%s:rate%lu,Get corresponding voltage error!\n", \r
449                                 __func__, dvfs_clk->name, temp_hz);\r
450                 return -1;\r
451         }\r
452         volt_old = dvfs_clk->vd->cur_volt;\r
453 \r
454         volt_clk_old = dvfs_clk->set_volt;\r
455 \r
456         dvfs_clk->set_volt = clk_fv.index;\r
457 \r
458         volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
459 \r
460         DVFS_LOG("dvfs--(%s),volt=%d(was %dmV),rate=%lu(was %lu),vd%u=(was%u)\n",\r
461                         dvfs_clk->name, clk_fv.index, dvfs_clk->set_volt, temp_hz, clk_get_rate(clk)\r
462                         , volt_new, volt_old);\r
463 \r
464         if (flag_core_set_volt_err) {\r
465                 /* It means the last time set voltage error */  \r
466                 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);\r
467                 if (flag_set_volt_correct <= 0) {\r
468                         DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload core_volt error %d!!! stop scaling\n", \r
469                                         __func__, dvfs_clk->name, volt_new, volt_old, \r
470                                         temp_hz, clk_get_rate(clk), flag_set_volt_correct);\r
471                         return -1;\r
472                 }\r
473 \r
474                 flag_core_set_volt_err = 0;\r
475                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload core_volt! core_volt_correct = %d\n", \r
476                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
477                                 temp_hz, clk_get_rate(clk), flag_set_volt_correct);\r
478 \r
479                 /* Reset vd's voltage */\r
480                 dvfs_clk->vd->cur_volt = flag_set_volt_correct;\r
481                 volt_old = dvfs_clk->vd->cur_volt;\r
482         }\r
483 \r
484         /* if up the voltage */\r
485         if (volt_old < volt_new) {\r
486                 if (dvfs_clk->vd->regulator) {\r
487                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
488                         if (ret < 0) {\r
489                                 flag_core_set_volt_err = 1;\r
490                                 DVFS_ERR("%s %s set voltage up err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
491                                                 __func__, dvfs_clk->name, ret, \r
492                                                 temp_hz, clk_get_rate(clk), volt_new, volt_old);\r
493                                 return -1;\r
494                         }\r
495 \r
496                 } else {\r
497                         DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
498                         return -1;\r
499                 }\r
500 \r
501                 dvfs_clk->vd->cur_volt = volt_new;\r
502                 udelay(get_volt_up_delay(volt_new, volt_old));\r
503                 DVFS_LOG("%s %s set voltage OK up ret = %d, Vnew = %d(was %d), Rnew = %lu(was %lu)\n", \r
504                                 __func__, dvfs_clk->name, ret, volt_new, volt_old, temp_hz, clk_get_rate(clk));\r
505         }\r
506 \r
507         if (dvfs_clk->clk_dvfs_target) {\r
508                 ret = dvfs_clk->clk_dvfs_target(clk, temp_hz, clk_set_rate_locked);\r
509         } else {\r
510                 ret = clk_set_rate_locked(clk, temp_hz);\r
511         }\r
512 \r
513         if (ret < 0) {\r
514 \r
515                 dvfs_clk->set_volt = volt_old;\r
516                 dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
517                 DVFS_ERR("set rate err\n");\r
518                 return -1;\r
519         }\r
520         dvfs_clk->set_freq      = temp_hz / 1000;\r
521 \r
522         /* if down the voltage */\r
523         if (volt_old > volt_new) {\r
524                 if (dvfs_clk->vd->regulator) {\r
525                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
526                         if (ret < 0) {\r
527                                 flag_core_set_volt_err = 1;\r
528                                 DVFS_ERR("%s %s set voltage down err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
529                                                 __func__, dvfs_clk->name, ret, temp_hz, clk_get_rate(clk), \r
530                                                 volt_new, volt_old);\r
531                                 return -1;\r
532                         }\r
533 \r
534                 } else {\r
535                         DVFS_ERR("%s down volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
536                         return -1;\r
537                 }\r
538 \r
539                 dvfs_clk->vd->cur_volt = volt_new;\r
540                 DVFS_LOG("dvfs %s set volt ok dn\n", dvfs_clk->name);\r
541 \r
542         }\r
543 \r
544         return 0;\r
545 }\r
546 \r
547 static int flag_arm_set_volt_err = 0;\r
548 int dvfs_target_cpu(struct clk *clk, unsigned long rate_hz)\r
549 {\r
550         struct clk_node *dvfs_clk;\r
551         int volt_new = 0, volt_old = 0;\r
552         struct cpufreq_frequency_table clk_fv;\r
553         int ret = 0;\r
554         int flag_set_volt_correct = 0;\r
555         unsigned long temp_hz, pre_rate_hz;\r
556 \r
557 \r
558         if (!clk) {\r
559                 DVFS_ERR("%s is not clk\n", __func__);\r
560                 return -1;\r
561         }\r
562         dvfs_clk = clk_get_dvfs_info(clk);\r
563 \r
564         if (!dvfs_clk || dvfs_clk->vd->regulator == NULL) {\r
565                 DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);\r
566                 return -1;\r
567         }\r
568 \r
569         /* need round rate */\r
570         temp_hz = clk_round_rate_nolock(clk, rate_hz);\r
571         DVFS_DBG("dvfs(%s) round rate (%lu)(rount %lu)\n", dvfs_clk->name, rate_hz, temp_hz);\r
572 \r
573         pre_rate_hz = clk_get_rate(clk);\r
574         /* find the clk corresponding voltage */\r
575         if (0 != dvfs_clk_get_ref_volt(dvfs_clk, temp_hz / 1000, &clk_fv)) {\r
576                 DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
577                 return -1;\r
578         }\r
579 \r
580         volt_old = dvfs_clk->vd->cur_volt;\r
581         volt_new = clk_fv.index;\r
582         if (flag_arm_set_volt_err) {\r
583                 /* It means the last time set voltage error */\r
584                 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);\r
585                 if (flag_set_volt_correct <= 0) {\r
586                         DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload arm_volt error %d!!! stop scaling\n", \r
587                                         __func__, dvfs_clk->name, volt_new, volt_old, \r
588                                         temp_hz, clk_get_rate(clk), flag_set_volt_correct);\r
589                         return -1;\r
590                 }\r
591 \r
592                 flag_arm_set_volt_err = 0;\r
593                 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload arm_volt! arm_volt_correct = %d\n", \r
594                                 __func__, dvfs_clk->name, volt_new, volt_old, \r
595                                 temp_hz, clk_get_rate(clk), flag_set_volt_correct);\r
596 \r
597                 /* Reset vd's voltage */\r
598                 dvfs_clk->vd->cur_volt = flag_set_volt_correct;\r
599                 volt_old = dvfs_clk->vd->cur_volt;\r
600         }\r
601 #ifdef LOGIC_VOLT_SCALING\r
602         if (temp_hz > JUMP_RATE && pre_rate_hz <= JUMP_RATE) {\r
603                 ret = dvfs_up_volt_logic();\r
604                 if (ret != 0) {\r
605                         DVFS_ERR("%s up logic volt error %d", __func__, ret);\r
606                         return -1;\r
607                 }\r
608         }\r
609 #endif\r
610         /* if up the voltage */\r
611         if (volt_old < volt_new) {\r
612                 if (dvfs_clk->vd->regulator) {\r
613                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
614                         if (ret < 0) {\r
615                                 flag_arm_set_volt_err = 1;\r
616                                 DVFS_ERR("%s %s set voltage up err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
617                                                 __func__, dvfs_clk->name, ret, temp_hz, clk_get_rate(clk), \r
618                                                 volt_new, volt_old);\r
619                                 return -1;\r
620                         }\r
621 \r
622                 } else {\r
623                         DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
624                         return -1;\r
625                 }\r
626 \r
627                 dvfs_clk->vd->cur_volt = volt_new;\r
628                 udelay(get_volt_up_delay(volt_new, volt_old));\r
629                 DVFS_LOG("%s %s set voltage OK up ret = %d, Vnew = %d(was %d), Rnew = %lu(was %lu)\n", \r
630                                 __func__, dvfs_clk->name, ret, volt_new, volt_old, temp_hz, clk_get_rate(clk));\r
631         }\r
632 \r
633         if (dvfs_clk->clk_dvfs_target) {\r
634                 ret = dvfs_clk->clk_dvfs_target(clk, temp_hz, clk_set_rate_locked);\r
635         } else {\r
636                 ret = clk_set_rate_locked(clk, temp_hz);\r
637         }\r
638 \r
639         if (ret < 0) {\r
640                 DVFS_ERR("set rate err\n");\r
641                 return -1;\r
642         }\r
643         dvfs_clk->set_freq      = temp_hz / 1000;\r
644 \r
645         DVFS_LOG("dvfs %s set rate%lu ok\n", dvfs_clk->name, clk_get_rate(clk));\r
646 \r
647         /* if down the voltage */\r
648         if (volt_old > volt_new) {\r
649                 if (dvfs_clk->vd->regulator) {\r
650                         ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);\r
651                         if (ret < 0) {\r
652                                 flag_arm_set_volt_err = 1;\r
653                                 DVFS_ERR("%s %s set voltage down err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n", \r
654                                                 __func__, dvfs_clk->name, ret, temp_hz, clk_get_rate(clk), \r
655                                                 volt_new, volt_old);\r
656                                 return -1;\r
657                         }\r
658 \r
659                 } else {\r
660                         DVFS_ERR("%s down volt dvfs_clk->vd->regulator == NULL\n", __func__);\r
661                         return -1;\r
662                 }\r
663 \r
664                 dvfs_clk->vd->cur_volt = volt_new;\r
665                 DVFS_LOG("dvfs %s set volt ok dn\n", dvfs_clk->name);\r
666 \r
667         }\r
668 #ifdef LOGIC_VOLT_SCALING\r
669         if (temp_hz <= JUMP_RATE && pre_rate_hz > JUMP_RATE) {\r
670                 ret = dvfs_down_volt_logic();\r
671                 if (ret != 0) {\r
672                         DVFS_ERR("%s down logic volt error %d", __func__, ret);\r
673                         return -1;\r
674                 }\r
675         }\r
676 #endif\r
677         return ret;\r
678 }\r
679 \r
680 \r
681 \r
682 /*****************************init**************************/\r
683 /**\r
684  * rate must be raising sequence\r
685  */\r
686 static struct cpufreq_frequency_table cpu_dvfs_table[] = {\r
687         //{.frequency   = 48 * DVFS_KHZ, .index = 920*DVFS_MV},\r
688         //{.frequency   = 126 * DVFS_KHZ, .index        = 970 * DVFS_MV},\r
689         // {.frequency  = 252 * DVFS_KHZ, .index        = 1040 * DVFS_MV},\r
690         // {.frequency  = 504 * DVFS_KHZ, .index        = 1060 * DVFS_MV},\r
691         {.frequency     = 816 * DVFS_KHZ, .index        = 1080 * DVFS_MV},\r
692         //  {.frequency = 1008 * DVFS_KHZ, .index       = 1100 * DVFS_MV},\r
693         {.frequency     = CPUFREQ_TABLE_END},\r
694 };\r
695 \r
696 static struct cpufreq_frequency_table ddr_dvfs_table[] = {\r
697         //{.frequency = 100 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
698         {.frequency = 200 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
699         {.frequency = 300 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
700         {.frequency = 400 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
701         {.frequency = 500 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
702         {.frequency = 600 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
703         {.frequency = CPUFREQ_TABLE_END},\r
704 };\r
705 \r
706 static struct cpufreq_frequency_table gpu_dvfs_table[] = {\r
707         {.frequency = 100 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
708         {.frequency = 200 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
709         {.frequency = 300 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
710         {.frequency = 400 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
711         {.frequency = 500 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
712         {.frequency = CPUFREQ_TABLE_END},\r
713 };\r
714 \r
715 static struct cpufreq_frequency_table peri_aclk_dvfs_table[] = {\r
716         {.frequency = 100 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
717         {.frequency = 200 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
718         {.frequency = 300 * DVFS_KHZ, .index = 1070 * DVFS_MV},\r
719         {.frequency = 500 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
720         {.frequency = CPUFREQ_TABLE_END},\r
721 };\r
722 \r
723 static struct vd_node vd_cpu = {\r
724         .name           = "vd_cpu",\r
725         .regulator_name = "vdd_cpu",\r
726         .vd_dvfs_target = dvfs_target_cpu,\r
727 };\r
728 \r
729 static struct vd_node vd_core = {\r
730         .name           = "vd_core",\r
731         .regulator_name = "vdd_core",\r
732         .vd_dvfs_target = dvfs_target_core,\r
733 };\r
734 \r
735 static struct vd_node vd_rtc = {\r
736         .name           = "vd_rtc",\r
737         .regulator_name = "vdd_rtc",\r
738         .vd_dvfs_target = NULL,\r
739 };\r
740 \r
741 static struct vd_node *rk30_vds[] = {&vd_cpu, &vd_core, &vd_rtc};\r
742 \r
743 static struct pd_node pd_a9_0 = {\r
744         .name                   = "pd_a9_0",\r
745         .vd                     = &vd_cpu,\r
746 };\r
747 static struct pd_node pd_a9_1 = {\r
748         .name                   = "pd_a9_1",\r
749         .vd                     = &vd_cpu,\r
750 };\r
751 static struct pd_node pd_debug = {\r
752         .name                   = "pd_debug",\r
753         .vd                     = &vd_cpu,\r
754 };\r
755 static struct pd_node pd_scu = {\r
756         .name                   = "pd_scu",\r
757         .vd                     = &vd_cpu,\r
758 };\r
759 static struct pd_node pd_video = {\r
760         .name                   = "pd_video",\r
761         .vd                     = &vd_core,\r
762 };\r
763 static struct pd_node pd_vio = {\r
764         .name                   = "pd_vio",\r
765         .vd                     = &vd_core,\r
766 };\r
767 static struct pd_node pd_gpu = {\r
768         .name                   = "pd_gpu",\r
769         .vd                     = &vd_core,\r
770 };\r
771 static struct pd_node pd_peri = {\r
772         .name                   = "pd_peri",\r
773         .vd                     = &vd_core,\r
774 };\r
775 static struct pd_node pd_cpu = {\r
776         .name                   = "pd_cpu",\r
777         .vd                     = &vd_core,\r
778 };\r
779 static struct pd_node pd_alive = {\r
780         .name                   = "pd_alive",\r
781         .vd                     = &vd_core,\r
782 };\r
783 static struct pd_node pd_rtc = {\r
784         .name                   = "pd_rtc",\r
785         .vd                     = &vd_rtc,\r
786 };\r
787 #define LOOKUP_PD(_ppd) \\r
788 {       \\r
789         .pd     = _ppd, \\r
790 }\r
791 static struct pd_node_lookup rk30_pds[] = {\r
792         LOOKUP_PD(&pd_a9_0),\r
793         LOOKUP_PD(&pd_a9_1),\r
794         LOOKUP_PD(&pd_debug),\r
795         LOOKUP_PD(&pd_scu),\r
796         LOOKUP_PD(&pd_video),\r
797         LOOKUP_PD(&pd_vio),\r
798         LOOKUP_PD(&pd_gpu),\r
799         LOOKUP_PD(&pd_peri),\r
800         LOOKUP_PD(&pd_cpu),\r
801         LOOKUP_PD(&pd_alive),\r
802         LOOKUP_PD(&pd_rtc),\r
803 };\r
804 \r
805 #define CLK_PDS(_ppd) \\r
806 {       \\r
807         .pd     = _ppd, \\r
808 }\r
809 \r
810 static struct pds_list cpu_pds[] = {\r
811         CLK_PDS(&pd_a9_0),\r
812         CLK_PDS(&pd_a9_1),\r
813         CLK_PDS(NULL),\r
814 };\r
815 \r
816 static struct pds_list ddr_pds[] = {\r
817         CLK_PDS(&pd_cpu),\r
818         CLK_PDS(NULL),\r
819 };\r
820 \r
821 static struct pds_list gpu_pds[] = {\r
822         CLK_PDS(&pd_gpu),\r
823         CLK_PDS(NULL),\r
824 };\r
825 \r
826 #define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb) \\r
827 { \\r
828         .name   = _clk_name, \\r
829         .pds = _ppds,\\r
830         .dvfs_table = _dvfs_table,      \\r
831         .dvfs_nb        = _dvfs_nb,     \\r
832 }\r
833 \r
834 static struct pds_list aclk_periph_pds[] = {\r
835         CLK_PDS(&pd_peri),\r
836         CLK_PDS(NULL),\r
837 };\r
838 \r
839 \r
840 static struct clk_node rk30_clks[] = {\r
841         RK_CLKS("cpu", cpu_pds, cpu_dvfs_table, &rk_dvfs_clk_notifier),\r
842         RK_CLKS("ddr", ddr_pds, ddr_dvfs_table, &rk_dvfs_clk_notifier),\r
843         RK_CLKS("gpu", gpu_pds, gpu_dvfs_table, &rk_dvfs_clk_notifier),\r
844         RK_CLKS("aclk_periph", aclk_periph_pds, peri_aclk_dvfs_table, &rk_dvfs_clk_notifier),\r
845 };\r
846 \r
847 int rk30_dvfs_init(void)\r
848 {\r
849         int i = 0;\r
850         for (i = 0; i < ARRAY_SIZE(rk30_vds); i++) {\r
851                 rk_regist_vd(rk30_vds[i]);\r
852         }\r
853         for (i = 0; i < ARRAY_SIZE(rk30_pds); i++) {\r
854                 rk_regist_pd(&rk30_pds[i]);\r
855         }\r
856         for (i = 0; i < ARRAY_SIZE(rk30_clks); i++) {\r
857                 rk_regist_clk(&rk30_clks[i]);\r
858         }\r
859 \r
860         return 0;\r
861 }\r
862 \r
863 //#define DVFS_DUMP_DBG\r
864 #ifdef DVFS_DUMP_DBG\r
865 /**\r
866  * dump_dbg_map() : Draw all informations of dvfs while debug\r
867  */\r
868 static void dump_dbg_map(void)\r
869 {\r
870         int i;\r
871         struct vd_node  *vd;\r
872         struct pd_node  *pd, *clkparent;\r
873         struct clk_list *child;\r
874         struct clk_node *dvfs_clk;\r
875 \r
876         DVFS_DBG("-------------DVFS DEBUG-----------\n\n\n");\r
877         DVFS_DBG("RK30 DVFS TREE:\n");\r
878         list_for_each_entry(vd, &rk_dvfs_tree, node) {\r
879                 DVFS_DBG("|\n|- voltage domain:%s\n", vd->name);\r
880                 DVFS_DBG("|- current voltage:%d\n", vd->cur_volt);\r
881 \r
882                 list_for_each_entry(pd, &vd->pd_list, node) {\r
883                         DVFS_DBG("|  |\n|  |- power domain:%s, status = %s, current volt = %d\n",\r
884                                         pd->name, (pd->pd_status == PD_ON) ? "ON" : "OFF", pd->cur_volt);\r
885 \r
886                         list_for_each_entry(child, &pd->clk_list, node) {\r
887                                 dvfs_clk = child->dvfs_clk;\r
888                                 DVFS_DBG("|  |  |\n|  |  |- clock: %s current: rate %d, volt = %d, enable_dvfs = %s\n",\r
889                                                 dvfs_clk->name, dvfs_clk->set_freq, dvfs_clk->set_volt, \r
890                                                 dvfs_clk->enable_dvfs == 0 ? "DISABLE" : "ENABLE");\r
891                                 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {\r
892                                         clkparent = dvfs_clk->pds[i].pd;\r
893                                         DVFS_DBG("|  |  |  |- clock parents: %s, vd_parent = %s\n", \r
894                                                         clkparent->name, clkparent->vd->name);\r
895                                 }\r
896 \r
897                                 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {\r
898                                         DVFS_DBG("|  |  |  |- freq = %d, volt = %d\n", \r
899                                                         dvfs_clk->dvfs_table[i].frequency, \r
900                                                         dvfs_clk->dvfs_table[i].index);\r
901 \r
902                                 }\r
903                         }\r
904                 }\r
905         }\r
906         DVFS_DBG("-------------DVFS DEBUG END------------\n");\r
907 }\r
908 #endif\r
909 \r
910 \r
911 \r