〇、引子
書接上回,即:S3C2416睡眠的底層實現。
話說,春夢了無痕,秋鴻有信終需醒。睡醒後的恢復操作以及恢復哪些東西,在s3c_pm_enter(suspend_state_t state)函數的後半部分有具體實現:
arch/arm/plat-samsung/pm.c
static int s3c_pm_enter(suspend_state_t state) { ...... /* restore the system state */ s3c_pm_restore_core(); s3c_pm_restore_uarts(); samsung_pm_restore_gpios(); s3c_pm_restored_gpios(); s3c_pm_debug_init(); /* check what irq (if any) restored the system */ s3c_pm_arch_show_resume_irqs(); S3C_PMDBG("%s: post sleep, preparing to return\n", __func__); /* LEDs should now be 1110 */ s3c_pm_debug_smdkled(1 << 1, 0); s3c_pm_check_restore(); /* ok, let's return from sleep */ S3C_PMDBG("S3C PM Resume (post-restore)\n"); return 0; }這裡一筆帶過。接下來從喚醒源入手,看怎麼把指定的外部中斷或RTC設置為喚醒源,以及,喚醒源是怎麼被內核識別的。
一、插曲:
開始,是從以下兩個全局變了入手的,但最後進入了死胡同,出口渺然無蹤:
unsigned long s3c_irqwake_intmask = 0xffffffffL; unsigned long s3c_irqwake_eintmask = 0xffffffffL;茫茫然時突然想到,為何不從喚醒源處入手?
二、正文:
以IRQ_EINT0作為喚醒源,添加在smdk_machine_init()函數中:
arch/arm/mach-s3c24xx/common-smdk.c
void __init smdk_machine_init(void)
{
request_irq(IRQ_EINT0, button_irq, IRQ_TYPE_EDGE_FALLING, "BUTTON_IRQ_EINT0", NULL);
enable_irq_wake(IRQ_EINT0);
s3c_pm_init();
}
enable_irq_wake()函數的入參作為喚醒源標號:
include/linux/interrupt.h
static inline intenable_irq_wake(unsigned int irq)
{
return
irq_set_irq_wake(irq, 1);
}
irq_set_irq_wake()函數的第二個參數非零,就使能喚醒源IRQ_EINT0:
kernel/irq/manage.c
intirq_set_irq_wake(unsigned int irq, unsigned int on)
{
/* Wakeup mode lets this IRQ wake the system from sleep
* states like "suspend to RAM".
*/
if (on) {
if (desc->wake_depth++ == 0) {
ret =
set_irq_wake_real(irq, on);
if (ret)
desc->wake_depth = 0;
else
irqd_set(&desc->irq_data, IRQD_WAKEUP_STATE);
}
}
}
static intset_irq_wake_real(unsigned int irq, unsigned int on)
{
struct irq_desc *desc = irq_to_desc(irq);
int ret = -ENXIO;
if (irq_desc_get_chip(desc)->flags & IRQCHIP_SKIP_SET_WAKE)
return 0;
if (desc->irq_data.chip->irq_set_wake)
ret = desc->irq_data.chip->irq_set_wake(&desc->irq_data, on);
return ret;
}
irq_set_wake是函數指針,原型定義:
int (*irq_set_wake)(struct irq_data *data, unsigned int on);
到了這裡,死胡同由出現了;它指向哪裡?也即功能的實現實在哪裡呢?
這時,先前提到的兩個全局變量s3c_irqwake_intmask、s3c_irqwake_eintmask就“粉墨登場”了,irq_set_wake指向函數s3c_irq_wake()就在這兩個變量的下面:
arch/arm/mach-s3c24xx/irq-pm.c
Linux的源代碼,一定記得使用如下網站:
http://lxr.free-electrons.com/ident?i=
至此,Linux內核對睡眠/喚醒的支持流程分析完畢。