[PATCH] SECURITY must depend on SYSFS
[sfrench/cifs-2.6.git] / arch / ppc / platforms / adir_pic.c
1 /*
2  * arch/ppc/platforms/adir_pic.c
3  *
4  * Interrupt controller support for SBS Adirondack
5  *
6  * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
7  * based on the K2 and SCM versions by Matt Porter <mporter@mvista.com>
8  */
9
10 #include <linux/stddef.h>
11 #include <linux/init.h>
12 #include <linux/sched.h>
13 #include <linux/pci.h>
14 #include <linux/interrupt.h>
15
16 #include <asm/io.h>
17 #include <asm/i8259.h>
18 #include "adir.h"
19
20 static void adir_onboard_pic_enable(unsigned int irq);
21 static void adir_onboard_pic_disable(unsigned int irq);
22
23 __init static void
24 adir_onboard_pic_init(void)
25 {
26         volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
27
28         /* Disable all Adirondack onboard interrupts */
29         out_be16(maskreg, 0xFFFF);
30 }
31
32 static int
33 adir_onboard_pic_get_irq(void)
34 {
35         volatile u_short *statreg = (volatile u_short *) ADIR_PROCA_INT_STAT;
36         int irq;
37         u_short int_status, int_test;
38
39         int_status = in_be16(statreg);
40         for (irq = 0, int_test = 1; irq < 16; irq++, int_test <<= 1) {
41                 if (int_status & int_test)
42                         break;
43         }
44
45         if (irq == 16)
46                 return -1;
47
48         return (irq+16);
49 }
50
51 static void
52 adir_onboard_pic_enable(unsigned int irq)
53 {
54         volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
55
56         /* Change irq to Adirondack onboard native value */
57         irq -= 16;
58
59         /* Enable requested irq number */
60         out_be16(maskreg, in_be16(maskreg) & ~(1 << irq));
61 }
62
63 static void
64 adir_onboard_pic_disable(unsigned int irq)
65 {
66         volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
67
68         /* Change irq to Adirondack onboard native value */
69         irq -= 16;
70
71         /* Disable requested irq number */
72         out_be16(maskreg, in_be16(maskreg) | (1 << irq));
73 }
74
75 static struct hw_interrupt_type adir_onboard_pic = {
76         " ADIR PIC ",
77         NULL,
78         NULL,
79         adir_onboard_pic_enable,                /* unmask */
80         adir_onboard_pic_disable,               /* mask */
81         adir_onboard_pic_disable,               /* mask and ack */
82         NULL,
83         NULL
84 };
85
86 static struct irqaction noop_action = {
87         .handler        = no_action,
88         .flags          = SA_INTERRUPT,
89         .mask           = CPU_MASK_NONE,
90         .name           = "82c59 primary cascade",
91 };
92
93 /*
94  * Linux interrupt values are assigned as follows:
95  *
96  *      0-15            VT82C686 8259 interrupts
97  *      16-31           Adirondack CPLD interrupts
98  */
99 __init void
100 adir_init_IRQ(void)
101 {
102         int     i;
103
104         /* Initialize the cascaded 8259's on the VT82C686 */
105         for (i=0; i<16; i++)
106                 irq_desc[i].handler = &i8259_pic;
107         i8259_init(NULL);
108
109         /* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */
110         for (i=16; i<32; i++)
111                 irq_desc[i].handler = &adir_onboard_pic;
112         adir_onboard_pic_init();
113
114         /* Enable 8259 interrupt cascade */
115         setup_irq(ADIR_IRQ_VT82C686_INTR, &noop_action);
116 }
117
118 int
119 adir_get_irq(struct pt_regs *regs)
120 {
121         int     irq;
122
123         if ((irq = adir_onboard_pic_get_irq()) < 0)
124                 return irq;
125
126         if (irq == ADIR_IRQ_VT82C686_INTR)
127                 irq = i8259_irq(regs);
128
129         return irq;
130 }