aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorKyle Moffett <Kyle.D.Moffett@boeing.com>2011-12-22 05:19:13 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-02-22 18:50:00 -0500
commitc1b8d45db4dbc64cc6015f97922f767fdf782f64 (patch)
treec23f986f6601b2f67645eca5b8744c8d753bc094 /arch/powerpc/sysdev
parent5019609fce965dbdc66a7d947385fe92ca522231 (diff)
powerpc/mpic: Add "last-interrupt-source" property to override hardware
The FreeScale PowerQUICC-III-compatible (mpc85xx/mpc86xx) MPICs do not correctly report the number of hardware interrupt sources, so software needs to override the detected value with "256". To avoid needing to write custom board-specific code to detect that scenario, allow it to be easily overridden in the device-tree. Signed-off-by: Kyle Moffett <Kyle.D.Moffett@boeing.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/mpic.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index cbffeb742d66..90171d447c3d 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -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[] = {
@@ -1220,7 +1221,6 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1220 mpic->hc_tm = mpic_tm_chip; 1221 mpic->hc_tm = mpic_tm_chip;
1221 mpic->hc_tm.name = name; 1222 mpic->hc_tm.name = name;
1222 1223
1223 mpic->isu_size = isu_size;
1224 mpic->num_sources = 0; /* so far */ 1224 mpic->num_sources = 0; /* so far */
1225 1225
1226 if (mpic->flags & MPIC_LARGE_VECTORS) 1226 if (mpic->flags & MPIC_LARGE_VECTORS)
@@ -1308,20 +1308,6 @@ struct mpic * __init mpic_alloc(struct device_node *node,
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 (irq_count)
1317 mpic->num_sources = 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,18 +1322,38 @@ 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 */
1335 last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
1336 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;
1337 of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq);
1338 if (irq_count)
1339 last_irq = irq_count - 1;
1340
1339 /* Initialize main ISU if none provided */ 1341 /* Initialize main ISU if none provided */
1340 if (mpic->isu_size == 0) { 1342 if (!isu_size) {
1341 mpic->isu_size = mpic->num_sources; 1343 isu_size = last_irq + 1;
1344 mpic->num_sources = isu_size;
1342 mpic_map(mpic, mpic->paddr, &mpic->isus[0], 1345 mpic_map(mpic, mpic->paddr, &mpic->isus[0],
1343 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1346 MPIC_INFO(IRQ_BASE),
1347 MPIC_INFO(IRQ_STRIDE) * isu_size);
1344 } 1348 }
1349
1350 mpic->isu_size = isu_size;
1345 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); 1351 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
1346 mpic->isu_mask = (1 << mpic->isu_shift) - 1; 1352 mpic->isu_mask = (1 << mpic->isu_shift) - 1;
1347 1353
1348 mpic->irqhost = irq_alloc_host(mpic->node, IRQ_HOST_MAP_LINEAR, 1354 mpic->irqhost = irq_alloc_host(mpic->node, IRQ_HOST_MAP_LINEAR,
1349 isu_size ? isu_size : mpic->num_sources, 1355 mpic->isu_size, &mpic_host_ops,
1350 &mpic_host_ops, intvec_top + 1); 1356 intvec_top + 1);
1351 1357
1352 /* 1358 /*
1353 * FIXME: The code leaks the MPIC object and mappings here; this 1359 * FIXME: The code leaks the MPIC object and mappings here; this