From: Jason Wu Date: Tue, 23 Oct 2012 08:31:49 +0000 (+1000) Subject: net: gem_old: Add auto phy detection to Xilinx Gem driver X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e977e9c61340b071e4f4e96694a50f1839f8c64f;p=thirdparty%2Fu-boot.git net: gem_old: Add auto phy detection to Xilinx Gem driver PetaLinux is using phy auto detection. Support it too. Signed-off-by: Jason Wu --- diff --git a/drivers/net/zynq_gem.h b/drivers/net/zynq_gem.h index 101db96dc84..ab0916a7344 100644 --- a/drivers/net/zynq_gem.h +++ b/drivers/net/zynq_gem.h @@ -375,6 +375,16 @@ extern "C" { #define XEMACPSS_MAX_VLAN_FRAME_SIZE (XEMACPSS_MTU + XEMACPSS_HDR_SIZE + \ XEMACPSS_HDR_VLAN_SIZE + XEMACPSS_TRL_SIZE) +/* Use MII register 1 (MII status register) to detect PHY */ +#define PHY_DETECT_REG 1 + +/* Mask used to verify certain PHY features (or register contents) + * in the register above: + * 0x1000: 10Mbps full duplex support + * 0x0800: 10Mbps half duplex support + * 0x0008: Auto-negotiation support + */ +#define PHY_DETECT_MASK 0x1808 /**************************** Type Definitions ******************************/ /** @name Typedefs for callback functions @@ -429,6 +439,7 @@ typedef struct XEmacPss { u32 IsStarted; /* Device is currently started */ u32 IsReady; /* Device is initialized and ready */ u32 Options; /* Current options word */ + int phyaddr; /* Phy address */ XEmacPss_BdRing TxBdRing; /* Transmit BD ring */ XEmacPss_BdRing RxBdRing; /* Receive BD ring */ diff --git a/drivers/net/zynq_gem_wrap.c b/drivers/net/zynq_gem_wrap.c index b780f11e085..c4ef62f1594 100644 --- a/drivers/net/zynq_gem_wrap.c +++ b/drivers/net/zynq_gem_wrap.c @@ -103,7 +103,7 @@ static u32 phy_rd(XEmacPss * e, u32 a) u16 PhyData; phy_spinwait(e); - XEmacPss_PhyRead(e, CONFIG_XGMAC_PHY_ADDR, a, &PhyData); + XEmacPss_PhyRead(e, e->phyaddr, a, &PhyData); phy_spinwait(e); return PhyData; } @@ -111,7 +111,7 @@ static u32 phy_rd(XEmacPss * e, u32 a) static void phy_wr(XEmacPss * e, u32 a, u32 v) { phy_spinwait(e); - XEmacPss_PhyWrite(e, CONFIG_XGMAC_PHY_ADDR, a, v); + XEmacPss_PhyWrite(e, e->phyaddr, a, v); phy_spinwait(e); } @@ -523,9 +523,46 @@ static int Xgmac_write_hwaddr(struct eth_device *dev) return 0; } +static void phy_detection(struct eth_device * dev) +{ + int i; + u16 phyreg; + struct XEmacPss *priv = dev->priv; + + if (priv->phyaddr != -1 ) { + XEmacPss_PhyRead(dev->priv, priv->phyaddr, PHY_DETECT_REG, &phyreg); + if ((phyreg != 0xFFFF) && + ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { + /* Found a valid PHY address */ + debug("Default phy address %d is valid\n", priv->phyaddr); + return; + } else { + debug("PHY address is not setup correctly %d\n", priv->phyaddr); + priv->phyaddr = -1; + } + } + + debug("detecting phy address\n"); + if (priv->phyaddr == -1 ) { + /* detect the PHY address */ + for (i = 31; i >= 0; i--) { + XEmacPss_PhyRead(dev->priv, i, PHY_DETECT_REG, &phyreg); + if ((phyreg != 0xFFFF) && + ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { + /* Found a valid PHY address */ + priv->phyaddr = i; + debug("Found valid phy address, %d\n", i); + return; + } + } + } + printf("PHY is not detected\n"); +} + int zynq_gem_initialize_old(bd_t *bis) { struct eth_device *dev; + struct XEmacPss *priv; dev = malloc(sizeof(*dev)); if (dev == NULL) return 1; @@ -544,9 +581,16 @@ int zynq_gem_initialize_old(bd_t *bis) dev->send = Xgmac_send; dev->recv = Xgmac_rx; dev->write_hwaddr = Xgmac_write_hwaddr; - + priv = dev->priv; eth_register(dev); +#ifdef CONFIG_PHY_ADDR + priv->phyaddr = CONFIG_PHY_ADDR; +#else + priv->phyaddr = -1; +#endif + phy_detection(dev); + #if defined(CONFIG_CMD_MII) && !defined(CONFIG_BITBANGMII) miiphy_register(dev->name, Xgmac_mii_read, Xgmac_mii_write); #endif