summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/xeon_sp/chip_common.c72
-rw-r--r--src/soc/intel/xeon_sp/cpx/soc_util.c5
-rw-r--r--src/soc/intel/xeon_sp/include/soc/util.h1
-rw-r--r--src/soc/intel/xeon_sp/skx/soc_util.c23
-rw-r--r--src/soc/intel/xeon_sp/spr/soc_util.c5
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.