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