summaryrefslogtreecommitdiff
path: root/src/northbridge/amd
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/amd')
-rw-r--r--src/northbridge/amd/amdk8/incoherent_ht.c234
1 files changed, 126 insertions, 108 deletions
diff --git a/src/northbridge/amd/amdk8/incoherent_ht.c b/src/northbridge/amd/amdk8/incoherent_ht.c
index efab9edb58..db44650a1d 100644
--- a/src/northbridge/amd/amdk8/incoherent_ht.c
+++ b/src/northbridge/amd/amdk8/incoherent_ht.c
@@ -12,7 +12,7 @@ static unsigned ht_lookup_slave_capability(device_t dev)
hdr_type &= 0x7f;
if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
- (hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
+ (hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
pos = PCI_CAPABILITY_LIST;
}
if (pos > PCI_CAP_LIST_NEXT) {
@@ -48,7 +48,7 @@ static void ht_collapse_previous_enumeration(unsigned bus)
id = pci_read_config32(dev, PCI_VENDOR_ID);
if ((id == 0xffffffff) || (id == 0x00000000) ||
- (id == 0x0000ffff) || (id == 0xffff0000)) {
+ (id == 0x0000ffff) || (id == 0xffff0000)) {
continue;
}
pos = ht_lookup_slave_capability(dev);
@@ -63,7 +63,6 @@ static void ht_collapse_previous_enumeration(unsigned bus)
}
}
-
static unsigned ht_read_freq_cap(device_t dev, unsigned pos)
{
/* Handle bugs in valid hypertransport frequency reporting */
@@ -90,27 +89,27 @@ static unsigned ht_read_freq_cap(device_t dev, unsigned pos)
return freq_cap;
}
-#define LINK_OFFS(WIDTH,FREQ,FREQ_CAP) \
+#define LINK_OFFS(WIDTH,FREQ,FREQ_CAP) \
(((WIDTH & 0xff) << 16) | ((FREQ & 0xff) << 8) | (FREQ_CAP & 0xFF))
#define LINK_WIDTH(OFFS) ((OFFS >> 16) & 0xFF)
#define LINK_FREQ(OFFS) ((OFFS >> 8) & 0xFF)
#define LINK_FREQ_CAP(OFFS) ((OFFS) & 0xFF)
-#define PCI_HT_HOST_OFFS LINK_OFFS( \
- PCI_HT_CAP_HOST_WIDTH, \
- PCI_HT_CAP_HOST_FREQ, \
- PCI_HT_CAP_HOST_FREQ_CAP)
+#define PCI_HT_HOST_OFFS LINK_OFFS( \
+ PCI_HT_CAP_HOST_WIDTH, \
+ PCI_HT_CAP_HOST_FREQ, \
+ PCI_HT_CAP_HOST_FREQ_CAP)
-#define PCI_HT_SLAVE0_OFFS LINK_OFFS( \
- PCI_HT_CAP_SLAVE_WIDTH0, \
- PCI_HT_CAP_SLAVE_FREQ0, \
- PCI_HT_CAP_SLAVE_FREQ_CAP0)
+#define PCI_HT_SLAVE0_OFFS LINK_OFFS( \
+ PCI_HT_CAP_SLAVE_WIDTH0, \
+ PCI_HT_CAP_SLAVE_FREQ0, \
+ PCI_HT_CAP_SLAVE_FREQ_CAP0)
-#define PCI_HT_SLAVE1_OFFS LINK_OFFS( \
- PCI_HT_CAP_SLAVE_WIDTH1, \
- PCI_HT_CAP_SLAVE_FREQ1, \
- PCI_HT_CAP_SLAVE_FREQ_CAP1)
+#define PCI_HT_SLAVE1_OFFS LINK_OFFS( \
+ PCI_HT_CAP_SLAVE_WIDTH1, \
+ PCI_HT_CAP_SLAVE_FREQ1, \
+ PCI_HT_CAP_SLAVE_FREQ_CAP1)
static int ht_optimize_link(
device_t dev1, uint8_t pos1, unsigned offs1,
@@ -212,8 +211,8 @@ static int ht_setup_chain(device_t udev, unsigned upos)
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) ||
- (((id >> 16) & 0xffff) == 0x0000)) {
+ (((id >> 16) & 0xffff) == 0xffff) ||
+ (((id >> 16) & 0xffff) == 0x0000)) {
break;
}
pos = ht_lookup_slave_capability(dev);
@@ -242,111 +241,130 @@ static int ht_setup_chain(device_t udev, unsigned upos)
} while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
return reset_needed;
}
+
struct ht_chain {
- device_t udev;
- unsigned upos;
- unsigned devreg;
- unsigned mindev;
-};
+ device_t udev;
+ unsigned upos;
+ unsigned devreg;
+};
+
+static int ht_setup_chainx(device_t udev, unsigned upos, unsigned next_unitid)
+{
+ unsigned last_unitid;
+ unsigned uoffs;
+ int reset_needed=0;
+
+ uoffs = PCI_HT_HOST_OFFS;
+ do {
+ uint32_t id;
+ uint8_t pos;
+ unsigned flags, count;
+ device_t dev = PCI_DEV(0, 0, 0);
+ last_unitid = next_unitid;
+
+ 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) ||
+ (((id >> 16) & 0xffff) == 0x0000)) {
+ break;
+ }
+ pos = ht_lookup_slave_capability(dev);
+ if (!pos) {
+ print_err("HT link capability not found\r\n");
+ break;
+ }
+ /* Setup the Hypertransport link */
+ reset_needed |= ht_optimize_link(udev, upos, uoffs, dev, pos, PCI_HT_SLAVE0_OFFS);
+
+ /* Update the Unitid of the current device */
+ flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
+ flags &= ~0x1f; /* mask out the bse Unit ID */
+ flags |= next_unitid & 0x1f;
+ pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
+
+ /* Remeber the location of the last device */
+ udev = PCI_DEV(0, next_unitid, 0);
+ upos = pos;
+ uoffs = PCI_HT_SLAVE1_OFFS;
+
+ /* Compute the number of unitids consumed */
+ count = (flags >> 5) & 0x1f;
+ next_unitid += count;
+
+ } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
+ if(reset_needed!=0) next_unitid |= 0xffff0000;
+ return next_unitid;
+}
static int ht_setup_chains(const struct ht_chain *ht_c, int ht_c_num)
-{
- /* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
- * On most boards this just happens. If a cpu has multiple
- * non Coherent links the appropriate bus registers for the
- * links needs to be programed to point at bus 0.
- */
- unsigned next_unitid, last_unitid;
- int reset_needed;
- unsigned uoffs;
- unsigned upos;
- device_t udev;
- int i;
-
- /* Make certain the HT bus is not enumerated */
- ht_collapse_previous_enumeration(0);
-
- reset_needed = 0;
- next_unitid = 1;
-
-
- for(i=0;i<ht_c_num;i++) {
-#if 0
- unsigned tmp;
- tmp = pci_read_config8(PCI_DEV(0,0x18,1),ht_c[i].devreg);
-#endif
+{
+ /* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
+ * On most boards this just happens. If a cpu has multiple
+ * non Coherent links the appropriate bus registers for the
+ * links needs to be programed to point at bus 0.
+ */
+ unsigned next_unitid;
+ int reset_needed;
+ unsigned upos;
+ device_t udev;
+ int i;
+
+ /* Make certain the HT bus is not enumerated */
+ ht_collapse_previous_enumeration(0);
+
+ reset_needed = 0;
+ next_unitid = 1;
+
+
+ for(i=0;i<ht_c_num;i++) {
+ uint32_t reg;
+ uint8_t reg8;
+ reg = pci_read_config32(PCI_DEV(0,0x18,1), ht_c[i].devreg);
+ reg |= (0xff<<24) | 7;
+ reg &= ~(0xff<<16);
+ pci_write_config32(PCI_DEV(0,0x18,1), ht_c[i].devreg, reg);
- pci_write_config8(PCI_DEV(0,0x18,1), ht_c[i].devreg, 0);
#if CONFIG_MAX_CPUS > 1
- pci_write_config8(PCI_DEV(0,0x19,1), ht_c[i].devreg, 0);
+ pci_write_config32(PCI_DEV(0,0x19,1), ht_c[i].devreg, reg);
#endif
#if CONFIG_MAX_CPUS > 2
- pci_write_config8(PCI_DEV(0,0x1a,1), ht_c[i].devreg, 0);
- pci_write_config8(PCI_DEV(0,0x1b,1), ht_c[i].devreg, 0);
+ pci_write_config32(PCI_DEV(0,0x1a,1), ht_c[i].devreg, reg);
+ pci_write_config32(PCI_DEV(0,0x1b,1), ht_c[i].devreg, reg);
#endif
- uoffs = PCI_HT_HOST_OFFS;
- upos = ht_c[i].upos;
- udev = ht_c[i].udev;
- do {
- uint32_t id;
- uint8_t pos;
- unsigned flags, count;
- device_t dev = PCI_DEV(0, 0, 0);
- last_unitid = next_unitid;
-
- 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) ||
- (((id >> 16) & 0xffff) == 0x0000)) {
- break;
- }
- pos = ht_lookup_slave_capability(dev);
- if (!pos) {
- print_err("HT link capability not found\r\n");
- break;
- }
- /* Setup the Hypertransport link */
- reset_needed |= ht_optimize_link(udev, upos, uoffs, dev, pos, PCI_HT_SLAVE0_OFFS);
-
- /* Update the Unitid of the current device */
- flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
- flags &= ~0x1f; /* mask out the bse Unit ID */
- flags |= next_unitid & 0x1f;
- pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
-
- /* Remeber the location of the last device */
- udev = PCI_DEV(0, next_unitid, 0);
- upos = pos;
- uoffs = PCI_HT_SLAVE1_OFFS;
-
- /* Compute the number of unitids consumed */
- count = (flags >> 5) & 0x1f;
- next_unitid += count;
-
- } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
-#if 0
- pci_write_config8(PCI_DEV(0,0x18,1), ht_c[i].devreg, tmp);
+ //Store dev min
+ reg8 = next_unitid & 0xff ;
+ upos = ht_c[i].upos;
+ udev = ht_c[i].udev;
+
+ next_unitid = ht_setup_chainx(udev,upos,next_unitid);
+ if((next_unitid & 0xffff0000) == 0xffff0000) {
+ reset_needed |= 1;
+ next_unitid &=0x0000ffff;
+ }
+
+ //set dev min
+ pci_write_config8(PCI_DEV(0,0x18,1), ht_c[i].devreg+2, reg8);
#if CONFIG_MAX_CPUS > 1
- pci_write_config8(PCI_DEV(0,0x19,1), ht_c[i].devreg, tmp);
+ pci_write_config8(PCI_DEV(0,0x19,1), ht_c[i].devreg+2, reg8);
#endif
#if CONFIG_MAX_CPUS > 2
- pci_write_config8(PCI_DEV(0,0x1a,1), ht_c[i].devreg, tmp);
- pci_write_config8(PCI_DEV(0,0x1b,1), ht_c[i].devreg, tmp);
+ pci_write_config8(PCI_DEV(0,0x1a,1), ht_c[i].devreg+2, reg8);
+ pci_write_config8(PCI_DEV(0,0x1b,1), ht_c[i].devreg+2, reg8);
#endif
-#else
- pci_write_config8(PCI_DEV(0,0x18,1), ht_c[i].devreg, ht_c[i].mindev);
-#if CONFIG_MAX_CPUS > 1
- pci_write_config8(PCI_DEV(0,0x19,1), ht_c[i].devreg, ht_c[i].mindev);
+
+ //Set dev max
+ reg8 = (next_unitid-1) & 0xff ;
+ pci_write_config8(PCI_DEV(0,0x18,1), ht_c[i].devreg+3, reg8);
+#if CONFIG_MAX_CPUS > 1
+ pci_write_config8(PCI_DEV(0,0x19,1), ht_c[i].devreg+3, reg8);
#endif
#if CONFIG_MAX_CPUS > 2
- pci_write_config8(PCI_DEV(0,0x1a,1), ht_c[i].devreg, ht_c[i].mindev);
- pci_write_config8(PCI_DEV(0,0x1b,1), ht_c[i].devreg, ht_c[i].mindev);
+ pci_write_config8(PCI_DEV(0,0x1a,1), ht_c[i].devreg+3, reg8);
+ pci_write_config8(PCI_DEV(0,0x1b,1), ht_c[i].devreg+3, reg8);
#endif
-#endif
-
- }
+ }
- return reset_needed;
+ return reset_needed;
}