PXA310的电源管理(2)
2011-7-1 14:43:17
read 方法主要是返回一个事件,或者一直阻塞,直到返回一个事件为止
struct ipme_queue{
int head;
int tail;
int len;
struct ipm_event ipmes[MAX_IPME_NUM];
wait_queue_head_t waitq;
};
来描述一个事件队列
static struct ipme_queue ipme_queue;
首先会把当前进程加入到ipme_queue的等待队列中
如果open方式是非阻塞的就立即返回
如果当前进程有了信号就返回。
当ipme_queue有了事件后,就从ipme_queue中取出事件 返回。
那么这个事件是谁来插入的呢?
事件来源有很多。
如camere在open的时候会通知ipm事件
write 方法 没有实现。
poll 实际上就是查询事件产生
ioctl 方法
IPMC_IOCTL_GET_FV_OP 获取当前的操作点。
降低CPU 频率也是节能中比较重要的一项。
相关代码位于cpu-freq-voltage-pxa3xx.c中
operating point: 电源管理的一组配置数据。
这组配置数据一旦确定,能源消耗率和系统性能也就相应的确定了。
PXA310来使用如下结构体来描述操作点。
struct pxa3xx_fv_info {
unsigned long xl;
unsigned long xn;
unsigned int vcc_core;
unsigned int vcc_sram;
unsigned long smcfs;
unsigned long sflfs;
unsigned long hss;
unsigned long dmcfs;
unsigned long df_clk;
unsigned long empi_clk;
unsigned long d0cs;
/* WARNING: above fields must be consistent with PM_FV_INFO!!!*/
unsigned long lpj; /* New value for loops_per_jiffy */
};
所有操作点存放在struct pxa3xx_fv_info pxa3xx_por_op[DVFM_MAX_OP]中
这个模块向系统注册了这样一个平台驱动。
static struct platform_driver pxa3xx_fv_driver = {
.driver = {
.name = "pxa3xx_fv",
},
.probe = pxa3xx_fv_probe,
.remove = pxa3xx_fv_remove,
.suspend = pxa3xx_fv_suspend,
.resume = pxa3xx_fv_resume,
};
probe 方法
先统计出当前有效的操作点数目
查找当前所属的操作点,就是查找频率和电压
频率就通过下面2个寄存器查找
#define MEMCLKCFG __REG_2(0x4A000068) /* SCLK speed configuration */
#define ACSR __REG(0x41340004) /* Application Subsystem Clock Status Register */
然后通过PMIC找到对应的电压
可以通过如下操作来查看当前所处的op
/sys/devices/system/cpu/cpu0 # cat op
op:4, xl:24, xn:2,vcc_core:1375, vcc_sram:1400,smcfs:5, sflfs:3, hss:2, dmcfs:3, df_clk:3,empi_clk:3, d0cs:0, lpj:3112960
注意 正常工作模式下为CPU频率为624M,而睡眠模式下为 426M
suspend 和 suspend就是在不同的操作点之间进行切换。
从框架上说 PRM是中心,ipmc要想获取当前操作点也得通过PRM
对应的还有设置op的操作
IPMC_IOCTL_SET_FV_OP
用户层传入的结构体为
struct ipmc_ioctl_setfvop {
unsigned int op;
unsigned int mode;
};
需要加入的一个额外的步骤就是需要检查当前client是否有权限来访问操作点资源
IPMC_IOCTL_GET_FV_OP_COUNT
获取op的数目
IPMC_IOCTL_GET_FV_OP_INFO
除了获取op信息外还获取op id