diff options
-rw-r--r-- | Documentation/devicetree/bindings/powerpc/fsl/mpic.txt | 7 | ||||
-rw-r--r-- | arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi | 1 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 46 |
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 b393ccf1e9f3..dc5744636a57 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 | |||
73 | INTERRUPT SPECIFIER DEFINITION | 80 | INTERRUPT 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 658bd81982cb..fdedf7b1fe0f 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 | ||
46 | timer@41100 { | 47 | timer@41100 { |
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 |