Rk平台dvfs流程简易分析

DVFS 即动态电压频率调整,动态技术则是根据芯片所运行的应用程序对计算能力的不同需要,动态调节芯片的运行频率和电压,从而达到节能的目的。

Sysfs接口:

       Cpufreq提供接口位于/sys/devices/system/cpu/cpu0/cpufreq 目录

cat scaling_available_frequencies:打印当前软件支持的频率值,与board文件static struct dvfs_arm_tabledvfs_cpu_logic_table[]给出频率值一样

cat cpuinfo_cur_freq:打印当前系统运行频率值

Dvfs大致控制流程:

1.采集与系统负载有关的信号,计算当前的系统负载。
2.根据系统的当前负载,预测系统在下一时间段需要的性能。
3.将预测的性能转换成需要的频率,从而调整芯片的时钟设置。
4.根据新的频率计算相应的电压。通知电源管理模块调整给CPU的电压。

 相应知识还可以参考:http://blog.csdn.net/droidphone/article/details/9346981

以rk3066boxcore为例。rk3066box采用了分立电源,DVFS调节系统的VDD_ARM、VDD_LOG电压是通过PWM模块控制;如果是采用PMU电源管理的话,那这二个电压是通过PMU Regulator来控制的。

 

一、DVFS 设备资源层代码实现:代码位于Board-rk30-box.c(arch\arm\mach-rk30)

1) rk3066box是通过DVS0_CTL信号调节VDD_ARM、DVS1_CTL信号调节VDD_LOG电压。pwm资源层代码实现:

static struct regulator_consumer_supplypwm_dcdc1_consumers[] = {

{

           .supply= "vdd_cpu",  //用户支持的接口映射

}

};

struct regulator_init_data pwm_regulator_init_dcdc[] =

{

{//Regulator操作约束,比如这里设置电压范围:0.6-1.8V

           .constraints= {

                    .name= "PWM_DCDC1",

                    .min_uV= 600000,

                    .max_uV= 1800000,        //0.6-1.8V

                    .apply_uV= true,

                    .valid_ops_mask= REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE,

           },

           .num_consumer_supplies= ARRAY_SIZE(pwm_dcdc1_consumers),

           .consumer_supplies= pwm_dcdc1_consumers,

},

};

static struct pwm_platform_data pwm_regulator_info[] ={

{//pwm资源设置,比如pwm GPIO口、挂起电压、参考电压、电压范围的设置

           .pwm_id= 0,

           .pwm_gpio= RK30_PIN0_PA3,

           .pwm_iomux_name= GPIO0A3_PWM0_NAME,

           .pwm_iomux_pwm= GPIO0A_PWM0,

           .pwm_iomux_gpio= GPIO0A_GPIO0A3,

           .pwm_voltage= 1300000,

           .suspend_voltage= 1050000,

           .min_uV= 950000,

           .max_uV      = 1400000,

           .coefficient= 455,   //45.5%

           .pwm_voltage_map= pwm_voltage_map,

           .init_data      = &pwm_regulator_init_dcdc[0],

},

};

2) 动态调频的资源设置

static struct dvfs_arm_table dvfs_cpu_logic_table[] = {

//frequency为频率值、cpu_volt为arm电压值、logic_volt为log电压值

{.frequency = 504* 1000,  .cpu_volt = 1150 * 1000,   .logic_volt = 1125 *1000},//0.975V/1.000V

{.frequency =1200 * 1000,         .cpu_volt = 1250 *1000,   .logic_volt = 1250 *1000},//1.100V/1.050V

{.frequency =1608 * 1000,         .cpu_volt = 1400 *1000,   .logic_volt = 1350 *1000},//1.325V/1.175V

{.frequency =CPUFREQ_TABLE_END},

};

二、DVFS初始化流程:Dvfs.c(arch\arm\mach-rk30) 和 Dvfs.c (arch\arm\plat-rk)

         int rk_dvfs_init(void)

{

         int i = 0;

         //创建并初始化DVFS工作队列

         for (i = 0; i <ARRAY_SIZE(rk30_vds); i++) {

                   rk_regist_vd(rk30_vds[i]);

         }

         for (i = 0; i <ARRAY_SIZE(rk30_pds); i++) {

                   rk_regist_pd(&rk30_pds[i]);

         }

         for (i = 0; i <ARRAY_SIZE(rk30_clks); i++) {

                   rk_regist_clk(&rk30_clks[i]);

         }

         for (i = 0; i <ARRAY_SIZE(rk30_depends); i++) {

                   rk_regist_depends(&rk30_depends[i]);

         }

         //获得cpu系统时钟信号

         dvfs_clk_cpu =dvfs_get_dvfs_clk_byname("cpu");

         avs_board_init(&rk30_avs_ctr);

         printk("rk30_dvfs_init\n");

         return 0;

}

 

三、DVFS 动态调频流程

         当发生了频率的调整,DVFS通过dvfs_set_rate()【Dvfs.c (arch\arm\plat-rk)】函数来改变频率值

         int dvfs_set_rate(struct clk *clk,unsigned long rate)

{

         int ret = 0;

         struct vd_node *vd;

         DVFS_DBG("%s(%s(%lu))\n",__func__, clk->name, rate);

         if (!clk->dvfs_info) {

                   DVFS_ERR("%s :This clkdo not support dvfs!\n", __func__);

                   ret = -1;

         } else {

                   vd =clk->dvfs_info->vd;

                   //mutex_lock(&vd->dvfs_mutex);

                   mutex_lock(&rk_dvfs_mutex);

                   ret =vd->vd_dvfs_target(clk, rate);

                   mutex_unlock(&rk_dvfs_mutex);

                   //mutex_unlock(&vd->dvfs_mutex);

         }

         DVFS_DBG("%s(%s(%lu)),isend\n", __func__, clk->name, rate);

         return ret;

}

dvfs_set_rate()改变的频率值,通过cpufreq_notify_transition()【Cpufreq.c (drivers\cpufreq)】函数更新当前系统的频率值

voidcpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)

{

}

VDD_ARM与VDD_LOG电压通过dvfs_scale_volt()【Dvfs.c (arch\arm\plat-rk)】来调整的。

         int dvfs_scale_volt(struct vd_node*vd_clk, struct vd_node *vd_dep,

                   int volt_old, int volt_new,int volt_dep_old, int volt_dep_new, int clk_biger_than_dep, intdep_biger_than_clk)

{        …..

         ……

         dvfs_regulator_set_voltage_readback(regulator,volt, volt); //调用这个函数,最终会调用pwm_regulator_set_voltage()调节电压

         …….

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值