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