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));
102 /* print_debug("applicaton cpu apic_id: ");
103 print_debug_hex32(apic_id);
106 if(apic_id!=0) { //AP apic_id == node_id ??
107 // set the ColdResetbit to notify BSP that AP is stopped
108 reg = pci_read_config32(NODE_HT(apic_id), 0x6C);
110 pci_write_config32(NODE_HT(apic_id), 0x6C, reg);
116 static void enable_routing(u8 node)
120 /* HT Initialization Control Register
122 * [ 0: 0] Routing Table Disable
123 * 0 = Packets are routed according to routing tables
124 * 1 = Packets are routed according to the default link field
125 * [ 1: 1] Request Disable (BSP should clear this)
126 * 0 = Request packets may be generated
127 * 1 = Request packets may not be generated.
128 * [ 3: 2] Default Link (Read-only)
132 * 11 = CPU on same node
134 * - Scratch bit cleared by a cold reset
135 * [ 5: 5] BIOS Reset Detect
136 * - Scratch bit cleared by a cold reset
137 * [ 6: 6] INIT Detect
138 * - Scratch bit cleared by a warm or cold reset not by an INIT
142 /* Enable routing table */
143 print_debug("Enabling routing table for node ");
144 print_debug_hex32(node);
146 val=pci_read_config32(NODE_HT(node), 0x6c);
147 val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
148 pci_write_config32(NODE_HT(node), 0x6c, val);
157 print_debug(" done.\r\n");
160 #if CONFIG_MAX_CPUS > 1
162 static void rename_temp_node(u8 node)
166 print_debug("Renaming current temp node to ");
167 print_debug_hex32(node);
169 val=pci_read_config32(NODE_HT(7), 0x60);
170 val &= (~7); /* clear low bits. */
171 val |= node; /* new node */
172 pci_write_config32(NODE_HT(7), 0x60, val);
174 print_debug(" done.\r\n");
179 static bool check_connection(u8 src, u8 dest, u8 link)
181 /* this function does 2 things:
182 * 1) detect whether the coherent HT link is connected.
183 * 2) verify that the coherent hypertransport link
184 * is established and actually working by reading the
185 * remote node's vendor/device id
195 val=pci_read_config32(NODE_HT(src), 0x98+link);
196 if ( (val&0x17) != 0x03)
200 val=pci_read_config32(NODE_HT(dest),0);
201 if(val != 0x11001022)
207 static void fill_row(u8 node, u8 row, u32 value)
210 print_debug("fill_row: pci_write_config32(");
211 print_debug_hex32(NODE_HT(node));
212 print_debug_char(',');
213 print_debug_hex32(0x40 + (row << 2));
214 print_debug_char(',');
215 print_debug_hex32(value);
216 print_debug(")\r\n");
218 pci_write_config32(NODE_HT(node), 0x40+(row<<2), value);
221 static void setup_row(u8 source, u8 dest, u8 cpus)
224 printk_spew("setting up link from node %d to %d (%d cpus)\r\n",
228 fill_row(source,dest,generate_row(source,dest,cpus));
231 static void setup_temp_row(u8 source, u8 dest, u8 cpus)
234 printk_spew("setting up temp. link from node %d to %d (%d cpus)\r\n",
238 fill_row(source,7,generate_temp_row(source,dest,cpus));
241 static void setup_node(u8 node, u8 cpus)
244 for(row=0; row<cpus; row++)
245 setup_row(node, row, cpus);
248 static void setup_remote_row(u8 source, u8 dest, u8 cpus)
250 fill_row(7, dest, generate_row(source, dest, cpus));
253 static void setup_remote_node(u8 node, u8 cpus)
255 static const uint8_t pci_reg[] = {
256 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
257 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
258 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
259 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
260 0xc4, 0xcc, 0xd4, 0xdc,
261 0xc0, 0xc8, 0xd0, 0xd8,
262 0xe0, 0xe4, 0xe8, 0xec,
267 print_debug("setup_remote_node\r\n");
269 for(row=0; row<cpus; row++)
270 setup_remote_row(node, row, cpus);
272 /* copy the default resource map from node 0 */
273 for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
278 print_debug("copying reg: ");
279 print_debug_hex8(reg);
282 value = pci_read_config32(NODE_MP(0), reg);
283 pci_write_config32(NODE_MP(7), reg, value);
287 print_debug("setup_remote_done\r\n");
293 #if CONFIG_MAX_CPUS > 2
294 static void setup_temp_node(u8 node, u8 cpus)
297 for(row=0; row<cpus; row++)
298 fill_row(7,row,generate_row(node,row,cpus));
302 static u8 setup_uniprocessor(void)
304 print_debug("Enabling UP settings\r\n");
309 #if CONFIG_MAX_CPUS > 1
310 static u8 setup_smp(void)
314 print_debug("Enabling SMP settings\r\n");
317 /* Setup and check a temporary connection to node 1 */
318 setup_temp_row(0,1,cpus);
320 if (!check_connection(0, 7, ACROSS)) { // Link: ACROSS
321 print_debug("No connection to Node 1.\r\n");
322 clear_temp_row(0); /* delete temp connection */
323 setup_uniprocessor(); /* and get up working */
327 /* We found 2 nodes so far */
328 setup_node(0, cpus); /* Node 1 is there. Setup Node 0 correctly */
329 setup_remote_node(1, cpus); /* Setup the routes on the remote node */
330 rename_temp_node(1); /* Rename Node 7 to Node 1 */
331 enable_routing(1); /* Enable routing on Node 1 */
333 clear_temp_row(0); /* delete temporary connection */
335 #if CONFIG_MAX_CPUS > 2
338 /* Setup and check temporary connection from Node 0 to Node 2 */
339 setup_temp_row(0,2,cpus);
341 if (!check_connection(0, 7, UP)) { // Link: UP
342 print_debug("No connection to Node 2.\r\n");
343 clear_temp_row(0); /* delete temp connection */
347 /* We found 3 nodes so far. Now setup a temporary
348 * connection from node 0 to node 3 via node 1
351 setup_temp_row(0,1,cpus); /* temp. link between nodes 0 and 1 */
352 setup_temp_row(1,3,cpus); /* temp. link between nodes 1 and 3 */
354 if (!check_connection(1, 7, UP)) { // Link: UP
355 print_debug("No connection to Node 3.\r\n");
356 clear_temp_row(0); /* delete temp connection */
357 clear_temp_row(1); /* delete temp connection */
361 /* We found 4 nodes so far. Now setup all nodes for 4p */
363 setup_node(0, cpus); /* The first 2 nodes are configured */
364 setup_node(1, cpus); /* already. Just configure them for 4p */
366 setup_temp_row(0,2,cpus);
367 setup_temp_node(2,cpus);
371 setup_temp_row(0,1,cpus);
372 setup_temp_row(1,3,cpus);
373 setup_temp_node(3,cpus);
375 enable_routing(3); /* enable routing on node 3 (temp.) */
383 print_debug_hex32(cpus);
384 print_debug(" nodes initialized.\r\n");
389 #if CONFIG_MAX_CPUS > 1
390 static unsigned detect_mp_capabilities(unsigned cpus)
392 unsigned node, row, mask;
396 print_debug("detect_mp_capabilities: ");
397 print_debug_hex32(cpus);
401 mask=0x06; /* BigMPCap */
403 mask=0x02; /* MPCap */
405 for (node=0; node<cpus; node++) {
406 if ((pci_read_config32(NODE_MC(node), 0xe8) & mask)!=mask)
413 /* one of our cpus is not mp capable */
415 print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
417 for (node=cpus; node>0; node--)
418 for (row=cpus; row>0; row--)
419 fill_row(NODE_HT(node-1), row-1, DEFAULT);
421 return setup_uniprocessor();
426 /* this is a shrunken cpuid. */
428 static unsigned int cpuid(unsigned int op)
432 asm volatile ( "cpuid" : "=a" (ret) : "a" (op));
437 static void coherent_ht_finalize(unsigned cpus)
442 /* set up cpu count and node count and enable Limit
443 * Config Space Range for all available CPUs.
444 * Also clear non coherent hypertransport bus range
445 * registers on Hammer A0 revision.
449 print_debug("coherent_ht_finalize\r\n");
451 rev_a0=((cpuid(1)&0xffff)==0x0f10);
453 for (node=0; node<cpus; node++) {
455 val=pci_read_config32(NODE_HT(node), 0x60);
456 val &= (~0x000F0070);
457 val |= ((cpus-1)<<16)|((cpus-1)<<4);
458 pci_write_config32(NODE_HT(node),0x60,val);
460 val=pci_read_config32(NODE_HT(node), 0x68);
461 val |= 0x0f00c800; // 0x00008000->0f00c800 BY LYH
462 pci_write_config32(NODE_HT(node),0x68,val);
465 pci_write_config32(NODE_HT(node),0x94,0);
466 pci_write_config32(NODE_HT(node),0xb4,0);
467 pci_write_config32(NODE_HT(node),0xd4,0);
471 print_debug("done\r\n");
475 static int setup_coherent_ht_domain(void)
478 int reset_needed = 0;
480 enable_bsp_routing();
482 #if CONFIG_MAX_CPUS == 1
483 cpus=setup_uniprocessor();
486 cpus=detect_mp_capabilities(cpus);
488 coherent_ht_finalize(cpus);
490 /* this should probably go away again. */
491 coherent_ht_mainboard(cpus);