diff --git a/ThirdParty/sw_services/lwip141/src/ChangeLog b/ThirdParty/sw_services/lwip141/src/ChangeLog index 122ecc81..0bee3155 100644 --- a/ThirdParty/sw_services/lwip141/src/ChangeLog +++ b/ThirdParty/sw_services/lwip141/src/ChangeLog @@ -1,10 +1,11 @@ Change Log for lwip ================================= -2015-09-30 +2015-10-12 * Created a new version lwip141_v1_3. * Made changes in xemacpsif_dma.c to add required barriers. * Remove repeated sysarch protect and unprotect calls. * Replace printf with xil_printf. + * Add support for TI phy. 2015-09-09 * Fix compilation issues with the non hier axi eth design 2015-09-04 diff --git a/ThirdParty/sw_services/lwip141/src/contrib/ports/xilinx/netif/xemacpsif_physpeed.c b/ThirdParty/sw_services/lwip141/src/contrib/ports/xilinx/netif/xemacpsif_physpeed.c index 5ed0de4d..d07264c5 100644 --- a/ThirdParty/sw_services/lwip141/src/contrib/ports/xilinx/netif/xemacpsif_physpeed.c +++ b/ThirdParty/sw_services/lwip141/src/contrib/ports/xilinx/netif/xemacpsif_physpeed.c @@ -155,12 +155,22 @@ #define PHY_IDENTIFIER_1_REG 2 #define PHY_DETECT_MASK 0x1808 #define PHY_MARVELL_IDENTIFIER 0x0141 +#define PHY_TI_IDENTIFIER 0x2000 #define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140 #define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100 #define XEMACPS_GMII2RGMII_SPEED10_FD 0x100 #define XEMACPS_GMII2RGMII_REG_NUM 0x10 +#define PHY_REGCR 0x0D +#define PHY_ADDAR 0x0E +#define PHY_RGMIIDCTL 0x86 +#define PHY_RGMIICTL 0x32 +#define PHY_STS 0x11 + +#define PHY_REGCR_ADDR 0x001F +#define PHY_REGCR_DATA 0x401F + /* Frequency setting */ #define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4) #define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8) @@ -296,8 +306,9 @@ void detect_phy(XEmacPs *xemacpsp) XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG, &phy_reg); - if (phy_reg != PHY_MARVELL_IDENTIFIER) { - xil_printf("WARNING: Not a Marvell Ethernet PHY. Please verify the initialization sequence\r\n"); + if ((phy_reg != PHY_MARVELL_IDENTIFIER) && + (phy_reg != PHY_TI_IDENTIFIER)) { + xil_printf("WARNING: Not a Marvell or TI Ethernet PHY. Please verify the initialization sequence\r\n"); } } } @@ -360,17 +371,150 @@ u32_t phy_setup (XEmacPs *xemacpsp, u32_t phy_addr) return link_speed; } -static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) +static u32_t get_TI_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) { u16_t temp; u16_t control; u16_t status; u16_t status_speed; - u32_t gigeversion = 2; u32_t timeout_counter = 0; u32_t temp_speed; + u32_t phyregtemp; + int i; + u32_t RetStatus; - gigeversion = ((Xil_In32(xemacpsp->Config.BaseAddress + 0xFC)) >> 16) & 0xFFF; + xil_printf("Start PHY autonegotiation \r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, &phyregtemp); + phyregtemp |= 0x4000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, phyregtemp); + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, &phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error during sw reset \n\r"); + return XST_FAILURE; + } + + XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &phyregtemp); + phyregtemp |= 0x8000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, phyregtemp); + + /* + * Delay + */ + for(i=0;i<1000000000;i++); + + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error during reset \n\r"); + return XST_FAILURE; + } + + /* FIFO depth */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x10, 0x5048); + XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x10, phyregtemp); + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0x10, &phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error writing to 0x10 \n\r"); + return XST_FAILURE; + } + + /* TX/RX tuning */ + /* Write to PHY_RGMIIDCTL */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xA8); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error in tuning"); + return XST_FAILURE; + } + + /* Read PHY_RGMIIDCTL */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, &phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error in tuning"); + return XST_FAILURE; + } + + /* Write PHY_RGMIICTL */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xD3); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error in tuning"); + return XST_FAILURE; + } + + /* Read PHY_RGMIICTL */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, &phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error in tuning"); + return XST_FAILURE; + } + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); + control |= IEEE_ASYMMETRIC_PAUSE_MASK; + control |= IEEE_PAUSE_MASK; + control |= ADVERTISE_100; + control |= ADVERTISE_10; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + &control); + control |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; + control |= IEEE_STAT_AUTONEGOTIATE_RESTART; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); + + while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { + sleep(1); + timeout_counter++; + + if (timeout_counter == 30) { + xil_printf("Auto negotiation error \r\n"); + return; + } + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + } + xil_printf("autonegotiation complete \r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_STS, &status_speed); + if ((status_speed & 0xC000) == 0x8000) { + return 1000; + } else if ((status_speed & 0xC000) == 0x4000) { + return 100; + } else { + return 10; + } + + return XST_SUCCESS; +} + +static u32_t get_Marvell_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) +{ + u16_t temp; + u16_t control; + u16_t status; + u16_t status_speed; + u32_t timeout_counter = 0; + u32_t temp_speed; + u32_t phyregtemp; xil_printf("Start PHY autonegotiation \r\n"); @@ -388,19 +532,11 @@ static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) control |= ADVERTISE_10; XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); - if (gigeversion == 2) { - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, - &control); - control |= ADVERTISE_1000; - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, - control); - } else { - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, - &control); - control &= ~ADVERTISE_1000; - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, - control); - } + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + &control); + control |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + control); XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, @@ -425,25 +561,27 @@ static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) else break; } - xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); + while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { sleep(1); - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2, - &temp); + XEmacPs_PhyRead(xemacpsp, phy_addr, + IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp); timeout_counter++; if (timeout_counter == 30) { xil_printf("Auto negotiation error \r\n"); return; } - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, - &status); - } + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + } xil_printf("autonegotiation complete \r\n"); - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &status_speed); + XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG, + &status_speed); if (status_speed & 0x400) { temp_speed = status_speed & IEEE_SPEED_MASK; @@ -455,6 +593,26 @@ static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) return 10; } + return XST_SUCCESS; +} + +static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) +{ + u32_t phy_identity; + u32_t RetStatus; + + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG, + &phy_identity); + if (phy_identity == PHY_TI_IDENTIFIER) { + RetStatus = get_TI_phy_speed(xemacpsp, phy_addr); + } else { + RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr); + } + if (RetStatus != XST_SUCCESS) { + return RetStatus; + } + + return XST_SUCCESS; } static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed)