summaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdk8/early_ht.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai.lu@amd.com>2007-09-14 14:58:33 +0000
committerStefan Reinauer <stepan@openbios.org>2007-09-14 14:58:33 +0000
commit18c70d7222bcea65d08e1ff879d8f69f2705e7ab (patch)
treecea44a5202a4bcaffd52533c76fb2d33ab1fb664 /src/northbridge/amd/amdk8/early_ht.c
parent3335adb771c5e6bf2fb200285a8af7134446bb71 (diff)
downloadcoreboot-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.c106
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