]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
net: gem_old: Add auto phy detection to Xilinx Gem driver
authorJason Wu <huanyu@xilinx.com>
Tue, 23 Oct 2012 08:31:49 +0000 (18:31 +1000)
committerMichal Simek <monstr@monstr.eu>
Thu, 1 Nov 2012 10:51:53 +0000 (11:51 +0100)
PetaLinux is using phy auto detection. Support it too.

Signed-off-by: Jason Wu <huanyu@xilinx.com>
drivers/net/zynq_gem.h
drivers/net/zynq_gem_wrap.c

index 101db96dc84a5f6312cebb4ee16ade2de1beaf76..ab0916a73446ede241dd10ff099536a2d8cfcb1d 100644 (file)
@@ -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 */
index b780f11e0856c0e497bdba9c6caf5d8148da5e88..c4ef62f159424dcb6badc79ae58fa68d59e475ff 100644 (file)
@@ -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