diff options
-rw-r--r-- | src/soc/intel/xeon_sp/chip_common.c | 72 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/soc_util.c | 5 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/include/soc/util.h | 1 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/skx/soc_util.c | 23 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/soc_util.c | 5 |
5 files changed, 92 insertions, 14 deletions
diff --git a/src/soc/intel/xeon_sp/chip_common.c b/src/soc/intel/xeon_sp/chip_common.c index 144dba1665..08d723bffd 100644 --- a/src/soc/intel/xeon_sp/chip_common.c +++ b/src/soc/intel/xeon_sp/chip_common.c @@ -92,7 +92,51 @@ static struct device_operations iio_pcie_domain_ops = { .scan_bus = iio_pci_domain_scan_bus, }; -/* Attach IIO stack as domains */ +/* + * Used by UBOX stacks. Those contain multiple PCI host bridges, each having + * only one bus with UBOX devices. UBOX devices have no resources. + */ +static struct device_operations ubox_pcie_domain_ops = { + .read_resources = noop_read_resources, + .set_resources = noop_set_resources, + .scan_bus = pci_host_bridge_scan_bus, +}; + +/* + * On the first Xeon-SP generations there are no separate UBOX stacks, + * and the UBOX devices reside on the first and second IIO. Starting + * with 3rd gen Xeon-SP the UBOX devices are located on their own IIO. + */ +static void soc_create_ubox_domains(const union xeon_domain_path dp, struct bus *upstream, + const unsigned int bus_base, const unsigned int bus_limit) +{ + union xeon_domain_path new_path = { + .domain_path = dp.domain_path + }; + + 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_dev(upstream, &path); + if (!domain) + die("%s: out of memory.\n", __func__); + + domain->ops = &ubox_pcie_domain_ops; + + struct bus *const bus = alloc_bus(domain); + bus->secondary = i; + bus->subordinate = bus->secondary; + bus->max_subordinate = bus->secondary; + } +} + +/* Attach stack as domains */ void attach_iio_stacks(struct device *dev) { const IIO_UDS *hob = get_iio_uds(); @@ -114,19 +158,19 @@ void attach_iio_stacks(struct device *dev) dn.stack = x; dn.bus = ri->BusBase; - if (!is_pcie_iio_stack_res(ri)) { - if (CONFIG(HAVE_IOAT_DOMAINS)) - soc_create_ioat_domains(dn, dev->upstream, ri); - continue; - } - - struct device_path path; - path.type = DEVICE_PATH_DOMAIN; - path.domain.domain = dn.domain_path; - struct device *iio_domain = alloc_dev(dev->upstream, &path); - if (iio_domain == NULL) - die("%s: out of memory.\n", __func__); - iio_domain->ops = &iio_pcie_domain_ops; + if (is_ubox_stack_res(ri)) { + soc_create_ubox_domains(dn, dev->upstream, ri->BusBase, ri->BusLimit); + } else if (is_pcie_iio_stack_res(ri)) { + struct device_path path; + path.type = DEVICE_PATH_DOMAIN; + path.domain.domain = dn.domain_path; + struct device *iio_domain = alloc_dev(dev->upstream, &path); + if (iio_domain == NULL) + die("%s: out of memory.\n", __func__); + + iio_domain->ops = &iio_pcie_domain_ops; + } else if (CONFIG(HAVE_IOAT_DOMAINS)) + soc_create_ioat_domains(dn, dev->upstream, ri); } } } diff --git a/src/soc/intel/xeon_sp/cpx/soc_util.c b/src/soc/intel/xeon_sp/cpx/soc_util.c index 7a7e295b62..836cd0c81f 100644 --- a/src/soc/intel/xeon_sp/cpx/soc_util.c +++ b/src/soc/intel/xeon_sp/cpx/soc_util.c @@ -30,6 +30,11 @@ bool is_pcie_iio_stack_res(const STACK_RES *res) return res->Personality == TYPE_UBOX_IIO; } +bool is_ubox_stack_res(const STACK_RES *res) +{ + return res->Personality == TYPE_UBOX; +} + uint8_t get_stack_busno(const uint8_t stack) { if (stack >= MAX_IIO_STACK) { diff --git a/src/soc/intel/xeon_sp/include/soc/util.h b/src/soc/intel/xeon_sp/include/soc/util.h index fb9b1380b4..89cc5017fd 100644 --- a/src/soc/intel/xeon_sp/include/soc/util.h +++ b/src/soc/intel/xeon_sp/include/soc/util.h @@ -24,6 +24,7 @@ struct iiostack_resource { 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); void bios_done_msr(void *unused); #endif diff --git a/src/soc/intel/xeon_sp/skx/soc_util.c b/src/soc/intel/xeon_sp/skx/soc_util.c index a5db8fd309..3e0299956f 100644 --- a/src/soc/intel/xeon_sp/skx/soc_util.c +++ b/src/soc/intel/xeon_sp/skx/soc_util.c @@ -59,6 +59,29 @@ bool is_pcie_iio_stack_res(const STACK_RES *res) return res->BusBase < res->BusLimit; } +bool is_ubox_stack_res(const STACK_RES *res) +{ + /* + * Unlike on later platforms there's no separate "UBOX" stack. + * + * The UBOX devices can always be found on the first bus on the stack IIO0 (CSTACK). + * This bus is also referred to as uncore bus 0 or B(30). + * It has at a fixed address the UBOX: + * B(30):8.0 8086:2014 + * B(30):8.1 8086:2015 + * B(30):8.2 8086:2016 + * + * The PCU devices can always be on the first bus of the stack IIO1 (PSTACK). + * This bus is also referred to as uncore bus 1 or B(31). + * It has at a fixed address the PCU: + * B(31):30.0 8086:2080 + * B(31):30.1 8086:2081 + * B(31):30.2 8086:2082 + */ + + return false; +} + uint8_t get_stack_busno(const uint8_t stack) { if (stack >= MAX_IIO_STACK) { diff --git a/src/soc/intel/xeon_sp/spr/soc_util.c b/src/soc/intel/xeon_sp/spr/soc_util.c index 9c1a691418..fb8761189c 100644 --- a/src/soc/intel/xeon_sp/spr/soc_util.c +++ b/src/soc/intel/xeon_sp/spr/soc_util.c @@ -73,6 +73,11 @@ bool is_pcie_iio_stack_res(const STACK_RES *res) return res->Personality == TYPE_UBOX_IIO; } +bool is_ubox_stack_res(const STACK_RES *res) +{ + return res->Personality == TYPE_UBOX; +} + /* * Given a stack resource, figure out whether the corresponding stack has * CXL device. |