[推荐] 6410 休眠唤醒实现小结 [问题点数:40分]【转】

本文转载自: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;
}

原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/10238890.html