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