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:
@@ -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))
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user