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