2 * Amiga Linux interrupt handling code
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
9 #include <linux/init.h>
10 #include <linux/interrupt.h>
11 #include <linux/errno.h>
12 #ifdef CONFIG_GENERIC_HARDIRQS
13 #include <linux/irq.h>
17 #include <asm/traps.h>
18 #include <asm/amigahw.h>
19 #include <asm/amigaints.h>
20 #include <asm/amipcmcia.h>
24 * Enable/disable a particular machine specific interrupt source.
25 * Note that this may affect other interrupts in case of a shared interrupt.
26 * This function should only be called for a _very_ short time to change some
27 * internal data, that may not be changed by the interrupt at the same time.
30 static void amiga_irq_enable(struct irq_data *data)
32 amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
35 static void amiga_irq_disable(struct irq_data *data)
37 amiga_custom.intena = 1 << (data->irq - IRQ_USER);
40 static struct irq_chip amiga_irq_chip = {
42 .irq_enable = amiga_irq_enable,
43 .irq_disable = amiga_irq_disable,
48 * The builtin Amiga hardware interrupt handlers.
51 #ifdef CONFIG_GENERIC_HARDIRQS
52 static void ami_int1(unsigned int irq, struct irq_desc *desc)
54 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
56 /* if serial transmit buffer empty, interrupt */
58 amiga_custom.intreq = IF_TBE;
59 generic_handle_irq(IRQ_AMIGA_TBE);
62 /* if floppy disk transfer complete, interrupt */
63 if (ints & IF_DSKBLK) {
64 amiga_custom.intreq = IF_DSKBLK;
65 generic_handle_irq(IRQ_AMIGA_DSKBLK);
68 /* if software interrupt set, interrupt */
70 amiga_custom.intreq = IF_SOFT;
71 generic_handle_irq(IRQ_AMIGA_SOFT);
75 static void ami_int3(unsigned int irq, struct irq_desc *desc)
77 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
79 /* if a blitter interrupt */
81 amiga_custom.intreq = IF_BLIT;
82 generic_handle_irq(IRQ_AMIGA_BLIT);
85 /* if a copper interrupt */
86 if (ints & IF_COPER) {
87 amiga_custom.intreq = IF_COPER;
88 generic_handle_irq(IRQ_AMIGA_COPPER);
91 /* if a vertical blank interrupt */
92 if (ints & IF_VERTB) {
93 amiga_custom.intreq = IF_VERTB;
94 generic_handle_irq(IRQ_AMIGA_VERTB);
98 static void ami_int4(unsigned int irq, struct irq_desc *desc)
100 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
102 /* if audio 0 interrupt */
103 if (ints & IF_AUD0) {
104 amiga_custom.intreq = IF_AUD0;
105 generic_handle_irq(IRQ_AMIGA_AUD0);
108 /* if audio 1 interrupt */
109 if (ints & IF_AUD1) {
110 amiga_custom.intreq = IF_AUD1;
111 generic_handle_irq(IRQ_AMIGA_AUD1);
114 /* if audio 2 interrupt */
115 if (ints & IF_AUD2) {
116 amiga_custom.intreq = IF_AUD2;
117 generic_handle_irq(IRQ_AMIGA_AUD2);
120 /* if audio 3 interrupt */
121 if (ints & IF_AUD3) {
122 amiga_custom.intreq = IF_AUD3;
123 generic_handle_irq(IRQ_AMIGA_AUD3);
127 static void ami_int5(unsigned int irq, struct irq_desc *desc)
129 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
131 /* if serial receive buffer full interrupt */
133 /* acknowledge of IF_RBF must be done by the serial interrupt */
134 generic_handle_irq(IRQ_AMIGA_RBF);
137 /* if a disk sync interrupt */
138 if (ints & IF_DSKSYN) {
139 amiga_custom.intreq = IF_DSKSYN;
140 generic_handle_irq(IRQ_AMIGA_DSKSYN);
143 #else /* !CONFIG_GENERIC_HARDIRQS */
144 static irqreturn_t ami_int1(int irq, void *dev_id)
146 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
148 /* if serial transmit buffer empty, interrupt */
150 amiga_custom.intreq = IF_TBE;
151 generic_handle_irq(IRQ_AMIGA_TBE);
154 /* if floppy disk transfer complete, interrupt */
155 if (ints & IF_DSKBLK) {
156 amiga_custom.intreq = IF_DSKBLK;
157 generic_handle_irq(IRQ_AMIGA_DSKBLK);
160 /* if software interrupt set, interrupt */
161 if (ints & IF_SOFT) {
162 amiga_custom.intreq = IF_SOFT;
163 generic_handle_irq(IRQ_AMIGA_SOFT);
168 static irqreturn_t ami_int3(int irq, void *dev_id)
170 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
172 /* if a blitter interrupt */
173 if (ints & IF_BLIT) {
174 amiga_custom.intreq = IF_BLIT;
175 generic_handle_irq(IRQ_AMIGA_BLIT);
178 /* if a copper interrupt */
179 if (ints & IF_COPER) {
180 amiga_custom.intreq = IF_COPER;
181 generic_handle_irq(IRQ_AMIGA_COPPER);
184 /* if a vertical blank interrupt */
185 if (ints & IF_VERTB) {
186 amiga_custom.intreq = IF_VERTB;
187 generic_handle_irq(IRQ_AMIGA_VERTB);
192 static irqreturn_t ami_int4(int irq, void *dev_id)
194 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
196 /* if audio 0 interrupt */
197 if (ints & IF_AUD0) {
198 amiga_custom.intreq = IF_AUD0;
199 generic_handle_irq(IRQ_AMIGA_AUD0);
202 /* if audio 1 interrupt */
203 if (ints & IF_AUD1) {
204 amiga_custom.intreq = IF_AUD1;
205 generic_handle_irq(IRQ_AMIGA_AUD1);
208 /* if audio 2 interrupt */
209 if (ints & IF_AUD2) {
210 amiga_custom.intreq = IF_AUD2;
211 generic_handle_irq(IRQ_AMIGA_AUD2);
214 /* if audio 3 interrupt */
215 if (ints & IF_AUD3) {
216 amiga_custom.intreq = IF_AUD3;
217 generic_handle_irq(IRQ_AMIGA_AUD3);
222 static irqreturn_t ami_int5(int irq, void *dev_id)
224 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
226 /* if serial receive buffer full interrupt */
228 /* acknowledge of IF_RBF must be done by the serial interrupt */
229 generic_handle_irq(IRQ_AMIGA_RBF);
232 /* if a disk sync interrupt */
233 if (ints & IF_DSKSYN) {
234 amiga_custom.intreq = IF_DSKSYN;
235 generic_handle_irq(IRQ_AMIGA_DSKSYN);
239 #endif /* !CONFIG_GENERIC_HARDIRQS */
243 * void amiga_init_IRQ(void)
249 * This function should be called during kernel startup to initialize
250 * the amiga IRQ handling routines.
253 void __init amiga_init_IRQ(void)
255 #ifdef CONFIG_GENERIC_HARDIRQS
256 m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
259 irq_set_chained_handler(IRQ_AUTO_1, ami_int1);
260 irq_set_chained_handler(IRQ_AUTO_3, ami_int3);
261 irq_set_chained_handler(IRQ_AUTO_4, ami_int4);
262 irq_set_chained_handler(IRQ_AUTO_5, ami_int5);
263 #else /* !CONFIG_GENERIC_HARDIRQS */
264 if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
265 pr_err("Couldn't register int%d\n", 1);
266 if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
267 pr_err("Couldn't register int%d\n", 3);
268 if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
269 pr_err("Couldn't register int%d\n", 4);
270 if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
271 pr_err("Couldn't register int%d\n", 5);
273 m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
275 #endif /* !CONFIG_GENERIC_HARDIRQS */
277 /* turn off PCMCIA interrupts */
278 if (AMIGAHW_PRESENT(PCMCIA))
279 gayle.inten = GAYLE_IRQ_IDE;
281 /* turn off all interrupts and enable the master interrupt bit */
282 amiga_custom.intena = 0x7fff;
283 amiga_custom.intreq = 0x7fff;
284 amiga_custom.intena = IF_SETCLR | IF_INTEN;
286 cia_init_IRQ(&ciaa_base);
287 cia_init_IRQ(&ciab_base);