diff options
author | Kyle Moffett <Kyle.D.Moffett@boeing.com> | 2011-12-02 01:28:07 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-12-06 21:43:09 -0500 |
commit | 09dc34a95bfbc6062e1e7de0b96175480924aea8 (patch) | |
tree | d21a67d125278304324415ae2b7c23aa056584dc /arch | |
parent | c51242e7080d2265761de309cdea222d7e27bdfe (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.c | 23 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/pic.c | 36 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 30 |
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 | } |
185 | machine_subsys_initcall(cell, cell_publish_devices); | 185 | machine_subsys_initcall(cell, cell_publish_devices); |
186 | 186 | ||
187 | static 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 | |||
200 | static void __init mpic_init_IRQ(void) | 187 | static 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 | ||
467 | static 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 | |||
479 | static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) | 467 | static 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 */ | ||
1115 | static 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 | |||
1114 | static struct irq_host_ops mpic_host_ops = { | 1130 | static 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 | ||
1403 | void __init mpic_init(struct mpic *mpic) | 1419 | void __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 | ||
1493 | void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) | 1519 | void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) |