cleanup and make interrupt code more robust
authorFlorian Fainelli <florian@openwrt.org>
Thu, 6 Dec 2012 22:40:02 +0000 (22:40 +0000)
committerFlorian Fainelli <florian@openwrt.org>
Thu, 6 Dec 2012 22:40:02 +0000 (22:40 +0000)
Signed-off-by: Florian Fainelli <florian@openwrt.org>
SVN-Revision: 34552

target/linux/adm8668/files/arch/mips/adm8668/irq.c
target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/adm8668.h
target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/irq.h

index 9fa9e675e491d918bc973a0c01a778ac0058ef4f..62b7d2dc325290aae10fc32b04f72255d8f2f6ca 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
 /*
  * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
+ * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org>
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
 #include <asm/irq.h>
 #include <adm8668.h>
 
 #include <asm/irq.h>
 #include <adm8668.h>
 
+/* interrupt controller */
+#define IRQ_STATUS_REG         0x00    /* Read */
+#define IRQ_ENABLE_REG         0x08    /* Read/Write */
+#define IRQ_DISABLE_REG                0x0C    /* Write */
+
+#define IRQ_MASK               0xffff
+
+static inline void intc_write_reg(u32 val, unsigned int reg)
+{
+       void __iomem *base = (void __iomem *)KSEG1ADDR(ADM8668_INTC_BASE);
+
+       __raw_writel(val, base + reg);
+}
+
+static inline u32 intc_read_reg(unsigned int reg)
+{
+       void __iomem *base = (void __iomem *)KSEG1ADDR(ADM8668_INTC_BASE);
+
+       return __raw_readl(base + reg);
+}
+
 static void adm8668_irq_cascade(void)
 {
 static void adm8668_irq_cascade(void)
 {
-       int i;
-       unsigned long intsrc;
+       int irq;
+       u32 intsrc;
 
 
-       intsrc = ADM8668_INTC_REG(IRQ_STATUS_REG) & IRQ_MASK;
-       for (i = 0; intsrc; intsrc >>= 1, i++)
-               if (intsrc & 0x1)
-                       do_IRQ(i);
+       intsrc = intc_read_reg(IRQ_STATUS_REG) & IRQ_MASK;
+       if (intsrc) {
+               irq = fls(intsrc) - 1;
+               do_IRQ(irq);
+       } else
+               spurious_interrupt();
 }
 
 /*
 }
 
 /*
@@ -43,8 +67,10 @@ void plat_irq_dispatch(void)
        /* timer interrupt, that we renumbered */
        if (pending & STATUSF_IP7)
                do_IRQ(MIPS_CPU_IRQ_BASE + 7);
        /* timer interrupt, that we renumbered */
        if (pending & STATUSF_IP7)
                do_IRQ(MIPS_CPU_IRQ_BASE + 7);
-       if (pending & STATUSF_IP2)
+       else if (pending & STATUSF_IP2)
                adm8668_irq_cascade();
                adm8668_irq_cascade();
+       else
+               spurious_interrupt();
 }
 
 /*
 }
 
 /*
@@ -52,13 +78,13 @@ void plat_irq_dispatch(void)
  */
 static void enable_adm8668_irq(struct irq_data *d)
 {
  */
 static void enable_adm8668_irq(struct irq_data *d)
 {
-       ADM8668_INTC_REG(IRQ_ENABLE_REG) = (1 << d->irq);
+       intc_write_reg((1 << d->irq), IRQ_ENABLE_REG);
 }
 
 
 static void ack_adm8668_irq(struct irq_data *d)
 {
 }
 
 
 static void ack_adm8668_irq(struct irq_data *d)
 {
-       ADM8668_INTC_REG(IRQ_DISABLE_REG) = (1 << d->irq);
+       intc_write_reg((1 << d->irq), IRQ_DISABLE_REG);
 }
 
 /*
 }
 
 /*
@@ -79,6 +105,9 @@ static void __init init_adm8668_irqs(void)
 {
        int i;
 
 {
        int i;
 
+       /* disable all interrupts for the moment */
+       intc_write_reg(IRQ_MASK, IRQ_DISABLE_REG);
+
        for (i = 0; i <= INT_LVL_MAX; i++)
                irq_set_chip_and_handler(i, &adm8668_irq_type,
                        handle_level_irq);
        for (i = 0; i <= INT_LVL_MAX; i++)
                irq_set_chip_and_handler(i, &adm8668_irq_type,
                        handle_level_irq);
index bb4466c522add65eb6242e7a9fdf567efb98495d..250447bbf3574f688f378996b8e8248e53ca6a39 100644 (file)
 /** onboard uart **/
 #define ADM8668_UARTCLK_FREQ   62500000
 
 /** onboard uart **/
 #define ADM8668_UARTCLK_FREQ   62500000
 
-/* interrupt controller */
-#define IRQ_STATUS_REG         0x00    /* Read */
-#define IRQ_ENABLE_REG         0x08    /* Read/Write */
-#define IRQ_DISABLE_REG                0x0C    /* Write */
-
 /* interrupt levels */
 #define INT_LVL_SWI            1
 #define INT_LVL_COMMS_RX       2
 /* interrupt levels */
 #define INT_LVL_SWI            1
 #define INT_LVL_COMMS_RX       2
@@ -56,8 +51,6 @@
 #define INT_LVL_MAX            INT_LVL_USB
 
 /* register access macros */
 #define INT_LVL_MAX            INT_LVL_USB
 
 /* register access macros */
-#define ADM8668_INTC_REG(_reg) \
-       (*((volatile unsigned long *)(KSEG1ADDR(ADM8668_INTC_BASE + (_reg)))))
 #define ADM8668_LAN_REG(_reg)          \
        (*((volatile unsigned int *)(KSEG1ADDR(ADM8668_LAN_BASE + (_reg)))))
 #define ADM8668_WAN_REG(_reg)          \
 #define ADM8668_LAN_REG(_reg)          \
        (*((volatile unsigned int *)(KSEG1ADDR(ADM8668_LAN_BASE + (_reg)))))
 #define ADM8668_WAN_REG(_reg)          \
index 1341309f2bb0f2f8e65ce3dbf9c5bb65e76285fd..ea859f03af4e3aaa4f6bfaa51728eb2eec7b1bb3 100644 (file)
@@ -8,9 +8,7 @@
 #ifndef __ASM_MACH_ADM8668_IRQ_H
 #define __ASM_MACH_ADM8668_IRQ_H
 
 #ifndef __ASM_MACH_ADM8668_IRQ_H
 #define __ASM_MACH_ADM8668_IRQ_H
 
-#define        NR_IRQS 32
+#define        NR_IRQS                 32
 #define        MIPS_CPU_IRQ_BASE       16
 
 #define        MIPS_CPU_IRQ_BASE       16
 
-#define IRQ_MASK               0xffff
-
 #endif /* __ASM_MACH_ADM8668_IRQ_H */
 #endif /* __ASM_MACH_ADM8668_IRQ_H */