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