新闻中心

EEPW首页>电源与新能源>设计应用> 一种基于SEP0611的电源管理驱动设计方案实现

一种基于SEP0611的电源管理驱动设计方案实现

作者: 时间:2014-02-09 来源:网络 收藏
nd-color: rgb(255, 255, 255); ">volatile unsigned long *p_regs = i2s_info.base;

本文引用地址://m.amcfsurvey.com/article/226567.htm

i2s_regs = kmalloc((I2S_PM_REGS_NUM 《 2),

GFP_KERNEL);

if(i2s_regs == NULL)

return -ENOMEM;

for(i=0; i《I2S_PM_REGS_NUM; i++)

i2s_regs[i] = *p_regs++;

clk_disable(i2s_info.clk);

return 0;

这段代码主要实现:保存音频设备硬件寄存器;禁止音频设备时钟。 2、休眠进入和休眠退出

完成了进入休眠的准备工作,接下来就是进入休眠。

suspend_enter是休眠进入函数,该函数将调用suspend_ops-》enter(state),调用该函数即是调用驱动接口函数sep_pm_enter;该接口函数在sep_pm.c中实现。该文件将保存在CPU寄存器,将休眠代码搬运到sram中,然后系统在 sram中执行休眠代码,先让DDR进入自刷新状态,而后处理器进入sleep模式。当系统处于休眠模式时,一旦接收到唤醒事件的中断,如内部的RTC ALARM中断或者外部的Wakeup按键信号才能够让系统退出休眠,即唤醒系统。综上,进入/退出休眠的代码流程图如图2所示。

一种基于SEP0611的电源管理驱动设计方案实现

图2 进入/退出sleep模式的代码流图

在图2中的休眠进入部分,保存CPU各模式状态之后,跳转到sram执行DDR2的自刷新和休眠的进入,而这段代码(DDR2的自刷新和休眠的进入)此前已由copy_func_to_sram函数搬运至sram中;而跳转通过将sram的物理地址静态映射到linux内核(在对应架构的mm.c 中)实现。

此后,系统处于休眠(sleep)模式,直至唤醒信号的到来。

中可用的唤醒信号有:电源键、RTC的ALARM中断、外部GPIO(AO)口。一旦唤醒信号到来,即是该执行休眠退出部分了。PMU 硬件部分将让系统重新上电,而软件则回到bootloader部分执行,在bootloader中有一段分支代码,该部分代码判断是一次正常启动还是一次从休眠的唤醒,若是后者,则恢复CPU各模式状态,此后回到linux操作系统。需要说明的是,在进入休眠部分的保存CPU各模式状态之前,PC值(用于返回的地址,实际保存的是PC值加上0x10(合4条指令))已经被保存到一个硬件寄存器中;因此,在退出休眠部分的恢复CPU各模式状态之后,将PC值从硬件寄存器取出,通过其使程序回到linux操作系统执行。

3、完成唤醒

上面讲到了程序回到linux系统执行后,休眠内核层将通过suspend_devices_and_enter函数中位于调用suspend_enter之后的部分和suspend_finish函数完成与休眠准备相逆的操作。

首先在suspend_devices_and_enter函数中执行以下完成唤醒的工作:

(1) 调用dpm_suspend_end函数,该函数分为两步。

首先调用设备唤醒函数device_resume,该函数会遍历dpm_off 链表队列,依次调用该队列上设备驱动的resume函数,让驱动恢复正常工作模式,并将其从dpm_off 队列恢复至dpm_active 队列。然后调用device_complete函数,该函数通常无操作。下面仍以音频驱动为例展示设备驱动resume函数的填写(函数头略):

int i;

volatile unsigned long *p_regs = i2s_info.base;

clk_enable(i2s_info.clk);

init_i2s_gpio();

for(i=0;i《I2S_PM_REGS_NUM; i++)

*p_regs++ = i2s_regs[i];

kfree(i2s_regs);



关键词:SEP0611电源管理

评论


相关推荐

技术专区

关闭