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 #include <linux/irq.h>
15 #include <asm/traps.h>
16 #include <asm/amigahw.h>
17 #include <asm/amigaints.h>
18 #include <asm/amipcmcia.h>
22 * Enable/disable a particular machine specific interrupt source.
23 * Note that this may affect other interrupts in case of a shared interrupt.
24 * This function should only be called for a _very_ short time to change some
25 * internal data, that may not be changed by the interrupt at the same time.
28 static void amiga_irq_enable(struct irq_data
*data
)
30 amiga_custom
.intena
= IF_SETCLR
| (1 << (data
->irq
- IRQ_USER
));
33 static void amiga_irq_disable(struct irq_data
*data
)
35 amiga_custom
.intena
= 1 << (data
->irq
- IRQ_USER
);
38 static struct irq_chip amiga_irq_chip
= {
40 .irq_enable
= amiga_irq_enable
,
41 .irq_disable
= amiga_irq_disable
,
46 * The builtin Amiga hardware interrupt handlers.
49 static void ami_int1(struct irq_desc
*desc
)
51 unsigned short ints
= amiga_custom
.intreqr
& amiga_custom
.intenar
;
53 /* if serial transmit buffer empty, interrupt */
55 amiga_custom
.intreq
= IF_TBE
;
56 generic_handle_irq(IRQ_AMIGA_TBE
);
59 /* if floppy disk transfer complete, interrupt */
60 if (ints
& IF_DSKBLK
) {
61 amiga_custom
.intreq
= IF_DSKBLK
;
62 generic_handle_irq(IRQ_AMIGA_DSKBLK
);
65 /* if software interrupt set, interrupt */
67 amiga_custom
.intreq
= IF_SOFT
;
68 generic_handle_irq(IRQ_AMIGA_SOFT
);
72 static void ami_int3(struct irq_desc
*desc
)
74 unsigned short ints
= amiga_custom
.intreqr
& amiga_custom
.intenar
;
76 /* if a blitter interrupt */
78 amiga_custom
.intreq
= IF_BLIT
;
79 generic_handle_irq(IRQ_AMIGA_BLIT
);
82 /* if a copper interrupt */
83 if (ints
& IF_COPER
) {
84 amiga_custom
.intreq
= IF_COPER
;
85 generic_handle_irq(IRQ_AMIGA_COPPER
);
88 /* if a vertical blank interrupt */
89 if (ints
& IF_VERTB
) {
90 amiga_custom
.intreq
= IF_VERTB
;
91 generic_handle_irq(IRQ_AMIGA_VERTB
);
95 static void ami_int4(struct irq_desc
*desc
)
97 unsigned short ints
= amiga_custom
.intreqr
& amiga_custom
.intenar
;
99 /* if audio 0 interrupt */
100 if (ints
& IF_AUD0
) {
101 amiga_custom
.intreq
= IF_AUD0
;
102 generic_handle_irq(IRQ_AMIGA_AUD0
);
105 /* if audio 1 interrupt */
106 if (ints
& IF_AUD1
) {
107 amiga_custom
.intreq
= IF_AUD1
;
108 generic_handle_irq(IRQ_AMIGA_AUD1
);
111 /* if audio 2 interrupt */
112 if (ints
& IF_AUD2
) {
113 amiga_custom
.intreq
= IF_AUD2
;
114 generic_handle_irq(IRQ_AMIGA_AUD2
);
117 /* if audio 3 interrupt */
118 if (ints
& IF_AUD3
) {
119 amiga_custom
.intreq
= IF_AUD3
;
120 generic_handle_irq(IRQ_AMIGA_AUD3
);
124 static void ami_int5(struct irq_desc
*desc
)
126 unsigned short ints
= amiga_custom
.intreqr
& amiga_custom
.intenar
;
128 /* if serial receive buffer full interrupt */
130 /* acknowledge of IF_RBF must be done by the serial interrupt */
131 generic_handle_irq(IRQ_AMIGA_RBF
);
134 /* if a disk sync interrupt */
135 if (ints
& IF_DSKSYN
) {
136 amiga_custom
.intreq
= IF_DSKSYN
;
137 generic_handle_irq(IRQ_AMIGA_DSKSYN
);
143 * void amiga_init_IRQ(void)
149 * This function should be called during kernel startup to initialize
150 * the amiga IRQ handling routines.
153 void __init
amiga_init_IRQ(void)
155 m68k_setup_irq_controller(&amiga_irq_chip
, handle_simple_irq
, IRQ_USER
,
158 irq_set_chained_handler(IRQ_AUTO_1
, ami_int1
);
159 irq_set_chained_handler(IRQ_AUTO_3
, ami_int3
);
160 irq_set_chained_handler(IRQ_AUTO_4
, ami_int4
);
161 irq_set_chained_handler(IRQ_AUTO_5
, ami_int5
);
163 /* turn off PCMCIA interrupts */
164 if (AMIGAHW_PRESENT(PCMCIA
))
165 gayle
.inten
= GAYLE_IRQ_IDE
;
167 /* turn off all interrupts and enable the master interrupt bit */
168 amiga_custom
.intena
= 0x7fff;
169 amiga_custom
.intreq
= 0x7fff;
170 amiga_custom
.intena
= IF_SETCLR
| IF_INTEN
;
172 cia_init_IRQ(&ciaa_base
);
173 cia_init_IRQ(&ciab_base
);