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