intc.c 14.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * Shared interrupt handling code for IPR and INTC2 types of IRQs.
 *
 * Copyright (C) 2007 Magnus Damm
 *
 * Based on intc2.c and ipr.c
 *
 * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
 * Copyright (C) 2000  Kazumoto Kojima
 * Copyright (C) 2001  David J. Mckay (david.mckay@st.com)
 * Copyright (C) 2003  Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
 * Copyright (C) 2005, 2006  Paul Mundt
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 */
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/interrupt.h>
M
Magnus Damm 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
#include <linux/bootmem.h>

#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
	((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
	 ((addr_e) << 16) | ((addr_d << 24)))

#define _INTC_SHIFT(h) (h & 0x1f)
#define _INTC_WIDTH(h) ((h >> 5) & 0xf)
#define _INTC_FN(h) ((h >> 9) & 0xf)
#define _INTC_MODE(h) ((h >> 13) & 0x7)
#define _INTC_ADDR_E(h) ((h >> 16) & 0xff)
#define _INTC_ADDR_D(h) ((h >> 24) & 0xff)

struct intc_handle_int {
	unsigned int irq;
	unsigned long handle;
};
40

M
Magnus Damm 已提交
41 42 43 44 45 46 47 48 49
struct intc_desc_int {
	unsigned long *reg;
	unsigned int nr_reg;
	struct intc_handle_int *prio;
	unsigned int nr_prio;
	struct intc_handle_int *sense;
	unsigned int nr_sense;
	struct irq_chip chip;
};
50

M
Magnus Damm 已提交
51
static unsigned int intc_prio_level[NR_IRQS]; /* for now */
52

M
Magnus Damm 已提交
53
static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
54 55
{
	struct irq_chip *chip = get_irq_chip(irq);
M
Magnus Damm 已提交
56
	return (void *)((char *)chip - offsetof(struct intc_desc_int, chip));
57 58 59 60
}

static inline unsigned int set_field(unsigned int value,
				     unsigned int field_value,
M
Magnus Damm 已提交
61
				     unsigned int handle)
62
{
M
Magnus Damm 已提交
63 64 65
	unsigned int width = _INTC_WIDTH(handle);
	unsigned int shift = _INTC_SHIFT(handle);

66 67 68 69 70
	value &= ~(((1 << width) - 1) << shift);
	value |= field_value << shift;
	return value;
}

M
Magnus Damm 已提交
71
static void write_8(unsigned long addr, unsigned long h, unsigned long data)
72
{
M
Magnus Damm 已提交
73
	ctrl_outb(set_field(0, data, h), addr);
74 75
}

M
Magnus Damm 已提交
76
static void write_16(unsigned long addr, unsigned long h, unsigned long data)
77
{
M
Magnus Damm 已提交
78
	ctrl_outw(set_field(0, data, h), addr);
79 80
}

M
Magnus Damm 已提交
81
static void write_32(unsigned long addr, unsigned long h, unsigned long data)
82
{
M
Magnus Damm 已提交
83
	ctrl_outl(set_field(0, data, h), addr);
84 85
}

M
Magnus Damm 已提交
86
static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
87
{
M
Magnus Damm 已提交
88
	ctrl_outb(set_field(ctrl_inb(addr), data, h), addr);
89 90
}

M
Magnus Damm 已提交
91
static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
92
{
M
Magnus Damm 已提交
93
	ctrl_outw(set_field(ctrl_inw(addr), data, h), addr);
94 95
}

M
Magnus Damm 已提交
96
static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
97
{
M
Magnus Damm 已提交
98
	ctrl_outl(set_field(ctrl_inl(addr), data, h), addr);
99 100
}

M
Magnus Damm 已提交
101 102 103 104 105 106 107 108 109 110 111 112
enum {	REG_FN_ERR = 0, REG_FN_WRITE_BASE = 1, REG_FN_MODIFY_BASE = 5 };

static void (*intc_reg_fns[])(unsigned long addr,
			      unsigned long h,
			      unsigned long data) = {
	[REG_FN_WRITE_BASE + 0] = write_8,
	[REG_FN_WRITE_BASE + 1] = write_16,
	[REG_FN_WRITE_BASE + 3] = write_32,
	[REG_FN_MODIFY_BASE + 0] = modify_8,
	[REG_FN_MODIFY_BASE + 1] = modify_16,
	[REG_FN_MODIFY_BASE + 3] = modify_32,
};
113

M
Magnus Damm 已提交
114 115 116 117 118 119
enum {	MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
	MODE_MASK_REG,       /* Bit(s) set -> interrupt disabled */
	MODE_DUAL_REG,       /* Two registers, set bit to enable / disable */
	MODE_PRIO_REG,       /* Priority value written to enable interrupt */
	MODE_PCLR_REG,       /* Above plus all bits set to disable interrupt */
};
120

M
Magnus Damm 已提交
121 122 123 124 125 126
static void intc_mode_field(unsigned long addr,
			    unsigned long handle,
			    void (*fn)(unsigned long,
				       unsigned long,
				       unsigned long),
			    unsigned int irq)
127
{
M
Magnus Damm 已提交
128
	fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1));
129 130
}

M
Magnus Damm 已提交
131 132 133 134 135 136
static void intc_mode_zero(unsigned long addr,
			   unsigned long handle,
			   void (*fn)(unsigned long,
				       unsigned long,
				       unsigned long),
			   unsigned int irq)
137
{
M
Magnus Damm 已提交
138
	fn(addr, handle, 0);
139 140
}

M
Magnus Damm 已提交
141 142 143 144 145 146
static void intc_mode_prio(unsigned long addr,
			   unsigned long handle,
			   void (*fn)(unsigned long,
				       unsigned long,
				       unsigned long),
			   unsigned int irq)
147
{
M
Magnus Damm 已提交
148
	fn(addr, handle, intc_prio_level[irq]);
149 150
}

M
Magnus Damm 已提交
151 152 153 154 155 156 157 158 159 160 161 162
static void (*intc_enable_fns[])(unsigned long addr,
				 unsigned long handle,
				 void (*fn)(unsigned long,
					    unsigned long,
					    unsigned long),
				 unsigned int irq) = {
	[MODE_ENABLE_REG] = intc_mode_field,
	[MODE_MASK_REG] = intc_mode_zero,
	[MODE_DUAL_REG] = intc_mode_field,
	[MODE_PRIO_REG] = intc_mode_prio,
	[MODE_PCLR_REG] = intc_mode_prio,
};
163

M
Magnus Damm 已提交
164 165 166 167 168 169 170 171 172 173 174 175
static void (*intc_disable_fns[])(unsigned long addr,
				  unsigned long handle,
				  void (*fn)(unsigned long,
					     unsigned long,
					     unsigned long),
				  unsigned int irq) = {
	[MODE_ENABLE_REG] = intc_mode_zero,
	[MODE_MASK_REG] = intc_mode_field,
	[MODE_DUAL_REG] = intc_mode_field,
	[MODE_PRIO_REG] = intc_mode_zero,
	[MODE_PCLR_REG] = intc_mode_field,
};
176

M
Magnus Damm 已提交
177
static inline void _intc_enable(unsigned int irq, unsigned long handle)
178
{
M
Magnus Damm 已提交
179 180
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned long addr = d->reg[_INTC_ADDR_E(handle)];
181

M
Magnus Damm 已提交
182 183 184
	intc_enable_fns[_INTC_MODE(handle)](addr, handle,
					    intc_reg_fns[_INTC_FN(handle)],
					    irq);
185 186
}

187 188
static void intc_enable(unsigned int irq)
{
M
Magnus Damm 已提交
189
	_intc_enable(irq, (unsigned long)get_irq_chip_data(irq));
190 191 192 193
}

static void intc_disable(unsigned int irq)
{
M
Magnus Damm 已提交
194 195 196
	struct intc_desc_int *desc = get_intc_desc(irq);
	unsigned long handle = (unsigned long) get_irq_chip_data(irq);
	unsigned long addr = desc->reg[_INTC_ADDR_D(handle)];
197

M
Magnus Damm 已提交
198 199 200
	intc_disable_fns[_INTC_MODE(handle)](addr, handle,
					     intc_reg_fns[_INTC_FN(handle)],
					     irq);
201 202
}

M
Magnus Damm 已提交
203 204 205
static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
					     unsigned int nr_hp,
					     unsigned int irq)
206
{
M
Magnus Damm 已提交
207 208
	int i;

209 210 211 212 213 214 215 216 217 218 219 220
	/* this doesn't scale well, but...
	 *
	 * this function should only be used for cerain uncommon
	 * operations such as intc_set_priority() and intc_set_sense()
	 * and in those rare cases performance doesn't matter that much.
	 * keeping the memory footprint low is more important.
	 *
	 * one rather simple way to speed this up and still keep the
	 * memory footprint down is to make sure the array is sorted
	 * and then perform a bisect to lookup the irq.
	 */

M
Magnus Damm 已提交
221 222 223 224 225 226
	for (i = 0; i < nr_hp; i++) {
		if ((hp + i)->irq != irq)
			continue;

		return hp + i;
	}
227

M
Magnus Damm 已提交
228
	return NULL;
229 230
}

M
Magnus Damm 已提交
231
int intc_set_priority(unsigned int irq, unsigned int prio)
232
{
M
Magnus Damm 已提交
233 234 235 236 237 238 239 240
	struct intc_desc_int *d = get_intc_desc(irq);
	struct intc_handle_int *ihp;

	if (!intc_prio_level[irq] || prio <= 1)
		return -EINVAL;

	ihp = intc_find_irq(d->prio, d->nr_prio, irq);
	if (ihp) {
241
		if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
M
Magnus Damm 已提交
242
			return -EINVAL;
243

M
Magnus Damm 已提交
244 245 246 247 248 249 250 251
		intc_prio_level[irq] = prio;

		/*
		 * only set secondary masking method directly
		 * primary masking method is using intc_prio_level[irq]
		 * priority level will be set during next enable()
		 */

252
		if (_INTC_FN(ihp->handle) != REG_FN_ERR)
M
Magnus Damm 已提交
253 254 255
			_intc_enable(irq, ihp->handle);
	}
	return 0;
256 257 258 259 260 261 262 263 264 265 266 267 268
}

#define VALID(x) (x | 0x80)

static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
	[IRQ_TYPE_EDGE_FALLING] = VALID(0),
	[IRQ_TYPE_EDGE_RISING] = VALID(1),
	[IRQ_TYPE_LEVEL_LOW] = VALID(2),
	[IRQ_TYPE_LEVEL_HIGH] = VALID(3),
};

static int intc_set_sense(unsigned int irq, unsigned int type)
{
M
Magnus Damm 已提交
269
	struct intc_desc_int *d = get_intc_desc(irq);
270
	unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
M
Magnus Damm 已提交
271 272
	struct intc_handle_int *ihp;
	unsigned long addr;
273

M
Magnus Damm 已提交
274
	if (!value)
275 276
		return -EINVAL;

M
Magnus Damm 已提交
277 278 279 280
	ihp = intc_find_irq(d->sense, d->nr_sense, irq);
	if (ihp) {
		addr = d->reg[_INTC_ADDR_E(ihp->handle)];
		intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
281
	}
M
Magnus Damm 已提交
282
	return 0;
283 284
}

M
Magnus Damm 已提交
285 286
static unsigned int __init intc_get_reg(struct intc_desc_int *d,
				 unsigned long address)
287
{
M
Magnus Damm 已提交
288
	unsigned int k;
289

M
Magnus Damm 已提交
290 291 292
	for (k = 0; k < d->nr_reg; k++) {
		if (d->reg[k] == address)
			return k;
293 294 295
	}

	BUG();
M
Magnus Damm 已提交
296
	return 0;
297 298
}

M
Magnus Damm 已提交
299 300
static intc_enum __init intc_grp_id(struct intc_desc *desc,
				    intc_enum enum_id)
M
Magnus Damm 已提交
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
{
	struct intc_group *g = desc->groups;
	unsigned int i, j;

	for (i = 0; g && enum_id && i < desc->nr_groups; i++) {
		g = desc->groups + i;

		for (j = 0; g->enum_ids[j]; j++) {
			if (g->enum_ids[j] != enum_id)
				continue;

			return g->enum_id;
		}
	}

	return 0;
}

319
static unsigned int __init intc_prio_value(struct intc_desc *desc,
M
Magnus Damm 已提交
320
					   intc_enum enum_id, int do_grps)
321
{
M
Magnus Damm 已提交
322
	struct intc_prio *p = desc->priorities;
323 324
	unsigned int i;

M
Magnus Damm 已提交
325 326
	for (i = 0; p && enum_id && i < desc->nr_priorities; i++) {
		p = desc->priorities + i;
327 328 329 330 331 332 333

		if (p->enum_id != enum_id)
			continue;

		return p->priority;
	}

M
Magnus Damm 已提交
334 335 336 337 338 339 340 341
	if (do_grps)
		return intc_prio_value(desc, intc_grp_id(desc, enum_id), 0);

	/* default to the lowest priority possible if no priority is set
	 * - this needs to be at least 2 for 5-bit priorities on 7780
	 */

	return 2;
342 343 344
}

static unsigned int __init intc_mask_data(struct intc_desc *desc,
M
Magnus Damm 已提交
345
					  struct intc_desc_int *d,
M
Magnus Damm 已提交
346
					  intc_enum enum_id, int do_grps)
347
{
M
Magnus Damm 已提交
348
	struct intc_mask_reg *mr = desc->mask_regs;
M
Magnus Damm 已提交
349 350
	unsigned int i, j, fn, mode;
	unsigned long reg_e, reg_d;
351

M
Magnus Damm 已提交
352 353
	for (i = 0; mr && enum_id && i < desc->nr_mask_regs; i++) {
		mr = desc->mask_regs + i;
354 355 356 357 358

		for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
			if (mr->enum_ids[j] != enum_id)
				continue;

M
Magnus Damm 已提交
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
			if (mr->set_reg && mr->clr_reg) {
				fn = REG_FN_WRITE_BASE;
				mode = MODE_DUAL_REG;
				reg_e = mr->clr_reg;
				reg_d = mr->set_reg;
			} else {
				fn = REG_FN_MODIFY_BASE;
				if (mr->set_reg) {
					mode = MODE_ENABLE_REG;
					reg_e = mr->set_reg;
					reg_d = mr->set_reg;
				} else {
					mode = MODE_MASK_REG;
					reg_e = mr->clr_reg;
					reg_d = mr->clr_reg;
				}
375 376
			}

M
Magnus Damm 已提交
377 378 379 380 381 382
			fn += (mr->reg_width >> 3) - 1;
			return _INTC_MK(fn, mode,
					intc_get_reg(d, reg_e),
					intc_get_reg(d, reg_d),
					1,
					(mr->reg_width - 1) - j);
383 384 385
		}
	}

M
Magnus Damm 已提交
386
	if (do_grps)
M
Magnus Damm 已提交
387
		return intc_mask_data(desc, d, intc_grp_id(desc, enum_id), 0);
M
Magnus Damm 已提交
388

389 390 391 392
	return 0;
}

static unsigned int __init intc_prio_data(struct intc_desc *desc,
M
Magnus Damm 已提交
393
					  struct intc_desc_int *d,
M
Magnus Damm 已提交
394
					  intc_enum enum_id, int do_grps)
395
{
M
Magnus Damm 已提交
396
	struct intc_prio_reg *pr = desc->prio_regs;
M
Magnus Damm 已提交
397 398
	unsigned int i, j, fn, mode, bit;
	unsigned long reg_e, reg_d;
399

M
Magnus Damm 已提交
400 401
	for (i = 0; pr && enum_id && i < desc->nr_prio_regs; i++) {
		pr = desc->prio_regs + i;
402 403 404 405 406

		for (j = 0; j < ARRAY_SIZE(pr->enum_ids); j++) {
			if (pr->enum_ids[j] != enum_id)
				continue;

M
Magnus Damm 已提交
407 408 409 410 411 412 413 414 415 416 417 418 419
			if (pr->set_reg && pr->clr_reg) {
				fn = REG_FN_WRITE_BASE;
				mode = MODE_PCLR_REG;
				reg_e = pr->set_reg;
				reg_d = pr->clr_reg;
			} else {
				fn = REG_FN_MODIFY_BASE;
				mode = MODE_PRIO_REG;
				if (!pr->set_reg)
					BUG();
				reg_e = pr->set_reg;
				reg_d = pr->set_reg;
			}
420

M
Magnus Damm 已提交
421
			fn += (pr->reg_width >> 3) - 1;
422 423 424 425
			bit = pr->reg_width - ((j + 1) * pr->field_width);

			BUG_ON(bit < 0);

M
Magnus Damm 已提交
426 427 428 429
			return _INTC_MK(fn, mode,
					intc_get_reg(d, reg_e),
					intc_get_reg(d, reg_d),
					pr->field_width, bit);
430 431 432
		}
	}

M
Magnus Damm 已提交
433
	if (do_grps)
M
Magnus Damm 已提交
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
		return intc_prio_data(desc, d, intc_grp_id(desc, enum_id), 0);

	return 0;
}

static unsigned int __init intc_sense_data(struct intc_desc *desc,
					   struct intc_desc_int *d,
					   intc_enum enum_id)
{
	struct intc_sense_reg *sr = desc->sense_regs;
	unsigned int i, j, fn, bit;

	for (i = 0; sr && enum_id && i < desc->nr_sense_regs; i++) {
		sr = desc->sense_regs + i;

		for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
			if (sr->enum_ids[j] != enum_id)
				continue;

			fn = REG_FN_MODIFY_BASE;
			fn += (sr->reg_width >> 3) - 1;
			bit = sr->reg_width - ((j + 1) * sr->field_width);

			BUG_ON(bit < 0);

			return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg),
					0, sr->field_width, bit);
		}
	}
M
Magnus Damm 已提交
463

464 465 466
	return 0;
}

M
Magnus Damm 已提交
467 468 469
static void __init intc_register_irq(struct intc_desc *desc,
				     struct intc_desc_int *d,
				     intc_enum enum_id,
470 471
				     unsigned int irq)
{
472
	struct intc_handle_int *hp;
M
Magnus Damm 已提交
473 474 475 476 477 478 479 480
	unsigned int data[2], primary;

	/* Prefer single interrupt source bitmap over other combinations:
	 * 1. bitmap, single interrupt source
	 * 2. priority, single interrupt source
	 * 3. bitmap, multiple interrupt sources (groups)
	 * 4. priority, multiple interrupt sources (groups)
	 */
481

M
Magnus Damm 已提交
482 483
	data[0] = intc_mask_data(desc, d, enum_id, 0);
	data[1] = intc_prio_data(desc, d, enum_id, 0);
M
Magnus Damm 已提交
484 485 486 487 488

	primary = 0;
	if (!data[0] && data[1])
		primary = 1;

M
Magnus Damm 已提交
489 490
	data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
	data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);
M
Magnus Damm 已提交
491 492 493 494 495

	if (!data[primary])
		primary ^= 1;

	BUG_ON(!data[primary]); /* must have primary masking method */
496 497

	disable_irq_nosync(irq);
M
Magnus Damm 已提交
498
	set_irq_chip_and_handler_name(irq, &d->chip,
499
				      handle_level_irq, "level");
M
Magnus Damm 已提交
500
	set_irq_chip_data(irq, (void *)data[primary]);
501

M
Magnus Damm 已提交
502 503 504
	/* record the desired priority level */
	intc_prio_level[irq] = intc_prio_value(desc, enum_id, 1);

M
Magnus Damm 已提交
505 506
	/* enable secondary masking method if present */
	if (data[!primary])
M
Magnus Damm 已提交
507 508 509 510
		_intc_enable(irq, data[!primary]);

	/* add irq to d->prio list if priority is available */
	if (data[1]) {
511 512 513 514 515 516 517 518 519 520 521 522 523
		hp = d->prio + d->nr_prio;
		hp->irq = irq;
		hp->handle = data[1];

		if (primary) {
			/*
			 * only secondary priority should access registers, so
			 * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
			 */

			hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
			hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
		}
M
Magnus Damm 已提交
524 525 526 527 528 529 530 531 532 533
		d->nr_prio++;
	}

	/* add irq to d->sense list if sense is available */
	data[0] = intc_sense_data(desc, d, enum_id);
	if (data[0]) {
		(d->sense + d->nr_sense)->irq = irq;
		(d->sense + d->nr_sense)->handle = data[0];
		d->nr_sense++;
	}
534 535

	/* irq should be disabled by default */
M
Magnus Damm 已提交
536
	d->chip.mask(irq);
537 538 539 540
}

void __init register_intc_controller(struct intc_desc *desc)
{
M
Magnus Damm 已提交
541 542 543 544 545 546 547 548 549 550 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 577 578 579 580 581 582
	unsigned int i, k;
	struct intc_desc_int *d;

	d = alloc_bootmem(sizeof(*d));

	d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0;
	d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
	d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;

	d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
	k = 0;

	if (desc->mask_regs) {
		for (i = 0; i < desc->nr_mask_regs; i++) {
			if (desc->mask_regs[i].set_reg)
				d->reg[k++] = desc->mask_regs[i].set_reg;
			if (desc->mask_regs[i].clr_reg)
				d->reg[k++] = desc->mask_regs[i].clr_reg;
		}
	}

	if (desc->prio_regs) {
		d->prio = alloc_bootmem(desc->nr_vectors * sizeof(*d->prio));

		for (i = 0; i < desc->nr_prio_regs; i++) {
			if (desc->prio_regs[i].set_reg)
				d->reg[k++] = desc->prio_regs[i].set_reg;
			if (desc->prio_regs[i].clr_reg)
				d->reg[k++] = desc->prio_regs[i].clr_reg;
		}
	}

	if (desc->sense_regs) {
		d->sense = alloc_bootmem(desc->nr_vectors * sizeof(*d->sense));

		for (i = 0; i < desc->nr_sense_regs; i++) {
			if (desc->sense_regs[i].reg)
				d->reg[k++] = desc->sense_regs[i].reg;
		}
	}

	BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
583

M
Magnus Damm 已提交
584 585 586 587 588
	d->chip.name = desc->name;
	d->chip.mask = intc_disable;
	d->chip.unmask = intc_enable;
	d->chip.mask_ack = intc_disable;
	d->chip.set_type = intc_set_sense;
589 590 591 592

	for (i = 0; i < desc->nr_vectors; i++) {
		struct intc_vect *vect = desc->vectors + i;

M
Magnus Damm 已提交
593
		intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect));
594 595
	}
}