aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdk8
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/amd/amdk8')
-rw-r--r--src/northbridge/amd/amdk8/amdk8.h6
-rw-r--r--src/northbridge/amd/amdk8/coherent_ht.c2
-rw-r--r--src/northbridge/amd/amdk8/debug.c13
-rw-r--r--src/northbridge/amd/amdk8/early_ht.c35
-rw-r--r--src/northbridge/amd/amdk8/incoherent_ht.c360
-rw-r--r--src/northbridge/amd/amdk8/misc_control.c3
-rw-r--r--src/northbridge/amd/amdk8/northbridge.c81
7 files changed, 412 insertions, 88 deletions
diff --git a/src/northbridge/amd/amdk8/amdk8.h b/src/northbridge/amd/amdk8/amdk8.h
index 89c03fc16b..7e064af974 100644
--- a/src/northbridge/amd/amdk8/amdk8.h
+++ b/src/northbridge/amd/amdk8/amdk8.h
@@ -1,3 +1,7 @@
+#ifndef AMDK8_H
+
+#define AMDK8_H
+
/* Definitions of various K8 registers */
/* Function 0 */
#define HT_TRANSACTION_CONTROL 0x68
@@ -226,3 +230,5 @@
#define InitComplete (1 << 1)
#define NonCoherent (1 << 2)
#define ConnectionPending (1 << 4)
+
+#endif
diff --git a/src/northbridge/amd/amdk8/coherent_ht.c b/src/northbridge/amd/amdk8/coherent_ht.c
index 36d2dcded5..7d43f3c97d 100644
--- a/src/northbridge/amd/amdk8/coherent_ht.c
+++ b/src/northbridge/amd/amdk8/coherent_ht.c
@@ -1812,9 +1812,9 @@ static int setup_coherent_ht_domain(void)
#if CONFIG_MAX_PHYSICAL_CPUS > 1
result = setup_smp();
-#endif
result.nodes = verify_mp_capabilities(result.nodes);
clear_dead_routes(result.nodes);
+#endif
if (result.nodes == 1) {
setup_uniprocessor();
}
diff --git a/src/northbridge/amd/amdk8/debug.c b/src/northbridge/amd/amdk8/debug.c
index d0841e878e..ca45cbe519 100644
--- a/src/northbridge/amd/amdk8/debug.c
+++ b/src/northbridge/amd/amdk8/debug.c
@@ -2,6 +2,18 @@
* generic K8 debug code, used by mainboard specific auto.c
*
*/
+
+static inline void print_debug_addr(const char *str, void *val)
+{
+#if CACHE_AS_RAM_ADDRESS_DEBUG == 1
+ #if CONFIG_USE_INIT==1
+ printk_debug("------Address debug: %s%x------\r\n", str, val);
+ #else
+ print_debug ("------Address debug: "); print_debug(str); print_debug_hex32(val); print_debug("------\r\n");
+ #endif
+#endif
+}
+
#if 1
static void print_debug_pci_dev(unsigned dev)
{
@@ -34,6 +46,7 @@ static void print_pci_devices(void)
#if CONFIG_USE_INIT
printk_debug(" %04x:%04x\r\n", (id & 0xffff), (id>>16));
#else
+ print_debug(" ");
print_debug_hex32(id);
print_debug("\r\n");
#endif
diff --git a/src/northbridge/amd/amdk8/early_ht.c b/src/northbridge/amd/amdk8/early_ht.c
index 2711657455..5134494943 100644
--- a/src/northbridge/amd/amdk8/early_ht.c
+++ b/src/northbridge/amd/amdk8/early_ht.c
@@ -1,14 +1,26 @@
-static int enumerate_ht_chain(void)
+/*
+ 2005.11 yhlu add let the real sb to use small unitid
+*/
+// only for sb ht chain
+static void enumerate_ht_chain(void)
{
+#if HT_CHAIN_UNITID_BASE != 0
+/* HT_CHAIN_UNITID_BASE could be 0 (only one ht device in the ht chain), if so, don't need to go through the chain */
+
/* 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 = 0;
+#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
+ //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
+#endif
- next_unitid = 1;
+ next_unitid = HT_CHAIN_UNITID_BASE;
do {
uint32_t id;
uint8_t hdr_type, pos;
@@ -58,6 +70,11 @@ static int enumerate_ht_chain(void)
flags &= ~0x1f;
flags |= next_unitid & 0x1f;
count = (flags >> 5) & 0x1f;
+#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
+ real_last_unitid = next_unitid;
+ real_last_pos = pos;
+ ht_dev_num++ ;
+#endif
next_unitid += count;
/* Test for end of chain */
@@ -78,7 +95,17 @@ static int enumerate_ht_chain(void)
pos = pci_read_config8(PCI_DEV(0, 0, 0), pos + PCI_CAP_LIST_NEXT);
}
} while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
+#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
+ if(ht_dev_num>0) {
+ uint16_t flags;
+ flags = pci_read_config16(PCI_DEV(0,real_last_unitid,0), 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);
+ }
+#endif
+
+#endif
- return reset_needed;
}
diff --git a/src/northbridge/amd/amdk8/incoherent_ht.c b/src/northbridge/amd/amdk8/incoherent_ht.c
index bdb2676e39..02a0c2dccd 100644
--- a/src/northbridge/amd/amdk8/incoherent_ht.c
+++ b/src/northbridge/amd/amdk8/incoherent_ht.c
@@ -1,17 +1,12 @@
/*
This should be done by Eric
2004.12 yhlu add multi ht chain dynamically support
-
+ 2005.11 yhlu add let real sb to use small unitid
*/
#include <device/pci_def.h>
#include <device/pci_ids.h>
#include <device/hypertransport_def.h>
-
-/* We can reduce the size of code generated by romcc by
- * changing all of the fixed size types that live in registers
- * into simple unsigned variables. (ie s/uint8_t/unsigned/g)
- */
#ifndef K8_HT_FREQ_1G_SUPPORT
#define K8_HT_FREQ_1G_SUPPORT 0
#endif
@@ -20,15 +15,22 @@
#define K8_SCAN_PCI_BUS 0
#endif
+#ifndef K8_ALLOCATE_IO_RANGE
+ #define K8_ALLOCATE_IO_RANGE 0
+#endif
+
+// Do we need allocate MMIO? Current We direct last 64M to sblink only, We can not lose access to last 4M range to ROM
+#ifndef K8_ALLOCATE_MMIO_RANGE
+ #define K8_ALLOCATE_MMIO_RANGE 0
+#endif
+
static inline void print_linkn_in (const char *strval, uint8_t byteval)
{
-#if 1
#if CONFIG_USE_INIT
printk_debug("%s%02x\r\n", strval, byteval);
#else
print_debug(strval); print_debug_hex8(byteval); print_debug("\r\n");
#endif
-#endif
}
static uint8_t ht_lookup_capability(device_t dev, uint16_t val)
@@ -74,18 +76,27 @@ static uint8_t ht_lookup_host_capability(device_t dev)
return ht_lookup_capability(dev, 1); // Host/Secondary Interface Block Format
}
-static void ht_collapse_previous_enumeration(uint8_t bus)
+static void ht_collapse_previous_enumeration(uint8_t bus, unsigned offset_unitid)
{
device_t dev;
uint32_t id;
+ //actually, only for one HT device HT chain, and unitid is 0
+#if HT_CHAIN_UNITID_BASE == 0
+ if(offset_unitid) {
+ return;
+ }
+#endif
+
/* Check if is already collapsed */
- dev = PCI_DEV(bus, 0, 0);
- id = pci_read_config32(dev, PCI_VENDOR_ID);
- if ( ! ( (id == 0xffffffff) || (id == 0x00000000) ||
- (id == 0x0000ffff) || (id == 0xffff0000) ) ) {
- return;
- }
+ if((!offset_unitid) || (offset_unitid && (!((HT_CHAIN_END_UNITID_BASE == 0) && (HT_CHAIN_END_UNITID_BASE <HT_CHAIN_UNITID_BASE))))) {
+ dev = PCI_DEV(bus, 0, 0);
+ id = pci_read_config32(dev, PCI_VENDOR_ID);
+ if ( ! ( (id == 0xffffffff) || (id == 0x00000000) ||
+ (id == 0x0000ffff) || (id == 0xffff0000) ) ) {
+ return;
+ }
+ }
/* Spin through the devices and collapse any previous
* hypertransport enumeration.
@@ -136,21 +147,24 @@ static uint16_t ht_read_freq_cap(device_t dev, uint8_t pos)
/* AMD 8131 Errata 48 */
if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8131_PCIX << 16))) {
freq_cap &= ~(1 << HT_FREQ_800Mhz);
- }
+ return freq_cap;
+ }
/* AMD 8151 Errata 23 */
if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8151_SYSCTRL << 16))) {
freq_cap &= ~(1 << HT_FREQ_800Mhz);
+ return freq_cap;
}
/* AMD K8 Unsupported 1Ghz? */
if (id == (PCI_VENDOR_ID_AMD | (0x1100 << 16))) {
-#if K8_HT_FREQ_1G_SUPPORT == 1
- /* Supported starting with E0 */
- device_t dev_2 = PCI_DEV(0,0x18,2);
- if(pci_read_config32(dev_2,0x9c) < 0x20f00)
-#endif
+ #if K8_HT_FREQ_1G_SUPPORT == 1
+ if (is_cpu_pre_e0()) { // only E0 later support 1GHz
freq_cap &= ~(1 << HT_FREQ_1000Mhz);
+ }
+ #else
+ freq_cap &= ~(1 << HT_FREQ_1000Mhz);
+ #endif
}
return freq_cap;
@@ -236,6 +250,7 @@ static int ht_optimize_link(
/* See if I am changing dev1's width */
old_width = pci_read_config8(dev1, pos1 + LINK_WIDTH(offs1) + 1);
+ old_width &= 0x77;
needs_reset |= old_width != width;
/* Set dev1's widths */
@@ -246,6 +261,7 @@ static int ht_optimize_link(
/* See if I am changing dev2's width */
old_width = pci_read_config8(dev2, pos2 + LINK_WIDTH(offs2) + 1);
+ old_width &= 0x77;
needs_reset |= old_width != width;
/* Set dev2's widths */
@@ -254,8 +270,14 @@ static int ht_optimize_link(
return needs_reset;
}
#if (USE_DCACHE_RAM == 1) && (K8_SCAN_PCI_BUS == 1)
-static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus);
-static int scan_pci_bus( unsigned bus)
+
+#if RAMINIT_SYSINFO == 1
+static void ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus, unsigned offset_unitid, struct sys_info *sysinfo);
+static int scan_pci_bus( unsigned bus , struct sys_info *sysinfo)
+#else
+static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus, unsigned offset_unitid);
+static int scan_pci_bus( unsigned bus)
+#endif
{
/*
here we already can access PCI_DEV(bus, 0, 0) to PCI_DEV(bus, 0x1f, 0x7)
@@ -324,24 +346,30 @@ static int scan_pci_bus( unsigned bus)
((unsigned int) max_bus << 16));
pci_write_config32(dev, PCI_PRIMARY_BUS, buses);
- {
/* here we need to figure out if dev is a ht bridge
if it is ht bridge, we need to call ht_setup_chainx at first
Not verified --- yhlu
*/
- uint8_t upos;
- upos = ht_lookup_host_capability(dev); // one func one ht sub
- if (upos) { // sub ht chain
- uint8_t busn;
- busn = (new_bus & 0xff);
- /* Make certain the HT bus is not enumerated */
- ht_collapse_previous_enumeration(busn);
- /* scan the ht chain */
- new_bus |= (ht_setup_chainx(dev,upos,busn)<<16); // store reset_needed to upword
- }
- }
+ uint8_t upos;
+ upos = ht_lookup_host_capability(dev); // one func one ht sub
+ if (upos) { // sub ht chain
+ uint8_t busn;
+ busn = (new_bus & 0xff);
+ /* Make certain the HT bus is not enumerated */
+ ht_collapse_previous_enumeration(busn, 0);
+ /* scan the ht chain */
+ #if RAMINIT_SYSINFO == 1
+ ht_setup_chainx(dev,upos,busn, 0, sysinfo); // don't need offset unitid
+ #else
+ new_bus |= (ht_setup_chainx(dev, upos, busn, 0)<<16); // store reset_needed to upword
+ #endif
+ }
+ #if RAMINIT_SYSINFO == 1
+ new_bus = scan_pci_bus(new_bus, sysinfo);
+ #else
new_bus = scan_pci_bus(new_bus);
+ #endif
/* set real max bus num in that */
buses = (buses & 0xff00ffff) |
@@ -370,14 +398,31 @@ static int scan_pci_bus( unsigned bus)
return new_bus;
}
#endif
-static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus)
+
+#if RAMINIT_SYSINFO == 1
+static void ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus, unsigned offset_unitid, struct sys_info *sysinfo)
+#else
+static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus, unsigned offset_unitid)
+#endif
{
+ //even HT_CHAIN_UNITID_BASE == 0, we still can go through this function, because of end_of_chain check, also We need it to optimize link
+
uint8_t next_unitid, last_unitid;
unsigned uoffs;
- int reset_needed=0;
+
+#if RAMINIT_SYSINFO == 0
+ int reset_needed = 0;
+#endif
+
+#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
+ //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;
+#endif
uoffs = PCI_HT_HOST_OFFS;
- next_unitid = 1;
+ next_unitid = (offset_unitid) ? HT_CHAIN_UNITID_BASE:1;
do {
uint32_t id;
@@ -391,11 +436,24 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus)
ctrl = pci_read_config16(udev, upos + LINK_CTRL(uoffs));
/* Is this the end of the hypertransport chain? */
if (ctrl & (1 << 6)) {
- break;
+ goto end_of_chain;
}
- /* Has the link failed */
- if (ctrl & (1 << 4)) {
- break;
+
+ 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 << 6) | (1 <<8)); // Link fail + Crc
+ pci_write_config16(udev, upos + LINK_CTRL(uoffs), ctrl);
+ ctrl = pci_read_config16(udev, upos + LINK_CTRL(uoffs));
+ if (ctrl & ((1 << 4) | (1 << 8))) {
+ print_err("Detected error on Hypertransport Link\n");
+ break;
+ }
}
} while((ctrl & (1 << 5)) == 0);
@@ -413,7 +471,10 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus)
pos = ht_lookup_slave_capability(dev);
if (!pos) {
- print_err("HT link capability not found\r\n");
+ print_err("udev="); print_err_hex32(udev);
+ print_err("\tupos="); print_err_hex32(upos);
+ print_err("\tuoffs="); print_err_hex32(uoffs);
+ print_err("\tHT link capability not found\r\n");
break;
}
@@ -441,6 +502,14 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus)
/* Compute the number of unitids consumed */
count = (flags >> 5) & 0x1f;
+#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
+ if(offset_unitid) {
+ real_last_unitid = next_unitid;
+ real_last_pos = pos;
+ ht_dev_num++;
+ }
+#endif
+
next_unitid += count;
/* Find which side of the ht link we are on,
@@ -449,9 +518,22 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus)
*/
flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
offs = ((flags>>10) & 1) ? PCI_HT_SLAVE1_OFFS : PCI_HT_SLAVE0_OFFS;
-
- /* Setup the Hypertransport link */
- reset_needed |= ht_optimize_link(udev, upos, uoffs, dev, pos, offs);
+
+ #if RAMINIT_SYSINFO == 1
+ /* store the link pair here and we will Setup the Hypertransport link later, after we get final FID/VID */
+ {
+ struct link_pair_st *link_pair = &sysinfo->link_pair[sysinfo->link_pair_num];
+ link_pair->udev = udev;
+ link_pair->upos = upos;
+ link_pair->uoffs = uoffs;
+ link_pair->dev = dev;
+ link_pair->pos = pos;
+ link_pair->offs = offs;
+ sysinfo->link_pair_num++;
+ }
+ #else
+ reset_needed |= ht_optimize_link(udev, upos, uoffs, dev, pos, offs);
+ #endif
#if CK804_DEVN_BASE==0
if(id == 0x005e10de) {
@@ -466,11 +548,52 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus)
} while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
+end_of_chain: ;
+
+#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
+ if(offset_unitid && (ht_dev_num>0) ) {
+ uint16_t flags;
+ int i;
+ flags = pci_read_config16(PCI_DEV(bus,real_last_unitid,0), real_last_pos + PCI_CAP_FLAGS);
+ flags &= ~0x1f;
+ flags |= HT_CHAIN_END_UNITID_BASE & 0x1f;
+ pci_write_config16(PCI_DEV(bus, real_last_unitid, 0), real_last_pos + PCI_CAP_FLAGS, flags);
+
+ #if RAMINIT_SYSINFO == 1
+ // Here need to change the dev in the array
+ for(i=0;i<sysinfo->link_pair_num;i++)
+ {
+ struct link_pair_st *link_pair = &sysinfo->link_pair[i];
+ if(link_pair->udev == PCI_DEV(bus, real_last_unitid, 0)) {
+ link_pair->udev = PCI_DEV(bus, HT_CHAIN_END_UNITID_BASE, 0);
+ continue;
+ }
+ if(link_pair->dev == PCI_DEV(bus, real_last_unitid, 0)) {
+ link_pair->dev = PCI_DEV(bus, HT_CHAIN_END_UNITID_BASE, 0);
+ }
+ }
+ #endif
+
+ }
+#endif
+
+#if RAMINIT_SYSINFO == 0
return reset_needed;
+#endif
+
}
+#if RAMINIT_SYSINFO == 1
+static void ht_setup_chain(device_t udev, unsigned upos, struct sys_info *sysinfo)
+#else
static int ht_setup_chain(device_t udev, unsigned upos)
+#endif
{
+ unsigned offset_unitid = 0;
+#if HT_CHAIN_UNITID_BASE != 1
+ offset_unitid = 1;
+#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
@@ -478,9 +601,17 @@ static int ht_setup_chain(device_t udev, unsigned upos)
*/
/* Make certain the HT bus is not enumerated */
- ht_collapse_previous_enumeration(0);
+ ht_collapse_previous_enumeration(0, 0);
- return ht_setup_chainx(udev, upos, 0);
+#if HT_CHAIN_UNITID_BASE != 1
+ offset_unitid = 1;
+#endif
+
+#if RAMINIT_SYSINFO == 1
+ ht_setup_chainx(udev, upos, 0, offset_unitid, sysinfo);
+#else
+ return ht_setup_chainx(udev, upos, 0, offset_unitid);
+#endif
}
static int optimize_link_read_pointer(uint8_t node, uint8_t linkn, uint8_t linkt, uint8_t val)
{
@@ -506,7 +637,7 @@ static int optimize_link_read_pointer(uint8_t node, uint8_t linkn, uint8_t linkt
return 0;
}
-static int optimize_link_in_coherent(uint8_t ht_c_num)
+static int optimize_link_read_pointers_chain(uint8_t ht_c_num)
{
int reset_needed;
uint8_t i;
@@ -541,20 +672,28 @@ static int optimize_link_in_coherent(uint8_t ht_c_num)
return reset_needed;
}
+#if RAMINIT_SYSINFO == 1
+static void ht_setup_chains(uint8_t ht_c_num, struct sys_info *sysinfo)
+#else
static int ht_setup_chains(uint8_t ht_c_num)
+#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.
*/
- int reset_needed;
uint8_t upos;
device_t udev;
uint8_t i;
- reset_needed = 0;
+#if RAMINIT_SYSINFO == 0
+ int reset_needed = 0;
+#else
+ sysinfo->link_pair_num = 0;
+#endif
+ // first one is SB Chain
for (i = 0; i < ht_c_num; i++) {
uint32_t reg;
uint8_t devpos;
@@ -564,6 +703,7 @@ static int ht_setup_chains(uint8_t ht_c_num)
#if (USE_DCACHE_RAM == 1) && (K8_SCAN_PCI_BUS == 1)
unsigned bus;
#endif
+ unsigned offset_unitid = 0;
reg = pci_read_config32(PCI_DEV(0,0x18,1), 0xe0 + i * 4);
@@ -576,32 +716,57 @@ static int ht_setup_chains(uint8_t ht_c_num)
dword &= ~(0xffff<<8);
dword |= (reg & 0xffff0000)>>8;
pci_write_config32( PCI_DEV(0, devpos,0), regpos , dword);
-
+
+
+ #if HT_CHAIN_UNITID_BASE != 1
+ #if SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1
+ if(i==0) // to check if it is sb ht chain
+ #endif
+ offset_unitid = 1;
+ #endif
+
/* Make certain the HT bus is not enumerated */
- ht_collapse_previous_enumeration(busn);
+ ht_collapse_previous_enumeration(busn, offset_unitid);
upos = ((reg & 0xf00)>>8) * 0x20 + 0x80;
udev = PCI_DEV(0, devpos, 0);
-
- reset_needed |= ht_setup_chainx(udev,upos,busn);
+
+#if RAMINIT_SYSINFO == 1
+ ht_setup_chainx(udev,upos,busn, offset_unitid, sysinfo); // all not
+#else
+ reset_needed |= ht_setup_chainx(udev,upos,busn, offset_unitid); //all not
+#endif
#if (USE_DCACHE_RAM == 1) && (K8_SCAN_PCI_BUS == 1)
/* You can use use this in romcc, because there is function call in romcc, recursive will kill you */
bus = busn; // we need 32 bit
- reset_needed |= (scan_pci_bus(bus)>>16); // take out reset_needed that stored in upword
+#if RAMINIT_SYSINFO == 1
+ scan_pci_bus(bus, sysinfo);
+#else
+ reset_needed |= (scan_pci_bus(bus)>>16); // take out reset_needed that stored in upword
+#endif
#endif
}
- reset_needed |= optimize_link_in_coherent(ht_c_num);
-
+#if RAMINIT_SYSINFO == 0
+ reset_needed |= optimize_link_read_pointers_chain(ht_c_num);
+
return reset_needed;
+#endif
+
}
-#ifndef K8_ALLOCATE_IO_RANGE
- #define K8_ALLOCATE_IO_RANGE 0
-#endif
+static inline unsigned get_nodes(void)
+{
+ return ((pci_read_config32(PCI_DEV(0, 0x18, 0), 0x60)>>4) & 7) + 1;
+}
+
+#if RAMINIT_SYSINFO == 1
+static void ht_setup_chains_x(struct sys_info *sysinfo)
+#else
static int ht_setup_chains_x(void)
+#endif
{
uint8_t nodeid;
uint32_t reg;
@@ -612,11 +777,18 @@ static int ht_setup_chains_x(void)
#if K8_ALLOCATE_IO_RANGE == 1
unsigned next_io_base;
#endif
-
+
+ nodes = get_nodes();
+
/* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */
reg = pci_read_config32(PCI_DEV(0, 0x18, 0), 0x64);
/* update PCI_DEV(0, 0x18, 1) 0xe0 to 0x05000m03, and next_busn=0x3f+1 */
print_linkn_in("SBLink=", ((reg>>8) & 3) );
+#if RAMINIT_SYSINFO == 1
+ sysinfo->sblnk = (reg>>8) & 3;
+ sysinfo->sbbusn = 0;
+ sysinfo->nodes = nodes;
+#endif
tempreg = 3 | ( 0<<4) | (((reg>>8) & 3)<<8) | (0<<16)| (0x3f<<24);
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0, tempreg);
@@ -639,8 +811,6 @@ static int ht_setup_chains_x(void)
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xc0 + ht_c_num * 8, 0);
}
- nodes = ((pci_read_config32(PCI_DEV(0, 0x18, 0), 0x60)>>4) & 7) + 1;
-
for(nodeid=0; nodeid<nodes; nodeid++) {
device_t dev;
uint8_t linkn;
@@ -671,7 +841,7 @@ static int ht_setup_chains_x(void)
/* io range allocation */
tempreg = nodeid | (linkn<<4) | ((next_io_base+0x3)<<12); //limit
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xC4 + ht_c_num * 8, tempreg);
- tempreg = 3 | ( 3<<4) | (next_io_base<<12); //base
+ tempreg = 3 /*| ( 3<<4)*/ | (next_io_base<<12); //base :ISA and VGA ?
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xC0 + ht_c_num * 8, tempreg);
next_io_base += 0x3+0x1;
#endif
@@ -717,6 +887,64 @@ static int ht_setup_chains_x(void)
}
}
- return ht_setup_chains(i);
+#if RAMINIT_SYSINFO == 1
+ sysinfo->ht_c_num = i;
+ ht_setup_chains(i, sysinfo);
+#else
+ return ht_setup_chains(i);
+#endif
}
+
+#if RAMINIT_SYSINFO == 1
+static int optimize_link_incoherent_ht(struct sys_info *sysinfo)
+{
+ // We need to use recorded link pair info to optimize the link
+ int i;
+ int reset_needed = 0;
+
+ unsigned link_pair_num = sysinfo->link_pair_num;
+
+ for(i=0; i< link_pair_num; i++) {
+ struct link_pair_st *link_pair= &sysinfo->link_pair[i];
+ reset_needed |= ht_optimize_link(link_pair->udev, link_pair->upos, link_pair->uoffs, link_pair->dev, link_pair->pos, link_pair->offs);
+ }
+
+ reset_needed |= optimize_link_read_pointers(sysinfo->ht_c_num);
+
+ return reset_needed;
+
+}
+#endif
+
+
+static unsigned get_sblnk(void)
+{
+ uint32_t reg;
+ /* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */
+ reg = pci_read_config32(PCI_DEV(0, 0x18, 0), 0x64);
+ return ((reg>>8) & 3) ;
+}
+
+/* Look up a which bus a given node/link combination is on.
+ * return 0 when we can't find the answer.
+ */
+static unsigned node_link_to_bus(unsigned node, unsigned link)
+{
+ unsigned reg;
+
+ for(reg = 0xE0; reg < 0xF0; reg += 0x04) {
+ unsigned config_map;
+ config_map = pci_read_config32(PCI_DEV(0, 0x18, 1), reg);
+ if ((config_map & 3) != 3) {
+ continue;
+ }
+ if ((((config_map >> 4) & 7) == node) &&
+ (((config_map >> 8) & 3) == link))
+ {
+ return (config_map >> 16) & 0xff;
+ }
+ }
+ return 0;
+}
+
diff --git a/src/northbridge/amd/amdk8/misc_control.c b/src/northbridge/amd/amdk8/misc_control.c
index 4cd3d0d42d..c7176c3b0d 100644
--- a/src/northbridge/amd/amdk8/misc_control.c
+++ b/src/northbridge/amd/amdk8/misc_control.c
@@ -17,7 +17,8 @@
#include <part/hard_reset.h>
#include <pc80/mc146818rtc.h>
#include <bitops.h>
-#include "./cpu_rev.c"
+#include <cpu/amd/model_fxx_rev.h>
+
#include "amdk8.h"
/**
diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c
index 9febac2f06..d2db902beb 100644
--- a/src/northbridge/amd/amdk8/northbridge.c
+++ b/src/northbridge/amd/amdk8/northbridge.c
@@ -2,6 +2,7 @@
2004.12 yhlu add dual core support
2005.01 yhlu add support move apic before pci_domain in MB Config.lb
2005.02 yhlu add e0 memory hole support
+ 2005.11 yhlu add put sb ht chain on bus 0
*/
#include <console/console.h>
@@ -96,16 +97,15 @@ static unsigned int amdk8_nodeid(device_t dev)
return (dev->path.u.pci.devfn >> 3) - 0x18;
}
-static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
+static unsigned int amdk8_scan_chain(device_t dev, unsigned nodeid, unsigned link, unsigned sblink, unsigned int max, unsigned offset_unitid)
{
- unsigned nodeid;
- unsigned link;
- nodeid = amdk8_nodeid(dev);
#if 0
printk_debug("%s amdk8_scan_chains max: %d starting...\n",
dev_path(dev), max);
#endif
- for(link = 0; link < dev->links; link++) {
+// I want to put sb chain in bus 0 can I?
+
+
uint32_t link_type;
uint32_t busses, config_busses;
unsigned free_reg, config_reg;
@@ -114,13 +114,13 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
} while(link_type & ConnectionPending);
if (!(link_type & LinkConnected)) {
- continue;
+ return max;
}
do {
link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
} while(!(link_type & InitComplete));
if (!(link_type & NonCoherent)) {
- continue;
+ return max;
}
/* See if there is an available configuration space mapping
* register in function 1.
@@ -146,14 +146,21 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
* register skip this bus
*/
if (config_reg > 0xec) {
- continue;
+ return max;
}
/* Set up the primary, secondary and subordinate bus numbers.
* We have no idea how many busses are behind this bridge yet,
* so we set the subordinate bus number to 0xff for the moment.
*/
- dev->link[link].secondary = ++max;
+#if K8_SB_HT_CHAIN_ON_BUS0 == 1
+ if((nodeid == 0) && (sblink==link)) { // actually max is 0 here
+ dev->link[link].secondary = max;
+ }
+ else
+#endif
+ dev->link[link].secondary = ++max;
+
dev->link[link].subordinate = 0xff;
/* Read the existing primary/secondary/subordinate bus
@@ -188,7 +195,7 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
/* Now we can scan all of the subordinate busses i.e. the
* chain on the hypertranport link
*/
- max = hypertransport_scan_chain(&dev->link[link], 0, 0xbf, max);
+ max = hypertransport_scan_chain(&dev->link[link], 0, 0xbf, max, offset_unitid);
#if 0
printk_debug("%s Hyper transport scan link: %d new max: %d\n",
@@ -211,14 +218,57 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
printk_debug("%s Hypertransport scan link: %d done\n",
dev_path(dev), link);
#endif
- }
+
+ return max;
+}
+
+static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
+{
+ unsigned nodeid;
+ unsigned link;
+ unsigned sblink = 0;
+ unsigned offset_unitid = 0;
+ nodeid = amdk8_nodeid(dev);
+
+
#if 0
- printk_debug("%s amdk8_scan_chains max: %d done\n",
- dev_path(dev), max);
+ printk_debug("%s amdk8_scan_chains max: %d starting...\n",
+ dev_path(dev), max);
#endif
- return max;
+// I want to put sb chain in bus 0
+
+ if(nodeid==0) {
+ sblink = (pci_read_config32(dev, 0x64)>>8) & 3;
+#if K8_SB_HT_CHAIN_ON_BUS0 == 1
+ #if HT_CHAIN_UNITID_BASE != 1
+ 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
+#endif
+ }
+
+ for(link = 0; link < dev->links; link++) {
+#if K8_SB_HT_CHAIN_ON_BUS0 == 1
+ if( (nodeid == 0) && (sblink == link) ) continue; //already done
+#endif
+ offset_unitid = 0;
+ #if HT_CHAIN_UNITID_BASE != 1
+ #if SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1
+ if((nodeid == 0) && (sblink == link))
+ #endif
+ offset_unitid = 1;
+ #endif
+
+ max = amdk8_scan_chain(dev, nodeid, link, sblink, max, offset_unitid);
+ }
+#if 0
+ printk_debug("%s amdk8_scan_chains max: %d done\n",
+ dev_path(dev), max);
+#endif
+ return max;
}
+
static int reg_useable(unsigned reg,
device_t goal_dev, unsigned goal_nodeid, unsigned goal_link)
{
@@ -508,7 +558,6 @@ static void amdk8_create_vga_resource(device_t dev, unsigned nodeid)
/* release the temp resource */
resource->flags = 0;
-
}
static void amdk8_set_resources(device_t dev)
@@ -1041,7 +1090,7 @@ static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
for(reg = 0xe0; reg <= 0xec; reg += 4) {
f1_write_config32(reg, 0);
}
- max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0x18, 0), 0xff, max);
+ max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0x18, 0), 0xff, max);
/* Tune the hypertransport transaction for best performance.
* Including enabling relaxed ordering if it is safe.