From 4a3ae8e688872fdc63a2d7af1f3b48b3eba3b975 Mon Sep 17 00:00:00 2001 Message-Id: <4a3ae8e688872fdc63a2d7af1f3b48b3eba3b975.1531317141.git.marcel.ziswiler@toradex.com> In-Reply-To: <6654e1bd342708a683daf47e7558455f709a3e7e.1531317141.git.marcel.ziswiler@toradex.com> References: <6654e1bd342708a683daf47e7558455f709a3e7e.1531317141.git.marcel.ziswiler@toradex.com> From: Marcel Ziswiler Date: Mon, 13 Nov 2017 14:37:25 +0100 Subject: [PATCH 08/33] apalis-tk1: fix pcie reset for reliable gigabit ethernet operation It turns out that the current PCIe reset implementation is not quite working reliably due to some Intel i210 errata. Fix this by making sure the i210's +V3.3_ETH rail is properly disabled during its reset sequence. Also further improve on the bringing up the PCIe switch as found on the Apalis Evaluation board. Signed-off-by: Marcel Ziswiler Acked-by: Dominik Sliwa (downstream commit 7ad9771527d2b1c884beb22d9df28bae899f8d3d) --- drivers/pci/host/pci-tegra.c | 72 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 5c7916b5de73..0c6237159243 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -71,8 +71,12 @@ #ifdef CONFIG_MACH_APALIS_TK1 #define APALIS_GPIO7 TEGRA_GPIO(DD, 1) +#define LAN_DEV_OFF_N TEGRA_GPIO(O, 6) + #define LAN_RESET_N TEGRA_GPIO(S, 2) +#define LAN_WAKE_N TEGRA_GPIO(O, 5) + #define PEX_PERST_N APALIS_GPIO7 #define RESET_MOCI_N TEGRA_GPIO(U, 4) @@ -329,6 +333,11 @@ struct tegra_pcie { struct regulator_bulk_data *supplies; unsigned int num_supplies; +#ifdef CONFIG_MACH_APALIS_TK1 + struct regulator *regulator_apalis_tk1_ldo9; + struct regulator *regulator_apalis_tk1_ldo10; +#endif /* CONFIG_MACH_APALIS_TK1 */ + const struct tegra_pcie_soc *soc; struct dentry *debugfs; }; @@ -592,6 +601,42 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port) gpio_request(LAN_RESET_N, "LAN_RESET_N"); gpio_direction_output(LAN_RESET_N, 0); } + + /* + * Make sure we don't get any back feeding from LAN_WAKE_N resp. + * DEV_OFF_N + */ + gpio_request(LAN_WAKE_N, "LAN_WAKE_N"); + gpio_request(LAN_DEV_OFF_N, "LAN_DEV_OFF_N"); + gpio_direction_output(LAN_WAKE_N, 0); + gpio_direction_output(LAN_DEV_OFF_N, 0); + + /* Make sure LDO9 and LDO10 are initially disabled @ 0V */ + if (regulator_is_enabled(port->pcie->regulator_apalis_tk1_ldo9)) + regulator_disable(port->pcie->regulator_apalis_tk1_ldo9); + if (regulator_is_enabled(port->pcie->regulator_apalis_tk1_ldo10)) + regulator_disable(port->pcie->regulator_apalis_tk1_ldo10); + + mdelay(100); + + /* Make sure LAN_WAKE_N gets re-configured as a GPIO input */ + gpio_direction_input(LAN_WAKE_N); + + /* Make sure controller gets enabled by disabling DEV_OFF_N */ + gpio_set_value(LAN_DEV_OFF_N, 1); + + /* + * Enable LDO9 and LDO10 for +V3.3_ETH on patched prototype + * V1.0A and sample V1.0B and newer modules + */ + if (regulator_enable(port->pcie->regulator_apalis_tk1_ldo9) < 0) { + pr_err("pcie: couldn't enable regulator i210_vdd3p3_ldo9\n"); + return; + } + if (regulator_enable(port->pcie->regulator_apalis_tk1_ldo10) < 0) { + pr_err("pcie: couldn't enable regulator i210_vdd3p3_ldo10\n"); + return; + } #endif /* CONFIG_MACH_APALIS_TK1 */ #endif /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */ @@ -607,6 +652,10 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port) afi_writel(port->pcie, value, ctrl); #if defined(CONFIG_MACH_APALIS_T30) || defined(CONFIG_MACH_APALIS_TK1) +#ifdef CONFIG_MACH_APALIS_TK1 + gpio_set_value(LAN_RESET_N, 1); +#endif /* CONFIG_MACH_APALIS_TK1 */ + /* Must be asserted for 100 ms after power and clocks are stable */ if (g_pex_perst) gpio_set_value(PEX_PERST_N, 1); @@ -1181,6 +1230,29 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) return err; } +#ifdef CONFIG_MACH_APALIS_TK1 + if (pcie->regulator_apalis_tk1_ldo9 == NULL) { + pcie->regulator_apalis_tk1_ldo9 = regulator_get(pcie->dev, "i210_vdd3p3_ldo9"); + if (IS_ERR(pcie->regulator_apalis_tk1_ldo9)) { + pr_err("pcie: couldn't get regulator i210_vdd3p3_ldo9\n"); + pcie->regulator_apalis_tk1_ldo9 = 0; + } + } + + if (pcie->regulator_apalis_tk1_ldo10 == NULL) { + pcie->regulator_apalis_tk1_ldo10 = regulator_get(pcie->dev, "i210_vdd3p3_ldo10"); + if (IS_ERR(pcie->regulator_apalis_tk1_ldo10)) { + pr_err("pcie: couldn't get regulator i210_vdd3p3_ldo10\n"); + pcie->regulator_apalis_tk1_ldo10 = 0; + } + } + + if (pcie->regulator_apalis_tk1_ldo9) + err = regulator_enable(pcie->regulator_apalis_tk1_ldo9); + if (pcie->regulator_apalis_tk1_ldo10) + err = regulator_enable(pcie->regulator_apalis_tk1_ldo10); +#endif /* CONFIG_MACH_APALIS_TK1 */ + reset_control_deassert(pcie->afi_rst); err = clk_prepare_enable(pcie->afi_clk); -- 2.14.4