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