From ca741055e6b63b6722ad9837fa5360fa6b5b3e5b Mon Sep 17 00:00:00 2001 From: Eran Mitrani Date: Thu, 9 Jun 2022 10:50:22 -0700 Subject: soc/intel/adl: Add missing claimed memory regions The Alder Lake chipset has several more reserved memory regions that are unavailable to the resource allocator than are currently marked as such in the system agent code. This CL adds the following regions (documented in Intel docs #626540, #619503): 1. TSEG 2. GSM 3. DSM 4. PCH_RESERVED 5. CRAB_ABORT 6. APIC 7. TPM 8. LT_SECURITY Claimed regions before this change: ======================================================== base 0 size a0000 // 0 - > 0xa0000 base a0000 size 20000 // legacy VGA base c0000 size 40000 // RAM base c0000 size 76f40000 // 0xc0000 -> top_of_ram base 77000000 size 9400000 // top_of_ram -> TOLUD base c0000000 size 10000000 // PCIEXBAR base f8000000 size 2000000 // MMSPI base fb000000 size 1000 // REGBAR base fed80000 size 4000 // EDRAMBAR base fed84000 size 1000 // TBT0BAR base fed85000 size 1000 // TBT1BAR base fed86000 size 1000 // TBT2BAR base fed87000 size 1000 // TBT3BAR base fed90000 size 1000 // GFXVTBAR base fed91000 size 1000 // VTVC0BAR base fed92000 size 1000 // IPUVTBAR base feda0000 size 1000 // DMIBAR base feda1000 size 1000 // EPBAR base fedc0000 size 20000 // MCHBAR base 100000000 size 17fc00000 // 4GiB -> TOUUD Claimed regions with this change: ======================================================== base 0 size a0000 // 0 - > 0xa0000 base a0000 size 20000 // legacy VGA base c0000 size 40000 // RAM base c0000 size 76f40000 // 0xc0000 -> top_of_ram base 77000000 size 9400000 // top_of_ram -> TOLUD base 7b800000 size 800000 // TSEG base 7c000000 size 800000 // GSM base 7c800000 size 3c00000 // DSM base c0000000 size 10000000 // PCIEXBAR base f8000000 size 2000000 // MMSPI base fb000000 size 1000 // REGBAR base fc800000 size 2000000 // PCH_RESERVED base feb00000 size 80000 // CRAB_ABORT base fec00000 size 100000 // APIC base fed40000 size 10000 // TPM base fed50000 size 20000 // LT_SECURITY base fed80000 size 4000 // EDRAMBAR base fed84000 size 1000 // TBT0BAR base fed85000 size 1000 // TBT1BAR base fed86000 size 1000 // TBT2BAR base fed87000 size 1000 // TBT3BAR base fed90000 size 1000 // GFXVTBAR base fed91000 size 1000 // VTVC0BAR base fed92000 size 1000 // IPUVTBAR base feda0000 size 1000 // DMIBAR base feda1000 size 1000 // EPBAR base fedc0000 size 20000 // MCHBAR base 100000000 size 17fc00000 // 4GiB -> TOUUD BUG=b:149830546 BRANCH=firmware-brya-14505.B TEST='emerge-brya coreboot chromeos-bootimage' builds correctly. Tested on an Anahera device which successfully boots to ChromeOS with kernel version 5.10.109-15688-g857e654d1705. Also ran dmseg, and saw the added regions in e820 prints. Signed-off-by: Eran Mitrani Change-Id: I058a5c1cc59703e35ceddb8a7e26fb22a6a2b75e Signed-off-by: Eran Mitrani Reviewed-on: https://review.coreboot.org/c/coreboot/+/65072 Tested-by: build bot (Jenkins) Reviewed-by: Tim Wawrzynczak --- src/soc/intel/alderlake/include/soc/systemagent.h | 26 +++ src/soc/intel/alderlake/systemagent.c | 208 +++++++++++++++++++++- 2 files changed, 232 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/soc/intel/alderlake/include/soc/systemagent.h b/src/soc/intel/alderlake/include/soc/systemagent.h index ebb3d71392..f121b447a7 100644 --- a/src/soc/intel/alderlake/include/soc/systemagent.h +++ b/src/soc/intel/alderlake/include/soc/systemagent.h @@ -55,4 +55,30 @@ static const struct sa_mmio_descriptor soc_vtd_resources[] = { #define V_P2SB_CFG_HBDF_DEV 30 #define V_P2SB_CFG_HBDF_FUNC 6 +#define CRAB_ABORT_BASE_ADDR 0xFEB00000 +#define CRAB_ABORT_SIZE (512 * KiB) +#define TPM_BASE_ADDRESS 0xFED40000 +#define TPM_SIZE (64 * KiB) + +#define LT_SECURITY_BASE_ADDR 0xFED50000 +#define LT_SECURITY_SIZE (128 * KiB) +#define APIC_SIZE (1 * MiB) + +#define MASK_PCIEXBAR_LENGTH 0x0000000E // bits [3:1] +#define PCIEXBAR_LENGTH_LSB 1 // used to shift right + +#define DSM_BASE_ADDR_REG 0xB0 +#define MASK_DSM_LENGTH 0xFF00 // [15:8] +#define MASK_DSM_LENGTH_LSB 8 // used to shift right +#define MASK_GSM_LENGTH 0xC0 // [7:6] +#define MASK_GSM_LENGTH_LSB 6 // used to shift right +#define DPR_REG 0x5C +#define MASK_DPR_LENGTH 0xFF0 // [11:4] +#define MASK_DPR_LENGTH_LSB 4 // used to shift right + +uint64_t get_mmcfg_size(struct device *dev); +uint64_t get_dsm_size(struct device *dev); +uint64_t get_gsm_size(struct device *dev); +uint64_t get_dpr_size(struct device *dev); + #endif diff --git a/src/soc/intel/alderlake/systemagent.c b/src/soc/intel/alderlake/systemagent.c index bb58b75eec..170c56b71c 100644 --- a/src/soc/intel/alderlake/systemagent.c +++ b/src/soc/intel/alderlake/systemagent.c @@ -6,15 +6,20 @@ * Chapter number: 3 */ +#include #include #include #include #include +#include +#include #include #include #include #include #include +#include +#include "stddef.h" /* * SoC implementation @@ -25,13 +30,22 @@ void soc_add_fixed_mmio_resources(struct device *dev, int *index) { static const struct sa_mmio_descriptor soc_fixed_resources[] = { - { PCIEXBAR, CONFIG_ECAM_MMCONF_BASE_ADDRESS, CONFIG_ECAM_MMCONF_LENGTH, - "PCIEXBAR" }, { MCHBAR, MCH_BASE_ADDRESS, MCH_BASE_SIZE, "MCHBAR" }, { DMIBAR, DMI_BASE_ADDRESS, DMI_BASE_SIZE, "DMIBAR" }, { EPBAR, EP_BASE_ADDRESS, EP_BASE_SIZE, "EPBAR" }, { REGBAR, REG_BASE_ADDRESS, REG_BASE_SIZE, "REGBAR" }, { EDRAMBAR, EDRAM_BASE_ADDRESS, EDRAM_BASE_SIZE, "EDRAMBAR" }, + + /* first field (sa_mmio_descriptor.index) is not used, setting to 0: */ + { 0, CRAB_ABORT_BASE_ADDR, CRAB_ABORT_SIZE, "CRAB_ABORT" }, + { 0, TPM_BASE_ADDRESS, TPM_SIZE, "TPM" }, + { 0, LT_SECURITY_BASE_ADDR, LT_SECURITY_SIZE, "LT_SECURITY" }, + { 0, IO_APIC_ADDR, APIC_SIZE, "APIC" }, + // PCH_PRESERVERD covers: + // TraceHub SW BAR, SBREG, PMC MBAR, SPI BAR0, SerialIo BAR in ACPI mode + // eSPI LGMR BAR, eSPI2 SEGMR BAR, TraceHub MTB BAR, TraceHub FW BAR + // see fsp/ClientOneSiliconPkg/Fru/AdlPch/Include/PchReservedResourcesAdpP.h + { 0, PCH_PRESERVED_BASE_ADDRESS, PCH_PRESERVED_BASE_SIZE, "PCH_RESERVED" }, }; sa_add_fixed_mmio_resources(dev, index, soc_fixed_resources, @@ -45,6 +59,83 @@ void soc_add_fixed_mmio_resources(struct device *dev, int *index) ARRAY_SIZE(soc_vtd_resources)); } +/* + * set MMIO resource's fields + */ +static void set_mmio_resource( + struct sa_mmio_descriptor *resource, + uint64_t base, + uint64_t size, + const char *description) +{ + if (resource == NULL) { + printk(BIOS_ERR, "%s: argument resource is NULL for %s\n", + __func__, description); + return; + } + resource->base = base; + resource->size = size; + resource->description = description; +} + +/* + * SoC implementation + * + * Add all known configurable memory ranges for Host Controller/Memory + * controller. + */ +void soc_add_configurable_mmio_resources(struct device *dev, int *resource_cnt) +{ + uint64_t size, base, tseg_base; + int count = 0; + struct sa_mmio_descriptor cfg_rsrc[6]; /* Increase size when adding more resources */ + + /* MMCONF */ + size = get_mmcfg_size(dev); + if (size > 0) + set_mmio_resource(&(cfg_rsrc[count++]), CONFIG_ECAM_MMCONF_BASE_ADDRESS, + size, "MMCONF"); + + /* DSM */ + size = get_dsm_size(dev); + if (size > 0) { + base = pci_read_config32(dev, DSM_BASE_ADDR_REG) & 0xFFF00000; + set_mmio_resource(&(cfg_rsrc[count++]), base, size, "DSM"); + } + + /* TSEG */ + size = sa_get_tseg_size(); + tseg_base = sa_get_tseg_base(); + if (size > 0) + set_mmio_resource(&(cfg_rsrc[count++]), tseg_base, size, "TSEG"); + + /* PMRR */ + size = get_valid_prmrr_size(); + if (size > 0) { + uint64_t mask = pci_read_config32(dev, MSR_PRMRR_PHYS_MASK); + base = pci_read_config32(dev, MSR_PRMRR_PHYS_BASE) & mask; + set_mmio_resource(&(cfg_rsrc[count++]), base, size, "PMRR"); + } + + /* GSM */ + size = get_gsm_size(dev); + if (size > 0) { + base = sa_get_gsm_base(); + set_mmio_resource(&(cfg_rsrc[count++]), base, size, "GSM"); + } + + /* DPR */ + size = get_dpr_size(dev); + if (size > 0) { + /* DPR just below TSEG: */ + base = tseg_base - size; + set_mmio_resource(&(cfg_rsrc[count++]), base, size, "DPR"); + } + + /* Add all the above */ + sa_add_fixed_mmio_resources(dev, resource_cnt, cfg_rsrc, count); +} + /* * SoC implementation * @@ -101,3 +192,116 @@ uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz) return 65536; } } + +uint64_t get_mmcfg_size(struct device *dev) +{ + uint32_t pciexbar_reg; + uint64_t mmcfg_length; + + if (!dev) { + printk(BIOS_DEBUG, "%s : device is null\n", __func__); + return 0; + } + + pciexbar_reg = pci_read_config32(dev, PCIEXBAR); + + if (!(pciexbar_reg & (1 << 0))) { + printk(BIOS_DEBUG, "%s : PCIEXBAR disabled\n", __func__); + return 0; + } + + switch ((pciexbar_reg & MASK_PCIEXBAR_LENGTH) >> PCIEXBAR_LENGTH_LSB) { + case PCIEXBAR_LENGTH_4096MB: + mmcfg_length = 4 * ((uint64_t)GiB); + break; + case PCIEXBAR_LENGTH_2048MB: + mmcfg_length = 2 * ((uint64_t)GiB); + break; + case PCIEXBAR_LENGTH_1024MB: + mmcfg_length = 1 * GiB; + break; + case PCIEXBAR_LENGTH_512MB: + mmcfg_length = 512 * MiB; + break; + case PCIEXBAR_LENGTH_256MB: + mmcfg_length = 256 * MiB; + break; + case PCIEXBAR_LENGTH_128MB: + mmcfg_length = 128 * MiB; + break; + case PCIEXBAR_LENGTH_64MB: + mmcfg_length = 64 * MiB; + break; + default: + printk(BIOS_DEBUG, "%s : PCIEXBAR - invalid length (0x%x)\n", __func__, + pciexbar_reg & MASK_PCIEXBAR_LENGTH); + mmcfg_length = 0x0; + break; + } + + return mmcfg_length; +} + +uint64_t get_dsm_size(struct device *dev) +{ + // - size : B0/D0/F0:R 50h [15:8] + uint32_t reg32 = pci_read_config32(dev, GGC); + uint64_t size; + uint32_t size_field = (reg32 & MASK_DSM_LENGTH) >> MASK_DSM_LENGTH_LSB; + if (size_field <= 0x10) { // 0x0 - 0x10 + size = size_field * 32 * MiB; + } else if ((size_field >= 0xF0) && (size_field >= 0xFE)) { + size = (size_field - 0xEF) * 4 * MiB; + } else { + switch (size_field) { + case 0x20: + size = 1 * GiB; + break; + case 0x30: + size = 1536 * MiB; + break; + case 0x40: + size = 2 * (uint64_t)GiB; + break; + default: + printk(BIOS_DEBUG, "%s : DSM - invalid length (0x%x)\n", + __func__, size_field); + size = 0x0; + break; + } + } + return size; +} + +uint64_t get_gsm_size(struct device *dev) +{ + const u32 gsm_size = pci_read_config32(dev, GGC); + uint64_t size; + uint32_t size_field = (gsm_size & MASK_GSM_LENGTH) >> MASK_GSM_LENGTH_LSB; + switch (size_field) { + case 0x0: + size = 0; + break; + case 0x1: + size = 2 * MiB; + break; + case 0x2: + size = 4 * MiB; + break; + case 0x3: + size = 8 * MiB; + break; + default: + size = 0; + break; + } + return size; +} +uint64_t get_dpr_size(struct device *dev) +{ + uint64_t size; + uint32_t dpr_reg = pci_read_config32(dev, DPR_REG); + uint32_t size_field = (dpr_reg & MASK_DPR_LENGTH) >> MASK_DPR_LENGTH_LSB; + size = size_field * MiB; + return size; +} -- cgit v1.2.3