- UID
- 1029342
- 性别
- 男
|
这就是实现三个状态转换的三个钩子函数.
这个函数较为简单, 只是将/kerenel/power/main.c里的全局变量suspend_ops设置成
s3c_pm_ops而已了.
这就完成了这个全局变量的初始化.后续对suspend_ops的访问实质上都是访问s3c_pm_ops.
void suspend_set_ops(struct platform_suspend_ops *ops)
{
mutex_lock(&pm_mutex);
suspend_ops = ops;
mutex_unlock(&pm_mutex);
}
最后看看函数实现:
static int s3c_pm_prepare(void)
{
s3c_pm_check_prepare();
return 0;
}
static void s3c_pm_finish(void)
{
s3c_pm_check_cleanup();
}
这里主要是s3c_pm_nter函数:
static int s3c_pm_enter(suspend_state_t state)
{
//用于保存16个通用寄存器的栈
static unsigned long regs_save[16];
s3c_pm_debug_init();
S3C_PMDBG("%s(%d)\n", __func__, state);
if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL){
printk(KERN_ERR"%s: error: no cpu sleep function\n", __func__);
return -EINVAL;
}
//检查允许的唤醒中断
if (!any_allowed(s3c_irqwake_intmask,s3c_irqwake_intallow) &&
!any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
printk(KERN_ERR "%s: No wake-up sources!\n", __func__);
printk(KERN_ERR "%s: Aborting sleep\n", __func__);
return -EINVAL;
}
//寄存器的物理地址
s3c_sleep_save_phys =virt_to_phys(regs_save);
S3C_PMDBG("s3c_sleep_save_phys=0xlx\n",s3c_sleep_save_phys);
//保存不属于driver的核心寄存器, driver的各自保存
s3c_pm_save_gpios();
s3c_pm_save_uarts();
s3c_pm_save_core();
//设置外部中断用于唤醒
s3c_pm_configure_extint();
S3C_PMDBG("sleep: irq wakeup masks:lx,lx\n",
s3c_irqwake_intmask,s3c_irqwake_eintmask);
s3c_pm_arch_prepare_irqs();
pm_cpu_prep();
flush_cache_all();
s3c_pm_check_store();
s3c_pm_arch_stop_clocks();
s3c_cpu_save(regs_save);
//当接收到一个外部中断时,系统开始恢复
cpu_init();
s3c_pm_restore_core();
s3c_pm_restore_uarts();
s3c_pm_restore_gpios();
s3c_pm_debug_init();
s3c_pm_arch_show_resume_irqs();
S3C_PMDBG("%s: post sleep, preparing toreturn\n", __func__);
s3c_pm_check_restore();
S3C_PMDBG("S3C PM Resume(post-restore)\n");
return 0;
} |
|