xref: /OK3568_Linux_fs/kernel/arch/m68k/amiga/amiints.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Amiga Linux interrupt handling code
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * This file is subject to the terms and conditions of the GNU General Public
5*4882a593Smuzhiyun  * License.  See the file COPYING in the main directory of this archive
6*4882a593Smuzhiyun  * for more details.
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/errno.h>
12*4882a593Smuzhiyun #include <linux/irq.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <asm/irq.h>
15*4882a593Smuzhiyun #include <asm/traps.h>
16*4882a593Smuzhiyun #include <asm/amigahw.h>
17*4882a593Smuzhiyun #include <asm/amigaints.h>
18*4882a593Smuzhiyun #include <asm/amipcmcia.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /*
22*4882a593Smuzhiyun  * Enable/disable a particular machine specific interrupt source.
23*4882a593Smuzhiyun  * Note that this may affect other interrupts in case of a shared interrupt.
24*4882a593Smuzhiyun  * This function should only be called for a _very_ short time to change some
25*4882a593Smuzhiyun  * internal data, that may not be changed by the interrupt at the same time.
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun 
amiga_irq_enable(struct irq_data * data)28*4882a593Smuzhiyun static void amiga_irq_enable(struct irq_data *data)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun 	amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun 
amiga_irq_disable(struct irq_data * data)33*4882a593Smuzhiyun static void amiga_irq_disable(struct irq_data *data)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	amiga_custom.intena = 1 << (data->irq - IRQ_USER);
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun static struct irq_chip amiga_irq_chip = {
39*4882a593Smuzhiyun 	.name		= "amiga",
40*4882a593Smuzhiyun 	.irq_enable	= amiga_irq_enable,
41*4882a593Smuzhiyun 	.irq_disable	= amiga_irq_disable,
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /*
46*4882a593Smuzhiyun  * The builtin Amiga hardware interrupt handlers.
47*4882a593Smuzhiyun  */
48*4882a593Smuzhiyun 
ami_int1(struct irq_desc * desc)49*4882a593Smuzhiyun static void ami_int1(struct irq_desc *desc)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/* if serial transmit buffer empty, interrupt */
54*4882a593Smuzhiyun 	if (ints & IF_TBE) {
55*4882a593Smuzhiyun 		amiga_custom.intreq = IF_TBE;
56*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_TBE);
57*4882a593Smuzhiyun 	}
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	/* if floppy disk transfer complete, interrupt */
60*4882a593Smuzhiyun 	if (ints & IF_DSKBLK) {
61*4882a593Smuzhiyun 		amiga_custom.intreq = IF_DSKBLK;
62*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_DSKBLK);
63*4882a593Smuzhiyun 	}
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	/* if software interrupt set, interrupt */
66*4882a593Smuzhiyun 	if (ints & IF_SOFT) {
67*4882a593Smuzhiyun 		amiga_custom.intreq = IF_SOFT;
68*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_SOFT);
69*4882a593Smuzhiyun 	}
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
ami_int3(struct irq_desc * desc)72*4882a593Smuzhiyun static void ami_int3(struct irq_desc *desc)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	/* if a blitter interrupt */
77*4882a593Smuzhiyun 	if (ints & IF_BLIT) {
78*4882a593Smuzhiyun 		amiga_custom.intreq = IF_BLIT;
79*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_BLIT);
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	/* if a copper interrupt */
83*4882a593Smuzhiyun 	if (ints & IF_COPER) {
84*4882a593Smuzhiyun 		amiga_custom.intreq = IF_COPER;
85*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_COPPER);
86*4882a593Smuzhiyun 	}
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/* if a vertical blank interrupt */
89*4882a593Smuzhiyun 	if (ints & IF_VERTB) {
90*4882a593Smuzhiyun 		amiga_custom.intreq = IF_VERTB;
91*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_VERTB);
92*4882a593Smuzhiyun 	}
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
ami_int4(struct irq_desc * desc)95*4882a593Smuzhiyun static void ami_int4(struct irq_desc *desc)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	/* if audio 0 interrupt */
100*4882a593Smuzhiyun 	if (ints & IF_AUD0) {
101*4882a593Smuzhiyun 		amiga_custom.intreq = IF_AUD0;
102*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_AUD0);
103*4882a593Smuzhiyun 	}
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	/* if audio 1 interrupt */
106*4882a593Smuzhiyun 	if (ints & IF_AUD1) {
107*4882a593Smuzhiyun 		amiga_custom.intreq = IF_AUD1;
108*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_AUD1);
109*4882a593Smuzhiyun 	}
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	/* if audio 2 interrupt */
112*4882a593Smuzhiyun 	if (ints & IF_AUD2) {
113*4882a593Smuzhiyun 		amiga_custom.intreq = IF_AUD2;
114*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_AUD2);
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	/* if audio 3 interrupt */
118*4882a593Smuzhiyun 	if (ints & IF_AUD3) {
119*4882a593Smuzhiyun 		amiga_custom.intreq = IF_AUD3;
120*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_AUD3);
121*4882a593Smuzhiyun 	}
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
ami_int5(struct irq_desc * desc)124*4882a593Smuzhiyun static void ami_int5(struct irq_desc *desc)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	/* if serial receive buffer full interrupt */
129*4882a593Smuzhiyun 	if (ints & IF_RBF) {
130*4882a593Smuzhiyun 		/* acknowledge of IF_RBF must be done by the serial interrupt */
131*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_RBF);
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	/* if a disk sync interrupt */
135*4882a593Smuzhiyun 	if (ints & IF_DSKSYN) {
136*4882a593Smuzhiyun 		amiga_custom.intreq = IF_DSKSYN;
137*4882a593Smuzhiyun 		generic_handle_irq(IRQ_AMIGA_DSKSYN);
138*4882a593Smuzhiyun 	}
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun /*
143*4882a593Smuzhiyun  * void amiga_init_IRQ(void)
144*4882a593Smuzhiyun  *
145*4882a593Smuzhiyun  * Parameters:	None
146*4882a593Smuzhiyun  *
147*4882a593Smuzhiyun  * Returns:	Nothing
148*4882a593Smuzhiyun  *
149*4882a593Smuzhiyun  * This function should be called during kernel startup to initialize
150*4882a593Smuzhiyun  * the amiga IRQ handling routines.
151*4882a593Smuzhiyun  */
152*4882a593Smuzhiyun 
amiga_init_IRQ(void)153*4882a593Smuzhiyun void __init amiga_init_IRQ(void)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
156*4882a593Smuzhiyun 				  AMI_STD_IRQS);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	irq_set_chained_handler(IRQ_AUTO_1, ami_int1);
159*4882a593Smuzhiyun 	irq_set_chained_handler(IRQ_AUTO_3, ami_int3);
160*4882a593Smuzhiyun 	irq_set_chained_handler(IRQ_AUTO_4, ami_int4);
161*4882a593Smuzhiyun 	irq_set_chained_handler(IRQ_AUTO_5, ami_int5);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	/* turn off PCMCIA interrupts */
164*4882a593Smuzhiyun 	if (AMIGAHW_PRESENT(PCMCIA))
165*4882a593Smuzhiyun 		gayle.inten = GAYLE_IRQ_IDE;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	/* turn off all interrupts and enable the master interrupt bit */
168*4882a593Smuzhiyun 	amiga_custom.intena = 0x7fff;
169*4882a593Smuzhiyun 	amiga_custom.intreq = 0x7fff;
170*4882a593Smuzhiyun 	amiga_custom.intena = IF_SETCLR | IF_INTEN;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	cia_init_IRQ(&ciaa_base);
173*4882a593Smuzhiyun 	cia_init_IRQ(&ciab_base);
174*4882a593Smuzhiyun }
175