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