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 #define WAIT_TIMES 1000
82 static void wait_ap_stop(u8 node)
86 for(i=0;i<WAIT_TIMES;i++) {
88 regx = pci_read_config32(NODE_HT(node),0x6c);
89 if((regx & (1<<4))==1) break;
91 reg = pci_read_config32(NODE_HT(node),0x6c);
92 reg &= ~(1<<4); // clear it
93 pci_write_config32(NODE_HT(node), 0x6c, reg);
96 static void notify_bsp_ap_is_stopped(void)
99 unsigned long apic_id;
100 apic_id = *((volatile unsigned long *)(APIC_DEFAULT_BASE+APIC_ID));
103 print_debug("applicaton cpu apic_id: ");
104 print_debug_hex32(apic_id);
107 /* AP apic_id == node_id ? */
109 /* set the ColdResetbit to notify BSP that AP is stopped */
110 reg = pci_read_config32(NODE_HT(apic_id), 0x6C);
112 pci_write_config32(NODE_HT(apic_id), 0x6C, reg);
118 static void enable_routing(u8 node)
122 /* HT Initialization Control Register
124 * [ 0: 0] Routing Table Disable
125 * 0 = Packets are routed according to routing tables
126 * 1 = Packets are routed according to the default link field
127 * [ 1: 1] Request Disable (BSP should clear this)
128 * 0 = Request packets may be generated
129 * 1 = Request packets may not be generated.
130 * [ 3: 2] Default Link (Read-only)
134 * 11 = CPU on same node
136 * - Scratch bit cleared by a cold reset
137 * [ 5: 5] BIOS Reset Detect
138 * - Scratch bit cleared by a cold reset
139 * [ 6: 6] INIT Detect
140 * - Scratch bit cleared by a warm or cold reset not by an INIT
144 /* Enable routing table */
145 print_debug("Enabling routing table for node ");
146 print_debug_hex32(node);
148 val=pci_read_config32(NODE_HT(node), 0x6c);
149 val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
150 pci_write_config32(NODE_HT(node), 0x6c, val);
159 print_debug(" done.\r\n");
162 #if CONFIG_MAX_CPUS > 1
164 static void rename_temp_node(u8 node)
168 print_debug("Renaming current temp node to ");
169 print_debug_hex32(node);
171 val=pci_read_config32(NODE_HT(7), 0x60);
172 val &= (~7); /* clear low bits. */
173 val |= node; /* new node */
174 pci_write_config32(NODE_HT(7), 0x60, val);
176 print_debug(" done.\r\n");
181 static bool check_connection(u8 src, u8 dest, u8 link)
183 /* this function does 2 things:
184 * 1) detect whether the coherent HT link is connected.
185 * 2) verify that the coherent hypertransport link
186 * is established and actually working by reading the
187 * remote node's vendor/device id
197 val=pci_read_config32(NODE_HT(src), 0x98+link);
198 if ( (val&0x17) != 0x03)
202 val=pci_read_config32(NODE_HT(dest),0);
203 if(val != 0x11001022)
209 static void fill_row(u8 node, u8 row, u32 value)
212 print_debug("fill_row: pci_write_config32(");
213 print_debug_hex32(NODE_HT(node));
214 print_debug_char(',');
215 print_debug_hex32(0x40 + (row << 2));
216 print_debug_char(',');
217 print_debug_hex32(value);
218 print_debug(")\r\n");
220 pci_write_config32(NODE_HT(node), 0x40+(row<<2), value);
223 static void setup_row(u8 source, u8 dest, u8 cpus)
226 printk_spew("setting up link from node %d to %d (%d cpus)\r\n",
230 fill_row(source,dest,generate_row(source,dest,cpus));
233 static void setup_temp_row(u8 source, u8 dest, u8 cpus)
236 printk_spew("setting up temp. link from node %d to %d (%d cpus)\r\n",
240 fill_row(source,7,generate_temp_row(source,dest,cpus));
243 static void setup_node(u8 node, u8 cpus)
246 for(row=0; row<cpus; row++)
247 setup_row(node, row, cpus);
250 static void setup_remote_row(u8 source, u8 dest, u8 cpus)
252 fill_row(7, dest, generate_row(source, dest, cpus));
255 static void setup_remote_node(u8 node, u8 cpus)
257 static const uint8_t pci_reg[] = {
258 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
259 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
260 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
261 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
262 0xc4, 0xcc, 0xd4, 0xdc,
263 0xc0, 0xc8, 0xd0, 0xd8,
264 0xe0, 0xe4, 0xe8, 0xec,
269 print_debug("setup_remote_node\r\n");
271 for(row=0; row<cpus; row++)
272 setup_remote_row(node, row, cpus);
274 /* copy the default resource map from node 0 */
275 for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
280 print_debug("copying reg: ");
281 print_debug_hex8(reg);
284 value = pci_read_config32(NODE_MP(0), reg);
285 pci_write_config32(NODE_MP(7), reg, value);
289 print_debug("setup_remote_done\r\n");
295 #if CONFIG_MAX_CPUS > 2
296 static void setup_temp_node(u8 node, u8 cpus)
299 for(row=0; row<cpus; row++)
300 fill_row(7,row,generate_row(node,row,cpus));
304 static u8 setup_uniprocessor(void)
306 print_debug("Enabling UP settings\r\n");
311 #if CONFIG_MAX_CPUS > 1
312 static u8 setup_smp(void)
316 print_debug("Enabling SMP settings\r\n");
319 /* Setup and check a temporary connection to node 1 */
320 setup_temp_row(0,1,cpus);
322 if (!check_connection(0, 7, ACROSS)) { // Link: ACROSS
323 print_debug("No connection to Node 1.\r\n");
324 clear_temp_row(0); /* delete temp connection */
325 setup_uniprocessor(); /* and get up working */
329 /* We found 2 nodes so far */
330 setup_node(0, cpus); /* Node 1 is there. Setup Node 0 correctly */
331 setup_remote_node(1, cpus); /* Setup the routes on the remote node */
332 rename_temp_node(1); /* Rename Node 7 to Node 1 */
333 enable_routing(1); /* Enable routing on Node 1 */
335 clear_temp_row(0); /* delete temporary connection */
337 #if CONFIG_MAX_CPUS > 2
340 /* Setup and check temporary connection from Node 0 to Node 2 */
341 setup_temp_row(0,2,cpus);
343 if (!check_connection(0, 7, UP)) { // Link: UP
344 print_debug("No connection to Node 2.\r\n");
345 clear_temp_row(0); /* delete temp connection */
349 /* We found 3 nodes so far. Now setup a temporary
350 * connection from node 0 to node 3 via node 1
353 setup_temp_row(0,1,cpus); /* temp. link between nodes 0 and 1 */
354 setup_temp_row(1,3,cpus); /* temp. link between nodes 1 and 3 */
356 if (!check_connection(1, 7, UP)) { // Link: UP
357 print_debug("No connection to Node 3.\r\n");
358 clear_temp_row(0); /* delete temp connection */
359 clear_temp_row(1); /* delete temp connection */
363 /* We found 4 nodes so far. Now setup all nodes for 4p */
365 setup_node(0, cpus); /* The first 2 nodes are configured */
366 setup_node(1, cpus); /* already. Just configure them for 4p */
368 setup_temp_row(0,2,cpus);
369 setup_temp_node(2,cpus);
373 setup_temp_row(0,1,cpus);
374 setup_temp_row(1,3,cpus);
375 setup_temp_node(3,cpus);
377 enable_routing(3); /* enable routing on node 3 (temp.) */
385 print_debug_hex32(cpus);
386 print_debug(" nodes initialized.\r\n");
391 #if CONFIG_MAX_CPUS > 1
392 static unsigned detect_mp_capabilities(unsigned cpus)
394 unsigned node, row, mask;
398 print_debug("detect_mp_capabilities: ");
399 print_debug_hex32(cpus);
403 mask=0x06; /* BigMPCap */
405 mask=0x02; /* MPCap */
407 for (node=0; node<cpus; node++) {
408 if ((pci_read_config32(NODE_MC(node), 0xe8) & mask)!=mask)
415 /* one of our cpus is not mp capable */
417 print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
419 for (node=cpus; node>0; node--)
420 for (row=cpus; row>0; row--)
421 fill_row(NODE_HT(node-1), row-1, DEFAULT);
423 return setup_uniprocessor();
428 /* this is a shrunken cpuid. */
430 static unsigned int cpuid(unsigned int op)
434 asm volatile ( "cpuid" : "=a" (ret) : "a" (op));
439 static void coherent_ht_finalize(unsigned cpus)
444 /* set up cpu count and node count and enable Limit
445 * Config Space Range for all available CPUs.
446 * Also clear non coherent hypertransport bus range
447 * registers on Hammer A0 revision.
451 print_debug("coherent_ht_finalize\r\n");
453 rev_a0=((cpuid(1)&0xffff)==0x0f10);
455 for (node=0; node<cpus; node++) {
457 val=pci_read_config32(NODE_HT(node), 0x60);
458 val &= (~0x000F0070);
459 val |= ((cpus-1)<<16)|((cpus-1)<<4);
460 pci_write_config32(NODE_HT(node),0x60,val);
462 val=pci_read_config32(NODE_HT(node), 0x68);
463 val |= 0x0f00c800; // 0x00008000->0f00c800 BY LYH
464 pci_write_config32(NODE_HT(node),0x68,val);
467 pci_write_config32(NODE_HT(node),0x94,0);
468 pci_write_config32(NODE_HT(node),0xb4,0);
469 pci_write_config32(NODE_HT(node),0xd4,0);
473 print_debug("done\r\n");
477 static int setup_coherent_ht_domain(void)
480 int reset_needed = 0;
482 enable_bsp_routing();
484 #if CONFIG_MAX_CPUS == 1
485 cpus=setup_uniprocessor();
488 cpus=detect_mp_capabilities(cpus);
490 coherent_ht_finalize(cpus);
492 /* this should probably go away again. */
493 coherent_ht_mainboard(cpus);