summaryrefslogtreecommitdiff
path: root/recipes-kernel/linux/linux-toradex-mainline-4.14/0008-apalis-tk1-fix-pcie-reset-for-reliable-gigabit-ether.patch
blob: f97269c868dc22a35c02c0b1fd986f20ec4167b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
From f8ab701354544ed62591ea343c881efee973740d Mon Sep 17 00:00:00 2001
Message-Id: <f8ab701354544ed62591ea343c881efee973740d.1529072479.git.marcel.ziswiler@toradex.com>
In-Reply-To: <fb4764e8eb658d35e8fc62ae79c77e1f6e2b0ef3.1529072479.git.marcel.ziswiler@toradex.com>
References: <fb4764e8eb658d35e8fc62ae79c77e1f6e2b0ef3.1529072479.git.marcel.ziswiler@toradex.com>
From: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Date: Mon, 13 Nov 2017 14:37:25 +0100
Subject: [PATCH 08/27] 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 <marcel.ziswiler@toradex.com>
Acked-by: Dominik Sliwa <dominik.sliwa@toradex.com>
(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