diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/xics.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 87 |
1 files changed, 12 insertions, 75 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index a977f200db89..43df53c30aa0 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -516,6 +516,8 @@ static struct irq_chip xics_pic_lpar = { | |||
516 | .set_affinity = xics_set_affinity | 516 | .set_affinity = xics_set_affinity |
517 | }; | 517 | }; |
518 | 518 | ||
519 | /* Points to the irq_chip we're actually using */ | ||
520 | static struct irq_chip *xics_irq_chip; | ||
519 | 521 | ||
520 | static int xics_host_match(struct irq_host *h, struct device_node *node) | 522 | static int xics_host_match(struct irq_host *h, struct device_node *node) |
521 | { | 523 | { |
@@ -526,23 +528,13 @@ static int xics_host_match(struct irq_host *h, struct device_node *node) | |||
526 | return !of_device_is_compatible(node, "chrp,iic"); | 528 | return !of_device_is_compatible(node, "chrp,iic"); |
527 | } | 529 | } |
528 | 530 | ||
529 | static int xics_host_map_direct(struct irq_host *h, unsigned int virq, | 531 | static int xics_host_map(struct irq_host *h, unsigned int virq, |
530 | irq_hw_number_t hw) | 532 | irq_hw_number_t hw) |
531 | { | 533 | { |
532 | pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw); | 534 | pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw); |
533 | 535 | ||
534 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 536 | get_irq_desc(virq)->status |= IRQ_LEVEL; |
535 | set_irq_chip_and_handler(virq, &xics_pic_direct, handle_fasteoi_irq); | 537 | set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq); |
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static int xics_host_map_lpar(struct irq_host *h, unsigned int virq, | ||
540 | irq_hw_number_t hw) | ||
541 | { | ||
542 | pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw); | ||
543 | |||
544 | get_irq_desc(virq)->status |= IRQ_LEVEL; | ||
545 | set_irq_chip_and_handler(virq, &xics_pic_lpar, handle_fasteoi_irq); | ||
546 | return 0; | 538 | return 0; |
547 | } | 539 | } |
548 | 540 | ||
@@ -561,27 +553,20 @@ static int xics_host_xlate(struct irq_host *h, struct device_node *ct, | |||
561 | return 0; | 553 | return 0; |
562 | } | 554 | } |
563 | 555 | ||
564 | static struct irq_host_ops xics_host_direct_ops = { | 556 | static struct irq_host_ops xics_host_ops = { |
565 | .match = xics_host_match, | 557 | .match = xics_host_match, |
566 | .map = xics_host_map_direct, | 558 | .map = xics_host_map, |
567 | .xlate = xics_host_xlate, | ||
568 | }; | ||
569 | |||
570 | static struct irq_host_ops xics_host_lpar_ops = { | ||
571 | .match = xics_host_match, | ||
572 | .map = xics_host_map_lpar, | ||
573 | .xlate = xics_host_xlate, | 559 | .xlate = xics_host_xlate, |
574 | }; | 560 | }; |
575 | 561 | ||
576 | static void __init xics_init_host(void) | 562 | static void __init xics_init_host(void) |
577 | { | 563 | { |
578 | struct irq_host_ops *ops; | ||
579 | |||
580 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 564 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
581 | ops = &xics_host_lpar_ops; | 565 | xics_irq_chip = &xics_pic_lpar; |
582 | else | 566 | else |
583 | ops = &xics_host_direct_ops; | 567 | xics_irq_chip = &xics_pic_direct; |
584 | xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, ops, | 568 | |
569 | xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, &xics_host_ops, | ||
585 | XICS_IRQ_SPURIOUS); | 570 | XICS_IRQ_SPURIOUS); |
586 | BUG_ON(xics_host == NULL); | 571 | BUG_ON(xics_host == NULL); |
587 | irq_set_default_host(xics_host); | 572 | irq_set_default_host(xics_host); |
@@ -655,52 +640,6 @@ static void __init xics_init_one_node(struct device_node *np, | |||
655 | } | 640 | } |
656 | } | 641 | } |
657 | 642 | ||
658 | |||
659 | static void __init xics_setup_8259_cascade(void) | ||
660 | { | ||
661 | struct device_node *np, *old, *found = NULL; | ||
662 | int cascade, naddr; | ||
663 | const u32 *addrp; | ||
664 | unsigned long intack = 0; | ||
665 | |||
666 | for_each_node_by_type(np, "interrupt-controller") | ||
667 | if (of_device_is_compatible(np, "chrp,iic")) { | ||
668 | found = np; | ||
669 | break; | ||
670 | } | ||
671 | if (found == NULL) { | ||
672 | printk(KERN_DEBUG "xics: no ISA interrupt controller\n"); | ||
673 | return; | ||
674 | } | ||
675 | cascade = irq_of_parse_and_map(found, 0); | ||
676 | if (cascade == NO_IRQ) { | ||
677 | printk(KERN_ERR "xics: failed to map cascade interrupt"); | ||
678 | return; | ||
679 | } | ||
680 | pr_debug("xics: cascade mapped to irq %d\n", cascade); | ||
681 | |||
682 | for (old = of_node_get(found); old != NULL ; old = np) { | ||
683 | np = of_get_parent(old); | ||
684 | of_node_put(old); | ||
685 | if (np == NULL) | ||
686 | break; | ||
687 | if (strcmp(np->name, "pci") != 0) | ||
688 | continue; | ||
689 | addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); | ||
690 | if (addrp == NULL) | ||
691 | continue; | ||
692 | naddr = of_n_addr_cells(np); | ||
693 | intack = addrp[naddr-1]; | ||
694 | if (naddr > 1) | ||
695 | intack |= ((unsigned long)addrp[naddr-2]) << 32; | ||
696 | } | ||
697 | if (intack) | ||
698 | printk(KERN_DEBUG "xics: PCI 8259 intack at 0x%016lx\n", intack); | ||
699 | i8259_init(found, intack); | ||
700 | of_node_put(found); | ||
701 | set_irq_chained_handler(cascade, pseries_8259_cascade); | ||
702 | } | ||
703 | |||
704 | void __init xics_init_IRQ(void) | 643 | void __init xics_init_IRQ(void) |
705 | { | 644 | { |
706 | struct device_node *np; | 645 | struct device_node *np; |
@@ -733,8 +672,6 @@ void __init xics_init_IRQ(void) | |||
733 | 672 | ||
734 | xics_setup_cpu(); | 673 | xics_setup_cpu(); |
735 | 674 | ||
736 | xics_setup_8259_cascade(); | ||
737 | |||
738 | ppc64_boot_msg(0x21, "XICS Done"); | 675 | ppc64_boot_msg(0x21, "XICS Done"); |
739 | } | 676 | } |
740 | 677 | ||