aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-21 12:52:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-21 12:52:27 -0400
commit111f4268bd69cb040bf05038785cfbc4087f6341 (patch)
treed132d3296a7c44bb26659d698d0fdd4a05db1767 /arch/powerpc/sysdev/mpic.c
parenta44f99c7efdb88fa41128065c9a9445c19894e34 (diff)
parenta71f5d5d279375205009a4be56a3cf6682921292 (diff)
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: powerpc/ptrace: Remove BUG_ON when full register set not available powerpc: Factoring mpic cpu id fetching into a function powerpc: Make MPIC honor the "pic-no-reset" device tree property powerpc: Document the Open PIC device tree binding powerpc/pci: Fix crash in PCI code on ppc64 when matching device nodes
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c85
1 files changed, 63 insertions, 22 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index eb7021815e2d..0f7c6718d261 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}
@@ -913,6 +918,20 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
913 mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); 918 mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
914} 919}
915 920
921void mpic_set_destination(unsigned int virq, unsigned int cpuid)
922{
923 struct mpic *mpic = mpic_from_irq(virq);
924 unsigned int src = mpic_irq_to_hw(virq);
925
926 DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
927 mpic, virq, src, cpuid);
928
929 if (src >= mpic->irq_count)
930 return;
931
932 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
933}
934
916static struct irq_chip mpic_irq_chip = { 935static struct irq_chip mpic_irq_chip = {
917 .irq_mask = mpic_mask_irq, 936 .irq_mask = mpic_mask_irq,
918 .irq_unmask = mpic_unmask_irq, 937 .irq_unmask = mpic_unmask_irq,
@@ -993,6 +1012,16 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
993 /* Set default irq type */ 1012 /* Set default irq type */
994 set_irq_type(virq, IRQ_TYPE_NONE); 1013 set_irq_type(virq, IRQ_TYPE_NONE);
995 1014
1015 /* If the MPIC was reset, then all vectors have already been
1016 * initialized. Otherwise, a per source lazy initialization
1017 * is done here.
1018 */
1019 if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
1020 mpic_set_vector(virq, hw);
1021 mpic_set_destination(virq, mpic_processor_id(mpic));
1022 mpic_irq_set_priority(virq, 8);
1023 }
1024
996 return 0; 1025 return 0;
997} 1026}
998 1027
@@ -1040,6 +1069,11 @@ static struct irq_host_ops mpic_host_ops = {
1040 .xlate = mpic_host_xlate, 1069 .xlate = mpic_host_xlate,
1041}; 1070};
1042 1071
1072static int mpic_reset_prohibited(struct device_node *node)
1073{
1074 return node && of_get_property(node, "pic-no-reset", NULL);
1075}
1076
1043/* 1077/*
1044 * Exported functions 1078 * Exported functions
1045 */ 1079 */
@@ -1160,7 +1194,15 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1160 mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); 1194 mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
1161 1195
1162 /* Reset */ 1196 /* Reset */
1163 if (flags & MPIC_WANTS_RESET) { 1197
1198 /* When using a device-node, reset requests are only honored if the MPIC
1199 * is allowed to reset.
1200 */
1201 if (mpic_reset_prohibited(node))
1202 mpic->flags |= MPIC_NO_RESET;
1203
1204 if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
1205 printk(KERN_DEBUG "mpic: Resetting\n");
1164 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), 1206 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
1165 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) 1207 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
1166 | MPIC_GREG_GCONF_RESET); 1208 | MPIC_GREG_GCONF_RESET);
@@ -1320,22 +1362,21 @@ void __init mpic_init(struct mpic *mpic)
1320 1362
1321 mpic_pasemi_msi_init(mpic); 1363 mpic_pasemi_msi_init(mpic);
1322 1364
1323 if (mpic->flags & MPIC_PRIMARY) 1365 cpu = mpic_processor_id(mpic);
1324 cpu = hard_smp_processor_id();
1325 else
1326 cpu = 0;
1327 1366
1328 for (i = 0; i < mpic->num_sources; i++) { 1367 if (!(mpic->flags & MPIC_NO_RESET)) {
1329 /* start with vector = source number, and masked */ 1368 for (i = 0; i < mpic->num_sources; i++) {
1330 u32 vecpri = MPIC_VECPRI_MASK | i | 1369 /* start with vector = source number, and masked */
1331 (8 << MPIC_VECPRI_PRIORITY_SHIFT); 1370 u32 vecpri = MPIC_VECPRI_MASK | i |
1371 (8 << MPIC_VECPRI_PRIORITY_SHIFT);
1332 1372
1333 /* check if protected */ 1373 /* check if protected */
1334 if (mpic->protected && test_bit(i, mpic->protected)) 1374 if (mpic->protected && test_bit(i, mpic->protected))
1335 continue; 1375 continue;
1336 /* init hw */ 1376 /* init hw */
1337 mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); 1377 mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
1338 mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu); 1378 mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
1379 }
1339 } 1380 }
1340 1381
1341 /* Init spurious vector */ 1382 /* Init spurious vector */