diff options
author | Yinghai Lu <yinghai.lu@amd.com> | 2007-09-14 14:58:33 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2007-09-14 14:58:33 +0000 |
commit | 18c70d7222bcea65d08e1ff879d8f69f2705e7ab (patch) | |
tree | cea44a5202a4bcaffd52533c76fb2d33ab1fb664 /src/northbridge/amd/amdk8/early_ht.c | |
parent | 3335adb771c5e6bf2fb200285a8af7134446bb71 (diff) | |
download | coreboot-18c70d7222bcea65d08e1ff879d8f69f2705e7ab.tar.xz |
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 <yinghai.lu@amd.com>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2776 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge/amd/amdk8/early_ht.c')
-rw-r--r-- | src/northbridge/amd/amdk8/early_ht.c | 106 |
1 files changed, 68 insertions, 38 deletions
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 |