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