MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / arch / ppc / platforms / adir_pic.c
blobecdf1237bfbf58a080f2bd035c7c7c3ca24e4396
1 /*
2 * arch/ppc/platforms/adir_pic.c
4 * Interrupt controller support for SBS Adirondack
6 * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
7 * based on the K2 and SCM versions by Matt Porter <mporter@mvista.com>
8 */
10 #include <linux/stddef.h>
11 #include <linux/init.h>
12 #include <linux/sched.h>
13 #include <linux/pci.h>
14 #include <linux/irq.h>
16 #include <asm/io.h>
17 #include <asm/i8259.h>
18 #include "adir.h"
20 static void adir_onboard_pic_enable(unsigned int irq);
21 static void adir_onboard_pic_disable(unsigned int irq);
23 static void
24 no_action(int cpl, void *dev_id, struct pt_regs *regs)
28 __init static void
29 adir_onboard_pic_init(void)
31 volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
33 /* Disable all Adirondack onboard interrupts */
34 out_be16(maskreg, 0xFFFF);
37 static int
38 adir_onboard_pic_get_irq(void)
40 volatile u_short *statreg = (volatile u_short *) ADIR_PROCA_INT_STAT;
41 int irq;
42 u_short int_status, int_test;
44 int_status = in_be16(statreg);
45 for (irq = 0, int_test = 1; irq < 16; irq++, int_test <<= 1) {
46 if (int_status & int_test)
47 break;
50 if (irq == 16)
51 return -1;
53 return (irq+16);
56 static void
57 adir_onboard_pic_enable(unsigned int irq)
59 volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
61 /* Change irq to Adirondack onboard native value */
62 irq -= 16;
64 /* Enable requested irq number */
65 out_be16(maskreg, in_be16(maskreg) & ~(1 << irq));
68 static void
69 adir_onboard_pic_disable(unsigned int irq)
71 volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
73 /* Change irq to Adirondack onboard native value */
74 irq -= 16;
76 /* Disable requested irq number */
77 out_be16(maskreg, in_be16(maskreg) | (1 << irq));
80 static struct hw_interrupt_type adir_onboard_pic = {
81 " ADIR PIC ",
82 NULL,
83 NULL,
84 adir_onboard_pic_enable, /* unmask */
85 adir_onboard_pic_disable, /* mask */
86 adir_onboard_pic_disable, /* mask and ack */
87 NULL,
88 NULL
92 * Linux interrupt values are assigned as follows:
94 * 0-15 VT82C686 8259 interrupts
95 * 16-31 Adirondack CPLD interrupts
97 __init void
98 adir_init_IRQ(void)
100 int i;
102 /* Initialize the cascaded 8259's on the VT82C686 */
103 for (i=0; i<16; i++)
104 irq_desc[i].handler = &i8259_pic;
105 i8259_init(NULL);
107 /* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */
108 for (i=16; i<32; i++)
109 irq_desc[i].handler = &adir_onboard_pic;
110 adir_onboard_pic_init();
112 /* Enable 8259 interrupt cascade */
113 request_irq(ADIR_IRQ_VT82C686_INTR,
114 no_action,
115 SA_INTERRUPT,
116 "82c59 primary cascade",
117 NULL);
121 adir_get_irq(struct pt_regs *regs)
123 int irq;
125 if ((irq = adir_onboard_pic_get_irq()) < 0)
126 return irq;
128 if (irq == ADIR_IRQ_VT82C686_INTR)
129 irq = i8259_irq(regs);
131 return irq;