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/powerpc/sysdev/mpic.c | |
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/powerpc/sysdev/mpic.c')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 30 |
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 */ | ||
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) |