]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
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> | |
cae39d13 | 12 | #include <linux/export.h> |
1da177e4 | 13 | #include <linux/pci.h> |
631330f5 | 14 | #include <linux/smp.h> |
1da177e4 LT |
15 | #include <asm/sn/arch.h> |
16 | #include <asm/pci/bridge.h> | |
17 | #include <asm/paccess.h> | |
18 | #include <asm/sn/intr.h> | |
19 | #include <asm/sn/sn0/hub.h> | |
20 | ||
1da177e4 LT |
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, | |
70342287 | 33 | * we should try to move it later in the boot process. |
1da177e4 LT |
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 | ||
9e0c7afd | 43 | extern struct pci_ops bridge_pci_ops; |
1da177e4 | 44 | |
078a55fc | 45 | int bridge_probe(nasid_t nasid, int widget_id, int masterwid) |
1da177e4 LT |
46 | { |
47 | unsigned long offset = NODE_OFFSET(nasid); | |
48 | struct bridge_controller *bc; | |
49 | static int num_bridges = 0; | |
50 | bridge_t *bridge; | |
51 | int slot; | |
96173a6c | 52 | |
29090606 | 53 | pci_set_flags(PCI_PROBE_ONLY); |
1da177e4 LT |
54 | |
55 | printk("a bridge\n"); | |
56 | ||
57 | /* XXX: kludge alert.. */ | |
58 | if (!num_bridges) | |
59 | ioport_resource.end = ~0UL; | |
60 | ||
61 | bc = &bridges[num_bridges]; | |
62 | ||
63 | bc->pc.pci_ops = &bridge_pci_ops; | |
64 | bc->pc.mem_resource = &bc->mem; | |
65 | bc->pc.io_resource = &bc->io; | |
66 | ||
67 | bc->pc.index = num_bridges; | |
68 | ||
69 | bc->mem.name = "Bridge PCI MEM"; | |
70 | bc->pc.mem_offset = offset; | |
71 | bc->mem.start = 0; | |
72 | bc->mem.end = ~0UL; | |
73 | bc->mem.flags = IORESOURCE_MEM; | |
74 | ||
75 | bc->io.name = "Bridge IO MEM"; | |
76 | bc->pc.io_offset = offset; | |
77 | bc->io.start = 0UL; | |
78 | bc->io.end = ~0UL; | |
79 | bc->io.flags = IORESOURCE_IO; | |
80 | ||
81 | bc->irq_cpu = smp_processor_id(); | |
82 | bc->widget_id = widget_id; | |
83 | bc->nasid = nasid; | |
84 | ||
3a115456 | 85 | bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR; |
1da177e4 LT |
86 | |
87 | /* | |
88 | * point to this bridge | |
89 | */ | |
90 | bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); | |
91 | ||
92 | /* | |
a3dddd56 RB |
93 | * Clear all pending interrupts. |
94 | */ | |
1da177e4 LT |
95 | bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR; |
96 | ||
97 | /* | |
a3dddd56 RB |
98 | * Until otherwise set up, assume all interrupts are from slot 0 |
99 | */ | |
1da177e4 LT |
100 | bridge->b_int_device = 0x0; |
101 | ||
102 | /* | |
a3dddd56 RB |
103 | * swap pio's to pci mem and io space (big windows) |
104 | */ | |
1da177e4 | 105 | bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | |
70342287 | 106 | BRIDGE_CTRL_MEM_SWAP; |
96173a6c TB |
107 | #ifdef CONFIG_PAGE_SIZE_4KB |
108 | bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE; | |
109 | #else /* 16kB or larger */ | |
110 | bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE; | |
111 | #endif | |
1da177e4 LT |
112 | |
113 | /* | |
114 | * Hmm... IRIX sets additional bits in the address which | |
115 | * are documented as reserved in the bridge docs. | |
116 | */ | |
117 | bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); | |
118 | bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ | |
119 | bridge->b_dir_map = (masterwid << 20); /* DMA */ | |
120 | bridge->b_int_enable = 0; | |
121 | ||
122 | for (slot = 0; slot < 8; slot ++) { | |
123 | bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; | |
124 | bc->pci_int[slot] = -1; | |
125 | } | |
70342287 | 126 | bridge->b_wid_tflush; /* wait until Bridge PIO complete */ |
1da177e4 LT |
127 | |
128 | bc->base = bridge; | |
129 | ||
130 | register_pci_controller(&bc->pc); | |
131 | ||
132 | num_bridges++; | |
133 | ||
134 | return 0; | |
135 | } | |
136 | ||
137 | /* | |
138 | * All observed requests have pin == 1. We could have a global here, that | |
139 | * gets incremented and returned every time - unfortunately, pci_map_irq | |
140 | * may be called on the same device over and over, and need to return the | |
141 | * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. | |
142 | * | |
143 | * A given PCI device, in general, should be able to intr any of the cpus | |
144 | * on any one of the hubs connected to its xbow. | |
145 | */ | |
28eb0e46 | 146 | int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
f4d15f1c RB |
147 | { |
148 | return 0; | |
149 | } | |
150 | ||
f4d15f1c RB |
151 | static inline struct pci_dev *bridge_root_dev(struct pci_dev *dev) |
152 | { | |
153 | while (dev->bus->parent) { | |
154 | /* Move up the chain of bridges. */ | |
155 | dev = dev->bus->self; | |
156 | } | |
157 | ||
158 | return dev; | |
159 | } | |
160 | ||
161 | /* Do platform specific device initialization at pci_enable_device() time */ | |
162 | int pcibios_plat_dev_init(struct pci_dev *dev) | |
1da177e4 LT |
163 | { |
164 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | |
f4d15f1c RB |
165 | struct pci_dev *rdev = bridge_root_dev(dev); |
166 | int slot = PCI_SLOT(rdev->devfn); | |
167 | int irq; | |
1da177e4 | 168 | |
f4d15f1c | 169 | irq = bc->pci_int[slot]; |
1da177e4 | 170 | if (irq == -1) { |
f4d15f1c | 171 | irq = request_bridge_irq(bc); |
1da177e4 | 172 | if (irq < 0) |
f4d15f1c RB |
173 | return irq; |
174 | ||
175 | bc->pci_int[slot] = irq; | |
1da177e4 LT |
176 | } |
177 | ||
178 | irq_to_bridge[irq] = bc; | |
179 | irq_to_slot[irq] = slot; | |
180 | ||
f4d15f1c | 181 | dev->irq = irq; |
1da177e4 | 182 | |
1da177e4 LT |
183 | return 0; |
184 | } | |
185 | ||
186 | /* | |
70342287 | 187 | * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses |
1da177e4 LT |
188 | * to find the slot number in sense of the bridge device register. |
189 | * XXX This also means multiple devices might rely on conflicting bridge | |
190 | * settings. | |
191 | */ | |
192 | ||
193 | static inline void pci_disable_swapping(struct pci_dev *dev) | |
194 | { | |
195 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | |
196 | bridge_t *bridge = bc->base; | |
197 | int slot = PCI_SLOT(dev->devfn); | |
198 | ||
199 | /* Turn off byte swapping */ | |
200 | bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR; | |
201 | bridge->b_widget.w_tflush; /* Flush */ | |
202 | } | |
203 | ||
204 | static inline void pci_enable_swapping(struct pci_dev *dev) | |
205 | { | |
206 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | |
207 | bridge_t *bridge = bc->base; | |
208 | int slot = PCI_SLOT(dev->devfn); | |
209 | ||
210 | /* Turn on byte swapping */ | |
211 | bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; | |
212 | bridge->b_widget.w_tflush; /* Flush */ | |
213 | } | |
214 | ||
28eb0e46 | 215 | static void pci_fixup_ioc3(struct pci_dev *d) |
1da177e4 LT |
216 | { |
217 | pci_disable_swapping(d); | |
218 | } | |
219 | ||
4f675e8a | 220 | #ifdef CONFIG_NUMA |
9dbdfce8 RB |
221 | int pcibus_to_node(struct pci_bus *bus) |
222 | { | |
223 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | |
224 | ||
225 | return bc->nasid; | |
226 | } | |
a571444a | 227 | EXPORT_SYMBOL(pcibus_to_node); |
4f675e8a | 228 | #endif /* CONFIG_NUMA */ |
9dbdfce8 | 229 | |
1da177e4 LT |
230 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, |
231 | pci_fixup_ioc3); |