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>
This commit is contained in:
Kyle Moffett
2011-12-02 06:28:07 +00:00
committed by Benjamin Herrenschmidt
parent c51242e708
commit 09dc34a95b
3 changed files with 33 additions and 56 deletions

View File

@ -1111,6 +1111,22 @@ static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
return 0;
}
/* IRQ handler for a secondary MPIC cascaded from another IRQ controller */
static void mpic_cascade(unsigned int irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct mpic *mpic = irq_desc_get_handler_data(desc);
unsigned int virq;
BUG_ON(!(mpic->flags & MPIC_SECONDARY));
virq = mpic_get_one_irq(mpic);
if (virq != NO_IRQ)
generic_handle_irq(virq);
chip->irq_eoi(&desc->irq_data);
}
static struct irq_host_ops mpic_host_ops = {
.match = mpic_host_match,
.map = mpic_host_map,
@ -1402,8 +1418,7 @@ void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
void __init mpic_init(struct mpic *mpic)
{
int i;
int cpu;
int i, cpu;
BUG_ON(mpic->num_sources == 0);
@ -1488,6 +1503,17 @@ void __init mpic_init(struct mpic *mpic)
GFP_KERNEL);
BUG_ON(mpic->save_data == NULL);
#endif
/* Check if this MPIC is chained from a parent interrupt controller */
if (mpic->flags & MPIC_SECONDARY) {
int virq = irq_of_parse_and_map(mpic->node, 0);
if (virq != NO_IRQ) {
printk(KERN_INFO "%s: hooking up to IRQ %d\n",
mpic->node->full_name, virq);
irq_set_handler_data(virq, mpic);
irq_set_chained_handler(virq, &mpic_cascade);
}
}
}
void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)