164 lines
4.9 KiB
C
164 lines
4.9 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|
||
|
|
||
|
|