1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/mm.h>
18#include <linux/sched.h>
19#include <linux/pci.h>
20#include <linux/init.h>
21#include <linux/bitops.h>
22
23#include <asm/ptrace.h>
24#include <asm/system.h>
25#include <asm/dma.h>
26#include <asm/irq.h>
27#include <asm/mmu_context.h>
28#include <asm/io.h>
29#include <asm/pgtable.h>
30#include <asm/core_tsunami.h>
31#include <asm/hwrpb.h>
32#include <asm/tlbflush.h>
33
34#include "proto.h"
35#include "irq_impl.h"
36#include "pci_impl.h"
37#include "machvec_impl.h"
38
39
40
41static unsigned long cached_irq_mask;
42
43static unsigned long cpu_irq_affinity[4] = { 0UL, 0UL, 0UL, 0UL };
44
45DEFINE_SPINLOCK(dp264_irq_lock);
46
47static void
48tsunami_update_irq_hw(unsigned long mask)
49{
50 register tsunami_cchip *cchip = TSUNAMI_cchip;
51 unsigned long isa_enable = 1UL << 55;
52 register int bcpu = boot_cpuid;
53
54#ifdef CONFIG_SMP
55 volatile unsigned long *dim0, *dim1, *dim2, *dim3;
56 unsigned long mask0, mask1, mask2, mask3, dummy;
57
58 mask &= ~isa_enable;
59 mask0 = mask & cpu_irq_affinity[0];
60 mask1 = mask & cpu_irq_affinity[1];
61 mask2 = mask & cpu_irq_affinity[2];
62 mask3 = mask & cpu_irq_affinity[3];
63
64 if (bcpu == 0) mask0 |= isa_enable;
65 else if (bcpu == 1) mask1 |= isa_enable;
66 else if (bcpu == 2) mask2 |= isa_enable;
67 else mask3 |= isa_enable;
68
69 dim0 = &cchip->dim0.csr;
70 dim1 = &cchip->dim1.csr;
71 dim2 = &cchip->dim2.csr;
72 dim3 = &cchip->dim3.csr;
73 if (!cpu_possible(0)) dim0 = &dummy;
74 if (!cpu_possible(1)) dim1 = &dummy;
75 if (!cpu_possible(2)) dim2 = &dummy;
76 if (!cpu_possible(3)) dim3 = &dummy;
77
78 *dim0 = mask0;
79 *dim1 = mask1;
80 *dim2 = mask2;
81 *dim3 = mask3;
82 mb();
83 *dim0;
84 *dim1;
85 *dim2;
86 *dim3;
87#else
88 volatile unsigned long *dimB;
89 if (bcpu == 0) dimB = &cchip->dim0.csr;
90 else if (bcpu == 1) dimB = &cchip->dim1.csr;
91 else if (bcpu == 2) dimB = &cchip->dim2.csr;
92 else dimB = &cchip->dim3.csr;
93
94 *dimB = mask | isa_enable;
95 mb();
96 *dimB;
97#endif
98}
99
100static void
101dp264_enable_irq(unsigned int irq)
102{
103 spin_lock(&dp264_irq_lock);
104 cached_irq_mask |= 1UL << irq;
105 tsunami_update_irq_hw(cached_irq_mask);
106 spin_unlock(&dp264_irq_lock);
107}
108
109static void
110dp264_disable_irq(unsigned int irq)
111{
112 spin_lock(&dp264_irq_lock);
113 cached_irq_mask &= ~(1UL << irq);
114 tsunami_update_irq_hw(cached_irq_mask);
115 spin_unlock(&dp264_irq_lock);
116}
117
118static unsigned int
119dp264_startup_irq(unsigned int irq)
120{
121 dp264_enable_irq(irq);
122 return 0;
123}
124
125static void
126dp264_end_irq(unsigned int irq)
127{
128 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
129 dp264_enable_irq(irq);
130}
131
132static void
133clipper_enable_irq(unsigned int irq)
134{
135 spin_lock(&dp264_irq_lock);
136 cached_irq_mask |= 1UL << (irq - 16);
137 tsunami_update_irq_hw(cached_irq_mask);
138 spin_unlock(&dp264_irq_lock);
139}
140
141static void
142clipper_disable_irq(unsigned int irq)
143{
144 spin_lock(&dp264_irq_lock);
145 cached_irq_mask &= ~(1UL << (irq - 16));
146 tsunami_update_irq_hw(cached_irq_mask);
147 spin_unlock(&dp264_irq_lock);
148}
149
150static unsigned int
151clipper_startup_irq(unsigned int irq)
152{
153 clipper_enable_irq(irq);
154 return 0;
155}
156
157static void
158clipper_end_irq(unsigned int irq)
159{
160 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
161 clipper_enable_irq(irq);
162}
163
164static void
165cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
166{
167 int cpu;
168
169 for (cpu = 0; cpu < 4; cpu++) {
170 unsigned long aff = cpu_irq_affinity[cpu];
171 if (cpu_isset(cpu, affinity))
172 aff |= 1UL << irq;
173 else
174 aff &= ~(1UL << irq);
175 cpu_irq_affinity[cpu] = aff;
176 }
177}
178
179static void
180dp264_set_affinity(unsigned int irq, const struct cpumask *affinity)
181{
182 spin_lock(&dp264_irq_lock);
183 cpu_set_irq_affinity(irq, *affinity);
184 tsunami_update_irq_hw(cached_irq_mask);
185 spin_unlock(&dp264_irq_lock);
186}
187
188static void
189clipper_set_affinity(unsigned int irq, const struct cpumask *affinity)
190{
191 spin_lock(&dp264_irq_lock);
192 cpu_set_irq_affinity(irq - 16, *affinity);
193 tsunami_update_irq_hw(cached_irq_mask);
194 spin_unlock(&dp264_irq_lock);
195}
196
197static struct hw_interrupt_type dp264_irq_type = {
198 .typename = "DP264",
199 .startup = dp264_startup_irq,
200 .shutdown = dp264_disable_irq,
201 .enable = dp264_enable_irq,
202 .disable = dp264_disable_irq,
203 .ack = dp264_disable_irq,
204 .end = dp264_end_irq,
205 .set_affinity = dp264_set_affinity,
206};
207
208static struct hw_interrupt_type clipper_irq_type = {
209 .typename = "CLIPPER",
210 .startup = clipper_startup_irq,
211 .shutdown = clipper_disable_irq,
212 .enable = clipper_enable_irq,
213 .disable = clipper_disable_irq,
214 .ack = clipper_disable_irq,
215 .end = clipper_end_irq,
216 .set_affinity = clipper_set_affinity,
217};
218
219static void
220dp264_device_interrupt(unsigned long vector)
221{
222#if 1
223 printk("dp264_device_interrupt: NOT IMPLEMENTED YET!! \n");
224#else
225 unsigned long pld;
226 unsigned int i;
227
228
229 pld = TSUNAMI_cchip->dir0.csr;
230
231
232
233
234
235 while (pld) {
236 i = ffz(~pld);
237 pld &= pld - 1;
238 if (i == 55)
239 isa_device_interrupt(vector);
240 else
241 handle_irq(16 + i);
242#if 0
243 TSUNAMI_cchip->dir0.csr = 1UL << i; mb();
244 tmp = TSUNAMI_cchip->dir0.csr;
245#endif
246 }
247#endif
248}
249
250static void
251dp264_srm_device_interrupt(unsigned long vector)
252{
253 int irq;
254
255 irq = (vector - 0x800) >> 4;
256
257
258
259
260
261
262
263
264
265
266
267
268 if (irq >= 32)
269 irq -= 16;
270
271 handle_irq(irq);
272}
273
274static void
275clipper_srm_device_interrupt(unsigned long vector)
276{
277 int irq;
278
279 irq = (vector - 0x800) >> 4;
280
281
282
283
284
285
286
287
288
289
290
291
292
293 handle_irq(irq);
294}
295
296static void __init
297init_tsunami_irqs(struct hw_interrupt_type * ops, int imin, int imax)
298{
299 long i;
300 for (i = imin; i <= imax; ++i) {
301 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
302 irq_desc[i].chip = ops;
303 }
304}
305
306static void __init
307dp264_init_irq(void)
308{
309 outb(0, DMA1_RESET_REG);
310 outb(0, DMA2_RESET_REG);
311 outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
312 outb(0, DMA2_MASK_REG);
313
314 if (alpha_using_srm)
315 alpha_mv.device_interrupt = dp264_srm_device_interrupt;
316
317 tsunami_update_irq_hw(0);
318
319 init_i8259a_irqs();
320 init_tsunami_irqs(&dp264_irq_type, 16, 47);
321}
322
323static void __init
324clipper_init_irq(void)
325{
326 outb(0, DMA1_RESET_REG);
327 outb(0, DMA2_RESET_REG);
328 outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
329 outb(0, DMA2_MASK_REG);
330
331 if (alpha_using_srm)
332 alpha_mv.device_interrupt = clipper_srm_device_interrupt;
333
334 tsunami_update_irq_hw(0);
335
336 init_i8259a_irqs();
337 init_tsunami_irqs(&clipper_irq_type, 24, 63);
338}
339
340
341
342
343
344
345
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
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396static int __init
397isa_irq_fixup(struct pci_dev *dev, int irq)
398{
399 u8 irq8;
400
401 if (irq > 0)
402 return irq;
403
404
405
406
407 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8);
408
409 return irq8 & 0xf;
410}
411
412static int __init
413dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
414{
415 static char irq_tab[6][5] __initdata = {
416
417 { -1, -1, -1, -1, -1},
418 { 16+ 3, 16+ 3, 16+ 2, 16+ 2, 16+ 2},
419 { 16+15, 16+15, 16+14, 16+13, 16+12},
420 { 16+11, 16+11, 16+10, 16+ 9, 16+ 8},
421 { 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4},
422 { 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0}
423 };
424 const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
425 struct pci_controller *hose = dev->sysdata;
426 int irq = COMMON_TABLE_LOOKUP;
427
428 if (irq > 0)
429 irq += 16 * hose->index;
430
431 return isa_irq_fixup(dev, irq);
432}
433
434static int __init
435monet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
436{
437 static char irq_tab[13][5] __initdata = {
438
439 { 45, 45, 45, 45, 45},
440 { -1, -1, -1, -1, -1},
441 { -1, -1, -1, -1, -1},
442 { 47, 47, 47, 47, 47},
443 { -1, -1, -1, -1, -1},
444 { -1, -1, -1, -1, -1},
445#if 1
446 { 28, 28, 29, 30, 31},
447 { 24, 24, 25, 26, 27},
448#else
449 { -1, -1, -1, -1, -1},
450 { -1, -1, -1, -1, -1},
451#endif
452 { 40, 40, 41, 42, 43},
453 { 36, 36, 37, 38, 39},
454 { 32, 32, 33, 34, 35},
455 { 28, 28, 29, 30, 31},
456 { 24, 24, 25, 26, 27}
457 };
458 const long min_idsel = 3, max_idsel = 15, irqs_per_slot = 5;
459
460 return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
461}
462
463static u8 __init
464monet_swizzle(struct pci_dev *dev, u8 *pinp)
465{
466 struct pci_controller *hose = dev->sysdata;
467 int slot, pin = *pinp;
468
469 if (!dev->bus->parent) {
470 slot = PCI_SLOT(dev->devfn);
471 }
472
473 else if (hose->index == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) {
474 slot = PCI_SLOT(dev->devfn);
475 } else {
476
477 do {
478
479 if (hose->index == 1 &&
480 PCI_SLOT(dev->bus->self->devfn) == 8) {
481 slot = PCI_SLOT(dev->devfn);
482 break;
483 }
484 pin = pci_swizzle_interrupt_pin(dev, pin);
485
486
487 dev = dev->bus->self;
488
489 slot = PCI_SLOT(dev->devfn);
490 } while (dev->bus->self);
491 }
492 *pinp = pin;
493 return slot;
494}
495
496static int __init
497webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
498{
499 static char irq_tab[13][5] __initdata = {
500
501 { -1, -1, -1, -1, -1},
502 { -1, -1, -1, -1, -1},
503 { 29, 29, 29, 29, 29},
504 { -1, -1, -1, -1, -1},
505 { 30, 30, 30, 30, 30},
506 { -1, -1, -1, -1, -1},
507 { -1, -1, -1, -1, -1},
508 { 35, 35, 34, 33, 32},
509 { 39, 39, 38, 37, 36},
510 { 43, 43, 42, 41, 40},
511 { 47, 47, 46, 45, 44},
512 };
513 const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5;
514
515 return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
516}
517
518static int __init
519clipper_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
520{
521 static char irq_tab[7][5] __initdata = {
522
523 { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11},
524 { 16+12, 16+12, 16+13, 16+14, 16+15},
525 { 16+16, 16+16, 16+17, 16+18, 16+19},
526 { 16+20, 16+20, 16+21, 16+22, 16+23},
527 { 16+24, 16+24, 16+25, 16+26, 16+27},
528 { 16+28, 16+28, 16+29, 16+30, 16+31},
529 { -1, -1, -1, -1, -1}
530 };
531 const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5;
532 struct pci_controller *hose = dev->sysdata;
533 int irq = COMMON_TABLE_LOOKUP;
534
535 if (irq > 0)
536 irq += 16 * hose->index;
537
538 return isa_irq_fixup(dev, irq);
539}
540
541static void __init
542dp264_init_pci(void)
543{
544 common_init_pci();
545 SMC669_Init(0);
546 locate_and_init_vga(NULL);
547}
548
549static void __init
550monet_init_pci(void)
551{
552 common_init_pci();
553 SMC669_Init(1);
554 es1888_init();
555 locate_and_init_vga(NULL);
556}
557
558static void __init
559clipper_init_pci(void)
560{
561 common_init_pci();
562 locate_and_init_vga(NULL);
563}
564
565static void __init
566webbrick_init_arch(void)
567{
568 tsunami_init_arch();
569
570
571 hose_head->sg_isa->align_entry = 4;
572 hose_head->sg_pci->align_entry = 4;
573}
574
575
576
577
578
579
580struct alpha_machine_vector dp264_mv __initmv = {
581 .vector_name = "DP264",
582 DO_EV6_MMU,
583 DO_DEFAULT_RTC,
584 DO_TSUNAMI_IO,
585 .machine_check = tsunami_machine_check,
586 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
587 .min_io_address = DEFAULT_IO_BASE,
588 .min_mem_address = DEFAULT_MEM_BASE,
589 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
590
591 .nr_irqs = 64,
592 .device_interrupt = dp264_device_interrupt,
593
594 .init_arch = tsunami_init_arch,
595 .init_irq = dp264_init_irq,
596 .init_rtc = common_init_rtc,
597 .init_pci = dp264_init_pci,
598 .kill_arch = tsunami_kill_arch,
599 .pci_map_irq = dp264_map_irq,
600 .pci_swizzle = common_swizzle,
601};
602ALIAS_MV(dp264)
603
604struct alpha_machine_vector monet_mv __initmv = {
605 .vector_name = "Monet",
606 DO_EV6_MMU,
607 DO_DEFAULT_RTC,
608 DO_TSUNAMI_IO,
609 .machine_check = tsunami_machine_check,
610 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
611 .min_io_address = DEFAULT_IO_BASE,
612 .min_mem_address = DEFAULT_MEM_BASE,
613 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
614
615 .nr_irqs = 64,
616 .device_interrupt = dp264_device_interrupt,
617
618 .init_arch = tsunami_init_arch,
619 .init_irq = dp264_init_irq,
620 .init_rtc = common_init_rtc,
621 .init_pci = monet_init_pci,
622 .kill_arch = tsunami_kill_arch,
623 .pci_map_irq = monet_map_irq,
624 .pci_swizzle = monet_swizzle,
625};
626
627struct alpha_machine_vector webbrick_mv __initmv = {
628 .vector_name = "Webbrick",
629 DO_EV6_MMU,
630 DO_DEFAULT_RTC,
631 DO_TSUNAMI_IO,
632 .machine_check = tsunami_machine_check,
633 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
634 .min_io_address = DEFAULT_IO_BASE,
635 .min_mem_address = DEFAULT_MEM_BASE,
636 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
637
638 .nr_irqs = 64,
639 .device_interrupt = dp264_device_interrupt,
640
641 .init_arch = webbrick_init_arch,
642 .init_irq = dp264_init_irq,
643 .init_rtc = common_init_rtc,
644 .init_pci = common_init_pci,
645 .kill_arch = tsunami_kill_arch,
646 .pci_map_irq = webbrick_map_irq,
647 .pci_swizzle = common_swizzle,
648};
649
650struct alpha_machine_vector clipper_mv __initmv = {
651 .vector_name = "Clipper",
652 DO_EV6_MMU,
653 DO_DEFAULT_RTC,
654 DO_TSUNAMI_IO,
655 .machine_check = tsunami_machine_check,
656 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
657 .min_io_address = DEFAULT_IO_BASE,
658 .min_mem_address = DEFAULT_MEM_BASE,
659 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
660
661 .nr_irqs = 64,
662 .device_interrupt = dp264_device_interrupt,
663
664 .init_arch = tsunami_init_arch,
665 .init_irq = clipper_init_irq,
666 .init_rtc = common_init_rtc,
667 .init_pci = clipper_init_pci,
668 .kill_arch = tsunami_kill_arch,
669 .pci_map_irq = clipper_map_irq,
670 .pci_swizzle = common_swizzle,
671};
672
673
674
675
676
677
678struct alpha_machine_vector shark_mv __initmv = {
679 .vector_name = "Shark",
680 DO_EV6_MMU,
681 DO_DEFAULT_RTC,
682 DO_TSUNAMI_IO,
683 .machine_check = tsunami_machine_check,
684 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
685 .min_io_address = DEFAULT_IO_BASE,
686 .min_mem_address = DEFAULT_MEM_BASE,
687 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
688
689 .nr_irqs = 64,
690 .device_interrupt = dp264_device_interrupt,
691
692 .init_arch = tsunami_init_arch,
693 .init_irq = clipper_init_irq,
694 .init_rtc = common_init_rtc,
695 .init_pci = common_init_pci,
696 .kill_arch = tsunami_kill_arch,
697 .pci_map_irq = clipper_map_irq,
698 .pci_swizzle = common_swizzle,
699};
700
701
702
703