summaryrefslogtreecommitdiff
path: root/recipes-kernel/linux/linux-toradex-mainline-4.14/0032-apalis-tk1-fix-pcie-reset-for-reliable-gigabit-ether.patch
blob: e0f2483bb3a5a1dd11cc62c8ccca3f7bf350b7eb (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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
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 <marcel.ziswiler@toradex.com>
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 <marcel.ziswiler@toradex.com>
---
 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 = <&reg_5v0>;
 	};
 };
-
-&gpio {
-	/* Apalis GPIO7 MXM3 pin 15 PLX PEX 8605 PCIe Switch Reset */
-	pex_perst_n {
-		gpio-hog;
-		gpios = <TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>;
-		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 = <TEGRA_GPIO(S, 2) GPIO_ACTIVE_HIGH>;
-		output-high;
-		line-name = "LAN_RESET_N";
-	};
-
-	/* Control MXM3 pin 26 Reset Module Output Carrier Input */
-	reset_moci_ctrl {
-		gpio-hog;
-		gpios = <TEGRA_GPIO(U, 4) GPIO_ACTIVE_HIGH>;
-		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