xref: /openbmc/u-boot/board/freescale/p2041rdb/eth.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
20787ecc0SMingkai Hu /*
30787ecc0SMingkai Hu  * Copyright 2011 Freescale Semiconductor, Inc.
40787ecc0SMingkai Hu  * Author: Mingkai Hu <Mingkai.hu@freescale.com>
50787ecc0SMingkai Hu  */
60787ecc0SMingkai Hu 
70787ecc0SMingkai Hu /*
80787ecc0SMingkai Hu  * The RGMII PHYs are provided by the two on-board PHY. The SGMII PHYs
90787ecc0SMingkai Hu  * are provided by the three on-board PHY or by the standard Freescale
100787ecc0SMingkai Hu  * four-port SGMII riser card. We need to change the phy-handle in the
110787ecc0SMingkai Hu  * kernel dts file to point to the correct PHY according to serdes mux
120787ecc0SMingkai Hu  * and serdes protocol selection.
130787ecc0SMingkai Hu  */
140787ecc0SMingkai Hu 
150787ecc0SMingkai Hu #include <common.h>
160787ecc0SMingkai Hu #include <netdev.h>
170787ecc0SMingkai Hu #include <asm/fsl_serdes.h>
180787ecc0SMingkai Hu #include <fm_eth.h>
190787ecc0SMingkai Hu #include <fsl_mdio.h>
200787ecc0SMingkai Hu #include <malloc.h>
218225b2fdSShaohui Xie #include <fsl_dtsec.h>
220787ecc0SMingkai Hu 
230787ecc0SMingkai Hu #include "cpld.h"
240787ecc0SMingkai Hu #include "../common/fman.h"
250787ecc0SMingkai Hu 
260787ecc0SMingkai Hu #ifdef CONFIG_FMAN_ENET
270787ecc0SMingkai Hu /*
280787ecc0SMingkai Hu  * Mapping of all 18 SERDES lanes to board slots. A value of '0' here means
290787ecc0SMingkai Hu  * that the mapping must be determined dynamically, or that the lane maps to
300787ecc0SMingkai Hu  * something other than a board slot
310787ecc0SMingkai Hu  */
320787ecc0SMingkai Hu static u8 lane_to_slot[] = {
330787ecc0SMingkai Hu 	0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0
340787ecc0SMingkai Hu };
350787ecc0SMingkai Hu 
360787ecc0SMingkai Hu static int riser_phy_addr[] = {
370787ecc0SMingkai Hu 	CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR,
380787ecc0SMingkai Hu 	CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR,
390787ecc0SMingkai Hu 	CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR,
400787ecc0SMingkai Hu 	CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR,
410787ecc0SMingkai Hu };
420787ecc0SMingkai Hu 
430787ecc0SMingkai Hu /*
440787ecc0SMingkai Hu  * Initialize the lane_to_slot[] array.
450787ecc0SMingkai Hu  *
460787ecc0SMingkai Hu  * On the P2040RDB board the mapping is controlled by CPLD register.
470787ecc0SMingkai Hu  */
initialize_lane_to_slot(void)480787ecc0SMingkai Hu static void initialize_lane_to_slot(void)
490787ecc0SMingkai Hu {
500787ecc0SMingkai Hu 	u8 mux = CPLD_READ(serdes_mux);
510787ecc0SMingkai Hu 
520787ecc0SMingkai Hu 	lane_to_slot[6] = (mux & SERDES_MUX_LANE_6_MASK) ? 0 : 1;
530787ecc0SMingkai Hu 	lane_to_slot[10] = (mux & SERDES_MUX_LANE_A_MASK) ? 0 : 2;
540787ecc0SMingkai Hu 	lane_to_slot[12] = (mux & SERDES_MUX_LANE_C_MASK) ? 0 : 2;
550787ecc0SMingkai Hu 	lane_to_slot[13] = (mux & SERDES_MUX_LANE_D_MASK) ? 0 : 2;
560787ecc0SMingkai Hu }
570787ecc0SMingkai Hu 
580787ecc0SMingkai Hu /*
590787ecc0SMingkai Hu  * Given the following ...
600787ecc0SMingkai Hu  *
610787ecc0SMingkai Hu  * 1) A pointer to an Fman Ethernet node (as identified by the 'compat'
620787ecc0SMingkai Hu  * compatible string and 'addr' physical address)
630787ecc0SMingkai Hu  *
640787ecc0SMingkai Hu  * 2) An Fman port
650787ecc0SMingkai Hu  *
660787ecc0SMingkai Hu  * ... update the phy-handle property of the Ethernet node to point to the
670787ecc0SMingkai Hu  * right PHY.  This assumes that we already know the PHY for each port.
680787ecc0SMingkai Hu  *
690787ecc0SMingkai Hu  * The offset of the Fman Ethernet node is also passed in for convenience, but
700787ecc0SMingkai Hu  * it is not used, and we recalculate the offset anyway.
710787ecc0SMingkai Hu  *
720787ecc0SMingkai Hu  * Note that what we call "Fman ports" (enum fm_port) is really an Fman MAC.
730787ecc0SMingkai Hu  * Inside the Fman, "ports" are things that connect to MACs.  We only call them
740787ecc0SMingkai Hu  * ports in U-Boot because on previous Ethernet devices (e.g. Gianfar), MACs
750787ecc0SMingkai Hu  * and ports are the same thing.
760787ecc0SMingkai Hu  *
770787ecc0SMingkai Hu  */
board_ft_fman_fixup_port(void * fdt,char * compat,phys_addr_t addr,enum fm_port port,int offset)780787ecc0SMingkai Hu void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
790787ecc0SMingkai Hu 			      enum fm_port port, int offset)
800787ecc0SMingkai Hu {
810787ecc0SMingkai Hu 	phy_interface_t intf = fm_info_get_enet_if(port);
820787ecc0SMingkai Hu 	char phy[16];
830787ecc0SMingkai Hu 
840787ecc0SMingkai Hu 	/* The RGMII PHY is identified by the MAC connected to it */
850787ecc0SMingkai Hu 	if (intf == PHY_INTERFACE_MODE_RGMII) {
860787ecc0SMingkai Hu 		sprintf(phy, "phy_rgmii_%u", port == FM1_DTSEC5 ? 0 : 1);
870787ecc0SMingkai Hu 		fdt_set_phy_handle(fdt, compat, addr, phy);
880787ecc0SMingkai Hu 	}
890787ecc0SMingkai Hu 
900787ecc0SMingkai Hu 	/* The SGMII PHY is identified by the MAC connected to it */
910787ecc0SMingkai Hu 	if (intf == PHY_INTERFACE_MODE_SGMII) {
920787ecc0SMingkai Hu 		int lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + port);
930787ecc0SMingkai Hu 		u8 slot;
940787ecc0SMingkai Hu 		if (lane < 0)
950787ecc0SMingkai Hu 			return;
960787ecc0SMingkai Hu 		slot = lane_to_slot[lane];
970787ecc0SMingkai Hu 		if (slot) {
980787ecc0SMingkai Hu 			sprintf(phy, "phy_sgmii_%x",
990787ecc0SMingkai Hu 					CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR
1000787ecc0SMingkai Hu 					+ (port - FM1_DTSEC1));
1010787ecc0SMingkai Hu 			fdt_set_phy_handle(fdt, compat, addr, phy);
1020787ecc0SMingkai Hu 		} else {
1030787ecc0SMingkai Hu 			sprintf(phy, "phy_sgmii_%x",
1040787ecc0SMingkai Hu 					CONFIG_SYS_FM1_DTSEC1_PHY_ADDR
1050787ecc0SMingkai Hu 					+ (port - FM1_DTSEC1));
1060787ecc0SMingkai Hu 			fdt_set_phy_handle(fdt, compat, addr, phy);
1070787ecc0SMingkai Hu 		}
1080787ecc0SMingkai Hu 	}
1090787ecc0SMingkai Hu 
1100787ecc0SMingkai Hu 	if (intf == PHY_INTERFACE_MODE_XGMII) {
1110787ecc0SMingkai Hu 		/* XAUI */
1120787ecc0SMingkai Hu 		int lane = serdes_get_first_lane(XAUI_FM1);
1130787ecc0SMingkai Hu 		if (lane >= 0) {
1140787ecc0SMingkai Hu 			/* The XAUI PHY is identified by the slot */
1150787ecc0SMingkai Hu 			sprintf(phy, "phy_xgmii_%u", lane_to_slot[lane]);
1160787ecc0SMingkai Hu 			fdt_set_phy_handle(fdt, compat, addr, phy);
1170787ecc0SMingkai Hu 		}
1180787ecc0SMingkai Hu 	}
1190787ecc0SMingkai Hu }
1200787ecc0SMingkai Hu #endif /* #ifdef CONFIG_FMAN_ENET */
1210787ecc0SMingkai Hu 
board_eth_init(bd_t * bis)1220787ecc0SMingkai Hu int board_eth_init(bd_t *bis)
1230787ecc0SMingkai Hu {
1240787ecc0SMingkai Hu #ifdef CONFIG_FMAN_ENET
1250787ecc0SMingkai Hu 	struct fsl_pq_mdio_info dtsec_mdio_info;
1260787ecc0SMingkai Hu 	struct tgec_mdio_info tgec_mdio_info;
1270787ecc0SMingkai Hu 	unsigned int i, slot;
1280787ecc0SMingkai Hu 	int lane;
1290787ecc0SMingkai Hu 
1300787ecc0SMingkai Hu 	printf("Initializing Fman\n");
1310787ecc0SMingkai Hu 
1320787ecc0SMingkai Hu 	initialize_lane_to_slot();
1330787ecc0SMingkai Hu 
1340787ecc0SMingkai Hu 	dtsec_mdio_info.regs =
1350787ecc0SMingkai Hu 		(struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR;
1360787ecc0SMingkai Hu 	dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
1370787ecc0SMingkai Hu 
1380787ecc0SMingkai Hu 	/* Register the real 1G MDIO bus */
1390787ecc0SMingkai Hu 	fsl_pq_mdio_init(bis, &dtsec_mdio_info);
1400787ecc0SMingkai Hu 
1410787ecc0SMingkai Hu 	tgec_mdio_info.regs =
1420787ecc0SMingkai Hu 		(struct tgec_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
1430787ecc0SMingkai Hu 	tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
1440787ecc0SMingkai Hu 
1450787ecc0SMingkai Hu 	/* Register the real 10G MDIO bus */
1460787ecc0SMingkai Hu 	fm_tgec_mdio_init(bis, &tgec_mdio_info);
1470787ecc0SMingkai Hu 
1480787ecc0SMingkai Hu 	/*
1490787ecc0SMingkai Hu 	 * Program the three on-board SGMII PHY addresses. If the SGMII Riser
1500787ecc0SMingkai Hu 	 * card used, we'll override the PHY address later. For any DTSEC that
1510787ecc0SMingkai Hu 	 * is RGMII, we'll also override its PHY address later. We assume that
1520787ecc0SMingkai Hu 	 * DTSEC4 and DTSEC5 are used for RGMII.
1530787ecc0SMingkai Hu 	 */
1540787ecc0SMingkai Hu 	fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR);
1550787ecc0SMingkai Hu 	fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR);
1560787ecc0SMingkai Hu 	fm_info_set_phy_address(FM1_DTSEC3, CONFIG_SYS_FM1_DTSEC3_PHY_ADDR);
1570787ecc0SMingkai Hu 
1580787ecc0SMingkai Hu 	for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
1590787ecc0SMingkai Hu 		int idx = i - FM1_DTSEC1;
1600787ecc0SMingkai Hu 
1610787ecc0SMingkai Hu 		switch (fm_info_get_enet_if(i)) {
1620787ecc0SMingkai Hu 		case PHY_INTERFACE_MODE_SGMII:
1630787ecc0SMingkai Hu 			lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx);
1640787ecc0SMingkai Hu 			if (lane < 0)
1650787ecc0SMingkai Hu 				break;
1660787ecc0SMingkai Hu 			slot = lane_to_slot[lane];
1670787ecc0SMingkai Hu 			if (slot)
1680787ecc0SMingkai Hu 				fm_info_set_phy_address(i, riser_phy_addr[i]);
1690787ecc0SMingkai Hu 			break;
1700787ecc0SMingkai Hu 		case PHY_INTERFACE_MODE_RGMII:
1710787ecc0SMingkai Hu 			/* Only DTSEC4 and DTSEC5 can be routed to RGMII */
1720787ecc0SMingkai Hu 			fm_info_set_phy_address(i, i == FM1_DTSEC5 ?
1730787ecc0SMingkai Hu 					CONFIG_SYS_FM1_DTSEC5_PHY_ADDR :
1740787ecc0SMingkai Hu 					CONFIG_SYS_FM1_DTSEC4_PHY_ADDR);
1750787ecc0SMingkai Hu 			break;
1760787ecc0SMingkai Hu 		default:
1770787ecc0SMingkai Hu 			printf("Fman1: DTSEC%u set to unknown interface %i\n",
1780787ecc0SMingkai Hu 			       idx + 1, fm_info_get_enet_if(i));
1790787ecc0SMingkai Hu 			break;
1800787ecc0SMingkai Hu 		}
1810787ecc0SMingkai Hu 
1820787ecc0SMingkai Hu 		fm_info_set_mdio(i,
1830787ecc0SMingkai Hu 			miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
1840787ecc0SMingkai Hu 	}
1850787ecc0SMingkai Hu 
1860787ecc0SMingkai Hu 	lane = serdes_get_first_lane(XAUI_FM1);
1870787ecc0SMingkai Hu 	if (lane >= 0) {
1880787ecc0SMingkai Hu 		slot = lane_to_slot[lane];
1890787ecc0SMingkai Hu 		if (slot)
1900787ecc0SMingkai Hu 			fm_info_set_phy_address(FM1_10GEC1,
1910787ecc0SMingkai Hu 					CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
1920787ecc0SMingkai Hu 	}
1930787ecc0SMingkai Hu 
1940787ecc0SMingkai Hu 	fm_info_set_mdio(FM1_10GEC1,
1950787ecc0SMingkai Hu 			miiphy_get_dev_by_name(DEFAULT_FM_TGEC_MDIO_NAME));
1960787ecc0SMingkai Hu 	cpu_eth_init(bis);
1970787ecc0SMingkai Hu #endif
1980787ecc0SMingkai Hu 
1990787ecc0SMingkai Hu 	return pci_eth_init(bis);
2000787ecc0SMingkai Hu }
201