amd k8 routing table creation dynamically support
[coreboot.git] / src / northbridge / amd / amdk8 / coherent_ht.c
1 /* coherent hypertransport initialization for AMD64 
2  * 
3  * written by Stefan Reinauer <stepan@openbios.org>
4  * (c) 2003-2004 by SuSE Linux AG
5  *
6  * (c) 2004 Tyan Computer
7  *  2004.12 yhlu added support to create support to create routing table dynamically.
8  *          it also support 8 ways too. (8 ways ladder or 8 ways crossbar)      
9  * This code is licensed under GPL.
10  */
11
12 /*
13  * This algorithm assumes a grid configuration as follows:
14  *
15  * nodes :  1    2    4    6    8
16  * org.  :  1x1  2x1  2x2  2x3  2x4
17  *
18  */
19
20 #include <device/pci_def.h>
21 #include <device/pci_ids.h>
22 #include <device/hypertransport_def.h>
23 #include "arch/romcc_io.h"
24 #include "amdk8.h"
25
26 /* when generating a temporary row configuration we
27  * don't want broadcast to be enabled for that node.
28  */
29
30 #define enable_bsp_routing()    enable_routing(0)
31
32 #define NODE_HT(x) PCI_DEV(0,24+x,0)
33 #define NODE_MP(x) PCI_DEV(0,24+x,1)
34 #define NODE_MC(x) PCI_DEV(0,24+x,3)
35
36 #define DEFAULT 0x00010101      /* default row entry */
37
38 typedef uint8_t u8;
39 typedef uint32_t u32;
40 typedef int bool;
41
42 #define TRUE  (-1)
43 #define FALSE (0)
44
45 static u8 link_to_register(int ldt)
46 {
47         /*
48          * [ 0: 3] Request Route
49          *     [0] Route to this node
50          *     [1] Route to Link 0
51          *     [2] Route to Link 1
52          *     [3] Route to Link 2
53          */
54
55         if (ldt&0x08) return 0x40;
56         if (ldt&0x04) return 0x20;
57         if (ldt&0x02) return 0x00;
58         
59         /* we should never get here */
60         print_spew("Unknown Link\n");
61         return 0;
62 }
63
64 static void disable_probes(void)
65 {
66         /* disable read/write/fill probes for uniprocessor setup
67          * they don't make sense if only one cpu is available
68          */
69
70         /* Hypetransport Transaction Control Register 
71          * F0:0x68
72          * [ 0: 0] Disable read byte probe
73          *         0 = Probes issues
74          *         1 = Probes not issued
75          * [ 1: 1] Disable Read Doubleword probe
76          *         0 = Probes issued
77          *         1 = Probes not issued
78          * [ 2: 2] Disable write byte probes
79          *         0 = Probes issued
80          *         1 = Probes not issued
81          * [ 3: 3] Disable Write Doubleword Probes
82          *         0 = Probes issued
83          *         1 = Probes not issued.
84          * [10:10] Disable Fill Probe
85          *         0 = Probes issued for cache fills
86          *         1 = Probes not issued for cache fills.
87          */
88
89         u32 val;
90
91         print_spew("Disabling read/write/fill probes for UP... ");
92
93         val=pci_read_config32(NODE_HT(0), 0x68);
94         val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
95         pci_write_config32(NODE_HT(0), 0x68, val);
96
97         print_spew("done.\r\n");
98
99 }
100
101 static void enable_routing(u8 node)
102 {
103         u32 val;
104
105         /* HT Initialization Control Register
106          * F0:0x6C
107          * [ 0: 0] Routing Table Disable
108          *         0 = Packets are routed according to routing tables
109          *         1 = Packets are routed according to the default link field
110          * [ 1: 1] Request Disable (BSP should clear this)
111          *         0 = Request packets may be generated
112          *         1 = Request packets may not be generated.
113          * [ 3: 2] Default Link (Read-only)
114          *         00 = LDT0
115          *         01 = LDT1
116          *         10 = LDT2
117          *         11 = CPU on same node
118          * [ 4: 4] Cold Reset
119          *         - Scratch bit cleared by a cold reset
120          * [ 5: 5] BIOS Reset Detect
121          *         - Scratch bit cleared by a cold reset
122          * [ 6: 6] INIT Detect
123          *         - Scratch bit cleared by a warm or cold reset not by an INIT
124          *
125          */
126
127         /* Enable routing table */
128         print_spew("Enabling routing table for node ");
129         print_spew_hex8(node);
130
131         val=pci_read_config32(NODE_HT(node), 0x6c);
132         val &= ~((1<<1)|(1<<0));
133         pci_write_config32(NODE_HT(node), 0x6c, val);
134
135         print_spew(" done.\r\n");
136 }
137
138 static void fill_row(u8 node, u8 row, u32 value)
139 {
140         pci_write_config32(NODE_HT(node), 0x40+(row<<2), value);
141 }
142 static u32 get_row(u8 node, u8 row)
143 {
144         return pci_read_config32(NODE_HT(node), 0x40+(row<<2));
145 }
146
147 static int link_connection(u8 src, u8 dest)
148 {
149         /* we generate the needed link information from the rows
150          * by taking the Request Route of the according row.
151          */
152
153         return get_row(src, dest) & 0x0f;
154 }
155
156
157 #if CONFIG_MAX_CPUS > 1
158
159 static void rename_temp_node(u8 node)
160 {
161         uint32_t val;
162
163         print_spew("Renaming current temporary node to ");
164         print_spew_hex8(node);
165
166         val=pci_read_config32(NODE_HT(7), 0x60);
167         val &= (~7);  /* clear low bits. */
168         val |= node;   /* new node        */
169         pci_write_config32(NODE_HT(7), 0x60, val);
170
171         print_spew(" done.\r\n");
172 }
173
174 static bool check_connection(u8 dest)
175 {
176         /* See if we have a valid connection to dest */
177         u32 val;
178
179         /* Verify that the coherent hypertransport link is
180          * established and actually working by reading the
181          * remode node's vendor/device id
182          */
183         val = pci_read_config32(NODE_HT(dest),0);
184         if(val != 0x11001022)
185                 return 0;
186
187         return 1;
188 }
189
190 static unsigned read_freq_cap(device_t dev, unsigned pos)
191 {
192         /* Handle bugs in valid hypertransport frequency reporting */
193         unsigned freq_cap;
194         uint32_t id;
195
196         freq_cap = pci_read_config16(dev, pos);
197         freq_cap &= ~(1 << HT_FREQ_VENDOR); /* Ignore Vendor HT frequencies */
198
199         id = pci_read_config32(dev, 0);
200
201         /* AMD 8131 Errata 48 */
202         if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8131_PCIX << 16))) {
203                 freq_cap &= ~(1 << HT_FREQ_800Mhz);
204         }
205         /* AMD 8151 Errata 23 */
206         if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8151_SYSCTRL << 16))) {
207                 freq_cap &= ~(1 << HT_FREQ_800Mhz);
208         }
209         /* AMD K8 Unsupported 1Ghz? */
210         if (id == (PCI_VENDOR_ID_AMD | (0x1100 << 16))) {
211                 freq_cap &= ~(1 << HT_FREQ_1000Mhz);
212         }
213         return freq_cap;
214 }
215
216 static int optimize_connection(device_t node1, uint8_t link1, device_t node2, uint8_t link2)
217 {
218         static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
219         static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
220         uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
221         uint8_t width_cap1, width_cap2, width_cap, width, old_width, ln_width1, ln_width2;
222         uint8_t freq, old_freq;
223         int needs_reset;
224         /* Set link width and frequency */
225
226         /* Initially assume everything is already optimized and I don't need a reset */
227         needs_reset = 0;
228
229         /* Get the frequency capabilities */
230         freq_cap1 = read_freq_cap(node1, link1 + PCI_HT_CAP_HOST_FREQ_CAP);
231         freq_cap2 = read_freq_cap(node2, link2 + PCI_HT_CAP_HOST_FREQ_CAP);
232
233         /* Calculate the highest possible frequency */
234         freq = log2(freq_cap1 & freq_cap2);
235
236         /* See if I am changing the link freqency */
237         old_freq = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ);
238         needs_reset |= old_freq != freq;
239         old_freq = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ);
240         needs_reset |= old_freq != freq;
241
242         /* Set the Calulcated link frequency */
243         pci_write_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ, freq);
244         pci_write_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ, freq);
245
246         /* Get the width capabilities */
247         width_cap1 = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH);
248         width_cap2 = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH);
249
250         /* Calculate node1's input width */
251         ln_width1 = link_width_to_pow2[width_cap1 & 7];
252         ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
253         if (ln_width1 > ln_width2) {
254                 ln_width1 = ln_width2;
255         }
256         width = pow2_to_link_width[ln_width1];
257         /* Calculate node1's output width */
258         ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
259         ln_width2 = link_width_to_pow2[width_cap2 & 7];
260         if (ln_width1 > ln_width2) {
261                 ln_width1 = ln_width2;
262         }
263         width |= pow2_to_link_width[ln_width1] << 4;
264         
265         /* See if I am changing node1's width */
266         old_width = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1);
267         needs_reset |= old_width != width;
268
269         /* Set node1's widths */
270         pci_write_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1, width);
271
272         /* Calculate node2's width */
273         width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
274
275         /* See if I am changing node2's width */
276         old_width = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1);
277         needs_reset |= old_width != width;
278
279         /* Set node2's widths */
280         pci_write_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1, width);
281
282         return needs_reset;
283 }
284
285 static void setup_row_local(u8 source, u8 row) // source will be 7 when it is for temp use
286 {
287         unsigned linkn;
288         uint32_t val;
289         val = 1;
290         for(linkn = 0; linkn<3; linkn++) { 
291                 unsigned regpos; 
292                 uint32_t reg;
293                 regpos = 0x98 + 0x20 * linkn;
294                 reg = pci_read_config32(NODE_HT(source), regpos);
295                 if ((reg & 0x17) != 3) continue; // it is not conherent or not connected
296                 val |= 1<<(linkn+1); 
297         }
298         val <<= 16;
299         val |= 0x0101;
300         fill_row(source,row, val);
301 }
302
303 static void setup_row_direct(u8 source, u8 dest, u8 linkn)
304 {
305         uint32_t val;
306         val = 1<<16; 
307         val |= 1<<(linkn+1);
308         val |= 1<<(linkn+1+8); //for direct connect response route should equal to request table
309         fill_row(source,dest, val);
310 }
311 #if CONFIG_MAX_CPUS>2
312 static void setup_row_indirect(u8 source, u8 dest, u8 gateway)
313 {
314         //for indirect connection, we need to compute the val from val_s(source, source), and val_g(source, gateway)
315         uint32_t val_s;
316         uint32_t val_g;
317         uint32_t val;
318 #warning "FIXME is it the way to set the RESPONSE TABLE for indirect?"
319         val_s = get_row(source, source);
320         val_g = get_row(source, gateway);
321         
322         val = val_g & 0xff;
323         val_s >>=16;
324         val_s &=0xfe;
325         if(val_s!=val) { // use another connect as response
326                 val_s -= val;
327 #warning "FIXME I don't know how to set BROADCAST TABLE for indirect, 1?"
328                 val |= (1<<16) | (val_s<<8);
329         } else {
330                 val = val_g; // all the same to gateway
331         }
332
333         fill_row(source, dest, val);
334
335 }
336 static void setup_row_indirect_group(const u8 *conn, int num)
337 {
338         int i;
339         for(i=0; i<num; i+=3) {
340                 setup_row_indirect(conn[i*3], conn[i*3+1],conn[i*3+2]);
341         }  
342 }
343 #endif
344
345 static void setup_temp_row(u8 source, u8 dest)
346 {       
347         // copy val from (source, dest) to (source,7)
348         fill_row(source,7,get_row(source,dest));
349 }
350
351 static void clear_temp_row(u8 source)
352 {
353         fill_row(source, 7, DEFAULT);
354 }
355
356 static void setup_remote_row_direct(u8 source, u8 dest, u8 linkn)
357 {
358         uint32_t val;
359         val = 1<<16; 
360         val |= 1<<(linkn+1);
361         val |= 1<<(linkn+1+8); //for direct connect response route should equal to request table
362         fill_row(7,dest, val );
363 }       
364 #if CONFIG_MAX_CPUS>2
365 static void setup_remote_row_indirect(u8 source, u8 dest, u8 gateway)
366 {
367         //for indirect connection, we need to compute the val from val_s(source, source), and val_g(source, gateway)
368         uint32_t val_s;
369         uint32_t val_g;
370         uint32_t val;
371         
372         val_s = get_row(7, source);
373         val_g = get_row(7, gateway);
374         
375         val = val_g & 0xff;
376         val_s >>=16;
377         val_s &=0xfe;
378         if(val_s!=val) { // use another connect as response
379                 val_s -= val;
380                 val |= 1 | (val_s<<8);
381         } else {
382                 val = val_g; // all the same to gateway
383         }
384
385         fill_row(7, dest, val);
386
387 }
388 #endif
389
390 static void setup_remote_node(u8 node)
391 {
392         static const uint8_t pci_reg[] = { 
393                 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c, 
394                 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
395                 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
396                 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
397                 0xc4, 0xcc, 0xd4, 0xdc,
398                 0xc0, 0xc8, 0xd0, 0xd8,
399                 0xe0, 0xe4, 0xe8, 0xec,
400         };
401         int i;
402
403         print_spew("setup_remote_node: ");
404
405         /* copy the default resource map from node 0 */
406         for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
407                 uint32_t value;
408                 uint8_t reg;
409                 reg = pci_reg[i];
410                 value = pci_read_config32(NODE_MP(0), reg);
411                 pci_write_config32(NODE_MP(7), reg, value);
412
413         }
414         print_spew("done\r\n");
415 }
416
417 #endif
418
419 static void setup_uniprocessor(void)
420 {
421         print_spew("Enabling UP settings\r\n");
422         disable_probes();
423 }
424
425 struct setup_smp_result {
426         int nodes;
427         int needs_reset;
428 };
429
430 #if CONFIG_MAX_CPUS > 2
431 static int optimize_connection_group(const u8 *opt_conn, int num) {
432         int needs_reset = 0;
433         int i;
434         for(i=0; i<num; i+=2) {
435                 needs_reset = optimize_connection(
436                         NODE_HT(opt_conn[i*2]), 0x80 + link_to_register(link_connection(opt_conn[i*2],opt_conn[i*2+1])),
437                         NODE_HT(opt_conn[i*2+1]), 0x80 + link_to_register(link_connection(opt_conn[i*2+1],opt_conn[i*2])) );
438         }               
439         return needs_reset;
440 }  
441 #endif
442
443 #if CONFIG_MAX_CPUS > 1
444 static uint8_t get_linkn_first(uint8_t byte)
445 {
446         if(byte & 0x02) { byte = 0; }
447         else if(byte & 0x04) { byte = 1; }
448         else if(byte & 0x08) { byte = 2; }
449         return byte;
450 }
451 static uint8_t get_linkn_last(uint8_t byte)
452 {
453         if(byte & 0x02) { byte &= 0x0f; byte |= 0x00;  }
454         if(byte & 0x04) { byte &= 0x0f; byte |= 0x10;  }
455         if(byte & 0x08) { byte &= 0x0f; byte |= 0x20;  }
456         return byte>>4;
457 }
458 static uint8_t get_linkn_last_count(uint8_t byte)
459 {
460         byte &= 0x3f;
461         if(byte & 0x02) { byte &= 0xcf; byte |= 0x00; byte+=0x40; }
462         if(byte & 0x04) { byte &= 0xcf; byte |= 0x10; byte+=0x40; }
463         if(byte & 0x08) { byte &= 0xcf; byte |= 0x20; byte+=0x40; }
464         return byte>>4;
465 }
466
467 static struct setup_smp_result setup_smp(void)
468 {
469         struct setup_smp_result result;
470         u8 byte;
471         uint32_t val;
472         result.nodes = 2;
473         result.needs_reset = 0;
474
475         print_spew("Enabling SMP settings\r\n");
476
477         setup_row_local(0, 0); // it will update the broadcast RT
478         
479         val = get_row(0,0);
480         byte = (val>>16) & 0xfe;
481         if(byte<0x2) { // no coherent connection so get out.
482                 result.nodes = 1;
483                 return result;
484         }
485
486         /* Setup and check a temporary connection to node 1 */
487         //find out linkn
488
489         byte = get_linkn_first(byte);   
490         setup_row_direct(0,1, byte);
491         setup_temp_row(0, 1);
492         
493         if (!check_connection(7)) {
494                 print_spew("No connection to Node 1.\r\n");
495                 setup_uniprocessor();   /* and get up working     */
496                 result.nodes = 1;
497                 return result;
498         }
499
500         /* We found 2 nodes so far */
501         val = pci_read_config32(NODE_HT(7), 0x6c);
502         byte = (val>2) & 0x3; // get default link on 7 to 0
503         setup_row_local(7,1);
504         setup_remote_row_direct(1, 0, byte);
505
506 #if CONFIG_MAX_CPUS>4    
507         val = get_row(7,1);
508         byte = (val>>16) & 0xfe;
509         byte = get_linkn_last_count(byte);
510         if((byte>>2)==3) { // Oh! we need to treat it as cpu2.
511                 val = get_row(0,0);
512                 byte = (val>>16) & 0xfe;
513                 byte = get_linkn_last(byte);
514                 setup_row_direct(0,1, byte);
515                 setup_temp_row(0, 1);
516         
517                 if (!check_connection(7)) {
518                         print_spew("No connection to Node 1.\r\n");
519                         setup_uniprocessor();   /* and get up working     */
520                         result.nodes = 1;
521                         return result;
522                 }               
523                         
524                 /* We found 2 nodes so far */
525                 val = pci_read_config32(NODE_HT(7), 0x6c);
526                 byte = (val>2) & 0x3; // get default link on 7 to 0
527                 setup_row_local(7,1);
528                 setup_remote_row_direct(1, 0, byte);
529         }
530 #endif
531         
532         setup_remote_node(1);  /* Setup the regs on the remote node */
533         rename_temp_node(1);    /* Rename Node 7 to Node 1  */
534         enable_routing(1);      /* Enable routing on Node 1 */
535 #if 0
536         // don't need and it is done by clear_dead_links
537         clear_temp_row(0);
538 #endif
539         
540         result.needs_reset = optimize_connection(
541                 NODE_HT(0), 0x80 + link_to_register(link_connection(0,1)),
542                 NODE_HT(1), 0x80 + link_to_register(link_connection(1,0)) );
543
544 #if CONFIG_MAX_CPUS > 2
545         result.nodes=4;
546
547         /* Setup and check temporary connection from Node 0 to Node 2 */
548         val = get_row(0,0);
549         byte = ((val>>16) & 0xfe) - link_connection(0,1);
550         byte = get_linkn_last_count(byte);
551         
552         //find out linkn
553         if((byte>>2)==0) { // We should have two coherent for 4p and above
554                 result.nodes = 2;
555                 return result;
556         }
557         byte &= 3; // bit [3,2] is count-1
558         setup_row_direct(0, 2, byte);
559         setup_temp_row(0, 2);
560
561         if (!check_connection(7) ) {
562                 print_spew("No connection to Node 2.\r\n");
563                 result.nodes = 2;
564                 return result;
565         }
566
567         /* We found 3 nodes so far. Now setup a temporary
568          * connection from node 0 to node 3 via node 1
569          */
570         setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
571         /* here should setup_row_direct(1,3) at first, before that we should find the link in cpu 1 to 3*/
572         val = get_row(1,1);
573         byte = ((val>>16) & 0xfe) - link_connection(1,0);
574         byte = get_linkn_first(byte);
575         setup_row_direct(1,3,byte);
576         setup_temp_row(1,3); /* temp. link between nodes 1 and 3 */
577         
578         if (!check_connection(7)) {
579                 print_spew("No connection to Node 3.\r\n");
580                 result.nodes = 2;
581                 return result;
582         }
583
584         /* We found 4 nodes so far. Now setup all nodes for 4p */
585         /* for indirect we will use clockwise routing */
586         static const u8 conn4_1[] = {
587                 0,3,1,
588                 1,2,3,
589         };      
590
591         setup_row_indirect_group(conn4_1, sizeof(conn4_1)/sizeof(conn4_1[0]));
592         
593         setup_temp_row(0,2);
594
595         val = pci_read_config32(NODE_HT(7), 0x6c);
596         byte = (val>2) & 0x3; // get default link on 7 to 0
597
598         setup_row_local(7,2);
599         setup_remote_row_direct(2, 0, byte);
600         setup_remote_node(2);  /* Setup the regs on the remote node */
601
602         rename_temp_node(2);    /* Rename Node 7 to Node 2  */
603         enable_routing(2);      /* Enable routing on Node 2 */
604
605   
606         setup_temp_row(0,1);
607         setup_temp_row(1,3);
608
609         val = pci_read_config32(NODE_HT(7), 0x6c);
610         byte = (val>2) & 0x3; // get default link on 7 to 0
611
612         setup_row_local(7,3);
613         setup_remote_row_direct(3, 1, byte);
614         setup_remote_node(3);  /* Setup the regs on the remote node */
615
616         rename_temp_node(3);
617         enable_routing(3);      /* enable routing on node 3 (temp.) */
618
619         /* We need to init link between 2, and 3 direct link */
620         val = get_row(2,2);
621         byte = ((val>>16) & 0xfe) - link_connection(2,0);
622         byte = get_linkn_last_count(byte);
623 #if CONFIG_MAX_CPUS>4
624         // We need to find out which link it so CPU3
625         // methods is try to access another 7 actully it is cpu4
626         if((byte>>2)==2) { // one to CPU3, one to cpu0, one to CPU4
627                 setup_temp_row(0,2);
628                 setup_row_direct(2, 4, byte);
629                 setup_temp_row(2, 4);
630
631                 if (check_connection(7)) { // so the link is to CPU4
632                         //We need to re compute it
633                         val = get_row(2,2);
634                         byte = (val>>16) & 0xfe;
635                         byte = get_linkn_first(byte);
636                 }
637         }
638 #endif
639         setup_row_direct(2,3, byte & 0x3);
640         
641         val = get_row(3,3);
642         byte = ((val>>16) & 0xfe) - link_connection(3,1);
643         byte = get_linkn_last_count(byte);
644 #if CONFIG_MAX_CPUS>4
645         // We need to find out which link it so CPU2
646         // methods is try to access another 7 actully it is cpu5
647         if((byte>>2)==2) { // one to CPU2, one to cpu1, one to CPU5
648                 setup_temp_row(0,1);
649                 setup_temp_row(1,3);
650                 setup_row_direct(3, 5, byte);
651                 setup_temp_row(3, 5);
652
653                 if (check_connection(7)) { // so the link is to CPU5
654                         //We need to re compute it
655                         val = get_row(3, 3);
656                         byte = (val>>16) & 0xfe;
657                         byte = get_linkn_first(byte);
658                 }
659         }
660 #endif
661         setup_row_direct(3,2, byte & 0x3);
662
663         /* Set indirect connection to 0, and 1  for indirect we will use clockwise routing */
664         static const u8 conn4_2[] = {
665                 2,1,0,
666                 3,0,2,
667         };
668
669         setup_row_indirect_group(conn4_2, sizeof(conn4_2)/sizeof(conn4_2[0]));
670         
671         // We need to do sth to reverse work for setup_temp_row (0,1) (1,3)
672 #if 0
673         // it will be done by clear_dead_links
674         clear_temp_row(0);
675         clear_temp_row(1);
676 #endif
677
678         /* optimize physical connections - by LYH */
679         static const u8 opt_conn4[] = {
680                 0,2,
681                 1,3,
682                 2,3,
683         };
684
685         result.needs_reset = optimize_connection_group(opt_conn4, sizeof(opt_conn4)/sizeof(opt_conn4[0]));
686
687 #endif /* CONFIG_MAX_CPUS > 2 */
688
689 #if CONFIG_MAX_CPUS > 4
690         result.nodes=6;
691
692         /* Setup and check temporary connection from Node 0 to Node 4 via 2 */
693         val = get_row(2,2);
694         byte = ((val>>16) & 0xfe) - link_connection(2,3) - link_connection(2,0);
695         byte = get_linkn_last_count(byte);
696         
697         //find out linkn
698         if((byte>>2)==0) { // We should have two coherent for 4p and above
699                 result.nodes = 4;
700                 return result;
701         }
702         byte &= 3; // bit [3,2] is count-1
703         setup_row_direct(2, 4, byte);
704         
705         /* Setup and check temporary connection from Node 0 to Node 4  through 2*/
706         for(byte=0; byte<4; byte+=2) {
707                 setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
708         }
709         
710         if (!check_connection(7) ) {
711                 print_spew("No connection to Node 4.\r\n");
712                 result.nodes = 4;
713                 return result; 
714         }       
715         
716         /* Setup and check temporary connection from Node 0 to Node 5  through 1, 3*/
717
718         val = get_row(3,3);
719         byte = ((val>>16) & 0xfe) - link_connection(3,2) - link_connection(3,1);
720         byte = get_linkn_last_count(byte);
721         //find out linkn
722         if((byte>>2)==0) { // We should have two coherent for 4p and above
723                 result.nodes = 4;
724                 return result;
725         }
726
727         byte &= 3; // bit [3,2] is count-1
728         setup_row_direct(3, 5, byte);
729
730         setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
731         for(byte=0; byte<4; byte+=2) {
732                 setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */
733         }
734         
735         if (!check_connection(7)) {
736                 print_spew("No connection to Node 5.\r\n");
737                 result.nodes = 4;
738                 return result; 
739         }       
740         
741         /* We found 6 nodes so far. Now setup all nodes for 6p */
742         static const u8 conn6_1[] = {
743                 0, 4, 2,
744                 0, 5, 1,
745                 1, 4, 3,
746                 1, 5, 3,
747                 2, 5, 3,
748 #if !CROSS_BAR_47_56
749                 3, 4, 5,
750 #else
751                 3, 4, 2,
752 #endif
753         };
754
755         setup_row_indirect_group(conn6_1, sizeof(conn6_1)/sizeof(conn6_1[0]));
756
757         
758         for(byte=0; byte<4; byte+=2) {
759                 setup_temp_row(byte,byte+2);
760         }
761         val = pci_read_config32(NODE_HT(7), 0x6c);
762         byte = (val>2) & 0x3; // get default link on 7 to 0
763         
764         setup_row_local(7,4);
765         setup_remote_row_direct(4, 2, byte);
766         setup_remote_node(4);  /* Setup the regs on the remote node */
767         rename_temp_node(4);
768         enable_routing(4);
769
770         setup_temp_row(0,1);
771         for(byte=0; byte<4; byte+=2) {
772                 setup_temp_row(byte+1,byte+3);
773         }
774
775         val = pci_read_config32(NODE_HT(7), 0x6c);
776         byte = (val>2) & 0x3; // get default link on 7 to 0
777         setup_row_local(7,5);
778         setup_remote_row_direct(5, 3, byte);
779         setup_remote_node(5);  /* Setup the regs on the remote node */
780
781         rename_temp_node(5);
782         enable_routing(5);      /* enable routing on node 5 (temp.) */
783
784 #if !CROSS_BAR_47_56
785         /* We need to init link between 4, and 5 direct link */
786         val = get_row(4,4);
787         byte = ((val>>16) & 0xfe) - link_connection(4,2);
788         byte = get_linkn_last_count(byte);
789 #if CONFIG_MAX_CPUS>4
790         // We need to find out which link it so CPU5
791         // methods is try to access another 7 actully it is cpu6
792         if((byte>>2)==2) { // one to CPU5, one to cpu2, one to CPU6
793                 setup_temp_row(0,2);
794                 setup_temp_row(2,4);
795                 setup_row_direct(4, 6, byte);
796                 setup_temp_row(4, 6);
797         
798                 if (check_connection(7)) { // so the link is to CPU4
799                         //We need to re compute it
800                         val = get_row(4,4);
801                         byte = (val>>16) & 0xfe;
802                         byte = get_linkn_first(byte);
803                 }
804         }
805 #endif
806         setup_row_direct(4,5, byte & 0x3);
807
808         val = get_row(5,5);
809         byte = ((val>>16) & 0xfe) - link_connection(5,3);
810         byte = get_linkn_last_count(byte);
811 #if CONFIG_MAX_CPUS>4
812         // We need to find out which link it so CPU4
813         // methods is try to access another 7 actully it is cpu7
814         if((byte>>2)==2) { // one to CPU4, one to cpu3, one to CPU7
815                 setup_temp_row(0,1);
816                 setup_temp_row(1,3);
817                 setup_temp_row(3,7);
818                 setup_row_direct(5, 7, byte);
819                 setup_temp_row(5, 7);
820
821                 if (check_connection(7)) { // so the link is to CPU5
822                         //We need to re compute it
823                         val = get_row(5, 5);
824                         byte = (val>>16) & 0xfe;
825                         byte = get_linkn_first(byte);
826                 }
827         }
828 #endif
829         setup_row_direct(5,4, byte & 0x3);
830 #endif // !CROSS_BAR_47_56
831
832         /* Set indirect connection to 0, to 3  for indirect we will use clockwise routing */
833         static const u8 conn6_2[] = {
834 #if !CROSS_BAR_47_56
835                 4, 0, 2,
836                 4, 1, 2,
837                 4, 3, 2,
838                 5, 0, 4,
839                 5, 2, 4,
840                 5, 1, 3,
841 #else
842
843                 4, 0, 2,
844                 4, 1, 2,
845                 4, 3, 2,
846                 4, 5, 2,
847                 5, 0, 3,
848                 5, 2, 3,
849                 5, 1, 3,
850                 5, 4, 3,
851 #endif
852         };      
853         
854         setup_row_indirect_group(conn6_2, sizeof(conn6_2)/sizeof(conn6_2[0]));
855 #if 0
856         // We need to do sth about reverse about setup_temp_row (0,1), (2,4), (1, 3), (3,5)
857         // It will be done by clear_dead_links
858         for(byte=0; byte<4; byte++) {
859                 clear_temp_row(byte);
860         }
861 #endif
862         
863         /* optimize physical connections - by LYH */
864         static const uint8_t opt_conn6[] ={
865                 2, 4,
866                 3, 5,
867 #if !CROSS_BAR_47_56
868                 4, 5,
869 #endif
870         }; 
871         result.needs_reset = optimize_connection_group(opt_conn6, sizeof(opt_conn6)/sizeof(opt_conn6[0]));
872
873
874 #endif /* CONFIG_MAX_CPUS > 4 */
875
876 #if CONFIG_MAX_CPUS >6 
877         result.nodes=8;
878
879         /* Setup and check temporary connection from Node 0 to Node 6 via 2 and 4 to 7 */
880         val = get_row(4,4);
881 #if !CROSS_BAR_47_56
882         byte = ((val>>16) & 0xfe) - link_connection(4,5) - link_connection(4,2);
883 #else
884         byte = ((val>>16) & 0xfe) - link_connection(4,2);
885 #endif
886         byte = get_linkn_last_count(byte); // Max link to 6
887         if((byte>>2)==0) { // We should have two coherent for 8p and above
888                 result.nodes = 6;
889                 return result;
890         }
891         byte &= 3; // bit [3,2] is count-1
892         setup_row_direct(4, 6, byte);
893
894         /* Setup and check temporary connection from Node 0 to Node 6  through 2, and 4*/
895         for(byte=0; byte<6; byte+=2) {
896                 setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
897         }
898
899         if (!check_connection(7) ) {
900                 print_spew("No connection to Node 6.\r\n");
901                 result.nodes = 6;
902                 return result;
903         }
904 #if !CROSS_BAR_47_56
905         /* Setup and check temporary connection from Node 0 to Node 5  through 1, 3, 5*/
906
907         val = get_row(5,5);
908         byte = ((val>>16) & 0xfe) - link_connection(5,4) - link_connection(5,3);
909         byte = get_linkn_first(byte);
910         setup_row_direct(5, 7, byte);
911
912         setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
913         for(byte=0; byte<6; byte+=2) {
914                 setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */
915         }
916 #else
917         val = get_row(4,4);
918         byte = ((val>>16) & 0xfe) - link_connection(4,2) ;
919         byte = get_linkn_first(byte); // min link to 7
920         setup_row_direct(4, 7, byte);
921
922         /* Setup and check temporary connection from Node 0 to Node 7 through 2, and 4*/
923         for(byte=0; byte<4; byte+=2) {
924                 setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
925         }
926         setup_temp_row(4, 7);
927
928 #endif
929
930         if (!check_connection(7)) {
931                 print_spew("No connection to Node 7.\r\n");
932                 result.nodes = 6;
933                 return result;
934         }
935
936
937         /* We found 8 nodes so far. Now setup all nodes for 8p */
938         static const u8 conn8_1[] = {
939 #if !CROSS_BAR_47_56
940                 0, 6, 2,
941 //              0, 7, 1,
942                 1, 6, 3,
943 //              1, 7, 3,
944                 2, 6, 4,
945 //              2, 7, 3,
946                 3, 6, 5,
947 //              3, 7, 5,
948 //              4, 7, 5,
949 #else
950                 0, 6, 2,
951 //              0, 7, 2,
952                 1, 6, 3,
953 //                1, 7, 3,
954                 2, 6, 4,
955 //                2, 7, 4,
956                 3, 6, 5,
957 //                3, 7, 5,
958 #endif
959         };
960
961         setup_row_indirect_group(conn8_1,sizeof(conn8_1)/sizeof(conn8_1[0]));
962
963         for(byte=0; byte<6; byte+=2) {
964                 setup_temp_row(byte,byte+2);
965         }
966         val = pci_read_config32(NODE_HT(7), 0x6c);
967         byte = (val>2) & 0x3; // get default link on 7 to 0
968
969         setup_row_local(7,6);
970         setup_remote_row_direct(6, 4, byte);
971         setup_remote_node(6);  /* Setup the regs on the remote node */
972         rename_temp_node(6);
973         enable_routing(6);
974
975 #if !CROSS_BAR_47_56
976         setup_temp_row(0,1);
977         for(byte=0; byte<6; byte+=2) {
978                 setup_temp_row(byte+1,byte+3);
979         }
980
981         val = pci_read_config32(NODE_HT(7), 0x6c);
982         byte = (val>2) & 0x3; // get default link on 7 to 0
983         setup_row_local(7,7);
984         setup_remote_row_direct(7, 5, byte);
985
986 #else
987         for(byte=0; byte<4; byte+=2) {
988                 setup_temp_row(byte,byte+2);
989         }
990         setup_temp_row(4,7);
991         val = pci_read_config32(NODE_HT(7), 0x6c);
992         byte = (val>2) & 0x3; // get default link on 7 to 0
993
994         setup_row_local(7,7);
995         setup_remote_row_direct(7, 4, byte);
996         // till now 4-7, 7-4 done.
997 #endif
998         setup_remote_node(7);  /* Setup the regs on the remote node */
999 //        rename_temp_node(7);
1000         enable_routing(7);      /* enable routing on node 5 (temp.) */
1001
1002 #if CROSS_BAR_47_56
1003         //here init 5, 6 and 5, 7
1004         /* Setup and check temporary connection from Node 0 to Node 5  through 1, 3, 5*/
1005         
1006         val = get_row(5,5);
1007         byte = ((val>>16) & 0xfe) - link_connection(5,3);
1008         byte = get_linkn_last(byte);
1009         setup_row_direct(5, 7, byte);
1010         
1011         setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
1012         for(byte=0; byte<6; byte+=2) {
1013                 setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */
1014         }
1015
1016         if (!check_connection(7)) {
1017                 // We need to recompute link to 7
1018                 val = get_row(5,5);
1019                 byte = ((val>>16) & 0xfe) - link_connection(5,3);
1020                 byte = get_linkn_first(byte);
1021
1022                 byte &= 3; // bit [3,2] is count-1
1023                 setup_row_direct(5, 7, byte);
1024 #if 0
1025                 setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
1026                 for(byte=0; byte<6; byte+=2) {
1027                         setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */
1028                 }
1029 #else
1030                 setup_temp_row(5,7);
1031 #endif
1032                 check_connection(7);
1033         }
1034         val = pci_read_config32(NODE_HT(7), 0x6c);
1035         byte = (val>2) & 0x3; // get default link on 7 to 0
1036 //        setup_row_local(7,7);
1037         setup_remote_row_direct(7, 5, byte);
1038         //Till now 57, 75 done
1039         
1040         //init 5,6
1041         val = get_row(5,5);
1042         byte = ((val>>16) & 0xfe) - link_connection(5,3) - link_connection(5,7);
1043         byte = get_linkn_first(byte);
1044         setup_row_direct(5, 6, byte);
1045
1046
1047         val = get_row(6,6);
1048         byte = ((val>>16) & 0xfe) - link_connection(6,4);
1049         byte = get_linkn_last(byte);
1050         setup_row_direct(6, 7, byte);
1051
1052         for(byte=0; byte<6; byte+=2) {
1053                 setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
1054         }
1055         setup_temp_row(6,7);
1056
1057         if (!check_connection(7)) {
1058                 // We need to recompute link to 7
1059                 val = get_row(6,6);
1060                 byte = ((val>>16) & 0xfe) - link_connection(6,4);
1061                 byte = get_linkn_first(byte);
1062
1063                 setup_row_direct(6, 7, byte);
1064 #if 0
1065                 for(byte=0; byte<6; byte+=2) {
1066                         setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
1067                 }
1068 #endif
1069                 setup_temp_row(6,7);
1070                 check_connection(7);
1071         }
1072         val = pci_read_config32(NODE_HT(7), 0x6c);
1073         byte = (val>2) & 0x3; // get default link on 7 to 0
1074 //        setup_row_local(7,7);
1075         setup_remote_row_direct(7, 6, byte);
1076         //Till now 67, 76 done
1077
1078         //init 6,5
1079         val = get_row(6,6);
1080         byte = ((val>>16) & 0xfe) - link_connection(6,4) - link_connection(6,7);
1081         byte = get_linkn_first(byte);
1082         setup_row_direct(6, 5, byte);
1083
1084 #endif
1085
1086 #if !CROSS_BAR_47_56
1087         /* We need to init link between 6, and 7 direct link */
1088         val = get_row(6,6);
1089         byte = ((val>>16) & 0xfe) - link_connection(6,4);
1090         byte = get_linkn_first(byte);
1091         setup_row_direct(6,7, byte & 0x3);
1092
1093         val = get_row(7,7);
1094         byte = ((val>>16) & 0xfe) - link_connection(7,5);
1095         byte = get_linkn_first(byte);
1096         setup_row_direct(7,6, byte & 0x3);
1097 #endif
1098
1099         /* Set indirect connection to 0, to 3  for indirect we will use clockwise routing */
1100         static const u8 conn8_2[] = {
1101 #if !CROSS_BAR_47_56
1102                 0, 7, 1,  // restore it
1103                 1, 7, 3,
1104                 2, 7, 3,
1105                 3, 7, 5,
1106                 4, 7, 5,
1107
1108                 6, 0, 4,
1109                 6, 1, 4,
1110                 6, 2, 4,
1111                 6, 3, 4,
1112                 6, 5, 4,
1113                 7, 0, 6,
1114                 7, 1, 5,
1115                 7, 2, 6,
1116                 7, 3, 5,
1117                 7, 4, 6,
1118 #else
1119                 0, 7, 2,  // restore it
1120                 1, 7, 3,
1121                 2, 7, 4,
1122                 3, 7, 5,
1123                 
1124                 6, 0, 4,
1125                 6, 1, 4,
1126                 6, 2, 4,
1127                 6, 3, 4,
1128                 7, 0, 4,
1129                 7, 1, 5,
1130                 7, 2, 4,
1131                 7, 3, 5,
1132                 4, 5, 7,
1133                 5, 4, 6,
1134 #endif
1135         };
1136
1137         setup_row_indirect_group(conn8_2, sizeof(conn8_2)/sizeof(conn8_2[0]));
1138
1139         static const uint8_t opt_conn8[] ={
1140                 4, 6,
1141 #if CROSS_BAR_47_56
1142                 4, 7,
1143                 5, 6,
1144 #endif
1145                 5, 7,
1146                 6, 7,
1147         };
1148         /* optimize physical connections - by LYH */
1149         result.needs_reset = optimize_connection_group(opt_conn8, sizeof(opt_conn6)/sizeof(opt_conn8[0]));
1150
1151 #endif /* CONFIG_MAX_CPUS > 6 */
1152
1153         print_debug_hex8(result.nodes);
1154         print_debug(" nodes initialized.\r\n");
1155         return result;
1156 }
1157 #endif
1158
1159 static unsigned verify_mp_capabilities(unsigned nodes)
1160 {
1161         unsigned node, row, mask;
1162         bool mp_cap=TRUE;
1163
1164         if (nodes > 2) {
1165                 mask=0x06;      /* BigMPCap */
1166         } else if (nodes == 2) {
1167                 mask=0x02;      /* MPCap    */
1168         } else {
1169                 mask=0x00;      /* Non SMP */
1170         }
1171
1172         for (node=0; node<nodes; node++) {
1173                 if ((pci_read_config32(NODE_MC(node), 0xe8) & mask) != mask) {
1174                         mp_cap = FALSE;
1175                 }
1176         }
1177
1178         if (mp_cap) {
1179                 return nodes;
1180         }
1181
1182         /* one of our nodes is not mp capable */
1183
1184         print_err("One of the CPUs is not MP capable. Going back to UP\r\n");
1185         return 1;
1186 }
1187
1188 static void clear_dead_routes(unsigned nodes)
1189 {
1190         int last_row;
1191         int node, row;
1192 #if CONFIG_MAX_CPUS>6
1193         if(nodes==8) return;// don't touch (7,7)
1194 #endif
1195         last_row = nodes;
1196         if (nodes == 1) {
1197                 last_row = 0;
1198         }
1199         for(node = 7; node >= 0; node--) {
1200                 for(row = 7; row >= last_row; row--) {
1201                         fill_row(node, row, DEFAULT);
1202                 }
1203         }
1204 }
1205
1206 static void coherent_ht_finalize(unsigned nodes)
1207 {
1208         unsigned node;
1209         bool rev_a0;
1210         
1211         /* set up cpu count and node count and enable Limit
1212          * Config Space Range for all available CPUs.
1213          * Also clear non coherent hypertransport bus range
1214          * registers on Hammer A0 revision.
1215          */
1216
1217         print_spew("coherent_ht_finalize\r\n");
1218         rev_a0 = is_cpu_rev_a0();
1219         for (node = 0; node < nodes; node++) {
1220                 device_t dev;
1221                 uint32_t val;
1222                 dev = NODE_HT(node);
1223
1224                 /* Set the Total CPU and Node count in the system */
1225                 val = pci_read_config32(dev, 0x60);
1226                 val &= (~0x000F0070);
1227                 val |= ((nodes-1)<<16)|((nodes-1)<<4);
1228                 pci_write_config32(dev, 0x60, val);
1229
1230                 /* Only respond to real cpu pci configuration cycles
1231                  * and optimize the HT settings 
1232                  */
1233                 val=pci_read_config32(dev, 0x68);
1234                 val &= ~((HTTC_BUF_REL_PRI_MASK << HTTC_BUF_REL_PRI_SHIFT) |
1235                         (HTTC_MED_PRI_BYP_CNT_MASK << HTTC_MED_PRI_BYP_CNT_SHIFT) |
1236                         (HTTC_HI_PRI_BYP_CNT_MASK << HTTC_HI_PRI_BYP_CNT_SHIFT));
1237                 val |= HTTC_LIMIT_CLDT_CFG | 
1238                         (HTTC_BUF_REL_PRI_8 << HTTC_BUF_REL_PRI_SHIFT) |
1239                         HTTC_RSP_PASS_PW |
1240                         (3 << HTTC_MED_PRI_BYP_CNT_SHIFT) |
1241                         (3 << HTTC_HI_PRI_BYP_CNT_SHIFT);
1242                 pci_write_config32(dev, 0x68, val);
1243
1244                 if (rev_a0) {
1245                         print_spew("shit it is an old cup\n");
1246                         pci_write_config32(dev, 0x94, 0);
1247                         pci_write_config32(dev, 0xb4, 0);
1248                         pci_write_config32(dev, 0xd4, 0);
1249                 }
1250         }
1251
1252         print_spew("done\r\n");
1253 }
1254
1255 static int apply_cpu_errata_fixes(unsigned nodes, int needs_reset)
1256 {
1257         unsigned node;
1258         for(node = 0; node < nodes; node++) {
1259                 device_t dev;
1260                 uint32_t cmd;
1261                 dev = NODE_MC(node);
1262                 if (is_cpu_pre_c0()) {
1263
1264                         /* Errata 66
1265                          * Limit the number of downstream posted requests to 1 
1266                          */
1267                         cmd = pci_read_config32(dev, 0x70);
1268                         if ((cmd & (3 << 0)) != 2) {
1269                                 cmd &= ~(3<<0);
1270                                 cmd |= (2<<0);
1271                                 pci_write_config32(dev, 0x70, cmd );
1272                                 needs_reset = 1;
1273                         }
1274                         cmd = pci_read_config32(dev, 0x7c);
1275                         if ((cmd & (3 << 4)) != 0) {
1276                                 cmd &= ~(3<<4);
1277                                 cmd |= (0<<4);
1278                                 pci_write_config32(dev, 0x7c, cmd );
1279                                 needs_reset = 1;
1280                         }
1281                         /* Clock Power/Timing Low */
1282                         cmd = pci_read_config32(dev, 0xd4);
1283                         if (cmd != 0x000D0001) {
1284                                 cmd = 0x000D0001;
1285                                 pci_write_config32(dev, 0xd4, cmd);
1286                                 needs_reset = 1; /* Needed? */
1287                         }
1288
1289                 }
1290                 else {
1291                         uint32_t cmd_ref;
1292                         /* Errata 98 
1293                          * Set Clk Ramp Hystersis to 7
1294                          * Clock Power/Timing Low
1295                          */
1296                         cmd_ref = 0x04e20707; /* Registered */
1297                         cmd = pci_read_config32(dev, 0xd4);
1298                         if(cmd != cmd_ref) {
1299                                 pci_write_config32(dev, 0xd4, cmd_ref );
1300                                 needs_reset = 1; /* Needed? */
1301                         }
1302                 }
1303         }
1304         return needs_reset;
1305 }
1306
1307 static int optimize_link_read_pointers(unsigned nodes, int needs_reset)
1308 {
1309         unsigned node;
1310         for(node = 0; node < nodes; node = node + 1) {
1311                 device_t f0_dev, f3_dev;
1312                 uint32_t cmd_ref, cmd;
1313                 int link;
1314                 f0_dev = NODE_HT(node);
1315                 f3_dev = NODE_MC(node);
1316                 cmd_ref = cmd = pci_read_config32(f3_dev, 0xdc);
1317                 for(link = 0; link < 3; link = link + 1) {
1318                         uint32_t link_type;
1319                         unsigned reg;
1320                         /* This works on an Athlon64 because unimplemented links return 0 */
1321                         reg = 0x98 + (link * 0x20);
1322                         link_type = pci_read_config32(f0_dev, reg);
1323                         if (link_type & LinkConnected) {
1324                                 cmd &= 0xff << (link *8);
1325                                 /* FIXME this assumes the device on the other
1326                                  * side is an AMD device 
1327                                  */
1328                                 cmd |= 0x25 << (link *8);
1329                         }
1330                 }
1331                 if (cmd != cmd_ref) {
1332                         pci_write_config32(f3_dev, 0xdc, cmd);
1333                         needs_reset = 1;
1334                 }
1335         }
1336         return needs_reset;
1337 }
1338
1339 static int setup_coherent_ht_domain(void)
1340 {
1341         struct setup_smp_result result;
1342         result.nodes = 1;
1343         result.needs_reset = 0;
1344
1345         enable_bsp_routing();
1346
1347 #if CONFIG_MAX_CPUS > 1
1348         result = setup_smp();
1349 #endif
1350         result.nodes = verify_mp_capabilities(result.nodes);
1351         clear_dead_routes(result.nodes);
1352         if (result.nodes == 1) {
1353                 setup_uniprocessor();
1354         } 
1355         coherent_ht_finalize(result.nodes);
1356         result.needs_reset = apply_cpu_errata_fixes(result.nodes, result.needs_reset);
1357         result.needs_reset = optimize_link_read_pointers(result.nodes, result.needs_reset);
1358         return result.needs_reset;
1359 }