]>
Commit | Line | Data |
---|---|---|
b5b06fb7 YS |
1 | /* |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | |
3 | * Author: Sandeep Kumar Singh <[email protected]> | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
b5b06fb7 YS |
6 | */ |
7 | ||
8 | /* This file is based on board/freescale/corenet_ds/eth_superhydra.c */ | |
9 | ||
10 | /* | |
11 | * This file handles the board muxing between the Fman Ethernet MACs and | |
12 | * the RGMII/SGMII/XGMII PHYs on a Freescale B4860 "Centaur". The SGMII | |
13 | * PHYs are the two on-board 1Gb ports. There are no RGMII PHY on board. | |
14 | * The 10Gb XGMII PHY is provided via the XAUI riser card. There is only | |
15 | * one Fman device on B4860. The SERDES configuration is used to determine | |
16 | * where the SGMII and XAUI cards exist, and also which Fman MACs are routed | |
17 | * to which PHYs. So for a given Fman MAC, there is one and only PHY it | |
18 | * connects to. MACs cannot be routed to PHYs dynamically. This configuration | |
19 | * is done at boot time by reading SERDES protocol from RCW. | |
20 | */ | |
21 | ||
22 | #include <common.h> | |
23 | #include <netdev.h> | |
24 | #include <asm/fsl_serdes.h> | |
25 | #include <fm_eth.h> | |
26 | #include <fsl_mdio.h> | |
27 | #include <malloc.h> | |
28 | #include <fdt_support.h> | |
29 | #include <asm/fsl_dtsec.h> | |
30 | ||
31 | #include "../common/ngpixis.h" | |
32 | #include "../common/fman.h" | |
33 | #include "../common/qixis.h" | |
34 | #include "b4860qds_qixis.h" | |
35 | ||
36 | #define EMI_NONE 0xFFFFFFFF | |
37 | ||
38 | #ifdef CONFIG_FMAN_ENET | |
39 | ||
40 | /* | |
41 | * Mapping of all 16 SERDES lanes to board slots. A value n(>0) will mean that | |
42 | * lane at index is mapped to slot number n. A value of '0' will mean | |
43 | * that the mapping must be determined dynamically, or that the lane maps to | |
44 | * something other than a board slot | |
45 | */ | |
46 | static u8 lane_to_slot[] = { | |
47 | 0, 0, 0, 0, | |
48 | 0, 0, 0, 0, | |
49 | 1, 1, 1, 1, | |
50 | 0, 0, 0, 0 | |
51 | }; | |
52 | ||
53 | /* | |
54 | * This function initializes the lane_to_slot[] array. It reads RCW to check | |
55 | * if Serdes2{E,F,G,H} is configured as slot 2 or as SFP and initializes | |
56 | * lane_to_slot[] accordingly | |
57 | */ | |
58 | static void initialize_lane_to_slot(void) | |
59 | { | |
60 | unsigned int serdes2_prtcl; | |
61 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
62 | serdes2_prtcl = in_be32(&gur->rcwsr[4]) & | |
63 | FSL_CORENET2_RCWSR4_SRDS2_PRTCL; | |
64 | serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; | |
65 | debug("Initializing lane to slot: Serdes2 protocol: %x\n", | |
66 | serdes2_prtcl); | |
67 | ||
68 | switch (serdes2_prtcl) { | |
c7d506d4 | 69 | case 0x17: |
b5b06fb7 YS |
70 | case 0x18: |
71 | /* | |
72 | * Configuration: | |
73 | * SERDES: 2 | |
74 | * Lanes: A,B,C,D: SGMII | |
75 | * Lanes: E,F: Aur | |
76 | * Lanes: G,H: SRIO | |
77 | */ | |
78 | case 0x91: | |
79 | /* | |
80 | * Configuration: | |
81 | * SERDES: 2 | |
82 | * Lanes: A,B: SGMII | |
83 | * Lanes: C,D: SRIO2 | |
84 | * Lanes: E,F,G,H: XAUI2 | |
85 | */ | |
86 | case 0x93: | |
87 | /* | |
88 | * Configuration: | |
89 | * SERDES: 2 | |
90 | * Lanes: A,B,C,D: SGMII | |
91 | * Lanes: E,F,G,H: XAUI2 | |
92 | */ | |
93 | case 0x98: | |
94 | /* | |
95 | * Configuration: | |
96 | * SERDES: 2 | |
97 | * Lanes: A,B,C,D: XAUI2 | |
98 | * Lanes: E,F,G,H: XAUI2 | |
99 | */ | |
100 | case 0x9a: | |
101 | /* | |
102 | * Configuration: | |
103 | * SERDES: 2 | |
104 | * Lanes: A,B: PCI | |
105 | * Lanes: C,D: SGMII | |
106 | * Lanes: E,F,G,H: XAUI2 | |
107 | */ | |
108 | case 0x9e: | |
109 | /* | |
110 | * Configuration: | |
111 | * SERDES: 2 | |
112 | * Lanes: A,B,C,D: PCI | |
113 | * Lanes: E,F,G,H: XAUI2 | |
114 | */ | |
f1d8074c | 115 | case 0xb1: |
b5b06fb7 | 116 | case 0xb2: |
f1d8074c SL |
117 | case 0x8c: |
118 | case 0x8d: | |
b5b06fb7 YS |
119 | /* |
120 | * Configuration: | |
121 | * SERDES: 2 | |
122 | * Lanes: A,B,C,D: PCI | |
123 | * Lanes: E,F: SGMII 3&4 | |
124 | * Lanes: G,H: XFI | |
125 | */ | |
126 | case 0xc2: | |
127 | /* | |
128 | * Configuration: | |
129 | * SERDES: 2 | |
130 | * Lanes: A,B: SGMII | |
131 | * Lanes: C,D: SRIO2 | |
132 | * Lanes: E,F,G,H: XAUI2 | |
133 | */ | |
134 | lane_to_slot[12] = 2; | |
135 | lane_to_slot[13] = lane_to_slot[12]; | |
136 | lane_to_slot[14] = lane_to_slot[12]; | |
137 | lane_to_slot[15] = lane_to_slot[12]; | |
138 | break; | |
139 | ||
140 | default: | |
141 | printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n", | |
142 | serdes2_prtcl); | |
143 | break; | |
144 | } | |
145 | return; | |
146 | } | |
147 | ||
148 | #endif /* #ifdef CONFIG_FMAN_ENET */ | |
149 | ||
150 | int board_eth_init(bd_t *bis) | |
151 | { | |
152 | #ifdef CONFIG_FMAN_ENET | |
153 | struct memac_mdio_info memac_mdio_info; | |
154 | struct memac_mdio_info tg_memac_mdio_info; | |
155 | unsigned int i; | |
156 | unsigned int serdes1_prtcl, serdes2_prtcl; | |
ffee1dde ZQ |
157 | int qsgmii; |
158 | struct mii_dev *bus; | |
b5b06fb7 YS |
159 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); |
160 | serdes1_prtcl = in_be32(&gur->rcwsr[4]) & | |
161 | FSL_CORENET2_RCWSR4_SRDS1_PRTCL; | |
162 | if (!serdes1_prtcl) { | |
163 | printf("SERDES1 is not enabled\n"); | |
164 | return 0; | |
165 | } | |
166 | serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT; | |
167 | debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl); | |
168 | ||
169 | serdes2_prtcl = in_be32(&gur->rcwsr[4]) & | |
170 | FSL_CORENET2_RCWSR4_SRDS2_PRTCL; | |
171 | if (!serdes2_prtcl) { | |
172 | printf("SERDES2 is not enabled\n"); | |
173 | return 0; | |
174 | } | |
175 | serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; | |
176 | debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl); | |
177 | ||
178 | printf("Initializing Fman\n"); | |
179 | ||
180 | initialize_lane_to_slot(); | |
181 | ||
182 | memac_mdio_info.regs = | |
183 | (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR; | |
184 | memac_mdio_info.name = DEFAULT_FM_MDIO_NAME; | |
185 | ||
186 | /* Register the real 1G MDIO bus */ | |
187 | fm_memac_mdio_init(bis, &memac_mdio_info); | |
188 | ||
189 | tg_memac_mdio_info.regs = | |
190 | (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR; | |
191 | tg_memac_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME; | |
192 | ||
193 | /* Register the real 10G MDIO bus */ | |
194 | fm_memac_mdio_init(bis, &tg_memac_mdio_info); | |
195 | ||
196 | /* | |
197 | * Program the two on board DTSEC PHY addresses assuming that they are | |
198 | * all SGMII. RGMII is not supported on this board. Setting SGMII 5 and | |
199 | * 6 to on board SGMII phys | |
200 | */ | |
f1d8074c SL |
201 | fm_info_set_phy_address(FM1_DTSEC5, CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR); |
202 | fm_info_set_phy_address(FM1_DTSEC6, CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR); | |
b5b06fb7 YS |
203 | |
204 | switch (serdes1_prtcl) { | |
c7d506d4 | 205 | case 0x29: |
b5b06fb7 YS |
206 | case 0x2a: |
207 | /* Serdes 1: A-B SGMII, Configuring DTSEC 5 and 6 */ | |
f1d8074c SL |
208 | debug("Set phy addresses for FM1_DTSEC5:%x, FM1_DTSEC6:%x\n", |
209 | CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR, | |
210 | CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR); | |
b5b06fb7 | 211 | fm_info_set_phy_address(FM1_DTSEC5, |
f1d8074c | 212 | CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR); |
b5b06fb7 | 213 | fm_info_set_phy_address(FM1_DTSEC6, |
f1d8074c | 214 | CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR); |
b5b06fb7 YS |
215 | break; |
216 | #ifdef CONFIG_PPC_B4420 | |
c7d506d4 | 217 | case 0x17: |
b5b06fb7 YS |
218 | case 0x18: |
219 | /* Serdes 1: A-D SGMII, Configuring on board dual SGMII Phy */ | |
f1d8074c SL |
220 | debug("Set phy addresses for FM1_DTSEC3:%x, FM1_DTSEC4:%x\n", |
221 | CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR, | |
222 | CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR); | |
b5b06fb7 YS |
223 | /* Fixing Serdes clock by programming FPGA register */ |
224 | QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125); | |
225 | fm_info_set_phy_address(FM1_DTSEC3, | |
f1d8074c | 226 | CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR); |
b5b06fb7 | 227 | fm_info_set_phy_address(FM1_DTSEC4, |
f1d8074c | 228 | CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR); |
b5b06fb7 YS |
229 | break; |
230 | #endif | |
231 | default: | |
232 | printf("Fman: Unsupported SerDes1 Protocol 0x%02x\n", | |
233 | serdes1_prtcl); | |
234 | break; | |
235 | } | |
236 | switch (serdes2_prtcl) { | |
c7d506d4 | 237 | case 0x17: |
b5b06fb7 | 238 | case 0x18: |
f1d8074c SL |
239 | debug("Set phy address on SGMII Riser for FM1_DTSEC1:%x\n", |
240 | CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR); | |
b5b06fb7 YS |
241 | fm_info_set_phy_address(FM1_DTSEC1, |
242 | CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR); | |
243 | fm_info_set_phy_address(FM1_DTSEC2, | |
244 | CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR); | |
245 | fm_info_set_phy_address(FM1_DTSEC3, | |
246 | CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR); | |
247 | fm_info_set_phy_address(FM1_DTSEC4, | |
248 | CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR); | |
249 | break; | |
c7d506d4 | 250 | case 0x48: |
b5b06fb7 | 251 | case 0x49: |
f1d8074c SL |
252 | debug("Set phy address on SGMII Riser for FM1_DTSEC1:%x\n", |
253 | CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR); | |
b5b06fb7 YS |
254 | fm_info_set_phy_address(FM1_DTSEC1, |
255 | CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR); | |
256 | fm_info_set_phy_address(FM1_DTSEC2, | |
257 | CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR); | |
258 | fm_info_set_phy_address(FM1_DTSEC3, | |
259 | CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR); | |
260 | break; | |
f1d8074c | 261 | case 0xb1: |
b5b06fb7 | 262 | case 0xb2: |
f1d8074c SL |
263 | case 0x8c: |
264 | case 0x8d: | |
265 | debug("Set phy addresses on SGMII Riser for FM1_DTSEC1:%x\n", | |
266 | CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR); | |
b5b06fb7 YS |
267 | fm_info_set_phy_address(FM1_DTSEC3, |
268 | CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR); | |
269 | fm_info_set_phy_address(FM1_DTSEC4, | |
270 | CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR); | |
89b94d85 SX |
271 | /* |
272 | * XFI does not need a PHY to work, but to make U-boot | |
273 | * happy, assign a fake PHY address for a XFI port. | |
274 | */ | |
275 | fm_info_set_phy_address(FM1_10GEC1, 0); | |
276 | fm_info_set_phy_address(FM1_10GEC2, 1); | |
b5b06fb7 | 277 | break; |
16d88f41 SG |
278 | case 0x98: |
279 | /* XAUI in Slot1 and Slot2 */ | |
f1d8074c | 280 | debug("Set phy address of AMC2PEX-2S for FM1_10GEC1:%x\n", |
16d88f41 SG |
281 | CONFIG_SYS_FM1_10GEC1_PHY_ADDR); |
282 | fm_info_set_phy_address(FM1_10GEC1, | |
283 | CONFIG_SYS_FM1_10GEC1_PHY_ADDR); | |
f1d8074c | 284 | debug("Set phy address of AMC2PEX-2S for FM1_10GEC2:%x\n", |
16d88f41 SG |
285 | CONFIG_SYS_FM1_10GEC2_PHY_ADDR); |
286 | fm_info_set_phy_address(FM1_10GEC2, | |
287 | CONFIG_SYS_FM1_10GEC2_PHY_ADDR); | |
288 | break; | |
289 | case 0x9E: | |
290 | /* XAUI in Slot2 */ | |
f1d8074c | 291 | debug("Sett phy address of AMC2PEX-2S for FM1_10GEC2:%x\n", |
16d88f41 SG |
292 | CONFIG_SYS_FM1_10GEC2_PHY_ADDR); |
293 | fm_info_set_phy_address(FM1_10GEC2, | |
294 | CONFIG_SYS_FM1_10GEC2_PHY_ADDR); | |
295 | break; | |
b5b06fb7 YS |
296 | default: |
297 | printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n", | |
298 | serdes2_prtcl); | |
299 | break; | |
300 | } | |
301 | ||
ffee1dde ZQ |
302 | /*set PHY address for QSGMII Riser Card on slot2*/ |
303 | bus = miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME); | |
304 | qsgmii = is_qsgmii_riser_card(bus, PHY_BASE_ADDR, PORT_NUM, REGNUM); | |
305 | ||
306 | if (qsgmii) { | |
307 | switch (serdes2_prtcl) { | |
308 | case 0xb2: | |
309 | case 0x8d: | |
310 | fm_info_set_phy_address(FM1_DTSEC3, PHY_BASE_ADDR); | |
311 | fm_info_set_phy_address(FM1_DTSEC4, PHY_BASE_ADDR + 1); | |
312 | break; | |
313 | default: | |
314 | break; | |
315 | } | |
316 | } | |
317 | ||
b5b06fb7 YS |
318 | for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { |
319 | int idx = i - FM1_DTSEC1; | |
320 | ||
321 | switch (fm_info_get_enet_if(i)) { | |
322 | case PHY_INTERFACE_MODE_SGMII: | |
323 | fm_info_set_mdio(i, | |
324 | miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME)); | |
325 | break; | |
326 | case PHY_INTERFACE_MODE_NONE: | |
327 | fm_info_set_phy_address(i, 0); | |
328 | break; | |
329 | default: | |
330 | printf("Fman1: DTSEC%u set to unknown interface %i\n", | |
331 | idx + 1, fm_info_get_enet_if(i)); | |
332 | fm_info_set_phy_address(i, 0); | |
333 | break; | |
334 | } | |
335 | } | |
336 | ||
16d88f41 SG |
337 | for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) { |
338 | int idx = i - FM1_10GEC1; | |
339 | ||
340 | switch (fm_info_get_enet_if(i)) { | |
341 | case PHY_INTERFACE_MODE_XGMII: | |
342 | fm_info_set_mdio(i, | |
f1d8074c SL |
343 | miiphy_get_dev_by_name |
344 | (DEFAULT_FM_TGEC_MDIO_NAME)); | |
345 | break; | |
346 | case PHY_INTERFACE_MODE_NONE: | |
347 | fm_info_set_phy_address(i, 0); | |
16d88f41 SG |
348 | break; |
349 | default: | |
f1d8074c | 350 | printf("Fman1: TGEC%u set to unknown interface %i\n", |
16d88f41 SG |
351 | idx + 1, fm_info_get_enet_if(i)); |
352 | fm_info_set_phy_address(i, 0); | |
353 | break; | |
354 | } | |
355 | } | |
356 | ||
b5b06fb7 YS |
357 | cpu_eth_init(bis); |
358 | #endif | |
359 | ||
360 | return pci_eth_init(bis); | |
361 | } | |
362 | ||
363 | void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr, | |
364 | enum fm_port port, int offset) | |
365 | { | |
366 | int phy; | |
367 | char alias[32]; | |
90e80dc6 SX |
368 | struct fixed_link f_link; |
369 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
370 | u32 prtcl2 = in_be32(&gur->rcwsr[4]) & FSL_CORENET2_RCWSR4_SRDS2_PRTCL; | |
371 | ||
372 | prtcl2 >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; | |
b5b06fb7 YS |
373 | |
374 | if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) { | |
375 | phy = fm_info_get_phy_address(port); | |
376 | ||
377 | sprintf(alias, "phy_sgmii_%x", phy); | |
378 | fdt_set_phy_handle(fdt, compat, addr, alias); | |
f1d8074c | 379 | fdt_status_okay_by_alias(fdt, alias); |
90e80dc6 SX |
380 | } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_XGMII) { |
381 | /* check if it's XFI interface for 10g */ | |
382 | switch (prtcl2) { | |
383 | case 0x80: | |
384 | case 0x81: | |
385 | case 0x82: | |
386 | case 0x83: | |
387 | case 0x84: | |
388 | case 0x85: | |
389 | case 0x86: | |
390 | case 0x87: | |
391 | case 0x88: | |
392 | case 0x89: | |
393 | case 0x8a: | |
394 | case 0x8b: | |
395 | case 0x8c: | |
396 | case 0x8d: | |
397 | case 0x8e: | |
398 | case 0xb1: | |
399 | case 0xb2: | |
400 | f_link.phy_id = port; | |
401 | f_link.duplex = 1; | |
402 | f_link.link_speed = 10000; | |
403 | f_link.pause = 0; | |
404 | f_link.asym_pause = 0; | |
405 | ||
406 | fdt_delprop(fdt, offset, "phy-handle"); | |
407 | fdt_setprop(fdt, offset, "fixed-link", &f_link, | |
408 | sizeof(f_link)); | |
409 | break; | |
e2544e7a SG |
410 | case 0x98: /* XAUI interface */ |
411 | sprintf(alias, "phy_xaui_slot1"); | |
412 | fdt_status_okay_by_alias(fdt, alias); | |
413 | ||
414 | sprintf(alias, "phy_xaui_slot2"); | |
415 | fdt_status_okay_by_alias(fdt, alias); | |
416 | break; | |
417 | case 0x9e: /* XAUI interface */ | |
418 | case 0x9a: | |
419 | case 0x93: | |
420 | case 0x91: | |
421 | sprintf(alias, "phy_xaui_slot1"); | |
422 | fdt_status_okay_by_alias(fdt, alias); | |
423 | break; | |
424 | case 0x97: /* XAUI interface */ | |
425 | case 0xc3: | |
426 | sprintf(alias, "phy_xaui_slot2"); | |
427 | fdt_status_okay_by_alias(fdt, alias); | |
428 | break; | |
90e80dc6 SX |
429 | default: |
430 | break; | |
431 | } | |
b5b06fb7 YS |
432 | } |
433 | } | |
434 | ||
f1d8074c SL |
435 | /* |
436 | * Set status to disabled for unused ethernet node | |
437 | */ | |
b5b06fb7 YS |
438 | void fdt_fixup_board_enet(void *fdt) |
439 | { | |
440 | int i; | |
441 | char alias[32]; | |
442 | ||
f1d8074c | 443 | for (i = FM1_DTSEC1; i <= FM1_10GEC2; i++) { |
b5b06fb7 YS |
444 | switch (fm_info_get_enet_if(i)) { |
445 | case PHY_INTERFACE_MODE_NONE: | |
446 | sprintf(alias, "ethernet%u", i); | |
447 | fdt_status_disabled_by_alias(fdt, alias); | |
448 | break; | |
449 | default: | |
450 | break; | |
451 | } | |
452 | } | |
453 | } |