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