Commit dbdcc22c authored by Manikanta Maddireddy's avatar Manikanta Maddireddy Committed by Lorenzo Pieralisi

PCI: tegra: Add support for GPIO based PERST#

Tegra PCIe has fixed per port SFIO line to signal PERST#, which can be
controlled by AFI port register. However, if a platform routes a
different GPIO to the PCIe slot, then port register cannot control it.
Add support for GPIO based PERST# signal for such platforms. GPIO number
comes from per port PCIe device tree node. PCIe driver probe doesn't
fail if per port "reset-gpios" property is not populated, so platforms
that require this workaround must make sure that the DT property is not
missed in the corresponding device tree.

Link: https://lore.kernel.org/linux-pci/20190705084850.30777-1-jonathanh@nvidia.com/Signed-off-by: default avatarManikanta Maddireddy <mmaddireddy@nvidia.com>
[lorenzo.pieralisi@arm.com: squashed in fix in Link]
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: default avatarThierry Reding <treding@nvidia.com>
parent 0fc8b82f
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/irq.h> #include <linux/irq.h>
...@@ -399,6 +400,8 @@ struct tegra_pcie_port { ...@@ -399,6 +400,8 @@ struct tegra_pcie_port {
unsigned int lanes; unsigned int lanes;
struct phy **phys; struct phy **phys;
struct gpio_desc *reset_gpio;
}; };
struct tegra_pcie_bus { struct tegra_pcie_bus {
...@@ -544,15 +547,23 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port) ...@@ -544,15 +547,23 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
unsigned long value; unsigned long value;
/* pulse reset signal */ /* pulse reset signal */
value = afi_readl(port->pcie, ctrl); if (port->reset_gpio) {
value &= ~AFI_PEX_CTRL_RST; gpiod_set_value(port->reset_gpio, 1);
afi_writel(port->pcie, value, ctrl); } else {
value = afi_readl(port->pcie, ctrl);
value &= ~AFI_PEX_CTRL_RST;
afi_writel(port->pcie, value, ctrl);
}
usleep_range(1000, 2000); usleep_range(1000, 2000);
value = afi_readl(port->pcie, ctrl); if (port->reset_gpio) {
value |= AFI_PEX_CTRL_RST; gpiod_set_value(port->reset_gpio, 0);
afi_writel(port->pcie, value, ctrl); } else {
value = afi_readl(port->pcie, ctrl);
value |= AFI_PEX_CTRL_RST;
afi_writel(port->pcie, value, ctrl);
}
} }
static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port) static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
...@@ -2218,6 +2229,7 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) ...@@ -2218,6 +2229,7 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
struct tegra_pcie_port *rp; struct tegra_pcie_port *rp;
unsigned int index; unsigned int index;
u32 value; u32 value;
char *label;
err = of_pci_get_devfn(port); err = of_pci_get_devfn(port);
if (err < 0) { if (err < 0) {
...@@ -2276,6 +2288,31 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) ...@@ -2276,6 +2288,31 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
if (IS_ERR(rp->base)) if (IS_ERR(rp->base))
return PTR_ERR(rp->base); return PTR_ERR(rp->base);
label = devm_kasprintf(dev, GFP_KERNEL, "pex-reset-%u", index);
if (!label) {
dev_err(dev, "failed to create reset GPIO label\n");
return -ENOMEM;
}
/*
* Returns -ENOENT if reset-gpios property is not populated
* and in this case fall back to using AFI per port register
* to toggle PERST# SFIO line.
*/
rp->reset_gpio = devm_gpiod_get_from_of_node(dev, port,
"reset-gpios", 0,
GPIOD_OUT_LOW,
label);
if (IS_ERR(rp->reset_gpio)) {
if (PTR_ERR(rp->reset_gpio) == -ENOENT) {
rp->reset_gpio = NULL;
} else {
dev_err(dev, "failed to get reset GPIO: %d\n",
err);
return PTR_ERR(rp->reset_gpio);
}
}
list_add_tail(&rp->list, &pcie->ports); list_add_tail(&rp->list, &pcie->ports);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment