]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/alpha/kernel/sys_miata.c | |
3 | * | |
4 | * Copyright (C) 1995 David A Rusling | |
5 | * Copyright (C) 1996 Jay A Estabrook | |
6 | * Copyright (C) 1998, 1999, 2000 Richard Henderson | |
7 | * | |
8 | * Code supporting the MIATA (EV56+PYXIS). | |
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 | #include <linux/reboot.h> | |
18 | ||
19 | #include <asm/ptrace.h> | |
1da177e4 LT |
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_cia.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 | ||
33 | ||
34 | static void | |
7ca56053 | 35 | miata_srm_device_interrupt(unsigned long vector) |
1da177e4 LT |
36 | { |
37 | int irq; | |
38 | ||
39 | irq = (vector - 0x800) >> 4; | |
40 | ||
41 | /* | |
42 | * I really hate to do this, but the MIATA SRM console ignores the | |
43 | * low 8 bits in the interrupt summary register, and reports the | |
44 | * vector 0x80 *lower* than I expected from the bit numbering in | |
45 | * the documentation. | |
46 | * This was done because the low 8 summary bits really aren't used | |
47 | * for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't | |
48 | * used for this purpose, as PIC interrupts are delivered as the | |
49 | * vectors 0x800-0x8f0). | |
50 | * But I really don't want to change the fixup code for allocation | |
51 | * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which | |
52 | * look nice and clean now. | |
53 | * So, here's this grotty hack... :-( | |
54 | */ | |
55 | if (irq >= 16) | |
56 | irq = irq + 8; | |
57 | ||
3dbb8c62 | 58 | handle_irq(irq); |
1da177e4 LT |
59 | } |
60 | ||
61 | static void __init | |
62 | miata_init_irq(void) | |
63 | { | |
64 | if (alpha_using_srm) | |
65 | alpha_mv.device_interrupt = miata_srm_device_interrupt; | |
66 | ||
67 | #if 0 | |
68 | /* These break on MiataGL so we'll try not to do it at all. */ | |
69 | *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */ | |
70 | *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */ | |
71 | #endif | |
72 | ||
73 | init_i8259a_irqs(); | |
74 | ||
75 | /* Not interested in the bogus interrupts (3,10), Fan Fault (0), | |
76 | NMI (1), or EIDE (9). | |
77 | ||
78 | We also disable the risers (4,5), since we don't know how to | |
79 | route the interrupts behind the bridge. */ | |
80 | init_pyxis_irqs(0x63b0000); | |
81 | ||
82 | common_init_isa_dma(); | |
83 | setup_irq(16+2, &halt_switch_irqaction); /* SRM only? */ | |
84 | setup_irq(16+6, &timer_cascade_irqaction); | |
85 | } | |
86 | ||
87 | ||
88 | /* | |
89 | * PCI Fixup configuration. | |
90 | * | |
91 | * Summary @ PYXIS_INT_REQ: | |
92 | * Bit Meaning | |
93 | * 0 Fan Fault | |
94 | * 1 NMI | |
95 | * 2 Halt/Reset switch | |
96 | * 3 none | |
97 | * 4 CID0 (Riser ID) | |
98 | * 5 CID1 (Riser ID) | |
99 | * 6 Interval timer | |
100 | * 7 PCI-ISA Bridge | |
101 | * 8 Ethernet | |
102 | * 9 EIDE (deprecated, ISA 14/15 used) | |
103 | *10 none | |
104 | *11 USB | |
105 | *12 Interrupt Line A from slot 4 | |
106 | *13 Interrupt Line B from slot 4 | |
107 | *14 Interrupt Line C from slot 4 | |
108 | *15 Interrupt Line D from slot 4 | |
109 | *16 Interrupt Line A from slot 5 | |
110 | *17 Interrupt line B from slot 5 | |
111 | *18 Interrupt Line C from slot 5 | |
112 | *19 Interrupt Line D from slot 5 | |
113 | *20 Interrupt Line A from slot 1 | |
114 | *21 Interrupt Line B from slot 1 | |
115 | *22 Interrupt Line C from slot 1 | |
116 | *23 Interrupt Line D from slot 1 | |
117 | *24 Interrupt Line A from slot 2 | |
118 | *25 Interrupt Line B from slot 2 | |
119 | *26 Interrupt Line C from slot 2 | |
120 | *27 Interrupt Line D from slot 2 | |
121 | *27 Interrupt Line A from slot 3 | |
122 | *29 Interrupt Line B from slot 3 | |
123 | *30 Interrupt Line C from slot 3 | |
124 | *31 Interrupt Line D from slot 3 | |
125 | * | |
126 | * The device to slot mapping looks like: | |
127 | * | |
128 | * Slot Device | |
129 | * 3 DC21142 Ethernet | |
130 | * 4 EIDE CMD646 | |
131 | * 5 none | |
132 | * 6 USB | |
133 | * 7 PCI-ISA bridge | |
134 | * 8 PCI-PCI Bridge (SBU Riser) | |
135 | * 9 none | |
136 | * 10 none | |
137 | * 11 PCI on board slot 4 (SBU Riser) | |
138 | * 12 PCI on board slot 5 (SBU Riser) | |
139 | * | |
140 | * These are behind the bridge, so I'm not sure what to do... | |
141 | * | |
142 | * 13 PCI on board slot 1 (SBU Riser) | |
143 | * 14 PCI on board slot 2 (SBU Riser) | |
144 | * 15 PCI on board slot 3 (SBU Riser) | |
145 | * | |
146 | * | |
147 | * This two layered interrupt approach means that we allocate IRQ 16 and | |
148 | * above for PCI interrupts. The IRQ relates to which bit the interrupt | |
149 | * comes in on. This makes interrupt processing much easier. | |
150 | */ | |
151 | ||
152 | static int __init | |
d5341942 | 153 | miata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
1da177e4 LT |
154 | { |
155 | static char irq_tab[18][5] __initdata = { | |
156 | /*INT INTA INTB INTC INTD */ | |
157 | {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */ | |
158 | { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */ | |
159 | { -1, -1, -1, -1, -1}, /* IdSel 16, none */ | |
160 | { -1, -1, -1, -1, -1}, /* IdSel 17, none */ | |
161 | { -1, -1, -1, -1, -1}, /* IdSel 18, PCI-ISA */ | |
162 | { -1, -1, -1, -1, -1}, /* IdSel 19, PCI-PCI */ | |
163 | { -1, -1, -1, -1, -1}, /* IdSel 20, none */ | |
164 | { -1, -1, -1, -1, -1}, /* IdSel 21, none */ | |
165 | {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 22, slot 4 */ | |
166 | {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 23, slot 5 */ | |
167 | /* the next 7 are actually on PCI bus 1, across the bridge */ | |
168 | {16+11, 16+11, 16+11, 16+11, 16+11}, /* IdSel 24, QLISP/GL*/ | |
169 | { -1, -1, -1, -1, -1}, /* IdSel 25, none */ | |
170 | { -1, -1, -1, -1, -1}, /* IdSel 26, none */ | |
171 | { -1, -1, -1, -1, -1}, /* IdSel 27, none */ | |
172 | {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 28, slot 1 */ | |
173 | {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 29, slot 2 */ | |
174 | {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 30, slot 3 */ | |
175 | /* This bridge is on the main bus of the later orig MIATA */ | |
176 | { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */ | |
177 | }; | |
178 | const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5; | |
179 | ||
180 | /* the USB function of the 82c693 has it's interrupt connected to | |
181 | the 2nd 8259 controller. So we have to check for it first. */ | |
182 | ||
183 | if((slot == 7) && (PCI_FUNC(dev->devfn) == 3)) { | |
184 | u8 irq=0; | |
074cec54 AC |
185 | struct pci_dev *pdev = pci_get_slot(dev->bus, dev->devfn & ~7); |
186 | if(pdev == NULL || pci_read_config_byte(pdev, 0x40,&irq) != PCIBIOS_SUCCESSFUL) { | |
187 | pci_dev_put(pdev); | |
1da177e4 | 188 | return -1; |
074cec54 AC |
189 | } |
190 | else { | |
191 | pci_dev_put(pdev); | |
1da177e4 | 192 | return irq; |
074cec54 | 193 | } |
1da177e4 LT |
194 | } |
195 | ||
196 | return COMMON_TABLE_LOOKUP; | |
197 | } | |
198 | ||
199 | static u8 __init | |
200 | miata_swizzle(struct pci_dev *dev, u8 *pinp) | |
201 | { | |
202 | int slot, pin = *pinp; | |
203 | ||
204 | if (dev->bus->number == 0) { | |
205 | slot = PCI_SLOT(dev->devfn); | |
206 | } | |
207 | /* Check for the built-in bridge. */ | |
208 | else if ((PCI_SLOT(dev->bus->self->devfn) == 8) || | |
209 | (PCI_SLOT(dev->bus->self->devfn) == 20)) { | |
210 | slot = PCI_SLOT(dev->devfn) + 9; | |
211 | } | |
212 | else | |
213 | { | |
214 | /* Must be a card-based bridge. */ | |
215 | do { | |
216 | if ((PCI_SLOT(dev->bus->self->devfn) == 8) || | |
217 | (PCI_SLOT(dev->bus->self->devfn) == 20)) { | |
218 | slot = PCI_SLOT(dev->devfn) + 9; | |
219 | break; | |
220 | } | |
1be9baa0 | 221 | pin = pci_swizzle_interrupt_pin(dev, pin); |
1da177e4 LT |
222 | |
223 | /* Move up the chain of bridges. */ | |
224 | dev = dev->bus->self; | |
225 | /* Slot of the next bridge. */ | |
226 | slot = PCI_SLOT(dev->devfn); | |
227 | } while (dev->bus->self); | |
228 | } | |
229 | *pinp = pin; | |
230 | return slot; | |
231 | } | |
232 | ||
233 | static void __init | |
234 | miata_init_pci(void) | |
235 | { | |
236 | cia_init_pci(); | |
237 | SMC669_Init(0); /* it might be a GL (fails harmlessly if not) */ | |
238 | es1888_init(); | |
239 | } | |
240 | ||
241 | static void | |
242 | miata_kill_arch(int mode) | |
243 | { | |
244 | cia_kill_arch(mode); | |
245 | ||
246 | #ifndef ALPHA_RESTORE_SRM_SETUP | |
247 | switch(mode) { | |
248 | case LINUX_REBOOT_CMD_RESTART: | |
249 | /* Who said DEC engineers have no sense of humor? ;-) */ | |
250 | if (alpha_using_srm) { | |
251 | *(vuip) PYXIS_RESET = 0x0000dead; | |
252 | mb(); | |
253 | } | |
254 | break; | |
255 | case LINUX_REBOOT_CMD_HALT: | |
256 | break; | |
257 | case LINUX_REBOOT_CMD_POWER_OFF: | |
258 | break; | |
259 | } | |
260 | ||
261 | halt(); | |
262 | #endif | |
263 | } | |
264 | ||
265 | ||
266 | /* | |
267 | * The System Vector | |
268 | */ | |
269 | ||
270 | struct alpha_machine_vector miata_mv __initmv = { | |
271 | .vector_name = "Miata", | |
272 | DO_EV5_MMU, | |
273 | DO_DEFAULT_RTC, | |
274 | DO_PYXIS_IO, | |
275 | .machine_check = cia_machine_check, | |
276 | .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, | |
277 | .min_io_address = DEFAULT_IO_BASE, | |
278 | .min_mem_address = DEFAULT_MEM_BASE, | |
279 | .pci_dac_offset = PYXIS_DAC_OFFSET, | |
280 | ||
281 | .nr_irqs = 48, | |
282 | .device_interrupt = pyxis_device_interrupt, | |
283 | ||
284 | .init_arch = pyxis_init_arch, | |
285 | .init_irq = miata_init_irq, | |
286 | .init_rtc = common_init_rtc, | |
287 | .init_pci = miata_init_pci, | |
288 | .kill_arch = miata_kill_arch, | |
289 | .pci_map_irq = miata_map_irq, | |
290 | .pci_swizzle = miata_swizzle, | |
291 | }; | |
292 | ALIAS_MV(miata) |