blob: c0bcf7129929d75a6b426ef9d08fef3fa3747135 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Ashish Kumar1ef4c772017-08-31 16:12:55 +05302/*
3 * Copyright 2017 NXP
Ashish Kumar1ef4c772017-08-31 16:12:55 +05304 */
5
6#include <common.h>
Ashish Kumarbc6ceca2018-04-13 12:28:45 +05307#include <command.h>
Simon Glass0af6e2d2019-08-01 09:46:52 -06008#include <env.h>
Simon Glass0c364412019-12-28 10:44:48 -07009#include <net.h>
Ashish Kumar1ef4c772017-08-31 16:12:55 +053010#include <netdev.h>
11#include <asm/io.h>
12#include <asm/arch/fsl_serdes.h>
13#include <hwconfig.h>
14#include <fsl_mdio.h>
15#include <malloc.h>
Ashish Kumarbc6ceca2018-04-13 12:28:45 +053016#include <phy.h>
Ashish Kumar1ef4c772017-08-31 16:12:55 +053017#include <fm_eth.h>
18#include <i2c.h>
19#include <miiphy.h>
Bogdan Purcareata33ba9392017-10-05 06:56:53 +000020#include <fsl-mc/fsl_mc.h>
Ashish Kumar1ef4c772017-08-31 16:12:55 +053021#include <fsl-mc/ldpaa_wriop.h>
22
23#include "../common/qixis.h"
24
25#include "ls1088a_qixis.h"
26
Ashish Kumar1ef4c772017-08-31 16:12:55 +053027#ifdef CONFIG_FSL_MC_ENET
28
29#define SFP_TX 0
30
31 /* - In LS1088A A there are only 16 SERDES lanes, spread across 2 SERDES banks.
32 * Bank 1 -> Lanes A, B, C, D,
33 * Bank 2 -> Lanes A,B, C, D,
34 */
35
36 /* Mapping of 8 SERDES lanes to LS1088A QDS board slots. A value of '0' here
37 * means that the mapping must be determined dynamically, or that the lane
38 * maps to something other than a board slot.
39 */
40
41static u8 lane_to_slot_fsm1[] = {
42 0, 0, 0, 0, 0, 0, 0, 0
43};
44
45/* On the Vitesse VSC8234XHG SGMII riser card there are 4 SGMII PHYs
46 * housed.
47 */
48
49static int xqsgii_riser_phy_addr[] = {
50 XQSGMII_CARD_PHY1_PORT0_ADDR,
51 XQSGMII_CARD_PHY2_PORT0_ADDR,
52 XQSGMII_CARD_PHY3_PORT0_ADDR,
53 XQSGMII_CARD_PHY4_PORT0_ADDR,
54 XQSGMII_CARD_PHY3_PORT2_ADDR,
55 XQSGMII_CARD_PHY1_PORT2_ADDR,
56 XQSGMII_CARD_PHY4_PORT2_ADDR,
57 XQSGMII_CARD_PHY2_PORT2_ADDR,
58};
59
60static int sgmii_riser_phy_addr[] = {
61 SGMII_CARD_PORT1_PHY_ADDR,
62 SGMII_CARD_PORT2_PHY_ADDR,
63 SGMII_CARD_PORT3_PHY_ADDR,
64 SGMII_CARD_PORT4_PHY_ADDR,
65};
66
67/* Slot2 does not have EMI connections */
68#define EMI_NONE 0xFF
69#define EMI1_RGMII1 0
70#define EMI1_RGMII2 1
71#define EMI1_SLOT1 2
72
73static const char * const mdio_names[] = {
74 "LS1088A_QDS_MDIO0",
75 "LS1088A_QDS_MDIO1",
76 "LS1088A_QDS_MDIO2",
77 DEFAULT_WRIOP_MDIO2_NAME,
78};
79
80struct ls1088a_qds_mdio {
81 u8 muxval;
82 struct mii_dev *realbus;
83};
84
Chuanhua Handddcadb2019-07-26 20:25:35 +080085struct reg_pair {
86 uint addr;
87 u8 *val;
88};
89
Ashish Kumar1ef4c772017-08-31 16:12:55 +053090static void sgmii_configure_repeater(int dpmac)
91{
92 struct mii_dev *bus;
93 uint8_t a = 0xf;
Chuanhua Handddcadb2019-07-26 20:25:35 +080094 int i, j, k, ret;
Ashish Kumar1ef4c772017-08-31 16:12:55 +053095 unsigned short value;
96 const char *dev = "LS1088A_QDS_MDIO2";
97 int i2c_addr[] = {0x58, 0x59, 0x5a, 0x5b};
98 int i2c_phy_addr = 0;
99 int phy_addr = 0;
100
101 uint8_t ch_a_eq[] = {0x1, 0x2, 0x3, 0x7};
102 uint8_t ch_a_ctl2[] = {0x81, 0x82, 0x83, 0x84};
103 uint8_t ch_b_eq[] = {0x1, 0x2, 0x3, 0x7};
104 uint8_t ch_b_ctl2[] = {0x81, 0x82, 0x83, 0x84};
105
Chuanhua Handddcadb2019-07-26 20:25:35 +0800106 u8 reg_val[6] = {0x18, 0x38, 0x4, 0x14, 0xb5, 0x20};
107 struct reg_pair reg_pair[10] = {
108 {6, &reg_val[0]}, {4, &reg_val[1]},
109 {8, &reg_val[2]}, {0xf, NULL},
110 {0x11, NULL}, {0x16, NULL},
111 {0x18, NULL}, {0x23, &reg_val[3]},
112 {0x2d, &reg_val[4]}, {4, &reg_val[5]},
113 };
114#ifdef CONFIG_DM_I2C
115 struct udevice *udev;
116#endif
117
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530118 /* Set I2c to Slot 1 */
Chuanhua Handddcadb2019-07-26 20:25:35 +0800119#ifndef CONFIG_DM_I2C
120 ret = i2c_write(0x77, 0, 0, &a, 1);
121#else
122 ret = i2c_get_chip_for_busnum(0, 0x77, 1, &udev);
123 if (!ret)
124 ret = dm_i2c_write(udev, 0, &a, 1);
125#endif
126 if (ret)
127 goto error;
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530128
129 switch (dpmac) {
130 case 1:
131 i2c_phy_addr = i2c_addr[1];
132 phy_addr = 4;
133 break;
134 case 2:
135 i2c_phy_addr = i2c_addr[0];
136 phy_addr = 0;
137 break;
138 case 3:
139 i2c_phy_addr = i2c_addr[3];
140 phy_addr = 0xc;
141 break;
142 case 7:
143 i2c_phy_addr = i2c_addr[2];
144 phy_addr = 8;
145 break;
146 }
147
148 /* Check the PHY status */
149 ret = miiphy_set_current_dev(dev);
150 if (ret > 0)
151 goto error;
152
153 bus = mdio_get_current_dev();
154 debug("Reading from bus %s\n", bus->name);
155
156 ret = miiphy_write(dev, phy_addr, 0x1f, 3);
157 if (ret > 0)
158 goto error;
159
160 mdelay(10);
161 ret = miiphy_read(dev, phy_addr, 0x11, &value);
162 if (ret > 0)
163 goto error;
164
165 mdelay(10);
166
167 if ((value & 0xfff) == 0x401) {
168 miiphy_write(dev, phy_addr, 0x1f, 0);
169 printf("DPMAC %d:PHY is ..... Configured\n", dpmac);
170 return;
171 }
172
Chuanhua Handddcadb2019-07-26 20:25:35 +0800173#ifdef CONFIG_DM_I2C
174 i2c_get_chip_for_busnum(0, i2c_phy_addr, 1, &udev);
175#endif
176
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530177 for (i = 0; i < 4; i++) {
178 for (j = 0; j < 4; j++) {
Chuanhua Handddcadb2019-07-26 20:25:35 +0800179 reg_pair[3].val = &ch_a_eq[i];
180 reg_pair[4].val = &ch_a_ctl2[j];
181 reg_pair[5].val = &ch_b_eq[i];
182 reg_pair[6].val = &ch_b_ctl2[j];
183 for (k = 0; k < 10; k++) {
184#ifndef CONFIG_DM_I2C
185 ret = i2c_write(i2c_phy_addr,
186 reg_pair[k].addr,
187 1, reg_pair[k].val, 1);
188#else
189 ret = i2c_get_chip_for_busnum(0,
190 i2c_phy_addr,
191 1, &udev);
192 if (!ret)
193 ret = dm_i2c_write(udev,
194 reg_pair[k].addr,
195 reg_pair[k].val, 1);
196#endif
197 if (ret)
198 goto error;
199 }
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530200
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530201 mdelay(100);
202 ret = miiphy_read(dev, phy_addr, 0x11, &value);
203 if (ret > 0)
204 goto error;
205
206 mdelay(100);
207 ret = miiphy_read(dev, phy_addr, 0x11, &value);
208 if (ret > 0)
209 goto error;
210
211 if ((value & 0xfff) == 0x401) {
212 printf("DPMAC %d :PHY is configured ",
213 dpmac);
214 printf("after setting repeater 0x%x\n",
215 value);
216 i = 5;
217 j = 5;
218 } else {
219 printf("DPMAC %d :PHY is failed to ",
220 dpmac);
221 printf("configure the repeater 0x%x\n", value);
222 }
223 }
224 }
225 miiphy_write(dev, phy_addr, 0x1f, 0);
226error:
227 if (ret)
228 printf("DPMAC %d ..... FAILED to configure PHY\n", dpmac);
229 return;
230}
231
232static void qsgmii_configure_repeater(int dpmac)
233{
234 uint8_t a = 0xf;
Chuanhua Handddcadb2019-07-26 20:25:35 +0800235 int i, j, k;
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530236 int i2c_phy_addr = 0;
237 int phy_addr = 0;
238 int i2c_addr[] = {0x58, 0x59, 0x5a, 0x5b};
239
240 uint8_t ch_a_eq[] = {0x1, 0x2, 0x3, 0x7};
241 uint8_t ch_a_ctl2[] = {0x81, 0x82, 0x83, 0x84};
242 uint8_t ch_b_eq[] = {0x1, 0x2, 0x3, 0x7};
243 uint8_t ch_b_ctl2[] = {0x81, 0x82, 0x83, 0x84};
244
Chuanhua Handddcadb2019-07-26 20:25:35 +0800245 u8 reg_val[6] = {0x18, 0x38, 0x4, 0x14, 0xb5, 0x20};
246 struct reg_pair reg_pair[10] = {
247 {6, &reg_val[0]}, {4, &reg_val[1]},
248 {8, &reg_val[2]}, {0xf, NULL},
249 {0x11, NULL}, {0x16, NULL},
250 {0x18, NULL}, {0x23, &reg_val[3]},
251 {0x2d, &reg_val[4]}, {4, &reg_val[5]},
252 };
253
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530254 const char *dev = mdio_names[EMI1_SLOT1];
255 int ret = 0;
256 unsigned short value;
Chuanhua Handddcadb2019-07-26 20:25:35 +0800257#ifdef CONFIG_DM_I2C
258 struct udevice *udev;
259#endif
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530260
261 /* Set I2c to Slot 1 */
Chuanhua Handddcadb2019-07-26 20:25:35 +0800262#ifndef CONFIG_DM_I2C
263 ret = i2c_write(0x77, 0, 0, &a, 1);
264#else
265 ret = i2c_get_chip_for_busnum(0, 0x77, 1, &udev);
266 if (!ret)
267 ret = dm_i2c_write(udev, 0, &a, 1);
268#endif
269 if (ret)
270 goto error;
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530271
272 switch (dpmac) {
273 case 7:
274 case 8:
275 case 9:
276 case 10:
277 i2c_phy_addr = i2c_addr[2];
278 phy_addr = 8;
279 break;
280
281 case 3:
282 case 4:
283 case 5:
284 case 6:
285 i2c_phy_addr = i2c_addr[3];
286 phy_addr = 0xc;
287 break;
288 }
289
290 /* Check the PHY status */
291 ret = miiphy_set_current_dev(dev);
292 ret = miiphy_write(dev, phy_addr, 0x1f, 3);
293 mdelay(10);
294 ret = miiphy_read(dev, phy_addr, 0x11, &value);
295 mdelay(10);
296 ret = miiphy_read(dev, phy_addr, 0x11, &value);
297 mdelay(10);
298 if ((value & 0xf) == 0xf) {
299 miiphy_write(dev, phy_addr, 0x1f, 0);
300 printf("DPMAC %d :PHY is ..... Configured\n", dpmac);
301 return;
302 }
303
Chuanhua Handddcadb2019-07-26 20:25:35 +0800304#ifdef CONFIG_DM_I2C
305 i2c_get_chip_for_busnum(0, i2c_phy_addr, 1, &udev);
306#endif
307
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530308 for (i = 0; i < 4; i++) {
309 for (j = 0; j < 4; j++) {
Chuanhua Handddcadb2019-07-26 20:25:35 +0800310 reg_pair[3].val = &ch_a_eq[i];
311 reg_pair[4].val = &ch_a_ctl2[j];
312 reg_pair[5].val = &ch_b_eq[i];
313 reg_pair[6].val = &ch_b_ctl2[j];
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530314
Chuanhua Handddcadb2019-07-26 20:25:35 +0800315 for (k = 0; k < 10; k++) {
316#ifndef CONFIG_DM_I2C
317 ret = i2c_write(i2c_phy_addr,
318 reg_pair[k].addr,
319 1, reg_pair[k].val, 1);
320#else
321 ret = i2c_get_chip_for_busnum(0,
322 i2c_addr[dpmac],
323 1, &udev);
324 if (!ret)
325 ret = dm_i2c_write(udev,
326 reg_pair[k].addr,
327 reg_pair[k].val, 1);
328#endif
329 if (ret)
330 goto error;
331 }
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530332
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530333 ret = miiphy_read(dev, phy_addr, 0x11, &value);
334 if (ret > 0)
335 goto error;
336 mdelay(1);
337 ret = miiphy_read(dev, phy_addr, 0x11, &value);
338 if (ret > 0)
339 goto error;
340 mdelay(10);
341 if ((value & 0xf) == 0xf) {
342 miiphy_write(dev, phy_addr, 0x1f, 0);
343 printf("DPMAC %d :PHY is ..... Configured\n",
344 dpmac);
345 return;
346 }
347 }
348 }
349error:
350 printf("DPMAC %d :PHY ..... FAILED to configure PHY\n", dpmac);
351 return;
352}
353
354static const char *ls1088a_qds_mdio_name_for_muxval(u8 muxval)
355{
356 return mdio_names[muxval];
357}
358
359struct mii_dev *mii_dev_for_muxval(u8 muxval)
360{
361 struct mii_dev *bus;
362 const char *name = ls1088a_qds_mdio_name_for_muxval(muxval);
363
364 if (!name) {
365 printf("No bus for muxval %x\n", muxval);
366 return NULL;
367 }
368
369 bus = miiphy_get_dev_by_name(name);
370
371 if (!bus) {
372 printf("No bus by name %s\n", name);
373 return NULL;
374 }
375
376 return bus;
377}
378
379static void ls1088a_qds_enable_SFP_TX(u8 muxval)
380{
381 u8 brdcfg9;
382
383 brdcfg9 = QIXIS_READ(brdcfg[9]);
384 brdcfg9 &= ~BRDCFG9_SFPTX_MASK;
385 brdcfg9 |= (muxval << BRDCFG9_SFPTX_SHIFT);
386 QIXIS_WRITE(brdcfg[9], brdcfg9);
387}
388
389static void ls1088a_qds_mux_mdio(u8 muxval)
390{
391 u8 brdcfg4;
392
393 if (muxval <= 5) {
394 brdcfg4 = QIXIS_READ(brdcfg[4]);
395 brdcfg4 &= ~BRDCFG4_EMISEL_MASK;
396 brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT);
397 QIXIS_WRITE(brdcfg[4], brdcfg4);
398 }
399}
400
401static int ls1088a_qds_mdio_read(struct mii_dev *bus, int addr,
402 int devad, int regnum)
403{
404 struct ls1088a_qds_mdio *priv = bus->priv;
405
406 ls1088a_qds_mux_mdio(priv->muxval);
407
408 return priv->realbus->read(priv->realbus, addr, devad, regnum);
409}
410
411static int ls1088a_qds_mdio_write(struct mii_dev *bus, int addr, int devad,
412 int regnum, u16 value)
413{
414 struct ls1088a_qds_mdio *priv = bus->priv;
415
416 ls1088a_qds_mux_mdio(priv->muxval);
417
418 return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
419}
420
421static int ls1088a_qds_mdio_reset(struct mii_dev *bus)
422{
423 struct ls1088a_qds_mdio *priv = bus->priv;
424
425 return priv->realbus->reset(priv->realbus);
426}
427
428static int ls1088a_qds_mdio_init(char *realbusname, u8 muxval)
429{
430 struct ls1088a_qds_mdio *pmdio;
431 struct mii_dev *bus = mdio_alloc();
432
433 if (!bus) {
434 printf("Failed to allocate ls1088a_qds MDIO bus\n");
435 return -1;
436 }
437
438 pmdio = malloc(sizeof(*pmdio));
439 if (!pmdio) {
440 printf("Failed to allocate ls1088a_qds private data\n");
441 free(bus);
442 return -1;
443 }
444
445 bus->read = ls1088a_qds_mdio_read;
446 bus->write = ls1088a_qds_mdio_write;
447 bus->reset = ls1088a_qds_mdio_reset;
448 sprintf(bus->name, ls1088a_qds_mdio_name_for_muxval(muxval));
449
450 pmdio->realbus = miiphy_get_dev_by_name(realbusname);
451
452 if (!pmdio->realbus) {
453 printf("No bus with name %s\n", realbusname);
454 free(bus);
455 free(pmdio);
456 return -1;
457 }
458
459 pmdio->muxval = muxval;
460 bus->priv = pmdio;
461
462 return mdio_register(bus);
463}
464
465/*
466 * Initialize the dpmac_info array.
467 *
468 */
469static void initialize_dpmac_to_slot(void)
470{
471 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
472 u32 serdes1_prtcl, cfg;
473
474 cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) &
475 FSL_CHASSIS3_SRDS1_PRTCL_MASK;
476 cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
477 serdes1_prtcl = serdes_get_number(FSL_SRDS_1, cfg);
478
479 switch (serdes1_prtcl) {
480 case 0x12:
481 printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n",
482 serdes1_prtcl);
483 lane_to_slot_fsm1[0] = EMI1_SLOT1 - 1;
484 lane_to_slot_fsm1[1] = EMI1_SLOT1 - 1;
485 lane_to_slot_fsm1[2] = EMI1_SLOT1 - 1;
486 lane_to_slot_fsm1[3] = EMI1_SLOT1 - 1;
487 break;
488 case 0x15:
489 case 0x1D:
490 printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n",
491 serdes1_prtcl);
492 lane_to_slot_fsm1[0] = EMI1_SLOT1 - 1;
493 lane_to_slot_fsm1[1] = EMI1_SLOT1 - 1;
494 lane_to_slot_fsm1[2] = EMI_NONE;
495 lane_to_slot_fsm1[3] = EMI_NONE;
496 break;
497 case 0x1E:
498 printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n",
499 serdes1_prtcl);
500 lane_to_slot_fsm1[0] = EMI1_SLOT1 - 1;
501 lane_to_slot_fsm1[1] = EMI1_SLOT1 - 1;
502 lane_to_slot_fsm1[2] = EMI1_SLOT1 - 1;
503 lane_to_slot_fsm1[3] = EMI_NONE;
504 break;
505 case 0x3A:
506 printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n",
507 serdes1_prtcl);
508 lane_to_slot_fsm1[0] = EMI1_SLOT1 - 1;
509 lane_to_slot_fsm1[1] = EMI_NONE;
510 lane_to_slot_fsm1[2] = EMI1_SLOT1 - 1;
511 lane_to_slot_fsm1[3] = EMI1_SLOT1 - 1;
512 break;
513
514 default:
515 printf("%s qds: WRIOP: Unsupported SerDes1 Protocol 0x%02x\n",
516 __func__, serdes1_prtcl);
517 break;
518 }
519}
520
521void ls1088a_handle_phy_interface_sgmii(int dpmac_id)
522{
523 struct mii_dev *bus;
524 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
525 u32 serdes1_prtcl, cfg;
526
527 cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) &
528 FSL_CHASSIS3_SRDS1_PRTCL_MASK;
529 cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
530 serdes1_prtcl = serdes_get_number(FSL_SRDS_1, cfg);
531
532 int *riser_phy_addr;
533 char *env_hwconfig = env_get("hwconfig");
534
535 if (hwconfig_f("xqsgmii", env_hwconfig))
536 riser_phy_addr = &xqsgii_riser_phy_addr[0];
537 else
538 riser_phy_addr = &sgmii_riser_phy_addr[0];
539
540 switch (serdes1_prtcl) {
541 case 0x12:
542 case 0x15:
543 case 0x1E:
544 case 0x3A:
545 switch (dpmac_id) {
546 case 1:
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530547 wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[1]);
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530548 break;
549 case 2:
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530550 wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[0]);
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530551 break;
552 case 3:
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530553 wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[3]);
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530554 break;
555 case 7:
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530556 wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[2]);
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530557 break;
558 default:
559 printf("WRIOP: Wrong DPMAC%d set to SGMII", dpmac_id);
560 break;
561 }
562 break;
563 default:
564 printf("%s qds: WRIOP: Unsupported SerDes1 Protocol 0x%02x\n",
565 __func__, serdes1_prtcl);
566 return;
567 }
568 dpmac_info[dpmac_id].board_mux = EMI1_SLOT1;
569 bus = mii_dev_for_muxval(EMI1_SLOT1);
570 wriop_set_mdio(dpmac_id, bus);
571}
572
573void ls1088a_handle_phy_interface_qsgmii(int dpmac_id)
574{
575 struct mii_dev *bus;
576 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
577 u32 serdes1_prtcl, cfg;
578
579 cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) &
580 FSL_CHASSIS3_SRDS1_PRTCL_MASK;
581 cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
582 serdes1_prtcl = serdes_get_number(FSL_SRDS_1, cfg);
583
584 switch (serdes1_prtcl) {
585 case 0x1D:
586 case 0x1E:
587 switch (dpmac_id) {
588 case 3:
589 case 4:
590 case 5:
591 case 6:
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530592 wriop_set_phy_address(dpmac_id, 0, dpmac_id + 9);
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530593 break;
594 case 7:
595 case 8:
596 case 9:
597 case 10:
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530598 wriop_set_phy_address(dpmac_id, 0, dpmac_id + 1);
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530599 break;
600 }
601
602 dpmac_info[dpmac_id].board_mux = EMI1_SLOT1;
603 bus = mii_dev_for_muxval(EMI1_SLOT1);
604 wriop_set_mdio(dpmac_id, bus);
605 break;
606 default:
607 printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n",
608 serdes1_prtcl);
609 break;
610 }
611}
612
613void ls1088a_handle_phy_interface_xsgmii(int i)
614{
615 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
616 u32 serdes1_prtcl, cfg;
617
618 cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) &
619 FSL_CHASSIS3_SRDS1_PRTCL_MASK;
620 cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
621 serdes1_prtcl = serdes_get_number(FSL_SRDS_1, cfg);
622
623 switch (serdes1_prtcl) {
624 case 0x15:
625 case 0x1D:
626 case 0x1E:
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530627 wriop_set_phy_address(i, 0, i + 26);
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530628 ls1088a_qds_enable_SFP_TX(SFP_TX);
629 break;
630 default:
631 printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n",
632 serdes1_prtcl);
633 break;
634 }
635}
Prabhakar Kushwaha05f37b02017-08-31 16:37:32 +0530636
637static void ls1088a_handle_phy_interface_rgmii(int dpmac_id)
638{
639 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
640 u32 serdes1_prtcl, cfg;
641 struct mii_dev *bus;
642
643 cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) &
644 FSL_CHASSIS3_SRDS1_PRTCL_MASK;
645 cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
646 serdes1_prtcl = serdes_get_number(FSL_SRDS_1, cfg);
647
648 switch (dpmac_id) {
649 case 4:
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530650 wriop_set_phy_address(dpmac_id, 0, RGMII_PHY1_ADDR);
Prabhakar Kushwaha05f37b02017-08-31 16:37:32 +0530651 dpmac_info[dpmac_id].board_mux = EMI1_RGMII1;
652 bus = mii_dev_for_muxval(EMI1_RGMII1);
653 wriop_set_mdio(dpmac_id, bus);
654 break;
655 case 5:
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530656 wriop_set_phy_address(dpmac_id, 0, RGMII_PHY2_ADDR);
Prabhakar Kushwaha05f37b02017-08-31 16:37:32 +0530657 dpmac_info[dpmac_id].board_mux = EMI1_RGMII2;
658 bus = mii_dev_for_muxval(EMI1_RGMII2);
659 wriop_set_mdio(dpmac_id, bus);
660 break;
661 default:
662 printf("qds: WRIOP: Unsupported RGMII SerDes Protocol 0x%02x\n",
663 serdes1_prtcl);
664 break;
665 }
666}
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530667#endif
668
669int board_eth_init(bd_t *bis)
670{
671 int error = 0, i;
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530672#ifdef CONFIG_FSL_MC_ENET
673 struct memac_mdio_info *memac_mdio0_info;
674 char *env_hwconfig = env_get("hwconfig");
675
676 initialize_dpmac_to_slot();
677
678 memac_mdio0_info = (struct memac_mdio_info *)malloc(
679 sizeof(struct memac_mdio_info));
680 memac_mdio0_info->regs =
681 (struct memac_mdio_controller *)
682 CONFIG_SYS_FSL_WRIOP1_MDIO1;
683 memac_mdio0_info->name = DEFAULT_WRIOP_MDIO1_NAME;
684
685 /* Register the real MDIO1 bus */
686 fm_memac_mdio_init(bis, memac_mdio0_info);
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530687 /* Register the muxing front-ends to the MDIO buses */
688 ls1088a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_RGMII1);
689 ls1088a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_RGMII2);
690 ls1088a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT1);
691
692 for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
693 switch (wriop_get_enet_if(i)) {
Prabhakar Kushwaha05f37b02017-08-31 16:37:32 +0530694 case PHY_INTERFACE_MODE_RGMII:
Ashish Kumar856c9dc2017-10-12 15:21:54 +0530695 case PHY_INTERFACE_MODE_RGMII_ID:
Prabhakar Kushwaha05f37b02017-08-31 16:37:32 +0530696 ls1088a_handle_phy_interface_rgmii(i);
697 break;
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530698 case PHY_INTERFACE_MODE_QSGMII:
699 ls1088a_handle_phy_interface_qsgmii(i);
700 break;
701 case PHY_INTERFACE_MODE_SGMII:
702 ls1088a_handle_phy_interface_sgmii(i);
703 break;
704 case PHY_INTERFACE_MODE_XGMII:
705 ls1088a_handle_phy_interface_xsgmii(i);
706 break;
707 default:
708 break;
709
710 if (i == 16)
711 i = NUM_WRIOP_PORTS;
712 }
713 }
714
Ashish Kumar1ef4c772017-08-31 16:12:55 +0530715 error = cpu_eth_init(bis);
716
717 if (hwconfig_f("xqsgmii", env_hwconfig)) {
718 for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
719 switch (wriop_get_enet_if(i)) {
720 case PHY_INTERFACE_MODE_QSGMII:
721 qsgmii_configure_repeater(i);
722 break;
723 case PHY_INTERFACE_MODE_SGMII:
724 sgmii_configure_repeater(i);
725 break;
726 default:
727 break;
728 }
729
730 if (i == 16)
731 i = NUM_WRIOP_PORTS;
732 }
733 }
734#endif
735 error = pci_eth_init(bis);
736 return error;
737}
Bogdan Purcareata33ba9392017-10-05 06:56:53 +0000738
739#if defined(CONFIG_RESET_PHY_R)
740void reset_phy(void)
741{
742 mc_env_boot();
743}
744#endif /* CONFIG_RESET_PHY_R */
Ioana Ciornei666a2fb2020-05-15 09:56:48 +0300745
746#if defined(CONFIG_DM_ETH) && defined(CONFIG_MULTI_DTB_FIT)
747
748/* Structure to hold SERDES protocols supported in case of
749 * CONFIG_DM_ETH enabled (network interfaces are described in the DTS).
750 *
751 * @serdes_block: the index of the SERDES block
752 * @serdes_protocol: the decimal value of the protocol supported
753 * @dts_needed: DTS notes describing the current configuration are needed
754 *
755 * When dts_needed is true, the board_fit_config_name_match() function
756 * will try to exactly match the current configuration of the block with a DTS
757 * name provided.
758 */
759static struct serdes_configuration {
760 u8 serdes_block;
761 u32 serdes_protocol;
762 bool dts_needed;
763} supported_protocols[] = {
764 /* Serdes block #1 */
765 {1, 21, true},
766 {1, 29, true},
767};
768
769#define SUPPORTED_SERDES_PROTOCOLS ARRAY_SIZE(supported_protocols)
770
771static bool protocol_supported(u8 serdes_block, u32 protocol)
772{
773 struct serdes_configuration serdes_conf;
774 int i;
775
776 for (i = 0; i < SUPPORTED_SERDES_PROTOCOLS; i++) {
777 serdes_conf = supported_protocols[i];
778 if (serdes_conf.serdes_block == serdes_block &&
779 serdes_conf.serdes_protocol == protocol)
780 return true;
781 }
782
783 return false;
784}
785
786static void get_str_protocol(u8 serdes_block, u32 protocol, char *str)
787{
788 struct serdes_configuration serdes_conf;
789 int i;
790
791 for (i = 0; i < SUPPORTED_SERDES_PROTOCOLS; i++) {
792 serdes_conf = supported_protocols[i];
793 if (serdes_conf.serdes_block == serdes_block &&
794 serdes_conf.serdes_protocol == protocol) {
795 if (serdes_conf.dts_needed == true)
796 sprintf(str, "%u", protocol);
797 else
798 sprintf(str, "x");
799 return;
800 }
801 }
802}
803
804int board_fit_config_name_match(const char *name)
805{
806 struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
807 char expected_dts[100];
808 char srds_s1_str[2];
809 u32 srds_s1, cfg;
810
811 cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) &
812 FSL_CHASSIS3_SRDS1_PRTCL_MASK;
813 cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
814 srds_s1 = serdes_get_number(FSL_SRDS_1, cfg);
815
816 /* Check for supported protocols. The default DTS will be used
817 * in this case
818 */
819 if (!protocol_supported(1, srds_s1))
820 return -1;
821
822 get_str_protocol(1, srds_s1, srds_s1_str);
823
824 sprintf(expected_dts, "fsl-ls1088a-qds-%s-x", srds_s1_str);
825
826 if (!strcmp(name, expected_dts))
827 return 0;
828
829 return -1;
830}
831#endif