soc/intel/cmn/sa: Add APIs into System Agent (SA) common code

This commit streamlines code and strengthens common code robustness
by moving the following SoC-layer functions to the common layer:

- sa_get_mmcfg_size: Retrieves the MMIO (Memory-Mapped I/O)
                     configuration space size by reading offset
                     0x60 of the PCI Host Bridge (D0:F0).
- sa_get_dsm_size: Calculates the size of the DSM (Device Stolen
                   Memory) by reading offset 0x50 of the PCI
                   Host Bridge (D0:F0) to determine pre-allocated
                   memory for the IGD (Integrated Graphics Device).
- sa_get_gsm_size: Calculates the size of the GSM (Graphics Stolen
                   Memory) by reading offset 0x52 of the PCI Host
                   Bridge (D0:F0).
- sa_get_dpr_size: Determines the size of the DMA Protection
                   Range (DPR) by reading offset 0x5C of the PCI
                   Host Bridge (D0:F0).

TEST= Build and boot successful on google/screebo.

Change-Id: Ic00e001563ec6f0d737a445964c716b45db43327
Signed-off-by: Subrata Banik <subratabanik@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/80362
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
diff --git a/src/soc/intel/common/block/include/intelblocks/systemagent.h b/src/soc/intel/common/block/include/intelblocks/systemagent.h
index 3d4ff25..a3ae8c3 100644
--- a/src/soc/intel/common/block/include/intelblocks/systemagent.h
+++ b/src/soc/intel/common/block/include/intelblocks/systemagent.h
@@ -95,6 +95,14 @@
 size_t sa_get_tseg_size(void);
 /* API to lock PAM registers */
 void sa_lock_pam(void);
+/* API to get MMIO config size */
+uint64_t sa_get_mmcfg_size(void);
+/* API to get DSM size */
+uint64_t sa_get_dsm_size(void);
+/* API to get GSM size */
+uint64_t sa_get_gsm_size(void);
+/* API to get DPR size */
+uint64_t sa_get_dpr_size(void);
 
 /*
  * SoC overrides
diff --git a/src/soc/intel/common/block/systemagent/systemagent.c b/src/soc/intel/common/block/systemagent/systemagent.c
index c2d561a..bcae6a6 100644
--- a/src/soc/intel/common/block/systemagent/systemagent.c
+++ b/src/soc/intel/common/block/systemagent/systemagent.c
@@ -324,6 +324,84 @@
 	printk(BIOS_DEBUG, "PCI space above 4GB MMIO is at 0x%llx, len = 0x%llx\n", touud, len);
 }
 
+uint64_t sa_get_mmcfg_size(void)
+{
+	const uint32_t pciexbar_reg = pci_read_config32(__pci_0_00_0, PCIEXBAR);
+
+	if (!(pciexbar_reg & (1 << 0))) {
+		printk(BIOS_ERR, "%s : PCIEXBAR disabled\n", __func__);
+		return 0;
+	}
+
+	switch ((pciexbar_reg & PCIEXBAR_LENGTH_MASK) >> PCIEXBAR_LENGTH_MASK_LSB) {
+	case PCIEXBAR_LENGTH_4096MB:
+		return 4ULL * GiB;
+	case PCIEXBAR_LENGTH_2048MB:
+		return 2ULL * GiB;
+	case PCIEXBAR_LENGTH_1024MB:
+		return 1 * GiB;
+	case PCIEXBAR_LENGTH_512MB:
+		return 512 * MiB;
+	case PCIEXBAR_LENGTH_256MB:
+		return 256 * MiB;
+	case PCIEXBAR_LENGTH_128MB:
+		return 128 * MiB;
+	case PCIEXBAR_LENGTH_64MB:
+		return 64 * MiB;
+	default:
+		printk(BIOS_ERR, "%s : PCIEXBAR - invalid length (0x%x)\n", __func__,
+			(pciexbar_reg & PCIEXBAR_LENGTH_MASK) >> PCIEXBAR_LENGTH_MASK_LSB);
+		return 0x0;
+	}
+}
+
+uint64_t sa_get_dsm_size(void)
+{
+	const uint32_t size_field = (pci_read_config32(__pci_0_00_0, GGC) & DSM_LENGTH_MASK)
+					 >> DSM_LENGTH_MASK_LSB;
+	if (size_field <= 0x10) { /* 0x0 - 0x10 */
+		return size_field * 32 * MiB;
+	} else if ((size_field >= 0xF0) && (size_field >= 0xFE)) {
+		return ((uint64_t)size_field - 0xEF) * 4 * MiB;
+	} else {
+		switch (size_field) {
+		case 0x20:
+			return 1 * GiB;
+		case 0x30:
+			return 1536 * MiB;
+		case 0x40:
+			return 2 * (uint64_t)GiB;
+		default:
+			printk(BIOS_ERR, "%s : DSM - invalid length (0x%x)\n", __func__, size_field);
+			return 0x0;
+		}
+	}
+}
+
+uint64_t sa_get_gsm_size(void)
+{
+	const uint32_t size_field = (pci_read_config32(__pci_0_00_0, GGC) & GSM_LENGTH_MASK)
+					 >> GSM_LENGTH_MASK_LSB;
+	switch (size_field) {
+	case 0x0:
+	default:
+		return 0;
+	case 0x1:
+		return 2 * MiB;
+	case 0x2:
+		return 4 * MiB;
+	case 0x3:
+		return 8 * MiB;
+	}
+}
+
+uint64_t sa_get_dpr_size(void)
+{
+	const uint32_t size_field = (pci_read_config32(__pci_0_00_0, DPR) & DPR_LENGTH_MASK)
+					 >> DPR_LENGTH_MASK_LSB;
+	return (uint64_t)size_field * MiB;
+}
+
 struct device_operations systemagent_ops = {
 	.read_resources   = systemagent_read_resources,
 	.set_resources    = pci_dev_set_resources,
diff --git a/src/soc/intel/common/block/systemagent/systemagent_def.h b/src/soc/intel/common/block/systemagent/systemagent_def.h
index f913843..58d1113 100644
--- a/src/soc/intel/common/block/systemagent/systemagent_def.h
+++ b/src/soc/intel/common/block/systemagent/systemagent_def.h
@@ -29,6 +29,15 @@
 /* Device 0:0.0 MMIO space */
 #define MCH_PAIR	0x5418
 
+#define PCIEXBAR_LENGTH_MASK		0xE /* bits 1-3 */
+#define PCIEXBAR_LENGTH_MASK_LSB	1 /* used to shift right */
+#define DSM_LENGTH_MASK			0xFF00 /* bits 8-15 */
+#define DSM_LENGTH_MASK_LSB		8 /* used to shift right */
+#define GSM_LENGTH_MASK			0xC0 /* bits 6-7 */
+#define GSM_LENGTH_MASK_LSB		6 /* used to shift right */
+#define DPR_LENGTH_MASK			0xFF0 /* bits 4-11 */
+#define DPR_LENGTH_MASK_LSB		4 /* used to shift right */
+
 /*
  * IMR register in case CONFIG(SA_ENABLE_IMR) is selected by SoC.
  *