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