From 9fb08f55a86467ba1a36d4f5e6196a77b534778d Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Fri, 22 Jan 2016 18:56:23 +1100 Subject: nb/intel/x4x: Fix memory hole with both channels populated Previously, 0xa0000000 to 0xc0000000 needed to be reserved as a non-usable memory hole because it would hang on memory i/o. Memtest86+ now passes with no errors on both channels populated. Tested on GA-G41M-ES2L with 2x2GiB sticks of ram. Change-Id: Ib52a63a80f5f69c16841f10ddb896ab3c7d30462 Signed-off-by: Damien Zammit Reviewed-on: https://review.coreboot.org/13125 Reviewed-by: Aaron Durbin Tested-by: build bot (Jenkins) --- src/northbridge/intel/x4x/northbridge.c | 62 +++++++++++++++----------------- src/northbridge/intel/x4x/raminit_ddr2.c | 53 ++++++++++++++++++--------- 2 files changed, 65 insertions(+), 50 deletions(-) (limited to 'src/northbridge') diff --git a/src/northbridge/intel/x4x/northbridge.c b/src/northbridge/intel/x4x/northbridge.c index c5a89682a7..0fe8901957 100644 --- a/src/northbridge/intel/x4x/northbridge.c +++ b/src/northbridge/intel/x4x/northbridge.c @@ -26,25 +26,24 @@ #include #include #include +#include #include #include - -/* Reserve segments A and B: - * - * 0xa0000 - 0xbffff: legacy VGA - */ -static const int legacy_hole_base_k = 0xa0000 / 1024; -static const int legacy_hole_size_k = 128; +#include static void mch_domain_read_resources(device_t dev) { + u8 index; u64 tom, touud; - u32 tomk, tsegk, tolud, usable_tomk; + u32 tomk, tseg_sizek, tolud, usable_tomk; u32 pcie_config_base, pcie_config_size; u32 uma_sizek = 0; + const u32 top32memk = 4 * (GiB / KiB); + index = 3; + /* 1024KiB TSEG */ - tsegk = 1 << 10; + tseg_sizek = 1024; pci_domain_read_resources(dev); @@ -77,53 +76,52 @@ static void mch_domain_read_resources(device_t dev) const u32 gsm_sizek = decode_igd_gtt_size((ggc >> 8) & 0xf); printk(BIOS_DEBUG, " and %uM GTT\n", gsm_sizek >> 10); - uma_sizek = gms_sizek + gsm_sizek + tsegk; + uma_sizek = gms_sizek + gsm_sizek + tseg_sizek; usable_tomk = tomk - uma_sizek; printk(BIOS_INFO, "Available memory below 4GB: %uM\n", usable_tomk >> 10); /* Report the memory regions */ - ram_resource(dev, 3, 0, legacy_hole_base_k); - ram_resource(dev, 4, legacy_hole_base_k + legacy_hole_size_k, - (usable_tomk - (legacy_hole_base_k + legacy_hole_size_k))); + ram_resource(dev, index++, 0, 0xa0000 >> 10); + ram_resource(dev, index++, 1*MiB >> 10, (usable_tomk - (1*MiB >> 10))); /* * If >= 4GB installed then memory from TOLUD to 4GB * is remapped above TOM, TOUUD will account for both */ touud >>= 10; /* Convert to KB */ - if (touud > 4096 * 1024) { - ram_resource(dev, 5, 4096 * 1024, touud - (4096 * 1024)); + if (touud > top32memk) { + ram_resource(dev, index++, top32memk, touud - top32memk); printk(BIOS_INFO, "Available memory above 4GB: %lluM\n", - (touud >> 10) - 4096); + (touud - top32memk) >> 10); } printk(BIOS_DEBUG, "Adding UMA memory area base=0x%08x " - "size=0x%08x\n", usable_tomk << 10, uma_sizek << 10); - fixed_mem_resource(dev, 6, usable_tomk, uma_sizek, IORESOURCE_RESERVE); + "size=0x%08x\n", usable_tomk << 10, uma_sizek << 10); + fixed_mem_resource(dev, index++, usable_tomk, uma_sizek, + IORESOURCE_RESERVE); - /* Some strange hole, reserve it */ - //fixed_mem_resource(dev, 7, usable_tomk - (0x02000000 >> 10), 0x02000000 >> 10, IORESOURCE_RESERVE); + /* Reserve high memory where the NB BARs are up to 4GiB */ + fixed_mem_resource(dev, index++, DEFAULT_HECIBAR >> 10, + top32memk - (DEFAULT_HECIBAR >> 10), + IORESOURCE_RESERVE); if (decode_pciebar(&pcie_config_base, &pcie_config_size)) { printk(BIOS_DEBUG, "Adding PCIe config bar base=0x%08x " "size=0x%x\n", pcie_config_base, pcie_config_size); - fixed_mem_resource(dev, 7, pcie_config_base >> 10, + fixed_mem_resource(dev, index++, pcie_config_base >> 10, pcie_config_size >> 10, IORESOURCE_RESERVE); } + + set_top_of_ram(usable_tomk * 1024); } static void mch_domain_set_resources(device_t dev) { - struct resource *resource; - int i; - - for (i = 3; i < 8; ++i) { - /* Report read resources. */ - resource = probe_resource(dev, i); - if (resource) - report_resource_stored(dev, resource, ""); - } + struct resource *res; + + for (res = dev->resource_list; res; res = res->next) + report_resource_stored(dev, res, ""); assign_resources(dev->link_list); } @@ -141,10 +139,9 @@ static void mch_domain_init(device_t dev) static struct device_operations pci_domain_ops = { .read_resources = mch_domain_read_resources, .set_resources = mch_domain_set_resources, - .enable_resources = NULL, .init = mch_domain_init, .scan_bus = pci_domain_scan_bus, - .ops_pci_bus = pci_bus_default_ops, + .ops_pci_bus = pci_bus_default_ops, .write_acpi_tables = northbridge_write_acpi_tables, .acpi_fill_ssdt_generator = generate_cpu_entries, }; @@ -160,7 +157,6 @@ static struct device_operations cpu_bus_ops = { .set_resources = DEVICE_NOOP, .enable_resources = DEVICE_NOOP, .init = cpu_bus_init, - .scan_bus = 0, }; diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c index d77c2c4879..d21924b870 100644 --- a/src/northbridge/intel/x4x/raminit_ddr2.c +++ b/src/northbridge/intel/x4x/raminit_ddr2.c @@ -23,6 +23,8 @@ #include "iomap.h" #include "x4x.h" +#define ME_UMA_SIZEMB 0 + static inline void barrier(void) { asm volatile("mfence":::); @@ -1465,7 +1467,8 @@ static void dradrb_ddr2(struct sysinfo *s) u32 dra0; u32 dra1; u16 totalmemorymb; - u16 size, offset; + u32 size, offset; + u32 size0, size1; u8 dratab[2][2][2][4] = { { { @@ -1562,35 +1565,51 @@ static void dradrb_ddr2(struct sysinfo *s) MCHBAR16(0x606 + 2*msbpos(rankpop1)) = c0drb + c1drb; } - MCHBAR8(0x111) = MCHBAR8(0x111) | 0x2; - MCHBAR16(0x104) = 0; - size = s->channel_capacity[0] + s->channel_capacity[1]; - MCHBAR16(0x102) = size; + /* Populated channel sizes in MiB */ + size0 = s->channel_capacity[0]; + size1 = s->channel_capacity[1]; + + MCHBAR8(0x111) = MCHBAR8(0x111) & ~0x2; + MCHBAR8(0x111) = MCHBAR8(0x111) | (1 << 4); + + /* Set ME UMA size in MiB */ + MCHBAR16(0x100) = ME_UMA_SIZEMB; + + /* Set ME UMA Present bit */ + MCHBAR32(0x111) = MCHBAR32(0x111) | 1; + + size = MIN(size0 - ME_UMA_SIZEMB, size1) * 2; + + MCHBAR16(0x104) = size; + MCHBAR16(0x102) = size0 + size1 - size; + map = 0; - if (s->channel_capacity[0] == 0) { + if (size0 == 0) { map = 0; - } else if (s->channel_capacity[1] == 0) { + } else if (size1 == 0) { map |= 0x20; } else { map |= 0x40; } - map |= 0x18; - if (s->channel_capacity[0] <= s->channel_capacity[1]) { - map |= 0x5; - } else if (s->channel_capacity[0] > s->channel_capacity[1]) { + if (size == 0) { + map |= 0x18; + } + + if (size0 - ME_UMA_SIZEMB >= size1) { map |= 0x4; } MCHBAR8(0x110) = map; MCHBAR16(0x10e) = 0; - if (s->channel_capacity[1] != 0) { + + if (size1 != 0) { offset = 0; - } else if (s->channel_capacity[0] > s->channel_capacity[1]) { - offset = size; + } else if ((size0 > size1) && ((map & 0x7) == 0x4)) { + offset = size/2 + (size0 + size1 - size); } else { - offset = 0; + offset = size/2 + ME_UMA_SIZEMB; } MCHBAR16(0x108) = offset; - MCHBAR16(0x10a) = 0; + MCHBAR16(0x10a) = size/2; } static void mmap_ddr2(struct sysinfo *s) @@ -1605,7 +1624,7 @@ static void mmap_ddr2(struct sysinfo *s) gttsize = ggc2gtt[(ggc & 0xf00) >> 8]; tsegsize = 1; // 1MB TSEG mmiosize = 0x400; // 1GB MMIO - tom = s->channel_capacity[0] + s->channel_capacity[1]; + tom = s->channel_capacity[0] + s->channel_capacity[1] - ME_UMA_SIZEMB; tolud = MIN(0x1000 - mmiosize, tom); touud = tom; gfxbase = tolud - gfxsize; -- cgit v1.2.3