aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
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/powerpc/sysdev/mpic.c
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/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c30
1 files changed, 28 insertions, 2 deletions
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)