aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh/intc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sh/intc.c')
-rw-r--r--drivers/sh/intc.c71
1 files changed, 34 insertions, 37 deletions
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 3dd231a643b5..559b5fe9dc0f 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -77,7 +77,7 @@ static unsigned long ack_handle[NR_IRQS];
77static inline struct intc_desc_int *get_intc_desc(unsigned int irq) 77static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
78{ 78{
79 struct irq_chip *chip = get_irq_chip(irq); 79 struct irq_chip *chip = get_irq_chip(irq);
80 return (void *)((char *)chip - offsetof(struct intc_desc_int, chip)); 80 return container_of(chip, struct intc_desc_int, chip);
81} 81}
82 82
83static inline unsigned int set_field(unsigned int value, 83static inline unsigned int set_field(unsigned int value,
@@ -95,16 +95,19 @@ static inline unsigned int set_field(unsigned int value,
95static void write_8(unsigned long addr, unsigned long h, unsigned long data) 95static void write_8(unsigned long addr, unsigned long h, unsigned long data)
96{ 96{
97 __raw_writeb(set_field(0, data, h), addr); 97 __raw_writeb(set_field(0, data, h), addr);
98 (void)__raw_readb(addr); /* Defeat write posting */
98} 99}
99 100
100static void write_16(unsigned long addr, unsigned long h, unsigned long data) 101static void write_16(unsigned long addr, unsigned long h, unsigned long data)
101{ 102{
102 __raw_writew(set_field(0, data, h), addr); 103 __raw_writew(set_field(0, data, h), addr);
104 (void)__raw_readw(addr); /* Defeat write posting */
103} 105}
104 106
105static void write_32(unsigned long addr, unsigned long h, unsigned long data) 107static void write_32(unsigned long addr, unsigned long h, unsigned long data)
106{ 108{
107 __raw_writel(set_field(0, data, h), addr); 109 __raw_writel(set_field(0, data, h), addr);
110 (void)__raw_readl(addr); /* Defeat write posting */
108} 111}
109 112
110static void modify_8(unsigned long addr, unsigned long h, unsigned long data) 113static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
@@ -112,6 +115,7 @@ static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
112 unsigned long flags; 115 unsigned long flags;
113 local_irq_save(flags); 116 local_irq_save(flags);
114 __raw_writeb(set_field(__raw_readb(addr), data, h), addr); 117 __raw_writeb(set_field(__raw_readb(addr), data, h), addr);
118 (void)__raw_readb(addr); /* Defeat write posting */
115 local_irq_restore(flags); 119 local_irq_restore(flags);
116} 120}
117 121
@@ -120,6 +124,7 @@ static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
120 unsigned long flags; 124 unsigned long flags;
121 local_irq_save(flags); 125 local_irq_save(flags);
122 __raw_writew(set_field(__raw_readw(addr), data, h), addr); 126 __raw_writew(set_field(__raw_readw(addr), data, h), addr);
127 (void)__raw_readw(addr); /* Defeat write posting */
123 local_irq_restore(flags); 128 local_irq_restore(flags);
124} 129}
125 130
@@ -128,6 +133,7 @@ static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
128 unsigned long flags; 133 unsigned long flags;
129 local_irq_save(flags); 134 local_irq_save(flags);
130 __raw_writel(set_field(__raw_readl(addr), data, h), addr); 135 __raw_writel(set_field(__raw_readl(addr), data, h), addr);
136 (void)__raw_readl(addr); /* Defeat write posting */
131 local_irq_restore(flags); 137 local_irq_restore(flags);
132} 138}
133 139
@@ -657,16 +663,9 @@ static unsigned int __init save_reg(struct intc_desc_int *d,
657 return 0; 663 return 0;
658} 664}
659 665
660static unsigned char *intc_evt2irq_table; 666static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
661
662unsigned int intc_evt2irq(unsigned int vector)
663{ 667{
664 unsigned int irq = evt2irq(vector); 668 generic_handle_irq((unsigned int)get_irq_data(irq));
665
666 if (intc_evt2irq_table && intc_evt2irq_table[irq])
667 irq = intc_evt2irq_table[irq];
668
669 return irq;
670} 669}
671 670
672void __init register_intc_controller(struct intc_desc *desc) 671void __init register_intc_controller(struct intc_desc *desc)
@@ -739,50 +738,48 @@ void __init register_intc_controller(struct intc_desc *desc)
739 738
740 BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ 739 BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
741 740
742 /* keep the first vector only if same enum is used multiple times */ 741 /* register the vectors one by one */
743 for (i = 0; i < desc->nr_vectors; i++) { 742 for (i = 0; i < desc->nr_vectors; i++) {
744 struct intc_vect *vect = desc->vectors + i; 743 struct intc_vect *vect = desc->vectors + i;
745 int first_irq = evt2irq(vect->vect); 744 unsigned int irq = evt2irq(vect->vect);
745 struct irq_desc *irq_desc;
746 746
747 if (!vect->enum_id) 747 if (!vect->enum_id)
748 continue; 748 continue;
749 749
750 irq_desc = irq_to_desc_alloc_node(irq, numa_node_id());
751 if (unlikely(!irq_desc)) {
752 pr_info("can't get irq_desc for %d\n", irq);
753 continue;
754 }
755
756 intc_register_irq(desc, d, vect->enum_id, irq);
757
750 for (k = i + 1; k < desc->nr_vectors; k++) { 758 for (k = i + 1; k < desc->nr_vectors; k++) {
751 struct intc_vect *vect2 = desc->vectors + k; 759 struct intc_vect *vect2 = desc->vectors + k;
760 unsigned int irq2 = evt2irq(vect2->vect);
752 761
753 if (vect->enum_id != vect2->enum_id) 762 if (vect->enum_id != vect2->enum_id)
754 continue; 763 continue;
755 764
756 vect2->enum_id = 0; 765 /*
757 766 * In the case of multi-evt handling and sparse
758 if (!intc_evt2irq_table) 767 * IRQ support, each vector still needs to have
759 intc_evt2irq_table = kzalloc(NR_IRQS, GFP_NOWAIT); 768 * its own backing irq_desc.
760 769 */
761 if (!intc_evt2irq_table) { 770 irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id());
762 pr_warning("intc: cannot allocate evt2irq!\n"); 771 if (unlikely(!irq_desc)) {
772 pr_info("can't get irq_desc for %d\n", irq2);
763 continue; 773 continue;
764 } 774 }
765 775
766 intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq; 776 vect2->enum_id = 0;
767 }
768 }
769
770 /* register the vectors one by one */
771 for (i = 0; i < desc->nr_vectors; i++) {
772 struct intc_vect *vect = desc->vectors + i;
773 unsigned int irq = evt2irq(vect->vect);
774 struct irq_desc *irq_desc;
775
776 if (!vect->enum_id)
777 continue;
778 777
779 irq_desc = irq_to_desc_alloc_node(irq, numa_node_id()); 778 /* redirect this interrupts to the first one */
780 if (unlikely(!irq_desc)) { 779 set_irq_chip_and_handler_name(irq2, &d->chip,
781 printk(KERN_INFO "can not get irq_desc for %d\n", irq); 780 intc_redirect_irq, "redirect");
782 continue; 781 set_irq_data(irq2, (void *)irq);
783 } 782 }
784
785 intc_register_irq(desc, d, vect->enum_id, irq);
786 } 783 }
787} 784}
788 785