diff options
-rw-r--r-- | src/soc/intel/meteorlake/include/soc/systemagent.h | 24 | ||||
-rw-r--r-- | src/soc/intel/meteorlake/systemagent.c | 223 |
2 files changed, 245 insertions, 2 deletions
diff --git a/src/soc/intel/meteorlake/include/soc/systemagent.h b/src/soc/intel/meteorlake/include/soc/systemagent.h index 8d029f3e16..d463ce14b3 100644 --- a/src/soc/intel/meteorlake/include/soc/systemagent.h +++ b/src/soc/intel/meteorlake/include/soc/systemagent.h @@ -42,4 +42,28 @@ 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 0xFED20000 +#define LT_SECURITY_SIZE (384 * 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(const struct device *dev); +uint64_t get_dsm_size(const struct device *dev); +uint64_t get_gsm_size(const struct device *dev); +uint64_t get_dpr_size(const struct device *dev); #endif diff --git a/src/soc/intel/meteorlake/systemagent.c b/src/soc/intel/meteorlake/systemagent.c index d8fc0a4f2e..81e4bed38f 100644 --- a/src/soc/intel/meteorlake/systemagent.c +++ b/src/soc/intel/meteorlake/systemagent.c @@ -1,10 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include <arch/ioapic.h> #include <console/console.h> +#include <cpu/x86/msr.h> #include <device/device.h> #include <device/pci.h> #include <device/pci_ids.h> #include <delay.h> +#include <intelblocks/cpulib.h> +#include <intelblocks/msr.h> #include <intelblocks/power_limit.h> #include <intelblocks/systemagent.h> #include <soc/iomap.h> @@ -20,12 +24,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, LT_SECURITY_BASE_ADDR, LT_SECURITY_SIZE, "LT_SECURITY" }, + { 0, IO_APIC_ADDR, APIC_SIZE, "APIC" }, + // PCH_PRESERVERD covers: + // TraceHub SW BAR, PMC MBAR, SPI BAR0, SerialIo BAR in ACPI mode + // eSPI LGMR BAR, eSPI2 SEGMR BAR, TraceHub MTB BAR, TraceHub FW BAR + // IOE PMC BAR, Tracehub RTIT BAR (SOC), HECI{1,2,3} BAR0 + // see fsp/ClientOneSiliconPkg/Fru/MtlSoc/Include/PchReservedResources.h + { 0, PCH_PRESERVED_BASE_ADDRESS, PCH_PRESERVED_BASE_SIZE, "PCH_RESERVED" }, }; sa_add_fixed_mmio_resources(dev, index, soc_fixed_resources, @@ -40,6 +54,98 @@ void soc_add_fixed_mmio_resources(struct device *dev, int *index) } /* + * 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; +} + +int soc_get_uncore_prmmr_base_and_mask(uint64_t *prmrr_base, + uint64_t *prmrr_mask) +{ + msr_t msr; + msr = rdmsr(MSR_PRMRR_BASE_0); + *prmrr_base = (uint64_t)msr.hi << 32 | msr.lo; + msr = rdmsr(MSR_PRMRR_PHYS_MASK); + *prmrr_mask = (uint64_t)msr.hi << 32 | msr.lo; + return 0; +} + +/* + * 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; + if (soc_get_uncore_prmmr_base_and_mask(&base, &mask) == 0) { + base &= mask; + set_mmio_resource(&(cfg_rsrc[count++]), base, size, "PMRR"); + } else { + printk(BIOS_ERR, "SA: Failed to get PRMRR base and mask\n"); + } + } + + /* 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 * * Perform System Agent Initialization during Ramstage phase. @@ -100,3 +206,116 @@ uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz) return 65536; } } + +uint64_t get_mmcfg_size(const 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(const 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 = ((uint64_t)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(const 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(const 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 = (uint64_t)size_field * MiB; + return size; +} |