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
31 static LIST_HEAD(rk_dvfs_tree);
\r
32 static DEFINE_MUTEX(mutex);
\r
33 static DEFINE_MUTEX(rk_dvfs_mutex);
\r
35 static int dump_dbg_map(char *buf);
\r
37 static struct workqueue_struct *dvfs_wq;
\r
40 #define DVFS_STR(on) ((on) ? "enable" : "disable")
\r
42 #define get_volt_up_delay(new_volt, old_volt) \
\r
43 ((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 9) : 0)
\r
47 /**************************************vd regulator functions***************************************/
\r
48 static void dvfs_volt_up_delay(struct vd_node *vd, int new_volt, int old_volt)
\r
51 if(new_volt <= old_volt)
\r
53 if(vd->volt_time_flag > 0)
\r
54 u_time = regulator_set_voltage_time(vd->regulator, old_volt, new_volt);
\r
57 if(u_time < 0) { // regulator is not suported time,useing default time
\r
58 DVFS_DBG("%s:vd %s is not suported getting delay time,so we use default\n",
\r
59 __FUNCTION__, vd->name);
\r
60 u_time = ((new_volt) - (old_volt)) >> 9;
\r
62 DVFS_DBG("%s:vd %s volt %d to %d delay %d us\n", __FUNCTION__, vd->name,
\r
63 old_volt, new_volt, u_time);
\r
64 if (u_time >= 1000) {
\r
65 mdelay(u_time / 1000);
\r
66 udelay(u_time % 1000);
\r
67 DVFS_ERR("regulator set vol delay is larger 1ms,old is %d,new is %d\n", old_volt, new_volt);
\r
68 } else if (u_time) {
\r
72 int dvfs_regulator_set_voltage_readback(struct regulator *regulator, int min_uV, int max_uV)
\r
74 int ret = 0, read_back = 0;
\r
75 ret = dvfs_regulator_set_voltage(regulator, max_uV, max_uV);
\r
77 DVFS_ERR("%s now read back to check voltage\n", __func__);
\r
79 /* read back to judge if it is already effect */
\r
81 read_back = dvfs_regulator_get_voltage(regulator);
\r
82 if (read_back == max_uV) {
\r
83 DVFS_ERR("%s set ERROR but already effected, volt=%d\n", __func__, read_back);
\r
86 DVFS_ERR("%s set ERROR AND NOT effected, volt=%d\n", __func__, read_back);
\r
91 // for clk enable case to get vd regulator info
\r
92 void clk_enable_dvfs_regulator_check(struct vd_node *vd)
\r
94 vd->cur_volt = dvfs_regulator_get_voltage(vd->regulator);
\r
95 if(vd->cur_volt <= 0) {
\r
96 vd->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
98 vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
101 static void dvfs_get_vd_regulator_volt_list(struct vd_node *vd)
\r
103 unsigned i, selector = dvfs_regulator_count_voltages(vd->regulator);
\r
106 if(selector > VD_VOL_LIST_CNT)
\r
107 selector = VD_VOL_LIST_CNT;
\r
109 mutex_lock(&mutex);
\r
110 for (i = 0; i < selector; i++) {
\r
111 sel_volt = dvfs_regulator_list_voltage(vd->regulator, i);
\r
112 if(sel_volt <= 0) {
\r
113 DVFS_WARNING("%s : selector=%u,but volt <=0\n", vd->name, i);
\r
116 vd->volt_list[i] = sel_volt;
\r
117 DVFS_DBG("%s:selector=%u,volt %d\n", vd->name, i, sel_volt);
\r
119 vd->n_voltages = selector;
\r
120 mutex_unlock(&mutex);
\r
124 static int vd_regulator_round_volt_max(struct vd_node *vd, int volt)
\r
129 for (i = 0; i < vd->n_voltages; i++) {
\r
130 sel_volt = vd->volt_list[i];
\r
131 if(sel_volt <= 0) {
\r
132 DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n", __FUNCTION__, i);
\r
135 if(sel_volt >= volt)
\r
141 static int vd_regulator_round_volt_min(struct vd_node *vd, int volt)
\r
146 for (i = 0; i < vd->n_voltages; i++) {
\r
147 sel_volt = vd->volt_list[i];
\r
148 if(sel_volt <= 0) {
\r
149 DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n", __FUNCTION__, i);
\r
152 if(sel_volt > volt) {
\r
154 return vd->volt_list[i-1];
\r
163 int vd_regulator_round_volt(struct vd_node *vd, int volt, int flags)
\r
165 if(!vd->n_voltages)
\r
167 if(flags == VD_LIST_RELATION_L)
\r
168 return vd_regulator_round_volt_min(vd, volt);
\r
170 return vd_regulator_round_volt_max(vd, volt);
\r
172 EXPORT_SYMBOL(vd_regulator_round_volt);
\r
175 static void dvfs_table_round_volt(struct clk_node *dvfs_clk)
\r
179 if(!dvfs_clk->dvfs_table || !dvfs_clk->vd || IS_ERR_OR_NULL(dvfs_clk->vd->regulator))
\r
181 mutex_lock(&mutex);
\r
182 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
184 test_volt = vd_regulator_round_volt(dvfs_clk->vd, dvfs_clk->dvfs_table[i].index, VD_LIST_RELATION_H);
\r
185 if(test_volt <= 0) {
\r
186 DVFS_WARNING("clk %s:round_volt : is %d,but list <=0\n", dvfs_clk->name, dvfs_clk->dvfs_table[i].index);
\r
189 DVFS_DBG("clk %s:round_volt %d to %d\n", dvfs_clk->name, dvfs_clk->dvfs_table[i].index, test_volt);
\r
190 dvfs_clk->dvfs_table[i].index = test_volt;
\r
192 mutex_unlock(&mutex);
\r
194 void dvfs_vd_get_regulator_volt_time_info(struct vd_node *vd)
\r
196 if(vd->volt_time_flag <= 0) { // check regulator support get uping vol timer
\r
197 vd->volt_time_flag = dvfs_regulator_set_voltage_time(vd->regulator, vd->cur_volt, vd->cur_volt + 200 * 1000);
\r
198 if(vd->volt_time_flag < 0) {
\r
199 DVFS_DBG("%s,vd %s volt_time is no support\n", __FUNCTION__, vd->name);
\r
201 DVFS_DBG("%s,vd %s volt_time is support,up 200mv need delay %d us\n", __FUNCTION__, vd->name, vd->volt_time_flag);
\r
207 void dvfs_vd_get_regulator_mode_info(struct vd_node *vd)
\r
209 //REGULATOR_MODE_FAST
\r
210 if(vd->mode_flag <= 0) { // check regulator support get uping vol timer
\r
211 vd->mode_flag = dvfs_regulator_get_mode(vd->regulator);
\r
212 if(vd->mode_flag == REGULATOR_MODE_FAST || vd->mode_flag == REGULATOR_MODE_NORMAL
\r
213 || vd->mode_flag == REGULATOR_MODE_IDLE || vd->mode_flag == REGULATOR_MODE_STANDBY) {
\r
214 if(dvfs_regulator_set_mode(vd->regulator, vd->mode_flag) < 0) {
\r
215 vd->mode_flag = 0; // check again
\r
219 if(vd->mode_flag > 0) {
\r
220 DVFS_DBG("%s,vd %s mode(now is %d) support\n", __FUNCTION__, vd->name, vd->mode_flag);
\r
222 DVFS_DBG("%s,vd %s mode is not support now check\n", __FUNCTION__, vd->name);
\r
228 struct regulator *dvfs_get_regulator(char *regulator_name)
\r
230 struct vd_node *vd;
\r
231 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
232 if (strcmp(regulator_name, vd->regulator_name) == 0) {
\r
233 return vd->regulator;
\r
239 /**************************************dvfs clocks functions***************************************/
\r
240 int dvfs_clk_enable_limit(struct clk *clk, unsigned int min_rate, unsigned max_rate)
\r
242 struct clk_node *dvfs_clk;
\r
244 dvfs_clk = clk->dvfs_info;
\r
246 dvfs_clk->freq_limit_en = 1;
\r
247 dvfs_clk->min_rate = min_rate;
\r
248 dvfs_clk->max_rate = max_rate;
\r
250 rate = clk_get_rate(clk);
\r
251 if (rate < min_rate)
\r
252 dvfs_clk_set_rate(clk, min_rate);
\r
253 else if (rate > max_rate)
\r
254 dvfs_clk_set_rate(clk, max_rate);
\r
258 int dvfs_clk_disable_limit(struct clk *clk)
\r
260 struct clk_node *dvfs_clk;
\r
261 dvfs_clk = clk->dvfs_info;
\r
263 dvfs_clk->freq_limit_en = 0;
\r
268 int dvfs_vd_clk_set_rate(struct clk *clk, unsigned long rate)
\r
271 struct clk_node *dvfs_info = clk_get_dvfs_info(clk);
\r
273 DVFS_DBG("%s(%s(%lu))\n", __func__, dvfs_info->name, rate);
\r
275 #if 0 // judge by reference func in rk
\r
276 if (dvfs_support_clk_set_rate(dvfs_info) == false) {
\r
277 DVFS_ERR("dvfs func:%s is not support!\n", __func__);
\r
282 if(dvfs_info->vd && dvfs_info->vd->vd_dvfs_target) {
\r
283 // mutex_lock(&vd->dvfs_mutex);
\r
284 mutex_lock(&rk_dvfs_mutex);
\r
285 ret = dvfs_info->vd->vd_dvfs_target(clk, rate);
\r
286 mutex_unlock(&rk_dvfs_mutex);
\r
287 // mutex_unlock(&vd->dvfs_mutex);
\r
289 DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);
\r
292 EXPORT_SYMBOL(dvfs_vd_clk_set_rate);
\r
294 int dvfs_vd_clk_disable(struct clk *clk, int on)
\r
297 struct clk_node *dvfs_info = clk_get_dvfs_info(clk);
\r
298 DVFS_DBG("%s(%s(%s,%lu))\n", __func__, dvfs_info->name, DVFS_STR(on), clk_get_rate(clk));
\r
301 #if 0 // judge by reference func in rk
\r
302 if (dvfs_support_clk_disable(dvfs_info) == false) {
\r
303 DVFS_ERR("dvfs func:%s is not support!\n", __func__);
\r
308 if(dvfs_info->vd && dvfs_info->vd->vd_clk_disable_target) {
\r
309 // mutex_lock(&vd->dvfs_mutex);
\r
310 mutex_lock(&rk_dvfs_mutex);
\r
311 ret = dvfs_info->vd->vd_clk_disable_target(clk, on);
\r
312 mutex_unlock(&rk_dvfs_mutex);
\r
313 // mutex_unlock(&vd->dvfs_mutex);
\r
315 DVFS_DBG("%s(%s(%s)),is end\n", __func__, dvfs_info->name, DVFS_STR(on));
\r
320 EXPORT_SYMBOL(dvfs_vd_clk_disable);
\r
323 int dvfs_vd_clk_disable_target(struct clk *clk, int on)
\r
325 struct clk_node *dvfs_clk;
\r
326 struct clk_disable_ctr *disable_ctr;
\r
330 DVFS_ERR("%s is not a clk\n", __func__);
\r
333 dvfs_clk = clk_get_dvfs_info(clk);
\r
335 DVFS_ERR("%s is not a dvfs\n", __func__);
\r
339 DVFS_DBG("%s:clk=%s(%s),count=%d\n", __FUNCTION__, dvfs_clk->name,
\r
340 DVFS_STR(on), clk_used_count(clk));
\r
342 // enable ,is usecount =0,this time will set volt
\r
343 if(clk_used_count(clk) != 0)
\r
344 return clk_set_enable_locked(clk, on);
\r
346 //disabe, is usecount =1,this time will set volt
\r
347 if(clk_used_count(clk) != 1)
\r
348 return clk_set_enable_locked(clk, on);
\r
350 if(!dvfs_clk->disable_ctr)
\r
351 return clk_set_enable_locked(clk, on);
\r
353 disable_ctr = dvfs_clk->disable_ctr;
\r
355 if(disable_ctr->delay && disable_ctr->disable_work_fn)
\r
356 cancel_delayed_work(&disable_ctr->disable_work);
\r
357 if(disable_ctr->clk_disable_target) {
\r
358 for(i = 0; i < 2; i++) {
\r
359 ret = disable_ctr->clk_disable_target(clk, on);
\r
367 // volt resume fail, Muse set rate is mini
\r
369 clk_set_rate_locked(clk, dvfs_clk->min_rate);
\r
370 DVFS_WARNING("%s:clk=%s enable set volt fail,set min rate\n", __FUNCTION__, dvfs_clk->name);
\r
374 ret = clk_set_enable_locked(clk, on);
\r
378 if(disable_ctr->delay && disable_ctr->disable_work_fn) {
\r
379 DVFS_DBG("%s:clk=%s disable delay=%d\n", __FUNCTION__, dvfs_clk->name, disable_ctr->delay);
\r
380 queue_delayed_work_on(0, dvfs_wq, &disable_ctr->disable_work,
\r
381 msecs_to_jiffies(disable_ctr->delay));
\r
383 DVFS_DBG("%s:clk=%s disable now\n", __FUNCTION__, dvfs_clk->name);
\r
384 if(disable_ctr->clk_disable_target)
\r
385 ret = disable_ctr->clk_disable_target(clk, on);
\r
391 EXPORT_SYMBOL(dvfs_vd_clk_disable_target);
\r
393 void dvfs_clk_disable_delay_work(struct work_struct *work)
\r
395 struct clk_disable_ctr *disable_ctr = container_of(work, struct clk_disable_ctr, disable_work.work);
\r
396 struct clk_node *dvfs_clk;
\r
397 if(!disable_ctr->dvfs_clk)
\r
399 dvfs_clk = disable_ctr->dvfs_clk;
\r
400 mutex_lock(&rk_dvfs_mutex);
\r
401 DVFS_DBG("%s:clk=%s disable delay work\n", __FUNCTION__, dvfs_clk->name);
\r
402 if(disable_ctr->clk_disable_target && (!clk_used_count(dvfs_clk->clk)))
\r
403 disable_ctr->clk_disable_target(dvfs_clk->clk, 0);
\r
404 mutex_unlock(&rk_dvfs_mutex);
\r
406 EXPORT_SYMBOL(dvfs_clk_disable_delay_work);
\r
408 static void dvfs_table_round_clk_rate(struct clk_node *dvfs_clk)
\r
415 if(!dvfs_clk->dvfs_table || dvfs_clk->clk == NULL || is_suport_round_rate(dvfs_clk->clk) < 0)
\r
418 mutex_lock(&mutex);
\r
419 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
420 //ddr rate = real rate+flags
\r
421 flags = dvfs_clk->dvfs_table[i].frequency % 1000;
\r
422 rate = (dvfs_clk->dvfs_table[i].frequency / 1000) * 1000;
\r
423 temp_rate = clk_round_rate(dvfs_clk->clk, rate * 1000);
\r
424 if(temp_rate <= 0) {
\r
425 DVFS_WARNING("clk %s:round_clk_rate : is %d,but round <=0", dvfs_clk->name, dvfs_clk->dvfs_table[i].frequency);
\r
428 temp_rate = (temp_rate / 1000) + flags;
\r
430 DVFS_DBG("clk %s round_clk_rate %d to %d\n",
\r
431 dvfs_clk->name, dvfs_clk->dvfs_table[i].frequency, (int)(temp_rate));
\r
433 dvfs_clk->dvfs_table[i].frequency = temp_rate;
\r
435 mutex_unlock(&mutex);
\r
438 /***************************************************************************************************/
\r
439 static int dvfs_clk_get_ref_volt_depend(struct depend_list *depend, int rate_khz,
\r
440 struct cpufreq_frequency_table *clk_fv)
\r
443 if (rate_khz == 0 || !depend || !depend->dep_table) {
\r
446 clk_fv->frequency = rate_khz;
\r
449 for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
450 if (depend->dep_table[i].frequency >= rate_khz) {
\r
451 clk_fv->frequency = depend->dep_table[i].frequency;
\r
452 clk_fv->index = depend->dep_table[i].index;
\r
456 clk_fv->frequency = 0;
\r
460 int dvfs_clk_get_ref_volt(struct clk_node *dvfs_clk, int rate_khz,
\r
461 struct cpufreq_frequency_table *clk_fv)
\r
464 if (rate_khz == 0 || !dvfs_clk || !dvfs_clk->dvfs_table) {
\r
465 /* since no need */
\r
468 clk_fv->frequency = rate_khz;
\r
471 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
472 if (dvfs_clk->dvfs_table[i].frequency >= rate_khz) {
\r
473 clk_fv->frequency = dvfs_clk->dvfs_table[i].frequency;
\r
474 clk_fv->index = dvfs_clk->dvfs_table[i].index;
\r
475 // DVFS_DBG("%s,%s rate=%ukhz(vol=%d)\n",__func__,dvfs_clk->name,
\r
476 // clk_fv->frequency, clk_fv->index);
\r
480 clk_fv->frequency = 0;
\r
482 // DVFS_DBG("%s get corresponding voltage error! out of bound\n", dvfs_clk->name);
\r
486 static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct clk_node *dvfs_clk)
\r
488 struct clk_list *child;
\r
491 if (!pd || !dvfs_clk)
\r
494 if (dvfs_clk->set_volt >= pd->cur_volt) {
\r
495 return dvfs_clk->set_volt;
\r
498 list_for_each_entry(child, &pd->clk_list, node) {
\r
499 // DVFS_DBG("%s ,pd(%s),dvfs(%s),volt(%u)\n",__func__,pd->name,
\r
500 // dvfs_clk->name,dvfs_clk->set_volt);
\r
501 volt_max = max(volt_max, child->dvfs_clk->set_volt);
\r
506 void dvfs_update_clk_pds_volt(struct clk_node *dvfs_clk)
\r
508 struct pd_node *pd;
\r
512 for (i = 0; (dvfs_clk->pds[i].pd != NULL); i++) {
\r
513 pd = dvfs_clk->pds[i].pd;
\r
514 // DVFS_DBG("%s dvfs(%s),pd(%s)\n",__func__,dvfs_clk->name,pd->name);
\r
515 pd->cur_volt = dvfs_pd_get_newvolt_byclk(pd, dvfs_clk);
\r
519 int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)
\r
521 struct pd_node *pd;
\r
522 struct depend_list *depend;
\r
523 int volt_max_vd = 0;
\r
524 list_for_each_entry(pd, &vd->pd_list, node) {
\r
525 // DVFS_DBG("%s pd(%s,%u)\n",__func__,pd->name,pd->cur_volt);
\r
526 volt_max_vd = max(volt_max_vd, pd->cur_volt);
\r
529 /* some clks depend on this voltage domain */
\r
530 if (!list_empty(&vd->req_volt_list)) {
\r
531 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
\r
532 volt_max_vd = max(volt_max_vd, depend->req_volt);
\r
535 return volt_max_vd;
\r
538 int dvfs_vd_get_newvolt_byclk(struct clk_node *dvfs_clk)
\r
542 dvfs_update_clk_pds_volt(dvfs_clk);
\r
543 return dvfs_vd_get_newvolt_bypd(dvfs_clk->vd);
\r
546 void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target)
\r
548 struct clk_node *dvfs_clk = clk_get_dvfs_info(clk);
\r
549 if (IS_ERR_OR_NULL(dvfs_clk)) {
\r
550 DVFS_ERR("%s %s get dvfs_clk err\n", __func__, clk->name);
\r
553 dvfs_clk->clk_dvfs_target = clk_dvfs_target;
\r
556 /************************************************ freq volt table************************************/
\r
557 struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk)
\r
559 struct clk_node *info = clk_get_dvfs_info(clk);
\r
560 struct cpufreq_frequency_table *table;
\r
561 if (!info || !info->dvfs_table) {
\r
564 mutex_lock(&mutex);
\r
565 table = info->dvfs_table;
\r
566 mutex_unlock(&mutex);
\r
569 EXPORT_SYMBOL(dvfs_get_freq_volt_table);
\r
571 int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table)
\r
573 struct clk_node *info = clk_get_dvfs_info(clk);
\r
579 info->min_rate = 0;
\r
580 info->max_rate = 0;
\r
584 mutex_lock(&mutex);
\r
585 info->dvfs_table = table;
\r
586 if(table[0].frequency != CPUFREQ_TABLE_END) {
\r
588 info->min_rate = (table[0].frequency / 1000) * 1000 * 1000; //to hz
\r
590 info->min_rate = 0;
\r
591 info->max_rate = 0;
\r
595 for(i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
\r
598 info->max_rate = (table[i-1].frequency / 1000) * 1000 * 1000;
\r
600 DVFS_DBG("%s,clk %s,limit max=%u,min=%u\n", __FUNCTION__, info->name, info->max_rate, info->min_rate);
\r
602 mutex_unlock(&mutex);
\r
603 dvfs_table_round_clk_rate(info);
\r
604 dvfs_table_round_volt(info);
\r
607 EXPORT_SYMBOL(dvfs_set_freq_volt_table);
\r
609 int dvfs_set_depend_table(struct clk *clk, char *vd_name, struct cpufreq_frequency_table *table)
\r
611 struct vd_node *vd;
\r
612 struct depend_list *depend;
\r
613 struct clk_node *info;
\r
615 info = clk_get_dvfs_info(clk);
\r
616 if (!table || !info || !vd_name) {
\r
617 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! table or info or name empty\n", __func__);
\r
621 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
622 if (0 == strcmp(vd->name, vd_name)) {
\r
623 DVFS_DBG("FOUND A MATCH\n");
\r
624 mutex_lock(&mutex);
\r
625 list_for_each_entry(depend, &info->depend_list, node2clk) {
\r
626 if (vd == depend->dep_vd && info == depend->dvfs_clk) {
\r
627 depend->dep_table = table;
\r
631 mutex_unlock(&mutex);
\r
635 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! can not find vd:%s\n", __func__, vd_name);
\r
640 int dvfs_set_arm_logic_volt(struct dvfs_arm_table *dvfs_cpu_logic_table,
\r
641 struct cpufreq_frequency_table *cpu_dvfs_table,
\r
642 struct cpufreq_frequency_table *dep_cpu2core_table)
\r
645 for (i = 0; dvfs_cpu_logic_table[i].frequency != CPUFREQ_TABLE_END; i++) {
\r
646 cpu_dvfs_table[i].frequency = dvfs_cpu_logic_table[i].frequency;
\r
647 cpu_dvfs_table[i].index = dvfs_cpu_logic_table[i].cpu_volt;
\r
649 dep_cpu2core_table[i].frequency = dvfs_cpu_logic_table[i].frequency;
\r
650 dep_cpu2core_table[i].index = dvfs_cpu_logic_table[i].logic_volt;
\r
653 cpu_dvfs_table[i].frequency = CPUFREQ_TABLE_END;
\r
654 dep_cpu2core_table[i].frequency = CPUFREQ_TABLE_END;
\r
656 dvfs_set_freq_volt_table(clk_get(NULL, "cpu"), cpu_dvfs_table);
\r
657 dvfs_set_depend_table(clk_get(NULL, "cpu"), "vd_core", dep_cpu2core_table);
\r
662 int clk_enable_dvfs(struct clk *clk)
\r
664 struct clk_node *dvfs_clk;
\r
665 struct cpufreq_frequency_table clk_fv;
\r
667 DVFS_ERR("clk enable dvfs error\n");
\r
670 dvfs_clk = clk_get_dvfs_info(clk);
\r
671 if (!dvfs_clk || !dvfs_clk->vd) {
\r
672 DVFS_ERR("%s clk(%s) not support dvfs!\n", __func__, clk->name);
\r
675 if (dvfs_clk->enable_dvfs == 0) {
\r
677 if (IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {
\r
678 //regulator = NULL;
\r
679 if (dvfs_clk->vd->regulator_name)
\r
680 dvfs_clk->vd->regulator = dvfs_regulator_get(NULL, dvfs_clk->vd->regulator_name);
\r
681 if (!IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {
\r
682 // DVFS_DBG("dvfs_regulator_get(%s)\n",dvfs_clk->vd->regulator_name);
\r
683 clk_enable_dvfs_regulator_check(dvfs_clk->vd);
\r
684 dvfs_get_vd_regulator_volt_list(dvfs_clk->vd);
\r
685 dvfs_vd_get_regulator_volt_time_info(dvfs_clk->vd);
\r
686 //dvfs_vd_get_regulator_mode_info(dvfs_clk->vd);
\r
688 //dvfs_clk->vd->regulator = NULL;
\r
689 dvfs_clk->enable_dvfs = 0;
\r
690 DVFS_ERR("%s can't get regulator in %s\n", dvfs_clk->name, __func__);
\r
694 clk_enable_dvfs_regulator_check(dvfs_clk->vd);
\r
695 // DVFS_DBG("%s(%s) vd volt=%u\n",__func__,dvfs_clk->name,dvfs_clk->vd->cur_volt);
\r
698 dvfs_table_round_clk_rate(dvfs_clk);
\r
699 dvfs_table_round_volt(dvfs_clk);
\r
700 dvfs_clk->set_freq = dvfs_clk_get_rate_kz(clk);
\r
701 // DVFS_DBG("%s ,%s get freq%u!\n",__func__,dvfs_clk->name,dvfs_clk->set_freq);
\r
703 if (dvfs_clk_get_ref_volt(dvfs_clk, dvfs_clk->set_freq, &clk_fv)) {
\r
704 if (dvfs_clk->dvfs_table[0].frequency == CPUFREQ_TABLE_END) {
\r
705 DVFS_ERR("%s table empty\n", __func__);
\r
706 dvfs_clk->enable_dvfs = 0;
\r
709 DVFS_WARNING("%s table all value are smaller than default, use default, just enable dvfs\n", __func__);
\r
710 dvfs_clk->enable_dvfs++;
\r
715 dvfs_clk->set_volt = clk_fv.index;
\r
716 dvfs_vd_get_newvolt_byclk(dvfs_clk);
\r
717 // DVFS_DBG("%s,%s,freq%u(ref vol %u)\n",__func__,dvfs_clk->name,
\r
718 // dvfs_clk->set_freq,dvfs_clk->set_volt);
\r
720 if (dvfs_clk->dvfs_nb) {
\r
721 // must unregister when clk disable
\r
722 clk_notifier_register(clk, dvfs_clk->dvfs_nb);
\r
727 if(dvfs_clk->vd->cur_volt < dvfs_clk->set_volt) {
\r
729 mutex_lock(&rk_dvfs_mutex);
\r
730 ret = dvfs_regulator_set_voltage_readback(dvfs_clk->vd->regulator, dvfs_clk->set_volt, dvfs_clk->set_volt);
\r
732 dvfs_clk->vd->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
733 dvfs_clk->enable_dvfs = 0;
\r
734 DVFS_ERR("dvfs enable clk %s,set volt error \n", dvfs_clk->name);
\r
735 mutex_unlock(&rk_dvfs_mutex);
\r
738 dvfs_clk->vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
739 mutex_unlock(&rk_dvfs_mutex);
\r
742 dvfs_clk->enable_dvfs++;
\r
744 DVFS_ERR("dvfs already enable clk enable = %d!\n", dvfs_clk->enable_dvfs);
\r
745 dvfs_clk->enable_dvfs++;
\r
750 int clk_disable_dvfs(struct clk *clk)
\r
752 struct clk_node *dvfs_clk;
\r
753 dvfs_clk = clk->dvfs_info;
\r
754 if (!dvfs_clk->enable_dvfs) {
\r
755 DVFS_DBG("clk is already closed!\n");
\r
758 dvfs_clk->enable_dvfs--;
\r
759 if (0 == dvfs_clk->enable_dvfs) {
\r
760 DVFS_ERR("clk closed!\n");
\r
762 clk_notifier_unregister(clk, dvfs_clk->dvfs_nb);
\r
763 DVFS_DBG("clk unregister nb!\n");
\r
769 struct clk_node *dvfs_get_dvfs_clk_byname(char *name)
\r
771 struct vd_node *vd;
\r
772 struct pd_node *pd;
\r
773 struct clk_list *child;
\r
774 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
775 list_for_each_entry(pd, &vd->pd_list, node) {
\r
776 list_for_each_entry(child, &pd->clk_list, node) {
\r
777 if (0 == strcmp(child->dvfs_clk->name, name)) {
\r
778 return child->dvfs_clk;
\r
785 int rk_regist_vd(struct vd_node *vd)
\r
789 mutex_lock(&mutex);
\r
790 //mutex_init(&vd->dvfs_mutex);
\r
791 list_add(&vd->node, &rk_dvfs_tree);
\r
792 INIT_LIST_HEAD(&vd->pd_list);
\r
793 INIT_LIST_HEAD(&vd->req_volt_list);
\r
795 vd->volt_time_flag = 0;
\r
796 vd->n_voltages = 0;
\r
797 mutex_unlock(&mutex);
\r
801 int rk_regist_pd(struct pd_node_lookup *pd_lookup)
\r
803 struct vd_node *vd;
\r
804 struct pd_node *pd;
\r
806 mutex_lock(&mutex);
\r
807 pd = pd_lookup->pd;
\r
809 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
810 if (vd == pd->vd) {
\r
811 list_add(&pd->node, &vd->pd_list);
\r
812 INIT_LIST_HEAD(&pd->clk_list);
\r
816 mutex_unlock(&mutex);
\r
820 int rk_regist_clk(struct clk_node *dvfs_clk)
\r
822 struct pd_node *pd;
\r
823 struct clk_list *child;
\r
825 struct clk_disable_ctr *disable_ctr;
\r
831 if (!dvfs_clk->pds)
\r
833 mutex_lock(&mutex);
\r
834 dvfs_clk->enable_dvfs = 0;
\r
835 dvfs_clk->vd = dvfs_clk->pds[0].pd->vd;
\r
836 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {
\r
837 child = &(dvfs_clk->pds[i].clk_list);
\r
838 child->dvfs_clk = dvfs_clk;
\r
839 pd = dvfs_clk->pds[i].pd;
\r
840 list_add(&child->node, &pd->clk_list);
\r
842 clk = dvfs_clk_get(NULL, dvfs_clk->name);
\r
843 dvfs_clk->clk = clk;
\r
844 disable_ctr = dvfs_clk->disable_ctr;
\r
846 if(disable_ctr->clk_disable_target) {
\r
847 disable_ctr->dvfs_clk = dvfs_clk;
\r
849 if(disable_ctr->delay && disable_ctr->disable_work_fn) {
\r
850 INIT_DELAYED_WORK(&disable_ctr->disable_work, disable_ctr->disable_work_fn);
\r
853 dvfs_clk->disable_ctr = NULL;
\r
855 clk_register_dvfs(dvfs_clk, clk);
\r
856 INIT_LIST_HEAD(&dvfs_clk->depend_list);
\r
857 mutex_unlock(&mutex);
\r
861 int rk_regist_depends(struct depend_lookup *dep_node)
\r
863 struct depend_list *depend_list;
\r
864 struct clk_node *dvfs_clk;
\r
867 DVFS_ERR("%s : DVFS BAD depend node!\n", __func__);
\r
871 if (!dep_node->clk_name || !dep_node->dep_vd) {
\r
872 DVFS_ERR("%s : DVFS BAD depend members!\n", __func__);
\r
876 depend_list = &dep_node->dep_list;
\r
877 dvfs_clk = dvfs_get_dvfs_clk_byname(dep_node->clk_name);
\r
879 mutex_lock(&mutex);
\r
881 depend_list->dvfs_clk = dvfs_clk;
\r
882 depend_list->dep_vd = dep_node->dep_vd;
\r
883 depend_list->dep_table = dep_node->dep_table;
\r
885 list_add(&depend_list->node2clk, &dvfs_clk->depend_list);
\r
886 list_add(&depend_list->node2vd, &depend_list->dep_vd->req_volt_list);
\r
888 mutex_unlock(&mutex);
\r
892 int correct_volt(int *volt_clk, int *volt_dep, int clk_biger_than_dep, int dep_biger_than_clk)
\r
894 int up_boundary = 0, low_boundary = 0;
\r
896 up_boundary = *volt_clk + dep_biger_than_clk;
\r
897 low_boundary = *volt_clk - clk_biger_than_dep;
\r
899 if (*volt_dep < low_boundary || *volt_dep > up_boundary) {
\r
901 if (*volt_dep < low_boundary) {
\r
902 *volt_dep = low_boundary;
\r
904 } else if (*volt_dep > up_boundary) {
\r
905 *volt_clk = *volt_dep - dep_biger_than_clk;
\r
912 int dvfs_scale_volt(struct vd_node *vd_clk, struct vd_node *vd_dep,
\r
913 int volt_old, int volt_new, int volt_dep_old, int volt_dep_new, int clk_biger_than_dep, int dep_biger_than_clk)
\r
915 struct regulator *regulator, *regulator_dep;
\r
916 int volt = 0, volt_dep = 0, step = 0, step_dep = 0;
\r
917 int volt_pre = 0, volt_dep_pre = 0;
\r
920 DVFS_DBG("ENTER %s, volt=%d(old=%d), volt_dep=%d(dep_old=%d)\n", __func__,
\r
921 volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
922 regulator = vd_clk->regulator;
\r
923 regulator_dep = vd_dep->regulator;
\r
925 if (IS_ERR_OR_NULL(regulator) || IS_ERR(regulator_dep)) {
\r
926 DVFS_ERR("%s dvfs_clk->vd->regulator or depend->dep_vd->regulator == NULL\n", __func__);
\r
931 volt_dep = volt_dep_old;
\r
933 step = volt_new - volt_old > 0 ? 1 : (-1);
\r
934 step_dep = volt_dep_new - volt_dep_old > 0 ? 1 : (-1);
\r
936 DVFS_DBG("step=%d step_dep=%d %d\n", step, step_dep, step * step_dep);
\r
938 DVFS_DBG("Volt_new=%d(old=%d), volt_dep_new=%d(dep_old=%d)\n",
\r
939 volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
942 volt_dep_pre = volt_dep;
\r
943 if (step * step_dep < 0) {
\r
944 // target is between volt_old and volt_dep_old, just
\r
946 DVFS_DBG("step * step_dep < 0\n");
\r
948 volt_dep = volt_dep_new;
\r
950 } else if (step > 0) {
\r
952 DVFS_DBG("step > 0\n");
\r
954 if (volt > volt_dep) {
\r
955 if (volt_dep == volt_dep_new) {
\r
956 volt = volt_dep + clk_biger_than_dep;
\r
958 volt_dep = volt + dep_biger_than_clk;
\r
960 } else if (volt < volt_dep) {
\r
961 if (volt == volt_new) {
\r
962 volt_dep = volt + dep_biger_than_clk;
\r
964 volt = volt_dep + clk_biger_than_dep;
\r
967 if (volt != volt_new)
\r
968 volt = volt_dep + clk_biger_than_dep;
\r
969 if (volt_dep != volt_dep_new)
\r
970 volt_dep = volt + dep_biger_than_clk;
\r
972 volt = volt > volt_new ? volt_new : volt;
\r
973 volt_dep = volt_dep > volt_dep_new ? volt_dep_new : volt_dep;
\r
975 } else if (step < 0) {
\r
977 DVFS_DBG("step < 0\n");
\r
978 if (volt > volt_dep) {
\r
979 if (volt == volt_new) {
\r
980 volt_dep = volt - clk_biger_than_dep;
\r
982 volt = volt_dep - dep_biger_than_clk;
\r
984 } else if (volt < volt_dep) {
\r
985 if (volt_dep == volt_dep_new) {
\r
986 volt = volt_dep - dep_biger_than_clk;
\r
988 volt_dep = volt - clk_biger_than_dep;
\r
991 if (volt != volt_new)
\r
992 volt = volt_dep - dep_biger_than_clk;
\r
993 if (volt_dep != volt_dep_new)
\r
994 volt_dep = volt - clk_biger_than_dep;
\r
996 volt = volt < volt_new ? volt_new : volt;
\r
997 volt_dep = volt_dep < volt_dep_new ? volt_dep_new : volt_dep;
\r
1000 DVFS_ERR("Oops, some bugs here:Volt_new=%d(old=%d), volt_dep_new=%d(dep_old=%d)\n",
\r
1001 volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
1005 if (vd_clk->cur_volt != volt) {
\r
1006 DVFS_DBG("\t\t%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt);
\r
1007 ret = dvfs_regulator_set_voltage_readback(regulator, volt, volt);
\r
1008 //udelay(get_volt_up_delay(volt, volt_pre));
\r
1009 dvfs_volt_up_delay(vd_clk, volt, volt_pre);
\r
1011 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1012 __func__, vd_clk->name, ret, volt_new, volt_old);
\r
1015 vd_clk->cur_volt = volt;
\r
1017 if (vd_dep->cur_volt != volt_dep) {
\r
1018 DVFS_DBG("\t\t%s:%d->%d\n", vd_dep->name, vd_dep->cur_volt, volt_dep);
\r
1019 ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep, volt_dep);
\r
1020 //udelay(get_volt_up_delay(volt_dep, volt_dep_pre));
\r
1021 dvfs_volt_up_delay(vd_dep, volt_dep, volt_dep_pre);
\r
1023 DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1024 __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);
\r
1027 vd_dep->cur_volt = volt_dep;
\r
1030 DVFS_DBG("\t\tNOW:Volt=%d, volt_dep=%d\n", volt, volt_dep);
\r
1032 } while (volt != volt_new || volt_dep != volt_dep_new);
\r
1034 vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
1035 vd_clk->cur_volt = volt_new;
\r
1039 DVFS_ERR("+++++++++++++++++FAIL AREA\n");
\r
1040 vd_clk->cur_volt = volt_old;
\r
1041 vd_dep->cur_volt = volt_dep_old;
\r
1042 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
1043 ret = dvfs_regulator_set_voltage_readback(regulator, volt_old, volt_old);
\r
1045 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
1046 DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",
\r
1047 __func__, vd_clk->name, ret, volt_new, volt_old);
\r
1050 ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_old, volt_dep_old);
\r
1052 vd_dep->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
1053 DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",
\r
1054 __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);
\r
1060 int dvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new)
\r
1063 DVFS_DBG("ENTER %s, volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);
\r
1064 if (IS_ERR_OR_NULL(vd_clk)) {
\r
1065 DVFS_ERR("%s vd_node error\n", __func__);
\r
1069 DVFS_DBG("ENTER %s, volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);
\r
1070 if (!IS_ERR_OR_NULL(vd_clk->regulator)) {
\r
1071 ret = dvfs_regulator_set_voltage_readback(vd_clk->regulator, volt_new, volt_new);
\r
1072 //udelay(get_volt_up_delay(volt_new, vd_clk->cur_volt));
\r
1073 dvfs_volt_up_delay(vd_clk, volt_new, vd_clk->cur_volt);
\r
1075 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
1076 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1077 __func__, vd_clk->name, ret, volt_new, vd_clk->cur_volt);
\r
1082 DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);
\r
1086 vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
1087 vd_clk->cur_volt = volt_new;
\r
1093 int dvfs_scale_volt_bystep(struct vd_node *vd_clk, struct vd_node *vd_dep, int volt_new, int volt_dep_new,
\r
1094 int cur_clk_biger_than_dep, int cur_dep_biger_than_clk, int new_clk_biger_than_dep, int new_dep_biger_than_clk)
\r
1097 struct regulator *regulator, *regulator_dep;
\r
1098 int volt_new_corrected = 0, volt_dep_new_corrected = 0;
\r
1099 int volt_old = 0, volt_dep_old = 0;
\r
1102 volt_old = vd_clk->cur_volt;
\r
1103 volt_dep_old = vd_dep->cur_volt;
\r
1105 DVFS_DBG("ENTER %s, volt=%d(old=%d) vd_dep=%d(dep_old=%d)\n", __func__,
\r
1106 volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
1107 DVFS_DBG("ENTER %s, VOLT_DIFF: clk_cur=%d(clk_new=%d) dep_cur=%d(dep_new=%d)\n", __func__,
\r
1108 cur_clk_biger_than_dep, new_clk_biger_than_dep,
\r
1109 cur_dep_biger_than_clk, new_dep_biger_than_clk);
\r
1111 volt_new_corrected = volt_new;
\r
1112 volt_dep_new_corrected = volt_dep_new;
\r
1113 correct_volt(&volt_new_corrected, &volt_dep_new_corrected, cur_clk_biger_than_dep, cur_dep_biger_than_clk);
\r
1114 ret = dvfs_scale_volt(vd_clk, vd_dep, volt_old, volt_new_corrected, volt_dep_old, volt_dep_new_corrected,
\r
1115 cur_clk_biger_than_dep, cur_dep_biger_than_clk);
\r
1117 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
1118 DVFS_ERR("set volt error\n");
\r
1122 if (cur_clk_biger_than_dep != new_clk_biger_than_dep || cur_dep_biger_than_clk != new_dep_biger_than_clk) {
\r
1123 regulator = vd_clk->regulator;
\r
1124 regulator_dep = vd_dep->regulator;
\r
1126 volt_new_corrected = volt_new;
\r
1127 volt_dep_new_corrected = volt_dep_new;
\r
1128 correct_volt(&volt_new_corrected, &volt_dep_new_corrected, new_clk_biger_than_dep, new_dep_biger_than_clk);
\r
1129 DVFS_DBG("last step to correct volt:\n");
\r
1130 if (vd_clk->cur_volt != volt_new_corrected) {
\r
1131 DVFS_DBG("\t\t%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt_new_corrected);
\r
1132 ret = dvfs_regulator_set_voltage_readback(regulator, volt_new_corrected, volt_new_corrected);
\r
1133 //udelay(get_volt_up_delay(volt_new_corrected, vd_clk->cur_volt));
\r
1134 dvfs_volt_up_delay(vd_clk, volt_new_corrected, vd_clk->cur_volt);
\r
1136 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1137 __func__, vd_clk->name, ret, volt_new_corrected, vd_clk->cur_volt);
\r
1140 vd_clk->cur_volt = volt_new_corrected;
\r
1142 if (vd_dep->cur_volt != volt_dep_new_corrected) {
\r
1143 DVFS_DBG("\t\t%s:%d->%d\n", vd_dep->name, vd_dep->cur_volt, volt_dep_new_corrected);
\r
1144 ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_new_corrected, volt_dep_new_corrected);
\r
1145 //udelay(get_volt_up_delay(volt_dep_new_corrected, vd_dep->cur_volt));
\r
1146 dvfs_volt_up_delay(vd_dep, volt_dep_new_corrected, vd_dep->cur_volt);
\r
1148 DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1149 __func__, vd_dep->name, ret, volt_dep_new_corrected, vd_dep->cur_volt);
\r
1152 vd_dep->cur_volt = volt_dep_new_corrected;
\r
1159 int dvfs_reset_volt(struct vd_node *dvfs_vd)
\r
1161 int flag_set_volt_correct = 0;
\r
1162 if (!IS_ERR_OR_NULL(dvfs_vd->regulator))
\r
1163 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_vd->regulator);
\r
1165 DVFS_ERR("dvfs regulator is ERROR\n");
\r
1168 if (flag_set_volt_correct <= 0) {
\r
1169 DVFS_ERR("%s (vd:%s), try to reload volt ,by it is error again(%d)!!! stop scaling\n",
\r
1170 __func__, dvfs_vd->name, flag_set_volt_correct);
\r
1173 dvfs_vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
1174 DVFS_WARNING("%s (vd:%s), try to reload volt = %d\n",
\r
1175 __func__, dvfs_vd->name, flag_set_volt_correct);
\r
1177 /* Reset vd's voltage */
\r
1178 dvfs_vd->cur_volt = flag_set_volt_correct;
\r
1180 return dvfs_vd->cur_volt;
\r
1183 int dvfs_get_depend_volt(struct clk_node *dvfs_clk, struct vd_node *dvfs_vd_dep, int rate_new)
\r
1185 struct depend_list *depend;
\r
1186 struct cpufreq_frequency_table clk_fv_dep;
\r
1189 DVFS_DBG("ENTER %s, rate_new=%d\n", __func__, rate_new);
\r
1190 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {
\r
1191 DVFS_DBG("--round depend clk:%s(depend:%s)\n", depend->dvfs_clk->name, depend->dep_vd->name);
\r
1192 // this place just consider ONE depend voltage domain,
\r
1193 // multi-depends must have some differece
\r
1194 clk_fv_dep.index = 0;
\r
1195 if (depend->dep_vd == dvfs_vd_dep) {
\r
1196 ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv_dep);
\r
1198 DVFS_ERR("%s get dvfs_ref_volt_depend error\n", __func__);
\r
1201 depend->req_volt = clk_fv_dep.index;
\r
1202 return depend->req_volt;
\r
1206 DVFS_ERR("%s can not find vd node %s\n", __func__, dvfs_vd_dep->name);
\r
1211 * dump_dbg_map() : Draw all informations of dvfs while debug
\r
1213 static int dump_dbg_map(char *buf)
\r
1216 struct vd_node *vd;
\r
1217 struct pd_node *pd, *clkparent;
\r
1218 struct clk_list *child;
\r
1219 struct clk_node *dvfs_clk;
\r
1220 struct depend_list *depend;
\r
1222 mutex_lock(&rk_dvfs_mutex);
\r
1224 printk( "-------------DVFS TREE-----------\n\n\n");
\r
1225 printk( "DVFS TREE:\n");
\r
1226 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
1227 printk( "|\n|- voltage domain:%s\n", vd->name);
\r
1228 printk( "|- current voltage:%d\n", vd->cur_volt);
\r
1229 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
\r
1230 printk( "|- request voltage:%d, clk:%s\n", depend->req_volt, depend->dvfs_clk->name);
\r
1233 list_for_each_entry(pd, &vd->pd_list, node) {
\r
1234 printk( "| |\n| |- power domain:%s, status = %s, current volt = %d\n",
\r
1235 pd->name, (pd->pd_status == PD_ON) ? "ON" : "OFF", pd->cur_volt);
\r
1237 list_for_each_entry(child, &pd->clk_list, node) {
\r
1238 dvfs_clk = child->dvfs_clk;
\r
1239 printk( "| | |\n| | |- clock: %s current: rate %d, volt = %d, enable_dvfs = %s\n",
\r
1240 dvfs_clk->name, dvfs_clk->set_freq, dvfs_clk->set_volt,
\r
1241 dvfs_clk->enable_dvfs == 0 ? "DISABLE" : "ENABLE");
\r
1242 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {
\r
1243 clkparent = dvfs_clk->pds[i].pd;
\r
1244 printk( "| | | |- clock parents: %s, vd_parent = %s\n",
\r
1245 clkparent->name, clkparent->vd->name);
\r
1248 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
1249 printk( "| | | |- freq = %d, volt = %d\n",
\r
1250 dvfs_clk->dvfs_table[i].frequency,
\r
1251 dvfs_clk->dvfs_table[i].index);
\r
1255 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {
\r
1256 printk( "| | | | |- DEPEND VD: %s\n", depend->dep_vd->name);
\r
1257 for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
1258 printk( "| | | | |- freq = %d, req_volt = %d\n",
\r
1259 depend->dep_table[i].frequency,
\r
1261 depend->dep_table[i].index);
\r
1267 printk( "-------------DVFS TREE END------------\n");
\r
1269 mutex_unlock(&rk_dvfs_mutex);
\r
1272 /*******************************AVS AREA****************************************/
\r
1274 * To use AVS function, you must call avs_init in machine_rk30_board_init(void)(board-rk30-sdk.c)
\r
1275 * And then call(vdd_log):
\r
1276 * regulator_set_voltage(dcdc, 1100000, 1100000);
\r
1277 * avs_init_val_get(1,1100000,"wm8326 init");
\r
1279 * avs_set_scal_val(AVS_BASE);
\r
1280 * in wm831x_post_init(board-rk30-sdk-wm8326.c)
\r
1281 * AVS_BASE can use 172
\r
1284 static struct avs_ctr_st *avs_ctr_data = NULL;
\r
1285 #define init_avs_times 10
\r
1286 #define init_avs_st_num 5
\r
1288 struct init_avs_st {
\r
1290 u8 paramet[init_avs_times];
\r
1295 static struct init_avs_st init_avs_paramet[init_avs_st_num];
\r
1297 void avs_board_init(struct avs_ctr_st *data)
\r
1300 avs_ctr_data = data;
\r
1302 void avs_init(void)
\r
1304 memset(&init_avs_paramet[0].is_set, 0, sizeof(init_avs_paramet));
\r
1305 if(avs_ctr_data && avs_ctr_data->avs_init)
\r
1306 avs_ctr_data->avs_init();
\r
1307 avs_init_val_get(0, 1150000, "board_init");
\r
1309 static u8 rk_get_avs_val(void)
\r
1312 if(avs_ctr_data && avs_ctr_data->avs_get_val) {
\r
1313 return avs_ctr_data->avs_get_val();
\r
1318 /******************************int val get**************************************/
\r
1319 void avs_init_val_get(int index, int vol, char *s)
\r
1322 if(index >= init_avs_times)
\r
1324 init_avs_paramet[index].vol = vol;
\r
1325 init_avs_paramet[index].s = s;
\r
1326 init_avs_paramet[index].is_set++;
\r
1327 for(i = 0; i < init_avs_times; i++) {
\r
1328 init_avs_paramet[index].paramet[i] = rk_get_avs_val();
\r
1332 int avs_set_scal_val(u8 avs_base)
\r
1337 /*************************interface to get avs value and dvfs tree*************************/
\r
1338 #define USE_NORMAL_TIME
\r
1339 #ifdef USE_NORMAL_TIME
\r
1340 static struct timer_list avs_timer;
\r
1342 static struct hrtimer dvfs_hrtimer;
\r
1345 static u32 avs_dyn_start = 0;
\r
1346 static u32 avs_dyn_data_cnt;
\r
1347 static u8 *avs_dyn_data = NULL;
\r
1348 static u32 show_line_cnt = 0;
\r
1349 static u8 dly_min;
\r
1350 static u8 dly_max;
\r
1352 #define val_per_line (30)
\r
1353 #define line_pre_show (30)
\r
1354 #define avs_dyn_data_num (3*1000*1000)
\r
1356 static u32 print_avs_init(char *buf)
\r
1361 for(j = 0; j < init_avs_st_num; j++) {
\r
1362 if(init_avs_paramet[j].vol <= 0)
\r
1364 s += sprintf(s, "%s ,vol=%d,paramet following\n",
\r
1365 init_avs_paramet[j].s, init_avs_paramet[j].vol);
\r
1366 for(i = 0; i < init_avs_times; i++) {
\r
1367 s += sprintf(s, "%d ", init_avs_paramet[j].paramet[i]);
\r
1370 s += sprintf(s, "\n");
\r
1375 static ssize_t avs_init_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1378 return print_avs_init(buf);
\r
1381 static ssize_t avs_init_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1382 const char *buf, size_t n)
\r
1387 static ssize_t avs_now_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1390 return sprintf(buf, "%d\n", rk_get_avs_val());
\r
1393 static ssize_t avs_now_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1394 const char *buf, size_t n)
\r
1398 static ssize_t avs_dyn_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1404 if(avs_dyn_data == NULL)
\r
1407 if(avs_dyn_start) {
\r
1410 end_cnt = (avs_dyn_data_cnt ? (avs_dyn_data_cnt - 1) : 0);
\r
1411 if(end_cnt > (line_pre_show * val_per_line))
\r
1412 start_cnt = end_cnt - (line_pre_show * val_per_line);
\r
1416 dly_min = avs_dyn_data[start_cnt];
\r
1417 dly_max = avs_dyn_data[start_cnt];
\r
1419 //s += sprintf(s,"data start=%d\n",i);
\r
1420 for(i = start_cnt; i <= end_cnt;) {
\r
1421 s += sprintf(s, "%d", avs_dyn_data[i]);
\r
1422 dly_min = min(dly_min, avs_dyn_data[i]);
\r
1423 dly_max = max(dly_max, avs_dyn_data[i]);
\r
1425 if(!(i % val_per_line)) {
\r
1426 s += sprintf(s, "\n");
\r
1428 s += sprintf(s, " ");
\r
1431 s += sprintf(s, "\n");
\r
1433 s += sprintf(s, "new data is from=%d to %d\n", start_cnt, end_cnt);
\r
1434 //s += sprintf(s,"\n max=%d,min=%d,totolcnt=%d,line=%d\n",dly_max,dly_min,avs_dyn_data_cnt,show_line_cnt);
\r
1438 if(show_line_cnt == 0) {
\r
1439 dly_min = avs_dyn_data[0];
\r
1440 dly_max = avs_dyn_data[0];
\r
1444 for(i = show_line_cnt * (line_pre_show * val_per_line); i < avs_dyn_data_cnt;) {
\r
1445 s += sprintf(s, "%d", avs_dyn_data[i]);
\r
1446 dly_min = min(dly_min, avs_dyn_data[i]);
\r
1447 dly_max = max(dly_max, avs_dyn_data[i]);
\r
1449 if(!(i % val_per_line)) {
\r
1450 s += sprintf(s, "\n");
\r
1452 s += sprintf(s, " ");
\r
1453 if(i >= ((show_line_cnt + 1)*line_pre_show * val_per_line))
\r
1457 s += sprintf(s, "\n");
\r
1459 s += sprintf(s, "max=%d,min=%d,totolcnt=%d,line=%d\n",
\r
1460 dly_max, dly_min, avs_dyn_data_cnt, show_line_cnt);
\r
1462 if(((show_line_cnt * line_pre_show)*val_per_line) >= avs_dyn_data_cnt) {
\r
1464 show_line_cnt = 0;
\r
1466 s += sprintf(s, "data is over\n");
\r
1472 static ssize_t avs_dyn_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1473 const char *buf, size_t n)
\r
1477 if((strncmp(buf, "start", strlen("start")) == 0)) {
\r
1478 if(avs_dyn_data == NULL)
\r
1479 avs_dyn_data = kmalloc(avs_dyn_data_num, GFP_KERNEL);
\r
1480 if(avs_dyn_data == NULL)
\r
1483 pbuf = &buf[strlen("start")];
\r
1484 avs_dyn_data_cnt = 0;
\r
1485 show_line_cnt = 0;
\r
1486 if(avs_dyn_data) {
\r
1487 #ifdef USE_NORMAL_TIME
\r
1488 mod_timer(&avs_timer, jiffies + msecs_to_jiffies(5));
\r
1490 hrtimer_start(&dvfs_hrtimer, ktime_set(0, 5 * 1000 * 1000), HRTIMER_MODE_REL);
\r
1492 avs_dyn_start = 1;
\r
1494 //sscanf(pbuf, "%d %d", &number, &voltage);
\r
1495 //DVFS_DBG("---------ldo %d %d\n", number, voltage);
\r
1497 } else if((strncmp(buf, "stop", strlen("stop")) == 0)) {
\r
1498 pbuf = &buf[strlen("stop")];
\r
1499 avs_dyn_start = 0;
\r
1500 show_line_cnt = 0;
\r
1501 //sscanf(pbuf, "%d %d", &number, &voltage);
\r
1502 //DVFS_DBG("---------dcdc %d %d\n", number, voltage);
\r
1510 static ssize_t dvfs_tree_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1511 const char *buf, size_t n)
\r
1515 static ssize_t dvfs_tree_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1518 return dump_dbg_map(buf);
\r
1522 static void avs_timer_fn(unsigned long data)
\r
1525 for(i = 0; i < 1; i++) {
\r
1526 if(avs_dyn_data_cnt >= avs_dyn_data_num)
\r
1528 avs_dyn_data[avs_dyn_data_cnt] = rk_get_avs_val();
\r
1529 avs_dyn_data_cnt++;
\r
1532 mod_timer(&avs_timer, jiffies + msecs_to_jiffies(10));
\r
1535 struct hrtimer dvfs_hrtimer;
\r
1536 static enum hrtimer_restart dvfs_hrtimer_timer_func(struct hrtimer *timer)
\r
1539 for(i = 0; i < 1; i++) {
\r
1540 if(avs_dyn_data_cnt >= avs_dyn_data_num)
\r
1541 return HRTIMER_NORESTART;
\r
1542 avs_dyn_data[avs_dyn_data_cnt] = rk_get_avs_val();
\r
1543 avs_dyn_data_cnt++;
\r
1546 hrtimer_start(timer, ktime_set(0, 1 * 1000 * 1000), HRTIMER_MODE_REL);
\r
1550 /*********************************************************************************/
\r
1551 static struct kobject *dvfs_kobj;
\r
1552 struct dvfs_attribute {
\r
1553 struct attribute attr;
\r
1554 ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
\r
1556 ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
\r
1557 const char *buf, size_t n);
\r
1560 static struct dvfs_attribute dvfs_attrs[] = {
\r
1561 /* node_name permision show_func store_func */
\r
1562 #ifdef CONFIG_RK_CLOCK_PROC
\r
1563 __ATTR(dvfs_tree, S_IRUGO | S_IWUSR, dvfs_tree_show, dvfs_tree_store),
\r
1564 __ATTR(avs_init, S_IRUGO | S_IWUSR, avs_init_show, avs_init_store),
\r
1565 //__ATTR(avs_dyn, S_IRUGO | S_IWUSR, avs_dyn_show, avs_dyn_store),
\r
1566 __ATTR(avs_now, S_IRUGO | S_IWUSR, avs_now_show, avs_now_store),
\r
1570 static int __init dvfs_init(void)
\r
1573 #ifdef USE_NORMAL_TIME
\r
1574 init_timer(&avs_timer);
\r
1575 //avs_timer.expires = jiffies+msecs_to_jiffies(1);
\r
1576 avs_timer.function = avs_timer_fn;
\r
1577 //mod_timer(&avs_timer,jiffies+msecs_to_jiffies(1));
\r
1579 hrtimer_init(&dvfs_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
\r
1580 dvfs_hrtimer.function = dvfs_hrtimer_timer_func;
\r
1581 //hrtimer_start(&dvfs_hrtimer,ktime_set(0, 5*1000*1000),HRTIMER_MODE_REL);
\r
1584 dvfs_kobj = kobject_create_and_add("dvfs", NULL);
\r
1587 for (i = 0; i < ARRAY_SIZE(dvfs_attrs); i++) {
\r
1588 ret = sysfs_create_file(dvfs_kobj, &dvfs_attrs[i].attr);
\r
1590 DVFS_ERR("create index %d error\n", i);
\r
1594 dvfs_wq = create_singlethread_workqueue("rk dvfs wq");
\r
1598 subsys_initcall(dvfs_init);
\r