123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- /*
- * arch/ppc/platforms/adir_pic.c
- *
- * Interrupt controller support for SBS Adirondack
- *
- * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
- * based on the K2 and SCM versions by Matt Porter <mporter@mvista.com>
- */
- #include <linux/stddef.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <linux/pci.h>
- #include <linux/interrupt.h>
- #include <asm/io.h>
- #include <asm/i8259.h>
- #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;
- }
|