diff options
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r-- | drivers/pci/setup-bus.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index a00f85471b6e..b636e245445d 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -58,7 +58,6 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus) | |||
58 | res = list->res; | 58 | res = list->res; |
59 | idx = res - &list->dev->resource[0]; | 59 | idx = res - &list->dev->resource[0]; |
60 | if (pci_assign_resource(list->dev, idx)) { | 60 | if (pci_assign_resource(list->dev, idx)) { |
61 | /* FIXME: get rid of this */ | ||
62 | res->start = 0; | 61 | res->start = 0; |
63 | res->end = 0; | 62 | res->end = 0; |
64 | res->flags = 0; | 63 | res->flags = 0; |
@@ -143,6 +142,7 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
143 | struct pci_dev *bridge = bus->self; | 142 | struct pci_dev *bridge = bus->self; |
144 | struct pci_bus_region region; | 143 | struct pci_bus_region region; |
145 | u32 l, bu, lu, io_upper16; | 144 | u32 l, bu, lu, io_upper16; |
145 | int pref_mem64; | ||
146 | 146 | ||
147 | if (pci_is_enabled(bridge)) | 147 | if (pci_is_enabled(bridge)) |
148 | return; | 148 | return; |
@@ -198,16 +198,22 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
198 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); | 198 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); |
199 | 199 | ||
200 | /* Set up PREF base/limit. */ | 200 | /* Set up PREF base/limit. */ |
201 | pref_mem64 = 0; | ||
201 | bu = lu = 0; | 202 | bu = lu = 0; |
202 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); | 203 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); |
203 | if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { | 204 | if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { |
205 | int width = 8; | ||
204 | l = (region.start >> 16) & 0xfff0; | 206 | l = (region.start >> 16) & 0xfff0; |
205 | l |= region.end & 0xfff00000; | 207 | l |= region.end & 0xfff00000; |
206 | bu = upper_32_bits(region.start); | 208 | if (bus->resource[2]->flags & IORESOURCE_MEM_64) { |
207 | lu = upper_32_bits(region.end); | 209 | pref_mem64 = 1; |
208 | dev_info(&bridge->dev, " PREFETCH window: %#016llx-%#016llx\n", | 210 | bu = upper_32_bits(region.start); |
209 | (unsigned long long)region.start, | 211 | lu = upper_32_bits(region.end); |
210 | (unsigned long long)region.end); | 212 | width = 16; |
213 | } | ||
214 | dev_info(&bridge->dev, " PREFETCH window: %#0*llx-%#0*llx\n", | ||
215 | width, (unsigned long long)region.start, | ||
216 | width, (unsigned long long)region.end); | ||
211 | } | 217 | } |
212 | else { | 218 | else { |
213 | l = 0x0000fff0; | 219 | l = 0x0000fff0; |
@@ -215,9 +221,11 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
215 | } | 221 | } |
216 | pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); | 222 | pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); |
217 | 223 | ||
218 | /* Set the upper 32 bits of PREF base & limit. */ | 224 | if (pref_mem64) { |
219 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); | 225 | /* Set the upper 32 bits of PREF base & limit. */ |
220 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); | 226 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); |
227 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); | ||
228 | } | ||
221 | 229 | ||
222 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); | 230 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); |
223 | } | 231 | } |
@@ -255,8 +263,25 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) | |||
255 | pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); | 263 | pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); |
256 | pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); | 264 | pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); |
257 | } | 265 | } |
258 | if (pmem) | 266 | if (pmem) { |
259 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; | 267 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; |
268 | if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) | ||
269 | b_res[2].flags |= IORESOURCE_MEM_64; | ||
270 | } | ||
271 | |||
272 | /* double check if bridge does support 64 bit pref */ | ||
273 | if (b_res[2].flags & IORESOURCE_MEM_64) { | ||
274 | u32 mem_base_hi, tmp; | ||
275 | pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, | ||
276 | &mem_base_hi); | ||
277 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, | ||
278 | 0xffffffff); | ||
279 | pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp); | ||
280 | if (!tmp) | ||
281 | b_res[2].flags &= ~IORESOURCE_MEM_64; | ||
282 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, | ||
283 | mem_base_hi); | ||
284 | } | ||
260 | } | 285 | } |
261 | 286 | ||
262 | /* Helper function for sizing routines: find first available | 287 | /* Helper function for sizing routines: find first available |
@@ -336,6 +361,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long | |||
336 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ | 361 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
337 | int order, max_order; | 362 | int order, max_order; |
338 | struct resource *b_res = find_free_bus_resource(bus, type); | 363 | struct resource *b_res = find_free_bus_resource(bus, type); |
364 | unsigned int mem64_mask = 0; | ||
339 | 365 | ||
340 | if (!b_res) | 366 | if (!b_res) |
341 | return 0; | 367 | return 0; |
@@ -344,9 +370,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long | |||
344 | max_order = 0; | 370 | max_order = 0; |
345 | size = 0; | 371 | size = 0; |
346 | 372 | ||
373 | mem64_mask = b_res->flags & IORESOURCE_MEM_64; | ||
374 | b_res->flags &= ~IORESOURCE_MEM_64; | ||
375 | |||
347 | list_for_each_entry(dev, &bus->devices, bus_list) { | 376 | list_for_each_entry(dev, &bus->devices, bus_list) { |
348 | int i; | 377 | int i; |
349 | 378 | ||
350 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | 379 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { |
351 | struct resource *r = &dev->resource[i]; | 380 | struct resource *r = &dev->resource[i]; |
352 | resource_size_t r_size; | 381 | resource_size_t r_size; |
@@ -372,6 +401,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long | |||
372 | aligns[order] += align; | 401 | aligns[order] += align; |
373 | if (order > max_order) | 402 | if (order > max_order) |
374 | max_order = order; | 403 | max_order = order; |
404 | mem64_mask &= r->flags & IORESOURCE_MEM_64; | ||
375 | } | 405 | } |
376 | } | 406 | } |
377 | 407 | ||
@@ -396,6 +426,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long | |||
396 | b_res->start = min_align; | 426 | b_res->start = min_align; |
397 | b_res->end = size + min_align - 1; | 427 | b_res->end = size + min_align - 1; |
398 | b_res->flags |= IORESOURCE_STARTALIGN; | 428 | b_res->flags |= IORESOURCE_STARTALIGN; |
429 | b_res->flags |= mem64_mask; | ||
399 | return 1; | 430 | return 1; |
400 | } | 431 | } |
401 | 432 | ||