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