From 18c70d7222bcea65d08e1ff879d8f69f2705e7ab Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 14 Sep 2007 14:58:33 +0000 Subject: More range for HT_CHAIN_UNITID_BASE and HT_CHAIN_END_UNITID_BASE. For example: in C51/MCP55 or C51/MCP51 Will allow 1. C51 at 0x10 to 0x14, and MCP at 0 to 4 2. C51 at 1 to 4, and MCP at 7 to 0x0a The reason is c51/mcp51/mcp55 reported unitid is 0x0f (far beyond it needed), and will prevent us from putting them on bus 0. Typical values for c51/mcp55 or c51/mcp51: HT_CHAIN_UNITID_BASE = 0x10 # for C51 HT_CHAIN_END_UNITID_BASE = 0 # for mcp If only have mcp with c51, HT_CHAIN_UNITID_BASE = 0 # for MCP #HT_CHAIN_END_UNITID_BASE = 0 # default value 0x20 Signed-off-by: Yinghai Lu Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2776 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/northbridge/amd/amdk8/early_ht.c | 106 +++++++++++++++++++----------- src/northbridge/amd/amdk8/incoherent_ht.c | 72 ++++++++------------ src/northbridge/amd/amdk8/northbridge.c | 16 +++-- 3 files changed, 108 insertions(+), 86 deletions(-) (limited to 'src/northbridge') 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); + +out: + ; -#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE - if((ht_dev_num>1) && (real_last_unitid != HT_CHAIN_END_UNITID_BASE)) { +#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); - /* Note the change in device number */ - dev = PCI_DEV(bus, temp_unitid, 0); + /* Compute the number of unitids consumed */ + count = (flags >> 5) & 0x1f; - if(!not_use_count) - next_unitid += count; + /* Note the change in device number */ + 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; } -- cgit v1.2.3