ieee1394: raw1394: arm functions slept in atomic context
[pandora-kernel.git] / arch / sh / boards / harp / irq.c
1 /* 
2  * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3  *
4  * May be copied or modified under the terms of the GNU General Public
5  * License.  See linux/COPYING for more information.                            
6  *
7  * Looks after interrupts on the HARP board.
8  *
9  * Bases on the IPR irq system
10  */
11
12 #include <linux/init.h>
13 #include <linux/irq.h>
14
15 #include <asm/system.h>
16 #include <asm/io.h>
17 #include <asm/harp/harp.h>
18
19
20 #define NUM_EXTERNAL_IRQS 16
21
22 // Early versions of the STB1 Overdrive required this nasty frig
23 //#define INVERT_INTMASK_WRITES
24
25 static void enable_harp_irq(unsigned int irq);
26 static void disable_harp_irq(unsigned int irq);
27
28 /* shutdown is same as "disable" */
29 #define shutdown_harp_irq disable_harp_irq
30
31 static void mask_and_ack_harp(unsigned int);
32 static void end_harp_irq(unsigned int irq);
33
34 static unsigned int startup_harp_irq(unsigned int irq)
35 {
36         enable_harp_irq(irq);
37         return 0;               /* never anything pending */
38 }
39
40 static struct hw_interrupt_type harp_irq_type = {
41         .typename = "Harp-IRQ",
42         .startup = startup_harp_irq,
43         .shutdown = shutdown_harp_irq,
44         .enable = enable_harp_irq,
45         .disable = disable_harp_irq,
46         .ack = mask_and_ack_harp,
47         .end = end_harp_irq
48 };
49
50 static void disable_harp_irq(unsigned int irq)
51 {
52         unsigned val, flags;
53         unsigned maskReg;
54         unsigned mask;
55         int pri;
56
57         if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
58                 return;
59
60         pri = 15 - irq;
61
62         if (pri < 8) {
63                 maskReg = EPLD_INTMASK0;
64         } else {
65                 maskReg = EPLD_INTMASK1;
66                 pri -= 8;
67         }
68
69         local_irq_save(flags);
70         mask = ctrl_inl(maskReg);
71         mask &= (~(1 << pri));
72 #if defined(INVERT_INTMASK_WRITES)
73         mask ^= 0xff;
74 #endif
75         ctrl_outl(mask, maskReg);
76         local_irq_restore(flags);
77 }
78
79 static void enable_harp_irq(unsigned int irq)
80 {
81         unsigned flags;
82         unsigned maskReg;
83         unsigned mask;
84         int pri;
85
86         if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
87                 return;
88
89         pri = 15 - irq;
90
91         if (pri < 8) {
92                 maskReg = EPLD_INTMASK0;
93         } else {
94                 maskReg = EPLD_INTMASK1;
95                 pri -= 8;
96         }
97
98         local_irq_save(flags);
99         mask = ctrl_inl(maskReg);
100
101
102         mask |= (1 << pri);
103
104 #if defined(INVERT_INTMASK_WRITES)
105         mask ^= 0xff;
106 #endif
107         ctrl_outl(mask, maskReg);
108
109         local_irq_restore(flags);
110 }
111
112 /* This functions sets the desired irq handler to be an overdrive type */
113 static void __init make_harp_irq(unsigned int irq)
114 {
115         disable_irq_nosync(irq);
116         irq_desc[irq].chip = &harp_irq_type;
117         disable_harp_irq(irq);
118 }
119
120 static void mask_and_ack_harp(unsigned int irq)
121 {
122         disable_harp_irq(irq);
123 }
124
125 static void end_harp_irq(unsigned int irq)
126 {
127         enable_harp_irq(irq);
128 }
129
130 void __init init_harp_irq(void)
131 {
132         int i;
133
134 #if !defined(INVERT_INTMASK_WRITES)
135         // On the harp these are set to enable an interrupt
136         ctrl_outl(0x00, EPLD_INTMASK0);
137         ctrl_outl(0x00, EPLD_INTMASK1);
138 #else
139         // On the Overdrive the data is inverted before being stored in the reg
140         ctrl_outl(0xff, EPLD_INTMASK0);
141         ctrl_outl(0xff, EPLD_INTMASK1);
142 #endif
143
144         for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
145                 make_harp_irq(i);
146         }
147 }