/* * arch/ppc/platforms/adir_pic.c * * Interrupt controller support for SBS Adirondack * * By Michael Sokolov * based on the K2 and SCM versions by Matt Porter */ #include #include #include #include #include #include #include #include "adir.h" static void adir_onboard_pic_enable(unsigned int irq); static void adir_onboard_pic_disable(unsigned int irq); __init static void adir_onboard_pic_init(void) { volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK; /* Disable all Adirondack onboard interrupts */ out_be16(maskreg, 0xFFFF); } static int adir_onboard_pic_get_irq(void) { volatile u_short *statreg = (volatile u_short *) ADIR_PROCA_INT_STAT; int irq; u_short int_status, int_test; int_status = in_be16(statreg); for (irq = 0, int_test = 1; irq < 16; irq++, int_test <<= 1) { if (int_status & int_test) break; } if (irq == 16) return -1; return (irq+16); } static void adir_onboard_pic_enable(unsigned int irq) { volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK; /* Change irq to Adirondack onboard native value */ irq -= 16; /* Enable requested irq number */ out_be16(maskreg, in_be16(maskreg) & ~(1 << irq)); } static void adir_onboard_pic_disable(unsigned int irq) { volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK; /* Change irq to Adirondack onboard native value */ irq -= 16; /* Disable requested irq number */ out_be16(maskreg, in_be16(maskreg) | (1 << irq)); } static struct hw_interrupt_type adir_onboard_pic = { " ADIR PIC ", NULL, NULL, adir_onboard_pic_enable, /* unmask */ adir_onboard_pic_disable, /* mask */ adir_onboard_pic_disable, /* mask and ack */ NULL, NULL }; static struct irqaction noop_action = { .handler = no_action, .flags = SA_INTERRUPT, .mask = CPU_MASK_NONE, .name = "82c59 primary cascade", }; /* * Linux interrupt values are assigned as follows: * * 0-15 VT82C686 8259 interrupts * 16-31 Adirondack CPLD interrupts */ __init void adir_init_IRQ(void) { int i; /* Initialize the cascaded 8259's on the VT82C686 */ for (i=0; i<16; i++) irq_desc[i].handler = &i8259_pic; i8259_init(NULL); /* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */ for (i=16; i<32; i++) irq_desc[i].handler = &adir_onboard_pic; adir_onboard_pic_init(); /* Enable 8259 interrupt cascade */ setup_irq(ADIR_IRQ_VT82C686_INTR, &noop_action); } int adir_get_irq(struct pt_regs *regs) { int irq; if ((irq = adir_onboard_pic_get_irq()) < 0) return irq; if (irq == ADIR_IRQ_VT82C686_INTR) irq = i8259_irq(regs); return irq; }