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