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