[MIPS] Atlas: update interrupt handling
authorMaciej W. Rozycki <macro@mips.com>
Tue, 12 Sep 2006 18:12:18 +0000 (19:12 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 27 Sep 2006 12:37:42 +0000 (13:37 +0100)
The following change updates the Atlas interrupt handling to match that
of Malta.  Tested with a 5Kc and a 34Kf successfully.

Signed-off-by: Maciej W. Rozycki <macro@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/mips-boards/atlas/atlas_int.c
arch/mips/mips-boards/atlas/atlas_setup.c
arch/mips/mips-boards/generic/time.c
arch/mips/pci/fixup-atlas.c
include/asm-mips/mach-atlas/mc146818rtc.h
include/asm-mips/mips-boards/atlasint.h

index fb25e03..a020a3c 100644 (file)
@@ -1,6 +1,8 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2000, 2006  MIPS Technologies, Inc.
+ *     All rights reserved.
+ *     Authors: Carsten Langgaard <carstenl@mips.com>
+ *              Maciej W. Rozycki <macro@mips.com>
  *
  * ########################################################################
  *
  */
 #include <linux/compiler.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 
-#include <asm/irq.h>
+#include <asm/gdb-stub.h>
 #include <asm/io.h>
+#include <asm/irq_cpu.h>
+#include <asm/msc01_ic.h>
+
 #include <asm/mips-boards/atlas.h>
 #include <asm/mips-boards/atlasint.h>
-#include <asm/gdb-stub.h>
-
+#include <asm/mips-boards/generic.h>
 
 static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
@@ -47,13 +52,13 @@ static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
 void disable_atlas_irq(unsigned int irq_nr)
 {
-       atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE));
+       atlas_hw0_icregs->intrsten = 1 << (irq_nr - ATLAS_INT_BASE);
        iob();
 }
 
 void enable_atlas_irq(unsigned int irq_nr)
 {
-       atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE));
+       atlas_hw0_icregs->intseten = 1 << (irq_nr - ATLAS_INT_BASE);
        iob();
 }
 
@@ -107,7 +112,7 @@ static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
        if (unlikely(int_status == 0))
                return;
 
-       irq = ATLASINT_BASE + ls1bit32(int_status);
+       irq = ATLAS_INT_BASE + ls1bit32(int_status);
 
        DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
 
@@ -161,15 +166,14 @@ static inline unsigned int irq_ffs(unsigned int pending)
 }
 
 /*
- * IRQs on the Atlas board look basically (barring software IRQs which we
- * don't use at all and all external interrupt sources are combined together
- * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ * IRQs on the Atlas board look basically like (all external interrupt
+ * sources are combined together on hardware interrupt 0 (MIPS IRQ 2)):
  *
- *     MIPS IRQ        Source
+ *      MIPS IRQ        Source
  *      --------        ------
- *             0       Software (ignored)
- *             1        Software (ignored)
- *             2        Combined hardware interrupt (hw0)
+ *             0        Software 0 (reschedule IPI on MT)
+ *             1        Software 1 (remote call IPI on MT)
+ *             2        Combined Atlas hardware interrupt (hw0)
  *             3        Hardware (ignored)
  *             4        Hardware (ignored)
  *             5        Hardware (ignored)
@@ -179,7 +183,7 @@ static inline unsigned int irq_ffs(unsigned int pending)
  * We handle the IRQ according to _our_ priority which is:
  *
  * Highest ----     R4k Timer
- * Lowest  ----     Combined hardware interrupt
+ * Lowest  ----     Software 0
  *
  * then we just return, if multiple IRQs are pending then we will just take
  * another exception, big deal.
@@ -193,17 +197,19 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 
        if (irq == MIPSCPU_INT_ATLAS)
                atlas_hw0_irqdispatch(regs);
-       else if (irq > 0)
+       else if (irq >= 0)
                do_IRQ(MIPSCPU_INT_BASE + irq, regs);
        else
                spurious_interrupt(regs);
 }
 
-void __init arch_init_irq(void)
+static inline void init_atlas_irqs (int base)
 {
        int i;
 
-       atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *));
+       atlas_hw0_icregs = (struct atlas_ictrl_regs *)
+                          ioremap(ATLAS_ICTRL_REGS_BASE,
+                                  sizeof(struct atlas_ictrl_regs *));
 
        /*
         * Mask out all interrupt by writing "1" to all bit position in
@@ -211,7 +217,7 @@ void __init arch_init_irq(void)
         */
        atlas_hw0_icregs->intrsten = 0xffffffff;
 
-       for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
+       for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) {
                irq_desc[i].status      = IRQ_DISABLED;
                irq_desc[i].action      = 0;
                irq_desc[i].depth       = 1;
@@ -219,3 +225,62 @@ void __init arch_init_irq(void)
                spin_lock_init(&irq_desc[i].lock);
        }
 }
+
+static struct irqaction atlasirq = {
+       .handler = no_action,
+       .name = "Atlas cascade"
+};
+
+msc_irqmap_t __initdata msc_irqmap[] = {
+       {MSC01C_INT_TMR,                MSC01_IRQ_EDGE, 0},
+       {MSC01C_INT_PCI,                MSC01_IRQ_LEVEL, 0},
+};
+int __initdata msc_nr_irqs = sizeof(msc_irqmap) / sizeof(*msc_irqmap);
+
+msc_irqmap_t __initdata msc_eicirqmap[] = {
+       {MSC01E_INT_SW0,                MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_SW1,                MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_ATLAS,              MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_TMR,                MSC01_IRQ_EDGE, 0},
+       {MSC01E_INT_PCI,                MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_PERFCTR,            MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_CPUCTR,             MSC01_IRQ_LEVEL, 0}
+};
+int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap) / sizeof(*msc_eicirqmap);
+
+void __init arch_init_irq(void)
+{
+       init_atlas_irqs(ATLAS_INT_BASE);
+
+       if (!cpu_has_veic)
+               mips_cpu_irq_init(MIPSCPU_INT_BASE);
+
+       switch(mips_revision_corid) {
+       case MIPS_REVISION_CORID_CORE_MSC:
+       case MIPS_REVISION_CORID_CORE_FPGA2:
+       case MIPS_REVISION_CORID_CORE_FPGA3:
+       case MIPS_REVISION_CORID_CORE_24K:
+       case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+               if (cpu_has_veic)
+                       init_msc_irqs (MSC01E_INT_BASE,
+                                      msc_eicirqmap, msc_nr_eicirqs);
+               else
+                       init_msc_irqs (MSC01C_INT_BASE,
+                                      msc_irqmap, msc_nr_irqs);
+       }
+
+
+       if (cpu_has_veic) {
+               set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch);
+               setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq);
+       } else if (cpu_has_vint) {
+               set_vi_handler (MIPSCPU_INT_ATLAS, atlas_hw0_irqdispatch);
+#ifdef CONFIG_MIPS_MT_SMTC
+               setup_irq_smtc (MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS,
+                               &atlasirq, (0x100 << MIPSCPU_INT_ATLAS));
+#else /* Not SMTC */
+               setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+#endif /* CONFIG_MIPS_MT_SMTC */
+       } else
+               setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+}
index 9871a91..0c6b0ce 100644 (file)
@@ -77,7 +77,7 @@ static void __init serial_init(void)
 #else
        s.iobase = ATLAS_UART_REGS_BASE+3;
 #endif
-       s.irq = ATLASINT_UART;
+       s.irq = ATLAS_INT_UART;
        s.uartclk = ATLAS_BASE_BAUD * 16;
        s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ;
        s.iotype = UPIO_PORT;
index de5798e..8d15861 100644 (file)
 
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
+
+#ifdef CONFIG_MIPS_ATLAS
+#include <asm/mips-boards/atlasint.h>
+#endif
+#ifdef CONFIG_MIPS_MALTA
 #include <asm/mips-boards/maltaint.h>
-#include <asm/mc146818-time.h>
+#endif
 
 unsigned long cpu_khz;
 
index 439510a..c6cd6e9 100644 (file)
 
 #include <asm/mips-boards/atlasint.h>
 
-#define PCIA           ATLASINT_PCIA
-#define PCIB           ATLASINT_PCIB
-#define PCIC           ATLASINT_PCIC
-#define PCID           ATLASINT_PCID
-#define INTA           ATLASINT_INTA
-#define INTB           ATLASINT_INTB
-#define ETH            ATLASINT_ETH
-#define INTC           ATLASINT_INTC
-#define SCSI           ATLASINT_SCSI
-#define INTD           ATLASINT_INTD
+#define PCIA           ATLAS_INT_PCIA
+#define PCIB           ATLAS_INT_PCIB
+#define PCIC           ATLAS_INT_PCIC
+#define PCID           ATLAS_INT_PCID
+#define INTA           ATLAS_INT_INTA
+#define INTB           ATLAS_INT_INTB
+#define ETH            ATLAS_INT_ETH
+#define INTC           ATLAS_INT_INTC
+#define SCSI           ATLAS_INT_SCSI
+#define INTD           ATLAS_INT_INTD
 
 static char irq_tab[][5] __initdata = {
        /*      INTA    INTB    INTC    INTD */
index fc09928..a73a569 100644 (file)
@@ -33,7 +33,7 @@
 #define RTC_PORT(x)    (ATLAS_RTC_ADR_REG + (x) * 8)
 #define RTC_IO_EXTENT  0x100
 #define RTC_IOMAPPED   0
-#define RTC_IRQ                ATLASINT_RTC
+#define RTC_IRQ                ATLAS_INT_RTC
 
 static inline unsigned char CMOS_READ(unsigned long addr)
 {
index fd7ebc5..b15e4ea 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2006  MIPS Technologies, Inc.  All rights reserved.
+ *     Authors: Carsten Langgaard <carstenl@mips.com>
+ *              Maciej W. Rozycki <macro@mips.com>
  *
  * ########################################################################
  *
 #ifndef _MIPS_ATLASINT_H
 #define _MIPS_ATLASINT_H
 
-#define ATLASINT_BASE          1
-#define ATLASINT_UART          (ATLASINT_BASE+0)
-#define ATLASINT_TIM0          (ATLASINT_BASE+1)
-#define ATLASINT_RES2          (ATLASINT_BASE+2)
-#define ATLASINT_RES3          (ATLASINT_BASE+3)
-#define ATLASINT_RTC           (ATLASINT_BASE+4)
-#define ATLASINT_COREHI                (ATLASINT_BASE+5)
-#define ATLASINT_CORELO                (ATLASINT_BASE+6)
-#define ATLASINT_RES7          (ATLASINT_BASE+7)
-#define ATLASINT_PCIA          (ATLASINT_BASE+8)
-#define ATLASINT_PCIB          (ATLASINT_BASE+9)
-#define ATLASINT_PCIC          (ATLASINT_BASE+10)
-#define ATLASINT_PCID          (ATLASINT_BASE+11)
-#define ATLASINT_ENUM          (ATLASINT_BASE+12)
-#define ATLASINT_DEG           (ATLASINT_BASE+13)
-#define ATLASINT_ATXFAIL       (ATLASINT_BASE+14)
-#define ATLASINT_INTA          (ATLASINT_BASE+15)
-#define ATLASINT_INTB          (ATLASINT_BASE+16)
-#define ATLASINT_ETH           ATLASINT_INTB
-#define ATLASINT_INTC          (ATLASINT_BASE+17)
-#define ATLASINT_SCSI          ATLASINT_INTC
-#define ATLASINT_INTD          (ATLASINT_BASE+18)
-#define ATLASINT_SERR          (ATLASINT_BASE+19)
-#define ATLASINT_RES20         (ATLASINT_BASE+20)
-#define ATLASINT_RES21         (ATLASINT_BASE+21)
-#define ATLASINT_RES22         (ATLASINT_BASE+22)
-#define ATLASINT_RES23         (ATLASINT_BASE+23)
-#define ATLASINT_RES24         (ATLASINT_BASE+24)
-#define ATLASINT_RES25         (ATLASINT_BASE+25)
-#define ATLASINT_RES26         (ATLASINT_BASE+26)
-#define ATLASINT_RES27         (ATLASINT_BASE+27)
-#define ATLASINT_RES28         (ATLASINT_BASE+28)
-#define ATLASINT_RES29         (ATLASINT_BASE+29)
-#define ATLASINT_RES30         (ATLASINT_BASE+30)
-#define ATLASINT_RES31         (ATLASINT_BASE+31)
-#define ATLASINT_END           (ATLASINT_BASE+31)
+/*
+ * Interrupts 0..7 are used for Atlas CPU interrupts (nonEIC mode)
+ */
+#define MIPSCPU_INT_BASE       0
+
+/* CPU interrupt offsets */
+#define MIPSCPU_INT_SW0                0
+#define MIPSCPU_INT_SW1                1
+#define MIPSCPU_INT_MB0                2
+#define MIPSCPU_INT_ATLAS      MIPSCPU_INT_MB0
+#define MIPSCPU_INT_MB1                3
+#define MIPSCPU_INT_MB2                4
+#define MIPSCPU_INT_MB3                5
+#define MIPSCPU_INT_MB4                6
+#define MIPSCPU_INT_CPUCTR     7
+
+/*
+ * Interrupts 8..39 are used for Atlas interrupt controller interrupts
+ */
+#define ATLAS_INT_BASE         8
+#define ATLAS_INT_UART         (ATLAS_INT_BASE + 0)
+#define ATLAS_INT_TIM0         (ATLAS_INT_BASE + 1)
+#define ATLAS_INT_RES2         (ATLAS_INT_BASE + 2)
+#define ATLAS_INT_RES3         (ATLAS_INT_BASE + 3)
+#define ATLAS_INT_RTC          (ATLAS_INT_BASE + 4)
+#define ATLAS_INT_COREHI       (ATLAS_INT_BASE + 5)
+#define ATLAS_INT_CORELO       (ATLAS_INT_BASE + 6)
+#define ATLAS_INT_RES7         (ATLAS_INT_BASE + 7)
+#define ATLAS_INT_PCIA         (ATLAS_INT_BASE + 8)
+#define ATLAS_INT_PCIB         (ATLAS_INT_BASE + 9)
+#define ATLAS_INT_PCIC         (ATLAS_INT_BASE + 10)
+#define ATLAS_INT_PCID         (ATLAS_INT_BASE + 11)
+#define ATLAS_INT_ENUM         (ATLAS_INT_BASE + 12)
+#define ATLAS_INT_DEG          (ATLAS_INT_BASE + 13)
+#define ATLAS_INT_ATXFAIL      (ATLAS_INT_BASE + 14)
+#define ATLAS_INT_INTA         (ATLAS_INT_BASE + 15)
+#define ATLAS_INT_INTB         (ATLAS_INT_BASE + 16)
+#define ATLAS_INT_ETH          ATLAS_INT_INTB
+#define ATLAS_INT_INTC         (ATLAS_INT_BASE + 17)
+#define ATLAS_INT_SCSI         ATLAS_INT_INTC
+#define ATLAS_INT_INTD         (ATLAS_INT_BASE + 18)
+#define ATLAS_INT_SERR         (ATLAS_INT_BASE + 19)
+#define ATLAS_INT_RES20                (ATLAS_INT_BASE + 20)
+#define ATLAS_INT_RES21                (ATLAS_INT_BASE + 21)
+#define ATLAS_INT_RES22                (ATLAS_INT_BASE + 22)
+#define ATLAS_INT_RES23                (ATLAS_INT_BASE + 23)
+#define ATLAS_INT_RES24                (ATLAS_INT_BASE + 24)
+#define ATLAS_INT_RES25                (ATLAS_INT_BASE + 25)
+#define ATLAS_INT_RES26                (ATLAS_INT_BASE + 26)
+#define ATLAS_INT_RES27                (ATLAS_INT_BASE + 27)
+#define ATLAS_INT_RES28                (ATLAS_INT_BASE + 28)
+#define ATLAS_INT_RES29                (ATLAS_INT_BASE + 29)
+#define ATLAS_INT_RES30                (ATLAS_INT_BASE + 30)
+#define ATLAS_INT_RES31                (ATLAS_INT_BASE + 31)
+#define ATLAS_INT_END          (ATLAS_INT_BASE + 31)
+
+/*
+ * Interrupts 64..127 are used for Soc-it Classic interrupts
+ */
+#define MSC01C_INT_BASE                64
+
+/* SOC-it Classic interrupt offsets */
+#define MSC01C_INT_TMR         0
+#define MSC01C_INT_PCI         1
+
+/*
+ * Interrupts 64..127 are used for Soc-it EIC interrupts
+ */
+#define MSC01E_INT_BASE                64
+
+/* SOC-it EIC interrupt offsets */
+#define        MSC01E_INT_SW0          1
+#define        MSC01E_INT_SW1          2
+#define        MSC01E_INT_MB0          3
+#define        MSC01E_INT_ATLAS        MSC01E_INT_MB0
+#define        MSC01E_INT_MB1          4
+#define        MSC01E_INT_MB2          5
+#define        MSC01E_INT_MB3          6
+#define        MSC01E_INT_MB4          7
+#define        MSC01E_INT_TMR          8
+#define        MSC01E_INT_PCI          9
+#define        MSC01E_INT_PERFCTR      10
+#define        MSC01E_INT_CPUCTR       11
 
 #endif /* !(_MIPS_ATLASINT_H) */