]>
Commit | Line | Data |
---|---|---|
02b5d2ed SX |
1 | /* |
2 | * Copyright 2015 Freescale Semiconductor, Inc. | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <asm/io.h> | |
9 | #include <netdev.h> | |
73223f0e | 10 | #include <fdt_support.h> |
02b5d2ed SX |
11 | #include <fm_eth.h> |
12 | #include <fsl_mdio.h> | |
13 | #include <fsl_dtsec.h> | |
73223f0e | 14 | #include <libfdt.h> |
02b5d2ed SX |
15 | #include <malloc.h> |
16 | #include <asm/arch/fsl_serdes.h> | |
17 | ||
18 | #include "../common/qixis.h" | |
19 | #include "../common/fman.h" | |
20 | #include "ls1043aqds_qixis.h" | |
21 | ||
22 | #define EMI_NONE 0xFF | |
23 | #define EMI1_RGMII1 0 | |
24 | #define EMI1_RGMII2 1 | |
25 | #define EMI1_SLOT1 2 | |
26 | #define EMI1_SLOT2 3 | |
27 | #define EMI1_SLOT3 4 | |
28 | #define EMI1_SLOT4 5 | |
29 | #define EMI2 6 | |
30 | ||
31 | static int mdio_mux[NUM_FM_PORTS]; | |
32 | ||
33 | static const char * const mdio_names[] = { | |
34 | "LS1043AQDS_MDIO_RGMII1", | |
35 | "LS1043AQDS_MDIO_RGMII2", | |
36 | "LS1043AQDS_MDIO_SLOT1", | |
37 | "LS1043AQDS_MDIO_SLOT2", | |
38 | "LS1043AQDS_MDIO_SLOT3", | |
39 | "LS1043AQDS_MDIO_SLOT4", | |
40 | "NULL", | |
41 | }; | |
42 | ||
43 | /* Map SerDes1 4 lanes to default slot, will be initialized dynamically */ | |
44 | static u8 lane_to_slot[] = {1, 2, 3, 4}; | |
45 | ||
46 | static const char *ls1043aqds_mdio_name_for_muxval(u8 muxval) | |
47 | { | |
48 | return mdio_names[muxval]; | |
49 | } | |
50 | ||
51 | struct mii_dev *mii_dev_for_muxval(u8 muxval) | |
52 | { | |
53 | struct mii_dev *bus; | |
54 | const char *name; | |
55 | ||
56 | if (muxval > EMI2) | |
57 | return NULL; | |
58 | ||
59 | name = ls1043aqds_mdio_name_for_muxval(muxval); | |
60 | ||
61 | if (!name) { | |
62 | printf("No bus for muxval %x\n", muxval); | |
63 | return NULL; | |
64 | } | |
65 | ||
66 | bus = miiphy_get_dev_by_name(name); | |
67 | ||
68 | if (!bus) { | |
69 | printf("No bus by name %s\n", name); | |
70 | return NULL; | |
71 | } | |
72 | ||
73 | return bus; | |
74 | } | |
75 | ||
76 | struct ls1043aqds_mdio { | |
77 | u8 muxval; | |
78 | struct mii_dev *realbus; | |
79 | }; | |
80 | ||
81 | static void ls1043aqds_mux_mdio(u8 muxval) | |
82 | { | |
83 | u8 brdcfg4; | |
84 | ||
85 | if (muxval < 7) { | |
86 | brdcfg4 = QIXIS_READ(brdcfg[4]); | |
87 | brdcfg4 &= ~BRDCFG4_EMISEL_MASK; | |
88 | brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT); | |
89 | QIXIS_WRITE(brdcfg[4], brdcfg4); | |
90 | } | |
91 | } | |
92 | ||
93 | static int ls1043aqds_mdio_read(struct mii_dev *bus, int addr, int devad, | |
94 | int regnum) | |
95 | { | |
96 | struct ls1043aqds_mdio *priv = bus->priv; | |
97 | ||
98 | ls1043aqds_mux_mdio(priv->muxval); | |
99 | ||
100 | return priv->realbus->read(priv->realbus, addr, devad, regnum); | |
101 | } | |
102 | ||
103 | static int ls1043aqds_mdio_write(struct mii_dev *bus, int addr, int devad, | |
104 | int regnum, u16 value) | |
105 | { | |
106 | struct ls1043aqds_mdio *priv = bus->priv; | |
107 | ||
108 | ls1043aqds_mux_mdio(priv->muxval); | |
109 | ||
110 | return priv->realbus->write(priv->realbus, addr, devad, | |
111 | regnum, value); | |
112 | } | |
113 | ||
114 | static int ls1043aqds_mdio_reset(struct mii_dev *bus) | |
115 | { | |
116 | struct ls1043aqds_mdio *priv = bus->priv; | |
117 | ||
118 | return priv->realbus->reset(priv->realbus); | |
119 | } | |
120 | ||
121 | static int ls1043aqds_mdio_init(char *realbusname, u8 muxval) | |
122 | { | |
123 | struct ls1043aqds_mdio *pmdio; | |
124 | struct mii_dev *bus = mdio_alloc(); | |
125 | ||
126 | if (!bus) { | |
127 | printf("Failed to allocate ls1043aqds MDIO bus\n"); | |
128 | return -1; | |
129 | } | |
130 | ||
131 | pmdio = malloc(sizeof(*pmdio)); | |
132 | if (!pmdio) { | |
133 | printf("Failed to allocate ls1043aqds private data\n"); | |
134 | free(bus); | |
135 | return -1; | |
136 | } | |
137 | ||
138 | bus->read = ls1043aqds_mdio_read; | |
139 | bus->write = ls1043aqds_mdio_write; | |
140 | bus->reset = ls1043aqds_mdio_reset; | |
192bc694 | 141 | strcpy(bus->name, ls1043aqds_mdio_name_for_muxval(muxval)); |
02b5d2ed SX |
142 | |
143 | pmdio->realbus = miiphy_get_dev_by_name(realbusname); | |
144 | ||
145 | if (!pmdio->realbus) { | |
146 | printf("No bus with name %s\n", realbusname); | |
147 | free(bus); | |
148 | free(pmdio); | |
149 | return -1; | |
150 | } | |
151 | ||
152 | pmdio->muxval = muxval; | |
153 | bus->priv = pmdio; | |
154 | return mdio_register(bus); | |
155 | } | |
156 | ||
157 | void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr, | |
158 | enum fm_port port, int offset) | |
159 | { | |
160 | struct fixed_link f_link; | |
161 | ||
162 | if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) { | |
163 | if (port == FM1_DTSEC9) { | |
164 | fdt_set_phy_handle(fdt, compat, addr, | |
165 | "sgmii_riser_s1_p1"); | |
166 | } else if (port == FM1_DTSEC2) { | |
167 | fdt_set_phy_handle(fdt, compat, addr, | |
168 | "sgmii_riser_s2_p1"); | |
169 | } else if (port == FM1_DTSEC5) { | |
170 | fdt_set_phy_handle(fdt, compat, addr, | |
171 | "sgmii_riser_s3_p1"); | |
172 | } else if (port == FM1_DTSEC6) { | |
173 | fdt_set_phy_handle(fdt, compat, addr, | |
174 | "sgmii_riser_s4_p1"); | |
175 | } | |
176 | } else if (fm_info_get_enet_if(port) == | |
177 | PHY_INTERFACE_MODE_SGMII_2500) { | |
178 | /* 2.5G SGMII interface */ | |
179 | f_link.phy_id = port; | |
180 | f_link.duplex = 1; | |
181 | f_link.link_speed = 1000; | |
182 | f_link.pause = 0; | |
183 | f_link.asym_pause = 0; | |
184 | /* no PHY for 2.5G SGMII */ | |
185 | fdt_delprop(fdt, offset, "phy-handle"); | |
186 | fdt_setprop(fdt, offset, "fixed-link", &f_link, sizeof(f_link)); | |
187 | fdt_setprop_string(fdt, offset, "phy-connection-type", | |
188 | "sgmii-2500"); | |
189 | } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_QSGMII) { | |
190 | switch (mdio_mux[port]) { | |
191 | case EMI1_SLOT1: | |
192 | switch (port) { | |
193 | case FM1_DTSEC1: | |
194 | fdt_set_phy_handle(fdt, compat, addr, | |
195 | "qsgmii_s1_p1"); | |
196 | break; | |
197 | case FM1_DTSEC2: | |
198 | fdt_set_phy_handle(fdt, compat, addr, | |
199 | "qsgmii_s1_p2"); | |
200 | break; | |
201 | case FM1_DTSEC5: | |
202 | fdt_set_phy_handle(fdt, compat, addr, | |
203 | "qsgmii_s1_p3"); | |
204 | break; | |
205 | case FM1_DTSEC6: | |
206 | fdt_set_phy_handle(fdt, compat, addr, | |
207 | "qsgmii_s1_p4"); | |
208 | break; | |
209 | default: | |
210 | break; | |
211 | } | |
212 | break; | |
213 | case EMI1_SLOT2: | |
214 | switch (port) { | |
215 | case FM1_DTSEC1: | |
216 | fdt_set_phy_handle(fdt, compat, addr, | |
217 | "qsgmii_s2_p1"); | |
218 | break; | |
219 | case FM1_DTSEC2: | |
220 | fdt_set_phy_handle(fdt, compat, addr, | |
221 | "qsgmii_s2_p2"); | |
222 | break; | |
223 | case FM1_DTSEC5: | |
224 | fdt_set_phy_handle(fdt, compat, addr, | |
225 | "qsgmii_s2_p3"); | |
226 | break; | |
227 | case FM1_DTSEC6: | |
228 | fdt_set_phy_handle(fdt, compat, addr, | |
229 | "qsgmii_s2_p4"); | |
230 | break; | |
231 | default: | |
232 | break; | |
233 | } | |
234 | break; | |
235 | default: | |
236 | break; | |
237 | } | |
238 | fdt_delprop(fdt, offset, "phy-connection-type"); | |
239 | fdt_setprop_string(fdt, offset, "phy-connection-type", | |
240 | "qsgmii"); | |
241 | } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_XGMII && | |
242 | port == FM1_10GEC1) { | |
243 | /* XFI interface */ | |
244 | f_link.phy_id = port; | |
245 | f_link.duplex = 1; | |
246 | f_link.link_speed = 10000; | |
247 | f_link.pause = 0; | |
248 | f_link.asym_pause = 0; | |
249 | /* no PHY for XFI */ | |
250 | fdt_delprop(fdt, offset, "phy-handle"); | |
251 | fdt_setprop(fdt, offset, "fixed-link", &f_link, sizeof(f_link)); | |
252 | fdt_setprop_string(fdt, offset, "phy-connection-type", "xgmii"); | |
253 | } | |
254 | } | |
255 | ||
256 | void fdt_fixup_board_enet(void *fdt) | |
257 | { | |
258 | int i; | |
259 | struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
260 | u32 srds_s1; | |
261 | ||
262 | srds_s1 = in_be32(&gur->rcwsr[4]) & | |
263 | FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; | |
264 | srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; | |
265 | ||
266 | for (i = FM1_DTSEC1; i < NUM_FM_PORTS; i++) { | |
267 | switch (fm_info_get_enet_if(i)) { | |
268 | case PHY_INTERFACE_MODE_SGMII: | |
269 | case PHY_INTERFACE_MODE_QSGMII: | |
270 | switch (mdio_mux[i]) { | |
271 | case EMI1_SLOT1: | |
272 | fdt_status_okay_by_alias(fdt, "emi1_slot1"); | |
273 | break; | |
274 | case EMI1_SLOT2: | |
275 | fdt_status_okay_by_alias(fdt, "emi1_slot2"); | |
276 | break; | |
277 | case EMI1_SLOT3: | |
278 | fdt_status_okay_by_alias(fdt, "emi1_slot3"); | |
279 | break; | |
280 | case EMI1_SLOT4: | |
281 | fdt_status_okay_by_alias(fdt, "emi1_slot4"); | |
282 | break; | |
283 | default: | |
284 | break; | |
285 | } | |
286 | break; | |
287 | case PHY_INTERFACE_MODE_XGMII: | |
288 | break; | |
289 | default: | |
290 | break; | |
291 | } | |
292 | } | |
293 | } | |
294 | ||
295 | int board_eth_init(bd_t *bis) | |
296 | { | |
297 | #ifdef CONFIG_FMAN_ENET | |
298 | int i, idx, lane, slot, interface; | |
299 | struct memac_mdio_info dtsec_mdio_info; | |
300 | struct memac_mdio_info tgec_mdio_info; | |
301 | struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
302 | u32 srds_s1; | |
303 | ||
304 | srds_s1 = in_be32(&gur->rcwsr[4]) & | |
305 | FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; | |
306 | srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; | |
307 | ||
308 | /* Initialize the mdio_mux array so we can recognize empty elements */ | |
309 | for (i = 0; i < NUM_FM_PORTS; i++) | |
310 | mdio_mux[i] = EMI_NONE; | |
311 | ||
312 | dtsec_mdio_info.regs = | |
313 | (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR; | |
314 | ||
315 | dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME; | |
316 | ||
317 | /* Register the 1G MDIO bus */ | |
318 | fm_memac_mdio_init(bis, &dtsec_mdio_info); | |
319 | ||
320 | tgec_mdio_info.regs = | |
321 | (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR; | |
322 | tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME; | |
323 | ||
324 | /* Register the 10G MDIO bus */ | |
325 | fm_memac_mdio_init(bis, &tgec_mdio_info); | |
326 | ||
327 | /* Register the muxing front-ends to the MDIO buses */ | |
328 | ls1043aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII1); | |
329 | ls1043aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII2); | |
330 | ls1043aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT1); | |
331 | ls1043aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT2); | |
332 | ls1043aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT3); | |
333 | ls1043aqds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT4); | |
334 | ls1043aqds_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME, EMI2); | |
335 | ||
336 | /* Set the two on-board RGMII PHY address */ | |
337 | fm_info_set_phy_address(FM1_DTSEC3, RGMII_PHY1_ADDR); | |
338 | fm_info_set_phy_address(FM1_DTSEC4, RGMII_PHY2_ADDR); | |
339 | ||
340 | switch (srds_s1) { | |
341 | case 0x2555: | |
342 | /* 2.5G SGMII on lane A, MAC 9 */ | |
343 | fm_info_set_phy_address(FM1_DTSEC9, 9); | |
344 | break; | |
345 | case 0x4555: | |
346 | case 0x4558: | |
347 | /* QSGMII on lane A, MAC 1/2/5/6 */ | |
348 | fm_info_set_phy_address(FM1_DTSEC1, | |
349 | QSGMII_CARD_PORT1_PHY_ADDR_S1); | |
350 | fm_info_set_phy_address(FM1_DTSEC2, | |
351 | QSGMII_CARD_PORT2_PHY_ADDR_S1); | |
352 | fm_info_set_phy_address(FM1_DTSEC5, | |
353 | QSGMII_CARD_PORT3_PHY_ADDR_S1); | |
354 | fm_info_set_phy_address(FM1_DTSEC6, | |
355 | QSGMII_CARD_PORT4_PHY_ADDR_S1); | |
356 | break; | |
357 | case 0x1355: | |
358 | /* SGMII on lane B, MAC 2*/ | |
359 | fm_info_set_phy_address(FM1_DTSEC2, SGMII_CARD_PORT1_PHY_ADDR); | |
360 | break; | |
361 | case 0x2355: | |
362 | /* 2.5G SGMII on lane A, MAC 9 */ | |
363 | fm_info_set_phy_address(FM1_DTSEC9, 9); | |
364 | /* SGMII on lane B, MAC 2*/ | |
365 | fm_info_set_phy_address(FM1_DTSEC2, SGMII_CARD_PORT1_PHY_ADDR); | |
366 | break; | |
367 | case 0x3335: | |
368 | /* SGMII on lane C, MAC 5 */ | |
369 | fm_info_set_phy_address(FM1_DTSEC5, SGMII_CARD_PORT1_PHY_ADDR); | |
370 | case 0x3355: | |
371 | case 0x3358: | |
372 | /* SGMII on lane B, MAC 2 */ | |
373 | fm_info_set_phy_address(FM1_DTSEC2, SGMII_CARD_PORT1_PHY_ADDR); | |
374 | case 0x3555: | |
375 | case 0x3558: | |
376 | /* SGMII on lane A, MAC 9 */ | |
377 | fm_info_set_phy_address(FM1_DTSEC9, SGMII_CARD_PORT1_PHY_ADDR); | |
378 | break; | |
379 | case 0x1455: | |
380 | /* QSGMII on lane B, MAC 1/2/5/6 */ | |
381 | fm_info_set_phy_address(FM1_DTSEC1, | |
382 | QSGMII_CARD_PORT1_PHY_ADDR_S2); | |
383 | fm_info_set_phy_address(FM1_DTSEC2, | |
384 | QSGMII_CARD_PORT2_PHY_ADDR_S2); | |
385 | fm_info_set_phy_address(FM1_DTSEC5, | |
386 | QSGMII_CARD_PORT3_PHY_ADDR_S2); | |
387 | fm_info_set_phy_address(FM1_DTSEC6, | |
388 | QSGMII_CARD_PORT4_PHY_ADDR_S2); | |
389 | break; | |
390 | case 0x2455: | |
391 | /* 2.5G SGMII on lane A, MAC 9 */ | |
392 | fm_info_set_phy_address(FM1_DTSEC9, 9); | |
393 | /* QSGMII on lane B, MAC 1/2/5/6 */ | |
394 | fm_info_set_phy_address(FM1_DTSEC1, | |
395 | QSGMII_CARD_PORT1_PHY_ADDR_S2); | |
396 | fm_info_set_phy_address(FM1_DTSEC2, | |
397 | QSGMII_CARD_PORT2_PHY_ADDR_S2); | |
398 | fm_info_set_phy_address(FM1_DTSEC5, | |
399 | QSGMII_CARD_PORT3_PHY_ADDR_S2); | |
400 | fm_info_set_phy_address(FM1_DTSEC6, | |
401 | QSGMII_CARD_PORT4_PHY_ADDR_S2); | |
402 | break; | |
403 | case 0x2255: | |
404 | /* 2.5G SGMII on lane A, MAC 9 */ | |
405 | fm_info_set_phy_address(FM1_DTSEC9, 9); | |
406 | /* 2.5G SGMII on lane B, MAC 2 */ | |
407 | fm_info_set_phy_address(FM1_DTSEC2, 2); | |
408 | break; | |
409 | case 0x3333: | |
410 | /* SGMII on lane A/B/C/D, MAC 9/2/5/6 */ | |
411 | fm_info_set_phy_address(FM1_DTSEC9, | |
412 | SGMII_CARD_PORT1_PHY_ADDR); | |
413 | fm_info_set_phy_address(FM1_DTSEC2, | |
414 | SGMII_CARD_PORT1_PHY_ADDR); | |
415 | fm_info_set_phy_address(FM1_DTSEC5, | |
416 | SGMII_CARD_PORT1_PHY_ADDR); | |
417 | fm_info_set_phy_address(FM1_DTSEC6, | |
418 | SGMII_CARD_PORT1_PHY_ADDR); | |
419 | break; | |
420 | default: | |
421 | printf("Invalid SerDes protocol 0x%x for LS1043AQDS\n", | |
422 | srds_s1); | |
423 | break; | |
424 | } | |
425 | ||
426 | for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { | |
427 | idx = i - FM1_DTSEC1; | |
428 | interface = fm_info_get_enet_if(i); | |
429 | switch (interface) { | |
430 | case PHY_INTERFACE_MODE_SGMII: | |
431 | case PHY_INTERFACE_MODE_SGMII_2500: | |
432 | case PHY_INTERFACE_MODE_QSGMII: | |
433 | if (interface == PHY_INTERFACE_MODE_SGMII) { | |
434 | lane = serdes_get_first_lane(FSL_SRDS_1, | |
435 | SGMII_FM1_DTSEC1 + idx); | |
436 | } else if (interface == PHY_INTERFACE_MODE_SGMII_2500) { | |
437 | lane = serdes_get_first_lane(FSL_SRDS_1, | |
438 | SGMII_2500_FM1_DTSEC1 + idx); | |
439 | } else { | |
440 | lane = serdes_get_first_lane(FSL_SRDS_1, | |
441 | QSGMII_FM1_A); | |
442 | } | |
443 | ||
444 | if (lane < 0) | |
445 | break; | |
446 | ||
447 | slot = lane_to_slot[lane]; | |
448 | debug("FM1@DTSEC%u expects SGMII in slot %u\n", | |
449 | idx + 1, slot); | |
450 | if (QIXIS_READ(present2) & (1 << (slot - 1))) | |
451 | fm_disable_port(i); | |
452 | ||
453 | switch (slot) { | |
454 | case 1: | |
455 | mdio_mux[i] = EMI1_SLOT1; | |
456 | fm_info_set_mdio(i, mii_dev_for_muxval( | |
457 | mdio_mux[i])); | |
458 | break; | |
459 | case 2: | |
460 | mdio_mux[i] = EMI1_SLOT2; | |
461 | fm_info_set_mdio(i, mii_dev_for_muxval( | |
462 | mdio_mux[i])); | |
463 | break; | |
464 | case 3: | |
465 | mdio_mux[i] = EMI1_SLOT3; | |
466 | fm_info_set_mdio(i, mii_dev_for_muxval( | |
467 | mdio_mux[i])); | |
468 | break; | |
469 | case 4: | |
470 | mdio_mux[i] = EMI1_SLOT4; | |
471 | fm_info_set_mdio(i, mii_dev_for_muxval( | |
472 | mdio_mux[i])); | |
473 | break; | |
474 | default: | |
475 | break; | |
476 | } | |
477 | break; | |
478 | case PHY_INTERFACE_MODE_RGMII: | |
479 | if (i == FM1_DTSEC3) | |
480 | mdio_mux[i] = EMI1_RGMII1; | |
481 | else if (i == FM1_DTSEC4) | |
482 | mdio_mux[i] = EMI1_RGMII2; | |
483 | fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); | |
484 | break; | |
485 | default: | |
486 | break; | |
487 | } | |
488 | } | |
489 | ||
490 | cpu_eth_init(bis); | |
491 | #endif /* CONFIG_FMAN_ENET */ | |
492 | ||
493 | return pci_eth_init(bis); | |
494 | } |