summaryrefslogtreecommitdiff
path: root/src/soc/intel/cannonlake/memmap.c
diff options
context:
space:
mode:
authorSubrata Banik <subrata.banik@intel.com>2017-08-30 18:29:33 +0530
committerSubrata Banik <subrata.banik@intel.com>2017-09-01 02:55:45 +0000
commita281c0f1bf7b6b84c4e1f7739c52044299ae0be5 (patch)
treef1c7467908bdab3da7fd1f945f3790b9fc726746 /src/soc/intel/cannonlake/memmap.c
parentce90c78d7f27e41275deb36b5dea2787ffced8bf (diff)
downloadcoreboot-a281c0f1bf7b6b84c4e1f7739c52044299ae0be5.tar.xz
soc/intel/cannonlake: Perform dram top calculation based on HW registers
This patch ensures that entire system memory calculation is done based on host bridge registers. BRANCH=none BUG=b:63974384 TEST=Build and boot cannonlake RVP successfully with below configurations 1. Booting to OS with no UPD change 2. Enable ProbelessTrace UPD and boot to OS. 3. Enable PRMRR with size 1MB and boot to OS. 4. Enable PRMRR with size 32MB and boot to OS. 5. Enable PRMRR with size 2MB and unable to boot to OS due to unsupported PRMRR size. 6. Enable C6 DRAM with PRMRR size 0MB and boot to OS. Change-Id: I0a430a24f52cdf6e2517a49910b77ab08a199ca2 Signed-off-by: Subrata Banik <subrata.banik@intel.com> Reviewed-on: https://review.coreboot.org/21235 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/soc/intel/cannonlake/memmap.c')
-rw-r--r--src/soc/intel/cannonlake/memmap.c112
1 files changed, 108 insertions, 4 deletions
diff --git a/src/soc/intel/cannonlake/memmap.c b/src/soc/intel/cannonlake/memmap.c
index 8b487f6b83..8f842c0c5c 100644
--- a/src/soc/intel/cannonlake/memmap.c
+++ b/src/soc/intel/cannonlake/memmap.c
@@ -15,10 +15,16 @@
*/
#include <arch/io.h>
#include <cbmem.h>
+#include <chip.h>
#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
#include <fsp/util.h>
+#include <intelblocks/systemagent.h>
#include <soc/bootblock.h>
+#include <soc/pci_devs.h>
#include <soc/systemagent.h>
+#include <stdlib.h>
static void *top_of_ram_register(void)
{
@@ -34,15 +40,113 @@ void clear_cbmem_top(void)
write32(top_of_ram_register(), 0);
}
+static bool is_ptt_enable(void)
+{
+ if ((read32((void *)PTT_TXT_BASE_ADDRESS) & PTT_PRESENT) ==
+ PTT_PRESENT)
+ return true;
+
+ return false;
+}
+
+/*
+ * Host Memory Map:
+ *
+ * +--------------------------+ TOUUD
+ * | |
+ * +--------------------------+ 4GiB
+ * | PCI Address Space |
+ * +--------------------------+ TOLUD (also maps into MC address space)
+ * | iGD |
+ * +--------------------------+ BDSM
+ * | GTT |
+ * +--------------------------+ BGSM
+ * | TSEG |
+ * +--------------------------+ TSEGMB
+ * | DMA Protected Region |
+ * +--------------------------+ DPR
+ * | PRM (C6DRAM/SGX) |
+ * +--------------------------+ PRMRR
+ * | ME Stolen Memory |
+ * +--------------------------+ ME Stolen
+ * | PTT |
+ * +--------------------------+ top_of_ram
+ * | Reserved - FSP/CBMEM |
+ * +--------------------------+ TOLUM
+ * | Usage DRAM |
+ * +--------------------------+ 0
+ *
+ * Some of the base registers above can be equal making the size of those
+ * regions 0. The reason is because the memory controller internally subtracts
+ * the base registers from each other to determine sizes of the regions. In
+ * other words, the memory map is in a fixed order no matter what.
+ */
+static uintptr_t calculate_dram_base(void)
+{
+ const struct soc_intel_cannonlake_config *config;
+ const struct device *dev;
+ uintptr_t dram_base;
+ uintptr_t prmrr_base;
+ size_t prmrr_size;
+ size_t imr_size;
+
+ dev = dev_find_slot(0, PCI_DEVFN(SA_DEV_SLOT_IGD, 0));
+
+ /* Read TOLUD from Host Bridge offset */
+ dram_base = sa_get_tolud_base();
+
+ if (dev->enabled) {
+ /* Read BDSM from Host Bridge */
+ dram_base -= sa_get_dsm_size();
+
+ /* Read BGSM from Host Bridge */
+ dram_base -= sa_get_gsm_size();
+ }
+ /* Get TSEG size */
+ dram_base -= sa_get_tseg_size();
+
+ /* Get DPR size */
+ if (IS_ENABLED(CONFIG_SA_ENABLE_DPR))
+ dram_base -= sa_get_dpr_size();
+
+ config = dev->chip_info;
+ prmrr_size = config->PrmrrSize;
+
+ if (prmrr_size > 0) {
+ /*
+ * PRMRR Sizes that are > 1MB and < 32MB are
+ * not supported and will fail out.
+ */
+ if ((prmrr_size > 1*MiB) && (prmrr_size < 32*MiB))
+ die("PRMRR Sizes that are > 1MB and < 32MB are not"
+ "supported!\n");
+
+ prmrr_base = dram_base - prmrr_size;
+ if (prmrr_size >= 32*MiB)
+ prmrr_base = ALIGN_DOWN(prmrr_base, 128*MiB);
+ dram_base = prmrr_base;
+ } else if (config->enable_c6dram && prmrr_size == 0) {
+ /* Allocate PRMRR memory for C6DRAM */
+ dram_base -= 1*MiB;
+ }
+
+ /* ME stolen memory */
+ imr_size = MCHBAR32(IMRLIMIT) - MCHBAR32(IMRBASE);
+ if (imr_size > 0)
+ dram_base -= imr_size;
+
+ if (is_ptt_enable())
+ dram_base -= 4*KiB; /* Allocate 4KB for PTT if enable */
+
+ return dram_base;
+}
+
void cbmem_top_init(void)
{
- struct range_entry fsp_mem;
uintptr_t top;
- if (fsp_find_reserved_memory(&fsp_mem))
- die("Can't file top of ram.\n");
+ top = calculate_dram_base();
- top = ALIGN_UP(range_entry_base(&fsp_mem), 16 * MiB);
write32(top_of_ram_register(), top);
}