aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorKyle Moffett <Kyle.D.Moffett@boeing.com>2011-12-02 01:28:07 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-12-06 21:43:09 -0500
commit09dc34a95bfbc6062e1e7de0b96175480924aea8 (patch)
treed21a67d125278304324415ae2b7c23aa056584dc /arch
parentc51242e7080d2265761de309cdea222d7e27bdfe (diff)
powerpc/mpic: Add in-core support for cascaded MPICs
The Cell and PowerMac platforms use virtually identical cascaded-IRQ setup code, so just merge it into the core. Ideally this code would trigger automatically when an MPIC device-node specifies an "interrupts" property, perhaps even enabling MPIC_SECONDARY along the way. Unfortunately, Benjamin Herrenschmidt has had bad experiences in the past with the quality of Apple PowerMac device-trees, so to be safe we will only try to parse out an IRQ if the MPIC_SECONDARY flag is set by the caller. Signed-off-by: Kyle Moffett <Kyle.D.Moffett@boeing.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/setup.c23
-rw-r--r--arch/powerpc/platforms/powermac/pic.c36
-rw-r--r--arch/powerpc/sysdev/mpic.c30
3 files changed, 33 insertions, 56 deletions
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index cd00ca856038..62002a7edfed 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -184,24 +184,10 @@ static int __init cell_publish_devices(void)
184} 184}
185machine_subsys_initcall(cell, cell_publish_devices); 185machine_subsys_initcall(cell, cell_publish_devices);
186 186
187static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
188{
189 struct irq_chip *chip = irq_desc_get_chip(desc);
190 struct mpic *mpic = irq_desc_get_handler_data(desc);
191 unsigned int virq;
192
193 virq = mpic_get_one_irq(mpic);
194 if (virq != NO_IRQ)
195 generic_handle_irq(virq);
196
197 chip->irq_eoi(&desc->irq_data);
198}
199
200static void __init mpic_init_IRQ(void) 187static void __init mpic_init_IRQ(void)
201{ 188{
202 struct device_node *dn; 189 struct device_node *dn;
203 struct mpic *mpic; 190 struct mpic *mpic;
204 unsigned int virq;
205 191
206 for (dn = NULL; 192 for (dn = NULL;
207 (dn = of_find_node_by_name(dn, "interrupt-controller"));) { 193 (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
@@ -215,15 +201,6 @@ static void __init mpic_init_IRQ(void)
215 if (mpic == NULL) 201 if (mpic == NULL)
216 continue; 202 continue;
217 mpic_init(mpic); 203 mpic_init(mpic);
218
219 virq = irq_of_parse_and_map(dn, 0);
220 if (virq == NO_IRQ)
221 continue;
222
223 printk(KERN_INFO "%s : hooking up to IRQ %d\n",
224 dn->full_name, virq);
225 irq_set_handler_data(virq, mpic);
226 irq_set_chained_handler(virq, cell_mpic_cascade);
227 } 204 }
228} 205}
229 206
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index b962101744e5..d8aedf135bb6 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -464,18 +464,6 @@ int of_irq_map_oldworld(struct device_node *device, int index,
464} 464}
465#endif /* CONFIG_PPC32 */ 465#endif /* CONFIG_PPC32 */
466 466
467static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
468{
469 struct irq_chip *chip = irq_desc_get_chip(desc);
470 struct mpic *mpic = irq_desc_get_handler_data(desc);
471 unsigned int cascade_irq = mpic_get_one_irq(mpic);
472
473 if (cascade_irq != NO_IRQ)
474 generic_handle_irq(cascade_irq);
475
476 chip->irq_eoi(&desc->irq_data);
477}
478
479static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) 467static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
480{ 468{
481#if defined(CONFIG_XMON) && defined(CONFIG_PPC32) 469#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
@@ -526,7 +514,6 @@ static int __init pmac_pic_probe_mpic(void)
526{ 514{
527 struct mpic *mpic1, *mpic2; 515 struct mpic *mpic1, *mpic2;
528 struct device_node *np, *master = NULL, *slave = NULL; 516 struct device_node *np, *master = NULL, *slave = NULL;
529 unsigned int cascade;
530 517
531 /* We can have up to 2 MPICs cascaded */ 518 /* We can have up to 2 MPICs cascaded */
532 for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) 519 for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
@@ -562,27 +549,14 @@ static int __init pmac_pic_probe_mpic(void)
562 549
563 of_node_put(master); 550 of_node_put(master);
564 551
565 /* No slave, let's go out */ 552 /* Set up a cascaded controller, if present */
566 if (slave == NULL) 553 if (slave) {
567 return 0; 554 mpic2 = pmac_setup_one_mpic(slave, 0);
568 555 if (mpic2 == NULL)
569 /* Get/Map slave interrupt */ 556 printk(KERN_ERR "Failed to setup slave MPIC\n");
570 cascade = irq_of_parse_and_map(slave, 0);
571 if (cascade == NO_IRQ) {
572 printk(KERN_ERR "Failed to map cascade IRQ\n");
573 return 0;
574 }
575
576 mpic2 = pmac_setup_one_mpic(slave, 0);
577 if (mpic2 == NULL) {
578 printk(KERN_ERR "Failed to setup slave MPIC\n");
579 of_node_put(slave); 557 of_node_put(slave);
580 return 0;
581 } 558 }
582 irq_set_handler_data(cascade, mpic2);
583 irq_set_chained_handler(cascade, pmac_u3_cascade);
584 559
585 of_node_put(slave);
586 return 0; 560 return 0;
587} 561}
588 562
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 76110608543a..4e9ccb1015de 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1111,6 +1111,22 @@ static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
1111 return 0; 1111 return 0;
1112} 1112}
1113 1113
1114/* IRQ handler for a secondary MPIC cascaded from another IRQ controller */
1115static void mpic_cascade(unsigned int irq, struct irq_desc *desc)
1116{
1117 struct irq_chip *chip = irq_desc_get_chip(desc);
1118 struct mpic *mpic = irq_desc_get_handler_data(desc);
1119 unsigned int virq;
1120
1121 BUG_ON(!(mpic->flags & MPIC_SECONDARY));
1122
1123 virq = mpic_get_one_irq(mpic);
1124 if (virq != NO_IRQ)
1125 generic_handle_irq(virq);
1126
1127 chip->irq_eoi(&desc->irq_data);
1128}
1129
1114static struct irq_host_ops mpic_host_ops = { 1130static struct irq_host_ops mpic_host_ops = {
1115 .match = mpic_host_match, 1131 .match = mpic_host_match,
1116 .map = mpic_host_map, 1132 .map = mpic_host_map,
@@ -1402,8 +1418,7 @@ void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
1402 1418
1403void __init mpic_init(struct mpic *mpic) 1419void __init mpic_init(struct mpic *mpic)
1404{ 1420{
1405 int i; 1421 int i, cpu;
1406 int cpu;
1407 1422
1408 BUG_ON(mpic->num_sources == 0); 1423 BUG_ON(mpic->num_sources == 0);
1409 1424
@@ -1488,6 +1503,17 @@ void __init mpic_init(struct mpic *mpic)
1488 GFP_KERNEL); 1503 GFP_KERNEL);
1489 BUG_ON(mpic->save_data == NULL); 1504 BUG_ON(mpic->save_data == NULL);
1490#endif 1505#endif
1506
1507 /* Check if this MPIC is chained from a parent interrupt controller */
1508 if (mpic->flags & MPIC_SECONDARY) {
1509 int virq = irq_of_parse_and_map(mpic->node, 0);
1510 if (virq != NO_IRQ) {
1511 printk(KERN_INFO "%s: hooking up to IRQ %d\n",
1512 mpic->node->full_name, virq);
1513 irq_set_handler_data(virq, mpic);
1514 irq_set_chained_handler(virq, &mpic_cascade);
1515 }
1516 }
1491} 1517}
1492 1518
1493void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) 1519void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)