Hello, I am a first time poster so here goes: u-boot 1.3.1 rc2 (I checked the code in 1.3.4 rc2 and it is still there)
The problem is that when enumeration is taking place when a bridge is discovered it goes through pciauto_prescan_setup_bridge() which takes the current bus_lower value from the region struct and places it in the bridge pci_memory_base register. The next process is to scan behind the bridge and then to go through pciauto_postscan_setup_bridge() to figure out what needs to be put into the pci_memory_limit register. However, the algorithm for setting the limit register does not take into account that if nothing is found behind the bridge requiring memory then bus_lower has not changed, thus when it sets the register to bus_lower - 1 this makes the limit register less than the base register. I am able to duplicate this rather easily on our ATCA carrier with 8347 processor connected to a PLX 8111 pci2pcie bridge that in turn is connected to a PLX 8524 PCIe switch that connects to our 4 PCIe x4 AMC slots. I only populate the first AMC slot with a card that requires 8MB of space and after u-boot enumeration you cannot display the memory at the address from the AMC's BAR register. This is because the other bridge segments have all programmed the limit registers incorrectly. I put code in that checks to see if anything is behind the bridge with memory and if not then zero out the base and limit registers otherwise use the bus_lower - 1 value and everything works. So, here are the changes I did here local and am thinking that if this looks ok, then I will also need to add this to the pre-fetch logic as well. void pciauto_postscan_setup_bridge(struct pci_controller *hose, pci_dev_t dev, int sub_bus) { struct pci_region *pci_mem = hose->pci_mem; struct pci_region *pci_prefetch = hose->pci_prefetch; struct pci_region *pci_io = hose->pci_io; unsigned int bridge_mem_base = 0; /* Configure bus number registers */ pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus - hose->first_busno); if (pci_mem) { /* Round memory allocator to 1MB boundary */ pciauto_region_align(pci_mem, 0x100000); + /* danny, 15aug08 + * read the the bus_lower value that was placed in the + * PCI_MEMORY_BASE register during pciauto_prescan_setup_bridge + * and check to see if anything behind it consumed memory + */ + pci_hose_read_config_word(hose, dev, PCI_MEMORY_BASE, &bridge_mem_base) ; + + if((bridge_mem_base >> 16) == ((pci_mem->bus_lower & 0xfff00000) >> 16) ) { + /* danny, 15aug08 + * since no memory was allocated behind this bridge + * then don't try to program the base and limit + * otherwise the -1 will make the upper limit value + * less than the base causing memory routing problems + */ + pci_hose_write_config_dword(hose, dev, PCI_MEMORY_BASE, 0); + } else { + /* danny, 15aug08 + * else set the limit -1 behind the next address + * boundry + */ + pci_hose_write_config_word(hose, dev, PCI_MEMORY_LIMIT, + (pci_mem->bus_lower - 1) >> 16); + } + } void pciauto_postscan_setup_bridge(struct pci_controller *hose, pci_dev_t dev, int sub_bus) { struct pci_region *pci_mem = hose->pci_mem; struct pci_region *pci_prefetch = hose->pci_prefetch; struct pci_region *pci_io = hose->pci_io; /* Configure bus number registers */ pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus - hose->first_busno); if (pci_mem) { /* Round memory allocator to 1MB boundary */ pciauto_region_align(pci_mem, 0x100000); - pci_hose_write_config_word(hose, dev, PCI_MEMORY_LIMIT, (pci_mem->bus_lower-1) >> 16); } ------------------------------------------------------ Interphase - Designed to Perform, Designed to Last (R) Danny Waldron - Technical Support Phone - 214.654.5244 ------------------------------------------------------ Disc Golf - the wind is my friend...or....every putt is an adventure for this Texas Chain Ranger!
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot