ppc64: Add support for PowerMac G5 interrupts

parent 3f566849
......@@ -67,7 +67,7 @@
void chrp_progress(char *, unsigned short);
extern void openpic_init_IRQ(void);
extern void pSeries_init_openpic(void);
extern void find_and_init_phbs(void);
extern void pSeries_final_fixup(void);
......@@ -257,7 +257,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.setup_residual = NULL;
ppc_md.get_cpuinfo = chrp_get_cpuinfo;
if(naca->interrupt_controller == IC_OPEN_PIC) {
ppc_md.init_IRQ = openpic_init_IRQ;
ppc_md.init_IRQ = pSeries_init_openpic;
ppc_md.get_irq = openpic_get_irq;
} else {
ppc_md.init_IRQ = xics_init_IRQ;
......
......@@ -34,7 +34,42 @@ static volatile struct OpenPIC *OpenPIC = NULL;
u_int OpenPIC_NumInitSenses __initdata = 0;
u_char *OpenPIC_InitSenses __initdata = NULL;
void find_ISUs(void);
/*
* Local (static) OpenPIC Operations
*/
/* Global Operations */
static void openpic_reset(void);
static void openpic_enable_8259_pass_through(void);
static void openpic_disable_8259_pass_through(void);
static u_int openpic_irq(void);
static void openpic_eoi(void);
static u_int openpic_get_priority(void);
static void openpic_set_priority(u_int pri);
static u_int openpic_get_spurious(void);
static void openpic_set_spurious(u_int vector);
#ifdef CONFIG_SMP
/* Interprocessor Interrupts */
static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
static irqreturn_t openpic_ipi_action(int cpl, void *dev_id,
struct pt_regs *regs);
#endif
/* Timer Interrupts */
static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
static void openpic_maptimer(u_int timer, u_int cpumask);
/* Interrupt Sources */
static void openpic_enable_irq(u_int irq);
static void openpic_disable_irq(u_int irq);
static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
int is_level);
static void openpic_mapirq(u_int irq, u_int cpumask);
static void openpic_set_sense(u_int irq, int sense);
static void find_ISUs(void);
static u_int NumProcessors;
static u_int NumSources;
......@@ -130,7 +165,7 @@ unsigned int openpic_vec_spurious;
#define GET_ISU(source) ISU[(source) >> 4][(source) & 0xf]
void __init openpic_init_IRQ(void)
void __init pSeries_init_openpic(void)
{
struct device_node *np;
int i;
......@@ -359,9 +394,12 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
}
/* Init all external sources */
for (i = 1; i < NumSources; i++) {
for (i = 0; i < NumSources; i++) {
int pri, sense;
/* skip cascade if any */
if (offset && i == 0)
continue;
/* the bootloader may have left it enabled (bad !) */
openpic_disable_irq(i+offset);
......@@ -396,6 +434,9 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
*/
static int __init openpic_setup_i8259(void)
{
if (systemcfg->platform == PLATFORM_POWERMAC)
return 0;
if (naca->interrupt_controller == IC_OPEN_PIC) {
/* Initialize the cascade */
if (request_irq(NUM_8259_INTERRUPTS, no_action, SA_INTERRUPT,
......@@ -419,6 +460,14 @@ void openpic_setup_ISU(int isu_num, unsigned long addr)
void find_ISUs(void)
{
/* For PowerMac, setup ISUs on base openpic */
if (systemcfg->platform == PLATFORM_POWERMAC) {
int i;
for (i=0; i<128; i+=0x10) {
ISU[i>>4] = &((struct OpenPIC *)OpenPIC_Addr)->Source[i];
NumISUs++;
}
}
/* Use /interrupt-controller/reg and
* /interrupt-controller/interrupt-ranges from OF device tree
* the ISU array is setup in chrp_pci.c in ibm_add_bridges
......@@ -429,11 +478,22 @@ void find_ISUs(void)
/* basically each ISU is a bus, and this assumes that
* open_pic_isu_count interrupts per bus are possible
* ISU == Interrupt Source
*
* On G5, we keep the original NumSources provided by the controller,
* it's below 128, so we have room to stuff the IPIs and timers like darwin
* does. We put the spurrious vector up at 0xff though.
*/
NumSources = NumISUs * 0x10;
openpic_vec_ipi = NumSources + open_pic_irq_offset;
openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI;
openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS;
if (systemcfg->platform == PLATFORM_POWERMAC) {
openpic_vec_ipi = NumSources;
openpic_vec_timer = openpic_vec_ipi + 4;
openpic_vec_spurious = 0xff;
} else {
NumSources = NumISUs * 0x10;
openpic_vec_ipi = NumSources + open_pic_irq_offset;
openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI;
openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS;
}
}
static inline void openpic_reset(void)
......@@ -767,8 +827,7 @@ static inline void openpic_set_sense(u_int irq, int sense)
static void openpic_end_irq(unsigned int irq_nr)
{
if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0)
openpic_eoi();
openpic_eoi();
}
static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask)
......@@ -807,9 +866,7 @@ int openpic_get_irq(struct pt_regs *regs)
int irq = openpic_irq();
/* Management of the cascade should be moved out of here */
if (open_pic_irq_offset && irq == open_pic_irq_offset)
{
if (open_pic_irq_offset && irq == open_pic_irq_offset) {
/*
* This magic address generates a PCI IACK cycle.
*/
......
......@@ -40,6 +40,8 @@ extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
extern inline int openpic_to_irq(int irq)
{
if (systemcfg->platform == PLATFORM_POWERMAC)
return irq;
return irq += NUM_8259_INTERRUPTS;
}
/*extern int open_pic_irq_offset;*/
......
......@@ -279,40 +279,6 @@ extern volatile struct OpenPIC *OpenPIC;
#define Vector_Priority _Vector_Priority.Reg
#define Destination _Destination.Reg
/*
* Local (static) OpenPIC Operations
*/
/* Global Operations */
static void openpic_reset(void);
static void openpic_enable_8259_pass_through(void);
static void openpic_disable_8259_pass_through(void);
static u_int openpic_irq(void);
static void openpic_eoi(void);
static u_int openpic_get_priority(void);
static void openpic_set_priority(u_int pri);
static u_int openpic_get_spurious(void);
static void openpic_set_spurious(u_int vector);
#ifdef CONFIG_SMP
/* Interprocessor Interrupts */
static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
static irqreturn_t openpic_ipi_action(int cpl, void *dev_id,
struct pt_regs *regs);
#endif
/* Timer Interrupts */
static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
static void openpic_maptimer(u_int timer, u_int cpumask);
/* Interrupt Sources */
static void openpic_enable_irq(u_int irq);
static void openpic_disable_irq(u_int irq);
static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
int is_level);
static void openpic_mapirq(u_int irq, u_int cpumask);
static void openpic_set_sense(u_int irq, int sense);
#endif /* __KERNEL__ */
......
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