/* * Code provided by Xilinx. */ /* BSP includes. */ #include "xemaclite.h" /* lwIP includes. */ #include "lwip/opt.h" /* Advertisement control register. */ #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ #define ADVERTISE_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | ADVERTISE_10HALF | ADVERTISE_100HALF) /* PHY registers/offsets. */ #define IEEE_CONTROL_REG_OFFSET 0 #define IEEE_STATUS_REG_OFFSET 1 #define IEEE_AUTONEGO_ADVERTISE_REG 4 #define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5 #define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10 #define IEEE_1000_ADVERTISE_REG_OFFSET 9 #define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040 #define IEEE_CTRL_LINKSPEED_MASK 0x0040 #define IEEE_CTRL_LINKSPEED_1000M 0x0040 #define IEEE_CTRL_LINKSPEED_100M 0x2000 #define IEEE_CTRL_LINKSPEED_10M 0x0000 #define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000 #define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008 #define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020 #define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200 #define IEEE_STAT_1GBPS_EXTENSIONS 0x0100 #define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00 #define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380 #define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060 #define PHY_DETECT_REG 1 #define PHY_DETECT_MASK 0x1808 static int detect_phy_emaclite(XEmacLite *pxEMACLiteInstance); unsigned short vInitialisePHY( XEmacLite *pxEMACLiteInstance ) { u16 control; u16 status; u16 partner_capabilities; u16 partner_capabilities_1000; u16 phylinkspeed; u32 phy_addr = detect_phy_emaclite(pxEMACLiteInstance); /* Dont advertise PHY speed of 1000 Mbps */ XEmacLite_PhyWrite(pxEMACLiteInstance, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0); /* Advertise PHY speed of 100 and 10 Mbps */ XEmacLite_PhyWrite(pxEMACLiteInstance, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, ADVERTISE_100_AND_10); XEmacLite_PhyRead(pxEMACLiteInstance, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE | IEEE_STAT_AUTONEGOTIATE_RESTART); XEmacLite_PhyWrite(pxEMACLiteInstance, phy_addr, IEEE_CONTROL_REG_OFFSET, control); /* Read PHY control and status registers is successful. */ XEmacLite_PhyRead(pxEMACLiteInstance, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); XEmacLite_PhyRead(pxEMACLiteInstance, phy_addr, IEEE_STATUS_REG_OFFSET, &status); if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status & IEEE_STAT_AUTONEGOTIATE_CAPABLE)) { while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { XEmacLite_PhyRead(pxEMACLiteInstance, phy_addr, IEEE_STATUS_REG_OFFSET, &status); } XEmacLite_PhyRead(pxEMACLiteInstance, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &partner_capabilities); if (status & IEEE_STAT_1GBPS_EXTENSIONS) { XEmacLite_PhyRead(pxEMACLiteInstance, 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; } } } static int detect_phy_emaclite(XEmacLite *pxEMACLiteInstance) { u16 phy_reg; u32 phy_addr; for (phy_addr = 31; phy_addr > 0; phy_addr--) { XEmacLite_PhyRead(pxEMACLiteInstance, phy_addr, PHY_DETECT_REG, &phy_reg); if ((phy_reg != 0xFFFF) && ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { /* Found a valid PHY address */ LWIP_DEBUGF(NETIF_DEBUG, ("XEMacLite detect_phy: PHY detected at address %d.\r\n", phy_addr)); LWIP_DEBUGF(NETIF_DEBUG, ("XEMacLite detect_phy: PHY detected.\r\n")); return phy_addr; } } LWIP_DEBUGF(NETIF_DEBUG, ("XEMacLite detect_phy: No PHY detected. Assuming a PHY at address 0\r\n")); /* default to zero */ return 0; }