blob: d45d0c59fac76730d7ea8c8fd71a351660d69f0e [file] [log] [blame]
Bryan Wu1394f032007-05-06 14:50:22 -07001/*
Michael Hennerichcfefe3c2008-02-09 04:12:37 +08002 * File: arch/blackfin/mach-common/ints-priority.c
Bryan Wu1394f032007-05-06 14:50:22 -07003 *
Simon Arlottd2d50aa2007-06-11 15:31:30 +08004 * Description: Set up the interrupt priorities
Bryan Wu1394f032007-05-06 14:50:22 -07005 *
6 * Modified:
7 * 1996 Roman Zippel
8 * 1999 D. Jeff Dionne <jeff@uclinux.org>
9 * 2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca>
10 * 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
11 * 2003 Metrowerks/Motorola
12 * 2003 Bas Vermeulen <bas@buyways.nl>
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080013 * Copyright 2004-2008 Analog Devices Inc.
Bryan Wu1394f032007-05-06 14:50:22 -070014 *
15 * Bugs: Enter bugs at http://blackfin.uclinux.org/
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, see the file COPYING, or write
29 * to the Free Software Foundation, Inc.,
30 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 */
32
33#include <linux/module.h>
34#include <linux/kernel_stat.h>
35#include <linux/seq_file.h>
36#include <linux/irq.h>
37#ifdef CONFIG_KGDB
38#include <linux/kgdb.h>
39#endif
40#include <asm/traps.h>
41#include <asm/blackfin.h>
42#include <asm/gpio.h>
43#include <asm/irq_handler.h>
44
45#ifdef BF537_FAMILY
46# define BF537_GENERIC_ERROR_INT_DEMUX
47#else
48# undef BF537_GENERIC_ERROR_INT_DEMUX
49#endif
50
51/*
52 * NOTES:
53 * - we have separated the physical Hardware interrupt from the
54 * levels that the LINUX kernel sees (see the description in irq.h)
55 * -
56 */
57
Mike Frysingera99bbcc2007-10-22 00:19:31 +080058/* Initialize this to an actual value to force it into the .data
59 * section so that we know it is properly initialized at entry into
60 * the kernel but before bss is initialized to zero (which is where
61 * it would live otherwise). The 0x1f magic represents the IRQs we
62 * cannot actually mask out in hardware.
63 */
64unsigned long irq_flags = 0x1f;
Mike Frysingerfe8015c2008-10-28 11:07:15 +080065EXPORT_SYMBOL(irq_flags);
Bryan Wu1394f032007-05-06 14:50:22 -070066
67/* The number of spurious interrupts */
68atomic_t num_spurious;
69
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080070#ifdef CONFIG_PM
71unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */
Michael Hennerich4a88d0c2008-08-05 17:38:41 +080072unsigned vr_wakeup;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080073#endif
74
Bryan Wu1394f032007-05-06 14:50:22 -070075struct ivgx {
Michael Hennerich464abc52008-02-25 13:50:20 +080076 /* irq number for request_irq, available in mach-bf5xx/irq.h */
Roy Huang24a07a12007-07-12 22:41:45 +080077 unsigned int irqno;
Bryan Wu1394f032007-05-06 14:50:22 -070078 /* corresponding bit in the SIC_ISR register */
Roy Huang24a07a12007-07-12 22:41:45 +080079 unsigned int isrflag;
Bryan Wu1394f032007-05-06 14:50:22 -070080} ivg_table[NR_PERI_INTS];
81
82struct ivg_slice {
83 /* position of first irq in ivg_table for given ivg */
84 struct ivgx *ifirst;
85 struct ivgx *istop;
86} ivg7_13[IVG13 - IVG7 + 1];
87
Bryan Wu1394f032007-05-06 14:50:22 -070088
89/*
90 * Search SIC_IAR and fill tables with the irqvalues
91 * and their positions in the SIC_ISR register.
92 */
93static void __init search_IAR(void)
94{
95 unsigned ivg, irq_pos = 0;
96 for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
97 int irqn;
98
Michael Hennerich34e0fc82007-07-12 16:17:18 +080099 ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
Bryan Wu1394f032007-05-06 14:50:22 -0700100
101 for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
102 int iar_shift = (irqn & 7) * 4;
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800103 if (ivg == (0xf &
Bryan Wu2f6f4bc2008-11-18 17:48:21 +0800104#if defined(CONFIG_BF52x) || defined(CONFIG_BF538) \
105 || defined(CONFIG_BF539) || defined(CONFIG_BF51x)
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800106 bfin_read32((unsigned long *)SIC_IAR0 +
Michael Hennerichdc26aec2008-11-18 17:48:22 +0800107 ((irqn % 32) >> 3) + ((irqn / 32) *
108 ((SIC_IAR4 - SIC_IAR0) / 4))) >> iar_shift)) {
Michael Hennerich59003142007-10-21 16:54:27 +0800109#else
110 bfin_read32((unsigned long *)SIC_IAR0 +
Michael Hennerichdc26aec2008-11-18 17:48:22 +0800111 (irqn >> 3)) >> iar_shift)) {
Michael Hennerich59003142007-10-21 16:54:27 +0800112#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700113 ivg_table[irq_pos].irqno = IVG7 + irqn;
Roy Huang24a07a12007-07-12 22:41:45 +0800114 ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
Bryan Wu1394f032007-05-06 14:50:22 -0700115 ivg7_13[ivg].istop++;
116 irq_pos++;
117 }
118 }
119 }
120}
121
122/*
Michael Hennerich464abc52008-02-25 13:50:20 +0800123 * This is for core internal IRQs
Bryan Wu1394f032007-05-06 14:50:22 -0700124 */
125
Michael Hennerich464abc52008-02-25 13:50:20 +0800126static void bfin_ack_noop(unsigned int irq)
Bryan Wu1394f032007-05-06 14:50:22 -0700127{
128 /* Dummy function. */
129}
130
131static void bfin_core_mask_irq(unsigned int irq)
132{
133 irq_flags &= ~(1 << irq);
134 if (!irqs_disabled())
135 local_irq_enable();
136}
137
138static void bfin_core_unmask_irq(unsigned int irq)
139{
140 irq_flags |= 1 << irq;
141 /*
142 * If interrupts are enabled, IMASK must contain the same value
143 * as irq_flags. Make sure that invariant holds. If interrupts
144 * are currently disabled we need not do anything; one of the
145 * callers will take care of setting IMASK to the proper value
146 * when reenabling interrupts.
147 * local_irq_enable just does "STI irq_flags", so it's exactly
148 * what we need.
149 */
150 if (!irqs_disabled())
151 local_irq_enable();
152 return;
153}
154
155static void bfin_internal_mask_irq(unsigned int irq)
156{
Michael Hennerich59003142007-10-21 16:54:27 +0800157#ifdef CONFIG_BF53x
Bryan Wu1394f032007-05-06 14:50:22 -0700158 bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
Michael Hennerich464abc52008-02-25 13:50:20 +0800159 ~(1 << SIC_SYSIRQ(irq)));
Roy Huang24a07a12007-07-12 22:41:45 +0800160#else
161 unsigned mask_bank, mask_bit;
Michael Hennerich464abc52008-02-25 13:50:20 +0800162 mask_bank = SIC_SYSIRQ(irq) / 32;
163 mask_bit = SIC_SYSIRQ(irq) % 32;
Bryan Wuc04d66b2007-07-12 17:26:31 +0800164 bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
165 ~(1 << mask_bit));
Roy Huang24a07a12007-07-12 22:41:45 +0800166#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700167}
168
169static void bfin_internal_unmask_irq(unsigned int irq)
170{
Michael Hennerich59003142007-10-21 16:54:27 +0800171#ifdef CONFIG_BF53x
Bryan Wu1394f032007-05-06 14:50:22 -0700172 bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
Michael Hennerich464abc52008-02-25 13:50:20 +0800173 (1 << SIC_SYSIRQ(irq)));
Roy Huang24a07a12007-07-12 22:41:45 +0800174#else
175 unsigned mask_bank, mask_bit;
Michael Hennerich464abc52008-02-25 13:50:20 +0800176 mask_bank = SIC_SYSIRQ(irq) / 32;
177 mask_bit = SIC_SYSIRQ(irq) % 32;
Bryan Wuc04d66b2007-07-12 17:26:31 +0800178 bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) |
179 (1 << mask_bit));
Roy Huang24a07a12007-07-12 22:41:45 +0800180#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700181}
182
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800183#ifdef CONFIG_PM
184int bfin_internal_set_wake(unsigned int irq, unsigned int state)
185{
Michael Hennerich8d022372008-11-18 17:48:22 +0800186 u32 bank, bit, wakeup = 0;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800187 unsigned long flags;
Michael Hennerich464abc52008-02-25 13:50:20 +0800188 bank = SIC_SYSIRQ(irq) / 32;
189 bit = SIC_SYSIRQ(irq) % 32;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800190
Michael Hennerich4a88d0c2008-08-05 17:38:41 +0800191 switch (irq) {
192#ifdef IRQ_RTC
193 case IRQ_RTC:
194 wakeup |= WAKE;
195 break;
196#endif
197#ifdef IRQ_CAN0_RX
198 case IRQ_CAN0_RX:
199 wakeup |= CANWE;
200 break;
201#endif
202#ifdef IRQ_CAN1_RX
203 case IRQ_CAN1_RX:
204 wakeup |= CANWE;
205 break;
206#endif
207#ifdef IRQ_USB_INT0
208 case IRQ_USB_INT0:
209 wakeup |= USBWE;
210 break;
211#endif
212#ifdef IRQ_KEY
213 case IRQ_KEY:
214 wakeup |= KPADWE;
215 break;
216#endif
Michael Hennerichd310fb42008-08-28 17:32:01 +0800217#ifdef CONFIG_BF54x
Michael Hennerich4a88d0c2008-08-05 17:38:41 +0800218 case IRQ_CNT:
219 wakeup |= ROTWE;
220 break;
221#endif
222 default:
223 break;
224 }
225
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800226 local_irq_save(flags);
227
Michael Hennerich4a88d0c2008-08-05 17:38:41 +0800228 if (state) {
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800229 bfin_sic_iwr[bank] |= (1 << bit);
Michael Hennerich4a88d0c2008-08-05 17:38:41 +0800230 vr_wakeup |= wakeup;
231
232 } else {
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800233 bfin_sic_iwr[bank] &= ~(1 << bit);
Michael Hennerich4a88d0c2008-08-05 17:38:41 +0800234 vr_wakeup &= ~wakeup;
235 }
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800236
237 local_irq_restore(flags);
238
239 return 0;
240}
241#endif
242
Bryan Wu1394f032007-05-06 14:50:22 -0700243static struct irq_chip bfin_core_irqchip = {
Graf Yang763e63c2008-10-08 17:08:15 +0800244 .name = "CORE",
Michael Hennerich464abc52008-02-25 13:50:20 +0800245 .ack = bfin_ack_noop,
Bryan Wu1394f032007-05-06 14:50:22 -0700246 .mask = bfin_core_mask_irq,
247 .unmask = bfin_core_unmask_irq,
248};
249
250static struct irq_chip bfin_internal_irqchip = {
Graf Yang763e63c2008-10-08 17:08:15 +0800251 .name = "INTN",
Michael Hennerich464abc52008-02-25 13:50:20 +0800252 .ack = bfin_ack_noop,
Bryan Wu1394f032007-05-06 14:50:22 -0700253 .mask = bfin_internal_mask_irq,
254 .unmask = bfin_internal_unmask_irq,
Michael Hennerichce3b7bb2008-02-25 13:48:47 +0800255 .mask_ack = bfin_internal_mask_irq,
256 .disable = bfin_internal_mask_irq,
257 .enable = bfin_internal_unmask_irq,
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800258#ifdef CONFIG_PM
259 .set_wake = bfin_internal_set_wake,
260#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700261};
262
263#ifdef BF537_GENERIC_ERROR_INT_DEMUX
264static int error_int_mask;
265
Bryan Wu1394f032007-05-06 14:50:22 -0700266static void bfin_generic_error_mask_irq(unsigned int irq)
267{
268 error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR));
269
Michael Hennerich464abc52008-02-25 13:50:20 +0800270 if (!error_int_mask)
271 bfin_internal_mask_irq(IRQ_GENERIC_ERROR);
Bryan Wu1394f032007-05-06 14:50:22 -0700272}
273
274static void bfin_generic_error_unmask_irq(unsigned int irq)
275{
Michael Hennerich464abc52008-02-25 13:50:20 +0800276 bfin_internal_unmask_irq(IRQ_GENERIC_ERROR);
Bryan Wu1394f032007-05-06 14:50:22 -0700277 error_int_mask |= 1L << (irq - IRQ_PPI_ERROR);
278}
279
280static struct irq_chip bfin_generic_error_irqchip = {
Graf Yang763e63c2008-10-08 17:08:15 +0800281 .name = "ERROR",
Michael Hennerich464abc52008-02-25 13:50:20 +0800282 .ack = bfin_ack_noop,
283 .mask_ack = bfin_generic_error_mask_irq,
Bryan Wu1394f032007-05-06 14:50:22 -0700284 .mask = bfin_generic_error_mask_irq,
285 .unmask = bfin_generic_error_unmask_irq,
286};
287
288static void bfin_demux_error_irq(unsigned int int_err_irq,
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800289 struct irq_desc *inta_desc)
Bryan Wu1394f032007-05-06 14:50:22 -0700290{
291 int irq = 0;
292
Bryan Wu1394f032007-05-06 14:50:22 -0700293#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
294 if (bfin_read_EMAC_SYSTAT() & EMAC_ERR_MASK)
295 irq = IRQ_MAC_ERROR;
296 else
297#endif
298 if (bfin_read_SPORT0_STAT() & SPORT_ERR_MASK)
299 irq = IRQ_SPORT0_ERROR;
300 else if (bfin_read_SPORT1_STAT() & SPORT_ERR_MASK)
301 irq = IRQ_SPORT1_ERROR;
302 else if (bfin_read_PPI_STATUS() & PPI_ERR_MASK)
303 irq = IRQ_PPI_ERROR;
304 else if (bfin_read_CAN_GIF() & CAN_ERR_MASK)
305 irq = IRQ_CAN_ERROR;
306 else if (bfin_read_SPI_STAT() & SPI_ERR_MASK)
307 irq = IRQ_SPI_ERROR;
308 else if ((bfin_read_UART0_IIR() & UART_ERR_MASK_STAT1) &&
309 (bfin_read_UART0_IIR() & UART_ERR_MASK_STAT0))
310 irq = IRQ_UART0_ERROR;
311 else if ((bfin_read_UART1_IIR() & UART_ERR_MASK_STAT1) &&
312 (bfin_read_UART1_IIR() & UART_ERR_MASK_STAT0))
313 irq = IRQ_UART1_ERROR;
314
315 if (irq) {
316 if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) {
317 struct irq_desc *desc = irq_desc + irq;
318 desc->handle_irq(irq, desc);
319 } else {
320
321 switch (irq) {
322 case IRQ_PPI_ERROR:
323 bfin_write_PPI_STATUS(PPI_ERR_MASK);
324 break;
325#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
326 case IRQ_MAC_ERROR:
327 bfin_write_EMAC_SYSTAT(EMAC_ERR_MASK);
328 break;
329#endif
330 case IRQ_SPORT0_ERROR:
331 bfin_write_SPORT0_STAT(SPORT_ERR_MASK);
332 break;
333
334 case IRQ_SPORT1_ERROR:
335 bfin_write_SPORT1_STAT(SPORT_ERR_MASK);
336 break;
337
338 case IRQ_CAN_ERROR:
339 bfin_write_CAN_GIS(CAN_ERR_MASK);
340 break;
341
342 case IRQ_SPI_ERROR:
343 bfin_write_SPI_STAT(SPI_ERR_MASK);
344 break;
345
346 default:
347 break;
348 }
349
350 pr_debug("IRQ %d:"
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800351 " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
352 irq);
Bryan Wu1394f032007-05-06 14:50:22 -0700353 }
354 } else
355 printk(KERN_ERR
356 "%s : %s : LINE %d :\nIRQ ?: PERIPHERAL ERROR"
357 " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800358 __func__, __FILE__, __LINE__);
Bryan Wu1394f032007-05-06 14:50:22 -0700359
Bryan Wu1394f032007-05-06 14:50:22 -0700360}
361#endif /* BF537_GENERIC_ERROR_INT_DEMUX */
362
Graf Yangbfd15112008-10-08 18:02:44 +0800363static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
364{
365 struct irq_desc *desc = irq_desc + irq;
366 /* May not call generic set_irq_handler() due to spinlock
367 recursion. */
368 desc->handle_irq = handle;
369}
370
Michael Hennerich8d022372008-11-18 17:48:22 +0800371static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
Michael Hennerichaffee2b2008-04-24 08:10:10 +0800372extern void bfin_gpio_irq_prepare(unsigned gpio);
Michael Hennerich6fce6a82007-12-24 16:56:12 +0800373
Michael Hennerich8d022372008-11-18 17:48:22 +0800374#if !defined(CONFIG_BF54x)
375
Bryan Wu1394f032007-05-06 14:50:22 -0700376static void bfin_gpio_ack_irq(unsigned int irq)
377{
Michael Hennerich8d022372008-11-18 17:48:22 +0800378 /* AFAIK ack_irq in case mask_ack is provided
379 * get's only called for edge sense irqs
380 */
381 set_gpio_data(irq_to_gpio(irq), 0);
Bryan Wu1394f032007-05-06 14:50:22 -0700382}
383
384static void bfin_gpio_mask_ack_irq(unsigned int irq)
385{
Michael Hennerich8d022372008-11-18 17:48:22 +0800386 struct irq_desc *desc = irq_desc + irq;
387 u32 gpionr = irq_to_gpio(irq);
Bryan Wu1394f032007-05-06 14:50:22 -0700388
Michael Hennerich8d022372008-11-18 17:48:22 +0800389 if (desc->handle_irq == handle_edge_irq)
Bryan Wu1394f032007-05-06 14:50:22 -0700390 set_gpio_data(gpionr, 0);
Bryan Wu1394f032007-05-06 14:50:22 -0700391
392 set_gpio_maska(gpionr, 0);
Bryan Wu1394f032007-05-06 14:50:22 -0700393}
394
395static void bfin_gpio_mask_irq(unsigned int irq)
396{
Michael Hennerich8d022372008-11-18 17:48:22 +0800397 set_gpio_maska(irq_to_gpio(irq), 0);
Bryan Wu1394f032007-05-06 14:50:22 -0700398}
399
400static void bfin_gpio_unmask_irq(unsigned int irq)
401{
Michael Hennerich8d022372008-11-18 17:48:22 +0800402 set_gpio_maska(irq_to_gpio(irq), 1);
Bryan Wu1394f032007-05-06 14:50:22 -0700403}
404
405static unsigned int bfin_gpio_irq_startup(unsigned int irq)
406{
Michael Hennerich8d022372008-11-18 17:48:22 +0800407 u32 gpionr = irq_to_gpio(irq);
Bryan Wu1394f032007-05-06 14:50:22 -0700408
Michael Hennerich8d022372008-11-18 17:48:22 +0800409 if (__test_and_set_bit(gpionr, gpio_enabled))
Michael Hennerichaffee2b2008-04-24 08:10:10 +0800410 bfin_gpio_irq_prepare(gpionr);
Bryan Wu1394f032007-05-06 14:50:22 -0700411
Bryan Wu1394f032007-05-06 14:50:22 -0700412 bfin_gpio_unmask_irq(irq);
413
Michael Hennerichaffee2b2008-04-24 08:10:10 +0800414 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700415}
416
417static void bfin_gpio_irq_shutdown(unsigned int irq)
418{
419 bfin_gpio_mask_irq(irq);
Michael Hennerich8d022372008-11-18 17:48:22 +0800420 __clear_bit(irq_to_gpio(irq), gpio_enabled);
Bryan Wu1394f032007-05-06 14:50:22 -0700421}
422
423static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
424{
Michael Hennerich8d022372008-11-18 17:48:22 +0800425 u32 gpionr = irq_to_gpio(irq);
Bryan Wu1394f032007-05-06 14:50:22 -0700426
427 if (type == IRQ_TYPE_PROBE) {
428 /* only probe unenabled GPIO interrupt lines */
Michael Hennerich8d022372008-11-18 17:48:22 +0800429 if (__test_bit(gpionr, gpio_enabled))
Bryan Wu1394f032007-05-06 14:50:22 -0700430 return 0;
431 type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
432 }
433
434 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800435 IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
Michael Hennerich8d022372008-11-18 17:48:22 +0800436
437 if (__test_and_set_bit(gpionr, gpio_enabled))
Michael Hennerichaffee2b2008-04-24 08:10:10 +0800438 bfin_gpio_irq_prepare(gpionr);
Bryan Wu1394f032007-05-06 14:50:22 -0700439
Bryan Wu1394f032007-05-06 14:50:22 -0700440 } else {
Michael Hennerich8d022372008-11-18 17:48:22 +0800441 __clear_bit(gpionr, gpio_enabled);
Bryan Wu1394f032007-05-06 14:50:22 -0700442 return 0;
443 }
444
Michael Hennerichf1bceb42008-02-02 16:17:52 +0800445 set_gpio_inen(gpionr, 0);
Bryan Wu1394f032007-05-06 14:50:22 -0700446 set_gpio_dir(gpionr, 0);
Bryan Wu1394f032007-05-06 14:50:22 -0700447
448 if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
449 == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
450 set_gpio_both(gpionr, 1);
451 else
452 set_gpio_both(gpionr, 0);
453
454 if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
455 set_gpio_polar(gpionr, 1); /* low or falling edge denoted by one */
456 else
457 set_gpio_polar(gpionr, 0); /* high or rising edge denoted by zero */
458
Michael Hennerichf1bceb42008-02-02 16:17:52 +0800459 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
460 set_gpio_edge(gpionr, 1);
461 set_gpio_inen(gpionr, 1);
Michael Hennerichf1bceb42008-02-02 16:17:52 +0800462 set_gpio_data(gpionr, 0);
463
464 } else {
465 set_gpio_edge(gpionr, 0);
Michael Hennerichf1bceb42008-02-02 16:17:52 +0800466 set_gpio_inen(gpionr, 1);
467 }
468
Bryan Wu1394f032007-05-06 14:50:22 -0700469 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
Graf Yangbfd15112008-10-08 18:02:44 +0800470 bfin_set_irq_handler(irq, handle_edge_irq);
Bryan Wu1394f032007-05-06 14:50:22 -0700471 else
Graf Yangbfd15112008-10-08 18:02:44 +0800472 bfin_set_irq_handler(irq, handle_level_irq);
Bryan Wu1394f032007-05-06 14:50:22 -0700473
474 return 0;
475}
476
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800477#ifdef CONFIG_PM
478int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
479{
480 unsigned gpio = irq_to_gpio(irq);
481
482 if (state)
483 gpio_pm_wakeup_request(gpio, PM_WAKE_IGNORE);
484 else
485 gpio_pm_wakeup_free(gpio);
486
487 return 0;
488}
489#endif
490
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800491static void bfin_demux_gpio_irq(unsigned int inta_irq,
492 struct irq_desc *desc)
Bryan Wu1394f032007-05-06 14:50:22 -0700493{
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800494 unsigned int i, gpio, mask, irq, search = 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700495
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800496 switch (inta_irq) {
497#if defined(CONFIG_BF53x)
498 case IRQ_PROG_INTA:
499 irq = IRQ_PF0;
500 search = 1;
501 break;
502# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
503 case IRQ_MAC_RX:
504 irq = IRQ_PH0;
505 break;
506# endif
Michael Hennerichdc26aec2008-11-18 17:48:22 +0800507#elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
508 case IRQ_PORTF_INTA:
509 irq = IRQ_PF0;
510 break;
Bryan Wu2f6f4bc2008-11-18 17:48:21 +0800511#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800512 case IRQ_PORTF_INTA:
513 irq = IRQ_PF0;
514 break;
515 case IRQ_PORTG_INTA:
516 irq = IRQ_PG0;
517 break;
518 case IRQ_PORTH_INTA:
519 irq = IRQ_PH0;
520 break;
521#elif defined(CONFIG_BF561)
522 case IRQ_PROG0_INTA:
523 irq = IRQ_PF0;
524 break;
525 case IRQ_PROG1_INTA:
526 irq = IRQ_PF16;
527 break;
528 case IRQ_PROG2_INTA:
529 irq = IRQ_PF32;
530 break;
531#endif
532 default:
533 BUG();
534 return;
Bryan Wu1394f032007-05-06 14:50:22 -0700535 }
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800536
537 if (search) {
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800538 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800539 irq += i;
540
Michael Hennerich8d022372008-11-18 17:48:22 +0800541 mask = get_gpiop_data(i) & get_gpiop_maska(i);
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800542
543 while (mask) {
544 if (mask & 1) {
545 desc = irq_desc + irq;
546 desc->handle_irq(irq, desc);
547 }
548 irq++;
549 mask >>= 1;
550 }
551 }
552 } else {
553 gpio = irq_to_gpio(irq);
Michael Hennerich8d022372008-11-18 17:48:22 +0800554 mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio);
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800555
556 do {
557 if (mask & 1) {
558 desc = irq_desc + irq;
559 desc->handle_irq(irq, desc);
560 }
561 irq++;
562 mask >>= 1;
563 } while (mask);
564 }
565
Bryan Wu1394f032007-05-06 14:50:22 -0700566}
567
Mike Frysingera055b2b2007-11-15 21:12:32 +0800568#else /* CONFIG_BF54x */
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800569
570#define NR_PINT_SYS_IRQS 4
571#define NR_PINT_BITS 32
572#define NR_PINTS 160
573#define IRQ_NOT_AVAIL 0xFF
574
575#define PINT_2_BANK(x) ((x) >> 5)
576#define PINT_2_BIT(x) ((x) & 0x1F)
577#define PINT_BIT(x) (1 << (PINT_2_BIT(x)))
578
579static unsigned char irq2pint_lut[NR_PINTS];
Michael Henneriche3f23002007-07-12 16:39:29 +0800580static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800581
582struct pin_int_t {
583 unsigned int mask_set;
584 unsigned int mask_clear;
585 unsigned int request;
586 unsigned int assign;
587 unsigned int edge_set;
588 unsigned int edge_clear;
589 unsigned int invert_set;
590 unsigned int invert_clear;
591 unsigned int pinstate;
592 unsigned int latch;
593};
594
595static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
596 (struct pin_int_t *)PINT0_MASK_SET,
597 (struct pin_int_t *)PINT1_MASK_SET,
598 (struct pin_int_t *)PINT2_MASK_SET,
599 (struct pin_int_t *)PINT3_MASK_SET,
600};
601
Michael Hennerich8d022372008-11-18 17:48:22 +0800602inline unsigned int get_irq_base(u32 bank, u8 bmap)
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800603{
Michael Hennerich8d022372008-11-18 17:48:22 +0800604 unsigned int irq_base;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800605
606 if (bank < 2) { /*PA-PB */
607 irq_base = IRQ_PA0 + bmap * 16;
608 } else { /*PC-PJ */
609 irq_base = IRQ_PC0 + bmap * 16;
610 }
611
612 return irq_base;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800613}
614
615 /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
616void init_pint_lut(void)
617{
618 u16 bank, bit, irq_base, bit_pos;
619 u32 pint_assign;
620 u8 bmap;
621
622 memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut));
623
624 for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {
625
626 pint_assign = pint[bank]->assign;
627
628 for (bit = 0; bit < NR_PINT_BITS; bit++) {
629
630 bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF;
631
632 irq_base = get_irq_base(bank, bmap);
633
634 irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0);
635 bit_pos = bit + bank * NR_PINT_BITS;
636
Michael Henneriche3f23002007-07-12 16:39:29 +0800637 pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800638 irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800639 }
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800640 }
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800641}
642
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800643static void bfin_gpio_ack_irq(unsigned int irq)
644{
Michael Hennerich8d022372008-11-18 17:48:22 +0800645 struct irq_desc *desc = irq_desc + irq;
646 u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
Michael Hennerich8baf5602007-12-24 18:51:34 +0800647 u32 pintbit = PINT_BIT(pint_val);
Michael Hennerich8d022372008-11-18 17:48:22 +0800648 u32 bank = PINT_2_BANK(pint_val);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800649
Michael Hennerich8d022372008-11-18 17:48:22 +0800650 if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
Michael Hennerich8baf5602007-12-24 18:51:34 +0800651 if (pint[bank]->invert_set & pintbit)
652 pint[bank]->invert_clear = pintbit;
653 else
654 pint[bank]->invert_set = pintbit;
655 }
656 pint[bank]->request = pintbit;
657
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800658}
659
660static void bfin_gpio_mask_ack_irq(unsigned int irq)
661{
Michael Hennerich8d022372008-11-18 17:48:22 +0800662 struct irq_desc *desc = irq_desc + irq;
663 u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
Michael Henneriche3f23002007-07-12 16:39:29 +0800664 u32 pintbit = PINT_BIT(pint_val);
Michael Hennerich8d022372008-11-18 17:48:22 +0800665 u32 bank = PINT_2_BANK(pint_val);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800666
Michael Hennerich8d022372008-11-18 17:48:22 +0800667 if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
Michael Hennerich8baf5602007-12-24 18:51:34 +0800668 if (pint[bank]->invert_set & pintbit)
669 pint[bank]->invert_clear = pintbit;
670 else
671 pint[bank]->invert_set = pintbit;
672 }
673
Michael Henneriche3f23002007-07-12 16:39:29 +0800674 pint[bank]->request = pintbit;
675 pint[bank]->mask_clear = pintbit;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800676}
677
678static void bfin_gpio_mask_irq(unsigned int irq)
679{
Michael Hennerich8d022372008-11-18 17:48:22 +0800680 u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800681
682 pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800683}
684
685static void bfin_gpio_unmask_irq(unsigned int irq)
686{
Michael Hennerich8d022372008-11-18 17:48:22 +0800687 u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
Michael Henneriche3f23002007-07-12 16:39:29 +0800688 u32 pintbit = PINT_BIT(pint_val);
Michael Hennerich8d022372008-11-18 17:48:22 +0800689 u32 bank = PINT_2_BANK(pint_val);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800690
Michael Henneriche3f23002007-07-12 16:39:29 +0800691 pint[bank]->request = pintbit;
692 pint[bank]->mask_set = pintbit;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800693}
694
695static unsigned int bfin_gpio_irq_startup(unsigned int irq)
696{
Michael Hennerich8d022372008-11-18 17:48:22 +0800697 u32 gpionr = irq_to_gpio(irq);
698 u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800699
Michael Hennerich50e163c2007-07-24 16:17:28 +0800700 if (pint_val == IRQ_NOT_AVAIL) {
701 printk(KERN_ERR
702 "GPIO IRQ %d :Not in PINT Assign table "
703 "Reconfigure Interrupt to Port Assignemt\n", irq);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800704 return -ENODEV;
Michael Hennerich50e163c2007-07-24 16:17:28 +0800705 }
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800706
Michael Hennerich8d022372008-11-18 17:48:22 +0800707 if (__test_and_set_bit(gpionr, gpio_enabled))
Michael Hennerichaffee2b2008-04-24 08:10:10 +0800708 bfin_gpio_irq_prepare(gpionr);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800709
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800710 bfin_gpio_unmask_irq(irq);
711
Michael Hennerichaffee2b2008-04-24 08:10:10 +0800712 return 0;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800713}
714
715static void bfin_gpio_irq_shutdown(unsigned int irq)
716{
Michael Hennerich8d022372008-11-18 17:48:22 +0800717 u32 gpionr = irq_to_gpio(irq);
Michael Hennerich8baf5602007-12-24 18:51:34 +0800718
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800719 bfin_gpio_mask_irq(irq);
Michael Hennerich8d022372008-11-18 17:48:22 +0800720 __clear_bit(gpionr, gpio_enabled);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800721}
722
723static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
724{
725
Michael Hennerich8d022372008-11-18 17:48:22 +0800726 u32 gpionr = irq_to_gpio(irq);
727 u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
Michael Henneriche3f23002007-07-12 16:39:29 +0800728 u32 pintbit = PINT_BIT(pint_val);
Michael Hennerich8d022372008-11-18 17:48:22 +0800729 u32 bank = PINT_2_BANK(pint_val);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800730
731 if (pint_val == IRQ_NOT_AVAIL)
732 return -ENODEV;
733
734 if (type == IRQ_TYPE_PROBE) {
735 /* only probe unenabled GPIO interrupt lines */
Michael Hennerich8d022372008-11-18 17:48:22 +0800736 if (__test_bit(gpionr, gpio_enabled))
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800737 return 0;
738 type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
739 }
740
741 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
742 IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
Michael Hennerich8d022372008-11-18 17:48:22 +0800743 if (__test_and_set_bit(gpionr, gpio_enabled))
Michael Hennerichaffee2b2008-04-24 08:10:10 +0800744 bfin_gpio_irq_prepare(gpionr);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800745
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800746 } else {
Michael Hennerich8d022372008-11-18 17:48:22 +0800747 __clear_bit(gpionr, gpio_enabled);
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800748 return 0;
749 }
750
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800751 if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
Michael Henneriche3f23002007-07-12 16:39:29 +0800752 pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800753 else
Michael Hennerich8baf5602007-12-24 18:51:34 +0800754 pint[bank]->invert_clear = pintbit; /* high or rising edge denoted by zero */
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800755
Michael Hennerich8baf5602007-12-24 18:51:34 +0800756 if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
757 == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
Michael Hennerich8baf5602007-12-24 18:51:34 +0800758 if (gpio_get_value(gpionr))
759 pint[bank]->invert_set = pintbit;
760 else
761 pint[bank]->invert_clear = pintbit;
Michael Hennerich8baf5602007-12-24 18:51:34 +0800762 }
763
764 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
765 pint[bank]->edge_set = pintbit;
Graf Yangbfd15112008-10-08 18:02:44 +0800766 bfin_set_irq_handler(irq, handle_edge_irq);
Michael Hennerich8baf5602007-12-24 18:51:34 +0800767 } else {
768 pint[bank]->edge_clear = pintbit;
Graf Yangbfd15112008-10-08 18:02:44 +0800769 bfin_set_irq_handler(irq, handle_level_irq);
Michael Hennerich8baf5602007-12-24 18:51:34 +0800770 }
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800771
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800772 return 0;
773}
774
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800775#ifdef CONFIG_PM
776u32 pint_saved_masks[NR_PINT_SYS_IRQS];
777u32 pint_wakeup_masks[NR_PINT_SYS_IRQS];
778
779int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
780{
781 u32 pint_irq;
Michael Hennerich8d022372008-11-18 17:48:22 +0800782 u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800783 u32 bank = PINT_2_BANK(pint_val);
784 u32 pintbit = PINT_BIT(pint_val);
785
786 switch (bank) {
787 case 0:
788 pint_irq = IRQ_PINT0;
789 break;
790 case 2:
791 pint_irq = IRQ_PINT2;
792 break;
793 case 3:
794 pint_irq = IRQ_PINT3;
795 break;
796 case 1:
797 pint_irq = IRQ_PINT1;
798 break;
799 default:
800 return -EINVAL;
801 }
802
803 bfin_internal_set_wake(pint_irq, state);
804
805 if (state)
806 pint_wakeup_masks[bank] |= pintbit;
807 else
808 pint_wakeup_masks[bank] &= ~pintbit;
809
810 return 0;
811}
812
813u32 bfin_pm_setup(void)
814{
815 u32 val, i;
816
817 for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
818 val = pint[i]->mask_clear;
819 pint_saved_masks[i] = val;
820 if (val ^ pint_wakeup_masks[i]) {
821 pint[i]->mask_clear = val;
822 pint[i]->mask_set = pint_wakeup_masks[i];
823 }
824 }
825
826 return 0;
827}
828
829void bfin_pm_restore(void)
830{
831 u32 i, val;
832
833 for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
834 val = pint_saved_masks[i];
835 if (val ^ pint_wakeup_masks[i]) {
836 pint[i]->mask_clear = pint[i]->mask_clear;
837 pint[i]->mask_set = val;
838 }
839 }
840}
841#endif
842
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800843static void bfin_demux_gpio_irq(unsigned int inta_irq,
844 struct irq_desc *desc)
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800845{
Michael Hennerich8d022372008-11-18 17:48:22 +0800846 u32 bank, pint_val;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800847 u32 request, irq;
848
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800849 switch (inta_irq) {
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800850 case IRQ_PINT0:
851 bank = 0;
852 break;
853 case IRQ_PINT2:
854 bank = 2;
855 break;
856 case IRQ_PINT3:
857 bank = 3;
858 break;
859 case IRQ_PINT1:
860 bank = 1;
861 break;
Michael Henneriche3f23002007-07-12 16:39:29 +0800862 default:
863 return;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800864 }
865
866 pint_val = bank * NR_PINT_BITS;
867
868 request = pint[bank]->request;
869
870 while (request) {
871 if (request & 1) {
Michael Henneriche3f23002007-07-12 16:39:29 +0800872 irq = pint2irq_lut[pint_val] + SYS_IRQS;
873 desc = irq_desc + irq;
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800874 desc->handle_irq(irq, desc);
875 }
876 pint_val++;
877 request >>= 1;
878 }
879
880}
Mike Frysingera055b2b2007-11-15 21:12:32 +0800881#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700882
Michael Hennerich8d022372008-11-18 17:48:22 +0800883static struct irq_chip bfin_gpio_irqchip = {
884 .name = "GPIO",
885 .ack = bfin_gpio_ack_irq,
886 .mask = bfin_gpio_mask_irq,
887 .mask_ack = bfin_gpio_mask_ack_irq,
888 .unmask = bfin_gpio_unmask_irq,
889 .disable = bfin_gpio_mask_irq,
890 .enable = bfin_gpio_unmask_irq,
891 .set_type = bfin_gpio_irq_type,
892 .startup = bfin_gpio_irq_startup,
893 .shutdown = bfin_gpio_irq_shutdown,
894#ifdef CONFIG_PM
895 .set_wake = bfin_gpio_set_wake,
896#endif
897};
898
Bernd Schmidt8be80ed2007-07-25 14:44:49 +0800899void __init init_exception_vectors(void)
900{
Mike Frysingerf0b5d122007-08-05 17:03:59 +0800901 /* cannot program in software:
902 * evt0 - emulation (jtag)
903 * evt1 - reset
904 */
905 bfin_write_EVT2(evt_nmi);
Bernd Schmidt8be80ed2007-07-25 14:44:49 +0800906 bfin_write_EVT3(trap);
907 bfin_write_EVT5(evt_ivhw);
908 bfin_write_EVT6(evt_timer);
909 bfin_write_EVT7(evt_evt7);
910 bfin_write_EVT8(evt_evt8);
911 bfin_write_EVT9(evt_evt9);
912 bfin_write_EVT10(evt_evt10);
913 bfin_write_EVT11(evt_evt11);
914 bfin_write_EVT12(evt_evt12);
915 bfin_write_EVT13(evt_evt13);
916 bfin_write_EVT14(evt14_softirq);
917 bfin_write_EVT15(evt_system_call);
918 CSYNC();
919}
920
Bryan Wu1394f032007-05-06 14:50:22 -0700921/*
922 * This function should be called during kernel startup to initialize
923 * the BFin IRQ handling routines.
924 */
Michael Hennerich8d022372008-11-18 17:48:22 +0800925
Bryan Wu1394f032007-05-06 14:50:22 -0700926int __init init_arch_irq(void)
927{
928 int irq;
929 unsigned long ilat = 0;
930 /* Disable all the peripheral intrs - page 4-29 HW Ref manual */
Bryan Wu2f6f4bc2008-11-18 17:48:21 +0800931#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
932 || defined(BF538_FAMILY) || defined(CONFIG_BF51x)
Roy Huang24a07a12007-07-12 22:41:45 +0800933 bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
934 bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);
Mike Frysingera055b2b2007-11-15 21:12:32 +0800935# ifdef CONFIG_BF54x
Michael Hennerich59003142007-10-21 16:54:27 +0800936 bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
Mike Frysingera055b2b2007-11-15 21:12:32 +0800937# endif
Roy Huang24a07a12007-07-12 22:41:45 +0800938#else
Bryan Wu1394f032007-05-06 14:50:22 -0700939 bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
Roy Huang24a07a12007-07-12 22:41:45 +0800940#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700941
942 local_irq_disable();
943
Mike Frysingerd70536e2008-08-25 17:37:35 +0800944#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
Mike Frysinger95a86b52008-08-14 15:05:01 +0800945 /* Clear EMAC Interrupt Status bits so we can demux it later */
946 bfin_write_EMAC_SYSTAT(-1);
947#endif
948
Mike Frysingera055b2b2007-11-15 21:12:32 +0800949#ifdef CONFIG_BF54x
950# ifdef CONFIG_PINTx_REASSIGN
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800951 pint[0]->assign = CONFIG_PINT0_ASSIGN;
952 pint[1]->assign = CONFIG_PINT1_ASSIGN;
953 pint[2]->assign = CONFIG_PINT2_ASSIGN;
954 pint[3]->assign = CONFIG_PINT3_ASSIGN;
Mike Frysingera055b2b2007-11-15 21:12:32 +0800955# endif
Michael Hennerich34e0fc82007-07-12 16:17:18 +0800956 /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
957 init_pint_lut();
958#endif
959
960 for (irq = 0; irq <= SYS_IRQS; irq++) {
Bryan Wu1394f032007-05-06 14:50:22 -0700961 if (irq <= IRQ_CORETMR)
962 set_irq_chip(irq, &bfin_core_irqchip);
963 else
964 set_irq_chip(irq, &bfin_internal_irqchip);
Bryan Wu1394f032007-05-06 14:50:22 -0700965
Michael Hennerich464abc52008-02-25 13:50:20 +0800966 switch (irq) {
Michael Hennerich59003142007-10-21 16:54:27 +0800967#if defined(CONFIG_BF53x)
Michael Hennerich464abc52008-02-25 13:50:20 +0800968 case IRQ_PROG_INTA:
Mike Frysingera055b2b2007-11-15 21:12:32 +0800969# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
Michael Hennerich464abc52008-02-25 13:50:20 +0800970 case IRQ_MAC_RX:
Mike Frysingera055b2b2007-11-15 21:12:32 +0800971# endif
Michael Hennerich59003142007-10-21 16:54:27 +0800972#elif defined(CONFIG_BF54x)
Michael Hennerich464abc52008-02-25 13:50:20 +0800973 case IRQ_PINT0:
974 case IRQ_PINT1:
975 case IRQ_PINT2:
976 case IRQ_PINT3:
Bryan Wu2f6f4bc2008-11-18 17:48:21 +0800977#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Michael Hennerich464abc52008-02-25 13:50:20 +0800978 case IRQ_PORTF_INTA:
979 case IRQ_PORTG_INTA:
980 case IRQ_PORTH_INTA:
Michael Hennerich2c4f8292008-02-09 04:11:14 +0800981#elif defined(CONFIG_BF561)
Michael Hennerich464abc52008-02-25 13:50:20 +0800982 case IRQ_PROG0_INTA:
983 case IRQ_PROG1_INTA:
984 case IRQ_PROG2_INTA:
Michael Hennerichdc26aec2008-11-18 17:48:22 +0800985#elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
986 case IRQ_PORTF_INTA:
Michael Hennerich59003142007-10-21 16:54:27 +0800987#endif
Michael Hennerichdc26aec2008-11-18 17:48:22 +0800988
Michael Hennerich464abc52008-02-25 13:50:20 +0800989 set_irq_chained_handler(irq,
990 bfin_demux_gpio_irq);
991 break;
Bryan Wu1394f032007-05-06 14:50:22 -0700992#ifdef BF537_GENERIC_ERROR_INT_DEMUX
Michael Hennerich464abc52008-02-25 13:50:20 +0800993 case IRQ_GENERIC_ERROR:
Bryan Wu1394f032007-05-06 14:50:22 -0700994 set_irq_handler(irq, bfin_demux_error_irq);
Michael Hennerich464abc52008-02-25 13:50:20 +0800995
996 break;
997#endif
998 default:
999 set_irq_handler(irq, handle_simple_irq);
1000 break;
Bryan Wu1394f032007-05-06 14:50:22 -07001001 }
Bryan Wu1394f032007-05-06 14:50:22 -07001002 }
Michael Hennerich464abc52008-02-25 13:50:20 +08001003
Bryan Wu1394f032007-05-06 14:50:22 -07001004#ifdef BF537_GENERIC_ERROR_INT_DEMUX
Michael Hennerich464abc52008-02-25 13:50:20 +08001005 for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++)
1006 set_irq_chip_and_handler(irq, &bfin_generic_error_irqchip,
1007 handle_level_irq);
Bryan Wu1394f032007-05-06 14:50:22 -07001008#endif
1009
Michael Hennerich464abc52008-02-25 13:50:20 +08001010 /* if configured as edge, then will be changed to do_edge_IRQ */
1011 for (irq = GPIO_IRQ_BASE; irq < NR_IRQS; irq++)
1012 set_irq_chip_and_handler(irq, &bfin_gpio_irqchip,
1013 handle_level_irq);
Michael Hennerich2c4f8292008-02-09 04:11:14 +08001014
Mike Frysingera055b2b2007-11-15 21:12:32 +08001015
Bryan Wu1394f032007-05-06 14:50:22 -07001016 bfin_write_IMASK(0);
1017 CSYNC();
1018 ilat = bfin_read_ILAT();
1019 CSYNC();
1020 bfin_write_ILAT(ilat);
1021 CSYNC();
1022
Michael Hennerich34e0fc82007-07-12 16:17:18 +08001023 printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
Bryan Wu1394f032007-05-06 14:50:22 -07001024 /* IMASK=xxx is equivalent to STI xx or irq_flags=xx,
1025 * local_irq_enable()
1026 */
1027 program_IAR();
1028 /* Therefore it's better to setup IARs before interrupts enabled */
1029 search_IAR();
1030
1031 /* Enable interrupts IVG7-15 */
1032 irq_flags = irq_flags | IMASK_IVG15 |
1033 IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
Michael Hennerich34e0fc82007-07-12 16:17:18 +08001034 IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
Bryan Wu1394f032007-05-06 14:50:22 -07001035
Bryan Wu2f6f4bc2008-11-18 17:48:21 +08001036#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
1037 || defined(BF538_FAMILY) || defined(CONFIG_BF51x)
Michael Hennerich56f5f592008-08-06 17:55:32 +08001038 bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
Bryan Wu2f6f4bc2008-11-18 17:48:21 +08001039#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
1040 /* BF52x/BF51x system reset does not properly reset SIC_IWR1 which
Michael Hennerich55546ac2008-08-13 17:41:13 +08001041 * will screw up the bootrom as it relies on MDMA0/1 waking it
1042 * up from IDLE instructions. See this report for more info:
1043 * http://blackfin.uclinux.org/gf/tracker/4323
1044 */
1045 bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
1046#else
Michael Hennerich56f5f592008-08-06 17:55:32 +08001047 bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
Michael Hennerich55546ac2008-08-13 17:41:13 +08001048#endif
Michael Hennerichfe9ec9b2008-02-25 12:04:57 +08001049# ifdef CONFIG_BF54x
Michael Hennerich56f5f592008-08-06 17:55:32 +08001050 bfin_write_SIC_IWR2(IWR_DISABLE_ALL);
Michael Hennerichfe9ec9b2008-02-25 12:04:57 +08001051# endif
1052#else
Michael Hennerich56f5f592008-08-06 17:55:32 +08001053 bfin_write_SIC_IWR(IWR_DISABLE_ALL);
Michael Hennerichfe9ec9b2008-02-25 12:04:57 +08001054#endif
1055
Bryan Wu1394f032007-05-06 14:50:22 -07001056 return 0;
1057}
1058
1059#ifdef CONFIG_DO_IRQ_L1
Mike Frysingera055b2b2007-11-15 21:12:32 +08001060__attribute__((l1_text))
Bryan Wu1394f032007-05-06 14:50:22 -07001061#endif
Bryan Wu1394f032007-05-06 14:50:22 -07001062void do_irq(int vec, struct pt_regs *fp)
1063{
1064 if (vec == EVT_IVTMR_P) {
1065 vec = IRQ_CORETMR;
1066 } else {
1067 struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
1068 struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
Bryan Wu2f6f4bc2008-11-18 17:48:21 +08001069#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
1070 || defined(BF538_FAMILY) || defined(CONFIG_BF51x)
Roy Huang24a07a12007-07-12 22:41:45 +08001071 unsigned long sic_status[3];
Bryan Wu1394f032007-05-06 14:50:22 -07001072
Michael Hennerich4fb45242007-10-21 16:53:53 +08001073 sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
1074 sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
Michael Hennerich59003142007-10-21 16:54:27 +08001075#ifdef CONFIG_BF54x
Michael Hennerich4fb45242007-10-21 16:53:53 +08001076 sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
Michael Hennerich59003142007-10-21 16:54:27 +08001077#endif
Mike Frysinger1f83b8f2007-07-12 22:58:21 +08001078 for (;; ivg++) {
Roy Huang24a07a12007-07-12 22:41:45 +08001079 if (ivg >= ivg_stop) {
1080 atomic_inc(&num_spurious);
1081 return;
1082 }
Michael Hennerich34e0fc82007-07-12 16:17:18 +08001083 if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
Roy Huang24a07a12007-07-12 22:41:45 +08001084 break;
1085 }
1086#else
1087 unsigned long sic_status;
Michael Hennerich464abc52008-02-25 13:50:20 +08001088
Bryan Wu1394f032007-05-06 14:50:22 -07001089 sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
1090
1091 for (;; ivg++) {
1092 if (ivg >= ivg_stop) {
1093 atomic_inc(&num_spurious);
1094 return;
1095 } else if (sic_status & ivg->isrflag)
1096 break;
1097 }
Roy Huang24a07a12007-07-12 22:41:45 +08001098#endif
Bryan Wu1394f032007-05-06 14:50:22 -07001099 vec = ivg->irqno;
1100 }
1101 asm_do_IRQ(vec, fp);
Bryan Wu1394f032007-05-06 14:50:22 -07001102}