* [PATCH v8 0/3] PCI: Add support for PCIe WAKE# interrupt
@ 2026-03-13 7:08 Krishna Chaitanya Chundru
2026-03-13 7:08 ` [PATCH v8 1/3] PM: sleep: wakeirq: Add support for dedicated shared wake IRQ setup Krishna Chaitanya Chundru
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Krishna Chaitanya Chundru @ 2026-03-13 7:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
Linus Walleij
Cc: linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree, Krishna Chaitanya Chundru,
Manivannan Sadhasivam
PCIe WAKE# interrupt is needed for bringing back PCIe device state from
D3cold to D0.
This is pending from long time, there was two attempts done previously to
add WAKE# support[1], [2]. Those series tried to add support for legacy
interrupts along with WAKE#. Legacy interrupts are already available in
the latest kernel and we can ignore them. For the wake IRQ the series is
trying to use interrupts property define in the device tree.
This series is using gpio property instead of interrupts, from
gpio desc driver will allocate the dedicate IRQ.
Bjorn,
Can you take this series through PCI branch, once other subsystem
maintainers give us ACK.
WAKE# is added in dts schema and merged based on this patch.
https://lore.kernel.org/all/20250515090517.3506772-1-krishna.chundru@oss.qualcomm.com/
[1]: https://lore.kernel.org/all/b2b91240-95fe-145d-502c-d52225497a34@nvidia.com/T/
[2]: https://lore.kernel.org/all/20171226023646.17722-1-jeffy.chen@rock-chips.com/
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
---
Changes in v8:
- Moved the stub functions under CONFIG_OF_IRQ(mani).
- Added the description of how dev_pm_set_dedicated_shared_wake_irq()
works.
- Link to v7: https://lore.kernel.org/r/20260218-wakeirq_support-v7-0-0d4689830207@oss.qualcomm.com
Changes in v7:
- Updated the commit text (Mani).
- Couple of nits like using pci_err instead of dev_err,
use platform_pci_configure_wake(), platform_pci_remove_wake() instead
of calling directly calling pci_configure_of_wake_gpio() & pci_remove_of_wake_gpio() etc (Mani).
- Add a new fwnode_gpiod_get() API that wraps fwnode_gpiod_get_index(..0..), similar to
devm_fwnode_gpiod_get() (Mani).
- Link to v6: https://lore.kernel.org/r/20251127-wakeirq_support-v6-0-60f581f94205@oss.qualcomm.com
Changes in v6:
- Change the name to dev_pm_set_dedicated_shared_wake_irq() and make the
changes pointed by (Rafael).
- Link to v5: https://lore.kernel.org/r/20251107-wakeirq_support-v5-0-464e17f2c20c@oss.qualcomm.com
Changes in v5:
- Enable WAKE# irq only when there is wake -gpios defined in its device
tree node (Bjorn).
- For legacy bindings for direct atach check in root port if we haven't
find the wake in the endpoint node.
- Instead of hooking wake in driver bound case, do it in the framework
irrespective of the driver state (Bjorn).
- Link to v4: https://lore.kernel.org/r/20250801-wake_irq_support-v4-0-6b6639013a1a@oss.qualcomm.com
Changes in v4:
- Move wake from portdrv to core framework to endpoint (Bjorn).
- Added support for multiple WAKE# case (Bjorn). But traverse from
endpoint upstream port to root port till you get WAKE#. And use
IRQF_SHARED flag for requesting interrupts.
- Link to v3: https://lore.kernel.org/r/20250605-wake_irq_support-v3-0-7ba56dc909a5@oss.qualcomm.com
Changes in v3:
- Update the commit messages, function names etc as suggested by Mani.
- return wake_irq if returns error (Neil).
- Link to v2: https://lore.kernel.org/r/20250419-wake_irq_support-v2-0-06baed9a87a1@oss.qualcomm.com
Changes in v2:
- Move the wake irq teardown after pcie_port_device_remove
and move of_pci_setup_wake_irq before pcie_link_rcec (Lukas)
- teardown wake irq in shutdown also.
- Link to v1: https://lore.kernel.org/r/20250401-wake_irq_support-v1-0-d2e22f4a0efd@oss.qualcomm.com
---
Krishna Chaitanya Chundru (3):
PM: sleep: wakeirq: Add support for dedicated shared wake IRQ setup
gpio: Add fwnode_gpiod_get() helper
PCI: Add support for PCIe WAKE# interrupt
drivers/base/power/wakeirq.c | 39 ++++++++++++++++++++---
drivers/pci/of.c | 74 +++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pci.c | 10 ++++++
drivers/pci/pci.h | 2 ++
drivers/pci/probe.c | 2 ++
drivers/pci/remove.c | 1 +
include/linux/gpio/consumer.h | 9 ++++++
include/linux/of_pci.h | 4 +++
include/linux/pci.h | 2 ++
include/linux/pm_wakeirq.h | 6 ++++
10 files changed, 144 insertions(+), 5 deletions(-)
---
base-commit: b29fb8829bff243512bb8c8908fd39406f9fd4c3
change-id: 20251104-wakeirq_support-f54c4baa18c5
Best regards,
--
Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v8 1/3] PM: sleep: wakeirq: Add support for dedicated shared wake IRQ setup
2026-03-13 7:08 [PATCH v8 0/3] PCI: Add support for PCIe WAKE# interrupt Krishna Chaitanya Chundru
@ 2026-03-13 7:08 ` Krishna Chaitanya Chundru
2026-03-13 7:08 ` [PATCH v8 2/3] gpio: Add fwnode_gpiod_get() helper Krishna Chaitanya Chundru
2026-03-13 7:08 ` [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt Krishna Chaitanya Chundru
2 siblings, 0 replies; 10+ messages in thread
From: Krishna Chaitanya Chundru @ 2026-03-13 7:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
Linus Walleij
Cc: linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree, Krishna Chaitanya Chundru
Some devices require more flexibility when configuring their dedicated
wake-up interrupts, such as support for IRQF_SHARED or other IRQ flags.
This is particularly useful in PCIe systems where multiple endpoints
(e.g., Wi-Fi and Bluetooth controllers) share a common WAKE# signal
line which requests platform to re-establish power and reference clocks
to the components. In such cases, drivers can use this new API
dev_pm_set_dedicated_shared_wake_irq() to register a shared wake IRQ.
Update the internal helper __dev_pm_set_dedicated_wake_irq() to accept an
irq_flags argument. Modify the existing dev_pm_set_dedicated_wake_irq()
and dev_pm_set_dedicated_wake_irq_reverse() to preserve current behavior.
When IRQ registered with IRQF_SHARED we can't use IRQF_NO_AUTOEN flag,
so after registering for irq, disable it explicitly.
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
Acked-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
---
drivers/base/power/wakeirq.c | 39 ++++++++++++++++++++++++++++++++++-----
include/linux/pm_wakeirq.h | 6 ++++++
2 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index ad23f0fa5d1a5a9eb49b1af2288ee4908082b13e..b7b106f55559a7c85cb35d9e5ed22fe37970662d 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -171,7 +171,8 @@ static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq)
return IRQ_HANDLED;
}
-static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag)
+static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag,
+ unsigned int irq_flags)
{
struct wake_irq *wirq;
int err;
@@ -200,8 +201,7 @@ static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned
* so we use a threaded irq.
*/
err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq,
- IRQF_ONESHOT | IRQF_NO_AUTOEN,
- wirq->name, wirq);
+ IRQF_ONESHOT | irq_flags, wirq->name, wirq);
if (err)
goto err_free_name;
@@ -237,7 +237,7 @@ static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned
*/
int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
{
- return __dev_pm_set_dedicated_wake_irq(dev, irq, 0);
+ return __dev_pm_set_dedicated_wake_irq(dev, irq, 0, IRQF_NO_AUTOEN);
}
EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
@@ -258,10 +258,39 @@ EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
*/
int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
{
- return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE);
+ return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE,
+ IRQF_NO_AUTOEN);
}
EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse);
+/**
+ * dev_pm_set_dedicated_shared_wake_irq - Request a dedicated shared wake-up interrupt
+ * @dev: Device entry
+ * @irq: Device wake-up interrupt
+ * @flags: Custom IRQ flags (e.g., IRQ_TYPE_EDGE_FALLING)
+ *
+ * This API sets up a threaded interrupt handler for a device that has
+ * a shared wake-up interrupt in addition to the device IO interrupt. It also
+ * sets IRQ flags like IRQ_TYPE_EDGE_FALLING passed by the caller.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int dev_pm_set_dedicated_shared_wake_irq(struct device *dev, int irq, unsigned long flags)
+{
+ struct wake_irq *wirq;
+ int ret;
+
+ ret = __dev_pm_set_dedicated_wake_irq(dev, irq, 0, IRQF_SHARED | flags);
+ if (ret)
+ return ret;
+
+ wirq = dev->power.wakeirq;
+ disable_irq_nosync(wirq->irq);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_shared_wake_irq);
+
/**
* dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt
* @dev: Device
diff --git a/include/linux/pm_wakeirq.h b/include/linux/pm_wakeirq.h
index 25b63ed51b765c2c6919f259668a12675330835e..61f1e840745b56baa57db37563e450cb2d757a85 100644
--- a/include/linux/pm_wakeirq.h
+++ b/include/linux/pm_wakeirq.h
@@ -11,6 +11,7 @@ extern int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq);
extern int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq);
extern void dev_pm_clear_wake_irq(struct device *dev);
extern int devm_pm_set_wake_irq(struct device *dev, int irq);
+extern int dev_pm_set_dedicated_shared_wake_irq(struct device *dev, int irq, unsigned long flags);
#else /* !CONFIG_PM */
@@ -38,5 +39,10 @@ static inline int devm_pm_set_wake_irq(struct device *dev, int irq)
return 0;
}
+static inline int dev_pm_set_dedicated_shared_wake_irq(struct device *dev,
+ int irq, unsigned long flags)
+{
+ return 0;
+}
#endif /* CONFIG_PM */
#endif /* _LINUX_PM_WAKEIRQ_H */
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v8 2/3] gpio: Add fwnode_gpiod_get() helper
2026-03-13 7:08 [PATCH v8 0/3] PCI: Add support for PCIe WAKE# interrupt Krishna Chaitanya Chundru
2026-03-13 7:08 ` [PATCH v8 1/3] PM: sleep: wakeirq: Add support for dedicated shared wake IRQ setup Krishna Chaitanya Chundru
@ 2026-03-13 7:08 ` Krishna Chaitanya Chundru
2026-03-13 13:55 ` Bartosz Golaszewski
2026-03-13 7:08 ` [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt Krishna Chaitanya Chundru
2 siblings, 1 reply; 10+ messages in thread
From: Krishna Chaitanya Chundru @ 2026-03-13 7:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
Linus Walleij
Cc: linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree, Krishna Chaitanya Chundru,
Manivannan Sadhasivam
Add fwnode_gpiod_get() as a convenience wrapper around
fwnode_gpiod_get_index() for the common case where only the
first GPIO is required.
This mirrors existing gpiod_get() and devm_gpiod_get() helpers
and avoids open-coding index 0 at call sites.
Suggested-by: Manivannan Sadhasivam <mani@kernel.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
---
include/linux/gpio/consumer.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 0d8408582918680bfea6a04ccedfc0c75211907a..fee926c0262ce9dc4b9a3c151e74f2cf37470a49 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -596,6 +596,15 @@ static inline int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc,
}
#endif /* CONFIG_GPIOLIB && CONFIG_HTE */
+static inline
+struct gpio_desc *fwnode_gpiod_get(struct fwnode_handle *fwnode,
+ const char *con_id,
+ enum gpiod_flags flags,
+ const char *label)
+{
+ return fwnode_gpiod_get_index(fwnode, con_id, 0, flags, label);
+}
+
static inline
struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev,
struct fwnode_handle *fwnode,
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt
2026-03-13 7:08 [PATCH v8 0/3] PCI: Add support for PCIe WAKE# interrupt Krishna Chaitanya Chundru
2026-03-13 7:08 ` [PATCH v8 1/3] PM: sleep: wakeirq: Add support for dedicated shared wake IRQ setup Krishna Chaitanya Chundru
2026-03-13 7:08 ` [PATCH v8 2/3] gpio: Add fwnode_gpiod_get() helper Krishna Chaitanya Chundru
@ 2026-03-13 7:08 ` Krishna Chaitanya Chundru
2026-03-13 13:58 ` Manivannan Sadhasivam
2026-03-17 7:26 ` Manivannan Sadhasivam
2 siblings, 2 replies; 10+ messages in thread
From: Krishna Chaitanya Chundru @ 2026-03-13 7:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
Linus Walleij
Cc: linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree, Krishna Chaitanya Chundru
According to the PCI Express specification (PCIe r7.0, Section 5.3.3.2),
two link wakeup mechanisms are defined: Beacon and WAKE#. Beacon is a
hardware-only mechanism and is invisible to software (PCIe r7.0,
Section 4.2.7.8.1). This change adds support for the WAKE# mechanism in
the PCI core.
According to the PCIe specification, multiple WAKE# signals can exist in
a system or each component in the hierarchy could share a single WAKE#
signal. In configurations involving a PCIe switch, each downstream port
(DSP) of the switch may be connected to a separate WAKE# line, allowing
each endpoint to signal WAKE# independently. From figure 5.4 in sec
5.3.3.2, WAKE# can also be terminated at the switch itself. To support
this, the WAKE# should be described in the device tree node of the
endpoint/bridge. If all endpoints share a single WAKE# line, then each
endpoint node should describe the same WAKE# signal or a single WAKE# in
the Root Port node.
In pci_device_add(), PCI framework will search for the WAKE# in device
node, If not found, it searches in its upstream port only if upstream port
is Root Port. Once found, register for the wake IRQ in shared mode, as the
WAKE# may be shared among multiple endpoints.
dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with a
device and requests it, but the PM core keeps the IRQ disabled by default.
The IRQ is enabled only when the device is permitted to wake the system,
i.e. during system suspend and after runtime suspend, and only when device
wakeup is enabled.
When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume() to
bring the device back to an active power state, such as transitioning from
D3cold to D0. Once the device is active and the link is usable, the
endpoint may generate a PME, which is then handled by the PCI core through
PME polling or the PCIe PME service driver to complete the wakeup of the
endpoint.
WAKE# is added in dts schema and merged based on below links.
Link: https://lore.kernel.org/all/20250515090517.3506772-1-krishna.chundru@oss.qualcomm.com/
Link: https://github.com/devicetree-org/dt-schema/pull/170
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
---
drivers/pci/of.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pci.c | 10 +++++++
drivers/pci/pci.h | 2 ++
drivers/pci/probe.c | 2 ++
drivers/pci/remove.c | 1 +
include/linux/of_pci.h | 4 +++
include/linux/pci.h | 2 ++
7 files changed, 95 insertions(+)
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 9f8eb5df279ed28db7a3b2fd29c65da9975c2efa..b7199d3598b31b62245716c178a5a73565efc89e 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -7,6 +7,7 @@
#define pr_fmt(fmt) "PCI: OF: " fmt
#include <linux/cleanup.h>
+#include <linux/gpio/consumer.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -15,6 +16,7 @@
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
#include "pci.h"
#ifdef CONFIG_PCI
@@ -586,6 +588,78 @@ int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
return irq_create_of_mapping(&oirq);
}
EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
+
+static void pci_configure_wake_irq(struct pci_dev *pdev, struct gpio_desc *wake)
+{
+ int ret, wake_irq;
+
+ wake_irq = gpiod_to_irq(wake);
+ if (wake_irq < 0) {
+ pci_err(pdev, "Failed to get wake irq: %d\n", wake_irq);
+ return;
+ }
+
+ device_init_wakeup(&pdev->dev, true);
+
+ /*
+ * dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with the
+ * device and requests it, but the PM core keeps it disabled by default.
+ * The IRQ is enabled only when the device is allowed to wake the system
+ * (during system suspend and after runtime suspend), and only if device
+ * wakeup is enabled.
+ *
+ * When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume()
+ * to bring the device back to an active power state (e.g. from D3cold to D0).
+ * Once the device is active and the link is usable, the endpoint may signal
+ * a PME, which is then handled by the PCI core (either via PME polling or the
+ * PCIe PME service driver) to wakeup particular endpoint.
+ */
+ ret = dev_pm_set_dedicated_shared_wake_irq(&pdev->dev, wake_irq,
+ IRQ_TYPE_EDGE_FALLING);
+ if (ret < 0) {
+ pci_err(pdev, "Failed to set wake IRQ: %d\n", ret);
+ device_init_wakeup(&pdev->dev, false);
+ }
+}
+
+void pci_configure_of_wake_gpio(struct pci_dev *dev)
+{
+ struct device_node *dn = pci_device_to_OF_node(dev);
+ struct pci_dev *upstream;
+ struct gpio_desc *gpio;
+
+ if (!dn)
+ return;
+
+ /*
+ * The devices in a hierarchy expose wakeup capability through the 'wake-gpios'
+ * property defined either in the device node or in the Slot node. So first check
+ * for the property in device node and if not available, check in the Slot node.
+ */
+ gpio = fwnode_gpiod_get(of_fwnode_handle(dn), "wake",
+ GPIOD_IN | GPIOD_FLAGS_BIT_NONEXCLUSIVE, NULL);
+ if (IS_ERR(gpio)) {
+ upstream = pci_upstream_bridge(dev);
+ if (upstream && pci_is_root_bus(upstream->bus) && upstream->wake)
+ pci_configure_wake_irq(dev, upstream->wake);
+ } else {
+ dev->wake = gpio;
+ pci_configure_wake_irq(dev, gpio);
+ }
+}
+
+void pci_remove_of_wake_gpio(struct pci_dev *dev)
+{
+ struct device_node *dn = pci_device_to_OF_node(dev);
+
+ if (!dn)
+ return;
+
+ dev_pm_clear_wake_irq(&dev->dev);
+ device_init_wakeup(&dev->dev, false);
+ gpiod_put(dev->wake);
+ dev->wake = NULL;
+}
#endif /* CONFIG_OF_IRQ */
static int pci_parse_request_of_pci_ranges(struct device *dev,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8479c2e1f74f1044416281aba11bf071ea89488a..3d858f36ab48a6daec645574ca9027d9d6f071de 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -17,6 +17,7 @@
#include <linux/lockdep.h>
#include <linux/msi.h>
#include <linux/of.h>
+#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/slab.h>
@@ -1123,6 +1124,15 @@ static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
return acpi_pci_bridge_d3(dev);
}
+void platform_pci_configure_wake(struct pci_dev *dev)
+{
+ return pci_configure_of_wake_gpio(dev);
+}
+
+void platform_pci_remove_wake(struct pci_dev *dev)
+{
+ return pci_remove_of_wake_gpio(dev);
+}
/**
* pci_update_current_state - Read power state of given device and cache it
* @dev: PCI device to handle.
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 13d998fbacce6698514d92500dfea03cc562cdc2..65ca9551e558d2e3331fab0a968620d6b2a2522a 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -282,6 +282,8 @@ void pci_msix_init(struct pci_dev *dev);
bool pci_bridge_d3_possible(struct pci_dev *dev);
void pci_bridge_d3_update(struct pci_dev *dev);
int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type);
+void platform_pci_configure_wake(struct pci_dev *dev);
+void platform_pci_remove_wake(struct pci_dev *dev);
static inline bool pci_bus_rrs_vendor_id(u32 l)
{
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bccc7a4bdd794384b7877d453c7989941471c999..372b0d2f4531ea53c0570608306a547101d59e7b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2771,6 +2771,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
/* Establish pdev->tsm for newly added (e.g. new SR-IOV VFs) */
pci_tsm_init(dev);
+ platform_pci_configure_wake(dev);
+
pci_npem_create(dev);
pci_doe_sysfs_init(dev);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index e9d519993853f92f1810d3eff9f44ca7e3e1abd9..d781b41e57c4444077075690cec926a9fe15334f 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -35,6 +35,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
if (pci_dev_test_and_set_removed(dev))
return;
+ platform_pci_remove_wake(dev);
pci_doe_sysfs_teardown(dev);
pci_npem_remove(dev);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 29658c0ee71ff10122760214d04ee2bab01709fd..0efd6e9cb4d3d3beaafb42ea411303139f1150d5 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -30,12 +30,16 @@ static inline void of_pci_check_probe_only(void) { }
#if IS_ENABLED(CONFIG_OF_IRQ)
int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
+void pci_configure_of_wake_gpio(struct pci_dev *dev);
+void pci_remove_of_wake_gpio(struct pci_dev *dev);
#else
static inline int
of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
{
return 0;
}
+static inline void pci_configure_of_wake_gpio(struct pci_dev *dev) { }
+static inline void pci_remove_of_wake_gpio(struct pci_dev *dev) { }
#endif
#endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1c270f1d512301de4d462fe7e5097c32af5c6f8d..d1e08df8a8deaa87780589f23242767fdcdba541 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -586,6 +586,8 @@ struct pci_dev {
/* These methods index pci_reset_fn_methods[] */
u8 reset_methods[PCI_NUM_RESET_METHODS]; /* In priority order */
+ struct gpio_desc *wake; /* Holds WAKE# gpio */
+
#ifdef CONFIG_PCIE_TPH
u16 tph_cap; /* TPH capability offset */
u8 tph_mode; /* TPH mode */
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v8 2/3] gpio: Add fwnode_gpiod_get() helper
2026-03-13 7:08 ` [PATCH v8 2/3] gpio: Add fwnode_gpiod_get() helper Krishna Chaitanya Chundru
@ 2026-03-13 13:55 ` Bartosz Golaszewski
0 siblings, 0 replies; 10+ messages in thread
From: Bartosz Golaszewski @ 2026-03-13 13:55 UTC (permalink / raw)
To: Krishna Chaitanya Chundru
Cc: linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree, Manivannan Sadhasivam,
Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan
On Fri, 13 Mar 2026 08:08:41 +0100, Krishna Chaitanya Chundru
<krishna.chundru@oss.qualcomm.com> said:
> Add fwnode_gpiod_get() as a convenience wrapper around
> fwnode_gpiod_get_index() for the common case where only the
> first GPIO is required.
>
> This mirrors existing gpiod_get() and devm_gpiod_get() helpers
> and avoids open-coding index 0 at call sites.
>
> Suggested-by: Manivannan Sadhasivam <mani@kernel.org>
> Acked-by: Manivannan Sadhasivam <mani@kernel.org>
> Reviewed-by: Linus Walleij <linusw@kernel.org>
> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
> ---
> include/linux/gpio/consumer.h | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
> index 0d8408582918680bfea6a04ccedfc0c75211907a..fee926c0262ce9dc4b9a3c151e74f2cf37470a49 100644
> --- a/include/linux/gpio/consumer.h
> +++ b/include/linux/gpio/consumer.h
> @@ -596,6 +596,15 @@ static inline int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc,
> }
> #endif /* CONFIG_GPIOLIB && CONFIG_HTE */
>
> +static inline
> +struct gpio_desc *fwnode_gpiod_get(struct fwnode_handle *fwnode,
> + const char *con_id,
> + enum gpiod_flags flags,
> + const char *label)
> +{
> + return fwnode_gpiod_get_index(fwnode, con_id, 0, flags, label);
> +}
> +
> static inline
> struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev,
> struct fwnode_handle *fwnode,
>
> --
> 2.34.1
>
>
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt
2026-03-13 7:08 ` [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt Krishna Chaitanya Chundru
@ 2026-03-13 13:58 ` Manivannan Sadhasivam
2026-03-16 12:16 ` Krishna Chaitanya Chundru
2026-03-17 7:26 ` Manivannan Sadhasivam
1 sibling, 1 reply; 10+ messages in thread
From: Manivannan Sadhasivam @ 2026-03-13 13:58 UTC (permalink / raw)
To: Krishna Chaitanya Chundru
Cc: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree
On Fri, Mar 13, 2026 at 12:38:42PM +0530, Krishna Chaitanya Chundru wrote:
> According to the PCI Express specification (PCIe r7.0, Section 5.3.3.2),
> two link wakeup mechanisms are defined: Beacon and WAKE#. Beacon is a
> hardware-only mechanism and is invisible to software (PCIe r7.0,
> Section 4.2.7.8.1). This change adds support for the WAKE# mechanism in
> the PCI core.
>
> According to the PCIe specification, multiple WAKE# signals can exist in
> a system or each component in the hierarchy could share a single WAKE#
> signal. In configurations involving a PCIe switch, each downstream port
> (DSP) of the switch may be connected to a separate WAKE# line, allowing
> each endpoint to signal WAKE# independently. From figure 5.4 in sec
> 5.3.3.2, WAKE# can also be terminated at the switch itself. To support
> this, the WAKE# should be described in the device tree node of the
> endpoint/bridge. If all endpoints share a single WAKE# line, then each
> endpoint node should describe the same WAKE# signal or a single WAKE# in
> the Root Port node.
>
> In pci_device_add(), PCI framework will search for the WAKE# in device
> node, If not found, it searches in its upstream port only if upstream port
> is Root Port. Once found, register for the wake IRQ in shared mode, as the
> WAKE# may be shared among multiple endpoints.
>
> dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with a
> device and requests it, but the PM core keeps the IRQ disabled by default.
> The IRQ is enabled only when the device is permitted to wake the system,
> i.e. during system suspend and after runtime suspend, and only when device
> wakeup is enabled.
>
> When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume() to
> bring the device back to an active power state, such as transitioning from
> D3cold to D0. Once the device is active and the link is usable, the
> endpoint may generate a PME, which is then handled by the PCI core through
> PME polling or the PCIe PME service driver to complete the wakeup of the
> endpoint.
>
> WAKE# is added in dts schema and merged based on below links.
>
> Link: https://lore.kernel.org/all/20250515090517.3506772-1-krishna.chundru@oss.qualcomm.com/
> Link: https://github.com/devicetree-org/dt-schema/pull/170
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
No. Linus never gave this tag for *this* patch.
- Mani
> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
> ---
> drivers/pci/of.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/pci/pci.c | 10 +++++++
> drivers/pci/pci.h | 2 ++
> drivers/pci/probe.c | 2 ++
> drivers/pci/remove.c | 1 +
> include/linux/of_pci.h | 4 +++
> include/linux/pci.h | 2 ++
> 7 files changed, 95 insertions(+)
>
> diff --git a/drivers/pci/of.c b/drivers/pci/of.c
> index 9f8eb5df279ed28db7a3b2fd29c65da9975c2efa..b7199d3598b31b62245716c178a5a73565efc89e 100644
> --- a/drivers/pci/of.c
> +++ b/drivers/pci/of.c
> @@ -7,6 +7,7 @@
> #define pr_fmt(fmt) "PCI: OF: " fmt
>
> #include <linux/cleanup.h>
> +#include <linux/gpio/consumer.h>
> #include <linux/irqdomain.h>
> #include <linux/kernel.h>
> #include <linux/pci.h>
> @@ -15,6 +16,7 @@
> #include <linux/of_address.h>
> #include <linux/of_pci.h>
> #include <linux/platform_device.h>
> +#include <linux/pm_wakeirq.h>
> #include "pci.h"
>
> #ifdef CONFIG_PCI
> @@ -586,6 +588,78 @@ int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
> return irq_create_of_mapping(&oirq);
> }
> EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
> +
> +static void pci_configure_wake_irq(struct pci_dev *pdev, struct gpio_desc *wake)
> +{
> + int ret, wake_irq;
> +
> + wake_irq = gpiod_to_irq(wake);
> + if (wake_irq < 0) {
> + pci_err(pdev, "Failed to get wake irq: %d\n", wake_irq);
> + return;
> + }
> +
> + device_init_wakeup(&pdev->dev, true);
> +
> + /*
> + * dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with the
> + * device and requests it, but the PM core keeps it disabled by default.
> + * The IRQ is enabled only when the device is allowed to wake the system
> + * (during system suspend and after runtime suspend), and only if device
> + * wakeup is enabled.
> + *
> + * When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume()
> + * to bring the device back to an active power state (e.g. from D3cold to D0).
> + * Once the device is active and the link is usable, the endpoint may signal
> + * a PME, which is then handled by the PCI core (either via PME polling or the
> + * PCIe PME service driver) to wakeup particular endpoint.
> + */
> + ret = dev_pm_set_dedicated_shared_wake_irq(&pdev->dev, wake_irq,
> + IRQ_TYPE_EDGE_FALLING);
> + if (ret < 0) {
> + pci_err(pdev, "Failed to set wake IRQ: %d\n", ret);
> + device_init_wakeup(&pdev->dev, false);
> + }
> +}
> +
> +void pci_configure_of_wake_gpio(struct pci_dev *dev)
> +{
> + struct device_node *dn = pci_device_to_OF_node(dev);
> + struct pci_dev *upstream;
> + struct gpio_desc *gpio;
> +
> + if (!dn)
> + return;
> +
> + /*
> + * The devices in a hierarchy expose wakeup capability through the 'wake-gpios'
> + * property defined either in the device node or in the Slot node. So first check
> + * for the property in device node and if not available, check in the Slot node.
> + */
> + gpio = fwnode_gpiod_get(of_fwnode_handle(dn), "wake",
> + GPIOD_IN | GPIOD_FLAGS_BIT_NONEXCLUSIVE, NULL);
> + if (IS_ERR(gpio)) {
> + upstream = pci_upstream_bridge(dev);
> + if (upstream && pci_is_root_bus(upstream->bus) && upstream->wake)
> + pci_configure_wake_irq(dev, upstream->wake);
> + } else {
> + dev->wake = gpio;
> + pci_configure_wake_irq(dev, gpio);
> + }
> +}
> +
> +void pci_remove_of_wake_gpio(struct pci_dev *dev)
> +{
> + struct device_node *dn = pci_device_to_OF_node(dev);
> +
> + if (!dn)
> + return;
> +
> + dev_pm_clear_wake_irq(&dev->dev);
> + device_init_wakeup(&dev->dev, false);
> + gpiod_put(dev->wake);
> + dev->wake = NULL;
> +}
> #endif /* CONFIG_OF_IRQ */
>
> static int pci_parse_request_of_pci_ranges(struct device *dev,
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 8479c2e1f74f1044416281aba11bf071ea89488a..3d858f36ab48a6daec645574ca9027d9d6f071de 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -17,6 +17,7 @@
> #include <linux/lockdep.h>
> #include <linux/msi.h>
> #include <linux/of.h>
> +#include <linux/of_pci.h>
> #include <linux/pci.h>
> #include <linux/pm.h>
> #include <linux/slab.h>
> @@ -1123,6 +1124,15 @@ static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
> return acpi_pci_bridge_d3(dev);
> }
>
> +void platform_pci_configure_wake(struct pci_dev *dev)
> +{
> + return pci_configure_of_wake_gpio(dev);
> +}
> +
> +void platform_pci_remove_wake(struct pci_dev *dev)
> +{
> + return pci_remove_of_wake_gpio(dev);
> +}
> /**
> * pci_update_current_state - Read power state of given device and cache it
> * @dev: PCI device to handle.
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 13d998fbacce6698514d92500dfea03cc562cdc2..65ca9551e558d2e3331fab0a968620d6b2a2522a 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -282,6 +282,8 @@ void pci_msix_init(struct pci_dev *dev);
> bool pci_bridge_d3_possible(struct pci_dev *dev);
> void pci_bridge_d3_update(struct pci_dev *dev);
> int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type);
> +void platform_pci_configure_wake(struct pci_dev *dev);
> +void platform_pci_remove_wake(struct pci_dev *dev);
>
> static inline bool pci_bus_rrs_vendor_id(u32 l)
> {
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index bccc7a4bdd794384b7877d453c7989941471c999..372b0d2f4531ea53c0570608306a547101d59e7b 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -2771,6 +2771,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
> /* Establish pdev->tsm for newly added (e.g. new SR-IOV VFs) */
> pci_tsm_init(dev);
>
> + platform_pci_configure_wake(dev);
> +
> pci_npem_create(dev);
>
> pci_doe_sysfs_init(dev);
> diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
> index e9d519993853f92f1810d3eff9f44ca7e3e1abd9..d781b41e57c4444077075690cec926a9fe15334f 100644
> --- a/drivers/pci/remove.c
> +++ b/drivers/pci/remove.c
> @@ -35,6 +35,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
> if (pci_dev_test_and_set_removed(dev))
> return;
>
> + platform_pci_remove_wake(dev);
> pci_doe_sysfs_teardown(dev);
> pci_npem_remove(dev);
>
> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
> index 29658c0ee71ff10122760214d04ee2bab01709fd..0efd6e9cb4d3d3beaafb42ea411303139f1150d5 100644
> --- a/include/linux/of_pci.h
> +++ b/include/linux/of_pci.h
> @@ -30,12 +30,16 @@ static inline void of_pci_check_probe_only(void) { }
>
> #if IS_ENABLED(CONFIG_OF_IRQ)
> int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
> +void pci_configure_of_wake_gpio(struct pci_dev *dev);
> +void pci_remove_of_wake_gpio(struct pci_dev *dev);
> #else
> static inline int
> of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
> {
> return 0;
> }
> +static inline void pci_configure_of_wake_gpio(struct pci_dev *dev) { }
> +static inline void pci_remove_of_wake_gpio(struct pci_dev *dev) { }
> #endif
>
> #endif
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 1c270f1d512301de4d462fe7e5097c32af5c6f8d..d1e08df8a8deaa87780589f23242767fdcdba541 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -586,6 +586,8 @@ struct pci_dev {
> /* These methods index pci_reset_fn_methods[] */
> u8 reset_methods[PCI_NUM_RESET_METHODS]; /* In priority order */
>
> + struct gpio_desc *wake; /* Holds WAKE# gpio */
> +
> #ifdef CONFIG_PCIE_TPH
> u16 tph_cap; /* TPH capability offset */
> u8 tph_mode; /* TPH mode */
>
> --
> 2.34.1
>
>
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt
2026-03-13 13:58 ` Manivannan Sadhasivam
@ 2026-03-16 12:16 ` Krishna Chaitanya Chundru
2026-03-17 7:07 ` Manivannan Sadhasivam
0 siblings, 1 reply; 10+ messages in thread
From: Krishna Chaitanya Chundru @ 2026-03-16 12:16 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree
On 3/13/2026 7:28 PM, Manivannan Sadhasivam wrote:
> On Fri, Mar 13, 2026 at 12:38:42PM +0530, Krishna Chaitanya Chundru wrote:
>> According to the PCI Express specification (PCIe r7.0, Section 5.3.3.2),
>> two link wakeup mechanisms are defined: Beacon and WAKE#. Beacon is a
>> hardware-only mechanism and is invisible to software (PCIe r7.0,
>> Section 4.2.7.8.1). This change adds support for the WAKE# mechanism in
>> the PCI core.
>>
>> According to the PCIe specification, multiple WAKE# signals can exist in
>> a system or each component in the hierarchy could share a single WAKE#
>> signal. In configurations involving a PCIe switch, each downstream port
>> (DSP) of the switch may be connected to a separate WAKE# line, allowing
>> each endpoint to signal WAKE# independently. From figure 5.4 in sec
>> 5.3.3.2, WAKE# can also be terminated at the switch itself. To support
>> this, the WAKE# should be described in the device tree node of the
>> endpoint/bridge. If all endpoints share a single WAKE# line, then each
>> endpoint node should describe the same WAKE# signal or a single WAKE# in
>> the Root Port node.
>>
>> In pci_device_add(), PCI framework will search for the WAKE# in device
>> node, If not found, it searches in its upstream port only if upstream port
>> is Root Port. Once found, register for the wake IRQ in shared mode, as the
>> WAKE# may be shared among multiple endpoints.
>>
>> dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with a
>> device and requests it, but the PM core keeps the IRQ disabled by default.
>> The IRQ is enabled only when the device is permitted to wake the system,
>> i.e. during system suspend and after runtime suspend, and only when device
>> wakeup is enabled.
>>
>> When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume() to
>> bring the device back to an active power state, such as transitioning from
>> D3cold to D0. Once the device is active and the link is usable, the
>> endpoint may generate a PME, which is then handled by the PCI core through
>> PME polling or the PCIe PME service driver to complete the wakeup of the
>> endpoint.
>>
>> WAKE# is added in dts schema and merged based on below links.
>>
>> Link: https://lore.kernel.org/all/20250515090517.3506772-1-krishna.chundru@oss.qualcomm.com/
>> Link: https://github.com/devicetree-org/dt-schema/pull/170
>> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> No. Linus never gave this tag for *this* patch.
Linus gave this on v5 [1], might be a overlook.
[1] Re: [PATCH v5 2/2] PCI: Add support for PCIe WAKE# interrupt - Linus
Walleij
<https://lore.kernel.org/all/CACRpkdY9HsnG=xo=swnMcVha+unmvmxR6e6Ynsj09srM_tPmWA@mail.gmail.com/>
- Krishna Chaitanya.
> - Mani
>
>> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
>> ---
>> drivers/pci/of.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
>> drivers/pci/pci.c | 10 +++++++
>> drivers/pci/pci.h | 2 ++
>> drivers/pci/probe.c | 2 ++
>> drivers/pci/remove.c | 1 +
>> include/linux/of_pci.h | 4 +++
>> include/linux/pci.h | 2 ++
>> 7 files changed, 95 insertions(+)
>>
>> diff --git a/drivers/pci/of.c b/drivers/pci/of.c
>> index 9f8eb5df279ed28db7a3b2fd29c65da9975c2efa..b7199d3598b31b62245716c178a5a73565efc89e 100644
>> --- a/drivers/pci/of.c
>> +++ b/drivers/pci/of.c
>> @@ -7,6 +7,7 @@
>> #define pr_fmt(fmt) "PCI: OF: " fmt
>>
>> #include <linux/cleanup.h>
>> +#include <linux/gpio/consumer.h>
>> #include <linux/irqdomain.h>
>> #include <linux/kernel.h>
>> #include <linux/pci.h>
>> @@ -15,6 +16,7 @@
>> #include <linux/of_address.h>
>> #include <linux/of_pci.h>
>> #include <linux/platform_device.h>
>> +#include <linux/pm_wakeirq.h>
>> #include "pci.h"
>>
>> #ifdef CONFIG_PCI
>> @@ -586,6 +588,78 @@ int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
>> return irq_create_of_mapping(&oirq);
>> }
>> EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
>> +
>> +static void pci_configure_wake_irq(struct pci_dev *pdev, struct gpio_desc *wake)
>> +{
>> + int ret, wake_irq;
>> +
>> + wake_irq = gpiod_to_irq(wake);
>> + if (wake_irq < 0) {
>> + pci_err(pdev, "Failed to get wake irq: %d\n", wake_irq);
>> + return;
>> + }
>> +
>> + device_init_wakeup(&pdev->dev, true);
>> +
>> + /*
>> + * dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with the
>> + * device and requests it, but the PM core keeps it disabled by default.
>> + * The IRQ is enabled only when the device is allowed to wake the system
>> + * (during system suspend and after runtime suspend), and only if device
>> + * wakeup is enabled.
>> + *
>> + * When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume()
>> + * to bring the device back to an active power state (e.g. from D3cold to D0).
>> + * Once the device is active and the link is usable, the endpoint may signal
>> + * a PME, which is then handled by the PCI core (either via PME polling or the
>> + * PCIe PME service driver) to wakeup particular endpoint.
>> + */
>> + ret = dev_pm_set_dedicated_shared_wake_irq(&pdev->dev, wake_irq,
>> + IRQ_TYPE_EDGE_FALLING);
>> + if (ret < 0) {
>> + pci_err(pdev, "Failed to set wake IRQ: %d\n", ret);
>> + device_init_wakeup(&pdev->dev, false);
>> + }
>> +}
>> +
>> +void pci_configure_of_wake_gpio(struct pci_dev *dev)
>> +{
>> + struct device_node *dn = pci_device_to_OF_node(dev);
>> + struct pci_dev *upstream;
>> + struct gpio_desc *gpio;
>> +
>> + if (!dn)
>> + return;
>> +
>> + /*
>> + * The devices in a hierarchy expose wakeup capability through the 'wake-gpios'
>> + * property defined either in the device node or in the Slot node. So first check
>> + * for the property in device node and if not available, check in the Slot node.
>> + */
>> + gpio = fwnode_gpiod_get(of_fwnode_handle(dn), "wake",
>> + GPIOD_IN | GPIOD_FLAGS_BIT_NONEXCLUSIVE, NULL);
>> + if (IS_ERR(gpio)) {
>> + upstream = pci_upstream_bridge(dev);
>> + if (upstream && pci_is_root_bus(upstream->bus) && upstream->wake)
>> + pci_configure_wake_irq(dev, upstream->wake);
>> + } else {
>> + dev->wake = gpio;
>> + pci_configure_wake_irq(dev, gpio);
>> + }
>> +}
>> +
>> +void pci_remove_of_wake_gpio(struct pci_dev *dev)
>> +{
>> + struct device_node *dn = pci_device_to_OF_node(dev);
>> +
>> + if (!dn)
>> + return;
>> +
>> + dev_pm_clear_wake_irq(&dev->dev);
>> + device_init_wakeup(&dev->dev, false);
>> + gpiod_put(dev->wake);
>> + dev->wake = NULL;
>> +}
>> #endif /* CONFIG_OF_IRQ */
>>
>> static int pci_parse_request_of_pci_ranges(struct device *dev,
>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> index 8479c2e1f74f1044416281aba11bf071ea89488a..3d858f36ab48a6daec645574ca9027d9d6f071de 100644
>> --- a/drivers/pci/pci.c
>> +++ b/drivers/pci/pci.c
>> @@ -17,6 +17,7 @@
>> #include <linux/lockdep.h>
>> #include <linux/msi.h>
>> #include <linux/of.h>
>> +#include <linux/of_pci.h>
>> #include <linux/pci.h>
>> #include <linux/pm.h>
>> #include <linux/slab.h>
>> @@ -1123,6 +1124,15 @@ static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
>> return acpi_pci_bridge_d3(dev);
>> }
>>
>> +void platform_pci_configure_wake(struct pci_dev *dev)
>> +{
>> + return pci_configure_of_wake_gpio(dev);
>> +}
>> +
>> +void platform_pci_remove_wake(struct pci_dev *dev)
>> +{
>> + return pci_remove_of_wake_gpio(dev);
>> +}
>> /**
>> * pci_update_current_state - Read power state of given device and cache it
>> * @dev: PCI device to handle.
>> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
>> index 13d998fbacce6698514d92500dfea03cc562cdc2..65ca9551e558d2e3331fab0a968620d6b2a2522a 100644
>> --- a/drivers/pci/pci.h
>> +++ b/drivers/pci/pci.h
>> @@ -282,6 +282,8 @@ void pci_msix_init(struct pci_dev *dev);
>> bool pci_bridge_d3_possible(struct pci_dev *dev);
>> void pci_bridge_d3_update(struct pci_dev *dev);
>> int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type);
>> +void platform_pci_configure_wake(struct pci_dev *dev);
>> +void platform_pci_remove_wake(struct pci_dev *dev);
>>
>> static inline bool pci_bus_rrs_vendor_id(u32 l)
>> {
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index bccc7a4bdd794384b7877d453c7989941471c999..372b0d2f4531ea53c0570608306a547101d59e7b 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -2771,6 +2771,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
>> /* Establish pdev->tsm for newly added (e.g. new SR-IOV VFs) */
>> pci_tsm_init(dev);
>>
>> + platform_pci_configure_wake(dev);
>> +
>> pci_npem_create(dev);
>>
>> pci_doe_sysfs_init(dev);
>> diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
>> index e9d519993853f92f1810d3eff9f44ca7e3e1abd9..d781b41e57c4444077075690cec926a9fe15334f 100644
>> --- a/drivers/pci/remove.c
>> +++ b/drivers/pci/remove.c
>> @@ -35,6 +35,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
>> if (pci_dev_test_and_set_removed(dev))
>> return;
>>
>> + platform_pci_remove_wake(dev);
>> pci_doe_sysfs_teardown(dev);
>> pci_npem_remove(dev);
>>
>> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
>> index 29658c0ee71ff10122760214d04ee2bab01709fd..0efd6e9cb4d3d3beaafb42ea411303139f1150d5 100644
>> --- a/include/linux/of_pci.h
>> +++ b/include/linux/of_pci.h
>> @@ -30,12 +30,16 @@ static inline void of_pci_check_probe_only(void) { }
>>
>> #if IS_ENABLED(CONFIG_OF_IRQ)
>> int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
>> +void pci_configure_of_wake_gpio(struct pci_dev *dev);
>> +void pci_remove_of_wake_gpio(struct pci_dev *dev);
>> #else
>> static inline int
>> of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
>> {
>> return 0;
>> }
>> +static inline void pci_configure_of_wake_gpio(struct pci_dev *dev) { }
>> +static inline void pci_remove_of_wake_gpio(struct pci_dev *dev) { }
>> #endif
>>
>> #endif
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index 1c270f1d512301de4d462fe7e5097c32af5c6f8d..d1e08df8a8deaa87780589f23242767fdcdba541 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -586,6 +586,8 @@ struct pci_dev {
>> /* These methods index pci_reset_fn_methods[] */
>> u8 reset_methods[PCI_NUM_RESET_METHODS]; /* In priority order */
>>
>> + struct gpio_desc *wake; /* Holds WAKE# gpio */
>> +
>> #ifdef CONFIG_PCIE_TPH
>> u16 tph_cap; /* TPH capability offset */
>> u8 tph_mode; /* TPH mode */
>>
>> --
>> 2.34.1
>>
>>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt
2026-03-16 12:16 ` Krishna Chaitanya Chundru
@ 2026-03-17 7:07 ` Manivannan Sadhasivam
0 siblings, 0 replies; 10+ messages in thread
From: Manivannan Sadhasivam @ 2026-03-17 7:07 UTC (permalink / raw)
To: Krishna Chaitanya Chundru
Cc: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree
On Mon, Mar 16, 2026 at 05:46:58PM +0530, Krishna Chaitanya Chundru wrote:
>
>
> On 3/13/2026 7:28 PM, Manivannan Sadhasivam wrote:
> > On Fri, Mar 13, 2026 at 12:38:42PM +0530, Krishna Chaitanya Chundru wrote:
> > > According to the PCI Express specification (PCIe r7.0, Section 5.3.3.2),
> > > two link wakeup mechanisms are defined: Beacon and WAKE#. Beacon is a
> > > hardware-only mechanism and is invisible to software (PCIe r7.0,
> > > Section 4.2.7.8.1). This change adds support for the WAKE# mechanism in
> > > the PCI core.
> > >
> > > According to the PCIe specification, multiple WAKE# signals can exist in
> > > a system or each component in the hierarchy could share a single WAKE#
> > > signal. In configurations involving a PCIe switch, each downstream port
> > > (DSP) of the switch may be connected to a separate WAKE# line, allowing
> > > each endpoint to signal WAKE# independently. From figure 5.4 in sec
> > > 5.3.3.2, WAKE# can also be terminated at the switch itself. To support
> > > this, the WAKE# should be described in the device tree node of the
> > > endpoint/bridge. If all endpoints share a single WAKE# line, then each
> > > endpoint node should describe the same WAKE# signal or a single WAKE# in
> > > the Root Port node.
> > >
> > > In pci_device_add(), PCI framework will search for the WAKE# in device
> > > node, If not found, it searches in its upstream port only if upstream port
> > > is Root Port. Once found, register for the wake IRQ in shared mode, as the
> > > WAKE# may be shared among multiple endpoints.
> > >
> > > dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with a
> > > device and requests it, but the PM core keeps the IRQ disabled by default.
> > > The IRQ is enabled only when the device is permitted to wake the system,
> > > i.e. during system suspend and after runtime suspend, and only when device
> > > wakeup is enabled.
> > >
> > > When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume() to
> > > bring the device back to an active power state, such as transitioning from
> > > D3cold to D0. Once the device is active and the link is usable, the
> > > endpoint may generate a PME, which is then handled by the PCI core through
> > > PME polling or the PCIe PME service driver to complete the wakeup of the
> > > endpoint.
> > >
> > > WAKE# is added in dts schema and merged based on below links.
> > >
> > > Link: https://lore.kernel.org/all/20250515090517.3506772-1-krishna.chundru@oss.qualcomm.com/
> > > Link: https://github.com/devicetree-org/dt-schema/pull/170
> > > Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> > No. Linus never gave this tag for *this* patch.
> Linus gave this on v5 [1], might be a overlook.
>
> [1] Re: [PATCH v5 2/2] PCI: Add support for PCIe WAKE# interrupt - Linus
> Walleij <https://lore.kernel.org/all/CACRpkdY9HsnG=xo=swnMcVha+unmvmxR6e6Ynsj09srM_tPmWA@mail.gmail.com/>
>
Oh yes. I didn't check it properly. Please ignore my comment.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt
2026-03-13 7:08 ` [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt Krishna Chaitanya Chundru
2026-03-13 13:58 ` Manivannan Sadhasivam
@ 2026-03-17 7:26 ` Manivannan Sadhasivam
2026-03-24 12:03 ` Krishna Chaitanya Chundru
1 sibling, 1 reply; 10+ messages in thread
From: Manivannan Sadhasivam @ 2026-03-17 7:26 UTC (permalink / raw)
To: Krishna Chaitanya Chundru
Cc: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree
On Fri, Mar 13, 2026 at 12:38:42PM +0530, Krishna Chaitanya Chundru wrote:
> According to the PCI Express specification (PCIe r7.0, Section 5.3.3.2),
> two link wakeup mechanisms are defined: Beacon and WAKE#. Beacon is a
> hardware-only mechanism and is invisible to software (PCIe r7.0,
> Section 4.2.7.8.1). This change adds support for the WAKE# mechanism in
> the PCI core.
>
> According to the PCIe specification, multiple WAKE# signals can exist in
> a system or each component in the hierarchy could share a single WAKE#
> signal. In configurations involving a PCIe switch, each downstream port
> (DSP) of the switch may be connected to a separate WAKE# line, allowing
> each endpoint to signal WAKE# independently. From figure 5.4 in sec
> 5.3.3.2, WAKE# can also be terminated at the switch itself. To support
> this, the WAKE# should be described in the device tree node of the
> endpoint/bridge. If all endpoints share a single WAKE# line, then each
> endpoint node should describe the same WAKE# signal or a single WAKE# in
> the Root Port node.
>
> In pci_device_add(), PCI framework will search for the WAKE# in device
> node, If not found, it searches in its upstream port only if upstream port
> is Root Port. Once found, register for the wake IRQ in shared mode, as the
> WAKE# may be shared among multiple endpoints.
>
> dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with a
> device and requests it, but the PM core keeps the IRQ disabled by default.
> The IRQ is enabled only when the device is permitted to wake the system,
> i.e. during system suspend and after runtime suspend, and only when device
> wakeup is enabled.
>
> When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume() to
> bring the device back to an active power state, such as transitioning from
> D3cold to D0. Once the device is active and the link is usable, the
> endpoint may generate a PME, which is then handled by the PCI core through
> PME polling or the PCIe PME service driver to complete the wakeup of the
> endpoint.
>
> WAKE# is added in dts schema and merged based on below links.
>
> Link: https://lore.kernel.org/all/20250515090517.3506772-1-krishna.chundru@oss.qualcomm.com/
> Link: https://github.com/devicetree-org/dt-schema/pull/170
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
> ---
> drivers/pci/of.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/pci/pci.c | 10 +++++++
> drivers/pci/pci.h | 2 ++
> drivers/pci/probe.c | 2 ++
> drivers/pci/remove.c | 1 +
> include/linux/of_pci.h | 4 +++
> include/linux/pci.h | 2 ++
> 7 files changed, 95 insertions(+)
>
> diff --git a/drivers/pci/of.c b/drivers/pci/of.c
> index 9f8eb5df279ed28db7a3b2fd29c65da9975c2efa..b7199d3598b31b62245716c178a5a73565efc89e 100644
> --- a/drivers/pci/of.c
> +++ b/drivers/pci/of.c
> @@ -7,6 +7,7 @@
> #define pr_fmt(fmt) "PCI: OF: " fmt
>
> #include <linux/cleanup.h>
> +#include <linux/gpio/consumer.h>
> #include <linux/irqdomain.h>
> #include <linux/kernel.h>
> #include <linux/pci.h>
> @@ -15,6 +16,7 @@
> #include <linux/of_address.h>
> #include <linux/of_pci.h>
> #include <linux/platform_device.h>
> +#include <linux/pm_wakeirq.h>
> #include "pci.h"
>
> #ifdef CONFIG_PCI
> @@ -586,6 +588,78 @@ int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
> return irq_create_of_mapping(&oirq);
> }
> EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
> +
> +static void pci_configure_wake_irq(struct pci_dev *pdev, struct gpio_desc *wake)
> +{
> + int ret, wake_irq;
> +
> + wake_irq = gpiod_to_irq(wake);
> + if (wake_irq < 0) {
> + pci_err(pdev, "Failed to get wake irq: %d\n", wake_irq);
> + return;
> + }
> +
> + device_init_wakeup(&pdev->dev, true);
Just set wakeup only if dev_pm_set_dedicated_shared_wake_irq() succeeds.
> +
> + /*
> + * dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with the
> + * device and requests it, but the PM core keeps it disabled by default.
> + * The IRQ is enabled only when the device is allowed to wake the system
> + * (during system suspend and after runtime suspend), and only if device
> + * wakeup is enabled.
> + *
> + * When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume()
> + * to bring the device back to an active power state (e.g. from D3cold to D0).
> + * Once the device is active and the link is usable, the endpoint may signal
> + * a PME, which is then handled by the PCI core (either via PME polling or the
> + * PCIe PME service driver) to wakeup particular endpoint.
> + */
> + ret = dev_pm_set_dedicated_shared_wake_irq(&pdev->dev, wake_irq,
> + IRQ_TYPE_EDGE_FALLING);
Isn't WAKE# a level triggered signal?
> + if (ret < 0) {
> + pci_err(pdev, "Failed to set wake IRQ: %d\n", ret);
s/wake/WAKE#
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt
2026-03-17 7:26 ` Manivannan Sadhasivam
@ 2026-03-24 12:03 ` Krishna Chaitanya Chundru
0 siblings, 0 replies; 10+ messages in thread
From: Krishna Chaitanya Chundru @ 2026-03-24 12:03 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree
On 3/17/2026 12:56 PM, Manivannan Sadhasivam wrote:
> On Fri, Mar 13, 2026 at 12:38:42PM +0530, Krishna Chaitanya Chundru wrote:
>> According to the PCI Express specification (PCIe r7.0, Section 5.3.3.2),
>> two link wakeup mechanisms are defined: Beacon and WAKE#. Beacon is a
>> hardware-only mechanism and is invisible to software (PCIe r7.0,
>> Section 4.2.7.8.1). This change adds support for the WAKE# mechanism in
>> the PCI core.
>>
>> According to the PCIe specification, multiple WAKE# signals can exist in
>> a system or each component in the hierarchy could share a single WAKE#
>> signal. In configurations involving a PCIe switch, each downstream port
>> (DSP) of the switch may be connected to a separate WAKE# line, allowing
>> each endpoint to signal WAKE# independently. From figure 5.4 in sec
>> 5.3.3.2, WAKE# can also be terminated at the switch itself. To support
>> this, the WAKE# should be described in the device tree node of the
>> endpoint/bridge. If all endpoints share a single WAKE# line, then each
>> endpoint node should describe the same WAKE# signal or a single WAKE# in
>> the Root Port node.
>>
>> In pci_device_add(), PCI framework will search for the WAKE# in device
>> node, If not found, it searches in its upstream port only if upstream port
>> is Root Port. Once found, register for the wake IRQ in shared mode, as the
>> WAKE# may be shared among multiple endpoints.
>>
>> dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with a
>> device and requests it, but the PM core keeps the IRQ disabled by default.
>> The IRQ is enabled only when the device is permitted to wake the system,
>> i.e. during system suspend and after runtime suspend, and only when device
>> wakeup is enabled.
>>
>> When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume() to
>> bring the device back to an active power state, such as transitioning from
>> D3cold to D0. Once the device is active and the link is usable, the
>> endpoint may generate a PME, which is then handled by the PCI core through
>> PME polling or the PCIe PME service driver to complete the wakeup of the
>> endpoint.
>>
>> WAKE# is added in dts schema and merged based on below links.
>>
>> Link: https://lore.kernel.org/all/20250515090517.3506772-1-krishna.chundru@oss.qualcomm.com/
>> Link: https://github.com/devicetree-org/dt-schema/pull/170
>> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
>> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
>> ---
>> drivers/pci/of.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
>> drivers/pci/pci.c | 10 +++++++
>> drivers/pci/pci.h | 2 ++
>> drivers/pci/probe.c | 2 ++
>> drivers/pci/remove.c | 1 +
>> include/linux/of_pci.h | 4 +++
>> include/linux/pci.h | 2 ++
>> 7 files changed, 95 insertions(+)
>>
>> diff --git a/drivers/pci/of.c b/drivers/pci/of.c
>> index 9f8eb5df279ed28db7a3b2fd29c65da9975c2efa..b7199d3598b31b62245716c178a5a73565efc89e 100644
>> --- a/drivers/pci/of.c
>> +++ b/drivers/pci/of.c
>> @@ -7,6 +7,7 @@
>> #define pr_fmt(fmt) "PCI: OF: " fmt
>>
>> #include <linux/cleanup.h>
>> +#include <linux/gpio/consumer.h>
>> #include <linux/irqdomain.h>
>> #include <linux/kernel.h>
>> #include <linux/pci.h>
>> @@ -15,6 +16,7 @@
>> #include <linux/of_address.h>
>> #include <linux/of_pci.h>
>> #include <linux/platform_device.h>
>> +#include <linux/pm_wakeirq.h>
>> #include "pci.h"
>>
>> #ifdef CONFIG_PCI
>> @@ -586,6 +588,78 @@ int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
>> return irq_create_of_mapping(&oirq);
>> }
>> EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
>> +
>> +static void pci_configure_wake_irq(struct pci_dev *pdev, struct gpio_desc *wake)
>> +{
>> + int ret, wake_irq;
>> +
>> + wake_irq = gpiod_to_irq(wake);
>> + if (wake_irq < 0) {
>> + pci_err(pdev, "Failed to get wake irq: %d\n", wake_irq);
>> + return;
>> + }
>> +
>> + device_init_wakeup(&pdev->dev, true);
> Just set wakeup only if dev_pm_set_dedicated_shared_wake_irq() succeeds.
ack.
>> +
>> + /*
>> + * dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with the
>> + * device and requests it, but the PM core keeps it disabled by default.
>> + * The IRQ is enabled only when the device is allowed to wake the system
>> + * (during system suspend and after runtime suspend), and only if device
>> + * wakeup is enabled.
>> + *
>> + * When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume()
>> + * to bring the device back to an active power state (e.g. from D3cold to D0).
>> + * Once the device is active and the link is usable, the endpoint may signal
>> + * a PME, which is then handled by the PCI core (either via PME polling or the
>> + * PCIe PME service driver) to wakeup particular endpoint.
>> + */
>> + ret = dev_pm_set_dedicated_shared_wake_irq(&pdev->dev, wake_irq,
>> + IRQ_TYPE_EDGE_FALLING);
> Isn't WAKE# a level triggered signal?
Ack. I will change IRQ_TYPE_EDGE_FALLING to IRQ_TYPE_LEVEL_LOW.
>> + if (ret < 0) {
>> + pci_err(pdev, "Failed to set wake IRQ: %d\n", ret);
> s/wake/WAKE#
ack.
- Krishna Chaitanya.
> - Mani
>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-03-24 12:05 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-13 7:08 [PATCH v8 0/3] PCI: Add support for PCIe WAKE# interrupt Krishna Chaitanya Chundru
2026-03-13 7:08 ` [PATCH v8 1/3] PM: sleep: wakeirq: Add support for dedicated shared wake IRQ setup Krishna Chaitanya Chundru
2026-03-13 7:08 ` [PATCH v8 2/3] gpio: Add fwnode_gpiod_get() helper Krishna Chaitanya Chundru
2026-03-13 13:55 ` Bartosz Golaszewski
2026-03-13 7:08 ` [PATCH v8 3/3] PCI: Add support for PCIe WAKE# interrupt Krishna Chaitanya Chundru
2026-03-13 13:58 ` Manivannan Sadhasivam
2026-03-16 12:16 ` Krishna Chaitanya Chundru
2026-03-17 7:07 ` Manivannan Sadhasivam
2026-03-17 7:26 ` Manivannan Sadhasivam
2026-03-24 12:03 ` Krishna Chaitanya Chundru
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome