diff options
Diffstat (limited to 'arch/mips/pci/pci-ip27.c')
-rw-r--r-- | arch/mips/pci/pci-ip27.c | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c new file mode 100644 index 000000000000..068e0e508e15 --- /dev/null +++ b/arch/mips/pci/pci-ip27.c | |||
@@ -0,0 +1,489 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003 Christoph Hellwig (hch@lst.de) | ||
7 | * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) | ||
8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | ||
9 | */ | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/pci.h> | ||
13 | #include <asm/sn/arch.h> | ||
14 | #include <asm/pci/bridge.h> | ||
15 | #include <asm/paccess.h> | ||
16 | #include <asm/sn/intr.h> | ||
17 | #include <asm/sn/sn0/hub.h> | ||
18 | |||
19 | extern unsigned int allocate_irqno(void); | ||
20 | |||
21 | /* | ||
22 | * Max #PCI busses we can handle; ie, max #PCI bridges. | ||
23 | */ | ||
24 | #define MAX_PCI_BUSSES 40 | ||
25 | |||
26 | /* | ||
27 | * Max #PCI devices (like scsi controllers) we handle on a bus. | ||
28 | */ | ||
29 | #define MAX_DEVICES_PER_PCIBUS 8 | ||
30 | |||
31 | /* | ||
32 | * XXX: No kmalloc available when we do our crosstalk scan, | ||
33 | * we should try to move it later in the boot process. | ||
34 | */ | ||
35 | static struct bridge_controller bridges[MAX_PCI_BUSSES]; | ||
36 | |||
37 | /* | ||
38 | * Translate from irq to software PCI bus number and PCI slot. | ||
39 | */ | ||
40 | struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; | ||
41 | int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; | ||
42 | |||
43 | /* | ||
44 | * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is | ||
45 | * not really documented, so right now I can't write code which uses it. | ||
46 | * Therefore we use type 0 accesses for now even though they won't work | ||
47 | * correcly for PCI-to-PCI bridges. | ||
48 | * | ||
49 | * The function is complicated by the ultimate brokeness of the IOC3 chip | ||
50 | * which is used in SGI systems. The IOC3 can only handle 32-bit PCI | ||
51 | * accesses and does only decode parts of it's address space. | ||
52 | */ | ||
53 | |||
54 | static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, | ||
55 | int where, int size, u32 * value) | ||
56 | { | ||
57 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
58 | bridge_t *bridge = bc->base; | ||
59 | int slot = PCI_SLOT(devfn); | ||
60 | int fn = PCI_FUNC(devfn); | ||
61 | volatile void *addr; | ||
62 | u32 cf, shift, mask; | ||
63 | int res; | ||
64 | |||
65 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
66 | if (get_dbe(cf, (u32 *) addr)) | ||
67 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
68 | |||
69 | /* | ||
70 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
71 | * generic PCI code a chance to look at it for real ... | ||
72 | */ | ||
73 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
74 | goto oh_my_gawd; | ||
75 | |||
76 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
77 | |||
78 | if (size == 1) | ||
79 | res = get_dbe(*value, (u8 *) addr); | ||
80 | else if (size == 2) | ||
81 | res = get_dbe(*value, (u16 *) addr); | ||
82 | else | ||
83 | res = get_dbe(*value, (u32 *) addr); | ||
84 | |||
85 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
86 | |||
87 | oh_my_gawd: | ||
88 | |||
89 | /* | ||
90 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
91 | * generic PCI code a chance to look at the wrong register. | ||
92 | */ | ||
93 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
94 | *value = 0; | ||
95 | return PCIBIOS_SUCCESSFUL; | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
100 | * anything but 32-bit words ... | ||
101 | */ | ||
102 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
103 | |||
104 | if (get_dbe(cf, (u32 *) addr)) | ||
105 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
106 | |||
107 | shift = ((where & 3) << 3); | ||
108 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
109 | *value = (cf >> shift) & mask; | ||
110 | |||
111 | return PCIBIOS_SUCCESSFUL; | ||
112 | } | ||
113 | |||
114 | static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, | ||
115 | int where, int size, u32 * value) | ||
116 | { | ||
117 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
118 | bridge_t *bridge = bc->base; | ||
119 | int busno = bus->number; | ||
120 | int slot = PCI_SLOT(devfn); | ||
121 | int fn = PCI_FUNC(devfn); | ||
122 | volatile void *addr; | ||
123 | u32 cf, shift, mask; | ||
124 | int res; | ||
125 | |||
126 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
127 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
128 | if (get_dbe(cf, (u32 *) addr)) | ||
129 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
130 | |||
131 | /* | ||
132 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
133 | * generic PCI code a chance to look at it for real ... | ||
134 | */ | ||
135 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
136 | goto oh_my_gawd; | ||
137 | |||
138 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
139 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
140 | |||
141 | if (size == 1) | ||
142 | res = get_dbe(*value, (u8 *) addr); | ||
143 | else if (size == 2) | ||
144 | res = get_dbe(*value, (u16 *) addr); | ||
145 | else | ||
146 | res = get_dbe(*value, (u32 *) addr); | ||
147 | |||
148 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
149 | |||
150 | oh_my_gawd: | ||
151 | |||
152 | /* | ||
153 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
154 | * generic PCI code a chance to look at the wrong register. | ||
155 | */ | ||
156 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
157 | *value = 0; | ||
158 | return PCIBIOS_SUCCESSFUL; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
163 | * anything but 32-bit words ... | ||
164 | */ | ||
165 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
166 | addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; | ||
167 | |||
168 | if (get_dbe(cf, (u32 *) addr)) | ||
169 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
170 | |||
171 | shift = ((where & 3) << 3); | ||
172 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
173 | *value = (cf >> shift) & mask; | ||
174 | |||
175 | return PCIBIOS_SUCCESSFUL; | ||
176 | } | ||
177 | |||
178 | static int pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
179 | int where, int size, u32 * value) | ||
180 | { | ||
181 | if (bus->number > 0) | ||
182 | return pci_conf1_read_config(bus, devfn, where, size, value); | ||
183 | |||
184 | return pci_conf0_read_config(bus, devfn, where, size, value); | ||
185 | } | ||
186 | |||
187 | static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, | ||
188 | int where, int size, u32 value) | ||
189 | { | ||
190 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
191 | bridge_t *bridge = bc->base; | ||
192 | int slot = PCI_SLOT(devfn); | ||
193 | int fn = PCI_FUNC(devfn); | ||
194 | volatile void *addr; | ||
195 | u32 cf, shift, mask, smask; | ||
196 | int res; | ||
197 | |||
198 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
199 | if (get_dbe(cf, (u32 *) addr)) | ||
200 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
201 | |||
202 | /* | ||
203 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
204 | * generic PCI code a chance to look at it for real ... | ||
205 | */ | ||
206 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
207 | goto oh_my_gawd; | ||
208 | |||
209 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
210 | |||
211 | if (size == 1) { | ||
212 | res = put_dbe(value, (u8 *) addr); | ||
213 | } else if (size == 2) { | ||
214 | res = put_dbe(value, (u16 *) addr); | ||
215 | } else { | ||
216 | res = put_dbe(value, (u32 *) addr); | ||
217 | } | ||
218 | |||
219 | if (res) | ||
220 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
221 | |||
222 | return PCIBIOS_SUCCESSFUL; | ||
223 | |||
224 | oh_my_gawd: | ||
225 | |||
226 | /* | ||
227 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
228 | * generic PCI code a chance to touch the wrong register. | ||
229 | */ | ||
230 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
231 | return PCIBIOS_SUCCESSFUL; | ||
232 | |||
233 | /* | ||
234 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
235 | * anything but 32-bit words ... | ||
236 | */ | ||
237 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
238 | |||
239 | if (get_dbe(cf, (u32 *) addr)) | ||
240 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
241 | |||
242 | shift = ((where & 3) << 3); | ||
243 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
244 | smask = mask << shift; | ||
245 | |||
246 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
247 | if (put_dbe(cf, (u32 *) addr)) | ||
248 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
249 | |||
250 | return PCIBIOS_SUCCESSFUL; | ||
251 | } | ||
252 | |||
253 | static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, | ||
254 | int where, int size, u32 value) | ||
255 | { | ||
256 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
257 | bridge_t *bridge = bc->base; | ||
258 | int slot = PCI_SLOT(devfn); | ||
259 | int fn = PCI_FUNC(devfn); | ||
260 | int busno = bus->number; | ||
261 | volatile void *addr; | ||
262 | u32 cf, shift, mask, smask; | ||
263 | int res; | ||
264 | |||
265 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
266 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
267 | if (get_dbe(cf, (u32 *) addr)) | ||
268 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
269 | |||
270 | /* | ||
271 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
272 | * generic PCI code a chance to look at it for real ... | ||
273 | */ | ||
274 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
275 | goto oh_my_gawd; | ||
276 | |||
277 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
278 | |||
279 | if (size == 1) { | ||
280 | res = put_dbe(value, (u8 *) addr); | ||
281 | } else if (size == 2) { | ||
282 | res = put_dbe(value, (u16 *) addr); | ||
283 | } else { | ||
284 | res = put_dbe(value, (u32 *) addr); | ||
285 | } | ||
286 | |||
287 | if (res) | ||
288 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
289 | |||
290 | return PCIBIOS_SUCCESSFUL; | ||
291 | |||
292 | oh_my_gawd: | ||
293 | |||
294 | /* | ||
295 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
296 | * generic PCI code a chance to touch the wrong register. | ||
297 | */ | ||
298 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
299 | return PCIBIOS_SUCCESSFUL; | ||
300 | |||
301 | /* | ||
302 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
303 | * anything but 32-bit words ... | ||
304 | */ | ||
305 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
306 | |||
307 | if (get_dbe(cf, (u32 *) addr)) | ||
308 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
309 | |||
310 | shift = ((where & 3) << 3); | ||
311 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
312 | smask = mask << shift; | ||
313 | |||
314 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
315 | if (put_dbe(cf, (u32 *) addr)) | ||
316 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
317 | |||
318 | return PCIBIOS_SUCCESSFUL; | ||
319 | } | ||
320 | |||
321 | static int pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
322 | int where, int size, u32 value) | ||
323 | { | ||
324 | if (bus->number > 0) | ||
325 | return pci_conf1_write_config(bus, devfn, where, size, value); | ||
326 | |||
327 | return pci_conf0_write_config(bus, devfn, where, size, value); | ||
328 | } | ||
329 | |||
330 | static struct pci_ops bridge_pci_ops = { | ||
331 | .read = pci_read_config, | ||
332 | .write = pci_write_config, | ||
333 | }; | ||
334 | |||
335 | int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) | ||
336 | { | ||
337 | unsigned long offset = NODE_OFFSET(nasid); | ||
338 | struct bridge_controller *bc; | ||
339 | static int num_bridges = 0; | ||
340 | bridge_t *bridge; | ||
341 | int slot; | ||
342 | |||
343 | printk("a bridge\n"); | ||
344 | |||
345 | /* XXX: kludge alert.. */ | ||
346 | if (!num_bridges) | ||
347 | ioport_resource.end = ~0UL; | ||
348 | |||
349 | bc = &bridges[num_bridges]; | ||
350 | |||
351 | bc->pc.pci_ops = &bridge_pci_ops; | ||
352 | bc->pc.mem_resource = &bc->mem; | ||
353 | bc->pc.io_resource = &bc->io; | ||
354 | |||
355 | bc->pc.index = num_bridges; | ||
356 | |||
357 | bc->mem.name = "Bridge PCI MEM"; | ||
358 | bc->pc.mem_offset = offset; | ||
359 | bc->mem.start = 0; | ||
360 | bc->mem.end = ~0UL; | ||
361 | bc->mem.flags = IORESOURCE_MEM; | ||
362 | |||
363 | bc->io.name = "Bridge IO MEM"; | ||
364 | bc->pc.io_offset = offset; | ||
365 | bc->io.start = 0UL; | ||
366 | bc->io.end = ~0UL; | ||
367 | bc->io.flags = IORESOURCE_IO; | ||
368 | |||
369 | bc->irq_cpu = smp_processor_id(); | ||
370 | bc->widget_id = widget_id; | ||
371 | bc->nasid = nasid; | ||
372 | |||
373 | bc->baddr = (u64)masterwid << 60; | ||
374 | bc->baddr |= (1UL << 56); /* Barrier set */ | ||
375 | |||
376 | /* | ||
377 | * point to this bridge | ||
378 | */ | ||
379 | bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); | ||
380 | |||
381 | /* | ||
382 | * Clear all pending interrupts. | ||
383 | */ | ||
384 | bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR; | ||
385 | |||
386 | /* | ||
387 | * Until otherwise set up, assume all interrupts are from slot 0 | ||
388 | */ | ||
389 | bridge->b_int_device = 0x0; | ||
390 | |||
391 | /* | ||
392 | * swap pio's to pci mem and io space (big windows) | ||
393 | */ | ||
394 | bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | | ||
395 | BRIDGE_CTRL_MEM_SWAP; | ||
396 | |||
397 | /* | ||
398 | * Hmm... IRIX sets additional bits in the address which | ||
399 | * are documented as reserved in the bridge docs. | ||
400 | */ | ||
401 | bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); | ||
402 | bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ | ||
403 | bridge->b_dir_map = (masterwid << 20); /* DMA */ | ||
404 | bridge->b_int_enable = 0; | ||
405 | |||
406 | for (slot = 0; slot < 8; slot ++) { | ||
407 | bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; | ||
408 | bc->pci_int[slot] = -1; | ||
409 | } | ||
410 | bridge->b_wid_tflush; /* wait until Bridge PIO complete */ | ||
411 | |||
412 | bc->base = bridge; | ||
413 | |||
414 | register_pci_controller(&bc->pc); | ||
415 | |||
416 | num_bridges++; | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * All observed requests have pin == 1. We could have a global here, that | ||
423 | * gets incremented and returned every time - unfortunately, pci_map_irq | ||
424 | * may be called on the same device over and over, and need to return the | ||
425 | * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. | ||
426 | * | ||
427 | * A given PCI device, in general, should be able to intr any of the cpus | ||
428 | * on any one of the hubs connected to its xbow. | ||
429 | */ | ||
430 | int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
431 | { | ||
432 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
433 | int irq = bc->pci_int[slot]; | ||
434 | |||
435 | if (irq == -1) { | ||
436 | irq = bc->pci_int[slot] = request_bridge_irq(bc); | ||
437 | if (irq < 0) | ||
438 | panic("Can't allocate interrupt for PCI device %s\n", | ||
439 | pci_name(dev)); | ||
440 | } | ||
441 | |||
442 | irq_to_bridge[irq] = bc; | ||
443 | irq_to_slot[irq] = slot; | ||
444 | |||
445 | return irq; | ||
446 | } | ||
447 | |||
448 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
449 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
450 | { | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses | ||
456 | * to find the slot number in sense of the bridge device register. | ||
457 | * XXX This also means multiple devices might rely on conflicting bridge | ||
458 | * settings. | ||
459 | */ | ||
460 | |||
461 | static inline void pci_disable_swapping(struct pci_dev *dev) | ||
462 | { | ||
463 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
464 | bridge_t *bridge = bc->base; | ||
465 | int slot = PCI_SLOT(dev->devfn); | ||
466 | |||
467 | /* Turn off byte swapping */ | ||
468 | bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR; | ||
469 | bridge->b_widget.w_tflush; /* Flush */ | ||
470 | } | ||
471 | |||
472 | static inline void pci_enable_swapping(struct pci_dev *dev) | ||
473 | { | ||
474 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
475 | bridge_t *bridge = bc->base; | ||
476 | int slot = PCI_SLOT(dev->devfn); | ||
477 | |||
478 | /* Turn on byte swapping */ | ||
479 | bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; | ||
480 | bridge->b_widget.w_tflush; /* Flush */ | ||
481 | } | ||
482 | |||
483 | static void __init pci_fixup_ioc3(struct pci_dev *d) | ||
484 | { | ||
485 | pci_disable_swapping(d); | ||
486 | } | ||
487 | |||
488 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, | ||
489 | pci_fixup_ioc3); | ||