enable_irq_wake

FromKevin Hilman <>
SubjectRe: [PATCH 1/3] ARM: omap2+: set IRQCHIP_SKIP_SET_WAKE for INTC interrupts.
DateThu, 26 Apr 2012 13:39:07 -0700
NeilBrown <neilb@suse.de> writes:

> All interrupts can wake-from-sleep (I think) so it should be
> permissible to call enable_irq_wake().  Setting this flag allows that.
>
> It is needed because without this, an interrupt which is delivered
> during late suspend will get ignored but will not cause suspend to
> abort.
> If enable_irq_wake() is called and succeeds, check_wakuep_irqs()
> will abort the suspend if the interrupt has fired.
>
> Signed-off-by: NeilBrown <neilb@suse.de>

The name of this flag and the effect of setting it are somewhat
confusing (e.g. why does skipping set_wake suddenly make wakeups work.)
So I tried to make it clearer with a reworking of the changelog (below.)

If I understood this correctly, and if you're OK with the updated
changelog, I'll queue this up for v3.5.

Thanks,

Kevin

From 644742ddae59731bc10aacde94645d7c49ca5ecd Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Wed, 25 Apr 2012 13:05:24 +1000
Subject: [PATCH] ARM: omap2+: set IRQCHIP_SKIP_SET_WAKE for INTC interrupts.

Without an ->irq_set_wake() method in an irq_chip, calls to
enable_irq_wake() will fail.  This also causes these interrupts to not
be able to abort suspend (via check_wakeup_irqs() in late suspend.)

Currently, we don't implement ->irq_set_wake() for INTC interrupts
because they default to be wakeup enabled by setting the GRPSEL bits
in PM init.  Even though there is no ->irq_set_wake(), we want
enable_irq_wake() to succeed so these interrupts can abort suspend
when necessary.

To fix, set IRQCHIP_SKIP_SET_WAKE flag for all the INTC
interrupts which avoids trying to check irq_chip->irq_set_wake()
and failing when it doesn't exist.

Longer term, we need to implement ->irq_set_wake() for the INTC
which can manage the appropriate GRPSEL bits.

Signed-off-by: NeilBrown <neilb@suse.de>
[khilman@ti.com: rework changelog]
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/irq.c |    1 +
 1 file changed, 1 insertion(+)
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 65f0d257..b0790a9 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -148,6 +148,7 @@ omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
 	ct->chip.irq_ack = omap_mask_ack_irq;
 	ct->chip.irq_mask = irq_gc_mask_disable_reg;
 	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+	ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE;
 
 	ct->regs.ack = INTC_CONTROL;
 	ct->regs.enable = INTC_MIR_CLEAR0;
-- 
1.7.9.2
 
 
 

Linux下节能中断唤醒

在linux系统进入节能,如进入mem之后,可以通过中断唤醒系统。选择在节能模式下,是否支持该中断唤醒系统是本文要讲的内容。

例如,在触摸屏的suspend方法中,调用enable_irq_wake,则设置支持触摸屏中断唤醒系统休眠,在resume方法中,调用disable_irq_wake关闭支持。

enable_irq_wake

就该函数而言,可以从两方面思考。一,必须在进入suspend之前设置支持该中断,二,在中断唤醒表中标记对应的中断号,支持其中断唤醒。

enable_irq_wake调用函数set_irq_wake(irq,1),跟踪set_irq_wake.该函数首先获得中断描述符,禁止所有中断,调用set_irq_wake_real设置中断(步骤一),接着设置desc->status|=IRQ_WAKEUP(步骤二),该status会在进入suspend之前,通过检查status的标志位是否有IRQ_WAKEUP来决定是否支持中断唤醒休眠。

步骤一,set_irq_wake_real,该函数如下,

318 static int set_irq_wake_real(unsigned int irq, unsigned int on)
319 {
320         struct irq_desc *desc = irq_to_desc(irq);
321         int ret = -ENXIO;
322 
323         if (desc->chip->set_wake)
324                 ret = desc->chip->set_wake(irq, on);
325 
326         return ret;
327 }
        该函数实际调用的是中断相关芯片的set_wake操作。
    对于freescale的mx25而言(与体系相关),在MACHINE_START中,通过machine_desc,不同的体系有不同的machine_desc,配置中断,在set_irq_handler被调用时,有set_irq_chip设置chip操作,set_irq_chip实际就是不同的中断号对应的chip指针指向mxc_avic_chip.
    static struct irq_chip mxc_avic_chip = {
    .ack = mxc_mask_irq,
    .mask = mxc_mask_irq,
    .unmask = mxc_unmask_irq,
    .set_wake = mxc_set_wake_irq,
};
    Chip的所有操作,包括startup,enable,disable都是在上述方法的基础上封装的,具体与寄存器配置有关。
    Set_wake方法实际就是mxc系列在suspend期间允许相关中断的寄存器配置操作。
    
        步骤二,desc->status|=IRQ_WAKEUP,
    关于IRQ_WAKEUP,有两处涉及,
   (1)check_wakeup_irqs,该函数被sysdev_suspend所调用。在准备进入suspend时,会调用sysdev_suspend,该函数中通过调用check_wakeup_irqs,检查设置IRQ_WAKEUP的中断是否还有在pending状态,即进入中断未退出的,如果有,则禁止进入suspend。
   (2)对于不同的体系,进入节能配置允许中断唤醒的操作各不相同。所以Linux下有platform_suspend_ops提供出来,从而区别不同的方法统一操作。
    在late_initcall(mx25_pm_init)中,调用suspend_set_ops的方法设置platform_suspend_ops设置ops.
struct platform_suspend_ops mx25_suspend_ops = {
    .begin = mx25_pm_begin,
    .valid = mx25_pm_valid,
    .prepare = mx25_suspend_prepare,
    .enter = mx25_suspend_enter,
    .finish = mx25_suspend_finish,
};
    在sysdev_suspend成功之后,会调用mx25的enter方法,即mx25_suspend_enter,该函数最终调用mxc_cpu_lp_set(“mem”模式suspend)。该函数中,
    if ((desc->status & IRQ_WAKEUP) != 0)
                 lpimr &= ~(1 << (i - 32));
    配置lpimr寄存器,该寄存器就是允许休眠中断唤醒的中断设置。
       
    整体上睡眠中断唤醒的流程就这样,而disable_irq_wakeup与enable_irq_wakeup只是简单的类似操作。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值