diff options
Diffstat (limited to 'arch/alpha/kernel/sys_sable.c')
-rw-r--r-- | arch/alpha/kernel/sys_sable.c | 653 |
1 files changed, 653 insertions, 0 deletions
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c new file mode 100644 index 000000000000..a7ff84474ace --- /dev/null +++ b/arch/alpha/kernel/sys_sable.c | |||
@@ -0,0 +1,653 @@ | |||
1 | /* | ||
2 | * linux/arch/alpha/kernel/sys_sable.c | ||
3 | * | ||
4 | * Copyright (C) 1995 David A Rusling | ||
5 | * Copyright (C) 1996 Jay A Estabrook | ||
6 | * Copyright (C) 1998, 1999 Richard Henderson | ||
7 | * | ||
8 | * Code supporting the Sable, Sable-Gamma, and Lynx systems. | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/mm.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <asm/ptrace.h> | ||
20 | #include <asm/system.h> | ||
21 | #include <asm/dma.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/mmu_context.h> | ||
24 | #include <asm/io.h> | ||
25 | #include <asm/pgtable.h> | ||
26 | #include <asm/core_t2.h> | ||
27 | #include <asm/tlbflush.h> | ||
28 | |||
29 | #include "proto.h" | ||
30 | #include "irq_impl.h" | ||
31 | #include "pci_impl.h" | ||
32 | #include "machvec_impl.h" | ||
33 | |||
34 | DEFINE_SPINLOCK(sable_lynx_irq_lock); | ||
35 | |||
36 | typedef struct irq_swizzle_struct | ||
37 | { | ||
38 | char irq_to_mask[64]; | ||
39 | char mask_to_irq[64]; | ||
40 | |||
41 | /* Note mask bit is true for DISABLED irqs. */ | ||
42 | unsigned long shadow_mask; | ||
43 | |||
44 | void (*update_irq_hw)(unsigned long bit, unsigned long mask); | ||
45 | void (*ack_irq_hw)(unsigned long bit); | ||
46 | |||
47 | } irq_swizzle_t; | ||
48 | |||
49 | static irq_swizzle_t *sable_lynx_irq_swizzle; | ||
50 | |||
51 | static void sable_lynx_init_irq(int nr_irqs); | ||
52 | |||
53 | #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE) | ||
54 | |||
55 | /***********************************************************************/ | ||
56 | /* | ||
57 | * For SABLE, which is really baroque, we manage 40 IRQ's, but the | ||
58 | * hardware really only supports 24, not via normal ISA PIC, | ||
59 | * but cascaded custom 8259's, etc. | ||
60 | * 0-7 (char at 536) | ||
61 | * 8-15 (char at 53a) | ||
62 | * 16-23 (char at 53c) | ||
63 | * | ||
64 | * Summary Registers (536/53a/53c): | ||
65 | * | ||
66 | * Bit Meaning Kernel IRQ | ||
67 | *------------------------------------------ | ||
68 | * 0 PCI slot 0 34 | ||
69 | * 1 NCR810 (builtin) 33 | ||
70 | * 2 TULIP (builtin) 32 | ||
71 | * 3 mouse 12 | ||
72 | * 4 PCI slot 1 35 | ||
73 | * 5 PCI slot 2 36 | ||
74 | * 6 keyboard 1 | ||
75 | * 7 floppy 6 | ||
76 | * 8 COM2 3 | ||
77 | * 9 parallel port 7 | ||
78 | *10 EISA irq 3 - | ||
79 | *11 EISA irq 4 - | ||
80 | *12 EISA irq 5 5 | ||
81 | *13 EISA irq 6 - | ||
82 | *14 EISA irq 7 - | ||
83 | *15 COM1 4 | ||
84 | *16 EISA irq 9 9 | ||
85 | *17 EISA irq 10 10 | ||
86 | *18 EISA irq 11 11 | ||
87 | *19 EISA irq 12 - | ||
88 | *20 EISA irq 13 - | ||
89 | *21 EISA irq 14 14 | ||
90 | *22 NC 15 | ||
91 | *23 IIC - | ||
92 | */ | ||
93 | |||
94 | static void | ||
95 | sable_update_irq_hw(unsigned long bit, unsigned long mask) | ||
96 | { | ||
97 | int port = 0x537; | ||
98 | |||
99 | if (bit >= 16) { | ||
100 | port = 0x53d; | ||
101 | mask >>= 16; | ||
102 | } else if (bit >= 8) { | ||
103 | port = 0x53b; | ||
104 | mask >>= 8; | ||
105 | } | ||
106 | |||
107 | outb(mask, port); | ||
108 | } | ||
109 | |||
110 | static void | ||
111 | sable_ack_irq_hw(unsigned long bit) | ||
112 | { | ||
113 | int port, val1, val2; | ||
114 | |||
115 | if (bit >= 16) { | ||
116 | port = 0x53c; | ||
117 | val1 = 0xE0 | (bit - 16); | ||
118 | val2 = 0xE0 | 4; | ||
119 | } else if (bit >= 8) { | ||
120 | port = 0x53a; | ||
121 | val1 = 0xE0 | (bit - 8); | ||
122 | val2 = 0xE0 | 3; | ||
123 | } else { | ||
124 | port = 0x536; | ||
125 | val1 = 0xE0 | (bit - 0); | ||
126 | val2 = 0xE0 | 1; | ||
127 | } | ||
128 | |||
129 | outb(val1, port); /* ack the slave */ | ||
130 | outb(val2, 0x534); /* ack the master */ | ||
131 | } | ||
132 | |||
133 | static irq_swizzle_t sable_irq_swizzle = { | ||
134 | { | ||
135 | -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */ | ||
136 | -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */ | ||
137 | -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */ | ||
138 | -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */ | ||
139 | 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */ | ||
140 | -1, -1, -1, -1, -1, -1, -1, -1, /* */ | ||
141 | -1, -1, -1, -1, -1, -1, -1, -1, /* */ | ||
142 | -1, -1, -1, -1, -1, -1, -1, -1 /* */ | ||
143 | }, | ||
144 | { | ||
145 | 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */ | ||
146 | 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */ | ||
147 | 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */ | ||
148 | -1, -1, -1, -1, -1, -1, -1, -1, /* */ | ||
149 | -1, -1, -1, -1, -1, -1, -1, -1, /* */ | ||
150 | -1, -1, -1, -1, -1, -1, -1, -1, /* */ | ||
151 | -1, -1, -1, -1, -1, -1, -1, -1, /* */ | ||
152 | -1, -1, -1, -1, -1, -1, -1, -1 /* */ | ||
153 | }, | ||
154 | -1, | ||
155 | sable_update_irq_hw, | ||
156 | sable_ack_irq_hw | ||
157 | }; | ||
158 | |||
159 | static void __init | ||
160 | sable_init_irq(void) | ||
161 | { | ||
162 | outb(-1, 0x537); /* slave 0 */ | ||
163 | outb(-1, 0x53b); /* slave 1 */ | ||
164 | outb(-1, 0x53d); /* slave 2 */ | ||
165 | outb(0x44, 0x535); /* enable cascades in master */ | ||
166 | |||
167 | sable_lynx_irq_swizzle = &sable_irq_swizzle; | ||
168 | sable_lynx_init_irq(40); | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * PCI Fixup configuration for ALPHA SABLE (2100). | ||
173 | * | ||
174 | * The device to slot mapping looks like: | ||
175 | * | ||
176 | * Slot Device | ||
177 | * 0 TULIP | ||
178 | * 1 SCSI | ||
179 | * 2 PCI-EISA bridge | ||
180 | * 3 none | ||
181 | * 4 none | ||
182 | * 5 none | ||
183 | * 6 PCI on board slot 0 | ||
184 | * 7 PCI on board slot 1 | ||
185 | * 8 PCI on board slot 2 | ||
186 | * | ||
187 | * | ||
188 | * This two layered interrupt approach means that we allocate IRQ 16 and | ||
189 | * above for PCI interrupts. The IRQ relates to which bit the interrupt | ||
190 | * comes in on. This makes interrupt processing much easier. | ||
191 | */ | ||
192 | /* | ||
193 | * NOTE: the IRQ assignments below are arbitrary, but need to be consistent | ||
194 | * with the values in the irq swizzling tables above. | ||
195 | */ | ||
196 | |||
197 | static int __init | ||
198 | sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
199 | { | ||
200 | static char irq_tab[9][5] __initdata = { | ||
201 | /*INT INTA INTB INTC INTD */ | ||
202 | { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */ | ||
203 | { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */ | ||
204 | { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */ | ||
205 | { -1, -1, -1, -1, -1}, /* IdSel 3, none */ | ||
206 | { -1, -1, -1, -1, -1}, /* IdSel 4, none */ | ||
207 | { -1, -1, -1, -1, -1}, /* IdSel 5, none */ | ||
208 | { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */ | ||
209 | { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */ | ||
210 | { 32+4, 32+4, 32+4, 32+4, 32+4} /* IdSel 8, slot 2 */ | ||
211 | }; | ||
212 | long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5; | ||
213 | return COMMON_TABLE_LOOKUP; | ||
214 | } | ||
215 | #endif /* defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE) */ | ||
216 | |||
217 | #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX) | ||
218 | |||
219 | /***********************************************************************/ | ||
220 | /* LYNX hardware specifics | ||
221 | */ | ||
222 | /* | ||
223 | * For LYNX, which is also baroque, we manage 64 IRQs, via a custom IC. | ||
224 | * | ||
225 | * Bit Meaning Kernel IRQ | ||
226 | *------------------------------------------ | ||
227 | * 0 | ||
228 | * 1 | ||
229 | * 2 | ||
230 | * 3 mouse 12 | ||
231 | * 4 | ||
232 | * 5 | ||
233 | * 6 keyboard 1 | ||
234 | * 7 floppy 6 | ||
235 | * 8 COM2 3 | ||
236 | * 9 parallel port 7 | ||
237 | *10 EISA irq 3 - | ||
238 | *11 EISA irq 4 - | ||
239 | *12 EISA irq 5 5 | ||
240 | *13 EISA irq 6 - | ||
241 | *14 EISA irq 7 - | ||
242 | *15 COM1 4 | ||
243 | *16 EISA irq 9 9 | ||
244 | *17 EISA irq 10 10 | ||
245 | *18 EISA irq 11 11 | ||
246 | *19 EISA irq 12 - | ||
247 | *20 | ||
248 | *21 EISA irq 14 14 | ||
249 | *22 EISA irq 15 15 | ||
250 | *23 IIC - | ||
251 | *24 VGA (builtin) - | ||
252 | *25 | ||
253 | *26 | ||
254 | *27 | ||
255 | *28 NCR810 (builtin) 28 | ||
256 | *29 | ||
257 | *30 | ||
258 | *31 | ||
259 | *32 PCI 0 slot 4 A primary bus 32 | ||
260 | *33 PCI 0 slot 4 B primary bus 33 | ||
261 | *34 PCI 0 slot 4 C primary bus 34 | ||
262 | *35 PCI 0 slot 4 D primary bus | ||
263 | *36 PCI 0 slot 5 A primary bus | ||
264 | *37 PCI 0 slot 5 B primary bus | ||
265 | *38 PCI 0 slot 5 C primary bus | ||
266 | *39 PCI 0 slot 5 D primary bus | ||
267 | *40 PCI 0 slot 6 A primary bus | ||
268 | *41 PCI 0 slot 6 B primary bus | ||
269 | *42 PCI 0 slot 6 C primary bus | ||
270 | *43 PCI 0 slot 6 D primary bus | ||
271 | *44 PCI 0 slot 7 A primary bus | ||
272 | *45 PCI 0 slot 7 B primary bus | ||
273 | *46 PCI 0 slot 7 C primary bus | ||
274 | *47 PCI 0 slot 7 D primary bus | ||
275 | *48 PCI 0 slot 0 A secondary bus | ||
276 | *49 PCI 0 slot 0 B secondary bus | ||
277 | *50 PCI 0 slot 0 C secondary bus | ||
278 | *51 PCI 0 slot 0 D secondary bus | ||
279 | *52 PCI 0 slot 1 A secondary bus | ||
280 | *53 PCI 0 slot 1 B secondary bus | ||
281 | *54 PCI 0 slot 1 C secondary bus | ||
282 | *55 PCI 0 slot 1 D secondary bus | ||
283 | *56 PCI 0 slot 2 A secondary bus | ||
284 | *57 PCI 0 slot 2 B secondary bus | ||
285 | *58 PCI 0 slot 2 C secondary bus | ||
286 | *59 PCI 0 slot 2 D secondary bus | ||
287 | *60 PCI 0 slot 3 A secondary bus | ||
288 | *61 PCI 0 slot 3 B secondary bus | ||
289 | *62 PCI 0 slot 3 C secondary bus | ||
290 | *63 PCI 0 slot 3 D secondary bus | ||
291 | */ | ||
292 | |||
293 | static void | ||
294 | lynx_update_irq_hw(unsigned long bit, unsigned long mask) | ||
295 | { | ||
296 | /* | ||
297 | * Write the AIR register on the T3/T4 with the | ||
298 | * address of the IC mask register (offset 0x40) | ||
299 | */ | ||
300 | *(vulp)T2_AIR = 0x40; | ||
301 | mb(); | ||
302 | *(vulp)T2_AIR; /* re-read to force write */ | ||
303 | mb(); | ||
304 | *(vulp)T2_DIR = mask; | ||
305 | mb(); | ||
306 | mb(); | ||
307 | } | ||
308 | |||
309 | static void | ||
310 | lynx_ack_irq_hw(unsigned long bit) | ||
311 | { | ||
312 | *(vulp)T2_VAR = (u_long) bit; | ||
313 | mb(); | ||
314 | mb(); | ||
315 | } | ||
316 | |||
317 | static irq_swizzle_t lynx_irq_swizzle = { | ||
318 | { /* irq_to_mask */ | ||
319 | -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */ | ||
320 | -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */ | ||
321 | -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo */ | ||
322 | -1, -1, -1, -1, 28, -1, -1, -1, /* pseudo */ | ||
323 | 32, 33, 34, 35, 36, 37, 38, 39, /* mask 32-39 */ | ||
324 | 40, 41, 42, 43, 44, 45, 46, 47, /* mask 40-47 */ | ||
325 | 48, 49, 50, 51, 52, 53, 54, 55, /* mask 48-55 */ | ||
326 | 56, 57, 58, 59, 60, 61, 62, 63 /* mask 56-63 */ | ||
327 | }, | ||
328 | { /* mask_to_irq */ | ||
329 | -1, -1, -1, 12, -1, -1, 1, 6, /* mask 0-7 */ | ||
330 | 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */ | ||
331 | 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */ | ||
332 | -1, -1, -1, -1, 28, -1, -1, -1, /* mask 24-31 */ | ||
333 | 32, 33, 34, 35, 36, 37, 38, 39, /* mask 32-39 */ | ||
334 | 40, 41, 42, 43, 44, 45, 46, 47, /* mask 40-47 */ | ||
335 | 48, 49, 50, 51, 52, 53, 54, 55, /* mask 48-55 */ | ||
336 | 56, 57, 58, 59, 60, 61, 62, 63 /* mask 56-63 */ | ||
337 | }, | ||
338 | -1, | ||
339 | lynx_update_irq_hw, | ||
340 | lynx_ack_irq_hw | ||
341 | }; | ||
342 | |||
343 | static void __init | ||
344 | lynx_init_irq(void) | ||
345 | { | ||
346 | sable_lynx_irq_swizzle = &lynx_irq_swizzle; | ||
347 | sable_lynx_init_irq(64); | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * PCI Fixup configuration for ALPHA LYNX (2100A) | ||
352 | * | ||
353 | * The device to slot mapping looks like: | ||
354 | * | ||
355 | * Slot Device | ||
356 | * 0 none | ||
357 | * 1 none | ||
358 | * 2 PCI-EISA bridge | ||
359 | * 3 PCI-PCI bridge | ||
360 | * 4 NCR 810 (Demi-Lynx only) | ||
361 | * 5 none | ||
362 | * 6 PCI on board slot 4 | ||
363 | * 7 PCI on board slot 5 | ||
364 | * 8 PCI on board slot 6 | ||
365 | * 9 PCI on board slot 7 | ||
366 | * | ||
367 | * And behind the PPB we have: | ||
368 | * | ||
369 | * 11 PCI on board slot 0 | ||
370 | * 12 PCI on board slot 1 | ||
371 | * 13 PCI on board slot 2 | ||
372 | * 14 PCI on board slot 3 | ||
373 | */ | ||
374 | /* | ||
375 | * NOTE: the IRQ assignments below are arbitrary, but need to be consistent | ||
376 | * with the values in the irq swizzling tables above. | ||
377 | */ | ||
378 | |||
379 | static int __init | ||
380 | lynx_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
381 | { | ||
382 | static char irq_tab[19][5] __initdata = { | ||
383 | /*INT INTA INTB INTC INTD */ | ||
384 | { -1, -1, -1, -1, -1}, /* IdSel 13, PCEB */ | ||
385 | { -1, -1, -1, -1, -1}, /* IdSel 14, PPB */ | ||
386 | { 28, 28, 28, 28, 28}, /* IdSel 15, NCR demi */ | ||
387 | { -1, -1, -1, -1, -1}, /* IdSel 16, none */ | ||
388 | { 32, 32, 33, 34, 35}, /* IdSel 17, slot 4 */ | ||
389 | { 36, 36, 37, 38, 39}, /* IdSel 18, slot 5 */ | ||
390 | { 40, 40, 41, 42, 43}, /* IdSel 19, slot 6 */ | ||
391 | { 44, 44, 45, 46, 47}, /* IdSel 20, slot 7 */ | ||
392 | { -1, -1, -1, -1, -1}, /* IdSel 22, none */ | ||
393 | /* The following are actually behind the PPB. */ | ||
394 | { -1, -1, -1, -1, -1}, /* IdSel 16 none */ | ||
395 | { 28, 28, 28, 28, 28}, /* IdSel 17 NCR lynx */ | ||
396 | { -1, -1, -1, -1, -1}, /* IdSel 18 none */ | ||
397 | { -1, -1, -1, -1, -1}, /* IdSel 19 none */ | ||
398 | { -1, -1, -1, -1, -1}, /* IdSel 20 none */ | ||
399 | { -1, -1, -1, -1, -1}, /* IdSel 21 none */ | ||
400 | { 48, 48, 49, 50, 51}, /* IdSel 22 slot 0 */ | ||
401 | { 52, 52, 53, 54, 55}, /* IdSel 23 slot 1 */ | ||
402 | { 56, 56, 57, 58, 59}, /* IdSel 24 slot 2 */ | ||
403 | { 60, 60, 61, 62, 63} /* IdSel 25 slot 3 */ | ||
404 | }; | ||
405 | const long min_idsel = 2, max_idsel = 20, irqs_per_slot = 5; | ||
406 | return COMMON_TABLE_LOOKUP; | ||
407 | } | ||
408 | |||
409 | static u8 __init | ||
410 | lynx_swizzle(struct pci_dev *dev, u8 *pinp) | ||
411 | { | ||
412 | int slot, pin = *pinp; | ||
413 | |||
414 | if (dev->bus->number == 0) { | ||
415 | slot = PCI_SLOT(dev->devfn); | ||
416 | } | ||
417 | /* Check for the built-in bridge */ | ||
418 | else if (PCI_SLOT(dev->bus->self->devfn) == 3) { | ||
419 | slot = PCI_SLOT(dev->devfn) + 11; | ||
420 | } | ||
421 | else | ||
422 | { | ||
423 | /* Must be a card-based bridge. */ | ||
424 | do { | ||
425 | if (PCI_SLOT(dev->bus->self->devfn) == 3) { | ||
426 | slot = PCI_SLOT(dev->devfn) + 11; | ||
427 | break; | ||
428 | } | ||
429 | pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ; | ||
430 | |||
431 | /* Move up the chain of bridges. */ | ||
432 | dev = dev->bus->self; | ||
433 | /* Slot of the next bridge. */ | ||
434 | slot = PCI_SLOT(dev->devfn); | ||
435 | } while (dev->bus->self); | ||
436 | } | ||
437 | *pinp = pin; | ||
438 | return slot; | ||
439 | } | ||
440 | |||
441 | #endif /* defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX) */ | ||
442 | |||
443 | /***********************************************************************/ | ||
444 | /* GENERIC irq routines */ | ||
445 | |||
446 | static inline void | ||
447 | sable_lynx_enable_irq(unsigned int irq) | ||
448 | { | ||
449 | unsigned long bit, mask; | ||
450 | |||
451 | bit = sable_lynx_irq_swizzle->irq_to_mask[irq]; | ||
452 | spin_lock(&sable_lynx_irq_lock); | ||
453 | mask = sable_lynx_irq_swizzle->shadow_mask &= ~(1UL << bit); | ||
454 | sable_lynx_irq_swizzle->update_irq_hw(bit, mask); | ||
455 | spin_unlock(&sable_lynx_irq_lock); | ||
456 | #if 0 | ||
457 | printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n", | ||
458 | __FUNCTION__, mask, bit, irq); | ||
459 | #endif | ||
460 | } | ||
461 | |||
462 | static void | ||
463 | sable_lynx_disable_irq(unsigned int irq) | ||
464 | { | ||
465 | unsigned long bit, mask; | ||
466 | |||
467 | bit = sable_lynx_irq_swizzle->irq_to_mask[irq]; | ||
468 | spin_lock(&sable_lynx_irq_lock); | ||
469 | mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit; | ||
470 | sable_lynx_irq_swizzle->update_irq_hw(bit, mask); | ||
471 | spin_unlock(&sable_lynx_irq_lock); | ||
472 | #if 0 | ||
473 | printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n", | ||
474 | __FUNCTION__, mask, bit, irq); | ||
475 | #endif | ||
476 | } | ||
477 | |||
478 | static unsigned int | ||
479 | sable_lynx_startup_irq(unsigned int irq) | ||
480 | { | ||
481 | sable_lynx_enable_irq(irq); | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static void | ||
486 | sable_lynx_end_irq(unsigned int irq) | ||
487 | { | ||
488 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
489 | sable_lynx_enable_irq(irq); | ||
490 | } | ||
491 | |||
492 | static void | ||
493 | sable_lynx_mask_and_ack_irq(unsigned int irq) | ||
494 | { | ||
495 | unsigned long bit, mask; | ||
496 | |||
497 | bit = sable_lynx_irq_swizzle->irq_to_mask[irq]; | ||
498 | spin_lock(&sable_lynx_irq_lock); | ||
499 | mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit; | ||
500 | sable_lynx_irq_swizzle->update_irq_hw(bit, mask); | ||
501 | sable_lynx_irq_swizzle->ack_irq_hw(bit); | ||
502 | spin_unlock(&sable_lynx_irq_lock); | ||
503 | } | ||
504 | |||
505 | static struct hw_interrupt_type sable_lynx_irq_type = { | ||
506 | .typename = "SABLE/LYNX", | ||
507 | .startup = sable_lynx_startup_irq, | ||
508 | .shutdown = sable_lynx_disable_irq, | ||
509 | .enable = sable_lynx_enable_irq, | ||
510 | .disable = sable_lynx_disable_irq, | ||
511 | .ack = sable_lynx_mask_and_ack_irq, | ||
512 | .end = sable_lynx_end_irq, | ||
513 | }; | ||
514 | |||
515 | static void | ||
516 | sable_lynx_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) | ||
517 | { | ||
518 | /* Note that the vector reported by the SRM PALcode corresponds | ||
519 | to the interrupt mask bits, but we have to manage via the | ||
520 | so-called legacy IRQs for many common devices. */ | ||
521 | |||
522 | int bit, irq; | ||
523 | |||
524 | bit = (vector - 0x800) >> 4; | ||
525 | irq = sable_lynx_irq_swizzle->mask_to_irq[bit]; | ||
526 | #if 0 | ||
527 | printk("%s: vector 0x%lx bit 0x%x irq 0x%x\n", | ||
528 | __FUNCTION__, vector, bit, irq); | ||
529 | #endif | ||
530 | handle_irq(irq, regs); | ||
531 | } | ||
532 | |||
533 | static void __init | ||
534 | sable_lynx_init_irq(int nr_irqs) | ||
535 | { | ||
536 | long i; | ||
537 | |||
538 | for (i = 0; i < nr_irqs; ++i) { | ||
539 | irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; | ||
540 | irq_desc[i].handler = &sable_lynx_irq_type; | ||
541 | } | ||
542 | |||
543 | common_init_isa_dma(); | ||
544 | } | ||
545 | |||
546 | static void __init | ||
547 | sable_lynx_init_pci(void) | ||
548 | { | ||
549 | common_init_pci(); | ||
550 | } | ||
551 | |||
552 | /*****************************************************************/ | ||
553 | /* | ||
554 | * The System Vectors | ||
555 | * | ||
556 | * In order that T2_HAE_ADDRESS should be a constant, we play | ||
557 | * these games with GAMMA_BIAS. | ||
558 | */ | ||
559 | |||
560 | #if defined(CONFIG_ALPHA_GENERIC) || \ | ||
561 | (defined(CONFIG_ALPHA_SABLE) && !defined(CONFIG_ALPHA_GAMMA)) | ||
562 | #undef GAMMA_BIAS | ||
563 | #define GAMMA_BIAS 0 | ||
564 | struct alpha_machine_vector sable_mv __initmv = { | ||
565 | .vector_name = "Sable", | ||
566 | DO_EV4_MMU, | ||
567 | DO_DEFAULT_RTC, | ||
568 | DO_T2_IO, | ||
569 | .machine_check = t2_machine_check, | ||
570 | .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS, | ||
571 | .min_io_address = EISA_DEFAULT_IO_BASE, | ||
572 | .min_mem_address = T2_DEFAULT_MEM_BASE, | ||
573 | |||
574 | .nr_irqs = 40, | ||
575 | .device_interrupt = sable_lynx_srm_device_interrupt, | ||
576 | |||
577 | .init_arch = t2_init_arch, | ||
578 | .init_irq = sable_init_irq, | ||
579 | .init_rtc = common_init_rtc, | ||
580 | .init_pci = sable_lynx_init_pci, | ||
581 | .kill_arch = t2_kill_arch, | ||
582 | .pci_map_irq = sable_map_irq, | ||
583 | .pci_swizzle = common_swizzle, | ||
584 | |||
585 | .sys = { .t2 = { | ||
586 | .gamma_bias = 0 | ||
587 | } } | ||
588 | }; | ||
589 | ALIAS_MV(sable) | ||
590 | #endif /* GENERIC || (SABLE && !GAMMA) */ | ||
591 | |||
592 | #if defined(CONFIG_ALPHA_GENERIC) || \ | ||
593 | (defined(CONFIG_ALPHA_SABLE) && defined(CONFIG_ALPHA_GAMMA)) | ||
594 | #undef GAMMA_BIAS | ||
595 | #define GAMMA_BIAS _GAMMA_BIAS | ||
596 | struct alpha_machine_vector sable_gamma_mv __initmv = { | ||
597 | .vector_name = "Sable-Gamma", | ||
598 | DO_EV5_MMU, | ||
599 | DO_DEFAULT_RTC, | ||
600 | DO_T2_IO, | ||
601 | .machine_check = t2_machine_check, | ||
602 | .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS, | ||
603 | .min_io_address = EISA_DEFAULT_IO_BASE, | ||
604 | .min_mem_address = T2_DEFAULT_MEM_BASE, | ||
605 | |||
606 | .nr_irqs = 40, | ||
607 | .device_interrupt = sable_lynx_srm_device_interrupt, | ||
608 | |||
609 | .init_arch = t2_init_arch, | ||
610 | .init_irq = sable_init_irq, | ||
611 | .init_rtc = common_init_rtc, | ||
612 | .init_pci = sable_lynx_init_pci, | ||
613 | .kill_arch = t2_kill_arch, | ||
614 | .pci_map_irq = sable_map_irq, | ||
615 | .pci_swizzle = common_swizzle, | ||
616 | |||
617 | .sys = { .t2 = { | ||
618 | .gamma_bias = _GAMMA_BIAS | ||
619 | } } | ||
620 | }; | ||
621 | ALIAS_MV(sable_gamma) | ||
622 | #endif /* GENERIC || (SABLE && GAMMA) */ | ||
623 | |||
624 | #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX) | ||
625 | #undef GAMMA_BIAS | ||
626 | #define GAMMA_BIAS _GAMMA_BIAS | ||
627 | struct alpha_machine_vector lynx_mv __initmv = { | ||
628 | .vector_name = "Lynx", | ||
629 | DO_EV4_MMU, | ||
630 | DO_DEFAULT_RTC, | ||
631 | DO_T2_IO, | ||
632 | .machine_check = t2_machine_check, | ||
633 | .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS, | ||
634 | .min_io_address = EISA_DEFAULT_IO_BASE, | ||
635 | .min_mem_address = T2_DEFAULT_MEM_BASE, | ||
636 | |||
637 | .nr_irqs = 64, | ||
638 | .device_interrupt = sable_lynx_srm_device_interrupt, | ||
639 | |||
640 | .init_arch = t2_init_arch, | ||
641 | .init_irq = lynx_init_irq, | ||
642 | .init_rtc = common_init_rtc, | ||
643 | .init_pci = sable_lynx_init_pci, | ||
644 | .kill_arch = t2_kill_arch, | ||
645 | .pci_map_irq = lynx_map_irq, | ||
646 | .pci_swizzle = lynx_swizzle, | ||
647 | |||
648 | .sys = { .t2 = { | ||
649 | .gamma_bias = _GAMMA_BIAS | ||
650 | } } | ||
651 | }; | ||
652 | ALIAS_MV(lynx) | ||
653 | #endif /* GENERIC || LYNX */ | ||