diff options
Diffstat (limited to 'arch/powerpc/platforms/powermac/pic.c')
-rw-r--r-- | arch/powerpc/platforms/powermac/pic.c | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index dbb524a851aa..18bf3011d1e3 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
@@ -524,18 +524,56 @@ static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) | |||
524 | #endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */ | 524 | #endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */ |
525 | } | 525 | } |
526 | 526 | ||
527 | static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, | ||
528 | int master) | ||
529 | { | ||
530 | unsigned char senses[128]; | ||
531 | int offset = master ? 0 : 128; | ||
532 | int count = master ? 128 : 124; | ||
533 | const char *name = master ? " MPIC 1 " : " MPIC 2 "; | ||
534 | struct resource r; | ||
535 | struct mpic *mpic; | ||
536 | unsigned int flags = master ? MPIC_PRIMARY : 0; | ||
537 | int rc; | ||
538 | |||
539 | rc = of_address_to_resource(np, 0, &r); | ||
540 | if (rc) | ||
541 | return NULL; | ||
542 | |||
543 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0); | ||
544 | |||
545 | prom_get_irq_senses(senses, offset, offset + count); | ||
546 | |||
547 | flags |= MPIC_WANTS_RESET; | ||
548 | if (get_property(np, "big-endian", NULL)) | ||
549 | flags |= MPIC_BIG_ENDIAN; | ||
550 | |||
551 | /* Primary Big Endian means HT interrupts. This is quite dodgy | ||
552 | * but works until I find a better way | ||
553 | */ | ||
554 | if (master && (flags & MPIC_BIG_ENDIAN)) | ||
555 | flags |= MPIC_BROKEN_U3; | ||
556 | |||
557 | mpic = mpic_alloc(r.start, flags, 0, offset, count, master ? 252 : 0, | ||
558 | senses, count, name); | ||
559 | if (mpic == NULL) | ||
560 | return NULL; | ||
561 | |||
562 | mpic_init(mpic); | ||
563 | |||
564 | return mpic; | ||
565 | } | ||
566 | |||
527 | static int __init pmac_pic_probe_mpic(void) | 567 | static int __init pmac_pic_probe_mpic(void) |
528 | { | 568 | { |
529 | struct mpic *mpic1, *mpic2; | 569 | struct mpic *mpic1, *mpic2; |
530 | struct device_node *np, *master = NULL, *slave = NULL; | 570 | struct device_node *np, *master = NULL, *slave = NULL; |
531 | unsigned char senses[128]; | ||
532 | struct resource r; | ||
533 | 571 | ||
534 | /* We can have up to 2 MPICs cascaded */ | 572 | /* We can have up to 2 MPICs cascaded */ |
535 | for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) | 573 | for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) |
536 | != NULL;) { | 574 | != NULL;) { |
537 | if (master == NULL && | 575 | if (master == NULL && |
538 | get_property(np, "interrupt-parent", NULL) != NULL) | 576 | get_property(np, "interrupts", NULL) == NULL) |
539 | master = of_node_get(np); | 577 | master = of_node_get(np); |
540 | else if (slave == NULL) | 578 | else if (slave == NULL) |
541 | slave = of_node_get(np); | 579 | slave = of_node_get(np); |
@@ -557,13 +595,8 @@ static int __init pmac_pic_probe_mpic(void) | |||
557 | ppc_md.get_irq = mpic_get_irq; | 595 | ppc_md.get_irq = mpic_get_irq; |
558 | 596 | ||
559 | /* Setup master */ | 597 | /* Setup master */ |
560 | BUG_ON(of_address_to_resource(master, 0, &r)); | 598 | mpic1 = pmac_setup_one_mpic(master, 1); |
561 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, master, 0, 0); | ||
562 | prom_get_irq_senses(senses, 0, 128); | ||
563 | mpic1 = mpic_alloc(r.start, MPIC_PRIMARY | MPIC_WANTS_RESET, | ||
564 | 0, 0, 128, 252, senses, 128, " OpenPIC "); | ||
565 | BUG_ON(mpic1 == NULL); | 599 | BUG_ON(mpic1 == NULL); |
566 | mpic_init(mpic1); | ||
567 | 600 | ||
568 | /* Install NMI if any */ | 601 | /* Install NMI if any */ |
569 | pmac_pic_setup_mpic_nmi(mpic1); | 602 | pmac_pic_setup_mpic_nmi(mpic1); |
@@ -574,27 +607,12 @@ static int __init pmac_pic_probe_mpic(void) | |||
574 | if (slave == NULL || slave->n_intrs < 1) | 607 | if (slave == NULL || slave->n_intrs < 1) |
575 | return 0; | 608 | return 0; |
576 | 609 | ||
577 | /* Setup slave, failures are non-fatal */ | 610 | mpic2 = pmac_setup_one_mpic(slave, 0); |
578 | if (of_address_to_resource(slave, 0, &r)) { | ||
579 | printk(KERN_ERR "Can't get address of MPIC %s\n", | ||
580 | slave->full_name); | ||
581 | return 0; | ||
582 | } | ||
583 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, slave, 0, 0); | ||
584 | prom_get_irq_senses(senses, 128, 128 + 124); | ||
585 | |||
586 | /* We don't need to set MPIC_BROKEN_U3 here since we don't have | ||
587 | * hypertransport interrupts routed to it, at least not on currently | ||
588 | * supported machines, that may change. | ||
589 | */ | ||
590 | mpic2 = mpic_alloc(r.start, MPIC_BIG_ENDIAN | MPIC_WANTS_RESET, | ||
591 | 0, 128, 124, 0, senses, 124, " U3-MPIC "); | ||
592 | if (mpic2 == NULL) { | 611 | if (mpic2 == NULL) { |
593 | printk(KERN_ERR "Can't create slave MPIC %s\n", | 612 | printk(KERN_ERR "Failed to setup slave MPIC\n"); |
594 | slave->full_name); | 613 | of_node_put(slave); |
595 | return 0; | 614 | return 0; |
596 | } | 615 | } |
597 | mpic_init(mpic2); | ||
598 | mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2); | 616 | mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2); |
599 | 617 | ||
600 | of_node_put(slave); | 618 | of_node_put(slave); |