summaryrefslogtreecommitdiff
path: root/recipes-kernel/linux/linux-toradex-mainline-4.9/0001-apalis_t30-tk1-fix-pcie-clock-and-reset-not-conformi.patch
blob: c958ff67ac23244acfed80732e026297bf7c8ab8 (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
From a2286569bb02b2ef881302eedbd944f8482beabe Mon Sep 17 00:00:00 2001
From: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Date: Thu, 15 Dec 2016 10:24:58 +0100
Subject: [PATCH 1/4] apalis_t30/tk1: fix pcie clock and reset not conforming
 to specification

Fix PCIe clock and reset not conforming to specification by moving PCIe
reset handling including the PLX PEX 8605 errata 5 workaround from the
board platform data into the right places timing wise in the PCIe driver
itself.

Also add a kernel command line argument to allow using the Apalis GPIO7
as a regular GPIO rather than for above mentioned PLX PEX 8605
workaround:

pex_perst=0

Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Acked-by: Dominik Sliwa <dominik.sliwa@toradex.com>
(cherry picked from toradex_tk1_l4t_r21.5 commit
3e2259b04c2e2c029f742e9dda06a3a2739977d4)
(cherry picked from tegra commit
a2f63805703b43d55d91ae17f10d0049bf0f625e)

---

 drivers/pci/host/pci-tegra.c | 83 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 8dfccf7..1452fe4 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -55,6 +55,34 @@
 #include <asm/mach/map.h>
 #include <asm/mach/pci.h>
 
+//#define CONFIG_MACH_APALIS_T30
+#define CONFIG_MACH_APALIS_TK1
+#if defined(CONFIG_MACH_APALIS_T30) || defined(CONFIG_MACH_APALIS_TK1)
+#include <linux/gpio.h>
+
+#include "../../../arch/arm/boot/dts/include/dt-bindings/gpio/tegra-gpio.h"
+
+#ifdef CONFIG_MACH_APALIS_T30
+#define APALIS_GPIO7	TEGRA_GPIO(S, 7)
+
+#define LAN_RESET_N	-1
+
+#define PEX_PERST_N	APALIS_GPIO7
+
+#define RESET_MOCI_N	TEGRA_GPIO(I, 4)
+#endif
+
+#ifdef CONFIG_MACH_APALIS_TK1
+#define APALIS_GPIO7	TEGRA_GPIO(DD, 1)
+
+#define LAN_RESET_N	TEGRA_GPIO(S, 2)
+
+#define PEX_PERST_N	APALIS_GPIO7
+
+#define RESET_MOCI_N	TEGRA_GPIO(U, 4)
+#endif
+#endif
+
 #define INT_PCI_MSI_NR (8 * 32)
 
 /* register definitions */
@@ -322,6 +350,21 @@ struct tegra_pcie_bus {
 	unsigned int nr;
 };
 
+#if defined(CONFIG_MACH_APALIS_T30) || defined(CONFIG_MACH_APALIS_TK1)
+/* To disable the PCIe switch reset errata workaround */
+int g_pex_perst = 1;
+
+/* To disable the PCIe switch reset errata workaround */
+static int __init disable_pex_perst(char *s)
+{
+	if (!(*s) || !strcmp(s, "0"))
+		g_pex_perst = 0;
+
+	return 0;
+}
+__setup("pex_perst=", disable_pex_perst);
+#endif /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */
+
 static inline struct tegra_pcie *sys_to_pcie(struct pci_sys_data *sys)
 {
 	return sys->private_data;
@@ -528,6 +571,27 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
 	unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port);
 	unsigned long value;
 
+#if defined(CONFIG_MACH_APALIS_T30) || defined(CONFIG_MACH_APALIS_TK1)
+	/*
+	 * 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_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);
+	}
+#endif /* CONFIG_MACH_APALIS_TK1 */
+#endif /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */
+
 	/* pulse reset signal */
 	value = afi_readl(port->pcie, ctrl);
 	value &= ~AFI_PEX_CTRL_RST;
@@ -538,6 +602,25 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
 	value = afi_readl(port->pcie, ctrl);
 	value |= AFI_PEX_CTRL_RST;
 	afi_writel(port->pcie, value, ctrl);
+
+#if defined(CONFIG_MACH_APALIS_T30) || defined(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);
+
+#ifdef CONFIG_MACH_APALIS_TK1
+	/* Release I210 Gigabit Ethernet Controller Reset */
+	if (LAN_RESET_N)
+		gpio_set_value(LAN_RESET_N, 1);
+#endif /* CONFIG_MACH_APALIS_TK1 */
+#endif /* CONFIG_MACH_APALIS_T30 || CONFIG_MACH_APALIS_TK1 */
 }
 
 static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
-- 
2.9.3