[PATCH] PCI: qcom: Skip PERST# GPIOs provided by downstream PCIe devices

From: Manivannan Sadhasivam via B4 Relay

Date: Tue Jun 16 2026 - 12:27:55 EST


From: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxxxxxxxx>

Currently, the pcie-qcom driver recursively parses the PERST# GPIO from all
child nodes defined in DT and acquires them. But this creates issues with
PERST# GPIO provided by one of the child devices like the PCIe switch port.
In this case, the RC driver cannot acquire the PERST# GPIO since it will be
provided by the child PCIe device which was not yet enumerated during RC
driver probe.

Fix this by checking if the GPIO provider is a child of the RC's DT node
(i.e., sits behind this PCIe controller). If so, skip it, as PERST#
should be controlled by the respective PCIe client driver implementation.
GPIOs provided by external GPIO controllers (e.g., TLMM in Qcom SoCs)
continue to be handled normally.

Fixes: 2fd60a2edb83 ("PCI: qcom: Parse PERST# from all PCIe bridge nodes")
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxxxxxxxx>
---
drivers/pci/controller/dwc/pcie-qcom.c | 36 ++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index af6bf5cce65b..f90ff68cdaf2 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -1693,6 +1693,22 @@ static const struct pci_ecam_ops pci_qcom_ecam_ops = {
}
};

+static bool qcom_pcie_is_child_node(struct device *dev,
+ struct device_node *node)
+{
+ struct device_node *parent;
+
+ for (parent = of_get_parent(node); parent;
+ parent = of_get_next_parent(parent)) {
+ if (parent == dev->of_node) {
+ of_node_put(parent);
+ return true;
+ }
+ }
+
+ return false;
+}
+
/* Parse PERST# from all nodes in depth first manner starting from @np */
static int qcom_pcie_parse_perst(struct qcom_pcie *pcie,
struct qcom_pcie_port *port,
@@ -1700,12 +1716,32 @@ static int qcom_pcie_parse_perst(struct qcom_pcie *pcie,
{
struct device *dev = pcie->pci->dev;
struct qcom_pcie_perst *perst;
+ struct device_node *gpio_np;
struct gpio_desc *reset;
int ret;

if (!of_find_property(np, "reset-gpios", NULL))
goto parse_child_node;

+ /*
+ * Skip GPIOs provided by a PCIe device which is a child of the Root
+ * Complex (e.g., a PCIe switch with GPIO controller capability). Such
+ * controllers won't be available at RC probe time and their PERST#
+ * should be controlled by the respective PCI client driver
+ * implementation.
+ */
+ gpio_np = of_parse_phandle(np, "reset-gpios", 0);
+ if (!gpio_np) {
+ dev_err(dev, "Failed to parse GPIO provider\n");
+ return -EINVAL;
+ }
+
+ if (qcom_pcie_is_child_node(dev, gpio_np)) {
+ of_node_put(gpio_np);
+ goto parse_child_node;
+ }
+ of_node_put(gpio_np);
+
reset = devm_fwnode_gpiod_get(dev, of_fwnode_handle(np), "reset",
GPIOD_OUT_HIGH, "PERST#");
if (IS_ERR(reset)) {

---
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
change-id: 20260616-pci-qcom-perst-fix-00417aa57a96

Best regards,
--
Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxxxxxxxx>