blob: 6d5f3d1fda05dc02bb6f6a2353b31047de48d242 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
York Sun0789dc92012-12-23 19:25:27 +00002/*
3 * Copyright 2012 Freescale Semiconductor, Inc.
4 * Author: Sandeep Kumar Singh <sandeep@freescale.com>
York Sun0789dc92012-12-23 19:25:27 +00005 */
6
7/* This file is based on board/freescale/corenet_ds/eth_superhydra.c */
8
9/*
10 * This file handles the board muxing between the Fman Ethernet MACs and
11 * the RGMII/SGMII/XGMII PHYs on a Freescale B4860 "Centaur". The SGMII
12 * PHYs are the two on-board 1Gb ports. There are no RGMII PHY on board.
13 * The 10Gb XGMII PHY is provided via the XAUI riser card. There is only
14 * one Fman device on B4860. The SERDES configuration is used to determine
15 * where the SGMII and XAUI cards exist, and also which Fman MACs are routed
16 * to which PHYs. So for a given Fman MAC, there is one and only PHY it
17 * connects to. MACs cannot be routed to PHYs dynamically. This configuration
18 * is done at boot time by reading SERDES protocol from RCW.
19 */
20
21#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -060022#include <log.h>
Simon Glass274e0b02020-05-10 11:39:56 -060023#include <net.h>
York Sun0789dc92012-12-23 19:25:27 +000024#include <netdev.h>
25#include <asm/fsl_serdes.h>
26#include <fm_eth.h>
27#include <fsl_mdio.h>
28#include <malloc.h>
29#include <fdt_support.h>
Shaohui Xie513eaf22015-10-26 19:47:47 +080030#include <fsl_dtsec.h>
York Sun0789dc92012-12-23 19:25:27 +000031
32#include "../common/ngpixis.h"
33#include "../common/fman.h"
34#include "../common/qixis.h"
35#include "b4860qds_qixis.h"
36
37#define EMI_NONE 0xFFFFFFFF
38
39#ifdef CONFIG_FMAN_ENET
40
41/*
42 * Mapping of all 16 SERDES lanes to board slots. A value n(>0) will mean that
43 * lane at index is mapped to slot number n. A value of '0' will mean
44 * that the mapping must be determined dynamically, or that the lane maps to
45 * something other than a board slot
46 */
47static u8 lane_to_slot[] = {
48 0, 0, 0, 0,
49 0, 0, 0, 0,
50 1, 1, 1, 1,
51 0, 0, 0, 0
52};
53
54/*
55 * This function initializes the lane_to_slot[] array. It reads RCW to check
56 * if Serdes2{E,F,G,H} is configured as slot 2 or as SFP and initializes
57 * lane_to_slot[] accordingly
58 */
59static void initialize_lane_to_slot(void)
60{
61 unsigned int serdes2_prtcl;
62 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
63 serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
64 FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
65 serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
66 debug("Initializing lane to slot: Serdes2 protocol: %x\n",
67 serdes2_prtcl);
68
69 switch (serdes2_prtcl) {
poonam aggrwal331dd1d2014-02-17 08:38:58 +053070 case 0x17:
York Sun0789dc92012-12-23 19:25:27 +000071 case 0x18:
72 /*
73 * Configuration:
74 * SERDES: 2
75 * Lanes: A,B,C,D: SGMII
76 * Lanes: E,F: Aur
77 * Lanes: G,H: SRIO
78 */
79 case 0x91:
80 /*
81 * Configuration:
82 * SERDES: 2
83 * Lanes: A,B: SGMII
84 * Lanes: C,D: SRIO2
85 * Lanes: E,F,G,H: XAUI2
86 */
87 case 0x93:
88 /*
89 * Configuration:
90 * SERDES: 2
91 * Lanes: A,B,C,D: SGMII
92 * Lanes: E,F,G,H: XAUI2
93 */
94 case 0x98:
95 /*
96 * Configuration:
97 * SERDES: 2
98 * Lanes: A,B,C,D: XAUI2
99 * Lanes: E,F,G,H: XAUI2
100 */
101 case 0x9a:
102 /*
103 * Configuration:
104 * SERDES: 2
105 * Lanes: A,B: PCI
106 * Lanes: C,D: SGMII
107 * Lanes: E,F,G,H: XAUI2
108 */
109 case 0x9e:
110 /*
111 * Configuration:
112 * SERDES: 2
113 * Lanes: A,B,C,D: PCI
114 * Lanes: E,F,G,H: XAUI2
115 */
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530116 case 0xb1:
York Sun0789dc92012-12-23 19:25:27 +0000117 case 0xb2:
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530118 case 0x8c:
119 case 0x8d:
York Sun0789dc92012-12-23 19:25:27 +0000120 /*
121 * Configuration:
122 * SERDES: 2
123 * Lanes: A,B,C,D: PCI
124 * Lanes: E,F: SGMII 3&4
125 * Lanes: G,H: XFI
126 */
127 case 0xc2:
128 /*
129 * Configuration:
130 * SERDES: 2
131 * Lanes: A,B: SGMII
132 * Lanes: C,D: SRIO2
133 * Lanes: E,F,G,H: XAUI2
134 */
135 lane_to_slot[12] = 2;
136 lane_to_slot[13] = lane_to_slot[12];
137 lane_to_slot[14] = lane_to_slot[12];
138 lane_to_slot[15] = lane_to_slot[12];
139 break;
140
141 default:
142 printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n",
143 serdes2_prtcl);
144 break;
145 }
146 return;
147}
148
149#endif /* #ifdef CONFIG_FMAN_ENET */
150
151int board_eth_init(bd_t *bis)
152{
153#ifdef CONFIG_FMAN_ENET
154 struct memac_mdio_info memac_mdio_info;
155 struct memac_mdio_info tg_memac_mdio_info;
156 unsigned int i;
157 unsigned int serdes1_prtcl, serdes2_prtcl;
Zhao Qiang1ae99192013-09-04 10:11:27 +0800158 int qsgmii;
159 struct mii_dev *bus;
York Sun0789dc92012-12-23 19:25:27 +0000160 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
161 serdes1_prtcl = in_be32(&gur->rcwsr[4]) &
162 FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
163 if (!serdes1_prtcl) {
164 printf("SERDES1 is not enabled\n");
165 return 0;
166 }
167 serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
168 debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
169
170 serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
171 FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
172 if (!serdes2_prtcl) {
173 printf("SERDES2 is not enabled\n");
174 return 0;
175 }
176 serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
177 debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl);
178
179 printf("Initializing Fman\n");
180
181 initialize_lane_to_slot();
182
183 memac_mdio_info.regs =
184 (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
185 memac_mdio_info.name = DEFAULT_FM_MDIO_NAME;
186
187 /* Register the real 1G MDIO bus */
188 fm_memac_mdio_init(bis, &memac_mdio_info);
189
190 tg_memac_mdio_info.regs =
191 (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
192 tg_memac_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
193
194 /* Register the real 10G MDIO bus */
195 fm_memac_mdio_init(bis, &tg_memac_mdio_info);
196
197 /*
198 * Program the two on board DTSEC PHY addresses assuming that they are
199 * all SGMII. RGMII is not supported on this board. Setting SGMII 5 and
200 * 6 to on board SGMII phys
201 */
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530202 fm_info_set_phy_address(FM1_DTSEC5, CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR);
203 fm_info_set_phy_address(FM1_DTSEC6, CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000204
205 switch (serdes1_prtcl) {
poonam aggrwal331dd1d2014-02-17 08:38:58 +0530206 case 0x29:
York Sun0789dc92012-12-23 19:25:27 +0000207 case 0x2a:
208 /* Serdes 1: A-B SGMII, Configuring DTSEC 5 and 6 */
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530209 debug("Set phy addresses for FM1_DTSEC5:%x, FM1_DTSEC6:%x\n",
210 CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR,
211 CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000212 fm_info_set_phy_address(FM1_DTSEC5,
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530213 CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000214 fm_info_set_phy_address(FM1_DTSEC6,
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530215 CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000216 break;
York Sunfda566d2016-11-18 11:56:57 -0800217#ifdef CONFIG_ARCH_B4420
poonam aggrwal331dd1d2014-02-17 08:38:58 +0530218 case 0x17:
York Sun0789dc92012-12-23 19:25:27 +0000219 case 0x18:
220 /* Serdes 1: A-D SGMII, Configuring on board dual SGMII Phy */
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530221 debug("Set phy addresses for FM1_DTSEC3:%x, FM1_DTSEC4:%x\n",
222 CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR,
223 CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000224 /* Fixing Serdes clock by programming FPGA register */
225 QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125);
226 fm_info_set_phy_address(FM1_DTSEC3,
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530227 CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000228 fm_info_set_phy_address(FM1_DTSEC4,
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530229 CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000230 break;
231#endif
232 default:
233 printf("Fman: Unsupported SerDes1 Protocol 0x%02x\n",
234 serdes1_prtcl);
235 break;
236 }
237 switch (serdes2_prtcl) {
poonam aggrwal331dd1d2014-02-17 08:38:58 +0530238 case 0x17:
York Sun0789dc92012-12-23 19:25:27 +0000239 case 0x18:
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530240 debug("Set phy address on SGMII Riser for FM1_DTSEC1:%x\n",
241 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000242 fm_info_set_phy_address(FM1_DTSEC1,
243 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
244 fm_info_set_phy_address(FM1_DTSEC2,
245 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
246 fm_info_set_phy_address(FM1_DTSEC3,
247 CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR);
248 fm_info_set_phy_address(FM1_DTSEC4,
249 CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR);
250 break;
poonam aggrwal331dd1d2014-02-17 08:38:58 +0530251 case 0x48:
York Sun0789dc92012-12-23 19:25:27 +0000252 case 0x49:
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530253 debug("Set phy address on SGMII Riser for FM1_DTSEC1:%x\n",
254 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000255 fm_info_set_phy_address(FM1_DTSEC1,
256 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
257 fm_info_set_phy_address(FM1_DTSEC2,
258 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
259 fm_info_set_phy_address(FM1_DTSEC3,
260 CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR);
261 break;
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530262 case 0xb1:
York Sun0789dc92012-12-23 19:25:27 +0000263 case 0xb2:
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530264 case 0x8c:
265 case 0x8d:
266 debug("Set phy addresses on SGMII Riser for FM1_DTSEC1:%x\n",
267 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
York Sun0789dc92012-12-23 19:25:27 +0000268 fm_info_set_phy_address(FM1_DTSEC3,
269 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
270 fm_info_set_phy_address(FM1_DTSEC4,
271 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
Shaohui Xie37c82b52014-11-13 11:26:19 +0800272 /*
Bin Meng75574052016-02-05 19:30:11 -0800273 * XFI does not need a PHY to work, but to make U-Boot
Shaohui Xie37c82b52014-11-13 11:26:19 +0800274 * happy, assign a fake PHY address for a XFI port.
275 */
276 fm_info_set_phy_address(FM1_10GEC1, 0);
277 fm_info_set_phy_address(FM1_10GEC2, 1);
York Sun0789dc92012-12-23 19:25:27 +0000278 break;
Suresh Gupta4c3db712013-03-25 07:40:13 +0000279 case 0x98:
280 /* XAUI in Slot1 and Slot2 */
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530281 debug("Set phy address of AMC2PEX-2S for FM1_10GEC1:%x\n",
Suresh Gupta4c3db712013-03-25 07:40:13 +0000282 CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
283 fm_info_set_phy_address(FM1_10GEC1,
284 CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530285 debug("Set phy address of AMC2PEX-2S for FM1_10GEC2:%x\n",
Suresh Gupta4c3db712013-03-25 07:40:13 +0000286 CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
287 fm_info_set_phy_address(FM1_10GEC2,
288 CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
289 break;
290 case 0x9E:
291 /* XAUI in Slot2 */
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530292 debug("Sett phy address of AMC2PEX-2S for FM1_10GEC2:%x\n",
Suresh Gupta4c3db712013-03-25 07:40:13 +0000293 CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
294 fm_info_set_phy_address(FM1_10GEC2,
295 CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
296 break;
York Sun0789dc92012-12-23 19:25:27 +0000297 default:
298 printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n",
299 serdes2_prtcl);
300 break;
301 }
302
Zhao Qiang1ae99192013-09-04 10:11:27 +0800303 /*set PHY address for QSGMII Riser Card on slot2*/
304 bus = miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME);
305 qsgmii = is_qsgmii_riser_card(bus, PHY_BASE_ADDR, PORT_NUM, REGNUM);
306
307 if (qsgmii) {
308 switch (serdes2_prtcl) {
309 case 0xb2:
310 case 0x8d:
311 fm_info_set_phy_address(FM1_DTSEC3, PHY_BASE_ADDR);
312 fm_info_set_phy_address(FM1_DTSEC4, PHY_BASE_ADDR + 1);
313 break;
314 default:
315 break;
316 }
317 }
318
York Sun0789dc92012-12-23 19:25:27 +0000319 for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
320 int idx = i - FM1_DTSEC1;
321
322 switch (fm_info_get_enet_if(i)) {
323 case PHY_INTERFACE_MODE_SGMII:
324 fm_info_set_mdio(i,
325 miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
326 break;
327 case PHY_INTERFACE_MODE_NONE:
328 fm_info_set_phy_address(i, 0);
329 break;
330 default:
331 printf("Fman1: DTSEC%u set to unknown interface %i\n",
332 idx + 1, fm_info_get_enet_if(i));
333 fm_info_set_phy_address(i, 0);
334 break;
335 }
336 }
337
Suresh Gupta4c3db712013-03-25 07:40:13 +0000338 for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) {
339 int idx = i - FM1_10GEC1;
340
341 switch (fm_info_get_enet_if(i)) {
342 case PHY_INTERFACE_MODE_XGMII:
343 fm_info_set_mdio(i,
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530344 miiphy_get_dev_by_name
345 (DEFAULT_FM_TGEC_MDIO_NAME));
346 break;
347 case PHY_INTERFACE_MODE_NONE:
348 fm_info_set_phy_address(i, 0);
Suresh Gupta4c3db712013-03-25 07:40:13 +0000349 break;
350 default:
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530351 printf("Fman1: TGEC%u set to unknown interface %i\n",
Suresh Gupta4c3db712013-03-25 07:40:13 +0000352 idx + 1, fm_info_get_enet_if(i));
353 fm_info_set_phy_address(i, 0);
354 break;
355 }
356 }
357
York Sun0789dc92012-12-23 19:25:27 +0000358 cpu_eth_init(bis);
359#endif
360
361 return pci_eth_init(bis);
362}
363
364void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
365 enum fm_port port, int offset)
366{
367 int phy;
368 char alias[32];
Shaohui Xie2c033832014-11-13 11:27:12 +0800369 struct fixed_link f_link;
370 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
371 u32 prtcl2 = in_be32(&gur->rcwsr[4]) & FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
372
373 prtcl2 >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
York Sun0789dc92012-12-23 19:25:27 +0000374
375 if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) {
376 phy = fm_info_get_phy_address(port);
377
378 sprintf(alias, "phy_sgmii_%x", phy);
379 fdt_set_phy_handle(fdt, compat, addr, alias);
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530380 fdt_status_okay_by_alias(fdt, alias);
Shaohui Xie2c033832014-11-13 11:27:12 +0800381 } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_XGMII) {
382 /* check if it's XFI interface for 10g */
383 switch (prtcl2) {
384 case 0x80:
385 case 0x81:
386 case 0x82:
387 case 0x83:
388 case 0x84:
389 case 0x85:
390 case 0x86:
391 case 0x87:
392 case 0x88:
393 case 0x89:
394 case 0x8a:
395 case 0x8b:
396 case 0x8c:
397 case 0x8d:
398 case 0x8e:
399 case 0xb1:
400 case 0xb2:
401 f_link.phy_id = port;
402 f_link.duplex = 1;
403 f_link.link_speed = 10000;
404 f_link.pause = 0;
405 f_link.asym_pause = 0;
406
407 fdt_delprop(fdt, offset, "phy-handle");
408 fdt_setprop(fdt, offset, "fixed-link", &f_link,
409 sizeof(f_link));
410 break;
Suresh Gupta52c79d62014-11-13 11:28:09 +0800411 case 0x98: /* XAUI interface */
Ben Whitten34fd6c92015-12-30 13:05:58 +0000412 strcpy(alias, "phy_xaui_slot1");
Suresh Gupta52c79d62014-11-13 11:28:09 +0800413 fdt_status_okay_by_alias(fdt, alias);
414
Ben Whitten34fd6c92015-12-30 13:05:58 +0000415 strcpy(alias, "phy_xaui_slot2");
Suresh Gupta52c79d62014-11-13 11:28:09 +0800416 fdt_status_okay_by_alias(fdt, alias);
417 break;
418 case 0x9e: /* XAUI interface */
419 case 0x9a:
420 case 0x93:
421 case 0x91:
Ben Whitten34fd6c92015-12-30 13:05:58 +0000422 strcpy(alias, "phy_xaui_slot1");
Suresh Gupta52c79d62014-11-13 11:28:09 +0800423 fdt_status_okay_by_alias(fdt, alias);
424 break;
425 case 0x97: /* XAUI interface */
426 case 0xc3:
Ben Whitten34fd6c92015-12-30 13:05:58 +0000427 strcpy(alias, "phy_xaui_slot2");
Suresh Gupta52c79d62014-11-13 11:28:09 +0800428 fdt_status_okay_by_alias(fdt, alias);
429 break;
Shaohui Xie2c033832014-11-13 11:27:12 +0800430 default:
431 break;
432 }
York Sun0789dc92012-12-23 19:25:27 +0000433 }
434}
435
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530436/*
437 * Set status to disabled for unused ethernet node
438 */
York Sun0789dc92012-12-23 19:25:27 +0000439void fdt_fixup_board_enet(void *fdt)
440{
441 int i;
442 char alias[32];
443
Shaveta Leekha7c689e22014-11-12 16:00:22 +0530444 for (i = FM1_DTSEC1; i <= FM1_10GEC2; i++) {
York Sun0789dc92012-12-23 19:25:27 +0000445 switch (fm_info_get_enet_if(i)) {
446 case PHY_INTERFACE_MODE_NONE:
447 sprintf(alias, "ethernet%u", i);
448 fdt_status_disabled_by_alias(fdt, alias);
449 break;
450 default:
451 break;
452 }
453 }
454}