The 'reset-gpios' property specified in the device-tree corresponds to the PCI PERST# signal that is used to reset a PCI Endpoint. Since the on-board circuitry may not reset the PCI Endpoint, fetch the 'reset-gpios' device-tree property and toggle the GPIO line corresponding to the PERST# signal to enable the PCI Endpoint. In the absence of the 'reset-gpios' property in the device-tree, existing behavior is retained rather than returning an error.
Signed-off-by: Siddharth Vadapalli <[email protected]> --- drivers/pci/pcie_dw_ti.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/pci/pcie_dw_ti.c b/drivers/pci/pcie_dw_ti.c index fb39132f7c1..a34b142bbfb 100644 --- a/drivers/pci/pcie_dw_ti.c +++ b/drivers/pci/pcie_dw_ti.c @@ -58,6 +58,7 @@ struct pcie_dw_ti { /* Must be first member of the struct */ struct pcie_dw dw; void *app_base; + struct gpio_desc rst_gpio; u32 num_lanes; }; @@ -252,6 +253,17 @@ static int pcie_dw_ti_probe(struct udevice *dev) return ret; } + ret = gpio_request_by_name(dev, "reset-gpios", 0, &pci->rst_gpio, + GPIOD_IS_OUT); + if (ret && ret != -ENOENT) { + dev_err(dev, "failed to get reset-gpios\n"); + return ret; + } + + /* Keep the reset-line asserted until the PCI Controller is ready */ + if (dm_gpio_is_valid(&pci->rst_gpio)) + dm_gpio_set_value(&pci->rst_gpio, 1); + ret = generic_phy_get_by_name(dev, "pcie-phy0", &phy0); if (ret) { dev_err(dev, "Unable to get phy0"); @@ -281,6 +293,15 @@ static int pcie_dw_ti_probe(struct udevice *dev) dw_pcie_link_set_max_link_width(&pci->dw, pci->num_lanes); + /* + * The reset-gpio (PERST#) should be held deasserted for at-least 100 ms + * before the link is brought up. + */ + if (dm_gpio_is_valid(&pci->rst_gpio)) { + dm_gpio_set_value(&pci->rst_gpio, 0); + mdelay(100); + } + if (!pcie_dw_ti_pcie_link_up(pci, LINK_SPEED_GEN_2)) { printf("PCIE-%d: Link down\n", dev_seq(dev)); return -ENODEV; -- 2.51.1
