soc/intel/xeon_sp: Further share domain creation logics in Xeon-SP

With this patch, all domain creation logics are moved into the scope
of attach_iio_stack/chip_common.c for the ease of maintenance
and future SoC integration where the domain creation process for
specific stack types might be overridden.

TEST=intel/archercity CRB

1. Boot to CentOS 9 Stream Cloud.
2. Compare PCIe enumeration and ACPI table generation logs before and
and after this patch, no changes.

Change-Id: If06bb5ff41b5f04cef766cf29d38369c6022da79
Signed-off-by: Shuo Liu <shuo.liu@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/81098
Reviewed-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/soc/intel/xeon_sp/chip_common.c b/src/soc/intel/xeon_sp/chip_common.c
index 03ae70a..93949c8 100644
--- a/src/soc/intel/xeon_sp/chip_common.c
+++ b/src/soc/intel/xeon_sp/chip_common.c
@@ -148,22 +148,6 @@
 	}
 }
 
-void iio_pci_domain_scan_bus(struct device *dev)
-{
-	const STACK_RES *sr = domain_to_stack_res(dev);
-	if (!sr)
-		return;
-
-	struct bus *bus = alloc_bus(dev);
-	bus->secondary = sr->BusBase;
-	bus->subordinate = sr->BusBase;
-	bus->max_subordinate = sr->BusLimit;
-
-	printk(BIOS_SPEW, "Scanning IIO stack %d: busses %x-%x\n", dev->path.domain.domain,
-	       dev->downstream->secondary, dev->downstream->max_subordinate);
-	pci_host_bridge_scan_bus(dev);
-}
-
 /*
  * Used by IIO stacks for PCIe bridges. Those contain 1 PCI host bridges,
  *  all the bus numbers on the IIO stack can be used for this bridge
@@ -171,9 +155,10 @@
 static struct device_operations iio_pcie_domain_ops = {
 	.read_resources = iio_pci_domain_read_resources,
 	.set_resources = pci_domain_set_resources,
-	.scan_bus = iio_pci_domain_scan_bus,
+	.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
 };
 
@@ -187,22 +172,53 @@
 	.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
 };
 
+static void soc_create_pcie_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
+	};
+	new_path.bus = sr->BusBase;
+
+	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__);
+
+	domain->ops = &iio_pcie_domain_ops;
+	iio_domain_set_acpi_name(domain, DOMAIN_TYPE_PCIE);
+
+	struct bus *const bus = alloc_bus(domain);
+	bus->secondary = sr->BusBase;
+	bus->subordinate = sr->BusBase;
+	bus->max_subordinate = sr->BusLimit;
+}
+
 /*
  * 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)
+				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;
@@ -213,7 +229,7 @@
 				.domain = new_path.domain_path,
 			},
 		};
-		struct device *const domain = alloc_dev(upstream, &path);
+		struct device *const domain = alloc_find_dev(upstream, &path);
 		if (!domain)
 			die("%s: out of memory.\n", __func__);
 
@@ -229,19 +245,16 @@
 }
 
 /* Attach stack as domains */
-void attach_iio_stacks(struct device *dev)
+void attach_iio_stacks(void)
 {
 	const IIO_UDS *hob = get_iio_uds();
 	union xeon_domain_path dn = { .domain_path = 0 };
 	if (!hob)
 		return;
 
+	struct bus *root_bus = dev_root.downstream;
 	for (int s = 0; s < hob->PlatformData.numofIIO; ++s) {
 		for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
-			if (s == 0 && x == 0) {
-				iio_domain_set_acpi_name(dev, DOMAIN_TYPE_PCIE);
-				continue;
-			}
 			const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
 			if (ri->BusBase > ri->BusLimit)
 				continue;
@@ -249,22 +262,13 @@
 			/* Prepare domain path */
 			dn.socket = s;
 			dn.stack = x;
-			dn.bus = ri->BusBase;
 
-			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;
-				iio_domain_set_acpi_name(iio_domain, DOMAIN_TYPE_PCIE);
-			} else if (CONFIG(HAVE_IOAT_DOMAINS))
-				soc_create_ioat_domains(dn, dev->upstream, ri);
+			if (is_ubox_stack_res(ri))
+				soc_create_ubox_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))
+				soc_create_ioat_domains(dn, root_bus, ri);
 		}
 	}
 }
diff --git a/src/soc/intel/xeon_sp/cpx/chip.c b/src/soc/intel/xeon_sp/cpx/chip.c
index 5fc90e7..8a828c6 100644
--- a/src/soc/intel/xeon_sp/cpx/chip.c
+++ b/src/soc/intel/xeon_sp/cpx/chip.c
@@ -27,16 +27,6 @@
 	mainboard_silicon_init_params(silupd);
 }
 
-static struct device_operations pci_domain_ops = {
-	.read_resources = iio_pci_domain_read_resources,
-	.set_resources = pci_domain_set_resources,
-	.scan_bus = iio_pci_domain_scan_bus,
-#if CONFIG(HAVE_ACPI_TABLES)
-	.write_acpi_tables  = &northbridge_write_acpi_tables,
-	.acpi_name          = soc_acpi_name,
-#endif
-};
-
 static struct device_operations cpu_bus_ops = {
 	.read_resources = noop_read_resources,
 	.set_resources = noop_set_resources,
@@ -52,8 +42,7 @@
 {
 	/* Set the operations if it is a special bus type */
 	if (dev->path.type == DEVICE_PATH_DOMAIN) {
-		dev->ops = &pci_domain_ops;
-		attach_iio_stacks(dev);
+		/* domain ops are assigned at their creation */
 	} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
 		dev->ops = &cpu_bus_ops;
 	} else if (dev->path.type == DEVICE_PATH_GPIO) {
@@ -176,6 +165,9 @@
 {
 	printk(BIOS_DEBUG, "coreboot: calling fsp_silicon_init\n");
 	fsp_silicon_init();
+
+	attach_iio_stacks();
+
 	override_hpet_ioapic_bdf();
 	pch_enable_ioapic();
 	pch_lock_dmictl();
diff --git a/src/soc/intel/xeon_sp/include/soc/chip_common.h b/src/soc/intel/xeon_sp/include/soc/chip_common.h
index a010bd1..47dea8e 100644
--- a/src/soc/intel/xeon_sp/include/soc/chip_common.h
+++ b/src/soc/intel/xeon_sp/include/soc/chip_common.h
@@ -30,8 +30,7 @@
 #define DOMAIN_TYPE_UBX1       "UD"
 
 void iio_pci_domain_read_resources(struct device *dev);
-void iio_pci_domain_scan_bus(struct device *dev);
-void attach_iio_stacks(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);
 struct device *dev_find_device_on_socket(uint8_t socket, u16 vendor, u16 device);
diff --git a/src/soc/intel/xeon_sp/skx/chip.c b/src/soc/intel/xeon_sp/skx/chip.c
index 92663d9..1911e06 100644
--- a/src/soc/intel/xeon_sp/skx/chip.c
+++ b/src/soc/intel/xeon_sp/skx/chip.c
@@ -13,16 +13,6 @@
 #include <soc/soc_util.h>
 #include <soc/util.h>
 
-static struct device_operations pci_domain_ops = {
-	.read_resources = iio_pci_domain_read_resources,
-	.set_resources = pci_domain_set_resources,
-	.scan_bus = iio_pci_domain_scan_bus,
-#if CONFIG(HAVE_ACPI_TABLES)
-	.write_acpi_tables  = &northbridge_write_acpi_tables,
-	.acpi_name          = soc_acpi_name,
-#endif
-};
-
 static struct device_operations cpu_bus_ops = {
 	.read_resources = noop_read_resources,
 	.set_resources = noop_set_resources,
@@ -37,8 +27,7 @@
 {
 	/* Set the operations if it is a special bus type */
 	if (dev->path.type == DEVICE_PATH_DOMAIN) {
-		dev->ops = &pci_domain_ops;
-		attach_iio_stacks(dev);
+		/* domain ops are assigned at their creation */
 	} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
 		dev->ops = &cpu_bus_ops;
 	} else if (dev->path.type == DEVICE_PATH_GPIO) {
@@ -50,6 +39,9 @@
 {
 	printk(BIOS_DEBUG, "coreboot: calling fsp_silicon_init\n");
 	fsp_silicon_init();
+
+	attach_iio_stacks();
+
 	override_hpet_ioapic_bdf();
 	pch_lock_dmictl();
 }
diff --git a/src/soc/intel/xeon_sp/spr/chip.c b/src/soc/intel/xeon_sp/spr/chip.c
index cc3719d..a9387f4 100644
--- a/src/soc/intel/xeon_sp/spr/chip.c
+++ b/src/soc/intel/xeon_sp/spr/chip.c
@@ -38,17 +38,6 @@
 	mainboard_silicon_init_params(silupd);
 }
 
-
-static struct device_operations pci_domain_ops = {
-	.read_resources = iio_pci_domain_read_resources,
-	.set_resources = pci_domain_set_resources,
-	.scan_bus = iio_pci_domain_scan_bus,
-#if CONFIG(HAVE_ACPI_TABLES)
-	.write_acpi_tables = &northbridge_write_acpi_tables,
-	.acpi_name         = soc_acpi_name,
-#endif
-};
-
 static struct device_operations cpu_bus_ops = {
 	.read_resources = noop_read_resources,
 	.set_resources = noop_set_resources,
@@ -64,8 +53,7 @@
 {
 	/* Set the operations if it is a special bus type */
 	if (dev->path.type == DEVICE_PATH_DOMAIN) {
-		dev->ops = &pci_domain_ops;
-		attach_iio_stacks(dev);
+		/* domain ops are assigned at their creation */
 	} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
 		dev->ops = &cpu_bus_ops;
 	} else if (dev->path.type == DEVICE_PATH_GPIO) {
@@ -138,6 +126,9 @@
 {
 	printk(BIOS_DEBUG, "coreboot: calling fsp_silicon_init\n");
 	fsp_silicon_init();
+
+	attach_iio_stacks();
+
 	override_hpet_ioapic_bdf();
 	pch_enable_ioapic();
 	pch_lock_dmictl();
diff --git a/src/soc/intel/xeon_sp/spr/ioat.c b/src/soc/intel/xeon_sp/spr/ioat.c
index bde7eba..2b6aafa 100644
--- a/src/soc/intel/xeon_sp/spr/ioat.c
+++ b/src/soc/intel/xeon_sp/spr/ioat.c
@@ -25,6 +25,7 @@
 	.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
 };
 
@@ -45,7 +46,7 @@
 			.domain = new_path.domain_path,
 		},
 	};
-	struct device *const domain = alloc_dev(upstream, &path);
+	struct device *const domain = alloc_find_dev(upstream, &path);
 	if (!domain)
 		die("%s: out of memory.\n", __func__);
 
diff --git a/src/soc/intel/xeon_sp/uncore_acpi.c b/src/soc/intel/xeon_sp/uncore_acpi.c
index b7c6640..8154638 100644
--- a/src/soc/intel/xeon_sp/uncore_acpi.c
+++ b/src/soc/intel/xeon_sp/uncore_acpi.c
@@ -567,6 +567,10 @@
 unsigned long northbridge_write_acpi_tables(const struct device *device, unsigned long current,
 					    struct acpi_rsdp *rsdp)
 {
+	/* Only write uncore ACPI tables for domain0 */
+	if (device->path.domain.domain != 0)
+		return current;
+
 	acpi_srat_t *srat;
 	acpi_slit_t *slit;
 	acpi_dmar_t *dmar;