]> git.ipfire.org Git - u-boot.git/blob - board/MAI/AmigaOneG3SE/i8259.c
* Code cleanup:
[u-boot.git] / board / MAI / AmigaOneG3SE / i8259.c
1 /*
2 * (C) Copyright 2002
3 * John W. Linville, linville@tuxdriver.com
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24 #include <common.h>
25 #include "i8259.h"
26
27 #undef IRQ_DEBUG
28
29 #ifdef IRQ_DEBUG
30 #define PRINTF(fmt,args...) printf (fmt ,##args)
31 #else
32 #define PRINTF(fmt,args...)
33 #endif
34
35 static inline unsigned char read_byte(volatile unsigned char* from)
36 {
37 int x;
38 asm volatile ("lbz %0,%1\n eieio" : "=r" (x) : "m" (*from));
39 return (unsigned char)x;
40 }
41
42 static inline void write_byte(volatile unsigned char *to, int x)
43 {
44 asm volatile ("stb %1,%0\n eieio" : "=m" (*to) : "r" (x));
45 }
46
47 static inline unsigned long read_long_little(volatile unsigned long *from)
48 {
49 unsigned long x;
50 asm volatile ("lwbrx %0,0,%1\n eieio\n sync" : "=r" (x) : "r" (from), "m"(*from));
51 return (unsigned long)x;
52 }
53
54 #ifdef out8
55 #undef out8
56 #endif
57
58 #ifdef in8
59 #undef in8
60 #endif
61
62 #define out8(addr, byte) write_byte(0xFE000000 | addr, byte)
63 #define in8(addr) read_byte(0xFE000000 | addr)
64
65 /*
66 * This contains the irq mask for both 8259A irq controllers,
67 */
68 static char cached_imr[2] = {0xff, 0xff};
69
70 #define cached_imr1 (cached_imr[0])
71 #define cached_imr2 (cached_imr[1])
72
73 void i8259_init(void)
74 {
75 char dummy;
76 PRINTF("Initializing Interrupt controller\n");
77 /* init master interrupt controller */
78 out8(0x20, 0x11); /* 0x19); /###* Start init sequence */
79 out8(0x21, 0x00); /* Vector base */
80 out8(0x21, 0x04); /* edge tiggered, Cascade (slave) on IRQ2 */
81 out8(0x21, 0x11); /* was: 0x01); /###* Select 8086 mode */
82
83 /* init slave interrupt controller */
84 out8(0xA0, 0x11); /* 0x19); /###* Start init sequence */
85 out8(0xA1, 0x08); /* Vector base */
86 out8(0xA1, 0x02); /* edge triggered, Cascade (slave) on IRQ2 */
87 out8(0xA1, 0x11); /* was: 0x01); /###* Select 8086 mode */
88
89 /* always read ISR */
90 out8(0x20, 0x0B);
91 dummy = in8(ISR_1);
92 out8(0xA0, 0x0B);
93 dummy = in8(ISR_2);
94
95 /* out8(0x43, 0x30); */
96 /* out8(0x40, 0); */
97 /* out8(0x40, 0); */
98 /* out8(0x43, 0x70); */
99 /* out8(0x41, 0); */
100 /* out8(0x41, 0); */
101 /* out8(0x43, 0xb0); */
102 /* out8(0x42, 0); */
103 /* out8(0x42, 0); */
104
105 /* Mask all interrupts */
106 out8(IMR_2, cached_imr2);
107 out8(IMR_1, cached_imr1);
108
109 i8259_unmask_irq(2);
110 #if 0
111 {
112 int i;
113 for (i=0; i<16; i++)
114 {
115 i8259_unmask_irq(i);
116 }
117 }
118 #endif
119 }
120
121 static volatile char *pci_intack = (void *)0xFEF00000;
122
123 int i8259_irq(void)
124 {
125 int irq;
126
127 irq = read_long_little(pci_intack) & 0xff;
128 if (irq==7) {
129 /*
130 * This may be a spurious interrupt.
131 *
132 * Read the interrupt status register (ISR). If the most
133 * significant bit is not set then there is no valid
134 * interrupt.
135 */
136 if(~in8(0x20)&0x80) {
137 irq = -1;
138 }
139 }
140
141 return irq;
142 }
143 int i8259_get_irq(struct pt_regs *regs)
144 {
145 unsigned char irq;
146
147 /*
148 * Perform an interrupt acknowledge cycle on controller 1
149 */
150 out8(OCW3_1, 0x0C); /* prepare for poll */
151 irq = in8(IPL_1) & 7;
152 if (irq == 2) {
153 /*
154 * Interrupt is cascaded so perform interrupt
155 * acknowledge on controller 2
156 */
157 out8(OCW3_2, 0x0C); /* prepare for poll */
158 irq = (in8(IPL_2) & 7) + 8;
159 if (irq == 15) {
160 /*
161 * This may be a spurious interrupt
162 *
163 * Read the interrupt status register. If the most
164 * significant bit is not set then there is no valid
165 * interrupt
166 */
167 out8(OCW3_2, 0x0b);
168 if (~(in8(ISR_2) & 0x80)) {
169 return -1;
170 }
171 }
172 } else if (irq == 7) {
173 /*
174 * This may be a spurious interrupt
175 *
176 * Read the interrupt status register. If the most
177 * significant bit is not set then there is no valid
178 * interrupt
179 */
180 out8(OCW3_1, 0x0b);
181 if (~(in8(ISR_1) & 0x80)) {
182 return -1;
183 }
184 }
185 return irq;
186 }
187
188 /*
189 * Careful! The 8259A is a fragile beast, it pretty
190 * much _has_ to be done exactly like this (mask it
191 * first, _then_ send the EOI, and the order of EOI
192 * to the two 8259s is important!
193 */
194 void i8259_mask_and_ack(int irq)
195 {
196 if (irq > 7) {
197 cached_imr2 |= (1 << (irq - 8));
198 in8(IMR_2); /* DUMMY */
199 out8(IMR_2, cached_imr2);
200 out8(OCW2_2, 0x20); /* Non-specific EOI */
201 out8(OCW2_1, 0x20); /* Non-specific EOI to cascade */
202 } else {
203 cached_imr1 |= (1 << irq);
204 in8(IMR_1); /* DUMMY */
205 out8(IMR_1, cached_imr1);
206 out8(OCW2_1, 0x20); /* Non-specific EOI */
207 }
208 }
209
210 void i8259_mask_irq(int irq)
211 {
212 if (irq & 8) {
213 cached_imr2 |= (1 << (irq & 7));
214 out8(IMR_2, cached_imr2);
215 } else {
216 cached_imr1 |= (1 << irq);
217 out8(IMR_1, cached_imr1);
218 }
219 }
220
221 void i8259_unmask_irq(int irq)
222 {
223 if (irq & 8) {
224 cached_imr2 &= ~(1 << (irq & 7));
225 out8(IMR_2, cached_imr2);
226 } else {
227 cached_imr1 &= ~(1 << irq);
228 out8(IMR_1, cached_imr1);
229 }
230 }