If reset-gpio is defined by device-tree use that instead of a
board-specific function to toggle PCI reset.

The presense of 'reset-gpio' in the device-tree will override calling
the weak imx6_pcie_toggle_reset function therefore I've Cc'd all the
board maintainers who rely on that function here as I would like to
remove that function completely. The only user of a board-specific weak
imx6_pcie_toggle_reset is gwventana which I am the maintainer for and
once this patch is accepted I will be able to remove that use case and
would then like to remove the use of CONFIG_PCIE_IMX_PERST_GPIO
completely.

I would have preferred implementing this without changing the codepath
for the users of CONFIG_PCIE_IMX_PERST_GPIO but that would require
passing in the imx_pcie_priv struct to imx6_pcie_toggle_reset which
creates a chicken-and-egg scenario as that's currently a weak function
for boards to override.

Cc: Ian Ray <ian....@ge.com> (maintainer:GE BX50V3 BOARD)
Cc: Sebastian Reichel <sebastian.reic...@collabora.com> (maintainer:GE BX50V3 
BOARD)
Cc: Fabio Estevam <feste...@gmail.com> (maintainer:MX6SABRESD BOARD)
Cc: Marek Vasut <ma...@denx.de> (maintainer:NOVENA BOARD)
Cc: Soeren Moch <sm...@web.de> (maintainer:TBS2910 BOARD)
Cc: Silvio Fricke <open-sou...@softing.de> (maintainer:VINING_2000 BOARD)
Signed-off-by: Tim Harvey <thar...@gateworks.com>
---
 drivers/pci/pcie_imx.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c
index 73875e00db..c28951655d 100644
--- a/drivers/pci/pcie_imx.c
+++ b/drivers/pci/pcie_imx.c
@@ -100,6 +100,8 @@
 struct imx_pcie_priv {
        void __iomem            *dbi_base;
        void __iomem            *cfg_base;
+       struct gpio_desc        reset_gpio;
+       bool                    gpio_active_high;
 };
 
 /*
@@ -584,7 +586,7 @@ __weak int imx6_pcie_toggle_reset(void)
        return 0;
 }
 
-static int imx6_pcie_deassert_core_reset(void)
+static int imx6_pcie_deassert_core_reset(struct imx_pcie_priv *priv)
 {
        struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
 
@@ -612,7 +614,14 @@ static int imx6_pcie_deassert_core_reset(void)
        setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN);
 #endif
 
-       imx6_pcie_toggle_reset();
+       if (dm_gpio_is_valid(&priv->reset_gpio)) {
+               /* Assert PERST# for 50ms then de-assert */
+               dm_gpio_set_value(&priv->reset_gpio, priv->gpio_active_high ? 0 
: 1);
+               mdelay(50);
+               dm_gpio_set_value(&priv->reset_gpio, priv->gpio_active_high ? 1 
: 0);
+       } else {
+               imx6_pcie_toggle_reset();
+       }
 
        return 0;
 }
@@ -625,7 +634,7 @@ static int imx_pcie_link_up(struct imx_pcie_priv *priv)
 
        imx6_pcie_assert_core_reset(priv, false);
        imx6_pcie_init_phy();
-       imx6_pcie_deassert_core_reset();
+       imx6_pcie_deassert_core_reset(priv);
 
        imx_pcie_regions_setup(priv);
 
@@ -787,6 +796,15 @@ static int imx_pcie_dm_probe(struct udevice *dev)
 {
        struct imx_pcie_priv *priv = dev_get_priv(dev);
 
+       /* if PERST# valid from dt then assert it */
+       gpio_request_by_name(dev, "reset-gpio", 0, &priv->reset_gpio,
+                            GPIOD_IS_OUT);
+       priv->gpio_active_high = dev_read_bool(dev, "reset-gpio-active-high");
+       if (dm_gpio_is_valid(&priv->reset_gpio)) {
+               dm_gpio_set_value(&priv->reset_gpio,
+                                 priv->gpio_active_high ? 0 : 1);
+       }
+
        return imx_pcie_link_up(priv);
 }
 
-- 
2.17.1

Reply via email to