[Blackfin] arch: hook up set_irq_wake in Blackfin's irq code

 - Add support for irq_wake on system and gpio interrupts
 - Remove outdated kernel options
 - Add option to select default PM mode
 - Fix various places where SIC_IWRx was only handled partially

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>

diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 166dbba..81d0018 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -1,5 +1,5 @@
 /*
- * File:         arch/blackfin/mach-common/ints-priority-sc.c
+ * File:         arch/blackfin/mach-common/ints-priority.c
  * Based on:
  * Author:
  *
@@ -13,7 +13,7 @@
  *               2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
  *               2003 Metrowerks/Motorola
  *               2003 Bas Vermeulen <bas@buyways.nl>
- *               Copyright 2004-2007 Analog Devices Inc.
+ *               Copyright 2004-2008 Analog Devices Inc.
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
@@ -69,6 +69,10 @@
 /* The number of spurious interrupts */
 atomic_t num_spurious;
 
+#ifdef CONFIG_PM
+unsigned long bfin_sic_iwr[3];	/* Up to 3 SIC_IWRx registers */
+#endif
+
 struct ivgx {
 	/* irq number for request_irq, available in mach-bf533/irq.h */
 	unsigned int irqno;
@@ -178,6 +182,27 @@
 	SSYNC();
 }
 
+#ifdef CONFIG_PM
+int bfin_internal_set_wake(unsigned int irq, unsigned int state)
+{
+	unsigned bank, bit;
+	unsigned long flags;
+	bank = (irq - (IRQ_CORETMR + 1)) / 32;
+	bit = (irq - (IRQ_CORETMR + 1)) % 32;
+
+	local_irq_save(flags);
+
+	if (state)
+		bfin_sic_iwr[bank] |= (1 << bit);
+	else
+		bfin_sic_iwr[bank] &= ~(1 << bit);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+#endif
+
 static struct irq_chip bfin_core_irqchip = {
 	.ack = ack_noop,
 	.mask = bfin_core_mask_irq,
@@ -188,6 +213,9 @@
 	.ack = ack_noop,
 	.mask = bfin_internal_mask_irq,
 	.unmask = bfin_internal_unmask_irq,
+#ifdef CONFIG_PM
+	.set_wake = bfin_internal_set_wake,
+#endif
 };
 
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
@@ -434,6 +462,20 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+{
+	unsigned gpio = irq_to_gpio(irq);
+
+	if (state)
+		gpio_pm_wakeup_request(gpio, PM_WAKE_IGNORE);
+	else
+		gpio_pm_wakeup_free(gpio);
+
+	return 0;
+}
+#endif
+
 static struct irq_chip bfin_gpio_irqchip = {
 	.ack = bfin_gpio_ack_irq,
 	.mask = bfin_gpio_mask_irq,
@@ -441,7 +483,10 @@
 	.unmask = bfin_gpio_unmask_irq,
 	.set_type = bfin_gpio_irq_type,
 	.startup = bfin_gpio_irq_startup,
-	.shutdown = bfin_gpio_irq_shutdown
+	.shutdown = bfin_gpio_irq_shutdown,
+#ifdef CONFIG_PM
+	.set_wake = bfin_gpio_set_wake,
+#endif
 };
 
 static void bfin_demux_gpio_irq(unsigned int inta_irq,
@@ -487,7 +532,7 @@
 	}
 
 	if (search) {
-		for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) {
+		for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
 			irq += i;
 
 			mask = get_gpiop_data(i) &
@@ -763,6 +808,74 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+u32 pint_saved_masks[NR_PINT_SYS_IRQS];
+u32 pint_wakeup_masks[NR_PINT_SYS_IRQS];
+
+int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+{
+	u32 pint_irq;
+	u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 bank = PINT_2_BANK(pint_val);
+	u32 pintbit = PINT_BIT(pint_val);
+
+	switch (bank) {
+	case 0:
+		pint_irq = IRQ_PINT0;
+		break;
+	case 2:
+		pint_irq = IRQ_PINT2;
+		break;
+	case 3:
+		pint_irq = IRQ_PINT3;
+		break;
+	case 1:
+		pint_irq = IRQ_PINT1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	bfin_internal_set_wake(pint_irq, state);
+
+	if (state)
+		pint_wakeup_masks[bank] |= pintbit;
+	else
+		pint_wakeup_masks[bank] &= ~pintbit;
+
+	return 0;
+}
+
+u32 bfin_pm_setup(void)
+{
+	u32 val, i;
+
+	for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
+		val = pint[i]->mask_clear;
+		pint_saved_masks[i] = val;
+		if (val ^ pint_wakeup_masks[i]) {
+			pint[i]->mask_clear = val;
+			pint[i]->mask_set = pint_wakeup_masks[i];
+		}
+	}
+
+	return 0;
+}
+
+void bfin_pm_restore(void)
+{
+	u32 i, val;
+
+	for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
+		val = pint_saved_masks[i];
+		if (val ^ pint_wakeup_masks[i]) {
+			pint[i]->mask_clear = pint[i]->mask_clear;
+			pint[i]->mask_set = val;
+		}
+	}
+}
+#endif
+
 static struct irq_chip bfin_gpio_irqchip = {
 	.ack = bfin_gpio_ack_irq,
 	.mask = bfin_gpio_mask_irq,
@@ -770,7 +883,10 @@
 	.unmask = bfin_gpio_unmask_irq,
 	.set_type = bfin_gpio_irq_type,
 	.startup = bfin_gpio_irq_startup,
-	.shutdown = bfin_gpio_irq_shutdown
+	.shutdown = bfin_gpio_irq_shutdown,
+#ifdef CONFIG_PM
+	.set_wake = bfin_gpio_set_wake,
+#endif
 };
 
 static void bfin_demux_gpio_irq(unsigned int inta_irq,