soc/intel/xeon_sp: Create CXL domains
SPR CXL IIO stack is divided into 2 PCI domains. The 1st domain
is a PCI domain with single bus number and PCIe RCiEPs (Root
Complex Integrated End Points) on it. The 2nd domain is a CXL
domain with remaining buses for CXL 1.0/1.1 end points and
possible SR-IOV (Single Root IO Virtualizaton) VFs (Virtual
Function) if any.
TEST=intel/archercity CRB
P.S. The SUT is not with CXL cards however we hope this refactor
could be integrated first as an improvement of the design.
Change-Id: I643bcfbae7b6e8cfe11c147cc89374bc6b4d5a80
Signed-off-by: Shuo Liu <shuo.liu@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/81099
Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/soc/intel/xeon_sp/chip_common.c b/src/soc/intel/xeon_sp/chip_common.c
index 93949c8..67c1089 100644
--- a/src/soc/intel/xeon_sp/chip_common.c
+++ b/src/soc/intel/xeon_sp/chip_common.c
@@ -176,32 +176,32 @@
#endif
};
-static void soc_create_pcie_domains(const union xeon_domain_path dp, struct bus *upstream,
- const STACK_RES *sr)
+static void soc_create_domains(const union xeon_domain_path dp, struct bus *upstream,
+ int bus_base, int bus_limit, const char *type,
+ struct device_operations *ops)
{
- union xeon_domain_path new_path = {
- .domain_path = dp.domain_path
- };
- new_path.bus = sr->BusBase;
-
- struct device_path path = {
- .type = DEVICE_PATH_DOMAIN,
- .domain = {
- .domain = new_path.domain_path,
- },
- };
+ struct device_path path;
+ init_xeon_domain_path(&path, dp.socket, dp.stack, bus_base);
struct device *const domain = alloc_find_dev(upstream, &path);
if (!domain)
die("%s: out of memory.\n", __func__);
- domain->ops = &iio_pcie_domain_ops;
- iio_domain_set_acpi_name(domain, DOMAIN_TYPE_PCIE);
+ domain->ops = ops;
+ iio_domain_set_acpi_name(domain, type);
struct bus *const bus = alloc_bus(domain);
- bus->secondary = sr->BusBase;
- bus->subordinate = sr->BusBase;
- bus->max_subordinate = sr->BusLimit;
+ bus->secondary = bus_base;
+ bus->subordinate = bus_base;
+ bus->max_subordinate = bus_limit;
+}
+
+
+static void soc_create_pcie_domains(const union xeon_domain_path dp, struct bus *upstream,
+ const STACK_RES *sr)
+{
+ soc_create_domains(dp, upstream, sr->BusBase, sr->BusLimit, DOMAIN_TYPE_PCIE,
+ &iio_pcie_domain_ops);
}
/*
@@ -212,38 +212,74 @@
static void soc_create_ubox_domains(const union xeon_domain_path dp, struct bus *upstream,
const STACK_RES *sr)
{
- union xeon_domain_path new_path = {
- .domain_path = dp.domain_path
- };
-
/* Only expect 2 UBOX buses here */
- int bus_base = sr->BusBase;
- int bus_limit = sr->BusLimit;
- assert(bus_base + 1 == bus_limit);
- for (int i = bus_base; i <= bus_limit; i++) {
- new_path.bus = i;
+ assert(sr->BusBase + 1 == sr->BusLimit);
- struct device_path path = {
- .type = DEVICE_PATH_DOMAIN,
- .domain = {
- .domain = new_path.domain_path,
- },
- };
- struct device *const domain = alloc_find_dev(upstream, &path);
- if (!domain)
- die("%s: out of memory.\n", __func__);
+ soc_create_domains(dp, upstream, sr->BusBase, sr->BusBase, DOMAIN_TYPE_UBX0,
+ &ubox_pcie_domain_ops);
+ soc_create_domains(dp, upstream, sr->BusLimit, sr->BusLimit, DOMAIN_TYPE_UBX1,
+ &ubox_pcie_domain_ops);
+}
- domain->ops = &ubox_pcie_domain_ops;
- const char *prefix = (i == bus_base) ? DOMAIN_TYPE_UBX0 : DOMAIN_TYPE_UBX1;
- iio_domain_set_acpi_name(domain, prefix);
+#if CONFIG(SOC_INTEL_HAS_CXL)
+void iio_cxl_domain_read_resources(struct device *dev)
+{
+ struct resource *res;
+ const STACK_RES *sr = domain_to_stack_res(dev);
- struct bus *const bus = alloc_bus(domain);
- bus->secondary = i;
- bus->subordinate = bus->secondary;
- bus->max_subordinate = bus->secondary;
+ if (!sr)
+ return;
+
+ int index = 0;
+
+ if (sr->IoBase < sr->PciResourceIoBase) {
+ res = new_resource(dev, index++);
+ res->base = sr->IoBase;
+ res->limit = sr->PciResourceIoBase - 1;
+ res->size = res->limit - res->base + 1;
+ res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED;
+ }
+
+ if (sr->Mmio32Base < sr->PciResourceMem32Base) {
+ res = new_resource(dev, index++);
+ res->base = sr->Mmio32Base;
+ res->limit = sr->PciResourceMem32Base - 1;
+ res->size = res->limit - res->base + 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
+ }
+
+ if (sr->Mmio64Base < sr->PciResourceMem64Base) {
+ res = new_resource(dev, index++);
+ res->base = sr->Mmio64Base;
+ res->limit = sr->PciResourceMem64Base - 1;
+ res->size = res->limit - res->base + 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
}
}
+static struct device_operations iio_cxl_domain_ops = {
+ .read_resources = iio_cxl_domain_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .scan_bus = pci_host_bridge_scan_bus,
+#if CONFIG(HAVE_ACPI_TABLES)
+ .acpi_name = soc_acpi_name,
+ .write_acpi_tables = northbridge_write_acpi_tables,
+#endif
+};
+
+void soc_create_cxl_domains(const union xeon_domain_path dp, struct bus *bus,
+ const STACK_RES *sr)
+{
+ assert(sr->BusBase + 1 <= sr->BusLimit);
+ /* 1st domain contains PCIe RCiEPs */
+ soc_create_domains(dp, bus, sr->BusBase, sr->BusBase, DOMAIN_TYPE_PCIE,
+ &iio_pcie_domain_ops);
+ /* 2nd domain contains CXL 1.1 end-points */
+ soc_create_domains(dp, bus, sr->BusBase + 1, sr->BusLimit, DOMAIN_TYPE_CXL,
+ &iio_cxl_domain_ops);
+}
+#endif //CONFIG(SOC_INTEL_HAS_CXL)
+
/* Attach stack as domains */
void attach_iio_stacks(void)
{
@@ -265,6 +301,8 @@
if (is_ubox_stack_res(ri))
soc_create_ubox_domains(dn, root_bus, ri);
+ else if (CONFIG(SOC_INTEL_HAS_CXL) && is_iio_cxl_stack_res(ri))
+ soc_create_cxl_domains(dn, root_bus, ri);
else if (is_pcie_iio_stack_res(ri))
soc_create_pcie_domains(dn, root_bus, ri);
else if (CONFIG(HAVE_IOAT_DOMAINS) && is_ioat_iio_stack_res(ri))
diff --git a/src/soc/intel/xeon_sp/include/soc/chip_common.h b/src/soc/intel/xeon_sp/include/soc/chip_common.h
index 47dea8e..bcfdf62 100644
--- a/src/soc/intel/xeon_sp/include/soc/chip_common.h
+++ b/src/soc/intel/xeon_sp/include/soc/chip_common.h
@@ -3,6 +3,7 @@
#ifndef _CHIP_COMMON_H_
#define _CHIP_COMMON_H_
+#include <device/path.h>
#include <hob_iiouds.h>
union xeon_domain_path {
@@ -15,6 +16,19 @@
};
};
+
+static inline void init_xeon_domain_path(struct device_path *path, int socket,
+ int stack, int bus)
+{
+ union xeon_domain_path dp = {
+ .socket = socket,
+ .stack = stack,
+ .bus = bus,
+ };
+ path->type = DEVICE_PATH_DOMAIN;
+ path->domain.domain = dp.domain_path;
+};
+
/*
* Every STACK can have multiple PCI domains with an unique domain type.
* This is only of cosmetic nature and generates more readable ACPI code,
@@ -28,11 +42,14 @@
#define DOMAIN_TYPE_PCIE "PC"
#define DOMAIN_TYPE_UBX0 "UC"
#define DOMAIN_TYPE_UBX1 "UD"
+#define DOMAIN_TYPE_CXL "CX"
void iio_pci_domain_read_resources(struct device *dev);
+void iio_cxl_domain_read_resources(struct device *dev);
void attach_iio_stacks(void);
void soc_create_ioat_domains(union xeon_domain_path path, struct bus *bus, const STACK_RES *sr);
+void soc_create_cxl_domains(const union xeon_domain_path dp, struct bus *bus, const STACK_RES *sr);
struct device *dev_find_device_on_socket(uint8_t socket, u16 vendor, u16 device);
int iio_pci_domain_socket_from_dev(struct device *dev);
int iio_pci_domain_stack_from_dev(struct device *dev);
diff --git a/src/soc/intel/xeon_sp/include/soc/util.h b/src/soc/intel/xeon_sp/include/soc/util.h
index a7d5dac..db66fcb 100644
--- a/src/soc/intel/xeon_sp/include/soc/util.h
+++ b/src/soc/intel/xeon_sp/include/soc/util.h
@@ -32,6 +32,7 @@
bool is_pcie_iio_stack_res(const STACK_RES *res);
bool is_ubox_stack_res(const STACK_RES *res);
bool is_ioat_iio_stack_res(const STACK_RES *res);
+bool is_iio_cxl_stack_res(const STACK_RES *res);
void bios_done_msr(void *unused);
#endif
diff --git a/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h b/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h
index 631601e..bf81f3d 100644
--- a/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h
+++ b/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h
@@ -31,8 +31,6 @@
const struct SystemMemoryMapHob *get_system_memory_map(void);
const struct SystemMemoryMapElement *get_system_memory_map_elment(uint8_t *num);
-bool is_iio_cxl_stack_res(const STACK_RES *res);
-
void soc_display_iio_universal_data_hob(const IIO_UDS *hob);
void soc_display_memmap_hob(const struct SystemMemoryMapHob **hob_addr);