From 7e4a3d7ee5cf304ce0c5a5be6e1dcb7cafc34a1b Mon Sep 17 00:00:00 2001 Message-Id: <7e4a3d7ee5cf304ce0c5a5be6e1dcb7cafc34a1b.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: Wed, 11 Jul 2018 15:44:16 +0200 Subject: [PATCH 32/33] apalis-tk1: fix pcie reset for reliable gigabit ethernet operation It turns out that the forward port of the current PCIe reset implementation was not quite working reliably due to differences in regulator naming. Another shortcoming was that it currently resets multiple times due to not differentiating which PCIe port needs resetting. Improve this by doing specific reset per port only. Signed-off-by: Marcel Ziswiler --- arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts | 10 -- arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi | 20 --- arch/arm/boot/dts/tegra124-apalis.dtsi | 2 - drivers/pci/host/pci-tegra.c | 171 ++++++++++++++---------- 4 files changed, 103 insertions(+), 100 deletions(-) diff --git a/arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts b/arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts index 046a415d5db8..4f2e4766379d 100644 --- a/arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts +++ b/arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts @@ -250,13 +250,3 @@ vin-supply = <®_5v0>; }; }; - -&gpio { - /* Apalis GPIO7 MXM3 pin 15 PLX PEX 8605 PCIe Switch Reset */ - pex_perst_n { - gpio-hog; - gpios = ; - output-high; - line-name = "PEX_PERST_N"; - }; -}; diff --git a/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi b/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi index 08e4b08e26f8..1336e8caf95d 100644 --- a/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi +++ b/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi @@ -1721,14 +1721,12 @@ regulator-name = "+V3.3_ETH(ldo9)"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - regulator-always-on; }; ldo10 { regulator-name = "+V3.3_ETH(ldo10)"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - regulator-always-on; }; ldo11 { @@ -2065,21 +2063,3 @@ }; }; }; - -&gpio { - /* I210 Gigabit Ethernet Controller Reset */ - lan_reset_n { - gpio-hog; - gpios = ; - output-high; - line-name = "LAN_RESET_N"; - }; - - /* Control MXM3 pin 26 Reset Module Output Carrier Input */ - reset_moci_ctrl { - gpio-hog; - gpios = ; - output-high; - line-name = "RESET_MOCI_CTRL"; - }; -}; diff --git a/arch/arm/boot/dts/tegra124-apalis.dtsi b/arch/arm/boot/dts/tegra124-apalis.dtsi index a19844e61adc..00920c26f60a 100644 --- a/arch/arm/boot/dts/tegra124-apalis.dtsi +++ b/arch/arm/boot/dts/tegra124-apalis.dtsi @@ -1756,14 +1756,12 @@ regulator-name = "+V3.3_ETH(ldo9)"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - regulator-always-on; }; ldo10 { regulator-name = "+V3.3_ETH(ldo10)"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - regulator-always-on; }; ldo11 { diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 0c6237159243..0e19ff52275e 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -333,6 +333,9 @@ struct tegra_pcie { struct regulator_bulk_data *supplies; unsigned int num_supplies; +#ifdef CONFIG_MACH_APALIS_T30 + int pci_reset_status; +#endif #ifdef CONFIG_MACH_APALIS_TK1 struct regulator *regulator_apalis_tk1_ldo9; struct regulator *regulator_apalis_tk1_ldo10; @@ -584,58 +587,82 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port) unsigned long value; #if defined(CONFIG_MACH_APALIS_T30) || defined(CONFIG_MACH_APALIS_TK1) +#ifdef CONFIG_MACH_APALIS_T30 /* - * Reset PLX PEX 8605 PCIe Switch plus PCIe devices on Apalis Evaluation - * Board + * Apalis PCIe aka port 1 and Apalis Type Specific 4 Lane PCIe aka port + * 0 share the same RESET_MOCI therefore only assert it once for both + * ports to avoid loosing the previously brought up port again. */ - if (g_pex_perst) - gpio_request(PEX_PERST_N, "PEX_PERST_N"); - gpio_request(RESET_MOCI_N, "RESET_MOCI_N"); - if (g_pex_perst) - gpio_direction_output(PEX_PERST_N, 0); - gpio_direction_output(RESET_MOCI_N, 0); - + if ((port->index == 1) || (port->index == 0)) { + /* only do it once per init cycle */ + if (port->pcie->pci_reset_status % 2 == 0) { +#endif #ifdef CONFIG_MACH_APALIS_TK1 - /* Reset I210 Gigabit Ethernet Controller */ - if (LAN_RESET_N) { - gpio_request(LAN_RESET_N, "LAN_RESET_N"); - gpio_direction_output(LAN_RESET_N, 0); + if (port->index == 0) { /* Apalis PCIe */ +#endif + /* + * Reset PLX PEX 8605 PCIe Switch plus PCIe devices on Apalis Evaluation + * Board + */ + if (g_pex_perst) + gpio_request(PEX_PERST_N, "PEX_PERST_N"); + gpio_request(RESET_MOCI_N, "RESET_MOCI_N"); + if (g_pex_perst) + gpio_direction_output(PEX_PERST_N, 0); + gpio_direction_output(RESET_MOCI_N, 0); +#ifdef CONFIG_MACH_APALIS_T30 + } +#endif } +#ifdef CONFIG_MACH_APALIS_TK1 + if (port->index == 1) { /* I210 Gigabit Ethernet Controller (On-module) */ + /* Reset I210 Gigabit Ethernet Controller */ + if (LAN_RESET_N >= 0) { + 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); + /* + * 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)) { + value = regulator_enable(port->pcie->regulator_apalis_tk1_ldo9); + if (regulator_disable(port->pcie->regulator_apalis_tk1_ldo9) < 0) + pr_err("failed disabling +V3.3_ETH(ldo9)\n"); + } + if (regulator_is_enabled(port->pcie->regulator_apalis_tk1_ldo10)) { + value = regulator_enable(port->pcie->regulator_apalis_tk1_ldo10); + if (regulator_disable(port->pcie->regulator_apalis_tk1_ldo10) <0) + pr_err("failed disabling +V3.3_ETH(ldo10)\n"); + } - mdelay(100); + mdelay(100); - /* Make sure LAN_WAKE_N gets re-configured as a GPIO input */ - gpio_direction_input(LAN_WAKE_N); + /* 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); + /* 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; + /* + * 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 +V3.3_ETH(ldo9)\n"); + return; + } + if (regulator_enable(port->pcie->regulator_apalis_tk1_ldo10) < 0) { + pr_err("pcie: couldn't enable regulator +V3.3_ETH(ldo10)\n"); + return; + } } #endif /* CONFIG_MACH_APALIS_TK1 */ #endif /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */ @@ -652,25 +679,38 @@ 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_T30 + if ((port->index == 1) || (port->index == 0)) { + /* only do it once per init cycle */ + if (port->pcie->pci_reset_status % 2 == 0) { +#endif #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); - /* - * Err_5: PEX_REFCLK_OUTpx/nx Clock Outputs is not Guaranteed Until - * 900 us After PEX_PERST# De-assertion - */ - if (g_pex_perst) - mdelay(1); - gpio_set_value(RESET_MOCI_N, 1); + if (port->index == 0) { /* Apalis PCIe */ +#endif + /* Must be asserted for 100 ms after power and clocks are stable */ + if (g_pex_perst) + gpio_set_value(PEX_PERST_N, 1); + /* + * Err_5: PEX_REFCLK_OUTpx/nx Clock Outputs is not Guaranteed Until + * 900 us After PEX_PERST# De-assertion + */ + if (g_pex_perst) + mdelay(1); + gpio_set_value(RESET_MOCI_N, 1); +#ifdef CONFIG_MACH_APALIS_T30 + } + port->pcie->pci_reset_status++; +#endif + } #ifdef CONFIG_MACH_APALIS_TK1 - /* Release I210 Gigabit Ethernet Controller Reset */ - if (LAN_RESET_N) - gpio_set_value(LAN_RESET_N, 1); + mdelay(5); + + if (port->index == 1) { /* I210 Gigabit Ethernet Controller (On-module) */ + /* Release I210 Gigabit Ethernet Controller Reset */ + if (LAN_RESET_N >= 0) + gpio_set_value(LAN_RESET_N, 1); + } #endif /* CONFIG_MACH_APALIS_TK1 */ #endif /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */ } @@ -1232,25 +1272,20 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) #ifdef CONFIG_MACH_APALIS_TK1 if (pcie->regulator_apalis_tk1_ldo9 == NULL) { - pcie->regulator_apalis_tk1_ldo9 = regulator_get(pcie->dev, "i210_vdd3p3_ldo9"); + pcie->regulator_apalis_tk1_ldo9 = regulator_get(pcie->dev, "+V3.3_ETH(ldo9)"); if (IS_ERR(pcie->regulator_apalis_tk1_ldo9)) { - pr_err("pcie: couldn't get regulator i210_vdd3p3_ldo9\n"); + pr_err("pcie: couldn't get regulator +V3.3_ETH(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"); + pcie->regulator_apalis_tk1_ldo10 = regulator_get(pcie->dev, "+V3.3_ETH(ldo10)"); if (IS_ERR(pcie->regulator_apalis_tk1_ldo10)) { - pr_err("pcie: couldn't get regulator i210_vdd3p3_ldo10\n"); + pr_err("pcie: couldn't get regulator +V3.3_ETH(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); -- 2.14.4