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 <damien@zamaudio.com> Reviewed-on: https://review.coreboot.org/13125 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Tested-by: build bot (Jenkins)
This commit is contained in:
parent
43f16f8dd8
commit
9fb08f55a8
|
@ -26,25 +26,24 @@
|
||||||
#include <cpu/cpu.h>
|
#include <cpu/cpu.h>
|
||||||
#include <boot/tables.h>
|
#include <boot/tables.h>
|
||||||
#include <arch/acpi.h>
|
#include <arch/acpi.h>
|
||||||
|
#include <northbridge/intel/x4x/iomap.h>
|
||||||
#include <northbridge/intel/x4x/chip.h>
|
#include <northbridge/intel/x4x/chip.h>
|
||||||
#include <northbridge/intel/x4x/x4x.h>
|
#include <northbridge/intel/x4x/x4x.h>
|
||||||
|
#include <cbmem.h>
|
||||||
/* 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;
|
|
||||||
|
|
||||||
static void mch_domain_read_resources(device_t dev)
|
static void mch_domain_read_resources(device_t dev)
|
||||||
{
|
{
|
||||||
|
u8 index;
|
||||||
u64 tom, touud;
|
u64 tom, touud;
|
||||||
u32 tomk, tsegk, tolud, usable_tomk;
|
u32 tomk, tseg_sizek, tolud, usable_tomk;
|
||||||
u32 pcie_config_base, pcie_config_size;
|
u32 pcie_config_base, pcie_config_size;
|
||||||
u32 uma_sizek = 0;
|
u32 uma_sizek = 0;
|
||||||
|
|
||||||
|
const u32 top32memk = 4 * (GiB / KiB);
|
||||||
|
index = 3;
|
||||||
|
|
||||||
/* 1024KiB TSEG */
|
/* 1024KiB TSEG */
|
||||||
tsegk = 1 << 10;
|
tseg_sizek = 1024;
|
||||||
|
|
||||||
pci_domain_read_resources(dev);
|
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);
|
const u32 gsm_sizek = decode_igd_gtt_size((ggc >> 8) & 0xf);
|
||||||
printk(BIOS_DEBUG, " and %uM GTT\n", gsm_sizek >> 10);
|
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;
|
usable_tomk = tomk - uma_sizek;
|
||||||
|
|
||||||
printk(BIOS_INFO, "Available memory below 4GB: %uM\n", usable_tomk >> 10);
|
printk(BIOS_INFO, "Available memory below 4GB: %uM\n", usable_tomk >> 10);
|
||||||
|
|
||||||
/* Report the memory regions */
|
/* Report the memory regions */
|
||||||
ram_resource(dev, 3, 0, legacy_hole_base_k);
|
ram_resource(dev, index++, 0, 0xa0000 >> 10);
|
||||||
ram_resource(dev, 4, legacy_hole_base_k + legacy_hole_size_k,
|
ram_resource(dev, index++, 1*MiB >> 10, (usable_tomk - (1*MiB >> 10)));
|
||||||
(usable_tomk - (legacy_hole_base_k + legacy_hole_size_k)));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If >= 4GB installed then memory from TOLUD to 4GB
|
* If >= 4GB installed then memory from TOLUD to 4GB
|
||||||
* is remapped above TOM, TOUUD will account for both
|
* is remapped above TOM, TOUUD will account for both
|
||||||
*/
|
*/
|
||||||
touud >>= 10; /* Convert to KB */
|
touud >>= 10; /* Convert to KB */
|
||||||
if (touud > 4096 * 1024) {
|
if (touud > top32memk) {
|
||||||
ram_resource(dev, 5, 4096 * 1024, touud - (4096 * 1024));
|
ram_resource(dev, index++, top32memk, touud - top32memk);
|
||||||
printk(BIOS_INFO, "Available memory above 4GB: %lluM\n",
|
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 "
|
printk(BIOS_DEBUG, "Adding UMA memory area base=0x%08x "
|
||||||
"size=0x%08x\n", usable_tomk << 10, uma_sizek << 10);
|
"size=0x%08x\n", usable_tomk << 10, uma_sizek << 10);
|
||||||
fixed_mem_resource(dev, 6, usable_tomk, uma_sizek, IORESOURCE_RESERVE);
|
fixed_mem_resource(dev, index++, usable_tomk, uma_sizek,
|
||||||
|
IORESOURCE_RESERVE);
|
||||||
|
|
||||||
/* Some strange hole, reserve it */
|
/* Reserve high memory where the NB BARs are up to 4GiB */
|
||||||
//fixed_mem_resource(dev, 7, usable_tomk - (0x02000000 >> 10), 0x02000000 >> 10, IORESOURCE_RESERVE);
|
fixed_mem_resource(dev, index++, DEFAULT_HECIBAR >> 10,
|
||||||
|
top32memk - (DEFAULT_HECIBAR >> 10),
|
||||||
|
IORESOURCE_RESERVE);
|
||||||
|
|
||||||
if (decode_pciebar(&pcie_config_base, &pcie_config_size)) {
|
if (decode_pciebar(&pcie_config_base, &pcie_config_size)) {
|
||||||
printk(BIOS_DEBUG, "Adding PCIe config bar base=0x%08x "
|
printk(BIOS_DEBUG, "Adding PCIe config bar base=0x%08x "
|
||||||
"size=0x%x\n", pcie_config_base, pcie_config_size);
|
"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);
|
pcie_config_size >> 10, IORESOURCE_RESERVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_top_of_ram(usable_tomk * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mch_domain_set_resources(device_t dev)
|
static void mch_domain_set_resources(device_t dev)
|
||||||
{
|
{
|
||||||
struct resource *resource;
|
struct resource *res;
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 3; i < 8; ++i) {
|
for (res = dev->resource_list; res; res = res->next)
|
||||||
/* Report read resources. */
|
report_resource_stored(dev, res, "");
|
||||||
resource = probe_resource(dev, i);
|
|
||||||
if (resource)
|
|
||||||
report_resource_stored(dev, resource, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
assign_resources(dev->link_list);
|
assign_resources(dev->link_list);
|
||||||
}
|
}
|
||||||
|
@ -141,10 +139,9 @@ static void mch_domain_init(device_t dev)
|
||||||
static struct device_operations pci_domain_ops = {
|
static struct device_operations pci_domain_ops = {
|
||||||
.read_resources = mch_domain_read_resources,
|
.read_resources = mch_domain_read_resources,
|
||||||
.set_resources = mch_domain_set_resources,
|
.set_resources = mch_domain_set_resources,
|
||||||
.enable_resources = NULL,
|
|
||||||
.init = mch_domain_init,
|
.init = mch_domain_init,
|
||||||
.scan_bus = pci_domain_scan_bus,
|
.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,
|
.write_acpi_tables = northbridge_write_acpi_tables,
|
||||||
.acpi_fill_ssdt_generator = generate_cpu_entries,
|
.acpi_fill_ssdt_generator = generate_cpu_entries,
|
||||||
};
|
};
|
||||||
|
@ -160,7 +157,6 @@ static struct device_operations cpu_bus_ops = {
|
||||||
.set_resources = DEVICE_NOOP,
|
.set_resources = DEVICE_NOOP,
|
||||||
.enable_resources = DEVICE_NOOP,
|
.enable_resources = DEVICE_NOOP,
|
||||||
.init = cpu_bus_init,
|
.init = cpu_bus_init,
|
||||||
.scan_bus = 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "x4x.h"
|
#include "x4x.h"
|
||||||
|
|
||||||
|
#define ME_UMA_SIZEMB 0
|
||||||
|
|
||||||
static inline void barrier(void)
|
static inline void barrier(void)
|
||||||
{
|
{
|
||||||
asm volatile("mfence":::);
|
asm volatile("mfence":::);
|
||||||
|
@ -1465,7 +1467,8 @@ static void dradrb_ddr2(struct sysinfo *s)
|
||||||
u32 dra0;
|
u32 dra0;
|
||||||
u32 dra1;
|
u32 dra1;
|
||||||
u16 totalmemorymb;
|
u16 totalmemorymb;
|
||||||
u16 size, offset;
|
u32 size, offset;
|
||||||
|
u32 size0, size1;
|
||||||
u8 dratab[2][2][2][4] = {
|
u8 dratab[2][2][2][4] = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -1562,35 +1565,51 @@ static void dradrb_ddr2(struct sysinfo *s)
|
||||||
MCHBAR16(0x606 + 2*msbpos(rankpop1)) = c0drb + c1drb;
|
MCHBAR16(0x606 + 2*msbpos(rankpop1)) = c0drb + c1drb;
|
||||||
}
|
}
|
||||||
|
|
||||||
MCHBAR8(0x111) = MCHBAR8(0x111) | 0x2;
|
/* Populated channel sizes in MiB */
|
||||||
MCHBAR16(0x104) = 0;
|
size0 = s->channel_capacity[0];
|
||||||
size = s->channel_capacity[0] + s->channel_capacity[1];
|
size1 = s->channel_capacity[1];
|
||||||
MCHBAR16(0x102) = size;
|
|
||||||
|
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;
|
map = 0;
|
||||||
if (s->channel_capacity[0] == 0) {
|
if (size0 == 0) {
|
||||||
map = 0;
|
map = 0;
|
||||||
} else if (s->channel_capacity[1] == 0) {
|
} else if (size1 == 0) {
|
||||||
map |= 0x20;
|
map |= 0x20;
|
||||||
} else {
|
} else {
|
||||||
map |= 0x40;
|
map |= 0x40;
|
||||||
}
|
}
|
||||||
map |= 0x18;
|
if (size == 0) {
|
||||||
if (s->channel_capacity[0] <= s->channel_capacity[1]) {
|
map |= 0x18;
|
||||||
map |= 0x5;
|
}
|
||||||
} else if (s->channel_capacity[0] > s->channel_capacity[1]) {
|
|
||||||
|
if (size0 - ME_UMA_SIZEMB >= size1) {
|
||||||
map |= 0x4;
|
map |= 0x4;
|
||||||
}
|
}
|
||||||
MCHBAR8(0x110) = map;
|
MCHBAR8(0x110) = map;
|
||||||
MCHBAR16(0x10e) = 0;
|
MCHBAR16(0x10e) = 0;
|
||||||
if (s->channel_capacity[1] != 0) {
|
|
||||||
|
if (size1 != 0) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
} else if (s->channel_capacity[0] > s->channel_capacity[1]) {
|
} else if ((size0 > size1) && ((map & 0x7) == 0x4)) {
|
||||||
offset = size;
|
offset = size/2 + (size0 + size1 - size);
|
||||||
} else {
|
} else {
|
||||||
offset = 0;
|
offset = size/2 + ME_UMA_SIZEMB;
|
||||||
}
|
}
|
||||||
MCHBAR16(0x108) = offset;
|
MCHBAR16(0x108) = offset;
|
||||||
MCHBAR16(0x10a) = 0;
|
MCHBAR16(0x10a) = size/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mmap_ddr2(struct sysinfo *s)
|
static void mmap_ddr2(struct sysinfo *s)
|
||||||
|
@ -1605,7 +1624,7 @@ static void mmap_ddr2(struct sysinfo *s)
|
||||||
gttsize = ggc2gtt[(ggc & 0xf00) >> 8];
|
gttsize = ggc2gtt[(ggc & 0xf00) >> 8];
|
||||||
tsegsize = 1; // 1MB TSEG
|
tsegsize = 1; // 1MB TSEG
|
||||||
mmiosize = 0x400; // 1GB MMIO
|
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);
|
tolud = MIN(0x1000 - mmiosize, tom);
|
||||||
touud = tom;
|
touud = tom;
|
||||||
gfxbase = tolud - gfxsize;
|
gfxbase = tolud - gfxsize;
|
||||||
|
|
Loading…
Reference in New Issue