a228645cf56d3f8a06c10dbdb5b08b531511f190
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rk3188 / 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 <mach/dvfs.h>\r
24 #include <mach/clock.h>\r
25 #include <linux/regulator/consumer.h>\r
26 #include <linux/delay.h>\r
27 #include <linux/io.h>\r
28 #include <linux/hrtimer.h>\r
29 \r
30 static int rk_dvfs_clk_notifier_event(struct notifier_block *this,\r
31                 unsigned long event, void *ptr)\r
32 {\r
33         struct clk_notifier_data *noti_info;\r
34         struct clk *clk;\r
35         struct clk_node *dvfs_clk;\r
36         noti_info = (struct clk_notifier_data *)ptr;\r
37         clk = noti_info->clk;\r
38         dvfs_clk = clk->dvfs_info;\r
39 \r
40         switch (event) {\r
41                 case CLK_PRE_RATE_CHANGE:\r
42                         DVFS_DBG("%s CLK_PRE_RATE_CHANGE\n", __func__);\r
43                         break;\r
44                 case CLK_POST_RATE_CHANGE:\r
45                         DVFS_DBG("%s CLK_POST_RATE_CHANGE\n", __func__);\r
46                         break;\r
47                 case CLK_ABORT_RATE_CHANGE:\r
48                         DVFS_DBG("%s CLK_ABORT_RATE_CHANGE\n", __func__);\r
49                         break;\r
50                 case CLK_PRE_ENABLE:\r
51                         DVFS_DBG("%s CLK_PRE_ENABLE\n", __func__);\r
52                         break;\r
53                 case CLK_POST_ENABLE:\r
54                         DVFS_DBG("%s CLK_POST_ENABLE\n", __func__);\r
55                         break;\r
56                 case CLK_ABORT_ENABLE:\r
57                         DVFS_DBG("%s CLK_ABORT_ENABLE\n", __func__);\r
58                         break;\r
59                 case CLK_PRE_DISABLE:\r
60                         DVFS_DBG("%s CLK_PRE_DISABLE\n", __func__);\r
61                         break;\r
62                 case CLK_POST_DISABLE:\r
63                         DVFS_DBG("%s CLK_POST_DISABLE\n", __func__);\r
64                         dvfs_clk->set_freq = 0;\r
65                         break;\r
66                 case CLK_ABORT_DISABLE:\r
67                         DVFS_DBG("%s CLK_ABORT_DISABLE\n", __func__);\r
68 \r
69                         break;\r
70                 default:\r
71                         break;\r
72         }\r
73         return 0;\r
74 }\r
75 \r
76 static struct notifier_block rk_dvfs_clk_notifier = {\r
77         .notifier_call = rk_dvfs_clk_notifier_event,\r
78 };\r
79 \r
80 #define NO_VOLT_DIFF\r
81 #ifdef NO_VOLT_DIFF\r
82 \r
83 int dvfs_target(struct clk *clk, unsigned long rate_hz)\r
84 {\r
85         struct clk_node *dvfs_clk;\r
86         int volt_new = 0, clk_volt_store = 0;\r
87         struct cpufreq_frequency_table clk_fv;\r
88         int ret = 0;\r
89         unsigned long rate_new, rate_old;\r
90 \r
91         if (!clk) {\r
92                 DVFS_ERR("%s is not a clk\n", __func__);\r
93                 return -1;\r
94         }\r
95         dvfs_clk = clk_get_dvfs_info(clk);\r
96         DVFS_DBG("enter %s: clk(%s) rate = %lu Hz\n", __func__, dvfs_clk->name, rate_hz);\r
97 \r
98         if (!dvfs_clk || dvfs_clk->vd == NULL || IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {\r
99                 DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);\r
100                 return -1;\r
101         }\r
102 \r
103         if (dvfs_clk->vd->volt_set_flag == DVFS_SET_VOLT_FAILURE) {\r
104                 /* It means the last time set voltage error */\r
105                 ret = dvfs_reset_volt(dvfs_clk->vd);\r
106                 if (ret < 0) {\r
107                         return -1;\r
108                 }\r
109         }\r
110 \r
111         /* Check limit rate */\r
112         //if (dvfs_clk->freq_limit_en) {\r
113                 if (rate_hz < dvfs_clk->min_rate) {\r
114                         rate_hz = dvfs_clk->min_rate;\r
115                 } else if (rate_hz > dvfs_clk->max_rate) {\r
116                         rate_hz = dvfs_clk->max_rate;\r
117                 }\r
118         //}\r
119 \r
120         /* need round rate */\r
121         rate_old = clk_get_rate(clk);\r
122         rate_new = clk_round_rate_nolock(clk, rate_hz);\r
123         if(rate_new == rate_old)\r
124                 return 0;\r
125 \r
126         DVFS_DBG("dvfs(%s) round rate (%lu)(rount %lu) old (%lu)\n",\r
127                         dvfs_clk->name, rate_hz, rate_new, rate_old);\r
128 \r
129         /* find the clk corresponding voltage */\r
130         if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {\r
131                 DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
132                 return -1;\r
133         }\r
134         clk_volt_store = dvfs_clk->set_volt;\r
135         dvfs_clk->set_volt = clk_fv.index;\r
136         volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
137         DVFS_DBG("%s,%s,new rate=%lu(was=%lu),new volt=%lu,(was=%d)\n",__FUNCTION__,dvfs_clk->name,rate_new,\r
138                                 rate_old,volt_new,dvfs_clk->vd->cur_volt);\r
139 \r
140         /* if up the rate */\r
141         if (rate_new > rate_old) {\r
142                 ret = dvfs_scale_volt_direct(dvfs_clk->vd, volt_new);\r
143                 if (ret < 0)\r
144                         goto fail_roll_back;\r
145         }\r
146 \r
147         /* scale rate */\r
148         if (dvfs_clk->clk_dvfs_target) {\r
149                 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);\r
150         } else {\r
151                 ret = clk_set_rate_locked(clk, rate_new);\r
152         }\r
153 \r
154         if (ret < 0) {\r
155                 DVFS_ERR("%s set rate err\n", __func__);\r
156                 goto fail_roll_back;\r
157         }\r
158         dvfs_clk->set_freq      = rate_new / 1000;\r
159 \r
160         DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));\r
161 \r
162         /* if down the rate */\r
163         if (rate_new < rate_old) {\r
164                 ret = dvfs_scale_volt_direct(dvfs_clk->vd, volt_new);\r
165                 if (ret < 0)\r
166                         goto out;\r
167         }\r
168 \r
169         return ret;\r
170 fail_roll_back:\r
171         dvfs_clk->set_volt = clk_volt_store;\r
172 out:\r
173         return -1;\r
174 }\r
175 \r
176 \r
177 #else\r
178 \r
179 #ifdef CONFIG_ARCH_RK3188\r
180 static int g_arm_high_logic = 50 * 1000;\r
181 static int g_logic_high_arm = 100 * 1000;\r
182 #else\r
183 static int g_arm_high_logic = 150 * 1000;\r
184 static int g_logic_high_arm = 100 * 1000;\r
185 #endif\r
186 \r
187 \r
188 #ifdef CONFIG_ARCH_RK3188\r
189 static struct cpufreq_frequency_table arm_high_logic_table[] = {\r
190         {.frequency = 1416 * DVFS_KHZ, .index = 25 * DVFS_MV},\r
191         {.frequency = 1608 * DVFS_KHZ, .index = 25 * DVFS_MV},\r
192         {.frequency = CPUFREQ_TABLE_END},\r
193 };\r
194 \r
195 static struct cpufreq_frequency_table logic_high_arm_table[] = {\r
196         {.frequency = 1008 * DVFS_KHZ, .index = 150 * DVFS_MV},\r
197         {.frequency = 1608 * DVFS_KHZ, .index = 75 * DVFS_MV},\r
198         {.frequency = CPUFREQ_TABLE_END},\r
199 };\r
200 #else\r
201 static struct cpufreq_frequency_table arm_high_logic_table[] = {\r
202         {.frequency = 1416 * DVFS_KHZ, .index = 50 * DVFS_MV},\r
203         {.frequency = 1608 * DVFS_KHZ, .index = 100 * DVFS_MV},\r
204         {.frequency = CPUFREQ_TABLE_END},\r
205 };\r
206 static struct cpufreq_frequency_table logic_high_arm_table[] = {\r
207         {.frequency = 816 * DVFS_KHZ,  .index = 200 * DVFS_MV},\r
208         {.frequency = 1416 * DVFS_KHZ, .index = 150 * DVFS_MV},\r
209         {.frequency = 1608 * DVFS_KHZ, .index = 100 * DVFS_MV},\r
210 };\r
211 #endif\r
212 \r
213 \r
214 int get_arm_logic_limit(unsigned long arm_rate, int *arm_high_logic, int *logic_high_arm)\r
215 {\r
216         int i;\r
217 \r
218         for (i = 0; arm_high_logic_table[i].frequency != CPUFREQ_TABLE_END; i++) {\r
219                 if (arm_rate <= arm_high_logic_table[i].frequency) {\r
220                         *arm_high_logic = arm_high_logic_table[i].index;\r
221                         break;\r
222                 }\r
223         }\r
224 \r
225         if (arm_high_logic_table[i].frequency == CPUFREQ_TABLE_END) {\r
226                 *arm_high_logic = arm_high_logic_table[i-1].index;\r
227         }\r
228 \r
229         for (i = 0; logic_high_arm_table[i].frequency != CPUFREQ_TABLE_END; i++) {\r
230                 if (arm_rate <= logic_high_arm_table[i].frequency) {\r
231                         *logic_high_arm = logic_high_arm_table[i].index;\r
232                         break;\r
233                 }\r
234         }\r
235         if (logic_high_arm_table[i].frequency == CPUFREQ_TABLE_END)\r
236                 *logic_high_arm = logic_high_arm_table[i-1].index;\r
237 \r
238         return 0;\r
239 }\r
240 \r
241 static struct clk_node *dvfs_clk_cpu;\r
242 static struct vd_node vd_core;\r
243 int dvfs_target_cpu(struct clk *clk, unsigned long rate_hz)\r
244 {\r
245         struct clk_node *dvfs_clk;\r
246         int volt_new = 0, volt_dep_new = 0, clk_volt_store = 0;\r
247         struct cpufreq_frequency_table clk_fv;\r
248         int ret = 0;\r
249         unsigned long rate_new, rate_old;\r
250         int cur_arm_high_logic, cur_logic_high_arm;\r
251 \r
252         if (!clk) {\r
253                 DVFS_ERR("%s is not a clk\n", __func__);\r
254                 return -1;\r
255         }\r
256         dvfs_clk = clk_get_dvfs_info(clk);\r
257         DVFS_DBG("enter %s: clk(%s) rate = %lu Hz\n", __func__, dvfs_clk->name, rate_hz);\r
258 \r
259         if (!dvfs_clk || dvfs_clk->vd == NULL || IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {\r
260                 DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);\r
261                 return -1;\r
262         }\r
263 \r
264         if (dvfs_clk->vd->volt_set_flag == DVFS_SET_VOLT_FAILURE) {\r
265                 /* It means the last time set voltage error */\r
266                 ret = dvfs_reset_volt(dvfs_clk->vd);\r
267                 if (ret < 0) {\r
268                         return -1;\r
269                 }\r
270         }\r
271 \r
272         /* Check limit rate */\r
273         //if (dvfs_clk->freq_limit_en) {\r
274                 if (rate_hz < dvfs_clk->min_rate) {\r
275                         rate_hz = dvfs_clk->min_rate;\r
276                 } else if (rate_hz > dvfs_clk->max_rate) {\r
277                         rate_hz = dvfs_clk->max_rate;\r
278                 }\r
279         //}\r
280 \r
281         /* need round rate */\r
282         rate_old = clk_get_rate(clk);\r
283         rate_new = clk_round_rate_nolock(clk, rate_hz);\r
284         if(rate_new == rate_old)\r
285                 return 0;\r
286 \r
287         DVFS_DBG("dvfs(%s) round rate (%lu)(rount %lu) old (%lu)\n",\r
288                         dvfs_clk->name, rate_hz, rate_new, rate_old);\r
289 \r
290         /* find the clk corresponding voltage */\r
291         if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {\r
292                 DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
293                 return -1;\r
294         }\r
295         clk_volt_store = dvfs_clk->set_volt;\r
296         dvfs_clk->set_volt = clk_fv.index;\r
297         volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
298 \r
299         /* if up the rate */\r
300         if (rate_new > rate_old) {\r
301                 if (!list_empty(&dvfs_clk->depend_list)) {\r
302                         // update depend's req_volt\r
303                         ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_new);\r
304                         if (ret <= 0)\r
305                                 goto fail_roll_back;\r
306                 }\r
307                 volt_dep_new = dvfs_vd_get_newvolt_bypd(&vd_core);\r
308                 if (volt_dep_new <= 0)\r
309                         goto fail_roll_back;\r
310 \r
311                 cur_arm_high_logic = g_arm_high_logic;\r
312                 cur_logic_high_arm = g_logic_high_arm;\r
313 \r
314 #ifdef CONFIG_ARCH_RK3188\r
315                 get_arm_logic_limit(rate_new / 1000, &g_arm_high_logic, &g_logic_high_arm);\r
316 #endif\r
317 \r
318                 ret = dvfs_scale_volt_bystep(dvfs_clk->vd, &vd_core, volt_new, volt_dep_new,\r
319                                 cur_arm_high_logic, cur_logic_high_arm, g_arm_high_logic, g_logic_high_arm);\r
320                 if (ret < 0)\r
321                         goto fail_roll_back;\r
322 \r
323         }\r
324 \r
325         /* scale rate */\r
326         if (dvfs_clk->clk_dvfs_target) {\r
327                 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);\r
328         } else {\r
329                 ret = clk_set_rate_locked(clk, rate_new);\r
330         }\r
331 \r
332         if (ret < 0) {\r
333                 DVFS_ERR("%s set rate err\n", __func__);\r
334                 goto fail_roll_back;\r
335         }\r
336         dvfs_clk->set_freq      = rate_new / 1000;\r
337 \r
338         DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));\r
339 \r
340         /* if down the rate */\r
341         if (rate_new < rate_old) {\r
342                 if (!list_empty(&dvfs_clk->depend_list)) {\r
343                         // update depend's req_volt\r
344                         ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_new);\r
345                         if (ret <= 0)\r
346                                 goto out;\r
347                 }\r
348 \r
349                 volt_dep_new = dvfs_vd_get_newvolt_bypd(&vd_core);\r
350                 if (volt_dep_new <= 0)\r
351                         goto out;\r
352 \r
353 #ifdef CONFIG_ARCH_RK3188\r
354                 get_arm_logic_limit(rate_new / 1000, &g_arm_high_logic, &g_logic_high_arm);\r
355 #endif\r
356                 cur_arm_high_logic = g_arm_high_logic;\r
357                 cur_logic_high_arm = g_logic_high_arm;\r
358 \r
359                 ret = dvfs_scale_volt_bystep(dvfs_clk->vd, &vd_core, volt_new, volt_dep_new,\r
360                                 cur_arm_high_logic, cur_logic_high_arm, g_arm_high_logic, g_logic_high_arm);\r
361                 if (ret < 0)\r
362                         goto out;\r
363 \r
364         }\r
365 \r
366         return ret;\r
367 fail_roll_back:\r
368         dvfs_clk->set_volt = clk_volt_store;\r
369         ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_old);\r
370         if (ret <= 0) {\r
371                 DVFS_ERR("%s dvfs_get_depend_volt error when roll back!\n", __func__);\r
372         }\r
373 out:\r
374         return -1;\r
375 }\r
376 \r
377 int dvfs_target_core(struct clk *clk, unsigned long rate_hz)\r
378 {\r
379         struct clk_node *dvfs_clk;\r
380         int volt_new = 0, volt_dep_new = 0, clk_volt_store = 0;\r
381         struct cpufreq_frequency_table clk_fv;\r
382         int ret = 0;\r
383         unsigned long rate_new, rate_old;\r
384 \r
385         if (!clk) {\r
386                 DVFS_ERR("%s is not a clk\n", __func__);\r
387                 return -1;\r
388         }\r
389         dvfs_clk = clk_get_dvfs_info(clk);\r
390         DVFS_DBG("enter %s: clk(%s) rate = %lu Hz\n", __func__, dvfs_clk->name, rate_hz);\r
391 \r
392         if (!dvfs_clk || dvfs_clk->vd == NULL || IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {\r
393                 DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);\r
394                 return -1;\r
395         }\r
396 \r
397         if (dvfs_clk->vd->volt_set_flag == DVFS_SET_VOLT_FAILURE) {\r
398                 /* It means the last time set voltage error */\r
399                 ret = dvfs_reset_volt(dvfs_clk->vd);\r
400                 if (ret < 0) {\r
401                         return -1;\r
402                 }\r
403         }\r
404 \r
405         /* Check limit rate */\r
406         //if (dvfs_clk->freq_limit_en) {\r
407                 if (rate_hz < dvfs_clk->min_rate) {\r
408                         rate_hz = dvfs_clk->min_rate;\r
409                 } else if (rate_hz > dvfs_clk->max_rate) {\r
410                         rate_hz = dvfs_clk->max_rate;\r
411                 }\r
412         //}\r
413 \r
414         /* need round rate */\r
415         rate_old = clk_get_rate(clk);\r
416         rate_new = clk_round_rate_nolock(clk, rate_hz);\r
417         if(rate_new == rate_old)\r
418                 return 0;\r
419         DVFS_DBG("dvfs(%s) round rate (%lu)(rount %lu) old (%lu)\n",\r
420                         dvfs_clk->name, rate_hz, rate_new, rate_old);\r
421 \r
422         /* find the clk corresponding voltage */\r
423         if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {\r
424                 DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
425                 return -1;\r
426         }\r
427         clk_volt_store = dvfs_clk->set_volt;\r
428         dvfs_clk->set_volt = clk_fv.index;\r
429         volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
430 \r
431         /* if up the rate */\r
432         if (rate_new > rate_old) {\r
433                 DVFS_DBG("-----------------------------rate_new > rate_old\n");\r
434                 volt_dep_new = dvfs_vd_get_newvolt_byclk(dvfs_clk_cpu);\r
435 \r
436                 if (volt_dep_new < 0)\r
437                         goto fail_roll_back;\r
438                 ret = dvfs_scale_volt_bystep(dvfs_clk->vd, dvfs_clk_cpu->vd, volt_new, volt_dep_new,\r
439                                 g_logic_high_arm, g_arm_high_logic, g_logic_high_arm, g_arm_high_logic);\r
440                 if (ret < 0)\r
441                         goto fail_roll_back;\r
442         }\r
443 \r
444         /* scale rate */\r
445         if (dvfs_clk->clk_dvfs_target) {\r
446                 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);\r
447         } else {\r
448                 ret = clk_set_rate_locked(clk, rate_new);\r
449         }\r
450 \r
451         if (ret < 0) {\r
452                 DVFS_ERR("%s set rate err\n", __func__);\r
453                 goto fail_roll_back;\r
454         }\r
455         dvfs_clk->set_freq      = rate_new / 1000;\r
456 \r
457         DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));\r
458 \r
459         /* if down the rate */\r
460         if (rate_new < rate_old) {\r
461                 DVFS_DBG("-----------------------------rate_new < rate_old\n");\r
462                 volt_dep_new = dvfs_vd_get_newvolt_byclk(dvfs_clk_cpu);\r
463 \r
464                 if (volt_dep_new < 0)\r
465                         goto out;\r
466                 ret = dvfs_scale_volt_bystep(dvfs_clk->vd, dvfs_clk_cpu->vd, volt_new, volt_dep_new,\r
467                                 g_logic_high_arm, g_arm_high_logic, g_logic_high_arm, g_arm_high_logic);\r
468                 if (ret < 0)\r
469                         goto out;\r
470         }\r
471 \r
472         return ret;\r
473 fail_roll_back:\r
474         dvfs_clk->set_volt = clk_volt_store;\r
475         ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_old);\r
476         if (ret <= 0) {\r
477                 DVFS_ERR("%s dvfs_get_depend_volt error when roll back!\n", __func__);\r
478         }\r
479 \r
480 out:\r
481         return -1;\r
482 }\r
483 \r
484 \r
485 #endif\r
486 /*****************************init**************************/\r
487 /**\r
488  * rate must be raising sequence\r
489  */\r
490 static struct cpufreq_frequency_table cpu_dvfs_table[] = {\r
491         // {.frequency  = 48 * DVFS_KHZ, .index = 920*DVFS_MV},\r
492         // {.frequency  = 126 * DVFS_KHZ, .index        = 970 * DVFS_MV},\r
493         // {.frequency  = 252 * DVFS_KHZ, .index        = 1040 * DVFS_MV},\r
494         // {.frequency  = 504 * DVFS_KHZ, .index        = 1050 * DVFS_MV},\r
495         {.frequency     = 816 * DVFS_KHZ, .index        = 1050 * DVFS_MV},\r
496         // {.frequency  = 1008 * DVFS_KHZ, .index       = 1100 * DVFS_MV},\r
497         {.frequency     = CPUFREQ_TABLE_END},\r
498 };\r
499 \r
500 static struct cpufreq_frequency_table ddr_dvfs_table[] = {\r
501         // {.frequency = 100 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
502         {.frequency = 200 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
503         {.frequency = 300 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
504         {.frequency = 400 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
505         {.frequency = 500 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
506         {.frequency = 600 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
507         {.frequency = CPUFREQ_TABLE_END},\r
508 };\r
509 \r
510 static struct cpufreq_frequency_table gpu_dvfs_table[] = {\r
511         {.frequency = 90 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
512         {.frequency = 180 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
513         {.frequency = 300 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
514         {.frequency = 400 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
515         {.frequency = 500 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
516         {.frequency = CPUFREQ_TABLE_END},\r
517 };\r
518 \r
519 static struct cpufreq_frequency_table peri_aclk_dvfs_table[] = {\r
520         {.frequency = 100 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
521         {.frequency = 200 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
522         {.frequency = 300 * DVFS_KHZ, .index = 1070 * DVFS_MV},\r
523         {.frequency = 500 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
524         {.frequency = CPUFREQ_TABLE_END},\r
525 };\r
526 \r
527 static struct cpufreq_frequency_table dep_cpu2core_table[] = {\r
528         // {.frequency = 252 * DVFS_KHZ, .index    = 1025 * DVFS_MV},\r
529         // {.frequency = 504 * DVFS_KHZ, .index    = 1025 * DVFS_MV},\r
530         {.frequency = 816 * DVFS_KHZ, .index    = 1050 * DVFS_MV},//logic 1.050V\r
531         // {.frequency = 1008 * DVFS_KHZ,.index    = 1050 * DVFS_MV},\r
532         // {.frequency = 1200 * DVFS_KHZ,.index    = 1050 * DVFS_MV},\r
533         // {.frequency = 1272 * DVFS_KHZ,.index    = 1050 * DVFS_MV},//logic 1.050V\r
534         // {.frequency = 1416 * DVFS_KHZ,.index    = 1100 * DVFS_MV},//logic 1.100V\r
535         // {.frequency = 1512 * DVFS_KHZ,.index    = 1125 * DVFS_MV},//logic 1.125V\r
536         // {.frequency = 1608 * DVFS_KHZ,.index    = 1175 * DVFS_MV},//logic 1.175V\r
537         {.frequency     = CPUFREQ_TABLE_END},\r
538 };\r
539 \r
540 static struct vd_node vd_cpu = {\r
541         .name           = "vd_cpu",\r
542         .regulator_name = "vdd_cpu",\r
543         .volt_set_flag          = DVFS_SET_VOLT_FAILURE,\r
544 #ifdef NO_VOLT_DIFF\r
545         .vd_dvfs_target = dvfs_target,\r
546 #else\r
547         .vd_dvfs_target = dvfs_target_cpu,\r
548 #endif\r
549 };\r
550 \r
551 static struct vd_node vd_core = {\r
552         .name           = "vd_core",\r
553         .regulator_name = "vdd_core",\r
554         .volt_set_flag          = DVFS_SET_VOLT_FAILURE,\r
555 #ifdef NO_VOLT_DIFF\r
556         .vd_dvfs_target = dvfs_target,\r
557 #else\r
558         .vd_dvfs_target = dvfs_target_core,\r
559 #endif\r
560 \r
561 };\r
562 \r
563 static struct vd_node vd_rtc = {\r
564         .name           = "vd_rtc",\r
565         .regulator_name = "vdd_rtc",\r
566         .volt_set_flag          = DVFS_SET_VOLT_FAILURE,\r
567         .vd_dvfs_target = NULL,\r
568 };\r
569 \r
570 static struct vd_node *rk30_vds[] = {&vd_cpu, &vd_core, &vd_rtc};\r
571 \r
572 static struct pd_node pd_a9_0 = {\r
573         .name                   = "pd_a9_0",\r
574         .vd                     = &vd_cpu,\r
575 };\r
576 static struct pd_node pd_a9_1 = {\r
577         .name                   = "pd_a9_1",\r
578         .vd                     = &vd_cpu,\r
579 };\r
580 static struct pd_node pd_a9_2 = {\r
581         .name                   = "pd_a9_2",\r
582         .vd                     = &vd_cpu,\r
583 };\r
584 static struct pd_node pd_a9_3 = {\r
585         .name                   = "pd_a9_3",\r
586         .vd                     = &vd_cpu,\r
587 };\r
588 \r
589 static struct pd_node pd_debug = {\r
590         .name                   = "pd_debug",\r
591         .vd                     = &vd_cpu,\r
592 };\r
593 static struct pd_node pd_scu = {\r
594         .name                   = "pd_scu",\r
595         .vd                     = &vd_cpu,\r
596 };\r
597 static struct pd_node pd_video = {\r
598         .name                   = "pd_video",\r
599         .vd                     = &vd_core,\r
600 };\r
601 static struct pd_node pd_vio = {\r
602         .name                   = "pd_vio",\r
603         .vd                     = &vd_core,\r
604 };\r
605 static struct pd_node pd_gpu = {\r
606         .name                   = "pd_gpu",\r
607         .vd                     = &vd_core,\r
608 };\r
609 static struct pd_node pd_peri = {\r
610         .name                   = "pd_peri",\r
611         .vd                     = &vd_core,\r
612 };\r
613 static struct pd_node pd_cpu = {\r
614         .name                   = "pd_cpu",\r
615         .vd                     = &vd_core,\r
616 };\r
617 static struct pd_node pd_alive = {\r
618         .name                   = "pd_alive",\r
619         .vd                     = &vd_core,\r
620 };\r
621 static struct pd_node pd_rtc = {\r
622         .name                   = "pd_rtc",\r
623         .vd                     = &vd_rtc,\r
624 };\r
625 #define LOOKUP_PD(_ppd) \\r
626 {       \\r
627         .pd     = _ppd, \\r
628 }\r
629 static struct pd_node_lookup rk30_pds[] = {\r
630         LOOKUP_PD(&pd_a9_0),\r
631         LOOKUP_PD(&pd_a9_1),\r
632         LOOKUP_PD(&pd_a9_2),\r
633         LOOKUP_PD(&pd_a9_3),\r
634         LOOKUP_PD(&pd_debug),\r
635         LOOKUP_PD(&pd_scu),\r
636         LOOKUP_PD(&pd_video),\r
637         LOOKUP_PD(&pd_vio),\r
638         LOOKUP_PD(&pd_gpu),\r
639         LOOKUP_PD(&pd_peri),\r
640         LOOKUP_PD(&pd_cpu),\r
641         LOOKUP_PD(&pd_alive),\r
642         LOOKUP_PD(&pd_rtc),\r
643 };\r
644 \r
645 #define CLK_PDS(_ppd) \\r
646 {       \\r
647         .pd     = _ppd, \\r
648 }\r
649 \r
650 static struct pds_list cpu_pds[] = {\r
651         CLK_PDS(&pd_a9_0),\r
652         CLK_PDS(&pd_a9_1),\r
653         CLK_PDS(&pd_a9_2),\r
654         CLK_PDS(&pd_a9_3),\r
655         CLK_PDS(NULL),\r
656 };\r
657 \r
658 static struct pds_list ddr_pds[] = {\r
659         CLK_PDS(&pd_cpu),\r
660         CLK_PDS(NULL),\r
661 };\r
662 \r
663 static struct pds_list gpu_pds[] = {\r
664         CLK_PDS(&pd_gpu),\r
665         CLK_PDS(NULL),\r
666 };\r
667 \r
668 static struct pds_list aclk_periph_pds[] = {\r
669         CLK_PDS(&pd_peri),\r
670         CLK_PDS(NULL),\r
671 };\r
672 \r
673 #define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb) \\r
674 { \\r
675         .name   = _clk_name, \\r
676         .pds = _ppds,\\r
677         .dvfs_table = _dvfs_table,      \\r
678         .dvfs_nb        = _dvfs_nb,     \\r
679 }\r
680 \r
681 static struct clk_node rk30_clks[] = {\r
682         RK_CLKS("cpu", cpu_pds, cpu_dvfs_table, &rk_dvfs_clk_notifier),\r
683         RK_CLKS("ddr", ddr_pds, ddr_dvfs_table, &rk_dvfs_clk_notifier),\r
684         RK_CLKS("gpu", gpu_pds, gpu_dvfs_table, &rk_dvfs_clk_notifier),\r
685         RK_CLKS("aclk_periph", aclk_periph_pds, peri_aclk_dvfs_table, &rk_dvfs_clk_notifier),\r
686 };\r
687 \r
688 #if 0\r
689 #define RK_DEPPENDS(_clk_name, _pvd, _dep_table) \\r
690 { \\r
691         .clk_name       = _clk_name, \\r
692         .dep_vd         = _pvd,\\r
693         .dep_table      = _dep_table,   \\r
694 }\r
695 \r
696 static struct depend_lookup rk30_depends[] = {\r
697 #ifndef CONFIG_ARCH_RK3188\r
698         RK_DEPPENDS("cpu", &vd_core, dep_cpu2core_table),\r
699 #endif\r
700         //RK_DEPPENDS("gpu", &vd_cpu, NULL),\r
701         //RK_DEPPENDS("gpu", &vd_cpu, NULL),\r
702 };\r
703 #endif\r
704 //static struct avs_ctr_st rk30_avs_ctr;\r
705 \r
706 int rk3188_dvfs_init(void)\r
707 {\r
708         int i = 0;\r
709         for (i = 0; i < ARRAY_SIZE(rk30_vds); i++) {\r
710                 rk_regist_vd(rk30_vds[i]);\r
711         }\r
712         for (i = 0; i < ARRAY_SIZE(rk30_pds); i++) {\r
713                 rk_regist_pd(&rk30_pds[i]);\r
714         }\r
715         for (i = 0; i < ARRAY_SIZE(rk30_clks); i++) {\r
716                 rk_regist_clk(&rk30_clks[i]);\r
717         }\r
718         #if 0\r
719         for (i = 0; i < ARRAY_SIZE(rk30_depends); i++) {\r
720                 rk_regist_depends(&rk30_depends[i]);\r
721         }\r
722         #endif\r
723 #ifndef NO_VOLT_DIFF\r
724         dvfs_clk_cpu = dvfs_get_dvfs_clk_byname("cpu");\r
725 #endif\r
726         //avs_board_init(&rk30_avs_ctr);\r
727         return 0;\r
728 }\r
729 \r
730 \r
731 \r
732 /******************************rk30 avs**************************************************/\r
733 \r
734 #if 0\r
735 \r
736 static void __iomem *rk30_nandc_base=NULL;\r
737 \r
738 #define nandc_readl(offset)     readl_relaxed(rk30_nandc_base + offset)\r
739 #define nandc_writel(v, offset) do { writel_relaxed(v, rk30_nandc_base + offset); dsb(); } while (0)\r
740 static u8 rk30_get_avs_val(void)\r
741 {\r
742         u32 nanc_save_reg[4];\r
743         unsigned long flags;\r
744         u32 paramet = 0;\r
745         u32 count = 100;\r
746         if(rk30_nandc_base==NULL)       \r
747                 return 0;\r
748                 \r
749         preempt_disable();\r
750         local_irq_save(flags);\r
751 \r
752         nanc_save_reg[0] = nandc_readl(0);\r
753         nanc_save_reg[1] = nandc_readl(0x130);\r
754         nanc_save_reg[2] = nandc_readl(0x134);\r
755         nanc_save_reg[3] = nandc_readl(0x158);\r
756 \r
757         nandc_writel(nanc_save_reg[0] | 0x1 << 14, 0);\r
758         nandc_writel(0x5, 0x130);\r
759 \r
760         nandc_writel(3, 0x158);\r
761         nandc_writel(1, 0x134);\r
762 \r
763         while(count--) {\r
764                 paramet = nandc_readl(0x138);\r
765                 if((paramet & 0x1))\r
766                         break;\r
767                 udelay(1);\r
768         };\r
769         paramet = (paramet >> 1) & 0xff;\r
770         nandc_writel(nanc_save_reg[0], 0);\r
771         nandc_writel(nanc_save_reg[1], 0x130);\r
772         nandc_writel(nanc_save_reg[2], 0x134);\r
773         nandc_writel(nanc_save_reg[3], 0x158);\r
774 \r
775         local_irq_restore(flags);\r
776         preempt_enable();\r
777         return (u8)paramet;\r
778 \r
779 }\r
780 \r
781 void rk30_avs_init(void)\r
782 {\r
783         rk30_nandc_base = ioremap(RK30_NANDC_PHYS, RK30_NANDC_SIZE);\r
784 }\r
785 static struct avs_ctr_st rk30_avs_ctr= {\r
786         .avs_init               =rk30_avs_init,\r
787         .avs_get_val    = rk30_get_avs_val,\r
788 };\r
789 #endif\r
790 \r
791 \r