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
39 #define DVFS_STR_DISABLE(on) ((on)?"enable":"disable")
\r
41 #define get_volt_up_delay(new_volt, old_volt) \
\r
42 ((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 9) : 0)
\r
46 /**************************************vd regulator functions***************************************/
\r
47 static void dvfs_volt_up_delay(struct vd_node *vd,int new_volt, int old_volt)
\r
50 if(new_volt<=old_volt)
\r
52 if(vd->volt_time_flag>0)
\r
53 u_time=regulator_set_voltage_time(vd->regulator,old_volt,new_volt);
\r
56 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
97 vd->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
99 vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
102 static void dvfs_get_vd_regulator_volt_list(struct vd_node *vd)
\r
104 unsigned i,selector=dvfs_regulator_count_voltages(vd->regulator);
\r
107 if(selector>VD_VOL_LIST_CNT)
\r
108 selector=VD_VOL_LIST_CNT;
\r
110 mutex_lock(&mutex);
\r
111 for (i = 0; i<selector; i++) {
\r
112 sel_volt=dvfs_regulator_list_voltage(vd->regulator,i);
\r
115 DVFS_WARNING("%s : selector=%u,but volt <=0\n",vd->name,i);
\r
118 vd->volt_list[i]=sel_volt;
\r
119 DVFS_DBG("%s:selector=%u,volt %d\n",vd->name,i,sel_volt);
\r
121 vd->n_voltages=selector;
\r
122 mutex_unlock(&mutex);
\r
126 static int vd_regulator_round_volt_max(struct vd_node *vd, int volt)
\r
131 for (i = 0; i<vd->n_voltages; i++) {
\r
132 sel_volt=vd->volt_list[i];
\r
135 DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n",__FUNCTION__,i);
\r
144 static int vd_regulator_round_volt_min(struct vd_node *vd, int volt)
\r
149 for (i = 0; i<vd->n_voltages; i++) {
\r
150 sel_volt=vd->volt_list[i];
\r
153 DVFS_WARNING("%s:list_volt : selector=%u,but volt <=0\n",__FUNCTION__,i);
\r
159 return vd->volt_list[i-1];
\r
168 int vd_regulator_round_volt(struct vd_node *vd, int volt,int flags)
\r
170 if(!vd->n_voltages)
\r
172 if(flags==VD_LIST_RELATION_L)
\r
173 return vd_regulator_round_volt_min(vd,volt);
\r
175 return vd_regulator_round_volt_max(vd,volt);
\r
177 EXPORT_SYMBOL(vd_regulator_round_volt);
\r
180 static void dvfs_table_round_volt(struct clk_node *dvfs_clk)
\r
184 if(!dvfs_clk->dvfs_table||!dvfs_clk->vd||IS_ERR_OR_NULL(dvfs_clk->vd->regulator))
\r
186 mutex_lock(&mutex);
\r
187 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
189 test_volt=vd_regulator_round_volt(dvfs_clk->vd,dvfs_clk->dvfs_table[i].index,VD_LIST_RELATION_H);
\r
192 DVFS_WARNING("clk %s:round_volt : is %d,but list <=0\n",dvfs_clk->name,dvfs_clk->dvfs_table[i].index);
\r
195 DVFS_DBG("clk %s:round_volt %d to %d\n",dvfs_clk->name,dvfs_clk->dvfs_table[i].index,test_volt);
\r
196 dvfs_clk->dvfs_table[i].index=test_volt;
\r
198 mutex_unlock(&mutex);
\r
200 void dvfs_vd_get_regulator_volt_time_info(struct vd_node *vd)
\r
202 if(vd->volt_time_flag<=0)// check regulator support get uping vol timer
\r
204 vd->volt_time_flag=dvfs_regulator_set_voltage_time(vd->regulator,vd->cur_volt,vd->cur_volt+200*1000);
\r
205 if(vd->volt_time_flag<0)
\r
207 DVFS_DBG("%s,vd %s volt_time is no support\n",__FUNCTION__,vd->name);
\r
211 DVFS_DBG("%s,vd %s volt_time is support,up 200mv need delay %d us\n",__FUNCTION__,vd->name,vd->volt_time_flag);
\r
217 void dvfs_vd_get_regulator_mode_info(struct vd_node *vd)
\r
219 //REGULATOR_MODE_FAST
\r
220 if(vd->mode_flag<=0)// check regulator support get uping vol timer
\r
222 vd->mode_flag=dvfs_regulator_get_mode(vd->regulator);
\r
223 if(vd->mode_flag==REGULATOR_MODE_FAST||vd->mode_flag==REGULATOR_MODE_NORMAL
\r
224 ||vd->mode_flag==REGULATOR_MODE_IDLE||vd->mode_flag==REGULATOR_MODE_STANDBY)
\r
226 if(dvfs_regulator_set_mode(vd->regulator,vd->mode_flag)<0)
\r
228 vd->mode_flag=0;// check again
\r
232 if(vd->mode_flag>0)
\r
234 DVFS_DBG("%s,vd %s mode(now is %d) support\n",__FUNCTION__,vd->name,vd->mode_flag);
\r
238 DVFS_DBG("%s,vd %s mode is not support now check\n",__FUNCTION__,vd->name);
\r
244 struct regulator *dvfs_get_regulator(char *regulator_name)
\r
246 struct vd_node *vd;
\r
247 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
248 if (strcmp(regulator_name, vd->regulator_name) == 0) {
\r
249 return vd->regulator;
\r
255 /**************************************dvfs clocks functions***************************************/
\r
256 int dvfs_clk_enable_limit(struct clk *clk, unsigned int min_rate, unsigned max_rate)
\r
258 struct clk_node *dvfs_clk;
\r
260 dvfs_clk = clk->dvfs_info;
\r
262 dvfs_clk->freq_limit_en = 1;
\r
263 dvfs_clk->min_rate = min_rate;
\r
264 dvfs_clk->max_rate = max_rate;
\r
266 rate = clk_get_rate(clk);
\r
267 if (rate < min_rate)
\r
268 dvfs_clk_set_rate(clk, min_rate);
\r
269 else if (rate > max_rate)
\r
270 dvfs_clk_set_rate(clk, max_rate);
\r
274 int dvfs_clk_disable_limit(struct clk *clk)
\r
276 struct clk_node *dvfs_clk;
\r
277 dvfs_clk = clk->dvfs_info;
\r
279 dvfs_clk->freq_limit_en = 0;
\r
284 int dvfs_vd_clk_set_rate(struct clk *clk, unsigned long rate)
\r
287 struct clk_node *dvfs_info=clk_get_dvfs_info(clk);
\r
289 DVFS_DBG("%s(%s(%lu))\n", __func__, dvfs_info->name, rate);
\r
291 #if 0 // judge by reference func in rk
\r
292 if (dvfs_support_clk_set_rate(dvfs_info)==false) {
\r
293 DVFS_ERR("dvfs func:%s is not support!\n", __func__);
\r
298 if(dvfs_info->vd&&dvfs_info->vd->vd_dvfs_target){
\r
299 // mutex_lock(&vd->dvfs_mutex);
\r
300 mutex_lock(&rk_dvfs_mutex);
\r
301 ret = dvfs_info->vd->vd_dvfs_target(clk, rate);
\r
302 mutex_unlock(&rk_dvfs_mutex);
\r
303 // mutex_unlock(&vd->dvfs_mutex);
\r
307 DVFS_WARNING("%s(%s),vd is no target callback\n", __func__, clk->name);
\r
310 DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);
\r
313 EXPORT_SYMBOL(dvfs_vd_clk_set_rate);
\r
315 int dvfs_vd_clk_disable(struct clk *clk, int on)
\r
318 struct clk_node *dvfs_info=clk_get_dvfs_info(clk);
\r
319 DVFS_DBG("%s(%s(%s,%lu))\n", __func__, dvfs_info->name, DVFS_STR_DISABLE(on),clk_get_rate(clk));
\r
322 #if 0 // judge by reference func in rk
\r
323 if (dvfs_support_clk_disable(dvfs_info)==false) {
\r
324 DVFS_ERR("dvfs func:%s is not support!\n", __func__);
\r
329 if(dvfs_info->vd&&dvfs_info->vd->vd_clk_disable_target){
\r
330 // mutex_lock(&vd->dvfs_mutex);
\r
331 mutex_lock(&rk_dvfs_mutex);
\r
332 ret = dvfs_info->vd->vd_clk_disable_target(clk, on);
\r
333 mutex_unlock(&rk_dvfs_mutex);
\r
334 // mutex_unlock(&vd->dvfs_mutex);
\r
338 DVFS_WARNING("%s(%s),vd is no target callback\n", __func__, clk->name);
\r
341 DVFS_DBG("%s(%s(%lu)),is end\n", __func__, dvfs_info->name, DVFS_STR_ON(on));
\r
346 EXPORT_SYMBOL(dvfs_vd_clk_disable);
\r
348 static void dvfs_table_round_clk_rate(struct clk_node *dvfs_clk)
\r
355 if(!dvfs_clk->dvfs_table||dvfs_clk->clk==NULL||is_suport_round_rate(dvfs_clk->clk)<0)
\r
358 mutex_lock(&mutex);
\r
359 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
360 //ddr rate = real rate+flags
\r
361 flags=dvfs_clk->dvfs_table[i].frequency%1000;
\r
362 rate=(dvfs_clk->dvfs_table[i].frequency/1000)*1000;
\r
363 temp_rate=clk_round_rate(dvfs_clk->clk,rate*1000);
\r
366 DVFS_WARNING("clk %s:round_clk_rate : is %d,but round <=0",dvfs_clk->name,dvfs_clk->dvfs_table[i].frequency);
\r
369 temp_rate=(temp_rate/1000)+flags;
\r
371 DVFS_DBG("clk %s round_clk_rate %d to %d\n",
\r
372 dvfs_clk->name,dvfs_clk->dvfs_table[i].frequency,(int)(temp_rate));
\r
374 dvfs_clk->dvfs_table[i].frequency=temp_rate;
\r
376 mutex_unlock(&mutex);
\r
379 /***************************************************************************************************/
\r
380 static int dvfs_clk_get_ref_volt_depend(struct depend_list *depend, int rate_khz,
\r
381 struct cpufreq_frequency_table *clk_fv)
\r
384 if (rate_khz == 0 || !depend || !depend->dep_table) {
\r
387 clk_fv->frequency = rate_khz;
\r
390 for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
391 if (depend->dep_table[i].frequency >= rate_khz) {
\r
392 clk_fv->frequency = depend->dep_table[i].frequency;
\r
393 clk_fv->index = depend->dep_table[i].index;
\r
397 clk_fv->frequency = 0;
\r
401 int dvfs_clk_get_ref_volt(struct clk_node *dvfs_clk, int rate_khz,
\r
402 struct cpufreq_frequency_table *clk_fv)
\r
405 if (rate_khz == 0 || !dvfs_clk || !dvfs_clk->dvfs_table) {
\r
406 /* since no need */
\r
409 clk_fv->frequency = rate_khz;
\r
412 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
413 if (dvfs_clk->dvfs_table[i].frequency >= rate_khz) {
\r
414 clk_fv->frequency = dvfs_clk->dvfs_table[i].frequency;
\r
415 clk_fv->index = dvfs_clk->dvfs_table[i].index;
\r
416 // DVFS_DBG("%s,%s rate=%ukhz(vol=%d)\n",__func__,dvfs_clk->name,
\r
417 // clk_fv->frequency, clk_fv->index);
\r
421 clk_fv->frequency = 0;
\r
423 // DVFS_DBG("%s get corresponding voltage error! out of bound\n", dvfs_clk->name);
\r
427 static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct clk_node *dvfs_clk)
\r
429 struct clk_list *child;
\r
432 if (!pd || !dvfs_clk)
\r
435 if (dvfs_clk->set_volt >= pd->cur_volt) {
\r
436 return dvfs_clk->set_volt;
\r
439 list_for_each_entry(child, &pd->clk_list, node) {
\r
440 // DVFS_DBG("%s ,pd(%s),dvfs(%s),volt(%u)\n",__func__,pd->name,
\r
441 // dvfs_clk->name,dvfs_clk->set_volt);
\r
442 volt_max = max(volt_max, child->dvfs_clk->set_volt);
\r
447 void dvfs_update_clk_pds_volt(struct clk_node *dvfs_clk)
\r
449 struct pd_node *pd;
\r
453 for (i = 0; (dvfs_clk->pds[i].pd != NULL); i++) {
\r
454 pd = dvfs_clk->pds[i].pd;
\r
455 // DVFS_DBG("%s dvfs(%s),pd(%s)\n",__func__,dvfs_clk->name,pd->name);
\r
456 pd->cur_volt = dvfs_pd_get_newvolt_byclk(pd, dvfs_clk);
\r
460 int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)
\r
462 struct pd_node *pd;
\r
463 struct depend_list *depend;
\r
464 int volt_max_vd = 0;
\r
465 list_for_each_entry(pd, &vd->pd_list, node) {
\r
466 // DVFS_DBG("%s pd(%s,%u)\n",__func__,pd->name,pd->cur_volt);
\r
467 volt_max_vd = max(volt_max_vd, pd->cur_volt);
\r
470 /* some clks depend on this voltage domain */
\r
471 if (!list_empty(&vd->req_volt_list)) {
\r
472 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
\r
473 volt_max_vd = max(volt_max_vd, depend->req_volt);
\r
476 return volt_max_vd;
\r
479 int dvfs_vd_get_newvolt_byclk(struct clk_node *dvfs_clk)
\r
483 dvfs_update_clk_pds_volt(dvfs_clk);
\r
484 return dvfs_vd_get_newvolt_bypd(dvfs_clk->vd);
\r
487 void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target)
\r
489 struct clk_node *dvfs_clk = clk_get_dvfs_info(clk);
\r
490 if (IS_ERR_OR_NULL(dvfs_clk)) {
\r
491 DVFS_ERR("%s %s get dvfs_clk err\n", __func__, clk->name);
\r
494 dvfs_clk->clk_dvfs_target = clk_dvfs_target;
\r
497 /************************************************ freq volt table************************************/
\r
498 struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk)
\r
500 struct clk_node *info = clk_get_dvfs_info(clk);
\r
501 struct cpufreq_frequency_table *table;
\r
502 if (!info || !info->dvfs_table) {
\r
505 mutex_lock(&mutex);
\r
506 table = info->dvfs_table;
\r
507 mutex_unlock(&mutex);
\r
510 EXPORT_SYMBOL(dvfs_get_freq_volt_table);
\r
512 int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table)
\r
514 struct clk_node *info = clk_get_dvfs_info(clk);
\r
526 mutex_lock(&mutex);
\r
527 info->dvfs_table = table;
\r
528 if(table[0].frequency!= CPUFREQ_TABLE_END)
\r
531 info->min_rate=(table[0].frequency/1000)*1000*1000;//to hz
\r
540 for(i=0;table[i].frequency!= CPUFREQ_TABLE_END;i++)
\r
544 info->max_rate=(table[i-1].frequency/1000)*1000*1000;
\r
546 DVFS_DBG("%s,clk %s,limit max=%lu,min=%lu\n",__FUNCTION__,info->name,info->max_rate,info->min_rate);
\r
548 mutex_unlock(&mutex);
\r
549 dvfs_table_round_clk_rate(info);
\r
550 dvfs_table_round_volt(info);
\r
553 EXPORT_SYMBOL(dvfs_set_freq_volt_table);
\r
555 int dvfs_set_depend_table(struct clk *clk, char *vd_name, struct cpufreq_frequency_table *table)
\r
557 struct vd_node *vd;
\r
558 struct depend_list *depend;
\r
559 struct clk_node *info;
\r
561 info = clk_get_dvfs_info(clk);
\r
562 if (!table || !info || !vd_name) {
\r
563 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! table or info or name empty\n", __func__);
\r
567 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
568 if (0 == strcmp(vd->name, vd_name)) {
\r
569 DVFS_DBG("FOUND A MATCH\n");
\r
570 mutex_lock(&mutex);
\r
571 list_for_each_entry(depend, &info->depend_list, node2clk) {
\r
572 if (vd == depend->dep_vd && info == depend->dvfs_clk) {
\r
573 depend->dep_table = table;
\r
577 mutex_unlock(&mutex);
\r
581 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! can not find vd:%s\n", __func__, vd_name);
\r
586 int dvfs_set_arm_logic_volt(struct dvfs_arm_table *dvfs_cpu_logic_table,
\r
587 struct cpufreq_frequency_table *cpu_dvfs_table,
\r
588 struct cpufreq_frequency_table *dep_cpu2core_table)
\r
591 for (i = 0; dvfs_cpu_logic_table[i].frequency != CPUFREQ_TABLE_END; i++) {
\r
592 cpu_dvfs_table[i].frequency = dvfs_cpu_logic_table[i].frequency;
\r
593 cpu_dvfs_table[i].index = dvfs_cpu_logic_table[i].cpu_volt;
\r
595 dep_cpu2core_table[i].frequency = dvfs_cpu_logic_table[i].frequency;
\r
596 dep_cpu2core_table[i].index = dvfs_cpu_logic_table[i].logic_volt;
\r
599 cpu_dvfs_table[i].frequency = CPUFREQ_TABLE_END;
\r
600 dep_cpu2core_table[i].frequency = CPUFREQ_TABLE_END;
\r
602 dvfs_set_freq_volt_table(clk_get(NULL, "cpu"), cpu_dvfs_table);
\r
603 dvfs_set_depend_table(clk_get(NULL, "cpu"), "vd_core", dep_cpu2core_table);
\r
608 int clk_enable_dvfs(struct clk *clk)
\r
610 struct clk_node *dvfs_clk;
\r
611 struct cpufreq_frequency_table clk_fv;
\r
613 DVFS_ERR("clk enable dvfs error\n");
\r
616 dvfs_clk = clk_get_dvfs_info(clk);
\r
617 if (!dvfs_clk || !dvfs_clk->vd) {
\r
618 DVFS_ERR("%s clk(%s) not support dvfs!\n", __func__, clk->name);
\r
621 if (dvfs_clk->enable_dvfs == 0) {
\r
623 if (IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {
\r
624 //regulator = NULL;
\r
625 if (dvfs_clk->vd->regulator_name)
\r
626 dvfs_clk->vd->regulator = dvfs_regulator_get(NULL, dvfs_clk->vd->regulator_name);
\r
627 if (!IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {
\r
628 // DVFS_DBG("dvfs_regulator_get(%s)\n",dvfs_clk->vd->regulator_name);
\r
629 clk_enable_dvfs_regulator_check(dvfs_clk->vd);
\r
630 dvfs_get_vd_regulator_volt_list(dvfs_clk->vd);
\r
631 dvfs_vd_get_regulator_volt_time_info(dvfs_clk->vd);
\r
632 //dvfs_vd_get_regulator_mode_info(dvfs_clk->vd);
\r
634 //dvfs_clk->vd->regulator = NULL;
\r
635 dvfs_clk->enable_dvfs = 0;
\r
636 DVFS_ERR("%s can't get regulator in %s\n", dvfs_clk->name, __func__);
\r
640 clk_enable_dvfs_regulator_check(dvfs_clk->vd);
\r
641 // DVFS_DBG("%s(%s) vd volt=%u\n",__func__,dvfs_clk->name,dvfs_clk->vd->cur_volt);
\r
644 dvfs_table_round_clk_rate(dvfs_clk);
\r
645 dvfs_table_round_volt(dvfs_clk);
\r
646 dvfs_clk->set_freq = dvfs_clk_get_rate_kz(clk);
\r
647 // DVFS_DBG("%s ,%s get freq%u!\n",__func__,dvfs_clk->name,dvfs_clk->set_freq);
\r
649 if (dvfs_clk_get_ref_volt(dvfs_clk, dvfs_clk->set_freq, &clk_fv)) {
\r
650 if (dvfs_clk->dvfs_table[0].frequency == CPUFREQ_TABLE_END) {
\r
651 DVFS_ERR("%s table empty\n", __func__);
\r
652 dvfs_clk->enable_dvfs = 0;
\r
655 DVFS_WARNING("%s table all value are smaller than default, use default, just enable dvfs\n", __func__);
\r
656 dvfs_clk->enable_dvfs++;
\r
661 dvfs_clk->set_volt = clk_fv.index;
\r
662 dvfs_vd_get_newvolt_byclk(dvfs_clk);
\r
663 // DVFS_DBG("%s,%s,freq%u(ref vol %u)\n",__func__,dvfs_clk->name,
\r
664 // dvfs_clk->set_freq,dvfs_clk->set_volt);
\r
666 if (dvfs_clk->dvfs_nb) {
\r
667 // must unregister when clk disable
\r
668 clk_notifier_register(clk, dvfs_clk->dvfs_nb);
\r
673 if(dvfs_clk->vd->cur_volt < dvfs_clk->set_volt) {
\r
675 mutex_lock(&rk_dvfs_mutex);
\r
676 ret = dvfs_regulator_set_voltage_readback(dvfs_clk->vd->regulator, dvfs_clk->set_volt, dvfs_clk->set_volt);
\r
678 dvfs_clk->vd->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
679 dvfs_clk->enable_dvfs = 0;
\r
680 DVFS_ERR("dvfs enable clk %s,set volt error \n", dvfs_clk->name);
\r
681 mutex_unlock(&rk_dvfs_mutex);
\r
684 dvfs_clk->vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
685 mutex_unlock(&rk_dvfs_mutex);
\r
688 dvfs_clk->enable_dvfs++;
\r
690 DVFS_ERR("dvfs already enable clk enable = %d!\n", dvfs_clk->enable_dvfs);
\r
691 dvfs_clk->enable_dvfs++;
\r
696 int clk_disable_dvfs(struct clk *clk)
\r
698 struct clk_node *dvfs_clk;
\r
699 dvfs_clk = clk->dvfs_info;
\r
700 if (!dvfs_clk->enable_dvfs) {
\r
701 DVFS_DBG("clk is already closed!\n");
\r
704 dvfs_clk->enable_dvfs--;
\r
705 if (0 == dvfs_clk->enable_dvfs) {
\r
706 DVFS_ERR("clk closed!\n");
\r
708 clk_notifier_unregister(clk, dvfs_clk->dvfs_nb);
\r
709 DVFS_DBG("clk unregister nb!\n");
\r
715 struct clk_node *dvfs_get_dvfs_clk_byname(char *name)
\r
717 struct vd_node *vd;
\r
718 struct pd_node *pd;
\r
719 struct clk_list *child;
\r
720 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
721 list_for_each_entry(pd, &vd->pd_list, node) {
\r
722 list_for_each_entry(child, &pd->clk_list, node) {
\r
723 if (0 == strcmp(child->dvfs_clk->name, name)) {
\r
724 return child->dvfs_clk;
\r
731 int rk_regist_vd(struct vd_node *vd)
\r
735 mutex_lock(&mutex);
\r
736 //mutex_init(&vd->dvfs_mutex);
\r
737 list_add(&vd->node, &rk_dvfs_tree);
\r
738 INIT_LIST_HEAD(&vd->pd_list);
\r
739 INIT_LIST_HEAD(&vd->req_volt_list);
\r
741 vd->volt_time_flag=0;
\r
743 mutex_unlock(&mutex);
\r
747 int rk_regist_pd(struct pd_node_lookup *pd_lookup)
\r
749 struct vd_node *vd;
\r
750 struct pd_node *pd;
\r
752 mutex_lock(&mutex);
\r
753 pd = pd_lookup->pd;
\r
755 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
756 if (vd == pd->vd) {
\r
757 list_add(&pd->node, &vd->pd_list);
\r
758 INIT_LIST_HEAD(&pd->clk_list);
\r
762 mutex_unlock(&mutex);
\r
766 int rk_regist_clk(struct clk_node *dvfs_clk)
\r
768 struct pd_node *pd;
\r
769 struct clk_list *child;
\r
776 if (!dvfs_clk->pds)
\r
778 mutex_lock(&mutex);
\r
779 dvfs_clk->enable_dvfs = 0;
\r
780 dvfs_clk->vd = dvfs_clk->pds[0].pd->vd;
\r
781 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {
\r
782 child = &(dvfs_clk->pds[i].clk_list);
\r
783 child->dvfs_clk = dvfs_clk;
\r
784 pd = dvfs_clk->pds[i].pd;
\r
785 list_add(&child->node, &pd->clk_list);
\r
787 clk = dvfs_clk_get(NULL, dvfs_clk->name);
\r
788 dvfs_clk->clk = clk;
\r
789 clk_register_dvfs(dvfs_clk, clk);
\r
790 INIT_LIST_HEAD(&dvfs_clk->depend_list);
\r
791 mutex_unlock(&mutex);
\r
795 int rk_regist_depends(struct depend_lookup *dep_node)
\r
797 struct depend_list *depend_list;
\r
798 struct clk_node *dvfs_clk;
\r
801 DVFS_ERR("%s : DVFS BAD depend node!\n", __func__);
\r
805 if (!dep_node->clk_name || !dep_node->dep_vd) {
\r
806 DVFS_ERR("%s : DVFS BAD depend members!\n", __func__);
\r
810 depend_list = &dep_node->dep_list;
\r
811 dvfs_clk = dvfs_get_dvfs_clk_byname(dep_node->clk_name);
\r
813 mutex_lock(&mutex);
\r
815 depend_list->dvfs_clk = dvfs_clk;
\r
816 depend_list->dep_vd = dep_node->dep_vd;
\r
817 depend_list->dep_table = dep_node->dep_table;
\r
819 list_add(&depend_list->node2clk, &dvfs_clk->depend_list);
\r
820 list_add(&depend_list->node2vd, &depend_list->dep_vd->req_volt_list);
\r
822 mutex_unlock(&mutex);
\r
826 int correct_volt(int *volt_clk, int *volt_dep, int clk_biger_than_dep, int dep_biger_than_clk)
\r
828 int up_boundary = 0, low_boundary = 0;
\r
830 up_boundary = *volt_clk + dep_biger_than_clk;
\r
831 low_boundary = *volt_clk - clk_biger_than_dep;
\r
833 if (*volt_dep < low_boundary || *volt_dep > up_boundary) {
\r
835 if (*volt_dep < low_boundary) {
\r
836 *volt_dep = low_boundary;
\r
838 } else if (*volt_dep > up_boundary) {
\r
839 *volt_clk = *volt_dep - dep_biger_than_clk;
\r
846 int dvfs_scale_volt(struct vd_node *vd_clk, struct vd_node *vd_dep,
\r
847 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
849 struct regulator *regulator, *regulator_dep;
\r
850 int volt = 0, volt_dep = 0, step = 0, step_dep = 0;
\r
851 int volt_pre = 0, volt_dep_pre = 0;
\r
854 DVFS_DBG("ENTER %s, volt=%d(old=%d), volt_dep=%d(dep_old=%d)\n", __func__, volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
855 regulator = vd_clk->regulator;
\r
856 regulator_dep = vd_dep->regulator;
\r
858 if (IS_ERR_OR_NULL(regulator) || IS_ERR(regulator_dep)) {
\r
859 DVFS_ERR("%s dvfs_clk->vd->regulator or depend->dep_vd->regulator == NULL\n", __func__);
\r
864 volt_dep = volt_dep_old;
\r
866 step = volt_new - volt_old > 0 ? 1 : (-1);
\r
867 step_dep = volt_dep_new - volt_dep_old > 0 ? 1 : (-1);
\r
869 DVFS_DBG("step=%d step_dep=%d %d\n", step, step_dep, step * step_dep);
\r
871 DVFS_DBG("Volt_new=%d(old=%d), volt_dep_new=%d(dep_old=%d)\n",
\r
872 volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
875 volt_dep_pre = volt_dep;
\r
876 if (step * step_dep < 0) {
\r
877 // target is between volt_old and volt_dep_old, just
\r
879 DVFS_DBG("step * step_dep < 0\n");
\r
881 volt_dep = volt_dep_new;
\r
883 } else if (step > 0) {
\r
885 DVFS_DBG("step > 0\n");
\r
887 if (volt > volt_dep) {
\r
888 if (volt_dep == volt_dep_new) {
\r
889 volt = volt_dep + clk_biger_than_dep;
\r
891 volt_dep = volt + dep_biger_than_clk;
\r
893 } else if (volt < volt_dep){
\r
894 if (volt == volt_new) {
\r
895 volt_dep = volt + dep_biger_than_clk;
\r
897 volt = volt_dep + clk_biger_than_dep;
\r
900 if (volt != volt_new)
\r
901 volt = volt_dep + clk_biger_than_dep;
\r
902 if (volt_dep != volt_dep_new)
\r
903 volt_dep = volt + dep_biger_than_clk;
\r
905 volt = volt > volt_new ? volt_new : volt;
\r
906 volt_dep = volt_dep > volt_dep_new ? volt_dep_new : volt_dep;
\r
908 } else if (step < 0) {
\r
910 DVFS_DBG("step < 0\n");
\r
911 if (volt > volt_dep) {
\r
912 if (volt == volt_new) {
\r
913 volt_dep = volt - clk_biger_than_dep;
\r
915 volt = volt_dep - dep_biger_than_clk;
\r
917 } else if (volt < volt_dep){
\r
918 if (volt_dep == volt_dep_new) {
\r
919 volt = volt_dep - dep_biger_than_clk;
\r
921 volt_dep = volt - clk_biger_than_dep;
\r
924 if (volt != volt_new)
\r
925 volt = volt_dep - dep_biger_than_clk;
\r
926 if (volt_dep != volt_dep_new)
\r
927 volt_dep = volt - clk_biger_than_dep;
\r
929 volt = volt < volt_new ? volt_new : volt;
\r
930 volt_dep = volt_dep < volt_dep_new ? volt_dep_new : volt_dep;
\r
933 DVFS_ERR("Oops, some bugs here:Volt_new=%d(old=%d), volt_dep_new=%d(dep_old=%d)\n",
\r
934 volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
938 if (vd_clk->cur_volt != volt) {
\r
939 DVFS_DBG("\t\t%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt);
\r
940 ret = dvfs_regulator_set_voltage_readback(regulator, volt, volt);
\r
941 //udelay(get_volt_up_delay(volt, volt_pre));
\r
942 dvfs_volt_up_delay(vd_clk,volt, volt_pre);
\r
944 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
945 __func__, vd_clk->name, ret, volt_new, volt_old);
\r
948 vd_clk->cur_volt = volt;
\r
950 if (vd_dep->cur_volt != volt_dep) {
\r
951 DVFS_DBG("\t\t%s:%d->%d\n", vd_dep->name, vd_dep->cur_volt, volt_dep);
\r
952 ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep, volt_dep);
\r
953 //udelay(get_volt_up_delay(volt_dep, volt_dep_pre));
\r
954 dvfs_volt_up_delay(vd_dep,volt_dep, volt_dep_pre);
\r
956 DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
957 __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);
\r
960 vd_dep->cur_volt = volt_dep;
\r
963 DVFS_DBG("\t\tNOW:Volt=%d, volt_dep=%d\n", volt, volt_dep);
\r
965 } while (volt != volt_new || volt_dep != volt_dep_new);
\r
967 vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
968 vd_clk->cur_volt = volt_new;
\r
972 DVFS_ERR("+++++++++++++++++FAIL AREA\n");
\r
973 vd_clk->cur_volt = volt_old;
\r
974 vd_dep->cur_volt = volt_dep_old;
\r
975 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
976 ret = dvfs_regulator_set_voltage_readback(regulator, volt_old, volt_old);
\r
978 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
979 DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",
\r
980 __func__, vd_clk->name, ret, volt_new, volt_old);
\r
983 ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_old, volt_dep_old);
\r
985 vd_dep->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
986 DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",
\r
987 __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);
\r
993 int dvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new)
\r
996 DVFS_DBG("ENTER %s, volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);
\r
997 if (IS_ERR_OR_NULL(vd_clk)) {
\r
998 DVFS_ERR("%s vd_node error\n", __func__);
\r
1002 DVFS_DBG("ENTER %s, volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);
\r
1003 if (!IS_ERR_OR_NULL(vd_clk->regulator)) {
\r
1004 ret = dvfs_regulator_set_voltage_readback(vd_clk->regulator, volt_new, volt_new);
\r
1005 //udelay(get_volt_up_delay(volt_new, vd_clk->cur_volt));
\r
1006 dvfs_volt_up_delay(vd_clk,volt_new, vd_clk->cur_volt);
\r
1008 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
1009 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1010 __func__, vd_clk->name, ret, volt_new, vd_clk->cur_volt);
\r
1015 DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);
\r
1019 vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
1020 vd_clk->cur_volt = volt_new;
\r
1026 int dvfs_scale_volt_bystep(struct vd_node *vd_clk, struct vd_node *vd_dep, int volt_new, int volt_dep_new,
\r
1027 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
1030 struct regulator *regulator, *regulator_dep;
\r
1031 int volt_new_corrected = 0, volt_dep_new_corrected = 0;
\r
1032 int volt_old = 0, volt_dep_old = 0;
\r
1035 volt_old = vd_clk->cur_volt;
\r
1036 volt_dep_old = vd_dep->cur_volt;
\r
1038 DVFS_DBG("ENTER %s, volt=%d(old=%d) vd_dep=%d(dep_old=%d)\n", __func__,
\r
1039 volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
1040 DVFS_DBG("ENTER %s, VOLT_DIFF: clk_cur=%d(clk_new=%d) dep_cur=%d(dep_new=%d)\n", __func__,
\r
1041 cur_clk_biger_than_dep, new_clk_biger_than_dep,
\r
1042 cur_dep_biger_than_clk, new_dep_biger_than_clk);
\r
1044 volt_new_corrected = volt_new;
\r
1045 volt_dep_new_corrected = volt_dep_new;
\r
1046 correct_volt(&volt_new_corrected, &volt_dep_new_corrected, cur_clk_biger_than_dep, cur_dep_biger_than_clk);
\r
1047 ret = dvfs_scale_volt(vd_clk, vd_dep, volt_old, volt_new_corrected, volt_dep_old, volt_dep_new_corrected,
\r
1048 cur_clk_biger_than_dep, cur_dep_biger_than_clk);
\r
1050 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
1051 DVFS_ERR("set volt error\n");
\r
1055 if (cur_clk_biger_than_dep != new_clk_biger_than_dep || cur_dep_biger_than_clk != new_dep_biger_than_clk) {
\r
1056 regulator = vd_clk->regulator;
\r
1057 regulator_dep = vd_dep->regulator;
\r
1059 volt_new_corrected = volt_new;
\r
1060 volt_dep_new_corrected = volt_dep_new;
\r
1061 correct_volt(&volt_new_corrected, &volt_dep_new_corrected, new_clk_biger_than_dep, new_dep_biger_than_clk);
\r
1063 if (vd_clk->cur_volt != volt_new_corrected) {
\r
1064 DVFS_DBG("%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt_new_corrected);
\r
1065 ret = dvfs_regulator_set_voltage_readback(regulator, volt_new_corrected, volt_new_corrected);
\r
1066 //udelay(get_volt_up_delay(volt_new_corrected, vd_clk->cur_volt));
\r
1067 dvfs_volt_up_delay(vd_clk,volt_new_corrected, vd_clk->cur_volt);
\r
1069 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1070 __func__, vd_clk->name, ret, volt_new_corrected, vd_clk->cur_volt);
\r
1073 vd_clk->cur_volt = volt_new_corrected;
\r
1075 if (vd_dep->cur_volt != volt_dep_new_corrected) {
\r
1076 DVFS_DBG("%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt_dep_new_corrected);
\r
1077 ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_new_corrected, volt_dep_new_corrected);
\r
1078 //udelay(get_volt_up_delay(volt_dep_new_corrected, vd_dep->cur_volt));
\r
1079 dvfs_volt_up_delay(vd_dep,volt_dep_new_corrected, vd_dep->cur_volt);
\r
1081 DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1082 __func__, vd_dep->name, ret, volt_dep_new_corrected, vd_dep->cur_volt);
\r
1085 vd_dep->cur_volt = volt_dep_new_corrected;
\r
1092 int dvfs_reset_volt(struct vd_node *dvfs_vd)
\r
1094 int flag_set_volt_correct = 0;
\r
1095 if (!IS_ERR_OR_NULL(dvfs_vd->regulator))
\r
1096 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_vd->regulator);
\r
1098 DVFS_ERR("dvfs regulator is ERROR\n");
\r
1101 if (flag_set_volt_correct <= 0) {
\r
1102 DVFS_ERR("%s (vd:%s), try to reload volt ,by it is error again(%d)!!! stop scaling\n",
\r
1103 __func__, dvfs_vd->name, flag_set_volt_correct);
\r
1106 dvfs_vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
1107 DVFS_WARNING("%s (vd:%s), try to reload volt = %d\n",
\r
1108 __func__, dvfs_vd->name, flag_set_volt_correct);
\r
1110 /* Reset vd's voltage */
\r
1111 dvfs_vd->cur_volt = flag_set_volt_correct;
\r
1113 return dvfs_vd->cur_volt;
\r
1116 int dvfs_get_depend_volt(struct clk_node *dvfs_clk, struct vd_node *dvfs_vd_dep, int rate_new)
\r
1118 struct depend_list *depend;
\r
1119 struct cpufreq_frequency_table clk_fv_dep;
\r
1122 DVFS_DBG("ENTER %s, rate_new=%d\n", __func__, rate_new);
\r
1123 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {
\r
1124 DVFS_DBG("--round depend clk:%s(depend:%s)\n", depend->dvfs_clk->name, depend->dep_vd->name);
\r
1125 // this place just consider ONE depend voltage domain,
\r
1126 // multi-depends must have some differece
\r
1127 clk_fv_dep.index = 0;
\r
1128 if (depend->dep_vd == dvfs_vd_dep) {
\r
1129 ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv_dep);
\r
1131 DVFS_ERR("%s get dvfs_ref_volt_depend error\n", __func__);
\r
1134 depend->req_volt = clk_fv_dep.index;
\r
1135 return depend->req_volt;
\r
1139 DVFS_ERR("%s can not find vd node %s\n", __func__, dvfs_vd_dep->name);
\r
1144 * dump_dbg_map() : Draw all informations of dvfs while debug
\r
1146 static int dump_dbg_map(char *buf)
\r
1149 struct vd_node *vd;
\r
1150 struct pd_node *pd, *clkparent;
\r
1151 struct clk_list *child;
\r
1152 struct clk_node *dvfs_clk;
\r
1153 struct depend_list *depend;
\r
1155 mutex_lock(&rk_dvfs_mutex);
\r
1157 printk( "-------------DVFS TREE-----------\n\n\n");
\r
1158 printk( "DVFS TREE:\n");
\r
1159 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
1160 printk( "|\n|- voltage domain:%s\n", vd->name);
\r
1161 printk( "|- current voltage:%d\n", vd->cur_volt);
\r
1162 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
\r
1163 printk( "|- request voltage:%d, clk:%s\n", depend->req_volt, depend->dvfs_clk->name);
\r
1166 list_for_each_entry(pd, &vd->pd_list, node) {
\r
1167 printk( "| |\n| |- power domain:%s, status = %s, current volt = %d\n",
\r
1168 pd->name, (pd->pd_status == PD_ON) ? "ON" : "OFF", pd->cur_volt);
\r
1170 list_for_each_entry(child, &pd->clk_list, node) {
\r
1171 dvfs_clk = child->dvfs_clk;
\r
1172 printk( "| | |\n| | |- clock: %s current: rate %d, volt = %d, enable_dvfs = %s\n",
\r
1173 dvfs_clk->name, dvfs_clk->set_freq, dvfs_clk->set_volt,
\r
1174 dvfs_clk->enable_dvfs == 0 ? "DISABLE" : "ENABLE");
\r
1175 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {
\r
1176 clkparent = dvfs_clk->pds[i].pd;
\r
1177 printk( "| | | |- clock parents: %s, vd_parent = %s\n",
\r
1178 clkparent->name, clkparent->vd->name);
\r
1181 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
1182 printk( "| | | |- freq = %d, volt = %d\n",
\r
1183 dvfs_clk->dvfs_table[i].frequency,
\r
1184 dvfs_clk->dvfs_table[i].index);
\r
1188 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {
\r
1189 printk( "| | | | |- DEPEND VD: %s\n", depend->dep_vd->name);
\r
1190 for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
1191 printk( "| | | | |- freq = %d, req_volt = %d\n",
\r
1192 depend->dep_table[i].frequency,
\r
1194 depend->dep_table[i].index);
\r
1200 printk( "-------------DVFS TREE END------------\n");
\r
1202 mutex_unlock(&rk_dvfs_mutex);
\r
1205 /*******************************AVS AREA****************************************/
\r
1207 * To use AVS function, you must call avs_init in machine_rk30_board_init(void)(board-rk30-sdk.c)
\r
1208 * And then call(vdd_log):
\r
1209 * regulator_set_voltage(dcdc, 1100000, 1100000);
\r
1210 * avs_init_val_get(1,1100000,"wm8326 init");
\r
1212 * avs_set_scal_val(AVS_BASE);
\r
1213 * in wm831x_post_init(board-rk30-sdk-wm8326.c)
\r
1214 * AVS_BASE can use 172
\r
1217 static struct avs_ctr_st *avs_ctr_data=NULL;
\r
1218 #define init_avs_times 10
\r
1219 #define init_avs_st_num 5
\r
1221 struct init_avs_st {
\r
1223 u8 paramet[init_avs_times];
\r
1228 static struct init_avs_st init_avs_paramet[init_avs_st_num];
\r
1230 void avs_board_init(struct avs_ctr_st *data)
\r
1233 avs_ctr_data=data;
\r
1235 void avs_init(void)
\r
1237 memset(&init_avs_paramet[0].is_set, 0, sizeof(init_avs_paramet));
\r
1238 if(avs_ctr_data&&avs_ctr_data->avs_init)
\r
1239 avs_ctr_data->avs_init();
\r
1240 avs_init_val_get(0,1150000,"board_init");
\r
1242 static u8 rk_get_avs_val(void)
\r
1245 if(avs_ctr_data&&avs_ctr_data->avs_get_val)
\r
1247 return avs_ctr_data->avs_get_val();
\r
1252 /******************************int val get**************************************/
\r
1253 void avs_init_val_get(int index, int vol, char *s)
\r
1256 if(index >= init_avs_times)
\r
1258 init_avs_paramet[index].vol = vol;
\r
1259 init_avs_paramet[index].s = s;
\r
1260 init_avs_paramet[index].is_set++;
\r
1261 for(i = 0; i < init_avs_times; i++) {
\r
1262 init_avs_paramet[index].paramet[i] = rk_get_avs_val();
\r
1266 int avs_set_scal_val(u8 avs_base)
\r
1271 /*************************interface to get avs value and dvfs tree*************************/
\r
1272 #define USE_NORMAL_TIME
\r
1273 #ifdef USE_NORMAL_TIME
\r
1274 static struct timer_list avs_timer;
\r
1276 static struct hrtimer dvfs_hrtimer;
\r
1279 static u32 avs_dyn_start = 0;
\r
1280 static u32 avs_dyn_data_cnt;
\r
1281 static u8 *avs_dyn_data = NULL;
\r
1282 static u32 show_line_cnt = 0;
\r
1283 static u8 dly_min;
\r
1284 static u8 dly_max;
\r
1286 #define val_per_line (30)
\r
1287 #define line_pre_show (30)
\r
1288 #define avs_dyn_data_num (3*1000*1000)
\r
1290 static u32 print_avs_init(char *buf)
\r
1295 for(j = 0; j < init_avs_st_num; j++) {
\r
1296 if(init_avs_paramet[j].vol <= 0)
\r
1298 s += sprintf(s, "%s ,vol=%d,paramet following\n",
\r
1299 init_avs_paramet[j].s, init_avs_paramet[j].vol);
\r
1300 for(i = 0; i < init_avs_times; i++) {
\r
1301 s += sprintf(s, "%d ", init_avs_paramet[j].paramet[i]);
\r
1304 s += sprintf(s, "\n");
\r
1309 static ssize_t avs_init_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1312 return print_avs_init(buf);
\r
1315 static ssize_t avs_init_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1316 const char *buf, size_t n)
\r
1321 static ssize_t avs_now_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1324 return sprintf(buf, "%d\n", rk_get_avs_val());
\r
1327 static ssize_t avs_now_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1328 const char *buf, size_t n)
\r
1332 static ssize_t avs_dyn_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1338 if(avs_dyn_data == NULL)
\r
1341 if(avs_dyn_start) {
\r
1344 end_cnt = (avs_dyn_data_cnt ? (avs_dyn_data_cnt - 1) : 0);
\r
1345 if(end_cnt > (line_pre_show * val_per_line))
\r
1346 start_cnt = end_cnt - (line_pre_show * val_per_line);
\r
1350 dly_min = avs_dyn_data[start_cnt];
\r
1351 dly_max = avs_dyn_data[start_cnt];
\r
1353 //s += sprintf(s,"data start=%d\n",i);
\r
1354 for(i = start_cnt; i <= end_cnt;) {
\r
1355 s += sprintf(s, "%d", avs_dyn_data[i]);
\r
1356 dly_min = min(dly_min, avs_dyn_data[i]);
\r
1357 dly_max = max(dly_max, avs_dyn_data[i]);
\r
1359 if(!(i % val_per_line)) {
\r
1360 s += sprintf(s, "\n");
\r
1362 s += sprintf(s, " ");
\r
1365 s += sprintf(s, "\n");
\r
1367 s += sprintf(s, "new data is from=%d to %d\n", start_cnt, end_cnt);
\r
1368 //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
1372 if(show_line_cnt == 0) {
\r
1373 dly_min = avs_dyn_data[0];
\r
1374 dly_max = avs_dyn_data[0];
\r
1378 for(i = show_line_cnt * (line_pre_show * val_per_line); i < avs_dyn_data_cnt;) {
\r
1379 s += sprintf(s, "%d", avs_dyn_data[i]);
\r
1380 dly_min = min(dly_min, avs_dyn_data[i]);
\r
1381 dly_max = max(dly_max, avs_dyn_data[i]);
\r
1383 if(!(i % val_per_line)) {
\r
1384 s += sprintf(s, "\n");
\r
1386 s += sprintf(s, " ");
\r
1387 if(i >= ((show_line_cnt + 1)*line_pre_show * val_per_line))
\r
1391 s += sprintf(s, "\n");
\r
1393 s += sprintf(s, "max=%d,min=%d,totolcnt=%d,line=%d\n",
\r
1394 dly_max, dly_min, avs_dyn_data_cnt, show_line_cnt);
\r
1396 if(((show_line_cnt * line_pre_show)*val_per_line) >= avs_dyn_data_cnt) {
\r
1398 show_line_cnt = 0;
\r
1400 s += sprintf(s, "data is over\n");
\r
1406 static ssize_t avs_dyn_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1407 const char *buf, size_t n)
\r
1411 if((strncmp(buf, "start", strlen("start")) == 0)) {
\r
1412 if(avs_dyn_data == NULL)
\r
1413 avs_dyn_data = kmalloc(avs_dyn_data_num, GFP_KERNEL);
\r
1414 if(avs_dyn_data == NULL)
\r
1417 pbuf = &buf[strlen("start")];
\r
1418 avs_dyn_data_cnt = 0;
\r
1419 show_line_cnt = 0;
\r
1420 if(avs_dyn_data) {
\r
1421 #ifdef USE_NORMAL_TIME
\r
1422 mod_timer(&avs_timer, jiffies + msecs_to_jiffies(5));
\r
1424 hrtimer_start(&dvfs_hrtimer, ktime_set(0, 5 * 1000 * 1000), HRTIMER_MODE_REL);
\r
1426 avs_dyn_start = 1;
\r
1428 //sscanf(pbuf, "%d %d", &number, &voltage);
\r
1429 //DVFS_DBG("---------ldo %d %d\n", number, voltage);
\r
1431 } else if((strncmp(buf, "stop", strlen("stop")) == 0)) {
\r
1432 pbuf = &buf[strlen("stop")];
\r
1433 avs_dyn_start = 0;
\r
1434 show_line_cnt = 0;
\r
1435 //sscanf(pbuf, "%d %d", &number, &voltage);
\r
1436 //DVFS_DBG("---------dcdc %d %d\n", number, voltage);
\r
1444 static ssize_t dvfs_tree_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1445 const char *buf, size_t n)
\r
1449 static ssize_t dvfs_tree_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1452 return dump_dbg_map(buf);
\r
1456 static void avs_timer_fn(unsigned long data)
\r
1459 for(i = 0; i < 1; i++) {
\r
1460 if(avs_dyn_data_cnt >= avs_dyn_data_num)
\r
1462 avs_dyn_data[avs_dyn_data_cnt] = rk_get_avs_val();
\r
1463 avs_dyn_data_cnt++;
\r
1466 mod_timer(&avs_timer, jiffies + msecs_to_jiffies(10));
\r
1469 struct hrtimer dvfs_hrtimer;
\r
1470 static enum hrtimer_restart dvfs_hrtimer_timer_func(struct hrtimer *timer)
\r
1473 for(i = 0; i < 1; i++) {
\r
1474 if(avs_dyn_data_cnt >= avs_dyn_data_num)
\r
1475 return HRTIMER_NORESTART;
\r
1476 avs_dyn_data[avs_dyn_data_cnt] = rk_get_avs_val();
\r
1477 avs_dyn_data_cnt++;
\r
1480 hrtimer_start(timer, ktime_set(0, 1 * 1000 * 1000), HRTIMER_MODE_REL);
\r
1484 /*********************************************************************************/
\r
1485 static struct kobject *dvfs_kobj;
\r
1486 struct dvfs_attribute {
\r
1487 struct attribute attr;
\r
1488 ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
\r
1490 ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
\r
1491 const char *buf, size_t n);
\r
1494 static struct dvfs_attribute dvfs_attrs[] = {
\r
1495 /* node_name permision show_func store_func */
\r
1496 #ifdef CONFIG_RK_CLOCK_PROC
\r
1497 __ATTR(dvfs_tree, S_IRUSR | S_IRGRP | S_IWUSR, dvfs_tree_show, dvfs_tree_store),
\r
1498 __ATTR(avs_init, S_IRUSR | S_IRGRP | S_IWUSR, avs_init_show, avs_init_store),
\r
1499 // __ATTR(avs_dyn, S_IRUSR | S_IRGRP | S_IWUSR, avs_dyn_show, avs_dyn_store),
\r
1500 __ATTR(avs_now, S_IRUSR | S_IRGRP | S_IWUSR, avs_now_show, avs_now_store),
\r
1504 static int __init dvfs_init(void)
\r
1507 #ifdef USE_NORMAL_TIME
\r
1508 init_timer(&avs_timer);
\r
1509 //avs_timer.expires = jiffies+msecs_to_jiffies(1);
\r
1510 avs_timer.function = avs_timer_fn;
\r
1511 //mod_timer(&avs_timer,jiffies+msecs_to_jiffies(1));
\r
1513 hrtimer_init(&dvfs_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
\r
1514 dvfs_hrtimer.function = dvfs_hrtimer_timer_func;
\r
1515 //hrtimer_start(&dvfs_hrtimer,ktime_set(0, 5*1000*1000),HRTIMER_MODE_REL);
\r
1518 dvfs_kobj = kobject_create_and_add("dvfs", NULL);
\r
1521 for (i = 0; i < ARRAY_SIZE(dvfs_attrs); i++) {
\r
1522 ret = sysfs_create_file(dvfs_kobj, &dvfs_attrs[i].attr);
\r
1524 DVFS_ERR("create index %d error\n", i);
\r
1531 subsys_initcall(dvfs_init);
\r