ints-priority.c 26.4 KB
Newer Older
B
Bryan Wu 已提交
1
/*
2
 * File:         arch/blackfin/mach-common/ints-priority.c
B
Bryan Wu 已提交
3
 *
S
Simon Arlott 已提交
4
 * Description:  Set up the interrupt priorities
B
Bryan Wu 已提交
5 6 7 8 9 10 11 12
 *
 * Modified:
 *               1996 Roman Zippel
 *               1999 D. Jeff Dionne <jeff@uclinux.org>
 *               2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca>
 *               2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
 *               2003 Metrowerks/Motorola
 *               2003 Bas Vermeulen <bas@buyways.nl>
13
 *               Copyright 2004-2008 Analog Devices Inc.
B
Bryan Wu 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 *
 * Bugs:         Enter bugs at http://blackfin.uclinux.org/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see the file COPYING, or write
 * to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <linux/module.h>
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <linux/irq.h>
#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>

45 46
#define SIC_SYSIRQ(irq)	(irq - (IRQ_CORETMR + 1))

B
Bryan Wu 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59
#ifdef BF537_FAMILY
# define BF537_GENERIC_ERROR_INT_DEMUX
#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)
 * -
 */

60
#ifndef CONFIG_SMP
61 62 63 64 65 66
/* 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.
 */
67 68
unsigned long bfin_irq_flags = 0x1f;
EXPORT_SYMBOL(bfin_irq_flags);
69
#endif
B
Bryan Wu 已提交
70 71 72 73

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

74 75
#ifdef CONFIG_PM
unsigned long bfin_sic_iwr[3];	/* Up to 3 SIC_IWRx registers */
76
unsigned vr_wakeup;
77 78
#endif

B
Bryan Wu 已提交
79
struct ivgx {
80
	/* irq number for request_irq, available in mach-bf5xx/irq.h */
81
	unsigned int irqno;
B
Bryan Wu 已提交
82
	/* corresponding bit in the SIC_ISR register */
83
	unsigned int isrflag;
B
Bryan Wu 已提交
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
} 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;

103
		ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
B
Bryan Wu 已提交
104 105 106

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

/*
127
 * This is for core internal IRQs
B
Bryan Wu 已提交
128 129
 */

130
static void bfin_ack_noop(unsigned int irq)
B
Bryan Wu 已提交
131 132 133 134 135 136
{
	/* Dummy function.  */
}

static void bfin_core_mask_irq(unsigned int irq)
{
137
	bfin_irq_flags &= ~(1 << irq);
B
Bryan Wu 已提交
138 139 140 141 142 143
	if (!irqs_disabled())
		local_irq_enable();
}

static void bfin_core_unmask_irq(unsigned int irq)
{
144
	bfin_irq_flags |= 1 << irq;
B
Bryan Wu 已提交
145 146
	/*
	 * If interrupts are enabled, IMASK must contain the same value
147
	 * as bfin_irq_flags.  Make sure that invariant holds.  If interrupts
B
Bryan Wu 已提交
148 149 150
	 * 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.
151
	 * local_irq_enable just does "STI bfin_irq_flags", so it's exactly
B
Bryan Wu 已提交
152 153 154 155 156 157 158 159 160
	 * what we need.
	 */
	if (!irqs_disabled())
		local_irq_enable();
	return;
}

static void bfin_internal_mask_irq(unsigned int irq)
{
161
#ifdef CONFIG_BF53x
B
Bryan Wu 已提交
162
	bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
163
			     ~(1 << SIC_SYSIRQ(irq)));
164 165
#else
	unsigned mask_bank, mask_bit;
166 167
	mask_bank = SIC_SYSIRQ(irq) / 32;
	mask_bit = SIC_SYSIRQ(irq) % 32;
168 169
	bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
			     ~(1 << mask_bit));
170 171 172 173
#ifdef CONFIG_SMP
	bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) &
			     ~(1 << mask_bit));
#endif
174
#endif
B
Bryan Wu 已提交
175 176 177 178
}

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

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

203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
	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
229
#ifdef CONFIG_BF54x
230 231 232 233 234 235 236 237
	case IRQ_CNT:
	wakeup |= ROTWE;
	break;
#endif
	default:
	break;
	}

238 239
	local_irq_save(flags);

240
	if (state) {
241
		bfin_sic_iwr[bank] |= (1 << bit);
242 243 244
		vr_wakeup  |= wakeup;

	} else {
245
		bfin_sic_iwr[bank] &= ~(1 << bit);
246 247
		vr_wakeup  &= ~wakeup;
	}
248 249 250 251 252 253 254

	local_irq_restore(flags);

	return 0;
}
#endif

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

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

#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));

282 283
	if (!error_int_mask)
		bfin_internal_mask_irq(IRQ_GENERIC_ERROR);
B
Bryan Wu 已提交
284 285 286 287
}

static void bfin_generic_error_unmask_irq(unsigned int irq)
{
288
	bfin_internal_unmask_irq(IRQ_GENERIC_ERROR);
B
Bryan Wu 已提交
289 290 291 292
	error_int_mask |= 1L << (irq - IRQ_PPI_ERROR);
}

static struct irq_chip bfin_generic_error_irqchip = {
293
	.name = "ERROR",
294 295
	.ack = bfin_ack_noop,
	.mask_ack = bfin_generic_error_mask_irq,
B
Bryan Wu 已提交
296 297 298 299 300
	.mask = bfin_generic_error_mask_irq,
	.unmask = bfin_generic_error_unmask_irq,
};

static void bfin_demux_error_irq(unsigned int int_err_irq,
301
				 struct irq_desc *inta_desc)
B
Bryan Wu 已提交
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
{
	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;
	else if ((bfin_read_UART0_IIR() & UART_ERR_MASK_STAT1) &&
		 (bfin_read_UART0_IIR() & UART_ERR_MASK_STAT0))
		irq = IRQ_UART0_ERROR;
	else if ((bfin_read_UART1_IIR() & UART_ERR_MASK_STAT1) &&
		 (bfin_read_UART1_IIR() & UART_ERR_MASK_STAT0))
		irq = IRQ_UART1_ERROR;

	if (irq) {
		if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) {
			struct irq_desc *desc = irq_desc + irq;
			desc->handle_irq(irq, desc);
		} else {

			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:"
363 364
				 " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
				 irq);
B
Bryan Wu 已提交
365 366 367 368 369
		}
	} else
		printk(KERN_ERR
		       "%s : %s : LINE %d :\nIRQ ?: PERIPHERAL ERROR"
		       " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
370
		       __func__, __FILE__, __LINE__);
B
Bryan Wu 已提交
371 372 373 374

}
#endif				/* BF537_GENERIC_ERROR_INT_DEMUX */

375 376 377 378 379 380 381 382
static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
{
	struct irq_desc *desc = irq_desc + irq;
	/* May not call generic set_irq_handler() due to spinlock
	   recursion. */
	desc->handle_irq = handle;
}

383
static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
384
extern void bfin_gpio_irq_prepare(unsigned gpio);
385

386 387
#if !defined(CONFIG_BF54x)

B
Bryan Wu 已提交
388 389
static void bfin_gpio_ack_irq(unsigned int irq)
{
390 391 392 393
	/* 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 已提交
394 395 396 397
}

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

401
	if (desc->handle_irq == handle_edge_irq)
B
Bryan Wu 已提交
402 403 404 405 406 407 408
		set_gpio_data(gpionr, 0);

	set_gpio_maska(gpionr, 0);
}

static void bfin_gpio_mask_irq(unsigned int irq)
{
409
	set_gpio_maska(irq_to_gpio(irq), 0);
B
Bryan Wu 已提交
410 411 412 413
}

static void bfin_gpio_unmask_irq(unsigned int irq)
{
414
	set_gpio_maska(irq_to_gpio(irq), 1);
B
Bryan Wu 已提交
415 416 417 418
}

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

421
	if (__test_and_set_bit(gpionr, gpio_enabled))
422
		bfin_gpio_irq_prepare(gpionr);
B
Bryan Wu 已提交
423 424 425

	bfin_gpio_unmask_irq(irq);

426
	return 0;
B
Bryan Wu 已提交
427 428 429 430
}

static void bfin_gpio_irq_shutdown(unsigned int irq)
{
431 432
	u32 gpionr = irq_to_gpio(irq);

B
Bryan Wu 已提交
433
	bfin_gpio_mask_irq(irq);
434 435
	__clear_bit(gpionr, gpio_enabled);
	bfin_gpio_free(gpionr);
B
Bryan Wu 已提交
436 437 438 439
}

static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
{
440
	u32 gpionr = irq_to_gpio(irq);
B
Bryan Wu 已提交
441 442 443

	if (type == IRQ_TYPE_PROBE) {
		/* only probe unenabled GPIO interrupt lines */
444
		if (__test_bit(gpionr, gpio_enabled))
B
Bryan Wu 已提交
445 446 447 448 449
			return 0;
		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
	}

	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
450
		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
451 452

		if (__test_and_set_bit(gpionr, gpio_enabled))
453
			bfin_gpio_irq_prepare(gpionr);
B
Bryan Wu 已提交
454 455

	} else {
456
		__clear_bit(gpionr, gpio_enabled);
B
Bryan Wu 已提交
457 458 459
		return 0;
	}

460
	set_gpio_inen(gpionr, 0);
B
Bryan Wu 已提交
461 462 463 464 465 466 467 468 469 470 471 472 473
	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 */

474 475 476 477 478 479 480 481 482 483
	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 已提交
484
	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
485
		bfin_set_irq_handler(irq, handle_edge_irq);
B
Bryan Wu 已提交
486
	else
487
		bfin_set_irq_handler(irq, handle_level_irq);
B
Bryan Wu 已提交
488 489 490 491

	return 0;
}

492 493 494 495 496 497 498 499 500 501 502 503 504 505
#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

506 507
static void bfin_demux_gpio_irq(unsigned int inta_irq,
				struct irq_desc *desc)
B
Bryan Wu 已提交
508
{
509 510 511 512 513 514 515 516 517 518 519 520 521
	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
522 523 524 525
#elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
	case IRQ_PORTF_INTA:
		irq = IRQ_PF0;
		break;
526
#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
	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) {
553
		for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
554 555
			irq += i;

556
			mask = get_gpiop_data(i) & get_gpiop_maska(i);
557 558 559 560 561 562 563 564

			while (mask) {
				if (mask & 1) {
					desc = irq_desc + irq;
					desc->handle_irq(irq, desc);
				}
				irq++;
				mask >>= 1;
B
Bryan Wu 已提交
565 566
			}
		}
567 568
	} else {
			gpio = irq_to_gpio(irq);
569
			mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio);
570 571 572 573 574 575 576 577 578

			do {
				if (mask & 1) {
					desc = irq_desc + irq;
					desc->handle_irq(irq, desc);
				}
				irq++;
				mask >>= 1;
			} while (mask);
B
Bryan Wu 已提交
579
	}
580

B
Bryan Wu 已提交
581 582
}

583
#else				/* CONFIG_BF54x */
584 585 586 587 588 589 590 591 592 593 594

#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];
595
static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616

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,
};

617
inline unsigned int get_irq_base(u32 bank, u8 bmap)
618
{
619
	unsigned int irq_base;
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651

	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;

652
			pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;
653 654 655 656 657 658 659
			irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;
		}
	}
}

static void bfin_gpio_ack_irq(unsigned int irq)
{
660 661
	struct irq_desc *desc = irq_desc + irq;
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
662
	u32 pintbit = PINT_BIT(pint_val);
663
	u32 bank = PINT_2_BANK(pint_val);
664

665
	if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
666 667 668 669 670 671
		if (pint[bank]->invert_set & pintbit)
			pint[bank]->invert_clear = pintbit;
		else
			pint[bank]->invert_set = pintbit;
	}
	pint[bank]->request = pintbit;
672 673 674 675 676

}

static void bfin_gpio_mask_ack_irq(unsigned int irq)
{
677 678
	struct irq_desc *desc = irq_desc + irq;
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
679
	u32 pintbit = PINT_BIT(pint_val);
680
	u32 bank = PINT_2_BANK(pint_val);
681

682
	if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
683 684 685 686 687 688
		if (pint[bank]->invert_set & pintbit)
			pint[bank]->invert_clear = pintbit;
		else
			pint[bank]->invert_set = pintbit;
	}

689 690
	pint[bank]->request = pintbit;
	pint[bank]->mask_clear = pintbit;
691 692 693 694
}

static void bfin_gpio_mask_irq(unsigned int irq)
{
695
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
696 697 698 699 700 701

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

static void bfin_gpio_unmask_irq(unsigned int irq)
{
702
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
703
	u32 pintbit = PINT_BIT(pint_val);
704
	u32 bank = PINT_2_BANK(pint_val);
705

706 707
	pint[bank]->request = pintbit;
	pint[bank]->mask_set = pintbit;
708 709 710 711
}

static unsigned int bfin_gpio_irq_startup(unsigned int irq)
{
712 713
	u32 gpionr = irq_to_gpio(irq);
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
714

715 716 717 718
	if (pint_val == IRQ_NOT_AVAIL) {
		printk(KERN_ERR
		"GPIO IRQ %d :Not in PINT Assign table "
		"Reconfigure Interrupt to Port Assignemt\n", irq);
719
		return -ENODEV;
720
	}
721

722
	if (__test_and_set_bit(gpionr, gpio_enabled))
723
		bfin_gpio_irq_prepare(gpionr);
724 725 726

	bfin_gpio_unmask_irq(irq);

727
	return 0;
728 729 730 731
}

static void bfin_gpio_irq_shutdown(unsigned int irq)
{
732
	u32 gpionr = irq_to_gpio(irq);
733

734
	bfin_gpio_mask_irq(irq);
735
	__clear_bit(gpionr, gpio_enabled);
736
	bfin_gpio_free(gpionr);
737 738 739 740 741
}

static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
{

742 743
	u32 gpionr = irq_to_gpio(irq);
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
744
	u32 pintbit = PINT_BIT(pint_val);
745
	u32 bank = PINT_2_BANK(pint_val);
746 747 748 749 750 751

	if (pint_val == IRQ_NOT_AVAIL)
		return -ENODEV;

	if (type == IRQ_TYPE_PROBE) {
		/* only probe unenabled GPIO interrupt lines */
752
		if (__test_bit(gpionr, gpio_enabled))
753 754 755 756 757 758
			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)) {
759
		if (__test_and_set_bit(gpionr, gpio_enabled))
760
			bfin_gpio_irq_prepare(gpionr);
761 762

	} else {
763
		__clear_bit(gpionr, gpio_enabled);
764 765 766 767
		return 0;
	}

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

772 773 774 775 776 777 778 779 780 781
	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;
782
		bfin_set_irq_handler(irq, handle_edge_irq);
783 784
	} else {
		pint[bank]->edge_clear = pintbit;
785
		bfin_set_irq_handler(irq, handle_level_irq);
786 787
	}

788 789 790
	return 0;
}

791 792 793 794 795 796 797
#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;
798
	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 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
	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

859 860
static void bfin_demux_gpio_irq(unsigned int inta_irq,
				struct irq_desc *desc)
861
{
862
	u32 bank, pint_val;
863 864
	u32 request, irq;

865
	switch (inta_irq) {
866 867 868 869 870 871 872 873 874 875 876 877
	case IRQ_PINT0:
		bank = 0;
		break;
	case IRQ_PINT2:
		bank = 2;
		break;
	case IRQ_PINT3:
		bank = 3;
		break;
	case IRQ_PINT1:
		bank = 1;
		break;
878 879
	default:
		return;
880 881 882 883 884 885 886 887
	}

	pint_val = bank * NR_PINT_BITS;

	request = pint[bank]->request;

	while (request) {
		if (request & 1) {
888 889
			irq = pint2irq_lut[pint_val] + SYS_IRQS;
			desc = irq_desc + irq;
890 891 892 893 894 895 896
			desc->handle_irq(irq, desc);
		}
		pint_val++;
		request >>= 1;
	}

}
897
#endif
B
Bryan Wu 已提交
898

899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914
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
};

915
void __cpuinit init_exception_vectors(void)
916
{
917 918 919 920 921
	/* cannot program in software:
	 * evt0 - emulation (jtag)
	 * evt1 - reset
	 */
	bfin_write_EVT2(evt_nmi);
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
	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);
	bfin_write_EVT14(evt14_softirq);
	bfin_write_EVT15(evt_system_call);
	CSYNC();
}

B
Bryan Wu 已提交
937 938 939 940
/*
 * This function should be called during kernel startup to initialize
 * the BFin IRQ handling routines.
 */
941

B
Bryan Wu 已提交
942 943 944 945 946
int __init init_arch_irq(void)
{
	int irq;
	unsigned long ilat = 0;
	/*  Disable all the peripheral intrs  - page 4-29 HW Ref manual */
947 948
#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
	|| defined(BF538_FAMILY) || defined(CONFIG_BF51x)
949 950
	bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
	bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);
951
# ifdef CONFIG_BF54x
952
	bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
953
# endif
954 955 956 957
# ifdef CONFIG_SMP
	bfin_write_SICB_IMASK0(SIC_UNMASK_ALL);
	bfin_write_SICB_IMASK1(SIC_UNMASK_ALL);
# endif
958
#else
B
Bryan Wu 已提交
959
	bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
960
#endif
B
Bryan Wu 已提交
961 962 963

	local_irq_disable();

964
#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
965 966 967 968
	/* Clear EMAC Interrupt Status bits so we can demux it later */
	bfin_write_EMAC_SYSTAT(-1);
#endif

969 970
#ifdef CONFIG_BF54x
# ifdef CONFIG_PINTx_REASSIGN
971 972 973 974
	pint[0]->assign = CONFIG_PINT0_ASSIGN;
	pint[1]->assign = CONFIG_PINT1_ASSIGN;
	pint[2]->assign = CONFIG_PINT2_ASSIGN;
	pint[3]->assign = CONFIG_PINT3_ASSIGN;
975
# endif
976 977 978 979 980
	/* 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 已提交
981 982 983 984 985
		if (irq <= IRQ_CORETMR)
			set_irq_chip(irq, &bfin_core_irqchip);
		else
			set_irq_chip(irq, &bfin_internal_irqchip);

986
		switch (irq) {
987
#if defined(CONFIG_BF53x)
988
		case IRQ_PROG_INTA:
989
# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
990
		case IRQ_MAC_RX:
991
# endif
992
#elif defined(CONFIG_BF54x)
993 994 995 996
		case IRQ_PINT0:
		case IRQ_PINT1:
		case IRQ_PINT2:
		case IRQ_PINT3:
997
#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
998 999 1000
		case IRQ_PORTF_INTA:
		case IRQ_PORTG_INTA:
		case IRQ_PORTH_INTA:
1001
#elif defined(CONFIG_BF561)
1002 1003 1004
		case IRQ_PROG0_INTA:
		case IRQ_PROG1_INTA:
		case IRQ_PROG2_INTA:
1005 1006
#elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
		case IRQ_PORTF_INTA:
B
Bryan Wu 已提交
1007
#endif
1008

1009 1010 1011
			set_irq_chained_handler(irq,
						bfin_demux_gpio_irq);
			break;
B
Bryan Wu 已提交
1012
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
1013
		case IRQ_GENERIC_ERROR:
B
Bryan Wu 已提交
1014
			set_irq_handler(irq, bfin_demux_error_irq);
1015 1016

			break;
B
Bryan Wu 已提交
1017
#endif
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
#ifdef CONFIG_TICK_SOURCE_SYSTMR0
		case IRQ_TIMER0:
			set_irq_handler(irq, handle_percpu_irq);
			break;
#endif
#ifdef CONFIG_SMP
		case IRQ_SUPPLE_0:
		case IRQ_SUPPLE_1:
			set_irq_handler(irq, handle_percpu_irq);
			break;
#endif
1029 1030 1031 1032
		default:
			set_irq_handler(irq, handle_simple_irq);
			break;
		}
B
Bryan Wu 已提交
1033
	}
1034

B
Bryan Wu 已提交
1035
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
1036 1037 1038
	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 已提交
1039 1040
#endif

1041 1042 1043 1044
	/* 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);
1045

1046

B
Bryan Wu 已提交
1047 1048 1049 1050 1051 1052 1053
	bfin_write_IMASK(0);
	CSYNC();
	ilat = bfin_read_ILAT();
	CSYNC();
	bfin_write_ILAT(ilat);
	CSYNC();

1054
	printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
1055
	/* IMASK=xxx is equivalent to STI xx or bfin_irq_flags=xx,
B
Bryan Wu 已提交
1056 1057 1058 1059 1060 1061 1062
	 * local_irq_enable()
	 */
	program_IAR();
	/* Therefore it's better to setup IARs before interrupts enabled */
	search_IAR();

	/* Enable interrupts IVG7-15 */
1063
	bfin_irq_flags |= IMASK_IVG15 |
B
Bryan Wu 已提交
1064
	    IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
1065
	    IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
B
Bryan Wu 已提交
1066

1067 1068
#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
	|| defined(BF538_FAMILY) || defined(CONFIG_BF51x)
1069
	bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
1070 1071
#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
	/* BF52x/BF51x system reset does not properly reset SIC_IWR1 which
1072 1073 1074 1075
	 * 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
	 */
1076 1077 1078 1079
	if (ANOMALY_05000435)
		bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
	else
		bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
1080
#else
1081
	bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
1082
#endif
1083
# ifdef CONFIG_BF54x
1084
	bfin_write_SIC_IWR2(IWR_DISABLE_ALL);
1085 1086
# endif
#else
1087
	bfin_write_SIC_IWR(IWR_DISABLE_ALL);
1088 1089
#endif

B
Bryan Wu 已提交
1090 1091 1092 1093
	return 0;
}

#ifdef CONFIG_DO_IRQ_L1
1094
__attribute__((l1_text))
B
Bryan Wu 已提交
1095 1096 1097 1098 1099 1100 1101 1102
#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;
1103 1104
#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
	|| defined(BF538_FAMILY) || defined(CONFIG_BF51x)
1105
		unsigned long sic_status[3];
B
Bryan Wu 已提交
1106

1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
		if (smp_processor_id()) {
#ifdef CONFIG_SMP
			/* 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();
#endif
		} else {
			sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
			sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
		}
1117
#ifdef CONFIG_BF54x
1118
		sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
1119
#endif
1120
		for (;; ivg++) {
1121 1122 1123 1124
			if (ivg >= ivg_stop) {
				atomic_inc(&num_spurious);
				return;
			}
1125
			if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
1126 1127 1128 1129
				break;
		}
#else
		unsigned long sic_status;
1130

B
Bryan Wu 已提交
1131 1132 1133 1134 1135 1136 1137 1138 1139
		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;
		}
1140
#endif
B
Bryan Wu 已提交
1141 1142 1143 1144
		vec = ivg->irqno;
	}
	asm_do_IRQ(vec, fp);
}