]> git.karo-electronics.de Git - mv-sheeva.git/blob - arch/m68k/amiga/amiints.c
m68k/irq: Switch irq_chip methods to "struct irq_data *data"
[mv-sheeva.git] / arch / m68k / amiga / amiints.c
1 /*
2  * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file COPYING in the main directory of this archive
6  * for more details.
7  *
8  * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
9  *           this sources where it makes sense (VERTB/PORTS/EXTER) and you must
10  *           be careful that dev_id for this sources is unique since this the
11  *           only possibility to distinguish between different handlers for
12  *           free_irq. irq lists also have different irq flags:
13  *           - IRQ_FLG_FAST: handler is inserted at top of list (after other
14  *                           fast handlers)
15  *           - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
16  *                           they're executed irq level is set to the previous
17  *                           one, but handlers don't need to be reentrant, if
18  *                           reentrance occurred, slow handlers will be just
19  *                           called again.
20  *           The whole interrupt handling for CIAs is moved to cia.c
21  *           /Roman Zippel
22  *
23  * 07/08/99: rewamp of the interrupt handling - we now have two types of
24  *           interrupts, normal and fast handlers, fast handlers being
25  *           marked with IRQF_DISABLED and runs with all other interrupts
26  *           disabled. Normal interrupts disable their own source but
27  *           run with all other interrupt sources enabled.
28  *           PORTS and EXTER interrupts are always shared even if the
29  *           drivers do not explicitly mark this when calling
30  *           request_irq which they really should do.
31  *           This is similar to the way interrupts are handled on all
32  *           other architectures and makes a ton of sense besides
33  *           having the advantage of making it easier to share
34  *           drivers.
35  *           /Jes
36  */
37
38 #include <linux/init.h>
39 #include <linux/interrupt.h>
40 #include <linux/errno.h>
41
42 #include <asm/irq.h>
43 #include <asm/traps.h>
44 #include <asm/amigahw.h>
45 #include <asm/amigaints.h>
46 #include <asm/amipcmcia.h>
47
48 static void amiga_irq_enable(struct irq_data *data);
49 static void amiga_irq_disable(struct irq_data *data);
50 static irqreturn_t ami_int1(int irq, void *dev_id);
51 static irqreturn_t ami_int3(int irq, void *dev_id);
52 static irqreturn_t ami_int4(int irq, void *dev_id);
53 static irqreturn_t ami_int5(int irq, void *dev_id);
54
55 static struct irq_chip amiga_irq_chip = {
56         .name           = "amiga",
57         .irq_enable     = amiga_irq_enable,
58         .irq_disable    = amiga_irq_disable,
59 };
60
61 /*
62  * void amiga_init_IRQ(void)
63  *
64  * Parameters:  None
65  *
66  * Returns:     Nothing
67  *
68  * This function should be called during kernel startup to initialize
69  * the amiga IRQ handling routines.
70  */
71
72 void __init amiga_init_IRQ(void)
73 {
74         if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
75                 pr_err("Couldn't register int%d\n", 1);
76         if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
77                 pr_err("Couldn't register int%d\n", 3);
78         if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
79                 pr_err("Couldn't register int%d\n", 4);
80         if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
81                 pr_err("Couldn't register int%d\n", 5);
82
83         m68k_setup_irq_chip(&amiga_irq_chip, IRQ_USER, AMI_STD_IRQS);
84
85         /* turn off PCMCIA interrupts */
86         if (AMIGAHW_PRESENT(PCMCIA))
87                 gayle.inten = GAYLE_IRQ_IDE;
88
89         /* turn off all interrupts and enable the master interrupt bit */
90         amiga_custom.intena = 0x7fff;
91         amiga_custom.intreq = 0x7fff;
92         amiga_custom.intena = IF_SETCLR | IF_INTEN;
93
94         cia_init_IRQ(&ciaa_base);
95         cia_init_IRQ(&ciab_base);
96 }
97
98 /*
99  * Enable/disable a particular machine specific interrupt source.
100  * Note that this may affect other interrupts in case of a shared interrupt.
101  * This function should only be called for a _very_ short time to change some
102  * internal data, that may not be changed by the interrupt at the same time.
103  */
104
105 static void amiga_irq_enable(struct irq_data *data)
106 {
107         amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
108 }
109
110 static void amiga_irq_disable(struct irq_data *data)
111 {
112         amiga_custom.intena = 1 << (data->irq - IRQ_USER);
113 }
114
115 /*
116  * The builtin Amiga hardware interrupt handlers.
117  */
118
119 static irqreturn_t ami_int1(int irq, void *dev_id)
120 {
121         unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
122
123         /* if serial transmit buffer empty, interrupt */
124         if (ints & IF_TBE) {
125                 amiga_custom.intreq = IF_TBE;
126                 m68k_handle_int(IRQ_AMIGA_TBE);
127         }
128
129         /* if floppy disk transfer complete, interrupt */
130         if (ints & IF_DSKBLK) {
131                 amiga_custom.intreq = IF_DSKBLK;
132                 m68k_handle_int(IRQ_AMIGA_DSKBLK);
133         }
134
135         /* if software interrupt set, interrupt */
136         if (ints & IF_SOFT) {
137                 amiga_custom.intreq = IF_SOFT;
138                 m68k_handle_int(IRQ_AMIGA_SOFT);
139         }
140         return IRQ_HANDLED;
141 }
142
143 static irqreturn_t ami_int3(int irq, void *dev_id)
144 {
145         unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
146
147         /* if a blitter interrupt */
148         if (ints & IF_BLIT) {
149                 amiga_custom.intreq = IF_BLIT;
150                 m68k_handle_int(IRQ_AMIGA_BLIT);
151         }
152
153         /* if a copper interrupt */
154         if (ints & IF_COPER) {
155                 amiga_custom.intreq = IF_COPER;
156                 m68k_handle_int(IRQ_AMIGA_COPPER);
157         }
158
159         /* if a vertical blank interrupt */
160         if (ints & IF_VERTB) {
161                 amiga_custom.intreq = IF_VERTB;
162                 m68k_handle_int(IRQ_AMIGA_VERTB);
163         }
164         return IRQ_HANDLED;
165 }
166
167 static irqreturn_t ami_int4(int irq, void *dev_id)
168 {
169         unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
170
171         /* if audio 0 interrupt */
172         if (ints & IF_AUD0) {
173                 amiga_custom.intreq = IF_AUD0;
174                 m68k_handle_int(IRQ_AMIGA_AUD0);
175         }
176
177         /* if audio 1 interrupt */
178         if (ints & IF_AUD1) {
179                 amiga_custom.intreq = IF_AUD1;
180                 m68k_handle_int(IRQ_AMIGA_AUD1);
181         }
182
183         /* if audio 2 interrupt */
184         if (ints & IF_AUD2) {
185                 amiga_custom.intreq = IF_AUD2;
186                 m68k_handle_int(IRQ_AMIGA_AUD2);
187         }
188
189         /* if audio 3 interrupt */
190         if (ints & IF_AUD3) {
191                 amiga_custom.intreq = IF_AUD3;
192                 m68k_handle_int(IRQ_AMIGA_AUD3);
193         }
194         return IRQ_HANDLED;
195 }
196
197 static irqreturn_t ami_int5(int irq, void *dev_id)
198 {
199         unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
200
201         /* if serial receive buffer full interrupt */
202         if (ints & IF_RBF) {
203                 /* acknowledge of IF_RBF must be done by the serial interrupt */
204                 m68k_handle_int(IRQ_AMIGA_RBF);
205         }
206
207         /* if a disk sync interrupt */
208         if (ints & IF_DSKSYN) {
209                 amiga_custom.intreq = IF_DSKSYN;
210                 m68k_handle_int(IRQ_AMIGA_DSKSYN);
211         }
212         return IRQ_HANDLED;
213 }