blob: 003af44308b3d4b77fbe20a58abf8ea1889d6676 [file] [log] [blame]
/*
* 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;
}