ints-priority.c 29.5 KB
Newer Older
B
Bryan Wu 已提交
1
/*
2
 * Set up the interrupt priorities
B
Bryan Wu 已提交
3
 *
4 5 6 7 8 9
 * Copyright  2004-2009 Analog Devices Inc.
 *                 2003 Bas Vermeulen <bas@buyways.nl>
 *                 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
 *            2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca>
 *                 1999 D. Jeff Dionne <jeff@uclinux.org>
 *                 1996 Roman Zippel
B
Bryan Wu 已提交
10
 *
11
 * Licensed under the GPL-2
B
Bryan Wu 已提交
12 13 14 15 16 17
 */

#include <linux/module.h>
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <linux/irq.h>
18 19 20
#ifdef CONFIG_IPIPE
#include <linux/ipipe.h>
#endif
B
Bryan Wu 已提交
21 22 23 24 25 26 27
#ifdef CONFIG_KGDB
#include <linux/kgdb.h>
#endif
#include <asm/traps.h>
#include <asm/blackfin.h>
#include <asm/gpio.h>
#include <asm/irq_handler.h>
28
#include <asm/dpmc.h>
29 30
#include <asm/bfin5xx_spi.h>
#include <asm/bfin_sport.h>
B
Bryan Wu 已提交
31

32 33
#define SIC_SYSIRQ(irq)	(irq - (IRQ_CORETMR + 1))

B
Bryan Wu 已提交
34 35
#ifdef BF537_FAMILY
# define BF537_GENERIC_ERROR_INT_DEMUX
36 37 38 39 40 41
# define SPI_ERR_MASK   (BIT_STAT_TXCOL | BIT_STAT_RBSY | BIT_STAT_MODF | BIT_STAT_TXE)	/* SPI_STAT */
# define SPORT_ERR_MASK (ROVF | RUVF | TOVF | TUVF)	/* SPORT_STAT */
# define PPI_ERR_MASK   (0xFFFF & ~FLD)	/* PPI_STATUS */
# define EMAC_ERR_MASK  (PHYINT | MMCINT | RXFSINT | TXFSINT | WAKEDET | RXDMAERR | TXDMAERR | STMDONE)	/* EMAC_SYSTAT */
# define UART_ERR_MASK  (0x6)	/* UART_IIR */
# define CAN_ERR_MASK   (EWTIF | EWRIF | EPIF | BOIF | WUIF | UIAIF | AAIF | RMLIF | UCEIF | EXTIF | ADIF)	/* CAN_GIF */
B
Bryan Wu 已提交
42 43 44 45 46 47 48 49 50 51 52
#else
# undef BF537_GENERIC_ERROR_INT_DEMUX
#endif

/*
 * NOTES:
 * - we have separated the physical Hardware interrupt from the
 * levels that the LINUX kernel sees (see the description in irq.h)
 * -
 */

53
#ifndef CONFIG_SMP
54 55 56 57 58 59
/* Initialize this to an actual value to force it into the .data
 * section so that we know it is properly initialized at entry into
 * the kernel but before bss is initialized to zero (which is where
 * it would live otherwise).  The 0x1f magic represents the IRQs we
 * cannot actually mask out in hardware.
 */
60 61
unsigned long bfin_irq_flags = 0x1f;
EXPORT_SYMBOL(bfin_irq_flags);
62
#endif
B
Bryan Wu 已提交
63 64 65 66

/* The number of spurious interrupts */
atomic_t num_spurious;

67 68
#ifdef CONFIG_PM
unsigned long bfin_sic_iwr[3];	/* Up to 3 SIC_IWRx registers */
69
unsigned vr_wakeup;
70 71
#endif

B
Bryan Wu 已提交
72
struct ivgx {
73
	/* irq number for request_irq, available in mach-bf5xx/irq.h */
74
	unsigned int irqno;
B
Bryan Wu 已提交
75
	/* corresponding bit in the SIC_ISR register */
76
	unsigned int isrflag;
B
Bryan Wu 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
} ivg_table[NR_PERI_INTS];

struct ivg_slice {
	/* position of first irq in ivg_table for given ivg */
	struct ivgx *ifirst;
	struct ivgx *istop;
} ivg7_13[IVG13 - IVG7 + 1];


/*
 * Search SIC_IAR and fill tables with the irqvalues
 * and their positions in the SIC_ISR register.
 */
static void __init search_IAR(void)
{
	unsigned ivg, irq_pos = 0;
	for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
		int irqn;

96
		ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
B
Bryan Wu 已提交
97 98 99

		for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
			int iar_shift = (irqn & 7) * 4;
100
				if (ivg == (0xf &
101 102
#if defined(CONFIG_BF52x) || defined(CONFIG_BF538) \
	|| defined(CONFIG_BF539) || defined(CONFIG_BF51x)
103
			     bfin_read32((unsigned long *)SIC_IAR0 +
104 105
					 ((irqn % 32) >> 3) + ((irqn / 32) *
					 ((SIC_IAR4 - SIC_IAR0) / 4))) >> iar_shift)) {
106 107
#else
			     bfin_read32((unsigned long *)SIC_IAR0 +
108
					 (irqn >> 3)) >> iar_shift)) {
109
#endif
B
Bryan Wu 已提交
110
				ivg_table[irq_pos].irqno = IVG7 + irqn;
111
				ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
B
Bryan Wu 已提交
112 113 114 115 116 117 118 119
				ivg7_13[ivg].istop++;
				irq_pos++;
			}
		}
	}
}

/*
120
 * This is for core internal IRQs
B
Bryan Wu 已提交
121 122
 */

123
static void bfin_ack_noop(unsigned int irq)
B
Bryan Wu 已提交
124 125 126 127 128 129
{
	/* Dummy function.  */
}

static void bfin_core_mask_irq(unsigned int irq)
{
130
	bfin_irq_flags &= ~(1 << irq);
131 132
	if (!irqs_disabled_hw())
		local_irq_enable_hw();
B
Bryan Wu 已提交
133 134 135 136
}

static void bfin_core_unmask_irq(unsigned int irq)
{
137
	bfin_irq_flags |= 1 << irq;
B
Bryan Wu 已提交
138 139
	/*
	 * If interrupts are enabled, IMASK must contain the same value
140
	 * as bfin_irq_flags.  Make sure that invariant holds.  If interrupts
B
Bryan Wu 已提交
141 142 143
	 * are currently disabled we need not do anything; one of the
	 * callers will take care of setting IMASK to the proper value
	 * when reenabling interrupts.
144
	 * local_irq_enable just does "STI bfin_irq_flags", so it's exactly
B
Bryan Wu 已提交
145 146
	 * what we need.
	 */
147 148
	if (!irqs_disabled_hw())
		local_irq_enable_hw();
B
Bryan Wu 已提交
149 150 151 152 153
	return;
}

static void bfin_internal_mask_irq(unsigned int irq)
{
154 155
	unsigned long flags;

156
#ifdef CONFIG_BF53x
157
	local_irq_save_hw(flags);
B
Bryan Wu 已提交
158
	bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
159
			     ~(1 << SIC_SYSIRQ(irq)));
160 161
#else
	unsigned mask_bank, mask_bit;
162
	local_irq_save_hw(flags);
163 164
	mask_bank = SIC_SYSIRQ(irq) / 32;
	mask_bit = SIC_SYSIRQ(irq) % 32;
165 166
	bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
			     ~(1 << mask_bit));
167 168 169 170
#ifdef CONFIG_SMP
	bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) &
			     ~(1 << mask_bit));
#endif
171
#endif
172
	local_irq_restore_hw(flags);
B
Bryan Wu 已提交
173 174 175 176
}

static void bfin_internal_unmask_irq(unsigned int irq)
{
177 178
	unsigned long flags;

179
#ifdef CONFIG_BF53x
180
	local_irq_save_hw(flags);
B
Bryan Wu 已提交
181
	bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
182
			     (1 << SIC_SYSIRQ(irq)));
183 184
#else
	unsigned mask_bank, mask_bit;
185
	local_irq_save_hw(flags);
186 187
	mask_bank = SIC_SYSIRQ(irq) / 32;
	mask_bit = SIC_SYSIRQ(irq) % 32;
188 189
	bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) |
			     (1 << mask_bit));
190 191 192 193
#ifdef CONFIG_SMP
	bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) |
			     (1 << mask_bit));
#endif
194
#endif
195
	local_irq_restore_hw(flags);
B
Bryan Wu 已提交
196 197
}

198 199 200
#ifdef CONFIG_PM
int bfin_internal_set_wake(unsigned int irq, unsigned int state)
{
201
	u32 bank, bit, wakeup = 0;
202
	unsigned long flags;
203 204
	bank = SIC_SYSIRQ(irq) / 32;
	bit = SIC_SYSIRQ(irq) % 32;
205

206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
	switch (irq) {
#ifdef IRQ_RTC
	case IRQ_RTC:
	wakeup |= WAKE;
	break;
#endif
#ifdef IRQ_CAN0_RX
	case IRQ_CAN0_RX:
	wakeup |= CANWE;
	break;
#endif
#ifdef IRQ_CAN1_RX
	case IRQ_CAN1_RX:
	wakeup |= CANWE;
	break;
#endif
#ifdef IRQ_USB_INT0
	case IRQ_USB_INT0:
	wakeup |= USBWE;
	break;
#endif
#ifdef IRQ_KEY
	case IRQ_KEY:
	wakeup |= KPADWE;
	break;
#endif
232
#ifdef CONFIG_BF54x
233 234 235 236 237 238 239 240
	case IRQ_CNT:
	wakeup |= ROTWE;
	break;
#endif
	default:
	break;
	}

241
	local_irq_save_hw(flags);
242

243
	if (state) {
244
		bfin_sic_iwr[bank] |= (1 << bit);
245 246 247
		vr_wakeup  |= wakeup;

	} else {
248
		bfin_sic_iwr[bank] &= ~(1 << bit);
249 250
		vr_wakeup  &= ~wakeup;
	}
251

252
	local_irq_restore_hw(flags);
253 254 255 256 257

	return 0;
}
#endif

B
Bryan Wu 已提交
258
static struct irq_chip bfin_core_irqchip = {
259
	.name = "CORE",
260
	.ack = bfin_ack_noop,
B
Bryan Wu 已提交
261 262 263 264 265
	.mask = bfin_core_mask_irq,
	.unmask = bfin_core_unmask_irq,
};

static struct irq_chip bfin_internal_irqchip = {
266
	.name = "INTN",
267
	.ack = bfin_ack_noop,
B
Bryan Wu 已提交
268 269
	.mask = bfin_internal_mask_irq,
	.unmask = bfin_internal_unmask_irq,
270 271 272
	.mask_ack = bfin_internal_mask_irq,
	.disable = bfin_internal_mask_irq,
	.enable = bfin_internal_unmask_irq,
273 274 275
#ifdef CONFIG_PM
	.set_wake = bfin_internal_set_wake,
#endif
B
Bryan Wu 已提交
276 277
};

278 279 280 281 282 283 284 285 286 287 288 289 290
static void bfin_handle_irq(unsigned irq)
{
#ifdef CONFIG_IPIPE
	struct pt_regs regs;    /* Contents not used. */
	ipipe_trace_irq_entry(irq);
	__ipipe_handle_irq(irq, &regs);
	ipipe_trace_irq_exit(irq);
#else /* !CONFIG_IPIPE */
	struct irq_desc *desc = irq_desc + irq;
	desc->handle_irq(irq, desc);
#endif  /* !CONFIG_IPIPE */
}

B
Bryan Wu 已提交
291 292 293 294 295 296 297
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
static int error_int_mask;

static void bfin_generic_error_mask_irq(unsigned int irq)
{
	error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR));

298 299
	if (!error_int_mask)
		bfin_internal_mask_irq(IRQ_GENERIC_ERROR);
B
Bryan Wu 已提交
300 301 302 303
}

static void bfin_generic_error_unmask_irq(unsigned int irq)
{
304
	bfin_internal_unmask_irq(IRQ_GENERIC_ERROR);
B
Bryan Wu 已提交
305 306 307 308
	error_int_mask |= 1L << (irq - IRQ_PPI_ERROR);
}

static struct irq_chip bfin_generic_error_irqchip = {
309
	.name = "ERROR",
310 311
	.ack = bfin_ack_noop,
	.mask_ack = bfin_generic_error_mask_irq,
B
Bryan Wu 已提交
312 313 314 315 316
	.mask = bfin_generic_error_mask_irq,
	.unmask = bfin_generic_error_unmask_irq,
};

static void bfin_demux_error_irq(unsigned int int_err_irq,
317
				 struct irq_desc *inta_desc)
B
Bryan Wu 已提交
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
{
	int irq = 0;

#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
	if (bfin_read_EMAC_SYSTAT() & EMAC_ERR_MASK)
		irq = IRQ_MAC_ERROR;
	else
#endif
	if (bfin_read_SPORT0_STAT() & SPORT_ERR_MASK)
		irq = IRQ_SPORT0_ERROR;
	else if (bfin_read_SPORT1_STAT() & SPORT_ERR_MASK)
		irq = IRQ_SPORT1_ERROR;
	else if (bfin_read_PPI_STATUS() & PPI_ERR_MASK)
		irq = IRQ_PPI_ERROR;
	else if (bfin_read_CAN_GIF() & CAN_ERR_MASK)
		irq = IRQ_CAN_ERROR;
	else if (bfin_read_SPI_STAT() & SPI_ERR_MASK)
		irq = IRQ_SPI_ERROR;
336
	else if ((bfin_read_UART0_IIR() & UART_ERR_MASK) == UART_ERR_MASK)
B
Bryan Wu 已提交
337
		irq = IRQ_UART0_ERROR;
338
	else if ((bfin_read_UART1_IIR() & UART_ERR_MASK) == UART_ERR_MASK)
B
Bryan Wu 已提交
339 340 341
		irq = IRQ_UART1_ERROR;

	if (irq) {
342 343 344
		if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR)))
			bfin_handle_irq(irq);
		else {
B
Bryan Wu 已提交
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375

			switch (irq) {
			case IRQ_PPI_ERROR:
				bfin_write_PPI_STATUS(PPI_ERR_MASK);
				break;
#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
			case IRQ_MAC_ERROR:
				bfin_write_EMAC_SYSTAT(EMAC_ERR_MASK);
				break;
#endif
			case IRQ_SPORT0_ERROR:
				bfin_write_SPORT0_STAT(SPORT_ERR_MASK);
				break;

			case IRQ_SPORT1_ERROR:
				bfin_write_SPORT1_STAT(SPORT_ERR_MASK);
				break;

			case IRQ_CAN_ERROR:
				bfin_write_CAN_GIS(CAN_ERR_MASK);
				break;

			case IRQ_SPI_ERROR:
				bfin_write_SPI_STAT(SPI_ERR_MASK);
				break;

			default:
				break;
			}

			pr_debug("IRQ %d:"
376 377
				 " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
				 irq);
B
Bryan Wu 已提交
378 379 380 381 382
		}
	} else
		printk(KERN_ERR
		       "%s : %s : LINE %d :\nIRQ ?: PERIPHERAL ERROR"
		       " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
383
		       __func__, __FILE__, __LINE__);
B
Bryan Wu 已提交
384 385 386 387

}
#endif				/* BF537_GENERIC_ERROR_INT_DEMUX */

388 389
static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
{
390
#ifdef CONFIG_IPIPE
391
	_set_irq_handler(irq, handle_level_irq);
392
#else
393 394 395 396
	struct irq_desc *desc = irq_desc + irq;
	/* May not call generic set_irq_handler() due to spinlock
	   recursion. */
	desc->handle_irq = handle;
397
#endif
398 399
}

400
static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
401
extern void bfin_gpio_irq_prepare(unsigned gpio);
402

403 404
#if !defined(CONFIG_BF54x)

B
Bryan Wu 已提交
405 406
static void bfin_gpio_ack_irq(unsigned int irq)
{
407 408 409 410
	/* AFAIK ack_irq in case mask_ack is provided
	 * get's only called for edge sense irqs
	 */
	set_gpio_data(irq_to_gpio(irq), 0);
B
Bryan Wu 已提交
411 412 413 414
}

static void bfin_gpio_mask_ack_irq(unsigned int irq)
{
415 416
	struct irq_desc *desc = irq_desc + irq;
	u32 gpionr = irq_to_gpio(irq);
B
Bryan Wu 已提交
417

418
	if (desc->handle_irq == handle_edge_irq)
B
Bryan Wu 已提交
419 420 421 422 423 424 425
		set_gpio_data(gpionr, 0);

	set_gpio_maska(gpionr, 0);
}

static void bfin_gpio_mask_irq(unsigned int irq)
{
426
	set_gpio_maska(irq_to_gpio(irq), 0);
B
Bryan Wu 已提交
427 428 429 430
}

static void bfin_gpio_unmask_irq(unsigned int irq)
{
431
	set_gpio_maska(irq_to_gpio(irq), 1);
B
Bryan Wu 已提交
432 433 434 435
}

static unsigned int bfin_gpio_irq_startup(unsigned int irq)
{
436
	u32 gpionr = irq_to_gpio(irq);
B
Bryan Wu 已提交
437

438
	if (__test_and_set_bit(gpionr, gpio_enabled))
439
		bfin_gpio_irq_prepare(gpionr);
B
Bryan Wu 已提交
440 441 442

	bfin_gpio_unmask_irq(irq);

443
	return 0;
B
Bryan Wu 已提交
444 445 446 447
}

static void bfin_gpio_irq_shutdown(unsigned int irq)
{
448 449
	u32 gpionr = irq_to_gpio(irq);

B
Bryan Wu 已提交
450
	bfin_gpio_mask_irq(irq);
451
	__clear_bit(gpionr, gpio_enabled);
452
	bfin_gpio_irq_free(gpionr);
B
Bryan Wu 已提交
453 454 455 456
}

static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
{
457 458
	int ret;
	char buf[16];
459
	u32 gpionr = irq_to_gpio(irq);
B
Bryan Wu 已提交
460 461 462

	if (type == IRQ_TYPE_PROBE) {
		/* only probe unenabled GPIO interrupt lines */
463
		if (test_bit(gpionr, gpio_enabled))
B
Bryan Wu 已提交
464 465 466 467 468
			return 0;
		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
	}

	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
469
		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
470

471 472 473 474 475
		snprintf(buf, 16, "gpio-irq%d", irq);
		ret = bfin_gpio_irq_request(gpionr, buf);
		if (ret)
			return ret;

476
		if (__test_and_set_bit(gpionr, gpio_enabled))
477
			bfin_gpio_irq_prepare(gpionr);
B
Bryan Wu 已提交
478 479

	} else {
480
		__clear_bit(gpionr, gpio_enabled);
B
Bryan Wu 已提交
481 482 483
		return 0;
	}

484
	set_gpio_inen(gpionr, 0);
B
Bryan Wu 已提交
485 486 487 488 489 490 491 492 493 494 495 496 497
	set_gpio_dir(gpionr, 0);

	if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
	    == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
		set_gpio_both(gpionr, 1);
	else
		set_gpio_both(gpionr, 0);

	if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
		set_gpio_polar(gpionr, 1);	/* low or falling edge denoted by one */
	else
		set_gpio_polar(gpionr, 0);	/* high or rising edge denoted by zero */

498 499 500 501 502 503 504 505 506 507
	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
		set_gpio_edge(gpionr, 1);
		set_gpio_inen(gpionr, 1);
		set_gpio_data(gpionr, 0);

	} else {
		set_gpio_edge(gpionr, 0);
		set_gpio_inen(gpionr, 1);
	}

B
Bryan Wu 已提交
508
	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
509
		bfin_set_irq_handler(irq, handle_edge_irq);
B
Bryan Wu 已提交
510
	else
511
		bfin_set_irq_handler(irq, handle_level_irq);
B
Bryan Wu 已提交
512 513 514 515

	return 0;
}

516 517 518 519 520 521 522 523 524 525 526 527 528 529
#ifdef CONFIG_PM
int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
{
	unsigned gpio = irq_to_gpio(irq);

	if (state)
		gpio_pm_wakeup_request(gpio, PM_WAKE_IGNORE);
	else
		gpio_pm_wakeup_free(gpio);

	return 0;
}
#endif

530 531
static void bfin_demux_gpio_irq(unsigned int inta_irq,
				struct irq_desc *desc)
B
Bryan Wu 已提交
532
{
533 534 535 536 537 538 539 540 541 542 543 544 545
	unsigned int i, gpio, mask, irq, search = 0;

	switch (inta_irq) {
#if defined(CONFIG_BF53x)
	case IRQ_PROG_INTA:
		irq = IRQ_PF0;
		search = 1;
		break;
# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
	case IRQ_MAC_RX:
		irq = IRQ_PH0;
		break;
# endif
546 547 548 549
#elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
	case IRQ_PORTF_INTA:
		irq = IRQ_PF0;
		break;
550
#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
	case IRQ_PORTF_INTA:
		irq = IRQ_PF0;
		break;
	case IRQ_PORTG_INTA:
		irq = IRQ_PG0;
		break;
	case IRQ_PORTH_INTA:
		irq = IRQ_PH0;
		break;
#elif defined(CONFIG_BF561)
	case IRQ_PROG0_INTA:
		irq = IRQ_PF0;
		break;
	case IRQ_PROG1_INTA:
		irq = IRQ_PF16;
		break;
	case IRQ_PROG2_INTA:
		irq = IRQ_PF32;
		break;
#endif
	default:
		BUG();
		return;
	}

	if (search) {
577
		for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
578 579
			irq += i;

580
			mask = get_gpiop_data(i) & get_gpiop_maska(i);
581 582

			while (mask) {
583 584
				if (mask & 1)
					bfin_handle_irq(irq);
585 586
				irq++;
				mask >>= 1;
B
Bryan Wu 已提交
587 588
			}
		}
589 590
	} else {
			gpio = irq_to_gpio(irq);
591
			mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio);
592 593

			do {
594 595
				if (mask & 1)
					bfin_handle_irq(irq);
596 597 598
				irq++;
				mask >>= 1;
			} while (mask);
B
Bryan Wu 已提交
599
	}
600

B
Bryan Wu 已提交
601 602
}

603
#else				/* CONFIG_BF54x */
604 605 606 607 608 609 610 611 612 613 614

#define NR_PINT_SYS_IRQS	4
#define NR_PINT_BITS		32
#define NR_PINTS		160
#define IRQ_NOT_AVAIL		0xFF

#define PINT_2_BANK(x)		((x) >> 5)
#define PINT_2_BIT(x)		((x) & 0x1F)
#define PINT_BIT(x)		(1 << (PINT_2_BIT(x)))

static unsigned char irq2pint_lut[NR_PINTS];
615
static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636

struct pin_int_t {
	unsigned int mask_set;
	unsigned int mask_clear;
	unsigned int request;
	unsigned int assign;
	unsigned int edge_set;
	unsigned int edge_clear;
	unsigned int invert_set;
	unsigned int invert_clear;
	unsigned int pinstate;
	unsigned int latch;
};

static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
	(struct pin_int_t *)PINT0_MASK_SET,
	(struct pin_int_t *)PINT1_MASK_SET,
	(struct pin_int_t *)PINT2_MASK_SET,
	(struct pin_int_t *)PINT3_MASK_SET,
};

637
inline unsigned int get_irq_base(u32 bank, u8 bmap)
638
{
639
	unsigned int irq_base;
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671

	if (bank < 2) {		/*PA-PB */
		irq_base = IRQ_PA0 + bmap * 16;
	} else {		/*PC-PJ */
		irq_base = IRQ_PC0 + bmap * 16;
	}

	return irq_base;
}

	/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
void init_pint_lut(void)
{
	u16 bank, bit, irq_base, bit_pos;
	u32 pint_assign;
	u8 bmap;

	memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut));

	for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {

		pint_assign = pint[bank]->assign;

		for (bit = 0; bit < NR_PINT_BITS; bit++) {

			bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF;

			irq_base = get_irq_base(bank, bmap);

			irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0);
			bit_pos = bit + bank * NR_PINT_BITS;

672
			pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;
673 674 675 676 677 678 679
			irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;
		}
	}
}

static void bfin_gpio_ack_irq(unsigned int irq)
{
680 681
	struct irq_desc *desc = irq_desc + irq;
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
682
	u32 pintbit = PINT_BIT(pint_val);
683
	u32 bank = PINT_2_BANK(pint_val);
684

685
	if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
686 687 688 689 690 691
		if (pint[bank]->invert_set & pintbit)
			pint[bank]->invert_clear = pintbit;
		else
			pint[bank]->invert_set = pintbit;
	}
	pint[bank]->request = pintbit;
692 693 694 695 696

}

static void bfin_gpio_mask_ack_irq(unsigned int irq)
{
697 698
	struct irq_desc *desc = irq_desc + irq;
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
699
	u32 pintbit = PINT_BIT(pint_val);
700
	u32 bank = PINT_2_BANK(pint_val);
701

702
	if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
703 704 705 706 707 708
		if (pint[bank]->invert_set & pintbit)
			pint[bank]->invert_clear = pintbit;
		else
			pint[bank]->invert_set = pintbit;
	}

709 710
	pint[bank]->request = pintbit;
	pint[bank]->mask_clear = pintbit;
711 712 713 714
}

static void bfin_gpio_mask_irq(unsigned int irq)
{
715
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
716 717 718 719 720 721

	pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);
}

static void bfin_gpio_unmask_irq(unsigned int irq)
{
722
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
723
	u32 pintbit = PINT_BIT(pint_val);
724
	u32 bank = PINT_2_BANK(pint_val);
725

726 727
	pint[bank]->request = pintbit;
	pint[bank]->mask_set = pintbit;
728 729 730 731
}

static unsigned int bfin_gpio_irq_startup(unsigned int irq)
{
732 733
	u32 gpionr = irq_to_gpio(irq);
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
734

735 736 737 738
	if (pint_val == IRQ_NOT_AVAIL) {
		printk(KERN_ERR
		"GPIO IRQ %d :Not in PINT Assign table "
		"Reconfigure Interrupt to Port Assignemt\n", irq);
739
		return -ENODEV;
740
	}
741

742
	if (__test_and_set_bit(gpionr, gpio_enabled))
743
		bfin_gpio_irq_prepare(gpionr);
744 745 746

	bfin_gpio_unmask_irq(irq);

747
	return 0;
748 749 750 751
}

static void bfin_gpio_irq_shutdown(unsigned int irq)
{
752
	u32 gpionr = irq_to_gpio(irq);
753

754
	bfin_gpio_mask_irq(irq);
755
	__clear_bit(gpionr, gpio_enabled);
756
	bfin_gpio_irq_free(gpionr);
757 758 759 760
}

static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
{
761 762
	int ret;
	char buf[16];
763 764
	u32 gpionr = irq_to_gpio(irq);
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
765
	u32 pintbit = PINT_BIT(pint_val);
766
	u32 bank = PINT_2_BANK(pint_val);
767 768 769 770 771 772

	if (pint_val == IRQ_NOT_AVAIL)
		return -ENODEV;

	if (type == IRQ_TYPE_PROBE) {
		/* only probe unenabled GPIO interrupt lines */
773
		if (test_bit(gpionr, gpio_enabled))
774 775 776 777 778 779
			return 0;
		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
	}

	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
780 781 782 783 784 785

		snprintf(buf, 16, "gpio-irq%d", irq);
		ret = bfin_gpio_irq_request(gpionr, buf);
		if (ret)
			return ret;

786
		if (__test_and_set_bit(gpionr, gpio_enabled))
787
			bfin_gpio_irq_prepare(gpionr);
788 789

	} else {
790
		__clear_bit(gpionr, gpio_enabled);
791 792 793 794
		return 0;
	}

	if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
795
		pint[bank]->invert_set = pintbit;	/* low or falling edge denoted by one */
796
	else
797
		pint[bank]->invert_clear = pintbit;	/* high or rising edge denoted by zero */
798

799 800 801 802 803 804 805 806 807 808
	if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
	    == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
		if (gpio_get_value(gpionr))
			pint[bank]->invert_set = pintbit;
		else
			pint[bank]->invert_clear = pintbit;
	}

	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
		pint[bank]->edge_set = pintbit;
809
		bfin_set_irq_handler(irq, handle_edge_irq);
810 811
	} else {
		pint[bank]->edge_clear = pintbit;
812
		bfin_set_irq_handler(irq, handle_level_irq);
813 814
	}

815 816 817
	return 0;
}

818 819 820 821 822 823 824
#ifdef CONFIG_PM
u32 pint_saved_masks[NR_PINT_SYS_IRQS];
u32 pint_wakeup_masks[NR_PINT_SYS_IRQS];

int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
{
	u32 pint_irq;
825
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
	u32 bank = PINT_2_BANK(pint_val);
	u32 pintbit = PINT_BIT(pint_val);

	switch (bank) {
	case 0:
		pint_irq = IRQ_PINT0;
		break;
	case 2:
		pint_irq = IRQ_PINT2;
		break;
	case 3:
		pint_irq = IRQ_PINT3;
		break;
	case 1:
		pint_irq = IRQ_PINT1;
		break;
	default:
		return -EINVAL;
	}

	bfin_internal_set_wake(pint_irq, state);

	if (state)
		pint_wakeup_masks[bank] |= pintbit;
	else
		pint_wakeup_masks[bank] &= ~pintbit;

	return 0;
}

u32 bfin_pm_setup(void)
{
	u32 val, i;

	for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
		val = pint[i]->mask_clear;
		pint_saved_masks[i] = val;
		if (val ^ pint_wakeup_masks[i]) {
			pint[i]->mask_clear = val;
			pint[i]->mask_set = pint_wakeup_masks[i];
		}
	}

	return 0;
}

void bfin_pm_restore(void)
{
	u32 i, val;

	for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
		val = pint_saved_masks[i];
		if (val ^ pint_wakeup_masks[i]) {
			pint[i]->mask_clear = pint[i]->mask_clear;
			pint[i]->mask_set = val;
		}
	}
}
#endif

886 887
static void bfin_demux_gpio_irq(unsigned int inta_irq,
				struct irq_desc *desc)
888
{
889
	u32 bank, pint_val;
890 891
	u32 request, irq;

892
	switch (inta_irq) {
893 894 895 896 897 898 899 900 901 902 903 904
	case IRQ_PINT0:
		bank = 0;
		break;
	case IRQ_PINT2:
		bank = 2;
		break;
	case IRQ_PINT3:
		bank = 3;
		break;
	case IRQ_PINT1:
		bank = 1;
		break;
905 906
	default:
		return;
907 908 909 910 911 912 913 914
	}

	pint_val = bank * NR_PINT_BITS;

	request = pint[bank]->request;

	while (request) {
		if (request & 1) {
915
			irq = pint2irq_lut[pint_val] + SYS_IRQS;
916
			bfin_handle_irq(irq);
917 918 919 920 921 922
		}
		pint_val++;
		request >>= 1;
	}

}
923
#endif
B
Bryan Wu 已提交
924

925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
static struct irq_chip bfin_gpio_irqchip = {
	.name = "GPIO",
	.ack = bfin_gpio_ack_irq,
	.mask = bfin_gpio_mask_irq,
	.mask_ack = bfin_gpio_mask_ack_irq,
	.unmask = bfin_gpio_unmask_irq,
	.disable = bfin_gpio_mask_irq,
	.enable = bfin_gpio_unmask_irq,
	.set_type = bfin_gpio_irq_type,
	.startup = bfin_gpio_irq_startup,
	.shutdown = bfin_gpio_irq_shutdown,
#ifdef CONFIG_PM
	.set_wake = bfin_gpio_set_wake,
#endif
};

941
void __cpuinit init_exception_vectors(void)
942
{
943 944 945 946 947
	/* cannot program in software:
	 * evt0 - emulation (jtag)
	 * evt1 - reset
	 */
	bfin_write_EVT2(evt_nmi);
948 949 950 951 952 953 954 955 956 957
	bfin_write_EVT3(trap);
	bfin_write_EVT5(evt_ivhw);
	bfin_write_EVT6(evt_timer);
	bfin_write_EVT7(evt_evt7);
	bfin_write_EVT8(evt_evt8);
	bfin_write_EVT9(evt_evt9);
	bfin_write_EVT10(evt_evt10);
	bfin_write_EVT11(evt_evt11);
	bfin_write_EVT12(evt_evt12);
	bfin_write_EVT13(evt_evt13);
958
	bfin_write_EVT14(evt_evt14);
959 960 961 962
	bfin_write_EVT15(evt_system_call);
	CSYNC();
}

B
Bryan Wu 已提交
963 964 965 966
/*
 * This function should be called during kernel startup to initialize
 * the BFin IRQ handling routines.
 */
967

B
Bryan Wu 已提交
968 969 970 971 972
int __init init_arch_irq(void)
{
	int irq;
	unsigned long ilat = 0;
	/*  Disable all the peripheral intrs  - page 4-29 HW Ref manual */
973 974
#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
	|| defined(BF538_FAMILY) || defined(CONFIG_BF51x)
975 976
	bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
	bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);
977
# ifdef CONFIG_BF54x
978
	bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
979
# endif
980 981 982 983
# ifdef CONFIG_SMP
	bfin_write_SICB_IMASK0(SIC_UNMASK_ALL);
	bfin_write_SICB_IMASK1(SIC_UNMASK_ALL);
# endif
984
#else
B
Bryan Wu 已提交
985
	bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
986
#endif
B
Bryan Wu 已提交
987 988 989

	local_irq_disable();

990
#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
991 992 993 994
	/* Clear EMAC Interrupt Status bits so we can demux it later */
	bfin_write_EMAC_SYSTAT(-1);
#endif

995 996
#ifdef CONFIG_BF54x
# ifdef CONFIG_PINTx_REASSIGN
997 998 999 1000
	pint[0]->assign = CONFIG_PINT0_ASSIGN;
	pint[1]->assign = CONFIG_PINT1_ASSIGN;
	pint[2]->assign = CONFIG_PINT2_ASSIGN;
	pint[3]->assign = CONFIG_PINT3_ASSIGN;
1001
# endif
1002 1003 1004 1005 1006
	/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
	init_pint_lut();
#endif

	for (irq = 0; irq <= SYS_IRQS; irq++) {
B
Bryan Wu 已提交
1007 1008 1009 1010 1011
		if (irq <= IRQ_CORETMR)
			set_irq_chip(irq, &bfin_core_irqchip);
		else
			set_irq_chip(irq, &bfin_internal_irqchip);

1012
		switch (irq) {
1013
#if defined(CONFIG_BF53x)
1014
		case IRQ_PROG_INTA:
1015
# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
1016
		case IRQ_MAC_RX:
1017
# endif
1018
#elif defined(CONFIG_BF54x)
1019 1020 1021 1022
		case IRQ_PINT0:
		case IRQ_PINT1:
		case IRQ_PINT2:
		case IRQ_PINT3:
1023
#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
1024 1025 1026
		case IRQ_PORTF_INTA:
		case IRQ_PORTG_INTA:
		case IRQ_PORTH_INTA:
1027
#elif defined(CONFIG_BF561)
1028 1029 1030
		case IRQ_PROG0_INTA:
		case IRQ_PROG1_INTA:
		case IRQ_PROG2_INTA:
1031 1032
#elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
		case IRQ_PORTF_INTA:
B
Bryan Wu 已提交
1033
#endif
1034

1035 1036 1037
			set_irq_chained_handler(irq,
						bfin_demux_gpio_irq);
			break;
B
Bryan Wu 已提交
1038
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
1039
		case IRQ_GENERIC_ERROR:
1040
			set_irq_chained_handler(irq, bfin_demux_error_irq);
1041
			break;
B
Bryan Wu 已提交
1042
#endif
1043

1044
#ifdef CONFIG_SMP
1045 1046 1047 1048 1049 1050
#ifdef CONFIG_TICKSOURCE_GPTMR0
		case IRQ_TIMER0:
#endif
#ifdef CONFIG_TICKSOURCE_CORETMR
		case IRQ_CORETMR:
#endif
1051 1052 1053 1054 1055
		case IRQ_SUPPLE_0:
		case IRQ_SUPPLE_1:
			set_irq_handler(irq, handle_percpu_irq);
			break;
#endif
1056

1057
#ifdef CONFIG_IPIPE
1058 1059 1060 1061
#ifndef CONFIG_TICKSOURCE_CORETMR
		case IRQ_TIMER0:
			set_irq_handler(irq, handle_simple_irq);
			break;
1062
#endif
1063 1064 1065 1066 1067 1068
		case IRQ_CORETMR:
			set_irq_handler(irq, handle_simple_irq);
			break;
		default:
			set_irq_handler(irq, handle_level_irq);
			break;
1069
#else /* !CONFIG_IPIPE */
1070
		default:
1071 1072
			set_irq_handler(irq, handle_simple_irq);
			break;
1073
#endif /* !CONFIG_IPIPE */
1074
		}
B
Bryan Wu 已提交
1075
	}
1076

B
Bryan Wu 已提交
1077
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
1078 1079 1080
	for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++)
		set_irq_chip_and_handler(irq, &bfin_generic_error_irqchip,
					 handle_level_irq);
B
Bryan Wu 已提交
1081 1082
#endif

1083 1084 1085 1086
	/* if configured as edge, then will be changed to do_edge_IRQ */
	for (irq = GPIO_IRQ_BASE; irq < NR_IRQS; irq++)
		set_irq_chip_and_handler(irq, &bfin_gpio_irqchip,
					 handle_level_irq);
1087

1088

B
Bryan Wu 已提交
1089 1090 1091 1092 1093 1094 1095
	bfin_write_IMASK(0);
	CSYNC();
	ilat = bfin_read_ILAT();
	CSYNC();
	bfin_write_ILAT(ilat);
	CSYNC();

1096
	printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
1097
	/* IMASK=xxx is equivalent to STI xx or bfin_irq_flags=xx,
B
Bryan Wu 已提交
1098 1099 1100 1101 1102 1103 1104
	 * local_irq_enable()
	 */
	program_IAR();
	/* Therefore it's better to setup IARs before interrupts enabled */
	search_IAR();

	/* Enable interrupts IVG7-15 */
1105
	bfin_irq_flags |= IMASK_IVG15 |
B
Bryan Wu 已提交
1106
	    IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
1107
	    IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
B
Bryan Wu 已提交
1108

1109 1110 1111
	/* This implicitly covers ANOMALY_05000171
	 * Boot-ROM code modifies SICA_IWRx wakeup registers
	 */
1112
#ifdef SIC_IWR0
1113
	bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
1114
# ifdef SIC_IWR1
1115
	/* BF52x/BF51x system reset does not properly reset SIC_IWR1 which
1116 1117 1118 1119
	 * will screw up the bootrom as it relies on MDMA0/1 waking it
	 * up from IDLE instructions.  See this report for more info:
	 * http://blackfin.uclinux.org/gf/tracker/4323
	 */
1120 1121 1122 1123
	if (ANOMALY_05000435)
		bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
	else
		bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
1124 1125
# endif
# ifdef SIC_IWR2
1126
	bfin_write_SIC_IWR2(IWR_DISABLE_ALL);
1127 1128
# endif
#else
1129
	bfin_write_SIC_IWR(IWR_DISABLE_ALL);
1130 1131
#endif

B
Bryan Wu 已提交
1132 1133 1134 1135
	return 0;
}

#ifdef CONFIG_DO_IRQ_L1
1136
__attribute__((l1_text))
B
Bryan Wu 已提交
1137 1138 1139 1140 1141 1142 1143 1144
#endif
void do_irq(int vec, struct pt_regs *fp)
{
	if (vec == EVT_IVTMR_P) {
		vec = IRQ_CORETMR;
	} else {
		struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
		struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
1145
#if defined(SIC_ISR0) || defined(SICA_ISR0)
1146
		unsigned long sic_status[3];
B
Bryan Wu 已提交
1147

1148
		if (smp_processor_id()) {
1149
# ifdef SICB_ISR0
1150 1151 1152
			/* This will be optimized out in UP mode. */
			sic_status[0] = bfin_read_SICB_ISR0() & bfin_read_SICB_IMASK0();
			sic_status[1] = bfin_read_SICB_ISR1() & bfin_read_SICB_IMASK1();
1153
# endif
1154 1155 1156 1157
		} else {
			sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
			sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
		}
1158
# ifdef SIC_ISR2
1159
		sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
1160
# endif
1161
		for (;; ivg++) {
1162 1163 1164 1165
			if (ivg >= ivg_stop) {
				atomic_inc(&num_spurious);
				return;
			}
1166
			if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
1167 1168 1169 1170
				break;
		}
#else
		unsigned long sic_status;
1171

B
Bryan Wu 已提交
1172 1173 1174 1175 1176 1177 1178 1179 1180
		sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();

		for (;; ivg++) {
			if (ivg >= ivg_stop) {
				atomic_inc(&num_spurious);
				return;
			} else if (sic_status & ivg->isrflag)
				break;
		}
1181
#endif
B
Bryan Wu 已提交
1182 1183 1184 1185
		vec = ivg->irqno;
	}
	asm_do_IRQ(vec, fp);
}
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215

#ifdef CONFIG_IPIPE

int __ipipe_get_irq_priority(unsigned irq)
{
	int ient, prio;

	if (irq <= IRQ_CORETMR)
		return irq;

	for (ient = 0; ient < NR_PERI_INTS; ient++) {
		struct ivgx *ivg = ivg_table + ient;
		if (ivg->irqno == irq) {
			for (prio = 0; prio <= IVG13-IVG7; prio++) {
				if (ivg7_13[prio].ifirst <= ivg &&
				    ivg7_13[prio].istop > ivg)
					return IVG7 + prio;
			}
		}
	}

	return IVG15;
}

/* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */
#ifdef CONFIG_DO_IRQ_L1
__attribute__((l1_text))
#endif
asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
{
1216
	struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
1217
	struct ipipe_domain *this_domain = __ipipe_current_domain;
1218 1219
	struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
	struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
1220
	int irq, s;
1221

1222
	if (likely(vec == EVT_IVTMR_P))
1223
		irq = IRQ_CORETMR;
1224
	else {
1225
#if defined(SIC_ISR0) || defined(SICA_ISR0)
1226 1227 1228 1229
		unsigned long sic_status[3];

		sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
		sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
1230
# ifdef SIC_ISR2
1231
		sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
1232
# endif
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
		for (;; ivg++) {
			if (ivg >= ivg_stop) {
				atomic_inc(&num_spurious);
				return 0;
			}
			if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
				break;
		}
#else
		unsigned long sic_status;

		sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();

		for (;; ivg++) {
			if (ivg >= ivg_stop) {
				atomic_inc(&num_spurious);
				return 0;
			} else if (sic_status & ivg->isrflag)
				break;
		}
#endif
1254 1255
		irq = ivg->irqno;
	}
1256 1257

	if (irq == IRQ_SYSTMR) {
1258
#if !defined(CONFIG_GENERIC_CLOCKEVENTS) || defined(CONFIG_TICKSOURCE_GPTMR0)
1259
		bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */
1260
#endif
1261 1262 1263
		/* This is basically what we need from the register frame. */
		__raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend;
		__raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc;
1264
		if (this_domain != ipipe_root_domain)
1265
			__raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10;
1266 1267
		else
			__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
1268 1269
	}

1270 1271 1272 1273
	if (this_domain == ipipe_root_domain) {
		s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
		barrier();
	}
1274 1275 1276

	ipipe_trace_irq_entry(irq);
	__ipipe_handle_irq(irq, regs);
1277
	ipipe_trace_irq_exit(irq);
1278

1279 1280 1281 1282 1283 1284 1285
	if (this_domain == ipipe_root_domain) {
		set_thread_flag(TIF_IRQ_SYNC);
		if (!s) {
			__clear_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
			return !test_bit(IPIPE_STALL_FLAG, &p->status);
		}
	}
1286

1287
	return 0;
1288 1289 1290
}

#endif /* CONFIG_IPIPE */