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