/* * Copyright 2013 Freescale Semiconductor, Inc. * * SPDX-License-Identifier: GPL-2.0+ */ /* * The RGMII PHYs are provided by the two on-board PHY connected to * dTSEC instances 4 and 5. The SGMII PHYs are provided by one on-board * PHY or by the standard four-port SGMII riser card (VSC). */ #include #include #include #include #include #include #include #include #include #include "../common/fman.h" #include "../common/qixis.h" #include "t1040qds_qixis.h" #ifdef CONFIG_FMAN_ENET /* - In T1040 there are only 8 SERDES lanes, spread across 2 SERDES banks. * Bank 1 -> Lanes A, B, C, D * Bank 2 -> Lanes E, F, G, H */ /* Mapping of 8 SERDES lanes to T1040 QDS board slots. A value of '0' here * means that the mapping must be determined dynamically, or that the lane * maps to something other than a board slot. */ static u8 lane_to_slot[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* On the Vitesse VSC8234XHG SGMII riser card there are 4 SGMII PHYs * housed. */ static int riser_phy_addr[] = { CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR, CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR, CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR, CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR, }; /* Slot2 does not have EMI connections */ #define EMI_NONE 0xFFFFFFFF #define EMI1_RGMII0 0 #define EMI1_RGMII1 1 #define EMI1_SLOT1 2 #define EMI1_SLOT3 3 #define EMI1_SLOT4 4 #define EMI1_SLOT5 5 #define EMI1_SLOT6 6 #define EMI1_SLOT7 7 #define EMI2 8 static int mdio_mux[NUM_FM_PORTS]; static const char * const mdio_names[] = { "T1040_QDS_MDIO0", "T1040_QDS_MDIO1", "T1040_QDS_MDIO2", "T1040_QDS_MDIO3", "T1040_QDS_MDIO4", "T1040_QDS_MDIO5", "T1040_QDS_MDIO6", "T1040_QDS_MDIO7", }; struct t1040_qds_mdio { u8 muxval; struct mii_dev *realbus; }; static const char *t1040_qds_mdio_name_for_muxval(u8 muxval) { return mdio_names[muxval]; } struct mii_dev *mii_dev_for_muxval(u8 muxval) { struct mii_dev *bus; const char *name = t1040_qds_mdio_name_for_muxval(muxval); if (!name) { printf("No bus for muxval %x\n", muxval); return NULL; } bus = miiphy_get_dev_by_name(name); if (!bus) { printf("No bus by name %s\n", name); return NULL; } return bus; } static void t1040_qds_mux_mdio(u8 muxval) { u8 brdcfg4; if (muxval <= 7) { brdcfg4 = QIXIS_READ(brdcfg[4]); brdcfg4 &= ~BRDCFG4_EMISEL_MASK; brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT); QIXIS_WRITE(brdcfg[4], brdcfg4); } } static int t1040_qds_mdio_read(struct mii_dev *bus, int addr, int devad, int regnum) { struct t1040_qds_mdio *priv = bus->priv; t1040_qds_mux_mdio(priv->muxval); return priv->realbus->read(priv->realbus, addr, devad, regnum); } static int t1040_qds_mdio_write(struct mii_dev *bus, int addr, int devad, int regnum, u16 value) { struct t1040_qds_mdio *priv = bus->priv; t1040_qds_mux_mdio(priv->muxval); return priv->realbus->write(priv->realbus, addr, devad, regnum, value); } static int t1040_qds_mdio_reset(struct mii_dev *bus) { struct t1040_qds_mdio *priv = bus->priv; return priv->realbus->reset(priv->realbus); } static int t1040_qds_mdio_init(char *realbusname, u8 muxval) { struct t1040_qds_mdio *pmdio; struct mii_dev *bus = mdio_alloc(); if (!bus) { printf("Failed to allocate t1040_qds MDIO bus\n"); return -1; } pmdio = malloc(sizeof(*pmdio)); if (!pmdio) { printf("Failed to allocate t1040_qds private data\n"); free(bus); return -1; } bus->read = t1040_qds_mdio_read; bus->write = t1040_qds_mdio_write; bus->reset = t1040_qds_mdio_reset; sprintf(bus->name, t1040_qds_mdio_name_for_muxval(muxval)); pmdio->realbus = miiphy_get_dev_by_name(realbusname); if (!pmdio->realbus) { printf("No bus with name %s\n", realbusname); free(bus); free(pmdio); return -1; } pmdio->muxval = muxval; bus->priv = pmdio; return mdio_register(bus); } /* * Initialize the lane_to_slot[] array. * * On the T1040QDS board the mapping is controlled by ?? register. */ static void initialize_lane_to_slot(void) { ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR; int serdes1_prtcl = (in_be32(&gur->rcwsr[4]) & FSL_CORENET2_RCWSR4_SRDS1_PRTCL) >> FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT; QIXIS_WRITE(cms[0], 0x07); switch (serdes1_prtcl) { case 0x60: case 0x66: case 0x67: case 0x69: lane_to_slot[1] = 7; lane_to_slot[2] = 6; lane_to_slot[3] = 5; break; case 0x86: lane_to_slot[1] = 7; lane_to_slot[2] = 7; lane_to_slot[3] = 7; break; case 0x87: lane_to_slot[1] = 7; lane_to_slot[2] = 7; lane_to_slot[3] = 7; lane_to_slot[7] = 7; break; case 0x89: lane_to_slot[1] = 7; lane_to_slot[2] = 7; lane_to_slot[3] = 7; lane_to_slot[6] = 7; lane_to_slot[7] = 7; break; case 0x8d: lane_to_slot[1] = 7; lane_to_slot[2] = 7; lane_to_slot[3] = 7; lane_to_slot[5] = 3; lane_to_slot[6] = 3; lane_to_slot[7] = 3; break; case 0x8F: case 0x85: lane_to_slot[1] = 7; lane_to_slot[2] = 6; lane_to_slot[3] = 5; lane_to_slot[6] = 3; lane_to_slot[7] = 3; break; case 0xA5: lane_to_slot[1] = 7; lane_to_slot[6] = 3; lane_to_slot[7] = 3; break; case 0xA7: lane_to_slot[1] = 7; lane_to_slot[2] = 6; lane_to_slot[3] = 5; lane_to_slot[7] = 7; break; case 0xAA: lane_to_slot[1] = 7; lane_to_slot[6] = 7; lane_to_slot[7] = 7; break; case 0x40: lane_to_slot[2] = 7; lane_to_slot[3] = 7; break; default: printf("qds: Fman: Unsupported SerDes Protocol 0x%02x\n", serdes1_prtcl); break; } } /* * Given the following ... * * 1) A pointer to an Fman Ethernet node (as identified by the 'compat' * compatible string and 'addr' physical address) * * 2) An Fman port * * ... update the phy-handle property of the Ethernet node to point to the * right PHY. This assumes that we already know the PHY for each port. * * The offset of the Fman Ethernet node is also passed in for convenience, but * it is not used, and we recalculate the offset anyway. * * Note that what we call "Fman ports" (enum fm_port) is really an Fman MAC. * Inside the Fman, "ports" are things that connect to MACs. We only call them * ports in U-Boot because on previous Ethernet devices (e.g. Gianfar), MACs * and ports are the same thing. * */ void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr, enum fm_port port, int offset) { phy_interface_t intf = fm_info_get_enet_if(port); char phy[16]; /* The RGMII PHY is identified by the MAC connected to it */ if (intf == PHY_INTERFACE_MODE_RGMII) { sprintf(phy, "rgmii_phy%u", port == FM1_DTSEC4 ? 1 : 2); fdt_set_phy_handle(fdt, compat, addr, phy); } /* The SGMII PHY is identified by the MAC connected to it */ if (intf == PHY_INTERFACE_MODE_SGMII) { int lane = serdes_get_first_lane(FSL_SRDS_1, SGMII_FM1_DTSEC1 + port); u8 slot; if (lane < 0) return; slot = lane_to_slot[lane]; if (slot) { /* Slot housing a SGMII riser card */ sprintf(phy, "phy_s%x_%02x", slot, (fm_info_get_phy_address(port - FM1_DTSEC1)- CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR + 1)); fdt_set_phy_handle(fdt, compat, addr, phy); } } } void fdt_fixup_board_enet(void *fdt) { int i, lane, idx; for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { idx = i - FM1_DTSEC1; switch (fm_info_get_enet_if(i)) { case PHY_INTERFACE_MODE_SGMII: lane = serdes_get_first_lane(FSL_SRDS_1, SGMII_FM1_DTSEC1 + idx); if (lane < 0) break; switch (mdio_mux[i]) { case EMI1_SLOT3: fdt_status_okay_by_alias(fdt, "emi1_slot3"); break; case EMI1_SLOT5: fdt_status_okay_by_alias(fdt, "emi1_slot5"); break; case EMI1_SLOT6: fdt_status_okay_by_alias(fdt, "emi1_slot6"); break; case EMI1_SLOT7: fdt_status_okay_by_alias(fdt, "emi1_slot7"); break; } break; case PHY_INTERFACE_MODE_RGMII: if (i == FM1_DTSEC4) fdt_status_okay_by_alias(fdt, "emi1_rgmii0"); if (i == FM1_DTSEC5) fdt_status_okay_by_alias(fdt, "emi1_rgmii1"); break; default: break; } } } #endif /* #ifdef CONFIG_FMAN_ENET */ static void set_brdcfg9_for_gtx_clk(void) { u8 brdcfg9; brdcfg9 = QIXIS_READ(brdcfg[9]); /* Initializing EPHY2 clock to RGMII mode */ brdcfg9 &= ~(BRDCFG9_EPHY2_MASK); brdcfg9 |= (BRDCFG9_EPHY2_VAL); QIXIS_WRITE(brdcfg[9], brdcfg9); } void t1040_handle_phy_interface_sgmii(int i) { int lane, idx, slot; idx = i - FM1_DTSEC1; lane = serdes_get_first_lane(FSL_SRDS_1, SGMII_FM1_DTSEC1 + idx); if (lane < 0) return; slot = lane_to_slot[lane]; switch (slot) { case 1: mdio_mux[i] = EMI1_SLOT1; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; case 3: if (FM1_DTSEC4 == i) fm_info_set_phy_address(i, riser_phy_addr[0]); if (FM1_DTSEC5 == i) fm_info_set_phy_address(i, riser_phy_addr[1]); mdio_mux[i] = EMI1_SLOT3; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; case 4: mdio_mux[i] = EMI1_SLOT4; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; case 5: /* Slot housing a SGMII riser card? */ fm_info_set_phy_address(i, riser_phy_addr[0]); mdio_mux[i] = EMI1_SLOT5; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; case 6: /* Slot housing a SGMII riser card? */ fm_info_set_phy_address(i, riser_phy_addr[0]); mdio_mux[i] = EMI1_SLOT6; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; case 7: if (FM1_DTSEC1 == i) fm_info_set_phy_address(i, riser_phy_addr[0]); if (FM1_DTSEC2 == i) fm_info_set_phy_address(i, riser_phy_addr[1]); if (FM1_DTSEC3 == i) fm_info_set_phy_address(i, riser_phy_addr[2]); if (FM1_DTSEC5 == i) fm_info_set_phy_address(i, riser_phy_addr[3]); mdio_mux[i] = EMI1_SLOT7; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; default: break; } fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); } void t1040_handle_phy_interface_rgmii(int i) { fm_info_set_phy_address(i, i == FM1_DTSEC5 ? CONFIG_SYS_FM1_DTSEC5_PHY_ADDR : CONFIG_SYS_FM1_DTSEC4_PHY_ADDR); mdio_mux[i] = (i == FM1_DTSEC5) ? EMI1_RGMII1 : EMI1_RGMII0; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); } int board_eth_init(bd_t *bis) { #ifdef CONFIG_FMAN_ENET struct memac_mdio_info memac_mdio_info; unsigned int i; #ifdef CONFIG_VSC9953 int lane; int phy_addr; phy_interface_t phy_int; struct mii_dev *bus; #endif printf("Initializing Fman\n"); set_brdcfg9_for_gtx_clk(); initialize_lane_to_slot(); /* Initialize the mdio_mux array so we can recognize empty elements */ for (i = 0; i < NUM_FM_PORTS; i++) mdio_mux[i] = EMI_NONE; memac_mdio_info.regs = (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR; memac_mdio_info.name = DEFAULT_FM_MDIO_NAME; /* Register the real 1G MDIO bus */ fm_memac_mdio_init(bis, &memac_mdio_info); /* Register the muxing front-ends to the MDIO buses */ t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII0); t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII1); t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT1); t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT3); t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT4); t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT5); t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT6); t1040_qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT7); /* * Program on board RGMII PHY addresses. If the SGMII Riser * card used, we'll override the PHY address later. For any DTSEC that * is RGMII, we'll also override its PHY address later. We assume that * DTSEC4 and DTSEC5 are used for RGMII. */ fm_info_set_phy_address(FM1_DTSEC4, CONFIG_SYS_FM1_DTSEC4_PHY_ADDR); fm_info_set_phy_address(FM1_DTSEC5, CONFIG_SYS_FM1_DTSEC5_PHY_ADDR); for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { switch (fm_info_get_enet_if(i)) { case PHY_INTERFACE_MODE_QSGMII: fm_info_set_mdio(i, NULL); break; case PHY_INTERFACE_MODE_SGMII: t1040_handle_phy_interface_sgmii(i); break; case PHY_INTERFACE_MODE_RGMII: /* Only DTSEC4 and DTSEC5 can be routed to RGMII */ t1040_handle_phy_interface_rgmii(i); break; default: break; } } #ifdef CONFIG_VSC9953 for (i = 0; i < VSC9953_MAX_PORTS; i++) { lane = -1; phy_addr = 0; phy_int = PHY_INTERFACE_MODE_NONE; switch (i) { case 0: case 1: case 2: case 3: lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_SW1_A); /* PHYs connected over QSGMII */ if (lane >= 0) { phy_addr = CONFIG_SYS_FM1_QSGMII21_PHY_ADDR + i; phy_int = PHY_INTERFACE_MODE_QSGMII; break; } lane = serdes_get_first_lane(FSL_SRDS_1, SGMII_SW1_MAC1 + i); if (lane < 0) break; /* PHYs connected over QSGMII */ if (i != 3 || lane_to_slot[lane] == 7) phy_addr = CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR + i; else phy_addr = CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR; phy_int = PHY_INTERFACE_MODE_SGMII; break; case 4: case 5: case 6: case 7: lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_SW1_B); /* PHYs connected over QSGMII */ if (lane >= 0) { phy_addr = CONFIG_SYS_FM1_QSGMII11_PHY_ADDR + i - 4; phy_int = PHY_INTERFACE_MODE_QSGMII; break; } lane = serdes_get_first_lane(FSL_SRDS_1, SGMII_SW1_MAC1 + i); /* PHYs connected over SGMII */ if (lane >= 0) { phy_addr = CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR + i - 3; phy_int = PHY_INTERFACE_MODE_SGMII; } break; case 8: if (serdes_get_first_lane(FSL_SRDS_1, SGMII_FM1_DTSEC1) < 0) /* FM1@DTSEC1 is connected to SW1@PORT8 */ vsc9953_port_enable(i); break; case 9: if (serdes_get_first_lane(FSL_SRDS_1, SGMII_FM1_DTSEC2) < 0) { /* Enable L2 On MAC2 using SCFG */ struct ccsr_scfg *scfg = (struct ccsr_scfg *) CONFIG_SYS_MPC85xx_SCFG; out_be32(&scfg->esgmiiselcr, in_be32(&scfg->esgmiiselcr) | (0x80000000)); vsc9953_port_enable(i); } break; } if (lane >= 0) { bus = mii_dev_for_muxval(lane_to_slot[lane]); vsc9953_port_info_set_mdio(i, bus); vsc9953_port_enable(i); } vsc9953_port_info_set_phy_address(i, phy_addr); vsc9953_port_info_set_phy_int(i, phy_int); } #endif cpu_eth_init(bis); #endif return pci_eth_init(bis); }