diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 7d31d7cc392d..9cecebaa0360 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -405,20 +405,22 @@ static void mpic_unmask_irq(unsigned int irq) | |||
405 | unsigned int loops = 100000; | 405 | unsigned int loops = 100000; |
406 | struct mpic *mpic = mpic_from_irq(irq); | 406 | struct mpic *mpic = mpic_from_irq(irq); |
407 | unsigned int src = mpic_irq_to_hw(irq); | 407 | unsigned int src = mpic_irq_to_hw(irq); |
408 | unsigned long flags; | ||
408 | 409 | ||
409 | DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); | 410 | DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); |
410 | 411 | ||
412 | spin_lock_irqsave(&mpic_lock, flags); | ||
411 | mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, | 413 | mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, |
412 | mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & | 414 | mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & |
413 | ~MPIC_VECPRI_MASK); | 415 | ~MPIC_VECPRI_MASK); |
414 | |||
415 | /* make sure mask gets to controller before we return to user */ | 416 | /* make sure mask gets to controller before we return to user */ |
416 | do { | 417 | do { |
417 | if (!loops--) { | 418 | if (!loops--) { |
418 | printk(KERN_ERR "mpic_enable_irq timeout\n"); | 419 | printk(KERN_ERR "mpic_enable_irq timeout\n"); |
419 | break; | 420 | break; |
420 | } | 421 | } |
421 | } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); | 422 | } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); |
423 | spin_unlock_irqrestore(&mpic_lock, flags); | ||
422 | } | 424 | } |
423 | 425 | ||
424 | static void mpic_mask_irq(unsigned int irq) | 426 | static void mpic_mask_irq(unsigned int irq) |
@@ -426,9 +428,11 @@ static void mpic_mask_irq(unsigned int irq) | |||
426 | unsigned int loops = 100000; | 428 | unsigned int loops = 100000; |
427 | struct mpic *mpic = mpic_from_irq(irq); | 429 | struct mpic *mpic = mpic_from_irq(irq); |
428 | unsigned int src = mpic_irq_to_hw(irq); | 430 | unsigned int src = mpic_irq_to_hw(irq); |
431 | unsigned long flags; | ||
429 | 432 | ||
430 | DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); | 433 | DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); |
431 | 434 | ||
435 | spin_lock_irqsave(&mpic_lock, flags); | ||
432 | mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, | 436 | mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, |
433 | mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | | 437 | mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | |
434 | MPIC_VECPRI_MASK); | 438 | MPIC_VECPRI_MASK); |
@@ -440,6 +444,7 @@ static void mpic_mask_irq(unsigned int irq) | |||
440 | break; | 444 | break; |
441 | } | 445 | } |
442 | } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); | 446 | } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); |
447 | spin_unlock_irqrestore(&mpic_lock, flags); | ||
443 | } | 448 | } |
444 | 449 | ||
445 | static void mpic_end_irq(unsigned int irq) | 450 | static void mpic_end_irq(unsigned int irq) |
@@ -624,9 +629,10 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, | |||
624 | struct irq_desc *desc = get_irq_desc(virq); | 629 | struct irq_desc *desc = get_irq_desc(virq); |
625 | struct irq_chip *chip; | 630 | struct irq_chip *chip; |
626 | struct mpic *mpic = h->host_data; | 631 | struct mpic *mpic = h->host_data; |
627 | unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL | | 632 | u32 v, vecpri = MPIC_VECPRI_SENSE_LEVEL | |
628 | MPIC_VECPRI_POLARITY_NEGATIVE; | 633 | MPIC_VECPRI_POLARITY_NEGATIVE; |
629 | int level; | 634 | int level; |
635 | unsigned long iflags; | ||
630 | 636 | ||
631 | pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n", | 637 | pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n", |
632 | virq, hw, flags); | 638 | virq, hw, flags); |
@@ -668,11 +674,21 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, | |||
668 | } | 674 | } |
669 | #endif | 675 | #endif |
670 | 676 | ||
671 | /* Reconfigure irq */ | 677 | /* Reconfigure irq. We must preserve the mask bit as we can be called |
672 | vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT); | 678 | * while the interrupt is still active (This may change in the future |
673 | mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri); | 679 | * but for now, it is the case). |
674 | 680 | */ | |
675 | pr_debug("mpic: mapping as IRQ\n"); | 681 | spin_lock_irqsave(&mpic_lock, iflags); |
682 | v = mpic_irq_read(hw, MPIC_IRQ_VECTOR_PRI); | ||
683 | vecpri = (v & | ||
684 | ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK)) | | ||
685 | vecpri; | ||
686 | if (vecpri != v) | ||
687 | mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri); | ||
688 | spin_unlock_irqrestore(&mpic_lock, iflags); | ||
689 | |||
690 | pr_debug("mpic: mapping as IRQ, vecpri = 0x%08x (was 0x%08x)\n", | ||
691 | vecpri, v); | ||
676 | 692 | ||
677 | set_irq_chip_data(virq, mpic); | 693 | set_irq_chip_data(virq, mpic); |
678 | set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq); | 694 | set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq); |
@@ -904,8 +920,8 @@ void __init mpic_init(struct mpic *mpic) | |||
904 | 920 | ||
905 | /* do senses munging */ | 921 | /* do senses munging */ |
906 | if (mpic->senses && i < mpic->senses_count) | 922 | if (mpic->senses && i < mpic->senses_count) |
907 | vecpri = mpic_flags_to_vecpri(mpic->senses[i], | 923 | vecpri |= mpic_flags_to_vecpri(mpic->senses[i], |
908 | &level); | 924 | &level); |
909 | else | 925 | else |
910 | vecpri |= MPIC_VECPRI_SENSE_LEVEL; | 926 | vecpri |= MPIC_VECPRI_SENSE_LEVEL; |
911 | 927 | ||
@@ -955,14 +971,17 @@ void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) | |||
955 | 971 | ||
956 | void __init mpic_set_serial_int(struct mpic *mpic, int enable) | 972 | void __init mpic_set_serial_int(struct mpic *mpic, int enable) |
957 | { | 973 | { |
974 | unsigned long flags; | ||
958 | u32 v; | 975 | u32 v; |
959 | 976 | ||
977 | spin_lock_irqsave(&mpic_lock, flags); | ||
960 | v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1); | 978 | v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1); |
961 | if (enable) | 979 | if (enable) |
962 | v |= MPIC_GREG_GLOBAL_CONF_1_SIE; | 980 | v |= MPIC_GREG_GLOBAL_CONF_1_SIE; |
963 | else | 981 | else |
964 | v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE; | 982 | v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE; |
965 | mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v); | 983 | mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v); |
984 | spin_unlock_irqrestore(&mpic_lock, flags); | ||
966 | } | 985 | } |
967 | 986 | ||
968 | void mpic_irq_set_priority(unsigned int irq, unsigned int pri) | 987 | void mpic_irq_set_priority(unsigned int irq, unsigned int pri) |