From a454b6293743f12c8387a7b6a15f0b29715e39d6 Mon Sep 17 00:00:00 2001 From: Shuo Liu Date: Thu, 7 Mar 2024 07:38:36 +0800 Subject: 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/81099 Reviewed-by: Lean Sheng Tan Tested-by: build bot (Jenkins) --- src/soc/intel/xeon_sp/chip_common.c | 126 +++++++++++++++-------- src/soc/intel/xeon_sp/include/soc/chip_common.h | 17 +++ src/soc/intel/xeon_sp/include/soc/util.h | 1 + src/soc/intel/xeon_sp/spr/include/soc/soc_util.h | 2 - 4 files changed, 100 insertions(+), 46 deletions(-) (limited to 'src/soc') diff --git a/src/soc/intel/xeon_sp/chip_common.c b/src/soc/intel/xeon_sp/chip_common.c index 93949c870d..67c1089635 100644 --- a/src/soc/intel/xeon_sp/chip_common.c +++ b/src/soc/intel/xeon_sp/chip_common.c @@ -176,32 +176,32 @@ static struct device_operations ubox_pcie_domain_ops = { #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_pcie_domains(const union xeon_domain_path dp, struct bus 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; - - 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__); + assert(sr->BusBase + 1 == sr->BusLimit); + + 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); +} + +#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); + + if (!sr) + return; - 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); + int index = 0; - struct bus *const bus = alloc_bus(domain); - bus->secondary = i; - bus->subordinate = bus->secondary; - bus->max_subordinate = bus->secondary; + 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 @@ void attach_iio_stacks(void) 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 47dea8e948..bcfdf62346 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 #include union xeon_domain_path { @@ -15,6 +16,19 @@ union xeon_domain_path { }; }; + +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 @@ union xeon_domain_path { #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 a7d5dac0e6..db66fcb07f 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 @@ void get_iiostack_info(struct iiostack_resource *info); 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 631601e9d8..bf81f3dd07 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); -- cgit v1.2.3