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.c257
1 files changed, 176 insertions, 81 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index f91c065bed5a..3a8de5bb628a 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -6,6 +6,7 @@
6 * with various broken implementations of this HW. 6 * with various broken implementations of this HW.
7 * 7 *
8 * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. 8 * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
9 * Copyright 2010-2011 Freescale Semiconductor, Inc.
9 * 10 *
10 * This file is subject to the terms and conditions of the GNU General Public 11 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive 12 * License. See the file COPYING in the main directory of this archive
@@ -27,6 +28,7 @@
27#include <linux/spinlock.h> 28#include <linux/spinlock.h>
28#include <linux/pci.h> 29#include <linux/pci.h>
29#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/syscore_ops.h>
30 32
31#include <asm/ptrace.h> 33#include <asm/ptrace.h>
32#include <asm/signal.h> 34#include <asm/signal.h>
@@ -218,6 +220,28 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu
218 _mpic_write(mpic->reg_type, &mpic->gregs, offset, value); 220 _mpic_write(mpic->reg_type, &mpic->gregs, offset, value);
219} 221}
220 222
223static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm)
224{
225 unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) +
226 ((tm & 3) * MPIC_INFO(TIMER_STRIDE));
227
228 if (tm >= 4)
229 offset += 0x1000 / 4;
230
231 return _mpic_read(mpic->reg_type, &mpic->tmregs, offset);
232}
233
234static inline void _mpic_tm_write(struct mpic *mpic, unsigned int tm, u32 value)
235{
236 unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) +
237 ((tm & 3) * MPIC_INFO(TIMER_STRIDE));
238
239 if (tm >= 4)
240 offset += 0x1000 / 4;
241
242 _mpic_write(mpic->reg_type, &mpic->tmregs, offset, value);
243}
244
221static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) 245static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
222{ 246{
223 unsigned int cpu = mpic_processor_id(mpic); 247 unsigned int cpu = mpic_processor_id(mpic);
@@ -268,6 +292,8 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
268#define mpic_write(b,r,v) _mpic_write(mpic->reg_type,&(b),(r),(v)) 292#define mpic_write(b,r,v) _mpic_write(mpic->reg_type,&(b),(r),(v))
269#define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i)) 293#define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i))
270#define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v)) 294#define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v))
295#define mpic_tm_read(i) _mpic_tm_read(mpic,(i))
296#define mpic_tm_write(i,v) _mpic_tm_write(mpic,(i),(v))
271#define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i)) 297#define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i))
272#define mpic_cpu_write(i,v) _mpic_cpu_write(mpic,(i),(v)) 298#define mpic_cpu_write(i,v) _mpic_cpu_write(mpic,(i),(v))
273#define mpic_irq_read(s,r) _mpic_irq_read(mpic,(s),(r)) 299#define mpic_irq_read(s,r) _mpic_irq_read(mpic,(s),(r))
@@ -607,8 +633,6 @@ static int irq_choose_cpu(const struct cpumask *mask)
607} 633}
608#endif 634#endif
609 635
610#define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
611
612/* Find an mpic associated with a given linux interrupt */ 636/* Find an mpic associated with a given linux interrupt */
613static struct mpic *mpic_find(unsigned int irq) 637static struct mpic *mpic_find(unsigned int irq)
614{ 638{
@@ -621,11 +645,18 @@ static struct mpic *mpic_find(unsigned int irq)
621/* Determine if the linux irq is an IPI */ 645/* Determine if the linux irq is an IPI */
622static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq) 646static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq)
623{ 647{
624 unsigned int src = mpic_irq_to_hw(irq); 648 unsigned int src = virq_to_hw(irq);
625 649
626 return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]); 650 return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]);
627} 651}
628 652
653/* Determine if the linux irq is a timer */
654static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int irq)
655{
656 unsigned int src = virq_to_hw(irq);
657
658 return (src >= mpic->timer_vecs[0] && src <= mpic->timer_vecs[7]);
659}
629 660
630/* Convert a cpu mask from logical to physical cpu numbers. */ 661/* Convert a cpu mask from logical to physical cpu numbers. */
631static inline u32 mpic_physmask(u32 cpumask) 662static inline u32 mpic_physmask(u32 cpumask)
@@ -633,7 +664,7 @@ static inline u32 mpic_physmask(u32 cpumask)
633 int i; 664 int i;
634 u32 mask = 0; 665 u32 mask = 0;
635 666
636 for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1) 667 for (i = 0; i < min(32, NR_CPUS); ++i, cpumask >>= 1)
637 mask |= (cpumask & 1) << get_hard_smp_processor_id(i); 668 mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
638 return mask; 669 return mask;
639} 670}
@@ -674,7 +705,7 @@ void mpic_unmask_irq(struct irq_data *d)
674{ 705{
675 unsigned int loops = 100000; 706 unsigned int loops = 100000;
676 struct mpic *mpic = mpic_from_irq_data(d); 707 struct mpic *mpic = mpic_from_irq_data(d);
677 unsigned int src = mpic_irq_to_hw(d->irq); 708 unsigned int src = irqd_to_hwirq(d);
678 709
679 DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src); 710 DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src);
680 711
@@ -695,7 +726,7 @@ void mpic_mask_irq(struct irq_data *d)
695{ 726{
696 unsigned int loops = 100000; 727 unsigned int loops = 100000;
697 struct mpic *mpic = mpic_from_irq_data(d); 728 struct mpic *mpic = mpic_from_irq_data(d);
698 unsigned int src = mpic_irq_to_hw(d->irq); 729 unsigned int src = irqd_to_hwirq(d);
699 730
700 DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src); 731 DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src);
701 732
@@ -733,7 +764,7 @@ void mpic_end_irq(struct irq_data *d)
733static void mpic_unmask_ht_irq(struct irq_data *d) 764static void mpic_unmask_ht_irq(struct irq_data *d)
734{ 765{
735 struct mpic *mpic = mpic_from_irq_data(d); 766 struct mpic *mpic = mpic_from_irq_data(d);
736 unsigned int src = mpic_irq_to_hw(d->irq); 767 unsigned int src = irqd_to_hwirq(d);
737 768
738 mpic_unmask_irq(d); 769 mpic_unmask_irq(d);
739 770
@@ -744,7 +775,7 @@ static void mpic_unmask_ht_irq(struct irq_data *d)
744static unsigned int mpic_startup_ht_irq(struct irq_data *d) 775static unsigned int mpic_startup_ht_irq(struct irq_data *d)
745{ 776{
746 struct mpic *mpic = mpic_from_irq_data(d); 777 struct mpic *mpic = mpic_from_irq_data(d);
747 unsigned int src = mpic_irq_to_hw(d->irq); 778 unsigned int src = irqd_to_hwirq(d);
748 779
749 mpic_unmask_irq(d); 780 mpic_unmask_irq(d);
750 mpic_startup_ht_interrupt(mpic, src, irqd_is_level_type(d)); 781 mpic_startup_ht_interrupt(mpic, src, irqd_is_level_type(d));
@@ -755,7 +786,7 @@ static unsigned int mpic_startup_ht_irq(struct irq_data *d)
755static void mpic_shutdown_ht_irq(struct irq_data *d) 786static void mpic_shutdown_ht_irq(struct irq_data *d)
756{ 787{
757 struct mpic *mpic = mpic_from_irq_data(d); 788 struct mpic *mpic = mpic_from_irq_data(d);
758 unsigned int src = mpic_irq_to_hw(d->irq); 789 unsigned int src = irqd_to_hwirq(d);
759 790
760 mpic_shutdown_ht_interrupt(mpic, src); 791 mpic_shutdown_ht_interrupt(mpic, src);
761 mpic_mask_irq(d); 792 mpic_mask_irq(d);
@@ -764,7 +795,7 @@ static void mpic_shutdown_ht_irq(struct irq_data *d)
764static void mpic_end_ht_irq(struct irq_data *d) 795static void mpic_end_ht_irq(struct irq_data *d)
765{ 796{
766 struct mpic *mpic = mpic_from_irq_data(d); 797 struct mpic *mpic = mpic_from_irq_data(d);
767 unsigned int src = mpic_irq_to_hw(d->irq); 798 unsigned int src = irqd_to_hwirq(d);
768 799
769#ifdef DEBUG_IRQ 800#ifdef DEBUG_IRQ
770 DBG("%s: end_irq: %d\n", mpic->name, d->irq); 801 DBG("%s: end_irq: %d\n", mpic->name, d->irq);
@@ -785,7 +816,7 @@ static void mpic_end_ht_irq(struct irq_data *d)
785static void mpic_unmask_ipi(struct irq_data *d) 816static void mpic_unmask_ipi(struct irq_data *d)
786{ 817{
787 struct mpic *mpic = mpic_from_ipi(d); 818 struct mpic *mpic = mpic_from_ipi(d);
788 unsigned int src = mpic_irq_to_hw(d->irq) - mpic->ipi_vecs[0]; 819 unsigned int src = virq_to_hw(d->irq) - mpic->ipi_vecs[0];
789 820
790 DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src); 821 DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
791 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); 822 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
@@ -812,27 +843,42 @@ static void mpic_end_ipi(struct irq_data *d)
812 843
813#endif /* CONFIG_SMP */ 844#endif /* CONFIG_SMP */
814 845
846static void mpic_unmask_tm(struct irq_data *d)
847{
848 struct mpic *mpic = mpic_from_irq_data(d);
849 unsigned int src = virq_to_hw(d->irq) - mpic->timer_vecs[0];
850
851 DBG("%s: enable_tm: %d (tm %d)\n", mpic->name, irq, src);
852 mpic_tm_write(src, mpic_tm_read(src) & ~MPIC_VECPRI_MASK);
853 mpic_tm_read(src);
854}
855
856static void mpic_mask_tm(struct irq_data *d)
857{
858 struct mpic *mpic = mpic_from_irq_data(d);
859 unsigned int src = virq_to_hw(d->irq) - mpic->timer_vecs[0];
860
861 mpic_tm_write(src, mpic_tm_read(src) | MPIC_VECPRI_MASK);
862 mpic_tm_read(src);
863}
864
815int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, 865int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
816 bool force) 866 bool force)
817{ 867{
818 struct mpic *mpic = mpic_from_irq_data(d); 868 struct mpic *mpic = mpic_from_irq_data(d);
819 unsigned int src = mpic_irq_to_hw(d->irq); 869 unsigned int src = irqd_to_hwirq(d);
820 870
821 if (mpic->flags & MPIC_SINGLE_DEST_CPU) { 871 if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
822 int cpuid = irq_choose_cpu(cpumask); 872 int cpuid = irq_choose_cpu(cpumask);
823 873
824 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); 874 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
825 } else { 875 } else {
826 cpumask_var_t tmp; 876 u32 mask = cpumask_bits(cpumask)[0];
827
828 alloc_cpumask_var(&tmp, GFP_KERNEL);
829 877
830 cpumask_and(tmp, cpumask, cpu_online_mask); 878 mask &= cpumask_bits(cpu_online_mask)[0];
831 879
832 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 880 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
833 mpic_physmask(cpumask_bits(tmp)[0])); 881 mpic_physmask(mask));
834
835 free_cpumask_var(tmp);
836 } 882 }
837 883
838 return 0; 884 return 0;
@@ -862,7 +908,7 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
862int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type) 908int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
863{ 909{
864 struct mpic *mpic = mpic_from_irq_data(d); 910 struct mpic *mpic = mpic_from_irq_data(d);
865 unsigned int src = mpic_irq_to_hw(d->irq); 911 unsigned int src = irqd_to_hwirq(d);
866 unsigned int vecpri, vold, vnew; 912 unsigned int vecpri, vold, vnew;
867 913
868 DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", 914 DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
@@ -898,7 +944,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
898void mpic_set_vector(unsigned int virq, unsigned int vector) 944void mpic_set_vector(unsigned int virq, unsigned int vector)
899{ 945{
900 struct mpic *mpic = mpic_from_irq(virq); 946 struct mpic *mpic = mpic_from_irq(virq);
901 unsigned int src = mpic_irq_to_hw(virq); 947 unsigned int src = virq_to_hw(virq);
902 unsigned int vecpri; 948 unsigned int vecpri;
903 949
904 DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n", 950 DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n",
@@ -916,7 +962,7 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
916void mpic_set_destination(unsigned int virq, unsigned int cpuid) 962void mpic_set_destination(unsigned int virq, unsigned int cpuid)
917{ 963{
918 struct mpic *mpic = mpic_from_irq(virq); 964 struct mpic *mpic = mpic_from_irq(virq);
919 unsigned int src = mpic_irq_to_hw(virq); 965 unsigned int src = virq_to_hw(virq);
920 966
921 DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n", 967 DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
922 mpic, virq, src, cpuid); 968 mpic, virq, src, cpuid);
@@ -942,6 +988,12 @@ static struct irq_chip mpic_ipi_chip = {
942}; 988};
943#endif /* CONFIG_SMP */ 989#endif /* CONFIG_SMP */
944 990
991static struct irq_chip mpic_tm_chip = {
992 .irq_mask = mpic_mask_tm,
993 .irq_unmask = mpic_unmask_tm,
994 .irq_eoi = mpic_end_irq,
995};
996
945#ifdef CONFIG_MPIC_U3_HT_IRQS 997#ifdef CONFIG_MPIC_U3_HT_IRQS
946static struct irq_chip mpic_irq_ht_chip = { 998static struct irq_chip mpic_irq_ht_chip = {
947 .irq_startup = mpic_startup_ht_irq, 999 .irq_startup = mpic_startup_ht_irq,
@@ -985,6 +1037,16 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
985 } 1037 }
986#endif /* CONFIG_SMP */ 1038#endif /* CONFIG_SMP */
987 1039
1040 if (hw >= mpic->timer_vecs[0] && hw <= mpic->timer_vecs[7]) {
1041 WARN_ON(!(mpic->flags & MPIC_PRIMARY));
1042
1043 DBG("mpic: mapping as timer\n");
1044 irq_set_chip_data(virq, mpic);
1045 irq_set_chip_and_handler(virq, &mpic->hc_tm,
1046 handle_fasteoi_irq);
1047 return 0;
1048 }
1049
988 if (hw >= mpic->irq_count) 1050 if (hw >= mpic->irq_count)
989 return -EINVAL; 1051 return -EINVAL;
990 1052
@@ -1025,6 +1087,7 @@ static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
1025 irq_hw_number_t *out_hwirq, unsigned int *out_flags) 1087 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
1026 1088
1027{ 1089{
1090 struct mpic *mpic = h->host_data;
1028 static unsigned char map_mpic_senses[4] = { 1091 static unsigned char map_mpic_senses[4] = {
1029 IRQ_TYPE_EDGE_RISING, 1092 IRQ_TYPE_EDGE_RISING,
1030 IRQ_TYPE_LEVEL_LOW, 1093 IRQ_TYPE_LEVEL_LOW,
@@ -1033,7 +1096,38 @@ static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
1033 }; 1096 };
1034 1097
1035 *out_hwirq = intspec[0]; 1098 *out_hwirq = intspec[0];
1036 if (intsize > 1) { 1099 if (intsize >= 4 && (mpic->flags & MPIC_FSL)) {
1100 /*
1101 * Freescale MPIC with extended intspec:
1102 * First two cells are as usual. Third specifies
1103 * an "interrupt type". Fourth is type-specific data.
1104 *
1105 * See Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
1106 */
1107 switch (intspec[2]) {
1108 case 0:
1109 case 1: /* no EISR/EIMR support for now, treat as shared IRQ */
1110 break;
1111 case 2:
1112 if (intspec[0] >= ARRAY_SIZE(mpic->ipi_vecs))
1113 return -EINVAL;
1114
1115 *out_hwirq = mpic->ipi_vecs[intspec[0]];
1116 break;
1117 case 3:
1118 if (intspec[0] >= ARRAY_SIZE(mpic->timer_vecs))
1119 return -EINVAL;
1120
1121 *out_hwirq = mpic->timer_vecs[intspec[0]];
1122 break;
1123 default:
1124 pr_debug("%s: unknown irq type %u\n",
1125 __func__, intspec[2]);
1126 return -EINVAL;
1127 }
1128
1129 *out_flags = map_mpic_senses[intspec[1] & 3];
1130 } else if (intsize > 1) {
1037 u32 mask = 0x3; 1131 u32 mask = 0x3;
1038 1132
1039 /* Apple invented a new race of encoding on machines with 1133 /* Apple invented a new race of encoding on machines with
@@ -1109,6 +1203,9 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1109 mpic->hc_ipi.name = name; 1203 mpic->hc_ipi.name = name;
1110#endif /* CONFIG_SMP */ 1204#endif /* CONFIG_SMP */
1111 1205
1206 mpic->hc_tm = mpic_tm_chip;
1207 mpic->hc_tm.name = name;
1208
1112 mpic->flags = flags; 1209 mpic->flags = flags;
1113 mpic->isu_size = isu_size; 1210 mpic->isu_size = isu_size;
1114 mpic->irq_count = irq_count; 1211 mpic->irq_count = irq_count;
@@ -1119,10 +1216,14 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1119 else 1216 else
1120 intvec_top = 255; 1217 intvec_top = 255;
1121 1218
1122 mpic->timer_vecs[0] = intvec_top - 8; 1219 mpic->timer_vecs[0] = intvec_top - 12;
1123 mpic->timer_vecs[1] = intvec_top - 7; 1220 mpic->timer_vecs[1] = intvec_top - 11;
1124 mpic->timer_vecs[2] = intvec_top - 6; 1221 mpic->timer_vecs[2] = intvec_top - 10;
1125 mpic->timer_vecs[3] = intvec_top - 5; 1222 mpic->timer_vecs[3] = intvec_top - 9;
1223 mpic->timer_vecs[4] = intvec_top - 8;
1224 mpic->timer_vecs[5] = intvec_top - 7;
1225 mpic->timer_vecs[6] = intvec_top - 6;
1226 mpic->timer_vecs[7] = intvec_top - 5;
1126 mpic->ipi_vecs[0] = intvec_top - 4; 1227 mpic->ipi_vecs[0] = intvec_top - 4;
1127 mpic->ipi_vecs[1] = intvec_top - 3; 1228 mpic->ipi_vecs[1] = intvec_top - 3;
1128 mpic->ipi_vecs[2] = intvec_top - 2; 1229 mpic->ipi_vecs[2] = intvec_top - 2;
@@ -1132,6 +1233,8 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1132 /* Check for "big-endian" in device-tree */ 1233 /* Check for "big-endian" in device-tree */
1133 if (node && of_get_property(node, "big-endian", NULL) != NULL) 1234 if (node && of_get_property(node, "big-endian", NULL) != NULL)
1134 mpic->flags |= MPIC_BIG_ENDIAN; 1235 mpic->flags |= MPIC_BIG_ENDIAN;
1236 if (node && of_device_is_compatible(node, "fsl,mpic"))
1237 mpic->flags |= MPIC_FSL;
1135 1238
1136 /* Look for protected sources */ 1239 /* Look for protected sources */
1137 if (node) { 1240 if (node) {
@@ -1323,15 +1426,17 @@ void __init mpic_init(struct mpic *mpic)
1323 /* Set current processor priority to max */ 1426 /* Set current processor priority to max */
1324 mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); 1427 mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
1325 1428
1326 /* Initialize timers: just disable them all */ 1429 /* Initialize timers to our reserved vectors and mask them for now */
1327 for (i = 0; i < 4; i++) { 1430 for (i = 0; i < 4; i++) {
1328 mpic_write(mpic->tmregs, 1431 mpic_write(mpic->tmregs,
1329 i * MPIC_INFO(TIMER_STRIDE) + 1432 i * MPIC_INFO(TIMER_STRIDE) +
1330 MPIC_INFO(TIMER_DESTINATION), 0); 1433 MPIC_INFO(TIMER_DESTINATION),
1434 1 << hard_smp_processor_id());
1331 mpic_write(mpic->tmregs, 1435 mpic_write(mpic->tmregs,
1332 i * MPIC_INFO(TIMER_STRIDE) + 1436 i * MPIC_INFO(TIMER_STRIDE) +
1333 MPIC_INFO(TIMER_VECTOR_PRI), 1437 MPIC_INFO(TIMER_VECTOR_PRI),
1334 MPIC_VECPRI_MASK | 1438 MPIC_VECPRI_MASK |
1439 (9 << MPIC_VECPRI_PRIORITY_SHIFT) |
1335 (mpic->timer_vecs[0] + i)); 1440 (mpic->timer_vecs[0] + i));
1336 } 1441 }
1337 1442
@@ -1427,7 +1532,7 @@ void __init mpic_set_serial_int(struct mpic *mpic, int enable)
1427void mpic_irq_set_priority(unsigned int irq, unsigned int pri) 1532void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
1428{ 1533{
1429 struct mpic *mpic = mpic_find(irq); 1534 struct mpic *mpic = mpic_find(irq);
1430 unsigned int src = mpic_irq_to_hw(irq); 1535 unsigned int src = virq_to_hw(irq);
1431 unsigned long flags; 1536 unsigned long flags;
1432 u32 reg; 1537 u32 reg;
1433 1538
@@ -1440,6 +1545,11 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
1440 ~MPIC_VECPRI_PRIORITY_MASK; 1545 ~MPIC_VECPRI_PRIORITY_MASK;
1441 mpic_ipi_write(src - mpic->ipi_vecs[0], 1546 mpic_ipi_write(src - mpic->ipi_vecs[0],
1442 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 1547 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
1548 } else if (mpic_is_tm(mpic, irq)) {
1549 reg = mpic_tm_read(src - mpic->timer_vecs[0]) &
1550 ~MPIC_VECPRI_PRIORITY_MASK;
1551 mpic_tm_write(src - mpic->timer_vecs[0],
1552 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
1443 } else { 1553 } else {
1444 reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) 1554 reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI))
1445 & ~MPIC_VECPRI_PRIORITY_MASK; 1555 & ~MPIC_VECPRI_PRIORITY_MASK;
@@ -1619,46 +1729,28 @@ void mpic_request_ipis(void)
1619 } 1729 }
1620} 1730}
1621 1731
1622static void mpic_send_ipi(unsigned int ipi_no, const struct cpumask *cpu_mask) 1732void smp_mpic_message_pass(int cpu, int msg)
1623{ 1733{
1624 struct mpic *mpic = mpic_primary; 1734 struct mpic *mpic = mpic_primary;
1735 u32 physmask;
1625 1736
1626 BUG_ON(mpic == NULL); 1737 BUG_ON(mpic == NULL);
1627 1738
1628#ifdef DEBUG_IPI
1629 DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
1630#endif
1631
1632 mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
1633 ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE),
1634 mpic_physmask(cpumask_bits(cpu_mask)[0]));
1635}
1636
1637void smp_mpic_message_pass(int target, int msg)
1638{
1639 cpumask_var_t tmp;
1640
1641 /* make sure we're sending something that translates to an IPI */ 1739 /* make sure we're sending something that translates to an IPI */
1642 if ((unsigned int)msg > 3) { 1740 if ((unsigned int)msg > 3) {
1643 printk("SMP %d: smp_message_pass: unknown msg %d\n", 1741 printk("SMP %d: smp_message_pass: unknown msg %d\n",
1644 smp_processor_id(), msg); 1742 smp_processor_id(), msg);
1645 return; 1743 return;
1646 } 1744 }
1647 switch (target) { 1745
1648 case MSG_ALL: 1746#ifdef DEBUG_IPI
1649 mpic_send_ipi(msg, cpu_online_mask); 1747 DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, msg);
1650 break; 1748#endif
1651 case MSG_ALL_BUT_SELF: 1749
1652 alloc_cpumask_var(&tmp, GFP_NOWAIT); 1750 physmask = 1 << get_hard_smp_processor_id(cpu);
1653 cpumask_andnot(tmp, cpu_online_mask, 1751
1654 cpumask_of(smp_processor_id())); 1752 mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
1655 mpic_send_ipi(msg, tmp); 1753 msg * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE), physmask);
1656 free_cpumask_var(tmp);
1657 break;
1658 default:
1659 mpic_send_ipi(msg, cpumask_of(target));
1660 break;
1661 }
1662} 1754}
1663 1755
1664int __init smp_mpic_probe(void) 1756int __init smp_mpic_probe(void)
@@ -1702,9 +1794,8 @@ void mpic_reset_core(int cpu)
1702#endif /* CONFIG_SMP */ 1794#endif /* CONFIG_SMP */
1703 1795
1704#ifdef CONFIG_PM 1796#ifdef CONFIG_PM
1705static int mpic_suspend(struct sys_device *dev, pm_message_t state) 1797static void mpic_suspend_one(struct mpic *mpic)
1706{ 1798{
1707 struct mpic *mpic = container_of(dev, struct mpic, sysdev);
1708 int i; 1799 int i;
1709 1800
1710 for (i = 0; i < mpic->num_sources; i++) { 1801 for (i = 0; i < mpic->num_sources; i++) {
@@ -1713,13 +1804,22 @@ static int mpic_suspend(struct sys_device *dev, pm_message_t state)
1713 mpic->save_data[i].dest = 1804 mpic->save_data[i].dest =
1714 mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)); 1805 mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
1715 } 1806 }
1807}
1808
1809static int mpic_suspend(void)
1810{
1811 struct mpic *mpic = mpics;
1812
1813 while (mpic) {
1814 mpic_suspend_one(mpic);
1815 mpic = mpic->next;
1816 }
1716 1817
1717 return 0; 1818 return 0;
1718} 1819}
1719 1820
1720static int mpic_resume(struct sys_device *dev) 1821static void mpic_resume_one(struct mpic *mpic)
1721{ 1822{
1722 struct mpic *mpic = container_of(dev, struct mpic, sysdev);
1723 int i; 1823 int i;
1724 1824
1725 for (i = 0; i < mpic->num_sources; i++) { 1825 for (i = 0; i < mpic->num_sources; i++) {
@@ -1746,33 +1846,28 @@ static int mpic_resume(struct sys_device *dev)
1746 } 1846 }
1747#endif 1847#endif
1748 } /* end for loop */ 1848 } /* end for loop */
1849}
1749 1850
1750 return 0; 1851static void mpic_resume(void)
1852{
1853 struct mpic *mpic = mpics;
1854
1855 while (mpic) {
1856 mpic_resume_one(mpic);
1857 mpic = mpic->next;
1858 }
1751} 1859}
1752#endif
1753 1860
1754static struct sysdev_class mpic_sysclass = { 1861static struct syscore_ops mpic_syscore_ops = {
1755#ifdef CONFIG_PM
1756 .resume = mpic_resume, 1862 .resume = mpic_resume,
1757 .suspend = mpic_suspend, 1863 .suspend = mpic_suspend,
1758#endif
1759 .name = "mpic",
1760}; 1864};
1761 1865
1762static int mpic_init_sys(void) 1866static int mpic_init_sys(void)
1763{ 1867{
1764 struct mpic *mpic = mpics; 1868 register_syscore_ops(&mpic_syscore_ops);
1765 int error, id = 0; 1869 return 0;
1766
1767 error = sysdev_class_register(&mpic_sysclass);
1768
1769 while (mpic && !error) {
1770 mpic->sysdev.cls = &mpic_sysclass;
1771 mpic->sysdev.id = id++;
1772 error = sysdev_register(&mpic->sysdev);
1773 mpic = mpic->next;
1774 }
1775 return error;
1776} 1870}
1777 1871
1778device_initcall(mpic_init_sys); 1872device_initcall(mpic_init_sys);
1873#endif