From 717b6e3151b6ea42aaa4b1ab2a708e143d098878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ky=C3=B6sti=20M=C3=A4lkki?= Date: Thu, 17 May 2018 14:16:03 +0300 Subject: aopen/dxplplusu intel/e7505: Move to EARLY_CBMEM_INIT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-on: https://review.coreboot.org/26585 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/northbridge/intel/e7505/Kconfig | 1 - src/northbridge/intel/e7505/Makefile.inc | 4 +- src/northbridge/intel/e7505/memmap.c | 66 ++++++++++++++++++ src/northbridge/intel/e7505/northbridge.c | 107 +++++++++--------------------- src/northbridge/intel/e7505/raminit.c | 96 +++++++++------------------ 5 files changed, 133 insertions(+), 141 deletions(-) create mode 100644 src/northbridge/intel/e7505/memmap.c (limited to 'src/northbridge') diff --git a/src/northbridge/intel/e7505/Kconfig b/src/northbridge/intel/e7505/Kconfig index 702ba1c913..bf35a6d11c 100644 --- a/src/northbridge/intel/e7505/Kconfig +++ b/src/northbridge/intel/e7505/Kconfig @@ -22,7 +22,6 @@ config NORTHBRIDGE_SPECIFIC_OPTIONS # dummy 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 89a5b8cb70..57c870fde4 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 0000000000..4a80608e81 --- /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 +#include +#include +#include +#include +#include +#include +#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 ea8b4598f4..6d351a3117 100644 --- a/src/northbridge/intel/e7505/northbridge.c +++ b/src/northbridge/intel/e7505/northbridge.c @@ -31,84 +31,43 @@ unsigned long acpi_fill_mcfg(unsigned long current) 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; - - /* 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); - - remapbase_r = pci_read_config16(mc_dev, REMAPBASE); - remapbase_r = (remapbasek >> 16) | (remapbase_r & 0xfc00); - pci_write_config16(mc_dev, REMAPBASE, remapbase_r); - - remaplimit_r = pci_read_config16(mc_dev, REMAPLIMIT); - remaplimit_r = (remaplimitk >> 16) | (remaplimit_r & 0xfc00); - pci_write_config16(mc_dev, REMAPLIMIT, remaplimit_r); - - /* 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); - } - - set_late_cbmem_top(tolmk * 1024); - } + mc_dev = dev_find_slot(0, PCI_DEVFN(0x0, 0)); + if (!mc_dev) + die("Could not find MCH device\n"); + + tolmk = pci_read_config16(mc_dev, TOLM) >> 11; + tolmk <<= 17; + + tomk = pci_read_config8(mc_dev, DRB_ROW_7); + tomk <<= 16; + + /* 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; + + remaplimitk = pci_read_config16(mc_dev, REMAPLIMIT) & 0x3ff; + remaplimitk += 1; + remaplimitk <<= 16; + + /* 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 f3a2520dba..7464a722fa 100644 --- a/src/northbridge/intel/e7505/raminit.c +++ b/src/northbridge/intel/e7505/raminit.c @@ -30,8 +30,8 @@ #include #include #include +#include #include - #include #include #include @@ -850,6 +850,12 @@ static void configure_e7501_ram_addresses(const struct mem_controller { 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 @@ static void configure_e7501_ram_addresses(const struct mem_controller 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. - - // 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. + tom = total_dram_64M_multiple * 64ULL * MiB; - // 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. + /* Reserve MMIO space. */ + tolm = 4ULL * GiB - 1 * GiB; + tolm = MIN(tolm, tom); - // NOTE: 0xC0000000 / (64 MB) == 0x30 + /* 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); - 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. - */ + remapbase_r = remapbase / (64 * MiB); + remaplimit_r = remaplimit / (64 * MiB); - // 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); + /* Limit register is inclusive. */ + remaplimit_r -= 1; + } - // 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 + /* 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); - if (total_dram_64M_multiple < 0x40) { - remap_base = 0x40; // 0x100000000 - remap_limit = - 0x40 + (total_dram_64M_multiple - 0x30) - 1; - } + reg = pci_read_config16(MCHDEV, REMAPBASE) & 0xfc00; + reg |= remapbase_r; + pci_write_config16(MCHDEV, REMAPBASE, reg); - pci_write_config16(MCHDEV, REMAPBASE, - remap_base); - pci_write_config16(MCHDEV, REMAPLIMIT, - remap_limit); - } + reg = pci_read_config16(MCHDEV, REMAPLIMIT) & 0xfc00; + reg |= remaplimit_r; + pci_write_config16(MCHDEV, REMAPLIMIT, reg); } /** @@ -1904,12 +1876,6 @@ void e7505_mch_init(const struct mem_controller *memctrl) 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. * -- cgit v1.2.3