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