diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-08-24 09:49:17 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-08-24 09:49:17 -0400 |
commit | 12cceb6251c2cd23e936b25eca66be99ba41b081 (patch) | |
tree | b7f62853e67b305519c375162760422fbfc81b8e /drivers | |
parent | f13327864f94c3a0e6acca923df537d20059639f (diff) | |
parent | 05ecd5a1f76c183cca381705b3adb7d77c9a0439 (diff) |
Merge branch 'sh/st-integration'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/sh/intc.c | 62 |
1 files changed, 24 insertions, 38 deletions
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 3dd231a643b5..a9174ec72853 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c | |||
@@ -77,7 +77,7 @@ static unsigned long ack_handle[NR_IRQS]; | |||
77 | static inline struct intc_desc_int *get_intc_desc(unsigned int irq) | 77 | static 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 | ||
83 | static inline unsigned int set_field(unsigned int value, | 83 | static inline unsigned int set_field(unsigned int value, |
@@ -95,16 +95,19 @@ static inline unsigned int set_field(unsigned int value, | |||
95 | static void write_8(unsigned long addr, unsigned long h, unsigned long data) | 95 | static 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 | ||
100 | static void write_16(unsigned long addr, unsigned long h, unsigned long data) | 101 | static 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 | ||
105 | static void write_32(unsigned long addr, unsigned long h, unsigned long data) | 107 | static 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 | ||
110 | static void modify_8(unsigned long addr, unsigned long h, unsigned long data) | 113 | static 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 | ||
660 | static unsigned char *intc_evt2irq_table; | 666 | static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc) |
661 | |||
662 | unsigned 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 | ||
672 | void __init register_intc_controller(struct intc_desc *desc) | 671 | void __init register_intc_controller(struct intc_desc *desc) |
@@ -739,34 +738,6 @@ 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 */ | ||
743 | for (i = 0; i < desc->nr_vectors; i++) { | ||
744 | struct intc_vect *vect = desc->vectors + i; | ||
745 | int first_irq = evt2irq(vect->vect); | ||
746 | |||
747 | if (!vect->enum_id) | ||
748 | continue; | ||
749 | |||
750 | for (k = i + 1; k < desc->nr_vectors; k++) { | ||
751 | struct intc_vect *vect2 = desc->vectors + k; | ||
752 | |||
753 | if (vect->enum_id != vect2->enum_id) | ||
754 | continue; | ||
755 | |||
756 | vect2->enum_id = 0; | ||
757 | |||
758 | if (!intc_evt2irq_table) | ||
759 | intc_evt2irq_table = kzalloc(NR_IRQS, GFP_NOWAIT); | ||
760 | |||
761 | if (!intc_evt2irq_table) { | ||
762 | pr_warning("intc: cannot allocate evt2irq!\n"); | ||
763 | continue; | ||
764 | } | ||
765 | |||
766 | intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq; | ||
767 | } | ||
768 | } | ||
769 | |||
770 | /* register the vectors one by one */ | 741 | /* register the vectors one by one */ |
771 | for (i = 0; i < desc->nr_vectors; i++) { | 742 | for (i = 0; i < desc->nr_vectors; i++) { |
772 | struct intc_vect *vect = desc->vectors + i; | 743 | struct intc_vect *vect = desc->vectors + i; |
@@ -783,6 +754,21 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
783 | } | 754 | } |
784 | 755 | ||
785 | intc_register_irq(desc, d, vect->enum_id, irq); | 756 | intc_register_irq(desc, d, vect->enum_id, irq); |
757 | |||
758 | for (k = i + 1; k < desc->nr_vectors; k++) { | ||
759 | struct intc_vect *vect2 = desc->vectors + k; | ||
760 | unsigned int irq2 = evt2irq(vect2->vect); | ||
761 | |||
762 | if (vect->enum_id != vect2->enum_id) | ||
763 | continue; | ||
764 | |||
765 | vect2->enum_id = 0; | ||
766 | |||
767 | /* redirect this interrupts to the first one */ | ||
768 | set_irq_chip_and_handler_name(irq2, &d->chip, | ||
769 | intc_redirect_irq, "redirect"); | ||
770 | set_irq_data(irq2, (void *)irq); | ||
771 | } | ||
786 | } | 772 | } |
787 | } | 773 | } |
788 | 774 | ||