1
2
3
4
5
6
7
8
9
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/mm.h>
14#include <linux/sched.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17
18#include <asm/ptrace.h>
19#include <asm/system.h>
20#include <asm/dma.h>
21#include <asm/irq.h>
22#include <asm/mmu_context.h>
23#include <asm/io.h>
24#include <asm/pgtable.h>
25#include <asm/core_t2.h>
26#include <asm/tlbflush.h>
27
28#include "proto.h"
29#include "irq_impl.h"
30#include "pci_impl.h"
31#include "machvec_impl.h"
32
33DEFINE_SPINLOCK(sable_lynx_irq_lock);
34
35typedef struct irq_swizzle_struct
36{
37 char irq_to_mask[64];
38 char mask_to_irq[64];
39
40
41 unsigned long shadow_mask;
42
43 void (*update_irq_hw)(unsigned long bit, unsigned long mask);
44 void (*ack_irq_hw)(unsigned long bit);
45
46} irq_swizzle_t;
47
48static irq_swizzle_t *sable_lynx_irq_swizzle;
49
50static void sable_lynx_init_irq(int nr_of_irqs);
51
52#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE)
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93static void
94sable_update_irq_hw(unsigned long bit, unsigned long mask)
95{
96 int port = 0x537;
97
98 if (bit >= 16) {
99 port = 0x53d;
100 mask >>= 16;
101 } else if (bit >= 8) {
102 port = 0x53b;
103 mask >>= 8;
104 }
105
106 outb(mask, port);
107}
108
109static void
110sable_ack_irq_hw(unsigned long bit)
111{
112 int port, val1, val2;
113
114 if (bit >= 16) {
115 port = 0x53c;
116 val1 = 0xE0 | (bit - 16);
117 val2 = 0xE0 | 4;
118 } else if (bit >= 8) {
119 port = 0x53a;
120 val1 = 0xE0 | (bit - 8);
121 val2 = 0xE0 | 3;
122 } else {
123 port = 0x536;
124 val1 = 0xE0 | (bit - 0);
125 val2 = 0xE0 | 1;
126 }
127
128 outb(val1, port);
129 outb(val2, 0x534);
130}
131
132static irq_swizzle_t sable_irq_swizzle = {
133 {
134 -1, 6, -1, 8, 15, 12, 7, 9,
135 -1, 16, 17, 18, 3, -1, 21, 22,
136 -1, -1, -1, -1, -1, -1, -1, -1,
137 -1, -1, -1, -1, -1, -1, -1, -1,
138 2, 1, 0, 4, 5, -1, -1, -1,
139 -1, -1, -1, -1, -1, -1, -1, -1,
140 -1, -1, -1, -1, -1, -1, -1, -1,
141 -1, -1, -1, -1, -1, -1, -1, -1
142 },
143 {
144 34, 33, 32, 12, 35, 36, 1, 6,
145 3, 7, -1, -1, 5, -1, -1, 4,
146 9, 10, 11, -1, -1, 14, 15, -1,
147 -1, -1, -1, -1, -1, -1, -1, -1,
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 },
153 -1,
154 sable_update_irq_hw,
155 sable_ack_irq_hw
156};
157
158static void __init
159sable_init_irq(void)
160{
161 outb(-1, 0x537);
162 outb(-1, 0x53b);
163 outb(-1, 0x53d);
164 outb(0x44, 0x535);
165
166 sable_lynx_irq_swizzle = &sable_irq_swizzle;
167 sable_lynx_init_irq(40);
168}
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196static int __init
197sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
198{
199 static char irq_tab[9][5] __initdata = {
200
201 { 32+0, 32+0, 32+0, 32+0, 32+0},
202 { 32+1, 32+1, 32+1, 32+1, 32+1},
203 { -1, -1, -1, -1, -1},
204 { -1, -1, -1, -1, -1},
205 { -1, -1, -1, -1, -1},
206 { -1, -1, -1, -1, -1},
207 { 32+2, 32+2, 32+2, 32+2, 32+2},
208 { 32+3, 32+3, 32+3, 32+3, 32+3},
209 { 32+4, 32+4, 32+4, 32+4, 32+4}
210 };
211 long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;
212 return COMMON_TABLE_LOOKUP;
213}
214#endif
215
216#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX)
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292static void
293lynx_update_irq_hw(unsigned long bit, unsigned long mask)
294{
295
296
297
298
299 *(vulp)T2_AIR = 0x40;
300 mb();
301 *(vulp)T2_AIR;
302 mb();
303 *(vulp)T2_DIR = mask;
304 mb();
305 mb();
306}
307
308static void
309lynx_ack_irq_hw(unsigned long bit)
310{
311 *(vulp)T2_VAR = (u_long) bit;
312 mb();
313 mb();
314}
315
316static irq_swizzle_t lynx_irq_swizzle = {
317 {
318 -1, 6, -1, 8, 15, 12, 7, 9,
319 -1, 16, 17, 18, 3, -1, 21, 22,
320 -1, -1, -1, -1, -1, -1, -1, -1,
321 -1, -1, -1, -1, 28, -1, -1, -1,
322 32, 33, 34, 35, 36, 37, 38, 39,
323 40, 41, 42, 43, 44, 45, 46, 47,
324 48, 49, 50, 51, 52, 53, 54, 55,
325 56, 57, 58, 59, 60, 61, 62, 63
326 },
327 {
328 -1, -1, -1, 12, -1, -1, 1, 6,
329 3, 7, -1, -1, 5, -1, -1, 4,
330 9, 10, 11, -1, -1, 14, 15, -1,
331 -1, -1, -1, -1, 28, -1, -1, -1,
332 32, 33, 34, 35, 36, 37, 38, 39,
333 40, 41, 42, 43, 44, 45, 46, 47,
334 48, 49, 50, 51, 52, 53, 54, 55,
335 56, 57, 58, 59, 60, 61, 62, 63
336 },
337 -1,
338 lynx_update_irq_hw,
339 lynx_ack_irq_hw
340};
341
342static void __init
343lynx_init_irq(void)
344{
345 sable_lynx_irq_swizzle = &lynx_irq_swizzle;
346 sable_lynx_init_irq(64);
347}
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378static int __init
379lynx_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
380{
381 static char irq_tab[19][5] __initdata = {
382
383 { -1, -1, -1, -1, -1},
384 { -1, -1, -1, -1, -1},
385 { 28, 28, 28, 28, 28},
386 { -1, -1, -1, -1, -1},
387 { 32, 32, 33, 34, 35},
388 { 36, 36, 37, 38, 39},
389 { 40, 40, 41, 42, 43},
390 { 44, 44, 45, 46, 47},
391 { -1, -1, -1, -1, -1},
392
393 { -1, -1, -1, -1, -1},
394 { 28, 28, 28, 28, 28},
395 { -1, -1, -1, -1, -1},
396 { -1, -1, -1, -1, -1},
397 { -1, -1, -1, -1, -1},
398 { -1, -1, -1, -1, -1},
399 { 48, 48, 49, 50, 51},
400 { 52, 52, 53, 54, 55},
401 { 56, 56, 57, 58, 59},
402 { 60, 60, 61, 62, 63}
403 };
404 const long min_idsel = 2, max_idsel = 20, irqs_per_slot = 5;
405 return COMMON_TABLE_LOOKUP;
406}
407
408static u8 __init
409lynx_swizzle(struct pci_dev *dev, u8 *pinp)
410{
411 int slot, pin = *pinp;
412
413 if (dev->bus->number == 0) {
414 slot = PCI_SLOT(dev->devfn);
415 }
416
417 else if (PCI_SLOT(dev->bus->self->devfn) == 3) {
418 slot = PCI_SLOT(dev->devfn) + 11;
419 }
420 else
421 {
422
423 do {
424 if (PCI_SLOT(dev->bus->self->devfn) == 3) {
425 slot = PCI_SLOT(dev->devfn) + 11;
426 break;
427 }
428 pin = pci_swizzle_interrupt_pin(dev, pin);
429
430
431 dev = dev->bus->self;
432
433 slot = PCI_SLOT(dev->devfn);
434 } while (dev->bus->self);
435 }
436 *pinp = pin;
437 return slot;
438}
439
440#endif
441
442
443
444
445static inline void
446sable_lynx_enable_irq(unsigned int irq)
447{
448 unsigned long bit, mask;
449
450 bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
451 spin_lock(&sable_lynx_irq_lock);
452 mask = sable_lynx_irq_swizzle->shadow_mask &= ~(1UL << bit);
453 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
454 spin_unlock(&sable_lynx_irq_lock);
455#if 0
456 printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n",
457 __func__, mask, bit, irq);
458#endif
459}
460
461static void
462sable_lynx_disable_irq(unsigned int irq)
463{
464 unsigned long bit, mask;
465
466 bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
467 spin_lock(&sable_lynx_irq_lock);
468 mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
469 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
470 spin_unlock(&sable_lynx_irq_lock);
471#if 0
472 printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n",
473 __func__, mask, bit, irq);
474#endif
475}
476
477static unsigned int
478sable_lynx_startup_irq(unsigned int irq)
479{
480 sable_lynx_enable_irq(irq);
481 return 0;
482}
483
484static void
485sable_lynx_end_irq(unsigned int irq)
486{
487 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
488 sable_lynx_enable_irq(irq);
489}
490
491static void
492sable_lynx_mask_and_ack_irq(unsigned int irq)
493{
494 unsigned long bit, mask;
495
496 bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
497 spin_lock(&sable_lynx_irq_lock);
498 mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
499 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
500 sable_lynx_irq_swizzle->ack_irq_hw(bit);
501 spin_unlock(&sable_lynx_irq_lock);
502}
503
504static struct irq_chip sable_lynx_irq_type = {
505 .name = "SABLE/LYNX",
506 .startup = sable_lynx_startup_irq,
507 .shutdown = sable_lynx_disable_irq,
508 .enable = sable_lynx_enable_irq,
509 .disable = sable_lynx_disable_irq,
510 .ack = sable_lynx_mask_and_ack_irq,
511 .end = sable_lynx_end_irq,
512};
513
514static void
515sable_lynx_srm_device_interrupt(unsigned long vector)
516{
517
518
519
520
521 int bit, irq;
522
523 bit = (vector - 0x800) >> 4;
524 irq = sable_lynx_irq_swizzle->mask_to_irq[bit];
525#if 0
526 printk("%s: vector 0x%lx bit 0x%x irq 0x%x\n",
527 __func__, vector, bit, irq);
528#endif
529 handle_irq(irq);
530}
531
532static void __init
533sable_lynx_init_irq(int nr_of_irqs)
534{
535 long i;
536
537 for (i = 0; i < nr_of_irqs; ++i) {
538 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
539 irq_desc[i].chip = &sable_lynx_irq_type;
540 }
541
542 common_init_isa_dma();
543}
544
545static void __init
546sable_lynx_init_pci(void)
547{
548 common_init_pci();
549}
550
551
552
553
554
555
556
557
558
559#if defined(CONFIG_ALPHA_GENERIC) || \
560 (defined(CONFIG_ALPHA_SABLE) && !defined(CONFIG_ALPHA_GAMMA))
561#undef GAMMA_BIAS
562#define GAMMA_BIAS 0
563struct alpha_machine_vector sable_mv __initmv = {
564 .vector_name = "Sable",
565 DO_EV4_MMU,
566 DO_DEFAULT_RTC,
567 DO_T2_IO,
568 .machine_check = t2_machine_check,
569 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
570 .min_io_address = EISA_DEFAULT_IO_BASE,
571 .min_mem_address = T2_DEFAULT_MEM_BASE,
572
573 .nr_irqs = 40,
574 .device_interrupt = sable_lynx_srm_device_interrupt,
575
576 .init_arch = t2_init_arch,
577 .init_irq = sable_init_irq,
578 .init_rtc = common_init_rtc,
579 .init_pci = sable_lynx_init_pci,
580 .kill_arch = t2_kill_arch,
581 .pci_map_irq = sable_map_irq,
582 .pci_swizzle = common_swizzle,
583
584 .sys = { .t2 = {
585 .gamma_bias = 0
586 } }
587};
588ALIAS_MV(sable)
589#endif
590
591#if defined(CONFIG_ALPHA_GENERIC) || \
592 (defined(CONFIG_ALPHA_SABLE) && defined(CONFIG_ALPHA_GAMMA))
593#undef GAMMA_BIAS
594#define GAMMA_BIAS _GAMMA_BIAS
595struct alpha_machine_vector sable_gamma_mv __initmv = {
596 .vector_name = "Sable-Gamma",
597 DO_EV5_MMU,
598 DO_DEFAULT_RTC,
599 DO_T2_IO,
600 .machine_check = t2_machine_check,
601 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
602 .min_io_address = EISA_DEFAULT_IO_BASE,
603 .min_mem_address = T2_DEFAULT_MEM_BASE,
604
605 .nr_irqs = 40,
606 .device_interrupt = sable_lynx_srm_device_interrupt,
607
608 .init_arch = t2_init_arch,
609 .init_irq = sable_init_irq,
610 .init_rtc = common_init_rtc,
611 .init_pci = sable_lynx_init_pci,
612 .kill_arch = t2_kill_arch,
613 .pci_map_irq = sable_map_irq,
614 .pci_swizzle = common_swizzle,
615
616 .sys = { .t2 = {
617 .gamma_bias = _GAMMA_BIAS
618 } }
619};
620ALIAS_MV(sable_gamma)
621#endif
622
623#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX)
624#undef GAMMA_BIAS
625#define GAMMA_BIAS _GAMMA_BIAS
626struct alpha_machine_vector lynx_mv __initmv = {
627 .vector_name = "Lynx",
628 DO_EV4_MMU,
629 DO_DEFAULT_RTC,
630 DO_T2_IO,
631 .machine_check = t2_machine_check,
632 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
633 .min_io_address = EISA_DEFAULT_IO_BASE,
634 .min_mem_address = T2_DEFAULT_MEM_BASE,
635
636 .nr_irqs = 64,
637 .device_interrupt = sable_lynx_srm_device_interrupt,
638
639 .init_arch = t2_init_arch,
640 .init_irq = lynx_init_irq,
641 .init_rtc = common_init_rtc,
642 .init_pci = sable_lynx_init_pci,
643 .kill_arch = t2_kill_arch,
644 .pci_map_irq = lynx_map_irq,
645 .pci_swizzle = lynx_swizzle,
646
647 .sys = { .t2 = {
648 .gamma_bias = _GAMMA_BIAS
649 } }
650};
651ALIAS_MV(lynx)
652#endif
653