blob: e1919d298855cc64485a971d376e212d8cfe53e7 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Shaohui Xiedd335672015-11-11 17:58:37 +08002/*
3 * Copyright 2015 Freescale Semiconductor, Inc.
Pankaj Bansalc8861b62019-04-22 06:31:42 +00004 * Copyright 2019 NXP
Shaohui Xiedd335672015-11-11 17:58:37 +08005 */
6
7#include <common.h>
8#include <asm/io.h>
9#include <netdev.h>
Simon Glasse3ee2fb2016-02-22 22:55:43 -070010#include <fdt_support.h>
Shaohui Xiedd335672015-11-11 17:58:37 +080011#include <fm_eth.h>
12#include <fsl_mdio.h>
13#include <fsl_dtsec.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090014#include <linux/libfdt.h>
Shaohui Xiedd335672015-11-11 17:58:37 +080015#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
31static int mdio_mux[NUM_FM_PORTS];
32
33static 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 */
44static u8 lane_to_slot[] = {1, 2, 3, 4};
45
46static const char *ls1043aqds_mdio_name_for_muxval(u8 muxval)
47{
48 return mdio_names[muxval];
49}
50
51struct 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
76struct ls1043aqds_mdio {
77 u8 muxval;
78 struct mii_dev *realbus;
79};
80
81static 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
93static 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
103static 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
114static 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
121static 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;
Ben Whitten34fd6c92015-12-30 13:05:58 +0000141 strcpy(bus->name, ls1043aqds_mdio_name_for_muxval(muxval));
Shaohui Xiedd335672015-11-11 17:58:37 +0800142
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
157void 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,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000165 "sgmii-riser-s1-p1");
Shaohui Xiedd335672015-11-11 17:58:37 +0800166 } else if (port == FM1_DTSEC2) {
167 fdt_set_phy_handle(fdt, compat, addr,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000168 "sgmii-riser-s2-p1");
Shaohui Xiedd335672015-11-11 17:58:37 +0800169 } else if (port == FM1_DTSEC5) {
170 fdt_set_phy_handle(fdt, compat, addr,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000171 "sgmii-riser-s3-p1");
Shaohui Xiedd335672015-11-11 17:58:37 +0800172 } else if (port == FM1_DTSEC6) {
173 fdt_set_phy_handle(fdt, compat, addr,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000174 "sgmii-riser-s4-p1");
Shaohui Xiedd335672015-11-11 17:58:37 +0800175 }
176 } else if (fm_info_get_enet_if(port) ==
177 PHY_INTERFACE_MODE_SGMII_2500) {
178 /* 2.5G SGMII interface */
Shaohui Xie673e0612016-03-25 11:36:51 +0800179 f_link.phy_id = cpu_to_fdt32(port);
180 f_link.duplex = cpu_to_fdt32(1);
181 f_link.link_speed = cpu_to_fdt32(1000);
Shaohui Xiedd335672015-11-11 17:58:37 +0800182 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,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000195 "qsgmii-s1-p1");
Shaohui Xiedd335672015-11-11 17:58:37 +0800196 break;
197 case FM1_DTSEC2:
198 fdt_set_phy_handle(fdt, compat, addr,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000199 "qsgmii-s1-p2");
Shaohui Xiedd335672015-11-11 17:58:37 +0800200 break;
201 case FM1_DTSEC5:
202 fdt_set_phy_handle(fdt, compat, addr,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000203 "qsgmii-s1-p3");
Shaohui Xiedd335672015-11-11 17:58:37 +0800204 break;
205 case FM1_DTSEC6:
206 fdt_set_phy_handle(fdt, compat, addr,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000207 "qsgmii-s1-p4");
Shaohui Xiedd335672015-11-11 17:58:37 +0800208 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,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000217 "qsgmii-s2-p1");
Shaohui Xiedd335672015-11-11 17:58:37 +0800218 break;
219 case FM1_DTSEC2:
220 fdt_set_phy_handle(fdt, compat, addr,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000221 "qsgmii-s2-p2");
Shaohui Xiedd335672015-11-11 17:58:37 +0800222 break;
223 case FM1_DTSEC5:
224 fdt_set_phy_handle(fdt, compat, addr,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000225 "qsgmii-s2-p3");
Shaohui Xiedd335672015-11-11 17:58:37 +0800226 break;
227 case FM1_DTSEC6:
228 fdt_set_phy_handle(fdt, compat, addr,
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000229 "qsgmii-s2-p4");
Shaohui Xiedd335672015-11-11 17:58:37 +0800230 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 */
Shaohui Xie673e0612016-03-25 11:36:51 +0800244 f_link.phy_id = cpu_to_fdt32(port);
245 f_link.duplex = cpu_to_fdt32(1);
246 f_link.link_speed = cpu_to_fdt32(10000);
Shaohui Xiedd335672015-11-11 17:58:37 +0800247 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
256void 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:
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000272 fdt_status_okay_by_alias(fdt, "emi1-slot1");
Shaohui Xiedd335672015-11-11 17:58:37 +0800273 break;
274 case EMI1_SLOT2:
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000275 fdt_status_okay_by_alias(fdt, "emi1-slot2");
Shaohui Xiedd335672015-11-11 17:58:37 +0800276 break;
277 case EMI1_SLOT3:
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000278 fdt_status_okay_by_alias(fdt, "emi1-slot3");
Shaohui Xiedd335672015-11-11 17:58:37 +0800279 break;
280 case EMI1_SLOT4:
Pankaj Bansalc8861b62019-04-22 06:31:42 +0000281 fdt_status_okay_by_alias(fdt, "emi1-slot4");
Shaohui Xiedd335672015-11-11 17:58:37 +0800282 break;
283 default:
284 break;
285 }
286 break;
287 case PHY_INTERFACE_MODE_XGMII:
288 break;
289 default:
290 break;
291 }
292 }
293}
294
295int 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:
Madalin Bucured50c442017-08-18 11:37:20 +0300479 case PHY_INTERFACE_MODE_RGMII_TXID:
Shaohui Xiedd335672015-11-11 17:58:37 +0800480 if (i == FM1_DTSEC3)
481 mdio_mux[i] = EMI1_RGMII1;
482 else if (i == FM1_DTSEC4)
483 mdio_mux[i] = EMI1_RGMII2;
484 fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
485 break;
486 default:
487 break;
488 }
489 }
490
491 cpu_eth_init(bis);
492#endif /* CONFIG_FMAN_ENET */
493
494 return pci_eth_init(bis);
495}