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