diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2005-07-14 11:57:16 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:31:53 -0400 |
commit | e01402b115cccb6357f956649487aca2c6f7fbba (patch) | |
tree | 256e14f8d2762de98b992219b1a47e8f56b4b0da /arch/mips/mips-boards/malta/malta_int.c | |
parent | 86071b637db7baf599df26fdf820dce2fc55ca9f (diff) |
More AP / SP bits for the 34K, the Malta bits and things. Still wants
a little polishing.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mips-boards/malta/malta_int.c')
-rw-r--r-- | arch/mips/mips-boards/malta/malta_int.c | 136 |
1 files changed, 105 insertions, 31 deletions
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c index dd2db35966bc..6f99a4492015 100644 --- a/arch/mips/mips-boards/malta/malta_int.c +++ b/arch/mips/mips-boards/malta/malta_int.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/random.h> | 30 | #include <linux/random.h> |
31 | 31 | ||
32 | #include <asm/i8259.h> | 32 | #include <asm/i8259.h> |
33 | #include <asm/irq_cpu.h> | ||
33 | #include <asm/io.h> | 34 | #include <asm/io.h> |
34 | #include <asm/mips-boards/malta.h> | 35 | #include <asm/mips-boards/malta.h> |
35 | #include <asm/mips-boards/maltaint.h> | 36 | #include <asm/mips-boards/maltaint.h> |
@@ -37,8 +38,10 @@ | |||
37 | #include <asm/gt64120.h> | 38 | #include <asm/gt64120.h> |
38 | #include <asm/mips-boards/generic.h> | 39 | #include <asm/mips-boards/generic.h> |
39 | #include <asm/mips-boards/msc01_pci.h> | 40 | #include <asm/mips-boards/msc01_pci.h> |
41 | #include <asm/msc01_ic.h> | ||
40 | 42 | ||
41 | extern asmlinkage void mipsIRQ(void); | 43 | extern asmlinkage void mipsIRQ(void); |
44 | extern void mips_timer_interrupt(void); | ||
42 | 45 | ||
43 | static DEFINE_SPINLOCK(mips_irq_lock); | 46 | static DEFINE_SPINLOCK(mips_irq_lock); |
44 | 47 | ||
@@ -91,13 +94,13 @@ static inline int mips_pcibios_iack(void) | |||
91 | return irq; | 94 | return irq; |
92 | } | 95 | } |
93 | 96 | ||
94 | static inline int get_int(int *irq) | 97 | static inline int get_int(void) |
95 | { | 98 | { |
96 | unsigned long flags; | 99 | unsigned long flags; |
97 | 100 | int irq; | |
98 | spin_lock_irqsave(&mips_irq_lock, flags); | 101 | spin_lock_irqsave(&mips_irq_lock, flags); |
99 | 102 | ||
100 | *irq = mips_pcibios_iack(); | 103 | irq = mips_pcibios_iack(); |
101 | 104 | ||
102 | /* | 105 | /* |
103 | * IRQ7 is used to detect spurious interrupts. | 106 | * IRQ7 is used to detect spurious interrupts. |
@@ -106,73 +109,82 @@ static inline int get_int(int *irq) | |||
106 | * We can differentiate between this situation and a | 109 | * We can differentiate between this situation and a |
107 | * "Normal" IRQ7 by reading the ISR. | 110 | * "Normal" IRQ7 by reading the ISR. |
108 | */ | 111 | */ |
109 | if (*irq == 7) | 112 | if (irq == 7) |
110 | { | 113 | { |
111 | outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, | 114 | outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, |
112 | PIIX4_ICTLR1_OCW3); | 115 | PIIX4_ICTLR1_OCW3); |
113 | if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) { | 116 | if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) { |
114 | spin_unlock_irqrestore(&mips_irq_lock, flags); | 117 | irq = -1; /* Spurious interrupt */ |
115 | printk("We got a spurious interrupt from PIIX4.\n"); | 118 | printk("We got a spurious interrupt from PIIX4.\n"); |
116 | atomic_inc(&irq_err_count); | 119 | atomic_inc(&irq_err_count); |
117 | return -1; /* Spurious interrupt. */ | ||
118 | } | 120 | } |
119 | } | 121 | } |
120 | 122 | ||
121 | spin_unlock_irqrestore(&mips_irq_lock, flags); | 123 | spin_unlock_irqrestore(&mips_irq_lock, flags); |
122 | 124 | ||
123 | return 0; | 125 | return irq; |
124 | } | 126 | } |
125 | 127 | ||
126 | void malta_hw0_irqdispatch(struct pt_regs *regs) | 128 | void malta_hw0_irqdispatch(struct pt_regs *regs) |
127 | { | 129 | { |
128 | int irq; | 130 | int irq; |
129 | 131 | ||
130 | if (get_int(&irq)) | 132 | irq = get_int(); |
131 | return; /* interrupt has already been cleared */ | 133 | if (irq < 0) |
134 | return; /* interrupt has already been cleared */ | ||
132 | 135 | ||
133 | do_IRQ(irq, regs); | 136 | do_IRQ(MALTA_INT_BASE+irq, regs); |
134 | } | 137 | } |
135 | 138 | ||
136 | void corehi_irqdispatch(struct pt_regs *regs) | 139 | void corehi_irqdispatch(struct pt_regs *regs) |
137 | { | 140 | { |
138 | unsigned int data,datahi; | 141 | unsigned int intrcause,datalo,datahi; |
139 | 142 | unsigned int pcimstat, intisr, inten, intpol, intedge, intsteer, pcicmd, pcibadaddr; | |
140 | /* Mask out corehi interrupt. */ | ||
141 | clear_c0_status(IE_IRQ3); | ||
142 | 143 | ||
143 | printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n"); | 144 | printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n"); |
144 | printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\nbadVaddr : %08lx\n" | 145 | printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\nbadVaddr : %08lx\n" |
145 | , regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr); | 146 | , regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr); |
147 | |||
148 | /* Read all the registers and then print them as there is a | ||
149 | problem with interspersed printk's upsetting the Bonito controller. | ||
150 | Do it for the others too. | ||
151 | */ | ||
152 | |||
146 | switch(mips_revision_corid) { | 153 | switch(mips_revision_corid) { |
147 | case MIPS_REVISION_CORID_CORE_MSC: | 154 | case MIPS_REVISION_CORID_CORE_MSC: |
148 | case MIPS_REVISION_CORID_CORE_FPGA2: | 155 | case MIPS_REVISION_CORID_CORE_FPGA2: |
149 | case MIPS_REVISION_CORID_CORE_EMUL_MSC: | 156 | case MIPS_REVISION_CORID_CORE_EMUL_MSC: |
157 | ll_msc_irq(regs); | ||
150 | break; | 158 | break; |
151 | case MIPS_REVISION_CORID_QED_RM5261: | 159 | case MIPS_REVISION_CORID_QED_RM5261: |
152 | case MIPS_REVISION_CORID_CORE_LV: | 160 | case MIPS_REVISION_CORID_CORE_LV: |
153 | case MIPS_REVISION_CORID_CORE_FPGA: | 161 | case MIPS_REVISION_CORID_CORE_FPGA: |
154 | case MIPS_REVISION_CORID_CORE_FPGAR2: | 162 | case MIPS_REVISION_CORID_CORE_FPGAR2: |
155 | data = GT_READ(GT_INTRCAUSE_OFS); | 163 | intrcause = GT_READ(GT_INTRCAUSE_OFS); |
156 | printk("GT_INTRCAUSE = %08x\n", data); | 164 | datalo = GT_READ(GT_CPUERR_ADDRLO_OFS); |
157 | data = GT_READ(GT_CPUERR_ADDRLO_OFS); | ||
158 | datahi = GT_READ(GT_CPUERR_ADDRHI_OFS); | 165 | datahi = GT_READ(GT_CPUERR_ADDRHI_OFS); |
159 | printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, data); | 166 | printk("GT_INTRCAUSE = %08x\n", intrcause); |
167 | printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, datalo); | ||
160 | break; | 168 | break; |
161 | case MIPS_REVISION_CORID_BONITO64: | 169 | case MIPS_REVISION_CORID_BONITO64: |
162 | case MIPS_REVISION_CORID_CORE_20K: | 170 | case MIPS_REVISION_CORID_CORE_20K: |
163 | case MIPS_REVISION_CORID_CORE_EMUL_BON: | 171 | case MIPS_REVISION_CORID_CORE_EMUL_BON: |
164 | data = BONITO_INTISR; | 172 | pcibadaddr = BONITO_PCIBADADDR; |
165 | printk("BONITO_INTISR = %08x\n", data); | 173 | pcimstat = BONITO_PCIMSTAT; |
166 | data = BONITO_INTEN; | 174 | intisr = BONITO_INTISR; |
167 | printk("BONITO_INTEN = %08x\n", data); | 175 | inten = BONITO_INTEN; |
168 | data = BONITO_INTPOL; | 176 | intpol = BONITO_INTPOL; |
169 | printk("BONITO_INTPOL = %08x\n", data); | 177 | intedge = BONITO_INTEDGE; |
170 | data = BONITO_INTEDGE; | 178 | intsteer = BONITO_INTSTEER; |
171 | printk("BONITO_INTEDGE = %08x\n", data); | 179 | pcicmd = BONITO_PCICMD; |
172 | data = BONITO_INTSTEER; | 180 | printk("BONITO_INTISR = %08x\n", intisr); |
173 | printk("BONITO_INTSTEER = %08x\n", data); | 181 | printk("BONITO_INTEN = %08x\n", inten); |
174 | data = BONITO_PCICMD; | 182 | printk("BONITO_INTPOL = %08x\n", intpol); |
175 | printk("BONITO_PCICMD = %08x\n", data); | 183 | printk("BONITO_INTEDGE = %08x\n", intedge); |
184 | printk("BONITO_INTSTEER = %08x\n", intsteer); | ||
185 | printk("BONITO_PCICMD = %08x\n", pcicmd); | ||
186 | printk("BONITO_PCIBADADDR = %08x\n", pcibadaddr); | ||
187 | printk("BONITO_PCIMSTAT = %08x\n", pcimstat); | ||
176 | break; | 188 | break; |
177 | } | 189 | } |
178 | 190 | ||
@@ -180,8 +192,70 @@ void corehi_irqdispatch(struct pt_regs *regs) | |||
180 | die("CoreHi interrupt", regs); | 192 | die("CoreHi interrupt", regs); |
181 | } | 193 | } |
182 | 194 | ||
195 | static struct irqaction i8259irq = { | ||
196 | .handler = no_action, | ||
197 | .name = "XT-PIC cascade" | ||
198 | }; | ||
199 | |||
200 | static struct irqaction corehi_irqaction = { | ||
201 | .handler = no_action, | ||
202 | .name = "CoreHi" | ||
203 | }; | ||
204 | |||
205 | msc_irqmap_t __initdata msc_irqmap[] = { | ||
206 | {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, | ||
207 | {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, | ||
208 | }; | ||
209 | int __initdata msc_nr_irqs = sizeof(msc_irqmap)/sizeof(msc_irqmap_t); | ||
210 | |||
211 | msc_irqmap_t __initdata msc_eicirqmap[] = { | ||
212 | {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, | ||
213 | {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0}, | ||
214 | {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0}, | ||
215 | {MSC01E_INT_SMI, MSC01_IRQ_LEVEL, 0}, | ||
216 | {MSC01E_INT_COREHI, MSC01_IRQ_LEVEL, 0}, | ||
217 | {MSC01E_INT_CORELO, MSC01_IRQ_LEVEL, 0}, | ||
218 | {MSC01E_INT_TMR, MSC01_IRQ_EDGE, 0}, | ||
219 | {MSC01E_INT_PCI, MSC01_IRQ_LEVEL, 0}, | ||
220 | {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0}, | ||
221 | {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} | ||
222 | }; | ||
223 | int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap)/sizeof(msc_irqmap_t); | ||
224 | |||
183 | void __init arch_init_irq(void) | 225 | void __init arch_init_irq(void) |
184 | { | 226 | { |
185 | set_except_vector(0, mipsIRQ); | 227 | set_except_vector(0, mipsIRQ); |
186 | init_i8259_irqs(); | 228 | init_i8259_irqs(); |
229 | |||
230 | if (!cpu_has_veic) | ||
231 | mips_cpu_irq_init (MIPSCPU_INT_BASE); | ||
232 | |||
233 | switch(mips_revision_corid) { | ||
234 | case MIPS_REVISION_CORID_CORE_MSC: | ||
235 | case MIPS_REVISION_CORID_CORE_FPGA2: | ||
236 | case MIPS_REVISION_CORID_CORE_EMUL_MSC: | ||
237 | if (cpu_has_veic) | ||
238 | init_msc_irqs (MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs); | ||
239 | else | ||
240 | init_msc_irqs (MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs); | ||
241 | } | ||
242 | |||
243 | if (cpu_has_veic) { | ||
244 | set_vi_handler (MSC01E_INT_I8259A, malta_hw0_irqdispatch); | ||
245 | set_vi_handler (MSC01E_INT_COREHI, corehi_irqdispatch); | ||
246 | setup_irq (MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq); | ||
247 | setup_irq (MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction); | ||
248 | } | ||
249 | else if (cpu_has_vint) { | ||
250 | set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); | ||
251 | set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch); | ||
252 | |||
253 | setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq); | ||
254 | setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); | ||
255 | } | ||
256 | else { | ||
257 | set_except_vector(0, mipsIRQ); | ||
258 | setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq); | ||
259 | setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); | ||
260 | } | ||
187 | } | 261 | } |