diff options
Diffstat (limited to 'drivers/pci/host/k2-platform.c')
-rw-r--r-- | drivers/pci/host/k2-platform.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/drivers/pci/host/k2-platform.c b/drivers/pci/host/k2-platform.c new file mode 100644 index 00000000000..6525c6f3c31 --- /dev/null +++ b/drivers/pci/host/k2-platform.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Texas Instruments, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #include <asm/setup.h> | ||
17 | |||
18 | #include <linux/delay.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_address.h> | ||
23 | |||
24 | #include "pci-pdata.h" | ||
25 | |||
26 | #define reg_dump(addr, mask) \ | ||
27 | pr_debug("reg %p has value %x\n", (void *)addr, \ | ||
28 | (__raw_readl(addr) & ~mask)) | ||
29 | |||
30 | #define PCIE0_RC_MODE (BIT(2)) | ||
31 | #define PCIE0_MODE_MASK (BIT(1) | BIT(2)) | ||
32 | #define PCIE1_RC_MODE (BIT(4)) | ||
33 | #define PCIE1_MODE_MASK (BIT(3) | BIT(4)) | ||
34 | |||
35 | /* mask bits point to bits being modified */ | ||
36 | #define reg_rmw(addr, value, mask) \ | ||
37 | __raw_writel(((__raw_readl(addr) & (~(mask))) | \ | ||
38 | (value & (mask))), (addr)) | ||
39 | |||
40 | /* bit mask from bit-a to bit-b inclusive */ | ||
41 | #define MASK(msb, lsb) \ | ||
42 | ((((msb) - (lsb)) == 31) ? 0xffffffff : \ | ||
43 | ((((u32)1 << ((msb) - (lsb) + 1)) - 1) << (lsb))) | ||
44 | |||
45 | #define FINSR(base, offset, msb, lsb, val) \ | ||
46 | reg_rmw((base) + (offset), ((val) << (lsb)), MASK((msb), (lsb))) | ||
47 | |||
48 | struct serdes_config { | ||
49 | u32 ofs; | ||
50 | u32 msb; | ||
51 | u32 lsb; | ||
52 | u32 val; | ||
53 | }; | ||
54 | |||
55 | static struct serdes_config k2_100mhz_pcie_5gbps_serdes[] = { | ||
56 | {0x0000, 15, 8, 0x08}, | ||
57 | {0x0060, 7, 0, 0x5c}, | ||
58 | {0x0060, 15, 8, 0x1c}, | ||
59 | {0x0060, 23, 16, 0x04}, | ||
60 | {0x0064, 15, 8, 0xc7}, | ||
61 | {0x0064, 23, 16, 0x43}, | ||
62 | {0x0064, 31, 24, 0x03}, | ||
63 | {0x006c, 7, 0, 0x12}, | ||
64 | {0x0068, 23, 16, 0x07}, | ||
65 | {0x0078, 15, 8, 0xc0}, | ||
66 | {0x0200, 7, 0, 0x00}, | ||
67 | {0x0204, 7, 0, 0x80}, | ||
68 | {0x0204, 31, 24, 0x5e}, | ||
69 | {0x0208, 7, 0, 0x06}, | ||
70 | {0x0210, 7, 0, 0x23}, | ||
71 | {0x0214, 7, 0, 0x60}, | ||
72 | {0x0214, 15, 8, 0x30}, | ||
73 | {0x0214, 31, 24, 0x2e}, | ||
74 | {0x0218, 31, 24, 0x76}, | ||
75 | {0x022c, 7, 0, 0x02}, | ||
76 | {0x022c, 23, 16, 0x20}, | ||
77 | {0x02a0, 23, 16, 0xee}, | ||
78 | {0x02a0, 31, 24, 0xff}, | ||
79 | {0x02a4, 7, 0, 0x0f}, | ||
80 | {0x0204, 31, 24, 0x5e}, | ||
81 | {0x0208, 7, 0, 0x06}, | ||
82 | {0x0278, 15, 8, 0x20}, | ||
83 | {0x0280, 7, 0, 0x28}, | ||
84 | {0x0280, 23, 16, 0x28}, | ||
85 | {0x0284, 7, 0, 0x85}, | ||
86 | {0x0284, 15, 8, 0x03}, | ||
87 | {0x0284, 23, 16, 0x0f}, | ||
88 | {0x0284, 31, 24, 0x2d}, | ||
89 | {0x0250, 31, 24, 0xd0}, | ||
90 | {0x0284, 7, 0, 0x85}, | ||
91 | {0x0294, 31, 24, 0x20}, | ||
92 | {0x0400, 7, 0, 0x00}, | ||
93 | {0x0404, 7, 0, 0x80}, | ||
94 | {0x0404, 31, 24, 0x5e}, | ||
95 | {0x0408, 7, 0, 0x06}, | ||
96 | {0x0410, 7, 0, 0x23}, | ||
97 | {0x0414, 7, 0, 0x60}, | ||
98 | {0x0414, 15, 8, 0x30}, | ||
99 | {0x0414, 31, 24, 0x2e}, | ||
100 | {0x0418, 31, 24, 0x76}, | ||
101 | {0x042c, 7, 0, 0x02}, | ||
102 | {0x042c, 23, 16, 0x20}, | ||
103 | {0x04a0, 23, 16, 0xee}, | ||
104 | {0x04a0, 31, 24, 0xff}, | ||
105 | {0x04a4, 7, 0, 0x0f}, | ||
106 | {0x0404, 31, 24, 0x5e}, | ||
107 | {0x0408, 7, 0, 0x06}, | ||
108 | {0x0478, 15, 8, 0x20}, | ||
109 | {0x0480, 7, 0, 0x28}, | ||
110 | {0x0480, 23, 16, 0x28}, | ||
111 | {0x0484, 7, 0, 0x85}, | ||
112 | {0x0484, 15, 8, 0x03}, | ||
113 | {0x0484, 23, 16, 0x0f}, | ||
114 | {0x0484, 31, 24, 0x2d}, | ||
115 | {0x0450, 31, 24, 0xd0}, | ||
116 | {0x0494, 31, 24, 0x20}, | ||
117 | {0x0604, 7, 0, 0x80}, | ||
118 | {0x0600, 7, 0, 0x00}, | ||
119 | {0x0604, 31, 24, 0x5e}, | ||
120 | {0x0608, 7, 0, 0x06}, | ||
121 | {0x0610, 7, 0, 0x23}, | ||
122 | {0x0614, 7, 0, 0x60}, | ||
123 | {0x0614, 15, 8, 0x30}, | ||
124 | {0x0614, 31, 24, 0x2e}, | ||
125 | {0x0618, 31, 24, 0x76}, | ||
126 | {0x062c, 7, 0, 0x02}, | ||
127 | {0x062c, 23, 16, 0x20}, | ||
128 | {0x06a0, 23, 16, 0xee}, | ||
129 | {0x06a0, 31, 24, 0xff}, | ||
130 | {0x06a4, 7, 0, 0x0f}, | ||
131 | {0x0604, 31, 24, 0x5e}, | ||
132 | {0x0608, 7, 0, 0x06}, | ||
133 | {0x0678, 15, 8, 0x20}, | ||
134 | {0x0680, 7, 0, 0x28}, | ||
135 | {0x0680, 23, 16, 0x28}, | ||
136 | {0x0684, 7, 0, 0x85}, | ||
137 | {0x0684, 15, 8, 0x03}, | ||
138 | {0x0684, 23, 16, 0x0f}, | ||
139 | {0x0684, 31, 24, 0x2d}, | ||
140 | {0x0650, 31, 24, 0xd0}, | ||
141 | {0x0694, 31, 24, 0x20}, | ||
142 | {0x0800, 7, 0, 0x00}, | ||
143 | {0x0804, 7, 0, 0x80}, | ||
144 | {0x0804, 31, 24, 0x5e}, | ||
145 | {0x0808, 7, 0, 0x06}, | ||
146 | {0x0810, 7, 0, 0x23}, | ||
147 | {0x0814, 7, 0, 0x60}, | ||
148 | {0x0814, 15, 8, 0x30}, | ||
149 | {0x0814, 31, 24, 0x2e}, | ||
150 | {0x0818, 31, 24, 0x76}, | ||
151 | {0x082c, 7, 0, 0x02}, | ||
152 | {0x082c, 23, 16, 0x20}, | ||
153 | {0x08a0, 23, 16, 0xee}, | ||
154 | {0x08a0, 31, 24, 0xff}, | ||
155 | {0x08a4, 7, 0, 0x0f}, | ||
156 | {0x0804, 31, 24, 0x5e}, | ||
157 | {0x0808, 7, 0, 0x06}, | ||
158 | {0x0878, 15, 8, 0x20}, | ||
159 | {0x0880, 7, 0, 0x28}, | ||
160 | {0x0880, 23, 16, 0x28}, | ||
161 | {0x0884, 7, 0, 0x85}, | ||
162 | {0x0884, 15, 8, 0x03}, | ||
163 | {0x0884, 23, 16, 0x0f}, | ||
164 | {0x0884, 31, 24, 0x2d}, | ||
165 | {0x0850, 31, 24, 0xd0}, | ||
166 | {0x0894, 31, 24, 0x20}, | ||
167 | {0x0a00, 15, 8, 0x01}, | ||
168 | {0x0a08, 7, 0, 0x08}, | ||
169 | {0x0a08, 15, 8, 0x2c}, | ||
170 | {0x0a08, 23, 16, 0xe1}, | ||
171 | {0x0a0c, 7, 0, 0x81}, | ||
172 | {0x0a18, 23, 16, 0xe8}, | ||
173 | {0x0a30, 15, 8, 0x2f}, | ||
174 | {0x0a30, 23, 16, 0x2f}, | ||
175 | {0x0a4c, 23, 16, 0x82}, | ||
176 | {0x0a4c, 31, 24, 0xac}, | ||
177 | {0x0a54, 31, 24, 0xc0}, | ||
178 | {0x0a58, 7, 0, 0x41}, | ||
179 | {0x0a58, 15, 8, 0x14}, | ||
180 | {0x0a84, 7, 0, 0x01}, | ||
181 | {0x0a84, 15, 8, 0x03}, | ||
182 | {0x0a8c, 23, 16, 0x03}, | ||
183 | {0x0a8c, 31, 24, 0x81}, | ||
184 | {0x0a90, 7, 0, 0x01}, | ||
185 | {0x0a90, 15, 8, 0x60}, | ||
186 | {0x0a94, 31, 24, 0x01}, | ||
187 | {0x0aa0, 31, 24, 0x81}, | ||
188 | {0x0abc, 31, 24, 0xff}, | ||
189 | {0x0ac0, 7, 0, 0x8b}, | ||
190 | {0x0a44, 15, 8, 0x3d}, | ||
191 | {0x0a44, 23, 16, 0x73}, | ||
192 | {0x0a44, 31, 24, 0x5f}, | ||
193 | {0x0a48, 15, 8, 0xca}, | ||
194 | {0x0a48, 23, 16, 0xfd}, | ||
195 | {0x0a5c, 23, 16, 0x00}, | ||
196 | {0x0a5c, 31, 24, 0x00}, | ||
197 | {0x0a60, 7, 0, 0x00}, | ||
198 | {0x0a60, 15, 8, 0x80}, | ||
199 | {0x0a60, 23, 16, 0x00}, | ||
200 | {0x0a60, 31, 24, 0x00}, | ||
201 | {0x0a64, 7, 0, 0x20}, | ||
202 | {0x0a64, 15, 8, 0x12}, | ||
203 | {0x0a64, 23, 16, 0x58}, | ||
204 | {0x0a64, 31, 24, 0x0c}, | ||
205 | {0x0a68, 7, 0, 0x02}, | ||
206 | {0x0a68, 15, 8, 0x06}, | ||
207 | {0x0a68, 23, 16, 0x3b}, | ||
208 | {0x0a68, 31, 24, 0xe1}, | ||
209 | {0x0a6c, 7, 0, 0xc1}, | ||
210 | {0x0a6c, 15, 8, 0x4c}, | ||
211 | {0x0a6c, 23, 16, 0x07}, | ||
212 | {0x0a6c, 31, 24, 0xb8}, | ||
213 | {0x0a70, 7, 0, 0x89}, | ||
214 | {0x0a70, 15, 8, 0xe9}, | ||
215 | {0x0a70, 23, 16, 0x02}, | ||
216 | {0x0a70, 31, 24, 0x3f}, | ||
217 | {0x0a74, 7, 0, 0x01}, | ||
218 | {0x0b14, 23, 16, 0x37}, | ||
219 | {0x0b10, 31, 24, 0x37}, | ||
220 | {0x0b14, 7, 0, 0x5d}, | ||
221 | {0x0000, 7, 0, 0x03}, | ||
222 | {0x0a00, 7, 0, 0x9f}, | ||
223 | }; | ||
224 | |||
225 | int k2_pcie_platform_setup(void *pdata, struct device_node *np, int domain) | ||
226 | { | ||
227 | struct serdes_config *p = &k2_100mhz_pcie_5gbps_serdes[0]; | ||
228 | struct keystone_pcie_pdata *p_data = pdata; | ||
229 | void __iomem *reg_serdes_base, *devcfg; | ||
230 | u32 val; | ||
231 | int i; | ||
232 | |||
233 | devcfg = of_iomap(np, 1); | ||
234 | reg_serdes_base = of_iomap(np, 2); | ||
235 | |||
236 | pr_info("keystone2_pcie_serdes_setup for domain %d\n", domain); | ||
237 | |||
238 | if (!reg_serdes_base) | ||
239 | pr_info("Assuming SERDES initialized by boot loader\n"); | ||
240 | |||
241 | if (!devcfg) { | ||
242 | pr_warn("pcie device cfg bindings missing\n"); | ||
243 | return -EINVAL; | ||
244 | } | ||
245 | |||
246 | if (reg_serdes_base) { | ||
247 | for (i = 0; i < ARRAY_SIZE(k2_100mhz_pcie_5gbps_serdes); i++) { | ||
248 | FINSR(reg_serdes_base, p[i].ofs, p[i].msb, p[i].lsb, | ||
249 | p[i].val); | ||
250 | reg_dump((reg_serdes_base + p[i].ofs), MASK(p[i].msb, | ||
251 | p[i].lsb)); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | udelay(2000); | ||
256 | |||
257 | /* enable RC mode in devcfg */ | ||
258 | val = __raw_readl(devcfg); | ||
259 | if (domain) { | ||
260 | val &= ~PCIE1_MODE_MASK; | ||
261 | val |= PCIE1_RC_MODE; | ||
262 | } else { | ||
263 | val &= ~PCIE0_MODE_MASK; | ||
264 | val |= PCIE0_RC_MODE; | ||
265 | } | ||
266 | __raw_writel(val, devcfg); | ||
267 | |||
268 | /* check if we need to enable link training */ | ||
269 | p_data->en_link_train = | ||
270 | (of_get_property(np, "enable-linktrain", NULL) != NULL); | ||
271 | |||
272 | pr_info("keystone2_pcie_serdes_setup done domain %d, en_link_train = %d\n", | ||
273 | domain, p_data->en_link_train); | ||
274 | iounmap(devcfg); | ||
275 | iounmap(reg_serdes_base); | ||
276 | return 0; | ||
277 | } | ||