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