diff options
Diffstat (limited to 'src/northbridge/amd')
-rw-r--r-- | src/northbridge/amd/amdk8/coherent_ht.c | 114 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/debug.c | 32 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/early_ht.c | 31 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/incoherent_ht.c | 334 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/misc_control.c | 5 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/northbridge.c | 260 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/setup_resource_map.c | 149 |
7 files changed, 626 insertions, 299 deletions
diff --git a/src/northbridge/amd/amdk8/coherent_ht.c b/src/northbridge/amd/amdk8/coherent_ht.c index d7be557d37..c79a432ab5 100644 --- a/src/northbridge/amd/amdk8/coherent_ht.c +++ b/src/northbridge/amd/amdk8/coherent_ht.c @@ -145,15 +145,16 @@ static void disable_probes(void) print_spew("Disabling read/write/fill probes for UP... "); - val=pci_read_config32(NODE_HT(0), 0x68); - val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0); - pci_write_config32(NODE_HT(0), 0x68, val); + val=pci_read_config32(NODE_HT(0), HT_TRANSACTION_CONTROL); + val |= HTTC_DIS_FILL_P | HTTC_DIS_RMT_MEM_C | HTTC_DIS_P_MEM_C | + HTTC_DIS_MTS | HTTC_DIS_WR_DW_P | HTTC_DIS_WR_B_P | + HTTC_DIS_RD_DW_P | HTTC_DIS_RD_B_P; + pci_write_config32(NODE_HT(0), HT_TRANSACTION_CONTROL, val); print_spew("done.\r\n"); } - #ifndef ENABLE_APIC_EXT_ID #define ENABLE_APIC_EXT_ID 0 #endif @@ -163,7 +164,7 @@ static void enable_apic_ext_id(u8 node) #if ENABLE_APIC_EXT_ID==1 #warning "FIXME Is the right place to enable apic ext id here?" - u32 val; + u32 val; val = pci_read_config32(NODE_HT(node), 0x68); val |= (HTTC_APIC_EXT_SPUR | HTTC_APIC_EXT_ID | HTTC_APIC_EXT_BRD_CST); @@ -171,8 +172,6 @@ static void enable_apic_ext_id(u8 node) #endif } - - static void enable_routing(u8 node) { u32 val; @@ -277,11 +276,11 @@ static void wait_ht_stable(uint8_t node) } #endif -static int check_connection(u8 dest) +static int verify_connection(u8 dest) { /* See if we have a valid connection to dest */ u32 val; - + /* Verify that the coherent hypertransport link is * established and actually working by reading the * remode node's vendor/device id @@ -289,10 +288,6 @@ static int check_connection(u8 dest) val = pci_read_config32(NODE_HT(dest),0); if(val != 0x11001022) return 0; -// needed? -#if K8_HT_CHECK_PENDING_LINK == 1 - wait_ht_stable(dest); -#endif return 1; } @@ -306,11 +301,11 @@ static uint16_t read_freq_cap(device_t dev, uint8_t pos) freq_cap = pci_read_config16(dev, pos); freq_cap &= ~(1 << HT_FREQ_VENDOR); /* Ignore Vendor HT frequencies */ - - #if K8_HT_FREQ_1G_SUPPORT == 1 - if (!is_cpu_pre_e0()) +#if K8_HT_FREQ_1G_SUPPORT == 1 + if (!is_cpu_pre_e0()) { return freq_cap; - #endif + } +#endif id = pci_read_config32(dev, 0); @@ -726,8 +721,8 @@ static struct setup_smp_result setup_smp2(void) print_linkn("(0,1) link=", byte); setup_row_direct(0,1, byte); setup_temp_row(0, 1); - - check_connection(7); + + verify_connection(7); /* We found 2 nodes so far */ val = pci_read_config32(NODE_HT(7), 0x6c); @@ -751,8 +746,8 @@ static struct setup_smp_result setup_smp2(void) print_linkn("\t-->(0,1) link=", byte); setup_row_direct(0,1, byte); setup_temp_row(0, 1); - - check_connection(7); + + verify_connection(7); /* We found 2 nodes so far */ val = pci_read_config32(NODE_HT(7), 0x6c); @@ -832,7 +827,7 @@ static struct setup_smp_result setup_smp4(int needs_reset) setup_row_indirect_group(conn4_1, sizeof(conn4_1)/sizeof(conn4_1[0])); setup_temp_row(0,2); - check_connection(7); + verify_connection(7); val = pci_read_config32(NODE_HT(7), 0x6c); byte = (val>>2) & 0x3; /* get default link on 7 to 0*/ print_linkn("(2,0) link=", byte); @@ -846,7 +841,7 @@ static struct setup_smp_result setup_smp4(int needs_reset) setup_temp_row(0,1); setup_temp_row(1,3); - check_connection(7); + verify_connection(7); val = pci_read_config32(NODE_HT(7), 0x6c); byte = (val>>2) & 0x3; /* get default link on 7 to 1*/ @@ -865,7 +860,7 @@ static struct setup_smp_result setup_smp4(int needs_reset) setup_row_direct(2,3, byte & 0x3); setup_temp_row(0,2); setup_temp_row(2,3); - check_connection(7); /* to 3*/ + verify_connection(7); /* to 3*/ #if (CONFIG_MAX_PHYSICAL_CPUS > 4) || (CONFIG_MAX_PHYSICAL_CPUS_4_BUT_MORE_INSTALLED == 1) /* We need to find out which link is to node3 */ @@ -878,7 +873,7 @@ static struct setup_smp_result setup_smp4(int needs_reset) print_linkn("\t-->(2,3) link=", byte); setup_row_direct(2,3,byte); setup_temp_row(2,3); - check_connection(7); /* to 3*/ + verify_connection(7); /* to 3*/ } } #endif @@ -1016,7 +1011,7 @@ static struct setup_smp_result setup_smp6(int needs_reset) for(byte=0; byte<4; byte+=2) { setup_temp_row(byte,byte+2); } - check_connection(7); + verify_connection(7); val = pci_read_config32(NODE_HT(7), 0x6c); byte = (val>>2) & 0x3; /*get default link on 7 to 2*/ print_linkn("(4,2) link=", byte); @@ -1044,7 +1039,7 @@ static struct setup_smp_result setup_smp6(int needs_reset) for(byte=0; byte<4; byte+=2) { setup_temp_row(byte+1,byte+3); } - check_connection(7); + verify_connection(7); val = pci_read_config32(NODE_HT(7), 0x6c); byte = (val>>2) & 0x3; /* get default link on 7 to 3*/ @@ -1064,7 +1059,7 @@ static struct setup_smp_result setup_smp6(int needs_reset) setup_temp_row(0,2); setup_temp_row(2,4); setup_temp_row(4,5); - check_connection(7); /* to 5*/ + verify_connection(7); /* to 5*/ #if CONFIG_MAX_PHYSICAL_CPUS > 6 /* We need to find out which link is to node5 */ @@ -1078,7 +1073,7 @@ static struct setup_smp_result setup_smp6(int needs_reset) print_linkn("\t-->(4,5) link=", byte); setup_row_direct(4,5,byte); setup_temp_row(4,5); - check_connection(7); /* to 5*/ + verify_connection(7); /* to 5*/ } } #endif @@ -1254,7 +1249,7 @@ static struct setup_smp_result setup_smp8(int needs_reset) for(byte=0; byte<6; byte+=2) { setup_temp_row(byte,byte+2); } - check_connection(7); + verify_connection(7); val = pci_read_config32(NODE_HT(7), 0x6c); byte = (val>>2) & 0x3; /* get default link on 7 to 4*/ print_linkn("(6,4) link=", byte); @@ -1294,7 +1289,7 @@ static struct setup_smp_result setup_smp8(int needs_reset) } setup_temp_row(5,6); - check_connection(7); + verify_connection(7); val = get_row(7,6); // to chect it if it is node6 before renaming if( (val>>16) == 1) { // it is real node 7 so swap it @@ -1316,7 +1311,7 @@ static struct setup_smp_result setup_smp8(int needs_reset) #endif setup_temp_row(5,6); - check_connection(7); + verify_connection(7); } val = pci_read_config32(NODE_HT(7), 0x6c); byte = (val>>2) & 0x3; /* get default link on 7 to 5*/ @@ -1334,7 +1329,7 @@ static struct setup_smp_result setup_smp8(int needs_reset) setup_temp_row(byte+1,byte+3); } - check_connection(7); + verify_connection(7); val = pci_read_config32(NODE_HT(7), 0x6c); byte = (val>>2) & 0x3; /* get default link on 7 to 5*/ @@ -1354,7 +1349,7 @@ static struct setup_smp_result setup_smp8(int needs_reset) setup_temp_row(byte,byte+2); } - check_connection(7); + verify_connection(7); val = pci_read_config32(NODE_HT(7), 0x6c); byte = (val>>2) & 0x3; /* get default link on 7 to 4*/ @@ -1379,7 +1374,7 @@ static struct setup_smp_result setup_smp8(int needs_reset) setup_temp_row(byte+1,byte+3); } - check_connection(7); + verify_connection(7); val = pci_read_config32(NODE_HT(7), 0x6c); byte = (val>>2) & 0x3; /* get default link on 7 to 5*/ @@ -1568,7 +1563,6 @@ static struct setup_smp_result setup_smp(void) #endif return result; - } static unsigned verify_mp_capabilities(unsigned nodes) @@ -1663,10 +1657,10 @@ static void coherent_ht_finalize(unsigned nodes) #endif /* set up cpu count and node count and enable Limit - * Config Space Range for all available CPUs. - * Also clear non coherent hypertransport bus range - * registers on Hammer A0 revision. - */ + * Config Space Range for all available CPUs. + * Also clear non coherent hypertransport bus range + * registers on Hammer A0 revision. + */ print_spew("coherent_ht_finalize\r\n"); rev_a0 = is_cpu_rev_a0(); @@ -1686,21 +1680,19 @@ static void coherent_ht_finalize(unsigned nodes) pci_write_config32(dev, 0x60, val); /* Only respond to real cpu pci configuration cycles - * and optimize the HT settings - */ - val=pci_read_config32(dev, 0x68); + * and optimize the HT settings + */ + val=pci_read_config32(dev, HT_TRANSACTION_CONTROL); val &= ~((HTTC_BUF_REL_PRI_MASK << HTTC_BUF_REL_PRI_SHIFT) | (HTTC_MED_PRI_BYP_CNT_MASK << HTTC_MED_PRI_BYP_CNT_SHIFT) | (HTTC_HI_PRI_BYP_CNT_MASK << HTTC_HI_PRI_BYP_CNT_SHIFT)); val |= HTTC_LIMIT_CLDT_CFG | (HTTC_BUF_REL_PRI_8 << HTTC_BUF_REL_PRI_SHIFT) | - HTTC_RSP_PASS_PW | (3 << HTTC_MED_PRI_BYP_CNT_SHIFT) | (3 << HTTC_HI_PRI_BYP_CNT_SHIFT); - pci_write_config32(dev, 0x68, val); + pci_write_config32(dev, HT_TRANSACTION_CONTROL, val); if (rev_a0) { - print_spew("shit it is an old cup\n"); pci_write_config32(dev, 0x94, 0); pci_write_config32(dev, 0xb4, 0); pci_write_config32(dev, 0xd4, 0); @@ -1720,8 +1712,8 @@ static int apply_cpu_errata_fixes(unsigned nodes, int needs_reset) if (is_cpu_pre_c0()) { /* Errata 66 - * Limit the number of downstream posted requests to 1 - */ + * Limit the number of downstream posted requests to 1 + */ cmd = pci_read_config32(dev, 0x70); if ((cmd & (3 << 0)) != 2) { cmd &= ~(3<<0); @@ -1745,12 +1737,12 @@ static int apply_cpu_errata_fixes(unsigned nodes, int needs_reset) } } - else if(is_cpu_pre_d0()) { // d0 later don't need it + else if (is_cpu_pre_d0()) { // d0 later don't need it uint32_t cmd_ref; /* Errata 98 - * Set Clk Ramp Hystersis to 7 - * Clock Power/Timing Low - */ + * Set Clk Ramp Hystersis to 7 + * Clock Power/Timing Low + */ cmd_ref = 0x04e20707; /* Registered */ cmd = pci_read_config32(dev, 0xd4); if(cmd != cmd_ref) { @@ -1778,7 +1770,10 @@ static int optimize_link_read_pointers(unsigned nodes, int needs_reset) /* This works on an Athlon64 because unimplemented links return 0 */ reg = 0x98 + (link * 0x20); link_type = pci_read_config32(f0_dev, reg); - if ((link_type & 7) == 3) { /* only handle coherent link here*/ + /* Only handle coherent links */ + if ((link_type & (LinkConnected | InitComplete|NonCoherent)) == + (LinkConnected|InitComplete)) + { cmd &= ~(0xff << (link *8)); cmd |= 0x25 << (link *8); } @@ -1794,6 +1789,8 @@ static int optimize_link_read_pointers(unsigned nodes, int needs_reset) static int setup_coherent_ht_domain(void) { struct setup_smp_result result; + result.nodes = 1; + result.needs_reset = 0; #if K8_HT_CHECK_PENDING_LINK == 1 //needed? @@ -1802,17 +1799,14 @@ static int setup_coherent_ht_domain(void) enable_bsp_routing(); #if CONFIG_MAX_PHYSICAL_CPUS > 1 - result = setup_smp(); - result.nodes = verify_mp_capabilities(result.nodes); - clear_dead_routes(result.nodes); -#else - result.nodes = 1; - result.needs_reset = 0; + result = setup_smp(); + result.nodes = verify_mp_capabilities(result.nodes); + clear_dead_routes(result.nodes); #endif if (result.nodes == 1) { setup_uniprocessor(); - } + } coherent_ht_finalize(result.nodes); result.needs_reset = apply_cpu_errata_fixes(result.nodes, result.needs_reset); result.needs_reset = optimize_link_read_pointers(result.nodes, result.needs_reset); diff --git a/src/northbridge/amd/amdk8/debug.c b/src/northbridge/amd/amdk8/debug.c index 861ad8c38a..d0841e878e 100644 --- a/src/northbridge/amd/amdk8/debug.c +++ b/src/northbridge/amd/amdk8/debug.c @@ -5,12 +5,16 @@ #if 1 static void print_debug_pci_dev(unsigned dev) { +#if CONFIG_USE_INIT + printk_debug("PCI: %02x:%02x.%02x", (dev>>16) & 0xff, (dev>>11) & 0x1f, (dev>>8) & 0x7); +#else print_debug("PCI: "); print_debug_hex8((dev >> 16) & 0xff); print_debug_char(':'); print_debug_hex8((dev >> 11) & 0x1f); print_debug_char('.'); print_debug_hex8((dev >> 8) & 7); +#endif } static void print_pci_devices(void) @@ -27,7 +31,19 @@ static void print_pci_devices(void) continue; } print_debug_pci_dev(dev); +#if CONFIG_USE_INIT + printk_debug(" %04x:%04x\r\n", (id & 0xffff), (id>>16)); +#else + print_debug_hex32(id); print_debug("\r\n"); +#endif + if(((dev>>8) & 0x07) == 0) { + uint8_t hdr_type; + hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); + if((hdr_type & 0x80) != 0x80) { + dev += PCI_DEV(0,0,7); + } + } } } @@ -72,6 +88,14 @@ static void dump_pci_devices(void) continue; } dump_pci_device(dev); + + if(((dev>>8) & 0x07) == 0) { + uint8_t hdr_type; + hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); + if((hdr_type & 0x80) != 0x80) { + dev += PCI_DEV(0,0,7); + } + } } } @@ -89,6 +113,14 @@ static void dump_pci_devices_on_bus(unsigned busn) continue; } dump_pci_device(dev); + + if(((dev>>8) & 0x07) == 0) { + uint8_t hdr_type; + hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); + if((hdr_type & 0x80) != 0x80) { + dev += PCI_DEV(0,0,7); + } + } } } diff --git a/src/northbridge/amd/amdk8/early_ht.c b/src/northbridge/amd/amdk8/early_ht.c index ab9d4592dd..2711657455 100644 --- a/src/northbridge/amd/amdk8/early_ht.c +++ b/src/northbridge/amd/amdk8/early_ht.c @@ -17,8 +17,9 @@ static int enumerate_ht_chain(void) id = pci_read_config32(PCI_DEV(0,0,0), 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; } @@ -35,7 +36,8 @@ static int enumerate_ht_chain(void) hdr_type &= 0x7f; if ((hdr_type == PCI_HEADER_TYPE_NORMAL) || - (hdr_type == PCI_HEADER_TYPE_BRIDGE)) { + (hdr_type == PCI_HEADER_TYPE_BRIDGE)) + { pos = pci_read_config8(PCI_DEV(0,0,0), PCI_CAPABILITY_LIST); } while(pos != 0) { @@ -43,24 +45,39 @@ static int enumerate_ht_chain(void) cap = pci_read_config8(PCI_DEV(0,0,0), 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); if ((flags >> 13) == 0) { unsigned count; + unsigned ctrl, ctrl_off; flags &= ~0x1f; flags |= next_unitid & 0x1f; count = (flags >> 5) & 0x1f; + next_unitid += count; + + /* 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); - - next_unitid += count; break; } } pos = pci_read_config8(PCI_DEV(0, 0, 0), pos + PCI_CAP_LIST_NEXT); } - } while((last_unitid != next_unitid) && (next_unitid <= 0x1f)); - + } while((last_unitid != next_unitid) && (next_unitid <= 0x1f)); return reset_needed; } diff --git a/src/northbridge/amd/amdk8/incoherent_ht.c b/src/northbridge/amd/amdk8/incoherent_ht.c index 7bb315d687..d4271efbda 100644 --- a/src/northbridge/amd/amdk8/incoherent_ht.c +++ b/src/northbridge/amd/amdk8/incoherent_ht.c @@ -10,6 +10,10 @@ #define K8_HT_FREQ_1G_SUPPORT 0 #endif +#ifndef K8_SCAN_PCI_BUS + #define K8_SCAN_PCI_BUS 0 +#endif + static inline void print_linkn_in (const char *strval, uint8_t byteval) { #if 1 @@ -21,7 +25,7 @@ static inline void print_linkn_in (const char *strval, uint8_t byteval) #endif } -static uint8_t ht_lookup_slave_capability(device_t dev) +static uint8_t ht_lookup_capability(device_t dev, uint16_t val) { uint8_t pos; uint8_t hdr_type; @@ -44,8 +48,8 @@ static uint8_t ht_lookup_slave_capability(device_t dev) uint16_t flags; flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS); - if ((flags >> 13) == 0) { - /* Entry is a Slave secondary, success... */ + if ((flags >> 13) == val) { + /* Entry is a slave or host , success... */ break; } } @@ -54,6 +58,16 @@ static uint8_t ht_lookup_slave_capability(device_t dev) return pos; } +static uint8_t ht_lookup_slave_capability(device_t dev) +{ + return ht_lookup_capability(dev, 0); // Slave/Primary Interface Block Format +} + +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) { device_t dev; @@ -135,25 +149,28 @@ static uint16_t ht_read_freq_cap(device_t dev, uint8_t pos) return freq_cap; } +#define LINK_OFFS(CTRL, WIDTH,FREQ,FREQ_CAP) \ + (((CTRL & 0xff) << 24) | ((WIDTH & 0xff) << 16) | ((FREQ & 0xff) << 8) | (FREQ_CAP & 0xFF)) -#define LINK_OFFS(WIDTH,FREQ,FREQ_CAP) \ - (((WIDTH & 0xff) << 16) | ((FREQ & 0xff) << 8) | (FREQ_CAP & 0xFF)) - +#define LINK_CTRL(OFFS) ((OFFS >> 24) & 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_CTRL, \ 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_CTRL0, \ 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_CTRL1, \ PCI_HT_CAP_SLAVE_WIDTH1, \ PCI_HT_CAP_SLAVE_FREQ1, \ PCI_HT_CAP_SLAVE_FREQ_CAP1) @@ -164,8 +181,8 @@ static int ht_optimize_link( { static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 }; static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 }; - uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask; - uint8_t width_cap1, width_cap2, width_cap, width, old_width, ln_width1, ln_width2; + uint16_t freq_cap1, freq_cap2; + uint8_t width_cap1, width_cap2, width, old_width, ln_width1, ln_width2; uint8_t freq, old_freq; int needs_reset; /* Set link width and frequency */ @@ -228,94 +245,123 @@ static int ht_optimize_link( return needs_reset; } -static int ht_setup_chain(device_t udev, uint8_t upos) +#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) { - /* 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. - */ - uint8_t next_unitid, last_unitid; - int reset_needed; - unsigned uoffs; - - /* Make certain the HT bus is not enumerated */ - ht_collapse_previous_enumeration(0); + /* + here we already can access PCI_DEV(bus, 0, 0) to PCI_DEV(bus, 0x1f, 0x7) + So We can scan these devices to find out if they are bridge + If it is pci bridge, We need to set busn in bridge, and go on + For ht bridge, We need to set the busn in bridge and ht_setup_chainx, and the scan_pci_bus + */ + unsigned int devfn; + unsigned new_bus; + unsigned max_bus; + + new_bus = (bus & 0xff); // mask out the reset_needed + + if(new_bus<0x40) { + max_bus = 0x3f; + } else if (new_bus<0x80) { + max_bus = 0x7f; + } else if (new_bus<0xc0) { + max_bus = 0xbf; + } else { + max_bus = 0xff; + } - reset_needed = 0; - uoffs = PCI_HT_HOST_OFFS; - next_unitid = 1; - do { - uint32_t id; - uint8_t pos; - uint16_t flags; - uint8_t count; - unsigned offs; + new_bus = bus; - device_t dev = PCI_DEV(0, 0, 0); - last_unitid = next_unitid; +#if 0 +#if CONFIG_USE_INIT == 1 + printk_debug("bus_num=%02x\r\n", bus); +#endif +#endif - 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; - } + for (devfn = 0; devfn <= 0xff; devfn++) { + uint8_t hdr_type; + uint16_t class; + uint32_t buses; + device_t dev; + uint16_t cr; + dev = PCI_DEV((bus & 0xff), ((devfn>>3) & 0x1f), (devfn & 0x7)); + hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); + class = pci_read_config16(dev, PCI_CLASS_DEVICE); - pos = ht_lookup_slave_capability(dev); - if (!pos) { - print_err("HT link capability not found\r\n"); - break; +#if 0 +#if CONFIG_USE_INIT == 1 + if(hdr_type !=0xff ) { + printk_debug("dev=%02x fn=%02x hdr_type=%02x class=%04x\r\n", + (devfn>>3)& 0x1f, (devfn & 0x7), hdr_type, class); } -#if CK804_DEVN_BASE==0 - //CK804 workaround: - // CK804 UnitID changes not use - id = pci_read_config32(dev, PCI_VENDOR_ID); - if(id != 0x005e10de) { #endif - - /* 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); - - dev = PCI_DEV(0, next_unitid, 0); -#if CK804_DEVN_BASE==0 - } - else { - dev = PCI_DEV(0, 0, 0); - } #endif - - /* Compute the number of unitids consumed */ - count = (flags >> 5) & 0x1f; - next_unitid += count; - - /* get ht direction */ - flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS); // double read ?? - - 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 CK804_DEVN_BASE==0 - if(id == 0x005e10de) { - break; + switch(hdr_type & 0x7f) { /* header type */ + case PCI_HEADER_TYPE_BRIDGE: + if (class != PCI_CLASS_BRIDGE_PCI) goto bad; + /* set the bus range dev */ + + /* Clear all status bits and turn off memory, I/O and master enables. */ + cr = pci_read_config16(dev, PCI_COMMAND); + pci_write_config16(dev, PCI_COMMAND, 0x0000); + pci_write_config16(dev, PCI_STATUS, 0xffff); + + buses = pci_read_config32(dev, PCI_PRIMARY_BUS); + + buses &= 0xff000000; + new_bus++; + buses |= (((unsigned int) (bus & 0xff) << 0) | + ((unsigned int) (new_bus & 0xff) << 8) | + ((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 + } + } + + new_bus = scan_pci_bus(new_bus); + /* set real max bus num in that */ + + buses = (buses & 0xff00ffff) | + ((unsigned int) (new_bus & 0xff) << 16); + pci_write_config32(dev, PCI_PRIMARY_BUS, buses); + + pci_write_config16(dev, PCI_COMMAND, cr); + + break; + default: + bad: + ; + } + + /* if this is not a multi function device, + * or the device is not present don't waste + * time probing another function. + * Skip to next device. + */ + if ( ((devfn & 0x07) == 0x00) && ((hdr_type & 0x80) != 0x80)) + { + devfn += 0x07; } -#endif - - /* Remeber the location of the last device */ - udev = dev; - upos = pos; - uoffs = (offs != PCI_HT_SLAVE0_OFFS) ? PCI_HT_SLAVE0_OFFS : PCI_HT_SLAVE1_OFFS; - - } while((last_unitid != next_unitid) && (next_unitid <= 0x1f)); - return reset_needed; + } + + return new_bus; } - +#endif static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus) { uint8_t next_unitid, last_unitid; @@ -328,25 +374,38 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus) do { uint32_t id; uint8_t pos; - uint16_t flags; + uint16_t flags, ctrl; uint8_t count; unsigned offs; - + + /* Wait until the link initialization is complete */ + do { + ctrl = pci_read_config16(udev, upos + LINK_CTRL(uoffs)); + /* Is this the end of the hypertransport chain? */ + if (ctrl & (1 << 6)) { + break; + } + /* Has the link failed */ + if (ctrl & (1 << 4)) { + break; + } + } while((ctrl & (1 << 5)) == 0); + device_t dev = PCI_DEV(bus, 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)) { + if ( (id == 0xffffffff) || (id == 0x00000000) || + (id == 0x0000ffff) || (id == 0xffff0000)) + { break; } pos = ht_lookup_slave_capability(dev); if (!pos) { - print_err(" HT link capability not found\r\n"); + print_err("HT link capability not found\r\n"); break; } @@ -363,6 +422,7 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus) flags |= next_unitid & 0x1f; pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags); + /* Note the change in device number */ dev = PCI_DEV(bus, next_unitid, 0); #if CK804_DEVN_BASE==0 } @@ -375,9 +435,11 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus) count = (flags >> 5) & 0x1f; next_unitid += count; - /* get ht direction */ - flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS); // double read ?? - + /* Find which side of the ht link we are on, + * by reading which direction our last write to PCI_CAP_FLAGS + * came from. + */ + 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 */ @@ -395,9 +457,23 @@ static int ht_setup_chainx(device_t udev, uint8_t upos, uint8_t bus) uoffs = ( offs != PCI_HT_SLAVE0_OFFS ) ? PCI_HT_SLAVE0_OFFS : PCI_HT_SLAVE1_OFFS; } while((last_unitid != next_unitid) && (next_unitid <= 0x1f)); + return reset_needed; } +static int ht_setup_chain(device_t udev, unsigned upos) +{ + /* 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. + */ + + /* Make certain the HT bus is not enumerated */ + ht_collapse_previous_enumeration(0); + + return ht_setup_chainx(udev, upos, 0); +} static int optimize_link_read_pointer(uint8_t node, uint8_t linkn, uint8_t linkt, uint8_t val) { uint32_t dword, dword_old; @@ -444,7 +520,7 @@ static int optimize_link_in_coherent(uint8_t ht_c_num) reg = pci_read_config32( PCI_DEV(busn, 1, 0), PCI_VENDOR_ID); if ( (reg & 0xffff) == PCI_VENDOR_ID_AMD) { val = 0x25; - } else if ( (reg & 0xffff) == 0x10de ) { + } else if ( (reg & 0xffff) == PCI_VENDOR_ID_NVIDIA ) { val = 0x25;//??? } else { continue; @@ -477,6 +553,9 @@ static int ht_setup_chains(uint8_t ht_c_num) unsigned regpos; uint32_t dword; uint8_t busn; + #if (USE_DCACHE_RAM == 1) && (K8_SCAN_PCI_BUS == 1) + unsigned bus; + #endif reg = pci_read_config32(PCI_DEV(0,0x18,1), 0xe0 + i * 4); @@ -498,7 +577,11 @@ static int ht_setup_chains(uint8_t ht_c_num) reset_needed |= ht_setup_chainx(udev,upos,busn); - + #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 + #endif } reset_needed |= optimize_link_in_coherent(ht_c_num); @@ -506,6 +589,10 @@ static int ht_setup_chains(uint8_t ht_c_num) return reset_needed; } +#ifndef K8_ALLOCATE_IO_RANGE + #define K8_ALLOCATE_IO_RANGE 0 +#endif + static int ht_setup_chains_x(void) { uint8_t nodeid; @@ -514,18 +601,34 @@ static int ht_setup_chains_x(void) uint8_t next_busn; uint8_t ht_c_num; uint8_t nodes; +#if K8_ALLOCATE_IO_RANGE == 1 + unsigned next_io_base; +#endif /* 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=5+1 */ + /* update PCI_DEV(0, 0x18, 1) 0xe0 to 0x05000m03, and next_busn=0x3f+1 */ print_linkn_in("SBLink=", ((reg>>8) & 3) ); - tempreg = 3 | ( 0<<4) | (((reg>>8) & 3)<<8) | (0<<16)| (5<<24); + tempreg = 3 | ( 0<<4) | (((reg>>8) & 3)<<8) | (0<<16)| (0x3f<<24); pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0, tempreg); - next_busn=5+1; /* 0 will be used ht chain with SB we need to keep SB in bus0 in auto stage*/ + next_busn=0x3f+1; /* 0 will be used ht chain with SB we need to keep SB in bus0 in auto stage*/ + +#if K8_ALLOCATE_IO_RANGE == 1 + /* io range allocation */ + tempreg = 0 | (((reg>>8) & 0x3) << 4 )| (0x3<<12); //limit + pci_write_config32(PCI_DEV(0, 0x18, 1), 0xC4, tempreg); + tempreg = 3 | ( 3<<4) | (0<<12); //base + pci_write_config32(PCI_DEV(0, 0x18, 1), 0xC0, tempreg); + next_io_base = 0x3+0x1; +#endif + /* clean others */ for(ht_c_num=1;ht_c_num<4; ht_c_num++) { pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4, 0); + /* io range allocation */ + pci_write_config32(PCI_DEV(0, 0x18, 1), 0xc4 + ht_c_num * 8, 0); + 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; @@ -548,13 +651,23 @@ static int ht_setup_chains_x(void) break; } } - if(ht_c_num == 4) break; /*used up onle 4 non conherent allowed*/ + if(ht_c_num == 4) break; /*used up only 4 non conherent allowed*/ /*update to 0xe0...*/ if((reg & 0xf) == 3) continue; /*SbLink so don't touch it */ print_linkn_in("\tbusn=", next_busn); - tempreg |= (next_busn<<16)|((next_busn+5)<<24); + tempreg |= (next_busn<<16)|((next_busn+0x3f)<<24); pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4, tempreg); - next_busn+=5+1; + next_busn+=0x3f+1; + +#if K8_ALLOCATE_IO_RANGE == 1 + /* 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 + pci_write_config32(PCI_DEV(0, 0x18, 1), 0xC0 + ht_c_num * 8, tempreg); + next_io_base += 0x3+0x1; +#endif + } } /*update 0xe0, 0xe4, 0xe8, 0xec from PCI_DEV(0, 0x18,1) to PCI_DEV(0, 0x19,1) to PCI_DEV(0, 0x1f,1);*/ @@ -568,8 +681,23 @@ static int ht_setup_chains_x(void) regpos = 0xe0 + i * 4; reg = pci_read_config32(PCI_DEV(0, 0x18, 1), regpos); pci_write_config32(dev, regpos, reg); + } +#if K8_ALLOCATE_IO_RANGE == 1 + /* io range allocation */ + for(i = 0; i< 4; i++) { + unsigned regpos; + regpos = 0xc4 + i * 8; + reg = pci_read_config32(PCI_DEV(0, 0x18, 1), regpos); + pci_write_config32(dev, regpos, reg); } + for(i = 0; i< 4; i++) { + unsigned regpos; + regpos = 0xc0 + i * 8; + reg = pci_read_config32(PCI_DEV(0, 0x18, 1), regpos); + pci_write_config32(dev, regpos, reg); + } +#endif } /* recount ht_c_num*/ diff --git a/src/northbridge/amd/amdk8/misc_control.c b/src/northbridge/amd/amdk8/misc_control.c index 4ac6ef473d..4cd3d0d42d 100644 --- a/src/northbridge/amd/amdk8/misc_control.c +++ b/src/northbridge/amd/amdk8/misc_control.c @@ -187,7 +187,10 @@ static void misc_control_init(struct device *dev) /* This works on an Athlon64 because unimplemented links return 0 */ reg = 0x98 + (link * 0x20); link_type = pci_read_config32(f0_dev, reg); - if ((link_type & 7) == 3) { /* Only handle coherent link here */ + /* Only handle coherent link here please */ + if ((link_type & (LinkConnected|InitComplete|NonCoherent)) + == (LinkConnected|InitComplete)) + { cmd &= ~(0xff << (link *8)); /* FIXME this assumes the device on the other side is an AMD device */ cmd |= 0x25 << (link *8); diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c index 89602f37a6..e45aff8242 100644 --- a/src/northbridge/amd/amdk8/northbridge.c +++ b/src/northbridge/amd/amdk8/northbridge.c @@ -40,7 +40,7 @@ static device_t __f1_dev[FX_DEVS]; static void debug_fx_devs(void) { int i; - for (i = 0; i < FX_DEVS; i++) { + for(i = 0; i < FX_DEVS; i++) { device_t dev; dev = __f0_dev[i]; if (dev) { @@ -62,7 +62,7 @@ static void get_fx_devs(void) if (__f1_dev[0]) { return; } - for (i = 0; i < FX_DEVS; i++) { + for(i = 0; i < FX_DEVS; i++) { __f0_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0)); __f1_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1)); } @@ -81,7 +81,7 @@ static void f1_write_config32(unsigned reg, uint32_t value) { int i; get_fx_devs(); - for (i = 0; i < FX_DEVS; i++) { + for(i = 0; i < FX_DEVS; i++) { device_t dev; dev = __f1_dev[i]; if (dev && dev->enabled) { @@ -102,9 +102,9 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) nodeid = amdk8_nodeid(dev); #if 0 printk_debug("%s amdk8_scan_chains max: %d starting...\n", - dev_path(dev), max); + dev_path(dev), max); #endif - for (link = 0; link < dev->links; link++) { + for(link = 0; link < dev->links; link++) { uint32_t link_type; uint32_t busses, config_busses; unsigned free_reg, config_reg; @@ -122,9 +122,10 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) continue; } /* See if there is an available configuration space mapping - * register in function 1. */ + * register in function 1. + */ free_reg = 0; - for (config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) { + for(config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) { uint32_t config; config = f1_read_config32(config_reg); if (!free_reg && ((config & 3) == 0)) { @@ -132,8 +133,8 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) continue; } if (((config & 3) == 3) && - (((config >> 4) & 7) == nodeid) && - (((config >> 8) & 3) == link)) { + (((config >> 4) & 7) == nodeid) && + (((config >> 8) & 3) == link)) { break; } } @@ -141,7 +142,8 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) config_reg = free_reg; } /* If we can't find an available configuration space mapping - * register skip this bus */ + * register skip this bus + */ if (config_reg > 0xec) { continue; } @@ -158,15 +160,15 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) */ busses = pci_read_config32(dev, dev->link[link].cap + 0x14); config_busses = f1_read_config32(config_reg); - + /* Configure the bus numbers for this bridge: the configuration * transactions will not be propagates by the bridge if it is * not correctly configured */ busses &= 0xff000000; busses |= (((unsigned int)(dev->bus->secondary) << 0) | - ((unsigned int)(dev->link[link].secondary) << 8) | - ((unsigned int)(dev->link[link].subordinate) << 16)); + ((unsigned int)(dev->link[link].secondary) << 8) | + ((unsigned int)(dev->link[link].subordinate) << 16)); pci_write_config32(dev, dev->link[link].cap + 0x14, busses); config_busses &= 0x000fc88; @@ -183,13 +185,14 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) dev_path(dev), link, max); #endif /* Now we can scan all of the subordinate busses i.e. the - * chain on the hypertranport link */ - max = hypertransport_scan_chain(&dev->link[link], max); + * chain on the hypertranport link + */ + max = hypertransport_scan_chain(&dev->link[link], 0, 0xbf, max); #if 0 printk_debug("%s Hyper transport scan link: %d new max: %d\n", dev_path(dev), link, max); -#endif +#endif /* We know the number of busses behind this bridge. Set the * subordinate bus number to it's real value @@ -202,6 +205,7 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) config_busses = (config_busses & 0x00ffffff) | (dev->link[link].subordinate << 24); f1_write_config32(config_reg, config_busses); + #if 0 printk_debug("%s Hypertransport scan link: %d done\n", dev_path(dev), link); @@ -214,32 +218,34 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) return max; } -static int reg_useable(unsigned reg, device_t goal_dev, unsigned goal_nodeid, - unsigned goal_link) +static int reg_useable(unsigned reg, + device_t goal_dev, unsigned goal_nodeid, unsigned goal_link) { struct resource *res; unsigned nodeid, link; int result; res = 0; - for (nodeid = 0; !res && (nodeid < 8); nodeid++) { + for(nodeid = 0; !res && (nodeid < 8); nodeid++) { device_t dev; dev = __f0_dev[nodeid]; - for (link = 0; !res && (link < 3); link++) { + for(link = 0; !res && (link < 3); link++) { res = probe_resource(dev, 0x100 + (reg | link)); } } result = 2; if (res) { result = 0; - if ((goal_link == (link - 1)) && - (goal_nodeid == (nodeid - 1)) && - (res->flags <= 1)) { + if ( (goal_link == (link - 1)) && + (goal_nodeid == (nodeid - 1)) && + (res->flags <= 1)) { result = 1; } } #if 0 printk_debug("reg: %02x result: %d gnodeid: %u glink: %u nodeid: %u link: %u\n", - reg, result, goal_nodeid, goal_link, nodeid, link); + reg, result, + goal_nodeid, goal_link, + nodeid, link); #endif return result; } @@ -250,7 +256,7 @@ static struct resource *amdk8_find_iopair(device_t dev, unsigned nodeid, unsigne unsigned free_reg, reg; resource = 0; free_reg = 0; - for (reg = 0xc0; reg <= 0xd8; reg += 0x8) { + for(reg = 0xc0; reg <= 0xd8; reg += 0x8) { int result; result = reg_useable(reg, dev, nodeid, link); if (result == 1) { @@ -277,7 +283,7 @@ static struct resource *amdk8_find_mempair(device_t dev, unsigned nodeid, unsign unsigned free_reg, reg; resource = 0; free_reg = 0; - for (reg = 0x80; reg <= 0xb8; reg += 0x8) { + for(reg = 0x80; reg <= 0xb8; reg += 0x8) { int result; result = reg_useable(reg, dev, nodeid, link); if (result == 1) { @@ -348,7 +354,7 @@ static void amdk8_read_resources(device_t dev) { unsigned nodeid, link; nodeid = amdk8_nodeid(dev); - for (link = 0; link < dev->links; link++) { + for(link = 0; link < dev->links; link++) { if (dev->link[link].children) { amdk8_link_read_bases(dev, nodeid, link); } @@ -499,11 +505,11 @@ static void amdk8_set_resources(device_t dev) amdk8_create_vga_resource(dev, nodeid); /* Set each resource we have found */ - for (i = 0; i < dev->resources; i++) { + for(i = 0; i < dev->resources; i++) { amdk8_set_resource(dev, &dev->resource[i], nodeid); } - for (link = 0; link < dev->links; link++) { + for(link = 0; link < dev->links; link++) { struct bus *bus; bus = &dev->link[link]; if (bus->children) { @@ -520,26 +526,9 @@ static void amdk8_enable_resources(device_t dev) static void mcf0_control_init(struct device *dev) { - uint32_t cmd; - #if 0 printk_debug("NB: Function 0 Misc Control.. "); #endif -#if 1 - /* improve latency and bandwith on HT */ - cmd = pci_read_config32(dev, 0x68); - cmd &= 0xffff80ff; - cmd |= 0x00004800; - pci_write_config32(dev, 0x68, cmd ); -#endif - -#if 0 - /* over drive the ht port to 1000 Mhz */ - cmd = pci_read_config32(dev, 0xa8); - cmd &= 0xfffff0ff; - cmd |= 0x00000600; - pci_write_config32(dev, 0xdc, cmd ); -#endif #if 0 printk_debug("done.\n"); #endif @@ -578,7 +567,7 @@ static void pci_domain_read_resources(device_t dev) /* Find the already assigned resource pairs */ get_fx_devs(); - for (reg = 0x80; reg <= 0xd8; reg+= 0x08) { + for(reg = 0x80; reg <= 0xd8; reg+= 0x08) { uint32_t base, limit; base = f1_read_config32(reg); limit = f1_read_config32(reg + 0x04); @@ -612,8 +601,8 @@ static void pci_domain_read_resources(device_t dev) resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; } -static void ram_resource(device_t dev, unsigned long index, - unsigned long basek, unsigned long sizek) +static void ram_resource(device_t dev, unsigned long index, + unsigned long basek, unsigned long sizek) { struct resource *resource; @@ -691,7 +680,7 @@ static void pci_domain_set_resources(device_t dev) #endif idx = 10; - for (i = 0; i < 8; i++) { + for(i = 0; i < 8; i++) { uint32_t base, limit; unsigned basek, limitk, sizek; base = f1_read_config32(0x40 + (i << 3)); @@ -737,11 +726,35 @@ static void pci_domain_set_resources(device_t dev) static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max) { unsigned reg; + int i; /* Unmap all of the HT chains */ - for (reg = 0xe0; reg <= 0xec; reg += 4) { + 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); + + /* Tune the hypertransport transaction for best performance. + * Including enabling relaxed ordering if it is safe. + */ + get_fx_devs(); + for(i = 0; i < FX_DEVS; i++) { + device_t f0_dev; + f0_dev = __f0_dev[i]; + if (f0_dev && f0_dev->enabled) { + uint32_t httc; + int j; + httc = pci_read_config32(f0_dev, HT_TRANSACTION_CONTROL); + httc &= ~HTTC_RSP_PASS_PW; + if (!dev->link[0].disable_relaxed_ordering) { + httc |= HTTC_RSP_PASS_PW; + } + printk_spew("%s passpw: %s\n", + dev_path(dev), + (!dev->link[0].disable_relaxed_ordering)? + "enabled":"disabled"); + pci_write_config32(f0_dev, HT_TRANSACTION_CONTROL, httc); + } + } return max; } @@ -755,20 +768,34 @@ static struct device_operations pci_domain_ops = { }; #define APIC_ID_OFFSET 0x10 + static unsigned int cpu_bus_scan(device_t dev, unsigned int max) { struct bus *cpu_bus; device_t dev_mc; + int bsp_apic_id; + int apic_id_offset; int i,j; - unsigned nb_cfg_54 = 0; - unsigned siblings = 0; - int enable_apic_ext_id = 0; - int bsp_apic_id = lapicid(); // bsp apicid - int apic_id_offset = bsp_apic_id; + unsigned nb_cfg_54; + int enable_apic_ext_id; + unsigned siblings; +#if CONFIG_LOGICAL_CPUS == 1 + int e0_later_single_core; + int disable_siblings; +#endif -#if CONFIG_LOGICAL_CPUS==1 - int e0_later_single_core; - int disable_siblings = !CONFIG_LOGICAL_CPUS; + nb_cfg_54 = 0; + enable_apic_ext_id = 0; + siblings = 0; + + /* Find the bootstrap processors apicid */ + bsp_apic_id = lapicid(); + + /* See if I will enable extended ids' */ + apic_id_offset = bsp_apic_id; + +#if CONFIG_LOGICAL_CPUS == 1 + disable_siblings = !CONFIG_LOGICAL_CPUS; get_option(&disable_siblings, "dual_core"); // for pre_e0, nb_cfg_54 can not be set, ( even set, when you read it still be 0) @@ -776,45 +803,42 @@ static unsigned int cpu_bus_scan(device_t dev, unsigned int max) nb_cfg_54 = read_nb_cfg_54(); #endif - dev_mc = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - if(pci_read_config32(dev_mc, 0x68) & ( HTTC_APIC_EXT_ID | HTTC_APIC_EXT_BRD_CST)) { + if (!dev_mc) { + die("0:18.0 not found?"); + } + if (pci_read_config32(dev_mc, 0x68) & (HTTC_APIC_EXT_ID|HTTC_APIC_EXT_BRD_CST)) + { enable_apic_ext_id = 1; - if(apic_id_offset==0) { //bsp apic id is not changed + if (apic_id_offset == 0) { + /* bsp apic id is not changed */ apic_id_offset = APIC_ID_OFFSET; } } - /* Find which cpus are present */ cpu_bus = &dev->link[0]; - for (i = 0; i < 8; i++) { + for(i = 0; i < 8; i++) { device_t dev, cpu; struct device_path cpu_path; - /* Find the cpu's memory controller */ + /* Find the cpu's pci device */ dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 3)); - if(!dev) { // in case we move apic cluser before pci_domain and not set that for second CPU - for(j=0; j<4; j++) { - struct device dummy; - uint32_t id; - dummy.bus = dev_mc->bus; - dummy.path.type = DEVICE_PATH_PCI; - dummy.path.u.pci.devfn = PCI_DEVFN(0x18 + i, j); - id = pci_read_config32(&dummy, PCI_VENDOR_ID); - if (id != 0xffffffff && id != 0x00000000 && - id != 0x0000ffff && id != 0xffff0000) { - //create that for it - dev = alloc_dev(dev_mc->bus, &dummy.path); - } + if (!dev) { + /* If I am probing things in a weird order + * ensure all of the cpu's pci devices are found. + */ + int j; + for(j = 0; j <= 3; j++) { + dev = pci_probe_dev(NULL, dev_mc->bus, + PCI_DEVFN(0x18 + i, j)); } } -#if CONFIG_LOGICAL_CPUS==1 +#if CONFIG_LOGICAL_CPUS == 1 e0_later_single_core = 0; - if((!disable_siblings) && dev && dev->enabled) { - j = (pci_read_config32(dev, 0xe8) >> 12) & 3; //dev is func 3 - + if ((!disable_siblings) && dev && dev->enabled) { + j = (pci_read_config32(dev, 0xe8) >> 12) & 3; // dev is func 3 printk_debug(" %s siblings=%d\r\n", dev_path(dev), j); if(nb_cfg_54) { @@ -843,51 +867,49 @@ static unsigned int cpu_bus_scan(device_t dev, unsigned int max) } } else { siblings = j; - } + } } #endif - #if CONFIG_LOGICAL_CPUS==1 for (j = 0; j <= (e0_later_single_core?0:siblings); j++ ) { #else - for (j = 0; j <= siblings; j++ ) { + for (j = 0; j <= siblings; j++ ) { #endif - /* Build the cpu device path */ - cpu_path.type = DEVICE_PATH_APIC; - cpu_path.u.apic.apic_id = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:8); - - /* See if I can find the cpu */ - cpu = find_dev_path(cpu_bus, &cpu_path); - - /* Enable the cpu if I have the processor */ - if (dev && dev->enabled) { - if (!cpu) { - cpu = alloc_dev(cpu_bus, &cpu_path); - } - if (cpu) { - cpu->enabled = 1; - } - } - - /* Disable the cpu if I don't have the processor */ - if (cpu && (!dev || !dev->enabled)) { - cpu->enabled = 0; - } - - /* Report what I have done */ - if (cpu) { - if(enable_apic_ext_id) { - if(cpu->path.u.apic.apic_id<apic_id_offset) { //all add offset except bsp core0 - if( (cpu->path.u.apic.apic_id > siblings) || (bsp_apic_id!=0) ) - cpu->path.u.apic.apic_id += apic_id_offset; - } + /* Build the cpu device path */ + cpu_path.type = DEVICE_PATH_APIC; + cpu_path.u.apic.apic_id = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:8); + + /* See if I can find the cpu */ + cpu = find_dev_path(cpu_bus, &cpu_path); + + /* Enable the cpu if I have the processor */ + if (dev && dev->enabled) { + if (!cpu) { + cpu = alloc_dev(cpu_bus, &cpu_path); } - printk_debug("CPU: %s %s\n", - dev_path(cpu), cpu->enabled?"enabled":"disabled"); - } - } //j + if (cpu) { + cpu->enabled = 1; + } + } + + /* Disable the cpu if I don't have the processor */ + if (cpu && (!dev || !dev->enabled)) { + cpu->enabled = 0; + } + + /* Report what I have done */ + if (cpu) { + if(enable_apic_ext_id) { + if(cpu->path.u.apic.apic_id<apic_id_offset) { //all add offset except bsp core0 + if( (cpu->path.u.apic.apic_id > siblings) || (bsp_apic_id!=0) ) + cpu->path.u.apic.apic_id += apic_id_offset; + } + } + printk_debug("CPU: %s %s\n", + dev_path(cpu), cpu->enabled?"enabled":"disabled"); + } + } //j } - return max; } diff --git a/src/northbridge/amd/amdk8/setup_resource_map.c b/src/northbridge/amd/amdk8/setup_resource_map.c index ebd1978a7c..27da719409 100644 --- a/src/northbridge/amd/amdk8/setup_resource_map.c +++ b/src/northbridge/amd/amdk8/setup_resource_map.c @@ -1,16 +1,53 @@ #define RES_DEBUG 0 +static void setup_resource_map_offset(const unsigned int *register_values, int max, unsigned offset_pci_dev, unsigned offset_io_base) +{ + int i; +// print_debug("setting up resource map offset...."); +#if 0 + print_debug("\r\n"); +#endif + for(i = 0; i < max; i += 3) { + device_t dev; + unsigned where; + unsigned long reg; +#if 0 + #if CONFIG_USE_INIT + prink_debug("%08x <- %08x\r\n", register_values[i] + offset_pci_dev, register_values[i+2]); + #else + print_debug_hex32(register_values[i] + offset_pci_dev); + print_debug(" <-"); + print_debug_hex32(register_values[i+2]); + print_debug("\r\n"); + #endif +#endif + dev = (register_values[i] & ~0xff) + offset_pci_dev; + where = register_values[i] & 0xff; + reg = pci_read_config32(dev, where); + reg &= register_values[i+1]; + reg |= register_values[i+2] + offset_io_base; + pci_write_config32(dev, where, reg); +#if 0 + reg = pci_read_config32(register_values[i]); + reg &= register_values[i+1]; + reg |= register_values[i+2] & ~register_values[i+1]; + pci_write_config32(register_values[i], reg); +#endif + } +// print_debug("done.\r\n"); +} + #define RES_PCI_IO 0x10 #define RES_PORT_IO_8 0x22 #define RES_PORT_IO_32 0x20 -#define RES_MEM_IO 0x30 +#define RES_MEM_IO 0x40 -static void setup_resource_map_x(const unsigned int *register_values, int max) +static void setup_resource_map_x_offset(const unsigned int *register_values, int max, unsigned offset_pci_dev, unsigned offset_io_base) { int i; #if RES_DEBUG - print_debug("setting up resource map ex...."); + print_debug("setting up resource map ex offset...."); #endif @@ -21,17 +58,23 @@ static void setup_resource_map_x(const unsigned int *register_values, int max) #if RES_DEBUG #if CONFIG_USE_INIT printk_debug("%04x: %02x %08x <- & %08x | %08x\r\n", - i/4, register_values[i],register_values[i+1], register_values[i+2], register_values[i+3]); + i/4, register_values[i], + register_values[i+1] + ( (register_values[i]==RES_PCI_IO) ? offset_pci_dev : 0), + register_values[i+2], + register_values[i+3] + ( ( (register_values[i] & RES_PORT_IO_32) == RES_PORT_IO_32) ? offset_io_base : 0) + ); #else print_debug_hex16(i/4); print_debug(": "); print_debug_hex8(register_values[i]); print_debug(" "); - print_debug_hex32(register_values[i+1]); + print_debug_hex32(register_values[i+1] + ( (register_values[i]==RES_PCI_IO) ? offset_pci_dev : 0) ); print_debug(" <- & "); print_debug_hex32(register_values[i+2]); print_debug(" | "); - print_debug_hex32(register_values[i+3]); + print_debug_hex32(register_values[i+3] + + (((register_values[i] & RES_PORT_IO_32) == RES_PORT_IO_32) ? offset_io_base : 0) + ); print_debug("\r\n"); #endif #endif @@ -41,7 +84,7 @@ static void setup_resource_map_x(const unsigned int *register_values, int max) device_t dev; unsigned where; unsigned long reg; - dev = register_values[i+1] & ~0xff; + dev = (register_values[i+1] & ~0xff) + offset_pci_dev; where = register_values[i+1] & 0xff; reg = pci_read_config32(dev, where); reg &= register_values[i+2]; @@ -53,7 +96,7 @@ static void setup_resource_map_x(const unsigned int *register_values, int max) { unsigned where; unsigned reg; - where = register_values[i+1]; + where = register_values[i+1] + offset_io_base; reg = inb(where); reg &= register_values[i+2]; reg |= register_values[i+3]; @@ -64,7 +107,7 @@ static void setup_resource_map_x(const unsigned int *register_values, int max) { unsigned where; unsigned long reg; - where = register_values[i+1]; + where = register_values[i+1] + offset_io_base; reg = inl(where); reg &= register_values[i+2]; reg |= register_values[i+3]; @@ -94,7 +137,95 @@ static void setup_resource_map_x(const unsigned int *register_values, int max) print_debug("done.\r\n"); #endif } +static void setup_resource_map_x(const unsigned int *register_values, int max) +{ + int i; +#if RES_DEBUG + print_debug("setting up resource map ex offset...."); + +#endif + +#if RES_DEBUG + print_debug("\r\n"); +#endif + for(i = 0; i < max; i += 4) { +#if RES_DEBUG + #if CONFIG_USE_INIT + printk_debug("%04x: %02x %08x <- & %08x | %08x\r\n", + i/4, register_values[i],register_values[i+1], register_values[i+2], register_values[i+3]); + #else + print_debug_hex16(i/4); + print_debug(": "); + print_debug_hex8(register_values[i]); + print_debug(" "); + print_debug_hex32(register_values[i+1]); + print_debug(" <- & "); + print_debug_hex32(register_values[i+2]); + print_debug(" | "); + print_debug_hex32(register_values[i+3]); + print_debug("\r\n"); + #endif +#endif + switch (register_values[i]) { + case RES_PCI_IO: //PCI + { + device_t dev; + unsigned where; + unsigned long reg; + dev = register_values[i+1] & ~0xff; + where = register_values[i+1] & 0xff; + reg = pci_read_config32(dev, where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + pci_write_config32(dev, where, reg); + } + break; + case RES_PORT_IO_8: // io 8 + { + unsigned where; + unsigned reg; + where = register_values[i+1]; + reg = inb(where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + outb(reg, where); + } + break; + case RES_PORT_IO_32: //io32 + { + unsigned where; + unsigned long reg; + where = register_values[i+1]; + reg = inl(where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + outl(reg, where); + } + break; +#if 0 + case RES_MEM_IO: //mem + { + unsigned where; + unsigned long reg; + where = register_values[i+1]; + reg = read32(where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + write32( where, reg); + } + break; +#endif + + } // switch + + + } + +#if RES_DEBUG + print_debug("done.\r\n"); +#endif +} static void setup_iob_resource_map(const unsigned int *register_values, int max) { |