1 /* arch/arm/mach-rk30/rk30_dvfs.c
\r
3 * Copyright (C) 2012 ROCKCHIP, Inc.
\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
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
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
30 static int rk_dvfs_clk_notifier_event(struct notifier_block *this,
\r
31 unsigned long event, void *ptr)
\r
33 struct clk_notifier_data *noti_info;
\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
41 case CLK_PRE_RATE_CHANGE:
\r
42 DVFS_DBG("%s CLK_PRE_RATE_CHANGE\n", __func__);
\r
44 case CLK_POST_RATE_CHANGE:
\r
45 DVFS_DBG("%s CLK_POST_RATE_CHANGE\n", __func__);
\r
47 case CLK_ABORT_RATE_CHANGE:
\r
48 DVFS_DBG("%s CLK_ABORT_RATE_CHANGE\n", __func__);
\r
50 case CLK_PRE_ENABLE:
\r
51 DVFS_DBG("%s CLK_PRE_ENABLE\n", __func__);
\r
53 case CLK_POST_ENABLE:
\r
54 DVFS_DBG("%s CLK_POST_ENABLE\n", __func__);
\r
56 case CLK_ABORT_ENABLE:
\r
57 DVFS_DBG("%s CLK_ABORT_ENABLE\n", __func__);
\r
59 case CLK_PRE_DISABLE:
\r
60 DVFS_DBG("%s CLK_PRE_DISABLE\n", __func__);
\r
62 case CLK_POST_DISABLE:
\r
63 DVFS_DBG("%s CLK_POST_DISABLE\n", __func__);
\r
64 dvfs_clk->set_freq = 0;
\r
66 case CLK_ABORT_DISABLE:
\r
67 DVFS_DBG("%s CLK_ABORT_DISABLE\n", __func__);
\r
76 static struct notifier_block rk_dvfs_clk_notifier = {
\r
77 .notifier_call = rk_dvfs_clk_notifier_event,
\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
83 static int g_arm_high_logic = 150 * 1000;
\r
84 static int g_logic_high_arm = 100 * 1000;
\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
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
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
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
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
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
124 int get_arm_logic_limit(unsigned long arm_rate, int *arm_high_logic, int *logic_high_arm)
\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
135 if (arm_high_logic_table[i].frequency == CPUFREQ_TABLE_END) {
\r
136 *arm_high_logic = arm_high_logic_table[i-1].index;
\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
145 if (logic_high_arm_table[i].frequency == CPUFREQ_TABLE_END)
\r
146 *logic_high_arm = logic_high_arm_table[i-1].index;
\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
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
159 unsigned long rate_new, rate_old;
\r
160 int cur_arm_high_logic, cur_logic_high_arm;
\r
163 DVFS_ERR("%s is not a clk\n", __func__);
\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
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
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
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
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
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
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
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
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
215 goto fail_roll_back;
\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
221 cur_arm_high_logic = g_arm_high_logic;
\r
222 cur_logic_high_arm = g_logic_high_arm;
\r
224 #ifdef CONFIG_ARCH_RK3066B
\r
225 get_arm_logic_limit(rate_new / 1000, &g_arm_high_logic, &g_logic_high_arm);
\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
231 goto fail_roll_back;
\r
236 if (dvfs_clk->clk_dvfs_target) {
\r
237 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);
\r
239 ret = clk_set_rate_locked(clk, rate_new);
\r
243 DVFS_ERR("%s set rate err\n", __func__);
\r
244 goto fail_roll_back;
\r
246 dvfs_clk->set_freq = rate_new / 1000;
\r
248 DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));
\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
259 volt_dep_new = dvfs_vd_get_newvolt_bypd(&vd_core);
\r
260 if (volt_dep_new <= 0)
\r
263 #ifdef CONFIG_ARCH_RK3066B
\r
264 get_arm_logic_limit(rate_new / 1000, &g_arm_high_logic, &g_logic_high_arm);
\r
266 cur_arm_high_logic = g_arm_high_logic;
\r
267 cur_logic_high_arm = g_logic_high_arm;
\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
278 dvfs_clk->set_volt = clk_volt_store;
\r
279 ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_old);
\r
281 DVFS_ERR("%s dvfs_get_depend_volt error when roll back!\n", __func__);
\r
287 int dvfs_target_core(struct clk *clk, unsigned long rate_hz)
\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
293 unsigned long rate_new, rate_old;
\r
296 DVFS_ERR("%s is not a clk\n", __func__);
\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
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
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
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
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
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
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
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
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
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
351 goto fail_roll_back;
\r
355 if (dvfs_clk->clk_dvfs_target) {
\r
356 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);
\r
358 ret = clk_set_rate_locked(clk, rate_new);
\r
362 DVFS_ERR("%s set rate err\n", __func__);
\r
363 goto fail_roll_back;
\r
365 dvfs_clk->set_freq = rate_new / 1000;
\r
367 DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));
\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
374 if (volt_dep_new < 0)
\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
384 dvfs_clk->set_volt = clk_volt_store;
\r
385 ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_old);
\r
387 DVFS_ERR("%s dvfs_get_depend_volt error when roll back!\n", __func__);
\r
394 /*****************************init**************************/
\r
396 * rate must be raising sequence
\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
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
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
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
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
448 static struct vd_node 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
455 static struct vd_node 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
462 static struct vd_node vd_rtc = {
\r
464 .regulator_name = "vdd_rtc",
\r
465 .volt_set_flag = DVFS_SET_VOLT_FAILURE,
\r
466 .vd_dvfs_target = NULL,
\r
469 static struct vd_node *rk30_vds[] = {&vd_cpu, &vd_core, &vd_rtc};
\r
471 static struct pd_node pd_a9_0 = {
\r
475 static struct pd_node pd_a9_1 = {
\r
479 static struct pd_node pd_debug = {
\r
480 .name = "pd_debug",
\r
483 static struct pd_node pd_scu = {
\r
487 static struct pd_node pd_video = {
\r
488 .name = "pd_video",
\r
491 static struct pd_node pd_vio = {
\r
495 static struct pd_node pd_gpu = {
\r
499 static struct pd_node pd_peri = {
\r
503 static struct pd_node pd_cpu = {
\r
507 static struct pd_node pd_alive = {
\r
508 .name = "pd_alive",
\r
511 static struct pd_node pd_rtc = {
\r
515 #define LOOKUP_PD(_ppd) \
\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
533 #define CLK_PDS(_ppd) \
\r
538 static struct pds_list cpu_pds[] = {
\r
544 static struct pds_list ddr_pds[] = {
\r
549 static struct pds_list gpu_pds[] = {
\r
554 static struct pds_list aclk_periph_pds[] = {
\r
559 #define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb) \
\r
561 .name = _clk_name, \
\r
563 .dvfs_table = _dvfs_table, \
\r
564 .dvfs_nb = _dvfs_nb, \
\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
574 #define RK_DEPPENDS(_clk_name, _pvd, _dep_table) \
\r
576 .clk_name = _clk_name, \
\r
578 .dep_table = _dep_table, \
\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
585 //RK_DEPPENDS("gpu", &vd_cpu, NULL),
\r
586 //RK_DEPPENDS("gpu", &vd_cpu, NULL),
\r
588 static struct avs_ctr_st rk30_avs_ctr;
\r
590 int rk_dvfs_init(void)
\r
593 for (i = 0; i < ARRAY_SIZE(rk30_vds); i++) {
\r
594 rk_regist_vd(rk30_vds[i]);
\r
596 for (i = 0; i < ARRAY_SIZE(rk30_pds); i++) {
\r
597 rk_regist_pd(&rk30_pds[i]);
\r
599 for (i = 0; i < ARRAY_SIZE(rk30_clks); i++) {
\r
600 rk_regist_clk(&rk30_clks[i]);
\r
602 for (i = 0; i < ARRAY_SIZE(rk30_depends); i++) {
\r
603 rk_regist_depends(&rk30_depends[i]);
\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
613 /******************************rk30 avs**************************************************/
\r
616 static void __iomem *rk30_nandc_base=NULL;
\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
622 u32 nanc_save_reg[4];
\r
623 unsigned long flags;
\r
626 if(rk30_nandc_base==NULL)
\r
630 local_irq_save(flags);
\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
637 nandc_writel(nanc_save_reg[0] | 0x1 << 14, 0);
\r
638 nandc_writel(0x5, 0x130);
\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
645 nandc_writel(7, 0x158);
\r
647 nandc_writel(1, 0x134);
\r
650 paramet = nandc_readl(0x138);
\r
651 if((paramet & 0x1))
\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
661 local_irq_restore(flags);
\r
663 return (u8)paramet;
\r
667 void rk30_avs_init(void)
\r
669 rk30_nandc_base = ioremap(RK30_NANDC_PHYS, RK30_NANDC_SIZE);
\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