Commit 30e76d5e3bc4c5208ee63585fe12b409d9308cd8
Committed by
Andrew Fleming-AFLEMING
1 parent
ae5f943ba8
Exists in
master
and in
54 other branches
pci: Allow for PCI addresses to be 64-bit
PCI bus is inherently 64-bit. While not all system require access to the full 64-bit PCI address range some do. This allows those systems to enable the full PCI address width via CONFIG_SYS_PCI_64BIT. Signed-off-by: Kumar Gala <galak@kernel.crashing.org> Signed-off-by: Andrew Fleming-AFLEMING <afleming@freescale.com> Acked-by: Wolfgang Denk <wd@denx.de>
Showing 3 changed files with 102 additions and 63 deletions Side-by-side Diff
drivers/pci/pci.c
... | ... | @@ -218,12 +218,12 @@ |
218 | 218 | * |
219 | 219 | */ |
220 | 220 | |
221 | -unsigned long pci_hose_phys_to_bus (struct pci_controller *hose, | |
221 | +pci_addr_t pci_hose_phys_to_bus (struct pci_controller *hose, | |
222 | 222 | phys_addr_t phys_addr, |
223 | 223 | unsigned long flags) |
224 | 224 | { |
225 | 225 | struct pci_region *res; |
226 | - unsigned long bus_addr; | |
226 | + pci_addr_t bus_addr; | |
227 | 227 | int i; |
228 | 228 | |
229 | 229 | if (!hose) { |
... | ... | @@ -252,7 +252,7 @@ |
252 | 252 | } |
253 | 253 | |
254 | 254 | phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, |
255 | - unsigned long bus_addr, | |
255 | + pci_addr_t bus_addr, | |
256 | 256 | unsigned long flags) |
257 | 257 | { |
258 | 258 | struct pci_region *res; |
259 | 259 | |
260 | 260 | |
... | ... | @@ -288,15 +288,17 @@ |
288 | 288 | int pci_hose_config_device(struct pci_controller *hose, |
289 | 289 | pci_dev_t dev, |
290 | 290 | unsigned long io, |
291 | - unsigned long mem, | |
291 | + pci_addr_t mem, | |
292 | 292 | unsigned long command) |
293 | 293 | { |
294 | - unsigned int bar_response, bar_size, bar_value, old_command; | |
294 | + unsigned int bar_response, old_command; | |
295 | + pci_addr_t bar_value; | |
296 | + pci_size_t bar_size; | |
295 | 297 | unsigned char pin; |
296 | 298 | int bar, found_mem64; |
297 | 299 | |
298 | - debug ("PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx\n", | |
299 | - io, mem, command); | |
300 | + debug ("PCI Config: I/O=0x%lx, Memory=0x%llx, Command=0x%lx\n", | |
301 | + io, (u64)mem, command); | |
300 | 302 | |
301 | 303 | pci_hose_write_config_dword (hose, dev, PCI_COMMAND, 0); |
302 | 304 | |
303 | 305 | |
304 | 306 | |
... | ... | @@ -319,11 +321,20 @@ |
319 | 321 | io = io + bar_size; |
320 | 322 | } else { |
321 | 323 | if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == |
322 | - PCI_BASE_ADDRESS_MEM_TYPE_64) | |
323 | - found_mem64 = 1; | |
324 | + PCI_BASE_ADDRESS_MEM_TYPE_64) { | |
325 | + u32 bar_response_upper; | |
326 | + u64 bar64; | |
327 | + pci_hose_write_config_dword(hose, dev, bar+4, 0xffffffff); | |
328 | + pci_hose_read_config_dword(hose, dev, bar+4, &bar_response_upper); | |
324 | 329 | |
325 | - bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1; | |
330 | + bar64 = ((u64)bar_response_upper << 32) | bar_response; | |
326 | 331 | |
332 | + bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1; | |
333 | + found_mem64 = 1; | |
334 | + } else { | |
335 | + bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1); | |
336 | + } | |
337 | + | |
327 | 338 | /* round up region base address to multiple of size */ |
328 | 339 | mem = ((mem - 1) | (bar_size - 1)) + 1; |
329 | 340 | bar_value = mem; |
330 | 341 | |
331 | 342 | |
... | ... | @@ -332,11 +343,15 @@ |
332 | 343 | } |
333 | 344 | |
334 | 345 | /* Write it out and update our limit */ |
335 | - pci_hose_write_config_dword (hose, dev, bar, bar_value); | |
346 | + pci_hose_write_config_dword (hose, dev, bar, (u32)bar_value); | |
336 | 347 | |
337 | 348 | if (found_mem64) { |
338 | 349 | bar += 4; |
350 | +#ifdef CONFIG_SYS_PCI_64BIT | |
351 | + pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32)); | |
352 | +#else | |
339 | 353 | pci_hose_write_config_dword (hose, dev, bar, 0x00000000); |
354 | +#endif | |
340 | 355 | } |
341 | 356 | } |
342 | 357 |
drivers/pci/pci_auto.c
... | ... | @@ -45,14 +45,14 @@ |
45 | 45 | res->bus_lower = res->bus_start ? res->bus_start : 0x1000; |
46 | 46 | } |
47 | 47 | |
48 | -void pciauto_region_align(struct pci_region *res, unsigned long size) | |
48 | +void pciauto_region_align(struct pci_region *res, pci_size_t size) | |
49 | 49 | { |
50 | 50 | res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1; |
51 | 51 | } |
52 | 52 | |
53 | -int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar) | |
53 | +int pciauto_region_allocate(struct pci_region* res, pci_size_t size, pci_addr_t *bar) | |
54 | 54 | { |
55 | - unsigned long addr; | |
55 | + pci_addr_t addr; | |
56 | 56 | |
57 | 57 | if (!res) { |
58 | 58 | DEBUGF("No resource"); |
59 | 59 | |
... | ... | @@ -68,13 +68,13 @@ |
68 | 68 | |
69 | 69 | res->bus_lower = addr + size; |
70 | 70 | |
71 | - DEBUGF("address=0x%lx bus_lower=%x", addr, res->bus_lower); | |
71 | + DEBUGF("address=0x%llx bus_lower=0x%llx", (u64)addr, (u64)res->bus_lower); | |
72 | 72 | |
73 | 73 | *bar = addr; |
74 | 74 | return 0; |
75 | 75 | |
76 | 76 | error: |
77 | - *bar = 0xffffffff; | |
77 | + *bar = (pci_addr_t)-1; | |
78 | 78 | return -1; |
79 | 79 | } |
80 | 80 | |
... | ... | @@ -88,7 +88,9 @@ |
88 | 88 | struct pci_region *prefetch, |
89 | 89 | struct pci_region *io) |
90 | 90 | { |
91 | - unsigned int bar_value, bar_response, bar_size; | |
91 | + unsigned int bar_response; | |
92 | + pci_addr_t bar_value; | |
93 | + pci_size_t bar_size; | |
92 | 94 | unsigned int cmdstat = 0; |
93 | 95 | struct pci_region *bar_res; |
94 | 96 | int bar, bar_nr = 0; |
95 | 97 | |
96 | 98 | |
97 | 99 | |
98 | 100 | |
99 | 101 | |
100 | 102 | |
101 | 103 | |
... | ... | @@ -114,33 +116,46 @@ |
114 | 116 | & 0xffff) + 1; |
115 | 117 | bar_res = io; |
116 | 118 | |
117 | - DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%x, ", bar_nr, bar_size); | |
119 | + DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", bar_nr, (u64)bar_size); | |
118 | 120 | } else { |
119 | 121 | if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == |
120 | - PCI_BASE_ADDRESS_MEM_TYPE_64) | |
121 | - found_mem64 = 1; | |
122 | + PCI_BASE_ADDRESS_MEM_TYPE_64) { | |
123 | + u32 bar_response_upper; | |
124 | + u64 bar64; | |
125 | + pci_hose_write_config_dword(hose, dev, bar+4, 0xffffffff); | |
126 | + pci_hose_read_config_dword(hose, dev, bar+4, &bar_response_upper); | |
122 | 127 | |
123 | - bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1; | |
128 | + bar64 = ((u64)bar_response_upper << 32) | bar_response; | |
129 | + | |
130 | + bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1; | |
131 | + found_mem64 = 1; | |
132 | + } else { | |
133 | + bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1); | |
134 | + } | |
124 | 135 | if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH)) |
125 | 136 | bar_res = prefetch; |
126 | 137 | else |
127 | 138 | bar_res = mem; |
128 | 139 | |
129 | - DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size); | |
140 | + DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%llx, ", bar_nr, (u64)bar_size); | |
130 | 141 | } |
131 | 142 | |
132 | 143 | if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0) { |
133 | 144 | /* Write it out and update our limit */ |
134 | - pci_hose_write_config_dword(hose, dev, bar, bar_value); | |
145 | + pci_hose_write_config_dword(hose, dev, bar, (u32)bar_value); | |
135 | 146 | |
136 | - /* | |
137 | - * If we are a 64-bit decoder then increment to the | |
138 | - * upper 32 bits of the bar and force it to locate | |
139 | - * in the lower 4GB of memory. | |
140 | - */ | |
141 | 147 | if (found_mem64) { |
142 | 148 | bar += 4; |
149 | +#ifdef CONFIG_SYS_PCI_64BIT | |
150 | + pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32)); | |
151 | +#else | |
152 | + /* | |
153 | + * If we are a 64-bit decoder then increment to the | |
154 | + * upper 32 bits of the bar and force it to locate | |
155 | + * in the lower 4GB of memory. | |
156 | + */ | |
143 | 157 | pci_hose_write_config_dword(hose, dev, bar, 0x00000000); |
158 | +#endif | |
144 | 159 | } |
145 | 160 | |
146 | 161 | cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ? |
147 | 162 | |
148 | 163 | |
... | ... | @@ -289,35 +304,36 @@ |
289 | 304 | if (hose->pci_mem) { |
290 | 305 | pciauto_region_init(hose->pci_mem); |
291 | 306 | |
292 | - DEBUGF("PCI Autoconfig: Bus Memory region: [%lx-%lx],\n" | |
293 | - "\t\tPhysical Memory [%x-%x]\n", | |
294 | - hose->pci_mem->bus_start, | |
295 | - hose->pci_mem->bus_start + hose->pci_mem->size - 1, | |
296 | - hose->pci_mem->phys_start, | |
297 | - hose->pci_mem->phys_start + hose->pci_mem->size - 1); | |
307 | + DEBUGF("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n" | |
308 | + "\t\tPhysical Memory [%llx-%llxx]\n", | |
309 | + (u64)hose->pci_mem->bus_start, | |
310 | + (u64)(hose->pci_mem->bus_start + hose->pci_mem->size - 1), | |
311 | + (u64)hose->pci_mem->phys_start, | |
312 | + (u64)(hose->pci_mem->phys_start + hose->pci_mem->size - 1)); | |
298 | 313 | } |
299 | 314 | |
300 | 315 | if (hose->pci_prefetch) { |
301 | 316 | pciauto_region_init(hose->pci_prefetch); |
302 | 317 | |
303 | - DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [%lx-%lx],\n" | |
304 | - "\t\tPhysical Memory [%x-%x]\n", | |
305 | - hose->pci_prefetch->bus_start, | |
306 | - hose->pci_prefetch->bus_start + hose->pci_prefetch->size - 1, | |
307 | - hose->pci_prefetch->phys_start, | |
308 | - hose->pci_prefetch->phys_start + | |
309 | - hose->pci_prefetch->size - 1); | |
318 | + DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n" | |
319 | + "\t\tPhysical Memory [%llx-%llx]\n", | |
320 | + (u64)hose->pci_prefetch->bus_start, | |
321 | + (u64)(hose->pci_prefetch->bus_start + | |
322 | + hose->pci_prefetch->size - 1), | |
323 | + (u64)hose->pci_prefetch->phys_start, | |
324 | + (u64)(hose->pci_prefetch->phys_start + | |
325 | + hose->pci_prefetch->size - 1)); | |
310 | 326 | } |
311 | 327 | |
312 | 328 | if (hose->pci_io) { |
313 | 329 | pciauto_region_init(hose->pci_io); |
314 | 330 | |
315 | - DEBUGF("PCI Autoconfig: Bus I/O region: [%lx-%lx],\n" | |
316 | - "\t\tPhysical Memory: [%x-%x]\n", | |
317 | - hose->pci_io->bus_start, | |
318 | - hose->pci_io->bus_start + hose->pci_io->size - 1, | |
319 | - hose->pci_io->phys_start, | |
320 | - hose->pci_io->phys_start + hose->pci_io->size - 1); | |
331 | + DEBUGF("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n" | |
332 | + "\t\tPhysical Memory: [%llx-%llx]\n", | |
333 | + (u64)hose->pci_io->bus_start, | |
334 | + (u64)(hose->pci_io->bus_start + hose->pci_io->size - 1), | |
335 | + (u64)hose->pci_io->phys_start, | |
336 | + (u64)(hose->pci_io->phys_start + hose->pci_io->size - 1)); | |
321 | 337 | |
322 | 338 | } |
323 | 339 | } |
include/pci.h
... | ... | @@ -101,8 +101,8 @@ |
101 | 101 | #define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ |
102 | 102 | #define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ |
103 | 103 | #define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ |
104 | -#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) | |
105 | -#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL) | |
104 | +#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fULL) | |
105 | +#define PCI_BASE_ADDRESS_IO_MASK (~0x03ULL) | |
106 | 106 | /* bit 1 is reserved if address_space = 1 */ |
107 | 107 | |
108 | 108 | /* Header type 0 (normal devices) */ |
... | ... | @@ -111,7 +111,7 @@ |
111 | 111 | #define PCI_SUBSYSTEM_ID 0x2e |
112 | 112 | #define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ |
113 | 113 | #define PCI_ROM_ADDRESS_ENABLE 0x01 |
114 | -#define PCI_ROM_ADDRESS_MASK (~0x7ffUL) | |
114 | +#define PCI_ROM_ADDRESS_MASK (~0x7ffULL) | |
115 | 115 | |
116 | 116 | #define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ |
117 | 117 | |
118 | 118 | |
119 | 119 | |
... | ... | @@ -312,13 +312,21 @@ |
312 | 312 | |
313 | 313 | #include <pci_ids.h> |
314 | 314 | |
315 | +#ifdef CONFIG_SYS_PCI_64BIT | |
316 | +typedef u64 pci_addr_t; | |
317 | +typedef u64 pci_size_t; | |
318 | +#else | |
319 | +typedef u32 pci_addr_t; | |
320 | +typedef u32 pci_size_t; | |
321 | +#endif | |
322 | + | |
315 | 323 | struct pci_region { |
316 | - unsigned long bus_start; /* Start on the bus */ | |
317 | - phys_addr_t phys_start; /* Start in physical address space */ | |
318 | - unsigned long size; /* Size */ | |
319 | - unsigned long flags; /* Resource flags */ | |
324 | + pci_addr_t bus_start; /* Start on the bus */ | |
325 | + phys_addr_t phys_start; /* Start in physical address space */ | |
326 | + pci_size_t size; /* Size */ | |
327 | + unsigned long flags; /* Resource flags */ | |
320 | 328 | |
321 | - unsigned long bus_lower; | |
329 | + pci_addr_t bus_lower; | |
322 | 330 | }; |
323 | 331 | |
324 | 332 | #define PCI_REGION_MEM 0x00000000 /* PCI memory space */ |
325 | 333 | |
... | ... | @@ -330,9 +338,9 @@ |
330 | 338 | #define PCI_REGION_RO 0x00000200 /* Read-only memory */ |
331 | 339 | |
332 | 340 | extern __inline__ void pci_set_region(struct pci_region *reg, |
333 | - unsigned long bus_start, | |
341 | + pci_addr_t bus_start, | |
334 | 342 | phys_addr_t phys_start, |
335 | - unsigned long size, | |
343 | + pci_size_t size, | |
336 | 344 | unsigned long flags) { |
337 | 345 | reg->bus_start = bus_start; |
338 | 346 | reg->phys_start = phys_start; |
... | ... | @@ -433,9 +441,9 @@ |
433 | 441 | extern void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data); |
434 | 442 | |
435 | 443 | extern phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, |
436 | - unsigned long addr, unsigned long flags); | |
437 | -extern unsigned long pci_hose_phys_to_bus(struct pci_controller* hose, | |
438 | - phys_addr_t addr, unsigned long flags); | |
444 | + pci_addr_t addr, unsigned long flags); | |
445 | +extern pci_addr_t pci_hose_phys_to_bus(struct pci_controller* hose, | |
446 | + phys_addr_t addr, unsigned long flags); | |
439 | 447 | |
440 | 448 | #define pci_phys_to_bus(dev, addr, flags) \ |
441 | 449 | pci_hose_phys_to_bus(pci_bus_to_hose(PCI_BUS(dev)), (addr), (flags)) |
... | ... | @@ -483,8 +491,8 @@ |
483 | 491 | extern int pci_hose_scan_bus(struct pci_controller *hose, int bus); |
484 | 492 | |
485 | 493 | extern void pciauto_region_init(struct pci_region* res); |
486 | -extern void pciauto_region_align(struct pci_region *res, unsigned long size); | |
487 | -extern int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar); | |
494 | +extern void pciauto_region_align(struct pci_region *res, pci_size_t size); | |
495 | +extern int pciauto_region_allocate(struct pci_region* res, pci_size_t size, pci_addr_t *bar); | |
488 | 496 | extern void pciauto_setup_device(struct pci_controller *hose, |
489 | 497 | pci_dev_t dev, int bars_num, |
490 | 498 | struct pci_region *mem, |
... | ... | @@ -500,7 +508,7 @@ |
500 | 508 | extern int pci_hose_config_device(struct pci_controller *hose, |
501 | 509 | pci_dev_t dev, |
502 | 510 | unsigned long io, |
503 | - unsigned long mem, | |
511 | + pci_addr_t mem, | |
504 | 512 | unsigned long command); |
505 | 513 | |
506 | 514 | #ifdef CONFIG_MPC824X |