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

Reply via email to