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