- Add a new chip northbridge/amd/amdk8/root_complex
[coreboot.git] / src / northbridge / amd / amdk8 / northbridge.c
1 #include <console/console.h>
2 #include <arch/io.h>
3 #include <stdint.h>
4 #include <device/device.h>
5 #include <device/pci.h>
6 #include <device/pci_ids.h>
7 #include <device/hypertransport.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <bitops.h>
11 #include <cpu/cpu.h>
12 #include "root_complex/chip.h"
13 #include "northbridge.h"
14 #include "amdk8.h"
15
16 #define FX_DEVS 8
17 static device_t __f0_dev[FX_DEVS];
18 static device_t __f1_dev[FX_DEVS];
19
20 #if 0
21 static void debug_fx_devs(void)
22 {
23         int i;
24         for(i = 0; i < FX_DEVS; i++) {
25                 device_t dev;
26                 dev = __f0_dev[i];
27                 if (dev) {
28                         printk_debug("__f0_dev[%d]: %s bus: %p\n",
29                                 i, dev_path(dev), dev->bus);
30                 }
31                 dev = __f1_dev[i];
32                 if (dev) {
33                         printk_debug("__f1_dev[%d]: %s bus: %p\n",
34                                 i, dev_path(dev), dev->bus);
35                 }
36         }
37 }
38 #endif
39
40 static void get_fx_devs(void)
41 {
42         int i;
43         if (__f1_dev[0]) {
44                 return;
45         }
46         for(i = 0; i < FX_DEVS; i++) {
47                 __f0_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0));
48                 __f1_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1));
49         }
50         if (!__f1_dev[0]) {
51                 die("Cannot find 0:0x18.1\n");
52         }
53 }
54
55 static uint32_t f1_read_config32(unsigned reg)
56 {
57         get_fx_devs();
58         return pci_read_config32(__f1_dev[0], reg);
59 }
60
61 static void f1_write_config32(unsigned reg, uint32_t value)
62 {
63         int i;
64         get_fx_devs();
65         for(i = 0; i < FX_DEVS; i++) {
66                 device_t dev;
67                 dev = __f1_dev[i];
68                 if (dev && dev->enabled) {
69                         pci_write_config32(dev, reg, value);
70                 }
71         }
72 }
73
74 static unsigned int amdk8_nodeid(device_t dev)
75 {
76         return (dev->path.u.pci.devfn >> 3) - 0x18;
77 }
78
79 static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
80 {
81         unsigned nodeid;
82         unsigned link;
83         nodeid = amdk8_nodeid(dev);
84 #if 0
85         printk_debug("%s amdk8_scan_chains max: %d starting...\n", 
86                 dev_path(dev), max);
87 #endif
88         for(link = 0; link < dev->links; link++) {
89                 uint32_t link_type;
90                 uint32_t busses, config_busses;
91                 unsigned free_reg, config_reg;
92                 dev->link[link].cap = 0x80 + (link *0x20);
93                 do {
94                         link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
95                 } while(link_type & ConnectionPending);
96                 if (!(link_type & LinkConnected)) {
97                         continue;
98                 }
99                 do {
100                         link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
101                 } while(!(link_type & InitComplete));
102                 if (!(link_type & NonCoherent)) {
103                         continue;
104                 }
105                 /* See if there is an available configuration space mapping register in function 1. */
106                 free_reg = 0;
107                 for(config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) {
108                         uint32_t config;
109                         config = f1_read_config32(config_reg);
110                         if (!free_reg && ((config & 3) == 0)) {
111                                 free_reg = config_reg;
112                                 continue;
113                         }
114                         if (((config & 3) == 3) && 
115                                 (((config >> 4) & 7) == nodeid) &&
116                                 (((config >> 8) & 3) == link)) {
117                                 break;
118                         }
119                 }
120                 if (free_reg && (config_reg > 0xec)) {
121                         config_reg = free_reg;
122                 }
123                 /* If we can't find an available configuration space mapping register skip this bus */
124                 if (config_reg > 0xec) {
125                         continue;
126                 }
127
128                 /* Set up the primary, secondary and subordinate bus numbers.  We have
129                  * no idea how many busses are behind this bridge yet, so we set the subordinate
130                  * bus number to 0xff for the moment.
131                  */
132                 dev->link[link].secondary = ++max;
133                 dev->link[link].subordinate = 0xff;
134
135                 /* Read the existing primary/secondary/subordinate bus
136                  * number configuration.
137                  */
138                 busses = pci_read_config32(dev, dev->link[link].cap + 0x14);
139                 config_busses = f1_read_config32(config_reg);
140                 
141                 /* Configure the bus numbers for this bridge: the configuration
142                  * transactions will not be propagates by the bridge if it is not
143                  * correctly configured
144                  */
145                 busses &= 0xff000000;
146                 busses |= (((unsigned int)(dev->bus->secondary) << 0) |
147                         ((unsigned int)(dev->link[link].secondary) << 8) |
148                         ((unsigned int)(dev->link[link].subordinate) << 16));
149                 pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
150
151                 config_busses &= 0x000fc88;
152                 config_busses |= 
153                         (3 << 0) |  /* rw enable, no device compare */
154                         (( nodeid & 7) << 4) | 
155                         (( link & 3 ) << 8) |  
156                         ((dev->link[link].secondary) << 16) |
157                         ((dev->link[link].subordinate) << 24);
158                 f1_write_config32(config_reg, config_busses);
159
160 #if 0
161                 printk_debug("%s Hyper transport scan link: %d max: %d\n", 
162                         dev_path(dev), link, max);
163 #endif          
164                 /* Now we can scan all of the subordinate busses i.e. the chain on the hypertranport link */
165                 max = hypertransport_scan_chain(&dev->link[link], max);
166
167 #if 0
168                 printk_debug("%s Hyper transport scan link: %d new max: %d\n",
169                         dev_path(dev), link, max);
170 #endif          
171
172                 /* We know the number of busses behind this bridge.  Set the subordinate
173                  * bus number to it's real value
174                  */
175                 dev->link[link].subordinate = max;
176                 busses = (busses & 0xff00ffff) |
177                         ((unsigned int) (dev->link[link].subordinate) << 16);
178                 pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
179
180                 config_busses = (config_busses & 0x00ffffff) | (dev->link[link].subordinate << 24);
181                 f1_write_config32(config_reg, config_busses);
182 #if 0
183                 printk_debug("%s Hypertransport scan link: %d done\n",
184                         dev_path(dev), link);
185 #endif          
186         }
187 #if 0
188         printk_debug("%s amdk8_scan_chains max: %d done\n", 
189                 dev_path(dev), max);
190 #endif
191         return max;
192 }
193
194 static int reg_useable(unsigned reg, 
195         device_t goal_dev, unsigned goal_nodeid, unsigned goal_link)
196 {
197         struct resource *res;
198         unsigned nodeid, link;
199         int result;
200         res = 0;
201         for(nodeid = 0; !res && (nodeid < 8); nodeid++) {
202                 device_t dev;
203                 dev = __f0_dev[nodeid];
204                 for(link = 0; !res && (link < 3); link++) {
205                         res = probe_resource(dev, 0x100 + (reg | link));
206                 }
207         }
208         result = 2;
209         if (res) {
210                 result = 0;
211                 if (    (goal_link == (link - 1)) && 
212                         (goal_nodeid == (nodeid - 1)) &&
213                         (res->flags <= 1)) {
214                         result = 1;
215                 }
216         }
217 #if 0
218         printk_debug("reg: %02x result: %d gnodeid: %u glink: %u nodeid: %u link: %u\n",
219                 reg, result, 
220                 goal_nodeid, goal_link, 
221                 nodeid, link);
222 #endif
223         return result;
224 }
225
226
227 static struct resource *amdk8_find_iopair(device_t dev, unsigned nodeid, unsigned link)
228 {
229         struct resource *resource;
230         unsigned free_reg, reg;
231         resource = 0;
232         free_reg = 0;
233         for(reg = 0xc0; reg <= 0xd8; reg += 0x8) {
234                 int result;
235                 result = reg_useable(reg, dev, nodeid, link);
236                 if (result == 1) {
237                         /* I have been allocated this one */
238                         break;
239                 }
240                 else if (result > 1) {
241                         /* I have a free register pair */
242                         free_reg = reg;
243                 }
244         }
245         if (reg > 0xd8) {
246                 reg = free_reg;
247         }
248         if (reg > 0) {
249                 resource = new_resource(dev, 0x100 + (reg | link));
250         }
251         return resource;
252 }
253
254 static struct resource *amdk8_find_mempair(device_t dev, unsigned nodeid, unsigned link)
255 {
256         struct resource *resource;
257         unsigned free_reg, reg;
258         resource = 0;
259         free_reg = 0;
260         for(reg = 0x80; reg <= 0xb8; reg += 0x8) {
261                 int result;
262                 result = reg_useable(reg, dev, nodeid, link);
263                 if (result == 1) {
264                         /* I have been allocated this one */
265                         break;
266                 }
267                 else if (result > 1) {
268                         /* I have a free register pair */
269                         free_reg = reg;
270                 }
271         }
272         if (reg > 0xb8) {
273                 reg = free_reg;
274         }
275         if (reg > 0) {
276                 resource = new_resource(dev, 0x100 + (reg | link));
277         }
278         return resource;
279 }
280 static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link)
281 {
282         struct resource *resource;
283         
284         /* Initialize the io space constraints on the current bus */
285         resource =  amdk8_find_iopair(dev, nodeid, link);
286         if (resource) {
287                 resource->base  = 0;
288                 resource->size  = 0;
289                 resource->align = log2(HT_IO_HOST_ALIGN);
290                 resource->gran  = log2(HT_IO_HOST_ALIGN);
291                 resource->limit = 0xffffUL;
292                 resource->flags = IORESOURCE_IO;
293                 compute_allocate_resource(&dev->link[link], resource, 
294                         IORESOURCE_IO, IORESOURCE_IO);
295         }
296
297         /* Initialize the prefetchable memory constraints on the current bus */
298         resource = amdk8_find_mempair(dev, nodeid, link);
299         if (resource) {
300                 resource->base  = 0;
301                 resource->size  = 0;
302                 resource->align = log2(HT_MEM_HOST_ALIGN);
303                 resource->gran  = log2(HT_MEM_HOST_ALIGN);
304                 resource->limit = 0xffffffffffULL;
305                 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
306                 compute_allocate_resource(&dev->link[link], resource, 
307                         IORESOURCE_MEM | IORESOURCE_PREFETCH, 
308                         IORESOURCE_MEM | IORESOURCE_PREFETCH);
309         }
310
311         /* Initialize the memory constraints on the current bus */
312         resource = amdk8_find_mempair(dev, nodeid, link);
313         if (resource) {
314                 resource->base  = 0;
315                 resource->size  = 0;
316                 resource->align = log2(HT_MEM_HOST_ALIGN);
317                 resource->gran  = log2(HT_MEM_HOST_ALIGN);
318                 resource->limit = 0xffffffffffULL;
319                 resource->flags = IORESOURCE_MEM;
320                 compute_allocate_resource(&dev->link[link], resource, 
321                         IORESOURCE_MEM | IORESOURCE_PREFETCH, 
322                         IORESOURCE_MEM);
323         }
324 }
325
326 static void amdk8_read_resources(device_t dev)
327 {
328         unsigned nodeid, link;
329         nodeid = amdk8_nodeid(dev);
330         for(link = 0; link < dev->links; link++) {
331                 if (dev->link[link].children) {
332                         amdk8_link_read_bases(dev, nodeid, link);
333                 }
334         }
335 }
336
337 static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned nodeid)
338 {
339         resource_t rbase, rend;
340         unsigned reg, link;
341         char buf[50];
342
343         /* Make certain the resource has actually been set */
344         if (!(resource->flags & IORESOURCE_ASSIGNED)) {
345                 return;
346         }
347
348         /* If I have already stored this resource don't worry about it */
349         if (resource->flags & IORESOURCE_STORED) {
350                 return;
351         }
352         
353         /* Only handle PCI memory and IO resources */
354         if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
355                 return;
356
357         /* Ensure I am actually looking at a resource of function 1 */
358         if (resource->index < 0x100) {
359                 return;
360         }
361         /* Get the base address */
362         rbase = resource->base;
363         
364         /* Get the limit (rounded up) */
365         rend  = resource_end(resource);
366
367         /* Get the register and link */
368         reg  = resource->index & 0xfc;
369         link = resource->index & 3;
370
371         if (resource->flags & IORESOURCE_IO) {
372                 uint32_t base, limit;
373                 compute_allocate_resource(&dev->link[link], resource,
374                         IORESOURCE_IO, IORESOURCE_IO);
375                 base  = f1_read_config32(reg);
376                 limit = f1_read_config32(reg + 0x4);
377                 base  &= 0xfe000fcc;
378                 base  |= rbase  & 0x01fff000;
379                 base  |= 3;
380                 limit &= 0xfe000fc8;
381                 limit |= rend & 0x01fff000;
382                 limit |= (link & 3) << 4;
383                 limit |= (nodeid & 7);
384
385                 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
386                         base |= PCI_IO_BASE_VGA_EN;
387                 }
388                 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
389                         base |= PCI_IO_BASE_NO_ISA;
390                 }
391                 
392                 f1_write_config32(reg + 0x4, limit);
393                 f1_write_config32(reg, base);
394         }
395         else if (resource->flags & IORESOURCE_MEM) {
396                 uint32_t base, limit;
397                 compute_allocate_resource(&dev->link[link], resource,
398                         IORESOURCE_MEM | IORESOURCE_PREFETCH,
399                         resource->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH));
400                 base  = f1_read_config32(reg);
401                 limit = f1_read_config32(reg + 0x4);
402                 base  &= 0x000000f0;
403                 base  |= (rbase >> 8) & 0xffffff00;
404                 base  |= 3;
405                 limit &= 0x00000048;
406                 limit |= (rend >> 8) & 0xffffff00;
407                 limit |= (link & 3) << 4;
408                 limit |= (nodeid & 7);
409                 f1_write_config32(reg + 0x4, limit);
410                 f1_write_config32(reg, base);
411         }
412         resource->flags |= IORESOURCE_STORED;
413         sprintf(buf, " <node %d link %d>",
414                 nodeid, link);
415         report_resource_stored(dev, resource, buf);
416 }
417
418 static void amdk8_set_resources(device_t dev)
419 {
420         unsigned nodeid, link;
421         int i;
422
423         /* Find the nodeid */
424         nodeid = amdk8_nodeid(dev);     
425
426         /* Set each resource we have found */
427         for(i = 0; i < dev->resources; i++) {
428                 amdk8_set_resource(dev, &dev->resource[i], nodeid);
429         }
430         
431         for(link = 0; link < dev->links; link++) {
432                 struct bus *bus;
433                 bus = &dev->link[link];
434                 if (bus->children) {
435                         assign_resources(bus);
436                 }
437         }
438 }
439
440 static void amdk8_enable_resources(device_t dev)
441 {
442         pci_dev_enable_resources(dev);
443         enable_childrens_resources(dev);
444 }
445
446 static void mcf0_control_init(struct device *dev)
447 {
448         uint32_t cmd;
449
450 #if 0   
451         printk_debug("NB: Function 0 Misc Control.. ");
452 #endif
453 #if 1
454         /* improve latency and bandwith on HT */
455         cmd = pci_read_config32(dev, 0x68);
456         cmd &= 0xffff80ff;
457         cmd |= 0x00004800;
458         pci_write_config32(dev, 0x68, cmd );
459 #endif
460
461 #if 0   
462         /* over drive the ht port to 1000 Mhz */
463         cmd = pci_read_config32(dev, 0xa8);
464         cmd &= 0xfffff0ff;
465         cmd |= 0x00000600;
466         pci_write_config32(dev, 0xdc, cmd );
467 #endif  
468 #if 0
469         printk_debug("done.\n");
470 #endif
471 }
472
473 static struct device_operations northbridge_operations = {
474         .read_resources   = amdk8_read_resources,
475         .set_resources    = amdk8_set_resources,
476         .enable_resources = amdk8_enable_resources,
477         .init             = mcf0_control_init,
478         .scan_bus         = amdk8_scan_chains,
479         .enable           = 0,
480         .ops_pci          = 0,
481 };
482
483
484 static struct pci_driver mcf0_driver __pci_driver = {
485         .ops    = &northbridge_operations,
486         .vendor = PCI_VENDOR_ID_AMD,
487         .device = 0x1100,
488 };
489
490
491 struct chip_operations northbridge_amd_amdk8_ops = {
492         CHIP_NAME("AMD K8 Northbridge")
493         .enable_dev = 0,
494 };
495
496 static void pci_domain_read_resources(device_t dev)
497 {
498         struct resource *resource;
499         unsigned reg;
500
501         /* Find the already assigned resource pairs */
502         get_fx_devs();
503         for(reg = 0x80; reg <= 0xd8; reg+= 0x08) {
504                 uint32_t base, limit;
505                 base  = f1_read_config32(reg);
506                 limit = f1_read_config32(reg + 0x04);
507                 /* Is this register allocated? */
508                 if ((base & 3) != 0) {
509                         unsigned nodeid, link;
510                         device_t dev;
511                         nodeid = limit & 7;
512                         link   = (limit >> 4) & 3;
513                         dev = __f0_dev[nodeid];
514                         if (dev) {
515                                 /* Reserve the resource  */
516                                 struct resource *resource;
517                                 resource = new_resource(dev, 0x100 + (reg | link));
518                                 if (resource) {
519                                         resource->flags = 1;
520                                 }
521                         }
522                 }
523         }
524
525         /* Initialize the system wide io space constraints */
526         resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
527         resource->base  = 0x400;
528         resource->limit = 0xffffUL;
529         resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
530         
531         /* Initialize the system wide memory resources constraints */
532         resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
533         resource->limit = 0xfcffffffffULL;
534         resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
535 }
536
537 static void ram_resource(device_t dev, unsigned long index, 
538         unsigned long basek, unsigned long sizek)
539 {
540         struct resource *resource;
541
542         if (!sizek) {
543                 return;
544         }
545         resource = new_resource(dev, index);
546         resource->base  = ((resource_t)basek) << 10;
547         resource->size  = ((resource_t)sizek) << 10;
548         resource->flags =  IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
549                 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
550 }
551
552 static void tolm_test(void *gp, struct device *dev, struct resource *new)
553 {
554         struct resource **best_p = gp;
555         struct resource *best;
556         best = *best_p;
557         if (!best || (best->base > new->base)) {
558                 best = new;
559         }
560         *best_p = best;
561 }
562
563 static uint32_t find_pci_tolm(struct bus *bus)
564 {
565         struct resource *min;
566         uint32_t tolm;
567         min = 0;
568         search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
569         tolm = 0xffffffffUL;
570         if (min && tolm > min->base) {
571                 tolm = min->base;
572         }
573         return tolm;
574 }
575
576 static void pci_domain_set_resources(device_t dev)
577 {
578         unsigned long mmio_basek;
579         uint32_t pci_tolm;
580         int i, idx;
581
582         pci_tolm = find_pci_tolm(&dev->link[0]);
583
584 #warning "FIXME handle interleaved nodes"
585         mmio_basek = pci_tolm >> 10;
586         /* Round mmio_basek to something the processor can support */
587         mmio_basek &= ~((1 << 6) -1);
588
589 #if 1
590 #warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole"
591         /* Round the mmio hold to 64M */
592         mmio_basek &= ~((64*1024) - 1);
593 #endif
594
595         idx = 10;
596         for(i = 0; i < 8; i++) {
597                 uint32_t base, limit;
598                 unsigned basek, limitk, sizek;
599                 base  = f1_read_config32(0x40 + (i << 3));
600                 limit = f1_read_config32(0x44 + (i << 3));
601                 if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
602                         continue;
603                 }
604                 basek = (base & 0xffff0000) >> 2;
605                 limitk = ((limit + 0x00010000) & 0xffff0000) >> 2;
606                 sizek = limitk - basek;
607
608                 /* see if we need a hole from 0xa0000 to 0xbffff */
609                 if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) {
610                         ram_resource(dev, idx++, basek, ((8*64)+(8*16)) - basek);
611                         basek = (8*64)+(16*16);
612                         sizek = limitk - ((8*64)+(16*16));
613                         
614                 }
615
616                 
617                 /* See if I need to split the region to accomodate pci memory space */
618                 if ((basek < mmio_basek) && (limitk > mmio_basek)) {
619                         if (basek < mmio_basek) {
620                                 unsigned pre_sizek;
621                                 pre_sizek = mmio_basek - basek;
622                                 ram_resource(dev, idx++, basek, pre_sizek);
623                                 sizek -= pre_sizek;
624                                 basek = mmio_basek;
625                         }
626                         if ((basek + sizek) <= 4*1024*1024) {
627                                 sizek = 0;
628                         }
629                         else {
630                                 basek = 4*1024*1024;
631                                 sizek -= (4*1024*1024 - mmio_basek);
632                         }
633                 }
634                 ram_resource(dev, idx++, basek, sizek);
635         }
636         assign_resources(&dev->link[0]);
637 }
638
639 static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
640 {
641         unsigned reg;
642         /* Unmap all of the HT chains */
643         for(reg = 0xe0; reg <= 0xec; reg += 4) {
644                 f1_write_config32(reg, 0);
645         }
646         max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0x18, 0), 0xff, max);
647         return max;
648 }
649
650 static struct device_operations pci_domain_ops = {
651         .read_resources   = pci_domain_read_resources,
652         .set_resources    = pci_domain_set_resources,
653         .enable_resources = enable_childrens_resources,
654         .init             = 0,
655         .scan_bus         = pci_domain_scan_bus,
656 };
657
658 static unsigned int cpu_bus_scan(device_t dev, unsigned int max)
659 {
660         struct bus *cpu_bus;
661         int i;
662
663         /* Find which cpus are present */
664         cpu_bus = &dev->link[0];
665         for(i = 0; i < 8; i++) {
666                 device_t dev, cpu;
667                 struct device_path cpu_path;
668
669                 /* Find the cpu's memory controller */
670                 dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0));
671
672                 /* Build the cpu device path */
673                 cpu_path.type = DEVICE_PATH_APIC;
674                 cpu_path.u.apic.apic_id = i;
675
676                 /* See if I can find the cpu */
677                 cpu = find_dev_path(cpu_bus, &cpu_path);
678
679                 /* Enable the cpu if I have the processor */
680                 if (dev && dev->enabled) {
681                         if (!cpu) {
682                                 cpu = alloc_dev(cpu_bus, &cpu_path);
683                         }
684                         if (cpu) {
685                                 cpu->enabled = 1;
686                         }
687                 }
688                 
689                 /* Disable the cpu if I don't have the processor */
690                 if (cpu && (!dev || !dev->enabled)) {
691                         cpu->enabled = 0;
692                 }
693                 
694                 /* Report what I have done */
695                 if (cpu) {
696                         printk_debug("CPU: %s %s\n",
697                                 dev_path(cpu), cpu->enabled?"enabled":"disabled");
698                 }
699         }
700         return max;
701 }
702
703 static void cpu_bus_init(device_t dev)
704 {
705         initialize_cpus(&dev->link[0]);
706 }
707
708 static void cpu_bus_noop(device_t dev) 
709 {
710 }
711
712 static struct device_operations cpu_bus_ops = {
713         .read_resources   = cpu_bus_noop,
714         .set_resources    = cpu_bus_noop,
715         .enable_resources = cpu_bus_noop,
716         .init             = cpu_bus_init,       
717         .scan_bus         = cpu_bus_scan,
718 };
719
720 static void root_complex_enable_dev(struct device *dev)
721 {
722         /* Set the operations if it is a special bus type */
723         if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
724                 dev->ops = &pci_domain_ops;
725                 pci_set_method_conf1();
726         }
727         else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
728                 dev->ops = &cpu_bus_ops;
729         }
730 }
731
732 struct chip_operations northbridge_amd_amdk8_root_complex_ops = {
733         CHIP_NAME("AMD K8 Root Complex")
734         .enable_dev = root_complex_enable_dev,
735 };