blob: 8bf34fa79ac6dfe93afeaeaf76d6b39456743b22 [file] [log] [blame]
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +05301/*
2 * Copyright 2013 Freescale Semiconductor, Inc.
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7/*
8 * The RGMII PHYs are provided by the two on-board PHY connected to
9 * dTSEC instances 4 and 5. The SGMII PHYs are provided by one on-board
10 * PHY or by the standard four-port SGMII riser card (VSC).
11 */
12
13#include <common.h>
14#include <netdev.h>
15#include <asm/fsl_serdes.h>
16#include <asm/immap_85xx.h>
17#include <fm_eth.h>
18#include <fsl_mdio.h>
19#include <malloc.h>
Shaohui Xie513eaf22015-10-26 19:47:47 +080020#include <fsl_dtsec.h>
Codrin Ciubotariua2d39cb2015-01-21 11:54:11 +020021#include <vsc9953.h>
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +053022
23#include "../common/fman.h"
24#include "../common/qixis.h"
25
26#include "t1040qds_qixis.h"
27
28#ifdef CONFIG_FMAN_ENET
29 /* - In T1040 there are only 8 SERDES lanes, spread across 2 SERDES banks.
30 * Bank 1 -> Lanes A, B, C, D
31 * Bank 2 -> Lanes E, F, G, H
32 */
33
34 /* Mapping of 8 SERDES lanes to T1040 QDS board slots. A value of '0' here
35 * means that the mapping must be determined dynamically, or that the lane
36 * maps to something other than a board slot.
37 */
38static u8 lane_to_slot[] = {
39 0, 0, 0, 0, 0, 0, 0, 0
40};
41
42/* On the Vitesse VSC8234XHG SGMII riser card there are 4 SGMII PHYs
43 * housed.
44 */
45static int riser_phy_addr[] = {
46 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR,
47 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR,
48 CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR,
49 CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR,
50};
51
52/* Slot2 does not have EMI connections */
53#define EMI_NONE 0xFFFFFFFF
54#define EMI1_RGMII0 0
55#define EMI1_RGMII1 1
56#define EMI1_SLOT1 2
57#define EMI1_SLOT3 3
58#define EMI1_SLOT4 4
59#define EMI1_SLOT5 5
60#define EMI1_SLOT6 6
61#define EMI1_SLOT7 7
62#define EMI2 8
63
64static int mdio_mux[NUM_FM_PORTS];
65
66static const char * const mdio_names[] = {
67 "T1040_QDS_MDIO0",
68 "T1040_QDS_MDIO1",
69 "T1040_QDS_MDIO2",
70 "T1040_QDS_MDIO3",
71 "T1040_QDS_MDIO4",
72 "T1040_QDS_MDIO5",
73 "T1040_QDS_MDIO6",
74 "T1040_QDS_MDIO7",
75};
76
77struct t1040_qds_mdio {
78 u8 muxval;
79 struct mii_dev *realbus;
80};
81
82static const char *t1040_qds_mdio_name_for_muxval(u8 muxval)
83{
84 return mdio_names[muxval];
85}
86
87struct mii_dev *mii_dev_for_muxval(u8 muxval)
88{
89 struct mii_dev *bus;
90 const char *name = t1040_qds_mdio_name_for_muxval(muxval);
91
92 if (!name) {
93 printf("No bus for muxval %x\n", muxval);
94 return NULL;
95 }
96
97 bus = miiphy_get_dev_by_name(name);
98
99 if (!bus) {
100 printf("No bus by name %s\n", name);
101 return NULL;
102 }
103
104 return bus;
105}
106
107static void t1040_qds_mux_mdio(u8 muxval)
108{
109 u8 brdcfg4;
110 if (muxval <= 7) {
111 brdcfg4 = QIXIS_READ(brdcfg[4]);
112 brdcfg4 &= ~BRDCFG4_EMISEL_MASK;
113 brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT);
114 QIXIS_WRITE(brdcfg[4], brdcfg4);
115 }
116}
117
118static int t1040_qds_mdio_read(struct mii_dev *bus, int addr, int devad,
119 int regnum)
120{
121 struct t1040_qds_mdio *priv = bus->priv;
122
123 t1040_qds_mux_mdio(priv->muxval);
124
125 return priv->realbus->read(priv->realbus, addr, devad, regnum);
126}
127
128static int t1040_qds_mdio_write(struct mii_dev *bus, int addr, int devad,
129 int regnum, u16 value)
130{
131 struct t1040_qds_mdio *priv = bus->priv;
132
133 t1040_qds_mux_mdio(priv->muxval);
134
135 return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
136}
137
138static int t1040_qds_mdio_reset(struct mii_dev *bus)
139{
140 struct t1040_qds_mdio *priv = bus->priv;
141
142 return priv->realbus->reset(priv->realbus);
143}
144
145static int t1040_qds_mdio_init(char *realbusname, u8 muxval)
146{
147 struct t1040_qds_mdio *pmdio;
148 struct mii_dev *bus = mdio_alloc();
149
150 if (!bus) {
151 printf("Failed to allocate t1040_qds MDIO bus\n");
152 return -1;
153 }
154
155 pmdio = malloc(sizeof(*pmdio));
156 if (!pmdio) {
157 printf("Failed to allocate t1040_qds private data\n");
158 free(bus);
159 return -1;
160 }
161
162 bus->read = t1040_qds_mdio_read;
163 bus->write = t1040_qds_mdio_write;
164 bus->reset = t1040_qds_mdio_reset;
165 sprintf(bus->name, t1040_qds_mdio_name_for_muxval(muxval));
166
167 pmdio->realbus = miiphy_get_dev_by_name(realbusname);
168
169 if (!pmdio->realbus) {
170 printf("No bus with name %s\n", realbusname);
171 free(bus);
172 free(pmdio);
173 return -1;
174 }
175
176 pmdio->muxval = muxval;
177 bus->priv = pmdio;
178
179 return mdio_register(bus);
180}
181
182/*
183 * Initialize the lane_to_slot[] array.
184 *
185 * On the T1040QDS board the mapping is controlled by ?? register.
186 */
187static void initialize_lane_to_slot(void)
188{
189 ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
190 int serdes1_prtcl = (in_be32(&gur->rcwsr[4]) &
191 FSL_CORENET2_RCWSR4_SRDS1_PRTCL)
192 >> FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
193
194 QIXIS_WRITE(cms[0], 0x07);
195
196 switch (serdes1_prtcl) {
197 case 0x60:
198 case 0x66:
199 case 0x67:
200 case 0x69:
201 lane_to_slot[1] = 7;
202 lane_to_slot[2] = 6;
203 lane_to_slot[3] = 5;
204 break;
205 case 0x86:
206 lane_to_slot[1] = 7;
207 lane_to_slot[2] = 7;
208 lane_to_slot[3] = 7;
209 break;
210 case 0x87:
211 lane_to_slot[1] = 7;
212 lane_to_slot[2] = 7;
213 lane_to_slot[3] = 7;
214 lane_to_slot[7] = 7;
215 break;
216 case 0x89:
217 lane_to_slot[1] = 7;
218 lane_to_slot[2] = 7;
219 lane_to_slot[3] = 7;
Codrin Ciubotariuee514942015-01-12 14:08:35 +0200220 lane_to_slot[6] = 7;
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +0530221 lane_to_slot[7] = 7;
222 break;
223 case 0x8d:
224 lane_to_slot[1] = 7;
225 lane_to_slot[2] = 7;
226 lane_to_slot[3] = 7;
227 lane_to_slot[5] = 3;
228 lane_to_slot[6] = 3;
229 lane_to_slot[7] = 3;
230 break;
231 case 0x8F:
232 case 0x85:
233 lane_to_slot[1] = 7;
234 lane_to_slot[2] = 6;
235 lane_to_slot[3] = 5;
236 lane_to_slot[6] = 3;
237 lane_to_slot[7] = 3;
238 break;
239 case 0xA5:
240 lane_to_slot[1] = 7;
241 lane_to_slot[6] = 3;
242 lane_to_slot[7] = 3;
243 break;
244 case 0xA7:
245 lane_to_slot[1] = 7;
Priyanka Jainded483c2014-09-08 13:20:52 +0530246 lane_to_slot[2] = 6;
247 lane_to_slot[3] = 5;
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +0530248 lane_to_slot[7] = 7;
249 break;
250 case 0xAA:
251 lane_to_slot[1] = 7;
252 lane_to_slot[6] = 7;
253 lane_to_slot[7] = 7;
254 break;
255 case 0x40:
256 lane_to_slot[2] = 7;
257 lane_to_slot[3] = 7;
258 break;
259 default:
260 printf("qds: Fman: Unsupported SerDes Protocol 0x%02x\n",
261 serdes1_prtcl);
262 break;
263 }
264}
265
266/*
267 * Given the following ...
268 *
269 * 1) A pointer to an Fman Ethernet node (as identified by the 'compat'
270 * compatible string and 'addr' physical address)
271 *
272 * 2) An Fman port
273 *
274 * ... update the phy-handle property of the Ethernet node to point to the
275 * right PHY. This assumes that we already know the PHY for each port.
276 *
277 * The offset of the Fman Ethernet node is also passed in for convenience, but
278 * it is not used, and we recalculate the offset anyway.
279 *
280 * Note that what we call "Fman ports" (enum fm_port) is really an Fman MAC.
281 * Inside the Fman, "ports" are things that connect to MACs. We only call them
282 * ports in U-Boot because on previous Ethernet devices (e.g. Gianfar), MACs
283 * and ports are the same thing.
284 *
285 */
286void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
287 enum fm_port port, int offset)
288{
289 phy_interface_t intf = fm_info_get_enet_if(port);
290 char phy[16];
291
292 /* The RGMII PHY is identified by the MAC connected to it */
293 if (intf == PHY_INTERFACE_MODE_RGMII) {
294 sprintf(phy, "rgmii_phy%u", port == FM1_DTSEC4 ? 1 : 2);
295 fdt_set_phy_handle(fdt, compat, addr, phy);
296 }
297
298 /* The SGMII PHY is identified by the MAC connected to it */
299 if (intf == PHY_INTERFACE_MODE_SGMII) {
300 int lane = serdes_get_first_lane(FSL_SRDS_1, SGMII_FM1_DTSEC1
301 + port);
302 u8 slot;
303 if (lane < 0)
304 return;
305 slot = lane_to_slot[lane];
306 if (slot) {
307 /* Slot housing a SGMII riser card */
308 sprintf(phy, "phy_s%x_%02x", slot,
309 (fm_info_get_phy_address(port - FM1_DTSEC1)-
310 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR + 1));
311 fdt_set_phy_handle(fdt, compat, addr, phy);
312 }
313 }
314}
315
316void fdt_fixup_board_enet(void *fdt)
317{
318 int i, lane, idx;
319
320 for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
321 idx = i - FM1_DTSEC1;
322 switch (fm_info_get_enet_if(i)) {
323 case PHY_INTERFACE_MODE_SGMII:
324 lane = serdes_get_first_lane(FSL_SRDS_1,
325 SGMII_FM1_DTSEC1 + idx);
326 if (lane < 0)
327 break;
328
329 switch (mdio_mux[i]) {
330 case EMI1_SLOT3:
331 fdt_status_okay_by_alias(fdt, "emi1_slot3");
332 break;
333 case EMI1_SLOT5:
334 fdt_status_okay_by_alias(fdt, "emi1_slot5");
335 break;
336 case EMI1_SLOT6:
337 fdt_status_okay_by_alias(fdt, "emi1_slot6");
338 break;
339 case EMI1_SLOT7:
340 fdt_status_okay_by_alias(fdt, "emi1_slot7");
341 break;
342 }
343 break;
344 case PHY_INTERFACE_MODE_RGMII:
345 if (i == FM1_DTSEC4)
346 fdt_status_okay_by_alias(fdt, "emi1_rgmii0");
347
348 if (i == FM1_DTSEC5)
349 fdt_status_okay_by_alias(fdt, "emi1_rgmii1");
350 break;
351 default:
352 break;
353 }
354 }
355}
356#endif /* #ifdef CONFIG_FMAN_ENET */
357
358static void set_brdcfg9_for_gtx_clk(void)
359{
360 u8 brdcfg9;
361 brdcfg9 = QIXIS_READ(brdcfg[9]);
vijay rai8e3de882014-06-20 10:45:29 +0530362/* Initializing EPHY2 clock to RGMII mode */
363 brdcfg9 &= ~(BRDCFG9_EPHY2_MASK);
364 brdcfg9 |= (BRDCFG9_EPHY2_VAL);
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +0530365 QIXIS_WRITE(brdcfg[9], brdcfg9);
366}
367
368void t1040_handle_phy_interface_sgmii(int i)
369{
370 int lane, idx, slot;
371 idx = i - FM1_DTSEC1;
372 lane = serdes_get_first_lane(FSL_SRDS_1,
373 SGMII_FM1_DTSEC1 + idx);
374
375 if (lane < 0)
376 return;
377 slot = lane_to_slot[lane];
378
379 switch (slot) {
380 case 1:
381 mdio_mux[i] = EMI1_SLOT1;
382 fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
383 break;
384 case 3:
385 if (FM1_DTSEC4 == i)
386 fm_info_set_phy_address(i, riser_phy_addr[0]);
387 if (FM1_DTSEC5 == i)
388 fm_info_set_phy_address(i, riser_phy_addr[1]);
389
390 mdio_mux[i] = EMI1_SLOT3;
391
392 fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
393 break;
394 case 4:
395 mdio_mux[i] = EMI1_SLOT4;
396 fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
397 break;
398 case 5:
399 /* Slot housing a SGMII riser card? */
400 fm_info_set_phy_address(i, riser_phy_addr[0]);
401 mdio_mux[i] = EMI1_SLOT5;
402 fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
403 break;
404 case 6:
405 /* Slot housing a SGMII riser card? */
406 fm_info_set_phy_address(i, riser_phy_addr[0]);
407 mdio_mux[i] = EMI1_SLOT6;
408 fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
409 break;
410 case 7:
411 if (FM1_DTSEC1 == i)
412 fm_info_set_phy_address(i, riser_phy_addr[0]);
413 if (FM1_DTSEC2 == i)
414 fm_info_set_phy_address(i, riser_phy_addr[1]);
415 if (FM1_DTSEC3 == i)
416 fm_info_set_phy_address(i, riser_phy_addr[2]);
Priyanka Jainded483c2014-09-08 13:20:52 +0530417 if (FM1_DTSEC5 == i)
418 fm_info_set_phy_address(i, riser_phy_addr[3]);
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +0530419
420 mdio_mux[i] = EMI1_SLOT7;
421 fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
422 break;
423 default:
424 break;
425 }
426 fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
427}
428void t1040_handle_phy_interface_rgmii(int i)
429{
430 fm_info_set_phy_address(i, i == FM1_DTSEC5 ?
431 CONFIG_SYS_FM1_DTSEC5_PHY_ADDR :
432 CONFIG_SYS_FM1_DTSEC4_PHY_ADDR);
433 mdio_mux[i] = (i == FM1_DTSEC5) ? EMI1_RGMII1 :
434 EMI1_RGMII0;
435 fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));
436}
437
438int board_eth_init(bd_t *bis)
439{
440#ifdef CONFIG_FMAN_ENET
441 struct memac_mdio_info memac_mdio_info;
442 unsigned int i;
Codrin Ciubotariua2d39cb2015-01-21 11:54:11 +0200443#ifdef CONFIG_VSC9953
444 int lane;
445 int phy_addr;
446 phy_interface_t phy_int;
447 struct mii_dev *bus;
448#endif
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +0530449
450 printf("Initializing Fman\n");
451 set_brdcfg9_for_gtx_clk();
452
453 initialize_lane_to_slot();
454
455 /* Initialize the mdio_mux array so we can recognize empty elements */
456 for (i = 0; i < NUM_FM_PORTS; i++)
457 mdio_mux[i] = EMI_NONE;
458
459 memac_mdio_info.regs =
460 (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
461 memac_mdio_info.name = DEFAULT_FM_MDIO_NAME;
462
463 /* Register the real 1G MDIO bus */
464 fm_memac_mdio_init(bis, &memac_mdio_info);
465
466 /* Register the muxing front-ends to the MDIO buses */
467 t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII0);
468 t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII1);
469 t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT1);
470 t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT3);
471 t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT4);
472 t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT5);
473 t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT6);
474 t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT7);
475
476 /*
477 * Program on board RGMII PHY addresses. If the SGMII Riser
478 * card used, we'll override the PHY address later. For any DTSEC that
479 * is RGMII, we'll also override its PHY address later. We assume that
480 * DTSEC4 and DTSEC5 are used for RGMII.
481 */
482 fm_info_set_phy_address(FM1_DTSEC4, CONFIG_SYS_FM1_DTSEC4_PHY_ADDR);
483 fm_info_set_phy_address(FM1_DTSEC5, CONFIG_SYS_FM1_DTSEC5_PHY_ADDR);
484
485 for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
486 switch (fm_info_get_enet_if(i)) {
487 case PHY_INTERFACE_MODE_QSGMII:
Codrin Ciubotariu6072aad2015-01-12 14:08:36 +0200488 fm_info_set_mdio(i, NULL);
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +0530489 break;
490 case PHY_INTERFACE_MODE_SGMII:
491 t1040_handle_phy_interface_sgmii(i);
492 break;
493
494 case PHY_INTERFACE_MODE_RGMII:
495 /* Only DTSEC4 and DTSEC5 can be routed to RGMII */
496 t1040_handle_phy_interface_rgmii(i);
497 break;
498 default:
499 break;
Codrin Ciubotariua2d39cb2015-01-21 11:54:11 +0200500 }
501 }
502
503#ifdef CONFIG_VSC9953
504 for (i = 0; i < VSC9953_MAX_PORTS; i++) {
505 lane = -1;
506 phy_addr = 0;
507 phy_int = PHY_INTERFACE_MODE_NONE;
508 switch (i) {
509 case 0:
510 case 1:
511 case 2:
512 case 3:
513 lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_SW1_A);
514 /* PHYs connected over QSGMII */
515 if (lane >= 0) {
516 phy_addr = CONFIG_SYS_FM1_QSGMII21_PHY_ADDR +
517 i;
518 phy_int = PHY_INTERFACE_MODE_QSGMII;
519 break;
520 }
521 lane = serdes_get_first_lane(FSL_SRDS_1,
522 SGMII_SW1_MAC1 + i);
523
524 if (lane < 0)
525 break;
526
527 /* PHYs connected over QSGMII */
528 if (i != 3 || lane_to_slot[lane] == 7)
529 phy_addr = CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR
530 + i;
531 else
532 phy_addr = CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR;
533 phy_int = PHY_INTERFACE_MODE_SGMII;
534 break;
535 case 4:
536 case 5:
537 case 6:
538 case 7:
539 lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_SW1_B);
540 /* PHYs connected over QSGMII */
541 if (lane >= 0) {
542 phy_addr = CONFIG_SYS_FM1_QSGMII11_PHY_ADDR +
543 i - 4;
544 phy_int = PHY_INTERFACE_MODE_QSGMII;
545 break;
546 }
547 lane = serdes_get_first_lane(FSL_SRDS_1,
548 SGMII_SW1_MAC1 + i);
549 /* PHYs connected over SGMII */
550 if (lane >= 0) {
551 phy_addr = CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR
552 + i - 3;
553 phy_int = PHY_INTERFACE_MODE_SGMII;
554 }
555 break;
556 case 8:
557 if (serdes_get_first_lane(FSL_SRDS_1,
558 SGMII_FM1_DTSEC1) < 0)
559 /* FM1@DTSEC1 is connected to SW1@PORT8 */
560 vsc9953_port_enable(i);
561 break;
562 case 9:
563 if (serdes_get_first_lane(FSL_SRDS_1,
564 SGMII_FM1_DTSEC2) < 0) {
565 /* Enable L2 On MAC2 using SCFG */
566 struct ccsr_scfg *scfg = (struct ccsr_scfg *)
567 CONFIG_SYS_MPC85xx_SCFG;
568
569 out_be32(&scfg->esgmiiselcr,
570 in_be32(&scfg->esgmiiselcr) |
571 (0x80000000));
572 vsc9953_port_enable(i);
573 }
574 break;
575 }
576
577 if (lane >= 0) {
578 bus = mii_dev_for_muxval(lane_to_slot[lane]);
579 vsc9953_port_info_set_mdio(i, bus);
580 vsc9953_port_enable(i);
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +0530581 }
Codrin Ciubotariua2d39cb2015-01-21 11:54:11 +0200582 vsc9953_port_info_set_phy_address(i, phy_addr);
583 vsc9953_port_info_set_phy_int(i, phy_int);
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +0530584 }
585
Codrin Ciubotariua2d39cb2015-01-21 11:54:11 +0200586#endif
Prabhakar Kushwahae70cd8d2014-01-27 15:55:20 +0530587 cpu_eth_init(bis);
588#endif
589
590 return pci_eth_init(bis);
591}