1 // SPDX-License-Identifier: GPL-2.0+
9 #include <fdt_support.h>
22 #include <asm/global_data.h>
23 #include <asm/arch/fsl_serdes.h>
24 #include <fsl-mc/fsl_mc.h>
25 #include <fsl-mc/ldpaa_wriop.h>
26 #include <linux/libfdt.h>
28 #include "../common/qixis.h"
30 DECLARE_GLOBAL_DATA_PTR
;
34 #define EMI1 1 /* Mdio Bus 1 */
35 #define EMI2 2 /* Mdio Bus 2 */
37 #if defined(CONFIG_FSL_MC_ENET)
53 struct lx2162a_qds_mdio
{
54 enum io_slot ioslot
: 4;
56 struct mii_dev
*realbus
;
59 /* structure explaining the phy configuration on 8 lanes of a serdes*/
60 struct serdes_phy_config
{
61 u8 serdes
; /* serdes protocol */
64 /* -1 terminated array */
65 int phy_address
[WRIOP_MAX_PHY_NUM
+ 1];
68 } phy_config
[SRDS_MAX_LANES
];
71 /* Table defining the phy configuration on 8 lanes of a serdes.
72 * Various assumptions have been made while defining this table.
73 * e.g. for serdes1 protocol 19 it is being assumed that X-M11-USXGMII
74 * card is being used for dpmac 3-4. (X-M12-XFI could also have been used)
75 * And also that this card is connected to IO Slot 1 (could have been connected
76 * to any of the 8 IO slots (IO slot 1 - IO slot 8)).
77 * similarly, it is also being assumed that MDIO 1 is selected on X-M7-40G card
78 * used in serdes1 protocol 19 (could have selected MDIO 2)
79 * To override these settings "dpmac" environment variable can be used after
80 * defining "dpmac_override" in hwconfig environment variable.
81 * This table has limited serdes protocol entries. It can be expanded as per
84 /*****************************************************************
85 *| SERDES_1 PROTOCOL | IO_SLOT | CARD |
86 ******************************************************************
87 *| 2 | IO_SLOT_1 | M4-PCIE-SGMII |
88 *| 3 | IO_SLOT_1 | M11-USXGMII |
89 *| 15 | IO_SLOT_1 | M13-25G |
90 *| 17 | IO_SLOT_1 | M13-25G |
91 *| 18 | IO_SLOT_1 | M11-USXGMII |
92 *| | IO_SLOT_6 | M13-25G |
93 *| 20 | IO_SLOT_1 | M7-40G |
94 *****************************************************************
96 static const struct serdes_phy_config serdes1_phy_config
[] = {
98 {2, {{WRIOP1_DPMAC3
, {SGMII_CARD_PORT1_PHY_ADDR
, -1},
100 {WRIOP1_DPMAC4
, {SGMII_CARD_PORT2_PHY_ADDR
, -1},
102 {WRIOP1_DPMAC5
, {SGMII_CARD_PORT3_PHY_ADDR
, -1},
104 {WRIOP1_DPMAC6
, {SGMII_CARD_PORT4_PHY_ADDR
, -1},
105 EMI1
, IO_SLOT_1
} } },
106 {3, {{WRIOP1_DPMAC3
, {AQ_PHY_ADDR1
, -1},
108 {WRIOP1_DPMAC4
, {AQ_PHY_ADDR2
, -1},
110 {WRIOP1_DPMAC5
, {AQ_PHY_ADDR3
, -1},
112 {WRIOP1_DPMAC6
, {AQ_PHY_ADDR4
, -1},
113 EMI1
, IO_SLOT_1
} } },
114 {15, {{WRIOP1_DPMAC1
, {INPHI_PHY_ADDR1
, INPHI_PHY_ADDR2
, -1},
116 {WRIOP1_DPMAC2
, {INPHI_PHY_ADDR1
, INPHI_PHY_ADDR2
, -1},
117 EMI1
, IO_SLOT_1
} } },
118 {17, {{WRIOP1_DPMAC3
, {INPHI_PHY_ADDR1
, INPHI_PHY_ADDR2
, -1},
120 {WRIOP1_DPMAC4
, {INPHI_PHY_ADDR1
, INPHI_PHY_ADDR2
, -1},
122 {WRIOP1_DPMAC5
, {INPHI_PHY_ADDR1
, INPHI_PHY_ADDR2
, -1},
124 {WRIOP1_DPMAC6
, {INPHI_PHY_ADDR1
, INPHI_PHY_ADDR2
, -1},
125 EMI1
, IO_SLOT_1
} } },
126 {18, {{WRIOP1_DPMAC3
, {AQ_PHY_ADDR1
, -1},
128 {WRIOP1_DPMAC4
, {AQ_PHY_ADDR2
, -1},
130 {WRIOP1_DPMAC5
, {INPHI_PHY_ADDR1
, INPHI_PHY_ADDR2
, -1},
132 {WRIOP1_DPMAC6
, {INPHI_PHY_ADDR1
, INPHI_PHY_ADDR2
, -1},
133 EMI1
, IO_SLOT_6
} } },
134 {20, {{WRIOP1_DPMAC1
, {CORTINA_PHY_ADDR1
, -1},
138 /*****************************************************************
139 *| SERDES_2 PROTOCOL | IO_SLOT | CARD |
140 ******************************************************************
141 *| 2 | IO_SLOT_7 | M4-PCIE-SGMII |
142 *| | IO_SLOT_8 | M4-PCIE-SGMII |
143 *| 3 | IO_SLOT_7 | M4-PCIE-SGMII |
144 *| | IO_SLOT_8 | M4-PCIE-SGMII |
145 *| 5 | IO_SLOT_7 | M4-PCIE-SGMII |
146 *| 10 | IO_SLOT_7 | M4-PCIE-SGMII |
147 *| | IO_SLOT_8 | M4-PCIE-SGMII |
148 *| 11 | IO_SLOT_7 | M4-PCIE-SGMII |
149 *| | IO_SLOT_8 | M4-PCIE-SGMII |
150 *| 12 | IO_SLOT_7 | M4-PCIE-SGMII |
151 *| | IO_SLOT_8 | M4-PCIE-SGMII |
152 ******************************************************************
154 static const struct serdes_phy_config serdes2_phy_config
[] = {
158 {10, {{WRIOP1_DPMAC11
, {SGMII_CARD_PORT1_PHY_ADDR
, -1},
160 {WRIOP1_DPMAC12
, {SGMII_CARD_PORT2_PHY_ADDR
, -1},
162 {WRIOP1_DPMAC17
, {SGMII_CARD_PORT3_PHY_ADDR
, -1},
164 {WRIOP1_DPMAC18
, {SGMII_CARD_PORT4_PHY_ADDR
, -1},
165 EMI1
, IO_SLOT_7
} } },
166 {11, {{WRIOP1_DPMAC12
, {SGMII_CARD_PORT2_PHY_ADDR
, -1},
168 {WRIOP1_DPMAC17
, {SGMII_CARD_PORT3_PHY_ADDR
, -1},
170 {WRIOP1_DPMAC18
, {SGMII_CARD_PORT4_PHY_ADDR
, -1},
172 {WRIOP1_DPMAC16
, {SGMII_CARD_PORT2_PHY_ADDR
, -1},
174 {WRIOP1_DPMAC13
, {SGMII_CARD_PORT3_PHY_ADDR
, -1},
176 {WRIOP1_DPMAC14
, {SGMII_CARD_PORT4_PHY_ADDR
, -1},
177 EMI1
, IO_SLOT_8
} } },
178 {12, {{WRIOP1_DPMAC11
, {SGMII_CARD_PORT1_PHY_ADDR
, -1},
180 {WRIOP1_DPMAC12
, {SGMII_CARD_PORT2_PHY_ADDR
, -1},
182 {WRIOP1_DPMAC17
, {SGMII_CARD_PORT3_PHY_ADDR
, -1},
184 {WRIOP1_DPMAC18
, {SGMII_CARD_PORT4_PHY_ADDR
, -1},
189 const struct phy_config
*get_phy_config(u8 serdes
,
190 const struct serdes_phy_config
*table
,
195 for (i
= 0; i
< table_size
; i
++) {
196 if (table
[i
].serdes
== serdes
)
197 return table
[i
].phy_config
;
203 /* BRDCFG4 controls EMI routing for the board.
205 * 7-6 EMI Interface #1 Primary Routing (CFG_MUX1_EMI1) (1.8V):
206 * EMI1 00= On-board PHY #1
207 * 01= On-board PHY #2
209 * 11= Slots 1..8 multiplexer and translator.
210 * 5-3 EMI Interface #1 Secondary Routing (CFG_MUX2_EMI1) (2.5V):
219 * 2-0 EMI Interface #2 Routing (CFG_MUX_EMI2):
220 * EMI2 000= Slot #1 (secondary EMI)
221 * 001= Slot #2 (secondary EMI)
222 * 010= Slot #3 (secondary EMI)
223 * 011= Slot #4 (secondary EMI)
224 * 100= Slot #5 (secondary EMI)
225 * 101= Slot #6 (secondary EMI)
226 * 110= Slot #7 (secondary EMI)
227 * 111= Slot #8 (secondary EMI)
229 static int lx2162a_qds_get_mdio_mux_val(u8 realbusnum
, enum io_slot ioslot
)
231 switch (realbusnum
) {
239 return (((ioslot
- 1) << BRDCFG4_EMI1SEL_SHIFT
) | 0xC0);
243 return ((ioslot
- 1) << BRDCFG4_EMI2SEL_SHIFT
);
249 static void lx2162a_qds_mux_mdio(struct lx2162a_qds_mdio
*priv
)
251 u8 brdcfg4
, mux_val
, reg
;
253 brdcfg4
= QIXIS_READ(brdcfg
[4]);
255 mux_val
= lx2162a_qds_get_mdio_mux_val(priv
->realbusnum
, priv
->ioslot
);
257 switch (priv
->realbusnum
) {
259 brdcfg4
&= ~BRDCFG4_EMI1SEL_MASK
;
263 brdcfg4
&= ~BRDCFG4_EMI2SEL_MASK
;
269 QIXIS_WRITE(brdcfg
[4], brdcfg4
);
272 static int lx2162a_qds_mdio_read(struct mii_dev
*bus
, int addr
,
273 int devad
, int regnum
)
275 struct lx2162a_qds_mdio
*priv
= bus
->priv
;
277 lx2162a_qds_mux_mdio(priv
);
279 return priv
->realbus
->read(priv
->realbus
, addr
, devad
, regnum
);
282 static int lx2162a_qds_mdio_write(struct mii_dev
*bus
, int addr
, int devad
,
283 int regnum
, u16 value
)
285 struct lx2162a_qds_mdio
*priv
= bus
->priv
;
287 lx2162a_qds_mux_mdio(priv
);
289 return priv
->realbus
->write(priv
->realbus
, addr
, devad
, regnum
, value
);
292 static int lx2162a_qds_mdio_reset(struct mii_dev
*bus
)
294 struct lx2162a_qds_mdio
*priv
= bus
->priv
;
296 return priv
->realbus
->reset(priv
->realbus
);
299 static struct mii_dev
*lx2162a_qds_mdio_init(u8 realbusnum
, enum io_slot ioslot
)
301 struct lx2162a_qds_mdio
*pmdio
;
303 /*should be within MDIO_NAME_LEN*/
304 char dummy_mdio_name
[] = "LX2162A_QDS_MDIO1_IOSLOT1";
306 if (realbusnum
== EMI2
) {
307 if (ioslot
< IO_SLOT_1
|| ioslot
> IO_SLOT_8
) {
308 printf("invalid ioslot %d\n", ioslot
);
311 } else if (realbusnum
== EMI1
) {
312 if (ioslot
< IO_SLOT_1
|| ioslot
> EMI1_RGMII2
) {
313 printf("invalid ioslot %d\n", ioslot
);
317 printf("not supported real mdio bus %d\n", realbusnum
);
321 if (ioslot
== EMI1_RGMII1
)
322 strcpy(dummy_mdio_name
, "LX2162A_QDS_MDIO1_RGMII1");
323 else if (ioslot
== EMI1_RGMII2
)
324 strcpy(dummy_mdio_name
, "LX2162A_QDS_MDIO1_RGMII2");
326 sprintf(dummy_mdio_name
, "LX2162A_QDS_MDIO%d_IOSLOT%d",
328 bus
= miiphy_get_dev_by_name(dummy_mdio_name
);
335 printf("Failed to allocate %s bus\n", dummy_mdio_name
);
339 pmdio
= malloc(sizeof(*pmdio
));
341 printf("Failed to allocate %s private data\n", dummy_mdio_name
);
346 switch (realbusnum
) {
349 miiphy_get_dev_by_name(DEFAULT_WRIOP_MDIO1_NAME
);
353 miiphy_get_dev_by_name(DEFAULT_WRIOP_MDIO2_NAME
);
357 if (!pmdio
->realbus
) {
358 printf("No real mdio bus num %d found\n", realbusnum
);
364 pmdio
->realbusnum
= realbusnum
;
365 pmdio
->ioslot
= ioslot
;
366 bus
->read
= lx2162a_qds_mdio_read
;
367 bus
->write
= lx2162a_qds_mdio_write
;
368 bus
->reset
= lx2162a_qds_mdio_reset
;
369 strcpy(bus
->name
, dummy_mdio_name
);
372 if (!mdio_register(bus
))
375 printf("No bus with name %s\n", dummy_mdio_name
);
381 static inline void do_phy_config(const struct phy_config
*phy_config
)
384 int i
, phy_num
, phy_address
;
386 for (i
= 0; i
< SRDS_MAX_LANES
; i
++) {
387 if (!phy_config
[i
].dpmacid
)
391 phy_num
< ARRAY_SIZE(phy_config
[i
].phy_address
);
393 phy_address
= phy_config
[i
].phy_address
[phy_num
];
394 if (phy_address
== -1)
396 wriop_set_phy_address(phy_config
[i
].dpmacid
,
397 phy_num
, phy_address
);
399 /*Register the muxing front-ends to the MDIO buses*/
400 bus
= lx2162a_qds_mdio_init(phy_config
[i
].mdio_bus
,
401 phy_config
[i
].ioslot
);
403 printf("could not get bus for mdio %d ioslot %d\n",
404 phy_config
[i
].mdio_bus
,
405 phy_config
[i
].ioslot
);
407 wriop_set_mdio(phy_config
[i
].dpmacid
, bus
);
411 static inline void do_dpmac_config(int dpmac
, const char *arg_dpmacid
,
416 u8 realbusnum
, ioslot
;
419 char *phystr
= "phy00";
421 /*search phy in dpmac arg*/
422 for (phy_num
= 0; phy_num
< WRIOP_MAX_PHY_NUM
; phy_num
++) {
423 sprintf(phystr
, "phy%d", phy_num
+ 1);
424 ret
= hwconfig_subarg_f(arg_dpmacid
, phystr
, &len
, env_dpmac
);
426 /*look for phy instead of phy1*/
428 ret
= hwconfig_subarg_f(arg_dpmacid
, "phy",
434 if (len
!= 4 || strncmp(ret
, "0x", 2))
435 printf("invalid phy format in %s variable.\n"
436 "specify phy%d for %s in hex format e.g. 0x12\n",
437 env_dpmac
, phy_num
+ 1, arg_dpmacid
);
439 wriop_set_phy_address(dpmac
, phy_num
,
443 /*search mdio in dpmac arg*/
444 ret
= hwconfig_subarg_f(arg_dpmacid
, "mdio", &len
, env_dpmac
);
446 realbusnum
= *ret
- '0';
448 realbusnum
= EMI_NONE
;
451 /*search io in dpmac arg*/
452 ret
= hwconfig_subarg_f(arg_dpmacid
, "io", &len
, env_dpmac
);
456 ioslot
= IO_SLOT_NONE
;
457 /*Register the muxing front-ends to the MDIO buses*/
458 bus
= lx2162a_qds_mdio_init(realbusnum
, ioslot
);
460 printf("could not get bus for mdio %d ioslot %d\n",
463 wriop_set_mdio(dpmac
, bus
);
468 #endif /* !CONFIG_DM_ETH */
470 int board_eth_init(struct bd_info
*bis
)
472 #ifndef CONFIG_DM_ETH
473 #if defined(CONFIG_FSL_MC_ENET)
474 struct memac_mdio_info mdio_info
;
475 struct memac_mdio_controller
*regs
;
479 char dpmacid
[] = "dpmac00", srds
[] = "00_00_00";
482 const struct phy_config
*phy_config
;
483 struct ccsr_gur
*gur
= (void *)(CFG_SYS_FSL_GUTS_ADDR
);
484 u32 srds_s1
, srds_s2
;
486 srds_s1
= in_le32(&gur
->rcwsr
[28]) &
487 FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK
;
488 srds_s1
>>= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT
;
490 srds_s2
= in_le32(&gur
->rcwsr
[28]) &
491 FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK
;
492 srds_s2
>>= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT
;
494 sprintf(srds
, "%d_%d", srds_s1
, srds_s2
);
496 regs
= (struct memac_mdio_controller
*)CFG_SYS_FSL_WRIOP1_MDIO1
;
497 mdio_info
.regs
= regs
;
498 mdio_info
.name
= DEFAULT_WRIOP_MDIO1_NAME
;
500 /*Register the EMI 1*/
501 fm_memac_mdio_init(bis
, &mdio_info
);
503 regs
= (struct memac_mdio_controller
*)CFG_SYS_FSL_WRIOP1_MDIO2
;
504 mdio_info
.regs
= regs
;
505 mdio_info
.name
= DEFAULT_WRIOP_MDIO2_NAME
;
507 /*Register the EMI 2*/
508 fm_memac_mdio_init(bis
, &mdio_info
);
510 /* "dpmac" environment variable can be used after
511 * defining "dpmac_override" in hwconfig environment variable.
513 if (hwconfig("dpmac_override")) {
514 env_dpmac
= env_get("dpmac");
516 ret
= hwconfig_arg_f("srds", &len
, env_dpmac
);
518 if (strncmp(ret
, srds
, strlen(srds
))) {
519 printf("SERDES configuration changed.\n"
520 "previous: %.*s, current: %s.\n"
521 "update dpmac variable.\n",
522 (int)len
, ret
, srds
);
525 printf("SERDES configuration not found.\n"
526 "Please add srds:%s in dpmac variable\n",
530 for (i
= WRIOP1_DPMAC1
; i
< NUM_WRIOP_PORTS
; i
++) {
531 /* Look for dpmac1 to dpmac24(current max) arg
532 * in dpmac environment variable
534 sprintf(dpmacid
, "dpmac%d", i
);
535 ret
= hwconfig_arg_f(dpmacid
, &len
, env_dpmac
);
537 do_dpmac_config(i
, dpmacid
, env_dpmac
);
540 printf("Warning: environment dpmac not found.\n"
541 "DPAA network interfaces may not work\n");
544 /*Look for phy config for serdes1 in phy config table*/
545 phy_config
= get_phy_config(srds_s1
, serdes1_phy_config
,
546 ARRAY_SIZE(serdes1_phy_config
));
548 printf("%s WRIOP: Unsupported SerDes1 Protocol %d\n",
551 do_phy_config(phy_config
);
553 phy_config
= get_phy_config(srds_s2
, serdes2_phy_config
,
554 ARRAY_SIZE(serdes2_phy_config
));
556 printf("%s WRIOP: Unsupported SerDes2 Protocol %d\n",
559 do_phy_config(phy_config
);
563 if (wriop_get_enet_if(WRIOP1_DPMAC17
) == PHY_INTERFACE_MODE_RGMII_ID
) {
564 wriop_set_phy_address(WRIOP1_DPMAC17
, 0, RGMII_PHY_ADDR1
);
565 bus
= lx2162a_qds_mdio_init(EMI1
, EMI1_RGMII1
);
567 printf("could not get bus for RGMII1\n");
569 wriop_set_mdio(WRIOP1_DPMAC17
, bus
);
572 if (wriop_get_enet_if(WRIOP1_DPMAC18
) == PHY_INTERFACE_MODE_RGMII_ID
) {
573 wriop_set_phy_address(WRIOP1_DPMAC18
, 0, RGMII_PHY_ADDR2
);
574 bus
= lx2162a_qds_mdio_init(EMI1
, EMI1_RGMII2
);
576 printf("could not get bus for RGMII2\n");
578 wriop_set_mdio(WRIOP1_DPMAC18
, bus
);
582 #endif /* CONFIG_FMAN_ENET */
583 #endif /* !CONFIG_DM_ETH */
585 #ifdef CONFIG_PHY_AQUANTIA
587 * Export functions to be used by AQ firmware
590 gd
->jt
->strcpy
= strcpy
;
591 gd
->jt
->mdelay
= mdelay
;
592 gd
->jt
->mdio_get_current_dev
= mdio_get_current_dev
;
593 gd
->jt
->phy_find_by_mask
= phy_find_by_mask
;
594 gd
->jt
->mdio_phydev_for_ethname
= mdio_phydev_for_ethname
;
595 gd
->jt
->miiphy_set_current_dev
= miiphy_set_current_dev
;
601 return pci_eth_init(bis
);
605 #if defined(CONFIG_RESET_PHY_R)
608 #if defined(CONFIG_FSL_MC_ENET)
612 #endif /* CONFIG_RESET_PHY_R */
614 #ifndef CONFIG_DM_ETH
615 #if defined(CONFIG_FSL_MC_ENET)
616 int fdt_fixup_dpmac_phy_handle(void *fdt
, int dpmac_id
, int node_phandle
)
620 char dpmac_str
[] = "dpmacs@00";
621 const char *phy_string
;
623 offset
= fdt_path_offset(fdt
, "/soc/fsl-mc/dpmacs");
626 offset
= fdt_path_offset(fdt
, "/fsl-mc/dpmacs");
629 printf("dpmacs node not found in device tree\n");
633 sprintf(dpmac_str
, "dpmac@%x", dpmac_id
);
634 debug("dpmac_str = %s\n", dpmac_str
);
636 offset
= fdt_subnode_offset(fdt
, offset
, dpmac_str
);
638 printf("%s node not found in device tree\n", dpmac_str
);
642 phy_string
= fdt_getprop(fdt
, offset
, "phy-connection-type", NULL
);
643 if (is_backplane_mode(phy_string
)) {
644 /* Backplane KR mode: skip fixups */
645 printf("Interface %d in backplane KR mode\n", dpmac_id
);
649 ret
= fdt_appendprop_cell(fdt
, offset
, "phy-handle", node_phandle
);
651 printf("%d@%s %d\n", __LINE__
, __func__
, ret
);
653 phy_string
= phy_string_for_interface(wriop_get_enet_if(dpmac_id
));
654 ret
= fdt_setprop_string(fdt
, offset
, "phy-connection-type",
657 printf("%d@%s %d\n", __LINE__
, __func__
, ret
);
662 int fdt_get_ioslot_offset(void *fdt
, struct mii_dev
*mii_dev
, int fpga_offset
)
664 char mdio_ioslot_str
[] = "mdio@00";
665 struct lx2162a_qds_mdio
*priv
;
670 /*Test if the MDIO bus is real mdio bus or muxing front end ?*/
671 if (strncmp(mii_dev
->name
, "LX2162A_QDS_MDIO",
672 strlen("LX2162A_QDS_MDIO")))
675 /*Get the real MDIO bus num and ioslot info from bus's priv data*/
676 priv
= mii_dev
->priv
;
678 debug("real_bus_num = %d, ioslot = %d\n",
679 priv
->realbusnum
, priv
->ioslot
);
681 if (priv
->realbusnum
== EMI1
)
682 reg
= CFG_SYS_FSL_WRIOP1_MDIO1
;
684 reg
= CFG_SYS_FSL_WRIOP1_MDIO2
;
686 offset
= fdt_node_offset_by_compat_reg(fdt
, "fsl,fman-memac-mdio", reg
);
688 printf("mdio@%llx node not found in device tree\n", reg
);
692 phandle
= fdt_get_phandle(fdt
, offset
);
693 phandle
= cpu_to_fdt32(phandle
);
694 offset
= fdt_node_offset_by_prop_value(fdt
, -1, "mdio-parent-bus",
697 printf("mdio-mux-%d node not found in device tree\n",
698 priv
->realbusnum
== EMI1
? 1 : 2);
702 mux_val
= lx2162a_qds_get_mdio_mux_val(priv
->realbusnum
, priv
->ioslot
);
703 if (priv
->realbusnum
== EMI1
)
704 mux_val
>>= BRDCFG4_EMI1SEL_SHIFT
;
706 mux_val
>>= BRDCFG4_EMI2SEL_SHIFT
;
707 sprintf(mdio_ioslot_str
, "mdio@%x", (u8
)mux_val
);
709 offset
= fdt_subnode_offset(fdt
, offset
, mdio_ioslot_str
);
711 printf("%s node not found in device tree\n", mdio_ioslot_str
);
718 int fdt_create_phy_node(void *fdt
, int offset
, u8 phyaddr
, int *subnodeoffset
,
719 struct phy_device
*phy_dev
, int phandle
)
721 char phy_node_name
[] = "ethernet-phy@00";
722 char phy_id_compatible_str
[] = "ethernet-phy-id0000.0000,";
725 sprintf(phy_node_name
, "ethernet-phy@%x", phyaddr
);
726 debug("phy_node_name = %s\n", phy_node_name
);
728 *subnodeoffset
= fdt_add_subnode(fdt
, offset
, phy_node_name
);
729 if (*subnodeoffset
<= 0) {
730 printf("Could not add subnode %s inside node %s err = %s\n",
731 phy_node_name
, fdt_get_name(fdt
, offset
, NULL
),
732 fdt_strerror(*subnodeoffset
));
733 return *subnodeoffset
;
736 sprintf(phy_id_compatible_str
, "ethernet-phy-id%04x.%04x,",
737 phy_dev
->phy_id
>> 16, phy_dev
->phy_id
& 0xFFFF);
738 debug("phy_id_compatible_str %s\n", phy_id_compatible_str
);
740 ret
= fdt_setprop_string(fdt
, *subnodeoffset
, "compatible",
741 phy_id_compatible_str
);
743 printf("%d@%s %d\n", __LINE__
, __func__
, ret
);
747 if (phy_dev
->is_c45
) {
748 ret
= fdt_appendprop_string(fdt
, *subnodeoffset
, "compatible",
749 "ethernet-phy-ieee802.3-c45");
751 printf("%d@%s %d\n", __LINE__
, __func__
, ret
);
755 ret
= fdt_appendprop_string(fdt
, *subnodeoffset
, "compatible",
756 "ethernet-phy-ieee802.3-c22");
758 printf("%d@%s %d\n", __LINE__
, __func__
, ret
);
763 ret
= fdt_setprop_cell(fdt
, *subnodeoffset
, "reg", phyaddr
);
765 printf("%d@%s %d\n", __LINE__
, __func__
, ret
);
769 ret
= fdt_set_phandle(fdt
, *subnodeoffset
, phandle
);
771 printf("%d@%s %d\n", __LINE__
, __func__
, ret
);
777 fdt_del_node(fdt
, *subnodeoffset
);
782 #define is_rgmii(dpmac_id) \
783 wriop_get_enet_if((dpmac_id)) == PHY_INTERFACE_MODE_RGMII_ID
785 int fdt_fixup_board_phy(void *fdt
)
787 int fpga_offset
, offset
, subnodeoffset
;
788 struct mii_dev
*mii_dev
;
789 struct list_head
*mii_devs
, *entry
;
790 int ret
, dpmac_id
, i
;
791 struct phy_device
*phy_dev
;
792 char ethname
[ETH_NAME_LEN
];
793 phy_interface_t phy_iface
;
797 /* we know FPGA is connected to i2c0, therefore search path directly,
798 * instead of compatible property, as it saves time
800 fpga_offset
= fdt_path_offset(fdt
, "/soc/i2c@2000000/fpga");
803 fpga_offset
= fdt_path_offset(fdt
, "/i2c@2000000/fpga");
805 if (fpga_offset
< 0) {
806 printf("i2c@2000000/fpga node not found in device tree\n");
810 ret
= fdt_generate_phandle(fdt
, &phandle
);
814 mii_devs
= mdio_get_list_head();
816 list_for_each(entry
, mii_devs
) {
817 mii_dev
= list_entry(entry
, struct mii_dev
, link
);
818 debug("mii_dev name : %s\n", mii_dev
->name
);
819 offset
= fdt_get_ioslot_offset(fdt
, mii_dev
, fpga_offset
);
823 // Look for phy devices attached to MDIO bus muxing front end
824 // and create their entries with compatible being the device id
825 for (i
= 0; i
< PHY_MAX_ADDR
; i
++) {
826 phy_dev
= mii_dev
->phymap
[i
];
830 // TODO: use sscanf instead of loop
831 dpmac_id
= WRIOP1_DPMAC1
;
832 while (dpmac_id
< NUM_WRIOP_PORTS
) {
833 phy_iface
= wriop_get_enet_if(dpmac_id
);
834 snprintf(ethname
, ETH_NAME_LEN
, "DPMAC%d@%s",
836 phy_string_for_interface(phy_iface
));
837 if (strcmp(ethname
, phy_dev
->dev
->name
) == 0)
841 if (dpmac_id
== NUM_WRIOP_PORTS
)
844 if ((dpmac_id
== 17 || dpmac_id
== 18) &&
848 ret
= fdt_create_phy_node(fdt
, offset
, i
,
854 ret
= fdt_fixup_dpmac_phy_handle(fdt
,
857 fdt_del_node(fdt
, subnodeoffset
);
860 /* calculate offset again as new node addition may have
863 offset
= fdt_get_ioslot_offset(fdt
, mii_dev
,
874 #endif // CONFIG_FSL_MC_ENET
877 #if defined(CONFIG_DM_ETH) && defined(CONFIG_MULTI_DTB_FIT)
879 /* Structure to hold SERDES protocols supported in case of
880 * CONFIG_DM_ETH enabled (network interfaces are described in the DTS).
882 * @serdes_block: the index of the SERDES block
883 * @serdes_protocol: the decimal value of the protocol supported
884 * @dts_needed: DTS notes describing the current configuration are needed
886 * When dts_needed is true, the board_fit_config_name_match() function
887 * will try to exactly match the current configuration of the block with a DTS
890 static struct serdes_configuration
{
894 } supported_protocols
[] = {
895 /* Serdes block #1 */
903 /* Serdes block #2 */
912 #define SUPPORTED_SERDES_PROTOCOLS ARRAY_SIZE(supported_protocols)
914 static bool protocol_supported(u8 serdes_block
, u32 protocol
)
916 struct serdes_configuration serdes_conf
;
919 for (i
= 0; i
< SUPPORTED_SERDES_PROTOCOLS
; i
++) {
920 serdes_conf
= supported_protocols
[i
];
921 if (serdes_conf
.serdes_block
== serdes_block
&&
922 serdes_conf
.serdes_protocol
== protocol
)
929 static void get_str_protocol(u8 serdes_block
, u32 protocol
, char *str
)
931 struct serdes_configuration serdes_conf
;
934 for (i
= 0; i
< SUPPORTED_SERDES_PROTOCOLS
; i
++) {
935 serdes_conf
= supported_protocols
[i
];
936 if (serdes_conf
.serdes_block
== serdes_block
&&
937 serdes_conf
.serdes_protocol
== protocol
) {
938 if (serdes_conf
.dts_needed
== true)
939 sprintf(str
, "%u", protocol
);
947 int board_fit_config_name_match(const char *name
)
949 struct ccsr_gur
*gur
= (void *)(CFG_SYS_FSL_GUTS_ADDR
);
950 u32 rcw_status
= in_le32(&gur
->rcwsr
[28]);
951 char srds_s1_str
[2], srds_s2_str
[2];
952 u32 srds_s1
, srds_s2
;
953 char expected_dts
[100];
955 srds_s1
= rcw_status
& FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK
;
956 srds_s1
>>= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT
;
958 srds_s2
= rcw_status
& FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK
;
959 srds_s2
>>= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT
;
961 /* Check for supported protocols. The default DTS will be used
964 if (!protocol_supported(1, srds_s1
) ||
965 !protocol_supported(2, srds_s2
))
968 get_str_protocol(1, srds_s1
, srds_s1_str
);
969 get_str_protocol(2, srds_s2
, srds_s2_str
);
971 sprintf(expected_dts
, "fsl-lx2160a-qds-%s-%s",
972 srds_s1_str
, srds_s2_str
);
974 if (!strcmp(name
, expected_dts
))