aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c193
1 files changed, 101 insertions, 92 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e469358895f..9a95f16c19a5 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -100,8 +100,8 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
100 100
101 if (mpic->flags & MPIC_PRIMARY) 101 if (mpic->flags & MPIC_PRIMARY)
102 cpu = hard_smp_processor_id(); 102 cpu = hard_smp_processor_id();
103 103 return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,
104 return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg); 104 mpic->cpuregs[cpu], reg);
105} 105}
106 106
107static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) 107static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
@@ -378,14 +378,14 @@ static inline u32 mpic_physmask(u32 cpumask)
378/* Get the mpic structure from the IPI number */ 378/* Get the mpic structure from the IPI number */
379static inline struct mpic * mpic_from_ipi(unsigned int ipi) 379static inline struct mpic * mpic_from_ipi(unsigned int ipi)
380{ 380{
381 return container_of(irq_desc[ipi].chip, struct mpic, hc_ipi); 381 return irq_desc[ipi].chip_data;
382} 382}
383#endif 383#endif
384 384
385/* Get the mpic structure from the irq number */ 385/* Get the mpic structure from the irq number */
386static inline struct mpic * mpic_from_irq(unsigned int irq) 386static inline struct mpic * mpic_from_irq(unsigned int irq)
387{ 387{
388 return container_of(irq_desc[irq].chip, struct mpic, hc_irq); 388 return irq_desc[irq].chip_data;
389} 389}
390 390
391/* Send an EOI */ 391/* Send an EOI */
@@ -410,7 +410,7 @@ static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
410 */ 410 */
411 411
412 412
413static void mpic_enable_irq(unsigned int irq) 413static void mpic_unmask_irq(unsigned int irq)
414{ 414{
415 unsigned int loops = 100000; 415 unsigned int loops = 100000;
416 struct mpic *mpic = mpic_from_irq(irq); 416 struct mpic *mpic = mpic_from_irq(irq);
@@ -429,35 +429,9 @@ static void mpic_enable_irq(unsigned int irq)
429 break; 429 break;
430 } 430 }
431 } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); 431 } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
432
433#ifdef CONFIG_MPIC_BROKEN_U3
434 if (mpic->flags & MPIC_BROKEN_U3) {
435 unsigned int src = irq - mpic->irq_offset;
436 if (mpic_is_ht_interrupt(mpic, src) &&
437 (irq_desc[irq].status & IRQ_LEVEL))
438 mpic_ht_end_irq(mpic, src);
439 }
440#endif /* CONFIG_MPIC_BROKEN_U3 */
441}
442
443static unsigned int mpic_startup_irq(unsigned int irq)
444{
445#ifdef CONFIG_MPIC_BROKEN_U3
446 struct mpic *mpic = mpic_from_irq(irq);
447 unsigned int src = irq - mpic->irq_offset;
448#endif /* CONFIG_MPIC_BROKEN_U3 */
449
450 mpic_enable_irq(irq);
451
452#ifdef CONFIG_MPIC_BROKEN_U3
453 if (mpic_is_ht_interrupt(mpic, src))
454 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
455#endif /* CONFIG_MPIC_BROKEN_U3 */
456
457 return 0;
458} 432}
459 433
460static void mpic_disable_irq(unsigned int irq) 434static void mpic_mask_irq(unsigned int irq)
461{ 435{
462 unsigned int loops = 100000; 436 unsigned int loops = 100000;
463 struct mpic *mpic = mpic_from_irq(irq); 437 struct mpic *mpic = mpic_from_irq(irq);
@@ -478,23 +452,58 @@ static void mpic_disable_irq(unsigned int irq)
478 } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); 452 } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
479} 453}
480 454
481static void mpic_shutdown_irq(unsigned int irq) 455static void mpic_end_irq(unsigned int irq)
482{ 456{
457 struct mpic *mpic = mpic_from_irq(irq);
458
459#ifdef DEBUG_IRQ
460 DBG("%s: end_irq: %d\n", mpic->name, irq);
461#endif
462 /* We always EOI on end_irq() even for edge interrupts since that
463 * should only lower the priority, the MPIC should have properly
464 * latched another edge interrupt coming in anyway
465 */
466
467 mpic_eoi(mpic);
468}
469
483#ifdef CONFIG_MPIC_BROKEN_U3 470#ifdef CONFIG_MPIC_BROKEN_U3
471
472static void mpic_unmask_ht_irq(unsigned int irq)
473{
484 struct mpic *mpic = mpic_from_irq(irq); 474 struct mpic *mpic = mpic_from_irq(irq);
485 unsigned int src = irq - mpic->irq_offset; 475 unsigned int src = irq - mpic->irq_offset;
486 476
487 if (mpic_is_ht_interrupt(mpic, src)) 477 mpic_unmask_irq(irq);
488 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
489 478
490#endif /* CONFIG_MPIC_BROKEN_U3 */ 479 if (irq_desc[irq].status & IRQ_LEVEL)
480 mpic_ht_end_irq(mpic, src);
481}
482
483static unsigned int mpic_startup_ht_irq(unsigned int irq)
484{
485 struct mpic *mpic = mpic_from_irq(irq);
486 unsigned int src = irq - mpic->irq_offset;
491 487
492 mpic_disable_irq(irq); 488 mpic_unmask_irq(irq);
489 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
490
491 return 0;
493} 492}
494 493
495static void mpic_end_irq(unsigned int irq) 494static void mpic_shutdown_ht_irq(unsigned int irq)
495{
496 struct mpic *mpic = mpic_from_irq(irq);
497 unsigned int src = irq - mpic->irq_offset;
498
499 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
500 mpic_mask_irq(irq);
501}
502
503static void mpic_end_ht_irq(unsigned int irq)
496{ 504{
497 struct mpic *mpic = mpic_from_irq(irq); 505 struct mpic *mpic = mpic_from_irq(irq);
506 unsigned int src = irq - mpic->irq_offset;
498 507
499#ifdef DEBUG_IRQ 508#ifdef DEBUG_IRQ
500 DBG("%s: end_irq: %d\n", mpic->name, irq); 509 DBG("%s: end_irq: %d\n", mpic->name, irq);
@@ -504,21 +513,16 @@ static void mpic_end_irq(unsigned int irq)
504 * latched another edge interrupt coming in anyway 513 * latched another edge interrupt coming in anyway
505 */ 514 */
506 515
507#ifdef CONFIG_MPIC_BROKEN_U3 516 if (irq_desc[irq].status & IRQ_LEVEL)
508 if (mpic->flags & MPIC_BROKEN_U3) { 517 mpic_ht_end_irq(mpic, src);
509 unsigned int src = irq - mpic->irq_offset;
510 if (mpic_is_ht_interrupt(mpic, src) &&
511 (irq_desc[irq].status & IRQ_LEVEL))
512 mpic_ht_end_irq(mpic, src);
513 }
514#endif /* CONFIG_MPIC_BROKEN_U3 */
515
516 mpic_eoi(mpic); 518 mpic_eoi(mpic);
517} 519}
518 520
521#endif /* CONFIG_MPIC_BROKEN_U3 */
522
519#ifdef CONFIG_SMP 523#ifdef CONFIG_SMP
520 524
521static void mpic_enable_ipi(unsigned int irq) 525static void mpic_unmask_ipi(unsigned int irq)
522{ 526{
523 struct mpic *mpic = mpic_from_ipi(irq); 527 struct mpic *mpic = mpic_from_ipi(irq);
524 unsigned int src = irq - mpic->ipi_offset; 528 unsigned int src = irq - mpic->ipi_offset;
@@ -527,7 +531,7 @@ static void mpic_enable_ipi(unsigned int irq)
527 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); 531 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
528} 532}
529 533
530static void mpic_disable_ipi(unsigned int irq) 534static void mpic_mask_ipi(unsigned int irq)
531{ 535{
532 /* NEVER disable an IPI... that's just plain wrong! */ 536 /* NEVER disable an IPI... that's just plain wrong! */
533} 537}
@@ -560,6 +564,30 @@ static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
560 mpic_physmask(cpus_addr(tmp)[0])); 564 mpic_physmask(cpus_addr(tmp)[0]));
561} 565}
562 566
567static struct irq_chip mpic_irq_chip = {
568 .mask = mpic_mask_irq,
569 .unmask = mpic_unmask_irq,
570 .eoi = mpic_end_irq,
571};
572
573#ifdef CONFIG_SMP
574static struct irq_chip mpic_ipi_chip = {
575 .mask = mpic_mask_ipi,
576 .unmask = mpic_unmask_ipi,
577 .eoi = mpic_end_ipi,
578};
579#endif /* CONFIG_SMP */
580
581#ifdef CONFIG_MPIC_BROKEN_U3
582static struct irq_chip mpic_irq_ht_chip = {
583 .startup = mpic_startup_ht_irq,
584 .shutdown = mpic_shutdown_ht_irq,
585 .mask = mpic_mask_irq,
586 .unmask = mpic_unmask_ht_irq,
587 .eoi = mpic_end_ht_irq,
588};
589#endif /* CONFIG_MPIC_BROKEN_U3 */
590
563 591
564/* 592/*
565 * Exported functions 593 * Exported functions
@@ -589,19 +617,19 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
589 memset(mpic, 0, sizeof(struct mpic)); 617 memset(mpic, 0, sizeof(struct mpic));
590 mpic->name = name; 618 mpic->name = name;
591 619
620 mpic->hc_irq = mpic_irq_chip;
592 mpic->hc_irq.typename = name; 621 mpic->hc_irq.typename = name;
593 mpic->hc_irq.startup = mpic_startup_irq;
594 mpic->hc_irq.shutdown = mpic_shutdown_irq;
595 mpic->hc_irq.enable = mpic_enable_irq;
596 mpic->hc_irq.disable = mpic_disable_irq;
597 mpic->hc_irq.end = mpic_end_irq;
598 if (flags & MPIC_PRIMARY) 622 if (flags & MPIC_PRIMARY)
599 mpic->hc_irq.set_affinity = mpic_set_affinity; 623 mpic->hc_irq.set_affinity = mpic_set_affinity;
624#ifdef CONFIG_MPIC_BROKEN_U3
625 mpic->hc_ht_irq = mpic_irq_ht_chip;
626 mpic->hc_ht_irq.typename = name;
627 if (flags & MPIC_PRIMARY)
628 mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
629#endif /* CONFIG_MPIC_BROKEN_U3 */
600#ifdef CONFIG_SMP 630#ifdef CONFIG_SMP
601 mpic->hc_ipi.typename = name; 631 mpic->hc_ipi.typename = name;
602 mpic->hc_ipi.enable = mpic_enable_ipi; 632 mpic->hc_ipi = mpic_ipi_chip;
603 mpic->hc_ipi.disable = mpic_disable_ipi;
604 mpic->hc_ipi.end = mpic_end_ipi;
605#endif /* CONFIG_SMP */ 633#endif /* CONFIG_SMP */
606 634
607 mpic->flags = flags; 635 mpic->flags = flags;
@@ -697,28 +725,6 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
697 mpic->num_sources = isu_first + mpic->isu_size; 725 mpic->num_sources = isu_first + mpic->isu_size;
698} 726}
699 727
700void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler,
701 void *data)
702{
703 struct mpic *mpic = mpic_find(irq, NULL);
704 unsigned long flags;
705
706 /* Synchronization here is a bit dodgy, so don't try to replace cascade
707 * interrupts on the fly too often ... but normally it's set up at boot.
708 */
709 spin_lock_irqsave(&mpic_lock, flags);
710 if (mpic->cascade)
711 mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
712 mpic->cascade = NULL;
713 wmb();
714 mpic->cascade_vec = irq - mpic->irq_offset;
715 mpic->cascade_data = data;
716 wmb();
717 mpic->cascade = handler;
718 mpic_enable_irq(irq);
719 spin_unlock_irqrestore(&mpic_lock, flags);
720}
721
722void __init mpic_init(struct mpic *mpic) 728void __init mpic_init(struct mpic *mpic)
723{ 729{
724 int i; 730 int i;
@@ -750,8 +756,10 @@ void __init mpic_init(struct mpic *mpic)
750#ifdef CONFIG_SMP 756#ifdef CONFIG_SMP
751 if (!(mpic->flags & MPIC_PRIMARY)) 757 if (!(mpic->flags & MPIC_PRIMARY))
752 continue; 758 continue;
753 irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU; 759 set_irq_chip_data(mpic->ipi_offset+i, mpic);
754 irq_desc[mpic->ipi_offset+i].chip = &mpic->hc_ipi; 760 set_irq_chip_and_handler(mpic->ipi_offset+i,
761 &mpic->hc_ipi,
762 handle_percpu_irq);
755#endif /* CONFIG_SMP */ 763#endif /* CONFIG_SMP */
756 } 764 }
757 765
@@ -763,7 +771,7 @@ void __init mpic_init(struct mpic *mpic)
763 /* Do the HT PIC fixups on U3 broken mpic */ 771 /* Do the HT PIC fixups on U3 broken mpic */
764 DBG("MPIC flags: %x\n", mpic->flags); 772 DBG("MPIC flags: %x\n", mpic->flags);
765 if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) 773 if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
766 mpic_scan_ht_pics(mpic); 774 mpic_scan_ht_pics(mpic);
767#endif /* CONFIG_MPIC_BROKEN_U3 */ 775#endif /* CONFIG_MPIC_BROKEN_U3 */
768 776
769 for (i = 0; i < mpic->num_sources; i++) { 777 for (i = 0; i < mpic->num_sources; i++) {
@@ -811,8 +819,17 @@ void __init mpic_init(struct mpic *mpic)
811 819
812 /* init linux descriptors */ 820 /* init linux descriptors */
813 if (i < mpic->irq_count) { 821 if (i < mpic->irq_count) {
814 irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0; 822 struct irq_chip *chip = &mpic->hc_irq;
815 irq_desc[mpic->irq_offset+i].chip = &mpic->hc_irq; 823
824 irq_desc[mpic->irq_offset+i].status |=
825 level ? IRQ_LEVEL : 0;
826#ifdef CONFIG_MPIC_BROKEN_U3
827 if (mpic_is_ht_interrupt(mpic, i))
828 chip = &mpic->hc_ht_irq;
829#endif /* CONFIG_MPIC_BROKEN_U3 */
830 set_irq_chip_data(mpic->irq_offset+i, mpic);
831 set_irq_chip_and_handler(mpic->irq_offset+i, chip,
832 handle_fasteoi_irq);
816 } 833 }
817 } 834 }
818 835
@@ -986,14 +1003,6 @@ int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
986#ifdef DEBUG_LOW 1003#ifdef DEBUG_LOW
987 DBG("%s: get_one_irq(): %d\n", mpic->name, irq); 1004 DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
988#endif 1005#endif
989 if (mpic->cascade && irq == mpic->cascade_vec) {
990#ifdef DEBUG_LOW
991 DBG("%s: cascading ...\n", mpic->name);
992#endif
993 irq = mpic->cascade(regs, mpic->cascade_data);
994 mpic_eoi(mpic);
995 return irq;
996 }
997 if (unlikely(irq == MPIC_VEC_SPURRIOUS)) 1006 if (unlikely(irq == MPIC_VEC_SPURRIOUS))
998 return -1; 1007 return -1;
999 if (irq < MPIC_VEC_IPI_0) { 1008 if (irq < MPIC_VEC_IPI_0) {