aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/irq.c')
-rw-r--r--arch/arm/mach-omap2/irq.c115
1 files changed, 37 insertions, 78 deletions
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 26aeef560aa3..3af2b7a1045e 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -47,7 +47,6 @@ static struct omap_irq_bank {
47} __attribute__ ((aligned(4))) irq_banks[] = { 47} __attribute__ ((aligned(4))) irq_banks[] = {
48 { 48 {
49 /* MPU INTC */ 49 /* MPU INTC */
50 .base_reg = 0,
51 .nr_irqs = 96, 50 .nr_irqs = 96,
52 }, 51 },
53}; 52};
@@ -62,8 +61,6 @@ struct omap3_intc_regs {
62 u32 mir[INTCPS_NR_MIR_REGS]; 61 u32 mir[INTCPS_NR_MIR_REGS];
63}; 62};
64 63
65static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
66
67/* INTC bank register get/set */ 64/* INTC bank register get/set */
68 65
69static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg) 66static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg)
@@ -76,81 +73,18 @@ static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg)
76 return __raw_readl(bank->base_reg + reg); 73 return __raw_readl(bank->base_reg + reg);
77} 74}
78 75
79static int previous_irq;
80
81/*
82 * On 34xx we can get occasional spurious interrupts if the ack from
83 * an interrupt handler does not get posted before we unmask. Warn about
84 * the interrupt handlers that need to flush posted writes.
85 */
86static int omap_check_spurious(unsigned int irq)
87{
88 u32 sir, spurious;
89
90 sir = intc_bank_read_reg(&irq_banks[0], INTC_SIR);
91 spurious = sir >> 7;
92
93 if (spurious) {
94 printk(KERN_WARNING "Spurious irq %i: 0x%08x, please flush "
95 "posted write for irq %i\n",
96 irq, sir, previous_irq);
97 return spurious;
98 }
99
100 return 0;
101}
102
103/* XXX: FIQ and additional INTC support (only MPU at the moment) */ 76/* XXX: FIQ and additional INTC support (only MPU at the moment) */
104static void omap_ack_irq(unsigned int irq) 77static void omap_ack_irq(struct irq_data *d)
105{ 78{
106 intc_bank_write_reg(0x1, &irq_banks[0], INTC_CONTROL); 79 intc_bank_write_reg(0x1, &irq_banks[0], INTC_CONTROL);
107} 80}
108 81
109static void omap_mask_irq(unsigned int irq) 82static void omap_mask_ack_irq(struct irq_data *d)
110{ 83{
111 int offset = irq & (~(IRQ_BITS_PER_REG - 1)); 84 irq_gc_mask_disable_reg(d);
112 85 omap_ack_irq(d);
113 if (cpu_is_omap34xx()) {
114 int spurious = 0;
115
116 /*
117 * INT_34XX_GPT12_IRQ is also the spurious irq. Maybe because
118 * it is the highest irq number?
119 */
120 if (irq == INT_34XX_GPT12_IRQ)
121 spurious = omap_check_spurious(irq);
122
123 if (!spurious)
124 previous_irq = irq;
125 }
126
127 irq &= (IRQ_BITS_PER_REG - 1);
128
129 intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset);
130} 86}
131 87
132static void omap_unmask_irq(unsigned int irq)
133{
134 int offset = irq & (~(IRQ_BITS_PER_REG - 1));
135
136 irq &= (IRQ_BITS_PER_REG - 1);
137
138 intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_CLEAR0 + offset);
139}
140
141static void omap_mask_ack_irq(unsigned int irq)
142{
143 omap_mask_irq(irq);
144 omap_ack_irq(irq);
145}
146
147static struct irq_chip omap_irq_chip = {
148 .name = "INTC",
149 .ack = omap_mask_ack_irq,
150 .mask = omap_mask_irq,
151 .unmask = omap_unmask_irq,
152};
153
154static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) 88static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
155{ 89{
156 unsigned long tmp; 90 unsigned long tmp;
@@ -187,11 +121,31 @@ int omap_irq_pending(void)
187 return 0; 121 return 0;
188} 122}
189 123
124static __init void
125omap_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
190void __init omap_init_irq(void) 144void __init omap_init_irq(void)
191{ 145{
192 unsigned long nr_of_irqs = 0; 146 unsigned long nr_of_irqs = 0;
193 unsigned int nr_banks = 0; 147 unsigned int nr_banks = 0;
194 int i; 148 int i, j;
195 149
196 for (i = 0; i < ARRAY_SIZE(irq_banks); i++) { 150 for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
197 unsigned long base = 0; 151 unsigned long base = 0;
@@ -204,6 +158,9 @@ void __init omap_init_irq(void)
204 158
205 BUG_ON(!base); 159 BUG_ON(!base);
206 160
161 if (cpu_is_ti816x())
162 bank->nr_irqs = 128;
163
207 /* Static mapping, never released */ 164 /* Static mapping, never released */
208 bank->base_reg = ioremap(base, SZ_4K); 165 bank->base_reg = ioremap(base, SZ_4K);
209 if (!bank->base_reg) { 166 if (!bank->base_reg) {
@@ -213,21 +170,20 @@ void __init omap_init_irq(void)
213 170
214 omap_irq_bank_init_one(bank); 171 omap_irq_bank_init_one(bank);
215 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
216 nr_of_irqs += bank->nr_irqs; 176 nr_of_irqs += bank->nr_irqs;
217 nr_banks++; 177 nr_banks++;
218 } 178 }
219 179
220 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",
221 nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : ""); 181 nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : "");
222
223 for (i = 0; i < nr_of_irqs; i++) {
224 set_irq_chip(i, &omap_irq_chip);
225 set_irq_handler(i, handle_level_irq);
226 set_irq_flags(i, IRQF_VALID);
227 }
228} 182}
229 183
230#ifdef CONFIG_ARCH_OMAP3 184#ifdef CONFIG_ARCH_OMAP3
185static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
186
231void omap_intc_save_context(void) 187void omap_intc_save_context(void)
232{ 188{
233 int ind = 0, i = 0; 189 int ind = 0, i = 0;
@@ -285,7 +241,10 @@ void omap3_intc_suspend(void)
285 241
286void omap3_intc_prepare_idle(void) 242void omap3_intc_prepare_idle(void)
287{ 243{
288 /* Disable autoidle as it can stall interrupt controller */ 244 /*
245 * Disable autoidle as it can stall interrupt controller,
246 * cf. errata ID i540 for 3430 (all revisions up to 3.1.x)
247 */
289 intc_bank_write_reg(0, &irq_banks[0], INTC_SYSCONFIG); 248 intc_bank_write_reg(0, &irq_banks[0], INTC_SYSCONFIG);
290} 249}
291 250