Revision: linuxbios@linuxbios.org--devel/freebios--devel--2.0--patch-34
[coreboot.git] / src / northbridge / amd / amdk8 / northbridge.c
1 /* This should be done by Eric
2         2004.12 yhlu add dual core support
3         2005.01 yhlu add support move apic before pci_domain in MB Config.lb
4         2005.02 yhlu add e0 memory hole support
5 */
6
7 #include <console/console.h>
8 #include <arch/io.h>
9 #include <stdint.h>
10 #include <device/device.h>
11 #include <device/pci.h>
12 #include <device/pci_ids.h>
13 #include <device/hypertransport.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <bitops.h>
17 #include <cpu/cpu.h>
18
19 #include <cpu/x86/lapic.h>
20
21 #if CONFIG_LOGICAL_CPUS==1
22 #include <cpu/amd/dualcore.h>
23 #include <pc80/mc146818rtc.h>
24 #endif
25
26 #include "chip.h"
27 #include "root_complex/chip.h"
28 #include "northbridge.h"
29 #include "amdk8.h"
30
31 #if K8_E0_MEM_HOLE_SIZEK != 0
32 #include "./cpu_rev.c"
33 #endif
34
35 #define FX_DEVS 8
36 static device_t __f0_dev[FX_DEVS];
37 static device_t __f1_dev[FX_DEVS];
38
39 #if 0
40 static void debug_fx_devs(void)
41 {
42         int i;
43         for (i = 0; i < FX_DEVS; i++) {
44                 device_t dev;
45                 dev = __f0_dev[i];
46                 if (dev) {
47                         printk_debug("__f0_dev[%d]: %s bus: %p\n",
48                                 i, dev_path(dev), dev->bus);
49                 }
50                 dev = __f1_dev[i];
51                 if (dev) {
52                         printk_debug("__f1_dev[%d]: %s bus: %p\n",
53                                 i, dev_path(dev), dev->bus);
54                 }
55         }
56 }
57 #endif
58
59 static void get_fx_devs(void)
60 {
61         int i;
62         if (__f1_dev[0]) {
63                 return;
64         }
65         for (i = 0; i < FX_DEVS; i++) {
66                 __f0_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0));
67                 __f1_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1));
68         }
69         if (!__f1_dev[0]) {
70                 die("Cannot find 0:0x18.1\n");
71         }
72 }
73
74 static uint32_t f1_read_config32(unsigned reg)
75 {
76         get_fx_devs();
77         return pci_read_config32(__f1_dev[0], reg);
78 }
79
80 static void f1_write_config32(unsigned reg, uint32_t value)
81 {
82         int i;
83         get_fx_devs();
84         for (i = 0; i < FX_DEVS; i++) {
85                 device_t dev;
86                 dev = __f1_dev[i];
87                 if (dev && dev->enabled) {
88                         pci_write_config32(dev, reg, value);
89                 }
90         }
91 }
92
93 static unsigned int amdk8_nodeid(device_t dev)
94 {
95         return (dev->path.u.pci.devfn >> 3) - 0x18;
96 }
97
98 static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
99 {
100         unsigned nodeid;
101         unsigned link;
102         nodeid = amdk8_nodeid(dev);
103 #if 0
104         printk_debug("%s amdk8_scan_chains max: %d starting...\n", 
105                      dev_path(dev), max);
106 #endif
107         for (link = 0; link < dev->links; link++) {
108                 uint32_t link_type;
109                 uint32_t busses, config_busses;
110                 unsigned free_reg, config_reg;
111                 dev->link[link].cap = 0x80 + (link *0x20);
112                 do {
113                         link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
114                 } while(link_type & ConnectionPending);
115                 if (!(link_type & LinkConnected)) {
116                         continue;
117                 }
118                 do {
119                         link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
120                 } while(!(link_type & InitComplete));
121                 if (!(link_type & NonCoherent)) {
122                         continue;
123                 }
124                 /* See if there is an available configuration space mapping
125                  * register in function 1. */
126                 free_reg = 0;
127                 for (config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) {
128                         uint32_t config;
129                         config = f1_read_config32(config_reg);
130                         if (!free_reg && ((config & 3) == 0)) {
131                                 free_reg = config_reg;
132                                 continue;
133                         }
134                         if (((config & 3) == 3) && 
135                             (((config >> 4) & 7) == nodeid) &&
136                             (((config >> 8) & 3) == link)) {
137                                 break;
138                         }
139                 }
140                 if (free_reg && (config_reg > 0xec)) {
141                         config_reg = free_reg;
142                 }
143                 /* If we can't find an available configuration space mapping
144                  * register skip this bus */
145                 if (config_reg > 0xec) {
146                         continue;
147                 }
148
149                 /* Set up the primary, secondary and subordinate bus numbers.
150                  * We have no idea how many busses are behind this bridge yet,
151                  * so we set the subordinate bus number to 0xff for the moment.
152                  */
153                 dev->link[link].secondary = ++max;
154                 dev->link[link].subordinate = 0xff;
155
156                 /* Read the existing primary/secondary/subordinate bus
157                  * number configuration.
158                  */
159                 busses = pci_read_config32(dev, dev->link[link].cap + 0x14);
160                 config_busses = f1_read_config32(config_reg);
161
162                 /* Configure the bus numbers for this bridge: the configuration
163                  * transactions will not be propagates by the bridge if it is
164                  * not correctly configured
165                  */
166                 busses &= 0xff000000;
167                 busses |= (((unsigned int)(dev->bus->secondary) << 0) |
168                            ((unsigned int)(dev->link[link].secondary) << 8) |
169                            ((unsigned int)(dev->link[link].subordinate) << 16));
170                 pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
171
172                 config_busses &= 0x000fc88;
173                 config_busses |= 
174                         (3 << 0) |  /* rw enable, no device compare */
175                         (( nodeid & 7) << 4) | 
176                         (( link & 3 ) << 8) |  
177                         ((dev->link[link].secondary) << 16) |
178                         ((dev->link[link].subordinate) << 24);
179                 f1_write_config32(config_reg, config_busses);
180
181 #if 0
182                 printk_debug("%s Hyper transport scan link: %d max: %d\n", 
183                         dev_path(dev), link, max);
184 #endif
185                 /* Now we can scan all of the subordinate busses i.e. the
186                  * chain on the hypertranport link */
187                 max = hypertransport_scan_chain(&dev->link[link], max);
188
189 #if 0
190                 printk_debug("%s Hyper transport scan link: %d new max: %d\n",
191                         dev_path(dev), link, max);
192 #endif
193
194                 /* We know the number of busses behind this bridge.  Set the
195                  * subordinate bus number to it's real value
196                  */
197                 dev->link[link].subordinate = max;
198                 busses = (busses & 0xff00ffff) |
199                         ((unsigned int) (dev->link[link].subordinate) << 16);
200                 pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
201
202                 config_busses = (config_busses & 0x00ffffff) |
203                         (dev->link[link].subordinate << 24);
204                 f1_write_config32(config_reg, config_busses);
205 #if 0
206                 printk_debug("%s Hypertransport scan link: %d done\n",
207                         dev_path(dev), link);
208 #endif
209         }
210 #if 0
211         printk_debug("%s amdk8_scan_chains max: %d done\n", 
212                 dev_path(dev), max);
213 #endif
214         return max;
215 }
216
217 static int reg_useable(unsigned reg, device_t goal_dev, unsigned goal_nodeid,
218                        unsigned goal_link)
219 {
220         struct resource *res;
221         unsigned nodeid, link;
222         int result;
223         res = 0;
224         for (nodeid = 0; !res && (nodeid < 8); nodeid++) {
225                 device_t dev;
226                 dev = __f0_dev[nodeid];
227                 for (link = 0; !res && (link < 3); link++) {
228                         res = probe_resource(dev, 0x100 + (reg | link));
229                 }
230         }
231         result = 2;
232         if (res) {
233                 result = 0;
234                 if ((goal_link == (link - 1)) && 
235                     (goal_nodeid == (nodeid - 1)) &&
236                     (res->flags <= 1)) {
237                         result = 1;
238                 }
239         }
240 #if 0
241         printk_debug("reg: %02x result: %d gnodeid: %u glink: %u nodeid: %u link: %u\n",
242                      reg, result, goal_nodeid, goal_link, nodeid, link);
243 #endif
244         return result;
245 }
246
247 static struct resource *amdk8_find_iopair(device_t dev, unsigned nodeid, unsigned link)
248 {
249         struct resource *resource;
250         unsigned free_reg, reg;
251         resource = 0;
252         free_reg = 0;
253         for (reg = 0xc0; reg <= 0xd8; reg += 0x8) {
254                 int result;
255                 result = reg_useable(reg, dev, nodeid, link);
256                 if (result == 1) {
257                         /* I have been allocated this one */
258                         break;
259                 }
260                 else if (result > 1) {
261                         /* I have a free register pair */
262                         free_reg = reg;
263                 }
264         }
265         if (reg > 0xd8) {
266                 reg = free_reg;
267         }
268         if (reg > 0) {
269                 resource = new_resource(dev, 0x100 + (reg | link));
270         }
271         return resource;
272 }
273
274 static struct resource *amdk8_find_mempair(device_t dev, unsigned nodeid, unsigned link)
275 {
276         struct resource *resource;
277         unsigned free_reg, reg;
278         resource = 0;
279         free_reg = 0;
280         for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
281                 int result;
282                 result = reg_useable(reg, dev, nodeid, link);
283                 if (result == 1) {
284                         /* I have been allocated this one */
285                         break;
286                 }
287                 else if (result > 1) {
288                         /* I have a free register pair */
289                         free_reg = reg;
290                 }
291         }
292         if (reg > 0xb8) {
293                 reg = free_reg;
294         }
295         if (reg > 0) {
296                 resource = new_resource(dev, 0x100 + (reg | link));
297         }
298         return resource;
299 }
300
301 static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link)
302 {
303         struct resource *resource;
304         
305         /* Initialize the io space constraints on the current bus */
306         resource =  amdk8_find_iopair(dev, nodeid, link);
307         if (resource) {
308                 resource->base  = 0;
309                 resource->size  = 0;
310                 resource->align = log2(HT_IO_HOST_ALIGN);
311                 resource->gran  = log2(HT_IO_HOST_ALIGN);
312                 resource->limit = 0xffffUL;
313                 resource->flags = IORESOURCE_IO;
314                 compute_allocate_resource(&dev->link[link], resource, 
315                         IORESOURCE_IO, IORESOURCE_IO);
316         }
317
318         /* Initialize the prefetchable memory constraints on the current bus */
319         resource = amdk8_find_mempair(dev, nodeid, link);
320         if (resource) {
321                 resource->base  = 0;
322                 resource->size  = 0;
323                 resource->align = log2(HT_MEM_HOST_ALIGN);
324                 resource->gran  = log2(HT_MEM_HOST_ALIGN);
325                 resource->limit = 0xffffffffffULL;
326                 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
327                 compute_allocate_resource(&dev->link[link], resource, 
328                         IORESOURCE_MEM | IORESOURCE_PREFETCH, 
329                         IORESOURCE_MEM | IORESOURCE_PREFETCH);
330         }
331
332         /* Initialize the memory constraints on the current bus */
333         resource = amdk8_find_mempair(dev, nodeid, link);
334         if (resource) {
335                 resource->base  = 0;
336                 resource->size  = 0;
337                 resource->align = log2(HT_MEM_HOST_ALIGN);
338                 resource->gran  = log2(HT_MEM_HOST_ALIGN);
339                 resource->limit = 0xffffffffffULL;
340                 resource->flags = IORESOURCE_MEM;
341                 compute_allocate_resource(&dev->link[link], resource, 
342                         IORESOURCE_MEM | IORESOURCE_PREFETCH, 
343                         IORESOURCE_MEM);
344         }
345 }
346
347 static void amdk8_read_resources(device_t dev)
348 {
349         unsigned nodeid, link;
350         nodeid = amdk8_nodeid(dev);
351         for (link = 0; link < dev->links; link++) {
352                 if (dev->link[link].children) {
353                         amdk8_link_read_bases(dev, nodeid, link);
354                 }
355         }
356 }
357
358 static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned nodeid)
359 {
360         resource_t rbase, rend;
361         unsigned reg, link;
362         char buf[50];
363
364         /* Make certain the resource has actually been set */
365         if (!(resource->flags & IORESOURCE_ASSIGNED)) {
366                 return;
367         }
368
369         /* If I have already stored this resource don't worry about it */
370         if (resource->flags & IORESOURCE_STORED) {
371                 return;
372         }
373         
374         /* Only handle PCI memory and IO resources */
375         if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
376                 return;
377
378         /* Ensure I am actually looking at a resource of function 1 */
379         if (resource->index < 0x100) {
380                 return;
381         }
382         /* Get the base address */
383         rbase = resource->base;
384         
385         /* Get the limit (rounded up) */
386         rend  = resource_end(resource);
387
388         /* Get the register and link */
389         reg  = resource->index & 0xfc;
390         link = resource->index & 3;
391
392         if (resource->flags & IORESOURCE_IO) {
393                 uint32_t base, limit;
394                 compute_allocate_resource(&dev->link[link], resource,
395                         IORESOURCE_IO, IORESOURCE_IO);
396                 base  = f1_read_config32(reg);
397                 limit = f1_read_config32(reg + 0x4);
398                 base  &= 0xfe000fcc;
399                 base  |= rbase  & 0x01fff000;
400                 base  |= 3;
401                 limit &= 0xfe000fc8;
402                 limit |= rend & 0x01fff000;
403                 limit |= (link & 3) << 4;
404                 limit |= (nodeid & 7);
405
406                 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
407                         printk_spew("%s, enabling legacy VGA IO forwarding for %s link %s\n",
408                                     __func__, dev_path(dev), link);             
409                         base |= PCI_IO_BASE_VGA_EN;
410                 }
411                 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
412                         base |= PCI_IO_BASE_NO_ISA;
413                 }
414                 
415                 f1_write_config32(reg + 0x4, limit);
416                 f1_write_config32(reg, base);
417         }
418         else if (resource->flags & IORESOURCE_MEM) {
419                 uint32_t base, limit;
420                 compute_allocate_resource(&dev->link[link], resource,
421                         IORESOURCE_MEM | IORESOURCE_PREFETCH,
422                         resource->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH));
423                 base  = f1_read_config32(reg);
424                 limit = f1_read_config32(reg + 0x4);
425                 base  &= 0x000000f0;
426                 base  |= (rbase >> 8) & 0xffffff00;
427                 base  |= 3;
428                 limit &= 0x00000048;
429                 limit |= (rend >> 8) & 0xffffff00;
430                 limit |= (link & 3) << 4;
431                 limit |= (nodeid & 7);
432                 f1_write_config32(reg + 0x4, limit);
433                 f1_write_config32(reg, base);
434         }
435         resource->flags |= IORESOURCE_STORED;
436         sprintf(buf, " <node %d link %d>",
437                 nodeid, link);
438         report_resource_stored(dev, resource, buf);
439 }
440
441 /**
442  *
443  * I tried to reuse the resource allocation code in amdk8_set_resource()
444  * but it is too diffcult to deal with the resource allocation magic.
445  */
446 static void amdk8_create_vga_resource(device_t dev, unsigned nodeid)
447 {
448         struct resource *resource;
449         unsigned link;
450         uint32_t base, limit;
451         unsigned reg;
452
453         /* find out which link the VGA card is connected,
454          * we only deal with the 'first' vga card */
455         for (link = 0; link < dev->links; link++) {
456                 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
457                         break;
458                 }
459         }
460         
461         printk_spew("%s: link %d has VGA device\n", __func__, link);
462
463         /* no VGA card installed */
464         if (link == dev->links)
465                 return;
466
467         /* allocate a temp resrouce for legacy VGA buffer */
468         resource = amdk8_find_mempair(dev, nodeid, link);
469         resource->base = 0xa0000;
470         resource->size = 0x20000;
471
472         /* write the resource to the hardware */
473         reg  = resource->index & 0xfc;
474         base  = f1_read_config32(reg);
475         limit = f1_read_config32(reg + 0x4);
476         base  &= 0x000000f0;
477         base  |= (resource->base >> 8) & 0xffffff00;
478         base  |= 3;
479         limit &= 0x00000048;
480         limit |= ((resource->base + resource->size) >> 8) & 0xffffff00;
481         limit |= (resource->index & 3) << 4;
482         limit |= (nodeid & 7);
483         f1_write_config32(reg + 0x4, limit);
484         f1_write_config32(reg, base);
485
486         /* release the temp resource */
487         resource->flags = 0;
488
489 }
490
491 static void amdk8_set_resources(device_t dev)
492 {
493         unsigned nodeid, link;
494         int i;
495
496         /* Find the nodeid */
497         nodeid = amdk8_nodeid(dev);
498
499         amdk8_create_vga_resource(dev, nodeid);
500         
501         /* Set each resource we have found */
502         for (i = 0; i < dev->resources; i++) {
503                 amdk8_set_resource(dev, &dev->resource[i], nodeid);
504         }
505
506         for (link = 0; link < dev->links; link++) {
507                 struct bus *bus;
508                 bus = &dev->link[link];
509                 if (bus->children) {
510                         assign_resources(bus);
511                 }
512         }
513 }
514
515 static void amdk8_enable_resources(device_t dev)
516 {
517         pci_dev_enable_resources(dev);
518         enable_childrens_resources(dev);
519 }
520
521 static void mcf0_control_init(struct device *dev)
522 {
523         uint32_t cmd;
524
525 #if 0   
526         printk_debug("NB: Function 0 Misc Control.. ");
527 #endif
528 #if 1
529         /* improve latency and bandwith on HT */
530         cmd = pci_read_config32(dev, 0x68);
531         cmd &= 0xffff80ff;
532         cmd |= 0x00004800;
533         pci_write_config32(dev, 0x68, cmd );
534 #endif
535
536 #if 0   
537         /* over drive the ht port to 1000 Mhz */
538         cmd = pci_read_config32(dev, 0xa8);
539         cmd &= 0xfffff0ff;
540         cmd |= 0x00000600;
541         pci_write_config32(dev, 0xdc, cmd );
542 #endif  
543 #if 0
544         printk_debug("done.\n");
545 #endif
546 }
547
548 static struct device_operations northbridge_operations = {
549         .read_resources   = amdk8_read_resources,
550         .set_resources    = amdk8_set_resources,
551         .enable_resources = amdk8_enable_resources,
552         .init             = mcf0_control_init,
553         .scan_bus         = amdk8_scan_chains,
554         .enable           = 0,
555         .ops_pci          = 0,
556 };
557
558
559 static struct pci_driver mcf0_driver __pci_driver = {
560         .ops    = &northbridge_operations,
561         .vendor = PCI_VENDOR_ID_AMD,
562         .device = 0x1100,
563 };
564
565 #if CONFIG_CHIP_NAME == 1
566
567 struct chip_operations northbridge_amd_amdk8_ops = {
568         CHIP_NAME("AMD K8 Northbridge")
569         .enable_dev = 0,
570 };
571
572 #endif
573
574 static void pci_domain_read_resources(device_t dev)
575 {
576         struct resource *resource;
577         unsigned reg;
578
579         /* Find the already assigned resource pairs */
580         get_fx_devs();
581         for (reg = 0x80; reg <= 0xd8; reg+= 0x08) {
582                 uint32_t base, limit;
583                 base  = f1_read_config32(reg);
584                 limit = f1_read_config32(reg + 0x04);
585                 /* Is this register allocated? */
586                 if ((base & 3) != 0) {
587                         unsigned nodeid, link;
588                         device_t dev;
589                         nodeid = limit & 7;
590                         link   = (limit >> 4) & 3;
591                         dev = __f0_dev[nodeid];
592                         if (dev) {
593                                 /* Reserve the resource  */
594                                 struct resource *resource;
595                                 resource = new_resource(dev, 0x100 + (reg | link));
596                                 if (resource) {
597                                         resource->flags = 1;
598                                 }
599                         }
600                 }
601         }
602
603         /* Initialize the system wide io space constraints */
604         resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
605         resource->base  = 0x400;
606         resource->limit = 0xffffUL;
607         resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
608
609         /* Initialize the system wide memory resources constraints */
610         resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
611         resource->limit = 0xfcffffffffULL;
612         resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
613 }
614
615 static void ram_resource(device_t dev, unsigned long index,
616                          unsigned long basek, unsigned long sizek)
617 {
618         struct resource *resource;
619
620         if (!sizek) {
621                 return;
622         }
623         resource = new_resource(dev, index);
624         resource->base  = ((resource_t)basek) << 10;
625         resource->size  = ((resource_t)sizek) << 10;
626         resource->flags =  IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
627                 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
628 }
629
630 static void tolm_test(void *gp, struct device *dev, struct resource *new)
631 {
632         struct resource **best_p = gp;
633         struct resource *best;
634         best = *best_p;
635         if (!best || (best->base > new->base)) {
636                 best = new;
637         }
638         *best_p = best;
639 }
640
641 static uint32_t find_pci_tolm(struct bus *bus)
642 {
643         struct resource *min;
644         uint32_t tolm;
645         min = 0;
646         search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
647         tolm = 0xffffffffUL;
648         if (min && tolm > min->base) {
649                 tolm = min->base;
650         }
651         return tolm;
652 }
653
654 static void pci_domain_set_resources(device_t dev)
655 {
656         unsigned long mmio_basek;
657         uint32_t pci_tolm;
658         int i, idx;
659
660         pci_tolm = find_pci_tolm(&dev->link[0]);
661
662 #warning "FIXME handle interleaved nodes"
663         mmio_basek = pci_tolm >> 10;
664         /* Round mmio_basek to something the processor can support */
665         mmio_basek &= ~((1 << 6) -1);
666
667 #if 1
668 #warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole"
669         /* Round the mmio hold to 64M */
670         mmio_basek &= ~((64*1024) - 1);
671 #endif
672
673 #if K8_E0_MEM_HOLE_SIZEK != 0
674         if (!is_cpu_pre_e0())
675         for (i = 0; i < 8; i++) {
676                 uint32_t base;
677                 base  = f1_read_config32(0x40 + (i << 3));
678                 if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
679                         continue;
680                 }
681                 
682                 base = pci_read_config32(__f1_dev[i], 0xf0);
683                 if((base & 1)==0) continue;
684                 base &= 0xff<<24;
685                 base >>= 10;
686                 if (mmio_basek > base) {
687                         mmio_basek = base;
688                 }
689                 break; // only one hole 
690         }
691 #endif
692
693         idx = 10;
694         for (i = 0; i < 8; i++) {
695                 uint32_t base, limit;
696                 unsigned basek, limitk, sizek;
697                 base  = f1_read_config32(0x40 + (i << 3));
698                 limit = f1_read_config32(0x44 + (i << 3));
699                 if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
700                         continue;
701                 }
702                 basek = (base & 0xffff0000) >> 2;
703                 limitk = ((limit + 0x00010000) & 0xffff0000) >> 2;
704                 sizek = limitk - basek;
705
706                 /* see if we need a hole from 0xa0000 to 0xbffff */
707                 if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) {
708                         ram_resource(dev, idx++, basek, ((8*64)+(8*16)) - basek);
709                         basek = (8*64)+(16*16);
710                         sizek = limitk - ((8*64)+(16*16));
711                         
712                 }
713
714                 
715                 /* See if I need to split the region to accomodate pci memory space */
716                 if ((basek < mmio_basek) && (limitk > mmio_basek)) {
717                         if (basek < mmio_basek) {
718                                 unsigned pre_sizek;
719                                 pre_sizek = mmio_basek - basek;
720                                 ram_resource(dev, idx++, basek, pre_sizek);
721                                 sizek -= pre_sizek;
722                                 basek = mmio_basek;
723                         }
724                         if ((basek + sizek) <= 4*1024*1024) {
725                                 sizek = 0;
726                         }
727                         else {
728                                 basek = 4*1024*1024;
729                                 sizek -= (4*1024*1024 - mmio_basek);
730                         }
731                 }
732                 ram_resource(dev, idx++, basek, sizek);
733         }
734         assign_resources(&dev->link[0]);
735 }
736
737 static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
738 {
739         unsigned reg;
740         /* Unmap all of the HT chains */
741         for (reg = 0xe0; reg <= 0xec; reg += 4) {
742                 f1_write_config32(reg, 0);
743         }
744         max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0x18, 0), 0xff, max);
745         return max;
746 }
747
748 static struct device_operations pci_domain_ops = {
749         .read_resources   = pci_domain_read_resources,
750         .set_resources    = pci_domain_set_resources,
751         .enable_resources = enable_childrens_resources,
752         .init             = 0,
753         .scan_bus         = pci_domain_scan_bus,
754         .ops_pci_bus      = &pci_cf8_conf1,
755 };
756
757 #define APIC_ID_OFFSET 0x10
758 static unsigned int cpu_bus_scan(device_t dev, unsigned int max)
759 {
760         struct bus *cpu_bus;
761         device_t dev_mc;
762         int i,j;
763         unsigned nb_cfg_54 = 0;
764         unsigned siblings = 0;
765         int enable_apic_ext_id = 0;
766         int bsp_apic_id = lapicid(); // bsp apicid
767         int apic_id_offset = bsp_apic_id;
768
769 #if CONFIG_LOGICAL_CPUS==1
770         int e0_later_single_core;
771         int disable_siblings = !CONFIG_LOGICAL_CPUS;
772         get_option(&disable_siblings, "dual_core");
773
774         // for pre_e0, nb_cfg_54 can not be set, ( even set, when you read it still be 0)
775         // How can I get the nb_cfg_54 of every node' nb_cfg_54 in bsp??? and differ d0 and e0 single core
776  
777         nb_cfg_54 = read_nb_cfg_54();
778 #endif
779
780         dev_mc = dev_find_slot(0, PCI_DEVFN(0x18, 0));
781         if(pci_read_config32(dev_mc, 0x68) & ( HTTC_APIC_EXT_ID | HTTC_APIC_EXT_BRD_CST)) {
782                 enable_apic_ext_id = 1;
783                 if(apic_id_offset==0) { //bsp apic id is not changed
784                         apic_id_offset = APIC_ID_OFFSET;
785                 }
786         }
787
788
789         /* Find which cpus are present */
790         cpu_bus = &dev->link[0];
791         for (i = 0; i < 8; i++) {
792                 device_t dev, cpu;
793                 struct device_path cpu_path;
794
795                 /* Find the cpu's memory controller */
796                 dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 3));
797                 if(!dev) { // in case we move apic cluser before pci_domain and not set that for second CPU
798                         for(j=0; j<4; j++) {
799                                 struct device dummy;
800                                 uint32_t id;
801                                 dummy.bus              = dev_mc->bus;
802                                 dummy.path.type        = DEVICE_PATH_PCI;
803                                 dummy.path.u.pci.devfn = PCI_DEVFN(0x18 + i, j);
804                                 id = pci_read_config32(&dummy, PCI_VENDOR_ID);
805                                 if (id != 0xffffffff && id != 0x00000000 &&
806                                         id != 0x0000ffff && id != 0xffff0000) {
807                                         //create that for it
808                                         dev = alloc_dev(dev_mc->bus, &dummy.path);
809                                 }
810                         }
811                 }
812
813 #if CONFIG_LOGICAL_CPUS==1
814                 e0_later_single_core = 0;
815                 if((!disable_siblings) && dev && dev->enabled) {
816                         j = (pci_read_config32(dev, 0xe8) >> 12) & 3;  //dev is func 3
817
818                         printk_debug("  %s siblings=%d\r\n", dev_path(dev), j);
819
820                         if(nb_cfg_54) {
821                                 // For e0 single core if nb_cfg_54 is set, apicid will be 0, 2, 4.... 
822                                 //  ----> you can mixed single core e0 and dual core e0 at any sequence
823                                 // That is the typical case
824
825                                 if(j == 0 ){
826                                        e0_later_single_core = is_e0_later_in_bsp(i);  // single core 
827                                 } else {
828                                        e0_later_single_core = 0;
829                                 }
830                                 if(e0_later_single_core) { 
831                                         printk_debug("\tFound e0 single core\r\n");
832                                         j=1; 
833                                 }
834         
835                                 if(siblings > j ) {
836                                         //actually we can't be here, because d0 nb_cfg_54 can not be set
837                                         //even worse is_e0_later_in_bsp() can not find out if it is d0 or e0
838
839                                         die("When NB_CFG_54 is set, if you want to mix e0 (single core and dual core) and single core(pre e0) CPUs, you need to put all the single core (pre e0) CPUs before all the (e0 single or dual core) CPUs\r\n");
840                                 }
841                                 else {
842                                         siblings = j;
843                                 }
844                         } else {
845                                 siblings = j;
846                         }
847                 }
848 #endif
849
850 #if CONFIG_LOGICAL_CPUS==1
851                 for (j = 0; j <= (e0_later_single_core?0:siblings); j++ ) {
852 #else 
853                 for (j = 0; j <= siblings; j++ ) {
854 #endif
855                         /* Build the cpu device path */
856                         cpu_path.type = DEVICE_PATH_APIC;
857                         cpu_path.u.apic.apic_id = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:8);
858   
859                         /* See if I can find the cpu */
860                         cpu = find_dev_path(cpu_bus, &cpu_path);
861   
862                         /* Enable the cpu if I have the processor */
863                         if (dev && dev->enabled) {
864                                 if (!cpu) {
865                                         cpu = alloc_dev(cpu_bus, &cpu_path);
866                                 }
867                                 if (cpu) {
868                                         cpu->enabled = 1; 
869                                 }
870                         }
871
872                         /* Disable the cpu if I don't have the processor */
873                         if (cpu && (!dev || !dev->enabled)) {
874                                 cpu->enabled = 0;
875                         }
876
877                         /* Report what I have done */
878                         if (cpu) {
879                                 if(enable_apic_ext_id) {
880                                         if(cpu->path.u.apic.apic_id<apic_id_offset) { //all add offset except bsp core0
881                                                 if( (cpu->path.u.apic.apic_id > siblings) || (bsp_apic_id!=0) )
882                                                         cpu->path.u.apic.apic_id += apic_id_offset;
883                                         }
884                                 }
885                                 printk_debug("CPU: %s %s\n",
886                                         dev_path(cpu), cpu->enabled?"enabled":"disabled");
887                         }
888                 } //j
889         }
890
891         return max;
892 }
893
894 static void cpu_bus_init(device_t dev)
895 {
896         initialize_cpus(&dev->link[0]);
897 }
898
899 static void cpu_bus_noop(device_t dev) 
900 {
901 }
902
903 static struct device_operations cpu_bus_ops = {
904         .read_resources   = cpu_bus_noop,
905         .set_resources    = cpu_bus_noop,
906         .enable_resources = cpu_bus_noop,
907         .init             = cpu_bus_init,
908         .scan_bus         = cpu_bus_scan,
909 };
910
911 static void root_complex_enable_dev(struct device *dev)
912 {
913         /* Set the operations if it is a special bus type */
914         if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
915                 dev->ops = &pci_domain_ops;
916         }
917         else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
918                 dev->ops = &cpu_bus_ops;
919         }
920 }
921
922 struct chip_operations northbridge_amd_amdk8_root_complex_ops = {
923         CHIP_NAME("AMD K8 Root Complex")
924         .enable_dev = root_complex_enable_dev,
925 };