diff options
author | Kyle Moffett <Kyle.D.Moffett@boeing.com> | 2011-12-22 05:19:13 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-02-22 18:50:00 -0500 |
commit | c1b8d45db4dbc64cc6015f97922f767fdf782f64 (patch) | |
tree | c23f986f6601b2f67645eca5b8744c8d753bc094 /arch/powerpc/sysdev | |
parent | 5019609fce965dbdc66a7d947385fe92ca522231 (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.c | 46 |
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 |