aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/sysdev/mpic.c39
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
424static void mpic_mask_irq(unsigned int irq) 426static 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
445static void mpic_end_irq(unsigned int irq) 450static 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
956void __init mpic_set_serial_int(struct mpic *mpic, int enable) 972void __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
968void mpic_irq_set_priority(unsigned int irq, unsigned int pri) 987void mpic_irq_set_priority(unsigned int irq, unsigned int pri)