]>
Commit | Line | Data |
---|---|---|
34a8258f | 1 | /* |
768d5b2b | 2 | * Copyright 2009-2011 Freescale Semiconductor, Inc. |
34a8258f | 3 | * |
1a459660 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
34a8258f KG |
5 | */ |
6 | ||
7 | #include <common.h> | |
61054ffa KG |
8 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 |
9 | #include <hwconfig.h> | |
10 | #endif | |
34a8258f KG |
11 | #include <asm/fsl_serdes.h> |
12 | #include <asm/immap_85xx.h> | |
13 | #include <asm/io.h> | |
14 | #include <asm/processor.h> | |
61054ffa | 15 | #include <asm/fsl_law.h> |
1221ce45 | 16 | #include <linux/errno.h> |
34a8258f KG |
17 | #include "fsl_corenet_serdes.h" |
18 | ||
26002826 TT |
19 | /* |
20 | * The work-arounds for erratum SERDES8 and SERDES-A001 are linked together. | |
21 | * The code is already very complicated as it is, and separating the two | |
22 | * completely would just make things worse. We try to keep them as separate | |
23 | * as possible, but for now we require SERDES8 if SERDES_A001 is defined. | |
24 | */ | |
25 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001 | |
26 | #ifndef CONFIG_SYS_P4080_ERRATUM_SERDES8 | |
27 | #error "CONFIG_SYS_P4080_ERRATUM_SERDES_A001 requires CONFIG_SYS_P4080_ERRATUM_SERDES8" | |
28 | #endif | |
29 | #endif | |
30 | ||
34a8258f KG |
31 | static u32 serdes_prtcl_map; |
32 | ||
33 | #ifdef DEBUG | |
34 | static const char *serdes_prtcl_str[] = { | |
35 | [NONE] = "NA", | |
36 | [PCIE1] = "PCIE1", | |
37 | [PCIE2] = "PCIE2", | |
38 | [PCIE3] = "PCIE3", | |
39 | [PCIE4] = "PCIE4", | |
40 | [SATA1] = "SATA1", | |
41 | [SATA2] = "SATA2", | |
42 | [SRIO1] = "SRIO1", | |
43 | [SRIO2] = "SRIO2", | |
44 | [SGMII_FM1_DTSEC1] = "SGMII_FM1_DTSEC1", | |
45 | [SGMII_FM1_DTSEC2] = "SGMII_FM1_DTSEC2", | |
46 | [SGMII_FM1_DTSEC3] = "SGMII_FM1_DTSEC3", | |
47 | [SGMII_FM1_DTSEC4] = "SGMII_FM1_DTSEC4", | |
48 | [SGMII_FM1_DTSEC5] = "SGMII_FM1_DTSEC5", | |
49 | [SGMII_FM2_DTSEC1] = "SGMII_FM2_DTSEC1", | |
50 | [SGMII_FM2_DTSEC2] = "SGMII_FM2_DTSEC2", | |
51 | [SGMII_FM2_DTSEC3] = "SGMII_FM2_DTSEC3", | |
52 | [SGMII_FM2_DTSEC4] = "SGMII_FM2_DTSEC4", | |
99abf7de | 53 | [SGMII_FM2_DTSEC5] = "SGMII_FM2_DTSEC5", |
34a8258f KG |
54 | [XAUI_FM1] = "XAUI_FM1", |
55 | [XAUI_FM2] = "XAUI_FM2", | |
56 | [AURORA] = "DEBUG", | |
57 | }; | |
58 | #endif | |
59 | ||
60 | static const struct { | |
61 | int idx; | |
62 | unsigned int lpd; /* RCW lane powerdown bit */ | |
63 | int bank; | |
64 | } lanes[SRDS_MAX_LANES] = { | |
65 | { 0, 152, FSL_SRDS_BANK_1 }, | |
66 | { 1, 153, FSL_SRDS_BANK_1 }, | |
67 | { 2, 154, FSL_SRDS_BANK_1 }, | |
68 | { 3, 155, FSL_SRDS_BANK_1 }, | |
69 | { 4, 156, FSL_SRDS_BANK_1 }, | |
70 | { 5, 157, FSL_SRDS_BANK_1 }, | |
71 | { 6, 158, FSL_SRDS_BANK_1 }, | |
72 | { 7, 159, FSL_SRDS_BANK_1 }, | |
73 | { 8, 160, FSL_SRDS_BANK_1 }, | |
74 | { 9, 161, FSL_SRDS_BANK_1 }, | |
75 | { 16, 162, FSL_SRDS_BANK_2 }, | |
76 | { 17, 163, FSL_SRDS_BANK_2 }, | |
77 | { 18, 164, FSL_SRDS_BANK_2 }, | |
78 | { 19, 165, FSL_SRDS_BANK_2 }, | |
e71372cb | 79 | #ifdef CONFIG_ARCH_P4080 |
34a8258f KG |
80 | { 20, 170, FSL_SRDS_BANK_3 }, |
81 | { 21, 171, FSL_SRDS_BANK_3 }, | |
82 | { 22, 172, FSL_SRDS_BANK_3 }, | |
83 | { 23, 173, FSL_SRDS_BANK_3 }, | |
4905443f TT |
84 | #else |
85 | { 20, 166, FSL_SRDS_BANK_3 }, | |
86 | { 21, 167, FSL_SRDS_BANK_3 }, | |
87 | { 22, 168, FSL_SRDS_BANK_3 }, | |
88 | { 23, 169, FSL_SRDS_BANK_3 }, | |
89 | #endif | |
ca9131c0 TT |
90 | #if SRDS_MAX_BANK > 3 |
91 | { 24, 175, FSL_SRDS_BANK_4 }, | |
92 | { 25, 176, FSL_SRDS_BANK_4 }, | |
93 | #endif | |
34a8258f KG |
94 | }; |
95 | ||
96 | int serdes_get_lane_idx(int lane) | |
97 | { | |
98 | return lanes[lane].idx; | |
99 | } | |
100 | ||
3d28c5c8 | 101 | int serdes_get_bank_by_lane(int lane) |
34a8258f KG |
102 | { |
103 | return lanes[lane].bank; | |
104 | } | |
105 | ||
106 | int serdes_lane_enabled(int lane) | |
107 | { | |
108 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
109 | serdes_corenet_t *regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; | |
110 | ||
111 | int bank = lanes[lane].bank; | |
112 | int word = lanes[lane].lpd / 32; | |
113 | int bit = lanes[lane].lpd % 32; | |
114 | ||
115 | if (in_be32(®s->bank[bank].rstctl) & SRDS_RSTCTL_SDPD) | |
116 | return 0; | |
117 | ||
61054ffa | 118 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 |
314b3ff1 TT |
119 | /* |
120 | * For banks two and three, use the srds_lpd_b[] array instead of the | |
121 | * RCW, because this array contains the real values of SRDS_LPD_B2 and | |
122 | * SRDS_LPD_B3. | |
123 | */ | |
124 | if (bank > 0) | |
125 | return !(srds_lpd_b[bank] & (8 >> (lane - (6 + 4 * bank)))); | |
61054ffa KG |
126 | #endif |
127 | ||
34a8258f KG |
128 | return !(in_be32(&gur->rcwsr[word]) & (0x80000000 >> bit)); |
129 | } | |
130 | ||
131 | int is_serdes_configured(enum srds_prtcl device) | |
132 | { | |
133 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
134 | ||
135 | /* Is serdes enabled at all? */ | |
136 | if (!(in_be32(&gur->rcwsr[5]) & FSL_CORENET_RCWSR5_SRDS_EN)) | |
137 | return 0; | |
138 | ||
71fe2225 HZ |
139 | if (!(serdes_prtcl_map & (1 << NONE))) |
140 | fsl_serdes_init(); | |
141 | ||
34a8258f KG |
142 | return (1 << device) & serdes_prtcl_map; |
143 | } | |
144 | ||
3d28c5c8 EM |
145 | static int __serdes_get_first_lane(uint32_t prtcl, enum srds_prtcl device) |
146 | { | |
147 | int i; | |
148 | ||
149 | for (i = 0; i < SRDS_MAX_LANES; i++) { | |
150 | if (serdes_get_prtcl(prtcl, i) == device) | |
151 | return i; | |
152 | } | |
153 | ||
154 | return -ENODEV; | |
155 | } | |
156 | ||
157 | /* | |
158 | * Returns the SERDES lane (0..SRDS_MAX_LANES-1) that routes to the given | |
159 | * device. This depends on the current SERDES protocol, as defined in the RCW. | |
160 | * | |
161 | * Returns a negative error code if SERDES is disabled or the given device is | |
162 | * not supported in the current SERDES protocol. | |
163 | */ | |
164 | int serdes_get_first_lane(enum srds_prtcl device) | |
165 | { | |
166 | u32 prtcl; | |
167 | const ccsr_gur_t *gur; | |
168 | ||
169 | gur = (typeof(gur))CONFIG_SYS_MPC85xx_GUTS_ADDR; | |
170 | ||
171 | /* Is serdes enabled at all? */ | |
172 | if (unlikely((in_be32(&gur->rcwsr[5]) & 0x2000) == 0)) | |
173 | return -ENODEV; | |
174 | ||
175 | prtcl = (in_be32(&gur->rcwsr[4]) & FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26; | |
176 | ||
177 | return __serdes_get_first_lane(prtcl, device); | |
178 | } | |
179 | ||
df8af0b4 EM |
180 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 |
181 | /* | |
182 | * Returns the SERDES bank (1, 2, or 3) that a given device is on for a given | |
183 | * SERDES protocol. | |
184 | * | |
185 | * Returns a negative error code if the given device is not supported for the | |
186 | * given SERDES protocol. | |
187 | */ | |
188 | static int serdes_get_bank_by_device(uint32_t prtcl, enum srds_prtcl device) | |
189 | { | |
190 | int lane; | |
191 | ||
192 | lane = __serdes_get_first_lane(prtcl, device); | |
193 | if (unlikely(lane < 0)) | |
194 | return lane; | |
195 | ||
196 | return serdes_get_bank_by_lane(lane); | |
197 | } | |
198 | ||
199 | static uint32_t __serdes_get_lane_count(uint32_t prtcl, enum srds_prtcl device, | |
200 | int first) | |
201 | { | |
202 | int lane; | |
203 | ||
204 | for (lane = first; lane < SRDS_MAX_LANES; lane++) { | |
205 | if (serdes_get_prtcl(prtcl, lane) != device) | |
206 | break; | |
207 | } | |
208 | ||
209 | return lane - first; | |
210 | } | |
211 | ||
212 | static void __serdes_reset_rx(serdes_corenet_t *regs, | |
213 | uint32_t prtcl, | |
214 | enum srds_prtcl device) | |
215 | { | |
216 | int lane, idx, first, last; | |
217 | ||
218 | lane = __serdes_get_first_lane(prtcl, device); | |
219 | if (unlikely(lane < 0)) | |
220 | return; | |
221 | first = serdes_get_lane_idx(lane); | |
222 | last = first + __serdes_get_lane_count(prtcl, device, lane); | |
223 | ||
224 | /* | |
225 | * Set BnGCRy0[RRST] = 0 for each lane in the each bank that is | |
226 | * selected as XAUI to place the lane into reset. | |
227 | */ | |
228 | for (idx = first; idx < last; idx++) | |
229 | clrbits_be32(®s->lane[idx].gcr0, SRDS_GCR0_RRST); | |
230 | ||
231 | /* Wait at least 250 ns */ | |
232 | udelay(1); | |
233 | ||
234 | /* | |
235 | * Set BnGCRy0[RRST] = 1 for each lane in the each bank that is | |
236 | * selected as XAUI to bring the lane out of reset. | |
237 | */ | |
238 | for (idx = first; idx < last; idx++) | |
239 | setbits_be32(®s->lane[idx].gcr0, SRDS_GCR0_RRST); | |
240 | } | |
241 | ||
242 | void serdes_reset_rx(enum srds_prtcl device) | |
243 | { | |
244 | u32 prtcl; | |
245 | const ccsr_gur_t *gur; | |
246 | serdes_corenet_t *regs; | |
247 | ||
248 | if (unlikely(device == NONE)) | |
249 | return; | |
250 | ||
251 | gur = (typeof(gur))CONFIG_SYS_MPC85xx_GUTS_ADDR; | |
252 | ||
253 | /* Is serdes enabled at all? */ | |
254 | if (unlikely((in_be32(&gur->rcwsr[5]) & 0x2000) == 0)) | |
255 | return; | |
256 | ||
257 | regs = (typeof(regs))CONFIG_SYS_FSL_CORENET_SERDES_ADDR; | |
258 | prtcl = (in_be32(&gur->rcwsr[4]) & FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26; | |
259 | ||
260 | __serdes_reset_rx(regs, prtcl, device); | |
261 | } | |
262 | #endif | |
263 | ||
61054ffa KG |
264 | #ifndef CONFIG_SYS_DCSRBAR_PHYS |
265 | #define CONFIG_SYS_DCSRBAR_PHYS 0x80000000 /* Must be 1GB-aligned for rev1.0 */ | |
266 | #define CONFIG_SYS_DCSRBAR 0x80000000 | |
267 | #define __DCSR_NOT_DEFINED_BY_CONFIG | |
268 | #endif | |
269 | ||
270 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 | |
26002826 TT |
271 | /* |
272 | * Enable a SERDES bank that was disabled via the RCW | |
273 | * | |
274 | * We only call this function for SERDES8 and SERDES-A001 in cases we really | |
275 | * want to enable the bank, whether we actually want to use the lanes or not, | |
276 | * so make sure at least one lane is enabled. We're only enabling this one | |
277 | * lane to satisfy errata requirements that the bank be enabled. | |
278 | * | |
279 | * We use a local variable instead of srds_lpd_b[] because we want drivers to | |
280 | * think that the lanes actually are disabled. | |
281 | */ | |
61054ffa KG |
282 | static void enable_bank(ccsr_gur_t *gur, int bank) |
283 | { | |
284 | u32 rcw5; | |
26002826 TT |
285 | u32 temp_lpd_b = srds_lpd_b[bank]; |
286 | ||
287 | /* | |
288 | * If we're asked to disable all lanes, just pretend we're doing | |
289 | * that. | |
290 | */ | |
291 | if (temp_lpd_b == 0xF) | |
292 | temp_lpd_b = 0xE; | |
61054ffa KG |
293 | |
294 | /* | |
295 | * Enable the lanes SRDS_LPD_Bn. The RCW bits are read-only in | |
296 | * CCSR, and read/write in DSCR. | |
297 | */ | |
298 | rcw5 = in_be32(gur->rcwsr + 5); | |
299 | if (bank == FSL_SRDS_BANK_2) { | |
300 | rcw5 &= ~FSL_CORENET_RCWSRn_SRDS_LPD_B2; | |
26002826 | 301 | rcw5 |= temp_lpd_b << 26; |
61054ffa KG |
302 | } else if (bank == FSL_SRDS_BANK_3) { |
303 | rcw5 &= ~FSL_CORENET_RCWSRn_SRDS_LPD_B3; | |
26002826 | 304 | rcw5 |= temp_lpd_b << 18; |
61054ffa KG |
305 | } else { |
306 | printf("SERDES: enable_bank: bad bank %d\n", bank + 1); | |
307 | return; | |
308 | } | |
309 | ||
310 | /* See similar code in cpu/mpc85xx/cpu_init.c for an explanation | |
311 | * of the DCSR mapping. | |
312 | */ | |
313 | { | |
314 | #ifdef __DCSR_NOT_DEFINED_BY_CONFIG | |
315 | struct law_entry law = find_law(CONFIG_SYS_DCSRBAR_PHYS); | |
316 | int law_index; | |
317 | if (law.index == -1) | |
318 | law_index = set_next_law(CONFIG_SYS_DCSRBAR_PHYS, | |
319 | LAW_SIZE_1M, LAW_TRGT_IF_DCSR); | |
320 | else | |
321 | set_law(law.index, CONFIG_SYS_DCSRBAR_PHYS, LAW_SIZE_1M, | |
322 | LAW_TRGT_IF_DCSR); | |
323 | #endif | |
324 | u32 *p = (void *)CONFIG_SYS_DCSRBAR + 0x20114; | |
325 | out_be32(p, rcw5); | |
326 | #ifdef __DCSR_NOT_DEFINED_BY_CONFIG | |
327 | if (law.index == -1) | |
328 | disable_law(law_index); | |
329 | else | |
330 | set_law(law.index, law.addr, law.size, law.trgt_id); | |
331 | #endif | |
332 | } | |
333 | } | |
334 | ||
335 | /* | |
336 | * To avoid problems with clock jitter, rev 2 p4080 uses the pll from | |
337 | * bank 3 to clock banks 2 and 3, as well as a limited selection of | |
338 | * protocol configurations. This requires that banks 2 and 3's lanes be | |
339 | * disabled in the RCW, and enabled with some fixup here to re-enable | |
340 | * them, and to configure bank 2's clock parameters in bank 3's pll in | |
341 | * cases where they differ. | |
342 | */ | |
343 | static void p4080_erratum_serdes8(serdes_corenet_t *regs, ccsr_gur_t *gur, | |
344 | u32 devdisr, u32 devdisr2, int cfg) | |
345 | { | |
346 | int srds_ratio_b2; | |
347 | int rfck_sel; | |
348 | ||
349 | /* | |
350 | * The disabled lanes of bank 2 will cause the associated | |
351 | * logic blocks to be disabled in DEVDISR. We reverse that here. | |
352 | * | |
353 | * Note that normally it is not permitted to clear DEVDISR bits | |
354 | * once the device has been disabled, but the hardware people | |
355 | * say that this special case is OK. | |
356 | */ | |
357 | clrbits_be32(&gur->devdisr, devdisr); | |
358 | clrbits_be32(&gur->devdisr2, devdisr2); | |
359 | ||
360 | /* | |
361 | * Some protocols require special handling. There are a few | |
362 | * additional protocol configurations that can be used, which are | |
363 | * not listed here. See app note 4065 for supported protocol | |
364 | * configurations. | |
365 | */ | |
366 | switch (cfg) { | |
367 | case 0x19: | |
368 | /* | |
369 | * Bank 2 has PCIe which wants BWSEL -- tell bank 3's PLL. | |
370 | * SGMII on bank 3 should still be usable. | |
371 | */ | |
372 | setbits_be32(®s->bank[FSL_SRDS_BANK_3].pllcr1, | |
373 | SRDS_PLLCR1_PLL_BWSEL); | |
61054ffa KG |
374 | break; |
375 | ||
376 | case 0x0f: | |
377 | case 0x10: | |
378 | /* | |
379 | * Banks 2 (XAUI) and 3 (SGMII) have different clocking | |
380 | * requirements in these configurations. Bank 3 cannot | |
381 | * be used and should have its lanes (but not the bank | |
382 | * itself) disabled in the RCW. We set up bank 3's pll | |
383 | * for bank 2's needs here. | |
384 | */ | |
385 | srds_ratio_b2 = (in_be32(&gur->rcwsr[4]) >> 13) & 7; | |
386 | ||
387 | /* Determine refclock from XAUI ratio */ | |
388 | switch (srds_ratio_b2) { | |
389 | case 1: /* 20:1 */ | |
390 | rfck_sel = SRDS_PLLCR0_RFCK_SEL_156_25; | |
391 | break; | |
392 | case 2: /* 25:1 */ | |
393 | rfck_sel = SRDS_PLLCR0_RFCK_SEL_125; | |
394 | break; | |
395 | default: | |
396 | printf("SERDES: bad SRDS_RATIO_B2 %d\n", | |
397 | srds_ratio_b2); | |
398 | return; | |
399 | } | |
400 | ||
401 | clrsetbits_be32(®s->bank[FSL_SRDS_BANK_3].pllcr0, | |
402 | SRDS_PLLCR0_RFCK_SEL_MASK, rfck_sel); | |
403 | ||
404 | clrsetbits_be32(®s->bank[FSL_SRDS_BANK_3].pllcr0, | |
405 | SRDS_PLLCR0_FRATE_SEL_MASK, | |
406 | SRDS_PLLCR0_FRATE_SEL_6_25); | |
407 | break; | |
61054ffa KG |
408 | } |
409 | ||
26002826 | 410 | enable_bank(gur, FSL_SRDS_BANK_3); |
61054ffa KG |
411 | } |
412 | #endif | |
413 | ||
da30b9fd TT |
414 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A005 |
415 | /* | |
416 | * If PCIe is not selected as a protocol for any lanes driven by a given PLL, | |
417 | * that PLL should have SRDSBnPLLCR1[PLLBW_SEL] = 0. | |
418 | */ | |
419 | static void p4080_erratum_serdes_a005(serdes_corenet_t *regs, unsigned int cfg) | |
420 | { | |
421 | enum srds_prtcl device; | |
422 | ||
423 | switch (cfg) { | |
424 | case 0x13: | |
425 | case 0x16: | |
426 | /* | |
427 | * If SRDS_PRTCL = 0x13 or 0x16, set SRDSB1PLLCR1[PLLBW_SEL] | |
428 | * to 0. | |
429 | */ | |
430 | clrbits_be32(®s->bank[FSL_SRDS_BANK_1].pllcr1, | |
431 | SRDS_PLLCR1_PLL_BWSEL); | |
432 | break; | |
433 | case 0x19: | |
434 | /* | |
435 | * If SRDS_PRTCL = 0x19, set SRDSB1PLLCR1[PLLBW_SEL] to 0 and | |
436 | * SRDSB3PLLCR1[PLLBW_SEL] to 1. | |
437 | */ | |
438 | clrbits_be32(®s->bank[FSL_SRDS_BANK_1].pllcr1, | |
439 | SRDS_PLLCR1_PLL_BWSEL); | |
440 | setbits_be32(®s->bank[FSL_SRDS_BANK_3].pllcr1, | |
441 | SRDS_PLLCR1_PLL_BWSEL); | |
442 | break; | |
443 | } | |
444 | ||
445 | /* | |
446 | * Set SRDSBnPLLCR1[PLLBW_SEL] to 0 for each bank that selects XAUI | |
447 | * before XAUI is initialized. | |
448 | */ | |
449 | for (device = XAUI_FM1; device <= XAUI_FM2; device++) { | |
450 | if (is_serdes_configured(device)) { | |
451 | int bank = serdes_get_bank_by_device(cfg, device); | |
452 | ||
453 | clrbits_be32(®s->bank[bank].pllcr1, | |
454 | SRDS_PLLCR1_PLL_BWSEL); | |
455 | } | |
456 | } | |
457 | } | |
458 | #endif | |
459 | ||
d90fdba6 TT |
460 | /* |
461 | * Wait for the RSTDONE bit to get set, or a one-second timeout. | |
462 | */ | |
463 | static void wait_for_rstdone(unsigned int bank) | |
464 | { | |
465 | serdes_corenet_t *srds_regs = | |
466 | (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; | |
467 | unsigned long long end_tick; | |
468 | u32 rstctl; | |
469 | ||
470 | /* wait for reset complete or 1-second timeout */ | |
471 | end_tick = usec2ticks(1000000) + get_ticks(); | |
472 | do { | |
473 | rstctl = in_be32(&srds_regs->bank[bank].rstctl); | |
474 | if (rstctl & SRDS_RSTCTL_RSTDONE) | |
475 | break; | |
476 | } while (end_tick > get_ticks()); | |
477 | ||
478 | if (!(rstctl & SRDS_RSTCTL_RSTDONE)) | |
26002826 | 479 | printf("SERDES: timeout resetting bank %u\n", bank + 1); |
d90fdba6 TT |
480 | } |
481 | ||
6d7b061a | 482 | |
e56143e5 | 483 | static void __soc_serdes_init(void) |
6d7b061a SL |
484 | { |
485 | /* Allow for SoC-specific initialization in <SOC>_serdes.c */ | |
486 | }; | |
487 | void soc_serdes_init(void) __attribute__((weak, alias("__soc_serdes_init"))); | |
488 | ||
34a8258f KG |
489 | void fsl_serdes_init(void) |
490 | { | |
491 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
492 | int cfg; | |
493 | serdes_corenet_t *srds_regs; | |
95390360 | 494 | #ifdef CONFIG_ARCH_P5040 |
4905443f TT |
495 | serdes_corenet_t *srds2_regs; |
496 | #endif | |
34a8258f | 497 | int lane, bank, idx; |
34a8258f | 498 | int have_bank[SRDS_MAX_BANK] = {}; |
61054ffa KG |
499 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 |
500 | u32 serdes8_devdisr = 0; | |
501 | u32 serdes8_devdisr2 = 0; | |
502 | char srds_lpd_opt[16]; | |
503 | const char *srds_lpd_arg; | |
504 | size_t arglen; | |
df8af0b4 | 505 | #endif |
d90fdba6 | 506 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001 |
472d5460 | 507 | int need_serdes_a001; /* true == need work-around for SERDES A001 */ |
61054ffa | 508 | #endif |
c1ee16b8 | 509 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 |
768d5b2b YS |
510 | char buffer[HWCONFIG_BUFFER_SIZE]; |
511 | char *buf = NULL; | |
512 | ||
513 | /* | |
514 | * Extract hwconfig from environment since we have not properly setup | |
515 | * the environment but need it for ddr config params | |
516 | */ | |
517 | if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0) | |
518 | buf = buffer; | |
c1ee16b8 | 519 | #endif |
71fe2225 HZ |
520 | if (serdes_prtcl_map & (1 << NONE)) |
521 | return; | |
34a8258f KG |
522 | |
523 | /* Is serdes enabled at all? */ | |
524 | if (!(in_be32(&gur->rcwsr[5]) & FSL_CORENET_RCWSR5_SRDS_EN)) | |
525 | return; | |
526 | ||
527 | srds_regs = (void *)(CONFIG_SYS_FSL_CORENET_SERDES_ADDR); | |
528 | cfg = (in_be32(&gur->rcwsr[4]) & FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26; | |
529 | debug("Using SERDES configuration 0x%x, lane settings:\n", cfg); | |
530 | ||
531 | if (!is_serdes_prtcl_valid(cfg)) { | |
532 | printf("SERDES[PRTCL] = 0x%x is not valid\n", cfg); | |
533 | return; | |
534 | } | |
535 | ||
61054ffa | 536 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 |
7d6d9ba9 TT |
537 | /* |
538 | * Display a warning if banks two and three are not disabled in the RCW, | |
539 | * since our work-around for SERDES8 depends on these banks being | |
540 | * disabled at power-on. | |
541 | */ | |
542 | #define B2_B3 (FSL_CORENET_RCWSRn_SRDS_LPD_B2 | FSL_CORENET_RCWSRn_SRDS_LPD_B3) | |
543 | if ((in_be32(&gur->rcwsr[5]) & B2_B3) != B2_B3) { | |
544 | printf("Warning: SERDES8 requires banks two and " | |
545 | "three to be disabled in the RCW\n"); | |
546 | } | |
547 | ||
314b3ff1 TT |
548 | /* |
549 | * Store the values of the fsl_srds_lpd_b2 and fsl_srds_lpd_b3 | |
550 | * hwconfig options into the srds_lpd_b[] array. See README.p4080ds | |
551 | * for a description of these options. | |
552 | */ | |
553 | for (bank = 1; bank < ARRAY_SIZE(srds_lpd_b); bank++) { | |
554 | sprintf(srds_lpd_opt, "fsl_srds_lpd_b%u", bank + 1); | |
555 | srds_lpd_arg = | |
556 | hwconfig_subarg_f("serdes", srds_lpd_opt, &arglen, buf); | |
557 | if (srds_lpd_arg) | |
558 | srds_lpd_b[bank] = | |
559 | simple_strtoul(srds_lpd_arg, NULL, 0) & 0xf; | |
560 | } | |
26002826 TT |
561 | |
562 | if ((cfg == 0xf) || (cfg == 0x10)) { | |
563 | /* | |
564 | * For SERDES protocols 0xF and 0x10, force bank 3 to be | |
565 | * disabled, because it is not supported. | |
566 | */ | |
567 | srds_lpd_b[FSL_SRDS_BANK_3] = 0xF; | |
568 | } | |
61054ffa KG |
569 | #endif |
570 | ||
34a8258f KG |
571 | /* Look for banks with all lanes disabled, and power down the bank. */ |
572 | for (lane = 0; lane < SRDS_MAX_LANES; lane++) { | |
573 | enum srds_prtcl lane_prtcl = serdes_get_prtcl(cfg, lane); | |
574 | if (serdes_lane_enabled(lane)) { | |
3d28c5c8 | 575 | have_bank[serdes_get_bank_by_lane(lane)] = 1; |
34a8258f KG |
576 | serdes_prtcl_map |= (1 << lane_prtcl); |
577 | } | |
578 | } | |
579 | ||
95390360 | 580 | #ifdef CONFIG_ARCH_P5040 |
4905443f TT |
581 | /* |
582 | * Lanes on bank 4 on P5040 are commented-out, but for some SERDES | |
583 | * protocols, these lanes are routed to SATA. We use serdes_prtcl_map | |
584 | * to decide whether a protocol is supported on a given lane, so SATA | |
585 | * will be identified as not supported, and therefore not initialized. | |
586 | * So for protocols which use SATA on bank4, we add SATA support in | |
587 | * serdes_prtcl_map. | |
588 | */ | |
589 | switch (cfg) { | |
590 | case 0x0: | |
591 | case 0x1: | |
592 | case 0x2: | |
593 | case 0x3: | |
594 | case 0x4: | |
595 | case 0x5: | |
596 | case 0x6: | |
597 | case 0x7: | |
598 | serdes_prtcl_map |= 1 << SATA1 | 1 << SATA2; | |
599 | break; | |
600 | default: | |
601 | srds2_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES2_ADDR; | |
602 | ||
603 | /* We don't need bank 4, so power it down */ | |
604 | setbits_be32(&srds2_regs->bank[0].rstctl, SRDS_RSTCTL_SDPD); | |
605 | } | |
606 | #endif | |
607 | ||
6d7b061a SL |
608 | soc_serdes_init(); |
609 | ||
61054ffa | 610 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 |
314b3ff1 TT |
611 | /* |
612 | * Bank two uses the clock from bank three, so if bank two is enabled, | |
613 | * then bank three must also be enabled. | |
614 | */ | |
615 | if (have_bank[FSL_SRDS_BANK_2]) | |
616 | have_bank[FSL_SRDS_BANK_3] = 1; | |
61054ffa KG |
617 | #endif |
618 | ||
d90fdba6 TT |
619 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001 |
620 | /* | |
621 | * The work-aroud for erratum SERDES-A001 is needed only if bank two | |
26002826 TT |
622 | * is disabled and bank three is enabled. The converse is also true, |
623 | * but SERDES8 ensures that bank 3 is always enabled if bank 2 is | |
624 | * enabled, so there's no point in complicating the code to handle | |
625 | * that situation. | |
d90fdba6 TT |
626 | */ |
627 | need_serdes_a001 = | |
628 | !have_bank[FSL_SRDS_BANK_2] && have_bank[FSL_SRDS_BANK_3]; | |
629 | #endif | |
630 | ||
631 | /* Power down the banks we're not interested in */ | |
34a8258f KG |
632 | for (bank = 0; bank < SRDS_MAX_BANK; bank++) { |
633 | if (!have_bank[bank]) { | |
634 | printf("SERDES: bank %d disabled\n", bank + 1); | |
d90fdba6 TT |
635 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001 |
636 | /* | |
637 | * Erratum SERDES-A001 says bank two needs to be powered | |
638 | * down after bank three is powered up, so don't power | |
639 | * down bank two here. | |
640 | */ | |
641 | if (!need_serdes_a001 || (bank != FSL_SRDS_BANK_2)) | |
642 | setbits_be32(&srds_regs->bank[bank].rstctl, | |
643 | SRDS_RSTCTL_SDPD); | |
644 | #else | |
34a8258f KG |
645 | setbits_be32(&srds_regs->bank[bank].rstctl, |
646 | SRDS_RSTCTL_SDPD); | |
d90fdba6 | 647 | #endif |
34a8258f KG |
648 | } |
649 | } | |
650 | ||
4905443f TT |
651 | #ifdef CONFIG_SYS_FSL_ERRATUM_A004699 |
652 | /* | |
653 | * To avoid the situation that resulted in the P4080 erratum | |
654 | * SERDES-8, a given SerDes bank will use the PLLs from the previous | |
655 | * bank if one of the PLL frequencies is a multiple of the other. For | |
656 | * instance, if bank 3 is running at 2.5GHz and bank 2 is at 1.25GHz, | |
657 | * then bank 3 will use bank 2's PLL. P5040 Erratum A-004699 says | |
658 | * that, in this situation, lane synchronization is not initiated. So | |
659 | * when we detect a bank with a "borrowed" PLL, we have to manually | |
660 | * initiate lane synchronization. | |
661 | */ | |
662 | for (bank = FSL_SRDS_BANK_2; bank <= FSL_SRDS_BANK_3; bank++) { | |
663 | /* Determine the first lane for this bank */ | |
664 | unsigned int lane; | |
665 | ||
666 | for (lane = 0; lane < SRDS_MAX_LANES; lane++) | |
667 | if (lanes[lane].bank == bank) | |
668 | break; | |
669 | idx = lanes[lane].idx; | |
670 | ||
671 | /* | |
672 | * Check if the PLL for the bank is borrowed. The UOTHL | |
673 | * bit of the first lane will tell us that. | |
674 | */ | |
675 | if (in_be32(&srds_regs->lane[idx].gcr0) & SRDS_GCR0_UOTHL) { | |
676 | /* Manually start lane synchronization */ | |
677 | setbits_be32(&srds_regs->bank[bank].pllcr0, | |
678 | SRDS_PLLCR0_PVCOCNT_EN); | |
679 | } | |
680 | } | |
681 | #endif | |
682 | ||
c1ee16b8 | 683 | #if defined(CONFIG_SYS_P4080_ERRATUM_SERDES8) || defined (CONFIG_SYS_P4080_ERRATUM_SERDES9) |
34a8258f | 684 | for (lane = 0; lane < SRDS_MAX_LANES; lane++) { |
c1ee16b8 KG |
685 | enum srds_prtcl lane_prtcl; |
686 | ||
34a8258f KG |
687 | idx = serdes_get_lane_idx(lane); |
688 | lane_prtcl = serdes_get_prtcl(cfg, lane); | |
689 | ||
690 | #ifdef DEBUG | |
691 | switch (lane) { | |
692 | case 0: | |
693 | puts("Bank1: "); | |
694 | break; | |
695 | case 10: | |
696 | puts("\nBank2: "); | |
697 | break; | |
698 | case 14: | |
699 | puts("\nBank3: "); | |
700 | break; | |
701 | default: | |
702 | break; | |
703 | } | |
704 | ||
705 | printf("%s ", serdes_prtcl_str[lane_prtcl]); | |
61054ffa KG |
706 | #endif |
707 | ||
f68d3063 TT |
708 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 |
709 | /* | |
b25f6de7 TT |
710 | * Set BnTTLCRy0[FLT_SEL] = 011011 and set BnTTLCRy0[31] = 1 |
711 | * for each of the SerDes lanes selected as SGMII, XAUI, SRIO, | |
712 | * or AURORA before the device is initialized. | |
713 | * | |
714 | * Note that this part of the SERDES-9 work-around is | |
715 | * redundant if the work-around for A-4580 has already been | |
716 | * applied via PBI. | |
f68d3063 TT |
717 | */ |
718 | switch (lane_prtcl) { | |
719 | case SGMII_FM1_DTSEC1: | |
720 | case SGMII_FM1_DTSEC2: | |
721 | case SGMII_FM1_DTSEC3: | |
722 | case SGMII_FM1_DTSEC4: | |
723 | case SGMII_FM2_DTSEC1: | |
724 | case SGMII_FM2_DTSEC2: | |
725 | case SGMII_FM2_DTSEC3: | |
726 | case SGMII_FM2_DTSEC4: | |
99abf7de | 727 | case SGMII_FM2_DTSEC5: |
f68d3063 TT |
728 | case XAUI_FM1: |
729 | case XAUI_FM2: | |
730 | case SRIO1: | |
731 | case SRIO2: | |
732 | case AURORA: | |
b25f6de7 TT |
733 | out_be32(&srds_regs->lane[idx].ttlcr0, |
734 | SRDS_TTLCR0_FLT_SEL_KFR_26 | | |
735 | SRDS_TTLCR0_FLT_SEL_KPH_28 | | |
736 | SRDS_TTLCR0_FLT_SEL_750PPM | | |
737 | SRDS_TTLCR0_FREQOVD_EN); | |
738 | break; | |
f68d3063 TT |
739 | default: |
740 | break; | |
741 | } | |
742 | #endif | |
743 | ||
61054ffa KG |
744 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 |
745 | switch (lane_prtcl) { | |
746 | case PCIE1: | |
747 | case PCIE2: | |
748 | case PCIE3: | |
749 | serdes8_devdisr |= FSL_CORENET_DEVDISR_PCIE1 >> | |
750 | (lane_prtcl - PCIE1); | |
751 | break; | |
752 | case SRIO1: | |
753 | case SRIO2: | |
754 | serdes8_devdisr |= FSL_CORENET_DEVDISR_SRIO1 >> | |
755 | (lane_prtcl - SRIO1); | |
756 | break; | |
757 | case SGMII_FM1_DTSEC1: | |
758 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 | | |
759 | FSL_CORENET_DEVDISR2_DTSEC1_1; | |
760 | break; | |
761 | case SGMII_FM1_DTSEC2: | |
762 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 | | |
763 | FSL_CORENET_DEVDISR2_DTSEC1_2; | |
764 | break; | |
765 | case SGMII_FM1_DTSEC3: | |
766 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 | | |
767 | FSL_CORENET_DEVDISR2_DTSEC1_3; | |
768 | break; | |
769 | case SGMII_FM1_DTSEC4: | |
770 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 | | |
771 | FSL_CORENET_DEVDISR2_DTSEC1_4; | |
772 | break; | |
773 | case SGMII_FM2_DTSEC1: | |
774 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | | |
775 | FSL_CORENET_DEVDISR2_DTSEC2_1; | |
776 | break; | |
777 | case SGMII_FM2_DTSEC2: | |
778 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | | |
779 | FSL_CORENET_DEVDISR2_DTSEC2_2; | |
780 | break; | |
781 | case SGMII_FM2_DTSEC3: | |
782 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | | |
783 | FSL_CORENET_DEVDISR2_DTSEC2_3; | |
784 | break; | |
785 | case SGMII_FM2_DTSEC4: | |
786 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | | |
787 | FSL_CORENET_DEVDISR2_DTSEC2_4; | |
788 | break; | |
99abf7de TT |
789 | case SGMII_FM2_DTSEC5: |
790 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | | |
791 | FSL_CORENET_DEVDISR2_DTSEC2_5; | |
792 | break; | |
61054ffa | 793 | case XAUI_FM1: |
f68d3063 TT |
794 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 | |
795 | FSL_CORENET_DEVDISR2_10GEC1; | |
796 | break; | |
61054ffa | 797 | case XAUI_FM2: |
f68d3063 TT |
798 | serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | |
799 | FSL_CORENET_DEVDISR2_10GEC2; | |
61054ffa KG |
800 | break; |
801 | case AURORA: | |
802 | break; | |
803 | default: | |
804 | break; | |
805 | } | |
806 | ||
34a8258f KG |
807 | #endif |
808 | } | |
c1ee16b8 | 809 | #endif |
34a8258f KG |
810 | |
811 | #ifdef DEBUG | |
812 | puts("\n"); | |
df8af0b4 EM |
813 | #endif |
814 | ||
da30b9fd TT |
815 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A005 |
816 | p4080_erratum_serdes_a005(srds_regs, cfg); | |
34a8258f KG |
817 | #endif |
818 | ||
819 | for (idx = 0; idx < SRDS_MAX_BANK; idx++) { | |
34a8258f KG |
820 | bank = idx; |
821 | ||
61054ffa | 822 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 |
314b3ff1 TT |
823 | /* |
824 | * Change bank init order to 0, 2, 1, so that the third bank's | |
825 | * PLL is established before we start the second bank. The | |
826 | * second bank uses the third bank's PLL. | |
827 | */ | |
61054ffa | 828 | |
314b3ff1 TT |
829 | if (idx == 1) |
830 | bank = FSL_SRDS_BANK_3; | |
831 | else if (idx == 2) | |
832 | bank = FSL_SRDS_BANK_2; | |
61054ffa KG |
833 | #endif |
834 | ||
34a8258f KG |
835 | /* Skip disabled banks */ |
836 | if (!have_bank[bank]) | |
837 | continue; | |
838 | ||
61054ffa | 839 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 |
314b3ff1 TT |
840 | if (idx == 1) { |
841 | /* | |
842 | * Re-enable devices on banks two and three that were | |
843 | * disabled by the RCW, and then enable bank three. The | |
844 | * devices need to be enabled before either bank is | |
845 | * powered up. | |
846 | */ | |
847 | p4080_erratum_serdes8(srds_regs, gur, serdes8_devdisr, | |
848 | serdes8_devdisr2, cfg); | |
849 | } else if (idx == 2) { | |
26002826 | 850 | /* Enable bank two now that bank three is enabled. */ |
314b3ff1 | 851 | enable_bank(gur, FSL_SRDS_BANK_2); |
61054ffa KG |
852 | } |
853 | #endif | |
854 | ||
d90fdba6 TT |
855 | wait_for_rstdone(bank); |
856 | } | |
857 | ||
858 | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001 | |
859 | if (need_serdes_a001) { | |
26002826 | 860 | /* Bank 3 has been enabled, so now we can disable bank 2 */ |
d90fdba6 TT |
861 | setbits_be32(&srds_regs->bank[FSL_SRDS_BANK_2].rstctl, |
862 | SRDS_RSTCTL_SDPD); | |
34a8258f | 863 | } |
d90fdba6 | 864 | #endif |
71fe2225 HZ |
865 | |
866 | /* Set the first bit to indicate serdes has been initialized */ | |
867 | serdes_prtcl_map |= (1 << NONE); | |
34a8258f | 868 | } |
935b402e VL |
869 | |
870 | const char *serdes_clock_to_string(u32 clock) | |
871 | { | |
872 | switch (clock) { | |
873 | case SRDS_PLLCR0_RFCK_SEL_100: | |
874 | return "100"; | |
875 | case SRDS_PLLCR0_RFCK_SEL_125: | |
876 | return "125"; | |
877 | case SRDS_PLLCR0_RFCK_SEL_156_25: | |
878 | return "156.25"; | |
879 | case SRDS_PLLCR0_RFCK_SEL_161_13: | |
880 | return "161.1328123"; | |
881 | default: | |
882 | return "150"; | |
883 | } | |
884 | } | |
885 |