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