aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-21 21:55:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-21 21:55:10 -0400
commit5375871d432ae9fc581014ac117b96aaee3cd0c7 (patch)
treebe98e8255b0f927fb920fb532a598b93fa140dbe /arch/powerpc/sysdev/mpic.c
parentb57cb7231b2ce52d3dda14a7b417ae125fb2eb97 (diff)
parentdfbc2d75c1bd47c3186fa91f1655ea2f3825b0ec (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc merge from Benjamin Herrenschmidt: "Here's the powerpc batch for this merge window. It is going to be a bit more nasty than usual as in touching things outside of arch/powerpc mostly due to the big iSeriesectomy :-) We finally got rid of the bugger (legacy iSeries support) which was a PITA to maintain and that nobody really used anymore. Here are some of the highlights: - Legacy iSeries is gone. Thanks Stephen ! There's still some bits and pieces remaining if you do a grep -ir series arch/powerpc but they are harmless and will be removed in the next few weeks hopefully. - The 'fadump' functionality (Firmware Assisted Dump) replaces the previous (equivalent) "pHyp assisted dump"... it's a rewrite of a mechanism to get the hypervisor to do crash dumps on pSeries, the new implementation hopefully being much more reliable. Thanks Mahesh Salgaonkar. - The "EEH" code (pSeries PCI error handling & recovery) got a big spring cleaning, motivated by the need to be able to implement a new backend for it on top of some new different type of firwmare. The work isn't complete yet, but a good chunk of the cleanups is there. Note that this adds a field to struct device_node which is not very nice and which Grant objects to. I will have a patch soon that moves that to a powerpc private data structure (hopefully before rc1) and we'll improve things further later on (hopefully getting rid of the need for that pointer completely). Thanks Gavin Shan. - I dug into our exception & interrupt handling code to improve the way we do lazy interrupt handling (and make it work properly with "edge" triggered interrupt sources), and while at it found & fixed a wagon of issues in those areas, including adding support for page fault retry & fatal signals on page faults. - Your usual random batch of small fixes & updates, including a bunch of new embedded boards, both Freescale and APM based ones, etc..." I fixed up some conflicts with the generalized irq-domain changes from Grant Likely, hopefully correctly. * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (141 commits) powerpc/ps3: Do not adjust the wrapper load address powerpc: Remove the rest of the legacy iSeries include files powerpc: Remove the remaining CONFIG_PPC_ISERIES pieces init: Remove CONFIG_PPC_ISERIES powerpc: Remove FW_FEATURE ISERIES from arch code tty/hvc_vio: FW_FEATURE_ISERIES is no longer selectable powerpc/spufs: Fix double unlocks powerpc/5200: convert mpc5200 to use of_platform_populate() powerpc/mpc5200: add options to mpc5200_defconfig powerpc/mpc52xx: add a4m072 board support powerpc/mpc5200: update mpc5200_defconfig to fit for charon board Documentation/powerpc/mpc52xx.txt: Checkpatch cleanup powerpc/44x: Add additional device support for APM821xx SoC and Bluestone board powerpc/44x: Add support PCI-E for APM821xx SoC and Bluestone board MAINTAINERS: Update PowerPC 4xx tree powerpc/44x: The bug fixed support for APM821xx SoC and Bluestone board powerpc: document the FSL MPIC message register binding powerpc: add support for MPIC message register API powerpc/fsl: Added aliased MSIIR register address to MSI node in dts powerpc/85xx: mpc8548cds - add 36-bit dts ...
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c104
1 files changed, 55 insertions, 49 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index c83a512fa175..9ac71ebd2c40 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -873,7 +873,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
873 DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", 873 DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
874 mpic, d->irq, src, flow_type); 874 mpic, d->irq, src, flow_type);
875 875
876 if (src >= mpic->irq_count) 876 if (src >= mpic->num_sources)
877 return -EINVAL; 877 return -EINVAL;
878 878
879 if (flow_type == IRQ_TYPE_NONE) 879 if (flow_type == IRQ_TYPE_NONE)
@@ -909,7 +909,7 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
909 DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n", 909 DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n",
910 mpic, virq, src, vector); 910 mpic, virq, src, vector);
911 911
912 if (src >= mpic->irq_count) 912 if (src >= mpic->num_sources)
913 return; 913 return;
914 914
915 vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); 915 vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
@@ -926,7 +926,7 @@ void mpic_set_destination(unsigned int virq, unsigned int cpuid)
926 DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n", 926 DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
927 mpic, virq, src, cpuid); 927 mpic, virq, src, cpuid);
928 928
929 if (src >= mpic->irq_count) 929 if (src >= mpic->num_sources)
930 return; 930 return;
931 931
932 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); 932 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
@@ -1006,7 +1006,7 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
1006 return 0; 1006 return 0;
1007 } 1007 }
1008 1008
1009 if (hw >= mpic->irq_count) 1009 if (hw >= mpic->num_sources)
1010 return -EINVAL; 1010 return -EINVAL;
1011 1011
1012 mpic_msi_reserve_hwirq(mpic, hw); 1012 mpic_msi_reserve_hwirq(mpic, hw);
@@ -1149,6 +1149,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1149 u32 greg_feature; 1149 u32 greg_feature;
1150 const char *vers; 1150 const char *vers;
1151 const u32 *psrc; 1151 const u32 *psrc;
1152 u32 last_irq;
1152 1153
1153 /* Default MPIC search parameters */ 1154 /* Default MPIC search parameters */
1154 static const struct of_device_id __initconst mpic_device_id[] = { 1155 static const struct of_device_id __initconst mpic_device_id[] = {
@@ -1182,6 +1183,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1182 } 1183 }
1183 } 1184 }
1184 1185
1186 /* Read extra device-tree properties into the flags variable */
1187 if (of_get_property(node, "big-endian", NULL))
1188 flags |= MPIC_BIG_ENDIAN;
1189 if (of_get_property(node, "pic-no-reset", NULL))
1190 flags |= MPIC_NO_RESET;
1191 if (of_get_property(node, "single-cpu-affinity", NULL))
1192 flags |= MPIC_SINGLE_DEST_CPU;
1193 if (of_device_is_compatible(node, "fsl,mpic"))
1194 flags |= MPIC_FSL;
1195
1185 mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL); 1196 mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL);
1186 if (mpic == NULL) 1197 if (mpic == NULL)
1187 goto err_of_node_put; 1198 goto err_of_node_put;
@@ -1189,15 +1200,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1189 mpic->name = name; 1200 mpic->name = name;
1190 mpic->node = node; 1201 mpic->node = node;
1191 mpic->paddr = phys_addr; 1202 mpic->paddr = phys_addr;
1203 mpic->flags = flags;
1192 1204
1193 mpic->hc_irq = mpic_irq_chip; 1205 mpic->hc_irq = mpic_irq_chip;
1194 mpic->hc_irq.name = name; 1206 mpic->hc_irq.name = name;
1195 if (!(flags & MPIC_SECONDARY)) 1207 if (!(mpic->flags & MPIC_SECONDARY))
1196 mpic->hc_irq.irq_set_affinity = mpic_set_affinity; 1208 mpic->hc_irq.irq_set_affinity = mpic_set_affinity;
1197#ifdef CONFIG_MPIC_U3_HT_IRQS 1209#ifdef CONFIG_MPIC_U3_HT_IRQS
1198 mpic->hc_ht_irq = mpic_irq_ht_chip; 1210 mpic->hc_ht_irq = mpic_irq_ht_chip;
1199 mpic->hc_ht_irq.name = name; 1211 mpic->hc_ht_irq.name = name;
1200 if (!(flags & MPIC_SECONDARY)) 1212 if (!(mpic->flags & MPIC_SECONDARY))
1201 mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity; 1213 mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity;
1202#endif /* CONFIG_MPIC_U3_HT_IRQS */ 1214#endif /* CONFIG_MPIC_U3_HT_IRQS */
1203 1215
@@ -1209,12 +1221,9 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1209 mpic->hc_tm = mpic_tm_chip; 1221 mpic->hc_tm = mpic_tm_chip;
1210 mpic->hc_tm.name = name; 1222 mpic->hc_tm.name = name;
1211 1223
1212 mpic->flags = flags;
1213 mpic->isu_size = isu_size;
1214 mpic->irq_count = irq_count;
1215 mpic->num_sources = 0; /* so far */ 1224 mpic->num_sources = 0; /* so far */
1216 1225
1217 if (flags & MPIC_LARGE_VECTORS) 1226 if (mpic->flags & MPIC_LARGE_VECTORS)
1218 intvec_top = 2047; 1227 intvec_top = 2047;
1219 else 1228 else
1220 intvec_top = 255; 1229 intvec_top = 255;
@@ -1233,12 +1242,6 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1233 mpic->ipi_vecs[3] = intvec_top - 1; 1242 mpic->ipi_vecs[3] = intvec_top - 1;
1234 mpic->spurious_vec = intvec_top; 1243 mpic->spurious_vec = intvec_top;
1235 1244
1236 /* Check for "big-endian" in device-tree */
1237 if (of_get_property(mpic->node, "big-endian", NULL) != NULL)
1238 mpic->flags |= MPIC_BIG_ENDIAN;
1239 if (of_device_is_compatible(mpic->node, "fsl,mpic"))
1240 mpic->flags |= MPIC_FSL;
1241
1242 /* Look for protected sources */ 1245 /* Look for protected sources */
1243 psrc = of_get_property(mpic->node, "protected-sources", &psize); 1246 psrc = of_get_property(mpic->node, "protected-sources", &psize);
1244 if (psrc) { 1247 if (psrc) {
@@ -1254,11 +1257,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1254 } 1257 }
1255 1258
1256#ifdef CONFIG_MPIC_WEIRD 1259#ifdef CONFIG_MPIC_WEIRD
1257 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; 1260 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(mpic->flags)];
1258#endif 1261#endif
1259 1262
1260 /* default register type */ 1263 /* default register type */
1261 if (flags & MPIC_BIG_ENDIAN) 1264 if (mpic->flags & MPIC_BIG_ENDIAN)
1262 mpic->reg_type = mpic_access_mmio_be; 1265 mpic->reg_type = mpic_access_mmio_be;
1263 else 1266 else
1264 mpic->reg_type = mpic_access_mmio_le; 1267 mpic->reg_type = mpic_access_mmio_le;
@@ -1268,10 +1271,10 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1268 * only if the kernel includes DCR support. 1271 * only if the kernel includes DCR support.
1269 */ 1272 */
1270#ifdef CONFIG_PPC_DCR 1273#ifdef CONFIG_PPC_DCR
1271 if (flags & MPIC_USES_DCR) 1274 if (mpic->flags & MPIC_USES_DCR)
1272 mpic->reg_type = mpic_access_dcr; 1275 mpic->reg_type = mpic_access_dcr;
1273#else 1276#else
1274 BUG_ON(flags & MPIC_USES_DCR); 1277 BUG_ON(mpic->flags & MPIC_USES_DCR);
1275#endif 1278#endif
1276 1279
1277 /* Map the global registers */ 1280 /* Map the global registers */
@@ -1283,10 +1286,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1283 /* When using a device-node, reset requests are only honored if the MPIC 1286 /* When using a device-node, reset requests are only honored if the MPIC
1284 * is allowed to reset. 1287 * is allowed to reset.
1285 */ 1288 */
1286 if (of_get_property(mpic->node, "pic-no-reset", NULL)) 1289 if (!(mpic->flags & MPIC_NO_RESET)) {
1287 mpic->flags |= MPIC_NO_RESET;
1288
1289 if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
1290 printk(KERN_DEBUG "mpic: Resetting\n"); 1290 printk(KERN_DEBUG "mpic: Resetting\n");
1291 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), 1291 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
1292 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) 1292 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
@@ -1297,31 +1297,17 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1297 } 1297 }
1298 1298
1299 /* CoreInt */ 1299 /* CoreInt */
1300 if (flags & MPIC_ENABLE_COREINT) 1300 if (mpic->flags & MPIC_ENABLE_COREINT)
1301 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), 1301 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
1302 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) 1302 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
1303 | MPIC_GREG_GCONF_COREINT); 1303 | MPIC_GREG_GCONF_COREINT);
1304 1304
1305 if (flags & MPIC_ENABLE_MCK) 1305 if (mpic->flags & MPIC_ENABLE_MCK)
1306 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), 1306 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
1307 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) 1307 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
1308 | MPIC_GREG_GCONF_MCK); 1308 | MPIC_GREG_GCONF_MCK);
1309 1309
1310 /* 1310 /*
1311 * Read feature register. For non-ISU MPICs, num sources as well. On
1312 * ISU MPICs, sources are counted as ISUs are added
1313 */
1314 greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
1315 if (isu_size == 0) {
1316 if (flags & MPIC_BROKEN_FRR_NIRQS)
1317 mpic->num_sources = mpic->irq_count;
1318 else
1319 mpic->num_sources =
1320 ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
1321 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
1322 }
1323
1324 /*
1325 * The MPIC driver will crash if there are more cores than we 1311 * The MPIC driver will crash if there are more cores than we
1326 * can initialize, so we may as well catch that problem here. 1312 * can initialize, so we may as well catch that problem here.
1327 */ 1313 */
@@ -1336,17 +1322,41 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1336 0x1000); 1322 0x1000);
1337 } 1323 }
1338 1324
1325 /*
1326 * Read feature register. For non-ISU MPICs, num sources as well. On
1327 * ISU MPICs, sources are counted as ISUs are added
1328 */
1329 greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
1330
1331 /*
1332 * By default, the last source number comes from the MPIC, but the
1333 * device-tree and board support code can override it on buggy hw.
1334 * If we get passed an isu_size (multi-isu MPIC) then we use that
1335 * as a default instead of the value read from the HW.
1336 */
1337 last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
1338 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;
1339 if (isu_size)
1340 last_irq = isu_size * MPIC_MAX_ISU - 1;
1341 of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq);
1342 if (irq_count)
1343 last_irq = irq_count - 1;
1344
1339 /* Initialize main ISU if none provided */ 1345 /* Initialize main ISU if none provided */
1340 if (mpic->isu_size == 0) { 1346 if (!isu_size) {
1341 mpic->isu_size = mpic->num_sources; 1347 isu_size = last_irq + 1;
1348 mpic->num_sources = isu_size;
1342 mpic_map(mpic, mpic->paddr, &mpic->isus[0], 1349 mpic_map(mpic, mpic->paddr, &mpic->isus[0],
1343 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1350 MPIC_INFO(IRQ_BASE),
1351 MPIC_INFO(IRQ_STRIDE) * isu_size);
1344 } 1352 }
1353
1354 mpic->isu_size = isu_size;
1345 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); 1355 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
1346 mpic->isu_mask = (1 << mpic->isu_shift) - 1; 1356 mpic->isu_mask = (1 << mpic->isu_shift) - 1;
1347 1357
1348 mpic->irqhost = irq_domain_add_linear(mpic->node, 1358 mpic->irqhost = irq_domain_add_linear(mpic->node,
1349 isu_size ? isu_size : mpic->num_sources, 1359 last_irq + 1,
1350 &mpic_host_ops, mpic); 1360 &mpic_host_ops, mpic);
1351 1361
1352 /* 1362 /*
@@ -1380,7 +1390,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1380 mpic->next = mpics; 1390 mpic->next = mpics;
1381 mpics = mpic; 1391 mpics = mpic;
1382 1392
1383 if (!(flags & MPIC_SECONDARY)) { 1393 if (!(mpic->flags & MPIC_SECONDARY)) {
1384 mpic_primary = mpic; 1394 mpic_primary = mpic;
1385 irq_set_default_host(mpic->irqhost); 1395 irq_set_default_host(mpic->irqhost);
1386 } 1396 }
@@ -1447,10 +1457,6 @@ void __init mpic_init(struct mpic *mpic)
1447 (mpic->ipi_vecs[0] + i)); 1457 (mpic->ipi_vecs[0] + i));
1448 } 1458 }
1449 1459
1450 /* Initialize interrupt sources */
1451 if (mpic->irq_count == 0)
1452 mpic->irq_count = mpic->num_sources;
1453
1454 /* Do the HT PIC fixups on U3 broken mpic */ 1460 /* Do the HT PIC fixups on U3 broken mpic */
1455 DBG("MPIC flags: %x\n", mpic->flags); 1461 DBG("MPIC flags: %x\n", mpic->flags);
1456 if ((mpic->flags & MPIC_U3_HT_IRQS) && !(mpic->flags & MPIC_SECONDARY)) { 1462 if ((mpic->flags & MPIC_U3_HT_IRQS) && !(mpic->flags & MPIC_SECONDARY)) {