diff options
author | Yinghai Lu <yinghailu@gmail.com> | 2004-12-21 22:14:12 +0000 |
---|---|---|
committer | Yinghai Lu <yinghailu@gmail.com> | 2004-12-21 22:14:12 +0000 |
commit | 1de80941c290ccbdce1a33f2a61f36184d040eff (patch) | |
tree | 134202cb5f40bcbf025ddeb4a3ee206f2c4d3b03 /src | |
parent | 2c956bbc19c5dec3b882db5ecc9a2074f3afb1e8 (diff) |
amd k8 routing table creation dynamically support
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1825 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src')
-rw-r--r-- | src/northbridge/amd/amdk8/coherent_ht.c | 855 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/incoherent_ht.c | 26 |
2 files changed, 793 insertions, 88 deletions
diff --git a/src/northbridge/amd/amdk8/coherent_ht.c b/src/northbridge/amd/amdk8/coherent_ht.c index 1c795ade3e..aa682c39a0 100644 --- a/src/northbridge/amd/amdk8/coherent_ht.c +++ b/src/northbridge/amd/amdk8/coherent_ht.c @@ -3,6 +3,9 @@ * written by Stefan Reinauer <stepan@openbios.org> * (c) 2003-2004 by SuSE Linux AG * + * (c) 2004 Tyan Computer + * 2004.12 yhlu added support to create support to create routing table dynamically. + * it also support 8 ways too. (8 ways ladder or 8 ways crossbar) * This code is licensed under GPL. */ @@ -24,7 +27,6 @@ * don't want broadcast to be enabled for that node. */ -#define generate_temp_row(...) ((generate_row(__VA_ARGS__)&(~0x0f0000))|0x010000) #define enable_bsp_routing() enable_routing(0) #define NODE_HT(x) PCI_DEV(0,24+x,0) @@ -59,15 +61,6 @@ static u8 link_to_register(int ldt) return 0; } -static int link_connection(int src, int dest) -{ - /* we generate the needed link information from the rows - * by taking the Request Route of the according row. - */ - - return generate_row(src, dest, CONFIG_MAX_CPUS) & 0x0f; -} - static void disable_probes(void) { /* disable read/write/fill probes for uniprocessor setup @@ -146,6 +139,19 @@ static void fill_row(u8 node, u8 row, u32 value) { pci_write_config32(NODE_HT(node), 0x40+(row<<2), value); } +static u32 get_row(u8 node, u8 row) +{ + return pci_read_config32(NODE_HT(node), 0x40+(row<<2)); +} + +static int link_connection(u8 src, u8 dest) +{ + /* we generate the needed link information from the rows + * by taking the Request Route of the according row. + */ + + return get_row(src, dest) & 0x0f; +} #if CONFIG_MAX_CPUS > 1 @@ -165,15 +171,10 @@ static void rename_temp_node(u8 node) print_spew(" done.\r\n"); } -static bool check_connection(u8 src, u8 dest, u8 link) +static bool check_connection(u8 dest) { /* See if we have a valid connection to dest */ u32 val; - - /* Detect if the coherent HT link is connected. */ - val = pci_read_config32(NODE_HT(src), 0x98+link); - if ( (val&0x17) != 0x03) - return 0; /* Verify that the coherent hypertransport link is * established and actually working by reading the @@ -281,29 +282,112 @@ static int optimize_connection(device_t node1, uint8_t link1, device_t node2, ui return needs_reset; } -static void setup_row(u8 source, u8 dest, u8 nodes) +static void setup_row_local(u8 source, u8 row) // source will be 7 when it is for temp use { - fill_row(source,dest,generate_row(source,dest,nodes)); + unsigned linkn; + uint32_t val; + val = 1; + for(linkn = 0; linkn<3; linkn++) { + unsigned regpos; + uint32_t reg; + regpos = 0x98 + 0x20 * linkn; + reg = pci_read_config32(NODE_HT(source), regpos); + if ((reg & 0x17) != 3) continue; // it is not conherent or not connected + val |= 1<<(linkn+1); + } + val <<= 16; + val |= 0x0101; + fill_row(source,row, val); } -static void setup_temp_row(u8 source, u8 dest, u8 nodes) +static void setup_row_direct(u8 source, u8 dest, u8 linkn) { - fill_row(source,7,generate_temp_row(source,dest,nodes)); + uint32_t val; + val = 1<<16; + val |= 1<<(linkn+1); + val |= 1<<(linkn+1+8); //for direct connect response route should equal to request table + fill_row(source,dest, val); +} +#if CONFIG_MAX_CPUS>2 +static void setup_row_indirect(u8 source, u8 dest, u8 gateway) +{ + //for indirect connection, we need to compute the val from val_s(source, source), and val_g(source, gateway) + uint32_t val_s; + uint32_t val_g; + uint32_t val; +#warning "FIXME is it the way to set the RESPONSE TABLE for indirect?" + val_s = get_row(source, source); + val_g = get_row(source, gateway); + + val = val_g & 0xff; + val_s >>=16; + val_s &=0xfe; + if(val_s!=val) { // use another connect as response + val_s -= val; +#warning "FIXME I don't know how to set BROADCAST TABLE for indirect, 1?" + val |= (1<<16) | (val_s<<8); + } else { + val = val_g; // all the same to gateway + } + + fill_row(source, dest, val); + +} +static void setup_row_indirect_group(const u8 *conn, int num) +{ + int i; + for(i=0; i<num; i+=3) { + setup_row_indirect(conn[i*3], conn[i*3+1],conn[i*3+2]); + } +} +#endif + +static void setup_temp_row(u8 source, u8 dest) +{ + // copy val from (source, dest) to (source,7) + fill_row(source,7,get_row(source,dest)); } -static void setup_node(u8 node, u8 nodes) +static void clear_temp_row(u8 source) { - u8 row; - for(row=0; row<nodes; row++) - setup_row(node, row, nodes); + fill_row(source, 7, DEFAULT); } -static void setup_remote_row(u8 source, u8 dest, u8 nodes) +static void setup_remote_row_direct(u8 source, u8 dest, u8 linkn) { - fill_row(7, dest, generate_row(source, dest, nodes)); + uint32_t val; + val = 1<<16; + val |= 1<<(linkn+1); + val |= 1<<(linkn+1+8); //for direct connect response route should equal to request table + fill_row(7,dest, val ); +} +#if CONFIG_MAX_CPUS>2 +static void setup_remote_row_indirect(u8 source, u8 dest, u8 gateway) +{ + //for indirect connection, we need to compute the val from val_s(source, source), and val_g(source, gateway) + uint32_t val_s; + uint32_t val_g; + uint32_t val; + + val_s = get_row(7, source); + val_g = get_row(7, gateway); + + val = val_g & 0xff; + val_s >>=16; + val_s &=0xfe; + if(val_s!=val) { // use another connect as response + val_s -= val; + val |= 1 | (val_s<<8); + } else { + val = val_g; // all the same to gateway + } + + fill_row(7, dest, val); + } +#endif -static void setup_remote_node(u8 node, u8 nodes) +static void setup_remote_node(u8 node) { static const uint8_t pci_reg[] = { 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c, @@ -314,12 +398,9 @@ static void setup_remote_node(u8 node, u8 nodes) 0xc0, 0xc8, 0xd0, 0xd8, 0xe0, 0xe4, 0xe8, 0xec, }; - uint8_t row; int i; print_spew("setup_remote_node: "); - for(row=0; row<nodes; row++) - setup_remote_row(node, row, nodes); /* copy the default resource map from node 0 */ for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) { @@ -335,15 +416,6 @@ static void setup_remote_node(u8 node, u8 nodes) #endif -#if CONFIG_MAX_CPUS > 2 -static void setup_temp_node(u8 node, u8 nodes) -{ - u8 row; - for(row=0; row<nodes; row++) - fill_row(7,row,generate_row(node,row,nodes)); -} -#endif - static void setup_uniprocessor(void) { print_spew("Enabling UP settings\r\n"); @@ -355,20 +427,70 @@ struct setup_smp_result { int needs_reset; }; +#if CONFIG_MAX_CPUS > 2 +static int optimize_connection_group(const u8 *opt_conn, int num) { + int needs_reset = 0; + int i; + for(i=0; i<num; i+=2) { + needs_reset = optimize_connection( + NODE_HT(opt_conn[i*2]), 0x80 + link_to_register(link_connection(opt_conn[i*2],opt_conn[i*2+1])), + NODE_HT(opt_conn[i*2+1]), 0x80 + link_to_register(link_connection(opt_conn[i*2+1],opt_conn[i*2])) ); + } + return needs_reset; +} +#endif + #if CONFIG_MAX_CPUS > 1 +static uint8_t get_linkn_first(uint8_t byte) +{ + if(byte & 0x02) { byte = 0; } + else if(byte & 0x04) { byte = 1; } + else if(byte & 0x08) { byte = 2; } + return byte; +} +static uint8_t get_linkn_last(uint8_t byte) +{ + if(byte & 0x02) { byte &= 0x0f; byte |= 0x00; } + if(byte & 0x04) { byte &= 0x0f; byte |= 0x10; } + if(byte & 0x08) { byte &= 0x0f; byte |= 0x20; } + return byte>>4; +} +static uint8_t get_linkn_last_count(uint8_t byte) +{ + byte &= 0x3f; + if(byte & 0x02) { byte &= 0xcf; byte |= 0x00; byte+=0x40; } + if(byte & 0x04) { byte &= 0xcf; byte |= 0x10; byte+=0x40; } + if(byte & 0x08) { byte &= 0xcf; byte |= 0x20; byte+=0x40; } + return byte>>4; +} + static struct setup_smp_result setup_smp(void) { struct setup_smp_result result; + u8 byte; + uint32_t val; result.nodes = 2; result.needs_reset = 0; print_spew("Enabling SMP settings\r\n"); - setup_row(0, 0, result.nodes); + setup_row_local(0, 0); // it will update the broadcast RT + + val = get_row(0,0); + byte = (val>>16) & 0xfe; + if(byte<0x2) { // no coherent connection so get out. + result.nodes = 1; + return result; + } + /* Setup and check a temporary connection to node 1 */ - setup_temp_row(0, 1, result.nodes); + //find out linkn + + byte = get_linkn_first(byte); + setup_row_direct(0,1, byte); + setup_temp_row(0, 1); - if (!check_connection(0, 7, link_to_register(link_connection(0,1)))) { + if (!check_connection(7)) { print_spew("No connection to Node 1.\r\n"); setup_uniprocessor(); /* and get up working */ result.nodes = 1; @@ -376,11 +498,44 @@ static struct setup_smp_result setup_smp(void) } /* We found 2 nodes so far */ + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 + setup_row_local(7,1); + setup_remote_row_direct(1, 0, byte); + +#if CONFIG_MAX_CPUS>4 + val = get_row(7,1); + byte = (val>>16) & 0xfe; + byte = get_linkn_last_count(byte); + if((byte>>2)==3) { // Oh! we need to treat it as cpu2. + val = get_row(0,0); + byte = (val>>16) & 0xfe; + byte = get_linkn_last(byte); + setup_row_direct(0,1, byte); + setup_temp_row(0, 1); + + if (!check_connection(7)) { + print_spew("No connection to Node 1.\r\n"); + setup_uniprocessor(); /* and get up working */ + result.nodes = 1; + return result; + } + + /* We found 2 nodes so far */ + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 + setup_row_local(7,1); + setup_remote_row_direct(1, 0, byte); + } +#endif - setup_node(0, result.nodes); /* Node 1 is there. Setup Node 0 correctly */ - setup_remote_node(1, result.nodes); /* Setup the routes on the remote node */ + setup_remote_node(1); /* Setup the regs on the remote node */ rename_temp_node(1); /* Rename Node 7 to Node 1 */ enable_routing(1); /* Enable routing on Node 1 */ +#if 0 + // don't need and it is done by clear_dead_links + clear_temp_row(0); +#endif result.needs_reset = optimize_connection( NODE_HT(0), 0x80 + link_to_register(link_connection(0,1)), @@ -388,11 +543,22 @@ static struct setup_smp_result setup_smp(void) #if CONFIG_MAX_CPUS > 2 result.nodes=4; - + /* Setup and check temporary connection from Node 0 to Node 2 */ - setup_temp_row(0,2, result.nodes); + val = get_row(0,0); + byte = ((val>>16) & 0xfe) - link_connection(0,1); + byte = get_linkn_last_count(byte); + + //find out linkn + if((byte>>2)==0) { // We should have two coherent for 4p and above + result.nodes = 2; + return result; + } + byte &= 3; // bit [3,2] is count-1 + setup_row_direct(0, 2, byte); + setup_temp_row(0, 2); - if (!check_connection(0, 7, link_to_register(link_connection(0,2))) ) { + if (!check_connection(7) ) { print_spew("No connection to Node 2.\r\n"); result.nodes = 2; return result; @@ -401,47 +567,589 @@ static struct setup_smp_result setup_smp(void) /* We found 3 nodes so far. Now setup a temporary * connection from node 0 to node 3 via node 1 */ - - setup_temp_row(0,1, result.nodes); /* temp. link between nodes 0 and 1 */ - setup_temp_row(1,3, result.nodes); /* temp. link between nodes 1 and 3 */ - - if (!check_connection(1, 7, link_to_register(link_connection(1,3)))) { + setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */ + /* here should setup_row_direct(1,3) at first, before that we should find the link in cpu 1 to 3*/ + val = get_row(1,1); + byte = ((val>>16) & 0xfe) - link_connection(1,0); + byte = get_linkn_first(byte); + setup_row_direct(1,3,byte); + setup_temp_row(1,3); /* temp. link between nodes 1 and 3 */ + + if (!check_connection(7)) { print_spew("No connection to Node 3.\r\n"); result.nodes = 2; return result; } /* We found 4 nodes so far. Now setup all nodes for 4p */ + /* for indirect we will use clockwise routing */ + static const u8 conn4_1[] = { + 0,3,1, + 1,2,3, + }; - setup_node(0, result.nodes); /* The first 2 nodes are configured */ - setup_node(1, result.nodes); /* already. Just configure them for 4p */ + setup_row_indirect_group(conn4_1, sizeof(conn4_1)/sizeof(conn4_1[0])); - setup_temp_row(0,2, result.nodes); - setup_temp_node(2, result.nodes); - rename_temp_node(2); - enable_routing(2); + setup_temp_row(0,2); + + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 + + setup_row_local(7,2); + setup_remote_row_direct(2, 0, byte); + setup_remote_node(2); /* Setup the regs on the remote node */ + + rename_temp_node(2); /* Rename Node 7 to Node 2 */ + enable_routing(2); /* Enable routing on Node 2 */ + - setup_temp_row(0,1, result.nodes); - setup_temp_row(1,3, result.nodes); - setup_temp_node(3, result.nodes); + setup_temp_row(0,1); + setup_temp_row(1,3); + + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 + + setup_row_local(7,3); + setup_remote_row_direct(3, 1, byte); + setup_remote_node(3); /* Setup the regs on the remote node */ + rename_temp_node(3); enable_routing(3); /* enable routing on node 3 (temp.) */ + + /* We need to init link between 2, and 3 direct link */ + val = get_row(2,2); + byte = ((val>>16) & 0xfe) - link_connection(2,0); + byte = get_linkn_last_count(byte); +#if CONFIG_MAX_CPUS>4 + // We need to find out which link it so CPU3 + // methods is try to access another 7 actully it is cpu4 + if((byte>>2)==2) { // one to CPU3, one to cpu0, one to CPU4 + setup_temp_row(0,2); + setup_row_direct(2, 4, byte); + setup_temp_row(2, 4); + + if (check_connection(7)) { // so the link is to CPU4 + //We need to re compute it + val = get_row(2,2); + byte = (val>>16) & 0xfe; + byte = get_linkn_first(byte); + } + } +#endif + setup_row_direct(2,3, byte & 0x3); - /* optimize physical connections - by LYH */ - result.needs_reset = optimize_connection( - NODE_HT(0), 0x80 + link_to_register(link_connection(0,2)), - NODE_HT(2), 0x80 + link_to_register(link_connection(2,0)) ); + val = get_row(3,3); + byte = ((val>>16) & 0xfe) - link_connection(3,1); + byte = get_linkn_last_count(byte); +#if CONFIG_MAX_CPUS>4 + // We need to find out which link it so CPU2 + // methods is try to access another 7 actully it is cpu5 + if((byte>>2)==2) { // one to CPU2, one to cpu1, one to CPU5 + setup_temp_row(0,1); + setup_temp_row(1,3); + setup_row_direct(3, 5, byte); + setup_temp_row(3, 5); + + if (check_connection(7)) { // so the link is to CPU5 + //We need to re compute it + val = get_row(3, 3); + byte = (val>>16) & 0xfe; + byte = get_linkn_first(byte); + } + } +#endif + setup_row_direct(3,2, byte & 0x3); - result.needs_reset = optimize_connection( - NODE_HT(1), 0x80 + link_to_register(link_connection(1,3)), - NODE_HT(3), 0x80 + link_to_register(link_connection(3,1)) ); + /* Set indirect connection to 0, and 1 for indirect we will use clockwise routing */ + static const u8 conn4_2[] = { + 2,1,0, + 3,0,2, + }; - result.needs_reset = optimize_connection( - NODE_HT(2), 0x80 + link_to_register(link_connection(2,3)), - NODE_HT(3), 0x80 + link_to_register(link_connection(3,2)) ); + setup_row_indirect_group(conn4_2, sizeof(conn4_2)/sizeof(conn4_2[0])); + + // We need to do sth to reverse work for setup_temp_row (0,1) (1,3) +#if 0 + // it will be done by clear_dead_links + clear_temp_row(0); + clear_temp_row(1); +#endif + + /* optimize physical connections - by LYH */ + static const u8 opt_conn4[] = { + 0,2, + 1,3, + 2,3, + }; + + result.needs_reset = optimize_connection_group(opt_conn4, sizeof(opt_conn4)/sizeof(opt_conn4[0])); #endif /* CONFIG_MAX_CPUS > 2 */ +#if CONFIG_MAX_CPUS > 4 + result.nodes=6; + + /* Setup and check temporary connection from Node 0 to Node 4 via 2 */ + val = get_row(2,2); + byte = ((val>>16) & 0xfe) - link_connection(2,3) - link_connection(2,0); + byte = get_linkn_last_count(byte); + + //find out linkn + if((byte>>2)==0) { // We should have two coherent for 4p and above + result.nodes = 4; + return result; + } + byte &= 3; // bit [3,2] is count-1 + setup_row_direct(2, 4, byte); + + /* Setup and check temporary connection from Node 0 to Node 4 through 2*/ + for(byte=0; byte<4; byte+=2) { + setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */ + } + + if (!check_connection(7) ) { + print_spew("No connection to Node 4.\r\n"); + result.nodes = 4; + return result; + } + + /* Setup and check temporary connection from Node 0 to Node 5 through 1, 3*/ + + val = get_row(3,3); + byte = ((val>>16) & 0xfe) - link_connection(3,2) - link_connection(3,1); + byte = get_linkn_last_count(byte); + //find out linkn + if((byte>>2)==0) { // We should have two coherent for 4p and above + result.nodes = 4; + return result; + } + + byte &= 3; // bit [3,2] is count-1 + setup_row_direct(3, 5, byte); + + setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */ + for(byte=0; byte<4; byte+=2) { + setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */ + } + + if (!check_connection(7)) { + print_spew("No connection to Node 5.\r\n"); + result.nodes = 4; + return result; + } + + /* We found 6 nodes so far. Now setup all nodes for 6p */ + static const u8 conn6_1[] = { + 0, 4, 2, + 0, 5, 1, + 1, 4, 3, + 1, 5, 3, + 2, 5, 3, +#if !CROSS_BAR_47_56 + 3, 4, 5, +#else + 3, 4, 2, +#endif + }; + + setup_row_indirect_group(conn6_1, sizeof(conn6_1)/sizeof(conn6_1[0])); + + + for(byte=0; byte<4; byte+=2) { + setup_temp_row(byte,byte+2); + } + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 + + setup_row_local(7,4); + setup_remote_row_direct(4, 2, byte); + setup_remote_node(4); /* Setup the regs on the remote node */ + rename_temp_node(4); + enable_routing(4); + + setup_temp_row(0,1); + for(byte=0; byte<4; byte+=2) { + setup_temp_row(byte+1,byte+3); + } + + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 + setup_row_local(7,5); + setup_remote_row_direct(5, 3, byte); + setup_remote_node(5); /* Setup the regs on the remote node */ + + rename_temp_node(5); + enable_routing(5); /* enable routing on node 5 (temp.) */ + +#if !CROSS_BAR_47_56 + /* We need to init link between 4, and 5 direct link */ + val = get_row(4,4); + byte = ((val>>16) & 0xfe) - link_connection(4,2); + byte = get_linkn_last_count(byte); +#if CONFIG_MAX_CPUS>4 + // We need to find out which link it so CPU5 + // methods is try to access another 7 actully it is cpu6 + if((byte>>2)==2) { // one to CPU5, one to cpu2, one to CPU6 + setup_temp_row(0,2); + setup_temp_row(2,4); + setup_row_direct(4, 6, byte); + setup_temp_row(4, 6); + + if (check_connection(7)) { // so the link is to CPU4 + //We need to re compute it + val = get_row(4,4); + byte = (val>>16) & 0xfe; + byte = get_linkn_first(byte); + } + } +#endif + setup_row_direct(4,5, byte & 0x3); + + val = get_row(5,5); + byte = ((val>>16) & 0xfe) - link_connection(5,3); + byte = get_linkn_last_count(byte); +#if CONFIG_MAX_CPUS>4 + // We need to find out which link it so CPU4 + // methods is try to access another 7 actully it is cpu7 + if((byte>>2)==2) { // one to CPU4, one to cpu3, one to CPU7 + setup_temp_row(0,1); + setup_temp_row(1,3); + setup_temp_row(3,7); + setup_row_direct(5, 7, byte); + setup_temp_row(5, 7); + + if (check_connection(7)) { // so the link is to CPU5 + //We need to re compute it + val = get_row(5, 5); + byte = (val>>16) & 0xfe; + byte = get_linkn_first(byte); + } + } +#endif + setup_row_direct(5,4, byte & 0x3); +#endif // !CROSS_BAR_47_56 + + /* Set indirect connection to 0, to 3 for indirect we will use clockwise routing */ + static const u8 conn6_2[] = { +#if !CROSS_BAR_47_56 + 4, 0, 2, + 4, 1, 2, + 4, 3, 2, + 5, 0, 4, + 5, 2, 4, + 5, 1, 3, +#else + + 4, 0, 2, + 4, 1, 2, + 4, 3, 2, + 4, 5, 2, + 5, 0, 3, + 5, 2, 3, + 5, 1, 3, + 5, 4, 3, +#endif + }; + + setup_row_indirect_group(conn6_2, sizeof(conn6_2)/sizeof(conn6_2[0])); +#if 0 + // We need to do sth about reverse about setup_temp_row (0,1), (2,4), (1, 3), (3,5) + // It will be done by clear_dead_links + for(byte=0; byte<4; byte++) { + clear_temp_row(byte); + } +#endif + + /* optimize physical connections - by LYH */ + static const uint8_t opt_conn6[] ={ + 2, 4, + 3, 5, +#if !CROSS_BAR_47_56 + 4, 5, +#endif + }; + result.needs_reset = optimize_connection_group(opt_conn6, sizeof(opt_conn6)/sizeof(opt_conn6[0])); + + +#endif /* CONFIG_MAX_CPUS > 4 */ + +#if CONFIG_MAX_CPUS >6 + result.nodes=8; + + /* Setup and check temporary connection from Node 0 to Node 6 via 2 and 4 to 7 */ + val = get_row(4,4); +#if !CROSS_BAR_47_56 + byte = ((val>>16) & 0xfe) - link_connection(4,5) - link_connection(4,2); +#else + byte = ((val>>16) & 0xfe) - link_connection(4,2); +#endif + byte = get_linkn_last_count(byte); // Max link to 6 + if((byte>>2)==0) { // We should have two coherent for 8p and above + result.nodes = 6; + return result; + } + byte &= 3; // bit [3,2] is count-1 + setup_row_direct(4, 6, byte); + + /* Setup and check temporary connection from Node 0 to Node 6 through 2, and 4*/ + for(byte=0; byte<6; byte+=2) { + setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */ + } + + if (!check_connection(7) ) { + print_spew("No connection to Node 6.\r\n"); + result.nodes = 6; + return result; + } +#if !CROSS_BAR_47_56 + /* Setup and check temporary connection from Node 0 to Node 5 through 1, 3, 5*/ + + val = get_row(5,5); + byte = ((val>>16) & 0xfe) - link_connection(5,4) - link_connection(5,3); + byte = get_linkn_first(byte); + setup_row_direct(5, 7, byte); + + setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */ + for(byte=0; byte<6; byte+=2) { + setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */ + } +#else + val = get_row(4,4); + byte = ((val>>16) & 0xfe) - link_connection(4,2) ; + byte = get_linkn_first(byte); // min link to 7 + setup_row_direct(4, 7, byte); + + /* Setup and check temporary connection from Node 0 to Node 7 through 2, and 4*/ + for(byte=0; byte<4; byte+=2) { + setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */ + } + setup_temp_row(4, 7); + +#endif + + if (!check_connection(7)) { + print_spew("No connection to Node 7.\r\n"); + result.nodes = 6; + return result; + } + + + /* We found 8 nodes so far. Now setup all nodes for 8p */ + static const u8 conn8_1[] = { +#if !CROSS_BAR_47_56 + 0, 6, 2, +// 0, 7, 1, + 1, 6, 3, +// 1, 7, 3, + 2, 6, 4, +// 2, 7, 3, + 3, 6, 5, +// 3, 7, 5, +// 4, 7, 5, +#else + 0, 6, 2, +// 0, 7, 2, + 1, 6, 3, +// 1, 7, 3, + 2, 6, 4, +// 2, 7, 4, + 3, 6, 5, +// 3, 7, 5, +#endif + }; + + setup_row_indirect_group(conn8_1,sizeof(conn8_1)/sizeof(conn8_1[0])); + + for(byte=0; byte<6; byte+=2) { + setup_temp_row(byte,byte+2); + } + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 + + setup_row_local(7,6); + setup_remote_row_direct(6, 4, byte); + setup_remote_node(6); /* Setup the regs on the remote node */ + rename_temp_node(6); + enable_routing(6); + +#if !CROSS_BAR_47_56 + setup_temp_row(0,1); + for(byte=0; byte<6; byte+=2) { + setup_temp_row(byte+1,byte+3); + } + + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 + setup_row_local(7,7); + setup_remote_row_direct(7, 5, byte); + +#else + for(byte=0; byte<4; byte+=2) { + setup_temp_row(byte,byte+2); + } + setup_temp_row(4,7); + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 + + setup_row_local(7,7); + setup_remote_row_direct(7, 4, byte); + // till now 4-7, 7-4 done. +#endif + setup_remote_node(7); /* Setup the regs on the remote node */ +// rename_temp_node(7); + enable_routing(7); /* enable routing on node 5 (temp.) */ + +#if CROSS_BAR_47_56 + //here init 5, 6 and 5, 7 + /* Setup and check temporary connection from Node 0 to Node 5 through 1, 3, 5*/ + + val = get_row(5,5); + byte = ((val>>16) & 0xfe) - link_connection(5,3); + byte = get_linkn_last(byte); + setup_row_direct(5, 7, byte); + + setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */ + for(byte=0; byte<6; byte+=2) { + setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */ + } + + if (!check_connection(7)) { + // We need to recompute link to 7 + val = get_row(5,5); + byte = ((val>>16) & 0xfe) - link_connection(5,3); + byte = get_linkn_first(byte); + + byte &= 3; // bit [3,2] is count-1 + setup_row_direct(5, 7, byte); +#if 0 + setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */ + for(byte=0; byte<6; byte+=2) { + setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */ + } +#else + setup_temp_row(5,7); +#endif + check_connection(7); + } + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 +// setup_row_local(7,7); + setup_remote_row_direct(7, 5, byte); + //Till now 57, 75 done + + //init 5,6 + val = get_row(5,5); + byte = ((val>>16) & 0xfe) - link_connection(5,3) - link_connection(5,7); + byte = get_linkn_first(byte); + setup_row_direct(5, 6, byte); + + + val = get_row(6,6); + byte = ((val>>16) & 0xfe) - link_connection(6,4); + byte = get_linkn_last(byte); + setup_row_direct(6, 7, byte); + + for(byte=0; byte<6; byte+=2) { + setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */ + } + setup_temp_row(6,7); + + if (!check_connection(7)) { + // We need to recompute link to 7 + val = get_row(6,6); + byte = ((val>>16) & 0xfe) - link_connection(6,4); + byte = get_linkn_first(byte); + + setup_row_direct(6, 7, byte); +#if 0 + for(byte=0; byte<6; byte+=2) { + setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */ + } +#endif + setup_temp_row(6,7); + check_connection(7); + } + val = pci_read_config32(NODE_HT(7), 0x6c); + byte = (val>2) & 0x3; // get default link on 7 to 0 +// setup_row_local(7,7); + setup_remote_row_direct(7, 6, byte); + //Till now 67, 76 done + + //init 6,5 + val = get_row(6,6); + byte = ((val>>16) & 0xfe) - link_connection(6,4) - link_connection(6,7); + byte = get_linkn_first(byte); + setup_row_direct(6, 5, byte); + +#endif + +#if !CROSS_BAR_47_56 + /* We need to init link between 6, and 7 direct link */ + val = get_row(6,6); + byte = ((val>>16) & 0xfe) - link_connection(6,4); + byte = get_linkn_first(byte); + setup_row_direct(6,7, byte & 0x3); + + val = get_row(7,7); + byte = ((val>>16) & 0xfe) - link_connection(7,5); + byte = get_linkn_first(byte); + setup_row_direct(7,6, byte & 0x3); +#endif + + /* Set indirect connection to 0, to 3 for indirect we will use clockwise routing */ + static const u8 conn8_2[] = { +#if !CROSS_BAR_47_56 + 0, 7, 1, // restore it + 1, 7, 3, + 2, 7, 3, + 3, 7, 5, + 4, 7, 5, + + 6, 0, 4, + 6, 1, 4, + 6, 2, 4, + 6, 3, 4, + 6, 5, 4, + 7, 0, 6, + 7, 1, 5, + 7, 2, 6, + 7, 3, 5, + 7, 4, 6, +#else + 0, 7, 2, // restore it + 1, 7, 3, + 2, 7, 4, + 3, 7, 5, + + 6, 0, 4, + 6, 1, 4, + 6, 2, 4, + 6, 3, 4, + 7, 0, 4, + 7, 1, 5, + 7, 2, 4, + 7, 3, 5, + 4, 5, 7, + 5, 4, 6, +#endif + }; + + setup_row_indirect_group(conn8_2, sizeof(conn8_2)/sizeof(conn8_2[0])); + + static const uint8_t opt_conn8[] ={ + 4, 6, +#if CROSS_BAR_47_56 + 4, 7, + 5, 6, +#endif + 5, 7, + 6, 7, + }; + /* optimize physical connections - by LYH */ + result.needs_reset = optimize_connection_group(opt_conn8, sizeof(opt_conn6)/sizeof(opt_conn8[0])); + +#endif /* CONFIG_MAX_CPUS > 6 */ + print_debug_hex8(result.nodes); print_debug(" nodes initialized.\r\n"); return result; @@ -481,6 +1189,9 @@ static void clear_dead_routes(unsigned nodes) { int last_row; int node, row; +#if CONFIG_MAX_CPUS>6 + if(nodes==8) return;// don't touch (7,7) +#endif last_row = nodes; if (nodes == 1) { last_row = 0; @@ -640,7 +1351,7 @@ static int setup_coherent_ht_domain(void) clear_dead_routes(result.nodes); 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/incoherent_ht.c b/src/northbridge/amd/amdk8/incoherent_ht.c index c5f7f2da6f..3255a03873 100644 --- a/src/northbridge/amd/amdk8/incoherent_ht.c +++ b/src/northbridge/amd/amdk8/incoherent_ht.c @@ -1,3 +1,8 @@ +/* + This should be done by Eric + 2004.12 yhlu add multi ht chain dynamically support +*/ + #include <device/pci_def.h> #include <device/pci_ids.h> #include <device/hypertransport_def.h> @@ -366,6 +371,7 @@ static int ht_setup_chains_x(void) uint32_t tempreg; unsigned next_busn; int ht_c_num; + int 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); @@ -377,18 +383,13 @@ static int ht_setup_chains_x(void) 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); } + + nodes = ((pci_read_config32(PCI_DEV(0, 0x18, 0), 0x60)>>4) & 7) + 1; - for(nodeid=0; nodeid<8; nodeid++) { + for(nodeid=0; nodeid<nodes; nodeid++) { device_t dev; unsigned linkn; dev = PCI_DEV(0, 0x18+nodeid,0); - //read id, check id to see if dev exists ; - reg = pci_read_config32(dev, PCI_VENDOR_ID); - if (((reg & 0xffff) == 0x0000) || ((reg & 0xffff) == 0xffff) || - (((reg >> 16) & 0xffff) == 0xffff) || - (((reg >> 16) & 0xffff) == 0x0000)) { - break; - } for(linkn = 0; linkn<3; linkn++) { unsigned regpos; regpos = 0x98 + 0x20 * linkn; @@ -412,17 +413,10 @@ static int ht_setup_chains_x(void) } //update 0xe0, 0xe4, 0xe8, 0xec from PCI_DEV(0, 0x18,1) to PCI_DEV(0, 0x19,1) to PCI_DEV(0, 0x1f,1); - for(nodeid = 1; nodeid<8; nodeid++) { + for(nodeid = 1; nodeid<nodes; nodeid++) { int i; device_t dev; dev = PCI_DEV(0, 0x18+nodeid,1); - //read id, check id to see if dev exists ; - reg = pci_read_config32(dev, PCI_VENDOR_ID); - if (((reg & 0xffff) == 0x0000) || ((reg & 0xffff) == 0xffff) || - (((reg >> 16) & 0xffff) == 0xffff) || - (((reg >> 16) & 0xffff) == 0x0000)) { - break; - } for(i = 0; i< 4; i++) { unsigned regpos; regpos = 0xe0 + i * 4; |