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
80 #define NO_VOLT_DIFF
\r
83 int dvfs_target(struct clk *clk, unsigned long rate_hz)
\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
89 unsigned long rate_new, rate_old;
\r
92 DVFS_ERR("%s is not a clk\n", __func__);
\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
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
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
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
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
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
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
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
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
144 goto fail_roll_back;
\r
148 if (dvfs_clk->clk_dvfs_target) {
\r
149 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);
\r
151 ret = clk_set_rate_locked(clk, rate_new);
\r
155 DVFS_ERR("%s set rate err\n", __func__);
\r
156 goto fail_roll_back;
\r
158 dvfs_clk->set_freq = rate_new / 1000;
\r
160 DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));
\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
171 dvfs_clk->set_volt = clk_volt_store;
\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
183 static int g_arm_high_logic = 150 * 1000;
\r
184 static int g_logic_high_arm = 100 * 1000;
\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
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
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
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
214 int get_arm_logic_limit(unsigned long arm_rate, int *arm_high_logic, int *logic_high_arm)
\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
225 if (arm_high_logic_table[i].frequency == CPUFREQ_TABLE_END) {
\r
226 *arm_high_logic = arm_high_logic_table[i-1].index;
\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
235 if (logic_high_arm_table[i].frequency == CPUFREQ_TABLE_END)
\r
236 *logic_high_arm = logic_high_arm_table[i-1].index;
\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
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
249 unsigned long rate_new, rate_old;
\r
250 int cur_arm_high_logic, cur_logic_high_arm;
\r
253 DVFS_ERR("%s is not a clk\n", __func__);
\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
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
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
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
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
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
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
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
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
305 goto fail_roll_back;
\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
311 cur_arm_high_logic = g_arm_high_logic;
\r
312 cur_logic_high_arm = g_logic_high_arm;
\r
314 #ifdef CONFIG_ARCH_RK3188
\r
315 get_arm_logic_limit(rate_new / 1000, &g_arm_high_logic, &g_logic_high_arm);
\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
321 goto fail_roll_back;
\r
326 if (dvfs_clk->clk_dvfs_target) {
\r
327 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);
\r
329 ret = clk_set_rate_locked(clk, rate_new);
\r
333 DVFS_ERR("%s set rate err\n", __func__);
\r
334 goto fail_roll_back;
\r
336 dvfs_clk->set_freq = rate_new / 1000;
\r
338 DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));
\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
349 volt_dep_new = dvfs_vd_get_newvolt_bypd(&vd_core);
\r
350 if (volt_dep_new <= 0)
\r
353 #ifdef CONFIG_ARCH_RK3188
\r
354 get_arm_logic_limit(rate_new / 1000, &g_arm_high_logic, &g_logic_high_arm);
\r
356 cur_arm_high_logic = g_arm_high_logic;
\r
357 cur_logic_high_arm = g_logic_high_arm;
\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
368 dvfs_clk->set_volt = clk_volt_store;
\r
369 ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_old);
\r
371 DVFS_ERR("%s dvfs_get_depend_volt error when roll back!\n", __func__);
\r
377 int dvfs_target_core(struct clk *clk, unsigned long rate_hz)
\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
383 unsigned long rate_new, rate_old;
\r
386 DVFS_ERR("%s is not a clk\n", __func__);
\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
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
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
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
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
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
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
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
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
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
441 goto fail_roll_back;
\r
445 if (dvfs_clk->clk_dvfs_target) {
\r
446 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);
\r
448 ret = clk_set_rate_locked(clk, rate_new);
\r
452 DVFS_ERR("%s set rate err\n", __func__);
\r
453 goto fail_roll_back;
\r
455 dvfs_clk->set_freq = rate_new / 1000;
\r
457 DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));
\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
464 if (volt_dep_new < 0)
\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
474 dvfs_clk->set_volt = clk_volt_store;
\r
475 ret = dvfs_get_depend_volt(dvfs_clk, &vd_core, rate_old);
\r
477 DVFS_ERR("%s dvfs_get_depend_volt error when roll back!\n", __func__);
\r
486 /*****************************init**************************/
\r
488 * rate must be raising sequence
\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
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
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
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
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
540 static struct vd_node 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
547 .vd_dvfs_target = dvfs_target_cpu,
\r
551 static struct vd_node 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
558 .vd_dvfs_target = dvfs_target_core,
\r
563 static struct vd_node vd_rtc = {
\r
565 .regulator_name = "vdd_rtc",
\r
566 .volt_set_flag = DVFS_SET_VOLT_FAILURE,
\r
567 .vd_dvfs_target = NULL,
\r
570 static struct vd_node *rk30_vds[] = {&vd_cpu, &vd_core, &vd_rtc};
\r
572 static struct pd_node pd_a9_0 = {
\r
576 static struct pd_node pd_a9_1 = {
\r
580 static struct pd_node pd_a9_2 = {
\r
584 static struct pd_node pd_a9_3 = {
\r
589 static struct pd_node pd_debug = {
\r
590 .name = "pd_debug",
\r
593 static struct pd_node pd_scu = {
\r
597 static struct pd_node pd_video = {
\r
598 .name = "pd_video",
\r
601 static struct pd_node pd_vio = {
\r
605 static struct pd_node pd_gpu = {
\r
609 static struct pd_node pd_peri = {
\r
613 static struct pd_node pd_cpu = {
\r
617 static struct pd_node pd_alive = {
\r
618 .name = "pd_alive",
\r
621 static struct pd_node pd_rtc = {
\r
625 #define LOOKUP_PD(_ppd) \
\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
645 #define CLK_PDS(_ppd) \
\r
650 static struct pds_list cpu_pds[] = {
\r
658 static struct pds_list ddr_pds[] = {
\r
663 static struct pds_list gpu_pds[] = {
\r
668 static struct pds_list aclk_periph_pds[] = {
\r
673 #define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb) \
\r
675 .name = _clk_name, \
\r
677 .dvfs_table = _dvfs_table, \
\r
678 .dvfs_nb = _dvfs_nb, \
\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
689 #define RK_DEPPENDS(_clk_name, _pvd, _dep_table) \
\r
691 .clk_name = _clk_name, \
\r
693 .dep_table = _dep_table, \
\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
700 //RK_DEPPENDS("gpu", &vd_cpu, NULL),
\r
701 //RK_DEPPENDS("gpu", &vd_cpu, NULL),
\r
704 //static struct avs_ctr_st rk30_avs_ctr;
\r
706 int rk3188_dvfs_init(void)
\r
709 for (i = 0; i < ARRAY_SIZE(rk30_vds); i++) {
\r
710 rk_regist_vd(rk30_vds[i]);
\r
712 for (i = 0; i < ARRAY_SIZE(rk30_pds); i++) {
\r
713 rk_regist_pd(&rk30_pds[i]);
\r
715 for (i = 0; i < ARRAY_SIZE(rk30_clks); i++) {
\r
716 rk_regist_clk(&rk30_clks[i]);
\r
719 for (i = 0; i < ARRAY_SIZE(rk30_depends); i++) {
\r
720 rk_regist_depends(&rk30_depends[i]);
\r
723 #ifndef NO_VOLT_DIFF
\r
724 dvfs_clk_cpu = dvfs_get_dvfs_clk_byname("cpu");
\r
726 //avs_board_init(&rk30_avs_ctr);
\r
732 /******************************rk30 avs**************************************************/
\r
736 static void __iomem *rk30_nandc_base=NULL;
\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
742 u32 nanc_save_reg[4];
\r
743 unsigned long flags;
\r
746 if(rk30_nandc_base==NULL)
\r
750 local_irq_save(flags);
\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
757 nandc_writel(nanc_save_reg[0] | 0x1 << 14, 0);
\r
758 nandc_writel(0x5, 0x130);
\r
760 nandc_writel(3, 0x158);
\r
761 nandc_writel(1, 0x134);
\r
764 paramet = nandc_readl(0x138);
\r
765 if((paramet & 0x1))
\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
775 local_irq_restore(flags);
\r
777 return (u8)paramet;
\r
781 void rk30_avs_init(void)
\r
783 rk30_nandc_base = ioremap(RK30_NANDC_PHYS, RK30_NANDC_SIZE);
\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