diff options
author | Myles Watson <mylesgw@gmail.com> | 2009-07-02 19:02:33 +0000 |
---|---|---|
committer | Myles Watson <mylesgw@gmail.com> | 2009-07-02 19:02:33 +0000 |
commit | c7233e089923870cb4dc483034f7e9c9334c9128 (patch) | |
tree | 9731134e5ac73f8a9762b7dae5bc64111d93a9af /src/northbridge | |
parent | 29cc9eda2021a87396ef31a6fc81daff6fd1be7a (diff) |
Update the k8 code for the v3 resource allocator.
The major change is that the K8 registers don't get touched until the end of
resource allocation.
Fam10 code could be updated the same way.
Move VGA code before resource allocation but after device enumeration.
Signed-off-by: Myles Watson <mylesgw@gmail.com>
Acked-by: Ronald G. Minnich <rminnich@gmail.com>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4395 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge')
-rw-r--r-- | src/northbridge/amd/amdk8/northbridge.c | 247 |
1 files changed, 114 insertions, 133 deletions
diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c index c07fdfcbcc..6086970717 100644 --- a/src/northbridge/amd/amdk8/northbridge.c +++ b/src/northbridge/amd/amdk8/northbridge.c @@ -36,56 +36,38 @@ struct amdk8_sysconf_t sysconf; -#define FX_DEVS 8 -static device_t __f0_dev[FX_DEVS]; -static device_t __f1_dev[FX_DEVS]; - -#if 0 -static void debug_fx_devs(void) -{ - int i; - for(i = 0; i < FX_DEVS; i++) { - device_t dev; - dev = __f0_dev[i]; - if (dev) { - printk_debug("__f0_dev[%d]: %s bus: %p\n", - i, dev_path(dev), dev->bus); - } - dev = __f1_dev[i]; - if (dev) { - printk_debug("__f1_dev[%d]: %s bus: %p\n", - i, dev_path(dev), dev->bus); - } - } -} -#endif +#define MAX_FX_DEVS 8 +static device_t __f0_dev[MAX_FX_DEVS]; +static device_t __f1_dev[MAX_FX_DEVS]; +static unsigned fx_devs=0; static void get_fx_devs(void) { int i; - if (__f1_dev[0]) { - return; - } - for(i = 0; i < FX_DEVS; i++) { + for(i = 0; i < MAX_FX_DEVS; i++) { __f0_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0)); __f1_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1)); + if (__f0_dev[i] != NULL && __f1_dev[i] != NULL) + fx_devs = i+1; } - if (!__f1_dev[0]) { - die("Cannot find 0:0x18.1\n"); + if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) { + die("Cannot find 0:0x18.[0|1]\n"); } } static uint32_t f1_read_config32(unsigned reg) { - get_fx_devs(); + if ( fx_devs == 0) + get_fx_devs(); return pci_read_config32(__f1_dev[0], reg); } static void f1_write_config32(unsigned reg, uint32_t value) { int i; - get_fx_devs(); - for(i = 0; i < FX_DEVS; i++) { + if ( fx_devs == 0) + get_fx_devs(); + for(i = 0; i < fx_devs; i++) { device_t dev; dev = __f1_dev[i]; if (dev && dev->enabled) { @@ -291,7 +273,7 @@ static int reg_useable(unsigned reg, unsigned nodeid, link=0; int result; res = 0; - for(nodeid = 0; !res && (nodeid < FX_DEVS); nodeid++) { + for(nodeid = 0; !res && (nodeid < fx_devs); nodeid++) { device_t dev; dev = __f0_dev[nodeid]; if (!dev) @@ -313,13 +295,14 @@ static int reg_useable(unsigned reg, return result; } -static struct resource *amdk8_find_iopair(device_t dev, unsigned nodeid, unsigned link) +static unsigned amdk8_find_reg(device_t dev, unsigned nodeid, unsigned link, + unsigned min, unsigned max) { - struct resource *resource; + unsigned resource; unsigned free_reg, reg; resource = 0; free_reg = 0; - for(reg = 0xc0; reg <= 0xd8; reg += 0x8) { + for(reg = min; reg <= max; reg += 0x8) { int result; result = reg_useable(reg, dev, nodeid, link); if (result == 1) { @@ -331,40 +314,23 @@ static struct resource *amdk8_find_iopair(device_t dev, unsigned nodeid, unsigne free_reg = reg; } } - if (reg > 0xd8) { + if (reg > max) { reg = free_reg; } if (reg > 0) { - resource = new_resource(dev, IOINDEX(0x100 + reg, link)); + resource = IOINDEX(0x100 + reg, link); } return resource; } -static struct resource *amdk8_find_mempair(device_t dev, unsigned nodeid, unsigned link) +static unsigned amdk8_find_iopair(device_t dev, unsigned nodeid, unsigned link) { - struct resource *resource; - unsigned free_reg, reg; - resource = 0; - free_reg = 0; - for(reg = 0x80; reg <= 0xb8; reg += 0x8) { - int result; - result = reg_useable(reg, dev, nodeid, link); - if (result == 1) { - /* I have been allocated this one */ - break; - } - else if (result > 1) { - /* I have a free register pair */ - free_reg = reg; - } - } - if (reg > 0xb8) { - reg = free_reg; - } - if (reg > 0) { - resource = new_resource(dev, IOINDEX(0x100 + reg, link)); - } - return resource; + return amdk8_find_reg(dev, nodeid, link, 0xc0, 0xd8); +} + +static unsigned amdk8_find_mempair(device_t dev, unsigned nodeid, unsigned link) +{ + return amdk8_find_reg(dev, nodeid, link, 0x80, 0xb8); } static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link) @@ -372,7 +338,7 @@ static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link) struct resource *resource; /* Initialize the io space constraints on the current bus */ - resource = amdk8_find_iopair(dev, nodeid, link); + resource = new_resource(dev, IOINDEX(0, link)); if (resource) { resource->base = 0; resource->size = 0; @@ -383,7 +349,7 @@ static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link) } /* Initialize the prefetchable memory constraints on the current bus */ - resource = amdk8_find_mempair(dev, nodeid, link); + resource = new_resource(dev, IOINDEX(2, link)); if (resource) { resource->base = 0; resource->size = 0; @@ -397,7 +363,7 @@ static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link) } /* Initialize the memory constraints on the current bus */ - resource = amdk8_find_mempair(dev, nodeid, link); + resource = new_resource(dev, IOINDEX(1, link)); if (resource) { resource->base = 0; resource->size = 0; @@ -408,6 +374,8 @@ static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link) } } +static void amdk8_create_vga_resource(device_t dev, unsigned nodeid); + static void amdk8_read_resources(device_t dev) { unsigned nodeid, link; @@ -417,6 +385,8 @@ static void amdk8_read_resources(device_t dev) amdk8_link_read_bases(dev, nodeid, link); } } + + amdk8_create_vga_resource(dev, nodeid); } static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned nodeid) @@ -518,8 +488,6 @@ static void amdk8_create_vga_resource(device_t dev, unsigned nodeid) { struct resource *resource; unsigned link; - uint32_t base, limit; - unsigned reg; /* find out which link the VGA card is connected, * we only deal with the 'first' vga card */ @@ -543,31 +511,17 @@ static void amdk8_create_vga_resource(device_t dev, unsigned nodeid) printk_debug("VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link); - /* allocate a temp resrouce for legacy VGA buffer */ - resource = amdk8_find_mempair(dev, nodeid, link); + /* allocate a temp resource for the legacy VGA buffer */ + resource = new_resource(dev, IOINDEX(4, link)); if(!resource){ - printk_debug("VGA: Can not find free mmio reg for legacy VGA buffer\n"); + printk_debug("VGA: %s out of resources.\n", dev_path(dev)); return; } resource->base = 0xa0000; resource->size = 0x20000; - - /* write the resource to the hardware */ - reg = resource->index & 0xfc; - base = f1_read_config32(reg); - limit = f1_read_config32(reg + 0x4); - base &= 0x000000f0; - base |= (resource->base >> 8) & 0xffffff00; - base |= 3; - limit &= 0x00000048; - limit |= (resource_end(resource) >> 8) & 0xffffff00; - limit |= (resource->index & 3) << 4; - limit |= (nodeid & 7); - f1_write_config32(reg + 0x4, limit); - f1_write_config32(reg, base); - - /* release the temp resource */ - resource->flags = 0; + resource->limit = 0xffffffff; + resource->flags = IORESOURCE_FIXED | IORESOURCE_MEM | + IORESOURCE_ASSIGNED; } static void amdk8_set_resources(device_t dev) @@ -578,13 +532,36 @@ static void amdk8_set_resources(device_t dev) /* Find the nodeid */ nodeid = amdk8_nodeid(dev); - amdk8_create_vga_resource(dev, nodeid); - /* Set each resource we have found */ for(i = 0; i < dev->resources; i++) { - amdk8_set_resource(dev, &dev->resource[i], nodeid); + struct resource *res = &dev->resource[i]; + struct resource *old = NULL; + unsigned index; + + if (res->size == 0) /* No need to allocate registers. */ + continue; + + if (res->flags & IORESOURCE_IO) + index = amdk8_find_iopair(dev, nodeid, + IOINDEX_LINK(res->index)); + else + index = amdk8_find_mempair(dev, nodeid, + IOINDEX_LINK(res->index)); + + old = probe_resource(dev, index); + if (old) { + res->index = old->index; + old->index = 0; + old->flags = 0; + } + else + res->index = index; + + amdk8_set_resource(dev, res, nodeid); } + compact_resources(dev); + for(link = 0; link < dev->links; link++) { struct bus *bus; bus = &dev->link[link]; @@ -634,7 +611,6 @@ struct chip_operations northbridge_amd_amdk8_ops = { static void amdk8_domain_read_resources(device_t dev) { - struct resource *resource; unsigned reg; /* Find the already assigned resource pairs */ @@ -652,10 +628,12 @@ static void amdk8_domain_read_resources(device_t dev) reg_dev = __f0_dev[nodeid]; if (reg_dev) { /* Reserve the resource */ - struct resource *reg_resource; - reg_resource = new_resource(reg_dev, IOINDEX(0x100 + reg, link)); - if (reg_resource) { - reg_resource->flags = 1; + struct resource *res; + res = new_resource(reg_dev, IOINDEX(0x100 + reg, link)); + if (res) { + res->base = base; + res->limit = limit; + res->flags = 1; } } } @@ -691,7 +669,8 @@ static void tolm_test(void *gp, struct device *dev, struct resource *new) struct resource **best_p = gp; struct resource *best; best = *best_p; - if (!best || (best->base > new->base)) { + /* Skip VGA. */ + if (!best || (best->base > new->base && new->base > 0xa0000)) { best = new; } *best_p = best; @@ -725,15 +704,14 @@ static struct hw_mem_hole_info get_hw_mem_hole_info(void) mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK; mem_hole.node_id = -1; - for (i = 0; i < FX_DEVS; i++) { + for (i = 0; i < fx_devs; i++) { uint32_t base; uint32_t hole; base = f1_read_config32(0x40 + (i << 3)); if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) { continue; } - if (!__f1_dev[i]) - continue; + hole = pci_read_config32(__f1_dev[i], 0xf0); if(hole & 1) { // we find the hole mem_hole.hole_startk = (hole & (0xff<<24)) >> 10; @@ -769,9 +747,10 @@ static struct hw_mem_hole_info get_hw_mem_hole_info(void) return mem_hole; } -static void disable_hoist_memory(unsigned long hole_startk, int i) + +static void disable_hoist_memory(unsigned long hole_startk, int node_id) { - int ii; + int i; device_t dev; uint32_t base, limit; uint32_t hoist; @@ -787,33 +766,35 @@ static void disable_hoist_memory(unsigned long hole_startk, int i) hole_sizek = (4*1024*1024) - hole_startk; - for(ii=7;ii>i;ii--) { + for(i=7;i>node_id;i--) { - base = f1_read_config32(0x40 + (ii << 3)); + base = f1_read_config32(0x40 + (i << 3)); if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) { continue; } - limit = f1_read_config32(0x44 + (ii << 3)); - f1_write_config32(0x44 + (ii << 3),limit - (hole_sizek << 2)); - f1_write_config32(0x40 + (ii << 3),base - (hole_sizek << 2)); + limit = f1_read_config32(0x44 + (i << 3)); + f1_write_config32(0x44 + (i << 3),limit - (hole_sizek << 2)); + f1_write_config32(0x40 + (i << 3),base - (hole_sizek << 2)); } - limit = f1_read_config32(0x44 + (i << 3)); - f1_write_config32(0x44 + (i << 3),limit - (hole_sizek << 2)); - dev = __f1_dev[i]; - if (dev) { - hoist = pci_read_config32(dev, 0xf0); - if(hoist & 1) { - pci_write_config32(dev, 0xf0, 0); - } else { - base = pci_read_config32(dev, 0x40 + (i << 3)); - f1_write_config32(0x40 + (i << 3),base - (hole_sizek << 2)); - } + limit = f1_read_config32(0x44 + (node_id << 3)); + f1_write_config32(0x44 + (node_id << 3),limit - (hole_sizek << 2)); + dev = __f1_dev[node_id]; + if (dev == NULL) { + printk_err("%s: node %x is NULL!\n", __func__, node_id); + return; + } + hoist = pci_read_config32(dev, 0xf0); + if(hoist & 1) + pci_write_config32(dev, 0xf0, 0); + else { + base = pci_read_config32(dev, 0x40 + (node_id << 3)); + f1_write_config32(0x40 + (node_id << 3),base - (hole_sizek << 2)); } } -static uint32_t hoist_memory(unsigned long hole_startk, int i) +static uint32_t hoist_memory(unsigned long hole_startk, int node_id) { - int ii; + int i; uint32_t carry_over; device_t dev; uint32_t base, limit; @@ -822,27 +803,27 @@ static uint32_t hoist_memory(unsigned long hole_startk, int i) carry_over = (4*1024*1024) - hole_startk; - for(ii=7;ii>i;ii--) { + for(i=7;i>node_id;i--) { - base = f1_read_config32(0x40 + (ii << 3)); + base = f1_read_config32(0x40 + (i << 3)); if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) { continue; } - limit = f1_read_config32(0x44 + (ii << 3)); - f1_write_config32(0x44 + (ii << 3),limit + (carry_over << 2)); - f1_write_config32(0x40 + (ii << 3),base + (carry_over << 2)); + limit = f1_read_config32(0x44 + (i << 3)); + f1_write_config32(0x44 + (i << 3),limit + (carry_over << 2)); + f1_write_config32(0x40 + (i << 3),base + (carry_over << 2)); } - limit = f1_read_config32(0x44 + (i << 3)); - f1_write_config32(0x44 + (i << 3),limit + (carry_over << 2)); - dev = __f1_dev[i]; - base = pci_read_config32(dev, 0x40 + (i << 3)); + limit = f1_read_config32(0x44 + (node_id << 3)); + f1_write_config32(0x44 + (node_id << 3),limit + (carry_over << 2)); + dev = __f1_dev[node_id]; + base = pci_read_config32(dev, 0x40 + (node_id << 3)); basek = (base & 0xffff0000) >> 2; if(basek == hole_startk) { //don't need set memhole here, because hole off set will be 0, overflow //so need to change base reg instead, new basek will be 4*1024*1024 base &= 0x0000ffff; base |= (4*1024*1024)<<2; - f1_write_config32(0x40 + (i<<3), base); + f1_write_config32(0x40 + (node_id<<3), base); } else if (dev) { @@ -980,7 +961,7 @@ static void amdk8_domain_set_resources(device_t dev) #if CONFIG_HW_MEM_HOLE_SIZE_AUTO_INC == 1 //We need to double check if the mmio_basek is valid for hole setting, if it is equal to basek, we need to decrease it some uint32_t basek_pri; - for (i = 0; i < FX_DEVS; i++) { + for (i = 0; i < fx_devs; i++) { uint32_t base; uint32_t basek; base = f1_read_config32(0x40 + (i << 3)); @@ -1005,7 +986,7 @@ static void amdk8_domain_set_resources(device_t dev) #endif idx = 0x10; - for(i = 0; i < FX_DEVS; i++) { + for(i = 0; i < fx_devs; i++) { uint32_t base, limit; unsigned basek, limitk, sizek; base = f1_read_config32(0x40 + (i << 3)); @@ -1043,7 +1024,7 @@ static void amdk8_domain_set_resources(device_t dev) /* Leave some space for ACPI, PIRQ and MP tables */ high_tables_base = (mmio_basek - HIGH_TABLES_SIZE) * 1024; high_tables_size = HIGH_TABLES_SIZE * 1024; - printk_debug("(split)%xK table at =%08llx\n", HIGH_TABLES_SIZE, + printk_debug(" split: %dK table at =%08llx\n", HIGH_TABLES_SIZE, high_tables_base); } #endif @@ -1100,7 +1081,7 @@ static unsigned int amdk8_domain_scan_bus(device_t dev, unsigned int max) * Including enabling relaxed ordering if it is safe. */ get_fx_devs(); - for(i = 0; i < FX_DEVS; i++) { + for(i = 0; i < fx_devs; i++) { device_t f0_dev; f0_dev = __f0_dev[i]; if (f0_dev && f0_dev->enabled) { |