Like eint wakeup mask, this patch is to calculate the
resuming-mask specific to eint.
If the wakeup eint(s) are level-triggered, the external device
would generate IRQ strom. In consequence, system would be looped
in handling low-level asm_IRQ stuff as resuming.
Matt
From: Matt Hsu <[EMAIL PROTECTED]>
Date: Thu, 13 Nov 2008 18:39:23 +0800
Like eint wakeup mask, this patch is to calculate the
resuming-mask specific to eint.
If the wakeup eint(s) are level-triggered, the external device
would generate IRQ strom. In consequence, system would be looped
in handling low-level asm_IRQ stuff as resuming.
---
arch/arm/plat-s3c24xx/irq.c | 72 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 71 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index f0ed85c..e91748d 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -85,6 +85,9 @@ unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
unsigned long s3c_irqwake_intmask = 0xffffffffL;
unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
unsigned long s3c_irqwake_eintmask = 0xffffffffL;
+unsigned long s3c_irqresume_eintmask = 0x0L;
+
+static int s3c_get_irqext_type(unsigned int irq);
int
s3c_irq_wake(unsigned int irqno, unsigned int state)
@@ -109,6 +112,7 @@ static int
s3c_irqext_wake(unsigned int irqno, unsigned int state)
{
unsigned long bit = 1L << (irqno - EXTINT_OFF);
+ unsigned int eint_type;
if (!(s3c_irqwake_eintallow & bit))
return -ENOENT;
@@ -118,8 +122,14 @@ s3c_irqext_wake(unsigned int irqno, unsigned int state)
if (!state)
s3c_irqwake_eintmask |= bit;
- else
+ else{
s3c_irqwake_eintmask &= ~bit;
+ eint_type = s3c_get_irqext_type(irqno);
+
+ if (eint_type == IRQ_TYPE_LEVEL_LOW ||
+ eint_type == IRQ_TYPE_LEVEL_HIGH)
+ s3c_irqresume_eintmask |= bit;
+ }
return 0;
}
@@ -275,6 +285,66 @@ s3c_irqext_unmask(unsigned int irqno)
__raw_writel(mask, S3C24XX_EINTMASK);
}
+static int
+s3c_get_irqext_type(unsigned int irq)
+{
+ void __iomem *extint_reg;
+ unsigned long value, extint_offset;
+ unsigned int type;
+
+ if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
+ {
+ extint_reg = S3C24XX_EXTINT0;
+ extint_offset = (irq - IRQ_EINT0) * 4;
+ }
+ else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
+ {
+ extint_reg = S3C24XX_EXTINT0;
+ extint_offset = (irq - (EXTINT_OFF)) * 4;
+ }
+ else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
+ {
+ extint_reg = S3C24XX_EXTINT1;
+ extint_offset = (irq - IRQ_EINT8) * 4;
+ }
+ else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
+ {
+ extint_reg = S3C24XX_EXTINT2;
+ extint_offset = (irq - IRQ_EINT16) * 4;
+ } else
+ return -1;
+
+ value = __raw_readl(extint_reg);
+ value = ((value >> extint_offset) & 7);
+
+ switch (value) {
+ case S3C2410_EXTINT_RISEEDGE:
+ type = IRQ_TYPE_EDGE_RISING;
+ break;
+
+ case S3C2410_EXTINT_FALLEDGE:
+ type = IRQ_TYPE_EDGE_FALLING;
+ break;
+
+ case S3C2410_EXTINT_BOTHEDGE:
+ type = IRQ_TYPE_EDGE_BOTH;
+ break;
+
+ case S3C2410_EXTINT_LOWLEV:
+ type = IRQ_TYPE_LEVEL_LOW;
+ break;
+
+ case S3C2410_EXTINT_HILEV:
+ type = IRQ_TYPE_LEVEL_HIGH;
+ break;
+
+ default:
+ printk(KERN_ERR "Unknown IRQ_TYPE %d \n", type);
+ return -1;
+ }
+ return type;
+}
+
int
s3c_irqext_type(unsigned int irq, unsigned int type)
{
--
1.5.5.1