[ARM] 3836/1: S3C24XX: Clear both EINT and INT status before sleep
[pandora-kernel.git] / arch / arm / mach-s3c2410 / irq.c
index 6822dc7..9c7463b 100644 (file)
@@ -86,7 +86,7 @@ unsigned long s3c_irqwake_intmask     = 0xffffffffL;
 unsigned long s3c_irqwake_eintallow    = 0x0000fff0L;
 unsigned long s3c_irqwake_eintmask     = 0xffffffffL;
 
-static int
+int
 s3c_irq_wake(unsigned int irqno, unsigned int state)
 {
        unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
@@ -260,7 +260,7 @@ s3c_irqext_unmask(unsigned int irqno)
        s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 }
 
-static int
+int
 s3c_irqext_type(unsigned int irq, unsigned int type)
 {
        void __iomem *extint_reg;
@@ -586,6 +586,59 @@ s3c_irq_demux_extint(unsigned int irq,
        }
 }
 
+#ifdef CONFIG_PM
+
+static struct sleep_save irq_save[] = {
+       SAVE_ITEM(S3C2410_INTMSK),
+       SAVE_ITEM(S3C2410_INTSUBMSK),
+};
+
+/* the extint values move between the s3c2410/s3c2440 and the s3c2412
+ * so we use an array to hold them, and to calculate the address of
+ * the register at run-time
+*/
+
+static unsigned long save_extint[3];
+static unsigned long save_eintflt[4];
+static unsigned long save_eintmask;
+
+int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+               save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
+
+       for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+               save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
+
+       s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+       save_eintmask = __raw_readl(S3C24XX_EINTMASK);
+
+       return 0;
+}
+
+int s3c24xx_irq_resume(struct sys_device *dev)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+               __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
+
+       for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+               __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
+
+       s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+       __raw_writel(save_eintmask, S3C24XX_EINTMASK);
+
+       return 0;
+}
+
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
+
 /* s3c24xx_init_irq
  *
  * Initialise S3C2410 IRQ system