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.c128
1 files changed, 82 insertions, 46 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index eb7021815e2d..f91c065bed5a 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -147,6 +147,16 @@ static u32 mpic_infos[][MPIC_IDX_END] = {
147 147
148#endif /* CONFIG_MPIC_WEIRD */ 148#endif /* CONFIG_MPIC_WEIRD */
149 149
150static inline unsigned int mpic_processor_id(struct mpic *mpic)
151{
152 unsigned int cpu = 0;
153
154 if (mpic->flags & MPIC_PRIMARY)
155 cpu = hard_smp_processor_id();
156
157 return cpu;
158}
159
150/* 160/*
151 * Register accessor functions 161 * Register accessor functions
152 */ 162 */
@@ -210,19 +220,14 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu
210 220
211static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) 221static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
212{ 222{
213 unsigned int cpu = 0; 223 unsigned int cpu = mpic_processor_id(mpic);
214 224
215 if (mpic->flags & MPIC_PRIMARY)
216 cpu = hard_smp_processor_id();
217 return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg); 225 return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg);
218} 226}
219 227
220static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) 228static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
221{ 229{
222 unsigned int cpu = 0; 230 unsigned int cpu = mpic_processor_id(mpic);
223
224 if (mpic->flags & MPIC_PRIMARY)
225 cpu = hard_smp_processor_id();
226 231
227 _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value); 232 _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value);
228} 233}
@@ -356,7 +361,7 @@ static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source)
356} 361}
357 362
358static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source, 363static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
359 unsigned int irqflags) 364 bool level)
360{ 365{
361 struct mpic_irq_fixup *fixup = &mpic->fixups[source]; 366 struct mpic_irq_fixup *fixup = &mpic->fixups[source];
362 unsigned long flags; 367 unsigned long flags;
@@ -365,14 +370,14 @@ static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
365 if (fixup->base == NULL) 370 if (fixup->base == NULL)
366 return; 371 return;
367 372
368 DBG("startup_ht_interrupt(0x%x, 0x%x) index: %d\n", 373 DBG("startup_ht_interrupt(0x%x) index: %d\n",
369 source, irqflags, fixup->index); 374 source, fixup->index);
370 raw_spin_lock_irqsave(&mpic->fixup_lock, flags); 375 raw_spin_lock_irqsave(&mpic->fixup_lock, flags);
371 /* Enable and configure */ 376 /* Enable and configure */
372 writeb(0x10 + 2 * fixup->index, fixup->base + 2); 377 writeb(0x10 + 2 * fixup->index, fixup->base + 2);
373 tmp = readl(fixup->base + 4); 378 tmp = readl(fixup->base + 4);
374 tmp &= ~(0x23U); 379 tmp &= ~(0x23U);
375 if (irqflags & IRQ_LEVEL) 380 if (level)
376 tmp |= 0x22; 381 tmp |= 0x22;
377 writel(tmp, fixup->base + 4); 382 writel(tmp, fixup->base + 4);
378 raw_spin_unlock_irqrestore(&mpic->fixup_lock, flags); 383 raw_spin_unlock_irqrestore(&mpic->fixup_lock, flags);
@@ -384,8 +389,7 @@ static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
384#endif 389#endif
385} 390}
386 391
387static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source, 392static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source)
388 unsigned int irqflags)
389{ 393{
390 struct mpic_irq_fixup *fixup = &mpic->fixups[source]; 394 struct mpic_irq_fixup *fixup = &mpic->fixups[source];
391 unsigned long flags; 395 unsigned long flags;
@@ -394,7 +398,7 @@ static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
394 if (fixup->base == NULL) 398 if (fixup->base == NULL)
395 return; 399 return;
396 400
397 DBG("shutdown_ht_interrupt(0x%x, 0x%x)\n", source, irqflags); 401 DBG("shutdown_ht_interrupt(0x%x)\n", source);
398 402
399 /* Disable */ 403 /* Disable */
400 raw_spin_lock_irqsave(&mpic->fixup_lock, flags); 404 raw_spin_lock_irqsave(&mpic->fixup_lock, flags);
@@ -611,7 +615,7 @@ static struct mpic *mpic_find(unsigned int irq)
611 if (irq < NUM_ISA_INTERRUPTS) 615 if (irq < NUM_ISA_INTERRUPTS)
612 return NULL; 616 return NULL;
613 617
614 return get_irq_chip_data(irq); 618 return irq_get_chip_data(irq);
615} 619}
616 620
617/* Determine if the linux irq is an IPI */ 621/* Determine if the linux irq is an IPI */
@@ -645,7 +649,7 @@ static inline struct mpic * mpic_from_ipi(struct irq_data *d)
645/* Get the mpic structure from the irq number */ 649/* Get the mpic structure from the irq number */
646static inline struct mpic * mpic_from_irq(unsigned int irq) 650static inline struct mpic * mpic_from_irq(unsigned int irq)
647{ 651{
648 return get_irq_chip_data(irq); 652 return irq_get_chip_data(irq);
649} 653}
650 654
651/* Get the mpic structure from the irq data */ 655/* Get the mpic structure from the irq data */
@@ -733,7 +737,7 @@ static void mpic_unmask_ht_irq(struct irq_data *d)
733 737
734 mpic_unmask_irq(d); 738 mpic_unmask_irq(d);
735 739
736 if (irq_to_desc(d->irq)->status & IRQ_LEVEL) 740 if (irqd_is_level_type(d))
737 mpic_ht_end_irq(mpic, src); 741 mpic_ht_end_irq(mpic, src);
738} 742}
739 743
@@ -743,7 +747,7 @@ static unsigned int mpic_startup_ht_irq(struct irq_data *d)
743 unsigned int src = mpic_irq_to_hw(d->irq); 747 unsigned int src = mpic_irq_to_hw(d->irq);
744 748
745 mpic_unmask_irq(d); 749 mpic_unmask_irq(d);
746 mpic_startup_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status); 750 mpic_startup_ht_interrupt(mpic, src, irqd_is_level_type(d));
747 751
748 return 0; 752 return 0;
749} 753}
@@ -753,7 +757,7 @@ static void mpic_shutdown_ht_irq(struct irq_data *d)
753 struct mpic *mpic = mpic_from_irq_data(d); 757 struct mpic *mpic = mpic_from_irq_data(d);
754 unsigned int src = mpic_irq_to_hw(d->irq); 758 unsigned int src = mpic_irq_to_hw(d->irq);
755 759
756 mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status); 760 mpic_shutdown_ht_interrupt(mpic, src);
757 mpic_mask_irq(d); 761 mpic_mask_irq(d);
758} 762}
759 763
@@ -770,7 +774,7 @@ static void mpic_end_ht_irq(struct irq_data *d)
770 * latched another edge interrupt coming in anyway 774 * latched another edge interrupt coming in anyway
771 */ 775 */
772 776
773 if (irq_to_desc(d->irq)->status & IRQ_LEVEL) 777 if (irqd_is_level_type(d))
774 mpic_ht_end_irq(mpic, src); 778 mpic_ht_end_irq(mpic, src);
775 mpic_eoi(mpic); 779 mpic_eoi(mpic);
776} 780}
@@ -859,7 +863,6 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
859{ 863{
860 struct mpic *mpic = mpic_from_irq_data(d); 864 struct mpic *mpic = mpic_from_irq_data(d);
861 unsigned int src = mpic_irq_to_hw(d->irq); 865 unsigned int src = mpic_irq_to_hw(d->irq);
862 struct irq_desc *desc = irq_to_desc(d->irq);
863 unsigned int vecpri, vold, vnew; 866 unsigned int vecpri, vold, vnew;
864 867
865 DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", 868 DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
@@ -874,10 +877,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
874 if (flow_type == IRQ_TYPE_NONE) 877 if (flow_type == IRQ_TYPE_NONE)
875 flow_type = IRQ_TYPE_LEVEL_LOW; 878 flow_type = IRQ_TYPE_LEVEL_LOW;
876 879
877 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); 880 irqd_set_trigger_type(d, flow_type);
878 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
879 if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
880 desc->status |= IRQ_LEVEL;
881 881
882 if (mpic_is_ht_interrupt(mpic, src)) 882 if (mpic_is_ht_interrupt(mpic, src))
883 vecpri = MPIC_VECPRI_POLARITY_POSITIVE | 883 vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
@@ -892,7 +892,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
892 if (vold != vnew) 892 if (vold != vnew)
893 mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew); 893 mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
894 894
895 return 0; 895 return IRQ_SET_MASK_OK_NOCOPY;;
896} 896}
897 897
898void mpic_set_vector(unsigned int virq, unsigned int vector) 898void mpic_set_vector(unsigned int virq, unsigned int vector)
@@ -913,6 +913,20 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
913 mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); 913 mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
914} 914}
915 915
916void mpic_set_destination(unsigned int virq, unsigned int cpuid)
917{
918 struct mpic *mpic = mpic_from_irq(virq);
919 unsigned int src = mpic_irq_to_hw(virq);
920
921 DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
922 mpic, virq, src, cpuid);
923
924 if (src >= mpic->irq_count)
925 return;
926
927 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
928}
929
916static struct irq_chip mpic_irq_chip = { 930static struct irq_chip mpic_irq_chip = {
917 .irq_mask = mpic_mask_irq, 931 .irq_mask = mpic_mask_irq,
918 .irq_unmask = mpic_unmask_irq, 932 .irq_unmask = mpic_unmask_irq,
@@ -964,8 +978,8 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
964 WARN_ON(!(mpic->flags & MPIC_PRIMARY)); 978 WARN_ON(!(mpic->flags & MPIC_PRIMARY));
965 979
966 DBG("mpic: mapping as IPI\n"); 980 DBG("mpic: mapping as IPI\n");
967 set_irq_chip_data(virq, mpic); 981 irq_set_chip_data(virq, mpic);
968 set_irq_chip_and_handler(virq, &mpic->hc_ipi, 982 irq_set_chip_and_handler(virq, &mpic->hc_ipi,
969 handle_percpu_irq); 983 handle_percpu_irq);
970 return 0; 984 return 0;
971 } 985 }
@@ -987,11 +1001,21 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
987 1001
988 DBG("mpic: mapping to irq chip @%p\n", chip); 1002 DBG("mpic: mapping to irq chip @%p\n", chip);
989 1003
990 set_irq_chip_data(virq, mpic); 1004 irq_set_chip_data(virq, mpic);
991 set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq); 1005 irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq);
992 1006
993 /* Set default irq type */ 1007 /* Set default irq type */
994 set_irq_type(virq, IRQ_TYPE_NONE); 1008 irq_set_irq_type(virq, IRQ_TYPE_NONE);
1009
1010 /* If the MPIC was reset, then all vectors have already been
1011 * initialized. Otherwise, a per source lazy initialization
1012 * is done here.
1013 */
1014 if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
1015 mpic_set_vector(virq, hw);
1016 mpic_set_destination(virq, mpic_processor_id(mpic));
1017 mpic_irq_set_priority(virq, 8);
1018 }
995 1019
996 return 0; 1020 return 0;
997} 1021}
@@ -1040,6 +1064,11 @@ static struct irq_host_ops mpic_host_ops = {
1040 .xlate = mpic_host_xlate, 1064 .xlate = mpic_host_xlate,
1041}; 1065};
1042 1066
1067static int mpic_reset_prohibited(struct device_node *node)
1068{
1069 return node && of_get_property(node, "pic-no-reset", NULL);
1070}
1071
1043/* 1072/*
1044 * Exported functions 1073 * Exported functions
1045 */ 1074 */
@@ -1160,7 +1189,15 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1160 mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); 1189 mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
1161 1190
1162 /* Reset */ 1191 /* Reset */
1163 if (flags & MPIC_WANTS_RESET) { 1192
1193 /* When using a device-node, reset requests are only honored if the MPIC
1194 * is allowed to reset.
1195 */
1196 if (mpic_reset_prohibited(node))
1197 mpic->flags |= MPIC_NO_RESET;
1198
1199 if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
1200 printk(KERN_DEBUG "mpic: Resetting\n");
1164 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), 1201 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
1165 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) 1202 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
1166 | MPIC_GREG_GCONF_RESET); 1203 | MPIC_GREG_GCONF_RESET);
@@ -1320,22 +1357,21 @@ void __init mpic_init(struct mpic *mpic)
1320 1357
1321 mpic_pasemi_msi_init(mpic); 1358 mpic_pasemi_msi_init(mpic);
1322 1359
1323 if (mpic->flags & MPIC_PRIMARY) 1360 cpu = mpic_processor_id(mpic);
1324 cpu = hard_smp_processor_id();
1325 else
1326 cpu = 0;
1327 1361
1328 for (i = 0; i < mpic->num_sources; i++) { 1362 if (!(mpic->flags & MPIC_NO_RESET)) {
1329 /* start with vector = source number, and masked */ 1363 for (i = 0; i < mpic->num_sources; i++) {
1330 u32 vecpri = MPIC_VECPRI_MASK | i | 1364 /* start with vector = source number, and masked */
1331 (8 << MPIC_VECPRI_PRIORITY_SHIFT); 1365 u32 vecpri = MPIC_VECPRI_MASK | i |
1366 (8 << MPIC_VECPRI_PRIORITY_SHIFT);
1332 1367
1333 /* check if protected */ 1368 /* check if protected */
1334 if (mpic->protected && test_bit(i, mpic->protected)) 1369 if (mpic->protected && test_bit(i, mpic->protected))
1335 continue; 1370 continue;
1336 /* init hw */ 1371 /* init hw */
1337 mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); 1372 mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
1338 mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu); 1373 mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
1374 }
1339 } 1375 }
1340 1376
1341 /* Init spurious vector */ 1377 /* Init spurious vector */