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;
}
示例#2
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;

		}

	}
}