ARM64: DTS: Add rk3399-firefly uart4 device, node as /dev/ttyS1
[firefly-linux-kernel-4.4.55.git] / 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 #ifdef CONFIG_ARCH_RK3066B\r
80 static int g_arm_high_logic = 50 * 1000;\r
81 static int g_logic_high_arm = 100 * 1000;\r
82 #else\r
83 static int g_arm_high_logic = 150 * 1000;\r
84 static int g_logic_high_arm = 100 * 1000;\r
85 #endif\r
86 \r
87 #if defined(CONFIG_SOC_RK3168) || defined(CONFIG_SOC_RK3028)\r
88 static struct cpufreq_frequency_table arm_high_logic_table[] = {\r
89         {.frequency = 1416 * DVFS_KHZ, .index = 0 * DVFS_MV},\r
90         {.frequency = 1608 * DVFS_KHZ, .index = 0 * DVFS_MV},\r
91         {.frequency = CPUFREQ_TABLE_END},\r
92 };\r
93 \r
94 static struct cpufreq_frequency_table logic_high_arm_table[] = {\r
95         {.frequency = 1008 * DVFS_KHZ, .index = 50 * DVFS_MV},\r
96         {.frequency = 1608 * DVFS_KHZ, .index = 50 * DVFS_MV},\r
97         {.frequency = CPUFREQ_TABLE_END},\r
98 };\r
99 #elif defined(CONFIG_ARCH_RK30XX)\r
100 static struct cpufreq_frequency_table arm_high_logic_table[] = {\r
101         {.frequency = 1416 * DVFS_KHZ, .index = 50 * DVFS_MV},\r
102         {.frequency = 1608 * DVFS_KHZ, .index = 100 * DVFS_MV},\r
103         {.frequency = CPUFREQ_TABLE_END},\r
104 };\r
105 static struct cpufreq_frequency_table logic_high_arm_table[] = {\r
106         {.frequency = 816 * DVFS_KHZ,  .index = 200 * DVFS_MV},\r
107         {.frequency = 1416 * DVFS_KHZ, .index = 150 * DVFS_MV},\r
108         {.frequency = 1608 * DVFS_KHZ, .index = 100 * DVFS_MV},\r
109 };\r
110 #else\r
111 static struct cpufreq_frequency_table arm_high_logic_table[] = {\r
112         {.frequency = 1416 * DVFS_KHZ, .index = 0 * DVFS_MV},\r
113         {.frequency = 1608 * DVFS_KHZ, .index = 0 * DVFS_MV},\r
114         {.frequency = CPUFREQ_TABLE_END},\r
115 };\r
116 \r
117 static struct cpufreq_frequency_table logic_high_arm_table[] = {\r
118         {.frequency = 1008 * DVFS_KHZ, .index = 50 * DVFS_MV},\r
119         {.frequency = 1608 * DVFS_KHZ, .index = 50 * DVFS_MV},\r
120         {.frequency = CPUFREQ_TABLE_END},\r
121 };\r
122 #endif\r
123 \r
124 int get_arm_logic_limit(unsigned long arm_rate, int *arm_high_logic, int *logic_high_arm)\r
125 {\r
126         int i;\r
127 \r
128         for (i = 0; arm_high_logic_table[i].frequency != CPUFREQ_TABLE_END; i++) {\r
129                 if (arm_rate <= arm_high_logic_table[i].frequency) {\r
130                         *arm_high_logic = arm_high_logic_table[i].index;\r
131                         break;\r
132                 }\r
133         }\r
134 \r
135         if (arm_high_logic_table[i].frequency == CPUFREQ_TABLE_END) {\r
136                 *arm_high_logic = arm_high_logic_table[i-1].index;\r
137         }\r
138 \r
139         for (i = 0; logic_high_arm_table[i].frequency != CPUFREQ_TABLE_END; i++) {\r
140                 if (arm_rate <= logic_high_arm_table[i].frequency) {\r
141                         *logic_high_arm = logic_high_arm_table[i].index;\r
142                         break;\r
143                 }\r
144         }\r
145         if (logic_high_arm_table[i].frequency == CPUFREQ_TABLE_END)\r
146                 *logic_high_arm = logic_high_arm_table[i-1].index;\r
147 \r
148         return 0;\r
149 }\r
150 \r
151 static struct clk_node *dvfs_clk_cpu;\r
152 static struct vd_node vd_core;\r
153 int dvfs_target_cpu(struct clk *clk, unsigned long rate_hz)\r
154 {\r
155         struct clk_node *dvfs_clk;\r
156         int volt_new = 0, volt_dep_new = 0, clk_volt_store = 0;\r
157         struct cpufreq_frequency_table clk_fv;\r
158         int ret = 0;\r
159         unsigned long rate_new, rate_old;\r
160         int cur_arm_high_logic, cur_logic_high_arm;\r
161 \r
162         if (!clk) {\r
163                 DVFS_ERR("%s is not a clk\n", __func__);\r
164                 return -1;\r
165         }\r
166         dvfs_clk = clk_get_dvfs_info(clk);\r
167         DVFS_DBG("enter %s: clk(%s) rate = %lu Hz\n", __func__, dvfs_clk->name, rate_hz);\r
168 \r
169         if (!dvfs_clk || dvfs_clk->vd == NULL || IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {\r
170                 DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);\r
171                 return -1;\r
172         }\r
173 \r
174         if (dvfs_clk->vd->volt_set_flag == DVFS_SET_VOLT_FAILURE) {\r
175                 /* It means the last time set voltage error */\r
176                 ret = dvfs_reset_volt(dvfs_clk->vd);\r
177                 if (ret < 0) {\r
178                         return -1;\r
179                 }\r
180         }\r
181 \r
182         /* Check limit rate */\r
183         //if (dvfs_clk->freq_limit_en) {\r
184                 if (rate_hz < dvfs_clk->min_rate) {\r
185                         rate_hz = dvfs_clk->min_rate;\r
186                 } else if (rate_hz > dvfs_clk->max_rate) {\r
187                         rate_hz = dvfs_clk->max_rate;\r
188                 }\r
189         //}\r
190 \r
191         /* need round rate */\r
192         rate_old = clk_get_rate(clk);\r
193         rate_new = clk_round_rate_nolock(clk, rate_hz);\r
194         if(rate_new == rate_old)\r
195                 return 0;\r
196 \r
197         DVFS_DBG("dvfs(%s) round rate (%lu)(rount %lu) old (%lu)\n",\r
198                         dvfs_clk->name, rate_hz, rate_new, rate_old);\r
199 \r
200         /* find the clk corresponding voltage */\r
201         if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {\r
202                 DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
203                 return -1;\r
204         }\r
205         clk_volt_store = dvfs_clk->set_volt;\r
206         dvfs_clk->set_volt = clk_fv.index;\r
207         volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
208 \r
209         /* if up the rate */\r
210         if (rate_new > rate_old) {\r
211                 if (!list_empty(&dvfs_clk->depend_list)) {\r
212                         // update depend's req_volt\r
213                         ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_new);\r
214                         if (ret <= 0)\r
215                                 goto fail_roll_back;\r
216                 }\r
217                 volt_dep_new = dvfs_vd_get_newvolt_bypd(&vd_core);\r
218                 if (volt_dep_new <= 0)\r
219                         goto fail_roll_back;\r
220 \r
221                 cur_arm_high_logic = g_arm_high_logic;\r
222                 cur_logic_high_arm = g_logic_high_arm;\r
223 \r
224 #ifdef CONFIG_ARCH_RK3066B\r
225                 get_arm_logic_limit(rate_new / 1000, &g_arm_high_logic, &g_logic_high_arm);\r
226 #endif\r
227 \r
228                 ret = dvfs_scale_volt_bystep(dvfs_clk->vd, &vd_core, volt_new, volt_dep_new,\r
229                                 cur_arm_high_logic, cur_logic_high_arm, g_arm_high_logic, g_logic_high_arm);\r
230                 if (ret < 0)\r
231                         goto fail_roll_back;\r
232 \r
233         }\r
234 \r
235         /* scale rate */\r
236         if (dvfs_clk->clk_dvfs_target) {\r
237                 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);\r
238         } else {\r
239                 ret = clk_set_rate_locked(clk, rate_new);\r
240         }\r
241 \r
242         if (ret < 0) {\r
243                 DVFS_ERR("%s set rate err\n", __func__);\r
244                 goto fail_roll_back;\r
245         }\r
246         dvfs_clk->set_freq      = rate_new / 1000;\r
247 \r
248         DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));\r
249 \r
250         /* if down the rate */\r
251         if (rate_new < rate_old) {\r
252                 if (!list_empty(&dvfs_clk->depend_list)) {\r
253                         // update depend's req_volt\r
254                         ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_new);\r
255                         if (ret <= 0)\r
256                                 goto out;\r
257                 }\r
258 \r
259                 volt_dep_new = dvfs_vd_get_newvolt_bypd(&vd_core);\r
260                 if (volt_dep_new <= 0)\r
261                         goto out;\r
262 \r
263 #ifdef CONFIG_ARCH_RK3066B\r
264                 get_arm_logic_limit(rate_new / 1000, &g_arm_high_logic, &g_logic_high_arm);\r
265 #endif\r
266                 cur_arm_high_logic = g_arm_high_logic;\r
267                 cur_logic_high_arm = g_logic_high_arm;\r
268 \r
269                 ret = dvfs_scale_volt_bystep(dvfs_clk->vd, &vd_core, volt_new, volt_dep_new,\r
270                                 cur_arm_high_logic, cur_logic_high_arm, g_arm_high_logic, g_logic_high_arm);\r
271                 if (ret < 0)\r
272                         goto out;\r
273 \r
274         }\r
275 \r
276         return ret;\r
277 fail_roll_back:\r
278         dvfs_clk->set_volt = clk_volt_store;\r
279         ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_old);\r
280         if (ret <= 0) {\r
281                 DVFS_ERR("%s dvfs_get_depend_volt error when roll back!\n", __func__);\r
282         }\r
283 out:\r
284         return -1;\r
285 }\r
286 \r
287 int dvfs_target_core(struct clk *clk, unsigned long rate_hz)\r
288 {\r
289         struct clk_node *dvfs_clk;\r
290         int volt_new = 0, volt_dep_new = 0, clk_volt_store = 0;\r
291         struct cpufreq_frequency_table clk_fv;\r
292         int ret = 0;\r
293         unsigned long rate_new, rate_old;\r
294 \r
295         if (!clk) {\r
296                 DVFS_ERR("%s is not a clk\n", __func__);\r
297                 return -1;\r
298         }\r
299         dvfs_clk = clk_get_dvfs_info(clk);\r
300         DVFS_DBG("enter %s: clk(%s) rate = %lu Hz\n", __func__, dvfs_clk->name, rate_hz);\r
301 \r
302         if (!dvfs_clk || dvfs_clk->vd == NULL || IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {\r
303                 DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);\r
304                 return -1;\r
305         }\r
306 \r
307         if (dvfs_clk->vd->volt_set_flag == DVFS_SET_VOLT_FAILURE) {\r
308                 /* It means the last time set voltage error */\r
309                 ret = dvfs_reset_volt(dvfs_clk->vd);\r
310                 if (ret < 0) {\r
311                         return -1;\r
312                 }\r
313         }\r
314 \r
315         /* Check limit rate */\r
316         //if (dvfs_clk->freq_limit_en) {\r
317                 if (rate_hz < dvfs_clk->min_rate) {\r
318                         rate_hz = dvfs_clk->min_rate;\r
319                 } else if (rate_hz > dvfs_clk->max_rate) {\r
320                         rate_hz = dvfs_clk->max_rate;\r
321                 }\r
322         //}\r
323 \r
324         /* need round rate */\r
325         rate_old = clk_get_rate(clk);\r
326         rate_new = clk_round_rate_nolock(clk, rate_hz);\r
327         if(rate_new == rate_old)\r
328                 return 0;\r
329         DVFS_DBG("dvfs(%s) round rate (%lu)(rount %lu) old (%lu)\n",\r
330                         dvfs_clk->name, rate_hz, rate_new, rate_old);\r
331 \r
332         /* find the clk corresponding voltage */\r
333         if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {\r
334                 DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
335                 return -1;\r
336         }\r
337         clk_volt_store = dvfs_clk->set_volt;\r
338         dvfs_clk->set_volt = clk_fv.index;\r
339         volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
340 \r
341         /* if up the rate */\r
342         if (rate_new > rate_old) {\r
343                 DVFS_DBG("-----------------------------rate_new > rate_old\n");\r
344                 volt_dep_new = dvfs_vd_get_newvolt_byclk(dvfs_clk_cpu);\r
345 \r
346                 if (volt_dep_new < 0)\r
347                         goto fail_roll_back;\r
348                 ret = dvfs_scale_volt_bystep(dvfs_clk->vd, dvfs_clk_cpu->vd, volt_new, volt_dep_new,\r
349                                 g_logic_high_arm, g_arm_high_logic, g_logic_high_arm, g_arm_high_logic);\r
350                 if (ret < 0)\r
351                         goto fail_roll_back;\r
352         }\r
353 \r
354         /* scale rate */\r
355         if (dvfs_clk->clk_dvfs_target) {\r
356                 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);\r
357         } else {\r
358                 ret = clk_set_rate_locked(clk, rate_new);\r
359         }\r
360 \r
361         if (ret < 0) {\r
362                 DVFS_ERR("%s set rate err\n", __func__);\r
363                 goto fail_roll_back;\r
364         }\r
365         dvfs_clk->set_freq      = rate_new / 1000;\r
366 \r
367         DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));\r
368 \r
369         /* if down the rate */\r
370         if (rate_new < rate_old) {\r
371                 DVFS_DBG("-----------------------------rate_new < rate_old\n");\r
372                 volt_dep_new = dvfs_vd_get_newvolt_byclk(dvfs_clk_cpu);\r
373 \r
374                 if (volt_dep_new < 0)\r
375                         goto out;\r
376                 ret = dvfs_scale_volt_bystep(dvfs_clk->vd, dvfs_clk_cpu->vd, volt_new, volt_dep_new,\r
377                                 g_logic_high_arm, g_arm_high_logic, g_logic_high_arm, g_arm_high_logic);\r
378                 if (ret < 0)\r
379                         goto out;\r
380         }\r
381 \r
382         return ret;\r
383 fail_roll_back:\r
384         dvfs_clk->set_volt = clk_volt_store;\r
385         ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_old);\r
386         if (ret <= 0) {\r
387                 DVFS_ERR("%s dvfs_get_depend_volt error when roll back!\n", __func__);\r
388         }\r
389 \r
390 out:\r
391         return -1;\r
392 }\r
393 \r
394 /*****************************init**************************/\r
395 /**\r
396  * rate must be raising sequence\r
397  */\r
398 static struct cpufreq_frequency_table cpu_dvfs_table[] = {\r
399         // {.frequency  = 48 * DVFS_KHZ, .index = 920*DVFS_MV},\r
400         // {.frequency  = 126 * DVFS_KHZ, .index        = 970 * DVFS_MV},\r
401         // {.frequency  = 252 * DVFS_KHZ, .index        = 1040 * DVFS_MV},\r
402         // {.frequency  = 504 * DVFS_KHZ, .index        = 1050 * DVFS_MV},\r
403         {.frequency     = 816 * DVFS_KHZ, .index        = 1050 * DVFS_MV},\r
404         // {.frequency  = 1008 * DVFS_KHZ, .index       = 1100 * DVFS_MV},\r
405         {.frequency     = CPUFREQ_TABLE_END},\r
406 };\r
407 \r
408 static struct cpufreq_frequency_table ddr_dvfs_table[] = {\r
409         // {.frequency = 100 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
410         {.frequency = 200 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
411         {.frequency = 300 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
412         {.frequency = 400 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
413         {.frequency = 500 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
414         {.frequency = 600 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
415         {.frequency = CPUFREQ_TABLE_END},\r
416 };\r
417 \r
418 static struct cpufreq_frequency_table gpu_dvfs_table[] = {\r
419         {.frequency = 90 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
420         {.frequency = 180 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
421         {.frequency = 300 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
422         {.frequency = 400 * DVFS_KHZ, .index = 1150 * DVFS_MV},\r
423         {.frequency = 500 * DVFS_KHZ, .index = 1200 * DVFS_MV},\r
424         {.frequency = CPUFREQ_TABLE_END},\r
425 };\r
426 \r
427 static struct cpufreq_frequency_table peri_aclk_dvfs_table[] = {\r
428         {.frequency = 100 * DVFS_KHZ, .index = 1000 * DVFS_MV},\r
429         {.frequency = 200 * DVFS_KHZ, .index = 1050 * DVFS_MV},\r
430         {.frequency = 300 * DVFS_KHZ, .index = 1070 * DVFS_MV},\r
431         {.frequency = 500 * DVFS_KHZ, .index = 1100 * DVFS_MV},\r
432         {.frequency = CPUFREQ_TABLE_END},\r
433 };\r
434 \r
435 static struct cpufreq_frequency_table dep_cpu2core_table[] = {\r
436         // {.frequency = 252 * DVFS_KHZ, .index    = 1025 * DVFS_MV},\r
437         // {.frequency = 504 * DVFS_KHZ, .index    = 1025 * DVFS_MV},\r
438         {.frequency = 816 * DVFS_KHZ, .index    = 1050 * DVFS_MV},//logic 1.050V\r
439         // {.frequency = 1008 * DVFS_KHZ,.index    = 1050 * DVFS_MV},\r
440         // {.frequency = 1200 * DVFS_KHZ,.index    = 1050 * DVFS_MV},\r
441         // {.frequency = 1272 * DVFS_KHZ,.index    = 1050 * DVFS_MV},//logic 1.050V\r
442         // {.frequency = 1416 * DVFS_KHZ,.index    = 1100 * DVFS_MV},//logic 1.100V\r
443         // {.frequency = 1512 * DVFS_KHZ,.index    = 1125 * DVFS_MV},//logic 1.125V\r
444         // {.frequency = 1608 * DVFS_KHZ,.index    = 1175 * DVFS_MV},//logic 1.175V\r
445         {.frequency     = CPUFREQ_TABLE_END},\r
446 };\r
447 \r
448 static struct vd_node vd_cpu = {\r
449         .name           = "vd_cpu",\r
450         .regulator_name = "vdd_cpu",\r
451         .volt_set_flag          = DVFS_SET_VOLT_FAILURE,\r
452         .vd_dvfs_target = dvfs_target_cpu,\r
453 };\r
454 \r
455 static struct vd_node vd_core = {\r
456         .name           = "vd_core",\r
457         .regulator_name = "vdd_core",\r
458         .volt_set_flag          = DVFS_SET_VOLT_FAILURE,\r
459         .vd_dvfs_target = dvfs_target_core,\r
460 };\r
461 \r
462 static struct vd_node vd_rtc = {\r
463         .name           = "vd_rtc",\r
464         .regulator_name = "vdd_rtc",\r
465         .volt_set_flag          = DVFS_SET_VOLT_FAILURE,\r
466         .vd_dvfs_target = NULL,\r
467 };\r
468 \r
469 static struct vd_node *rk30_vds[] = {&vd_cpu, &vd_core, &vd_rtc};\r
470 \r
471 static struct pd_node pd_a9_0 = {\r
472         .name                   = "pd_a9_0",\r
473         .vd                     = &vd_cpu,\r
474 };\r
475 static struct pd_node pd_a9_1 = {\r
476         .name                   = "pd_a9_1",\r
477         .vd                     = &vd_cpu,\r
478 };\r
479 static struct pd_node pd_debug = {\r
480         .name                   = "pd_debug",\r
481         .vd                     = &vd_cpu,\r
482 };\r
483 static struct pd_node pd_scu = {\r
484         .name                   = "pd_scu",\r
485         .vd                     = &vd_cpu,\r
486 };\r
487 static struct pd_node pd_video = {\r
488         .name                   = "pd_video",\r
489         .vd                     = &vd_core,\r
490 };\r
491 static struct pd_node pd_vio = {\r
492         .name                   = "pd_vio",\r
493         .vd                     = &vd_core,\r
494 };\r
495 static struct pd_node pd_gpu = {\r
496         .name                   = "pd_gpu",\r
497         .vd                     = &vd_core,\r
498 };\r
499 static struct pd_node pd_peri = {\r
500         .name                   = "pd_peri",\r
501         .vd                     = &vd_core,\r
502 };\r
503 static struct pd_node pd_cpu = {\r
504         .name                   = "pd_cpu",\r
505         .vd                     = &vd_core,\r
506 };\r
507 static struct pd_node pd_alive = {\r
508         .name                   = "pd_alive",\r
509         .vd                     = &vd_core,\r
510 };\r
511 static struct pd_node pd_rtc = {\r
512         .name                   = "pd_rtc",\r
513         .vd                     = &vd_rtc,\r
514 };\r
515 #define LOOKUP_PD(_ppd) \\r
516 {       \\r
517         .pd     = _ppd, \\r
518 }\r
519 static struct pd_node_lookup rk30_pds[] = {\r
520         LOOKUP_PD(&pd_a9_0),\r
521         LOOKUP_PD(&pd_a9_1),\r
522         LOOKUP_PD(&pd_debug),\r
523         LOOKUP_PD(&pd_scu),\r
524         LOOKUP_PD(&pd_video),\r
525         LOOKUP_PD(&pd_vio),\r
526         LOOKUP_PD(&pd_gpu),\r
527         LOOKUP_PD(&pd_peri),\r
528         LOOKUP_PD(&pd_cpu),\r
529         LOOKUP_PD(&pd_alive),\r
530         LOOKUP_PD(&pd_rtc),\r
531 };\r
532 \r
533 #define CLK_PDS(_ppd) \\r
534 {       \\r
535         .pd     = _ppd, \\r
536 }\r
537 \r
538 static struct pds_list cpu_pds[] = {\r
539         CLK_PDS(&pd_a9_0),\r
540         CLK_PDS(&pd_a9_1),\r
541         CLK_PDS(NULL),\r
542 };\r
543 \r
544 static struct pds_list ddr_pds[] = {\r
545         CLK_PDS(&pd_cpu),\r
546         CLK_PDS(NULL),\r
547 };\r
548 \r
549 static struct pds_list gpu_pds[] = {\r
550         CLK_PDS(&pd_gpu),\r
551         CLK_PDS(NULL),\r
552 };\r
553 \r
554 static struct pds_list aclk_periph_pds[] = {\r
555         CLK_PDS(&pd_peri),\r
556         CLK_PDS(NULL),\r
557 };\r
558 \r
559 #define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb) \\r
560 { \\r
561         .name   = _clk_name, \\r
562         .pds = _ppds,\\r
563         .dvfs_table = _dvfs_table,      \\r
564         .dvfs_nb        = _dvfs_nb,     \\r
565 }\r
566 \r
567 static struct clk_node rk30_clks[] = {\r
568         RK_CLKS("cpu", cpu_pds, cpu_dvfs_table, &rk_dvfs_clk_notifier),\r
569         RK_CLKS("ddr", ddr_pds, ddr_dvfs_table, &rk_dvfs_clk_notifier),\r
570         RK_CLKS("gpu", gpu_pds, gpu_dvfs_table, &rk_dvfs_clk_notifier),\r
571         RK_CLKS("aclk_periph", aclk_periph_pds, peri_aclk_dvfs_table, &rk_dvfs_clk_notifier),\r
572 };\r
573 \r
574 #define RK_DEPPENDS(_clk_name, _pvd, _dep_table) \\r
575 { \\r
576         .clk_name       = _clk_name, \\r
577         .dep_vd         = _pvd,\\r
578         .dep_table      = _dep_table,   \\r
579 }\r
580 \r
581 static struct depend_lookup rk30_depends[] = {\r
582 #ifndef CONFIG_ARCH_RK3066B\r
583         RK_DEPPENDS("cpu", &vd_core, dep_cpu2core_table),\r
584 #endif\r
585         //RK_DEPPENDS("gpu", &vd_cpu, NULL),\r
586         //RK_DEPPENDS("gpu", &vd_cpu, NULL),\r
587 };\r
588 static struct avs_ctr_st rk30_avs_ctr;\r
589 \r
590 int rk_dvfs_init(void)\r
591 {\r
592         int i = 0;\r
593         for (i = 0; i < ARRAY_SIZE(rk30_vds); i++) {\r
594                 rk_regist_vd(rk30_vds[i]);\r
595         }\r
596         for (i = 0; i < ARRAY_SIZE(rk30_pds); i++) {\r
597                 rk_regist_pd(&rk30_pds[i]);\r
598         }\r
599         for (i = 0; i < ARRAY_SIZE(rk30_clks); i++) {\r
600                 rk_regist_clk(&rk30_clks[i]);\r
601         }\r
602         for (i = 0; i < ARRAY_SIZE(rk30_depends); i++) {\r
603                 rk_regist_depends(&rk30_depends[i]);\r
604         }\r
605         dvfs_clk_cpu = dvfs_get_dvfs_clk_byname("cpu");\r
606         avs_board_init(&rk30_avs_ctr);\r
607         printk("rk30_dvfs_init\n");\r
608         return 0;\r
609 }\r
610 \r
611 \r
612 \r
613 /******************************rk30 avs**************************************************/\r
614 \r
615 \r
616 static void __iomem *rk30_nandc_base=NULL;\r
617 \r
618 #define nandc_readl(offset)     readl_relaxed(rk30_nandc_base + offset)\r
619 #define nandc_writel(v, offset) do { writel_relaxed(v, rk30_nandc_base + offset); dsb(); } while (0)\r
620 static u8 rk30_get_avs_val(void)\r
621 {\r
622         u32 nanc_save_reg[4];\r
623         unsigned long flags;\r
624         u32 paramet = 0;\r
625         u32 count = 100;\r
626         if(rk30_nandc_base==NULL)       \r
627                 return 0;\r
628                 \r
629         preempt_disable();\r
630         local_irq_save(flags);\r
631 \r
632         nanc_save_reg[0] = nandc_readl(0);\r
633         nanc_save_reg[1] = nandc_readl(0x130);\r
634         nanc_save_reg[2] = nandc_readl(0x134);\r
635         nanc_save_reg[3] = nandc_readl(0x158);\r
636 \r
637         nandc_writel(nanc_save_reg[0] | 0x1 << 14, 0);\r
638         nandc_writel(0x5, 0x130);\r
639 \r
640         /* Just break lock status */\r
641         nandc_writel(0x1, 0x158);\r
642 #ifdef CONFIG_ARCH_RK3066B\r
643         nandc_writel(3, 0x158);\r
644 #else\r
645         nandc_writel(7, 0x158);\r
646 #endif\r
647         nandc_writel(1, 0x134);\r
648 \r
649         while(count--) {\r
650                 paramet = nandc_readl(0x138);\r
651                 if((paramet & 0x1))\r
652                         break;\r
653                 udelay(1);\r
654         };\r
655         paramet = (paramet >> 1) & 0xff;\r
656         nandc_writel(nanc_save_reg[0], 0);\r
657         nandc_writel(nanc_save_reg[1], 0x130);\r
658         nandc_writel(nanc_save_reg[2], 0x134);\r
659         nandc_writel(nanc_save_reg[3], 0x158);\r
660 \r
661         local_irq_restore(flags);\r
662         preempt_enable();\r
663         return (u8)paramet;\r
664 \r
665 }\r
666 \r
667 void rk30_avs_init(void)\r
668 {\r
669         rk30_nandc_base = ioremap(RK30_NANDC_PHYS, RK30_NANDC_SIZE);\r
670 }\r
671 static struct avs_ctr_st rk30_avs_ctr= {\r
672         .avs_init               =rk30_avs_init,\r
673         .avs_get_val    = rk30_get_avs_val,\r
674 };\r
675 \r
676 \r