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>
This commit is contained in:
Shuo Liu
2024-03-07 07:38:36 +08:00
committed by Lean Sheng Tan
parent c4e68f6080
commit a454b62937
4 changed files with 99 additions and 45 deletions

View File

@@ -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;
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 @@ 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))

View File

@@ -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 @@ 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);

View File

@@ -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

View File

@@ -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);