net: mt7628-eth: make phy link up detection optional via DT
authorWeijie Gao <weijie.gao@mediatek.com>
Wed, 25 Sep 2019 09:45:33 +0000 (17:45 +0800)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Fri, 25 Oct 2019 15:20:44 +0000 (17:20 +0200)
The mt7628 has an embedded ethernet switch (5 phy ports + 1 cpu port).
Although in IOT mode only port0 is usable, the phy0 is still connected
to the switch, not the ethernet gmac directly.

This patch rewrites it and makes it optional. It can be turned on by adding
mediatek,poll-link-phy = <?> explicitly into the eth node. By default the
driver is switch mode with all 5 phy ports working without link detection.

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
drivers/net/Kconfig
drivers/net/mt7628-eth.c

index 2ce3092db0bc1eeaf2adbd6e8fbd505d42cff0c6..eb3d7ed45f09ba52c00562e34e7325aef786090b 100644 (file)
@@ -322,6 +322,7 @@ config MACB_ZYNQ
 config MT7628_ETH
        bool "MediaTek MT7628 Ethernet Interface"
        depends on SOC_MT7628
+       select PHYLIB
        help
          The MediaTek MT7628 ethernet interface is used on MT7628 and
          MT7688 based boards.
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);