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/dma.h>
20#include <asm/irq.h>
21#include <asm/mmu_context.h>
22#include <asm/io.h>
23#include <asm/pgtable.h>
24#include <asm/core_t2.h>
25#include <asm/tlbflush.h>
26
27#include "proto.h"
28#include "irq_impl.h"
29#include "pci_impl.h"
30#include "machvec_impl.h"
31
32DEFINE_SPINLOCK(sable_lynx_irq_lock);
33
34typedef struct irq_swizzle_struct
35{
36 char irq_to_mask[64];
37 char mask_to_irq[64];
38
39
40 unsigned long shadow_mask;
41
42 void (*update_irq_hw)(unsigned long bit, unsigned long mask);
43 void (*ack_irq_hw)(unsigned long bit);
44
45} irq_swizzle_t;
46
47static irq_swizzle_t *sable_lynx_irq_swizzle;
48
49static void sable_lynx_init_irq(int nr_of_irqs);
50
51#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE)
52
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
92static void
93sable_update_irq_hw(unsigned long bit, unsigned long mask)
94{
95 int port = 0x537;
96
97 if (bit >= 16) {
98 port = 0x53d;
99 mask >>= 16;
100 } else if (bit >= 8) {
101 port = 0x53b;
102 mask >>= 8;
103 }
104
105 outb(mask, port);
106}
107
108static void
109sable_ack_irq_hw(unsigned long bit)
110{
111 int port, val1, val2;
112
113 if (bit >= 16) {
114 port = 0x53c;
115 val1 = 0xE0 | (bit - 16);
116 val2 = 0xE0 | 4;
117 } else if (bit >= 8) {
118 port = 0x53a;
119 val1 = 0xE0 | (bit - 8);
120 val2 = 0xE0 | 3;
121 } else {
122 port = 0x536;
123 val1 = 0xE0 | (bit - 0);
124 val2 = 0xE0 | 1;
125 }
126
127 outb(val1, port);
128 outb(val2, 0x534);
129}
130
131static irq_swizzle_t sable_irq_swizzle = {
132 {
133 -1, 6, -1, 8, 15, 12, 7, 9,
134 -1, 16, 17, 18, 3, -1, 21, 22,
135 -1, -1, -1, -1, -1, -1, -1, -1,
136 -1, -1, -1, -1, -1, -1, -1, -1,
137 2, 1, 0, 4, 5, -1, -1, -1,
138 -1, -1, -1, -1, -1, -1, -1, -1,
139 -1, -1, -1, -1, -1, -1, -1, -1,
140 -1, -1, -1, -1, -1, -1, -1, -1
141 },
142 {
143 34, 33, 32, 12, 35, 36, 1, 6,
144 3, 7, -1, -1, 5, -1, -1, 4,
145 9, 10, 11, -1, -1, 14, 15, -1,
146 -1, -1, -1, -1, -1, -1, -1, -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 },
152 -1,
153 sable_update_irq_hw,
154 sable_ack_irq_hw
155};
156
157static void __init
158sable_init_irq(void)
159{
160 outb(-1, 0x537);
161 outb(-1, 0x53b);
162 outb(-1, 0x53d);
163 outb(0x44, 0x535);
164
165 sable_lynx_irq_swizzle = &sable_irq_swizzle;
166 sable_lynx_init_irq(40);
167}
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
195static int __init
196sable_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
197{
198 static char irq_tab[9][5] __initdata = {
199
200 { 32+0, 32+0, 32+0, 32+0, 32+0},
201 { 32+1, 32+1, 32+1, 32+1, 32+1},
202 { -1, -1, -1, -1, -1},
203 { -1, -1, -1, -1, -1},
204 { -1, -1, -1, -1, -1},
205 { -1, -1, -1, -1, -1},
206 { 32+2, 32+2, 32+2, 32+2, 32+2},
207 { 32+3, 32+3, 32+3, 32+3, 32+3},
208 { 32+4, 32+4, 32+4, 32+4, 32+4}
209 };
210 long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;
211 return COMMON_TABLE_LOOKUP;
212}
213#endif
214
215#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX)
216
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
291static void
292lynx_update_irq_hw(unsigned long bit, unsigned long mask)
293{
294
295
296
297
298 *(vulp)T2_AIR = 0x40;
299 mb();
300 *(vulp)T2_AIR;
301 mb();
302 *(vulp)T2_DIR = mask;
303 mb();
304 mb();
305}
306
307static void
308lynx_ack_irq_hw(unsigned long bit)
309{
310 *(vulp)T2_VAR = (u_long) bit;
311 mb();
312 mb();
313}
314
315static irq_swizzle_t lynx_irq_swizzle = {
316 {
317 -1, 6, -1, 8, 15, 12, 7, 9,
318 -1, 16, 17, 18, 3, -1, 21, 22,
319 -1, -1, -1, -1, -1, -1, -1, -1,
320 -1, -1, -1, -1, 28, -1, -1, -1,
321 32, 33, 34, 35, 36, 37, 38, 39,
322 40, 41, 42, 43, 44, 45, 46, 47,
323 48, 49, 50, 51, 52, 53, 54, 55,
324 56, 57, 58, 59, 60, 61, 62, 63
325 },
326 {
327 -1, -1, -1, 12, -1, -1, 1, 6,
328 3, 7, -1, -1, 5, -1, -1, 4,
329 9, 10, 11, -1, -1, 14, 15, -1,
330 -1, -1, -1, -1, 28, -1, -1, -1,
331 32, 33, 34, 35, 36, 37, 38, 39,
332 40, 41, 42, 43, 44, 45, 46, 47,
333 48, 49, 50, 51, 52, 53, 54, 55,
334 56, 57, 58, 59, 60, 61, 62, 63
335 },
336 -1,
337 lynx_update_irq_hw,
338 lynx_ack_irq_hw
339};
340
341static void __init
342lynx_init_irq(void)
343{
344 sable_lynx_irq_swizzle = &lynx_irq_swizzle;
345 sable_lynx_init_irq(64);
346}
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
377static int __init
378lynx_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
379{
380 static char irq_tab[19][5] __initdata = {
381
382 { -1, -1, -1, -1, -1},
383 { -1, -1, -1, -1, -1},
384 { 28, 28, 28, 28, 28},
385 { -1, -1, -1, -1, -1},
386 { 32, 32, 33, 34, 35},
387 { 36, 36, 37, 38, 39},
388 { 40, 40, 41, 42, 43},
389 { 44, 44, 45, 46, 47},
390 { -1, -1, -1, -1, -1},
391
392 { -1, -1, -1, -1, -1},
393 { 28, 28, 28, 28, 28},
394 { -1, -1, -1, -1, -1},
395 { -1, -1, -1, -1, -1},
396 { -1, -1, -1, -1, -1},
397 { -1, -1, -1, -1, -1},
398 { 48, 48, 49, 50, 51},
399 { 52, 52, 53, 54, 55},
400 { 56, 56, 57, 58, 59},
401 { 60, 60, 61, 62, 63}
402 };
403 const long min_idsel = 2, max_idsel = 20, irqs_per_slot = 5;
404 return COMMON_TABLE_LOOKUP;
405}
406
407static u8 __init
408lynx_swizzle(struct pci_dev *dev, u8 *pinp)
409{
410 int slot, pin = *pinp;
411
412 if (dev->bus->number == 0) {
413 slot = PCI_SLOT(dev->devfn);
414 }
415
416 else if (PCI_SLOT(dev->bus->self->devfn) == 3) {
417 slot = PCI_SLOT(dev->devfn) + 11;
418 }
419 else
420 {
421
422 do {
423 if (PCI_SLOT(dev->bus->self->devfn) == 3) {
424 slot = PCI_SLOT(dev->devfn) + 11;
425 break;
426 }
427 pin = pci_swizzle_interrupt_pin(dev, pin);
428
429
430 dev = dev->bus->self;
431
432 slot = PCI_SLOT(dev->devfn);
433 } while (dev->bus->self);
434 }
435 *pinp = pin;
436 return slot;
437}
438
439#endif
440
441
442
443
444static inline void
445sable_lynx_enable_irq(struct irq_data *d)
446{
447 unsigned long bit, mask;
448
449 bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];
450 spin_lock(&sable_lynx_irq_lock);
451 mask = sable_lynx_irq_swizzle->shadow_mask &= ~(1UL << bit);
452 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
453 spin_unlock(&sable_lynx_irq_lock);
454#if 0
455 printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n",
456 __func__, mask, bit, irq);
457#endif
458}
459
460static void
461sable_lynx_disable_irq(struct irq_data *d)
462{
463 unsigned long bit, mask;
464
465 bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];
466 spin_lock(&sable_lynx_irq_lock);
467 mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
468 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
469 spin_unlock(&sable_lynx_irq_lock);
470#if 0
471 printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n",
472 __func__, mask, bit, irq);
473#endif
474}
475
476static void
477sable_lynx_mask_and_ack_irq(struct irq_data *d)
478{
479 unsigned long bit, mask;
480
481 bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];
482 spin_lock(&sable_lynx_irq_lock);
483 mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
484 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
485 sable_lynx_irq_swizzle->ack_irq_hw(bit);
486 spin_unlock(&sable_lynx_irq_lock);
487}
488
489static struct irq_chip sable_lynx_irq_type = {
490 .name = "SABLE/LYNX",
491 .irq_unmask = sable_lynx_enable_irq,
492 .irq_mask = sable_lynx_disable_irq,
493 .irq_mask_ack = sable_lynx_mask_and_ack_irq,
494};
495
496static void
497sable_lynx_srm_device_interrupt(unsigned long vector)
498{
499
500
501
502
503 int bit, irq;
504
505 bit = (vector - 0x800) >> 4;
506 irq = sable_lynx_irq_swizzle->mask_to_irq[bit];
507#if 0
508 printk("%s: vector 0x%lx bit 0x%x irq 0x%x\n",
509 __func__, vector, bit, irq);
510#endif
511 handle_irq(irq);
512}
513
514static void __init
515sable_lynx_init_irq(int nr_of_irqs)
516{
517 long i;
518
519 for (i = 0; i < nr_of_irqs; ++i) {
520 irq_set_chip_and_handler(i, &sable_lynx_irq_type,
521 handle_level_irq);
522 irq_set_status_flags(i, IRQ_LEVEL);
523 }
524
525 common_init_isa_dma();
526}
527
528static void __init
529sable_lynx_init_pci(void)
530{
531 common_init_pci();
532}
533
534
535
536
537
538
539
540
541
542#if defined(CONFIG_ALPHA_GENERIC) || \
543 (defined(CONFIG_ALPHA_SABLE) && !defined(CONFIG_ALPHA_GAMMA))
544#undef GAMMA_BIAS
545#define GAMMA_BIAS 0
546struct alpha_machine_vector sable_mv __initmv = {
547 .vector_name = "Sable",
548 DO_EV4_MMU,
549 DO_DEFAULT_RTC,
550 DO_T2_IO,
551 .machine_check = t2_machine_check,
552 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
553 .min_io_address = EISA_DEFAULT_IO_BASE,
554 .min_mem_address = T2_DEFAULT_MEM_BASE,
555
556 .nr_irqs = 40,
557 .device_interrupt = sable_lynx_srm_device_interrupt,
558
559 .init_arch = t2_init_arch,
560 .init_irq = sable_init_irq,
561 .init_rtc = common_init_rtc,
562 .init_pci = sable_lynx_init_pci,
563 .kill_arch = t2_kill_arch,
564 .pci_map_irq = sable_map_irq,
565 .pci_swizzle = common_swizzle,
566
567 .sys = { .t2 = {
568 .gamma_bias = 0
569 } }
570};
571ALIAS_MV(sable)
572#endif
573
574#if defined(CONFIG_ALPHA_GENERIC) || \
575 (defined(CONFIG_ALPHA_SABLE) && defined(CONFIG_ALPHA_GAMMA))
576#undef GAMMA_BIAS
577#define GAMMA_BIAS _GAMMA_BIAS
578struct alpha_machine_vector sable_gamma_mv __initmv = {
579 .vector_name = "Sable-Gamma",
580 DO_EV5_MMU,
581 DO_DEFAULT_RTC,
582 DO_T2_IO,
583 .machine_check = t2_machine_check,
584 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
585 .min_io_address = EISA_DEFAULT_IO_BASE,
586 .min_mem_address = T2_DEFAULT_MEM_BASE,
587
588 .nr_irqs = 40,
589 .device_interrupt = sable_lynx_srm_device_interrupt,
590
591 .init_arch = t2_init_arch,
592 .init_irq = sable_init_irq,
593 .init_rtc = common_init_rtc,
594 .init_pci = sable_lynx_init_pci,
595 .kill_arch = t2_kill_arch,
596 .pci_map_irq = sable_map_irq,
597 .pci_swizzle = common_swizzle,
598
599 .sys = { .t2 = {
600 .gamma_bias = _GAMMA_BIAS
601 } }
602};
603ALIAS_MV(sable_gamma)
604#endif
605
606#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX)
607#undef GAMMA_BIAS
608#define GAMMA_BIAS _GAMMA_BIAS
609struct alpha_machine_vector lynx_mv __initmv = {
610 .vector_name = "Lynx",
611 DO_EV4_MMU,
612 DO_DEFAULT_RTC,
613 DO_T2_IO,
614 .machine_check = t2_machine_check,
615 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
616 .min_io_address = EISA_DEFAULT_IO_BASE,
617 .min_mem_address = T2_DEFAULT_MEM_BASE,
618
619 .nr_irqs = 64,
620 .device_interrupt = sable_lynx_srm_device_interrupt,
621
622 .init_arch = t2_init_arch,
623 .init_irq = lynx_init_irq,
624 .init_rtc = common_init_rtc,
625 .init_pci = sable_lynx_init_pci,
626 .kill_arch = t2_kill_arch,
627 .pci_map_irq = lynx_map_irq,
628 .pci_swizzle = lynx_swizzle,
629
630 .sys = { .t2 = {
631 .gamma_bias = _GAMMA_BIAS
632 } }
633};
634ALIAS_MV(lynx)
635#endif
636