X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=arch%2Fmips%2Fmips-boards%2Fatlas%2Fatlas_int.c;h=fb25e0377f11b3097d9dc46b1151083dac590eee;hb=58a3bb59973e33a428d72fa530a3d1d81feb0e8f;hp=9dd6b89255818ddbf22fbcc86e4f294b834c1499;hpb=4d3ce21fa9d2eaeda113aa2f9c2da80d972bef64;p=pandora-kernel.git diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c index 9dd6b8925581..dfa0acbd7fc2 100644 --- a/arch/mips/mips-boards/atlas/atlas_int.c +++ b/arch/mips/mips-boards/atlas/atlas_int.c @@ -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 + * Maciej W. Rozycki * * ######################################################################## * @@ -25,17 +27,21 @@ */ #include #include +#include #include #include #include #include +#include -#include +#include #include +#include +#include + #include #include -#include - +#include static struct atlas_ictrl_regs *atlas_hw0_icregs; @@ -47,39 +53,29 @@ 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(); } -static unsigned int startup_atlas_irq(unsigned int irq) -{ - enable_atlas_irq(irq); - return 0; /* never anything pending */ -} - -#define shutdown_atlas_irq disable_atlas_irq - -#define mask_and_ack_atlas_irq disable_atlas_irq - static void end_atlas_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) enable_atlas_irq(irq); } -static struct hw_interrupt_type atlas_irq_type = { - .typename = "Atlas", - .startup = startup_atlas_irq, - .shutdown = shutdown_atlas_irq, - .enable = enable_atlas_irq, - .disable = disable_atlas_irq, - .ack = mask_and_ack_atlas_irq, +static struct irq_chip atlas_irq_type = { + .name = "Atlas", + .ack = disable_atlas_irq, + .mask = disable_atlas_irq, + .mask_ack = disable_atlas_irq, + .unmask = enable_atlas_irq, + .eoi = enable_atlas_irq, .end = end_atlas_irq, }; @@ -96,7 +92,7 @@ static inline int ls1bit32(unsigned int x) return b; } -static inline void atlas_hw0_irqdispatch(struct pt_regs *regs) +static inline void atlas_hw0_irqdispatch(void) { unsigned long int_status; int irq; @@ -107,11 +103,11 @@ 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); - do_IRQ(irq, regs); + do_IRQ(irq); } static inline int clz(unsigned long x) @@ -161,15 +157,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,12 +174,12 @@ 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. */ -asmlinkage void plat_irq_dispatch(struct pt_regs *regs) +asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; int irq; @@ -192,18 +187,20 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs) irq = irq_ffs(pending); if (irq == MIPSCPU_INT_ATLAS) - atlas_hw0_irqdispatch(regs); - else if (irq > 0) - do_IRQ(MIPSCPU_INT_BASE + irq, regs); + atlas_hw0_irqdispatch(); + else if (irq >= 0) + do_IRQ(MIPSCPU_INT_BASE + irq); else - spurious_interrupt(regs); + spurious_interrupt(); } -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,11 +208,65 @@ void __init arch_init_irq(void) */ atlas_hw0_icregs->intrsten = 0xffffffff; - for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &atlas_irq_type; - spin_lock_init(&irq_desc[i].lock); + for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) + set_irq_chip_and_handler(i, &atlas_irq_type, handle_level_irq); +} + +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 = ARRAY_SIZE(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 = ARRAY_SIZE(msc_eicirqmap); + +void __init arch_init_irq(void) +{ + init_atlas_irqs(ATLAS_INT_BASE); + + if (!cpu_has_veic) + mips_cpu_irq_init(); + + 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); }