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 static irqreturn_t ami_int1(int irq, void *dev_id)
53 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
55 /* if serial transmit buffer empty, interrupt */
57 amiga_custom.intreq = IF_TBE;
58 generic_handle_irq(IRQ_AMIGA_TBE);
61 /* if floppy disk transfer complete, interrupt */
62 if (ints & IF_DSKBLK) {
63 amiga_custom.intreq = IF_DSKBLK;
64 generic_handle_irq(IRQ_AMIGA_DSKBLK);
67 /* if software interrupt set, interrupt */
69 amiga_custom.intreq = IF_SOFT;
70 generic_handle_irq(IRQ_AMIGA_SOFT);
75 static irqreturn_t ami_int3(int irq, void *dev_id)
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);
99 static irqreturn_t ami_int4(int irq, void *dev_id)
101 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
103 /* if audio 0 interrupt */
104 if (ints & IF_AUD0) {
105 amiga_custom.intreq = IF_AUD0;
106 generic_handle_irq(IRQ_AMIGA_AUD0);
109 /* if audio 1 interrupt */
110 if (ints & IF_AUD1) {
111 amiga_custom.intreq = IF_AUD1;
112 generic_handle_irq(IRQ_AMIGA_AUD1);
115 /* if audio 2 interrupt */
116 if (ints & IF_AUD2) {
117 amiga_custom.intreq = IF_AUD2;
118 generic_handle_irq(IRQ_AMIGA_AUD2);
121 /* if audio 3 interrupt */
122 if (ints & IF_AUD3) {
123 amiga_custom.intreq = IF_AUD3;
124 generic_handle_irq(IRQ_AMIGA_AUD3);
129 static irqreturn_t ami_int5(int irq, void *dev_id)
131 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
133 /* if serial receive buffer full interrupt */
135 /* acknowledge of IF_RBF must be done by the serial interrupt */
136 generic_handle_irq(IRQ_AMIGA_RBF);
139 /* if a disk sync interrupt */
140 if (ints & IF_DSKSYN) {
141 amiga_custom.intreq = IF_DSKSYN;
142 generic_handle_irq(IRQ_AMIGA_DSKSYN);
149 * void amiga_init_IRQ(void)
155 * This function should be called during kernel startup to initialize
156 * the amiga IRQ handling routines.
159 void __init amiga_init_IRQ(void)
161 if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
162 pr_err("Couldn't register int%d\n", 1);
163 if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
164 pr_err("Couldn't register int%d\n", 3);
165 if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
166 pr_err("Couldn't register int%d\n", 4);
167 if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
168 pr_err("Couldn't register int%d\n", 5);
170 m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
173 /* turn off PCMCIA interrupts */
174 if (AMIGAHW_PRESENT(PCMCIA))
175 gayle.inten = GAYLE_IRQ_IDE;
177 /* turn off all interrupts and enable the master interrupt bit */
178 amiga_custom.intena = 0x7fff;
179 amiga_custom.intreq = 0x7fff;
180 amiga_custom.intena = IF_SETCLR | IF_INTEN;
182 cia_init_IRQ(&ciaa_base);
183 cia_init_IRQ(&ciab_base);