aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/powerpc/fsl/mpic.txt7
-rw-r--r--arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi1
-rw-r--r--arch/powerpc/sysdev/mpic.c46
3 files changed, 34 insertions, 20 deletions
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt b/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
index b393ccf1e9f..dc5744636a5 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
@@ -70,6 +70,13 @@ PROPERTIES
70 If present the MPIC will be assumed to only be able to route 70 If present the MPIC will be assumed to only be able to route
71 non-IPI interrupts to a single CPU at a time (EG: Freescale MPIC). 71 non-IPI interrupts to a single CPU at a time (EG: Freescale MPIC).
72 72
73 - last-interrupt-source
74 Usage: optional
75 Value type: <u32>
76 Some MPICs do not correctly report the number of hardware sources
77 in the global feature registers. If specified, this field will
78 override the value read from MPIC_GREG_FEATURE_LAST_SRC.
79
73INTERRUPT SPECIFIER DEFINITION 80INTERRUPT SPECIFIER DEFINITION
74 81
75 Interrupt specifiers consists of 4 cells encoded as 82 Interrupt specifiers consists of 4 cells encoded as
diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
index 658bd81982c..fdedf7b1fe0 100644
--- a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
+++ b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
@@ -41,6 +41,7 @@ mpic: pic@40000 {
41 device_type = "open-pic"; 41 device_type = "open-pic";
42 big-endian; 42 big-endian;
43 single-cpu-affinity; 43 single-cpu-affinity;
44 last-interrupt-source = <255>;
44}; 45};
45 46
46timer@41100 { 47timer@41100 {
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index cbffeb742d6..90171d447c3 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