]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/mach-pxa/viper.c
Merge branch 'core-v28-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-omap-h63xx.git] / arch / arm / mach-pxa / viper.c
index d7632f63603c2967f2098a4df5d0792249603631..4b3120dbc049946b75f05b94b8f6479ca40ecdd9 100644 (file)
@@ -204,25 +204,54 @@ static void viper_set_core_cpu_voltage(unsigned long khz, int force)
 
 /* Interrupt handling */
 static unsigned long viper_irq_enabled_mask;
+static const int viper_isa_irqs[] = { 3, 4, 5, 6, 7, 10, 11, 12, 9, 14, 15 };
+static const int viper_isa_irq_map[] = {
+       0,              /* ISA irq #0, invalid */
+       0,              /* ISA irq #1, invalid */
+       0,              /* ISA irq #2, invalid */
+       1 << 0,         /* ISA irq #3 */
+       1 << 1,         /* ISA irq #4 */
+       1 << 2,         /* ISA irq #5 */
+       1 << 3,         /* ISA irq #6 */
+       1 << 4,         /* ISA irq #7 */
+       0,              /* ISA irq #8, invalid */
+       1 << 8,         /* ISA irq #9 */
+       1 << 5,         /* ISA irq #10 */
+       1 << 6,         /* ISA irq #11 */
+       1 << 7,         /* ISA irq #12 */
+       0,              /* ISA irq #13, invalid */
+       1 << 9,         /* ISA irq #14 */
+       1 << 10,        /* ISA irq #15 */
+};
+
+static inline int viper_irq_to_bitmask(unsigned int irq)
+{
+       return viper_isa_irq_map[irq - PXA_ISA_IRQ(0)];
+}
+
+static inline int viper_bit_to_irq(int bit)
+{
+       return viper_isa_irqs[bit] + PXA_ISA_IRQ(0);
+}
 
 static void viper_ack_irq(unsigned int irq)
 {
-       int viper_irq = irq - PXA_ISA_IRQ(0);
+       int viper_irq = viper_irq_to_bitmask(irq);
 
-       if (viper_irq < 8)
-               VIPER_LO_IRQ_STATUS = 1 << viper_irq;
+       if (viper_irq & 0xff)
+               VIPER_LO_IRQ_STATUS = viper_irq;
        else
-               VIPER_HI_IRQ_STATUS = 1 << (viper_irq - 8);
+               VIPER_HI_IRQ_STATUS = (viper_irq >> 8);
 }
 
 static void viper_mask_irq(unsigned int irq)
 {
-       viper_irq_enabled_mask &= ~(1 << (irq - PXA_ISA_IRQ(0)));
+       viper_irq_enabled_mask &= ~(viper_irq_to_bitmask(irq));
 }
 
 static void viper_unmask_irq(unsigned int irq)
 {
-       viper_irq_enabled_mask |= (1 << (irq - PXA_ISA_IRQ(0)));
+       viper_irq_enabled_mask |= viper_irq_to_bitmask(irq);
 }
 
 static inline unsigned long viper_irq_pending(void)
@@ -237,8 +266,12 @@ static void viper_irq_handler(unsigned int irq, struct irq_desc *desc)
 
        pending = viper_irq_pending();
        do {
+               /* we're in a chained irq handler,
+                * so ack the interrupt by hand */
+               GEDR(VIPER_CPLD_GPIO) = GPIO_bit(VIPER_CPLD_GPIO);
+
                if (likely(pending)) {
-                       irq = PXA_ISA_IRQ(0) + __ffs(pending);
+                       irq = viper_bit_to_irq(__ffs(pending));
                        generic_handle_irq(irq);
                }
                pending = viper_irq_pending();
@@ -254,15 +287,14 @@ static struct irq_chip viper_irq_chip = {
 
 static void __init viper_init_irq(void)
 {
-       const int isa_irqs[] = { 3, 4, 5, 6, 7, 10, 11, 12, 9, 14, 15 };
-       int irq;
+       int level;
        int isa_irq;
 
        pxa25x_init_irq();
 
        /* setup ISA IRQs */
-       for (irq = 0; irq < ARRAY_SIZE(isa_irqs); irq++) {
-               isa_irq = isa_irqs[irq];
+       for (level = 0; level < ARRAY_SIZE(viper_isa_irqs); level++) {
+               isa_irq = viper_bit_to_irq(level);
                set_irq_chip(isa_irq, &viper_irq_chip);
                set_irq_handler(isa_irq, handle_edge_irq);
                set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE);