diff options
author | Stefan Reinauer <stepan@openbios.org> | 2005-12-02 21:52:30 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2005-12-02 21:52:30 +0000 |
commit | 7ce8c54e2ba89059d28790550a8f74907b54b916 (patch) | |
tree | e89df947fbe9e3f85d6082af6926038e9fe8e61a /src/northbridge | |
parent | c2455dc0ce210b3da2b14be8885803ff47a781eb (diff) | |
download | coreboot-7ce8c54e2ba89059d28790550a8f74907b54b916.tar.xz |
1201_ht_bus0_dev0_fidvid_core.diff
https://openbios.org/roundup/linuxbios/issue41
Lord have mercy upon us.
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2118 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge')
-rw-r--r-- | src/northbridge/amd/amdk8/amdk8.h | 6 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/coherent_ht.c | 2 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/debug.c | 13 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/early_ht.c | 35 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/incoherent_ht.c | 360 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/misc_control.c | 3 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/northbridge.c | 81 |
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. |