1 /* coherent hypertransport initialization for AMD64
2 * written by Stefan Reinauer <stepan@openbios.info>
3 * (c) 2003 by SuSE Linux AG
5 * This code is licensed under GPL.
9 * This algorithm assumes a grid configuration as follows:
12 * org. : 1x1 2x1 2x2 2x3 2x4
16 #include <device/pci_def.h>
17 #include "arch/romcc_io.h"
23 /* when generating a temporary row configuration we
24 * don't want broadcast to be enabled for that node.
27 #define generate_temp_row(x...) ((generate_row(x)&(~0x0f0000))|0x010000)
28 #define clear_temp_row(x) fill_row(x,7,DEFAULT)
29 #define enable_bsp_routing() enable_routing(0)
31 #define NODE_HT(x) PCI_DEV(0,24+x,0)
32 #define NODE_MP(x) PCI_DEV(0,24+x,1)
33 #define NODE_MC(x) PCI_DEV(0,24+x,3)
35 #define DEFAULT 0x00010101 /* default row entry */
44 static void disable_probes(void)
46 /* disable read/write/fill probes for uniprocessor setup
47 * they don't make sense if only one cpu is available
50 /* Hypetransport Transaction Control Register
52 * [ 0: 0] Disable read byte probe
54 * 1 = Probes not issued
55 * [ 1: 1] Disable Read Doubleword probe
57 * 1 = Probes not issued
58 * [ 2: 2] Disable write byte probes
60 * 1 = Probes not issued
61 * [ 3: 3] Disable Write Doubleword Probes
63 * 1 = Probes not issued.
64 * [10:10] Disable Fill Probe
65 * 0 = Probes issued for cache fills
66 * 1 = Probes not issued for cache fills.
71 print_debug("Disabling read/write/fill probes for UP... ");
73 val=pci_read_config32(NODE_HT(0), 0x68);
74 val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
75 pci_write_config32(NODE_HT(0), 0x68, val);
77 print_debug("done.\r\n");
81 static void enable_routing(u8 node)
85 /* HT Initialization Control Register
87 * [ 0: 0] Routing Table Disable
88 * 0 = Packets are routed according to routing tables
89 * 1 = Packets are routed according to the default link field
90 * [ 1: 1] Request Disable (BSP should clear this)
91 * 0 = Request packets may be generated
92 * 1 = Request packets may not be generated.
93 * [ 3: 2] Default Link (Read-only)
97 * 11 = CPU on same node
99 * - Scratch bit cleared by a cold reset
100 * [ 5: 5] BIOS Reset Detect
101 * - Scratch bit cleared by a cold reset
102 * [ 6: 6] INIT Detect
103 * - Scratch bit cleared by a warm or cold reset not by an INIT
107 /* Enable routing table */
108 print_debug("Enabling routing table for node ");
109 print_debug_hex32(node);
111 val=pci_read_config32(NODE_HT(node), 0x6c);
112 val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
113 pci_write_config32(NODE_HT(node), 0x6c, val);
115 print_debug(" done.\r\n");
120 static void rename_temp_node(u8 node)
124 print_debug("Renaming current temp node to ");
125 print_debug_hex32(node);
127 val=pci_read_config32(NODE_HT(7), 0x60);
128 val &= (~7); /* clear low bits. */
129 val |= node; /* new node */
130 pci_write_config32(NODE_HT(7), 0x60, val);
132 print_debug(" done.\r\n");
137 static bool check_connection(u8 src, u8 dest, u8 link)
139 /* this function does 2 things:
140 * 1) detect whether the coherent HT link is connected.
141 * 2) verify that the coherent hypertransport link
142 * is established and actually working by reading the
143 * remote node's vendor/device id
153 val=pci_read_config32(NODE_HT(src), 0x98+link);
154 if ( (val&0x17) != 0x03)
158 val=pci_read_config32(NODE_HT(dest),0);
159 if(val != 0x11001022)
165 static void fill_row(u8 node, u8 row, u32 value)
168 print_debug("fill_row: pci_write_config32(");
169 print_debug_hex32(NODE_HT(node));
170 print_debug_char(',');
171 print_debug_hex32(0x40 + (row << 2));
172 print_debug_char(',');
173 print_debug_hex32(value);
174 print_debug(")\r\n");
176 pci_write_config32(NODE_HT(node), 0x40+(row<<2), value);
179 static void setup_row(u8 source, u8 dest, u8 cpus)
182 printk_spew("setting up link from node %d to %d (%d cpus)\r\n",
186 fill_row(source,dest,generate_row(source,dest,cpus));
189 static void setup_temp_row(u8 source, u8 dest, u8 cpus)
192 printk_spew("setting up temp. link from node %d to %d (%d cpus)\r\n",
196 fill_row(source,7,generate_temp_row(source,dest,cpus));
199 static void setup_node(u8 node, u8 cpus)
202 for(row=0; row<cpus; row++)
203 setup_row(node, row, cpus);
206 static void setup_remote_row(u8 source, u8 dest, u8 cpus)
208 fill_row(7, dest, generate_row(source, dest, cpus));
211 static void setup_remote_node(u8 node, u8 cpus)
213 static const uint8_t pci_reg[] = {
214 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
215 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
216 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
217 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
218 0xc4, 0xcc, 0xd4, 0xdc,
219 0xc0, 0xc8, 0xd0, 0xd8,
220 0xe0, 0xe4, 0xe8, 0xec,
225 print_debug("setup_remote_node\r\n");
227 for(row=0; row<cpus; row++)
228 setup_remote_row(node, row, cpus);
230 /* copy the default resource map from node 0 */
231 for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
236 print_debug("copying reg: ");
237 print_debug_hex8(reg);
240 value = pci_read_config32(NODE_MP(0), reg);
241 pci_write_config32(NODE_MP(7), reg, value);
245 print_debug("setup_remote_done\r\n");
252 static void setup_temp_node(u8 node, u8 cpus)
255 for(row=0; row<cpus; row++)
256 fill_row(7,row,generate_row(node,row,cpus));
260 static u8 setup_uniprocessor(void)
262 print_debug("Enabling UP settings\r\n");
268 static u8 setup_smp(void)
272 print_debug("Enabling SMP settings\r\n");
275 /* Setup and check a temporary connection to node 1 */
276 setup_temp_row(0,1,cpus);
278 if (!check_connection(0, 7, ACROSS)) { // Link: ACROSS
279 print_debug("No connection to Node 1.\r\n");
280 clear_temp_row(0); /* delete temp connection */
281 setup_uniprocessor(); /* and get up working */
285 /* We found 2 nodes so far */
286 setup_node(0, cpus); /* Node 1 is there. Setup Node 0 correctly */
287 setup_remote_node(1, cpus); /* Setup the routes on the remote node */
288 rename_temp_node(1); /* Rename Node 7 to Node 1 */
289 enable_routing(1); /* Enable routing on Node 1 */
291 clear_temp_row(0); /* delete temporary connection */
296 /* Setup and check temporary connection from Node 0 to Node 2 */
297 setup_temp_row(0,2,cpus);
299 if (!check_connection(0, 7, UP)) { // Link: UP
300 print_debug("No connection to Node 2.\r\n");
301 clear_temp_row(0); /* delete temp connection */
305 /* We found 3 nodes so far. Now setup a temporary
306 * connection from node 0 to node 3 via node 1
309 setup_temp_row(0,1,cpus); /* temp. link between nodes 0 and 1 */
310 setup_temp_row(1,3,cpus); /* temp. link between nodes 1 and 3 */
312 if (!check_connection(1, 7, UP)) { // Link: UP
313 print_debug("No connection to Node 3.\r\n");
314 clear_temp_row(0); /* delete temp connection */
315 clear_temp_row(1); /* delete temp connection */
319 /* We found 4 nodes so far. Now setup all nodes for 4p */
321 setup_node(0, cpus); /* The first 2 nodes are configured */
322 setup_node(1, cpus); /* already. Just configure them for 4p */
324 setup_temp_row(0,2,cpus);
325 setup_temp_node(2,cpus);
329 setup_temp_row(0,1,cpus);
330 setup_temp_row(1,3,cpus);
331 setup_temp_node(3,cpus);
333 enable_routing(3); /* enable routing on node 3 (temp.) */
341 print_debug_hex32(cpus);
342 print_debug(" nodes initialized.\r\n");
348 static unsigned detect_mp_capabilities(unsigned cpus)
350 unsigned node, row, mask;
354 print_debug("detect_mp_capabilities: ");
355 print_debug_hex32(cpus);
359 mask=0x06; /* BigMPCap */
361 mask=0x02; /* MPCap */
363 for (node=0; node<cpus; node++) {
364 if ((pci_read_config32(NODE_MC(node), 0xe8) & mask)!=mask)
371 /* one of our cpus is not mp capable */
373 print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
375 for (node=cpus; node>0; node--)
376 for (row=cpus; row>0; row--)
377 fill_row(NODE_HT(node-1), row-1, DEFAULT);
379 return setup_uniprocessor();
384 /* this is a shrunken cpuid. */
386 static unsigned int cpuid(unsigned int op)
390 asm volatile ( "cpuid" : "=a" (ret) : "a" (op));
395 static void coherent_ht_finalize(unsigned cpus)
400 /* set up cpu count and node count and enable Limit
401 * Config Space Range for all available CPUs.
402 * Also clear non coherent hypertransport bus range
403 * registers on Hammer A0 revision.
407 print_debug("coherent_ht_finalize\r\n");
409 rev_a0=((cpuid(1)&0xffff)==0x0f10);
411 for (node=0; node<cpus; node++) {
413 val=pci_read_config32(NODE_HT(node), 0x60);
414 val &= (~0x000F0070);
415 val |= ((cpus-1)<<16)|((cpus-1)<<4);
416 pci_write_config32(NODE_HT(node),0x60,val);
418 val=pci_read_config32(NODE_HT(node), 0x68);
420 pci_write_config32(NODE_HT(node),0x68,val);
423 pci_write_config32(NODE_HT(node),0x94,0);
424 pci_write_config32(NODE_HT(node),0xb4,0);
425 pci_write_config32(NODE_HT(node),0xd4,0);
430 print_debug("done\r\n");
434 static int setup_coherent_ht_domain(void)
437 int reset_needed = 0;
439 enable_bsp_routing();
442 cpus=setup_uniprocessor();
445 cpus=detect_mp_capabilities(cpus);
447 coherent_ht_finalize(cpus);