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