一、基本概念
DVFS(Dynamic Voltage and Frequency Scaling)动态电压频率调节,是一种实时的电压和频率调节技术。在 CMOS 电路中功率消耗主要可以分为动态功率消耗和静态功率消耗,公式如下:
其中 C 代表负载电容的容值,V 是工作电压,α 是当前频率下的翻转率,f为工作频率,I_dq 代表静态电流。公式的前部分代表的是动态功率消耗,后部分则代表的是静态功率消耗。从公式中可以看出,想要降低动态功率消耗可以从C、V、α、f着手,对于软件来讲常用的调节方式只涉及到V、f 两个因素。
二、代码解析
1、数据结构
系统中存在 7 大总线:ARM_CLK、AXI_CLK、DSP_CLK、APP_CLK、MPH_CLK、GE_CLK、VS_CLK,DVFS 系统的所有工作都围绕这几大总线以及核心电压CORE_VOLTAGE展开,代码里面用到的数据结构有:DVFS_REQ、DVFS_CMD、DVFS_NODE、DVFS_CDB,定义如下:
typedef struct {
const char* module; /* 发出调节请求的模块名称 */
unsigned char flag; /* 调节频率的标记: 有最低、最高、锁定三种 */
DVFS_CLK_e clk; /* 申请调节的时钟总线,有7大总线 */
int freq; /* 期望频率值 */
} DVFS_REQ;
typedef struct {
DVFS_CBF cb; /* 回调函数 */
int arg; /* 参数 */
int num; /* 本次请求的数目 */
DVFS_REQ reqs[MAX_REQ_NUM]; /* 请求存放的数组,最多8个请求 */
} DVFS_CMD;
typedef struct {
struct list_head head; /* 链表节点 */
DVFS_REQ req; /* 当前请求 */
} DVFS_NODE;
typedef struct {
// cmd queue managment
DVFS_CMD q_array[CMD_Q_LENGTH];
uint8_t q_idx_r;
uint8_t q_idx_w;
uint8_t q_idx_p;
spinlock_t q_lock;
// worker thread management
wait_queue_head_t q_wait; /* 等待队列 */
struct task_struct* task; /* 任务 */
// list of request for each clock
DVFS_NODE* req_lists[DVFS_CLK_ALL]; /* 指向每条总线的请求链表 */
// clock/voltage setttings
int curr_freq_idx[DVFS_CLK_ALL]; /* 当前频率的索引值 */
int trgt_freq_idx[DVFS_CLK_ALL]; /* 目标频率的索引值 */
struct clk* hw_clock[DVFS_CLK_ALL]; /* 时钟设置 */