]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
d31e53b4 TT |
2 | /* |
3 | * Copyright 2009-2011 Freescale Semiconductor, Inc. | |
4 | * Author: Srikanth Srinivasan <[email protected]> | |
d31e53b4 TT |
5 | */ |
6 | ||
7 | /* | |
8 | * This file handles the board muxing between the Fman Ethernet MACs and | |
9 | * the RGMII/SGMII/XGMII PHYs on a Freescale P5040 "Super Hydra" reference | |
10 | * board. The RGMII PHYs are the two on-board 1Gb ports. The SGMII PHYs are | |
11 | * provided by the standard Freescale four-port SGMII riser card. The 10Gb | |
12 | * XGMII PHYs are provided via the XAUI riser card. The P5040 has 2 FMans | |
13 | * and 5 1G interfaces and 10G interface per FMan. Based on the options in | |
14 | * the RCW, we could have upto 3 SGMII cards and 1 XAUI card at a time. | |
15 | * | |
16 | * Muxing is handled via the PIXIS BRDCFG1 register. The EMI1 bits control | |
17 | * muxing among the RGMII PHYs and the SGMII PHYs. The value for RGMII is | |
18 | * always the same (0). The value for SGMII depends on which slot the riser is | |
19 | * inserted in. The EMI2 bits control muxing for the the XGMII. Like SGMII, | |
20 | * the value is based on which slot the XAUI is inserted in. | |
21 | * | |
22 | * The SERDES configuration is used to determine where the SGMII and XAUI cards | |
23 | * exist, and also which Fman's MACs are routed to which PHYs. So for a given | |
24 | * Fman MAC, there is one and only PHY it connects to. MACs cannot be routed | |
25 | * to PHYs dynamically. | |
26 | * | |
27 | * | |
28 | * This file also updates the device tree in three ways: | |
29 | * | |
30 | * 1) The status of each virtual MDIO node that is referenced by an Ethernet | |
31 | * node is set to "okay". | |
32 | * | |
33 | * 2) The phy-handle property of each active Ethernet MAC node is set to the | |
34 | * appropriate PHY node. | |
35 | * | |
36 | * 3) The "mux value" for each virtual MDIO node is set to the correct value, | |
37 | * if necessary. Some virtual MDIO nodes do not have configurable mux | |
38 | * values, so those values are hard-coded in the DTS. On the HYDRA board, | |
39 | * the virtual MDIO node for the SGMII card needs to be updated. | |
40 | * | |
41 | * For all this to work, the device tree needs to have the following: | |
42 | * | |
43 | * 1) An alias for each PHY node that an Ethernet node could be routed to. | |
44 | * | |
45 | * 2) An alias for each real and virtual MDIO node that is disabled by default | |
46 | * and might need to be enabled, and also might need to have its mux-value | |
47 | * updated. | |
48 | */ | |
49 | ||
50 | #include <common.h> | |
51 | #include <netdev.h> | |
52 | #include <asm/fsl_serdes.h> | |
53 | #include <fm_eth.h> | |
54 | #include <fsl_mdio.h> | |
55 | #include <malloc.h> | |
56 | #include <fdt_support.h> | |
8225b2fd | 57 | #include <fsl_dtsec.h> |
d31e53b4 TT |
58 | |
59 | #include "../common/ngpixis.h" | |
60 | #include "../common/fman.h" | |
61 | ||
62 | #ifdef CONFIG_FMAN_ENET | |
63 | ||
64 | #define BRDCFG1_EMI1_SEL_MASK 0x70 | |
65 | #define BRDCFG1_EMI1_SEL_SLOT1 0x10 | |
66 | #define BRDCFG1_EMI1_SEL_SLOT2 0x20 | |
67 | #define BRDCFG1_EMI1_SEL_SLOT5 0x30 | |
68 | #define BRDCFG1_EMI1_SEL_SLOT6 0x40 | |
69 | #define BRDCFG1_EMI1_SEL_SLOT7 0x50 | |
70 | #define BRDCFG1_EMI1_SEL_SLOT3 0x60 | |
71 | #define BRDCFG1_EMI1_SEL_RGMII 0x00 | |
72 | #define BRDCFG1_EMI1_EN 0x08 | |
73 | #define BRDCFG1_EMI2_SEL_MASK 0x06 | |
74 | #define BRDCFG1_EMI2_SEL_SLOT1 0x00 | |
75 | #define BRDCFG1_EMI2_SEL_SLOT2 0x02 | |
76 | ||
77 | #define BRDCFG2_REG_GPIO_SEL 0x20 | |
78 | ||
ffee1dde ZQ |
79 | /* SGMII */ |
80 | #define PHY_BASE_ADDR 0x00 | |
81 | #define REGNUM 0x00 | |
82 | #define PORT_NUM_FM1 0x04 | |
83 | #define PORT_NUM_FM2 0x02 | |
84 | ||
d31e53b4 TT |
85 | /* |
86 | * BRDCFG1 mask and value for each MAC | |
87 | * | |
88 | * This array contains the BRDCFG1 values (in mask/val format) that route the | |
89 | * MDIO bus to a particular RGMII or SGMII PHY. | |
90 | */ | |
91 | static struct { | |
92 | u8 mask; | |
93 | u8 val; | |
94 | } mdio_mux[NUM_FM_PORTS]; | |
95 | ||
96 | /* | |
97 | * Mapping of all 18 SERDES lanes to board slots. A value of '0' here means | |
98 | * that the mapping must be determined dynamically, or that the lane maps to | |
99 | * something other than a board slot | |
100 | */ | |
101 | static u8 lane_to_slot[] = { | |
102 | 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0 | |
103 | }; | |
104 | ||
105 | /* | |
106 | * Set the board muxing for a given MAC | |
107 | * | |
108 | * The MDIO layer calls this function every time it wants to talk to a PHY. | |
109 | */ | |
110 | void super_hydra_mux_mdio(u8 mask, u8 val) | |
111 | { | |
112 | clrsetbits_8(&pixis->brdcfg1, mask, val); | |
113 | } | |
114 | ||
115 | struct super_hydra_mdio { | |
116 | u8 mask; | |
117 | u8 val; | |
118 | struct mii_dev *realbus; | |
119 | }; | |
120 | ||
121 | static int super_hydra_mdio_read(struct mii_dev *bus, int addr, int devad, | |
122 | int regnum) | |
123 | { | |
124 | struct super_hydra_mdio *priv = bus->priv; | |
125 | ||
126 | super_hydra_mux_mdio(priv->mask, priv->val); | |
127 | ||
128 | return priv->realbus->read(priv->realbus, addr, devad, regnum); | |
129 | } | |
130 | ||
131 | static int super_hydra_mdio_write(struct mii_dev *bus, int addr, int devad, | |
132 | int regnum, u16 value) | |
133 | { | |
134 | struct super_hydra_mdio *priv = bus->priv; | |
135 | ||
136 | super_hydra_mux_mdio(priv->mask, priv->val); | |
137 | ||
138 | return priv->realbus->write(priv->realbus, addr, devad, regnum, value); | |
139 | } | |
140 | ||
141 | static int super_hydra_mdio_reset(struct mii_dev *bus) | |
142 | { | |
143 | struct super_hydra_mdio *priv = bus->priv; | |
144 | ||
145 | return priv->realbus->reset(priv->realbus); | |
146 | } | |
147 | ||
148 | static void super_hydra_mdio_set_mux(char *name, u8 mask, u8 val) | |
149 | { | |
150 | struct mii_dev *bus = miiphy_get_dev_by_name(name); | |
151 | struct super_hydra_mdio *priv = bus->priv; | |
152 | ||
153 | priv->mask = mask; | |
154 | priv->val = val; | |
155 | } | |
156 | ||
157 | static int super_hydra_mdio_init(char *realbusname, char *fakebusname) | |
158 | { | |
159 | struct super_hydra_mdio *hmdio; | |
160 | struct mii_dev *bus = mdio_alloc(); | |
161 | ||
162 | if (!bus) { | |
163 | printf("Failed to allocate Hydra MDIO bus\n"); | |
164 | return -1; | |
165 | } | |
166 | ||
167 | hmdio = malloc(sizeof(*hmdio)); | |
168 | if (!hmdio) { | |
169 | printf("Failed to allocate Hydra private data\n"); | |
170 | free(bus); | |
171 | return -1; | |
172 | } | |
173 | ||
174 | bus->read = super_hydra_mdio_read; | |
175 | bus->write = super_hydra_mdio_write; | |
176 | bus->reset = super_hydra_mdio_reset; | |
192bc694 | 177 | strcpy(bus->name, fakebusname); |
d31e53b4 TT |
178 | |
179 | hmdio->realbus = miiphy_get_dev_by_name(realbusname); | |
180 | ||
181 | if (!hmdio->realbus) { | |
182 | printf("No bus with name %s\n", realbusname); | |
183 | free(bus); | |
184 | free(hmdio); | |
185 | return -1; | |
186 | } | |
187 | ||
188 | bus->priv = hmdio; | |
189 | ||
190 | return mdio_register(bus); | |
191 | } | |
192 | ||
193 | /* | |
194 | * Given the following ... | |
195 | * | |
196 | * 1) A pointer to an Fman Ethernet node (as identified by the 'compat' | |
197 | * compatible string and 'addr' physical address) | |
198 | * | |
199 | * 2) An Fman port | |
200 | * | |
201 | * ... update the phy-handle property of the Ethernet node to point to the | |
202 | * right PHY. This assumes that we already know the PHY for each port. That | |
203 | * information is stored in mdio_mux[]. | |
204 | * | |
205 | * The offset of the Fman Ethernet node is also passed in for convenience, but | |
206 | * it is not used. | |
207 | * | |
208 | * Note that what we call "Fman ports" (enum fm_port) is really an Fman MAC. | |
209 | * Inside the Fman, "ports" are things that connect to MACs. We only call them | |
210 | * ports in U-Boot because on previous Ethernet devices (e.g. Gianfar), MACs | |
211 | * and ports are the same thing. | |
212 | */ | |
213 | void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr, | |
214 | enum fm_port port, int offset) | |
215 | { | |
216 | enum srds_prtcl device; | |
217 | int lane, slot, phy; | |
218 | char alias[32]; | |
219 | ||
220 | /* RGMII and XGMII are already mapped correctly in the DTS */ | |
221 | ||
222 | if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) { | |
223 | device = serdes_device_from_fm_port(port); | |
224 | lane = serdes_get_first_lane(device); | |
225 | slot = lane_to_slot[lane]; | |
226 | phy = fm_info_get_phy_address(port); | |
227 | ||
228 | sprintf(alias, "phy_sgmii_slot%u_%x", slot, phy); | |
229 | fdt_set_phy_handle(fdt, compat, addr, alias); | |
230 | } | |
231 | } | |
232 | ||
233 | #define PIXIS_SW2_LANE_23_SEL 0x80 | |
234 | #define PIXIS_SW2_LANE_45_SEL 0x40 | |
235 | #define PIXIS_SW2_LANE_67_SEL_MASK 0x30 | |
236 | #define PIXIS_SW2_LANE_67_SEL_5 0x00 | |
237 | #define PIXIS_SW2_LANE_67_SEL_6 0x20 | |
238 | #define PIXIS_SW2_LANE_67_SEL_7 0x10 | |
239 | #define PIXIS_SW2_LANE_8_SEL 0x08 | |
240 | #define PIXIS_SW2_LANE_1617_SEL 0x04 | |
241 | #define PIXIS_SW11_LANE_9_SEL 0x04 | |
242 | /* | |
243 | * Initialize the lane_to_slot[] array. | |
244 | * | |
245 | * On the P4080DS "Expedition" board, the mapping of SERDES lanes to board | |
246 | * slots is hard-coded. On the Hydra board, however, the mapping is controlled | |
247 | * by board switch SW2, so the lane_to_slot[] array needs to be dynamically | |
248 | * initialized. | |
249 | */ | |
250 | static void initialize_lane_to_slot(void) | |
251 | { | |
252 | u8 sw2 = in_8(&PIXIS_SW(2)); | |
253 | /* SW11 appears in the programming model as SW9 */ | |
254 | u8 sw11 = in_8(&PIXIS_SW(9)); | |
255 | ||
256 | lane_to_slot[2] = (sw2 & PIXIS_SW2_LANE_23_SEL) ? 7 : 4; | |
257 | lane_to_slot[3] = lane_to_slot[2]; | |
258 | ||
259 | lane_to_slot[4] = (sw2 & PIXIS_SW2_LANE_45_SEL) ? 7 : 6; | |
260 | lane_to_slot[5] = lane_to_slot[4]; | |
261 | ||
262 | switch (sw2 & PIXIS_SW2_LANE_67_SEL_MASK) { | |
263 | case PIXIS_SW2_LANE_67_SEL_5: | |
264 | lane_to_slot[6] = 5; | |
265 | break; | |
266 | case PIXIS_SW2_LANE_67_SEL_6: | |
267 | lane_to_slot[6] = 6; | |
268 | break; | |
269 | case PIXIS_SW2_LANE_67_SEL_7: | |
270 | lane_to_slot[6] = 7; | |
271 | break; | |
272 | } | |
273 | lane_to_slot[7] = lane_to_slot[6]; | |
274 | ||
275 | lane_to_slot[8] = (sw2 & PIXIS_SW2_LANE_8_SEL) ? 3 : 0; | |
276 | lane_to_slot[9] = (sw11 & PIXIS_SW11_LANE_9_SEL) ? 0 : 3; | |
277 | ||
278 | lane_to_slot[16] = (sw2 & PIXIS_SW2_LANE_1617_SEL) ? 1 : 0; | |
279 | lane_to_slot[17] = lane_to_slot[16]; | |
280 | } | |
281 | ||
282 | #endif /* #ifdef CONFIG_FMAN_ENET */ | |
283 | ||
284 | /* | |
285 | * Configure the status for the virtual MDIO nodes | |
286 | * | |
287 | * Rather than create the virtual MDIO nodes from scratch for each active | |
288 | * virtual MDIO, we expect the DTS to have the nodes defined already, and we | |
289 | * only enable the ones that are actually active. | |
290 | * | |
291 | * We assume that the DTS already hard-codes the status for all the | |
292 | * virtual MDIO nodes to "disabled", so all we need to do is enable the | |
293 | * active ones. | |
294 | */ | |
295 | void fdt_fixup_board_enet(void *fdt) | |
296 | { | |
297 | #ifdef CONFIG_FMAN_ENET | |
298 | enum fm_port i; | |
299 | int lane, slot; | |
300 | ||
301 | for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { | |
302 | int idx = i - FM1_DTSEC1; | |
303 | ||
304 | switch (fm_info_get_enet_if(i)) { | |
305 | case PHY_INTERFACE_MODE_SGMII: | |
306 | lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx); | |
307 | if (lane >= 0) { | |
308 | char alias[32]; | |
309 | ||
310 | slot = lane_to_slot[lane]; | |
311 | sprintf(alias, "hydra_sg_slot%u", slot); | |
312 | fdt_status_okay_by_alias(fdt, alias); | |
313 | debug("Enabled MDIO node %s (slot %i)\n", | |
314 | alias, slot); | |
315 | } | |
316 | break; | |
317 | case PHY_INTERFACE_MODE_RGMII: | |
318 | fdt_status_okay_by_alias(fdt, "hydra_rg"); | |
319 | debug("Enabled MDIO node hydra_rg\n"); | |
320 | break; | |
321 | default: | |
322 | break; | |
323 | } | |
324 | } | |
325 | ||
326 | lane = serdes_get_first_lane(XAUI_FM1); | |
327 | if (lane >= 0) { | |
328 | char alias[32]; | |
329 | ||
330 | slot = lane_to_slot[lane]; | |
331 | sprintf(alias, "hydra_xg_slot%u", slot); | |
332 | fdt_status_okay_by_alias(fdt, alias); | |
333 | debug("Enabled MDIO node %s (slot %i)\n", alias, slot); | |
334 | } | |
335 | ||
336 | #if CONFIG_SYS_NUM_FMAN == 2 | |
337 | for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) { | |
338 | int idx = i - FM2_DTSEC1; | |
339 | ||
340 | switch (fm_info_get_enet_if(i)) { | |
341 | case PHY_INTERFACE_MODE_SGMII: | |
342 | lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx); | |
343 | if (lane >= 0) { | |
344 | char alias[32]; | |
345 | ||
346 | slot = lane_to_slot[lane]; | |
347 | sprintf(alias, "hydra_sg_slot%u", slot); | |
348 | fdt_status_okay_by_alias(fdt, alias); | |
349 | debug("Enabled MDIO node %s (slot %i)\n", | |
350 | alias, slot); | |
351 | } | |
352 | break; | |
353 | case PHY_INTERFACE_MODE_RGMII: | |
354 | fdt_status_okay_by_alias(fdt, "hydra_rg"); | |
355 | debug("Enabled MDIO node hydra_rg\n"); | |
356 | break; | |
357 | default: | |
358 | break; | |
359 | } | |
360 | } | |
361 | ||
362 | lane = serdes_get_first_lane(XAUI_FM2); | |
363 | if (lane >= 0) { | |
364 | char alias[32]; | |
365 | ||
366 | slot = lane_to_slot[lane]; | |
367 | sprintf(alias, "hydra_xg_slot%u", slot); | |
368 | fdt_status_okay_by_alias(fdt, alias); | |
369 | debug("Enabled MDIO node %s (slot %i)\n", alias, slot); | |
370 | } | |
371 | #endif /* CONFIG_SYS_NUM_FMAN == 2 */ | |
372 | #endif /* CONFIG_FMAN_ENET */ | |
373 | } | |
374 | ||
375 | /* | |
376 | * Mapping of SerDes Protocol to MDIO MUX value and PHY address. | |
377 | * | |
378 | * Fman 1: | |
379 | * DTSEC1 | DTSEC2 | DTSEC3 | DTSEC4 | |
380 | * Mux Phy | Mux Phy | Mux Phy | Mux Phy | |
381 | * Value Addr | Value Addr | Value Addr | Value Addr | |
382 | * 0x00 2 1c | 2 1d | 2 1e | 2 1f | |
383 | * 0x01 | | 6 1c | | |
384 | * 0x02 | | 3 1c | 3 1d | |
385 | * 0x03 2 1c | 2 1d | 2 1e | 2 1f | |
386 | * 0x04 2 1c | 2 1d | 2 1e | 2 1f | |
387 | * 0x05 | | 3 1c | 3 1d | |
388 | * 0x06 2 1c | 2 1d | 2 1e | 2 1f | |
389 | * 0x07 | | 6 1c | | |
390 | * 0x11 2 1c | 2 1d | 2 1e | 2 1f | |
391 | * 0x2a 2 | | 2 1e | 2 1f | |
392 | * 0x34 6 1c | 6 1d | 4 1e | 4 1f | |
393 | * 0x35 | | 3 1c | 3 1d | |
394 | * 0x36 6 1c | 6 1d | 4 1e | 4 1f | |
395 | * | | | | |
396 | * Fman 2: | | | | |
397 | * DTSEC1 | DTSEC2 | DTSEC3 | DTSEC4 | |
398 | * EMI1 | EMI1 | EMI1 | EMI1 | |
399 | * Mux Phy | Mux Phy | Mux Phy | Mux Phy | |
400 | * Value Addr | Value Addr | Value Addr | Value Addr | |
401 | * 0x00 | | 6 1c | 6 1d | |
402 | * 0x01 | | | | |
403 | * 0x02 | | 6 1c | 6 1d | |
404 | * 0x03 3 1c | 3 1d | 6 1c | 6 1d | |
405 | * 0x04 3 1c | 3 1d | 6 1c | 6 1d | |
406 | * 0x05 | | 6 1c | 6 1d | |
407 | * 0x06 | | 6 1c | 6 1d | |
408 | * 0x07 | | | | |
409 | * 0x11 | | | | |
410 | * 0x2a | | | | |
411 | * 0x34 | | | | |
412 | * 0x35 | | | | |
413 | * 0x36 | | | | |
414 | */ | |
415 | ||
416 | int board_eth_init(bd_t *bis) | |
417 | { | |
418 | #ifdef CONFIG_FMAN_ENET | |
419 | struct fsl_pq_mdio_info dtsec_mdio_info; | |
420 | struct tgec_mdio_info tgec_mdio_info; | |
421 | unsigned int i, slot; | |
422 | int lane; | |
ffee1dde ZQ |
423 | struct mii_dev *bus; |
424 | int qsgmii; | |
425 | int phy_real_addr; | |
d31e53b4 TT |
426 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); |
427 | int srds_prtcl = (in_be32(&gur->rcwsr[4]) & | |
428 | FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26; | |
429 | ||
430 | printf("Initializing Fman\n"); | |
431 | ||
432 | initialize_lane_to_slot(); | |
433 | ||
434 | /* We want to use the PIXIS to configure MUX routing, not GPIOs. */ | |
435 | setbits_8(&pixis->brdcfg2, BRDCFG2_REG_GPIO_SEL); | |
436 | ||
437 | memset(mdio_mux, 0, sizeof(mdio_mux)); | |
438 | ||
439 | dtsec_mdio_info.regs = | |
440 | (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR; | |
441 | dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME; | |
442 | ||
443 | /* Register the real 1G MDIO bus */ | |
444 | fsl_pq_mdio_init(bis, &dtsec_mdio_info); | |
445 | ||
446 | tgec_mdio_info.regs = | |
447 | (struct tgec_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR; | |
448 | tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME; | |
449 | ||
450 | /* Register the real 10G MDIO bus */ | |
451 | fm_tgec_mdio_init(bis, &tgec_mdio_info); | |
452 | ||
453 | /* Register the three virtual MDIO front-ends */ | |
454 | super_hydra_mdio_init(DEFAULT_FM_MDIO_NAME, | |
455 | "SUPER_HYDRA_RGMII_MDIO"); | |
456 | super_hydra_mdio_init(DEFAULT_FM_MDIO_NAME, | |
457 | "SUPER_HYDRA_FM1_SGMII_MDIO"); | |
458 | super_hydra_mdio_init(DEFAULT_FM_MDIO_NAME, | |
459 | "SUPER_HYDRA_FM2_SGMII_MDIO"); | |
d5689824 ZQ |
460 | super_hydra_mdio_init(DEFAULT_FM_MDIO_NAME, |
461 | "SUPER_HYDRA_FM3_SGMII_MDIO"); | |
d31e53b4 TT |
462 | super_hydra_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME, |
463 | "SUPER_HYDRA_FM1_TGEC_MDIO"); | |
464 | super_hydra_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME, | |
465 | "SUPER_HYDRA_FM2_TGEC_MDIO"); | |
466 | ||
467 | /* | |
468 | * Program the DTSEC PHY addresses assuming that they are all SGMII. | |
469 | * For any DTSEC that's RGMII, we'll override its PHY address later. | |
470 | * We assume that DTSEC5 is only used for RGMII. | |
471 | */ | |
472 | fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR); | |
473 | fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR); | |
474 | fm_info_set_phy_address(FM1_10GEC1, CONFIG_SYS_FM2_10GEC1_PHY_ADDR); | |
475 | ||
476 | #if (CONFIG_SYS_NUM_FMAN == 2) | |
477 | fm_info_set_phy_address(FM2_DTSEC1, CONFIG_SYS_FM2_DTSEC1_PHY_ADDR); | |
478 | fm_info_set_phy_address(FM2_DTSEC2, CONFIG_SYS_FM2_DTSEC2_PHY_ADDR); | |
479 | fm_info_set_phy_address(FM2_DTSEC3, CONFIG_SYS_FM2_DTSEC1_PHY_ADDR); | |
480 | fm_info_set_phy_address(FM2_DTSEC4, CONFIG_SYS_FM2_DTSEC2_PHY_ADDR); | |
481 | fm_info_set_phy_address(FM2_10GEC1, CONFIG_SYS_FM1_10GEC1_PHY_ADDR); | |
482 | #endif | |
483 | ||
484 | switch (srds_prtcl) { | |
485 | case 0: | |
486 | case 3: | |
487 | case 4: | |
488 | case 6: | |
489 | case 0x11: | |
490 | case 0x2a: | |
491 | case 0x34: | |
492 | case 0x36: | |
493 | fm_info_set_phy_address(FM1_DTSEC3, | |
494 | CONFIG_SYS_FM1_DTSEC3_PHY_ADDR); | |
495 | fm_info_set_phy_address(FM1_DTSEC4, | |
496 | CONFIG_SYS_FM1_DTSEC4_PHY_ADDR); | |
497 | break; | |
498 | case 1: | |
499 | case 2: | |
500 | case 5: | |
501 | case 7: | |
502 | case 0x35: | |
503 | fm_info_set_phy_address(FM1_DTSEC3, | |
504 | CONFIG_SYS_FM1_DTSEC1_PHY_ADDR); | |
505 | fm_info_set_phy_address(FM1_DTSEC4, | |
506 | CONFIG_SYS_FM1_DTSEC2_PHY_ADDR); | |
507 | break; | |
508 | default: | |
509 | printf("Fman: Unsupport SerDes Protocol 0x%02x\n", srds_prtcl); | |
510 | break; | |
511 | } | |
512 | ||
513 | for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { | |
514 | int idx = i - FM1_DTSEC1; | |
515 | ||
516 | switch (fm_info_get_enet_if(i)) { | |
517 | case PHY_INTERFACE_MODE_SGMII: | |
518 | lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx); | |
519 | if (lane < 0) | |
520 | break; | |
521 | slot = lane_to_slot[lane]; | |
522 | mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK; | |
523 | debug("FM1@DTSEC%u expects SGMII in slot %u\n", | |
524 | idx + 1, slot); | |
525 | switch (slot) { | |
526 | case 1: | |
527 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT1 | | |
528 | BRDCFG1_EMI1_EN; | |
529 | break; | |
530 | case 2: | |
531 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT2 | | |
532 | BRDCFG1_EMI1_EN; | |
533 | break; | |
534 | case 3: | |
535 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT3 | | |
536 | BRDCFG1_EMI1_EN; | |
537 | break; | |
538 | case 5: | |
539 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT5 | | |
540 | BRDCFG1_EMI1_EN; | |
541 | break; | |
542 | case 6: | |
543 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT6 | | |
544 | BRDCFG1_EMI1_EN; | |
545 | break; | |
546 | case 7: | |
547 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT7 | | |
548 | BRDCFG1_EMI1_EN; | |
549 | break; | |
550 | }; | |
551 | ||
552 | super_hydra_mdio_set_mux("SUPER_HYDRA_FM1_SGMII_MDIO", | |
553 | mdio_mux[i].mask, mdio_mux[i].val); | |
554 | fm_info_set_mdio(i, | |
555 | miiphy_get_dev_by_name("SUPER_HYDRA_FM1_SGMII_MDIO")); | |
556 | break; | |
557 | case PHY_INTERFACE_MODE_RGMII: | |
558 | /* | |
559 | * FM1 DTSEC5 is routed via EC1 to the first on-board | |
560 | * RGMII port. FM2 DTSEC5 is routed via EC2 to the | |
561 | * second on-board RGMII port. The other DTSECs cannot | |
562 | * be routed to RGMII. | |
563 | */ | |
564 | debug("FM1@DTSEC%u is RGMII at address %u\n", | |
565 | idx + 1, 0); | |
566 | fm_info_set_phy_address(i, 0); | |
567 | mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK; | |
568 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_RGMII | | |
569 | BRDCFG1_EMI1_EN; | |
570 | super_hydra_mdio_set_mux("SUPER_HYDRA_RGMII_MDIO", | |
571 | mdio_mux[i].mask, mdio_mux[i].val); | |
572 | fm_info_set_mdio(i, | |
573 | miiphy_get_dev_by_name("SUPER_HYDRA_RGMII_MDIO")); | |
574 | break; | |
575 | case PHY_INTERFACE_MODE_NONE: | |
576 | fm_info_set_phy_address(i, 0); | |
577 | break; | |
578 | default: | |
579 | printf("Fman1: DTSEC%u set to unknown interface %i\n", | |
580 | idx + 1, fm_info_get_enet_if(i)); | |
581 | fm_info_set_phy_address(i, 0); | |
582 | break; | |
583 | } | |
584 | } | |
585 | ||
ffee1dde ZQ |
586 | bus = miiphy_get_dev_by_name("SUPER_HYDRA_FM1_SGMII_MDIO"); |
587 | qsgmii = is_qsgmii_riser_card(bus, PHY_BASE_ADDR, PORT_NUM_FM1, REGNUM); | |
588 | ||
589 | if (qsgmii) { | |
590 | for (i = FM1_DTSEC1; i < FM1_DTSEC1 + PORT_NUM_FM1; i++) { | |
591 | if (fm_info_get_enet_if(i) == | |
592 | PHY_INTERFACE_MODE_SGMII) { | |
593 | phy_real_addr = PHY_BASE_ADDR + i - FM1_DTSEC1; | |
594 | fm_info_set_phy_address(i, phy_real_addr); | |
595 | } | |
596 | } | |
597 | switch (srds_prtcl) { | |
598 | case 0x00: | |
599 | case 0x03: | |
600 | case 0x04: | |
601 | case 0x06: | |
602 | case 0x11: | |
603 | case 0x2a: | |
604 | case 0x34: | |
605 | case 0x36: | |
606 | fm_info_set_phy_address(FM1_DTSEC3, PHY_BASE_ADDR + 2); | |
607 | fm_info_set_phy_address(FM1_DTSEC4, PHY_BASE_ADDR + 3); | |
608 | break; | |
609 | case 0x01: | |
610 | case 0x02: | |
611 | case 0x05: | |
612 | case 0x07: | |
613 | case 0x35: | |
614 | fm_info_set_phy_address(FM1_DTSEC3, PHY_BASE_ADDR + 0); | |
615 | fm_info_set_phy_address(FM1_DTSEC4, PHY_BASE_ADDR + 1); | |
616 | break; | |
617 | default: | |
618 | break; | |
619 | } | |
620 | } | |
621 | ||
d31e53b4 TT |
622 | /* |
623 | * For 10G, we only support one XAUI card per Fman. If present, then we | |
624 | * force its routing and never touch those bits again, which removes the | |
625 | * need for Linux to do any muxing. This works because of the way | |
626 | * BRDCFG1 is defined, but it's a bit hackish. | |
627 | * | |
628 | * The PHY address for the XAUI card depends on which slot it's in. The | |
629 | * macros we use imply that the PHY address is based on which FM, but | |
630 | * that's not true. On the P4080DS, FM1 could only use XAUI in slot 5, | |
631 | * and FM2 could only use a XAUI in slot 4. On the Hydra board, we | |
632 | * check the actual slot and just use the macros as-is, even though | |
633 | * the P3041 and P5020 only have one Fman. | |
634 | */ | |
635 | lane = serdes_get_first_lane(XAUI_FM1); | |
636 | if (lane >= 0) { | |
637 | debug("FM1@TGEC1 expects XAUI in slot %u\n", lane_to_slot[lane]); | |
e14cdc0a SX |
638 | mdio_mux[i].mask = BRDCFG1_EMI2_SEL_MASK; |
639 | mdio_mux[i].val = BRDCFG1_EMI2_SEL_SLOT2; | |
d31e53b4 TT |
640 | super_hydra_mdio_set_mux("SUPER_HYDRA_FM1_TGEC_MDIO", |
641 | mdio_mux[i].mask, mdio_mux[i].val); | |
642 | } | |
643 | ||
644 | fm_info_set_mdio(FM1_10GEC1, | |
645 | miiphy_get_dev_by_name("SUPER_HYDRA_FM1_TGEC_MDIO")); | |
646 | ||
647 | #if (CONFIG_SYS_NUM_FMAN == 2) | |
648 | for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) { | |
649 | int idx = i - FM2_DTSEC1; | |
650 | ||
651 | switch (fm_info_get_enet_if(i)) { | |
652 | case PHY_INTERFACE_MODE_SGMII: | |
653 | lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx); | |
654 | if (lane < 0) | |
655 | break; | |
656 | slot = lane_to_slot[lane]; | |
657 | mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK; | |
658 | debug("FM2@DTSEC%u expects SGMII in slot %u\n", | |
659 | idx + 1, slot); | |
660 | switch (slot) { | |
661 | case 1: | |
662 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT1 | | |
663 | BRDCFG1_EMI1_EN; | |
664 | break; | |
665 | case 2: | |
666 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT2 | | |
667 | BRDCFG1_EMI1_EN; | |
668 | break; | |
669 | case 3: | |
670 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT3 | | |
671 | BRDCFG1_EMI1_EN; | |
672 | break; | |
673 | case 5: | |
674 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT5 | | |
675 | BRDCFG1_EMI1_EN; | |
676 | break; | |
677 | case 6: | |
678 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT6 | | |
679 | BRDCFG1_EMI1_EN; | |
680 | break; | |
681 | case 7: | |
682 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT7 | | |
683 | BRDCFG1_EMI1_EN; | |
684 | break; | |
685 | }; | |
686 | ||
d5689824 ZQ |
687 | if (i == FM2_DTSEC1 || i == FM2_DTSEC2) { |
688 | super_hydra_mdio_set_mux( | |
689 | "SUPER_HYDRA_FM3_SGMII_MDIO", | |
690 | mdio_mux[i].mask, | |
691 | mdio_mux[i].val); | |
692 | fm_info_set_mdio(i, miiphy_get_dev_by_name( | |
693 | "SUPER_HYDRA_FM3_SGMII_MDIO")); | |
694 | } else { | |
695 | super_hydra_mdio_set_mux( | |
696 | "SUPER_HYDRA_FM2_SGMII_MDIO", | |
697 | mdio_mux[i].mask, | |
698 | mdio_mux[i].val); | |
699 | fm_info_set_mdio(i, miiphy_get_dev_by_name( | |
700 | "SUPER_HYDRA_FM2_SGMII_MDIO")); | |
701 | } | |
702 | ||
d31e53b4 TT |
703 | break; |
704 | case PHY_INTERFACE_MODE_RGMII: | |
705 | /* | |
706 | * FM1 DTSEC5 is routed via EC1 to the first on-board | |
707 | * RGMII port. FM2 DTSEC5 is routed via EC2 to the | |
708 | * second on-board RGMII port. The other DTSECs cannot | |
709 | * be routed to RGMII. | |
710 | */ | |
711 | debug("FM2@DTSEC%u is RGMII at address %u\n", | |
712 | idx + 1, 1); | |
713 | fm_info_set_phy_address(i, 1); | |
714 | mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK; | |
715 | mdio_mux[i].val = BRDCFG1_EMI1_SEL_RGMII | | |
716 | BRDCFG1_EMI1_EN; | |
717 | super_hydra_mdio_set_mux("SUPER_HYDRA_RGMII_MDIO", | |
718 | mdio_mux[i].mask, mdio_mux[i].val); | |
719 | fm_info_set_mdio(i, | |
720 | miiphy_get_dev_by_name("SUPER_HYDRA_RGMII_MDIO")); | |
721 | break; | |
722 | case PHY_INTERFACE_MODE_NONE: | |
723 | fm_info_set_phy_address(i, 0); | |
724 | break; | |
725 | default: | |
726 | printf("Fman2: DTSEC%u set to unknown interface %i\n", | |
727 | idx + 1, fm_info_get_enet_if(i)); | |
728 | fm_info_set_phy_address(i, 0); | |
729 | break; | |
730 | } | |
731 | } | |
732 | ||
ffee1dde ZQ |
733 | bus = miiphy_get_dev_by_name("SUPER_HYDRA_FM2_SGMII_MDIO"); |
734 | set_sgmii_phy(bus, FM2_DTSEC3, PORT_NUM_FM2, PHY_BASE_ADDR); | |
735 | bus = miiphy_get_dev_by_name("SUPER_HYDRA_FM3_SGMII_MDIO"); | |
736 | set_sgmii_phy(bus, FM2_DTSEC1, PORT_NUM_FM2, PHY_BASE_ADDR); | |
737 | ||
d31e53b4 TT |
738 | /* |
739 | * For 10G, we only support one XAUI card per Fman. If present, then we | |
740 | * force its routing and never touch those bits again, which removes the | |
741 | * need for Linux to do any muxing. This works because of the way | |
742 | * BRDCFG1 is defined, but it's a bit hackish. | |
743 | * | |
744 | * The PHY address for the XAUI card depends on which slot it's in. The | |
745 | * macros we use imply that the PHY address is based on which FM, but | |
746 | * that's not true. On the P4080DS, FM1 could only use XAUI in slot 5, | |
747 | * and FM2 could only use a XAUI in slot 4. On the Hydra board, we | |
748 | * check the actual slot and just use the macros as-is, even though | |
749 | * the P3041 and P5020 only have one Fman. | |
750 | */ | |
751 | lane = serdes_get_first_lane(XAUI_FM2); | |
752 | if (lane >= 0) { | |
753 | debug("FM2@TGEC1 expects XAUI in slot %u\n", lane_to_slot[lane]); | |
e14cdc0a SX |
754 | mdio_mux[i].mask = BRDCFG1_EMI2_SEL_MASK; |
755 | mdio_mux[i].val = BRDCFG1_EMI2_SEL_SLOT1; | |
d31e53b4 TT |
756 | super_hydra_mdio_set_mux("SUPER_HYDRA_FM2_TGEC_MDIO", |
757 | mdio_mux[i].mask, mdio_mux[i].val); | |
758 | } | |
759 | ||
760 | fm_info_set_mdio(FM2_10GEC1, | |
761 | miiphy_get_dev_by_name("SUPER_HYDRA_FM2_TGEC_MDIO")); | |
762 | ||
763 | #endif | |
764 | ||
765 | cpu_eth_init(bis); | |
766 | #endif | |
767 | ||
768 | return pci_eth_init(bis); | |
769 | } |