Files
Krishna Chaitanya Chundru 071e245ab7 PCI: Add support for PCIe WAKE# interrupt
According to PCIe r7.0, sec 5.3.3.2, two link wakeup mechanisms are
defined: Beacon and WAKE#. Beacon is a hardware-only mechanism and is
invisible to software (sec 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 several components in the hierarchy may 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. Such topologies
are typically not described in Device Tree, therefore it is out of scope
for this series.

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 shall 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. Once found, register for the wake IRQ through
dev_pm_set_dedicated_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 by the PM core, 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.

If the same WAKE# GPIO is described in multiple device tree nodes, only the
first device that successfully registers the wake IRQ will succeed, while
subsequent registrations may fail. This limitation does not affect
functional correctness, since WAKE# is only used to bring the link to D0,
and endpoint-specific wakeup handling is resolved later through PME
detection (PME_EN is set in suspend path by PCI core by default).

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/[email protected]/
Link: https://github.com/devicetree-org/dt-schema/pull/170
Signed-off-by: Krishna Chaitanya Chundru <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
Reviewed-by: Linus Walleij <[email protected]>
Reviewed-by: Bartosz Golaszewski <[email protected]>
Acked-by: Manivannan Sadhasivam <[email protected]>
Link: https://patch.msgid.link/[email protected]
2026-08-11 18:54:17 -05:00

48 lines
1.1 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __OF_PCI_H
#define __OF_PCI_H
#include <linux/types.h>
#include <linux/errno.h>
struct pci_dev;
struct device_node;
#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_PCI)
struct device_node *of_pci_find_child_device(struct device_node *parent,
unsigned int devfn);
int of_pci_get_devfn(struct device_node *np);
void of_pci_check_probe_only(void);
#else
static inline struct device_node *of_pci_find_child_device(struct device_node *parent,
unsigned int devfn)
{
return NULL;
}
static inline int of_pci_get_devfn(struct device_node *np)
{
return -EINVAL;
}
static inline void of_pci_check_probe_only(void) { }
#endif
#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