]>
Commit | Line | Data |
---|---|---|
e60476a0 PK |
1 | /* |
2 | * Copyright 2015 Freescale Semiconductor, Inc. | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <netdev.h> | |
9 | #include <asm/io.h> | |
10 | #include <asm/arch/fsl_serdes.h> | |
cf7ee6c4 | 11 | #include <hwconfig.h> |
e60476a0 PK |
12 | #include <fsl_mdio.h> |
13 | #include <malloc.h> | |
14 | #include <fm_eth.h> | |
cf7ee6c4 PK |
15 | #include <i2c.h> |
16 | #include <miiphy.h> | |
33a8991a | 17 | #include <fsl-mc/fsl_mc.h> |
e60476a0 PK |
18 | #include <fsl-mc/ldpaa_wriop.h> |
19 | ||
20 | #include "../common/qixis.h" | |
21 | ||
44937214 | 22 | #include "ls2080aqds_qixis.h" |
e60476a0 | 23 | |
30677dee | 24 | #define MC_BOOT_ENV_VAR "mcinitcmd" |
e60476a0 | 25 | |
1f55a938 | 26 | #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) |
44937214 | 27 | /* - In LS2080A there are only 16 SERDES lanes, spread across 2 SERDES banks. |
e60476a0 PK |
28 | * Bank 1 -> Lanes A, B, C, D, E, F, G, H |
29 | * Bank 2 -> Lanes A,B, C, D, E, F, G, H | |
30 | */ | |
31 | ||
44937214 | 32 | /* Mapping of 16 SERDES lanes to LS2080A QDS board slots. A value of '0' here |
e60476a0 PK |
33 | * means that the mapping must be determined dynamically, or that the lane |
34 | * maps to something other than a board slot. | |
35 | */ | |
36 | ||
cf7ee6c4 PK |
37 | static u8 lane_to_slot_fsm1[] = { |
38 | 0, 0, 0, 0, 0, 0, 0, 0 | |
39 | }; | |
40 | ||
e60476a0 PK |
41 | static u8 lane_to_slot_fsm2[] = { |
42 | 0, 0, 0, 0, 0, 0, 0, 0 | |
43 | }; | |
44 | ||
45 | /* On the Vitesse VSC8234XHG SGMII riser card there are 4 SGMII PHYs | |
46 | * housed. | |
47 | */ | |
cf7ee6c4 PK |
48 | |
49 | static int xqsgii_riser_phy_addr[] = { | |
50 | XQSGMII_CARD_PHY1_PORT0_ADDR, | |
51 | XQSGMII_CARD_PHY2_PORT0_ADDR, | |
52 | XQSGMII_CARD_PHY3_PORT0_ADDR, | |
53 | XQSGMII_CARD_PHY4_PORT0_ADDR, | |
54 | XQSGMII_CARD_PHY3_PORT2_ADDR, | |
55 | XQSGMII_CARD_PHY1_PORT2_ADDR, | |
56 | XQSGMII_CARD_PHY4_PORT2_ADDR, | |
57 | XQSGMII_CARD_PHY2_PORT2_ADDR, | |
58 | }; | |
59 | ||
60 | static int sgmii_riser_phy_addr[] = { | |
e60476a0 PK |
61 | SGMII_CARD_PORT1_PHY_ADDR, |
62 | SGMII_CARD_PORT2_PHY_ADDR, | |
63 | SGMII_CARD_PORT3_PHY_ADDR, | |
64 | SGMII_CARD_PORT4_PHY_ADDR, | |
65 | }; | |
66 | ||
67 | /* Slot2 does not have EMI connections */ | |
fc35adde | 68 | #define EMI_NONE 0xFF |
e60476a0 PK |
69 | #define EMI1_SLOT1 0 |
70 | #define EMI1_SLOT2 1 | |
71 | #define EMI1_SLOT3 2 | |
72 | #define EMI1_SLOT4 3 | |
73 | #define EMI1_SLOT5 4 | |
74 | #define EMI1_SLOT6 5 | |
75 | #define EMI2 6 | |
d7b76e89 | 76 | #define SFP_TX 0 |
e60476a0 PK |
77 | |
78 | static const char * const mdio_names[] = { | |
44937214 PK |
79 | "LS2080A_QDS_MDIO0", |
80 | "LS2080A_QDS_MDIO1", | |
81 | "LS2080A_QDS_MDIO2", | |
82 | "LS2080A_QDS_MDIO3", | |
83 | "LS2080A_QDS_MDIO4", | |
84 | "LS2080A_QDS_MDIO5", | |
e60476a0 PK |
85 | DEFAULT_WRIOP_MDIO2_NAME, |
86 | }; | |
87 | ||
44937214 | 88 | struct ls2080a_qds_mdio { |
e60476a0 PK |
89 | u8 muxval; |
90 | struct mii_dev *realbus; | |
91 | }; | |
92 | ||
cf7ee6c4 PK |
93 | static void sgmii_configure_repeater(int serdes_port) |
94 | { | |
95 | struct mii_dev *bus; | |
96 | uint8_t a = 0xf; | |
97 | int i, j, ret; | |
98 | int dpmac_id = 0, dpmac, mii_bus = 0; | |
99 | unsigned short value; | |
44937214 | 100 | char dev[2][20] = {"LS2080A_QDS_MDIO0", "LS2080A_QDS_MDIO3"}; |
cf7ee6c4 PK |
101 | uint8_t i2c_addr[] = {0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x60}; |
102 | ||
103 | uint8_t ch_a_eq[] = {0x1, 0x2, 0x3, 0x7}; | |
104 | uint8_t ch_a_ctl2[] = {0x81, 0x82, 0x83, 0x84}; | |
105 | uint8_t ch_b_eq[] = {0x1, 0x2, 0x3, 0x7}; | |
106 | uint8_t ch_b_ctl2[] = {0x81, 0x82, 0x83, 0x84}; | |
107 | ||
108 | int *riser_phy_addr = &xqsgii_riser_phy_addr[0]; | |
109 | ||
110 | /* Set I2c to Slot 1 */ | |
111 | i2c_write(0x77, 0, 0, &a, 1); | |
112 | ||
113 | for (dpmac = 0; dpmac < 8; dpmac++) { | |
114 | /* Check the PHY status */ | |
115 | switch (serdes_port) { | |
116 | case 1: | |
117 | mii_bus = 0; | |
118 | dpmac_id = dpmac + 1; | |
119 | break; | |
120 | case 2: | |
121 | mii_bus = 1; | |
122 | dpmac_id = dpmac + 9; | |
123 | a = 0xb; | |
124 | i2c_write(0x76, 0, 0, &a, 1); | |
125 | break; | |
126 | } | |
127 | ||
128 | ret = miiphy_set_current_dev(dev[mii_bus]); | |
129 | if (ret > 0) | |
130 | goto error; | |
131 | ||
132 | bus = mdio_get_current_dev(); | |
133 | debug("Reading from bus %s\n", bus->name); | |
134 | ||
135 | ret = miiphy_write(dev[mii_bus], riser_phy_addr[dpmac], 0x1f, | |
136 | 3); | |
137 | if (ret > 0) | |
138 | goto error; | |
139 | ||
140 | mdelay(10); | |
141 | ret = miiphy_read(dev[mii_bus], riser_phy_addr[dpmac], 0x11, | |
142 | &value); | |
143 | if (ret > 0) | |
144 | goto error; | |
145 | ||
146 | mdelay(10); | |
147 | ||
c435a7c8 | 148 | if ((value & 0xfff) == 0x401) { |
cf7ee6c4 | 149 | printf("DPMAC %d:PHY is ..... Configured\n", dpmac_id); |
c435a7c8 SX |
150 | miiphy_write(dev[mii_bus], riser_phy_addr[dpmac], |
151 | 0x1f, 0); | |
cf7ee6c4 PK |
152 | continue; |
153 | } | |
154 | ||
155 | for (i = 0; i < 4; i++) { | |
156 | for (j = 0; j < 4; j++) { | |
157 | a = 0x18; | |
158 | i2c_write(i2c_addr[dpmac], 6, 1, &a, 1); | |
159 | a = 0x38; | |
160 | i2c_write(i2c_addr[dpmac], 4, 1, &a, 1); | |
161 | a = 0x4; | |
162 | i2c_write(i2c_addr[dpmac], 8, 1, &a, 1); | |
163 | ||
164 | i2c_write(i2c_addr[dpmac], 0xf, 1, | |
165 | &ch_a_eq[i], 1); | |
166 | i2c_write(i2c_addr[dpmac], 0x11, 1, | |
167 | &ch_a_ctl2[j], 1); | |
168 | ||
169 | i2c_write(i2c_addr[dpmac], 0x16, 1, | |
170 | &ch_b_eq[i], 1); | |
171 | i2c_write(i2c_addr[dpmac], 0x18, 1, | |
172 | &ch_b_ctl2[j], 1); | |
173 | ||
174 | a = 0x14; | |
175 | i2c_write(i2c_addr[dpmac], 0x23, 1, &a, 1); | |
176 | a = 0xb5; | |
177 | i2c_write(i2c_addr[dpmac], 0x2d, 1, &a, 1); | |
178 | a = 0x20; | |
179 | i2c_write(i2c_addr[dpmac], 4, 1, &a, 1); | |
180 | mdelay(100); | |
181 | ret = miiphy_read(dev[mii_bus], | |
182 | riser_phy_addr[dpmac], | |
183 | 0x11, &value); | |
184 | if (ret > 0) | |
185 | goto error; | |
186 | ||
c435a7c8 | 187 | mdelay(100); |
cf7ee6c4 PK |
188 | ret = miiphy_read(dev[mii_bus], |
189 | riser_phy_addr[dpmac], | |
190 | 0x11, &value); | |
191 | if (ret > 0) | |
192 | goto error; | |
cf7ee6c4 | 193 | |
c435a7c8 | 194 | if ((value & 0xfff) == 0x401) { |
cf7ee6c4 PK |
195 | printf("DPMAC %d :PHY is configured ", |
196 | dpmac_id); | |
197 | printf("after setting repeater 0x%x\n", | |
198 | value); | |
199 | i = 5; | |
200 | j = 5; | |
c435a7c8 | 201 | } else { |
cf7ee6c4 PK |
202 | printf("DPMAC %d :PHY is failed to ", |
203 | dpmac_id); | |
204 | printf("configure the repeater 0x%x\n", | |
205 | value); | |
206 | } | |
c435a7c8 | 207 | } |
cf7ee6c4 | 208 | } |
c435a7c8 | 209 | miiphy_write(dev[mii_bus], riser_phy_addr[dpmac], 0x1f, 0); |
cf7ee6c4 PK |
210 | } |
211 | error: | |
212 | if (ret) | |
213 | printf("DPMAC %d ..... FAILED to configure PHY\n", dpmac_id); | |
214 | return; | |
215 | } | |
216 | ||
217 | static void qsgmii_configure_repeater(int dpmac) | |
218 | { | |
219 | uint8_t a = 0xf; | |
220 | int i, j; | |
221 | int i2c_phy_addr = 0; | |
222 | int phy_addr = 0; | |
223 | int i2c_addr[] = {0x58, 0x59, 0x5a, 0x5b}; | |
224 | ||
225 | uint8_t ch_a_eq[] = {0x1, 0x2, 0x3, 0x7}; | |
226 | uint8_t ch_a_ctl2[] = {0x81, 0x82, 0x83, 0x84}; | |
227 | uint8_t ch_b_eq[] = {0x1, 0x2, 0x3, 0x7}; | |
228 | uint8_t ch_b_ctl2[] = {0x81, 0x82, 0x83, 0x84}; | |
229 | ||
44937214 | 230 | const char *dev = "LS2080A_QDS_MDIO0"; |
cf7ee6c4 PK |
231 | int ret = 0; |
232 | unsigned short value; | |
233 | ||
234 | /* Set I2c to Slot 1 */ | |
235 | i2c_write(0x77, 0, 0, &a, 1); | |
236 | ||
237 | switch (dpmac) { | |
238 | case 1: | |
239 | case 2: | |
240 | case 3: | |
241 | case 4: | |
242 | i2c_phy_addr = i2c_addr[0]; | |
243 | phy_addr = 0; | |
244 | break; | |
245 | ||
246 | case 5: | |
247 | case 6: | |
248 | case 7: | |
249 | case 8: | |
250 | i2c_phy_addr = i2c_addr[1]; | |
251 | phy_addr = 4; | |
252 | break; | |
253 | ||
254 | case 9: | |
255 | case 10: | |
256 | case 11: | |
257 | case 12: | |
258 | i2c_phy_addr = i2c_addr[2]; | |
259 | phy_addr = 8; | |
260 | break; | |
261 | ||
262 | case 13: | |
263 | case 14: | |
264 | case 15: | |
265 | case 16: | |
266 | i2c_phy_addr = i2c_addr[3]; | |
267 | phy_addr = 0xc; | |
268 | break; | |
269 | } | |
270 | ||
271 | /* Check the PHY status */ | |
272 | ret = miiphy_set_current_dev(dev); | |
273 | ret = miiphy_write(dev, phy_addr, 0x1f, 3); | |
274 | mdelay(10); | |
275 | ret = miiphy_read(dev, phy_addr, 0x11, &value); | |
276 | mdelay(10); | |
277 | ret = miiphy_read(dev, phy_addr, 0x11, &value); | |
278 | mdelay(10); | |
279 | if ((value & 0xf) == 0xf) { | |
280 | printf("DPMAC %d :PHY is ..... Configured\n", dpmac); | |
281 | return; | |
282 | } | |
283 | ||
284 | for (i = 0; i < 4; i++) { | |
285 | for (j = 0; j < 4; j++) { | |
286 | a = 0x18; | |
287 | i2c_write(i2c_phy_addr, 6, 1, &a, 1); | |
288 | a = 0x38; | |
289 | i2c_write(i2c_phy_addr, 4, 1, &a, 1); | |
290 | a = 0x4; | |
291 | i2c_write(i2c_phy_addr, 8, 1, &a, 1); | |
292 | ||
293 | i2c_write(i2c_phy_addr, 0xf, 1, &ch_a_eq[i], 1); | |
294 | i2c_write(i2c_phy_addr, 0x11, 1, &ch_a_ctl2[j], 1); | |
295 | ||
296 | i2c_write(i2c_phy_addr, 0x16, 1, &ch_b_eq[i], 1); | |
297 | i2c_write(i2c_phy_addr, 0x18, 1, &ch_b_ctl2[j], 1); | |
298 | ||
299 | a = 0x14; | |
300 | i2c_write(i2c_phy_addr, 0x23, 1, &a, 1); | |
301 | a = 0xb5; | |
302 | i2c_write(i2c_phy_addr, 0x2d, 1, &a, 1); | |
303 | a = 0x20; | |
304 | i2c_write(i2c_phy_addr, 4, 1, &a, 1); | |
305 | mdelay(100); | |
306 | ret = miiphy_read(dev, phy_addr, 0x11, &value); | |
307 | if (ret > 0) | |
308 | goto error; | |
309 | mdelay(1); | |
310 | ret = miiphy_read(dev, phy_addr, 0x11, &value); | |
311 | if (ret > 0) | |
312 | goto error; | |
313 | mdelay(10); | |
314 | if ((value & 0xf) == 0xf) { | |
315 | printf("DPMAC %d :PHY is ..... Configured\n", | |
316 | dpmac); | |
317 | return; | |
318 | } | |
319 | } | |
320 | } | |
321 | error: | |
322 | printf("DPMAC %d :PHY ..... FAILED to configure PHY\n", dpmac); | |
323 | return; | |
324 | } | |
325 | ||
44937214 | 326 | static const char *ls2080a_qds_mdio_name_for_muxval(u8 muxval) |
e60476a0 PK |
327 | { |
328 | return mdio_names[muxval]; | |
329 | } | |
330 | ||
331 | struct mii_dev *mii_dev_for_muxval(u8 muxval) | |
332 | { | |
333 | struct mii_dev *bus; | |
44937214 | 334 | const char *name = ls2080a_qds_mdio_name_for_muxval(muxval); |
e60476a0 PK |
335 | |
336 | if (!name) { | |
337 | printf("No bus for muxval %x\n", muxval); | |
338 | return NULL; | |
339 | } | |
340 | ||
341 | bus = miiphy_get_dev_by_name(name); | |
342 | ||
343 | if (!bus) { | |
344 | printf("No bus by name %s\n", name); | |
345 | return NULL; | |
346 | } | |
347 | ||
348 | return bus; | |
349 | } | |
350 | ||
44937214 | 351 | static void ls2080a_qds_enable_SFP_TX(u8 muxval) |
e60476a0 PK |
352 | { |
353 | u8 brdcfg9; | |
354 | ||
355 | brdcfg9 = QIXIS_READ(brdcfg[9]); | |
356 | brdcfg9 &= ~BRDCFG9_SFPTX_MASK; | |
357 | brdcfg9 |= (muxval << BRDCFG9_SFPTX_SHIFT); | |
358 | QIXIS_WRITE(brdcfg[9], brdcfg9); | |
359 | } | |
360 | ||
44937214 | 361 | static void ls2080a_qds_mux_mdio(u8 muxval) |
e60476a0 PK |
362 | { |
363 | u8 brdcfg4; | |
364 | ||
365 | if (muxval <= 5) { | |
366 | brdcfg4 = QIXIS_READ(brdcfg[4]); | |
367 | brdcfg4 &= ~BRDCFG4_EMISEL_MASK; | |
368 | brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT); | |
369 | QIXIS_WRITE(brdcfg[4], brdcfg4); | |
370 | } | |
371 | } | |
372 | ||
44937214 | 373 | static int ls2080a_qds_mdio_read(struct mii_dev *bus, int addr, |
e60476a0 PK |
374 | int devad, int regnum) |
375 | { | |
44937214 | 376 | struct ls2080a_qds_mdio *priv = bus->priv; |
e60476a0 | 377 | |
44937214 | 378 | ls2080a_qds_mux_mdio(priv->muxval); |
e60476a0 PK |
379 | |
380 | return priv->realbus->read(priv->realbus, addr, devad, regnum); | |
381 | } | |
382 | ||
44937214 | 383 | static int ls2080a_qds_mdio_write(struct mii_dev *bus, int addr, int devad, |
e60476a0 PK |
384 | int regnum, u16 value) |
385 | { | |
44937214 | 386 | struct ls2080a_qds_mdio *priv = bus->priv; |
e60476a0 | 387 | |
44937214 | 388 | ls2080a_qds_mux_mdio(priv->muxval); |
e60476a0 PK |
389 | |
390 | return priv->realbus->write(priv->realbus, addr, devad, regnum, value); | |
391 | } | |
392 | ||
44937214 | 393 | static int ls2080a_qds_mdio_reset(struct mii_dev *bus) |
e60476a0 | 394 | { |
44937214 | 395 | struct ls2080a_qds_mdio *priv = bus->priv; |
e60476a0 PK |
396 | |
397 | return priv->realbus->reset(priv->realbus); | |
398 | } | |
399 | ||
44937214 | 400 | static int ls2080a_qds_mdio_init(char *realbusname, u8 muxval) |
e60476a0 | 401 | { |
44937214 | 402 | struct ls2080a_qds_mdio *pmdio; |
e60476a0 PK |
403 | struct mii_dev *bus = mdio_alloc(); |
404 | ||
405 | if (!bus) { | |
44937214 | 406 | printf("Failed to allocate ls2080a_qds MDIO bus\n"); |
e60476a0 PK |
407 | return -1; |
408 | } | |
409 | ||
410 | pmdio = malloc(sizeof(*pmdio)); | |
411 | if (!pmdio) { | |
44937214 | 412 | printf("Failed to allocate ls2080a_qds private data\n"); |
e60476a0 PK |
413 | free(bus); |
414 | return -1; | |
415 | } | |
416 | ||
44937214 PK |
417 | bus->read = ls2080a_qds_mdio_read; |
418 | bus->write = ls2080a_qds_mdio_write; | |
419 | bus->reset = ls2080a_qds_mdio_reset; | |
192bc694 | 420 | strcpy(bus->name, ls2080a_qds_mdio_name_for_muxval(muxval)); |
e60476a0 PK |
421 | |
422 | pmdio->realbus = miiphy_get_dev_by_name(realbusname); | |
423 | ||
424 | if (!pmdio->realbus) { | |
425 | printf("No bus with name %s\n", realbusname); | |
426 | free(bus); | |
427 | free(pmdio); | |
428 | return -1; | |
429 | } | |
430 | ||
431 | pmdio->muxval = muxval; | |
432 | bus->priv = pmdio; | |
433 | ||
434 | return mdio_register(bus); | |
435 | } | |
436 | ||
437 | /* | |
438 | * Initialize the dpmac_info array. | |
439 | * | |
440 | */ | |
441 | static void initialize_dpmac_to_slot(void) | |
442 | { | |
443 | struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; | |
444 | int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) & | |
445 | FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK) | |
446 | >> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT; | |
447 | int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) & | |
448 | FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK) | |
449 | >> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT; | |
450 | ||
cf7ee6c4 | 451 | char *env_hwconfig; |
00caae6d | 452 | env_hwconfig = env_get("hwconfig"); |
e60476a0 PK |
453 | |
454 | switch (serdes1_prtcl) { | |
cf7ee6c4 PK |
455 | case 0x07: |
456 | case 0x09: | |
457 | case 0x33: | |
458 | printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n", | |
459 | serdes1_prtcl); | |
460 | lane_to_slot_fsm1[0] = EMI1_SLOT1; | |
461 | lane_to_slot_fsm1[1] = EMI1_SLOT1; | |
462 | lane_to_slot_fsm1[2] = EMI1_SLOT1; | |
463 | lane_to_slot_fsm1[3] = EMI1_SLOT1; | |
464 | if (hwconfig_f("xqsgmii", env_hwconfig)) { | |
465 | lane_to_slot_fsm1[4] = EMI1_SLOT1; | |
466 | lane_to_slot_fsm1[5] = EMI1_SLOT1; | |
467 | lane_to_slot_fsm1[6] = EMI1_SLOT1; | |
468 | lane_to_slot_fsm1[7] = EMI1_SLOT1; | |
469 | } else { | |
470 | lane_to_slot_fsm1[4] = EMI1_SLOT2; | |
471 | lane_to_slot_fsm1[5] = EMI1_SLOT2; | |
472 | lane_to_slot_fsm1[6] = EMI1_SLOT2; | |
473 | lane_to_slot_fsm1[7] = EMI1_SLOT2; | |
474 | } | |
475 | break; | |
476 | ||
fc35adde PJ |
477 | case 0x39: |
478 | printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n", | |
479 | serdes1_prtcl); | |
480 | if (hwconfig_f("xqsgmii", env_hwconfig)) { | |
481 | lane_to_slot_fsm1[0] = EMI1_SLOT3; | |
482 | lane_to_slot_fsm1[1] = EMI1_SLOT3; | |
483 | lane_to_slot_fsm1[2] = EMI1_SLOT3; | |
484 | lane_to_slot_fsm1[3] = EMI_NONE; | |
485 | } else { | |
486 | lane_to_slot_fsm1[0] = EMI_NONE; | |
487 | lane_to_slot_fsm1[1] = EMI_NONE; | |
488 | lane_to_slot_fsm1[2] = EMI_NONE; | |
489 | lane_to_slot_fsm1[3] = EMI_NONE; | |
490 | } | |
491 | lane_to_slot_fsm1[4] = EMI1_SLOT3; | |
492 | lane_to_slot_fsm1[5] = EMI1_SLOT3; | |
493 | lane_to_slot_fsm1[6] = EMI1_SLOT3; | |
494 | lane_to_slot_fsm1[7] = EMI_NONE; | |
495 | break; | |
496 | ||
497 | case 0x4D: | |
498 | printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n", | |
499 | serdes1_prtcl); | |
500 | if (hwconfig_f("xqsgmii", env_hwconfig)) { | |
501 | lane_to_slot_fsm1[0] = EMI1_SLOT3; | |
502 | lane_to_slot_fsm1[1] = EMI1_SLOT3; | |
503 | lane_to_slot_fsm1[2] = EMI_NONE; | |
504 | lane_to_slot_fsm1[3] = EMI_NONE; | |
505 | } else { | |
506 | lane_to_slot_fsm1[0] = EMI_NONE; | |
507 | lane_to_slot_fsm1[1] = EMI_NONE; | |
508 | lane_to_slot_fsm1[2] = EMI_NONE; | |
509 | lane_to_slot_fsm1[3] = EMI_NONE; | |
510 | } | |
511 | lane_to_slot_fsm1[4] = EMI1_SLOT3; | |
512 | lane_to_slot_fsm1[5] = EMI1_SLOT3; | |
513 | lane_to_slot_fsm1[6] = EMI_NONE; | |
514 | lane_to_slot_fsm1[7] = EMI_NONE; | |
515 | break; | |
516 | ||
e60476a0 | 517 | case 0x2A: |
fc35adde PJ |
518 | case 0x4B: |
519 | case 0x4C: | |
cf7ee6c4 | 520 | printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n", |
e60476a0 PK |
521 | serdes1_prtcl); |
522 | break; | |
523 | default: | |
25af4137 PK |
524 | printf("%s qds: WRIOP: Unsupported SerDes1 Protocol 0x%02x\n", |
525 | __func__, serdes1_prtcl); | |
e60476a0 PK |
526 | break; |
527 | } | |
528 | ||
529 | switch (serdes2_prtcl) { | |
530 | case 0x07: | |
531 | case 0x08: | |
cf7ee6c4 | 532 | case 0x09: |
94540c56 | 533 | case 0x49: |
cf7ee6c4 | 534 | printf("qds: WRIOP: Supported SerDes2 Protocol 0x%02x\n", |
e60476a0 PK |
535 | serdes2_prtcl); |
536 | lane_to_slot_fsm2[0] = EMI1_SLOT4; | |
537 | lane_to_slot_fsm2[1] = EMI1_SLOT4; | |
538 | lane_to_slot_fsm2[2] = EMI1_SLOT4; | |
539 | lane_to_slot_fsm2[3] = EMI1_SLOT4; | |
cf7ee6c4 PK |
540 | |
541 | if (hwconfig_f("xqsgmii", env_hwconfig)) { | |
542 | lane_to_slot_fsm2[4] = EMI1_SLOT4; | |
543 | lane_to_slot_fsm2[5] = EMI1_SLOT4; | |
544 | lane_to_slot_fsm2[6] = EMI1_SLOT4; | |
545 | lane_to_slot_fsm2[7] = EMI1_SLOT4; | |
546 | } else { | |
547 | /* No MDIO physical connection */ | |
548 | lane_to_slot_fsm2[4] = EMI1_SLOT6; | |
549 | lane_to_slot_fsm2[5] = EMI1_SLOT6; | |
550 | lane_to_slot_fsm2[6] = EMI1_SLOT6; | |
551 | lane_to_slot_fsm2[7] = EMI1_SLOT6; | |
552 | } | |
e60476a0 | 553 | break; |
fc35adde PJ |
554 | |
555 | case 0x47: | |
556 | printf("qds: WRIOP: Supported SerDes2 Protocol 0x%02x\n", | |
557 | serdes2_prtcl); | |
558 | lane_to_slot_fsm2[0] = EMI_NONE; | |
559 | lane_to_slot_fsm2[1] = EMI1_SLOT5; | |
560 | lane_to_slot_fsm2[2] = EMI1_SLOT5; | |
561 | lane_to_slot_fsm2[3] = EMI1_SLOT5; | |
562 | ||
563 | if (hwconfig_f("xqsgmii", env_hwconfig)) { | |
564 | lane_to_slot_fsm2[4] = EMI_NONE; | |
565 | lane_to_slot_fsm2[5] = EMI1_SLOT5; | |
566 | lane_to_slot_fsm2[6] = EMI1_SLOT5; | |
567 | lane_to_slot_fsm2[7] = EMI1_SLOT5; | |
568 | } | |
569 | break; | |
570 | ||
571 | case 0x57: | |
572 | printf("qds: WRIOP: Supported SerDes2 Protocol 0x%02x\n", | |
573 | serdes2_prtcl); | |
574 | if (hwconfig_f("xqsgmii", env_hwconfig)) { | |
575 | lane_to_slot_fsm2[0] = EMI_NONE; | |
576 | lane_to_slot_fsm2[1] = EMI_NONE; | |
577 | lane_to_slot_fsm2[2] = EMI_NONE; | |
578 | lane_to_slot_fsm2[3] = EMI_NONE; | |
579 | } | |
580 | lane_to_slot_fsm2[4] = EMI_NONE; | |
581 | lane_to_slot_fsm2[5] = EMI_NONE; | |
582 | lane_to_slot_fsm2[6] = EMI1_SLOT5; | |
583 | lane_to_slot_fsm2[7] = EMI1_SLOT5; | |
584 | break; | |
585 | ||
e60476a0 | 586 | default: |
25af4137 PK |
587 | printf(" %s qds: WRIOP: Unsupported SerDes2 Protocol 0x%02x\n", |
588 | __func__ , serdes2_prtcl); | |
e60476a0 PK |
589 | break; |
590 | } | |
591 | } | |
592 | ||
44937214 | 593 | void ls2080a_handle_phy_interface_sgmii(int dpmac_id) |
e60476a0 PK |
594 | { |
595 | int lane, slot; | |
596 | struct mii_dev *bus; | |
597 | struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; | |
598 | int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) & | |
599 | FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK) | |
600 | >> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT; | |
601 | int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) & | |
602 | FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK) | |
603 | >> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT; | |
604 | ||
cf7ee6c4 | 605 | int *riser_phy_addr; |
00caae6d | 606 | char *env_hwconfig = env_get("hwconfig"); |
cf7ee6c4 PK |
607 | |
608 | if (hwconfig_f("xqsgmii", env_hwconfig)) | |
609 | riser_phy_addr = &xqsgii_riser_phy_addr[0]; | |
610 | else | |
611 | riser_phy_addr = &sgmii_riser_phy_addr[0]; | |
612 | ||
613 | if (dpmac_id > WRIOP1_DPMAC9) | |
614 | goto serdes2; | |
615 | ||
e60476a0 | 616 | switch (serdes1_prtcl) { |
cf7ee6c4 | 617 | case 0x07: |
fc35adde PJ |
618 | case 0x39: |
619 | case 0x4D: | |
620 | lane = serdes_get_first_lane(FSL_SRDS_1, SGMII1 + dpmac_id - 1); | |
cf7ee6c4 | 621 | |
cf7ee6c4 PK |
622 | slot = lane_to_slot_fsm1[lane]; |
623 | ||
624 | switch (++slot) { | |
625 | case 1: | |
626 | /* Slot housing a SGMII riser card? */ | |
627 | wriop_set_phy_address(dpmac_id, | |
628 | riser_phy_addr[dpmac_id - 1]); | |
629 | dpmac_info[dpmac_id].board_mux = EMI1_SLOT1; | |
630 | bus = mii_dev_for_muxval(EMI1_SLOT1); | |
631 | wriop_set_mdio(dpmac_id, bus); | |
cf7ee6c4 PK |
632 | break; |
633 | case 2: | |
634 | /* Slot housing a SGMII riser card? */ | |
635 | wriop_set_phy_address(dpmac_id, | |
636 | riser_phy_addr[dpmac_id - 1]); | |
637 | dpmac_info[dpmac_id].board_mux = EMI1_SLOT2; | |
638 | bus = mii_dev_for_muxval(EMI1_SLOT2); | |
639 | wriop_set_mdio(dpmac_id, bus); | |
cf7ee6c4 PK |
640 | break; |
641 | case 3: | |
fc35adde PJ |
642 | if (slot == EMI_NONE) |
643 | return; | |
644 | if (serdes1_prtcl == 0x39) { | |
645 | wriop_set_phy_address(dpmac_id, | |
646 | riser_phy_addr[dpmac_id - 2]); | |
647 | if (dpmac_id >= 6 && hwconfig_f("xqsgmii", | |
648 | env_hwconfig)) | |
649 | wriop_set_phy_address(dpmac_id, | |
650 | riser_phy_addr[dpmac_id - 3]); | |
651 | } else { | |
652 | wriop_set_phy_address(dpmac_id, | |
653 | riser_phy_addr[dpmac_id - 2]); | |
654 | if (dpmac_id >= 7 && hwconfig_f("xqsgmii", | |
655 | env_hwconfig)) | |
656 | wriop_set_phy_address(dpmac_id, | |
657 | riser_phy_addr[dpmac_id - 3]); | |
658 | } | |
659 | dpmac_info[dpmac_id].board_mux = EMI1_SLOT3; | |
660 | bus = mii_dev_for_muxval(EMI1_SLOT3); | |
661 | wriop_set_mdio(dpmac_id, bus); | |
cf7ee6c4 PK |
662 | break; |
663 | case 4: | |
664 | break; | |
665 | case 5: | |
666 | break; | |
667 | case 6: | |
668 | break; | |
669 | } | |
670 | break; | |
671 | default: | |
25af4137 PK |
672 | printf("%s qds: WRIOP: Unsupported SerDes1 Protocol 0x%02x\n", |
673 | __func__ , serdes1_prtcl); | |
cf7ee6c4 | 674 | break; |
e60476a0 PK |
675 | } |
676 | ||
cf7ee6c4 | 677 | serdes2: |
e60476a0 PK |
678 | switch (serdes2_prtcl) { |
679 | case 0x07: | |
680 | case 0x08: | |
94540c56 | 681 | case 0x49: |
fc35adde PJ |
682 | case 0x47: |
683 | case 0x57: | |
e60476a0 PK |
684 | lane = serdes_get_first_lane(FSL_SRDS_2, SGMII9 + |
685 | (dpmac_id - 9)); | |
686 | slot = lane_to_slot_fsm2[lane]; | |
687 | ||
688 | switch (++slot) { | |
689 | case 1: | |
690 | break; | |
691 | case 3: | |
692 | break; | |
693 | case 4: | |
694 | /* Slot housing a SGMII riser card? */ | |
695 | wriop_set_phy_address(dpmac_id, | |
696 | riser_phy_addr[dpmac_id - 9]); | |
697 | dpmac_info[dpmac_id].board_mux = EMI1_SLOT4; | |
698 | bus = mii_dev_for_muxval(EMI1_SLOT4); | |
699 | wriop_set_mdio(dpmac_id, bus); | |
e60476a0 PK |
700 | break; |
701 | case 5: | |
fc35adde PJ |
702 | if (slot == EMI_NONE) |
703 | return; | |
704 | if (serdes2_prtcl == 0x47) { | |
705 | wriop_set_phy_address(dpmac_id, | |
706 | riser_phy_addr[dpmac_id - 10]); | |
707 | if (dpmac_id >= 14 && hwconfig_f("xqsgmii", | |
708 | env_hwconfig)) | |
709 | wriop_set_phy_address(dpmac_id, | |
710 | riser_phy_addr[dpmac_id - 11]); | |
711 | } else { | |
712 | wriop_set_phy_address(dpmac_id, | |
713 | riser_phy_addr[dpmac_id - 11]); | |
714 | } | |
715 | dpmac_info[dpmac_id].board_mux = EMI1_SLOT5; | |
716 | bus = mii_dev_for_muxval(EMI1_SLOT5); | |
717 | wriop_set_mdio(dpmac_id, bus); | |
718 | break; | |
e60476a0 PK |
719 | case 6: |
720 | /* Slot housing a SGMII riser card? */ | |
721 | wriop_set_phy_address(dpmac_id, | |
722 | riser_phy_addr[dpmac_id - 13]); | |
723 | dpmac_info[dpmac_id].board_mux = EMI1_SLOT6; | |
724 | bus = mii_dev_for_muxval(EMI1_SLOT6); | |
725 | wriop_set_mdio(dpmac_id, bus); | |
726 | break; | |
727 | } | |
728 | break; | |
729 | default: | |
25af4137 PK |
730 | printf("%s qds: WRIOP: Unsupported SerDes2 Protocol 0x%02x\n", |
731 | __func__, serdes2_prtcl); | |
e60476a0 PK |
732 | break; |
733 | } | |
734 | } | |
cf7ee6c4 | 735 | |
44937214 | 736 | void ls2080a_handle_phy_interface_qsgmii(int dpmac_id) |
cf7ee6c4 PK |
737 | { |
738 | int lane = 0, slot; | |
739 | struct mii_dev *bus; | |
740 | struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; | |
741 | int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) & | |
742 | FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK) | |
743 | >> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT; | |
744 | ||
745 | switch (serdes1_prtcl) { | |
746 | case 0x33: | |
747 | switch (dpmac_id) { | |
748 | case 1: | |
749 | case 2: | |
750 | case 3: | |
751 | case 4: | |
752 | lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_A); | |
753 | break; | |
754 | case 5: | |
755 | case 6: | |
756 | case 7: | |
757 | case 8: | |
758 | lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_B); | |
759 | break; | |
760 | case 9: | |
761 | case 10: | |
762 | case 11: | |
763 | case 12: | |
764 | lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_C); | |
765 | break; | |
766 | case 13: | |
767 | case 14: | |
768 | case 15: | |
769 | case 16: | |
770 | lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_D); | |
771 | break; | |
772 | } | |
773 | ||
774 | slot = lane_to_slot_fsm1[lane]; | |
775 | ||
776 | switch (++slot) { | |
777 | case 1: | |
778 | /* Slot housing a QSGMII riser card? */ | |
779 | wriop_set_phy_address(dpmac_id, dpmac_id - 1); | |
780 | dpmac_info[dpmac_id].board_mux = EMI1_SLOT1; | |
781 | bus = mii_dev_for_muxval(EMI1_SLOT1); | |
782 | wriop_set_mdio(dpmac_id, bus); | |
cf7ee6c4 PK |
783 | break; |
784 | case 3: | |
785 | break; | |
786 | case 4: | |
787 | break; | |
788 | case 5: | |
789 | break; | |
790 | case 6: | |
791 | break; | |
792 | } | |
793 | break; | |
794 | default: | |
795 | printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n", | |
796 | serdes1_prtcl); | |
797 | break; | |
798 | } | |
799 | ||
800 | qsgmii_configure_repeater(dpmac_id); | |
801 | } | |
802 | ||
44937214 | 803 | void ls2080a_handle_phy_interface_xsgmii(int i) |
e60476a0 PK |
804 | { |
805 | struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; | |
806 | int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) & | |
807 | FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK) | |
808 | >> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT; | |
809 | ||
810 | switch (serdes1_prtcl) { | |
811 | case 0x2A: | |
fc35adde PJ |
812 | case 0x4B: |
813 | case 0x4C: | |
e60476a0 | 814 | /* |
a187559e | 815 | * XFI does not need a PHY to work, but to avoid U-Boot use |
e60476a0 PK |
816 | * default PHY address which is zero to a MAC when it found |
817 | * a MAC has no PHY address, we give a PHY address to XFI | |
818 | * MAC, and should not use a real XAUI PHY address, since | |
819 | * MDIO can access it successfully, and then MDIO thinks | |
820 | * the XAUI card is used for the XFI MAC, which will cause | |
821 | * error. | |
822 | */ | |
823 | wriop_set_phy_address(i, i + 4); | |
44937214 | 824 | ls2080a_qds_enable_SFP_TX(SFP_TX); |
e60476a0 PK |
825 | |
826 | break; | |
827 | default: | |
828 | printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n", | |
829 | serdes1_prtcl); | |
830 | break; | |
831 | } | |
832 | } | |
833 | #endif | |
834 | ||
835 | int board_eth_init(bd_t *bis) | |
836 | { | |
837 | int error; | |
1f55a938 | 838 | #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) |
cf7ee6c4 PK |
839 | struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; |
840 | int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) & | |
841 | FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK) | |
842 | >> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT; | |
843 | int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) & | |
844 | FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK) | |
845 | >> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT; | |
846 | ||
e60476a0 PK |
847 | struct memac_mdio_info *memac_mdio0_info; |
848 | struct memac_mdio_info *memac_mdio1_info; | |
849 | unsigned int i; | |
cf7ee6c4 PK |
850 | char *env_hwconfig; |
851 | ||
00caae6d | 852 | env_hwconfig = env_get("hwconfig"); |
e60476a0 PK |
853 | |
854 | initialize_dpmac_to_slot(); | |
855 | ||
856 | memac_mdio0_info = (struct memac_mdio_info *)malloc( | |
857 | sizeof(struct memac_mdio_info)); | |
858 | memac_mdio0_info->regs = | |
859 | (struct memac_mdio_controller *) | |
860 | CONFIG_SYS_FSL_WRIOP1_MDIO1; | |
861 | memac_mdio0_info->name = DEFAULT_WRIOP_MDIO1_NAME; | |
862 | ||
863 | /* Register the real MDIO1 bus */ | |
864 | fm_memac_mdio_init(bis, memac_mdio0_info); | |
865 | ||
866 | memac_mdio1_info = (struct memac_mdio_info *)malloc( | |
867 | sizeof(struct memac_mdio_info)); | |
868 | memac_mdio1_info->regs = | |
869 | (struct memac_mdio_controller *) | |
870 | CONFIG_SYS_FSL_WRIOP1_MDIO2; | |
871 | memac_mdio1_info->name = DEFAULT_WRIOP_MDIO2_NAME; | |
872 | ||
873 | /* Register the real MDIO2 bus */ | |
874 | fm_memac_mdio_init(bis, memac_mdio1_info); | |
875 | ||
876 | /* Register the muxing front-ends to the MDIO buses */ | |
44937214 PK |
877 | ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT1); |
878 | ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT2); | |
879 | ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT3); | |
880 | ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT4); | |
881 | ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT5); | |
882 | ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT6); | |
e60476a0 | 883 | |
44937214 | 884 | ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO2_NAME, EMI2); |
e60476a0 PK |
885 | |
886 | for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) { | |
887 | switch (wriop_get_enet_if(i)) { | |
888 | case PHY_INTERFACE_MODE_QSGMII: | |
44937214 | 889 | ls2080a_handle_phy_interface_qsgmii(i); |
e60476a0 PK |
890 | break; |
891 | case PHY_INTERFACE_MODE_SGMII: | |
44937214 | 892 | ls2080a_handle_phy_interface_sgmii(i); |
e60476a0 PK |
893 | break; |
894 | case PHY_INTERFACE_MODE_XGMII: | |
44937214 | 895 | ls2080a_handle_phy_interface_xsgmii(i); |
e60476a0 PK |
896 | break; |
897 | default: | |
898 | break; | |
cf7ee6c4 PK |
899 | |
900 | if (i == 16) | |
901 | i = NUM_WRIOP_PORTS; | |
e60476a0 PK |
902 | } |
903 | } | |
904 | ||
905 | error = cpu_eth_init(bis); | |
cf7ee6c4 PK |
906 | |
907 | if (hwconfig_f("xqsgmii", env_hwconfig)) { | |
908 | if (serdes1_prtcl == 0x7) | |
909 | sgmii_configure_repeater(1); | |
910 | if (serdes2_prtcl == 0x7 || serdes2_prtcl == 0x8 || | |
911 | serdes2_prtcl == 0x49) | |
912 | sgmii_configure_repeater(2); | |
913 | } | |
e60476a0 PK |
914 | #endif |
915 | error = pci_eth_init(bis); | |
916 | return error; | |
917 | } | |
cf7ee6c4 | 918 | |
33a8991a BP |
919 | #if defined(CONFIG_RESET_PHY_R) |
920 | void reset_phy(void) | |
921 | { | |
922 | mc_env_boot(); | |
923 | } | |
924 | #endif /* CONFIG_RESET_PHY_R */ |