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
7 #include <console/console.h>
10 #include <device/device.h>
11 #include <device/pci.h>
12 #include <device/pci_ids.h>
13 #include <device/hypertransport.h>
19 #include <cpu/x86/lapic.h>
21 #if CONFIG_LOGICAL_CPUS==1
22 #include <cpu/amd/dualcore.h>
23 #include <pc80/mc146818rtc.h>
27 #include "root_complex/chip.h"
28 #include "northbridge.h"
31 #if K8_E0_MEM_HOLE_SIZEK != 0
32 #include "./cpu_rev.c"
36 static device_t __f0_dev[FX_DEVS];
37 static device_t __f1_dev[FX_DEVS];
40 static void debug_fx_devs(void)
43 for (i = 0; i < FX_DEVS; i++) {
47 printk_debug("__f0_dev[%d]: %s bus: %p\n",
48 i, dev_path(dev), dev->bus);
52 printk_debug("__f1_dev[%d]: %s bus: %p\n",
53 i, dev_path(dev), dev->bus);
59 static void get_fx_devs(void)
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));
70 die("Cannot find 0:0x18.1\n");
74 static uint32_t f1_read_config32(unsigned reg)
77 return pci_read_config32(__f1_dev[0], reg);
80 static void f1_write_config32(unsigned reg, uint32_t value)
84 for (i = 0; i < FX_DEVS; i++) {
87 if (dev && dev->enabled) {
88 pci_write_config32(dev, reg, value);
93 static unsigned int amdk8_nodeid(device_t dev)
95 return (dev->path.u.pci.devfn >> 3) - 0x18;
98 static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
102 nodeid = amdk8_nodeid(dev);
104 printk_debug("%s amdk8_scan_chains max: %d starting...\n",
107 for (link = 0; link < dev->links; link++) {
109 uint32_t busses, config_busses;
110 unsigned free_reg, config_reg;
111 dev->link[link].cap = 0x80 + (link *0x20);
113 link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
114 } while(link_type & ConnectionPending);
115 if (!(link_type & LinkConnected)) {
119 link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
120 } while(!(link_type & InitComplete));
121 if (!(link_type & NonCoherent)) {
124 /* See if there is an available configuration space mapping
125 * register in function 1. */
127 for (config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) {
129 config = f1_read_config32(config_reg);
130 if (!free_reg && ((config & 3) == 0)) {
131 free_reg = config_reg;
134 if (((config & 3) == 3) &&
135 (((config >> 4) & 7) == nodeid) &&
136 (((config >> 8) & 3) == link)) {
140 if (free_reg && (config_reg > 0xec)) {
141 config_reg = free_reg;
143 /* If we can't find an available configuration space mapping
144 * register skip this bus */
145 if (config_reg > 0xec) {
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.
153 dev->link[link].secondary = ++max;
154 dev->link[link].subordinate = 0xff;
156 /* Read the existing primary/secondary/subordinate bus
157 * number configuration.
159 busses = pci_read_config32(dev, dev->link[link].cap + 0x14);
160 config_busses = f1_read_config32(config_reg);
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
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);
172 config_busses &= 0x000fc88;
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);
182 printk_debug("%s Hyper transport scan link: %d max: %d\n",
183 dev_path(dev), link, max);
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);
190 printk_debug("%s Hyper transport scan link: %d new max: %d\n",
191 dev_path(dev), link, max);
194 /* We know the number of busses behind this bridge. Set the
195 * subordinate bus number to it's real value
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);
202 config_busses = (config_busses & 0x00ffffff) |
203 (dev->link[link].subordinate << 24);
204 f1_write_config32(config_reg, config_busses);
206 printk_debug("%s Hypertransport scan link: %d done\n",
207 dev_path(dev), link);
211 printk_debug("%s amdk8_scan_chains max: %d done\n",
217 static int reg_useable(unsigned reg, device_t goal_dev, unsigned goal_nodeid,
220 struct resource *res;
221 unsigned nodeid, link;
224 for (nodeid = 0; !res && (nodeid < 8); nodeid++) {
226 dev = __f0_dev[nodeid];
227 for (link = 0; !res && (link < 3); link++) {
228 res = probe_resource(dev, 0x100 + (reg | link));
234 if ((goal_link == (link - 1)) &&
235 (goal_nodeid == (nodeid - 1)) &&
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);
247 static struct resource *amdk8_find_iopair(device_t dev, unsigned nodeid, unsigned link)
249 struct resource *resource;
250 unsigned free_reg, reg;
253 for (reg = 0xc0; reg <= 0xd8; reg += 0x8) {
255 result = reg_useable(reg, dev, nodeid, link);
257 /* I have been allocated this one */
260 else if (result > 1) {
261 /* I have a free register pair */
269 resource = new_resource(dev, 0x100 + (reg | link));
274 static struct resource *amdk8_find_mempair(device_t dev, unsigned nodeid, unsigned link)
276 struct resource *resource;
277 unsigned free_reg, reg;
280 for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
282 result = reg_useable(reg, dev, nodeid, link);
284 /* I have been allocated this one */
287 else if (result > 1) {
288 /* I have a free register pair */
296 resource = new_resource(dev, 0x100 + (reg | link));
301 static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link)
303 struct resource *resource;
305 /* Initialize the io space constraints on the current bus */
306 resource = amdk8_find_iopair(dev, nodeid, link);
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);
318 /* Initialize the prefetchable memory constraints on the current bus */
319 resource = amdk8_find_mempair(dev, nodeid, link);
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);
332 /* Initialize the memory constraints on the current bus */
333 resource = amdk8_find_mempair(dev, nodeid, link);
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,
347 static void amdk8_read_resources(device_t dev)
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);
358 static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned nodeid)
360 resource_t rbase, rend;
364 /* Make certain the resource has actually been set */
365 if (!(resource->flags & IORESOURCE_ASSIGNED)) {
369 /* If I have already stored this resource don't worry about it */
370 if (resource->flags & IORESOURCE_STORED) {
374 /* Only handle PCI memory and IO resources */
375 if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
378 /* Ensure I am actually looking at a resource of function 1 */
379 if (resource->index < 0x100) {
382 /* Get the base address */
383 rbase = resource->base;
385 /* Get the limit (rounded up) */
386 rend = resource_end(resource);
388 /* Get the register and link */
389 reg = resource->index & 0xfc;
390 link = resource->index & 3;
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);
399 base |= rbase & 0x01fff000;
402 limit |= rend & 0x01fff000;
403 limit |= (link & 3) << 4;
404 limit |= (nodeid & 7);
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;
411 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
412 base |= PCI_IO_BASE_NO_ISA;
415 f1_write_config32(reg + 0x4, limit);
416 f1_write_config32(reg, base);
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);
426 base |= (rbase >> 8) & 0xffffff00;
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);
435 resource->flags |= IORESOURCE_STORED;
436 sprintf(buf, " <node %d link %d>",
438 report_resource_stored(dev, resource, buf);
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.
446 static void amdk8_create_vga_resource(device_t dev, unsigned nodeid)
448 struct resource *resource;
450 uint32_t base, limit;
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) {
461 printk_spew("%s: link %d has VGA device\n", __func__, link);
463 /* no VGA card installed */
464 if (link == dev->links)
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;
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);
477 base |= (resource->base >> 8) & 0xffffff00;
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);
486 /* release the temp resource */
491 static void amdk8_set_resources(device_t dev)
493 unsigned nodeid, link;
496 /* Find the nodeid */
497 nodeid = amdk8_nodeid(dev);
499 amdk8_create_vga_resource(dev, nodeid);
501 /* Set each resource we have found */
502 for (i = 0; i < dev->resources; i++) {
503 amdk8_set_resource(dev, &dev->resource[i], nodeid);
506 for (link = 0; link < dev->links; link++) {
508 bus = &dev->link[link];
510 assign_resources(bus);
515 static void amdk8_enable_resources(device_t dev)
517 pci_dev_enable_resources(dev);
518 enable_childrens_resources(dev);
521 static void mcf0_control_init(struct device *dev)
526 printk_debug("NB: Function 0 Misc Control.. ");
529 /* improve latency and bandwith on HT */
530 cmd = pci_read_config32(dev, 0x68);
533 pci_write_config32(dev, 0x68, cmd );
537 /* over drive the ht port to 1000 Mhz */
538 cmd = pci_read_config32(dev, 0xa8);
541 pci_write_config32(dev, 0xdc, cmd );
544 printk_debug("done.\n");
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,
559 static struct pci_driver mcf0_driver __pci_driver = {
560 .ops = &northbridge_operations,
561 .vendor = PCI_VENDOR_ID_AMD,
565 #if CONFIG_CHIP_NAME == 1
567 struct chip_operations northbridge_amd_amdk8_ops = {
568 CHIP_NAME("AMD K8 Northbridge")
574 static void pci_domain_read_resources(device_t dev)
576 struct resource *resource;
579 /* Find the already assigned resource pairs */
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;
590 link = (limit >> 4) & 3;
591 dev = __f0_dev[nodeid];
593 /* Reserve the resource */
594 struct resource *resource;
595 resource = new_resource(dev, 0x100 + (reg | link));
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;
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;
615 static void ram_resource(device_t dev, unsigned long index,
616 unsigned long basek, unsigned long sizek)
618 struct resource *resource;
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;
630 static void tolm_test(void *gp, struct device *dev, struct resource *new)
632 struct resource **best_p = gp;
633 struct resource *best;
635 if (!best || (best->base > new->base)) {
641 static uint32_t find_pci_tolm(struct bus *bus)
643 struct resource *min;
646 search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
648 if (min && tolm > min->base) {
654 static void pci_domain_set_resources(device_t dev)
656 unsigned long mmio_basek;
660 pci_tolm = find_pci_tolm(&dev->link[0]);
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);
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);
673 #if K8_E0_MEM_HOLE_SIZEK != 0
674 if (!is_cpu_pre_e0())
675 for (i = 0; i < 8; i++) {
677 base = f1_read_config32(0x40 + (i << 3));
678 if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
682 base = pci_read_config32(__f1_dev[i], 0xf0);
683 if((base & 1)==0) continue;
686 if (mmio_basek > base) {
689 break; // only one hole
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))) {
702 basek = (base & 0xffff0000) >> 2;
703 limitk = ((limit + 0x00010000) & 0xffff0000) >> 2;
704 sizek = limitk - basek;
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));
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) {
719 pre_sizek = mmio_basek - basek;
720 ram_resource(dev, idx++, basek, pre_sizek);
724 if ((basek + sizek) <= 4*1024*1024) {
729 sizek -= (4*1024*1024 - mmio_basek);
732 ram_resource(dev, idx++, basek, sizek);
734 assign_resources(&dev->link[0]);
737 static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
740 /* Unmap all of the HT chains */
741 for (reg = 0xe0; reg <= 0xec; reg += 4) {
742 f1_write_config32(reg, 0);
744 max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0x18, 0), 0xff, max);
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,
753 .scan_bus = pci_domain_scan_bus,
754 .ops_pci_bus = &pci_cf8_conf1,
757 #define APIC_ID_OFFSET 0x10
758 static unsigned int cpu_bus_scan(device_t dev, unsigned int max)
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;
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");
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
777 nb_cfg_54 = read_nb_cfg_54();
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;
789 /* Find which cpus are present */
790 cpu_bus = &dev->link[0];
791 for (i = 0; i < 8; i++) {
793 struct device_path cpu_path;
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
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) {
808 dev = alloc_dev(dev_mc->bus, &dummy.path);
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
818 printk_debug(" %s siblings=%d\r\n", dev_path(dev), j);
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
826 e0_later_single_core = is_e0_later_in_bsp(i); // single core
828 e0_later_single_core = 0;
830 if(e0_later_single_core) {
831 printk_debug("\tFound e0 single core\r\n");
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
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");
850 #if CONFIG_LOGICAL_CPUS==1
851 for (j = 0; j <= (e0_later_single_core?0:siblings); j++ ) {
853 for (j = 0; j <= siblings; j++ ) {
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);
859 /* See if I can find the cpu */
860 cpu = find_dev_path(cpu_bus, &cpu_path);
862 /* Enable the cpu if I have the processor */
863 if (dev && dev->enabled) {
865 cpu = alloc_dev(cpu_bus, &cpu_path);
872 /* Disable the cpu if I don't have the processor */
873 if (cpu && (!dev || !dev->enabled)) {
877 /* Report what I have done */
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;
885 printk_debug("CPU: %s %s\n",
886 dev_path(cpu), cpu->enabled?"enabled":"disabled");
894 static void cpu_bus_init(device_t dev)
896 initialize_cpus(&dev->link[0]);
899 static void cpu_bus_noop(device_t dev)
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,
911 static void root_complex_enable_dev(struct device *dev)
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;
917 else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
918 dev->ops = &cpu_bus_ops;
922 struct chip_operations northbridge_amd_amdk8_root_complex_ops = {
923 CHIP_NAME("AMD K8 Root Complex")
924 .enable_dev = root_complex_enable_dev,