summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/stoneyridge/northbridge.c164
1 files changed, 40 insertions, 124 deletions
diff --git a/src/soc/amd/stoneyridge/northbridge.c b/src/soc/amd/stoneyridge/northbridge.c
index 2449077313..c640c1f00c 100644
--- a/src/soc/amd/stoneyridge/northbridge.c
+++ b/src/soc/amd/stoneyridge/northbridge.c
@@ -40,35 +40,6 @@
#include <stdlib.h>
#include <string.h>
-typedef struct dram_base_mask {
- u32 base; /* [47:27] at [28:8] */
- u32 mask; /* [47:27] at [28:8] and enable at bit 0 */
-} dram_base_mask_t;
-
-static dram_base_mask_t get_dram_base_mask(void)
-{
- device_t dev = dev_find_slot(0, ADDR_DEVFN);
- dram_base_mask_t d;
- u32 temp;
-
- /* [39:24] at [31:16] */
- temp = pci_read_config32(dev, 0x44);
-
- /* mask out DramMask [26:24] too */
- d.mask = ((temp & 0xfff80000) >> (8 + 3));
-
- /* [47:40] at [7:0] */
- temp = pci_read_config32(dev, 0x144) & 0xff;
- d.mask |= temp << 21;
-
- temp = pci_read_config32(dev, 0x40);
- d.mask |= (temp & 1); /* enable bit */
- d.base = ((temp & 0xfff80000) >> (8 + 3));
- temp = pci_read_config32(dev, 0x140) & 0xff;
- d.base |= temp << 21;
- return d;
-}
-
static void set_io_addr_reg(device_t dev, u32 nodeid, u32 linkn, u32 reg,
u32 io_min, u32 io_max)
{
@@ -433,109 +404,54 @@ void domain_enable_resources(device_t dev)
void domain_set_resources(device_t dev)
{
- unsigned long mmio_basek;
- u32 pci_tolm;
- u32 hole;
- int idx;
- struct bus *link;
- void *tseg_base;
- size_t tseg_size;
+ uint64_t uma_base = get_uma_base();
+ uint32_t uma_size = get_uma_size();
+ uint32_t mem_useable = (uintptr_t)cbmem_top();
+ msr_t tom = rdmsr(TOP_MEM);
+ msr_t high_tom = rdmsr(TOP_MEM2);
+ uint64_t high_mem_useable;
+ int idx = 0x10;
- pci_tolm = 0xffffffffUL;
- for (link = dev->link_list ; link ; link = link->next)
- pci_tolm = find_pci_tolm(link);
+ /* 0x0 -> 0x9ffff */
+ ram_resource(dev, idx++, 0, 0xa0000 / KiB);
- /* Start with alignment supportable in variable MTRR */
- mmio_basek = ALIGN_DOWN(pci_tolm, 4 * KiB) / KiB;
+ /* 0xa0000 -> 0xbffff: legacy VGA */
+ mmio_resource(dev, idx++, 0xa0000 / KiB, 0x20000 / KiB);
+
+ /* 0xc0000 -> 0xfffff: Option ROM */
+ reserved_ram_resource(dev, idx++, 0xc0000 / KiB, 0x40000 / KiB);
/*
- * AGESA may have programmed the memory hole and rounded down to a
- * 128MB boundary. If we find it's valid, adjust mmio_basek downward
- * to the hole bottom. D18F1xF0[DramHoleBase] is granular to 16MB.
+ * 0x100000 (1MiB) -> low top useable RAM
+ * cbmem_top() accounts for low UMA and TSEG if they are used.
*/
- hole = pci_read_config32(dev_find_slot(0, ADDR_DEVFN), D18F1_DRAM_HOLE);
- if (hole & DRAM_HOLE_VALID)
- mmio_basek = min(mmio_basek, ALIGN_DOWN(hole, 16 * MiB) / KiB);
-
- idx = 0x10;
- dram_base_mask_t d;
- resource_t basek, limitk, sizek; /* 4 1T */
-
- d = get_dram_base_mask();
-
- if ((d.mask & 1)) { /* if enabled... */
- /* could overflow, we may lose 6 bit here */
- basek = ((resource_t)(d.base & 0x1fffff00)) << 9;
- limitk = ((resource_t)(((d.mask & ~1) + 0x000ff)
- & 0x1fffff00)) << 9;
-
- sizek = limitk - basek;
-
- /* see if we need a hole from 0xa0000 to 0xbffff */
- if ((basek < ((8 * 64) + (8 * 16))) && (sizek > ((8 * 64) +
- (16 * 16)))) {
- ram_resource(dev, idx, basek,
- ((8 * 64) + (8 * 16)) - basek);
- idx += 0x10;
- basek = (8 * 64) + (16 * 16);
- sizek = limitk - ((8 * 64) + (16 * 16));
-
- }
-
- /* split the region to accommodate pci memory space */
- if ((basek < 4 * 1024 * 1024) && (limitk > mmio_basek)) {
- if (basek <= mmio_basek) {
- unsigned int pre_sizek;
- pre_sizek = mmio_basek - basek;
- if (pre_sizek > 0) {
- ram_resource(dev, idx, basek,
- pre_sizek);
- idx += 0x10;
- sizek -= pre_sizek;
- }
- basek = mmio_basek;
- }
- if ((basek + sizek) <= 4 * 1024 * 1024) {
- sizek = 0;
- } else {
- uint64_t topmem2 = bsp_topmem2();
- basek = 4 * 1024 * 1024;
- sizek = topmem2 / 1024 - basek;
- }
+ ram_resource(dev, idx++, (1 * MiB) / KiB,
+ (mem_useable - (1 * MiB)) / KiB);
+
+ /* Low top useable RAM -> Low top RAM (bottom pci mmio hole) */
+ reserved_ram_resource(dev, idx++, mem_useable / KiB,
+ (tom.lo - mem_useable) / KiB);
+
+ /* If there is memory above 4GiB */
+ if (high_tom.hi) {
+ /* 4GiB -> high top useable */
+ if (uma_base >= (4ull * GiB))
+ high_mem_useable = uma_base;
+ else
+ high_mem_useable = ((uint64_t)high_tom.lo |
+ ((uint64_t)high_tom.hi << 32));
+
+ ram_resource(dev, idx++, (4ull * GiB) / KiB,
+ ((high_mem_useable - (4ull * GiB)) / KiB));
+
+ /* High top useable RAM -> high top RAM */
+ if (uma_base >= (4ull * GiB)) {
+ reserved_ram_resource(dev, idx++, uma_base / KiB,
+ uma_size / KiB);
}
-
- ram_resource(dev, idx, basek, sizek);
- printk(BIOS_DEBUG, "node 0: mmio_basek=%08lx, basek=%08llx,"
- " limitk=%08llx\n", mmio_basek, basek, limitk);
}
- /* UMA is not set up yet, but infer the base & size to make cacheable */
- uint32_t uma_base = restore_top_of_low_cacheable();
- if (uma_base != bsp_topmem()) {
- uint32_t uma_size = bsp_topmem() - uma_base;
- printk(BIOS_INFO, "%s: uma size 0x%08x, memory start 0x%08x\n",
- __func__, uma_size, uma_base);
- reserved_ram_resource(dev, 7, uma_base / KiB, uma_size / KiB);
- }
-
- for (link = dev->link_list ; link ; link = link->next)
- if (link->children)
- assign_resources(link);
-
- /*
- * Reserve everything between A segment and 1MB:
- *
- * 0xa0000 - 0xbffff: legacy VGA
- * 0xc0000 - 0xfffff: RAM
- */
- mmio_resource(dev, 0xa0000, 0xa0000 / KiB, 0x20000 / KiB);
- reserved_ram_resource(dev, 0xc0000, 0xc0000 / KiB, 0x40000 / KiB);
-
- /* Reserve TSEG */
- smm_region_info(&tseg_base, &tseg_size);
- idx += 0x10;
- reserved_ram_resource(dev, idx, (unsigned long)tseg_base/KiB,
- tseg_size/KiB);
+ assign_resources(dev->link_list);
}
/*********************************************************************