Subrata Banik has uploaded this change for review. ( https://review.coreboot.org/21235
Change subject: soc/intel/cannonlake: Usable dram top calculation based on HW registers ......................................................................
soc/intel/cannonlake: Usable 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 --- M src/soc/intel/cannonlake/chip.h M src/soc/intel/cannonlake/include/soc/systemagent.h M src/soc/intel/cannonlake/memmap.c 3 files changed, 99 insertions(+), 4 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/35/21235/1
diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index 48305fe..9b50846 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -186,6 +186,8 @@
/* Enable/Disable EIST. 1b:Enabled, 0b:Disabled */ uint8_t eist_enable; + /* Enable C6 DRAM */ + uint8_t enable_c6dram; };
typedef struct soc_intel_cannonlake_config config_t; diff --git a/src/soc/intel/cannonlake/include/soc/systemagent.h b/src/soc/intel/cannonlake/include/soc/systemagent.h index 1902314..da83c38 100644 --- a/src/soc/intel/cannonlake/include/soc/systemagent.h +++ b/src/soc/intel/cannonlake/include/soc/systemagent.h @@ -40,4 +40,7 @@ #define MCH_DDR_POWER_LIMIT_LO 0x58e0 #define MCH_DDR_POWER_LIMIT_HI 0x58e4
+#define IMRBASE 0x6A40 +#define IMRLIMIT 0x6A48 + #endif diff --git a/src/soc/intel/cannonlake/memmap.c b/src/soc/intel/cannonlake/memmap.c index 8b487f6..1b6e6da 100644 --- a/src/soc/intel/cannonlake/memmap.c +++ b/src/soc/intel/cannonlake/memmap.c @@ -34,15 +34,105 @@ write32(top_of_ram_register(), 0); }
+/* + * 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 u32 calculate_dram_base(void) +{ + const struct soc_intel_cannonlake_config *config; + const struct device *dev; + uint32_t dram_base; + uint32_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 -= smm_region_size(); + + /* Get DPR size */ + if (IS_ENABLED(CONFIG_SA_ENABLE_DPR)) + dram_base -= sa_get_dpr_size(); + + dev = dev_find_slot(0, PCI_DEVFN(SA_DEV_SLOT_ROOT, 0)); + 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); }