diff options
author | Patrick Rudolph <patrick.rudolph@9elements.com> | 2024-01-18 07:57:07 +0100 |
---|---|---|
committer | Lean Sheng Tan <sheng.tan@9elements.com> | 2024-01-31 17:04:33 +0000 |
commit | 15672599e411bb39b9f63b8fc2fb8233f3c62ece (patch) | |
tree | a2f03ad3d9e28c8898d5a97719acde40dd61e15f /src/soc | |
parent | 789adfabb722cec627d29c6320c996de44169f86 (diff) |
soc/intel/xeon_sp: Attach UBOX stacks
Attach UBOX stacks on newer generation Xeon-SP.
In order to use PCI drivers for UBOX devices, locating UBOX devices
by vendor and device IDs and replacing device access by specifying
S:B:D:F numbers, add a PCI domain for the UBOX stacks and let the
PCI enumerator index all devices.
Since there are no PCI BARs on the UBOX bus the PCI locator doesn't
have to assign resources on those buses.
Once all PCI devices on the UBOX stack can be located without knowing
their UBOX bus number and PCI segment the Xeon-SP code can fully
enable the multi PCI segment group support.
Test: ibm/sbp1 (4S) is able to find all PCU devices by PCI ID.
Change-Id: I8f9d52dd117364a42de1c73d39cc86dafeaf2678
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/80091
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com>
Diffstat (limited to 'src/soc')
-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. |