本文转载自:https://bbs.csdn.net/topics/360192854
前一段时间调试了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 "
ioctl of suspend is entered!
");
printk(KERN_INFO "
suspend_state is %d %s
", 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 "
system is suspended
");
base_addr_pwrcfg = ioremap(0x7E00F804, 0x04);
base_addr_rtccon = ioremap(0x7E005050, 0x04);
printk(KERN_INFO " pwrcfg value is: %x
", readl(base_addr_pwrcfg));
printk(KERN_INFO " rtccon value is: %x
", 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
", readl(base_addr_pwrcfg));
printk(KERN_INFO " rtccon value is: %x
", 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;
}