xref: /linux/arch/mips/sgi-ip22/ip22-int.c (revision d1bef4ed5faf7d9872337b33c4269e45ae1bf960)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * ip22-int.c: Routines for generic manipulation of the INT[23] ASIC
31da177e4SLinus Torvalds  *             found on INDY and Indigo2 workstations.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
61da177e4SLinus Torvalds  * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
71da177e4SLinus Torvalds  * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu)
81da177e4SLinus Torvalds  *                    - Indigo2 changes
91da177e4SLinus Torvalds  *                    - Interrupt handling fixes
101da177e4SLinus Torvalds  * Copyright (C) 2001, 2003 Ladislav Michl (ladis@linux-mips.org)
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds #include <linux/config.h>
131da177e4SLinus Torvalds #include <linux/types.h>
141da177e4SLinus Torvalds #include <linux/init.h>
151da177e4SLinus Torvalds #include <linux/kernel_stat.h>
161da177e4SLinus Torvalds #include <linux/signal.h>
171da177e4SLinus Torvalds #include <linux/sched.h>
181da177e4SLinus Torvalds #include <linux/interrupt.h>
191da177e4SLinus Torvalds #include <linux/irq.h>
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds #include <asm/mipsregs.h>
221da177e4SLinus Torvalds #include <asm/addrspace.h>
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds #include <asm/sgi/ioc.h>
251da177e4SLinus Torvalds #include <asm/sgi/hpc3.h>
261da177e4SLinus Torvalds #include <asm/sgi/ip22.h>
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds /* #define DEBUG_SGINT */
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds /* So far nothing hangs here */
311da177e4SLinus Torvalds #undef USE_LIO3_IRQ
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds struct sgint_regs *sgint;
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds static char lc0msk_to_irqnr[256];
361da177e4SLinus Torvalds static char lc1msk_to_irqnr[256];
371da177e4SLinus Torvalds static char lc2msk_to_irqnr[256];
381da177e4SLinus Torvalds static char lc3msk_to_irqnr[256];
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds extern int ip22_eisa_init(void);
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds static void enable_local0_irq(unsigned int irq)
431da177e4SLinus Torvalds {
441da177e4SLinus Torvalds 	unsigned long flags;
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds 	local_irq_save(flags);
471da177e4SLinus Torvalds 	/* don't allow mappable interrupt to be enabled from setup_irq,
481da177e4SLinus Torvalds 	 * we have our own way to do so */
491da177e4SLinus Torvalds 	if (irq != SGI_MAP_0_IRQ)
501da177e4SLinus Torvalds 		sgint->imask0 |= (1 << (irq - SGINT_LOCAL0));
511da177e4SLinus Torvalds 	local_irq_restore(flags);
521da177e4SLinus Torvalds }
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds static unsigned int startup_local0_irq(unsigned int irq)
551da177e4SLinus Torvalds {
561da177e4SLinus Torvalds 	enable_local0_irq(irq);
571da177e4SLinus Torvalds 	return 0;		/* Never anything pending  */
581da177e4SLinus Torvalds }
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds static void disable_local0_irq(unsigned int irq)
611da177e4SLinus Torvalds {
621da177e4SLinus Torvalds 	unsigned long flags;
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds 	local_irq_save(flags);
651da177e4SLinus Torvalds 	sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0));
661da177e4SLinus Torvalds 	local_irq_restore(flags);
671da177e4SLinus Torvalds }
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds #define shutdown_local0_irq	disable_local0_irq
701da177e4SLinus Torvalds #define mask_and_ack_local0_irq	disable_local0_irq
711da177e4SLinus Torvalds 
721da177e4SLinus Torvalds static void end_local0_irq (unsigned int irq)
731da177e4SLinus Torvalds {
741da177e4SLinus Torvalds 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
751da177e4SLinus Torvalds 		enable_local0_irq(irq);
761da177e4SLinus Torvalds }
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds static struct hw_interrupt_type ip22_local0_irq_type = {
791da177e4SLinus Torvalds 	.typename	= "IP22 local 0",
801da177e4SLinus Torvalds 	.startup	= startup_local0_irq,
811da177e4SLinus Torvalds 	.shutdown	= shutdown_local0_irq,
821da177e4SLinus Torvalds 	.enable		= enable_local0_irq,
831da177e4SLinus Torvalds 	.disable	= disable_local0_irq,
841da177e4SLinus Torvalds 	.ack		= mask_and_ack_local0_irq,
851da177e4SLinus Torvalds 	.end		= end_local0_irq,
861da177e4SLinus Torvalds };
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds static void enable_local1_irq(unsigned int irq)
891da177e4SLinus Torvalds {
901da177e4SLinus Torvalds 	unsigned long flags;
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 	local_irq_save(flags);
931da177e4SLinus Torvalds 	/* don't allow mappable interrupt to be enabled from setup_irq,
941da177e4SLinus Torvalds 	 * we have our own way to do so */
951da177e4SLinus Torvalds 	if (irq != SGI_MAP_1_IRQ)
961da177e4SLinus Torvalds 		sgint->imask1 |= (1 << (irq - SGINT_LOCAL1));
971da177e4SLinus Torvalds 	local_irq_restore(flags);
981da177e4SLinus Torvalds }
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds static unsigned int startup_local1_irq(unsigned int irq)
1011da177e4SLinus Torvalds {
1021da177e4SLinus Torvalds 	enable_local1_irq(irq);
1031da177e4SLinus Torvalds 	return 0;		/* Never anything pending  */
1041da177e4SLinus Torvalds }
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds void disable_local1_irq(unsigned int irq)
1071da177e4SLinus Torvalds {
1081da177e4SLinus Torvalds 	unsigned long flags;
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds 	local_irq_save(flags);
1111da177e4SLinus Torvalds 	sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1));
1121da177e4SLinus Torvalds 	local_irq_restore(flags);
1131da177e4SLinus Torvalds }
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds #define shutdown_local1_irq	disable_local1_irq
1161da177e4SLinus Torvalds #define mask_and_ack_local1_irq	disable_local1_irq
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds static void end_local1_irq (unsigned int irq)
1191da177e4SLinus Torvalds {
1201da177e4SLinus Torvalds 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
1211da177e4SLinus Torvalds 		enable_local1_irq(irq);
1221da177e4SLinus Torvalds }
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds static struct hw_interrupt_type ip22_local1_irq_type = {
1251da177e4SLinus Torvalds 	.typename	= "IP22 local 1",
1261da177e4SLinus Torvalds 	.startup	= startup_local1_irq,
1271da177e4SLinus Torvalds 	.shutdown	= shutdown_local1_irq,
1281da177e4SLinus Torvalds 	.enable		= enable_local1_irq,
1291da177e4SLinus Torvalds 	.disable	= disable_local1_irq,
1301da177e4SLinus Torvalds 	.ack		= mask_and_ack_local1_irq,
1311da177e4SLinus Torvalds 	.end		= end_local1_irq,
1321da177e4SLinus Torvalds };
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds static void enable_local2_irq(unsigned int irq)
1351da177e4SLinus Torvalds {
1361da177e4SLinus Torvalds 	unsigned long flags;
1371da177e4SLinus Torvalds 
1381da177e4SLinus Torvalds 	local_irq_save(flags);
1391da177e4SLinus Torvalds 	sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
1401da177e4SLinus Torvalds 	sgint->cmeimask0 |= (1 << (irq - SGINT_LOCAL2));
1411da177e4SLinus Torvalds 	local_irq_restore(flags);
1421da177e4SLinus Torvalds }
1431da177e4SLinus Torvalds 
1441da177e4SLinus Torvalds static unsigned int startup_local2_irq(unsigned int irq)
1451da177e4SLinus Torvalds {
1461da177e4SLinus Torvalds 	enable_local2_irq(irq);
1471da177e4SLinus Torvalds 	return 0;		/* Never anything pending  */
1481da177e4SLinus Torvalds }
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds void disable_local2_irq(unsigned int irq)
1511da177e4SLinus Torvalds {
1521da177e4SLinus Torvalds 	unsigned long flags;
1531da177e4SLinus Torvalds 
1541da177e4SLinus Torvalds 	local_irq_save(flags);
1551da177e4SLinus Torvalds 	sgint->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2));
1561da177e4SLinus Torvalds 	if (!sgint->cmeimask0)
1571da177e4SLinus Torvalds 		sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
1581da177e4SLinus Torvalds 	local_irq_restore(flags);
1591da177e4SLinus Torvalds }
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds #define shutdown_local2_irq disable_local2_irq
1621da177e4SLinus Torvalds #define mask_and_ack_local2_irq	disable_local2_irq
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds static void end_local2_irq (unsigned int irq)
1651da177e4SLinus Torvalds {
1661da177e4SLinus Torvalds 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
1671da177e4SLinus Torvalds 		enable_local2_irq(irq);
1681da177e4SLinus Torvalds }
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds static struct hw_interrupt_type ip22_local2_irq_type = {
1711da177e4SLinus Torvalds 	.typename	= "IP22 local 2",
1721da177e4SLinus Torvalds 	.startup	= startup_local2_irq,
1731da177e4SLinus Torvalds 	.shutdown	= shutdown_local2_irq,
1741da177e4SLinus Torvalds 	.enable		= enable_local2_irq,
1751da177e4SLinus Torvalds 	.disable	= disable_local2_irq,
1761da177e4SLinus Torvalds 	.ack		= mask_and_ack_local2_irq,
1771da177e4SLinus Torvalds 	.end		= end_local2_irq,
1781da177e4SLinus Torvalds };
1791da177e4SLinus Torvalds 
1801da177e4SLinus Torvalds static void enable_local3_irq(unsigned int irq)
1811da177e4SLinus Torvalds {
1821da177e4SLinus Torvalds 	unsigned long flags;
1831da177e4SLinus Torvalds 
1841da177e4SLinus Torvalds 	local_irq_save(flags);
1851da177e4SLinus Torvalds 	sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
1861da177e4SLinus Torvalds 	sgint->cmeimask1 |= (1 << (irq - SGINT_LOCAL3));
1871da177e4SLinus Torvalds 	local_irq_restore(flags);
1881da177e4SLinus Torvalds }
1891da177e4SLinus Torvalds 
1901da177e4SLinus Torvalds static unsigned int startup_local3_irq(unsigned int irq)
1911da177e4SLinus Torvalds {
1921da177e4SLinus Torvalds 	enable_local3_irq(irq);
1931da177e4SLinus Torvalds 	return 0;		/* Never anything pending  */
1941da177e4SLinus Torvalds }
1951da177e4SLinus Torvalds 
1961da177e4SLinus Torvalds void disable_local3_irq(unsigned int irq)
1971da177e4SLinus Torvalds {
1981da177e4SLinus Torvalds 	unsigned long flags;
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds 	local_irq_save(flags);
2011da177e4SLinus Torvalds 	sgint->cmeimask1 &= ~(1 << (irq - SGINT_LOCAL3));
2021da177e4SLinus Torvalds 	if (!sgint->cmeimask1)
2031da177e4SLinus Torvalds 		sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
2041da177e4SLinus Torvalds 	local_irq_restore(flags);
2051da177e4SLinus Torvalds }
2061da177e4SLinus Torvalds 
2071da177e4SLinus Torvalds #define shutdown_local3_irq disable_local3_irq
2081da177e4SLinus Torvalds #define mask_and_ack_local3_irq	disable_local3_irq
2091da177e4SLinus Torvalds 
2101da177e4SLinus Torvalds static void end_local3_irq (unsigned int irq)
2111da177e4SLinus Torvalds {
2121da177e4SLinus Torvalds 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
2131da177e4SLinus Torvalds 		enable_local3_irq(irq);
2141da177e4SLinus Torvalds }
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds static struct hw_interrupt_type ip22_local3_irq_type = {
2171da177e4SLinus Torvalds 	.typename	= "IP22 local 3",
2181da177e4SLinus Torvalds 	.startup	= startup_local3_irq,
2191da177e4SLinus Torvalds 	.shutdown	= shutdown_local3_irq,
2201da177e4SLinus Torvalds 	.enable		= enable_local3_irq,
2211da177e4SLinus Torvalds 	.disable	= disable_local3_irq,
2221da177e4SLinus Torvalds 	.ack		= mask_and_ack_local3_irq,
2231da177e4SLinus Torvalds 	.end		= end_local3_irq,
2241da177e4SLinus Torvalds };
2251da177e4SLinus Torvalds 
226e4ac58afSRalf Baechle static void indy_local0_irqdispatch(struct pt_regs *regs)
2271da177e4SLinus Torvalds {
2281da177e4SLinus Torvalds 	u8 mask = sgint->istat0 & sgint->imask0;
2291da177e4SLinus Torvalds 	u8 mask2;
2301da177e4SLinus Torvalds 	int irq;
2311da177e4SLinus Torvalds 
2321da177e4SLinus Torvalds 	if (mask & SGINT_ISTAT0_LIO2) {
2331da177e4SLinus Torvalds 		mask2 = sgint->vmeistat & sgint->cmeimask0;
2341da177e4SLinus Torvalds 		irq = lc2msk_to_irqnr[mask2];
2351da177e4SLinus Torvalds 	} else
2361da177e4SLinus Torvalds 		irq = lc0msk_to_irqnr[mask];
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds 	/* if irq == 0, then the interrupt has already been cleared */
2391da177e4SLinus Torvalds 	if (irq)
2401da177e4SLinus Torvalds 		do_IRQ(irq, regs);
2411da177e4SLinus Torvalds 	return;
2421da177e4SLinus Torvalds }
2431da177e4SLinus Torvalds 
244e4ac58afSRalf Baechle static void indy_local1_irqdispatch(struct pt_regs *regs)
2451da177e4SLinus Torvalds {
2461da177e4SLinus Torvalds 	u8 mask = sgint->istat1 & sgint->imask1;
2471da177e4SLinus Torvalds 	u8 mask2;
2481da177e4SLinus Torvalds 	int irq;
2491da177e4SLinus Torvalds 
2501da177e4SLinus Torvalds 	if (mask & SGINT_ISTAT1_LIO3) {
2511da177e4SLinus Torvalds 		mask2 = sgint->vmeistat & sgint->cmeimask1;
2521da177e4SLinus Torvalds 		irq = lc3msk_to_irqnr[mask2];
2531da177e4SLinus Torvalds 	} else
2541da177e4SLinus Torvalds 		irq = lc1msk_to_irqnr[mask];
2551da177e4SLinus Torvalds 
2561da177e4SLinus Torvalds 	/* if irq == 0, then the interrupt has already been cleared */
2571da177e4SLinus Torvalds 	if (irq)
2581da177e4SLinus Torvalds 		do_IRQ(irq, regs);
2591da177e4SLinus Torvalds 	return;
2601da177e4SLinus Torvalds }
2611da177e4SLinus Torvalds 
2621da177e4SLinus Torvalds extern void ip22_be_interrupt(int irq, struct pt_regs *regs);
2631da177e4SLinus Torvalds 
264e4ac58afSRalf Baechle static void indy_buserror_irq(struct pt_regs *regs)
2651da177e4SLinus Torvalds {
2661da177e4SLinus Torvalds 	int irq = SGI_BUSERR_IRQ;
2671da177e4SLinus Torvalds 
2681da177e4SLinus Torvalds 	irq_enter();
2691da177e4SLinus Torvalds 	kstat_this_cpu.irqs[irq]++;
2701da177e4SLinus Torvalds 	ip22_be_interrupt(irq, regs);
2711da177e4SLinus Torvalds 	irq_exit();
2721da177e4SLinus Torvalds }
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds static struct irqaction local0_cascade = {
2751da177e4SLinus Torvalds 	.handler	= no_action,
2761da177e4SLinus Torvalds 	.flags		= SA_INTERRUPT,
2771da177e4SLinus Torvalds 	.name		= "local0 cascade",
2781da177e4SLinus Torvalds };
2791da177e4SLinus Torvalds 
2801da177e4SLinus Torvalds static struct irqaction local1_cascade = {
2811da177e4SLinus Torvalds 	.handler	= no_action,
2821da177e4SLinus Torvalds 	.flags		= SA_INTERRUPT,
2831da177e4SLinus Torvalds 	.name		= "local1 cascade",
2841da177e4SLinus Torvalds };
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds static struct irqaction buserr = {
2871da177e4SLinus Torvalds 	.handler	= no_action,
2881da177e4SLinus Torvalds 	.flags		= SA_INTERRUPT,
2891da177e4SLinus Torvalds 	.name		= "Bus Error",
2901da177e4SLinus Torvalds };
2911da177e4SLinus Torvalds 
2921da177e4SLinus Torvalds static struct irqaction map0_cascade = {
2931da177e4SLinus Torvalds 	.handler	= no_action,
2941da177e4SLinus Torvalds 	.flags		= SA_INTERRUPT,
2951da177e4SLinus Torvalds 	.name		= "mapable0 cascade",
2961da177e4SLinus Torvalds };
2971da177e4SLinus Torvalds 
2981da177e4SLinus Torvalds #ifdef USE_LIO3_IRQ
2991da177e4SLinus Torvalds static struct irqaction map1_cascade = {
3001da177e4SLinus Torvalds 	.handler	= no_action,
3011da177e4SLinus Torvalds 	.flags		= SA_INTERRUPT,
3021da177e4SLinus Torvalds 	.name		= "mapable1 cascade",
3031da177e4SLinus Torvalds };
3041da177e4SLinus Torvalds #define SGI_INTERRUPTS	SGINT_END
3051da177e4SLinus Torvalds #else
3061da177e4SLinus Torvalds #define SGI_INTERRUPTS	SGINT_LOCAL3
3071da177e4SLinus Torvalds #endif
3081da177e4SLinus Torvalds 
309e4ac58afSRalf Baechle extern void indy_r4k_timer_interrupt(struct pt_regs *regs);
310e4ac58afSRalf Baechle extern void indy_8254timer_irq(struct pt_regs *regs);
311e4ac58afSRalf Baechle 
312e4ac58afSRalf Baechle /*
313e4ac58afSRalf Baechle  * IRQs on the INDY look basically (barring software IRQs which we don't use
314e4ac58afSRalf Baechle  * at all) like:
315e4ac58afSRalf Baechle  *
316e4ac58afSRalf Baechle  *	MIPS IRQ	Source
317e4ac58afSRalf Baechle  *      --------        ------
318e4ac58afSRalf Baechle  *             0	Software (ignored)
319e4ac58afSRalf Baechle  *             1        Software (ignored)
320e4ac58afSRalf Baechle  *             2        Local IRQ level zero
321e4ac58afSRalf Baechle  *             3        Local IRQ level one
322e4ac58afSRalf Baechle  *             4        8254 Timer zero
323e4ac58afSRalf Baechle  *             5        8254 Timer one
324e4ac58afSRalf Baechle  *             6        Bus Error
325e4ac58afSRalf Baechle  *             7        R4k timer (what we use)
326e4ac58afSRalf Baechle  *
327e4ac58afSRalf Baechle  * We handle the IRQ according to _our_ priority which is:
328e4ac58afSRalf Baechle  *
329e4ac58afSRalf Baechle  * Highest ----     R4k Timer
330e4ac58afSRalf Baechle  *                  Local IRQ zero
331e4ac58afSRalf Baechle  *                  Local IRQ one
332e4ac58afSRalf Baechle  *                  Bus Error
333e4ac58afSRalf Baechle  *                  8254 Timer zero
334e4ac58afSRalf Baechle  * Lowest  ----     8254 Timer one
335e4ac58afSRalf Baechle  *
336e4ac58afSRalf Baechle  * then we just return, if multiple IRQs are pending then we will just take
337e4ac58afSRalf Baechle  * another exception, big deal.
338e4ac58afSRalf Baechle  */
339e4ac58afSRalf Baechle 
340e4ac58afSRalf Baechle asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
341e4ac58afSRalf Baechle {
342e4ac58afSRalf Baechle 	unsigned int pending = read_c0_cause();
343e4ac58afSRalf Baechle 
344e4ac58afSRalf Baechle 	/*
345e4ac58afSRalf Baechle 	 * First we check for r4k counter/timer IRQ.
346e4ac58afSRalf Baechle 	 */
347e4ac58afSRalf Baechle 	if (pending & CAUSEF_IP7)
348e4ac58afSRalf Baechle 		indy_r4k_timer_interrupt(regs);
349e4ac58afSRalf Baechle 	else if (pending & CAUSEF_IP2)
350e4ac58afSRalf Baechle 		indy_local0_irqdispatch(regs);
351e4ac58afSRalf Baechle 	else if (pending & CAUSEF_IP3)
352e4ac58afSRalf Baechle 		indy_local1_irqdispatch(regs);
353e4ac58afSRalf Baechle 	else if (pending & CAUSEF_IP6)
354e4ac58afSRalf Baechle 		indy_buserror_irq(regs);
355e4ac58afSRalf Baechle 	else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
356e4ac58afSRalf Baechle 		indy_8254timer_irq(regs);
357e4ac58afSRalf Baechle }
358e4ac58afSRalf Baechle 
3591da177e4SLinus Torvalds extern void mips_cpu_irq_init(unsigned int irq_base);
3601da177e4SLinus Torvalds 
3611da177e4SLinus Torvalds void __init arch_init_irq(void)
3621da177e4SLinus Torvalds {
3631da177e4SLinus Torvalds 	int i;
3641da177e4SLinus Torvalds 
3651da177e4SLinus Torvalds 	/* Init local mask --> irq tables. */
3661da177e4SLinus Torvalds 	for (i = 0; i < 256; i++) {
3671da177e4SLinus Torvalds 		if (i & 0x80) {
3681da177e4SLinus Torvalds 			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7;
3691da177e4SLinus Torvalds 			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7;
3701da177e4SLinus Torvalds 			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7;
3711da177e4SLinus Torvalds 			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7;
3721da177e4SLinus Torvalds 		} else if (i & 0x40) {
3731da177e4SLinus Torvalds 			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6;
3741da177e4SLinus Torvalds 			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6;
3751da177e4SLinus Torvalds 			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6;
3761da177e4SLinus Torvalds 			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6;
3771da177e4SLinus Torvalds 		} else if (i & 0x20) {
3781da177e4SLinus Torvalds 			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5;
3791da177e4SLinus Torvalds 			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5;
3801da177e4SLinus Torvalds 			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5;
3811da177e4SLinus Torvalds 			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5;
3821da177e4SLinus Torvalds 		} else if (i & 0x10) {
3831da177e4SLinus Torvalds 			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4;
3841da177e4SLinus Torvalds 			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4;
3851da177e4SLinus Torvalds 			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4;
3861da177e4SLinus Torvalds 			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4;
3871da177e4SLinus Torvalds 		} else if (i & 0x08) {
3881da177e4SLinus Torvalds 			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3;
3891da177e4SLinus Torvalds 			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3;
3901da177e4SLinus Torvalds 			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3;
3911da177e4SLinus Torvalds 			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3;
3921da177e4SLinus Torvalds 		} else if (i & 0x04) {
3931da177e4SLinus Torvalds 			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2;
3941da177e4SLinus Torvalds 			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2;
3951da177e4SLinus Torvalds 			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2;
3961da177e4SLinus Torvalds 			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2;
3971da177e4SLinus Torvalds 		} else if (i & 0x02) {
3981da177e4SLinus Torvalds 			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1;
3991da177e4SLinus Torvalds 			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1;
4001da177e4SLinus Torvalds 			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1;
4011da177e4SLinus Torvalds 			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1;
4021da177e4SLinus Torvalds 		} else if (i & 0x01) {
4031da177e4SLinus Torvalds 			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0;
4041da177e4SLinus Torvalds 			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0;
4051da177e4SLinus Torvalds 			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0;
4061da177e4SLinus Torvalds 			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0;
4071da177e4SLinus Torvalds 		} else {
4081da177e4SLinus Torvalds 			lc0msk_to_irqnr[i] = 0;
4091da177e4SLinus Torvalds 			lc1msk_to_irqnr[i] = 0;
4101da177e4SLinus Torvalds 			lc2msk_to_irqnr[i] = 0;
4111da177e4SLinus Torvalds 			lc3msk_to_irqnr[i] = 0;
4121da177e4SLinus Torvalds 		}
4131da177e4SLinus Torvalds 	}
4141da177e4SLinus Torvalds 
4151da177e4SLinus Torvalds 	/* Mask out all interrupts. */
4161da177e4SLinus Torvalds 	sgint->imask0 = 0;
4171da177e4SLinus Torvalds 	sgint->imask1 = 0;
4181da177e4SLinus Torvalds 	sgint->cmeimask0 = 0;
4191da177e4SLinus Torvalds 	sgint->cmeimask1 = 0;
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds 	/* init CPU irqs */
4221da177e4SLinus Torvalds 	mips_cpu_irq_init(SGINT_CPU);
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds 	for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) {
4251da177e4SLinus Torvalds 		hw_irq_controller *handler;
4261da177e4SLinus Torvalds 
4271da177e4SLinus Torvalds 		if (i < SGINT_LOCAL1)
4281da177e4SLinus Torvalds 			handler		= &ip22_local0_irq_type;
4291da177e4SLinus Torvalds 		else if (i < SGINT_LOCAL2)
4301da177e4SLinus Torvalds 			handler		= &ip22_local1_irq_type;
4311da177e4SLinus Torvalds 		else if (i < SGINT_LOCAL3)
4321da177e4SLinus Torvalds 			handler		= &ip22_local2_irq_type;
4331da177e4SLinus Torvalds 		else
4341da177e4SLinus Torvalds 			handler		= &ip22_local3_irq_type;
4351da177e4SLinus Torvalds 
4361da177e4SLinus Torvalds 		irq_desc[i].status	= IRQ_DISABLED;
4371da177e4SLinus Torvalds 		irq_desc[i].action	= 0;
4381da177e4SLinus Torvalds 		irq_desc[i].depth	= 1;
439*d1bef4edSIngo Molnar 		irq_desc[i].chip	= handler;
4401da177e4SLinus Torvalds 	}
4411da177e4SLinus Torvalds 
4421da177e4SLinus Torvalds 	/* vector handler. this register the IRQ as non-sharable */
4431da177e4SLinus Torvalds 	setup_irq(SGI_LOCAL_0_IRQ, &local0_cascade);
4441da177e4SLinus Torvalds 	setup_irq(SGI_LOCAL_1_IRQ, &local1_cascade);
4451da177e4SLinus Torvalds 	setup_irq(SGI_BUSERR_IRQ, &buserr);
4461da177e4SLinus Torvalds 
4471da177e4SLinus Torvalds 	/* cascade in cascade. i love Indy ;-) */
4481da177e4SLinus Torvalds 	setup_irq(SGI_MAP_0_IRQ, &map0_cascade);
4491da177e4SLinus Torvalds #ifdef USE_LIO3_IRQ
4501da177e4SLinus Torvalds 	setup_irq(SGI_MAP_1_IRQ, &map1_cascade);
4511da177e4SLinus Torvalds #endif
4521da177e4SLinus Torvalds 
4531da177e4SLinus Torvalds #ifdef CONFIG_EISA
4541da177e4SLinus Torvalds 	if (ip22_is_fullhouse())	/* Only Indigo-2 has EISA stuff */
4551da177e4SLinus Torvalds 	        ip22_eisa_init ();
4561da177e4SLinus Torvalds #endif
4571da177e4SLinus Torvalds }
458