cosmetics.. we'll not see more that 256cpus in linuxbios for a while
[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  * This code is licensed under GPL.
7  */
8
9 /*
10  * This algorithm assumes a grid configuration as follows:
11  *
12  * nodes :  1    2    4    6    8
13  * org.  :  1x1  2x1  2x2  2x3  2x4
14  *
15  */
16
17 #include <device/pci_def.h>
18 #include <device/pci_ids.h>
19 #include <device/hypertransport_def.h>
20 #include "arch/romcc_io.h"
21 #include "amdk8.h"
22
23 /*
24  * Until we have a completely dynamic setup we want
25  * to be able to map different cpu graphs.
26  */
27
28 #define UP      0x00
29 #define ACROSS  0x20
30 #define DOWN    0x40
31
32 /* 
33  * set some default values. These are used if they are not
34  * differently defined in the motherboard's auto.c file.
35  * See src/mainboard/amd/quartet/auto.c for an example.
36  */
37
38 #ifndef CONNECTION_0_1 
39 #define CONNECTION_0_1 ACROSS
40 #endif
41
42 #ifndef CONNECTION_0_2 
43 #define CONNECTION_0_2 UP
44 #endif
45
46 #ifndef CONNECTION_1_3 
47 #define CONNECTION_1_3 UP
48 #endif
49
50 /* when generating a temporary row configuration we
51  * don't want broadcast to be enabled for that node.
52  */
53
54 #define generate_temp_row(x...) ((generate_row(x)&(~0x0f0000))|0x010000)
55 #define clear_temp_row(x)       fill_row(x,7,DEFAULT)
56 #define enable_bsp_routing()    enable_routing(0)
57
58 #define NODE_HT(x) PCI_DEV(0,24+x,0)
59 #define NODE_MP(x) PCI_DEV(0,24+x,1)
60 #define NODE_MC(x) PCI_DEV(0,24+x,3)
61
62 #define DEFAULT 0x00010101      /* default row entry */
63
64 typedef uint8_t u8;
65 typedef uint32_t u32;
66 typedef int bool;
67
68 #define TRUE  (-1)
69 #define FALSE (0)
70
71 static void disable_probes(void)
72 {
73         /* disable read/write/fill probes for uniprocessor setup
74          * they don't make sense if only one cpu is available
75          */
76
77         /* Hypetransport Transaction Control Register 
78          * F0:0x68
79          * [ 0: 0] Disable read byte probe
80          *         0 = Probes issues
81          *         1 = Probes not issued
82          * [ 1: 1] Disable Read Doubleword probe
83          *         0 = Probes issued
84          *         1 = Probes not issued
85          * [ 2: 2] Disable write byte probes
86          *         0 = Probes issued
87          *         1 = Probes not issued
88          * [ 3: 3] Disable Write Doubleword Probes
89          *         0 = Probes issued
90          *         1 = Probes not issued.
91          * [10:10] Disable Fill Probe
92          *         0 = Probes issued for cache fills
93          *         1 = Probes not issued for cache fills.
94          */
95
96         u32 val;
97
98         print_spew("Disabling read/write/fill probes for UP... ");
99
100         val=pci_read_config32(NODE_HT(0), 0x68);
101         val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
102         pci_write_config32(NODE_HT(0), 0x68, val);
103
104         print_spew("done.\r\n");
105
106 }
107
108 static void enable_routing(u8 node)
109 {
110         u32 val;
111
112         /* HT Initialization Control Register
113          * F0:0x6C
114          * [ 0: 0] Routing Table Disable
115          *         0 = Packets are routed according to routing tables
116          *         1 = Packets are routed according to the default link field
117          * [ 1: 1] Request Disable (BSP should clear this)
118          *         0 = Request packets may be generated
119          *         1 = Request packets may not be generated.
120          * [ 3: 2] Default Link (Read-only)
121          *         00 = LDT0
122          *         01 = LDT1
123          *         10 = LDT2
124          *         11 = CPU on same node
125          * [ 4: 4] Cold Reset
126          *         - Scratch bit cleared by a cold reset
127          * [ 5: 5] BIOS Reset Detect
128          *         - Scratch bit cleared by a cold reset
129          * [ 6: 6] INIT Detect
130          *         - Scratch bit cleared by a warm or cold reset not by an INIT
131          *
132          */
133
134         /* Enable routing table */
135         print_spew("Enabling routing table for node ");
136         print_spew_hex8(node);
137
138         val=pci_read_config32(NODE_HT(node), 0x6c);
139         val &= ~((1<<1)|(1<<0));
140         pci_write_config32(NODE_HT(node), 0x6c, val);
141
142         print_spew(" done.\r\n");
143 }
144
145 #if CONFIG_MAX_CPUS > 1
146
147 static void rename_temp_node(u8 node)
148 {
149         uint32_t val;
150
151         print_spew("Renaming current temporary node to ");
152         print_spew_hex8(node);
153
154         val=pci_read_config32(NODE_HT(7), 0x60);
155         val &= (~7);  /* clear low bits. */
156         val |= node;   /* new node        */
157         pci_write_config32(NODE_HT(7), 0x60, val);
158
159         print_spew(" done.\r\n");
160 }
161
162 static bool check_connection(u8 src, u8 dest, u8 link)
163 {
164         /* See if we have a valid connection to dest */
165         u32 val;
166         
167         /* Detect if the coherent HT link is connected. */
168         val = pci_read_config32(NODE_HT(src), 0x98+link);
169         if ( (val&0x17) != 0x03)
170                 return 0;
171
172         /* Verify that the coherent hypertransport link is
173          * established and actually working by reading the
174          * remode node's vendor/device id
175          */
176         val = pci_read_config32(NODE_HT(dest),0);
177         if(val != 0x11001022)
178                 return 0;
179
180         return 1;
181 }
182
183 static unsigned read_freq_cap(device_t dev, unsigned pos)
184 {
185         /* Handle bugs in valid hypertransport frequency reporting */
186         unsigned freq_cap;
187         uint32_t id;
188
189         freq_cap = pci_read_config16(dev, pos);
190         freq_cap &= ~(1 << HT_FREQ_VENDOR); /* Ignore Vendor HT frequencies */
191
192         id = pci_read_config32(dev, 0);
193
194         /* AMD 8131 Errata 48 */
195         if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8131_PCIX << 16))) {
196                 freq_cap &= ~(1 << HT_FREQ_800Mhz);
197         }
198         /* AMD 8151 Errata 23 */
199         if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8151_SYSCTRL << 16))) {
200                 freq_cap &= ~(1 << HT_FREQ_800Mhz);
201         }
202         /* AMD K8 Unsupported 1Ghz? */
203         if (id == (PCI_VENDOR_ID_AMD | (0x1100 << 16))) {
204                 freq_cap &= ~(1 << HT_FREQ_1000Mhz);
205         }
206         return freq_cap;
207 }
208
209 static int optimize_connection(device_t node1, uint8_t link1, device_t node2, uint8_t link2)
210 {
211         static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
212         static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
213         uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
214         uint8_t width_cap1, width_cap2, width_cap, width, old_width, ln_width1, ln_width2;
215         uint8_t freq, old_freq;
216         int needs_reset;
217         /* Set link width and frequency */
218
219         /* Initially assume everything is already optimized and I don't need a reset */
220         needs_reset = 0;
221
222         /* Get the frequency capabilities */
223         freq_cap1 = read_freq_cap(node1, link1 + PCI_HT_CAP_HOST_FREQ_CAP);
224         freq_cap2 = read_freq_cap(node2, link2 + PCI_HT_CAP_HOST_FREQ_CAP);
225
226         /* Calculate the highest possible frequency */
227         freq = log2(freq_cap1 & freq_cap2);
228
229         /* See if I am changing the link freqency */
230         old_freq = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ);
231         needs_reset |= old_freq != freq;
232         old_freq = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ);
233         needs_reset |= old_freq != freq;
234
235         /* Set the Calulcated link frequency */
236         pci_write_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ, freq);
237         pci_write_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ, freq);
238
239         /* Get the width capabilities */
240         width_cap1 = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH);
241         width_cap2 = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH);
242
243         /* Calculate node1's input width */
244         ln_width1 = link_width_to_pow2[width_cap1 & 7];
245         ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
246         if (ln_width1 > ln_width2) {
247                 ln_width1 = ln_width2;
248         }
249         width = pow2_to_link_width[ln_width1];
250         /* Calculate node1's output width */
251         ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
252         ln_width2 = link_width_to_pow2[width_cap2 & 7];
253         if (ln_width1 > ln_width2) {
254                 ln_width1 = ln_width2;
255         }
256         width |= pow2_to_link_width[ln_width1] << 4;
257         
258         /* See if I am changing node1's width */
259         old_width = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1);
260         needs_reset |= old_width != width;
261
262         /* Set node1's widths */
263         pci_write_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1, width);
264
265         /* Calculate node2's width */
266         width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
267
268         /* See if I am changing node2's width */
269         old_width = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1);
270         needs_reset |= old_width != width;
271
272         /* Set node2's widths */
273         pci_write_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1, width);
274
275         return needs_reset;
276 }
277
278 static void fill_row(u8 node, u8 row, u32 value)
279 {
280         pci_write_config32(NODE_HT(node), 0x40+(row<<2), value);
281 }
282
283 static void setup_row(u8 source, u8 dest, u8 cpus)
284 {
285         fill_row(source,dest,generate_row(source,dest,cpus));
286 }
287
288 static void setup_temp_row(u8 source, u8 dest, u8 cpus)
289 {
290         fill_row(source,7,generate_temp_row(source,dest,cpus));
291 }
292
293 static void setup_node(u8 node, u8 cpus)
294 {
295         u8 row;
296         for(row=0; row<cpus; row++)
297                 setup_row(node, row, cpus);
298 }
299
300 static void setup_remote_row(u8 source, u8 dest, u8 cpus)
301 {
302         fill_row(7, dest, generate_row(source, dest, cpus));
303 }
304
305 static void setup_remote_node(u8 node, u8 cpus)
306 {
307         static const uint8_t pci_reg[] = { 
308                 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c, 
309                 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
310                 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
311                 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
312                 0xc4, 0xcc, 0xd4, 0xdc,
313                 0xc0, 0xc8, 0xd0, 0xd8,
314                 0xe0, 0xe4, 0xe8, 0xec,
315         };
316         uint8_t row;
317         int i;
318
319         print_spew("setup_remote_node: ");
320         for(row=0; row<cpus; row++)
321                 setup_remote_row(node, row, cpus);
322
323         /* copy the default resource map from node 0 */
324         for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
325                 uint32_t value;
326                 uint8_t reg;
327                 reg = pci_reg[i];
328                 value = pci_read_config32(NODE_MP(0), reg);
329                 pci_write_config32(NODE_MP(7), reg, value);
330
331         }
332         print_spew("done\r\n");
333 }
334
335 #endif
336
337 #if CONFIG_MAX_CPUS > 2
338 static void setup_temp_node(u8 node, u8 cpus)
339 {
340         u8 row;
341         for(row=0; row<cpus; row++)
342                 fill_row(7,row,generate_row(node,row,cpus));
343 }
344 #endif
345
346 static void setup_uniprocessor(void)
347 {
348         print_spew("Enabling UP settings\r\n");
349         disable_probes();
350 }
351
352 struct setup_smp_result {
353         int cpus;
354         int needs_reset;
355 };
356
357 #if CONFIG_MAX_CPUS > 1
358 static struct setup_smp_result setup_smp(void)
359 {
360         struct setup_smp_result result;
361         result.cpus = 2;
362         result.needs_reset = 0;
363
364         print_spew("Enabling SMP settings\r\n");
365
366         setup_row(0, 0, result.cpus);
367         /* Setup and check a temporary connection to node 1 */
368         setup_temp_row(0, 1, result.cpus);
369         
370         if (!check_connection(0, 7, CONNECTION_0_1)) {
371                 print_debug("No connection to Node 1.\r\n");
372                 clear_temp_row(0);      /* delete temp connection */
373                 setup_uniprocessor();   /* and get up working     */
374                 result.cpus = 1;
375                 return result;
376         }
377
378         /* We found 2 nodes so far */
379         result.needs_reset = 
380                 optimize_connection(NODE_HT(0), 0x80 + CONNECTION_0_1, NODE_HT(7), 0x80 + CONNECTION_0_1);
381         setup_node(0, result.cpus);     /* Node 1 is there. Setup Node 0 correctly */
382         setup_remote_node(1, result.cpus);  /* Setup the routes on the remote node */
383         rename_temp_node(1);    /* Rename Node 7 to Node 1  */
384         enable_routing(1);      /* Enable routing on Node 1 */
385         
386         clear_temp_row(0);      /* delete temporary connection */
387         
388 #if CONFIG_MAX_CPUS > 2
389         result.cpus=4;
390         
391         /* Setup and check temporary connection from Node 0 to Node 2 */
392         setup_temp_row(0,2, result.cpus);
393
394         if (!check_connection(0, 7, CONNECTION_0_2)) {
395                 print_debug("No connection to Node 2.\r\n");
396                 clear_temp_row(0);       /* delete temp connection */
397                 result.cpus = 2;
398                 return result;
399         }
400
401         /* We found 3 nodes so far. Now setup a temporary
402          * connection from node 0 to node 3 via node 1
403          */
404
405         setup_temp_row(0,1, result.cpus); /* temp. link between nodes 0 and 1 */
406         setup_temp_row(1,3, result.cpus); /* temp. link between nodes 1 and 3 */
407
408         if (!check_connection(1, 7, CONNECTION_1_3)) {
409                 print_debug("No connection to Node 3.\r\n");
410                 clear_temp_row(0);       /* delete temp connection */
411                 clear_temp_row(1);       /* delete temp connection */
412                 result.cpus = 2;
413                 return result;
414         }
415
416 #warning "FIXME optimize the physical connections"
417
418         /* We found 4 nodes so far. Now setup all nodes for 4p */
419
420         setup_node(0, result.cpus);  /* The first 2 nodes are configured    */
421         setup_node(1, result.cpus);  /* already. Just configure them for 4p */
422         
423         setup_temp_row(0,2, result.cpus);
424         setup_temp_node(2, result.cpus);
425         rename_temp_node(2);
426         enable_routing(2);
427   
428         setup_temp_row(0,1, result.cpus);
429         setup_temp_row(1,3, result.cpus);
430         setup_temp_node(3, result.cpus);
431         rename_temp_node(3);
432         enable_routing(3);      /* enable routing on node 3 (temp.) */
433         
434         clear_temp_row(0);
435         clear_temp_row(1);
436         clear_temp_row(2);
437         clear_temp_row(3);
438
439 #endif
440         print_debug_hex8(result.cpus);
441         print_debug(" nodes initialized.\r\n");
442         return result;
443 }
444 #endif
445
446 #if CONFIG_MAX_CPUS > 1
447 static unsigned verify_mp_capabilities(unsigned cpus)
448 {
449         unsigned node, row, mask;
450         bool mp_cap=TRUE;
451
452         if (cpus > 2) {
453                 mask=0x06;      /* BigMPCap */
454         } else {
455                 mask=0x02;      /* MPCap    */
456         }
457
458         for (node=0; node<cpus; node++) {
459                 if ((pci_read_config32(NODE_MC(node), 0xe8) & mask) != mask) {
460                         mp_cap = FALSE;
461                 }
462         }
463
464         if (mp_cap) {
465                 return cpus;
466         }
467
468         /* one of our cpus is not mp capable */
469
470         print_err("One of the CPUs is not MP capable. Going back to UP\r\n");
471
472         for (node = cpus; node > 0; node--) {
473                 for (row = cpus; row > 0; row--) {
474                         fill_row(NODE_HT(node-1), row-1, DEFAULT);
475                 }
476         }
477         setup_uniprocessor();
478         return 1;
479 }
480
481 #endif
482
483 static void coherent_ht_finalize(unsigned cpus)
484 {
485         unsigned node;
486         bool rev_a0;
487         
488         /* set up cpu count and node count and enable Limit
489          * Config Space Range for all available CPUs.
490          * Also clear non coherent hypertransport bus range
491          * registers on Hammer A0 revision.
492          */
493
494 #if 0
495         print_debug("coherent_ht_finalize\r\n");
496 #endif
497         rev_a0 = is_cpu_rev_a0();
498         for (node = 0; node < cpus; node++) {
499                 device_t dev;
500                 uint32_t val;
501                 dev = NODE_HT(node);
502
503                 /* Set the Total CPU and Node count in the system */
504                 val = pci_read_config32(dev, 0x60);
505                 val &= (~0x000F0070);
506                 val |= ((cpus-1)<<16)|((cpus-1)<<4);
507                 pci_write_config32(dev, 0x60, val);
508
509                 /* Only respond to real cpu pci configuration cycles
510                  * and optimize the HT settings 
511                  */
512                 val=pci_read_config32(dev, 0x68);
513                 val &= ~((HTTC_BUF_REL_PRI_MASK << HTTC_BUF_REL_PRI_SHIFT) |
514                         (HTTC_MED_PRI_BYP_CNT_MASK << HTTC_MED_PRI_BYP_CNT_SHIFT) |
515                         (HTTC_HI_PRI_BYP_CNT_MASK << HTTC_HI_PRI_BYP_CNT_SHIFT));
516                 val |= HTTC_LIMIT_CLDT_CFG | 
517                         (HTTC_BUF_REL_PRI_8 << HTTC_BUF_REL_PRI_SHIFT) |
518                         HTTC_RSP_PASS_PW |
519                         (3 << HTTC_MED_PRI_BYP_CNT_SHIFT) |
520                         (3 << HTTC_HI_PRI_BYP_CNT_SHIFT);
521                 pci_write_config32(dev, 0x68, val);
522
523                 if (rev_a0) {
524                         pci_write_config32(dev, 0x94, 0);
525                         pci_write_config32(dev, 0xb4, 0);
526                         pci_write_config32(dev, 0xd4, 0);
527                 }
528
529
530         }
531
532 #if 0
533         print_debug("done\r\n");
534 #endif
535 }
536
537 static int apply_cpu_errata_fixes(unsigned cpus, int needs_reset)
538 {
539         unsigned node;
540         for(node = 0; node < cpus; node++) {
541                 device_t dev;
542                 uint32_t cmd;
543                 dev = NODE_MC(node);
544                 if (is_cpu_pre_c0()) {
545
546                         /* Errata 66
547                          * Limit the number of downstream posted requests to 1 
548                          */
549                         cmd = pci_read_config32(dev, 0x70);
550                         if ((cmd & (3 << 0)) != 2) {
551                                 cmd &= ~(3<<0);
552                                 cmd |= (2<<0);
553                                 pci_write_config32(dev, 0x70, cmd );
554                                 needs_reset = 1;
555                         }
556                         cmd = pci_read_config32(dev, 0x7c);
557                         if ((cmd & (3 << 4)) != 0) {
558                                 cmd &= ~(3<<4);
559                                 cmd |= (0<<4);
560                                 pci_write_config32(dev, 0x7c, cmd );
561                                 needs_reset = 1;
562                         }
563                         /* Clock Power/Timing Low */
564                         cmd = pci_read_config32(dev, 0xd4);
565                         if (cmd != 0x000D0001) {
566                                 cmd = 0x000D0001;
567                                 pci_write_config32(dev, 0xd4, cmd);
568                                 needs_reset = 1; /* Needed? */
569                         }
570
571                 }
572                 else {
573                         uint32_t cmd_ref;
574                         /* Errata 98 
575                          * Set Clk Ramp Hystersis to 7
576                          * Clock Power/Timing Low
577                          */
578                         cmd_ref = 0x04e20707; /* Registered */
579                         cmd = pci_read_config32(dev, 0xd4);
580                         if(cmd != cmd_ref) {
581                                 pci_write_config32(dev, 0xd4, cmd_ref );
582                                 needs_reset = 1; /* Needed? */
583                         }
584                 }
585         }
586         return needs_reset;
587 }
588
589 static int optimize_link_read_pointers(unsigned cpus, int needs_reset)
590 {
591         unsigned node;
592         for(node = 0; node < cpus; node = node + 1) {
593                 device_t f0_dev, f3_dev;
594                 uint32_t cmd_ref, cmd;
595                 int link;
596                 f0_dev = NODE_HT(node);
597                 f3_dev = NODE_MC(node);
598                 cmd_ref = cmd = pci_read_config32(f3_dev, 0xdc);
599                 for(link = 0; link < 3; link = link + 1) {
600                         uint32_t link_type;
601                         unsigned reg;
602                         reg = 0x98 + (link * 0x20);
603                         link_type = pci_read_config32(f0_dev, reg);
604                         if (link_type & LinkConnected) {
605                                 cmd &= 0xff << (link *8);
606                                 /* FIXME this assumes the device on the other side is an AMD device */
607                                 cmd |= 0x25 << (link *8);
608                         }
609                 }
610                 if (cmd != cmd_ref) {
611                         pci_write_config32(f3_dev, 0xdc, cmd);
612                         needs_reset = 1;
613                 }
614         }
615         return needs_reset;
616 }
617
618 static int setup_coherent_ht_domain(void)
619 {
620         struct setup_smp_result result;
621         result.cpus = 1;
622         result.needs_reset = 0;
623
624         enable_bsp_routing();
625
626 #if CONFIG_MAX_CPUS == 1
627         setup_uniprocessor();
628 #else
629         result = setup_smp();
630         result.cpus = verify_mp_capabilities(result.cpus);
631 #endif
632         coherent_ht_finalize(result.cpus);
633         result.needs_reset = apply_cpu_errata_fixes(result.cpus, result.needs_reset);
634 #if CONFIG_MAX_CPUS > 1 /* Why doesn't this work on the solo? */
635         result.needs_reset = optimize_link_read_pointers(result.cpus, result.needs_reset);
636 #endif
637
638         return result.needs_reset;
639 }