lwip: Fix for SGMII/1000BASEX interface not working on zynq
This patch fixes the issues related to SGMII/1000BASEX phy that is connected to GEM or axi ethernet on zynq. Signed-off-by: Kedareswara rao Appana <appanad@xilinx.com>
This commit is contained in:
parent
c338c3c054
commit
62e8d52031
3 changed files with 235 additions and 258 deletions
5
ThirdParty/sw_services/lwip140/src/ChangeLog
vendored
5
ThirdParty/sw_services/lwip140/src/ChangeLog
vendored
|
@ -1,5 +1,10 @@
|
|||
Change Log for lwip
|
||||
=================================
|
||||
2014-29-30
|
||||
* Fix for CR 827686 - Gem connected 1000BASE-X in PL
|
||||
getting "PHY not connected" error.
|
||||
* Fix for CR 828796 - 2014.3 - AXI Ethernet - 1000BASEX interface not
|
||||
working with echo server design on Zynq.
|
||||
2014-13-06
|
||||
* Fix for CR 802558 - LWIP library doesn't compile
|
||||
with XilKernel/FreeRTOS BSP.
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#define IEEE_COPPER_SPECIFIC_CONTROL_REG 16
|
||||
#define IEEE_SPECIFIC_STATUS_REG 17
|
||||
#define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19
|
||||
#define IEEE_EXT_PHY_SPECIFIC_CONTROL_REG 20
|
||||
#define IEEE_CONTROL_REG_MAC 21
|
||||
#define IEEE_PAGE_ADDRESS_REGISTER 22
|
||||
|
||||
|
@ -119,7 +120,20 @@
|
|||
|
||||
/* Loop counters to check for reset done
|
||||
*/
|
||||
#define RESET_TIMEOUT 500
|
||||
#define RESET_TIMEOUT 0xFFFF
|
||||
#define AUTO_NEG_TIMEOUT 0x00FFFFFF
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
|
||||
XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
|
||||
#define PCM_PMA_CORE_PRESENT
|
||||
#else
|
||||
#undef PCM_PMA_CORE_PRESENT
|
||||
#endif
|
||||
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
#define IEEE_CTRL_RESET 0x9140
|
||||
#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
|
||||
#endif
|
||||
|
||||
void AxiEthernetUtilPhyDelay(unsigned int Seconds);
|
||||
|
||||
|
@ -147,7 +161,120 @@ static int detect_phy(XAxiEthernet *xaxiemacp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned get_phy_speed_88E1116R_model(XAxiEthernet *xaxiemacp, u32 phy_addr)
|
||||
unsigned int get_phy_negotiated_speed (XAxiEthernet *xaxiemacp, u32 phy_addr)
|
||||
{
|
||||
u16 phy_val;
|
||||
u16 control;
|
||||
u16 status;
|
||||
u16 partner_capabilities;
|
||||
u16 partner_capabilities_1000;
|
||||
u16 phylinkspeed;
|
||||
int TimeOut;
|
||||
u16 temp;
|
||||
|
||||
xil_printf("Start PHY autonegotiation \r\n");
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET,
|
||||
&control);
|
||||
|
||||
control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
|
||||
control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
control &= IEEE_CTRL_ISOLATE_DISABLE;
|
||||
#endif
|
||||
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET,
|
||||
control);
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
|
||||
xil_printf("Waiting for PHY to complete autonegotiation \r\n");
|
||||
while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
|
||||
AxiEthernetUtilPhyDelay(1);
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET,
|
||||
&status);
|
||||
|
||||
}
|
||||
|
||||
xil_printf("Autonegotiation complete \r\n");
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1);
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
|
||||
if ((temp & 0x0020) == 0x0020) {
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
|
||||
return 1000;
|
||||
}
|
||||
else {
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
|
||||
xil_printf("Link error, temp = %x\r\n", temp);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Read PHY control and status registers is successful. */
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET,
|
||||
&control);
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET,
|
||||
&status);
|
||||
if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &
|
||||
IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {
|
||||
xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
|
||||
while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr,
|
||||
IEEE_STATUS_REG_OFFSET,
|
||||
&status);
|
||||
}
|
||||
|
||||
xil_printf("autonegotiation complete \r\n");
|
||||
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr,
|
||||
IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
|
||||
&partner_capabilities);
|
||||
if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
|
||||
XAxiEthernet_PhyRead(xaxiemacp, 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int get_phy_speed_88E1116R(XAxiEthernet *xaxiemacp, u32 phy_addr)
|
||||
{
|
||||
u16 phy_val;
|
||||
u16 control;
|
||||
|
@ -226,143 +353,78 @@ unsigned get_phy_speed_88E1116R_model(XAxiEthernet *xaxiemacp, u32 phy_addr)
|
|||
return 10;
|
||||
}
|
||||
|
||||
unsigned get_IEEE_phy_speed(XAxiEthernet *xaxiemacp)
|
||||
|
||||
unsigned int get_phy_speed_88E1111 (XAxiEthernet *xaxiemacp, u32 phy_addr)
|
||||
{
|
||||
u32 phy_addr = detect_phy(xaxiemacp);
|
||||
u16 phy_val;
|
||||
u16 phy_identifier;
|
||||
u16 phy_model;
|
||||
u16 control;
|
||||
u16 status;
|
||||
u16 partner_capabilities;
|
||||
u16 partner_capabilities_1000;
|
||||
u16 phylinkspeed;
|
||||
int TimeOut;
|
||||
u16 phy_val;
|
||||
|
||||
if (XAxiEthernet_GetPhysicalInterface(xaxiemacp) ==
|
||||
XAE_PHY_TYPE_RGMII_2_0) {
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr,
|
||||
IEEE_EXT_PHY_SPECIFIC_CONTROL_REG, &phy_val);
|
||||
phy_val |= PHY_88E1111_RGMII_RX_CLOCK_DELAYED_MASK;
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr,
|
||||
IEEE_EXT_PHY_SPECIFIC_CONTROL_REG, phy_val);
|
||||
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET,
|
||||
&control);
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET,
|
||||
control | IEEE_CTRL_RESET_MASK);
|
||||
|
||||
TimeOut = RESET_TIMEOUT;
|
||||
while (TimeOut) {
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr,
|
||||
IEEE_CONTROL_REG_OFFSET, &control);
|
||||
if (!(control & IEEE_CTRL_RESET_MASK))
|
||||
break;
|
||||
TimeOut -= 1;
|
||||
}
|
||||
|
||||
if (!TimeOut) {
|
||||
xil_printf("%s: Phy Reset failed\n\r", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
|
||||
ADVERTISE_1000);
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
|
||||
ADVERTISE_100_AND_10);
|
||||
|
||||
return get_phy_negotiated_speed(xaxiemacp, phy_addr);
|
||||
}
|
||||
|
||||
unsigned get_IEEE_phy_speed(XAxiEthernet *xaxiemacp)
|
||||
{
|
||||
u16 phy_identifier;
|
||||
u16 phy_model;
|
||||
|
||||
#ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT
|
||||
u32 phy_addr = XPAR_PCSPMA_1000BASEX_PHYADDR;
|
||||
#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT
|
||||
u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
|
||||
#elif XPAR_AXIETHERNET_0_BASEADDR
|
||||
u32 phy_addr = detect_phy(xaxiemacp);
|
||||
|
||||
/* Get the PHY Identifier and Model number */
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 2, &phy_identifier);
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 3, &phy_model);
|
||||
phy_model = phy_model & PHY_MODEL_NUM_MASK;
|
||||
|
||||
if ((phy_identifier == MARVEL_PHY_IDENTIFIER) &&
|
||||
(phy_model == MARVEL_PHY_88E1116R_MODEL)) {
|
||||
|
||||
return get_phy_speed_88E1116R_model(xaxiemacp, phy_addr);
|
||||
}
|
||||
|
||||
if ((phy_identifier == MARVEL_PHY_IDENTIFIER) &&
|
||||
(phy_model == MARVEL_PHY_88E1111_MODEL)) {
|
||||
if (XAxiEthernet_GetPhysicalInterface(xaxiemacp) ==
|
||||
XAE_PHY_TYPE_RGMII_2_0) {
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 20, &phy_val);
|
||||
phy_val |= PHY_88E1111_RGMII_RX_CLOCK_DELAYED_MASK;
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, 20, phy_val);
|
||||
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 0, &control);
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, 0,
|
||||
control | IEEE_CTRL_RESET_MASK);
|
||||
|
||||
TimeOut = RESET_TIMEOUT;
|
||||
while (TimeOut) {
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 0, &control);
|
||||
if (!(control & IEEE_CTRL_RESET_MASK))
|
||||
break;
|
||||
|
||||
TimeOut -= 1;
|
||||
}
|
||||
|
||||
if (!TimeOut) {
|
||||
xil_printf("%s: Phy Reset failed\n\r", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr,
|
||||
IEEE_1000_ADVERTISE_REG_OFFSET,
|
||||
ADVERTISE_1000);
|
||||
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr,
|
||||
IEEE_AUTONEGO_ADVERTISE_REG,
|
||||
ADVERTISE_100_AND_10);
|
||||
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr,
|
||||
IEEE_CONTROL_REG_OFFSET,
|
||||
&control);
|
||||
control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |
|
||||
IEEE_STAT_AUTONEGOTIATE_RESTART);
|
||||
|
||||
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr,
|
||||
IEEE_CONTROL_REG_OFFSET,
|
||||
control);
|
||||
|
||||
/* Read PHY control and status registers is successful. */
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr,
|
||||
IEEE_CONTROL_REG_OFFSET,
|
||||
&control);
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr,
|
||||
IEEE_STATUS_REG_OFFSET,
|
||||
&status);
|
||||
|
||||
if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &
|
||||
IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {
|
||||
|
||||
while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr,
|
||||
IEEE_STATUS_REG_OFFSET,
|
||||
&status);
|
||||
}
|
||||
|
||||
XAxiEthernet_PhyRead(xaxiemacp, phy_addr,
|
||||
IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
|
||||
&partner_capabilities);
|
||||
|
||||
if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
|
||||
XAxiEthernet_PhyRead(xaxiemacp, 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;
|
||||
}
|
||||
|
||||
if (phy_identifier == MARVEL_PHY_IDENTIFIER) {
|
||||
if (phy_model == MARVEL_PHY_88E1116R_MODEL) {
|
||||
return get_phy_speed_88E1116R(xaxiemacp, phy_addr);
|
||||
} else if (phy_model == MARVEL_PHY_88E1111_MODEL) {
|
||||
return get_phy_speed_88E1111(xaxiemacp, phy_addr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
return get_phy_negotiated_speed(xaxiemacp, phy_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned configure_IEEE_phy_speed(XAxiEthernet *xaxiemacp, unsigned speed)
|
||||
|
|
|
@ -53,10 +53,6 @@
|
|||
#include "xparameters_ps.h"
|
||||
#include "xparameters.h"
|
||||
|
||||
/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
|
||||
*** to run it on a PEEP board
|
||||
***/
|
||||
|
||||
/* Advertisement control register. */
|
||||
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
|
||||
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
|
||||
|
@ -91,10 +87,7 @@
|
|||
#define IEEE_CTRL_LINKSPEED_10M 0x0000
|
||||
#define IEEE_CTRL_RESET_MASK 0x8000
|
||||
#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#define IEEE_CTRL_RESET 0x9140
|
||||
#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
|
||||
#endif
|
||||
|
||||
#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008
|
||||
#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020
|
||||
#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200
|
||||
|
@ -122,11 +115,6 @@
|
|||
#define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8)
|
||||
#define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)
|
||||
#define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)
|
||||
#ifdef PEEP
|
||||
#define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031
|
||||
#define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001
|
||||
#define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011
|
||||
#endif
|
||||
#define SLCR_LOCK_KEY_VALUE 0x767B
|
||||
#define SLCR_UNLOCK_KEY_VALUE 0xDF0D
|
||||
#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214)
|
||||
|
@ -135,6 +123,18 @@
|
|||
#define EMAC0_BASE_ADDRESS 0xE000B000
|
||||
#define EMAC1_BASE_ADDRESS 0xE000C000
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
|
||||
XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
|
||||
#define PCM_PMA_CORE_PRESENT
|
||||
#else
|
||||
#undef PCM_PMA_CORE_PRESENT
|
||||
#endif
|
||||
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
#define IEEE_CTRL_RESET 0x9140
|
||||
#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
|
||||
#endif
|
||||
|
||||
static int detect_phy(XEmacPs *xemacpsp)
|
||||
{
|
||||
u16 phy_reg;
|
||||
|
@ -160,104 +160,23 @@ static int detect_phy(XEmacPs *xemacpsp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef PEEP
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else /* Zynq */
|
||||
unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
|
||||
{
|
||||
u16 temp;
|
||||
u16 control;
|
||||
u16 status;
|
||||
u16 partner_capabilities;
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT
|
||||
u32 phy_addr = XPAR_PCSPMA_1000BASEX_PHYADDR;
|
||||
#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT
|
||||
u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
|
||||
#else
|
||||
#elif XPAR_XEMACPS_0_BASEADDR
|
||||
u32 phy_addr = detect_phy(xemacpsp);
|
||||
#endif
|
||||
|
||||
xil_printf("Start PHY autonegotiation \r\n");
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
#else
|
||||
XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
|
||||
|
@ -290,14 +209,12 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
|
|||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
|
||||
control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
|
||||
control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
control &= IEEE_CTRL_ISOLATE_DISABLE;
|
||||
#endif
|
||||
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
|
||||
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
#else
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
|
||||
control |= IEEE_CTRL_RESET_MASK;
|
||||
|
@ -316,7 +233,7 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
|
|||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
|
||||
while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
|
||||
sleep(1);
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
#else
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
|
||||
&temp);
|
||||
|
@ -330,32 +247,41 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
|
|||
|
||||
xil_printf("autonegotiation complete \r\n");
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#ifdef PCM_PMA_CORE_PRESENT
|
||||
#else
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);
|
||||
#endif
|
||||
|
||||
#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
|
||||
#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1);
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
|
||||
if ((temp & 0x0020) == 0x0020) {
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
|
||||
return 1000;
|
||||
}
|
||||
else {
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
|
||||
xil_printf("Link error, temp = %x\r\n", temp);
|
||||
return 0;
|
||||
}
|
||||
#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
|
||||
xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
|
||||
while(!(temp & 0x8000)) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
|
||||
}
|
||||
if((temp & 0x0C00) == 0x0800) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
|
||||
return 1000;
|
||||
}
|
||||
else if((temp & 0x0C00) == 0x0400) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
|
||||
return 100;
|
||||
}
|
||||
else if((temp & 0x0C00) == 0x0000) {
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
|
||||
return 10;
|
||||
} else {
|
||||
xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);
|
||||
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &temp);
|
||||
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, 0x0100);
|
||||
return 10;
|
||||
}
|
||||
#else
|
||||
|
@ -367,7 +293,6 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
|
|||
return 10;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)
|
||||
{
|
||||
|
@ -426,11 +351,9 @@ unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)
|
|||
static void SetUpSLCRDivisors(int mac_baseaddr, int speed)
|
||||
{
|
||||
volatile u32 slcrBaseAddress;
|
||||
#ifndef PEEP
|
||||
u32 SlcrDiv0;
|
||||
u32 SlcrDiv1;
|
||||
u32 SlcrTxClkCntrl;
|
||||
#endif
|
||||
|
||||
*(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
|
||||
|
||||
|
@ -439,18 +362,6 @@ static void SetUpSLCRDivisors(int mac_baseaddr, int speed)
|
|||
} else {
|
||||
slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
|
||||
}
|
||||
#ifdef PEEP
|
||||
if (speed == 1000) {
|
||||
*(volatile unsigned int *)(slcrBaseAddress) =
|
||||
SLCR_GEM_1G_CLK_CTRL_VALUE;
|
||||
} else if (speed == 100) {
|
||||
*(volatile unsigned int *)(slcrBaseAddress) =
|
||||
SLCR_GEM_100M_CLK_CTRL_VALUE;
|
||||
} else {
|
||||
*(volatile unsigned int *)(slcrBaseAddress) =
|
||||
SLCR_GEM_10M_CLK_CTRL_VALUE;
|
||||
}
|
||||
#else
|
||||
if (speed == 1000) {
|
||||
if (mac_baseaddr == EMAC0_BASE_ADDRESS) {
|
||||
#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
|
||||
|
@ -493,7 +404,6 @@ static void SetUpSLCRDivisors(int mac_baseaddr, int speed)
|
|||
SlcrTxClkCntrl |= (SlcrDiv1 << 20);
|
||||
SlcrTxClkCntrl |= (SlcrDiv0 << 8);
|
||||
*(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;
|
||||
#endif
|
||||
*(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue