Commit 6c4f928b authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc32: Add openpic_hookup_cascade()

From: Tom Rini <trini@kernel.crashing.org>

This patch adds openpic_hookup_cascade(offset, name, handler) which allows for
an arbitrary interrupt controller to be hooked up as a cascade to the openpic.
 This also allows for platforms to just not have a cascaded controller.
parent 9be15f90
......@@ -407,6 +407,9 @@ void __init chrp_init_IRQ(void)
OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
openpic_init(NUM_8259_INTERRUPTS);
/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
i8259_irq);
for (i = 0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
......
......@@ -208,6 +208,9 @@ lopec_init_IRQ(void)
openpic_set_sources(19, 1, OpenPIC_Addr + 0x110C0);
openpic_init(NUM_8259_INTERRUPTS);
/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
&i8259_irq);
/* Map i8259 interrupts */
for(i = 0; i < NUM_8259_INTERRUPTS; i++)
......
......@@ -30,9 +30,6 @@
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/irq.h>
#if 0
#include <linux/ide.h>
#endif
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/serial.h>
......@@ -385,6 +382,8 @@ mcpn765_init_IRQ(void)
ppc_md.progress("init_irq: enter", 0);
openpic_init(NUM_8259_INTERRUPTS);
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
i8259_irq);
for(i=0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
......
......@@ -138,6 +138,7 @@ mvme5100_init_IRQ(void)
#ifdef CONFIG_MVME5100_IPMC761_PRESENT
openpic_init(1, NUM_8259_INTERRUPTS, NULL, -1);
openpic_hookup_cascade(NUM_8259_INTERRUPTS,"82c59 cascade",&i8259_irq);
for(i=0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
......
......@@ -672,6 +672,8 @@ static void __init pplus_init_IRQ(void)
openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
openpic_init(NUM_8259_INTERRUPTS);
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
i8259_irq);
ppc_md.get_irq = openpic_get_irq;
}
......
......@@ -856,8 +856,12 @@ prep_init_IRQ(void)
int i;
unsigned int pci_viddid, pci_did;
if (OpenPIC_Addr != NULL)
if (OpenPIC_Addr != NULL) {
openpic_init(NUM_8259_INTERRUPTS);
/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
i8259_irq);
}
for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
irq_desc[i].handler = &i8259_pic;
/* If we have a Raven PCI bridge or a Hawk PCI bridge / Memory
......
......@@ -444,6 +444,8 @@ sandpoint_init_IRQ(void)
openpic_set_sources(0, 16, OpenPIC_Addr + 0x10200);
openpic_init(NUM_8259_INTERRUPTS);
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
i8259_irq);
/*
* openpic_init() has set up irq_desc[16-31] to be openpic
......
......@@ -39,7 +39,7 @@ obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \
obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o
obj-$(CONFIG_EV64260) += gt64260_common.o gt64260_pic.o \
indirect_pci.o todc_time.o pci_auto.o
obj-$(CONFIG_GEMINI) += open_pic.o i8259.o indirect_pci.o
obj-$(CONFIG_GEMINI) += open_pic.o indirect_pci.o
obj-$(CONFIG_K2) += i8259.o indirect_pci.o todc_time.o \
pci_auto.o
obj-$(CONFIG_LOPEC) += pci_auto.o open_pic.o i8259.o todc_time.o
......
......@@ -48,6 +48,8 @@ static u_int NumProcessors;
static u_int NumSources;
static int open_pic_irq_offset;
static volatile OpenPIC_Source *ISR[NR_IRQS];
static int openpic_cascade_irq = -1;
static int (*openpic_cascade_fn)(struct pt_regs *);
/* Global Operations */
static void openpic_disable_8259_pass_through(void);
......@@ -416,13 +418,6 @@ void __init openpic_init(int offset)
/* Initialize the spurious interrupt */
if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
openpic_set_spurious(OPENPIC_VEC_SPURIOUS+offset);
/* Initialize the cascade */
if (offset) {
if (request_irq(offset, no_action, SA_INTERRUPT,
"82c59 cascade", NULL))
printk("Unable to get OpenPIC IRQ 0 for cascade\n");
}
openpic_disable_8259_pass_through();
#ifdef CONFIG_EPIC_SERIAL_MODE
openpic_eicr_set_clk(7); /* Slowest value until we know better */
......@@ -682,6 +677,19 @@ openpic_init_nmi_irq(u_int irq)
*
*/
/*
* Hookup a cascade to the OpenPIC.
*/
void __init
openpic_hookup_cascade(u_int irq, char *name,
int (*cascade_fn)(struct pt_regs *))
{
openpic_cascade_irq = irq;
openpic_cascade_fn = cascade_fn;
if (request_irq(irq, no_action, SA_INTERRUPT, name, NULL))
printk("Unable to get OpenPIC IRQ %d for cascade\n",
irq - open_pic_irq_offset);
}
/*
* Enable/disable an external interrupt source
......@@ -841,14 +849,19 @@ openpic_get_irq(struct pt_regs *regs)
int irq = openpic_irq();
/*
* This needs to be cleaned up. We don't necessarily have
* an i8259 cascaded or even a cascade.
* Check for the cascade interrupt and call the cascaded
* interrupt controller function (usually i8259_irq) if so.
* This should move to irq.c eventually. -- paulus
*/
if (open_pic_irq_offset && irq == open_pic_irq_offset) {
/* Get the IRQ from the cascade. */
irq = i8259_irq(regs);
openpic_eoi();
} else if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset)
if (irq == openpic_cascade_irq && openpic_cascade_fn != NULL) {
int cirq = openpic_cascade_fn(regs);
/* Allow for the cascade being shared with other devices */
if (cirq != -1) {
irq = cirq;
openpic_eoi();
}
} else if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset)
irq = -1;
return irq;
}
......
......@@ -41,6 +41,8 @@ extern void* OpenPIC_Addr;
extern void openpic_set_sources(int first_irq, int num_irqs, void *isr);
extern void openpic_init(int linux_irq_offset);
extern void openpic_init_nmi_irq(u_int irq);
extern void openpic_hookup_cascade(u_int irq, char *name,
int (*cascade_fn)(struct pt_regs *));
extern u_int openpic_irq(void);
extern void openpic_eoi(void);
extern void openpic_request_IPIs(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment