net: mt7628-eth: make phy link up detection optional via DT
[oweals/u-boot.git] / drivers / net / mt7628-eth.c
index 4675b0f00319d81cb0253032ed3c51f7ded10508..abfdc75ad8d4da1c42e7a2a316b637960d3d7b57 100644 (file)
@@ -111,6 +111,7 @@ struct fe_tx_dma {
 
 #define NUM_RX_DESC            256
 #define NUM_TX_DESC            4
+#define NUM_PHYS               5
 
 #define PADDING_LENGTH         60
 
@@ -120,9 +121,6 @@ struct fe_tx_dma {
 #define CONFIG_DMA_STOP_TIMEOUT        100
 #define CONFIG_TX_DMA_TIMEOUT  100
 
-#define LINK_DELAY_TIME                500             /* 500 ms */
-#define LINK_TIMEOUT           10000           /* 10 seconds */
-
 struct mt7628_eth_dev {
        void __iomem *base;             /* frame engine base address */
        void __iomem *eth_sw_base;      /* switch base address */
@@ -140,6 +138,8 @@ struct mt7628_eth_dev {
        int tx_dma_idx;
 
        struct reset_ctl        rst_ephy;
+
+       struct phy_device *phy;
 };
 
 static int mdio_wait_read(struct mt7628_eth_dev *priv, u32 mask, bool mask_set)
@@ -437,20 +437,13 @@ static int mt7628_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
        return 0;
 }
 
-static int phy_link_up(struct mt7628_eth_dev *priv)
-{
-       u32 val;
-
-       mii_mgr_read(priv, 0x00, MII_BMSR, &val);
-       return !!(val & BMSR_LSTATUS);
-}
-
 static int mt7628_eth_start(struct udevice *dev)
 {
        struct mt7628_eth_dev *priv = dev_get_priv(dev);
        void __iomem *base = priv->base;
        uchar packet[MTK_QDMA_PAGE_SIZE];
        uchar *packetp;
+       int ret;
        int i;
 
        for (i = 0; i < NUM_RX_DESC; i++) {
@@ -493,25 +486,13 @@ static int mt7628_eth_start(struct udevice *dev)
        wmb();
        eth_dma_start(priv);
 
-       /* Check if link is not up yet */
-       if (!phy_link_up(priv)) {
-               /* Wait for link to come up */
-
-               printf("Waiting for link to come up .");
-               for (i = 0; i < (LINK_TIMEOUT / LINK_DELAY_TIME); i++) {
-                       mdelay(LINK_DELAY_TIME);
-                       if (phy_link_up(priv)) {
-                               mdelay(100);    /* Ensure all is ready */
-                               break;
-                       }
+       if (priv->phy) {
+               ret = phy_startup(priv->phy);
+               if (ret)
+                       return ret;
 
-                       printf(".");
-               }
-
-               if (phy_link_up(priv))
-                       printf(" done\n");
-               else
-                       printf(" timeout! Trying anyways\n");
+               if (!priv->phy->link)
+                       return -EAGAIN;
        }
 
        /*
@@ -538,6 +519,7 @@ static int mt7628_eth_probe(struct udevice *dev)
 {
        struct mt7628_eth_dev *priv = dev_get_priv(dev);
        struct mii_dev *bus;
+       int poll_link_phy;
        int ret;
        int i;
 
@@ -584,6 +566,25 @@ static int mt7628_eth_probe(struct udevice *dev)
        if (ret)
                return ret;
 
+       poll_link_phy = dev_read_u32_default(dev, "mediatek,poll-link-phy", -1);
+       if (poll_link_phy >= 0) {
+               if (poll_link_phy >= NUM_PHYS) {
+                       pr_err("invalid phy %d for poll-link-phy\n",
+                              poll_link_phy);
+                       return ret;
+               }
+
+               priv->phy = phy_connect(bus, poll_link_phy, dev,
+                                       PHY_INTERFACE_MODE_MII);
+               if (!priv->phy) {
+                       pr_err("failed to probe phy %d\n", poll_link_phy);
+                       return -ENODEV;
+               }
+
+               priv->phy->advertising = priv->phy->supported;
+               phy_config(priv->phy);
+       }
+
        /* Switch configuration */
        rt305x_esw_init(priv);