pci_device: Add a helper function for determining if PCI device is wake source

This change adds a helper function `pci_dev_is_wake_source()` that
checks PME_STATUS and PME_ENABLE bits in PM control and status
register to determine if the given device is the source of wake.

BUG=b:169802515
BRANCH=zork

Change-Id: I06e9530b568543ab2f05a4f38dc5c3a527ff391e
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/46030
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Rob Barnes <robbarnes@google.com>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index 8a6f123..ce3e509 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -1643,3 +1643,21 @@
 	pci_update_config16(dev, PCI_COMMAND, ~PCI_COMMAND_MASTER, 0x0);
 }
 #endif
+
+bool pci_dev_is_wake_source(const struct device *dev)
+{
+	unsigned int pm_cap;
+	uint16_t pmcs;
+
+	if (dev->path.type != DEVICE_PATH_PCI)
+		return false;
+
+	pm_cap = pci_find_capability(dev, PCI_CAP_ID_PM);
+	if (!pm_cap)
+		return false;
+
+	pmcs = pci_read_config16(dev, pm_cap + PCI_PM_CTRL);
+
+	/* PCI Device is a wake source if PME_ENABLE and PME_STATUS are set in PMCS register. */
+	return (pmcs & PCI_PM_CTRL_PME_ENABLE) && (pmcs & PCI_PM_CTRL_PME_STATUS);
+}
diff --git a/src/include/device/pci.h b/src/include/device/pci.h
index 6e28cb7..58f5904 100644
--- a/src/include/device/pci.h
+++ b/src/include/device/pci.h
@@ -80,6 +80,14 @@
 struct device *pci_probe_dev(struct device *dev, struct bus *bus,
 				unsigned int devfn);
 
+/*
+ * Determine if the given PCI device is the source of wake from sleep by checking PME_STATUS and
+ * PME_ENABLE bits in PM control and status register.
+ *
+ * Returns true if PCI device is wake source, false otherwise.
+ */
+bool pci_dev_is_wake_source(const struct device *dev);
+
 void do_pci_scan_bridge(struct device *dev,
 	void (*do_scan_bus)(struct bus *bus,
 		unsigned int min_devfn, unsigned int max_devfn));