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