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