m68k/amiga: Convert Amiga to genirq
[platform/adaptation/renesas_rcar/renesas_kernel.git] / arch / m68k / amiga / amiints.c
1 /*
2  * 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
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>
14 #endif
15
16 #include <asm/irq.h>
17 #include <asm/traps.h>
18 #include <asm/amigahw.h>
19 #include <asm/amigaints.h>
20 #include <asm/amipcmcia.h>
21
22
23 /*
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.
28  */
29
30 static void amiga_irq_enable(struct irq_data *data)
31 {
32         amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
33 }
34
35 static void amiga_irq_disable(struct irq_data *data)
36 {
37         amiga_custom.intena = 1 << (data->irq - IRQ_USER);
38 }
39
40 static struct irq_chip amiga_irq_chip = {
41         .name           = "amiga",
42         .irq_enable     = amiga_irq_enable,
43         .irq_disable    = amiga_irq_disable,
44 };
45
46
47 /*
48  * The builtin Amiga hardware interrupt handlers.
49  */
50
51 static irqreturn_t ami_int1(int irq, void *dev_id)
52 {
53         unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
54
55         /* if serial transmit buffer empty, interrupt */
56         if (ints & IF_TBE) {
57                 amiga_custom.intreq = IF_TBE;
58                 generic_handle_irq(IRQ_AMIGA_TBE);
59         }
60
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);
65         }
66
67         /* if software interrupt set, interrupt */
68         if (ints & IF_SOFT) {
69                 amiga_custom.intreq = IF_SOFT;
70                 generic_handle_irq(IRQ_AMIGA_SOFT);
71         }
72         return IRQ_HANDLED;
73 }
74
75 static irqreturn_t ami_int3(int irq, void *dev_id)
76 {
77         unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
78
79         /* if a blitter interrupt */
80         if (ints & IF_BLIT) {
81                 amiga_custom.intreq = IF_BLIT;
82                 generic_handle_irq(IRQ_AMIGA_BLIT);
83         }
84
85         /* if a copper interrupt */
86         if (ints & IF_COPER) {
87                 amiga_custom.intreq = IF_COPER;
88                 generic_handle_irq(IRQ_AMIGA_COPPER);
89         }
90
91         /* if a vertical blank interrupt */
92         if (ints & IF_VERTB) {
93                 amiga_custom.intreq = IF_VERTB;
94                 generic_handle_irq(IRQ_AMIGA_VERTB);
95         }
96         return IRQ_HANDLED;
97 }
98
99 static irqreturn_t ami_int4(int irq, void *dev_id)
100 {
101         unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
102
103         /* if audio 0 interrupt */
104         if (ints & IF_AUD0) {
105                 amiga_custom.intreq = IF_AUD0;
106                 generic_handle_irq(IRQ_AMIGA_AUD0);
107         }
108
109         /* if audio 1 interrupt */
110         if (ints & IF_AUD1) {
111                 amiga_custom.intreq = IF_AUD1;
112                 generic_handle_irq(IRQ_AMIGA_AUD1);
113         }
114
115         /* if audio 2 interrupt */
116         if (ints & IF_AUD2) {
117                 amiga_custom.intreq = IF_AUD2;
118                 generic_handle_irq(IRQ_AMIGA_AUD2);
119         }
120
121         /* if audio 3 interrupt */
122         if (ints & IF_AUD3) {
123                 amiga_custom.intreq = IF_AUD3;
124                 generic_handle_irq(IRQ_AMIGA_AUD3);
125         }
126         return IRQ_HANDLED;
127 }
128
129 static irqreturn_t ami_int5(int irq, void *dev_id)
130 {
131         unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
132
133         /* if serial receive buffer full interrupt */
134         if (ints & IF_RBF) {
135                 /* acknowledge of IF_RBF must be done by the serial interrupt */
136                 generic_handle_irq(IRQ_AMIGA_RBF);
137         }
138
139         /* if a disk sync interrupt */
140         if (ints & IF_DSKSYN) {
141                 amiga_custom.intreq = IF_DSKSYN;
142                 generic_handle_irq(IRQ_AMIGA_DSKSYN);
143         }
144         return IRQ_HANDLED;
145 }
146
147
148 /*
149  * void amiga_init_IRQ(void)
150  *
151  * Parameters:  None
152  *
153  * Returns:     Nothing
154  *
155  * This function should be called during kernel startup to initialize
156  * the amiga IRQ handling routines.
157  */
158
159 void __init amiga_init_IRQ(void)
160 {
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);
169
170         m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
171                                   AMI_STD_IRQS);
172
173         /* turn off PCMCIA interrupts */
174         if (AMIGAHW_PRESENT(PCMCIA))
175                 gayle.inten = GAYLE_IRQ_IDE;
176
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;
181
182         cia_init_IRQ(&ciaa_base);
183         cia_init_IRQ(&ciab_base);
184 }