aopen/dxplplusu intel/e7505: Move to EARLY_CBMEM_INIT
With implementation of LATE_CBMEM_INIT, top-of-low-memory
TOLM was adjusted late in ramstage. We do not allow that with
EARLY_CBMEM_INIT so the previous maximum of 1024 MiB of MMIO
space is now used with statically set TOLM.
Also remove support code for the obsolete LATE_CBMEM_INIT
this northbridge used.
Change-Id: Ib3094903d7614d2212fbe1870248962fbc92e412
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/26585
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
diff --git a/src/northbridge/intel/e7505/Kconfig b/src/northbridge/intel/e7505/Kconfig
index 702ba1c..bf35a6d 100644
--- a/src/northbridge/intel/e7505/Kconfig
+++ b/src/northbridge/intel/e7505/Kconfig
@@ -22,7 +22,6 @@
def_bool y
select NO_MMCONF_SUPPORT
select HAVE_DEBUG_RAM_SETUP
- select LATE_CBMEM_INIT
config HW_SCRUBBER
bool
diff --git a/src/northbridge/intel/e7505/Makefile.inc b/src/northbridge/intel/e7505/Makefile.inc
index 89a5b8c..57c870f 100644
--- a/src/northbridge/intel/e7505/Makefile.inc
+++ b/src/northbridge/intel/e7505/Makefile.inc
@@ -1,7 +1,9 @@
ifeq ($(CONFIG_NORTHBRIDGE_INTEL_E7505),y)
ramstage-y += northbridge.c
+ramstage-y += memmap.c
+
romstage-y += raminit.c
romstage-y += debug.c
-
+romstage-y += memmap.c
endif
diff --git a/src/northbridge/intel/e7505/memmap.c b/src/northbridge/intel/e7505/memmap.c
new file mode 100644
index 0000000..4a80608
--- /dev/null
+++ b/src/northbridge/intel/e7505/memmap.c
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+// Use simple device model for this file even in ramstage
+#define __SIMPLE_DEVICE__
+
+#include <arch/io.h>
+#include <arch/cpu.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/intel/romstage.h>
+#include <cpu/x86/mtrr.h>
+#include <program_loading.h>
+#include "e7505.h"
+
+void *cbmem_top(void)
+{
+ pci_devfn_t mch = PCI_DEV(0, 0, 0);
+ uintptr_t tolm;
+
+ /* This is at 128 MiB boundary. */
+ tolm = pci_read_config16(mch, TOLM) >> 11;
+ tolm <<= 27;
+
+ return (void *)tolm;
+}
+
+#define ROMSTAGE_RAM_STACK_SIZE 0x5000
+
+/* setup_stack_and_mtrrs() determines the stack to use after
+ * cache-as-ram is torn down as well as the MTRR settings to use. */
+void *setup_stack_and_mtrrs(void)
+{
+ struct postcar_frame pcf;
+ uintptr_t top_of_ram;
+
+ if (postcar_frame_init(&pcf, ROMSTAGE_RAM_STACK_SIZE))
+ die("Unable to initialize postcar frame.\n");
+
+ /* Cache the ROM as WP just below 4GiB. */
+ postcar_frame_add_mtrr(&pcf, CACHE_ROM_BASE, CACHE_ROM_SIZE,
+ MTRR_TYPE_WRPROT);
+
+ /* Cache RAM as WB from 0 -> CACHE_TMP_RAMTOP. */
+ postcar_frame_add_mtrr(&pcf, 0, CACHE_TMP_RAMTOP, MTRR_TYPE_WRBACK);
+
+ /* Cache CBMEM region as WB. */
+ top_of_ram = (uintptr_t)cbmem_top();
+ postcar_frame_add_mtrr(&pcf, top_of_ram - 8*MiB, 8*MiB,
+ MTRR_TYPE_WRBACK);
+
+ /* Save the number of MTRRs to setup. Return the stack location
+ * pointing to the number of MTRRs.
+ */
+ return postcar_commit_mtrrs(&pcf);
+}
diff --git a/src/northbridge/intel/e7505/northbridge.c b/src/northbridge/intel/e7505/northbridge.c
index ea8b459..6d351a3 100644
--- a/src/northbridge/intel/e7505/northbridge.c
+++ b/src/northbridge/intel/e7505/northbridge.c
@@ -31,84 +31,43 @@
static void mch_domain_read_resources(struct device *dev)
{
+ int idx;
+ unsigned long tomk, tolmk;
+ unsigned long remapbasek, remaplimitk;
+ const unsigned long basek_4G = 4 * (GiB / KiB);
struct device *mc_dev;
- uint32_t pci_tolm;
pci_domain_read_resources(dev);
- pci_tolm = find_pci_tolm(dev->link_list);
- mc_dev = dev->link_list->children;
- if (mc_dev) {
- /* Figure out which areas are/should be occupied by RAM.
- * This is all computed in kilobytes and converted to/from
- * the memory controller right at the edges.
- * Having different variables in different units is
- * too confusing to get right. Kilobytes are good up to
- * 4 Terabytes of RAM...
- */
- uint16_t tolm_r, remapbase_r, remaplimit_r;
- unsigned long tomk, tolmk;
- unsigned long remapbasek, remaplimitk;
- int idx;
+ mc_dev = dev_find_slot(0, PCI_DEVFN(0x0, 0));
+ if (!mc_dev)
+ die("Could not find MCH device\n");
- /* Get the value of the highest DRB. This tells the end of
- * the physical memory. The units are ticks of 64MB
- * i.e. 1 means 64MB.
- */
- tomk = ((unsigned long)pci_read_config8(mc_dev, DRB_ROW_7)) << 16;
- /* Compute the top of Low memory */
- tolmk = pci_tolm >> 10;
- if (tolmk >= tomk) {
- /* The PCI hole does not overlap memory
- * we won't use the remap window.
- */
- tolmk = tomk;
- remapbasek = 0x3ff << 16;
- remaplimitk = 0 << 16;
- }
- else {
- /* The PCI memory hole overlaps memory
- * setup the remap window.
- */
- /* Find the bottom of the remap window
- * is it above 4G?
- */
- remapbasek = 4*1024*1024;
- if (tomk > remapbasek) {
- remapbasek = tomk;
- }
- /* Find the limit of the remap window */
- remaplimitk = (remapbasek + (4*1024*1024 - tolmk) - (1 << 16));
- }
- /* Write the RAM configuration registers,
- * preserving the reserved bits.
- */
- tolm_r = pci_read_config16(mc_dev, TOLM);
- tolm_r = ((tolmk >> 17) << 11) | (tolm_r & 0x7ff);
- pci_write_config16(mc_dev, TOLM, tolm_r);
+ tolmk = pci_read_config16(mc_dev, TOLM) >> 11;
+ tolmk <<= 17;
- remapbase_r = pci_read_config16(mc_dev, REMAPBASE);
- remapbase_r = (remapbasek >> 16) | (remapbase_r & 0xfc00);
- pci_write_config16(mc_dev, REMAPBASE, remapbase_r);
+ tomk = pci_read_config8(mc_dev, DRB_ROW_7);
+ tomk <<= 16;
- remaplimit_r = pci_read_config16(mc_dev, REMAPLIMIT);
- remaplimit_r = (remaplimitk >> 16) | (remaplimit_r & 0xfc00);
- pci_write_config16(mc_dev, REMAPLIMIT, remaplimit_r);
+ /* Remapped region with a 64 MiB granularity in register
+ definition. Limit is inclusive, so add one. */
+ remapbasek = pci_read_config16(mc_dev, REMAPBASE) & 0x3ff;
+ remapbasek <<= 16;
- /* Report the memory regions */
- idx = 10;
- ram_resource(dev, idx++, 0, 640);
- ram_resource(dev, idx++, 768, tolmk - 768);
- if (tomk > 4*1024*1024) {
- ram_resource(dev, idx++, 4096*1024, tomk - 4*1024*1024);
- }
- if (remaplimitk >= remapbasek) {
- ram_resource(dev, idx++, remapbasek,
- (remaplimitk + 64*1024) - remapbasek);
- }
+ remaplimitk = pci_read_config16(mc_dev, REMAPLIMIT) & 0x3ff;
+ remaplimitk += 1;
+ remaplimitk <<= 16;
- set_late_cbmem_top(tolmk * 1024);
- }
+ /* Report the memory regions */
+ idx = 10;
+ ram_resource(dev, idx++, 0, 640);
+ ram_resource(dev, idx++, 768, tolmk - 768);
+
+ if (tomk > basek_4G)
+ ram_resource(dev, idx++, basek_4G, tomk - basek_4G);
+
+ if (remaplimitk > remapbasek)
+ ram_resource(dev, idx++, remapbasek, remaplimitk - remapbasek);
}
static void mch_domain_set_resources(struct device *dev)
diff --git a/src/northbridge/intel/e7505/raminit.c b/src/northbridge/intel/e7505/raminit.c
index f3a2520..7464a72 100644
--- a/src/northbridge/intel/e7505/raminit.c
+++ b/src/northbridge/intel/e7505/raminit.c
@@ -30,8 +30,8 @@
#include <arch/cpu.h>
#include <lib.h>
#include <stdlib.h>
+#include <commonlib/helpers.h>
#include <console/console.h>
-
#include <cpu/x86/mtrr.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/msr.h>
@@ -850,6 +850,12 @@
{
int i;
uint8_t total_dram_64M_multiple = 0;
+ uint64_t tolm, tom;
+ uint16_t reg;
+
+ /* Start with disabled remap range. */
+ uint16_t remapbase_r = 0x3ff;
+ uint16_t remaplimit_r = 0;
// Configure the E7501's DRAM row boundaries
// Start by zeroing out the temporary initial configuration
@@ -879,71 +885,37 @@
configure_dimm_row_boundaries(sz, total_dram_64M_multiple, i);
}
- // Configure the Top Of Low Memory (TOLM) in the E7501
- // This address must be a multiple of 128 MB that is less than 4 GB.
- // NOTE: 16-bit wide TOLM register stores only the highest 5 bits of a 32-bit address
- // in the highest 5 bits.
+ tom = total_dram_64M_multiple * 64ULL * MiB;
- // We set TOLM to the smaller of 0xC0000000 (3 GB) or the total DRAM in the system.
- // This reserves addresses from 0xC0000000 - 0xFFFFFFFF for non-DRAM purposes
- // such as flash and memory-mapped I/O.
+ /* Reserve MMIO space. */
+ tolm = 4ULL * GiB - 1 * GiB;
+ tolm = MIN(tolm, tom);
- // If there is more than 3 GB of DRAM, we define a remap window which
- // makes the DRAM "behind" the reserved region available above the top of physical
- // memory.
+ /* The PCI memory hole overlaps memory setup the remap window. */
+ if (tolm < tom) {
+ uint64_t remapbase = MAX(tom, 4ULL * GiB);
+ uint64_t remaplimit = remapbase + (4ULL * GiB - tolm);
- // NOTE: 0xC0000000 / (64 MB) == 0x30
+ remapbase_r = remapbase / (64 * MiB);
+ remaplimit_r = remaplimit / (64 * MiB);
- if (total_dram_64M_multiple <= 0x30) {
-
- // <= 3 GB total RAM
-
- /* I should really adjust all of this in C after I have resources
- * to all of the pci devices.
- */
-
- // Round up to 128MB granularity
- // SJM: Is "missing" 64 MB of memory a potential issue? Should this round down?
-
- uint8_t total_dram_128M_multiple =
- (total_dram_64M_multiple + 1) >> 1;
-
- // Convert to high 16 bits of address
- uint16_t top_of_low_memory =
- total_dram_128M_multiple << 11;
-
- pci_write_config16(MCHDEV, TOLM,
- top_of_low_memory);
-
- } else {
-
- // > 3 GB total RAM
-
- // Set defaults for > 4 GB DRAM, i.e. remap a 1 GB (= 0x10 * 64 MB) range of memory
- uint16_t remap_base = total_dram_64M_multiple; // A[25:0] == 0
- uint16_t remap_limit = total_dram_64M_multiple + 0x10 - 1; // A[25:0] == 0xF
-
- // Put TOLM at 3 GB
-
- pci_write_config16(MCHDEV, TOLM, 0xc000);
-
- // Define a remap window to make the RAM that would appear from 3 GB - 4 GB
- // visible just beyond 4 GB or the end of physical memory, whichever is larger
- // NOTE: 16-bit wide REMAP registers store only the highest 10 bits of a 36-bit address,
- // (i.e. a multiple of 64 MB) in the lowest 10 bits.
- // NOTE: 0x100000000 / (64 MB) == 0x40
-
- if (total_dram_64M_multiple < 0x40) {
- remap_base = 0x40; // 0x100000000
- remap_limit =
- 0x40 + (total_dram_64M_multiple - 0x30) - 1;
- }
-
- pci_write_config16(MCHDEV, REMAPBASE,
- remap_base);
- pci_write_config16(MCHDEV, REMAPLIMIT,
- remap_limit);
+ /* Limit register is inclusive. */
+ remaplimit_r -= 1;
}
+
+ /* Write the RAM configuration registers,
+ preserving the reserved bits. */
+ reg = pci_read_config16(MCHDEV, TOLM) & 0x7ff;
+ reg |= (tolm / (128 * MiB)) << 11;
+ pci_write_config16(MCHDEV, TOLM, reg);
+
+ reg = pci_read_config16(MCHDEV, REMAPBASE) & 0xfc00;
+ reg |= remapbase_r;
+ pci_write_config16(MCHDEV, REMAPBASE, reg);
+
+ reg = pci_read_config16(MCHDEV, REMAPLIMIT) & 0xfc00;
+ reg |= remaplimit_r;
+ pci_write_config16(MCHDEV, REMAPLIMIT, reg);
}
/**
@@ -1904,12 +1876,6 @@
sdram_enable(memctrl);
}
-uintptr_t restore_top_of_low_cacheable(void)
-{
- u32 tolm = (pci_read_config16(MCHDEV, TOLM) & ~0x7ff) << 16;
- return tolm;
-}
-
/**
* Scrub and reset error counts for ECC dimms.
*