6410 休眠唤醒实现小结

来源:互联网 发布:超级祝福油数据库 编辑:程序博客网 时间:2024/04/28 06:55

 前一段时间调试了6410的休眠和唤醒,一直没有时间自己总结一下,下面把具体的实现贴出来,供大家参考,又不对的地方,请帮忙纠正,谢谢。
1,在/driver/char中修改Makefile,添加以下语句:

obj-$(CONFIG_APM_EMULATION)+= apm-emulation.o

2,在/driver/char中修改Kconfig,添加以下语句:

config APM_EMULATION
bool "S3C64XX Power Management support"
help
Power Management of Linux Arm for S3C64XX support

3,进入menuconfig界面,执行以下操作:

选中选项“Power management options --->”  

内部选为:“[*] Power Management support  
  [ ] Power Management Debug Support
  [*] Suspend to RAM and standby 
  <*> Advanced Power Management Emulation ”

4,修改文件/driver/char/apm-emulation.c,将函数apm_ioctl改为以下代码,实现rtc定时唤醒功能:

/*
 * apm_ioctl - handle APM ioctl
 *
 * APM_IOC_SUSPEND
 * This IOCTL is overloaded, and performs two functions. It is used to:
 * - initiate a suspend
 * - acknowledge a suspend read from /dev/apm_bios.
 * Only when everyone who has opened /dev/apm_bios with write permission
 * has acknowledge does the actual suspend happen.
 */
static int
apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
{
struct apm_user *as = filp->private_data;
int err = -EINVAL;

if (!as->suser || !as->writer)
return -EPERM;

switch (cmd) {
case APM_IOC_SUSPEND:
mutex_lock(&state_lock);

as->suspend_result = -EINTR;

/* added by byc for test */
printk(KERN_INFO "/nioctl of suspend is entered!/n");
printk(KERN_INFO "/nsuspend_state is %d %s/n", as->suspend_state, as->suspend_state);
/* end */

switch (as->suspend_state) {
case SUSPEND_READ:
/*
* If we read a suspend command from /dev/apm_bios,
* then the corresponding APM_IOC_SUSPEND ioctl is
* interpreted as an acknowledge.
*/
as->suspend_state = SUSPEND_ACKED;
atomic_dec(&suspend_acks_pending);
mutex_unlock(&state_lock);

/*
* suspend_acks_pending changed, the notifier needs to
* be woken up for this
*/
wake_up(&apm_suspend_waitqueue);

/*
* Wait for the suspend/resume to complete. If there
* are pending acknowledges, we wait here for them.
*/
freezer_do_not_count();

wait_event(apm_suspend_waitqueue,
as->suspend_state == SUSPEND_DONE);

/*
* Since we are waiting until the suspend is done, the
* try_to_freeze() in freezer_count() will not trigger
*/
freezer_count();
break;
case SUSPEND_ACKTO:
as->suspend_result = -ETIMEDOUT;
mutex_unlock(&state_lock);
break;
default:
as->suspend_state = SUSPEND_WAIT;
mutex_unlock(&state_lock);

/*
* Otherwise it is a request to suspend the system.
* Just invoke pm_suspend(), we'll handle it from
* there via the notifier.
*/
/* added by byc for test */
static void __iomem *base_addr_pwrcfg;
static void __iomem *base_addr_rtccon;

printk(KERN_INFO "/nsystem is suspended/n");

base_addr_pwrcfg = ioremap(0x7E00F804, 0x04);
base_addr_rtccon = ioremap(0x7E005050, 0x04);

printk(KERN_INFO " pwrcfg value is: %x/n", readl(base_addr_pwrcfg));
printk(KERN_INFO " rtccon value is: %x/n", readl(base_addr_rtccon));

writel(readl(base_addr_pwrcfg) & 0xfffffbff, base_addr_pwrcfg);
writel(readl(base_addr_rtccon) | 0x47, base_addr_rtccon);

printk(KERN_INFO " pwrcfg value is: %x/n", readl(base_addr_pwrcfg));
printk(KERN_INFO " rtccon value is: %x/n", readl(base_addr_rtccon));
/* end */

as->suspend_result = pm_suspend(PM_SUSPEND_MEM);
}
/* added by byc for test */
//platform_driver_register(&sdhci_s3c_driver);
/* end */
mutex_lock(&state_lock);
err = as->suspend_result;
as->suspend_state = SUSPEND_NONE;
mutex_unlock(&state_lock);
break;
}

return err;
}

原创粉丝点击