diff options
Diffstat (limited to 'drivers/sh/intc.c')
-rw-r--r-- | drivers/sh/intc.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 58d24c5a76ce..d7b8959d9d92 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c | |||
@@ -568,6 +568,10 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
568 | if (!data[0] && data[1]) | 568 | if (!data[0] && data[1]) |
569 | primary = 1; | 569 | primary = 1; |
570 | 570 | ||
571 | if (!data[0] && !data[1]) | ||
572 | pr_warning("intc: missing unique irq mask for 0x%04x\n", | ||
573 | irq2evt(irq)); | ||
574 | |||
571 | data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1); | 575 | data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1); |
572 | data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1); | 576 | data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1); |
573 | 577 | ||
@@ -641,6 +645,17 @@ static unsigned int __init save_reg(struct intc_desc_int *d, | |||
641 | return 0; | 645 | return 0; |
642 | } | 646 | } |
643 | 647 | ||
648 | static unsigned char *intc_evt2irq_table; | ||
649 | |||
650 | unsigned int intc_evt2irq(unsigned int vector) | ||
651 | { | ||
652 | unsigned int irq = evt2irq(vector); | ||
653 | |||
654 | if (intc_evt2irq_table && intc_evt2irq_table[irq]) | ||
655 | irq = intc_evt2irq_table[irq]; | ||
656 | |||
657 | return irq; | ||
658 | } | ||
644 | 659 | ||
645 | void __init register_intc_controller(struct intc_desc *desc) | 660 | void __init register_intc_controller(struct intc_desc *desc) |
646 | { | 661 | { |
@@ -705,9 +720,41 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
705 | 720 | ||
706 | BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ | 721 | BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ |
707 | 722 | ||
723 | /* keep the first vector only if same enum is used multiple times */ | ||
724 | for (i = 0; i < desc->nr_vectors; i++) { | ||
725 | struct intc_vect *vect = desc->vectors + i; | ||
726 | int first_irq = evt2irq(vect->vect); | ||
727 | |||
728 | if (!vect->enum_id) | ||
729 | continue; | ||
730 | |||
731 | for (k = i + 1; k < desc->nr_vectors; k++) { | ||
732 | struct intc_vect *vect2 = desc->vectors + k; | ||
733 | |||
734 | if (vect->enum_id != vect2->enum_id) | ||
735 | continue; | ||
736 | |||
737 | vect2->enum_id = 0; | ||
738 | |||
739 | if (!intc_evt2irq_table) | ||
740 | intc_evt2irq_table = alloc_bootmem(NR_IRQS); | ||
741 | |||
742 | if (!intc_evt2irq_table) { | ||
743 | pr_warning("intc: cannot allocate evt2irq!\n"); | ||
744 | continue; | ||
745 | } | ||
746 | |||
747 | intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq; | ||
748 | } | ||
749 | } | ||
750 | |||
751 | /* register the vectors one by one */ | ||
708 | for (i = 0; i < desc->nr_vectors; i++) { | 752 | for (i = 0; i < desc->nr_vectors; i++) { |
709 | struct intc_vect *vect = desc->vectors + i; | 753 | struct intc_vect *vect = desc->vectors + i; |
710 | 754 | ||
755 | if (!vect->enum_id) | ||
756 | continue; | ||
757 | |||
711 | intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect)); | 758 | intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect)); |
712 | } | 759 | } |
713 | } | 760 | } |