aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/chrp
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-07-03 07:36:01 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-03 07:36:01 -0400
commit0ebfff1491ef85d41ddf9c633834838be144f69f (patch)
tree5b469a6d61a9fcfbf94e7b6d411e544dbdec8dec /arch/powerpc/platforms/chrp
parentf63e115fb50db39706b955b81e3375ef6bab2268 (diff)
[POWERPC] Add new interrupt mapping core and change platforms to use it
This adds the new irq remapper core and removes the old one. Because there are some fundamental conflicts with the old code, like the value of NO_IRQ which I'm now setting to 0 (as per discussions with Linus), etc..., this commit also changes the relevant platform and driver code over to use the new remapper (so as not to cause difficulties later in bisecting). This patch removes the old pre-parsing of the open firmware interrupt tree along with all the bogus assumptions it made to try to renumber interrupts according to the platform. This is all to be handled by the new code now. For the pSeries XICS interrupt controller, a single remapper host is created for the whole machine regardless of how many interrupt presentation and source controllers are found, and it's set to match any device node that isn't a 8259. That works fine on pSeries and avoids having to deal with some of the complexities of split source controllers vs. presentation controllers in the pSeries device trees. The powerpc i8259 PIC driver now always requests the legacy interrupt range. It also has the feature of being able to match any device node (including NULL) if passed no device node as an input. That will help porting over platforms with broken device-trees like Pegasos who don't have a proper interrupt tree. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/chrp')
-rw-r--r--arch/powerpc/platforms/chrp/pci.c11
-rw-r--r--arch/powerpc/platforms/chrp/setup.c110
-rw-r--r--arch/powerpc/platforms/chrp/smp.c1
3 files changed, 68 insertions, 54 deletions
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 66c25349880..6802cdc3168 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -18,7 +18,6 @@
18#include <asm/machdep.h> 18#include <asm/machdep.h>
19#include <asm/sections.h> 19#include <asm/sections.h>
20#include <asm/pci-bridge.h> 20#include <asm/pci-bridge.h>
21#include <asm/open_pic.h>
22#include <asm/grackle.h> 21#include <asm/grackle.h>
23#include <asm/rtas.h> 22#include <asm/rtas.h>
24 23
@@ -161,15 +160,9 @@ void __init
161chrp_pcibios_fixup(void) 160chrp_pcibios_fixup(void)
162{ 161{
163 struct pci_dev *dev = NULL; 162 struct pci_dev *dev = NULL;
164 struct device_node *np;
165 163
166 /* PCI interrupts are controlled by the OpenPIC */ 164 for_each_pci_dev(dev)
167 for_each_pci_dev(dev) { 165 pci_read_irq_line(dev);
168 np = pci_device_to_OF_node(dev);
169 if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
170 dev->irq = np->intrs[0].line;
171 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
172 }
173} 166}
174 167
175#define PRG_CL_RESET_VALID 0x00010000 168#define PRG_CL_RESET_VALID 0x00010000
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index a5dffc8d93a..bb10171132f 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -59,7 +59,7 @@ void rtas_indicator_progress(char *, unsigned short);
59int _chrp_type; 59int _chrp_type;
60EXPORT_SYMBOL(_chrp_type); 60EXPORT_SYMBOL(_chrp_type);
61 61
62struct mpic *chrp_mpic; 62static struct mpic *chrp_mpic;
63 63
64/* Used for doing CHRP event-scans */ 64/* Used for doing CHRP event-scans */
65DEFINE_PER_CPU(struct timer_list, heartbeat_timer); 65DEFINE_PER_CPU(struct timer_list, heartbeat_timer);
@@ -315,19 +315,13 @@ chrp_event_scan(unsigned long unused)
315 jiffies + event_scan_interval); 315 jiffies + event_scan_interval);
316} 316}
317 317
318void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc, 318static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc,
319 struct pt_regs *regs) 319 struct pt_regs *regs)
320{ 320{
321 unsigned int max = 100; 321 unsigned int cascade_irq = i8259_irq(regs);
322 322 if (cascade_irq != NO_IRQ)
323 while(max--) { 323 generic_handle_irq(cascade_irq, regs);
324 int irq = i8259_irq(regs); 324 desc->chip->eoi(irq);
325 if (max == 99)
326 desc->chip->eoi(irq);
327 if (irq < 0)
328 break;
329 generic_handle_irq(irq, regs);
330 };
331} 325}
332 326
333/* 327/*
@@ -336,18 +330,17 @@ void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc,
336static void __init chrp_find_openpic(void) 330static void __init chrp_find_openpic(void)
337{ 331{
338 struct device_node *np, *root; 332 struct device_node *np, *root;
339 int len, i, j, irq_count; 333 int len, i, j;
340 int isu_size, idu_size; 334 int isu_size, idu_size;
341 unsigned int *iranges, *opprop = NULL; 335 unsigned int *iranges, *opprop = NULL;
342 int oplen = 0; 336 int oplen = 0;
343 unsigned long opaddr; 337 unsigned long opaddr;
344 int na = 1; 338 int na = 1;
345 unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
346 339
347 np = find_type_devices("open-pic"); 340 np = of_find_node_by_type(NULL, "open-pic");
348 if (np == NULL) 341 if (np == NULL)
349 return; 342 return;
350 root = find_path_device("/"); 343 root = of_find_node_by_path("/");
351 if (root) { 344 if (root) {
352 opprop = (unsigned int *) get_property 345 opprop = (unsigned int *) get_property
353 (root, "platform-open-pic", &oplen); 346 (root, "platform-open-pic", &oplen);
@@ -358,19 +351,15 @@ static void __init chrp_find_openpic(void)
358 oplen /= na * sizeof(unsigned int); 351 oplen /= na * sizeof(unsigned int);
359 } else { 352 } else {
360 struct resource r; 353 struct resource r;
361 if (of_address_to_resource(np, 0, &r)) 354 if (of_address_to_resource(np, 0, &r)) {
362 return; 355 goto bail;
356 }
363 opaddr = r.start; 357 opaddr = r.start;
364 oplen = 0; 358 oplen = 0;
365 } 359 }
366 360
367 printk(KERN_INFO "OpenPIC at %lx\n", opaddr); 361 printk(KERN_INFO "OpenPIC at %lx\n", opaddr);
368 362
369 irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
370 prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4);
371 /* i8259 cascade is always positive level */
372 init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE;
373
374 iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); 363 iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
375 if (iranges == NULL) 364 if (iranges == NULL)
376 len = 0; /* non-distributed mpic */ 365 len = 0; /* non-distributed mpic */
@@ -397,15 +386,12 @@ static void __init chrp_find_openpic(void)
397 if (len > 1) 386 if (len > 1)
398 isu_size = iranges[3]; 387 isu_size = iranges[3];
399 388
400 chrp_mpic = mpic_alloc(opaddr, MPIC_PRIMARY, 389 chrp_mpic = mpic_alloc(np, opaddr, MPIC_PRIMARY,
401 isu_size, NUM_ISA_INTERRUPTS, irq_count, 390 isu_size, 0, " MPIC ");
402 NR_IRQS - 4, init_senses, irq_count,
403 " MPIC ");
404 if (chrp_mpic == NULL) { 391 if (chrp_mpic == NULL) {
405 printk(KERN_ERR "Failed to allocate MPIC structure\n"); 392 printk(KERN_ERR "Failed to allocate MPIC structure\n");
406 return; 393 goto bail;
407 } 394 }
408
409 j = na - 1; 395 j = na - 1;
410 for (i = 1; i < len; ++i) { 396 for (i = 1; i < len; ++i) {
411 iranges += 2; 397 iranges += 2;
@@ -417,7 +403,10 @@ static void __init chrp_find_openpic(void)
417 } 403 }
418 404
419 mpic_init(chrp_mpic); 405 mpic_init(chrp_mpic);
420 set_irq_chained_handler(NUM_ISA_INTERRUPTS, chrp_8259_cascade); 406 ppc_md.get_irq = mpic_get_irq;
407 bail:
408 of_node_put(root);
409 of_node_put(np);
421} 410}
422 411
423#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) 412#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
@@ -428,14 +417,34 @@ static struct irqaction xmon_irqaction = {
428}; 417};
429#endif 418#endif
430 419
431void __init chrp_init_IRQ(void) 420static void __init chrp_find_8259(void)
432{ 421{
433 struct device_node *np; 422 struct device_node *np, *pic = NULL;
434 unsigned long chrp_int_ack = 0; 423 unsigned long chrp_int_ack = 0;
435#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) 424 unsigned int cascade_irq;
436 struct device_node *kbd;
437#endif
438 425
426 /* Look for cascade */
427 for_each_node_by_type(np, "interrupt-controller")
428 if (device_is_compatible(np, "chrp,iic")) {
429 pic = np;
430 break;
431 }
432 /* Ok, 8259 wasn't found. We need to handle the case where
433 * we have a pegasos that claims to be chrp but doesn't have
434 * a proper interrupt tree
435 */
436 if (pic == NULL && chrp_mpic != NULL) {
437 printk(KERN_ERR "i8259: Not found in device-tree"
438 " assuming no legacy interrupts\n");
439 return;
440 }
441
442 /* Look for intack. In a perfect world, we would look for it on
443 * the ISA bus that holds the 8259 but heh... Works that way. If
444 * we ever see a problem, we can try to re-use the pSeries code here.
445 * Also, Pegasos-type platforms don't have a proper node to start
446 * from anyway
447 */
439 for (np = find_devices("pci"); np != NULL; np = np->next) { 448 for (np = find_devices("pci"); np != NULL; np = np->next) {
440 unsigned int *addrp = (unsigned int *) 449 unsigned int *addrp = (unsigned int *)
441 get_property(np, "8259-interrupt-acknowledge", NULL); 450 get_property(np, "8259-interrupt-acknowledge", NULL);
@@ -446,11 +455,29 @@ void __init chrp_init_IRQ(void)
446 break; 455 break;
447 } 456 }
448 if (np == NULL) 457 if (np == NULL)
449 printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n"); 458 printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
459 " address, polling\n");
460
461 i8259_init(pic, chrp_int_ack);
462 if (ppc_md.get_irq == NULL)
463 ppc_md.get_irq = i8259_irq;
464 if (chrp_mpic != NULL) {
465 cascade_irq = irq_of_parse_and_map(pic, 0);
466 if (cascade_irq == NO_IRQ)
467 printk(KERN_ERR "i8259: failed to map cascade irq\n");
468 else
469 set_irq_chained_handler(cascade_irq,
470 chrp_8259_cascade);
471 }
472}
450 473
474void __init chrp_init_IRQ(void)
475{
476#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
477 struct device_node *kbd;
478#endif
451 chrp_find_openpic(); 479 chrp_find_openpic();
452 480 chrp_find_8259();
453 i8259_init(chrp_int_ack, 0);
454 481
455 if (_chrp_type == _CHRP_Pegasos) 482 if (_chrp_type == _CHRP_Pegasos)
456 ppc_md.get_irq = i8259_irq; 483 ppc_md.get_irq = i8259_irq;
@@ -535,10 +562,6 @@ static int __init chrp_probe(void)
535 DMA_MODE_READ = 0x44; 562 DMA_MODE_READ = 0x44;
536 DMA_MODE_WRITE = 0x48; 563 DMA_MODE_WRITE = 0x48;
537 isa_io_base = CHRP_ISA_IO_BASE; /* default value */ 564 isa_io_base = CHRP_ISA_IO_BASE; /* default value */
538 ppc_do_canonicalize_irqs = 1;
539
540 /* Assume we have an 8259... */
541 __irq_offset_value = NUM_ISA_INTERRUPTS;
542 565
543 return 1; 566 return 1;
544} 567}
@@ -550,7 +573,6 @@ define_machine(chrp) {
550 .init = chrp_init2, 573 .init = chrp_init2,
551 .show_cpuinfo = chrp_show_cpuinfo, 574 .show_cpuinfo = chrp_show_cpuinfo,
552 .init_IRQ = chrp_init_IRQ, 575 .init_IRQ = chrp_init_IRQ,
553 .get_irq = mpic_get_irq,
554 .pcibios_fixup = chrp_pcibios_fixup, 576 .pcibios_fixup = chrp_pcibios_fixup,
555 .restart = rtas_restart, 577 .restart = rtas_restart,
556 .power_off = rtas_power_off, 578 .power_off = rtas_power_off,
diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c
index c298ca1ea68..1d2307e87c3 100644
--- a/arch/powerpc/platforms/chrp/smp.c
+++ b/arch/powerpc/platforms/chrp/smp.c
@@ -29,7 +29,6 @@
29#include <asm/smp.h> 29#include <asm/smp.h>
30#include <asm/residual.h> 30#include <asm/residual.h>
31#include <asm/time.h> 31#include <asm/time.h>
32#include <asm/open_pic.h>
33#include <asm/machdep.h> 32#include <asm/machdep.h>
34#include <asm/smp.h> 33#include <asm/smp.h>
35#include <asm/mpic.h> 34#include <asm/mpic.h>