unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed) { u16 control; u32 phy_addr = detect_phy(xemacpsp); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); control &= ~IEEE_CTRL_LINKSPEED_1000M; control &= ~IEEE_CTRL_LINKSPEED_100M; control &= ~IEEE_CTRL_LINKSPEED_10M; if (speed == 1000) { control |= IEEE_CTRL_LINKSPEED_1000M; } else if (speed == 100) { control |= IEEE_CTRL_LINKSPEED_100M; /* Dont advertise PHY speed of 1000 Mbps */ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0); /* Dont advertise PHY speed of 10 Mbps */ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, ADVERTISE_100); } else if (speed == 10) { control |= IEEE_CTRL_LINKSPEED_10M; /* Dont advertise PHY speed of 1000 Mbps */ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0); /* Dont advertise PHY speed of 100 Mbps */ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, ADVERTISE_10); } XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control | IEEE_CTRL_RESET_MASK); { volatile int wait; for (wait=0; wait < 100000; wait++); /*for (wait=0; wait < 100000; wait++);*/ } return 0; }
void init_emacps(xemacpsif_s *xemacps, struct netif *netif) { UINTPTR mac_address = (UINTPTR)(netif->state); XEmacPs *xemacpsp; XEmacPs_Config *mac_config; s32_t status = XST_SUCCESS; u32_t i; u32_t phyfoundforemac0 = FALSE; u32_t phyfoundforemac1 = FALSE; /* obtain config of this emac */ mac_config = (XEmacPs_Config *)xemacps_lookup_config(mac_address); xemacpsp = &xemacps->emacps; /* set mac address */ status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1); if (status != XST_SUCCESS) { xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__); } XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224); /* Please refer to file header comments for the file xemacpsif_physpeed.c * to know more about the PHY programming sequence. * For PCS PMA core, phy_setup is called with the predefined PHY address * exposed through xaparemeters.h * For RGMII case, assuming multiple PHYs can be present on the MDIO bus, * detect_phy is called to get the addresses of the PHY present on * a particular MDIO bus (emac0 or emac1). This address map is populated * in phymapemac0 or phymapemac1. * phy_setup is then called for each PHY present on the MDIO bus. */ #ifdef PCM_PMA_CORE_PRESENT #ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT link_speed = phy_setup(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR); #elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT link_speed = phy_setup(xemacpsp, XPAR_PCSPMA_SGMII_PHYADDR); #endif #else detect_phy(xemacpsp); for (i = 31; i > 0; i--) { if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) { if (phymapemac0[i] == TRUE) { link_speed = phy_setup(xemacpsp, i); phyfoundforemac0 = TRUE; } } else { if (phymapemac1[i] == TRUE) { link_speed = phy_setup(xemacpsp, i); phyfoundforemac1 = TRUE; } } } /* If no PHY was detected, use broadcast PHY address of 0 */ if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) { if (phyfoundforemac0 == FALSE) link_speed = phy_setup(xemacpsp, 0); } else { if (phyfoundforemac1 == FALSE) link_speed = phy_setup(xemacpsp, 0); } #endif XEmacPs_SetOperatingSpeed(xemacpsp, link_speed); /* Setting the operating speed of the MAC needs a delay. */ { volatile s32_t wait; for (wait=0; wait < 20000; wait++); } }
unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) { u16 control; u16 status; u16 partner_capabilities; u16 partner_capabilities_1000; u16 phylinkspeed; u32 phy_addr = detect_phy(xemacpsp); XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, ADVERTISE_1000); /* Advertise PHY speed of 100 and 10 Mbps */ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, ADVERTISE_100_AND_10); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE | IEEE_STAT_AUTONEGOTIATE_RESTART); XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); /* Read PHY control and status registers is successful. */ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status & IEEE_STAT_AUTONEGOTIATE_CAPABLE)) { while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); } XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &partner_capabilities); if (status & IEEE_STAT_1GBPS_EXTENSIONS) { XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET, &partner_capabilities_1000); if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS) return 1000; } if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS) return 100; if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS) return 10; xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n", __FUNCTION__); return 10; } else { /* Update TEMAC speed accordingly */ if (status & IEEE_STAT_1GBPS_EXTENSIONS) { /* Get commanded link speed */ phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK; switch (phylinkspeed) { case (IEEE_CTRL_LINKSPEED_1000M): return 1000; case (IEEE_CTRL_LINKSPEED_100M): return 100; case (IEEE_CTRL_LINKSPEED_10M): return 10; default: xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n", __FUNCTION__, phylinkspeed); return 10; } } else { return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10; } } }