diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2008-10-21 08:36:08 -0500 |
---|---|---|
committer | Andrew Fleming-AFLEMING <afleming@freescale.com> | 2008-10-24 17:32:49 -0500 |
commit | 30e76d5e3bc4c5208ee63585fe12b409d9308cd8 (patch) | |
tree | c52fa2eb68646b0a85dbe307520d373a0ff9b28a /drivers/pci | |
parent | ae5f943ba8ede448a4b1a145fd8911856701ecc5 (diff) | |
download | u-boot-30e76d5e3bc4c5208ee63585fe12b409d9308cd8.tar.gz u-boot-30e76d5e3bc4c5208ee63585fe12b409d9308cd8.tar.xz u-boot-30e76d5e3bc4c5208ee63585fe12b409d9308cd8.zip |
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>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci.c | 37 | ||||
-rw-r--r-- | drivers/pci/pci_auto.c | 88 |
2 files changed, 78 insertions, 47 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 41780dbe74..e2b05d8991 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -218,12 +218,12 @@ pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index) * */ -unsigned long pci_hose_phys_to_bus (struct pci_controller *hose, +pci_addr_t pci_hose_phys_to_bus (struct pci_controller *hose, phys_addr_t phys_addr, unsigned long flags) { struct pci_region *res; - unsigned long bus_addr; + pci_addr_t bus_addr; int i; if (!hose) { @@ -252,7 +252,7 @@ Done: } phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, - unsigned long bus_addr, + pci_addr_t bus_addr, unsigned long flags) { struct pci_region *res; @@ -288,15 +288,17 @@ Done: int pci_hose_config_device(struct pci_controller *hose, pci_dev_t dev, unsigned long io, - unsigned long mem, + pci_addr_t mem, unsigned long command) { - unsigned int bar_response, bar_size, bar_value, old_command; + unsigned int bar_response, old_command; + pci_addr_t bar_value; + pci_size_t bar_size; unsigned char pin; int bar, found_mem64; - debug ("PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx\n", - io, mem, command); + debug ("PCI Config: I/O=0x%lx, Memory=0x%llx, Command=0x%lx\n", + io, (u64)mem, command); pci_hose_write_config_dword (hose, dev, PCI_COMMAND, 0); @@ -319,10 +321,19 @@ int pci_hose_config_device(struct pci_controller *hose, io = io + bar_size; } else { if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == - PCI_BASE_ADDRESS_MEM_TYPE_64) - found_mem64 = 1; + PCI_BASE_ADDRESS_MEM_TYPE_64) { + u32 bar_response_upper; + u64 bar64; + pci_hose_write_config_dword(hose, dev, bar+4, 0xffffffff); + pci_hose_read_config_dword(hose, dev, bar+4, &bar_response_upper); - bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1; + bar64 = ((u64)bar_response_upper << 32) | bar_response; + + bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1; + found_mem64 = 1; + } else { + bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1); + } /* round up region base address to multiple of size */ mem = ((mem - 1) | (bar_size - 1)) + 1; @@ -332,11 +343,15 @@ int pci_hose_config_device(struct pci_controller *hose, } /* Write it out and update our limit */ - pci_hose_write_config_dword (hose, dev, bar, bar_value); + pci_hose_write_config_dword (hose, dev, bar, (u32)bar_value); if (found_mem64) { bar += 4; +#ifdef CONFIG_SYS_PCI_64BIT + pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32)); +#else pci_hose_write_config_dword (hose, dev, bar, 0x00000000); +#endif } } diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 3844359513..c20b981b89 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -45,14 +45,14 @@ void pciauto_region_init(struct pci_region* res) res->bus_lower = res->bus_start ? res->bus_start : 0x1000; } -void pciauto_region_align(struct pci_region *res, unsigned long size) +void pciauto_region_align(struct pci_region *res, pci_size_t size) { res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1; } -int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar) +int pciauto_region_allocate(struct pci_region* res, pci_size_t size, pci_addr_t *bar) { - unsigned long addr; + pci_addr_t addr; if (!res) { DEBUGF("No resource"); @@ -68,13 +68,13 @@ int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned res->bus_lower = addr + size; - DEBUGF("address=0x%lx bus_lower=%x", addr, res->bus_lower); + DEBUGF("address=0x%llx bus_lower=0x%llx", (u64)addr, (u64)res->bus_lower); *bar = addr; return 0; error: - *bar = 0xffffffff; + *bar = (pci_addr_t)-1; return -1; } @@ -88,7 +88,9 @@ void pciauto_setup_device(struct pci_controller *hose, struct pci_region *prefetch, struct pci_region *io) { - unsigned int bar_value, bar_response, bar_size; + unsigned int bar_response; + pci_addr_t bar_value; + pci_size_t bar_size; unsigned int cmdstat = 0; struct pci_region *bar_res; int bar, bar_nr = 0; @@ -114,33 +116,46 @@ void pciauto_setup_device(struct pci_controller *hose, & 0xffff) + 1; bar_res = io; - DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%x, ", bar_nr, bar_size); + DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", bar_nr, (u64)bar_size); } else { if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == - PCI_BASE_ADDRESS_MEM_TYPE_64) - found_mem64 = 1; + PCI_BASE_ADDRESS_MEM_TYPE_64) { + u32 bar_response_upper; + u64 bar64; + pci_hose_write_config_dword(hose, dev, bar+4, 0xffffffff); + pci_hose_read_config_dword(hose, dev, bar+4, &bar_response_upper); + + bar64 = ((u64)bar_response_upper << 32) | bar_response; - bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1; + bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1; + found_mem64 = 1; + } else { + bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1); + } if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH)) bar_res = prefetch; else bar_res = mem; - DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size); + DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%llx, ", bar_nr, (u64)bar_size); } if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0) { /* Write it out and update our limit */ - pci_hose_write_config_dword(hose, dev, bar, bar_value); + pci_hose_write_config_dword(hose, dev, bar, (u32)bar_value); - /* - * If we are a 64-bit decoder then increment to the - * upper 32 bits of the bar and force it to locate - * in the lower 4GB of memory. - */ if (found_mem64) { bar += 4; +#ifdef CONFIG_SYS_PCI_64BIT + pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32)); +#else + /* + * If we are a 64-bit decoder then increment to the + * upper 32 bits of the bar and force it to locate + * in the lower 4GB of memory. + */ pci_hose_write_config_dword(hose, dev, bar, 0x00000000); +#endif } cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ? @@ -289,35 +304,36 @@ void pciauto_config_init(struct pci_controller *hose) if (hose->pci_mem) { pciauto_region_init(hose->pci_mem); - DEBUGF("PCI Autoconfig: Bus Memory region: [%lx-%lx],\n" - "\t\tPhysical Memory [%x-%x]\n", - hose->pci_mem->bus_start, - hose->pci_mem->bus_start + hose->pci_mem->size - 1, - hose->pci_mem->phys_start, - hose->pci_mem->phys_start + hose->pci_mem->size - 1); + DEBUGF("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n" + "\t\tPhysical Memory [%llx-%llxx]\n", + (u64)hose->pci_mem->bus_start, + (u64)(hose->pci_mem->bus_start + hose->pci_mem->size - 1), + (u64)hose->pci_mem->phys_start, + (u64)(hose->pci_mem->phys_start + hose->pci_mem->size - 1)); } if (hose->pci_prefetch) { pciauto_region_init(hose->pci_prefetch); - DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [%lx-%lx],\n" - "\t\tPhysical Memory [%x-%x]\n", - hose->pci_prefetch->bus_start, - hose->pci_prefetch->bus_start + hose->pci_prefetch->size - 1, - hose->pci_prefetch->phys_start, - hose->pci_prefetch->phys_start + - hose->pci_prefetch->size - 1); + DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n" + "\t\tPhysical Memory [%llx-%llx]\n", + (u64)hose->pci_prefetch->bus_start, + (u64)(hose->pci_prefetch->bus_start + + hose->pci_prefetch->size - 1), + (u64)hose->pci_prefetch->phys_start, + (u64)(hose->pci_prefetch->phys_start + + hose->pci_prefetch->size - 1)); } if (hose->pci_io) { pciauto_region_init(hose->pci_io); - DEBUGF("PCI Autoconfig: Bus I/O region: [%lx-%lx],\n" - "\t\tPhysical Memory: [%x-%x]\n", - hose->pci_io->bus_start, - hose->pci_io->bus_start + hose->pci_io->size - 1, - hose->pci_io->phys_start, - hose->pci_io->phys_start + hose->pci_io->size - 1); + DEBUGF("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n" + "\t\tPhysical Memory: [%llx-%llx]\n", + (u64)hose->pci_io->bus_start, + (u64)(hose->pci_io->bus_start + hose->pci_io->size - 1), + (u64)hose->pci_io->phys_start, + (u64)(hose->pci_io->phys_start + hose->pci_io->size - 1)); } } |