diff --git a/src/devices/hypertransport.c b/src/devices/hypertransport.c index d1e3468874..9846794edd 100644 --- a/src/devices/hypertransport.c +++ b/src/devices/hypertransport.c @@ -383,14 +383,14 @@ unsigned int hypertransport_scan_chain(struct bus *bus, struct ht_link prev; device_t last_func = 0; int ht_dev_num = 0; - unsigned temp_unitid; - unsigned not_use_count; + unsigned max_unitid; -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE +#if HT_CHAIN_END_UNITID_BASE != 0x20 //let't record the device of last ht device, So we can set the Unitid to HT_CHAIN_END_UNITID_BASE unsigned real_last_unitid; uint8_t real_last_pos; device_t real_last_dev; + unsigned end_used = 0; #endif /* Restore the hypertransport chain to it's unitialized state */ @@ -410,7 +410,7 @@ unsigned int hypertransport_scan_chain(struct bus *bus, /* If present assign unitid to a hypertransport chain */ last_unitid = min_unitid -1; - next_unitid = min_unitid; + max_unitid = next_unitid = min_unitid; do { uint8_t pos; uint16_t flags; @@ -478,26 +478,27 @@ unsigned int hypertransport_scan_chain(struct bus *bus, flags &= ~0x1f; /* mask out base Unit ID */ count = (flags >> 5) & 0x1f; /* get unit count */ - not_use_count = 0; - temp_unitid = next_unitid; -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE +#if HT_CHAIN_END_UNITID_BASE != 0x20 if(offset_unitid) { - if((next_unitid+count)>=0x20) { - temp_unitid = HT_CHAIN_END_UNITID_BASE; - //still use the old next_unitid - not_use_count = 1; + if(next_unitid > (max_devfn>>3)) { // max_devfn will be (0x17<<3)|7 or (0x1f<<3)|7 + if(!end_used) { + next_unitid = HT_CHAIN_END_UNITID_BASE; + end_used = 1; + } else { + goto out; + } } } #endif - flags |= temp_unitid & 0x1f; + flags |= next_unitid & 0x1f; pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags); /* Update the Unitd id in the device structure */ static_count = 1; for(func = dev; func; func = func->sibling) { - func->path.u.pci.devfn += (temp_unitid << 3); + func->path.u.pci.devfn += (next_unitid << 3); static_count = (func->path.u.pci.devfn >> 3) - (dev->path.u.pci.devfn >> 3) + 1; last_func = func; @@ -508,20 +509,22 @@ unsigned int hypertransport_scan_chain(struct bus *bus, if (count < static_count) { count = static_count; } - if(!not_use_count) - next_unitid += count; /* Update the Unitid of the next device */ - ht_unitid_base[ht_dev_num] = temp_unitid; + ht_unitid_base[ht_dev_num] = next_unitid; ht_dev_num++; -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE - if(offset_unitid) { +#if HT_CHAIN_END_UNITID_BASE != 0x20 + if (offset_unitid) { real_last_pos = pos; - real_last_unitid = temp_unitid; + real_last_unitid = next_unitid; real_last_dev = dev; } #endif + next_unitid += count; + if (next_unitid > max_unitid) { + max_unitid = next_unitid; + } /* Setup the hypetransport link */ bus->reset_needed |= ht_setup_link(&prev, dev, pos); @@ -531,7 +534,8 @@ unsigned int hypertransport_scan_chain(struct bus *bus, dev->vendor, dev->device, (dev->enabled? "enabled": "disabled"), next_unitid); - } while((last_unitid != next_unitid) && (next_unitid <= 0x1f /*(max_devfn >> 3)*/ )); + } while (last_unitid != next_unitid); + out: end_of_chain: #if OPT_HT_LINK == 1 if(bus->reset_needed) { @@ -542,8 +546,8 @@ unsigned int hypertransport_scan_chain(struct bus *bus, } #endif -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE - if(offset_unitid && (ht_dev_num>1) && (real_last_unitid != HT_CHAIN_END_UNITID_BASE) ) { +#if HT_CHAIN_END_UNITID_BASE != 0x20 + if(offset_unitid && (ht_dev_num>1) && (real_last_unitid != HT_CHAIN_END_UNITID_BASE) && !end_used) { uint16_t flags; int i; device_t last_func = 0; @@ -559,15 +563,18 @@ unsigned int hypertransport_scan_chain(struct bus *bus, ht_unitid_base[ht_dev_num-1] = HT_CHAIN_END_UNITID_BASE; // update last one - next_unitid = real_last_unitid; + printk_debug(" unitid: %04x --> %04x\n", + real_last_unitid, HT_CHAIN_END_UNITID_BASE); + } #endif + next_unitid = max_unitid; - if (next_unitid > 0x1f) { - next_unitid = 0x1f; + if (next_unitid > 0x20) { + next_unitid = 0x20; } - if( (bus->secondary == 0) && (next_unitid > 0x17)) { - next_unitid = 0x17; /* avoid K8 on bus 0 */ + if( (bus->secondary == 0) && (next_unitid > 0x18)) { + next_unitid = 0x18; /* avoid K8 on bus 0 */ } /* Die if any leftover Static devices are are found. diff --git a/src/northbridge/amd/amdk8/early_ht.c b/src/northbridge/amd/amdk8/early_ht.c index 1a3975a0ea..57830717ed 100644 --- a/src/northbridge/amd/amdk8/early_ht.c +++ b/src/northbridge/amd/amdk8/early_ht.c @@ -13,22 +13,23 @@ static void enumerate_ht_chain(void) * links needs to be programed to point at bus 0. */ unsigned next_unitid, last_unitid; - unsigned temp_unitid; - unsigned not_use_count; -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE + device_t dev; +#if HT_CHAIN_END_UNITID_BASE != 0x20 //let't record the device of last ht device, So we can set the Unitid to HT_CHAIN_END_UNITID_BASE unsigned real_last_unitid; uint8_t real_last_pos; int ht_dev_num = 0; // except host_bridge + uint8_t end_used = 0; #endif + dev = PCI_DEV(0,0,0); next_unitid = HT_CHAIN_UNITID_BASE; do { uint32_t id; uint8_t hdr_type, pos; last_unitid = next_unitid; - id = pci_read_config32(PCI_DEV(0,0,0), PCI_VENDOR_ID); + id = pci_read_config32(dev, PCI_VENDOR_ID); /* If the chain is enumerated quit */ if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || (((id >> 16) & 0xffff) == 0xffff) || @@ -37,73 +38,102 @@ static void enumerate_ht_chain(void) break; } - hdr_type = pci_read_config8(PCI_DEV(0,0,0), PCI_HEADER_TYPE); + hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); pos = 0; hdr_type &= 0x7f; if ((hdr_type == PCI_HEADER_TYPE_NORMAL) || (hdr_type == PCI_HEADER_TYPE_BRIDGE)) { - pos = pci_read_config8(PCI_DEV(0,0,0), PCI_CAPABILITY_LIST); + pos = pci_read_config8(dev, PCI_CAPABILITY_LIST); } while(pos != 0) { uint8_t cap; - cap = pci_read_config8(PCI_DEV(0,0,0), pos + PCI_CAP_LIST_ID); + cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID); if (cap == PCI_CAP_ID_HT) { uint16_t flags; /* Read and write and reread flags so the link * direction bit is valid. */ - flags = pci_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS); - pci_write_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS, flags); - flags = pci_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS); + flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS); + pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags); + flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS); if ((flags >> 13) == 0) { unsigned count; unsigned ctrl, ctrl_off; + device_t devx; - flags &= ~0x1f; - count = (flags >> 5) & 0x1f; - not_use_count = 0; - temp_unitid = next_unitid; -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE - if ( (count + next_unitid) >= 0x20) { - temp_unitid = HT_CHAIN_END_UNITID_BASE; - not_use_count = 1; +#if HT_CHAIN_END_UNITID_BASE != 0x20 + if(next_unitid>=0x18) { // don't get mask out by k8, at this time BSP, RT is not enabled, it will response from 0x18,0--0x1f. + if(!end_used) { + next_unitid = HT_CHAIN_END_UNITID_BASE; + end_used = 1; + } else { + goto out; + } } - real_last_unitid = temp_unitid; + real_last_unitid = next_unitid; real_last_pos = pos; ht_dev_num++; #endif - flags |= temp_unitid & 0x1f; - if(!not_use_count) - next_unitid += count; + flags &= ~0x1f; + flags |= next_unitid & 0x1f; + count = (flags >> 5) & 0x1f; + + devx = PCI_DEV(0, next_unitid, 0); + pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags); + + next_unitid += count; + + flags = pci_read_config16(devx, pos + PCI_CAP_FLAGS); /* Test for end of chain */ ctrl_off = ((flags >> 10) & 1)? - PCI_HT_CAP_SLAVE_CTRL1 : PCI_HT_CAP_SLAVE_CTRL0; - ctrl = pci_read_config16(PCI_DEV(0,0,0), pos + ctrl_off); - /* Is this the end of the hypertransport chain. - * or has the link failed? - */ - if (ctrl & ((1 << 6)|(1 << 4))) { - next_unitid = 0x20; - } - - pci_write_config16(PCI_DEV(0, 0, 0), pos + PCI_CAP_FLAGS, flags); + PCI_HT_CAP_SLAVE_CTRL0 : PCI_HT_CAP_SLAVE_CTRL1; // another end + + do { + ctrl = pci_read_config16(devx, pos + ctrl_off); + /* Is this the end of the hypertransport chain? */ + if (ctrl & (1 << 6)) { + goto out; + } + + if (ctrl & ((1 << 4) | (1 << 8))) { + /* + * Either the link has failed, or we have + * a CRC error. + * Sometimes this can happen due to link + * retrain, so lets knock it down and see + * if its transient + */ + ctrl |= ((1 << 4) | (1 <<8)); // Link fail + Crc + pci_write_config16(devx, pos + ctrl_off, ctrl); + ctrl = pci_read_config16(devx, pos + ctrl_off); + if (ctrl & ((1 << 4) | (1 << 8))) { + // can not clear the error + break; + } + } + } while((ctrl & (1 << 5)) == 0); + break; } } - pos = pci_read_config8(PCI_DEV(0, 0, 0), pos + PCI_CAP_LIST_NEXT); + pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT); } - } while((last_unitid != next_unitid) && (next_unitid <= 0x1f)); + } while(last_unitid != next_unitid); -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE - if((ht_dev_num>1) && (real_last_unitid != HT_CHAIN_END_UNITID_BASE)) { +out: + ; + +#if HT_CHAIN_END_UNITID_BASE != 0x20 + if((ht_dev_num>1) && (real_last_unitid != HT_CHAIN_END_UNITID_BASE) && !end_used) { uint16_t flags; - flags = pci_read_config16(PCI_DEV(0,real_last_unitid,0), real_last_pos + PCI_CAP_FLAGS); + dev = PCI_DEV(0,real_last_unitid, 0); + flags = pci_read_config16(dev, real_last_pos + PCI_CAP_FLAGS); flags &= ~0x1f; flags |= HT_CHAIN_END_UNITID_BASE & 0x1f; - pci_write_config16(PCI_DEV(0, real_last_unitid, 0), real_last_pos + PCI_CAP_FLAGS, flags); + pci_write_config16(dev, real_last_pos + PCI_CAP_FLAGS, flags); } #endif diff --git a/src/northbridge/amd/amdk8/incoherent_ht.c b/src/northbridge/amd/amdk8/incoherent_ht.c index dff5c9f44f..58f06468ed 100644 --- a/src/northbridge/amd/amdk8/incoherent_ht.c +++ b/src/northbridge/amd/amdk8/incoherent_ht.c @@ -314,12 +314,6 @@ static int scan_pci_bus( unsigned bus) new_bus = bus; -#if 0 -#if CONFIG_USE_PRINTK_IN_CAR - printk_debug("bus_num=%02x\r\n", bus); -#endif -#endif - for (devfn = 0; devfn <= 0xff; devfn++) { uint8_t hdr_type; uint16_t class; @@ -330,14 +324,6 @@ static int scan_pci_bus( unsigned bus) hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); class = pci_read_config16(dev, PCI_CLASS_DEVICE); -#if 0 -#if CONFIG_USE_PRINTK_IN_CAR - if(hdr_type !=0xff ) { - printk_debug("dev=%02x fn=%02x hdr_type=%02x class=%04x\r\n", - (devfn>>3)& 0x1f, (devfn & 0x7), hdr_type, class); - } -#endif -#endif switch(hdr_type & 0x7f) { /* header type */ case PCI_HEADER_TYPE_BRIDGE: if (class != PCI_CLASS_BRIDGE_PCI) goto bad; @@ -420,18 +406,17 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus, unsigned of uint8_t next_unitid, last_unitid; unsigned uoffs; - uint8_t temp_unitid; - unsigned not_use_count; #if RAMINIT_SYSINFO == 0 int reset_needed = 0; #endif -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE +#if HT_CHAIN_END_UNITID_BASE != 0x20 //let't record the device of last ht device, So we can set the Unitid to HT_CHAIN_END_UNITID_BASE unsigned real_last_unitid; uint8_t real_last_pos; int ht_dev_num = 0; + uint8_t end_used = 0; #endif uoffs = PCI_HT_HOST_OFFS; @@ -491,36 +476,36 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus, unsigned of break; } - /* Update the Unitid of the current device */ - flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS); - /* Compute the number of unitids consumed */ - count = (flags >> 5) & 0x1f; - flags &= ~0x1f; /* mask out the base Unit ID */ - not_use_count = 0; - temp_unitid = next_unitid; -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE +#if HT_CHAIN_END_UNITID_BASE != 0x20 if(offset_unitid) { - if( (next_unitid + count) >= 0x20) { - temp_unitid = HT_CHAIN_END_UNITID_BASE; - // keep to use the old next_unitid - not_use_count = 1; + if(next_unitid>= (bus ? 0x20:0x18) ) { + if(!end_used) { + next_unitid = HT_CHAIN_END_UNITID_BASE; + end_used = 1; + } else { + goto out; + } + } real_last_pos = pos; - real_last_unitid = temp_unitid; + real_last_unitid = next_unitid; ht_dev_num++; } #endif - - flags |= temp_unitid & 0x1f; + /* Update the Unitid of the current device */ + flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS); + flags &= ~0x1f; /* mask out the base Unit ID */ + flags |= next_unitid & 0x1f; pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags); + /* Compute the number of unitids consumed */ + count = (flags >> 5) & 0x1f; + /* Note the change in device number */ - dev = PCI_DEV(bus, temp_unitid, 0); - - if(!not_use_count) - next_unitid += count; + dev = PCI_DEV(bus, next_unitid, 0); + next_unitid += count; /* Find which side of the ht link we are on, * by reading which direction our last write to PCI_CAP_FLAGS @@ -550,12 +535,13 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus, unsigned of upos = pos; uoffs = ( offs != PCI_HT_SLAVE0_OFFS ) ? PCI_HT_SLAVE0_OFFS : PCI_HT_SLAVE1_OFFS; - } while((last_unitid != next_unitid) && (next_unitid <= 0x1f)); + } while (last_unitid != next_unitid ); +out: end_of_chain: ; -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE - if(offset_unitid && (ht_dev_num>1) && (real_last_unitid != HT_CHAIN_END_UNITID_BASE) ) { +#if HT_CHAIN_END_UNITID_BASE != 0x20 + if(offset_unitid && (ht_dev_num>1) && (real_last_unitid != HT_CHAIN_END_UNITID_BASE) && !end_used ) { uint16_t flags; int i; flags = pci_read_config16(PCI_DEV(bus,real_last_unitid,0), real_last_pos + PCI_CAP_FLAGS); @@ -594,7 +580,7 @@ static int ht_setup_chain(device_t udev, unsigned upos) #endif { unsigned offset_unitid = 0; -#if HT_CHAIN_UNITID_BASE != 1 +#if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) offset_unitid = 1; #endif @@ -607,7 +593,7 @@ static int ht_setup_chain(device_t udev, unsigned upos) /* Make certain the HT bus is not enumerated */ ht_collapse_previous_enumeration(0, 0); -#if HT_CHAIN_UNITID_BASE != 1 +#if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) offset_unitid = 1; #endif @@ -655,7 +641,7 @@ static int optimize_link_read_pointers_chain(uint8_t ht_c_num) uint8_t val; unsigned devn = 1; - #if HT_CHAIN_UNITID_BASE != 1 + #if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) #if SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1 if(i==0) // to check if it is sb ht chain #endif @@ -788,7 +774,7 @@ static int ht_setup_chains(uint8_t ht_c_num) pci_write_config32( PCI_DEV(0, devpos,0), regpos , dword); - #if HT_CHAIN_UNITID_BASE != 1 + #if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) #if SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1 if(i==0) // to check if it is sb ht chain #endif diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c index b285426e66..dd97ee7d16 100644 --- a/src/northbridge/amd/amdk8/northbridge.c +++ b/src/northbridge/amd/amdk8/northbridge.c @@ -111,6 +111,7 @@ static unsigned int amdk8_scan_chain(device_t dev, unsigned nodeid, unsigned lin unsigned ht_unitid_base[4]; // here assume only 4 HT device on chain unsigned max_bus; unsigned min_bus; + unsigned max_devfn; dev->link[link].cap = 0x80 + (link *0x20); do { @@ -212,7 +213,13 @@ static unsigned int amdk8_scan_chain(device_t dev, unsigned nodeid, unsigned lin for(i=0;i<4;i++) { ht_unitid_base[i] = 0x20; } - max = hypertransport_scan_chain(&dev->link[link], 0, 0xbf, max, ht_unitid_base, offset_unitid); + + if (min_bus == 0) + max_devfn = (0x17<<3) | 7; + else + max_devfn = (0x1f<<3) | 7; + + max = hypertransport_scan_chain(&dev->link[link], 0, max_devfn, max, ht_unitid_base, offset_unitid); /* We know the number of busses behind this bridge. Set the * subordinate bus number to it's real value @@ -250,12 +257,10 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) unsigned offset_unitid = 0; nodeid = amdk8_nodeid(dev); - - if(nodeid==0) { sblink = (pci_read_config32(dev, 0x64)>>8) & 3; #if SB_HT_CHAIN_ON_BUS0 > 0 - #if HT_CHAIN_UNITID_BASE != 1 + #if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) offset_unitid = 1; #endif max = amdk8_scan_chain(dev, nodeid, sblink, sblink, max, offset_unitid ); // do sb ht chain at first, in case s2885 put sb chain (8131/8111) on link2, but put 8151 on link0 @@ -267,7 +272,7 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) if( (nodeid == 0) && (sblink == link) ) continue; //already done #endif offset_unitid = 0; - #if HT_CHAIN_UNITID_BASE != 1 + #if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) #if SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1 if((nodeid == 0) && (sblink == link)) #endif @@ -276,6 +281,7 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) max = amdk8_scan_chain(dev, nodeid, link, sblink, max, offset_unitid); } + return max; } diff --git a/src/southbridge/nvidia/mcp55/mcp55_enable_rom.c b/src/southbridge/nvidia/mcp55/mcp55_enable_rom.c index 6a2697537e..f18edb74a3 100644 --- a/src/southbridge/nvidia/mcp55/mcp55_enable_rom.c +++ b/src/southbridge/nvidia/mcp55/mcp55_enable_rom.c @@ -21,7 +21,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE +#if HT_CHAIN_END_UNITID_BASE != 0x20 #define MCP55_DEVN_BASE HT_CHAIN_END_UNITID_BASE #else #define MCP55_DEVN_BASE HT_CHAIN_UNITID_BASE diff --git a/src/southbridge/nvidia/mcp55/mcp55_enable_usbdebug_direct.c b/src/southbridge/nvidia/mcp55/mcp55_enable_usbdebug_direct.c index c431724c5c..ac4e42ab8d 100644 --- a/src/southbridge/nvidia/mcp55/mcp55_enable_usbdebug_direct.c +++ b/src/southbridge/nvidia/mcp55/mcp55_enable_usbdebug_direct.c @@ -21,7 +21,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE +#if HT_CHAIN_END_UNITID_BASE != 0x20 #define MCP55_DEVN_BASE HT_CHAIN_END_UNITID_BASE #else #define MCP55_DEVN_BASE HT_CHAIN_UNITID_BASE