]>
Commit | Line | Data |
---|---|---|
c609719b | 1 | /* |
a47a12be | 2 | * arch/powerpc/kernel/pci_auto.c |
c609719b WD |
3 | * |
4 | * PCI autoconfiguration library | |
5 | * | |
6 | * Author: Matt Porter <mporter@mvista.com> | |
7 | * | |
8 | * Copyright 2000 MontaVista Software Inc. | |
9 | * | |
1a459660 | 10 | * SPDX-License-Identifier: GPL-2.0+ |
c609719b WD |
11 | */ |
12 | ||
13 | #include <common.h> | |
14 | ||
c609719b WD |
15 | #include <pci.h> |
16 | ||
17 | #undef DEBUG | |
18 | #ifdef DEBUG | |
19 | #define DEBUGF(x...) printf(x) | |
20 | #else | |
21 | #define DEBUGF(x...) | |
22 | #endif /* DEBUG */ | |
23 | ||
24 | #define PCIAUTO_IDE_MODE_MASK 0x05 | |
25 | ||
6d0f6bcf JCPV |
26 | /* the user can define CONFIG_SYS_PCI_CACHE_LINE_SIZE to avoid problems */ |
27 | #ifndef CONFIG_SYS_PCI_CACHE_LINE_SIZE | |
28 | #define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8 | |
81b73dec GJ |
29 | #endif |
30 | ||
c609719b WD |
31 | /* |
32 | * | |
33 | */ | |
34 | ||
cb2bf931 | 35 | void pciauto_region_init(struct pci_region *res) |
c609719b | 36 | { |
b7598a43 SS |
37 | /* |
38 | * Avoid allocating PCI resources from address 0 -- this is illegal | |
39 | * according to PCI 2.1 and moreover, this is known to cause Linux IDE | |
40 | * drivers to fail. Use a reasonable starting value of 0x1000 instead. | |
41 | */ | |
42 | res->bus_lower = res->bus_start ? res->bus_start : 0x1000; | |
c609719b WD |
43 | } |
44 | ||
30e76d5e | 45 | void pciauto_region_align(struct pci_region *res, pci_size_t size) |
c609719b WD |
46 | { |
47 | res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1; | |
48 | } | |
49 | ||
cb2bf931 AS |
50 | int pciauto_region_allocate(struct pci_region *res, pci_size_t size, |
51 | pci_addr_t *bar) | |
c609719b | 52 | { |
30e76d5e | 53 | pci_addr_t addr; |
c609719b | 54 | |
3c74e32a | 55 | if (!res) { |
c609719b WD |
56 | DEBUGF("No resource"); |
57 | goto error; | |
58 | } | |
59 | ||
60 | addr = ((res->bus_lower - 1) | (size - 1)) + 1; | |
61 | ||
3c74e32a | 62 | if (addr - res->bus_start + size > res->size) { |
c609719b WD |
63 | DEBUGF("No room in resource"); |
64 | goto error; | |
65 | } | |
66 | ||
67 | res->bus_lower = addr + size; | |
68 | ||
30e76d5e | 69 | DEBUGF("address=0x%llx bus_lower=0x%llx", (u64)addr, (u64)res->bus_lower); |
c609719b WD |
70 | |
71 | *bar = addr; | |
72 | return 0; | |
73 | ||
74 | error: | |
30e76d5e | 75 | *bar = (pci_addr_t)-1; |
c609719b WD |
76 | return -1; |
77 | } | |
78 | ||
79 | /* | |
80 | * | |
81 | */ | |
82 | ||
83 | void pciauto_setup_device(struct pci_controller *hose, | |
84 | pci_dev_t dev, int bars_num, | |
85 | struct pci_region *mem, | |
a179012e | 86 | struct pci_region *prefetch, |
c609719b WD |
87 | struct pci_region *io) |
88 | { | |
cf5787f2 | 89 | u32 bar_response; |
30e76d5e | 90 | pci_size_t bar_size; |
af778c6d | 91 | u16 cmdstat = 0; |
c609719b | 92 | int bar, bar_nr = 0; |
69fd2d3b AS |
93 | #ifndef CONFIG_PCI_ENUM_ONLY |
94 | pci_addr_t bar_value; | |
95 | struct pci_region *bar_res; | |
c609719b | 96 | int found_mem64 = 0; |
69fd2d3b | 97 | #endif |
c609719b | 98 | |
af778c6d | 99 | pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); |
c609719b WD |
100 | cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER; |
101 | ||
cb2bf931 AS |
102 | for (bar = PCI_BASE_ADDRESS_0; |
103 | bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) { | |
c609719b | 104 | /* Tickle the BAR and get the response */ |
69fd2d3b | 105 | #ifndef CONFIG_PCI_ENUM_ONLY |
c609719b | 106 | pci_hose_write_config_dword(hose, dev, bar, 0xffffffff); |
69fd2d3b | 107 | #endif |
c609719b WD |
108 | pci_hose_read_config_dword(hose, dev, bar, &bar_response); |
109 | ||
110 | /* If BAR is not implemented go to the next BAR */ | |
111 | if (!bar_response) | |
112 | continue; | |
113 | ||
69fd2d3b | 114 | #ifndef CONFIG_PCI_ENUM_ONLY |
c609719b | 115 | found_mem64 = 0; |
69fd2d3b | 116 | #endif |
c609719b WD |
117 | |
118 | /* Check the BAR type and set our address mask */ | |
3c74e32a | 119 | if (bar_response & PCI_BASE_ADDRESS_SPACE) { |
bd22c2b9 JZR |
120 | bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK)) |
121 | & 0xffff) + 1; | |
69fd2d3b | 122 | #ifndef CONFIG_PCI_ENUM_ONLY |
c609719b | 123 | bar_res = io; |
69fd2d3b | 124 | #endif |
c609719b | 125 | |
30e76d5e | 126 | DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", bar_nr, (u64)bar_size); |
3c74e32a | 127 | } else { |
cb2bf931 | 128 | if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == |
30e76d5e KG |
129 | PCI_BASE_ADDRESS_MEM_TYPE_64) { |
130 | u32 bar_response_upper; | |
131 | u64 bar64; | |
69fd2d3b AS |
132 | |
133 | #ifndef CONFIG_PCI_ENUM_ONLY | |
cb2bf931 AS |
134 | pci_hose_write_config_dword(hose, dev, bar + 4, |
135 | 0xffffffff); | |
69fd2d3b | 136 | #endif |
cb2bf931 AS |
137 | pci_hose_read_config_dword(hose, dev, bar + 4, |
138 | &bar_response_upper); | |
30e76d5e KG |
139 | |
140 | bar64 = ((u64)bar_response_upper << 32) | bar_response; | |
c609719b | 141 | |
30e76d5e | 142 | bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1; |
69fd2d3b | 143 | #ifndef CONFIG_PCI_ENUM_ONLY |
30e76d5e | 144 | found_mem64 = 1; |
69fd2d3b | 145 | #endif |
30e76d5e KG |
146 | } else { |
147 | bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1); | |
148 | } | |
69fd2d3b | 149 | #ifndef CONFIG_PCI_ENUM_ONLY |
a179012e KG |
150 | if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH)) |
151 | bar_res = prefetch; | |
152 | else | |
153 | bar_res = mem; | |
69fd2d3b | 154 | #endif |
c609719b | 155 | |
30e76d5e | 156 | DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%llx, ", bar_nr, (u64)bar_size); |
c609719b WD |
157 | } |
158 | ||
69fd2d3b | 159 | #ifndef CONFIG_PCI_ENUM_ONLY |
3c74e32a | 160 | if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0) { |
c609719b | 161 | /* Write it out and update our limit */ |
30e76d5e | 162 | pci_hose_write_config_dword(hose, dev, bar, (u32)bar_value); |
c609719b | 163 | |
3c74e32a | 164 | if (found_mem64) { |
c609719b | 165 | bar += 4; |
30e76d5e KG |
166 | #ifdef CONFIG_SYS_PCI_64BIT |
167 | pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32)); | |
168 | #else | |
169 | /* | |
170 | * If we are a 64-bit decoder then increment to the | |
171 | * upper 32 bits of the bar and force it to locate | |
172 | * in the lower 4GB of memory. | |
173 | */ | |
c609719b | 174 | pci_hose_write_config_dword(hose, dev, bar, 0x00000000); |
30e76d5e | 175 | #endif |
c609719b WD |
176 | } |
177 | ||
c609719b | 178 | } |
69fd2d3b AS |
179 | #endif |
180 | cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ? | |
181 | PCI_COMMAND_IO : PCI_COMMAND_MEMORY; | |
c609719b WD |
182 | |
183 | DEBUGF("\n"); | |
184 | ||
185 | bar_nr++; | |
186 | } | |
187 | ||
af778c6d | 188 | pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat); |
81b73dec | 189 | pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, |
6d0f6bcf | 190 | CONFIG_SYS_PCI_CACHE_LINE_SIZE); |
c609719b WD |
191 | pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); |
192 | } | |
193 | ||
ba5feb12 | 194 | void pciauto_prescan_setup_bridge(struct pci_controller *hose, |
c609719b WD |
195 | pci_dev_t dev, int sub_bus) |
196 | { | |
197 | struct pci_region *pci_mem = hose->pci_mem; | |
a179012e | 198 | struct pci_region *pci_prefetch = hose->pci_prefetch; |
c609719b | 199 | struct pci_region *pci_io = hose->pci_io; |
af778c6d | 200 | u16 cmdstat; |
c609719b | 201 | |
af778c6d | 202 | pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); |
c609719b WD |
203 | |
204 | /* Configure bus number registers */ | |
e8b85f3b ES |
205 | pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, |
206 | PCI_BUS(dev) - hose->first_busno); | |
207 | pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, | |
208 | sub_bus - hose->first_busno); | |
c609719b WD |
209 | pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff); |
210 | ||
3c74e32a | 211 | if (pci_mem) { |
c609719b WD |
212 | /* Round memory allocator to 1MB boundary */ |
213 | pciauto_region_align(pci_mem, 0x100000); | |
214 | ||
215 | /* Set up memory and I/O filter limits, assume 32-bit I/O space */ | |
216 | pci_hose_write_config_word(hose, dev, PCI_MEMORY_BASE, | |
217 | (pci_mem->bus_lower & 0xfff00000) >> 16); | |
218 | ||
219 | cmdstat |= PCI_COMMAND_MEMORY; | |
220 | } | |
221 | ||
a179012e KG |
222 | if (pci_prefetch) { |
223 | /* Round memory allocator to 1MB boundary */ | |
224 | pciauto_region_align(pci_prefetch, 0x100000); | |
225 | ||
226 | /* Set up memory and I/O filter limits, assume 32-bit I/O space */ | |
227 | pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, | |
228 | (pci_prefetch->bus_lower & 0xfff00000) >> 16); | |
229 | ||
230 | cmdstat |= PCI_COMMAND_MEMORY; | |
231 | } else { | |
232 | /* We don't support prefetchable memory for now, so disable */ | |
233 | pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000); | |
a4e11558 | 234 | pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x0); |
a179012e KG |
235 | } |
236 | ||
3c74e32a | 237 | if (pci_io) { |
c609719b WD |
238 | /* Round I/O allocator to 4KB boundary */ |
239 | pciauto_region_align(pci_io, 0x1000); | |
240 | ||
241 | pci_hose_write_config_byte(hose, dev, PCI_IO_BASE, | |
242 | (pci_io->bus_lower & 0x0000f000) >> 8); | |
243 | pci_hose_write_config_word(hose, dev, PCI_IO_BASE_UPPER16, | |
244 | (pci_io->bus_lower & 0xffff0000) >> 16); | |
245 | ||
246 | cmdstat |= PCI_COMMAND_IO; | |
247 | } | |
248 | ||
c609719b | 249 | /* Enable memory and I/O accesses, enable bus master */ |
af778c6d AS |
250 | pci_hose_write_config_word(hose, dev, PCI_COMMAND, |
251 | cmdstat | PCI_COMMAND_MASTER); | |
c609719b WD |
252 | } |
253 | ||
ba5feb12 | 254 | void pciauto_postscan_setup_bridge(struct pci_controller *hose, |
c609719b WD |
255 | pci_dev_t dev, int sub_bus) |
256 | { | |
257 | struct pci_region *pci_mem = hose->pci_mem; | |
a179012e | 258 | struct pci_region *pci_prefetch = hose->pci_prefetch; |
c609719b WD |
259 | struct pci_region *pci_io = hose->pci_io; |
260 | ||
261 | /* Configure bus number registers */ | |
e8b85f3b ES |
262 | pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, |
263 | sub_bus - hose->first_busno); | |
c609719b | 264 | |
3c74e32a | 265 | if (pci_mem) { |
c609719b WD |
266 | /* Round memory allocator to 1MB boundary */ |
267 | pciauto_region_align(pci_mem, 0x100000); | |
268 | ||
269 | pci_hose_write_config_word(hose, dev, PCI_MEMORY_LIMIT, | |
cb2bf931 | 270 | (pci_mem->bus_lower - 1) >> 16); |
c609719b WD |
271 | } |
272 | ||
a179012e KG |
273 | if (pci_prefetch) { |
274 | /* Round memory allocator to 1MB boundary */ | |
275 | pciauto_region_align(pci_prefetch, 0x100000); | |
276 | ||
277 | pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, | |
cb2bf931 | 278 | (pci_prefetch->bus_lower - 1) >> 16); |
a179012e KG |
279 | } |
280 | ||
3c74e32a | 281 | if (pci_io) { |
c609719b WD |
282 | /* Round I/O allocator to 4KB boundary */ |
283 | pciauto_region_align(pci_io, 0x1000); | |
284 | ||
285 | pci_hose_write_config_byte(hose, dev, PCI_IO_LIMIT, | |
cb2bf931 | 286 | ((pci_io->bus_lower - 1) & 0x0000f000) >> 8); |
c609719b | 287 | pci_hose_write_config_word(hose, dev, PCI_IO_LIMIT_UPPER16, |
cb2bf931 | 288 | ((pci_io->bus_lower - 1) & 0xffff0000) >> 16); |
c609719b WD |
289 | } |
290 | } | |
291 | ||
292 | /* | |
293 | * | |
294 | */ | |
295 | ||
296 | void pciauto_config_init(struct pci_controller *hose) | |
297 | { | |
298 | int i; | |
299 | ||
010c480b | 300 | hose->pci_io = hose->pci_mem = hose->pci_prefetch = NULL; |
c609719b | 301 | |
cb2bf931 | 302 | for (i = 0; i < hose->region_count; i++) { |
3c74e32a | 303 | switch(hose->regions[i].flags) { |
c609719b WD |
304 | case PCI_REGION_IO: |
305 | if (!hose->pci_io || | |
306 | hose->pci_io->size < hose->regions[i].size) | |
307 | hose->pci_io = hose->regions + i; | |
308 | break; | |
309 | case PCI_REGION_MEM: | |
310 | if (!hose->pci_mem || | |
311 | hose->pci_mem->size < hose->regions[i].size) | |
312 | hose->pci_mem = hose->regions + i; | |
313 | break; | |
a179012e KG |
314 | case (PCI_REGION_MEM | PCI_REGION_PREFETCH): |
315 | if (!hose->pci_prefetch || | |
316 | hose->pci_prefetch->size < hose->regions[i].size) | |
317 | hose->pci_prefetch = hose->regions + i; | |
318 | break; | |
c609719b WD |
319 | } |
320 | } | |
321 | ||
322 | ||
3c74e32a | 323 | if (hose->pci_mem) { |
c609719b WD |
324 | pciauto_region_init(hose->pci_mem); |
325 | ||
30e76d5e KG |
326 | DEBUGF("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n" |
327 | "\t\tPhysical Memory [%llx-%llxx]\n", | |
328 | (u64)hose->pci_mem->bus_start, | |
329 | (u64)(hose->pci_mem->bus_start + hose->pci_mem->size - 1), | |
330 | (u64)hose->pci_mem->phys_start, | |
331 | (u64)(hose->pci_mem->phys_start + hose->pci_mem->size - 1)); | |
c609719b WD |
332 | } |
333 | ||
a179012e KG |
334 | if (hose->pci_prefetch) { |
335 | pciauto_region_init(hose->pci_prefetch); | |
336 | ||
30e76d5e KG |
337 | DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n" |
338 | "\t\tPhysical Memory [%llx-%llx]\n", | |
339 | (u64)hose->pci_prefetch->bus_start, | |
340 | (u64)(hose->pci_prefetch->bus_start + | |
341 | hose->pci_prefetch->size - 1), | |
342 | (u64)hose->pci_prefetch->phys_start, | |
343 | (u64)(hose->pci_prefetch->phys_start + | |
344 | hose->pci_prefetch->size - 1)); | |
a179012e KG |
345 | } |
346 | ||
3c74e32a | 347 | if (hose->pci_io) { |
c609719b WD |
348 | pciauto_region_init(hose->pci_io); |
349 | ||
30e76d5e KG |
350 | DEBUGF("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n" |
351 | "\t\tPhysical Memory: [%llx-%llx]\n", | |
352 | (u64)hose->pci_io->bus_start, | |
353 | (u64)(hose->pci_io->bus_start + hose->pci_io->size - 1), | |
354 | (u64)hose->pci_io->phys_start, | |
355 | (u64)(hose->pci_io->phys_start + hose->pci_io->size - 1)); | |
ba5feb12 | 356 | |
c609719b WD |
357 | } |
358 | } | |
359 | ||
cb2bf931 AS |
360 | /* |
361 | * HJF: Changed this to return int. I think this is required | |
c7de829c WD |
362 | * to get the correct result when scanning bridges |
363 | */ | |
364 | int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) | |
c609719b | 365 | { |
c7de829c | 366 | unsigned int sub_bus = PCI_BUS(dev); |
c609719b WD |
367 | unsigned short class; |
368 | unsigned char prg_iface; | |
5653fc33 | 369 | int n; |
c609719b WD |
370 | |
371 | pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class); | |
372 | ||
cb2bf931 | 373 | switch (class) { |
c609719b | 374 | case PCI_CLASS_BRIDGE_PCI: |
db2f721f | 375 | hose->current_busno++; |
cb2bf931 AS |
376 | pciauto_setup_device(hose, dev, 2, hose->pci_mem, |
377 | hose->pci_prefetch, hose->pci_io); | |
c609719b | 378 | |
db2f721f | 379 | DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev)); |
cd37d9e6 | 380 | |
3c74e32a | 381 | /* Passing in current_busno allows for sibling P2P bridges */ |
5653fc33 | 382 | pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); |
cd37d9e6 | 383 | /* |
3c74e32a | 384 | * need to figure out if this is a subordinate bridge on the bus |
5653fc33 WD |
385 | * to be able to properly set the pri/sec/sub bridge registers. |
386 | */ | |
387 | n = pci_hose_scan_bus(hose, hose->current_busno); | |
388 | ||
3c74e32a | 389 | /* figure out the deepest we've gone for this leg */ |
5653fc33 | 390 | sub_bus = max(n, sub_bus); |
db2f721f | 391 | pciauto_postscan_setup_bridge(hose, dev, sub_bus); |
5653fc33 | 392 | |
db2f721f | 393 | sub_bus = hose->current_busno; |
c609719b WD |
394 | break; |
395 | ||
396 | case PCI_CLASS_STORAGE_IDE: | |
397 | pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prg_iface); | |
3c74e32a WD |
398 | if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { |
399 | DEBUGF("PCI Autoconfig: Skipping legacy mode IDE controller\n"); | |
400 | return sub_bus; | |
401 | } | |
c609719b | 402 | |
cb2bf931 AS |
403 | pciauto_setup_device(hose, dev, 6, hose->pci_mem, |
404 | hose->pci_prefetch, hose->pci_io); | |
c609719b WD |
405 | break; |
406 | ||
1cb8e980 | 407 | case PCI_CLASS_BRIDGE_CARDBUS: |
cb2bf931 AS |
408 | /* |
409 | * just do a minimal setup of the bridge, | |
410 | * let the OS take care of the rest | |
411 | */ | |
412 | pciauto_setup_device(hose, dev, 0, hose->pci_mem, | |
413 | hose->pci_prefetch, hose->pci_io); | |
1cb8e980 | 414 | |
cb2bf931 AS |
415 | DEBUGF("PCI Autoconfig: Found P2CardBus bridge, device %d\n", |
416 | PCI_DEV(dev)); | |
1cb8e980 WD |
417 | |
418 | hose->current_busno++; | |
419 | break; | |
420 | ||
f33fca22 | 421 | #if defined(CONFIG_PCIAUTO_SKIP_HOST_BRIDGE) |
e0ac62d7 WD |
422 | case PCI_CLASS_BRIDGE_OTHER: |
423 | DEBUGF("PCI Autoconfig: Skipping bridge device %d\n", | |
424 | PCI_DEV(dev)); | |
425 | break; | |
426 | #endif | |
c2e49f70 | 427 | #if defined(CONFIG_MPC834x) && !defined(CONFIG_VME8349) |
6902df56 RJ |
428 | case PCI_CLASS_BRIDGE_OTHER: |
429 | /* | |
430 | * The host/PCI bridge 1 seems broken in 8349 - it presents | |
431 | * itself as 'PCI_CLASS_BRIDGE_OTHER' and appears as an _agent_ | |
432 | * device claiming resources io/mem/irq.. we only allow for | |
433 | * the PIMMR window to be allocated (BAR0 - 1MB size) | |
434 | */ | |
435 | DEBUGF("PCI Autoconfig: Broken bridge found, only minimal config\n"); | |
cb2bf931 AS |
436 | pciauto_setup_device(hose, dev, 0, hose->pci_mem, |
437 | hose->pci_prefetch, hose->pci_io); | |
6902df56 RJ |
438 | break; |
439 | #endif | |
69fd2d3b AS |
440 | |
441 | case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */ | |
442 | DEBUGF("PCI AutoConfig: Found PowerPC device\n"); | |
443 | ||
c609719b | 444 | default: |
cb2bf931 AS |
445 | pciauto_setup_device(hose, dev, 6, hose->pci_mem, |
446 | hose->pci_prefetch, hose->pci_io); | |
c609719b WD |
447 | break; |
448 | } | |
c7de829c WD |
449 | |
450 | return sub_bus; | |
c609719b | 451 | } |