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 <mitrani@google.com>
Change-Id: I058a5c1cc59703e35ceddb8a7e26fb22a6a2b75e
Signed-off-by: Eran Mitrani <mitrani@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/65072
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
diff --git a/src/soc/intel/alderlake/include/soc/systemagent.h b/src/soc/intel/alderlake/include/soc/systemagent.h
index ebb3d71..f121b44 100644
--- a/src/soc/intel/alderlake/include/soc/systemagent.h
+++ b/src/soc/intel/alderlake/include/soc/systemagent.h
@@ -55,4 +55,30 @@
#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 bb58b75..170c56b 100644
--- a/src/soc/intel/alderlake/systemagent.c
+++ b/src/soc/intel/alderlake/systemagent.c
@@ -6,15 +6,20 @@
* Chapter number: 3
*/
+#include <arch/ioapic.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.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>
#include <soc/soc_chip.h>
#include <soc/systemagent.h>
+#include <spi_flash.h>
+#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,
@@ -46,6 +60,83 @@
}
/*
+ * 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
*
* Perform System Agent Initialization during Ramstage phase.
@@ -101,3 +192,116 @@
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;
+}