1 /* arch/arm/mach-rk30/rk30_dvfs.c
\r
3 * Copyright (C) 2012 ROCKCHIP, Inc.
\r
5 * This software is licensed under the terms of the GNU General Public
\r
6 * License version 2, as published by the Free Software Foundation, and
\r
7 * may be copied, distributed, and modified under those terms.
\r
9 * This program is distributed in the hope that it will be useful,
\r
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 * GNU General Public License for more details.
\r
16 #include <linux/kernel.h>
\r
17 #include <linux/err.h>
\r
18 #include <linux/spinlock.h>
\r
19 #include <linux/list.h>
\r
20 #include <linux/slab.h>
\r
21 #include <linux/clk.h>
\r
22 #include <linux/cpufreq.h>
\r
23 #include <mach/dvfs.h>
\r
24 #include <mach/clock.h>
\r
25 #include <linux/regulator/consumer.h>
\r
26 #include <linux/delay.h>
\r
27 #include <linux/io.h>
\r
28 #include <linux/hrtimer.h>
\r
30 #define MHz (1000 * 1000)
\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
259 u32 rate = 0, ret = 0;
\r
260 dvfs_clk = clk_get_dvfs_info(clk);
\r
261 if (IS_ERR_OR_NULL(dvfs_clk)) {
\r
262 DVFS_ERR("%s: can not get dvfs clk(%s)\n", __func__, clk->name);
\r
267 if (dvfs_clk->vd && dvfs_clk->vd->vd_dvfs_target){
\r
268 mutex_lock(&rk_dvfs_mutex);
\r
270 dvfs_clk->freq_limit_en = 1;
\r
271 dvfs_clk->min_rate = min_rate;
\r
272 dvfs_clk->max_rate = max_rate;
\r
273 rate = clk_get_rate(clk);
\r
274 ret = dvfs_clk->vd->vd_dvfs_target(clk, rate);
\r
275 clk->last_set_rate = rate;
\r
277 mutex_unlock(&rk_dvfs_mutex);
\r
280 DVFS_DBG("%s: clk(%s) last_set_rate=%d; [min_rate, max_rate]=[%d, %d]\n",
\r
281 __func__, clk->name, clk->last_set_rate, dvfs_clk->min_rate, dvfs_clk->max_rate);
\r
285 int dvfs_clk_disable_limit(struct clk *clk)
\r
287 struct clk_node *dvfs_clk;
\r
289 dvfs_clk = clk_get_dvfs_info(clk);
\r
290 if (IS_ERR_OR_NULL(dvfs_clk)) {
\r
291 DVFS_ERR("%s: can not get dvfs clk(%s)\n", __func__, clk->name);
\r
296 if (dvfs_clk->vd && dvfs_clk->vd->vd_dvfs_target){
\r
297 mutex_lock(&rk_dvfs_mutex);
\r
298 /* To reset dvfs_clk->min_rate/max_rate */
\r
299 dvfs_set_freq_volt_table(clk, dvfs_clk->dvfs_table);
\r
301 dvfs_clk->freq_limit_en = 0;
\r
302 ret = dvfs_clk->vd->vd_dvfs_target(clk, clk->last_set_rate);
\r
304 mutex_unlock(&rk_dvfs_mutex);
\r
307 DVFS_DBG("%s: clk(%s) last_set_rate=%d; [min_rate, max_rate]=[%d, %d]\n",
\r
308 __func__, clk->name, clk->last_set_rate, dvfs_clk->min_rate, dvfs_clk->max_rate);
\r
312 int dvfs_vd_clk_set_rate(struct clk *clk, unsigned long rate)
\r
315 struct clk_node *dvfs_info=clk_get_dvfs_info(clk);
\r
317 DVFS_DBG("%s(%s(%lu))\n", __func__, dvfs_info->name, rate);
\r
319 #if 0 // judge by reference func in rk
\r
320 if (dvfs_support_clk_set_rate(dvfs_info)==false) {
\r
321 DVFS_ERR("dvfs func:%s is not support!\n", __func__);
\r
326 if(dvfs_info->vd&&dvfs_info->vd->vd_dvfs_target){
\r
327 // mutex_lock(&vd->dvfs_mutex);
\r
328 mutex_lock(&rk_dvfs_mutex);
\r
329 ret = dvfs_info->vd->vd_dvfs_target(clk, rate);
\r
330 mutex_unlock(&rk_dvfs_mutex);
\r
331 // mutex_unlock(&vd->dvfs_mutex);
\r
335 DVFS_WARNING("%s(%s),vd is no target callback\n", __func__, clk->name);
\r
338 DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);
\r
341 EXPORT_SYMBOL(dvfs_vd_clk_set_rate);
\r
343 int dvfs_vd_clk_disable(struct clk *clk, int on)
\r
346 struct clk_node *dvfs_info=clk_get_dvfs_info(clk);
\r
347 DVFS_DBG("%s(%s(%s,%lu))\n", __func__, dvfs_info->name, DVFS_STR_DISABLE(on),clk_get_rate(clk));
\r
350 #if 0 // judge by reference func in rk
\r
351 if (dvfs_support_clk_disable(dvfs_info)==false) {
\r
352 DVFS_ERR("dvfs func:%s is not support!\n", __func__);
\r
357 if(dvfs_info->vd&&dvfs_info->vd->vd_clk_disable_target){
\r
358 // mutex_lock(&vd->dvfs_mutex);
\r
359 mutex_lock(&rk_dvfs_mutex);
\r
360 ret = dvfs_info->vd->vd_clk_disable_target(clk, on);
\r
361 mutex_unlock(&rk_dvfs_mutex);
\r
362 // mutex_unlock(&vd->dvfs_mutex);
\r
366 DVFS_WARNING("%s(%s),vd is no target callback\n", __func__, clk->name);
\r
369 DVFS_DBG("%s(%s(%s)),is end\n", __func__, dvfs_info->name, DVFS_STR_DISABLE(on));
\r
374 EXPORT_SYMBOL(dvfs_vd_clk_disable);
\r
376 static void dvfs_table_round_clk_rate(struct clk_node *dvfs_clk)
\r
379 unsigned long temp_rate;
\r
383 if(!dvfs_clk->dvfs_table||dvfs_clk->clk==NULL||is_suport_round_rate(dvfs_clk->clk)<0)
\r
386 mutex_lock(&mutex);
\r
387 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
388 //ddr rate = real rate+flags
\r
389 flags=dvfs_clk->dvfs_table[i].frequency%1000;
\r
390 rate=(dvfs_clk->dvfs_table[i].frequency/1000)*1000;
\r
391 temp_rate=clk_round_rate(dvfs_clk->clk,rate*1000);
\r
394 DVFS_WARNING("clk %s:round_clk_rate : is %d,but round <=0",dvfs_clk->name,dvfs_clk->dvfs_table[i].frequency);
\r
398 /* Set rate unit as MHZ */
\r
399 if (temp_rate % MHz != 0)
\r
400 temp_rate = (temp_rate / MHz + 1) * MHz;
\r
402 temp_rate = (temp_rate / 1000) + flags;
\r
404 DVFS_DBG("clk %s round_clk_rate %d to %d\n",
\r
405 dvfs_clk->name,dvfs_clk->dvfs_table[i].frequency,(int)(temp_rate));
\r
407 dvfs_clk->dvfs_table[i].frequency=temp_rate;
\r
409 mutex_unlock(&mutex);
\r
412 /***************************************************************************************************/
\r
413 static int dvfs_clk_get_ref_volt_depend(struct depend_list *depend, int rate_khz,
\r
414 struct cpufreq_frequency_table *clk_fv)
\r
417 if (rate_khz == 0 || !depend || !depend->dep_table) {
\r
420 clk_fv->frequency = rate_khz;
\r
423 for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
424 if (depend->dep_table[i].frequency >= rate_khz) {
\r
425 clk_fv->frequency = depend->dep_table[i].frequency;
\r
426 clk_fv->index = depend->dep_table[i].index;
\r
430 clk_fv->frequency = 0;
\r
434 int dvfs_clk_get_ref_volt(struct clk_node *dvfs_clk, int rate_khz,
\r
435 struct cpufreq_frequency_table *clk_fv)
\r
438 if (rate_khz == 0 || !dvfs_clk || !dvfs_clk->dvfs_table) {
\r
439 /* since no need */
\r
442 clk_fv->frequency = rate_khz;
\r
445 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
446 if (dvfs_clk->dvfs_table[i].frequency >= rate_khz) {
\r
447 clk_fv->frequency = dvfs_clk->dvfs_table[i].frequency;
\r
448 clk_fv->index = dvfs_clk->dvfs_table[i].index;
\r
449 // DVFS_DBG("%s,%s rate=%ukhz(vol=%d)\n",__func__,dvfs_clk->name,
\r
450 // clk_fv->frequency, clk_fv->index);
\r
454 clk_fv->frequency = 0;
\r
456 // DVFS_DBG("%s get corresponding voltage error! out of bound\n", dvfs_clk->name);
\r
460 static int dvfs_pd_get_newvolt_byclk(struct pd_node *pd, struct clk_node *dvfs_clk)
\r
462 struct clk_list *child;
\r
465 if (!pd || !dvfs_clk)
\r
468 if (dvfs_clk->set_volt >= pd->cur_volt) {
\r
469 return dvfs_clk->set_volt;
\r
472 list_for_each_entry(child, &pd->clk_list, node) {
\r
473 // DVFS_DBG("%s ,pd(%s),dvfs(%s),volt(%u)\n",__func__,pd->name,
\r
474 // dvfs_clk->name,dvfs_clk->set_volt);
\r
475 volt_max = max(volt_max, child->dvfs_clk->set_volt);
\r
480 void dvfs_update_clk_pds_volt(struct clk_node *dvfs_clk)
\r
482 struct pd_node *pd;
\r
486 for (i = 0; (dvfs_clk->pds[i].pd != NULL); i++) {
\r
487 pd = dvfs_clk->pds[i].pd;
\r
488 // DVFS_DBG("%s dvfs(%s),pd(%s)\n",__func__,dvfs_clk->name,pd->name);
\r
489 pd->cur_volt = dvfs_pd_get_newvolt_byclk(pd, dvfs_clk);
\r
493 int dvfs_vd_get_newvolt_bypd(struct vd_node *vd)
\r
495 struct pd_node *pd;
\r
496 struct depend_list *depend;
\r
497 int volt_max_vd = 0;
\r
498 list_for_each_entry(pd, &vd->pd_list, node) {
\r
499 // DVFS_DBG("%s pd(%s,%u)\n",__func__,pd->name,pd->cur_volt);
\r
500 volt_max_vd = max(volt_max_vd, pd->cur_volt);
\r
503 /* some clks depend on this voltage domain */
\r
504 if (!list_empty(&vd->req_volt_list)) {
\r
505 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
\r
506 volt_max_vd = max(volt_max_vd, depend->req_volt);
\r
509 return volt_max_vd;
\r
512 int dvfs_vd_get_newvolt_byclk(struct clk_node *dvfs_clk)
\r
516 dvfs_update_clk_pds_volt(dvfs_clk);
\r
517 return dvfs_vd_get_newvolt_bypd(dvfs_clk->vd);
\r
520 void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target)
\r
522 struct clk_node *dvfs_clk = clk_get_dvfs_info(clk);
\r
523 if (IS_ERR_OR_NULL(dvfs_clk)) {
\r
524 DVFS_ERR("%s %s get dvfs_clk err\n", __func__, clk->name);
\r
527 dvfs_clk->clk_dvfs_target = clk_dvfs_target;
\r
530 /************************************************ freq volt table************************************/
\r
531 struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct clk *clk)
\r
533 struct clk_node *info = clk_get_dvfs_info(clk);
\r
534 struct cpufreq_frequency_table *table;
\r
535 if (!info || !info->dvfs_table) {
\r
538 mutex_lock(&mutex);
\r
539 table = info->dvfs_table;
\r
540 mutex_unlock(&mutex);
\r
543 EXPORT_SYMBOL(dvfs_get_freq_volt_table);
\r
545 int dvfs_set_freq_volt_table(struct clk *clk, struct cpufreq_frequency_table *table)
\r
547 struct clk_node *info = clk_get_dvfs_info(clk);
\r
559 mutex_lock(&mutex);
\r
560 info->dvfs_table = table;
\r
561 if(table[0].frequency!= CPUFREQ_TABLE_END)
\r
564 info->min_rate=(table[0].frequency/1000)*1000*1000;//to hz
\r
570 mutex_unlock(&mutex);
\r
574 for(i=0;table[i].frequency!= CPUFREQ_TABLE_END;i++)
\r
578 info->max_rate=(table[i-1].frequency/1000)*1000*1000;
\r
580 DVFS_DBG("%s,clk %s,limit max=%lu,min=%lu\n",__FUNCTION__,info->name,info->max_rate,info->min_rate);
\r
582 mutex_unlock(&mutex);
\r
583 dvfs_table_round_clk_rate(info);
\r
584 dvfs_table_round_volt(info);
\r
587 EXPORT_SYMBOL(dvfs_set_freq_volt_table);
\r
589 int dvfs_set_depend_table(struct clk *clk, char *vd_name, struct cpufreq_frequency_table *table)
\r
591 struct vd_node *vd;
\r
592 struct depend_list *depend;
\r
593 struct clk_node *info;
\r
595 info = clk_get_dvfs_info(clk);
\r
596 if (!table || !info || !vd_name) {
\r
597 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! table or info or name empty\n", __func__);
\r
601 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
602 if (0 == strcmp(vd->name, vd_name)) {
\r
603 DVFS_DBG("FOUND A MATCH\n");
\r
604 mutex_lock(&mutex);
\r
605 list_for_each_entry(depend, &info->depend_list, node2clk) {
\r
606 if (vd == depend->dep_vd && info == depend->dvfs_clk) {
\r
607 depend->dep_table = table;
\r
611 mutex_unlock(&mutex);
\r
615 DVFS_ERR("%s :DVFS SET DEPEND TABLE ERROR! can not find vd:%s\n", __func__, vd_name);
\r
620 int dvfs_set_arm_logic_volt(struct dvfs_arm_table *dvfs_cpu_logic_table,
\r
621 struct cpufreq_frequency_table *cpu_dvfs_table,
\r
622 struct cpufreq_frequency_table *dep_cpu2core_table)
\r
625 for (i = 0; dvfs_cpu_logic_table[i].frequency != CPUFREQ_TABLE_END; i++) {
\r
626 cpu_dvfs_table[i].frequency = dvfs_cpu_logic_table[i].frequency;
\r
627 cpu_dvfs_table[i].index = dvfs_cpu_logic_table[i].cpu_volt;
\r
629 dep_cpu2core_table[i].frequency = dvfs_cpu_logic_table[i].frequency;
\r
630 dep_cpu2core_table[i].index = dvfs_cpu_logic_table[i].logic_volt;
\r
633 cpu_dvfs_table[i].frequency = CPUFREQ_TABLE_END;
\r
634 dep_cpu2core_table[i].frequency = CPUFREQ_TABLE_END;
\r
636 dvfs_set_freq_volt_table(clk_get(NULL, "cpu"), cpu_dvfs_table);
\r
637 dvfs_set_depend_table(clk_get(NULL, "cpu"), "vd_core", dep_cpu2core_table);
\r
642 int clk_enable_dvfs(struct clk *clk)
\r
644 struct clk_node *dvfs_clk;
\r
645 struct cpufreq_frequency_table clk_fv;
\r
647 DVFS_ERR("clk enable dvfs error\n");
\r
650 dvfs_clk = clk_get_dvfs_info(clk);
\r
651 if (!dvfs_clk || !dvfs_clk->vd) {
\r
652 DVFS_ERR("%s clk(%s) not support dvfs!\n", __func__, clk->name);
\r
655 if (dvfs_clk->enable_dvfs == 0) {
\r
657 if (IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {
\r
658 //regulator = NULL;
\r
659 if (dvfs_clk->vd->regulator_name)
\r
660 dvfs_clk->vd->regulator = dvfs_regulator_get(NULL, dvfs_clk->vd->regulator_name);
\r
661 if (!IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {
\r
662 // DVFS_DBG("dvfs_regulator_get(%s)\n",dvfs_clk->vd->regulator_name);
\r
663 clk_enable_dvfs_regulator_check(dvfs_clk->vd);
\r
664 dvfs_get_vd_regulator_volt_list(dvfs_clk->vd);
\r
665 dvfs_vd_get_regulator_volt_time_info(dvfs_clk->vd);
\r
666 //dvfs_vd_get_regulator_mode_info(dvfs_clk->vd);
\r
668 //dvfs_clk->vd->regulator = NULL;
\r
669 dvfs_clk->enable_dvfs = 0;
\r
670 DVFS_ERR("%s can't get regulator in %s\n", dvfs_clk->name, __func__);
\r
674 clk_enable_dvfs_regulator_check(dvfs_clk->vd);
\r
675 // DVFS_DBG("%s(%s) vd volt=%u\n",__func__,dvfs_clk->name,dvfs_clk->vd->cur_volt);
\r
678 dvfs_table_round_clk_rate(dvfs_clk);
\r
679 dvfs_table_round_volt(dvfs_clk);
\r
680 dvfs_clk->set_freq = dvfs_clk_get_rate_kz(clk);
\r
681 // DVFS_DBG("%s ,%s get freq%u!\n",__func__,dvfs_clk->name,dvfs_clk->set_freq);
\r
683 if (dvfs_clk_get_ref_volt(dvfs_clk, dvfs_clk->set_freq, &clk_fv)) {
\r
684 if (dvfs_clk->dvfs_table[0].frequency == CPUFREQ_TABLE_END) {
\r
685 DVFS_ERR("%s table empty\n", __func__);
\r
686 dvfs_clk->enable_dvfs = 0;
\r
689 DVFS_WARNING("%s table all value are smaller than default, use default, just enable dvfs\n", __func__);
\r
690 dvfs_clk->enable_dvfs++;
\r
695 dvfs_clk->set_volt = clk_fv.index;
\r
696 dvfs_vd_get_newvolt_byclk(dvfs_clk);
\r
697 // DVFS_DBG("%s,%s,freq%u(ref vol %u)\n",__func__,dvfs_clk->name,
\r
698 // dvfs_clk->set_freq,dvfs_clk->set_volt);
\r
700 if (dvfs_clk->dvfs_nb) {
\r
701 // must unregister when clk disable
\r
702 clk_notifier_register(clk, dvfs_clk->dvfs_nb);
\r
707 if(dvfs_clk->vd->cur_volt < dvfs_clk->set_volt) {
\r
709 mutex_lock(&rk_dvfs_mutex);
\r
710 ret = dvfs_regulator_set_voltage_readback(dvfs_clk->vd->regulator, dvfs_clk->set_volt, dvfs_clk->set_volt);
\r
712 dvfs_clk->vd->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
713 dvfs_clk->enable_dvfs = 0;
\r
714 DVFS_ERR("dvfs enable clk %s,set volt error \n", dvfs_clk->name);
\r
715 mutex_unlock(&rk_dvfs_mutex);
\r
718 dvfs_clk->vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
719 mutex_unlock(&rk_dvfs_mutex);
\r
722 dvfs_clk->enable_dvfs++;
\r
724 DVFS_ERR("dvfs already enable clk enable = %d!\n", dvfs_clk->enable_dvfs);
\r
725 dvfs_clk->enable_dvfs++;
\r
730 int clk_disable_dvfs(struct clk *clk)
\r
732 struct clk_node *dvfs_clk;
\r
733 dvfs_clk = clk->dvfs_info;
\r
734 if (!dvfs_clk->enable_dvfs) {
\r
735 DVFS_DBG("clk is already closed!\n");
\r
738 dvfs_clk->enable_dvfs--;
\r
739 if (0 == dvfs_clk->enable_dvfs) {
\r
740 DVFS_ERR("clk closed!\n");
\r
742 clk_notifier_unregister(clk, dvfs_clk->dvfs_nb);
\r
743 DVFS_DBG("clk unregister nb!\n");
\r
749 struct clk_node *dvfs_get_dvfs_clk_byname(char *name)
\r
751 struct vd_node *vd;
\r
752 struct pd_node *pd;
\r
753 struct clk_list *child;
\r
754 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
755 list_for_each_entry(pd, &vd->pd_list, node) {
\r
756 list_for_each_entry(child, &pd->clk_list, node) {
\r
757 if (0 == strcmp(child->dvfs_clk->name, name)) {
\r
758 return child->dvfs_clk;
\r
765 int rk_regist_vd(struct vd_node *vd)
\r
769 mutex_lock(&mutex);
\r
770 //mutex_init(&vd->dvfs_mutex);
\r
771 list_add(&vd->node, &rk_dvfs_tree);
\r
772 INIT_LIST_HEAD(&vd->pd_list);
\r
773 INIT_LIST_HEAD(&vd->req_volt_list);
\r
775 vd->volt_time_flag=0;
\r
777 mutex_unlock(&mutex);
\r
781 int rk_regist_pd(struct pd_node_lookup *pd_lookup)
\r
783 struct vd_node *vd;
\r
784 struct pd_node *pd;
\r
786 mutex_lock(&mutex);
\r
787 pd = pd_lookup->pd;
\r
789 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
790 if (vd == pd->vd) {
\r
791 list_add(&pd->node, &vd->pd_list);
\r
792 INIT_LIST_HEAD(&pd->clk_list);
\r
796 mutex_unlock(&mutex);
\r
800 int rk_regist_clk(struct clk_node *dvfs_clk)
\r
802 struct pd_node *pd;
\r
803 struct clk_list *child;
\r
810 if (!dvfs_clk->pds)
\r
812 mutex_lock(&mutex);
\r
813 dvfs_clk->enable_dvfs = 0;
\r
814 dvfs_clk->vd = dvfs_clk->pds[0].pd->vd;
\r
815 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {
\r
816 child = &(dvfs_clk->pds[i].clk_list);
\r
817 child->dvfs_clk = dvfs_clk;
\r
818 pd = dvfs_clk->pds[i].pd;
\r
819 list_add(&child->node, &pd->clk_list);
\r
821 clk = dvfs_clk_get(NULL, dvfs_clk->name);
\r
822 dvfs_clk->clk = clk;
\r
823 clk_register_dvfs(dvfs_clk, clk);
\r
824 INIT_LIST_HEAD(&dvfs_clk->depend_list);
\r
825 mutex_unlock(&mutex);
\r
829 int rk_regist_depends(struct depend_lookup *dep_node)
\r
831 struct depend_list *depend_list;
\r
832 struct clk_node *dvfs_clk;
\r
835 DVFS_ERR("%s : DVFS BAD depend node!\n", __func__);
\r
839 if (!dep_node->clk_name || !dep_node->dep_vd) {
\r
840 DVFS_ERR("%s : DVFS BAD depend members!\n", __func__);
\r
844 depend_list = &dep_node->dep_list;
\r
845 dvfs_clk = dvfs_get_dvfs_clk_byname(dep_node->clk_name);
\r
847 mutex_lock(&mutex);
\r
849 depend_list->dvfs_clk = dvfs_clk;
\r
850 depend_list->dep_vd = dep_node->dep_vd;
\r
851 depend_list->dep_table = dep_node->dep_table;
\r
853 list_add(&depend_list->node2clk, &dvfs_clk->depend_list);
\r
854 list_add(&depend_list->node2vd, &depend_list->dep_vd->req_volt_list);
\r
856 mutex_unlock(&mutex);
\r
860 int correct_volt(int *volt_clk, int *volt_dep, int clk_biger_than_dep, int dep_biger_than_clk)
\r
862 int up_boundary = 0, low_boundary = 0;
\r
864 up_boundary = *volt_clk + dep_biger_than_clk;
\r
865 low_boundary = *volt_clk - clk_biger_than_dep;
\r
867 if (*volt_dep < low_boundary || *volt_dep > up_boundary) {
\r
869 if (*volt_dep < low_boundary) {
\r
870 *volt_dep = low_boundary;
\r
872 } else if (*volt_dep > up_boundary) {
\r
873 *volt_clk = *volt_dep - dep_biger_than_clk;
\r
880 int dvfs_scale_volt(struct vd_node *vd_clk, struct vd_node *vd_dep,
\r
881 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
883 struct regulator *regulator, *regulator_dep;
\r
884 int volt = 0, volt_dep = 0, step = 0, step_dep = 0;
\r
885 int volt_tmp = 0, volt_dep_tmp = 0;
\r
886 int volt_pre = 0, volt_dep_pre = 0;
\r
889 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
890 regulator = vd_clk->regulator;
\r
891 regulator_dep = vd_dep->regulator;
\r
893 if (IS_ERR_OR_NULL(regulator) || IS_ERR(regulator_dep)) {
\r
894 DVFS_ERR("%s dvfs_clk->vd->regulator or depend->dep_vd->regulator == NULL\n", __func__);
\r
899 volt_dep = volt_dep_old;
\r
901 step = volt_new - volt_old > 0 ? 1 : (-1);
\r
902 step_dep = volt_dep_new - volt_dep_old > 0 ? 1 : (-1);
\r
904 DVFS_DBG("step=%d step_dep=%d %d\n", step, step_dep, step * step_dep);
\r
906 DVFS_DBG("Volt_new=%d(old=%d), volt_dep_new=%d(dep_old=%d)\n",
\r
907 volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
910 volt_dep_pre = volt_dep;
\r
911 if (step * step_dep < 0) {
\r
912 // target is between volt_old and volt_dep_old, just
\r
914 DVFS_DBG("step * step_dep < 0\n");
\r
916 volt_dep = volt_dep_new;
\r
918 } else if (step > 0) {
\r
920 DVFS_DBG("step > 0\n");
\r
921 volt_tmp = volt_dep + clk_biger_than_dep;
\r
922 volt_dep_tmp = volt + dep_biger_than_clk;
\r
924 volt = volt_tmp > volt_new ? volt_new : volt_tmp;
\r
925 volt_dep = volt_dep_tmp > volt_dep_new ? volt_dep_new : volt_dep_tmp;
\r
927 } else if (step < 0) {
\r
929 DVFS_DBG("step < 0\n");
\r
931 volt_tmp = volt_dep - dep_biger_than_clk;
\r
932 volt_dep_tmp = volt - clk_biger_than_dep;
\r
934 volt = volt_tmp < volt_new ? volt_new : volt_tmp;
\r
935 volt_dep = volt_dep_tmp < volt_dep_new ? volt_dep_new : volt_dep_tmp;
\r
938 DVFS_ERR("Oops, some bugs here: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
943 if (vd_clk->cur_volt != volt) {
\r
944 DVFS_DBG("\t\t%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt);
\r
945 ret = dvfs_regulator_set_voltage_readback(regulator, volt, volt);
\r
946 //udelay(get_volt_up_delay(volt, volt_pre));
\r
947 dvfs_volt_up_delay(vd_clk,volt, volt_pre);
\r
949 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
950 __func__, vd_clk->name, ret, volt_new, volt_old);
\r
953 vd_clk->cur_volt = volt;
\r
955 if (vd_dep->cur_volt != volt_dep) {
\r
956 DVFS_DBG("\t\t%s:%d->%d\n", vd_dep->name, vd_dep->cur_volt, volt_dep);
\r
957 ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep, volt_dep);
\r
958 //udelay(get_volt_up_delay(volt_dep, volt_dep_pre));
\r
959 dvfs_volt_up_delay(vd_dep,volt_dep, volt_dep_pre);
\r
961 DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
962 __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);
\r
965 vd_dep->cur_volt = volt_dep;
\r
968 DVFS_DBG("\t\tNOW:Volt=%d, volt_dep=%d\n", volt, volt_dep);
\r
970 } while (volt != volt_new || volt_dep != volt_dep_new);
\r
972 vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
973 vd_clk->cur_volt = volt_new;
\r
977 DVFS_ERR("+++++++++++++++++FAIL AREA\n");
\r
978 vd_clk->cur_volt = volt_old;
\r
979 vd_dep->cur_volt = volt_dep_old;
\r
980 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
981 ret = dvfs_regulator_set_voltage_readback(regulator, volt_old, volt_old);
\r
983 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
984 DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",
\r
985 __func__, vd_clk->name, ret, volt_new, volt_old);
\r
988 ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_old, volt_dep_old);
\r
990 vd_dep->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
991 DVFS_ERR("%s %s set callback voltage err ret = %d, Vnew = %d(was %d)mV\n",
\r
992 __func__, vd_dep->name, ret, volt_dep_new, volt_dep_old);
\r
998 int dvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new)
\r
1001 DVFS_DBG("ENTER %s, volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);
\r
1002 if (IS_ERR_OR_NULL(vd_clk)) {
\r
1003 DVFS_ERR("%s vd_node error\n", __func__);
\r
1007 DVFS_DBG("ENTER %s, volt=%d(old=%d)\n", __func__, volt_new, vd_clk->cur_volt);
\r
1008 if (!IS_ERR_OR_NULL(vd_clk->regulator)) {
\r
1009 ret = dvfs_regulator_set_voltage_readback(vd_clk->regulator, volt_new, volt_new);
\r
1010 //udelay(get_volt_up_delay(volt_new, vd_clk->cur_volt));
\r
1011 dvfs_volt_up_delay(vd_clk,volt_new, vd_clk->cur_volt);
\r
1013 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
1014 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1015 __func__, vd_clk->name, ret, volt_new, vd_clk->cur_volt);
\r
1020 DVFS_ERR("%s up volt dvfs_clk->vd->regulator == NULL\n", __func__);
\r
1024 vd_clk->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
1025 vd_clk->cur_volt = volt_new;
\r
1031 int dvfs_scale_volt_bystep(struct vd_node *vd_clk, struct vd_node *vd_dep, int volt_new, int volt_dep_new,
\r
1032 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
1035 struct regulator *regulator, *regulator_dep;
\r
1036 int volt_new_corrected = 0, volt_dep_new_corrected = 0;
\r
1037 int volt_old = 0, volt_dep_old = 0;
\r
1040 volt_old = vd_clk->cur_volt;
\r
1041 volt_dep_old = vd_dep->cur_volt;
\r
1043 DVFS_DBG("ENTER %s, volt=%d(old=%d) vd_dep=%d(dep_old=%d)\n", __func__,
\r
1044 volt_new, volt_old, volt_dep_new, volt_dep_old);
\r
1045 DVFS_DBG("ENTER %s, VOLT_DIFF: clk_cur=%d(clk_new=%d) dep_cur=%d(dep_new=%d)\n", __func__,
\r
1046 cur_clk_biger_than_dep, new_clk_biger_than_dep,
\r
1047 cur_dep_biger_than_clk, new_dep_biger_than_clk);
\r
1049 volt_new_corrected = volt_new;
\r
1050 volt_dep_new_corrected = volt_dep_new;
\r
1051 correct_volt(&volt_new_corrected, &volt_dep_new_corrected, cur_clk_biger_than_dep, cur_dep_biger_than_clk);
\r
1052 ret = dvfs_scale_volt(vd_clk, vd_dep, volt_old, volt_new_corrected, volt_dep_old, volt_dep_new_corrected,
\r
1053 cur_clk_biger_than_dep, cur_dep_biger_than_clk);
\r
1055 vd_clk->volt_set_flag = DVFS_SET_VOLT_FAILURE;
\r
1056 DVFS_ERR("set volt error\n");
\r
1060 if (cur_clk_biger_than_dep != new_clk_biger_than_dep || cur_dep_biger_than_clk != new_dep_biger_than_clk) {
\r
1061 regulator = vd_clk->regulator;
\r
1062 regulator_dep = vd_dep->regulator;
\r
1064 volt_new_corrected = volt_new;
\r
1065 volt_dep_new_corrected = volt_dep_new;
\r
1066 correct_volt(&volt_new_corrected, &volt_dep_new_corrected, new_clk_biger_than_dep, new_dep_biger_than_clk);
\r
1068 if (vd_clk->cur_volt != volt_new_corrected) {
\r
1069 DVFS_DBG("%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt_new_corrected);
\r
1070 ret = dvfs_regulator_set_voltage_readback(regulator, volt_new_corrected, volt_new_corrected);
\r
1071 //udelay(get_volt_up_delay(volt_new_corrected, vd_clk->cur_volt));
\r
1072 dvfs_volt_up_delay(vd_clk,volt_new_corrected, vd_clk->cur_volt);
\r
1074 DVFS_ERR("%s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1075 __func__, vd_clk->name, ret, volt_new_corrected, vd_clk->cur_volt);
\r
1078 vd_clk->cur_volt = volt_new_corrected;
\r
1080 if (vd_dep->cur_volt != volt_dep_new_corrected) {
\r
1081 DVFS_DBG("%s:%d->%d\n", vd_clk->name, vd_clk->cur_volt, volt_dep_new_corrected);
\r
1082 ret = dvfs_regulator_set_voltage_readback(regulator_dep, volt_dep_new_corrected, volt_dep_new_corrected);
\r
1083 //udelay(get_volt_up_delay(volt_dep_new_corrected, vd_dep->cur_volt));
\r
1084 dvfs_volt_up_delay(vd_dep,volt_dep_new_corrected, vd_dep->cur_volt);
\r
1086 DVFS_ERR("depend %s %s set voltage up err ret = %d, Vnew = %d(was %d)mV\n",
\r
1087 __func__, vd_dep->name, ret, volt_dep_new_corrected, vd_dep->cur_volt);
\r
1090 vd_dep->cur_volt = volt_dep_new_corrected;
\r
1097 int dvfs_reset_volt(struct vd_node *dvfs_vd)
\r
1099 int flag_set_volt_correct = 0;
\r
1100 if (!IS_ERR_OR_NULL(dvfs_vd->regulator))
\r
1101 flag_set_volt_correct = dvfs_regulator_get_voltage(dvfs_vd->regulator);
\r
1103 DVFS_ERR("dvfs regulator is ERROR\n");
\r
1106 if (flag_set_volt_correct <= 0) {
\r
1107 DVFS_ERR("%s (vd:%s), try to reload volt ,by it is error again(%d)!!! stop scaling\n",
\r
1108 __func__, dvfs_vd->name, flag_set_volt_correct);
\r
1111 dvfs_vd->volt_set_flag = DVFS_SET_VOLT_SUCCESS;
\r
1112 DVFS_WARNING("%s (vd:%s), try to reload volt = %d\n",
\r
1113 __func__, dvfs_vd->name, flag_set_volt_correct);
\r
1115 /* Reset vd's voltage */
\r
1116 dvfs_vd->cur_volt = flag_set_volt_correct;
\r
1118 return dvfs_vd->cur_volt;
\r
1121 int dvfs_get_depend_volt(struct clk_node *dvfs_clk, struct vd_node *dvfs_vd_dep, int rate_new)
\r
1123 struct depend_list *depend;
\r
1124 struct cpufreq_frequency_table clk_fv_dep;
\r
1127 DVFS_DBG("ENTER %s, rate_new=%d\n", __func__, rate_new);
\r
1128 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {
\r
1129 DVFS_DBG("--round depend clk:%s(depend:%s)\n", depend->dvfs_clk->name, depend->dep_vd->name);
\r
1130 // this place just consider ONE depend voltage domain,
\r
1131 // multi-depends must have some differece
\r
1132 clk_fv_dep.index = 0;
\r
1133 if (depend->dep_vd == dvfs_vd_dep) {
\r
1134 ret = dvfs_clk_get_ref_volt_depend(depend, rate_new / 1000, &clk_fv_dep);
\r
1136 DVFS_ERR("%s get dvfs_ref_volt_depend error\n", __func__);
\r
1139 depend->req_volt = clk_fv_dep.index;
\r
1140 return depend->req_volt;
\r
1144 DVFS_ERR("%s can not find vd node %s\n", __func__, dvfs_vd_dep->name);
\r
1149 * dump_dbg_map() : Draw all informations of dvfs while debug
\r
1151 static int dump_dbg_map(char *buf)
\r
1154 struct vd_node *vd;
\r
1155 struct pd_node *pd, *clkparent;
\r
1156 struct clk_list *child;
\r
1157 struct clk_node *dvfs_clk;
\r
1158 struct depend_list *depend;
\r
1160 mutex_lock(&rk_dvfs_mutex);
\r
1162 printk( "-------------DVFS TREE-----------\n\n\n");
\r
1163 printk( "DVFS TREE:\n");
\r
1164 list_for_each_entry(vd, &rk_dvfs_tree, node) {
\r
1165 printk( "|\n|- voltage domain:%s\n", vd->name);
\r
1166 printk( "|- current voltage:%d\n", vd->cur_volt);
\r
1167 list_for_each_entry(depend, &vd->req_volt_list, node2vd) {
\r
1168 printk( "|- request voltage:%d, clk:%s\n", depend->req_volt, depend->dvfs_clk->name);
\r
1171 list_for_each_entry(pd, &vd->pd_list, node) {
\r
1172 printk( "| |\n| |- power domain:%s, status = %s, current volt = %d\n",
\r
1173 pd->name, (pd->pd_status == PD_ON) ? "ON" : "OFF", pd->cur_volt);
\r
1175 list_for_each_entry(child, &pd->clk_list, node) {
\r
1176 dvfs_clk = child->dvfs_clk;
\r
1177 printk( "| | |\n| | |- clock: %s current: rate %d, volt = %d,"
\r
1178 " enable_dvfs = %s\n",
\r
1179 dvfs_clk->name, dvfs_clk->set_freq, dvfs_clk->set_volt,
\r
1180 dvfs_clk->enable_dvfs == 0 ? "DISABLE" : "ENABLE");
\r
1181 printk( "| | |- clk limit:[%d, %d]; last set rate = %lu\n",
\r
1182 dvfs_clk->min_rate, dvfs_clk->max_rate,
\r
1183 dvfs_clk->clk->last_set_rate);
\r
1185 for (i = 0; dvfs_clk->pds[i].pd != NULL; i++) {
\r
1186 clkparent = dvfs_clk->pds[i].pd;
\r
1187 printk( "| | | |- clock parents: %s, vd_parent = %s\n",
\r
1188 clkparent->name, clkparent->vd->name);
\r
1191 for (i = 0; (dvfs_clk->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
1192 printk( "| | | |- freq = %d, volt = %d\n",
\r
1193 dvfs_clk->dvfs_table[i].frequency,
\r
1194 dvfs_clk->dvfs_table[i].index);
\r
1198 list_for_each_entry(depend, &dvfs_clk->depend_list, node2clk) {
\r
1199 printk( "| | | | |- DEPEND VD: %s\n", depend->dep_vd->name);
\r
1200 for (i = 0; (depend->dep_table[i].frequency != CPUFREQ_TABLE_END); i++) {
\r
1201 printk( "| | | | |- freq = %d, req_volt = %d\n",
\r
1202 depend->dep_table[i].frequency,
\r
1204 depend->dep_table[i].index);
\r
1210 printk( "-------------DVFS TREE END------------\n");
\r
1212 mutex_unlock(&rk_dvfs_mutex);
\r
1215 /*******************************AVS AREA****************************************/
\r
1217 * To use AVS function, you must call avs_init in machine_rk30_board_init(void)(board-rk30-sdk.c)
\r
1218 * And then call(vdd_log):
\r
1219 * regulator_set_voltage(dcdc, 1100000, 1100000);
\r
1220 * avs_init_val_get(1,1100000,"wm8326 init");
\r
1222 * avs_set_scal_val(AVS_BASE);
\r
1223 * in wm831x_post_init(board-rk30-sdk-wm8326.c)
\r
1224 * AVS_BASE can use 172
\r
1227 static struct avs_ctr_st *avs_ctr_data=NULL;
\r
1228 #define init_avs_times 10
\r
1229 #define init_avs_st_num 5
\r
1231 struct init_avs_st {
\r
1233 u8 paramet[init_avs_times];
\r
1238 static struct init_avs_st init_avs_paramet[init_avs_st_num];
\r
1240 void avs_board_init(struct avs_ctr_st *data)
\r
1243 avs_ctr_data=data;
\r
1245 void avs_init(void)
\r
1247 memset(&init_avs_paramet[0].is_set, 0, sizeof(init_avs_paramet));
\r
1248 if(avs_ctr_data&&avs_ctr_data->avs_init)
\r
1249 avs_ctr_data->avs_init();
\r
1250 avs_init_val_get(0, 1200000,"board_init");
\r
1252 static u8 rk_get_avs_val(void)
\r
1255 if(avs_ctr_data&&avs_ctr_data->avs_get_val)
\r
1257 return avs_ctr_data->avs_get_val();
\r
1262 /******************************int val get**************************************/
\r
1263 void avs_init_val_get(int index, int vol, char *s)
\r
1266 if(index >= init_avs_times)
\r
1268 init_avs_paramet[index].vol = vol;
\r
1269 init_avs_paramet[index].s = s;
\r
1270 init_avs_paramet[index].is_set++;
\r
1271 printk("DVFS MSG:\tAVS Value(index=%d): ", index);
\r
1272 for(i = 0; i < init_avs_times; i++) {
\r
1273 init_avs_paramet[index].paramet[i] = rk_get_avs_val();
\r
1275 printk("%d ", init_avs_paramet[index].paramet[i]);
\r
1279 int avs_set_scal_val(u8 avs_base)
\r
1284 /*************************interface to get avs value and dvfs tree*************************/
\r
1285 #define USE_NORMAL_TIME
\r
1286 #ifdef USE_NORMAL_TIME
\r
1287 static struct timer_list avs_timer;
\r
1289 static struct hrtimer dvfs_hrtimer;
\r
1292 static u32 avs_dyn_start = 0;
\r
1293 static u32 avs_dyn_data_cnt;
\r
1294 static u8 *avs_dyn_data = NULL;
\r
1295 static u32 show_line_cnt = 0;
\r
1296 static u8 dly_min;
\r
1297 static u8 dly_max;
\r
1299 #define val_per_line (30)
\r
1300 #define line_pre_show (30)
\r
1301 #define avs_dyn_data_num (3*1000*1000)
\r
1303 static u32 print_avs_init(char *buf)
\r
1308 for(j = 0; j < init_avs_st_num; j++) {
\r
1309 if(init_avs_paramet[j].vol <= 0)
\r
1311 s += sprintf(s, "%s ,vol=%d,paramet following\n",
\r
1312 init_avs_paramet[j].s, init_avs_paramet[j].vol);
\r
1313 for(i = 0; i < init_avs_times; i++) {
\r
1314 s += sprintf(s, "%d ", init_avs_paramet[j].paramet[i]);
\r
1317 s += sprintf(s, "\n");
\r
1322 static ssize_t avs_init_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1325 return print_avs_init(buf);
\r
1328 static ssize_t avs_init_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1329 const char *buf, size_t n)
\r
1334 static ssize_t avs_now_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1337 return sprintf(buf, "%d\n", rk_get_avs_val());
\r
1340 static ssize_t avs_now_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1341 const char *buf, size_t n)
\r
1345 static ssize_t avs_dyn_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1351 if(avs_dyn_data == NULL)
\r
1354 if(avs_dyn_start) {
\r
1357 end_cnt = (avs_dyn_data_cnt ? (avs_dyn_data_cnt - 1) : 0);
\r
1358 if(end_cnt > (line_pre_show * val_per_line))
\r
1359 start_cnt = end_cnt - (line_pre_show * val_per_line);
\r
1363 dly_min = avs_dyn_data[start_cnt];
\r
1364 dly_max = avs_dyn_data[start_cnt];
\r
1366 //s += sprintf(s,"data start=%d\n",i);
\r
1367 for(i = start_cnt; i <= end_cnt;) {
\r
1368 s += sprintf(s, "%d", avs_dyn_data[i]);
\r
1369 dly_min = min(dly_min, avs_dyn_data[i]);
\r
1370 dly_max = max(dly_max, avs_dyn_data[i]);
\r
1372 if(!(i % val_per_line)) {
\r
1373 s += sprintf(s, "\n");
\r
1375 s += sprintf(s, " ");
\r
1378 s += sprintf(s, "\n");
\r
1380 s += sprintf(s, "new data is from=%d to %d\n", start_cnt, end_cnt);
\r
1381 //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
1385 if(show_line_cnt == 0) {
\r
1386 dly_min = avs_dyn_data[0];
\r
1387 dly_max = avs_dyn_data[0];
\r
1391 for(i = show_line_cnt * (line_pre_show * val_per_line); i < avs_dyn_data_cnt;) {
\r
1392 s += sprintf(s, "%d", avs_dyn_data[i]);
\r
1393 dly_min = min(dly_min, avs_dyn_data[i]);
\r
1394 dly_max = max(dly_max, avs_dyn_data[i]);
\r
1396 if(!(i % val_per_line)) {
\r
1397 s += sprintf(s, "\n");
\r
1399 s += sprintf(s, " ");
\r
1400 if(i >= ((show_line_cnt + 1)*line_pre_show * val_per_line))
\r
1404 s += sprintf(s, "\n");
\r
1406 s += sprintf(s, "max=%d,min=%d,totolcnt=%d,line=%d\n",
\r
1407 dly_max, dly_min, avs_dyn_data_cnt, show_line_cnt);
\r
1409 if(((show_line_cnt * line_pre_show)*val_per_line) >= avs_dyn_data_cnt) {
\r
1411 show_line_cnt = 0;
\r
1413 s += sprintf(s, "data is over\n");
\r
1419 static ssize_t avs_dyn_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1420 const char *buf, size_t n)
\r
1424 if((strncmp(buf, "start", strlen("start")) == 0)) {
\r
1425 if(avs_dyn_data == NULL)
\r
1426 avs_dyn_data = kmalloc(avs_dyn_data_num, GFP_KERNEL);
\r
1427 if(avs_dyn_data == NULL)
\r
1430 pbuf = &buf[strlen("start")];
\r
1431 avs_dyn_data_cnt = 0;
\r
1432 show_line_cnt = 0;
\r
1433 if(avs_dyn_data) {
\r
1434 #ifdef USE_NORMAL_TIME
\r
1435 mod_timer(&avs_timer, jiffies + msecs_to_jiffies(5));
\r
1437 hrtimer_start(&dvfs_hrtimer, ktime_set(0, 5 * 1000 * 1000), HRTIMER_MODE_REL);
\r
1439 avs_dyn_start = 1;
\r
1441 //sscanf(pbuf, "%d %d", &number, &voltage);
\r
1442 //DVFS_DBG("---------ldo %d %d\n", number, voltage);
\r
1444 } else if((strncmp(buf, "stop", strlen("stop")) == 0)) {
\r
1445 pbuf = &buf[strlen("stop")];
\r
1446 avs_dyn_start = 0;
\r
1447 show_line_cnt = 0;
\r
1448 //sscanf(pbuf, "%d %d", &number, &voltage);
\r
1449 //DVFS_DBG("---------dcdc %d %d\n", number, voltage);
\r
1457 static ssize_t dvfs_tree_store(struct kobject *kobj, struct kobj_attribute *attr,
\r
1458 const char *buf, size_t n)
\r
1462 static ssize_t dvfs_tree_show(struct kobject *kobj, struct kobj_attribute *attr,
\r
1465 return dump_dbg_map(buf);
\r
1469 static void avs_timer_fn(unsigned long data)
\r
1472 for(i = 0; i < 1; i++) {
\r
1473 if(avs_dyn_data_cnt >= avs_dyn_data_num)
\r
1475 avs_dyn_data[avs_dyn_data_cnt] = rk_get_avs_val();
\r
1476 avs_dyn_data_cnt++;
\r
1479 mod_timer(&avs_timer, jiffies + msecs_to_jiffies(10));
\r
1482 struct hrtimer dvfs_hrtimer;
\r
1483 static enum hrtimer_restart dvfs_hrtimer_timer_func(struct hrtimer *timer)
\r
1486 for(i = 0; i < 1; i++) {
\r
1487 if(avs_dyn_data_cnt >= avs_dyn_data_num)
\r
1488 return HRTIMER_NORESTART;
\r
1489 avs_dyn_data[avs_dyn_data_cnt] = rk_get_avs_val();
\r
1490 avs_dyn_data_cnt++;
\r
1493 hrtimer_start(timer, ktime_set(0, 1 * 1000 * 1000), HRTIMER_MODE_REL);
\r
1497 /*********************************************************************************/
\r
1498 static struct kobject *dvfs_kobj;
\r
1499 struct dvfs_attribute {
\r
1500 struct attribute attr;
\r
1501 ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
\r
1503 ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
\r
1504 const char *buf, size_t n);
\r
1507 static struct dvfs_attribute dvfs_attrs[] = {
\r
1508 /* node_name permision show_func store_func */
\r
1509 #ifdef CONFIG_RK_CLOCK_PROC
\r
1510 __ATTR(dvfs_tree, S_IRUSR | S_IRGRP | S_IWUSR, dvfs_tree_show, dvfs_tree_store),
\r
1511 __ATTR(avs_init, S_IRUSR | S_IRGRP | S_IWUSR, avs_init_show, avs_init_store),
\r
1512 // __ATTR(avs_dyn, S_IRUSR | S_IRGRP | S_IWUSR, avs_dyn_show, avs_dyn_store),
\r
1513 __ATTR(avs_now, S_IRUSR | S_IRGRP | S_IWUSR, avs_now_show, avs_now_store),
\r
1517 static int __init dvfs_init(void)
\r
1520 #ifdef USE_NORMAL_TIME
\r
1521 init_timer(&avs_timer);
\r
1522 //avs_timer.expires = jiffies+msecs_to_jiffies(1);
\r
1523 avs_timer.function = avs_timer_fn;
\r
1524 //mod_timer(&avs_timer,jiffies+msecs_to_jiffies(1));
\r
1526 hrtimer_init(&dvfs_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
\r
1527 dvfs_hrtimer.function = dvfs_hrtimer_timer_func;
\r
1528 //hrtimer_start(&dvfs_hrtimer,ktime_set(0, 5*1000*1000),HRTIMER_MODE_REL);
\r
1531 dvfs_kobj = kobject_create_and_add("dvfs", NULL);
\r
1534 for (i = 0; i < ARRAY_SIZE(dvfs_attrs); i++) {
\r
1535 ret = sysfs_create_file(dvfs_kobj, &dvfs_attrs[i].attr);
\r
1537 DVFS_ERR("create index %d error\n", i);
\r
1544 subsys_initcall(dvfs_init);
\r