Commit 7b230f61db319d87d51449d4620d520822813fbb
Exists in
master
and in
54 other branches
Merge with git://git.kernel.org/pub/scm/boot/u-boot/u-boot.git#pci
Showing 5 changed files Side-by-side Diff
CHANGELOG
... | ... | @@ -2,6 +2,24 @@ |
2 | 2 | Changes since U-Boot 1.1.4: |
3 | 3 | ====================================================================== |
4 | 4 | |
5 | +* Fixed PCI indirect config ops to handle multiple PCI controllers | |
6 | + We need to adjust the bus number we are trying to access based | |
7 | + on which PCI controller its on | |
8 | + Patch by Kumar Gala 12 Jan 2006 | |
9 | + | |
10 | +* Report back PCI bus when doing table based device config | |
11 | + Patch by Kumar Gala 11 Jan 2006 | |
12 | + | |
13 | +* Added support for PCI prefetchable region and BARs | |
14 | + If a host controller sets up a region as prefetchable and | |
15 | + a device's BAR denotes it as prefetchable, allocate the | |
16 | + BAR into the prefetch region. | |
17 | + | |
18 | + If a BAR is prefetchable and no prefetchable region has | |
19 | + been setup by the controller we fall back to allocating | |
20 | + the BAR into the normally memory region. | |
21 | + Patch by Kumar Gala 11 Jan 2006 | |
22 | + | |
5 | 23 | * Add helper function for generic flat device tree fixups for mpc83xx |
6 | 24 | Patch by Kumar Gala, 11 Jan 2006 |
7 | 25 |
drivers/pci.c
drivers/pci_auto.c
... | ... | @@ -77,6 +77,7 @@ |
77 | 77 | void pciauto_setup_device(struct pci_controller *hose, |
78 | 78 | pci_dev_t dev, int bars_num, |
79 | 79 | struct pci_region *mem, |
80 | + struct pci_region *prefetch, | |
80 | 81 | struct pci_region *io) |
81 | 82 | { |
82 | 83 | unsigned int bar_value, bar_response, bar_size; |
... | ... | @@ -111,7 +112,10 @@ |
111 | 112 | found_mem64 = 1; |
112 | 113 | |
113 | 114 | bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1; |
114 | - bar_res = mem; | |
115 | + if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH)) | |
116 | + bar_res = prefetch; | |
117 | + else | |
118 | + bar_res = mem; | |
115 | 119 | |
116 | 120 | DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size); |
117 | 121 | } |
... | ... | @@ -148,6 +152,7 @@ |
148 | 152 | pci_dev_t dev, int sub_bus) |
149 | 153 | { |
150 | 154 | struct pci_region *pci_mem = hose->pci_mem; |
155 | + struct pci_region *pci_prefetch = hose->pci_prefetch; | |
151 | 156 | struct pci_region *pci_io = hose->pci_io; |
152 | 157 | unsigned int cmdstat; |
153 | 158 | |
... | ... | @@ -169,6 +174,21 @@ |
169 | 174 | cmdstat |= PCI_COMMAND_MEMORY; |
170 | 175 | } |
171 | 176 | |
177 | + if (pci_prefetch) { | |
178 | + /* Round memory allocator to 1MB boundary */ | |
179 | + pciauto_region_align(pci_prefetch, 0x100000); | |
180 | + | |
181 | + /* Set up memory and I/O filter limits, assume 32-bit I/O space */ | |
182 | + pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, | |
183 | + (pci_prefetch->bus_lower & 0xfff00000) >> 16); | |
184 | + | |
185 | + cmdstat |= PCI_COMMAND_MEMORY; | |
186 | + } else { | |
187 | + /* We don't support prefetchable memory for now, so disable */ | |
188 | + pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000); | |
189 | + pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x1000); | |
190 | + } | |
191 | + | |
172 | 192 | if (pci_io) { |
173 | 193 | /* Round I/O allocator to 4KB boundary */ |
174 | 194 | pciauto_region_align(pci_io, 0x1000); |
... | ... | @@ -181,10 +201,6 @@ |
181 | 201 | cmdstat |= PCI_COMMAND_IO; |
182 | 202 | } |
183 | 203 | |
184 | - /* We don't support prefetchable memory for now, so disable */ | |
185 | - pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000); | |
186 | - pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x1000); | |
187 | - | |
188 | 204 | /* Enable memory and I/O accesses, enable bus master */ |
189 | 205 | pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat | PCI_COMMAND_MASTER); |
190 | 206 | } |
... | ... | @@ -193,6 +209,7 @@ |
193 | 209 | pci_dev_t dev, int sub_bus) |
194 | 210 | { |
195 | 211 | struct pci_region *pci_mem = hose->pci_mem; |
212 | + struct pci_region *pci_prefetch = hose->pci_prefetch; | |
196 | 213 | struct pci_region *pci_io = hose->pci_io; |
197 | 214 | |
198 | 215 | /* Configure bus number registers */ |
... | ... | @@ -206,6 +223,14 @@ |
206 | 223 | (pci_mem->bus_lower-1) >> 16); |
207 | 224 | } |
208 | 225 | |
226 | + if (pci_prefetch) { | |
227 | + /* Round memory allocator to 1MB boundary */ | |
228 | + pciauto_region_align(pci_prefetch, 0x100000); | |
229 | + | |
230 | + pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, | |
231 | + (pci_prefetch->bus_lower-1) >> 16); | |
232 | + } | |
233 | + | |
209 | 234 | if (pci_io) { |
210 | 235 | /* Round I/O allocator to 4KB boundary */ |
211 | 236 | pciauto_region_align(pci_io, 0x1000); |
... | ... | @@ -239,6 +264,11 @@ |
239 | 264 | hose->pci_mem->size < hose->regions[i].size) |
240 | 265 | hose->pci_mem = hose->regions + i; |
241 | 266 | break; |
267 | + case (PCI_REGION_MEM | PCI_REGION_PREFETCH): | |
268 | + if (!hose->pci_prefetch || | |
269 | + hose->pci_prefetch->size < hose->regions[i].size) | |
270 | + hose->pci_prefetch = hose->regions + i; | |
271 | + break; | |
242 | 272 | } |
243 | 273 | } |
244 | 274 | |
... | ... | @@ -251,6 +281,14 @@ |
251 | 281 | hose->pci_mem->bus_start + hose->pci_mem->size - 1); |
252 | 282 | } |
253 | 283 | |
284 | + if (hose->pci_prefetch) { | |
285 | + pciauto_region_init(hose->pci_prefetch); | |
286 | + | |
287 | + DEBUGF("PCI Autoconfig: Prefetchable Memory region: [%lx-%lx]\n", | |
288 | + hose->pci_prefetch->bus_start, | |
289 | + hose->pci_prefetch->bus_start + hose->pci_prefetch->size - 1); | |
290 | + } | |
291 | + | |
254 | 292 | if (hose->pci_io) { |
255 | 293 | pciauto_region_init(hose->pci_io); |
256 | 294 | |
... | ... | @@ -275,7 +313,7 @@ |
275 | 313 | switch(class) { |
276 | 314 | case PCI_CLASS_BRIDGE_PCI: |
277 | 315 | hose->current_busno++; |
278 | - pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_io); | |
316 | + pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_prefetch, hose->pci_io); | |
279 | 317 | |
280 | 318 | DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev)); |
281 | 319 | |
282 | 320 | |
... | ... | @@ -301,12 +339,12 @@ |
301 | 339 | return sub_bus; |
302 | 340 | } |
303 | 341 | |
304 | - pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io); | |
342 | + pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_prefetch, hose->pci_io); | |
305 | 343 | break; |
306 | 344 | |
307 | 345 | case PCI_CLASS_BRIDGE_CARDBUS: |
308 | 346 | /* just do a minimal setup of the bridge, let the OS take care of the rest */ |
309 | - pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_io); | |
347 | + pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_prefetch, hose->pci_io); | |
310 | 348 | |
311 | 349 | DEBUGF("PCI Autoconfig: Found P2CardBus bridge, device %d\n", PCI_DEV(dev)); |
312 | 350 | |
313 | 351 | |
... | ... | @@ -328,11 +366,11 @@ |
328 | 366 | * the PIMMR window to be allocated (BAR0 - 1MB size) |
329 | 367 | */ |
330 | 368 | DEBUGF("PCI Autoconfig: Broken bridge found, only minimal config\n"); |
331 | - pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_io); | |
369 | + pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_prefetch, hose->pci_io); | |
332 | 370 | break; |
333 | 371 | #endif |
334 | 372 | default: |
335 | - pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io); | |
373 | + pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_prefetch, hose->pci_io); | |
336 | 374 | break; |
337 | 375 | } |
338 | 376 |
drivers/pci_indirect.c
... | ... | @@ -36,6 +36,10 @@ |
36 | 36 | indirect_##rw##_config_##size(struct pci_controller *hose, \ |
37 | 37 | pci_dev_t dev, int offset, type val) \ |
38 | 38 | { \ |
39 | + u32 b, d,f; \ | |
40 | + b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev); \ | |
41 | + b = b - hose->first_busno; \ | |
42 | + dev = PCI_BDF(b, d, f); \ | |
39 | 43 | out_le32(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000000); \ |
40 | 44 | sync(); \ |
41 | 45 | cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \ |
... | ... | @@ -47,6 +51,10 @@ |
47 | 51 | indirect_##rw##_config_##size(struct pci_controller *hose, \ |
48 | 52 | pci_dev_t dev, int offset, type val) \ |
49 | 53 | { \ |
54 | + u32 b, d,f; \ | |
55 | + b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev); \ | |
56 | + b = b - hose->first_busno; \ | |
57 | + dev = PCI_BDF(b, d, f); \ | |
50 | 58 | *(hose->cfg_addr) = dev | (offset & 0xfc) | 0x80000000; \ |
51 | 59 | sync(); \ |
52 | 60 | cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \ |
... | ... | @@ -58,6 +66,10 @@ |
58 | 66 | indirect_##rw##_config_##size(struct pci_controller *hose, \ |
59 | 67 | pci_dev_t dev, int offset, type val) \ |
60 | 68 | { \ |
69 | + u32 b, d,f; \ | |
70 | + b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev); \ | |
71 | + b = b - hose->first_busno; \ | |
72 | + dev = PCI_BDF(b, d, f); \ | |
61 | 73 | if (PCI_BUS(dev) > 0) \ |
62 | 74 | out_le32(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000001); \ |
63 | 75 | else \ |
... | ... | @@ -71,6 +83,10 @@ |
71 | 83 | indirect_##rw##_config_##size(struct pci_controller *hose, \ |
72 | 84 | pci_dev_t dev, int offset, type val) \ |
73 | 85 | { \ |
86 | + u32 b, d,f; \ | |
87 | + b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev); \ | |
88 | + b = b - hose->first_busno; \ | |
89 | + dev = PCI_BDF(b, d, f); \ | |
74 | 90 | out_le32(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000000); \ |
75 | 91 | cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \ |
76 | 92 | return 0; \ |
include/pci.h
... | ... | @@ -309,6 +309,7 @@ |
309 | 309 | #define PCI_REGION_MEM 0x00000000 /* PCI memory space */ |
310 | 310 | #define PCI_REGION_IO 0x00000001 /* PCI IO space */ |
311 | 311 | #define PCI_REGION_TYPE 0x00000001 |
312 | +#define PCI_REGION_PREFETCH 0x00000008 /* prefetchable PCI memory */ | |
312 | 313 | |
313 | 314 | #define PCI_REGION_MEMORY 0x00000100 /* System memory */ |
314 | 315 | #define PCI_REGION_RO 0x00000200 /* Read-only memory */ |
... | ... | @@ -386,7 +387,7 @@ |
386 | 387 | int (*write_dword)(struct pci_controller*, pci_dev_t, int where, u32); |
387 | 388 | |
388 | 389 | /* Used by auto config */ |
389 | - struct pci_region *pci_mem, *pci_io; | |
390 | + struct pci_region *pci_mem, *pci_io, *pci_prefetch; | |
390 | 391 | |
391 | 392 | /* Used by ppc405 autoconfig*/ |
392 | 393 | struct pci_region *pci_fb; |
... | ... | @@ -472,6 +473,7 @@ |
472 | 473 | extern void pciauto_setup_device(struct pci_controller *hose, |
473 | 474 | pci_dev_t dev, int bars_num, |
474 | 475 | struct pci_region *mem, |
476 | + struct pci_region *prefetch, | |
475 | 477 | struct pci_region *io); |
476 | 478 | int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev); |
477 | 479 |