8 ways support changes
[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 support to create routing table dynamically.
8  *          it also support 8 ways too. (8 ways ladder or 8 ways crossbar)      
9  * This code is licensed under GPL.
10  */
11
12 /*
13  * This algorithm assumes a grid configuration as follows:
14  *
15  * nodes :  1    2    4    6    8
16  * org.  :  1x1  2x1  2x2  2x3  2x4
17  *
18  */
19
20 #include <device/pci_def.h>
21 #include <device/pci_ids.h>
22 #include <device/hypertransport_def.h>
23 #include "arch/romcc_io.h"
24 #include "amdk8.h"
25
26 /* when generating a temporary row configuration we
27  * don't want broadcast to be enabled for that node.
28  */
29
30 #define enable_bsp_routing()    enable_routing(0)
31
32 #define NODE_HT(x) PCI_DEV(0,24+x,0)
33 #define NODE_MP(x) PCI_DEV(0,24+x,1)
34 #define NODE_MC(x) PCI_DEV(0,24+x,3)
35
36 #define DEFAULT 0x00010101      /* default row entry */
37
38 typedef uint8_t u8;
39 typedef uint32_t u32;
40 typedef int bool;
41
42 #define TRUE  (-1)
43 #define FALSE (0)
44
45 static u8 link_to_register(int ldt)
46 {
47         /*
48          * [ 0: 3] Request Route
49          *     [0] Route to this node
50          *     [1] Route to Link 0
51          *     [2] Route to Link 1
52          *     [3] Route to Link 2
53          */
54
55         if (ldt&0x08) return 0x40;
56         if (ldt&0x04) return 0x20;
57         if (ldt&0x02) return 0x00;
58         
59         /* we should never get here */
60         print_spew("Unknown Link\n");
61         return 0;
62 }
63
64 static void disable_probes(void)
65 {
66         /* disable read/write/fill probes for uniprocessor setup
67          * they don't make sense if only one cpu is available
68          */
69
70         /* Hypetransport Transaction Control Register 
71          * F0:0x68
72          * [ 0: 0] Disable read byte probe
73          *         0 = Probes issues
74          *         1 = Probes not issued
75          * [ 1: 1] Disable Read Doubleword probe
76          *         0 = Probes issued
77          *         1 = Probes not issued
78          * [ 2: 2] Disable write byte probes
79          *         0 = Probes issued
80          *         1 = Probes not issued
81          * [ 3: 3] Disable Write Doubleword Probes
82          *         0 = Probes issued
83          *         1 = Probes not issued.
84          * [10:10] Disable Fill Probe
85          *         0 = Probes issued for cache fills
86          *         1 = Probes not issued for cache fills.
87          */
88
89         u32 val;
90
91         print_spew("Disabling read/write/fill probes for UP... ");
92
93         val=pci_read_config32(NODE_HT(0), 0x68);
94         val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
95         pci_write_config32(NODE_HT(0), 0x68, val);
96
97         print_spew("done.\r\n");
98
99 }
100
101 static void enable_routing(u8 node)
102 {
103         u32 val;
104
105         /* HT Initialization Control Register
106          * F0:0x6C
107          * [ 0: 0] Routing Table Disable
108          *         0 = Packets are routed according to routing tables
109          *         1 = Packets are routed according to the default link field
110          * [ 1: 1] Request Disable (BSP should clear this)
111          *         0 = Request packets may be generated
112          *         1 = Request packets may not be generated.
113          * [ 3: 2] Default Link (Read-only)
114          *         00 = LDT0
115          *         01 = LDT1
116          *         10 = LDT2
117          *         11 = CPU on same node
118          * [ 4: 4] Cold Reset
119          *         - Scratch bit cleared by a cold reset
120          * [ 5: 5] BIOS Reset Detect
121          *         - Scratch bit cleared by a cold reset
122          * [ 6: 6] INIT Detect
123          *         - Scratch bit cleared by a warm or cold reset not by an INIT
124          *
125          */
126
127         /* Enable routing table */
128         print_spew("Enabling routing table for node ");
129         print_spew_hex8(node);
130
131         val=pci_read_config32(NODE_HT(node), 0x6c);
132         val &= ~((1<<1)|(1<<0));
133         pci_write_config32(NODE_HT(node), 0x6c, val);
134
135         print_spew(" done.\r\n");
136 }
137
138 static void fill_row(u8 node, u8 row, u32 value)
139 {
140         pci_write_config32(NODE_HT(node), 0x40+(row<<2), value);
141 }
142 static u32 get_row(u8 node, u8 row)
143 {
144         return pci_read_config32(NODE_HT(node), 0x40+(row<<2));
145 }
146
147 static int link_connection(u8 src, u8 dest)
148 {
149         /* we generate the needed link information from the rows
150          * by taking the Request Route of the according row.
151          */
152
153         return get_row(src, dest) & 0x0f;
154 }
155
156
157 #if CONFIG_MAX_CPUS > 1
158
159 static void rename_temp_node(u8 node)
160 {
161         uint32_t val;
162
163         print_spew("Renaming current temporary node to ");
164         print_spew_hex8(node);
165
166         val=pci_read_config32(NODE_HT(7), 0x60);
167         val &= (~7);  /* clear low bits. */
168         val |= node;   /* new node        */
169         pci_write_config32(NODE_HT(7), 0x60, val);
170
171         print_spew(" done.\r\n");
172 }
173
174 static bool check_connection(u8 dest)
175 {
176         /* See if we have a valid connection to dest */
177         u32 val;
178
179         /* Verify that the coherent hypertransport link is
180          * established and actually working by reading the
181          * remode node's vendor/device id
182          */
183         val = pci_read_config32(NODE_HT(dest),0);
184         if(val != 0x11001022)
185                 return 0;
186
187         return 1;
188 }
189
190 static unsigned read_freq_cap(device_t dev, unsigned pos)
191 {
192         /* Handle bugs in valid hypertransport frequency reporting */
193         unsigned freq_cap;
194         uint32_t id;
195
196         freq_cap = pci_read_config16(dev, pos);
197         freq_cap &= ~(1 << HT_FREQ_VENDOR); /* Ignore Vendor HT frequencies */
198
199         id = pci_read_config32(dev, 0);
200
201         /* AMD 8131 Errata 48 */
202         if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8131_PCIX << 16))) {
203                 freq_cap &= ~(1 << HT_FREQ_800Mhz);
204         }
205         /* AMD 8151 Errata 23 */
206         if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8151_SYSCTRL << 16))) {
207                 freq_cap &= ~(1 << HT_FREQ_800Mhz);
208         }
209         /* AMD K8 Unsupported 1Ghz? */
210         if (id == (PCI_VENDOR_ID_AMD | (0x1100 << 16))) {
211                 freq_cap &= ~(1 << HT_FREQ_1000Mhz);
212         }
213         return freq_cap;
214 }
215
216 static int optimize_connection(device_t node1, uint8_t link1, device_t node2, uint8_t link2)
217 {
218         static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
219         static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
220         uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
221         uint8_t width_cap1, width_cap2, width_cap, width, old_width, ln_width1, ln_width2;
222         uint8_t freq, old_freq;
223         int needs_reset;
224         /* Set link width and frequency */
225
226         /* Initially assume everything is already optimized and I don't need a reset */
227         needs_reset = 0;
228
229         /* Get the frequency capabilities */
230         freq_cap1 = read_freq_cap(node1, link1 + PCI_HT_CAP_HOST_FREQ_CAP);
231         freq_cap2 = read_freq_cap(node2, link2 + PCI_HT_CAP_HOST_FREQ_CAP);
232
233         /* Calculate the highest possible frequency */
234         freq = log2(freq_cap1 & freq_cap2);
235
236         /* See if I am changing the link freqency */
237         old_freq = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ);
238         needs_reset |= old_freq != freq;
239         old_freq = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ);
240         needs_reset |= old_freq != freq;
241
242         /* Set the Calulcated link frequency */
243         pci_write_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ, freq);
244         pci_write_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ, freq);
245
246         /* Get the width capabilities */
247         width_cap1 = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH);
248         width_cap2 = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH);
249
250         /* Calculate node1's input width */
251         ln_width1 = link_width_to_pow2[width_cap1 & 7];
252         ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
253         if (ln_width1 > ln_width2) {
254                 ln_width1 = ln_width2;
255         }
256         width = pow2_to_link_width[ln_width1];
257         /* Calculate node1's output width */
258         ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
259         ln_width2 = link_width_to_pow2[width_cap2 & 7];
260         if (ln_width1 > ln_width2) {
261                 ln_width1 = ln_width2;
262         }
263         width |= pow2_to_link_width[ln_width1] << 4;
264         
265         /* See if I am changing node1's width */
266         old_width = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1);
267         needs_reset |= old_width != width;
268
269         /* Set node1's widths */
270         pci_write_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1, width);
271
272         /* Calculate node2's width */
273         width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
274
275         /* See if I am changing node2's width */
276         old_width = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1);
277         needs_reset |= old_width != width;
278
279         /* Set node2's widths */
280         pci_write_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1, width);
281
282         return needs_reset;
283 }
284
285 static void setup_row_local(u8 source, u8 row) // source will be 7 when it is for temp use
286 {
287         unsigned linkn;
288         uint32_t val;
289         val = 1;
290         for(linkn = 0; linkn<3; linkn++) { 
291                 unsigned regpos; 
292                 uint32_t reg;
293                 regpos = 0x98 + 0x20 * linkn;
294                 reg = pci_read_config32(NODE_HT(source), regpos);
295                 if ((reg & 0x17) != 3) continue; // it is not conherent or not connected
296                 val |= 1<<(linkn+1); 
297         }
298         val <<= 16;
299         val |= 0x0101;
300         fill_row(source,row, val);
301 }
302
303 static void setup_row_direct(u8 source, u8 dest, u8 linkn)
304 {
305         uint32_t val;
306         val = 1<<16; 
307         val |= 1<<(linkn+1);
308         val |= 1<<(linkn+1+8); //for direct connect response route should equal to request table
309         fill_row(source,dest, val);
310 }
311 static uint8_t get_linkn_first(uint8_t byte)
312 {
313         if(byte & 0x02) { byte = 0; }
314         else if(byte & 0x04) { byte = 1; }
315         else if(byte & 0x08) { byte = 2; }
316         return byte; 
317 }       
318 static uint8_t get_linkn_last(uint8_t byte)
319 {
320         if(byte & 0x02) { byte &= 0x0f; byte |= 0x00;  }
321         if(byte & 0x04) { byte &= 0x0f; byte |= 0x10;  }
322         if(byte & 0x08) { byte &= 0x0f; byte |= 0x20;  }
323         return byte>>4; 
324 }
325 static uint8_t get_linkn_last_count(uint8_t byte)
326 {
327         byte &= 0x3f;
328         if(byte & 0x02) { byte &= 0xcf; byte |= 0x00; byte+=0x40; }
329         if(byte & 0x04) { byte &= 0xcf; byte |= 0x10; byte+=0x40; }
330         if(byte & 0x08) { byte &= 0xcf; byte |= 0x20; byte+=0x40; }
331         return byte>>4;
332 }
333
334 #if CONFIG_MAX_CPUS>2
335 #if !CROSS_BAR_47_56
336 static void setup_row_indirect(u8 source, u8 dest, u8 gateway)
337 #else
338 static void setup_row_indirect(u8 source, u8 dest, u8 gateway, u8 diff)
339 #endif
340 {
341         //for indirect connection, we need to compute the val from val_s(source, source), and val_g(source, gateway)
342         uint32_t val_s;
343         uint32_t val_g;
344         uint32_t val;
345         uint8_t byte;
346 #warning "FIXME is it the way to set the RESPONSE TABLE for indirect?"
347 #warning "FIXME I don't know how to set BROADCAST TABLE for indirect, 1?"
348         val_s = get_row(source, source);
349         val_g = get_row(source, gateway);
350         
351         val = val_g & 0xff;
352         val_s >>=16;
353         val_s &=0xfe;
354 #if !CROSS_BAR_47_56
355         if(((source&1)!=(dest &1)) && (val_s!=val) ) { // use another connect as response
356                 val_s -= val;
357 #if CONFIG_MAX_CPUS>4
358                 // Some node have two links left
359                 byte = val_s;
360                 byte = get_linkn_last_count(byte);
361                 if((byte>>2)>1) {
362                         if(source<dest) {
363                                 val_s-=link_connection(source, source-2); // - down
364                         } else {
365                                 val_s-=link_connection(source, source+2); // - up
366                         }
367                 }
368 #endif
369                 val |= (1<<16) | (val_s<<8);
370         } else {
371                 val = val_g; // all the same to gateway
372         }
373 #else 
374         if(diff && (val_s!=val) ) { // use another connect as response
375                 val_s -= val;
376 #if CONFIG_MAX_CPUS>4
377                 // Some node have two links left
378                 // don't worry we only have (2, (3 as source need to handle
379                 byte = val_s;
380                 byte = get_linkn_last_count(byte);
381                 if((byte>>2)>1) {
382                         if(source<dest) {
383                                 val_s-=link_connection(source, source-2); // -down
384                         } else {
385                                 val_s-=link_connection(source, source+2); // -up
386                         }
387                 }
388 #endif
389                 val |= (1<<16) | (val_s<<8);
390         } else {
391                 val = val_g; // all the same to gateway
392         }
393
394 #endif
395
396         fill_row(source, dest, val);
397
398 }
399 static void setup_row_indirect_group(const u8 *conn, int num)
400 {
401         int i;
402         for(i=0; i<num; i+=4) {
403 #if !CROSS_BAR_47_56
404         setup_row_indirect(conn[i*3], conn[i*3+1],conn[i*3+2]);
405 #else
406         setup_row_indirect(conn[i*4], conn[i*4+1],conn[i*4+2], conn[i*4+3]);
407 #endif
408
409         }  
410 }
411 #endif
412
413 static void setup_temp_row(u8 source, u8 dest)
414 {       
415         // copy val from (source, dest) to (source,7)
416         fill_row(source,7,get_row(source,dest));
417 }
418
419 static void clear_temp_row(u8 source)
420 {
421         fill_row(source, 7, DEFAULT);
422 }
423
424 static void setup_remote_row_direct(u8 source, u8 dest, u8 linkn)
425 {
426         uint32_t val;
427         val = 1<<16; 
428         val |= 1<<(linkn+1);
429         val |= 1<<(linkn+1+8); //for direct connect response route should equal to request table
430         fill_row(7,dest, val );
431 }       
432 #if CONFIG_MAX_CPUS>2
433 static void setup_remote_row_indirect(u8 source, u8 dest, u8 gateway)
434 {
435         //for indirect connection, we need to compute the val from val_s(source, source), and val_g(source, gateway)
436         uint32_t val_s;
437         uint32_t val_g;
438         uint32_t val;
439         
440         val_s = get_row(7, source);
441         val_g = get_row(7, gateway);
442         
443         val = val_g & 0xff;
444         val_s >>=16;
445         val_s &=0xfe;
446         if(val_s!=val) { // use another connect as response
447                 val_s -= val;
448                 val |= 1 | (val_s<<8);
449         } else {
450                 val = val_g; // all the same to gateway
451         }
452
453         fill_row(7, dest, val);
454
455 }
456 #endif
457
458 static void setup_remote_node(u8 node)
459 {
460         static const uint8_t pci_reg[] = { 
461                 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c, 
462                 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
463                 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
464                 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
465                 0xc4, 0xcc, 0xd4, 0xdc,
466                 0xc0, 0xc8, 0xd0, 0xd8,
467                 0xe0, 0xe4, 0xe8, 0xec,
468         };
469         int i;
470
471         print_spew("setup_remote_node: ");
472
473         /* copy the default resource map from node 0 */
474         for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
475                 uint32_t value;
476                 uint8_t reg;
477                 reg = pci_reg[i];
478                 value = pci_read_config32(NODE_MP(0), reg);
479                 pci_write_config32(NODE_MP(7), reg, value);
480
481         }
482         print_spew("done\r\n");
483 }
484
485 #endif
486
487 static void setup_uniprocessor(void)
488 {
489         print_spew("Enabling UP settings\r\n");
490         disable_probes();
491 }
492
493 struct setup_smp_result {
494         int nodes;
495         int needs_reset;
496 };
497
498 #if CONFIG_MAX_CPUS > 2
499 static int optimize_connection_group(const u8 *opt_conn, int num) {
500         int needs_reset = 0;
501         int i;
502         for(i=0; i<num; i+=2) {
503                 needs_reset = optimize_connection(
504                         NODE_HT(opt_conn[i*2]), 0x80 + link_to_register(link_connection(opt_conn[i*2],opt_conn[i*2+1])),
505                         NODE_HT(opt_conn[i*2+1]), 0x80 + link_to_register(link_connection(opt_conn[i*2+1],opt_conn[i*2])) );
506         }               
507         return needs_reset;
508 }  
509 #endif
510
511 #if CONFIG_MAX_CPUS > 1
512 static struct setup_smp_result setup_smp(void)
513 {
514         struct setup_smp_result result;
515         u8 byte;
516         uint32_t val;
517         result.nodes = 2;
518         result.needs_reset = 0;
519
520         print_spew("Enabling SMP settings\r\n");
521
522         setup_row_local(0, 0); // it will update the broadcast RT
523         
524         val = get_row(0,0);
525         byte = (val>>16) & 0xfe;
526         if(byte<0x2) { // no coherent connection so get out.
527                 result.nodes = 1;
528                 return result;
529         }
530
531         /* Setup and check a temporary connection to node 1 */
532         //find out linkn
533
534         byte = get_linkn_first(byte);   
535         setup_row_direct(0,1, byte);
536         setup_temp_row(0, 1);
537         
538         if (!check_connection(7)) {
539                 print_spew("No connection to Node 1.\r\n");
540                 setup_uniprocessor();   /* and get up working     */
541                 result.nodes = 1;
542                 return result;
543         }
544
545         /* We found 2 nodes so far */
546         val = pci_read_config32(NODE_HT(7), 0x6c);
547         byte = (val>2) & 0x3; // get default link on 7 to 0
548         setup_row_local(7,1);
549         setup_remote_row_direct(1, 0, byte);
550
551 #if CONFIG_MAX_CPUS>4    
552         val = get_row(7,1);
553         byte = (val>>16) & 0xfe;
554         byte = get_linkn_last_count(byte);
555         if((byte>>2)==3) { // Oh! we need to treat it as cpu2.
556                 val = get_row(0,0);
557                 byte = (val>>16) & 0xfe;
558                 byte = get_linkn_last(byte);
559                 setup_row_direct(0,1, byte);
560                 setup_temp_row(0, 1);
561         
562                 if (!check_connection(7)) {
563                         print_spew("No connection to Node 1.\r\n");
564                         setup_uniprocessor();   /* and get up working     */
565                         result.nodes = 1;
566                         return result;
567                 }               
568                         
569                 /* We found 2 nodes so far */
570                 val = pci_read_config32(NODE_HT(7), 0x6c);
571                 byte = (val>2) & 0x3; // get default link on 7 to 0
572                 setup_row_local(7,1);
573                 setup_remote_row_direct(1, 0, byte);
574         }
575 #endif
576         
577         setup_remote_node(1);  /* Setup the regs on the remote node */
578         rename_temp_node(1);    /* Rename Node 7 to Node 1  */
579         enable_routing(1);      /* Enable routing on Node 1 */
580 #if 0
581         // don't need and it is done by clear_dead_links
582         clear_temp_row(0);
583 #endif
584         
585         result.needs_reset = optimize_connection(
586                 NODE_HT(0), 0x80 + link_to_register(link_connection(0,1)),
587                 NODE_HT(1), 0x80 + link_to_register(link_connection(1,0)) );
588
589 #if CONFIG_MAX_CPUS > 2
590         result.nodes=4;
591
592         /* Setup and check temporary connection from Node 0 to Node 2 */
593         val = get_row(0,0);
594         byte = ((val>>16) & 0xfe) - link_connection(0,1);
595         byte = get_linkn_last_count(byte);
596         
597         //find out linkn
598         if((byte>>2)==0) { // We should have two coherent for 4p and above
599                 result.nodes = 2;
600                 return result;
601         }
602         byte &= 3; // bit [3,2] is count-1
603         setup_row_direct(0, 2, byte);
604         setup_temp_row(0, 2);
605
606         if (!check_connection(7) ) {
607                 print_spew("No connection to Node 2.\r\n");
608                 result.nodes = 2;
609                 return result;
610         }
611
612         /* We found 3 nodes so far. Now setup a temporary
613          * connection from node 0 to node 3 via node 1
614          */
615         setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
616         /* here should setup_row_direct(1,3) at first, before that we should find the link in cpu 1 to 3*/
617         val = get_row(1,1);
618         byte = ((val>>16) & 0xfe) - link_connection(1,0);
619         byte = get_linkn_first(byte);
620         setup_row_direct(1,3,byte);
621         setup_temp_row(1,3); /* temp. link between nodes 1 and 3 */
622         
623         if (!check_connection(7)) {
624                 print_spew("No connection to Node 3.\r\n");
625                 result.nodes = 2;
626                 return result;
627         }
628
629         /* We found 4 nodes so far. Now setup all nodes for 4p */
630         /* for indirect we will use clockwise routing */
631 #if !CROSS_BAR_47_56
632         static const u8 conn4_1[] = {
633                 0,3,1,
634                 1,2,3,
635         };      
636 #else
637         static const u8 conn4_1[] = {
638                 0,3,1,1,
639                 1,2,3,1,
640         };
641 #endif
642
643         setup_row_indirect_group(conn4_1, sizeof(conn4_1)/sizeof(conn4_1[0]));
644         
645         setup_temp_row(0,2);
646
647         val = pci_read_config32(NODE_HT(7), 0x6c);
648         byte = (val>2) & 0x3; // get default link on 7 to 0
649
650         setup_row_local(7,2);
651         setup_remote_row_direct(2, 0, byte);
652         setup_remote_node(2);  /* Setup the regs on the remote node */
653
654         rename_temp_node(2);    /* Rename Node 7 to Node 2  */
655         enable_routing(2);      /* Enable routing on Node 2 */
656
657   
658         setup_temp_row(0,1);
659         setup_temp_row(1,3);
660
661         val = pci_read_config32(NODE_HT(7), 0x6c);
662         byte = (val>2) & 0x3; // get default link on 7 to 0
663
664         setup_row_local(7,3);
665         setup_remote_row_direct(3, 1, byte);
666         setup_remote_node(3);  /* Setup the regs on the remote node */
667
668         rename_temp_node(3);
669         enable_routing(3);      /* enable routing on node 3 (temp.) */
670
671         /* We need to init link between 2, and 3 direct link */
672         val = get_row(2,2);
673         byte = ((val>>16) & 0xfe) - link_connection(2,0);
674         byte = get_linkn_last_count(byte);
675 #if CONFIG_MAX_CPUS>4
676         // We need to find out which link it so CPU3
677         // methods is try to access another 7 actully it is cpu4
678         if((byte>>2)==2) { // one to CPU3, one to cpu0, one to CPU4
679                 setup_temp_row(0,2);
680                 setup_row_direct(2, 4, byte);
681                 setup_temp_row(2, 4);
682
683                 if (check_connection(7)) { // so the link is to CPU4
684                         //We need to re compute it
685                         val = get_row(2,2);
686                         byte = (val>>16) & 0xfe;
687                         byte = get_linkn_first(byte);
688                 }
689         }
690 #endif
691         setup_row_direct(2,3, byte & 0x3);
692         
693         val = get_row(3,3);
694         byte = ((val>>16) & 0xfe) - link_connection(3,1);
695         byte = get_linkn_last_count(byte);
696 #if CONFIG_MAX_CPUS>4
697         // We need to find out which link it so CPU2
698         // methods is try to access another 7 actully it is cpu5
699         if((byte>>2)==2) { // one to CPU2, one to cpu1, one to CPU5
700                 setup_temp_row(0,1);
701                 setup_temp_row(1,3);
702                 setup_row_direct(3, 5, byte);
703                 setup_temp_row(3, 5);
704
705                 if (check_connection(7)) { // so the link is to CPU5
706                         //We need to re compute it
707                         val = get_row(3, 3);
708                         byte = (val>>16) & 0xfe;
709                         byte = get_linkn_first(byte);
710                 }
711         }
712 #endif
713         setup_row_direct(3,2, byte & 0x3);
714
715         /* Set indirect connection to 0, and 1  for indirect we will use clockwise routing */
716 #if !CROSS_BAR_47_56
717         static const u8 conn4_2[] = {
718                 2,1,0,
719                 3,0,2,
720         };
721 #else
722         static const u8 conn4_2[] = {
723                 2,1,0,1,
724                 3,0,2,1,
725         };
726 #endif
727
728         setup_row_indirect_group(conn4_2, sizeof(conn4_2)/sizeof(conn4_2[0]));
729         
730         // We need to do sth to reverse work for setup_temp_row (0,1) (1,3)
731 #if 0
732         // it will be done by clear_dead_links
733         clear_temp_row(0);
734         clear_temp_row(1);
735 #endif
736
737         /* optimize physical connections - by LYH */
738         static const u8 opt_conn4[] = {
739                 0,2,
740                 1,3,
741                 2,3,
742         };
743
744         result.needs_reset = optimize_connection_group(opt_conn4, sizeof(opt_conn4)/sizeof(opt_conn4[0]));
745
746 #endif /* CONFIG_MAX_CPUS > 2 */
747
748 #if CONFIG_MAX_CPUS > 4
749         result.nodes=6;
750
751         /* Setup and check temporary connection from Node 0 to Node 4 via 2 */
752         val = get_row(2,2);
753         byte = ((val>>16) & 0xfe) - link_connection(2,3) - link_connection(2,0);
754         byte = get_linkn_last_count(byte);
755         
756         //find out linkn
757         if((byte>>2)==0) { // We should have two coherent for 4p and above
758                 result.nodes = 4;
759                 return result;
760         }
761         byte &= 3; // bit [3,2] is count-1
762         setup_row_direct(2, 4, byte);
763         
764         /* Setup and check temporary connection from Node 0 to Node 4  through 2*/
765         for(byte=0; byte<4; byte+=2) {
766                 setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
767         }
768         
769         if (!check_connection(7) ) {
770                 print_spew("No connection to Node 4.\r\n");
771                 result.nodes = 4;
772                 return result; 
773         }       
774         
775         /* Setup and check temporary connection from Node 0 to Node 5  through 1, 3*/
776
777         val = get_row(3,3);
778         byte = ((val>>16) & 0xfe) - link_connection(3,2) - link_connection(3,1);
779         byte = get_linkn_last_count(byte);
780         //find out linkn
781         if((byte>>2)==0) { // We should have two coherent for 4p and above
782                 result.nodes = 4;
783                 return result;
784         }
785
786         byte &= 3; // bit [3,2] is count-1
787         setup_row_direct(3, 5, byte);
788
789         setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
790         for(byte=0; byte<4; byte+=2) {
791                 setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */
792         }
793         
794         if (!check_connection(7)) {
795                 print_spew("No connection to Node 5.\r\n");
796                 result.nodes = 4;
797                 return result; 
798         }       
799         
800         /* We found 6 nodes so far. Now setup all nodes for 6p */
801         static const u8 conn6_1[] = {
802 #if !CROSS_BAR_47_56
803                 0, 4, 2,
804                 0, 5, 1,
805                 1, 4, 3,
806                 1, 5, 3,
807                 2, 5, 3,
808                 3, 4, 5,
809 #else
810                 0, 4, 2, 0,
811                 0, 5, 1, 1,
812                 1, 4, 3, 1,
813                 1, 5, 3, 0,
814                 2, 5, 3, 0,
815                 3, 4, 2, 0,
816 #endif
817         }; 
818
819         setup_row_indirect_group(conn6_1, sizeof(conn6_1)/sizeof(conn6_1[0]));
820
821         
822         for(byte=0; byte<4; byte+=2) {
823                 setup_temp_row(byte,byte+2);
824         }
825         val = pci_read_config32(NODE_HT(7), 0x6c);
826         byte = (val>2) & 0x3; // get default link on 7 to 0
827         
828         setup_row_local(7,4);
829         setup_remote_row_direct(4, 2, byte);
830         setup_remote_node(4);  /* Setup the regs on the remote node */
831         rename_temp_node(4);
832         enable_routing(4);
833
834         setup_temp_row(0,1);
835         for(byte=0; byte<4; byte+=2) {
836                 setup_temp_row(byte+1,byte+3);
837         }
838
839         val = pci_read_config32(NODE_HT(7), 0x6c);
840         byte = (val>2) & 0x3; // get default link on 7 to 0
841         setup_row_local(7,5);
842         setup_remote_row_direct(5, 3, byte);
843         setup_remote_node(5);  /* Setup the regs on the remote node */
844
845         rename_temp_node(5);
846         enable_routing(5);      /* enable routing on node 5 (temp.) */
847
848 #if !CROSS_BAR_47_56
849         /* We need to init link between 4, and 5 direct link */
850         val = get_row(4,4);
851         byte = ((val>>16) & 0xfe) - link_connection(4,2);
852         byte = get_linkn_last_count(byte);
853 #if CONFIG_MAX_CPUS>4
854         // We need to find out which link it so CPU5
855         // methods is try to access another 7 actully it is cpu6
856         if((byte>>2)==2) { // one to CPU5, one to cpu2, one to CPU6
857                 setup_temp_row(0,2);
858                 setup_temp_row(2,4);
859                 setup_row_direct(4, 6, byte);
860                 setup_temp_row(4, 6);
861         
862                 if (check_connection(7)) { // so the link is to CPU4
863                         //We need to re compute it
864                         val = get_row(4,4);
865                         byte = (val>>16) & 0xfe;
866                         byte = get_linkn_first(byte);
867                 }
868         }
869 #endif
870         setup_row_direct(4,5, byte & 0x3);
871
872         val = get_row(5,5);
873         byte = ((val>>16) & 0xfe) - link_connection(5,3);
874         byte = get_linkn_last_count(byte);
875 #if CONFIG_MAX_CPUS>4
876         // We need to find out which link it so CPU4
877         // methods is try to access another 7 actully it is cpu7
878         if((byte>>2)==2) { // one to CPU4, one to cpu3, one to CPU7
879                 setup_temp_row(0,1);
880                 setup_temp_row(1,3);
881                 setup_temp_row(3,7);
882                 setup_row_direct(5, 7, byte);
883                 setup_temp_row(5, 7);
884
885                 if (check_connection(7)) { // so the link is to CPU5
886                         //We need to re compute it
887                         val = get_row(5, 5);
888                         byte = (val>>16) & 0xfe;
889                         byte = get_linkn_first(byte);
890                 }
891         }
892 #endif
893         setup_row_direct(5,4, byte & 0x3);
894 #endif // !CROSS_BAR_47_56
895
896         /* Set indirect connection to 0, to 3  for indirect we will use clockwise routing */
897         static const u8 conn6_2[] = {
898 #if !CROSS_BAR_47_56
899                 4, 0, 2,
900                 4, 1, 2,
901                 4, 3, 2,
902                 5, 0, 4,
903                 5, 2, 4,
904                 5, 1, 3,
905 #else
906                 4, 0, 2, 0,
907                 4, 1, 2, 0,
908                 4, 3, 2, 0,
909                 4, 5, 2, 0,
910                 5, 0, 3, 0,
911                 5, 2, 3, 0,
912                 5, 1, 3, 0,
913                 5, 4, 3, 0,
914 #endif
915         };      
916         
917         setup_row_indirect_group(conn6_2, sizeof(conn6_2)/sizeof(conn6_2[0]));
918 #if 0
919         // We need to do sth about reverse about setup_temp_row (0,1), (2,4), (1, 3), (3,5)
920         // It will be done by clear_dead_links
921         for(byte=0; byte<4; byte++) {
922                 clear_temp_row(byte);
923         }
924 #endif
925         
926         /* optimize physical connections - by LYH */
927         static const uint8_t opt_conn6[] ={
928                 2, 4,
929                 3, 5,
930 #if !CROSS_BAR_47_56
931                 4, 5,
932 #endif
933         }; 
934         result.needs_reset = optimize_connection_group(opt_conn6, sizeof(opt_conn6)/sizeof(opt_conn6[0]));
935
936
937 #endif /* CONFIG_MAX_CPUS > 4 */
938
939 #if CONFIG_MAX_CPUS >6 
940         result.nodes=8;
941
942         /* Setup and check temporary connection from Node 0 to Node 6 via 2 and 4 to 7 */
943         val = get_row(4,4);
944 #if !CROSS_BAR_47_56
945         byte = ((val>>16) & 0xfe) - link_connection(4,5) - link_connection(4,2);
946 #else
947         byte = ((val>>16) & 0xfe) - link_connection(4,2);
948 #endif
949         byte = get_linkn_last_count(byte); // Max link to 6
950         if((byte>>2)==0) { // We should have two coherent for 8p and above
951                 result.nodes = 6;
952                 return result;
953         }
954         byte &= 3; // bit [3,2] is count-1
955         setup_row_direct(4, 6, byte);
956
957         /* Setup and check temporary connection from Node 0 to Node 6  through 2, and 4*/
958         for(byte=0; byte<6; byte+=2) {
959                 setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
960         }
961
962         if (!check_connection(7) ) {
963                 print_spew("No connection to Node 6.\r\n");
964                 result.nodes = 6;
965                 return result;
966         }
967 #if !CROSS_BAR_47_56
968         /* Setup and check temporary connection from Node 0 to Node 5  through 1, 3, 5*/
969
970         val = get_row(5,5);
971         byte = ((val>>16) & 0xfe) - link_connection(5,4) - link_connection(5,3);
972         byte = get_linkn_first(byte);
973         setup_row_direct(5, 7, byte);
974
975         setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
976         for(byte=0; byte<6; byte+=2) {
977                 setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */
978         }
979 #else
980         val = get_row(4,4);
981         byte = ((val>>16) & 0xfe) - link_connection(4,2) ;
982         byte = get_linkn_first(byte); // min link to 7
983         setup_row_direct(4, 7, byte);
984
985         /* Setup and check temporary connection from Node 0 to Node 7 through 2, and 4*/
986         for(byte=0; byte<4; byte+=2) {
987                 setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
988         }
989         setup_temp_row(4, 7);
990
991 #endif
992
993         if (!check_connection(7)) {
994                 print_spew("No connection to Node 7.\r\n");
995                 result.nodes = 6;
996                 return result;
997         }
998
999
1000         /* We found 8 nodes so far. Now setup all nodes for 8p */
1001         static const u8 conn8_1[] = {
1002 #if !CROSS_BAR_47_56
1003                 0, 6, 2,
1004 //              0, 7, 1,
1005                 1, 6, 3,
1006 //              1, 7, 3,
1007                 2, 6, 4,
1008 //              2, 7, 3,
1009                 3, 6, 5,
1010 //              3, 7, 5,
1011 //              4, 7, 5,
1012 #else
1013                 0, 6, 2, 0,
1014 //              0, 7, 2, 0,
1015                 1, 6, 3, 0,
1016 //                1, 7, 3, 0,
1017                 2, 6, 4, 0,
1018 //                2, 7, 4, 0,
1019                 3, 6, 5, 0,
1020 //                3, 7, 5, 0,
1021 #endif
1022         };
1023
1024         setup_row_indirect_group(conn8_1,sizeof(conn8_1)/sizeof(conn8_1[0]));
1025
1026         for(byte=0; byte<6; byte+=2) {
1027                 setup_temp_row(byte,byte+2);
1028         }
1029         val = pci_read_config32(NODE_HT(7), 0x6c);
1030         byte = (val>2) & 0x3; // get default link on 7 to 0
1031
1032         setup_row_local(7,6);
1033         setup_remote_row_direct(6, 4, byte);
1034         setup_remote_node(6);  /* Setup the regs on the remote node */
1035         rename_temp_node(6);
1036         enable_routing(6);
1037
1038 #if !CROSS_BAR_47_56
1039         setup_temp_row(0,1);
1040         for(byte=0; byte<6; byte+=2) {
1041                 setup_temp_row(byte+1,byte+3);
1042         }
1043
1044         val = pci_read_config32(NODE_HT(7), 0x6c);
1045         byte = (val>2) & 0x3; // get default link on 7 to 0
1046         setup_row_local(7,7);
1047         setup_remote_row_direct(7, 5, byte);
1048
1049 #else
1050         for(byte=0; byte<4; byte+=2) {
1051                 setup_temp_row(byte,byte+2);
1052         }
1053         setup_temp_row(4,7);
1054         val = pci_read_config32(NODE_HT(7), 0x6c);
1055         byte = (val>2) & 0x3; // get default link on 7 to 0
1056
1057         setup_row_local(7,7);
1058         setup_remote_row_direct(7, 4, byte);
1059         // till now 4-7, 7-4 done.
1060 #endif
1061         setup_remote_node(7);  /* Setup the regs on the remote node */
1062 //        rename_temp_node(7);
1063         enable_routing(7);      /* enable routing on node 5 (temp.) */
1064
1065 #if CROSS_BAR_47_56
1066         //here init 5, 6 and 5, 7
1067         /* Setup and check temporary connection from Node 0 to Node 5  through 1, 3, 5*/
1068         
1069         val = get_row(5,5);
1070         byte = ((val>>16) & 0xfe) - link_connection(5,3);
1071         byte = get_linkn_last(byte);
1072         setup_row_direct(5, 7, byte);
1073         
1074         setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
1075         for(byte=0; byte<6; byte+=2) {
1076                 setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */
1077         }
1078
1079         if (!check_connection(7)) {
1080                 // We need to recompute link to 7
1081                 val = get_row(5,5);
1082                 byte = ((val>>16) & 0xfe) - link_connection(5,3);
1083                 byte = get_linkn_first(byte);
1084
1085                 byte &= 3; // bit [3,2] is count-1
1086                 setup_row_direct(5, 7, byte);
1087 #if 0
1088                 setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */
1089                 for(byte=0; byte<6; byte+=2) {
1090                         setup_temp_row(byte+1,byte+3); /* temp. link between nodes 1 and 3 */
1091                 }
1092 #else
1093                 setup_temp_row(5,7);
1094 #endif
1095                 check_connection(7);
1096         }
1097         val = pci_read_config32(NODE_HT(7), 0x6c);
1098         byte = (val>2) & 0x3; // get default link on 7 to 0
1099 //        setup_row_local(7,7);
1100         setup_remote_row_direct(7, 5, byte);
1101         //Till now 57, 75 done
1102         
1103         //init 5,6
1104         val = get_row(5,5);
1105         byte = ((val>>16) & 0xfe) - link_connection(5,3) - link_connection(5,7);
1106         byte = get_linkn_first(byte);
1107         setup_row_direct(5, 6, byte);
1108
1109
1110         val = get_row(6,6);
1111         byte = ((val>>16) & 0xfe) - link_connection(6,4);
1112         byte = get_linkn_last(byte);
1113         setup_row_direct(6, 7, byte);
1114
1115         for(byte=0; byte<6; byte+=2) {
1116                 setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
1117         }
1118         setup_temp_row(6,7);
1119
1120         if (!check_connection(7)) {
1121                 // We need to recompute link to 7
1122                 val = get_row(6,6);
1123                 byte = ((val>>16) & 0xfe) - link_connection(6,4);
1124                 byte = get_linkn_first(byte);
1125
1126                 setup_row_direct(6, 7, byte);
1127 #if 0
1128                 for(byte=0; byte<6; byte+=2) {
1129                         setup_temp_row(byte,byte+2); /* temp. link between nodes 0 and 2 */
1130                 }
1131 #endif
1132                 setup_temp_row(6,7);
1133                 check_connection(7);
1134         }
1135         val = pci_read_config32(NODE_HT(7), 0x6c);
1136         byte = (val>2) & 0x3; // get default link on 7 to 0
1137 //        setup_row_local(7,7);
1138         setup_remote_row_direct(7, 6, byte);
1139         //Till now 67, 76 done
1140
1141         //init 6,5
1142         val = get_row(6,6);
1143         byte = ((val>>16) & 0xfe) - link_connection(6,4) - link_connection(6,7);
1144         byte = get_linkn_first(byte);
1145         setup_row_direct(6, 5, byte);
1146
1147 #endif
1148
1149 #if !CROSS_BAR_47_56
1150         /* We need to init link between 6, and 7 direct link */
1151         val = get_row(6,6);
1152         byte = ((val>>16) & 0xfe) - link_connection(6,4);
1153         byte = get_linkn_first(byte);
1154         setup_row_direct(6,7, byte & 0x3);
1155
1156         val = get_row(7,7);
1157         byte = ((val>>16) & 0xfe) - link_connection(7,5);
1158         byte = get_linkn_first(byte);
1159         setup_row_direct(7,6, byte & 0x3);
1160 #endif
1161
1162         /* Set indirect connection to 0, to 3  for indirect we will use clockwise routing */
1163         static const u8 conn8_2[] = {
1164 #if !CROSS_BAR_47_56
1165                 0, 7, 1,  // restore it
1166                 1, 7, 3,
1167                 2, 7, 3,
1168                 3, 7, 5,
1169                 4, 7, 5,
1170
1171                 6, 0, 4,
1172                 6, 1, 4,
1173                 6, 2, 4,
1174                 6, 3, 4,
1175                 6, 5, 4,
1176                 7, 0, 6,
1177                 7, 1, 5,
1178                 7, 2, 6,
1179                 7, 3, 5,
1180                 7, 4, 6,
1181 #else
1182                 0, 7, 2, 0, // restore it
1183                 1, 7, 3, 0,
1184                 2, 7, 4, 0,
1185                 3, 7, 5, 0,
1186                 
1187                 6, 0, 4, 0,
1188                 6, 1, 5, 0,
1189                 6, 2, 4, 0,
1190                 6, 3, 5, 0,
1191                 7, 0, 4, 0,
1192                 7, 1, 5, 0,
1193                 7, 2, 4, 0,
1194                 7, 3, 5, 0,
1195                 4, 5, 7, 0,
1196                 5, 4, 6, 0,
1197 #endif
1198         };
1199
1200         setup_row_indirect_group(conn8_2, sizeof(conn8_2)/sizeof(conn8_2[0]));
1201
1202         static const uint8_t opt_conn8[] ={
1203                 4, 6,
1204 #if CROSS_BAR_47_56
1205                 4, 7,
1206                 5, 6,
1207 #endif
1208                 5, 7,
1209                 6, 7,
1210         };
1211         /* optimize physical connections - by LYH */
1212         result.needs_reset = optimize_connection_group(opt_conn8, sizeof(opt_conn6)/sizeof(opt_conn8[0]));
1213
1214 #endif /* CONFIG_MAX_CPUS > 6 */
1215
1216         print_debug_hex8(result.nodes);
1217         print_debug(" nodes initialized.\r\n");
1218         return result;
1219 }
1220 #endif
1221
1222 static unsigned verify_mp_capabilities(unsigned nodes)
1223 {
1224         unsigned node, row, mask;
1225         bool mp_cap=TRUE;
1226
1227         if (nodes > 2) {
1228                 mask=0x06;      /* BigMPCap */
1229         } else if (nodes == 2) {
1230                 mask=0x02;      /* MPCap    */
1231         } else {
1232                 mask=0x00;      /* Non SMP */
1233         }
1234
1235         for (node=0; node<nodes; node++) {
1236                 if ((pci_read_config32(NODE_MC(node), 0xe8) & mask) != mask) {
1237                         mp_cap = FALSE;
1238                 }
1239         }
1240
1241         if (mp_cap) {
1242                 return nodes;
1243         }
1244
1245         /* one of our nodes is not mp capable */
1246
1247         print_err("One of the CPUs is not MP capable. Going back to UP\r\n");
1248         return 1;
1249 }
1250
1251 static void clear_dead_routes(unsigned nodes)
1252 {
1253         int last_row;
1254         int node, row;
1255 #if CONFIG_MAX_CPUS>6
1256         if(nodes==8) return;// don't touch (7,7)
1257 #endif
1258         last_row = nodes;
1259         if (nodes == 1) {
1260                 last_row = 0;
1261         }
1262         for(node = 7; node >= 0; node--) {
1263                 for(row = 7; row >= last_row; row--) {
1264                         fill_row(node, row, DEFAULT);
1265                 }
1266         }
1267 }
1268
1269 static void coherent_ht_finalize(unsigned nodes)
1270 {
1271         unsigned node;
1272         bool rev_a0;
1273         
1274         /* set up cpu count and node count and enable Limit
1275          * Config Space Range for all available CPUs.
1276          * Also clear non coherent hypertransport bus range
1277          * registers on Hammer A0 revision.
1278          */
1279
1280         print_spew("coherent_ht_finalize\r\n");
1281         rev_a0 = is_cpu_rev_a0();
1282         for (node = 0; node < nodes; node++) {
1283                 device_t dev;
1284                 uint32_t val;
1285                 dev = NODE_HT(node);
1286
1287                 /* Set the Total CPU and Node count in the system */
1288                 val = pci_read_config32(dev, 0x60);
1289                 val &= (~0x000F0070);
1290                 val |= ((nodes-1)<<16)|((nodes-1)<<4);
1291                 pci_write_config32(dev, 0x60, val);
1292
1293                 /* Only respond to real cpu pci configuration cycles
1294                  * and optimize the HT settings 
1295                  */
1296                 val=pci_read_config32(dev, 0x68);
1297                 val &= ~((HTTC_BUF_REL_PRI_MASK << HTTC_BUF_REL_PRI_SHIFT) |
1298                         (HTTC_MED_PRI_BYP_CNT_MASK << HTTC_MED_PRI_BYP_CNT_SHIFT) |
1299                         (HTTC_HI_PRI_BYP_CNT_MASK << HTTC_HI_PRI_BYP_CNT_SHIFT));
1300                 val |= HTTC_LIMIT_CLDT_CFG | 
1301                         (HTTC_BUF_REL_PRI_8 << HTTC_BUF_REL_PRI_SHIFT) |
1302                         HTTC_RSP_PASS_PW |
1303                         (3 << HTTC_MED_PRI_BYP_CNT_SHIFT) |
1304                         (3 << HTTC_HI_PRI_BYP_CNT_SHIFT);
1305                 pci_write_config32(dev, 0x68, val);
1306
1307                 if (rev_a0) {
1308                         print_spew("shit it is an old cup\n");
1309                         pci_write_config32(dev, 0x94, 0);
1310                         pci_write_config32(dev, 0xb4, 0);
1311                         pci_write_config32(dev, 0xd4, 0);
1312                 }
1313         }
1314
1315         print_spew("done\r\n");
1316 }
1317
1318 static int apply_cpu_errata_fixes(unsigned nodes, int needs_reset)
1319 {
1320         unsigned node;
1321         for(node = 0; node < nodes; node++) {
1322                 device_t dev;
1323                 uint32_t cmd;
1324                 dev = NODE_MC(node);
1325                 if (is_cpu_pre_c0()) {
1326
1327                         /* Errata 66
1328                          * Limit the number of downstream posted requests to 1 
1329                          */
1330                         cmd = pci_read_config32(dev, 0x70);
1331                         if ((cmd & (3 << 0)) != 2) {
1332                                 cmd &= ~(3<<0);
1333                                 cmd |= (2<<0);
1334                                 pci_write_config32(dev, 0x70, cmd );
1335                                 needs_reset = 1;
1336                         }
1337                         cmd = pci_read_config32(dev, 0x7c);
1338                         if ((cmd & (3 << 4)) != 0) {
1339                                 cmd &= ~(3<<4);
1340                                 cmd |= (0<<4);
1341                                 pci_write_config32(dev, 0x7c, cmd );
1342                                 needs_reset = 1;
1343                         }
1344                         /* Clock Power/Timing Low */
1345                         cmd = pci_read_config32(dev, 0xd4);
1346                         if (cmd != 0x000D0001) {
1347                                 cmd = 0x000D0001;
1348                                 pci_write_config32(dev, 0xd4, cmd);
1349                                 needs_reset = 1; /* Needed? */
1350                         }
1351
1352                 }
1353                 else {
1354                         uint32_t cmd_ref;
1355                         /* Errata 98 
1356                          * Set Clk Ramp Hystersis to 7
1357                          * Clock Power/Timing Low
1358                          */
1359                         cmd_ref = 0x04e20707; /* Registered */
1360                         cmd = pci_read_config32(dev, 0xd4);
1361                         if(cmd != cmd_ref) {
1362                                 pci_write_config32(dev, 0xd4, cmd_ref );
1363                                 needs_reset = 1; /* Needed? */
1364                         }
1365                 }
1366         }
1367         return needs_reset;
1368 }
1369
1370 static int optimize_link_read_pointers(unsigned nodes, int needs_reset)
1371 {
1372         unsigned node;
1373         for(node = 0; node < nodes; node = node + 1) {
1374                 device_t f0_dev, f3_dev;
1375                 uint32_t cmd_ref, cmd;
1376                 int link;
1377                 f0_dev = NODE_HT(node);
1378                 f3_dev = NODE_MC(node);
1379                 cmd_ref = cmd = pci_read_config32(f3_dev, 0xdc);
1380                 for(link = 0; link < 3; link = link + 1) {
1381                         uint32_t link_type;
1382                         unsigned reg;
1383                         /* This works on an Athlon64 because unimplemented links return 0 */
1384                         reg = 0x98 + (link * 0x20);
1385                         link_type = pci_read_config32(f0_dev, reg);
1386                         if (link_type & LinkConnected) {
1387                                 cmd &= 0xff << (link *8);
1388                                 /* FIXME this assumes the device on the other
1389                                  * side is an AMD device 
1390                                  */
1391                                 cmd |= 0x25 << (link *8);
1392                         }
1393                 }
1394                 if (cmd != cmd_ref) {
1395                         pci_write_config32(f3_dev, 0xdc, cmd);
1396                         needs_reset = 1;
1397                 }
1398         }
1399         return needs_reset;
1400 }
1401
1402 static int setup_coherent_ht_domain(void)
1403 {
1404         struct setup_smp_result result;
1405         result.nodes = 1;
1406         result.needs_reset = 0;
1407
1408         enable_bsp_routing();
1409
1410 #if CONFIG_MAX_CPUS > 1
1411         result = setup_smp();
1412 #endif
1413         result.nodes = verify_mp_capabilities(result.nodes);
1414         clear_dead_routes(result.nodes);
1415         if (result.nodes == 1) {
1416                 setup_uniprocessor();
1417         } 
1418         coherent_ht_finalize(result.nodes);
1419         result.needs_reset = apply_cpu_errata_fixes(result.nodes, result.needs_reset);
1420         result.needs_reset = optimize_link_read_pointers(result.nodes, result.needs_reset);
1421         return result.needs_reset;
1422 }