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