[+cc Rob] On Tue, Apr 21, 2020 at 01:16:56PM +0200, Marek Behún wrote: > From: Pali Rohár <pali@xxxxxxxxxx> > > Add support for issuing PERST via GPIO specified in 'reset-gpios' > property (as described in PCI device tree bindings). > > Some buggy cards (e.g. Compex WLE900VX or WLE1216) are not detected > after reboot when PERST is not issued during driver initialization. Does this slot support hotplug? If so, I don't think this fix will help the hot-add case, will it? > Tested on Turris MOX. > > Signed-off-by: Pali Rohár <pali@xxxxxxxxxx> > --- > drivers/pci/controller/pci-aardvark.c | 32 +++++++++++++++++++++++++++ > 1 file changed, 32 insertions(+) > > diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c > index 606bae1e7a88..e2d18094d8ca 100644 > --- a/drivers/pci/controller/pci-aardvark.c > +++ b/drivers/pci/controller/pci-aardvark.c > @@ -9,6 +9,7 @@ > */ > > #include <linux/delay.h> > +#include <linux/gpio.h> > #include <linux/interrupt.h> > #include <linux/irq.h> > #include <linux/irqdomain.h> > @@ -18,6 +19,7 @@ > #include <linux/platform_device.h> > #include <linux/msi.h> > #include <linux/of_address.h> > +#include <linux/of_gpio.h> > #include <linux/of_pci.h> > > #include "../pci.h" > @@ -204,6 +206,7 @@ struct advk_pcie { > int root_bus_nr; > int link_gen; > struct pci_bridge_emul bridge; > + struct gpio_desc *reset_gpio; > }; > > static inline void advk_writel(struct advk_pcie *pcie, u32 val, u64 reg) > @@ -329,10 +332,23 @@ static void advk_pcie_train_link(struct advk_pcie *pcie) > dev_err(dev, "link never came up\n"); > } > > +static void advk_pcie_issue_perst(struct advk_pcie *pcie) > +{ > + if (!pcie->reset_gpio) > + return; > + > + dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 1ms\n"); > + gpiod_set_value_cansleep(pcie->reset_gpio, 1); > + usleep_range(1000, 2000); > + gpiod_set_value_cansleep(pcie->reset_gpio, 0); > +} > + > static void advk_pcie_setup_hw(struct advk_pcie *pcie) > { > u32 reg; > > + advk_pcie_issue_perst(pcie); > + > /* Set to Direct mode */ > reg = advk_readl(pcie, CTRL_CONFIG_REG); > reg &= ~(CTRL_MODE_MASK << CTRL_MODE_SHIFT); > @@ -1045,6 +1061,22 @@ static int advk_pcie_probe(struct platform_device *pdev) > } > pcie->root_bus_nr = bus->start; > > + pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node, > + "reset-gpios", 0, > + GPIOD_OUT_LOW, > + "pcie1-reset"); > + ret = PTR_ERR_OR_ZERO(pcie->reset_gpio); > + if (ret) { > + if (ret == -ENOENT) { > + pcie->reset_gpio = NULL; > + } else { > + if (ret != -EPROBE_DEFER) > + dev_err(dev, "Failed to get reset-gpio: %i\n", > + ret); > + return ret; > + } > + } > + > pcie->link_gen = of_pci_get_max_link_speed(dev->of_node); > if (pcie->link_gen < 1 || pcie->link_gen > 2) > pcie->link_gen = 2; > -- > 2.24.1 >