diff options
author | Tony Lindgren <tony@atomide.com> | 2011-05-16 05:07:38 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2011-05-16 05:28:58 -0400 |
commit | 667a11facee70c0bd15cf07946fba71236490e07 (patch) | |
tree | c7913b182e9b97e0f318a80ccc3e6ad1965afbf2 /arch/arm/mach-omap2 | |
parent | cfefd21e693dca791bf9ecfc9dd3794facad533c (diff) |
arm: omap2/3: Use generic irq chip
Use generic irq chip for omap2 & 3.
Note that this patch also leaves out the spurious IRQ warning
for omap3.
This warning should no longer be needed as the interrupt handlers
for various devices have implemented the necessayr read-back of
the posted write.
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/irq.c | 97 |
1 files changed, 25 insertions, 72 deletions
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 237e4530abf2..3af2b7a1045e 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c | |||
@@ -73,83 +73,18 @@ static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg) | |||
73 | return __raw_readl(bank->base_reg + reg); | 73 | return __raw_readl(bank->base_reg + reg); |
74 | } | 74 | } |
75 | 75 | ||
76 | static int previous_irq; | ||
77 | |||
78 | /* | ||
79 | * On 34xx we can get occasional spurious interrupts if the ack from | ||
80 | * an interrupt handler does not get posted before we unmask. Warn about | ||
81 | * the interrupt handlers that need to flush posted writes. | ||
82 | */ | ||
83 | static int omap_check_spurious(unsigned int irq) | ||
84 | { | ||
85 | u32 sir, spurious; | ||
86 | |||
87 | sir = intc_bank_read_reg(&irq_banks[0], INTC_SIR); | ||
88 | spurious = sir >> 7; | ||
89 | |||
90 | if (spurious) { | ||
91 | printk(KERN_WARNING "Spurious irq %i: 0x%08x, please flush " | ||
92 | "posted write for irq %i\n", | ||
93 | irq, sir, previous_irq); | ||
94 | return spurious; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* XXX: FIQ and additional INTC support (only MPU at the moment) */ | 76 | /* XXX: FIQ and additional INTC support (only MPU at the moment) */ |
101 | static void omap_ack_irq(struct irq_data *d) | 77 | static void omap_ack_irq(struct irq_data *d) |
102 | { | 78 | { |
103 | intc_bank_write_reg(0x1, &irq_banks[0], INTC_CONTROL); | 79 | intc_bank_write_reg(0x1, &irq_banks[0], INTC_CONTROL); |
104 | } | 80 | } |
105 | 81 | ||
106 | static void omap_mask_irq(struct irq_data *d) | ||
107 | { | ||
108 | unsigned int irq = d->irq; | ||
109 | int offset = irq & (~(IRQ_BITS_PER_REG - 1)); | ||
110 | |||
111 | if (cpu_is_omap34xx() && !cpu_is_ti816x()) { | ||
112 | int spurious = 0; | ||
113 | |||
114 | /* | ||
115 | * INT_34XX_GPT12_IRQ is also the spurious irq. Maybe because | ||
116 | * it is the highest irq number? | ||
117 | */ | ||
118 | if (irq == INT_34XX_GPT12_IRQ) | ||
119 | spurious = omap_check_spurious(irq); | ||
120 | |||
121 | if (!spurious) | ||
122 | previous_irq = irq; | ||
123 | } | ||
124 | |||
125 | irq &= (IRQ_BITS_PER_REG - 1); | ||
126 | |||
127 | intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset); | ||
128 | } | ||
129 | |||
130 | static void omap_unmask_irq(struct irq_data *d) | ||
131 | { | ||
132 | unsigned int irq = d->irq; | ||
133 | int offset = irq & (~(IRQ_BITS_PER_REG - 1)); | ||
134 | |||
135 | irq &= (IRQ_BITS_PER_REG - 1); | ||
136 | |||
137 | intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_CLEAR0 + offset); | ||
138 | } | ||
139 | |||
140 | static void omap_mask_ack_irq(struct irq_data *d) | 82 | static void omap_mask_ack_irq(struct irq_data *d) |
141 | { | 83 | { |
142 | omap_mask_irq(d); | 84 | irq_gc_mask_disable_reg(d); |
143 | omap_ack_irq(d); | 85 | omap_ack_irq(d); |
144 | } | 86 | } |
145 | 87 | ||
146 | static struct irq_chip omap_irq_chip = { | ||
147 | .name = "INTC", | ||
148 | .irq_ack = omap_mask_ack_irq, | ||
149 | .irq_mask = omap_mask_irq, | ||
150 | .irq_unmask = omap_unmask_irq, | ||
151 | }; | ||
152 | |||
153 | static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) | 88 | static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) |
154 | { | 89 | { |
155 | unsigned long tmp; | 90 | unsigned long tmp; |
@@ -186,11 +121,31 @@ int omap_irq_pending(void) | |||
186 | return 0; | 121 | return 0; |
187 | } | 122 | } |
188 | 123 | ||
124 | static __init void | ||
125 | omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) | ||
126 | { | ||
127 | struct irq_chip_generic *gc; | ||
128 | struct irq_chip_type *ct; | ||
129 | |||
130 | gc = irq_alloc_generic_chip("INTC", 1, irq_start, base, | ||
131 | handle_level_irq); | ||
132 | ct = gc->chip_types; | ||
133 | ct->chip.irq_ack = omap_mask_ack_irq; | ||
134 | ct->chip.irq_mask = irq_gc_mask_disable_reg; | ||
135 | ct->chip.irq_unmask = irq_gc_unmask_enable_reg; | ||
136 | |||
137 | ct->regs.ack = INTC_CONTROL; | ||
138 | ct->regs.enable = INTC_MIR_CLEAR0; | ||
139 | ct->regs.disable = INTC_MIR_SET0; | ||
140 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, | ||
141 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
142 | } | ||
143 | |||
189 | void __init omap_init_irq(void) | 144 | void __init omap_init_irq(void) |
190 | { | 145 | { |
191 | unsigned long nr_of_irqs = 0; | 146 | unsigned long nr_of_irqs = 0; |
192 | unsigned int nr_banks = 0; | 147 | unsigned int nr_banks = 0; |
193 | int i; | 148 | int i, j; |
194 | 149 | ||
195 | for (i = 0; i < ARRAY_SIZE(irq_banks); i++) { | 150 | for (i = 0; i < ARRAY_SIZE(irq_banks); i++) { |
196 | unsigned long base = 0; | 151 | unsigned long base = 0; |
@@ -215,17 +170,15 @@ void __init omap_init_irq(void) | |||
215 | 170 | ||
216 | omap_irq_bank_init_one(bank); | 171 | omap_irq_bank_init_one(bank); |
217 | 172 | ||
173 | for (i = 0, j = 0; i < bank->nr_irqs; i += 32, j += 0x20) | ||
174 | omap_alloc_gc(bank->base_reg + j, i, 32); | ||
175 | |||
218 | nr_of_irqs += bank->nr_irqs; | 176 | nr_of_irqs += bank->nr_irqs; |
219 | nr_banks++; | 177 | nr_banks++; |
220 | } | 178 | } |
221 | 179 | ||
222 | printk(KERN_INFO "Total of %ld interrupts on %d active controller%s\n", | 180 | printk(KERN_INFO "Total of %ld interrupts on %d active controller%s\n", |
223 | nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : ""); | 181 | nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : ""); |
224 | |||
225 | for (i = 0; i < nr_of_irqs; i++) { | ||
226 | irq_set_chip_and_handler(i, &omap_irq_chip, handle_level_irq); | ||
227 | set_irq_flags(i, IRQF_VALID); | ||
228 | } | ||
229 | } | 182 | } |
230 | 183 | ||
231 | #ifdef CONFIG_ARCH_OMAP3 | 184 | #ifdef CONFIG_ARCH_OMAP3 |