xref: /openbmc/linux/arch/mips/cobalt/irq.c (revision 87c2ce3b)
1 /*
2  * IRQ vector handles
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file "COPYING" in the main directory of this archive
6  * for more details.
7  *
8  * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
9  */
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/irq.h>
13 #include <linux/interrupt.h>
14 #include <linux/pci.h>
15 
16 #include <asm/i8259.h>
17 #include <asm/irq_cpu.h>
18 #include <asm/gt64120.h>
19 #include <asm/ptrace.h>
20 
21 #include <asm/cobalt/cobalt.h>
22 
23 extern void cobalt_handle_int(void);
24 
25 /*
26  * We have two types of interrupts that we handle, ones that come in through
27  * the CPU interrupt lines, and ones that come in on the via chip. The CPU
28  * mappings are:
29  *
30  *    16   - Software interrupt 0 (unused)	IE_SW0
31  *    17   - Software interrupt 1 (unused)	IE_SW1
32  *    18   - Galileo chip (timer)		IE_IRQ0
33  *    19   - Tulip 0 + NCR SCSI			IE_IRQ1
34  *    20   - Tulip 1				IE_IRQ2
35  *    21   - 16550 UART				IE_IRQ3
36  *    22   - VIA southbridge PIC		IE_IRQ4
37  *    23   - unused				IE_IRQ5
38  *
39  * The VIA chip is a master/slave 8259 setup and has the following interrupts:
40  *
41  *     8  - RTC
42  *     9  - PCI
43  *    14  - IDE0
44  *    15  - IDE1
45  */
46 
47 static inline void galileo_irq(struct pt_regs *regs)
48 {
49 	unsigned int mask, pending, devfn;
50 
51 	mask = GALILEO_INL(GT_INTRMASK_OFS);
52 	pending = GALILEO_INL(GT_INTRCAUSE_OFS) & mask;
53 
54 	if (pending & GALILEO_INTR_T0EXP) {
55 
56 		GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS);
57 		do_IRQ(COBALT_GALILEO_IRQ, regs);
58 
59 	} else if (pending & GALILEO_INTR_RETRY_CTR) {
60 
61 		devfn = GALILEO_INL(GT_PCI0_CFGADDR_OFS) >> 8;
62 		GALILEO_OUTL(~GALILEO_INTR_RETRY_CTR, GT_INTRCAUSE_OFS);
63 		printk(KERN_WARNING "Galileo: PCI retry count exceeded (%02x.%u)\n",
64 			PCI_SLOT(devfn), PCI_FUNC(devfn));
65 
66 	} else {
67 
68 		GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS);
69 		printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending);
70 	}
71 }
72 
73 static inline void via_pic_irq(struct pt_regs *regs)
74 {
75 	int irq;
76 
77 	irq = i8259_irq();
78 	if (irq >= 0)
79 		do_IRQ(irq, regs);
80 }
81 
82 asmlinkage void cobalt_irq(struct pt_regs *regs)
83 {
84 	unsigned pending;
85 
86 	pending = read_c0_status() & read_c0_cause();
87 
88 	if (pending & CAUSEF_IP2)			/* COBALT_GALILEO_IRQ (18) */
89 
90 		galileo_irq(regs);
91 
92 	else if (pending & CAUSEF_IP6)			/* COBALT_VIA_IRQ (22) */
93 
94 		via_pic_irq(regs);
95 
96 	else if (pending & CAUSEF_IP3)			/* COBALT_ETH0_IRQ (19) */
97 
98 		do_IRQ(COBALT_CPU_IRQ + 3, regs);
99 
100 	else if (pending & CAUSEF_IP4)			/* COBALT_ETH1_IRQ (20) */
101 
102 		do_IRQ(COBALT_CPU_IRQ + 4, regs);
103 
104 	else if (pending & CAUSEF_IP5)			/* COBALT_SERIAL_IRQ (21) */
105 
106 		do_IRQ(COBALT_CPU_IRQ + 5, regs);
107 
108 	else if (pending & CAUSEF_IP7)			/* IRQ 23 */
109 
110 		do_IRQ(COBALT_CPU_IRQ + 7, regs);
111 }
112 
113 static struct irqaction irq_via = {
114 	no_action, 0, { { 0, } }, "cascade", NULL, NULL
115 };
116 
117 void __init arch_init_irq(void)
118 {
119 	/*
120 	 * Mask all Galileo interrupts. The Galileo
121 	 * handler is set in cobalt_timer_setup()
122 	 */
123 	GALILEO_OUTL(0, GT_INTRMASK_OFS);
124 
125 	set_except_vector(0, cobalt_handle_int);
126 
127 	init_i8259_irqs();				/*  0 ... 15 */
128 	mips_cpu_irq_init(COBALT_CPU_IRQ);		/* 16 ... 23 */
129 
130 	/*
131 	 * Mask all cpu interrupts
132 	 *  (except IE4, we already masked those at VIA level)
133 	 */
134 	change_c0_status(ST0_IM, IE_IRQ4);
135 
136 	setup_irq(COBALT_VIA_IRQ, &irq_via);
137 }
138