Skip to content

Commit 1d0156c

Browse files
samushamMani-Sadhasivam
authored andcommitted
PCI: amd-mdb: Add support for PCIe RP PERST# signal handling
Add support for handling the AMD Versal Gen 2 MDB PCIe Root Port PERST# signal via a GPIO by parsing the new PCIe bridge node to acquire the reset GPIO. If the bridge node is not found, fall back to acquiring it from the PCIe host bridge node. As part of this, update the interrupt controller node parsing to use of_get_child_by_name() instead of of_get_next_child(), since the PCIe host bridge node now has multiple children. This ensures the correct node is selected during initialization. Signed-off-by: Sai Krishna Musham <[email protected]> Signed-off-by: Manivannan Sadhasivam <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 0b9275e commit 1d0156c

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

drivers/pci/controller/dwc/pcie-amd-mdb.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/resource.h>
1919
#include <linux/types.h>
2020

21+
#include "../../pci.h"
2122
#include "pcie-designware.h"
2223

2324
#define AMD_MDB_TLP_IR_STATUS_MISC 0x4C0
@@ -56,13 +57,15 @@
5657
* @slcr: MDB System Level Control and Status Register (SLCR) base
5758
* @intx_domain: INTx IRQ domain pointer
5859
* @mdb_domain: MDB IRQ domain pointer
60+
* @perst_gpio: GPIO descriptor for PERST# signal handling
5961
* @intx_irq: INTx IRQ interrupt number
6062
*/
6163
struct amd_mdb_pcie {
6264
struct dw_pcie pci;
6365
void __iomem *slcr;
6466
struct irq_domain *intx_domain;
6567
struct irq_domain *mdb_domain;
68+
struct gpio_desc *perst_gpio;
6669
int intx_irq;
6770
};
6871

@@ -284,7 +287,7 @@ static int amd_mdb_pcie_init_irq_domains(struct amd_mdb_pcie *pcie,
284287
struct device_node *pcie_intc_node;
285288
int err;
286289

287-
pcie_intc_node = of_get_next_child(node, NULL);
290+
pcie_intc_node = of_get_child_by_name(node, "interrupt-controller");
288291
if (!pcie_intc_node) {
289292
dev_err(dev, "No PCIe Intc node found\n");
290293
return -ENODEV;
@@ -402,6 +405,28 @@ static int amd_mdb_setup_irq(struct amd_mdb_pcie *pcie,
402405
return 0;
403406
}
404407

408+
static int amd_mdb_parse_pcie_port(struct amd_mdb_pcie *pcie)
409+
{
410+
struct device *dev = pcie->pci.dev;
411+
struct device_node *pcie_port_node __maybe_unused;
412+
413+
/*
414+
* This platform currently supports only one Root Port, so the loop
415+
* will execute only once.
416+
* TODO: Enhance the driver to handle multiple Root Ports in the future.
417+
*/
418+
for_each_child_of_node_with_prefix(dev->of_node, pcie_port_node, "pcie") {
419+
pcie->perst_gpio = devm_fwnode_gpiod_get(dev, of_fwnode_handle(pcie_port_node),
420+
"reset", GPIOD_OUT_HIGH, NULL);
421+
if (IS_ERR(pcie->perst_gpio))
422+
return dev_err_probe(dev, PTR_ERR(pcie->perst_gpio),
423+
"Failed to request reset GPIO\n");
424+
return 0;
425+
}
426+
427+
return -ENODEV;
428+
}
429+
405430
static int amd_mdb_add_pcie_port(struct amd_mdb_pcie *pcie,
406431
struct platform_device *pdev)
407432
{
@@ -426,6 +451,12 @@ static int amd_mdb_add_pcie_port(struct amd_mdb_pcie *pcie,
426451

427452
pp->ops = &amd_mdb_pcie_host_ops;
428453

454+
if (pcie->perst_gpio) {
455+
mdelay(PCIE_T_PVPERL_MS);
456+
gpiod_set_value_cansleep(pcie->perst_gpio, 0);
457+
mdelay(PCIE_RESET_CONFIG_WAIT_MS);
458+
}
459+
429460
err = dw_pcie_host_init(pp);
430461
if (err) {
431462
dev_err(dev, "Failed to initialize host, err=%d\n", err);
@@ -444,6 +475,7 @@ static int amd_mdb_pcie_probe(struct platform_device *pdev)
444475
struct device *dev = &pdev->dev;
445476
struct amd_mdb_pcie *pcie;
446477
struct dw_pcie *pci;
478+
int ret;
447479

448480
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
449481
if (!pcie)
@@ -454,6 +486,24 @@ static int amd_mdb_pcie_probe(struct platform_device *pdev)
454486

455487
platform_set_drvdata(pdev, pcie);
456488

489+
ret = amd_mdb_parse_pcie_port(pcie);
490+
/*
491+
* If amd_mdb_parse_pcie_port returns -ENODEV, it indicates that the
492+
* PCIe Bridge node was not found in the device tree. This is not
493+
* considered a fatal error and will trigger a fallback where the
494+
* reset GPIO is acquired directly from the PCIe Host Bridge node.
495+
*/
496+
if (ret) {
497+
if (ret != -ENODEV)
498+
return ret;
499+
500+
pcie->perst_gpio = devm_gpiod_get_optional(dev, "reset",
501+
GPIOD_OUT_HIGH);
502+
if (IS_ERR(pcie->perst_gpio))
503+
return dev_err_probe(dev, PTR_ERR(pcie->perst_gpio),
504+
"Failed to request reset GPIO\n");
505+
}
506+
457507
return amd_mdb_add_pcie_port(pcie, pdev);
458508
}
459509

0 commit comments

Comments
 (0)