1 diff -urN linux.orig/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
2 --- linux.orig/arch/ppc/kernel/chrp_setup.c Sun Mar 25 18:31:49 2001
3 +++ linux/arch/ppc/kernel/chrp_setup.c Tue Aug 27 15:46:50 2002
5 * Copyright (C) 1995 Linus Torvalds
6 * Adapted from 'alpha' version by Gary Thomas
7 * Modified by Cort Dougan (cort@cs.nmt.edu)
8 + * Fixed IRQ time out problem by Krzysztof Taraszka (dzimi@pld.org.pl)
17 +chrp_do_IRQ(struct pt_regs *regs,
22 + unsigned long bits = 0;
23 + int openpic_eoi_done = 0;
27 + unsigned int loops = 1000000;
28 + while (test_bit(0, &global_irq_lock)) {
29 + if (smp_processor_id() == global_irq_holder) {
30 + printk("uh oh, interrupt while we hold global irq lock!\n");
37 + printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
46 + irq = openpic_irq(smp_processor_id());
47 + if (irq == IRQ_8259_CASCADE)
50 + * This magic address generates a PCI IACK cycle.
52 + * This should go in the above mask/ack code soon. -- Cort
54 + if ( chrp_int_ack_special )
55 + irq = *chrp_int_ack_special;
59 + * Acknowledge as soon as possible to allow i8259
60 + * interrupt nesting */
61 + openpic_eoi(smp_processor_id());
62 + openpic_eoi_done = 1;
64 + if (irq == OPENPIC_VEC_SPURIOUS)
67 + * Spurious interrupts should never be
70 + ppc_spurious_interrupts++;
71 + openpic_eoi_done = 1;
78 + printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
80 + ppc_spurious_interrupts++;
84 + ppc_irq_dispatch_handler( regs, irq );
87 + if (!openpic_eoi_done)
88 + openpic_eoi(smp_processor_id());
95 ppc_md.get_cpuinfo = chrp_get_cpuinfo;
96 ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
97 ppc_md.init_IRQ = chrp_init_IRQ;
98 - ppc_md.do_IRQ = open_pic_do_IRQ;
99 + ppc_md.do_IRQ = chrp_do_IRQ;
101 ppc_md.init = chrp_init2;
103 diff -urN linux.orig/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
104 --- linux.orig/arch/ppc/kernel/open_pic.c Sun Mar 25 18:31:49 2001
105 +++ linux/arch/ppc/kernel/open_pic.c Tue Aug 27 15:46:50 2002
107 #include <linux/signal.h>
108 #include <linux/openpic.h>
110 -#include <asm/processor.h>
111 #include "open_pic.h"
114 -extern volatile unsigned char *chrp_int_ack_special;
116 -void open_pic_do_IRQ(struct pt_regs *regs, int cpu, int isfake)
119 - int openpic_eoi_done = 0;
123 - unsigned int loops = 1000000;
124 - while (test_bit(0, &global_irq_lock)) {
125 - if (smp_processor_id() == global_irq_holder) {
126 - printk("uh oh, interrupt while we hold global irq lock!\n");
132 - if (loops-- == 0) {
133 - printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
140 +void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
142 + smp_message_recv(cpl-OPENPIC_VEC_IPI);
146 - irq = openpic_irq(smp_processor_id());
147 - /* make sure open_pic.irq_offset is set to something!
148 - * do we really need the _MACH_Pmac test??
150 - if (!(_machine == _MACH_Pmac) && (irq == open_pic.irq_offset))
153 - * This magic address generates a PCI IACK cycle.
155 - * This should go in the above mask/ack code soon. -- Cort
157 - if ( chrp_int_ack_special )
158 - irq = *chrp_int_ack_special;
161 - irq = i8259_irq(0);
164 - * Acknowledge as soon as possible to allow i8259
165 - * interrupt nesting */
166 - openpic_eoi(smp_processor_id());
167 - openpic_eoi_done = 1;
169 - if (irq == OPENPIC_VEC_SPURIOUS)
172 - * Spurious interrupts should never be
175 - ppc_spurious_interrupts++;
176 - openpic_eoi_done = 1;
182 - printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
184 - ppc_spurious_interrupts++;
188 - ppc_irq_dispatch_handler( regs, irq );
191 - if (!openpic_eoi_done)
192 - openpic_eoi(smp_processor_id());
193 +void chrp_mask_and_ack_irq(unsigned int irq_nr)
195 + if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
196 + i8259_pic.mask_and_ack(irq_nr);
200 -void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
201 +static void chrp_mask_irq(unsigned int irq_nr)
203 - smp_message_recv(cpl-OPENPIC_VEC_IPI);
204 + if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
205 + i8259_pic.disable(irq_nr);
207 + openpic_disable_irq(irq_nr-open_pic.irq_offset);
209 -#endif /* __SMP__ */
211 +static void chrp_unmask_irq(unsigned int irq_nr)
213 + if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
214 + i8259_pic.enable(irq_nr);
216 + openpic_enable_irq(irq_nr-open_pic.irq_offset);
219 struct hw_interrupt_type open_pic = {
224 - openpic_enable_irq,
225 - openpic_disable_irq,
226 - /* Theorically, the mask&ack should be NULL for OpenPIC. However, doing
227 - * so shows tons of bogus interrupts coming in.
228 - * This problem is apparently due to the common code always calling
229 - * unmask(). I apparently (need more test) fixed it in the 2.4 new IRQ
230 - * management by cleanly implementing the handler's end() function, so
231 - * neither mask nor unmask are needed. In the meantime, the fix below will
232 - * work for 2.2 -Benh
234 - * Hopefully this will fix my bogus interrups on MTX
235 - * I merged everthing together so we don't have the same code in three
236 - * places. This might cause stability problems, but I'd rather
237 - * get it right once than three different times because someone forgot
238 - * to make the same change to PReP or something --Troy
240 - openpic_disable_irq,
243 + chrp_mask_and_ack_irq,
246 diff -urN linux.orig/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h
247 --- linux.orig/arch/ppc/kernel/open_pic.h Sun Mar 25 18:31:49 2001
248 +++ linux/arch/ppc/kernel/open_pic.h Tue Aug 27 15:46:50 2002
251 extern struct hw_interrupt_type open_pic;
253 -void open_pic_do_IRQ(struct pt_regs *regs, int cpu, int isfake);
254 void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
255 void openpic_enable_IPI(u_int ipi);
256 void do_openpic_setup_cpu(void);
257 diff -urN linux.orig/arch/ppc/kernel/openpic.c linux/arch/ppc/kernel/openpic.c
258 --- linux.orig/arch/ppc/kernel/openpic.c Fri Nov 2 17:39:05 2001
259 +++ linux/arch/ppc/kernel/openpic.c Tue Aug 27 15:46:50 2002
261 * to avoid bogus interrupts and to make sure the disable function exits with
262 * the interrupt actually masked. --BenH
263 * Todo: map interrupts to all available CPUs after the ack round
265 + * Fixed IRQ time out problem by
266 + * Krzysztof Taraszka (dzimi@pld.org.pl)
268 * This file is subject to the terms and conditions of the GNU General Public
269 * License. See the file COPYING in the main directory of this archive
271 #define REGISTER_DEBUG
272 #undef REGISTER_DEBUG
274 +#define OPENPIC_SENSE_POLARITY 0x00800000 /* Undoc'd */
277 extern int use_of_interrupt_tree;
280 * other ones are just masked out.
281 * Note: We might want to adjust priorities too.
284 /* Not an init func, called on pbook wakeup --BenH */
289 /* Initialize IPI interrupts */
290 for (i = 0; i < OPENPIC_NUM_IPI; i++) {
291 - openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i);
292 + openpic_initipi(i, 0/*10*/, OPENPIC_VEC_IPI+i);
295 if (_machine != _MACH_Pmac) {
297 openpic_initirq( np->intrs[j].line,
301 + np->intrs[j].sense,
303 irq_desc[np->intrs[j].line].level = np->intrs[j].sense;
306 /* Fixme: read level value from controller */
307 printk("openpic: WARNING, openpic running without interrupt tree\n");
313 /* Initialize the spurious interrupt */
314 openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
318 openpic_setfield(&OpenPIC->Global.Global_Configuration0,
319 OPENPIC_CONFIG_RESET);
320 - /* Wait for reset to complete */
321 - while(openpic_readfield(&OpenPIC->Global.Global_Configuration0,
322 - OPENPIC_CONFIG_RESET))
327 @@ -465,12 +465,12 @@
329 for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
330 openpic_enable_IPI(i);
333 /* let the openpic know we want intrs */
334 for ( i = 0; i < NumSources ; i++ )
335 openpic_mapirq(i, openpic_read(&OpenPIC->Source[i].Destination)
336 | (1<<smp_processor_id()) );
339 openpic_set_priority(smp_processor_id(), 0);
344 void openpic_enable_irq(u_int irq)
346 - /* on SMP, we get IPI vector numbers here, we should handle them
347 - * or at least ignore them.
349 - if (irq < 0 || irq >= NumSources)
351 + check_arg_irq(irq);
352 openpic_clearfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
353 /* make sure mask gets to controller before we return to user */
355 @@ -519,30 +515,15 @@
359 -u_int openpic_get_enable(u_int irq)
361 - if (irq < 0 || irq >= NumSources)
363 - return !openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
367 void openpic_disable_irq(u_int irq)
371 - /* on SMP, we get IPI vector numbers here, we should handle them
372 - * or at least ignore them.
374 - if (irq < 0 || irq >= NumSources)
376 + check_arg_irq(irq);
377 openpic_setfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
378 /* make sure mask gets to controller before we return to user */
380 - mb(); /* sync is probably useless here */
381 - vp = openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
382 - OPENPIC_MASK | OPENPIC_ACTIVITY);
383 - } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
385 + } while(!openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
390 @@ -561,11 +542,10 @@
392 openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
393 OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
394 - OPENPIC_POLARITY_MASK | OPENPIC_SENSE_MASK,
395 + OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
396 (pri << OPENPIC_PRIORITY_SHIFT) | vec |
397 - (pol ? OPENPIC_POLARITY_POSITIVE :
398 - OPENPIC_POLARITY_NEGATIVE) |
399 - (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
400 + (pol ? OPENPIC_SENSE_POLARITY : 0) |
401 + (sense ? OPENPIC_SENSE_LEVEL : 0));
406 save_irq_src_vp[i] = openpic_read(&OpenPIC->Source[i].Vector_Priority);
407 save_irq_src_dest[i] = openpic_read(&OpenPIC->Source[i].Destination);
409 - for (i=0; i<NumProcessors; i++) {
410 +for (i=0; i<NumProcessors; i++) {
411 save_cpu_task_pri[i] = openpic_read(&OpenPIC->Processor[i].Current_Task_Priority);
412 openpic_set_priority(i, 0xf);
416 for (i=0; i<OPENPIC_NUM_IPI; i++)
417 openpic_write(&OpenPIC->Global.IPI_Vector_Priority(i), save_ipi_vp[i]);
418 - for (i=0; i<NumSources; i++) {
419 +for (i=0; i<NumSources; i++) {
420 openpic_write(&OpenPIC->Source[i].Vector_Priority, save_irq_src_vp[i]);
421 openpic_write(&OpenPIC->Source[i].Destination, save_irq_src_dest[i]);
423 diff -urN linux.orig/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
424 --- linux.orig/arch/ppc/kernel/pmac_pic.c Sun Mar 25 18:31:49 2001
425 +++ linux/arch/ppc/kernel/pmac_pic.c Tue Aug 27 15:47:42 2002
428 extern u_int openpic_read(volatile u_int *addr);
430 +extern void chrp_do_IRQ(struct pt_regs *,int , int);
432 #define MAXCOUNT 10000000
434 #define GATWICK_IRQ_POOL_SIZE 10
436 irq_desc[i].ctl = &open_pic;
437 irq_desc[i].level = 0;
439 - ppc_md.do_IRQ = open_pic_do_IRQ;
440 + ppc_md.do_IRQ = chrp_do_IRQ;
441 open_pic.irq_offset = 0;
444 diff -urN linux.orig/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
445 --- linux.orig/arch/ppc/kernel/prep_pci.c Sun Mar 25 18:31:49 2001
446 +++ linux/arch/ppc/kernel/prep_pci.c Tue Aug 27 15:46:50 2002
448 * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
450 * The motherboard routes/maps will disappear shortly. -- Cort
452 + * Add chrp_do_IRQ into ppc_md.do_IRQ -- Krzysztof Taraszka (dzimi@pld.org.pl)
456 #include <linux/types.h>
458 /* Used for Motorola to store system config register */
459 static unsigned long *ProcInfo;
461 +extern void chrp_do_IRQ(struct pt_regs *,int , int);
463 /* Tables for known hardware */
465 /* Motorola PowerStackII - Utah */
467 OpenPIC_InitSenses = mvme2600_openpic_initsenses;
468 OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses);
470 - ppc_md.do_IRQ = open_pic_do_IRQ;
471 + ppc_md.do_IRQ = chrp_do_IRQ;
473 /* If raven is present on Motorola store the system config register