soc/intel/xeon_sp: Add helper functions

Provide a helper function to locate PCI devices on a given socket
by their PCI vendor and device IDs and functions to return
information about the current device, like the corresponding stack
and socket.
In addition add functions to return "location" information, like stack
and socket affiliation.
This becomes handy when locating devices and generating ACPI code.

Change-Id: I266360588548ba579f46b228c4d5b3ae6e39a029
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/80094
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Shuo Liu <shuo.liu@intel.com>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
diff --git a/src/soc/intel/xeon_sp/chip_common.c b/src/soc/intel/xeon_sp/chip_common.c
index 08d723b..0c1d52b 100644
--- a/src/soc/intel/xeon_sp/chip_common.c
+++ b/src/soc/intel/xeon_sp/chip_common.c
@@ -22,6 +22,86 @@
 	return &hob->PlatformData.IIO_resource[dn.socket].StackRes[dn.stack];
 }
 
+/**
+ * Find a device of a given vendor and type for the specified socket.
+ * The function iterates over all PCI domains of the specified socket
+ * and matches the PCI vendor and device ID.
+ *
+ * @param socket The socket where to search for the device.
+ * @param vendor A PCI vendor ID (e.g. 0x8086 for Intel).
+ * @param device A PCI device ID.
+ * @return Pointer to the device struct.
+ */
+struct device *dev_find_device_on_socket(uint8_t socket, u16 vendor, u16 device)
+{
+	struct device *domain, *dev = NULL;
+	union xeon_domain_path dn;
+
+	while ((dev = dev_find_device(vendor, device, dev))) {
+		domain = dev_get_pci_domain(dev);
+		if (!domain)
+			continue;
+		dn.domain_path = domain->path.domain.domain;
+		if (dn.socket != socket)
+			continue;
+		return dev;
+	}
+
+	return NULL;
+}
+
+/**
+ * Returns the socket ID where the specified device is connected to.
+ * This is an integer in the range [0, CONFIG_MAX_SOCKET).
+ *
+ * @param dev The device to look up
+ *
+ * @return Socket ID the device is attached to, negative number on error.
+ */
+int iio_pci_domain_socket_from_dev(struct device *dev)
+{
+	struct device *domain;
+	union xeon_domain_path dn;
+
+	if (dev->path.type == DEVICE_PATH_DOMAIN)
+		domain = dev;
+	else
+		domain = dev_get_pci_domain(dev);
+
+	if (!domain)
+		return -1;
+
+	dn.domain_path = domain->path.domain.domain;
+
+	return dn.socket;
+}
+
+/**
+ * Returns the stack ID where the specified device is connected to.
+ * This is an integer in the range [0, MAX_IIO_STACK).
+ *
+ * @param dev The device to look up
+ *
+ * @return Stack ID the device is attached to, negative number on error.
+ */
+int iio_pci_domain_stack_from_dev(struct device *dev)
+{
+	struct device *domain;
+	union xeon_domain_path dn;
+
+	if (dev->path.type == DEVICE_PATH_DOMAIN)
+		domain = dev;
+	else
+		domain = dev_get_pci_domain(dev);
+
+	if (!domain)
+		return -1;
+
+	dn.domain_path = domain->path.domain.domain;
+
+	return dn.stack;
+}
+
 void iio_pci_domain_read_resources(struct device *dev)
 {
 	struct resource *res;
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 f3cb950..3727777 100644
--- a/src/soc/intel/xeon_sp/include/soc/chip_common.h
+++ b/src/soc/intel/xeon_sp/include/soc/chip_common.h
@@ -20,5 +20,8 @@
 void attach_iio_stacks(struct device *dev);
 
 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);
+int iio_pci_domain_socket_from_dev(struct device *dev);
+int iio_pci_domain_stack_from_dev(struct device *dev);
 
 #endif /* _CHIP_COMMON_H_ */