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
24 #include <mach/dvfs.h>
\r
25 #include <mach/clock.h>
\r
26 #include <linux/regulator/consumer.h>
\r
27 #include <linux/delay.h>
\r
29 #define DVFS_DBG(fmt, args...) {while(0);}
\r
30 #define DVFS_ERR(fmt, args...) pr_err("DVFS ERR:\t"fmt, ##args)
\r
31 #define DVFS_LOG(fmt, args...) pr_debug(fmt, ##args)
\r
32 //#define DVFS_LOG(fmt, args...) pr_err(fmt, ##args)
\r
34 #define dvfs_regulator_get(dev,id) regulator_get((dev),(id))
\r
35 #define dvfs_regulator_put(regu) regulator_put((regu))
\r
36 #define dvfs_regulator_set_voltage(regu,min_uV,max_uV) regulator_set_voltage((regu),(min_uV),(max_uV))
\r
37 #define dvfs_regulator_get_voltage(regu) regulator_get_voltage((regu))
\r
39 #define dvfs_clk_get(a,b) clk_get((a),(b))
\r
40 #define dvfs_clk_get_rate_kz(a) (clk_get_rate((a))/1000)
\r
41 #define dvfs_clk_set_rate(a,b) clk_set_rate((a),(b))
\r
42 #define dvfs_clk_enable(a) clk_enable((a))
\r
43 #define dvfs_clk_disable(a) clk_disable((a))
\r
45 #define DVFS_MHZ (1000*1000)
\r
46 #define DVFS_KHZ (1000)
\r
48 #define DVFS_V (1000*1000)
\r
49 #define DVFS_MV (1000)
\r
52 static LIST_HEAD(rk_dvfs_tree);
\r
53 static DEFINE_MUTEX(mutex);
\r
54 static DEFINE_MUTEX(rk_dvfs_mutex);
\r
56 extern int rk30_clk_notifier_register(struct clk *clk, struct notifier_block *nb);
\r
57 extern int rk30_clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
\r
59 // #define DVFS_DUMP_TREE
\r
60 #ifdef DVFS_DUMP_TREE
\r
61 static void dump_dbg_map(void);
\r
67 int is_support_dvfs(struct clk_node *dvfs_info)
\r
69 return (dvfs_info->vd && dvfs_info->vd->vd_dvfs_target && dvfs_info->enable_dvfs);
\r
72 int dvfs_set_rate(struct clk *clk, unsigned long rate)
\r
76 DVFS_DBG("%s(%s(%lu))\n", __func__, clk->name, rate);
\r
77 if (!clk->dvfs_info) {
\r
78 DVFS_ERR("%s :This clk do not support dvfs!\n", __func__);
\r
81 vd = clk->dvfs_info->vd;
\r
82 // mutex_lock(&vd->dvfs_mutex);
\r
83 mutex_lock(&rk_dvfs_mutex);
\r
84 ret = vd->vd_dvfs_target(clk, rate);
\r
85 mutex_unlock(&rk_dvfs_mutex);
\r
86 // mutex_unlock(&vd->dvfs_mutex);
\r
88 DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);
\r
92 static int dvfs_clk_get_ref_volt_depend(struct depend_list *depend, int rate_khz,
\r
93 struct cpufreq_frequency_table *clk_fv)
\r
96 if (rate_khz == 0 || !depend || !depend->dep_table) {
\r
99 clk_fv->frequency = rate_khz;
\r
102 for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
103 if (depend->dep_table[i].frequency >= rate_khz) {
\r
104 clk_fv->frequency = depend->dep_table[i].frequency;
\r
105 clk_fv->index = depend->dep_table[i].index;
\r
109 clk_fv->frequency = 0;
\r
113 static int dvfs_clk_get_ref_volt(struct clk_node *dvfs_clk, int rate_khz,
\r
114 struct cpufreq_frequency_table *clk_fv)
\r
117 if (rate_khz == 0 || !dvfs_clk || !dvfs_clk->dvfs_table) {
\r
118 /* since no need */
\r
121 clk_fv->frequency = rate_khz;
\r
124 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
125 if (dvfs_clk->dvfs_table[i].frequency >= rate_khz) {
\r
126 clk_fv->frequency = dvfs_clk->dvfs_table[i].frequency;
\r
127 clk_fv->index = dvfs_clk->dvfs_table[i].index;
\r
128 // DVFS_DBG("%s,%s rate=%ukhz(vol=%d)\n",__func__,dvfs_clk->name,
\r
129 // clk_fv->frequency, clk_fv->index);
\r
133 clk_fv->frequency = 0;
\r
135 // DVFS_DBG("%s get corresponding voltage error! out of bound\n", dvfs_clk->name);
\r
139 static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct clk_node *dvfs_clk)
\r
141 struct clk_list *child;
\r
144 if (!pd || !dvfs_clk)
\r
147 if (dvfs_clk->set_volt >= pd->cur_volt) {
\r
148 return dvfs_clk->set_volt;
\r
151 list_for_each_entry(child, &pd->clk_list, node) {
\r
152 // DVFS_DBG("%s ,pd(%s),dvfs(%s),volt(%u)\n",__func__,pd->name,
\r
153 // dvfs_clk->name,dvfs_clk->set_volt);
\r
154 volt_max = max(volt_max, child->dvfs_clk->set_volt);
\r
159 void dvfs_update_clk_pds_volt(struct clk_node *dvfs_clk)
\r
161 struct pd_node *pd;
\r
165 for (i = 0; (dvfs_clk->pds[i].pd != NULL); i++) {
\r
166 pd = dvfs_clk->pds[i].pd;
\r
167 // DVFS_DBG("%s dvfs(%s),pd(%s)\n",__func__,dvfs_clk->name,pd->name);
\r
168 pd->cur_volt = dvfs_pd_get_newvolt_byclk(pd, dvfs_clk);
\r
172 static int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)
\r
174 struct pd_node *pd;
\r
175 struct depend_list *depend;
\r
176 int volt_max_vd = 0;
\r
177 list_for_each_entry(pd, &vd->pd_list, node) {
\r
178 // DVFS_DBG("%s pd(%s,%u)\n",__func__,pd->name,pd->cur_volt);
\r
179 volt_max_vd = max(volt_max_vd, pd->cur_volt);
\r
182 /* some clks depend on this voltage domain */
\r
183 if (!list_empty(&vd->req_volt_list)) {
\r
184 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
\r
185 volt_max_vd = max(volt_max_vd, depend->req_volt);
\r
188 return volt_max_vd;
\r
191 static int dvfs_vd_get_newvolt_byclk(struct clk_node *dvfs_clk)
\r
195 dvfs_update_clk_pds_volt(dvfs_clk);
\r
196 return dvfs_vd_get_newvolt_bypd(dvfs_clk->vd);
\r
199 void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target)
\r
201 struct clk_node *dvfs_clk = clk_get_dvfs_info(clk);
\r
202 dvfs_clk->clk_dvfs_target = clk_dvfs_target;
\r
205 struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk)
\r
207 struct clk_node *info = clk_get_dvfs_info(clk);
\r
208 struct cpufreq_frequency_table *table;
\r
209 if (!info || !info->dvfs_table) {
\r
212 mutex_lock(&mutex);
\r
213 table = info->dvfs_table;
\r
214 mutex_unlock(&mutex);
\r
218 int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table)
\r
220 struct clk_node *info = clk_get_dvfs_info(clk);
\r
221 if (!table || !info)
\r
224 mutex_lock(&mutex);
\r
225 info->dvfs_table = table;
\r
226 mutex_unlock(&mutex);
\r
230 int dvfs_set_depend_table(struct clk *clk, char *vd_name, struct cpufreq_frequency_table *table)
\r
232 struct vd_node *vd;
\r
233 struct depend_list *depend;
\r
234 struct clk_node *info;
\r
235 info = clk_get_dvfs_info(clk);
\r
236 if (!table || !info || !vd_name) {
\r
237 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! table or info or name empty\n", __func__);
\r
241 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
242 if (0 == strcmp(vd->name, vd_name)) {
\r
243 DVFS_LOG("FOUND A MATCH\n");
\r
244 mutex_lock(&mutex);
\r
245 list_for_each_entry(depend, &info->depend_list, node2clk) {
\r
246 if (vd == depend->dep_vd && info == depend->dvfs_clk) {
\r
247 depend->dep_table = table;
\r
251 mutex_unlock(&mutex);
\r
252 #ifdef DVFS_DUMP_TREE
\r
258 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! can not find vd:%s\n", __func__, vd_name);
\r
263 int dvfs_set_arm_logic_volt(struct dvfs_arm_table *dvfs_cpu_logic_table,
\r
264 struct cpufreq_frequency_table *cpu_dvfs_table,
\r
265 struct cpufreq_frequency_table *dep_cpu2core_table)
\r
268 for (i = 0; dvfs_cpu_logic_table[i].frequency != CPUFREQ_TABLE_END; i++) {
\r
269 cpu_dvfs_table[i].frequency = dvfs_cpu_logic_table[i].frequency;
\r
270 cpu_dvfs_table[i].index = dvfs_cpu_logic_table[i].cpu_volt;
\r
272 dep_cpu2core_table[i].frequency = dvfs_cpu_logic_table[i].frequency;
\r
273 dep_cpu2core_table[i].index = dvfs_cpu_logic_table[i].logic_volt;
\r
276 cpu_dvfs_table[i].frequency = CPUFREQ_TABLE_END;
\r
277 dep_cpu2core_table[i].frequency = CPUFREQ_TABLE_END;
\r
279 dvfs_set_freq_volt_table(clk_get(NULL, "cpu"), cpu_dvfs_table);
\r
280 dvfs_set_depend_table(clk_get(NULL, "cpu"), "vd_core", dep_cpu2core_table);
\r
284 int clk_enable_dvfs(struct clk *clk)
\r
286 struct regulator *regulator;
\r
287 struct clk_node *dvfs_clk;
\r
288 struct cpufreq_frequency_table clk_fv;
\r
290 DVFS_ERR("clk enable dvfs error\n");
\r
293 dvfs_clk = clk_get_dvfs_info(clk);
\r
294 if (!dvfs_clk || !dvfs_clk->vd) {
\r
295 DVFS_ERR("%s clk(%s) not support dvfs!\n", __func__, clk->name);
\r
298 if (dvfs_clk->enable_dvfs == 0) {
\r
300 if (!dvfs_clk->vd->regulator) {
\r
302 if (dvfs_clk->vd->regulator_name)
\r
303 regulator = dvfs_regulator_get(NULL, dvfs_clk->vd->regulator_name);
\r
304 if (!IS_ERR(regulator)) {
\r
305 // DVFS_DBG("dvfs_regulator_get(%s)\n",dvfs_clk->vd->regulator_name);
\r
306 dvfs_clk->vd->regulator = regulator;
\r
308 dvfs_clk->vd->regulator = NULL;
\r
309 dvfs_clk->enable_dvfs = 0;
\r
310 DVFS_ERR("%s can't get regulator in %s\n", dvfs_clk->name, __func__);
\r
314 if (!IS_ERR(dvfs_clk->vd->regulator))
\r
315 dvfs_clk->vd->cur_volt = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);
\r
317 DVFS_ERR("%s regulator not NULL but error\n", __func__);
\r
320 // DVFS_DBG("%s(%s) vd volt=%u\n",__func__,dvfs_clk->name,dvfs_clk->vd->cur_volt);
\r
323 dvfs_clk->set_freq = dvfs_clk_get_rate_kz(clk);
\r
324 // DVFS_DBG("%s ,%s get freq%u!\n",__func__,dvfs_clk->name,dvfs_clk->set_freq);
\r
326 if (dvfs_clk_get_ref_volt(dvfs_clk, dvfs_clk->set_freq, &clk_fv)) {
\r
327 if (dvfs_clk->dvfs_table[0].frequency == CPUFREQ_TABLE_END) {
\r
328 DVFS_ERR("%s table empty\n", __func__);
\r
329 dvfs_clk->enable_dvfs = 0;
\r
332 DVFS_ERR("WARNING: %s table all value are smaller than default, use default, just enable dvfs\n", __func__);
\r
333 dvfs_clk->enable_dvfs++;
\r
338 dvfs_clk->set_volt = clk_fv.index;
\r
339 // DVFS_DBG("%s,%s,freq%u(ref vol %u)\n",__func__,dvfs_clk->name,
\r
340 // dvfs_clk->set_freq,dvfs_clk->set_volt);
\r
342 if (dvfs_clk->dvfs_nb) {
\r
343 // must unregister when clk disable
\r
344 rk30_clk_notifier_register(clk, dvfs_clk->dvfs_nb);
\r
347 dvfs_vd_get_newvolt_byclk(dvfs_clk);
\r
348 dvfs_clk->enable_dvfs++;
\r
350 DVFS_ERR("dvfs already enable clk enable = %d!\n", dvfs_clk->enable_dvfs);
\r
351 dvfs_clk->enable_dvfs++;
\r
356 int clk_disable_dvfs(struct clk *clk)
\r
358 struct clk_node *dvfs_clk;
\r
359 dvfs_clk = clk->dvfs_info;
\r
360 if (!dvfs_clk->enable_dvfs) {
\r
361 DVFS_DBG("clk is already closed!\n");
\r
364 dvfs_clk->enable_dvfs--;
\r
365 if (0 == dvfs_clk->enable_dvfs) {
\r
366 DVFS_ERR("clk closed!\n");
\r
367 rk30_clk_notifier_unregister(clk, dvfs_clk->dvfs_nb);
\r
368 DVFS_DBG("clk unregister nb!\n");
\r
374 static int rk_dvfs_clk_notifier_event(struct notifier_block *this,
\r
375 unsigned long event, void *ptr)
\r
377 struct clk_notifier_data *noti_info;
\r
379 struct clk_node *dvfs_clk;
\r
380 noti_info = (struct clk_notifier_data *)ptr;
\r
381 clk = noti_info->clk;
\r
382 dvfs_clk = clk->dvfs_info;
\r
385 case CLK_PRE_RATE_CHANGE:
\r
386 DVFS_DBG("%s CLK_PRE_RATE_CHANGE\n", __func__);
\r
388 case CLK_POST_RATE_CHANGE:
\r
389 DVFS_DBG("%s CLK_POST_RATE_CHANGE\n", __func__);
\r
391 case CLK_ABORT_RATE_CHANGE:
\r
392 DVFS_DBG("%s CLK_ABORT_RATE_CHANGE\n", __func__);
\r
394 case CLK_PRE_ENABLE:
\r
395 DVFS_DBG("%s CLK_PRE_ENABLE\n", __func__);
\r
397 case CLK_POST_ENABLE:
\r
398 DVFS_DBG("%s CLK_POST_ENABLE\n", __func__);
\r
400 case CLK_ABORT_ENABLE:
\r
401 DVFS_DBG("%s CLK_ABORT_ENABLE\n", __func__);
\r
403 case CLK_PRE_DISABLE:
\r
404 DVFS_DBG("%s CLK_PRE_DISABLE\n", __func__);
\r
406 case CLK_POST_DISABLE:
\r
407 DVFS_DBG("%s CLK_POST_DISABLE\n", __func__);
\r
408 dvfs_clk->set_freq = 0;
\r
410 case CLK_ABORT_DISABLE:
\r
411 DVFS_DBG("%s CLK_ABORT_DISABLE\n", __func__);
\r
420 static struct notifier_block rk_dvfs_clk_notifier = {
\r
421 .notifier_call = rk_dvfs_clk_notifier_event,
\r
424 static struct clk_node *dvfs_get_dvfs_clk_byname(char *name)
\r
426 struct vd_node *vd;
\r
427 struct pd_node *pd;
\r
428 struct clk_list *child;
\r
429 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
430 list_for_each_entry(pd, &vd->pd_list, node) {
\r
431 list_for_each_entry(child, &pd->clk_list, node) {
\r
432 if (0 == strcmp(child->dvfs_clk->name, name)) {
\r
433 return child->dvfs_clk;
\r
440 static int rk_regist_vd(struct vd_node *vd)
\r
444 mutex_lock(&mutex);
\r
445 //mutex_init(&vd->dvfs_mutex);
\r
446 list_add(&vd->node, &rk_dvfs_tree);
\r
447 INIT_LIST_HEAD(&vd->pd_list);
\r
448 INIT_LIST_HEAD(&vd->req_volt_list);
\r
450 mutex_unlock(&mutex);
\r
454 static int rk_regist_pd(struct pd_node_lookup *pd_lookup)
\r
456 struct vd_node *vd;
\r
457 struct pd_node *pd;
\r
459 mutex_lock(&mutex);
\r
460 pd = pd_lookup->pd;
\r
462 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
463 if (vd == pd->vd) {
\r
464 list_add(&pd->node, &vd->pd_list);
\r
465 INIT_LIST_HEAD(&pd->clk_list);
\r
469 mutex_unlock(&mutex);
\r
473 static int rk_regist_clk(struct clk_node *dvfs_clk)
\r
475 struct pd_node *pd;
\r
476 struct clk_list *child;
\r
483 if (!dvfs_clk->pds)
\r
485 mutex_lock(&mutex);
\r
486 dvfs_clk->enable_dvfs = 0;
\r
487 dvfs_clk->vd = dvfs_clk->pds[0].pd->vd;
\r
488 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {
\r
489 child = &(dvfs_clk->pds[i].clk_list);
\r
490 child->dvfs_clk = dvfs_clk;
\r
491 pd = dvfs_clk->pds[i].pd;
\r
492 list_add(&child->node, &pd->clk_list);
\r
494 clk = dvfs_clk_get(NULL, dvfs_clk->name);
\r
495 dvfs_clk->clk = clk;
\r
496 clk_register_dvfs(dvfs_clk, clk);
\r
497 INIT_LIST_HEAD(&dvfs_clk->depend_list);
\r
498 mutex_unlock(&mutex);
\r
502 static int rk_regist_depends(struct depend_lookup *dep_node)
\r
504 struct depend_list *depend_list;
\r
505 struct clk_node *dvfs_clk;
\r
508 DVFS_ERR("%s : DVFS BAD depend node!\n", __func__);
\r
512 if (!dep_node->clk_name || !dep_node->dep_vd) {
\r
513 DVFS_ERR("%s : DVFS BAD depend members!\n", __func__);
\r
517 depend_list = &dep_node->dep_list;
\r
518 dvfs_clk = dvfs_get_dvfs_clk_byname(dep_node->clk_name);
\r
520 mutex_lock(&mutex);
\r
522 depend_list->dvfs_clk = dvfs_clk;
\r
523 depend_list->dep_vd = dep_node->dep_vd;
\r
524 depend_list->dep_table = dep_node->dep_table;
\r
526 list_add(&depend_list->node2clk, &dvfs_clk->depend_list);
\r
527 list_add(&depend_list->node2vd, &depend_list->dep_vd->req_volt_list);
\r
529 mutex_unlock(&mutex);
\r
533 #define get_volt_up_delay(new_volt, old_volt) \
\r
534 ((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 10) : 0)
\r
536 static int dvfs_set_depend_pre(struct clk_node *dvfs_clk, unsigned long rate_old, unsigned long rate_new)
\r
538 struct depend_list *depend;
\r
539 struct cpufreq_frequency_table clk_fv;
\r
542 struct regulator *regulator;
\r
544 if (rate_old >= rate_new) {
\r
547 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {
\r
548 ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv);
\r
550 DVFS_ERR("%s LOGIC DVFS CAN NOT GET REF VOLT!, frequency too large!\n", __func__);
\r
554 if (!depend->dep_vd->regulator) {
\r
555 DVFS_LOG("%s regulator empty\n", __func__);
\r
556 regulator = dvfs_regulator_get(NULL, depend->dep_vd->regulator_name);
\r
558 DVFS_ERR("%s get regulator err\n", __func__);
\r
562 depend->dep_vd->regulator = regulator;
\r
564 if (IS_ERR(depend->dep_vd->regulator)) {
\r
565 DVFS_ERR("%s vd's(%s) regulator not NULL but error\n", __func__, depend->dep_vd->name);
\r
569 if (clk_fv.index == dvfs_regulator_get_voltage(depend->dep_vd->regulator)) {
\r
570 depend->req_volt = clk_fv.index;
\r
571 DVFS_LOG("%s same voltage\n", __func__);
\r
575 depend->req_volt = clk_fv.index;
\r
576 volt = dvfs_vd_get_newvolt_bypd(depend->dep_vd);
\r
577 DVFS_LOG("%s setting voltage = %d\n", __func__, volt);
\r
578 ret = dvfs_regulator_set_voltage(depend->dep_vd->regulator, volt, volt);
\r
580 DVFS_ERR("%s set voltage = %d ERROR, ret = %d\n", __func__, volt, ret);
\r
584 DVFS_LOG("%s set voltage = %d OK, ret = %d\n", __func__, volt, ret);
\r
586 DVFS_ERR("%s err, ret = %d\n", __func__, ret);
\r
594 static int dvfs_set_depend_post(struct clk_node *dvfs_clk, unsigned long rate_old, unsigned long rate_new)
\r
596 struct depend_list *depend;
\r
597 struct cpufreq_frequency_table clk_fv;
\r
600 struct regulator *regulator;
\r
602 if (rate_old <= rate_new)
\r
604 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {
\r
605 ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv);
\r
607 DVFS_ERR("%s LOGIC DVFS CAN NOT GET REF VOLT!, frequency too large!\n", __func__);
\r
611 if (!depend->dep_vd->regulator) {
\r
612 DVFS_LOG("%s regulator empty\n", __func__);
\r
613 regulator = dvfs_regulator_get(NULL, depend->dep_vd->regulator_name);
\r
615 DVFS_ERR("%s get regulator err\n", __func__);
\r
619 depend->dep_vd->regulator = regulator;
\r
621 if (IS_ERR(depend->dep_vd->regulator)) {
\r
622 DVFS_ERR("%s vd's(%s) regulator not NULL but error\n", __func__, depend->dep_vd->name);
\r
626 if (clk_fv.index == dvfs_regulator_get_voltage(depend->dep_vd->regulator)) {
\r
627 depend->req_volt = clk_fv.index;
\r
628 DVFS_LOG("%s same voltage\n", __func__);
\r
632 depend->req_volt = clk_fv.index;
\r
633 volt = dvfs_vd_get_newvolt_bypd(depend->dep_vd);
\r
634 DVFS_LOG("%s setting voltage = %d\n", __func__, volt);
\r
635 ret = dvfs_regulator_set_voltage(depend->dep_vd->regulator, volt, volt);
\r
637 DVFS_ERR("%s set voltage = %d ERROR, ret = %d\n", __func__, volt, ret);
\r
641 DVFS_LOG("%s set voltage = %d OK, ret = %d\n", __func__, volt, ret);
\r
643 DVFS_ERR("%s err, ret = %d\n", __func__, ret);
\r
651 static int flag_core_set_volt_err = 0;
\r
652 int dvfs_target_core(struct clk *clk, unsigned long rate_hz)
\r
654 struct clk_node *dvfs_clk;
\r
655 unsigned int volt_new = 0, volt_old = 0, volt_clk_old = 0;
\r
656 struct cpufreq_frequency_table clk_fv = {0, 0};
\r
658 int flag_set_volt_correct = 0;
\r
659 unsigned long rate_new, rate_old;
\r
662 DVFS_ERR("%s is not clk\n", __func__);
\r
665 dvfs_clk = clk_get_dvfs_info(clk);
\r
667 if (!dvfs_clk || dvfs_clk->vd->regulator == NULL) {
\r
668 DVFS_ERR("%s can't get dvfs regulater\n", clk->name);
\r
672 rate_new = rate_hz;
\r
673 rate_old = clk_get_rate(clk);
\r
674 if(!is_suport_round_rate(clk))
\r
676 rate_new=clk_round_rate_nolock(clk, rate_hz);
\r
678 if(rate_new==rate_old)
\r
682 // DVFS_DBG("dvfs(%s) round rate(%lu)(rount %lu)\n",dvfs_clk->name,rate_hz,rate_new);
\r
684 /* find the clk corresponding voltage */
\r
685 if (dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {
\r
686 DVFS_ERR("%s--%s:rate%lu,Get corresponding voltage error!\n",
\r
687 __func__, dvfs_clk->name, rate_new);
\r
690 volt_old = dvfs_clk->vd->cur_volt;
\r
691 volt_clk_old = dvfs_clk->set_volt;
\r
692 dvfs_clk->set_volt = clk_fv.index;
\r
693 volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);
\r
695 DVFS_DBG("dvfs--(%s),volt=%d(was %dmV),rate=%lu(was %lu),vd%u=(was%u)\n",
\r
696 dvfs_clk->name, clk_fv.index, dvfs_clk->set_volt, rate_new, rate_old
\r
697 , volt_new, volt_old);
\r
699 if (flag_core_set_volt_err) {
\r
700 /* It means the last time set voltage error */
\r
701 if (!IS_ERR(dvfs_clk->vd->regulator))
\r
702 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);
\r
704 DVFS_ERR("dvfs regulator is ERROR\n");
\r
707 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);
\r
708 if (flag_set_volt_correct <= 0) {
\r
709 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload core_volt error %d!!! stop scaling\n",
\r
710 __func__, dvfs_clk->name, volt_new, volt_old,
\r
711 rate_new, rate_old, flag_set_volt_correct);
\r
715 flag_core_set_volt_err = 0;
\r
716 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload core_volt! core_volt_correct = %d\n",
\r
717 __func__, dvfs_clk->name, volt_new, volt_old,
\r
718 rate_new, rate_old, flag_set_volt_correct);
\r
720 /* Reset vd's voltage */
\r
721 dvfs_clk->vd->cur_volt = flag_set_volt_correct;
\r
722 volt_old = dvfs_clk->vd->cur_volt;
\r
725 /* if up the voltage */
\r
726 if (volt_old < volt_new) {
\r
727 if (!IS_ERR(dvfs_clk->vd->regulator)) {
\r
728 ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);
\r
730 flag_core_set_volt_err = 1;
\r
731 DVFS_ERR("%s %s set voltage up err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n",
\r
732 __func__, dvfs_clk->name, ret,
\r
733 rate_new, rate_old, volt_new, volt_old);
\r
738 DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);
\r
742 dvfs_clk->vd->cur_volt = volt_new;
\r
743 udelay(get_volt_up_delay(volt_new, volt_old));
\r
744 DVFS_DBG("%s %s set voltage OK up ret = %d, Vnew = %d(was %d), Rnew = %lu(was %lu)\n",
\r
745 __func__, dvfs_clk->name, ret, volt_new, volt_old, rate_new, rate_old);
\r
748 if (dvfs_clk->clk_dvfs_target) {
\r
749 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);
\r
751 ret = clk_set_rate_locked(clk, rate_new);
\r
756 dvfs_clk->set_volt = volt_old;
\r
757 dvfs_vd_get_newvolt_byclk(dvfs_clk);
\r
758 DVFS_ERR("set rate err\n");
\r
761 dvfs_clk->set_freq = rate_new / 1000;
\r
763 /* if down the voltage */
\r
764 if (volt_old > volt_new) {
\r
765 if (!IS_ERR(dvfs_clk->vd->regulator)) {
\r
766 ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);
\r
768 flag_core_set_volt_err = 1;
\r
769 DVFS_ERR("%s %s set voltage down err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n",
\r
770 __func__, dvfs_clk->name, ret, rate_new, rate_old,
\r
771 volt_new, volt_old);
\r
776 DVFS_ERR("%s down volt dvfs_clk->vd->regulator == NULL\n", __func__);
\r
780 dvfs_clk->vd->cur_volt = volt_new;
\r
781 DVFS_DBG("dvfs %s set volt ok dn\n", dvfs_clk->name);
\r
788 static int flag_arm_set_volt_err = 0;
\r
789 int dvfs_target_cpu(struct clk *clk, unsigned long rate_hz)
\r
791 struct clk_node *dvfs_clk;
\r
792 int volt_new = 0, volt_old = 0;
\r
793 struct cpufreq_frequency_table clk_fv;
\r
795 int flag_set_volt_correct = 0;
\r
796 unsigned long rate_new, rate_old;
\r
800 DVFS_ERR("%s is not clk\n", __func__);
\r
803 dvfs_clk = clk_get_dvfs_info(clk);
\r
805 if (!dvfs_clk || dvfs_clk->vd->regulator == NULL) {
\r
806 DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);
\r
810 /* need round rate */
\r
811 rate_new = clk_round_rate_nolock(clk, rate_hz);
\r
812 DVFS_DBG("dvfs(%s) round rate (%lu)(rount %lu)\n", dvfs_clk->name, rate_hz, rate_new);
\r
814 rate_old = clk_get_rate(clk);
\r
815 /* find the clk corresponding voltage */
\r
816 if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_new / 1000, &clk_fv)) {
\r
817 DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);
\r
821 volt_old = dvfs_clk->vd->cur_volt;
\r
822 volt_new = clk_fv.index;
\r
823 if (flag_arm_set_volt_err) {
\r
824 /* It means the last time set voltage error */
\r
825 if (!IS_ERR(dvfs_clk->vd->regulator))
\r
826 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_clk->vd->regulator);
\r
828 DVFS_ERR("dvfs regulator is ERROR\n");
\r
830 if (flag_set_volt_correct <= 0) {
\r
831 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload arm_volt error %d!!! stop scaling\n",
\r
832 __func__, dvfs_clk->name, volt_new, volt_old,
\r
833 rate_new, rate_old, flag_set_volt_correct);
\r
837 flag_arm_set_volt_err = 0;
\r
838 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), try to reload arm_volt! arm_volt_correct = %d\n",
\r
839 __func__, dvfs_clk->name, volt_new, volt_old,
\r
840 rate_new, rate_old, flag_set_volt_correct);
\r
842 /* Reset vd's voltage */
\r
843 dvfs_clk->vd->cur_volt = flag_set_volt_correct;
\r
844 volt_old = dvfs_clk->vd->cur_volt;
\r
847 /* if up the voltage */
\r
848 if (volt_old < volt_new) {
\r
849 if (!IS_ERR(dvfs_clk->vd->regulator)) {
\r
850 ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);
\r
852 flag_arm_set_volt_err = 1;
\r
853 DVFS_ERR("%s %s set voltage up err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n",
\r
854 __func__, dvfs_clk->name, ret, rate_new, rate_old,
\r
855 volt_new, volt_old);
\r
860 DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);
\r
864 dvfs_clk->vd->cur_volt = volt_new;
\r
865 udelay(get_volt_up_delay(volt_new, volt_old));
\r
866 DVFS_DBG("%s %s set voltage OK up ret = %d, Vnew = %d(was %d), Rnew = %lu(was %lu)\n",
\r
867 __func__, dvfs_clk->name, ret, volt_new, volt_old, rate_new, rate_old);
\r
870 /* depend voltage domain set up*/
\r
871 if (0 != dvfs_set_depend_pre(dvfs_clk, rate_old, rate_new)) {
\r
872 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), set depend pre voltage err, stop scaling\n",
\r
873 __func__, dvfs_clk->name, volt_new, volt_old,
\r
874 rate_new, rate_old);
\r
878 if (dvfs_clk->clk_dvfs_target) {
\r
879 ret = dvfs_clk->clk_dvfs_target(clk, rate_new, clk_set_rate_locked);
\r
881 ret = clk_set_rate_locked(clk, rate_new);
\r
885 DVFS_ERR("set rate err\n");
\r
888 dvfs_clk->set_freq = rate_new / 1000;
\r
890 DVFS_DBG("dvfs %s set rate %lu ok\n", dvfs_clk->name, clk_get_rate(clk));
\r
892 /* depend voltage domain set down*/
\r
893 if (0 != dvfs_set_depend_post(dvfs_clk, rate_old, rate_new)) {
\r
894 DVFS_ERR("%s (clk:%s),volt=%d(was %dmV),rate=%lu(was %lu), set depend post voltage err, stop scaling\n",
\r
895 __func__, dvfs_clk->name, volt_new, volt_old,
\r
896 rate_new, rate_old);
\r
900 /* if down the voltage */
\r
901 if (volt_old > volt_new) {
\r
902 if (!IS_ERR(dvfs_clk->vd->regulator)) {
\r
903 ret = dvfs_regulator_set_voltage(dvfs_clk->vd->regulator, volt_new, volt_new);
\r
905 flag_arm_set_volt_err = 1;
\r
906 DVFS_ERR("%s %s set voltage down err ret = %d, Rnew = %lu(was %lu)Hz, Vnew = %d(was %d)mV\n",
\r
907 __func__, dvfs_clk->name, ret, rate_new, rate_old,
\r
908 volt_new, volt_old);
\r
913 DVFS_ERR("%s down volt dvfs_clk->vd->regulator == NULL\n", __func__);
\r
917 dvfs_clk->vd->cur_volt = volt_new;
\r
918 DVFS_DBG("dvfs %s set volt ok dn\n", dvfs_clk->name);
\r
927 /*****************************init**************************/
\r
929 * rate must be raising sequence
\r
931 static struct cpufreq_frequency_table cpu_dvfs_table[] = {
\r
932 // {.frequency = 48 * DVFS_KHZ, .index = 920*DVFS_MV},
\r
933 // {.frequency = 126 * DVFS_KHZ, .index = 970 * DVFS_MV},
\r
934 // {.frequency = 252 * DVFS_KHZ, .index = 1040 * DVFS_MV},
\r
935 // {.frequency = 504 * DVFS_KHZ, .index = 1050 * DVFS_MV},
\r
936 {.frequency = 816 * DVFS_KHZ, .index = 1050 * DVFS_MV},
\r
937 // {.frequency = 1008 * DVFS_KHZ, .index = 1100 * DVFS_MV},
\r
938 {.frequency = CPUFREQ_TABLE_END},
\r
941 static struct cpufreq_frequency_table ddr_dvfs_table[] = {
\r
942 // {.frequency = 100 * DVFS_KHZ, .index = 1100 * DVFS_MV},
\r
943 {.frequency = 200 * DVFS_KHZ, .index = 1000 * DVFS_MV},
\r
944 {.frequency = 300 * DVFS_KHZ, .index = 1050 * DVFS_MV},
\r
945 {.frequency = 400 * DVFS_KHZ, .index = 1100 * DVFS_MV},
\r
946 {.frequency = 500 * DVFS_KHZ, .index = 1150 * DVFS_MV},
\r
947 {.frequency = 600 * DVFS_KHZ, .index = 1200 * DVFS_MV},
\r
948 {.frequency = CPUFREQ_TABLE_END},
\r
951 static struct cpufreq_frequency_table gpu_dvfs_table[] = {
\r
952 {.frequency = 90 * DVFS_KHZ, .index = 1100 * DVFS_MV},
\r
953 {.frequency = 180 * DVFS_KHZ, .index = 1150 * DVFS_MV},
\r
954 {.frequency = 300 * DVFS_KHZ, .index = 1100 * DVFS_MV},
\r
955 {.frequency = 400 * DVFS_KHZ, .index = 1150 * DVFS_MV},
\r
956 {.frequency = 500 * DVFS_KHZ, .index = 1200 * DVFS_MV},
\r
957 {.frequency = CPUFREQ_TABLE_END},
\r
960 static struct cpufreq_frequency_table peri_aclk_dvfs_table[] = {
\r
961 {.frequency = 100 * DVFS_KHZ, .index = 1000 * DVFS_MV},
\r
962 {.frequency = 200 * DVFS_KHZ, .index = 1050 * DVFS_MV},
\r
963 {.frequency = 300 * DVFS_KHZ, .index = 1070 * DVFS_MV},
\r
964 {.frequency = 500 * DVFS_KHZ, .index = 1100 * DVFS_MV},
\r
965 {.frequency = CPUFREQ_TABLE_END},
\r
968 static struct cpufreq_frequency_table dep_cpu2core_table[] = {
\r
969 // {.frequency = 252 * DVFS_KHZ, .index = 1025 * DVFS_MV},
\r
970 // {.frequency = 504 * DVFS_KHZ, .index = 1025 * DVFS_MV},
\r
971 {.frequency = 816 * DVFS_KHZ, .index = 1050 * DVFS_MV},//logic 1.050V
\r
972 // {.frequency = 1008 * DVFS_KHZ,.index = 1050 * DVFS_MV},
\r
973 // {.frequency = 1200 * DVFS_KHZ,.index = 1050 * DVFS_MV},
\r
974 // {.frequency = 1272 * DVFS_KHZ,.index = 1050 * DVFS_MV},//logic 1.050V
\r
975 // {.frequency = 1416 * DVFS_KHZ,.index = 1100 * DVFS_MV},//logic 1.100V
\r
976 // {.frequency = 1512 * DVFS_KHZ,.index = 1125 * DVFS_MV},//logic 1.125V
\r
977 // {.frequency = 1608 * DVFS_KHZ,.index = 1175 * DVFS_MV},//logic 1.175V
\r
978 {.frequency = CPUFREQ_TABLE_END},
\r
981 static struct vd_node vd_cpu = {
\r
983 .regulator_name = "vdd_cpu",
\r
984 .vd_dvfs_target = dvfs_target_cpu,
\r
987 static struct vd_node vd_core = {
\r
989 .regulator_name = "vdd_core",
\r
990 .vd_dvfs_target = dvfs_target_core,
\r
993 static struct vd_node vd_rtc = {
\r
995 .regulator_name = "vdd_rtc",
\r
996 .vd_dvfs_target = NULL,
\r
999 static struct vd_node *rk30_vds[] = {&vd_cpu, &vd_core, &vd_rtc};
\r
1001 static struct pd_node pd_a9_0 = {
\r
1002 .name = "pd_a9_0",
\r
1005 static struct pd_node pd_a9_1 = {
\r
1006 .name = "pd_a9_1",
\r
1009 static struct pd_node pd_debug = {
\r
1010 .name = "pd_debug",
\r
1013 static struct pd_node pd_scu = {
\r
1017 static struct pd_node pd_video = {
\r
1018 .name = "pd_video",
\r
1021 static struct pd_node pd_vio = {
\r
1025 static struct pd_node pd_gpu = {
\r
1029 static struct pd_node pd_peri = {
\r
1030 .name = "pd_peri",
\r
1033 static struct pd_node pd_cpu = {
\r
1037 static struct pd_node pd_alive = {
\r
1038 .name = "pd_alive",
\r
1041 static struct pd_node pd_rtc = {
\r
1045 #define LOOKUP_PD(_ppd) \
\r
1049 static struct pd_node_lookup rk30_pds[] = {
\r
1050 LOOKUP_PD(&pd_a9_0),
\r
1051 LOOKUP_PD(&pd_a9_1),
\r
1052 LOOKUP_PD(&pd_debug),
\r
1053 LOOKUP_PD(&pd_scu),
\r
1054 LOOKUP_PD(&pd_video),
\r
1055 LOOKUP_PD(&pd_vio),
\r
1056 LOOKUP_PD(&pd_gpu),
\r
1057 LOOKUP_PD(&pd_peri),
\r
1058 LOOKUP_PD(&pd_cpu),
\r
1059 LOOKUP_PD(&pd_alive),
\r
1060 LOOKUP_PD(&pd_rtc),
\r
1063 #define CLK_PDS(_ppd) \
\r
1068 static struct pds_list cpu_pds[] = {
\r
1069 CLK_PDS(&pd_a9_0),
\r
1070 CLK_PDS(&pd_a9_1),
\r
1074 static struct pds_list ddr_pds[] = {
\r
1079 static struct pds_list gpu_pds[] = {
\r
1084 static struct pds_list aclk_periph_pds[] = {
\r
1085 CLK_PDS(&pd_peri),
\r
1089 #define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb) \
\r
1091 .name = _clk_name, \
\r
1093 .dvfs_table = _dvfs_table, \
\r
1094 .dvfs_nb = _dvfs_nb, \
\r
1097 static struct clk_node rk30_clks[] = {
\r
1098 RK_CLKS("cpu", cpu_pds, cpu_dvfs_table, &rk_dvfs_clk_notifier),
\r
1099 RK_CLKS("ddr", ddr_pds, ddr_dvfs_table, &rk_dvfs_clk_notifier),
\r
1100 RK_CLKS("gpu", gpu_pds, gpu_dvfs_table, &rk_dvfs_clk_notifier),
\r
1101 RK_CLKS("aclk_periph", aclk_periph_pds, peri_aclk_dvfs_table, &rk_dvfs_clk_notifier),
\r
1104 #define RK_DEPPENDS(_clk_name, _pvd, _dep_table) \
\r
1106 .clk_name = _clk_name, \
\r
1108 .dep_table = _dep_table, \
\r
1111 static struct depend_lookup rk30_depends[] = {
\r
1112 RK_DEPPENDS("cpu", &vd_core, dep_cpu2core_table),
\r
1115 int rk30_dvfs_init(void)
\r
1118 for (i = 0; i < ARRAY_SIZE(rk30_vds); i++) {
\r
1119 rk_regist_vd(rk30_vds[i]);
\r
1121 for (i = 0; i < ARRAY_SIZE(rk30_pds); i++) {
\r
1122 rk_regist_pd(&rk30_pds[i]);
\r
1124 for (i = 0; i < ARRAY_SIZE(rk30_clks); i++) {
\r
1125 rk_regist_clk(&rk30_clks[i]);
\r
1127 for (i = 0; i < ARRAY_SIZE(rk30_depends); i++) {
\r
1128 rk_regist_depends(&rk30_depends[i]);
\r
1130 #ifdef DVFS_DUMP_TREE
\r
1136 #ifdef DVFS_DUMP_TREE
\r
1138 * dump_dbg_map() : Draw all informations of dvfs while debug
\r
1140 static void dump_dbg_map(void)
\r
1143 struct vd_node *vd;
\r
1144 struct pd_node *pd, *clkparent;
\r
1145 struct clk_list *child;
\r
1146 struct clk_node *dvfs_clk;
\r
1147 struct depend_list *depend;
\r
1149 DVFS_LOG("-------------DVFS DEBUG-----------\n\n\n");
\r
1150 DVFS_LOG("RK30 DVFS TREE:\n");
\r
1151 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
1152 DVFS_LOG("|\n|- voltage domain:%s\n", vd->name);
\r
1153 DVFS_LOG("|- current voltage:%d\n", vd->cur_volt);
\r
1154 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
\r
1155 DVFS_LOG("|- request voltage:%d, clk:%s\n", depend->req_volt, depend->dvfs_clk->name);
\r
1158 list_for_each_entry(pd, &vd->pd_list, node) {
\r
1159 DVFS_LOG("| |\n| |- power domain:%s, status = %s, current volt = %d\n",
\r
1160 pd->name, (pd->pd_status == PD_ON) ? "ON" : "OFF", pd->cur_volt);
\r
1162 list_for_each_entry(child, &pd->clk_list, node) {
\r
1163 dvfs_clk = child->dvfs_clk;
\r
1164 DVFS_LOG("| | |\n| | |- clock: %s current: rate %d, volt = %d, enable_dvfs = %s\n",
\r
1165 dvfs_clk->name, dvfs_clk->set_freq, dvfs_clk->set_volt,
\r
1166 dvfs_clk->enable_dvfs == 0 ? "DISABLE" : "ENABLE");
\r
1167 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {
\r
1168 clkparent = dvfs_clk->pds[i].pd;
\r
1169 DVFS_LOG("| | | |- clock parents: %s, vd_parent = %s\n",
\r
1170 clkparent->name, clkparent->vd->name);
\r
1173 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
1174 DVFS_LOG("| | | |- freq = %d, volt = %d\n",
\r
1175 dvfs_clk->dvfs_table[i].frequency,
\r
1176 dvfs_clk->dvfs_table[i].index);
\r
1180 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {
\r
1181 DVFS_LOG("| | | | |- DEPEND VD: %s\n", depend->dep_vd->name);
\r
1182 for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
1183 DVFS_LOG("| | | | |- freq = %d, req_volt = %d\n",
\r
1184 depend->dep_table[i].frequency,
\r
1185 depend->dep_table[i].index);
\r
1192 DVFS_LOG("-------------DVFS DEBUG END------------\n");
\r