diff options
author | Kim Phillips <kim.phillips@freescale.com> | 2006-08-25 12:59:07 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-08-29 20:34:33 -0400 |
commit | b9f0f1bb2bcaae96dd3267f6bd3ad1ca44a1f5ad (patch) | |
tree | 3b9f29de777df859406ee649cc5a29b703c026ae /arch/powerpc | |
parent | bf4152dd7ccb6c060d786200a893dfe30193a07f (diff) |
[POWERPC] Adapt ipic driver to new host_ops interface, add set_irq_type to set IRQ sense
This converts ipic code to Benh's IRQ mods. For the IPIC, IRQ sense values in the device tree equal those in include/linux/irq.h; that's 8 for low assertion (most internal IRQs on mpc83xx), and 2 for high-to-low change.
spinlocks added to [un]mask, ack operations; default handler and type now set in host_map; and redundant condition check eliminated.
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/sysdev/ipic.c | 303 | ||||
-rw-r--r-- | arch/powerpc/sysdev/ipic.h | 23 |
2 files changed, 228 insertions, 98 deletions
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 46801f5ec03f..70e707785d49 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c | |||
@@ -19,15 +19,18 @@ | |||
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/signal.h> | 20 | #include <linux/signal.h> |
21 | #include <linux/sysdev.h> | 21 | #include <linux/sysdev.h> |
22 | #include <linux/device.h> | ||
23 | #include <linux/bootmem.h> | ||
24 | #include <linux/spinlock.h> | ||
22 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
23 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <asm/prom.h> | ||
24 | #include <asm/ipic.h> | 28 | #include <asm/ipic.h> |
25 | #include <asm/mpc83xx.h> | ||
26 | 29 | ||
27 | #include "ipic.h" | 30 | #include "ipic.h" |
28 | 31 | ||
29 | static struct ipic p_ipic; | ||
30 | static struct ipic * primary_ipic; | 32 | static struct ipic * primary_ipic; |
33 | static DEFINE_SPINLOCK(ipic_lock); | ||
31 | 34 | ||
32 | static struct ipic_info ipic_info[] = { | 35 | static struct ipic_info ipic_info[] = { |
33 | [9] = { | 36 | [9] = { |
@@ -373,74 +376,220 @@ static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 | |||
373 | out_be32(base + (reg >> 2), value); | 376 | out_be32(base + (reg >> 2), value); |
374 | } | 377 | } |
375 | 378 | ||
376 | static inline struct ipic * ipic_from_irq(unsigned int irq) | 379 | static inline struct ipic * ipic_from_irq(unsigned int virq) |
377 | { | 380 | { |
378 | return primary_ipic; | 381 | return primary_ipic; |
379 | } | 382 | } |
380 | 383 | ||
381 | static void ipic_enable_irq(unsigned int irq) | 384 | #define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) |
385 | |||
386 | static void ipic_unmask_irq(unsigned int virq) | ||
382 | { | 387 | { |
383 | struct ipic *ipic = ipic_from_irq(irq); | 388 | struct ipic *ipic = ipic_from_irq(virq); |
384 | unsigned int src = irq - ipic->irq_offset; | 389 | unsigned int src = ipic_irq_to_hw(virq); |
390 | unsigned long flags; | ||
385 | u32 temp; | 391 | u32 temp; |
386 | 392 | ||
393 | spin_lock_irqsave(&ipic_lock, flags); | ||
394 | |||
387 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | 395 | temp = ipic_read(ipic->regs, ipic_info[src].mask); |
388 | temp |= (1 << (31 - ipic_info[src].bit)); | 396 | temp |= (1 << (31 - ipic_info[src].bit)); |
389 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | 397 | ipic_write(ipic->regs, ipic_info[src].mask, temp); |
398 | |||
399 | spin_unlock_irqrestore(&ipic_lock, flags); | ||
390 | } | 400 | } |
391 | 401 | ||
392 | static void ipic_disable_irq(unsigned int irq) | 402 | static void ipic_mask_irq(unsigned int virq) |
393 | { | 403 | { |
394 | struct ipic *ipic = ipic_from_irq(irq); | 404 | struct ipic *ipic = ipic_from_irq(virq); |
395 | unsigned int src = irq - ipic->irq_offset; | 405 | unsigned int src = ipic_irq_to_hw(virq); |
406 | unsigned long flags; | ||
396 | u32 temp; | 407 | u32 temp; |
397 | 408 | ||
409 | spin_lock_irqsave(&ipic_lock, flags); | ||
410 | |||
398 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | 411 | temp = ipic_read(ipic->regs, ipic_info[src].mask); |
399 | temp &= ~(1 << (31 - ipic_info[src].bit)); | 412 | temp &= ~(1 << (31 - ipic_info[src].bit)); |
400 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | 413 | ipic_write(ipic->regs, ipic_info[src].mask, temp); |
414 | |||
415 | spin_unlock_irqrestore(&ipic_lock, flags); | ||
401 | } | 416 | } |
402 | 417 | ||
403 | static void ipic_disable_irq_and_ack(unsigned int irq) | 418 | static void ipic_ack_irq(unsigned int virq) |
404 | { | 419 | { |
405 | struct ipic *ipic = ipic_from_irq(irq); | 420 | struct ipic *ipic = ipic_from_irq(virq); |
406 | unsigned int src = irq - ipic->irq_offset; | 421 | unsigned int src = ipic_irq_to_hw(virq); |
422 | unsigned long flags; | ||
407 | u32 temp; | 423 | u32 temp; |
408 | 424 | ||
409 | ipic_disable_irq(irq); | 425 | spin_lock_irqsave(&ipic_lock, flags); |
410 | 426 | ||
411 | temp = ipic_read(ipic->regs, ipic_info[src].pend); | 427 | temp = ipic_read(ipic->regs, ipic_info[src].pend); |
412 | temp |= (1 << (31 - ipic_info[src].bit)); | 428 | temp |= (1 << (31 - ipic_info[src].bit)); |
413 | ipic_write(ipic->regs, ipic_info[src].pend, temp); | 429 | ipic_write(ipic->regs, ipic_info[src].pend, temp); |
430 | |||
431 | spin_unlock_irqrestore(&ipic_lock, flags); | ||
414 | } | 432 | } |
415 | 433 | ||
416 | static void ipic_end_irq(unsigned int irq) | 434 | static void ipic_mask_irq_and_ack(unsigned int virq) |
417 | { | 435 | { |
418 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 436 | struct ipic *ipic = ipic_from_irq(virq); |
419 | ipic_enable_irq(irq); | 437 | unsigned int src = ipic_irq_to_hw(virq); |
438 | unsigned long flags; | ||
439 | u32 temp; | ||
440 | |||
441 | spin_lock_irqsave(&ipic_lock, flags); | ||
442 | |||
443 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | ||
444 | temp &= ~(1 << (31 - ipic_info[src].bit)); | ||
445 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | ||
446 | |||
447 | temp = ipic_read(ipic->regs, ipic_info[src].pend); | ||
448 | temp |= (1 << (31 - ipic_info[src].bit)); | ||
449 | ipic_write(ipic->regs, ipic_info[src].pend, temp); | ||
450 | |||
451 | spin_unlock_irqrestore(&ipic_lock, flags); | ||
420 | } | 452 | } |
421 | 453 | ||
422 | struct hw_interrupt_type ipic = { | 454 | static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) |
423 | .typename = " IPIC ", | 455 | { |
424 | .enable = ipic_enable_irq, | 456 | struct ipic *ipic = ipic_from_irq(virq); |
425 | .disable = ipic_disable_irq, | 457 | unsigned int src = ipic_irq_to_hw(virq); |
426 | .ack = ipic_disable_irq_and_ack, | 458 | struct irq_desc *desc = get_irq_desc(virq); |
427 | .end = ipic_end_irq, | 459 | unsigned int vold, vnew, edibit; |
460 | |||
461 | if (flow_type == IRQ_TYPE_NONE) | ||
462 | flow_type = IRQ_TYPE_LEVEL_LOW; | ||
463 | |||
464 | /* ipic supports only low assertion and high-to-low change senses | ||
465 | */ | ||
466 | if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) { | ||
467 | printk(KERN_ERR "ipic: sense type 0x%x not supported\n", | ||
468 | flow_type); | ||
469 | return -EINVAL; | ||
470 | } | ||
471 | |||
472 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); | ||
473 | desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; | ||
474 | if (flow_type & IRQ_TYPE_LEVEL_LOW) { | ||
475 | desc->status |= IRQ_LEVEL; | ||
476 | set_irq_handler(virq, handle_level_irq); | ||
477 | } else { | ||
478 | set_irq_handler(virq, handle_edge_irq); | ||
479 | } | ||
480 | |||
481 | /* only EXT IRQ senses are programmable on ipic | ||
482 | * internal IRQ senses are LEVEL_LOW | ||
483 | */ | ||
484 | if (src == IPIC_IRQ_EXT0) | ||
485 | edibit = 15; | ||
486 | else | ||
487 | if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7) | ||
488 | edibit = (14 - (src - IPIC_IRQ_EXT1)); | ||
489 | else | ||
490 | return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; | ||
491 | |||
492 | vold = ipic_read(ipic->regs, IPIC_SECNR); | ||
493 | if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) { | ||
494 | vnew = vold | (1 << edibit); | ||
495 | } else { | ||
496 | vnew = vold & ~(1 << edibit); | ||
497 | } | ||
498 | if (vold != vnew) | ||
499 | ipic_write(ipic->regs, IPIC_SECNR, vnew); | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static struct irq_chip ipic_irq_chip = { | ||
504 | .typename = " IPIC ", | ||
505 | .unmask = ipic_unmask_irq, | ||
506 | .mask = ipic_mask_irq, | ||
507 | .mask_ack = ipic_mask_irq_and_ack, | ||
508 | .ack = ipic_ack_irq, | ||
509 | .set_type = ipic_set_irq_type, | ||
510 | }; | ||
511 | |||
512 | static int ipic_host_match(struct irq_host *h, struct device_node *node) | ||
513 | { | ||
514 | struct ipic *ipic = h->host_data; | ||
515 | |||
516 | /* Exact match, unless ipic node is NULL */ | ||
517 | return ipic->of_node == NULL || ipic->of_node == node; | ||
518 | } | ||
519 | |||
520 | static int ipic_host_map(struct irq_host *h, unsigned int virq, | ||
521 | irq_hw_number_t hw) | ||
522 | { | ||
523 | struct ipic *ipic = h->host_data; | ||
524 | struct irq_chip *chip; | ||
525 | |||
526 | /* Default chip */ | ||
527 | chip = &ipic->hc_irq; | ||
528 | |||
529 | set_irq_chip_data(virq, ipic); | ||
530 | set_irq_chip_and_handler(virq, chip, handle_level_irq); | ||
531 | |||
532 | /* Set default irq type */ | ||
533 | set_irq_type(virq, IRQ_TYPE_NONE); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, | ||
539 | u32 *intspec, unsigned int intsize, | ||
540 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | ||
541 | |||
542 | { | ||
543 | /* interrupt sense values coming from the device tree equal either | ||
544 | * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change) | ||
545 | */ | ||
546 | *out_hwirq = intspec[0]; | ||
547 | if (intsize > 1) | ||
548 | *out_flags = intspec[1]; | ||
549 | else | ||
550 | *out_flags = IRQ_TYPE_NONE; | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | static struct irq_host_ops ipic_host_ops = { | ||
555 | .match = ipic_host_match, | ||
556 | .map = ipic_host_map, | ||
557 | .xlate = ipic_host_xlate, | ||
428 | }; | 558 | }; |
429 | 559 | ||
430 | void __init ipic_init(phys_addr_t phys_addr, | 560 | void __init ipic_init(struct device_node *node, |
431 | unsigned int flags, | 561 | unsigned int flags) |
432 | unsigned int irq_offset, | ||
433 | unsigned char *senses, | ||
434 | unsigned int senses_count) | ||
435 | { | 562 | { |
436 | u32 i, temp = 0; | 563 | struct ipic *ipic; |
564 | struct resource res; | ||
565 | u32 temp = 0, ret; | ||
566 | |||
567 | ipic = alloc_bootmem(sizeof(struct ipic)); | ||
568 | if (ipic == NULL) | ||
569 | return; | ||
570 | |||
571 | memset(ipic, 0, sizeof(struct ipic)); | ||
572 | ipic->of_node = node ? of_node_get(node) : NULL; | ||
573 | |||
574 | ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, | ||
575 | NR_IPIC_INTS, | ||
576 | &ipic_host_ops, 0); | ||
577 | if (ipic->irqhost == NULL) { | ||
578 | of_node_put(node); | ||
579 | return; | ||
580 | } | ||
581 | |||
582 | ret = of_address_to_resource(node, 0, &res); | ||
583 | if (ret) | ||
584 | return; | ||
437 | 585 | ||
438 | primary_ipic = &p_ipic; | 586 | ipic->regs = ioremap(res.start, res.end - res.start + 1); |
439 | primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE); | ||
440 | 587 | ||
441 | primary_ipic->irq_offset = irq_offset; | 588 | ipic->irqhost->host_data = ipic; |
589 | ipic->hc_irq = ipic_irq_chip; | ||
442 | 590 | ||
443 | ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0); | 591 | /* init hw */ |
592 | ipic_write(ipic->regs, IPIC_SICNR, 0x0); | ||
444 | 593 | ||
445 | /* default priority scheme is grouped. If spread mode is required | 594 | /* default priority scheme is grouped. If spread mode is required |
446 | * configure SICFR accordingly */ | 595 | * configure SICFR accordingly */ |
@@ -453,49 +602,35 @@ void __init ipic_init(phys_addr_t phys_addr, | |||
453 | if (flags & IPIC_SPREADMODE_MIX_B) | 602 | if (flags & IPIC_SPREADMODE_MIX_B) |
454 | temp |= SICFR_MPSB; | 603 | temp |= SICFR_MPSB; |
455 | 604 | ||
456 | ipic_write(primary_ipic->regs, IPIC_SICNR, temp); | 605 | ipic_write(ipic->regs, IPIC_SICNR, temp); |
457 | 606 | ||
458 | /* handle MCP route */ | 607 | /* handle MCP route */ |
459 | temp = 0; | 608 | temp = 0; |
460 | if (flags & IPIC_DISABLE_MCP_OUT) | 609 | if (flags & IPIC_DISABLE_MCP_OUT) |
461 | temp = SERCR_MCPR; | 610 | temp = SERCR_MCPR; |
462 | ipic_write(primary_ipic->regs, IPIC_SERCR, temp); | 611 | ipic_write(ipic->regs, IPIC_SERCR, temp); |
463 | 612 | ||
464 | /* handle routing of IRQ0 to MCP */ | 613 | /* handle routing of IRQ0 to MCP */ |
465 | temp = ipic_read(primary_ipic->regs, IPIC_SEMSR); | 614 | temp = ipic_read(ipic->regs, IPIC_SEMSR); |
466 | 615 | ||
467 | if (flags & IPIC_IRQ0_MCP) | 616 | if (flags & IPIC_IRQ0_MCP) |
468 | temp |= SEMSR_SIRQ0; | 617 | temp |= SEMSR_SIRQ0; |
469 | else | 618 | else |
470 | temp &= ~SEMSR_SIRQ0; | 619 | temp &= ~SEMSR_SIRQ0; |
471 | 620 | ||
472 | ipic_write(primary_ipic->regs, IPIC_SEMSR, temp); | 621 | ipic_write(ipic->regs, IPIC_SEMSR, temp); |
473 | 622 | ||
474 | for (i = 0 ; i < NR_IPIC_INTS ; i++) { | 623 | primary_ipic = ipic; |
475 | irq_desc[i+irq_offset].chip = &ipic; | 624 | irq_set_default_host(primary_ipic->irqhost); |
476 | irq_desc[i+irq_offset].status = IRQ_LEVEL; | ||
477 | } | ||
478 | 625 | ||
479 | temp = 0; | 626 | printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS, |
480 | for (i = 0 ; i < senses_count ; i++) { | 627 | primary_ipic->regs); |
481 | if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) { | ||
482 | temp |= 1 << (15 - i); | ||
483 | if (i != 0) | ||
484 | irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0; | ||
485 | else | ||
486 | irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0; | ||
487 | } | ||
488 | } | ||
489 | ipic_write(primary_ipic->regs, IPIC_SECNR, temp); | ||
490 | |||
491 | printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS, | ||
492 | senses_count, primary_ipic->regs); | ||
493 | } | 628 | } |
494 | 629 | ||
495 | int ipic_set_priority(unsigned int irq, unsigned int priority) | 630 | int ipic_set_priority(unsigned int virq, unsigned int priority) |
496 | { | 631 | { |
497 | struct ipic *ipic = ipic_from_irq(irq); | 632 | struct ipic *ipic = ipic_from_irq(virq); |
498 | unsigned int src = irq - ipic->irq_offset; | 633 | unsigned int src = ipic_irq_to_hw(virq); |
499 | u32 temp; | 634 | u32 temp; |
500 | 635 | ||
501 | if (priority > 7) | 636 | if (priority > 7) |
@@ -520,10 +655,10 @@ int ipic_set_priority(unsigned int irq, unsigned int priority) | |||
520 | return 0; | 655 | return 0; |
521 | } | 656 | } |
522 | 657 | ||
523 | void ipic_set_highest_priority(unsigned int irq) | 658 | void ipic_set_highest_priority(unsigned int virq) |
524 | { | 659 | { |
525 | struct ipic *ipic = ipic_from_irq(irq); | 660 | struct ipic *ipic = ipic_from_irq(virq); |
526 | unsigned int src = irq - ipic->irq_offset; | 661 | unsigned int src = ipic_irq_to_hw(virq); |
527 | u32 temp; | 662 | u32 temp; |
528 | 663 | ||
529 | temp = ipic_read(ipic->regs, IPIC_SICFR); | 664 | temp = ipic_read(ipic->regs, IPIC_SICFR); |
@@ -537,37 +672,10 @@ void ipic_set_highest_priority(unsigned int irq) | |||
537 | 672 | ||
538 | void ipic_set_default_priority(void) | 673 | void ipic_set_default_priority(void) |
539 | { | 674 | { |
540 | ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0); | 675 | ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT); |
541 | ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1); | 676 | ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT); |
542 | ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2); | 677 | ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT); |
543 | ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3); | 678 | ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT); |
544 | ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4); | ||
545 | ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5); | ||
546 | ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6); | ||
547 | ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7); | ||
548 | |||
549 | ipic_set_priority(MPC83xx_IRQ_UART1, 0); | ||
550 | ipic_set_priority(MPC83xx_IRQ_UART2, 1); | ||
551 | ipic_set_priority(MPC83xx_IRQ_SEC2, 2); | ||
552 | ipic_set_priority(MPC83xx_IRQ_IIC1, 5); | ||
553 | ipic_set_priority(MPC83xx_IRQ_IIC2, 6); | ||
554 | ipic_set_priority(MPC83xx_IRQ_SPI, 7); | ||
555 | ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0); | ||
556 | ipic_set_priority(MPC83xx_IRQ_PIT, 1); | ||
557 | ipic_set_priority(MPC83xx_IRQ_PCI1, 2); | ||
558 | ipic_set_priority(MPC83xx_IRQ_PCI2, 3); | ||
559 | ipic_set_priority(MPC83xx_IRQ_EXT0, 4); | ||
560 | ipic_set_priority(MPC83xx_IRQ_EXT1, 5); | ||
561 | ipic_set_priority(MPC83xx_IRQ_EXT2, 6); | ||
562 | ipic_set_priority(MPC83xx_IRQ_EXT3, 7); | ||
563 | ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0); | ||
564 | ipic_set_priority(MPC83xx_IRQ_MU, 1); | ||
565 | ipic_set_priority(MPC83xx_IRQ_SBA, 2); | ||
566 | ipic_set_priority(MPC83xx_IRQ_DMA, 3); | ||
567 | ipic_set_priority(MPC83xx_IRQ_EXT4, 4); | ||
568 | ipic_set_priority(MPC83xx_IRQ_EXT5, 5); | ||
569 | ipic_set_priority(MPC83xx_IRQ_EXT6, 6); | ||
570 | ipic_set_priority(MPC83xx_IRQ_EXT7, 7); | ||
571 | } | 679 | } |
572 | 680 | ||
573 | void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) | 681 | void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) |
@@ -600,17 +708,20 @@ void ipic_clear_mcp_status(u32 mask) | |||
600 | ipic_write(primary_ipic->regs, IPIC_SERMR, mask); | 708 | ipic_write(primary_ipic->regs, IPIC_SERMR, mask); |
601 | } | 709 | } |
602 | 710 | ||
603 | /* Return an interrupt vector or -1 if no interrupt is pending. */ | 711 | /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ |
604 | int ipic_get_irq(struct pt_regs *regs) | 712 | unsigned int ipic_get_irq(struct pt_regs *regs) |
605 | { | 713 | { |
606 | int irq; | 714 | int irq; |
607 | 715 | ||
608 | irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f; | 716 | BUG_ON(primary_ipic == NULL); |
717 | |||
718 | #define IPIC_SIVCR_VECTOR_MASK 0x7f | ||
719 | irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK; | ||
609 | 720 | ||
610 | if (irq == 0) /* 0 --> no irq is pending */ | 721 | if (irq == 0) /* 0 --> no irq is pending */ |
611 | irq = -1; | 722 | return NO_IRQ; |
612 | 723 | ||
613 | return irq; | 724 | return irq_linear_revmap(primary_ipic->irqhost, irq); |
614 | } | 725 | } |
615 | 726 | ||
616 | static struct sysdev_class ipic_sysclass = { | 727 | static struct sysdev_class ipic_sysclass = { |
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h index a60c9d18bb7f..c28e589877eb 100644 --- a/arch/powerpc/sysdev/ipic.h +++ b/arch/powerpc/sysdev/ipic.h | |||
@@ -15,7 +15,18 @@ | |||
15 | 15 | ||
16 | #include <asm/ipic.h> | 16 | #include <asm/ipic.h> |
17 | 17 | ||
18 | #define MPC83xx_IPIC_SIZE (0x00100) | 18 | #define NR_IPIC_INTS 128 |
19 | |||
20 | /* External IRQS */ | ||
21 | #define IPIC_IRQ_EXT0 48 | ||
22 | #define IPIC_IRQ_EXT1 17 | ||
23 | #define IPIC_IRQ_EXT7 23 | ||
24 | |||
25 | /* Default Priority Registers */ | ||
26 | #define IPIC_SIPRR_A_DEFAULT 0x05309770 | ||
27 | #define IPIC_SIPRR_D_DEFAULT 0x05309770 | ||
28 | #define IPIC_SMPRR_A_DEFAULT 0x05309770 | ||
29 | #define IPIC_SMPRR_B_DEFAULT 0x05309770 | ||
19 | 30 | ||
20 | /* System Global Interrupt Configuration Register */ | 31 | /* System Global Interrupt Configuration Register */ |
21 | #define SICFR_IPSA 0x00010000 | 32 | #define SICFR_IPSA 0x00010000 |
@@ -31,7 +42,15 @@ | |||
31 | 42 | ||
32 | struct ipic { | 43 | struct ipic { |
33 | volatile u32 __iomem *regs; | 44 | volatile u32 __iomem *regs; |
34 | unsigned int irq_offset; | 45 | |
46 | /* The remapper for this IPIC */ | ||
47 | struct irq_host *irqhost; | ||
48 | |||
49 | /* The "linux" controller struct */ | ||
50 | struct irq_chip hc_irq; | ||
51 | |||
52 | /* The device node of the interrupt controller */ | ||
53 | struct device_node *of_node; | ||
35 | }; | 54 | }; |
36 | 55 | ||
37 | struct ipic_info { | 56 | struct ipic_info { |