From: Chao-ying Fu <c...@mips.com>

Add optional PHY reset support via GPIO defined in the device tree.

Improve robustness by handling probe errors and falling back to the
environment-provided MAC address if no hardware MAC is found.

Signed-off-by: Chao-ying Fu <c...@mips.com>
Signed-off-by: Uros Stajic <uros.sta...@htecgroup.com>
---
 board/mips/boston-riscv/Kconfig |  4 ++++
 drivers/net/pch_gbe.c           | 36 +++++++++++++++++++++++++++++++--
 drivers/net/pch_gbe.h           |  1 +
 net/eth-uclass.c                |  2 ++
 4 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/board/mips/boston-riscv/Kconfig b/board/mips/boston-riscv/Kconfig
index 68c5fc50489..4d55d96603e 100644
--- a/board/mips/boston-riscv/Kconfig
+++ b/board/mips/boston-riscv/Kconfig
@@ -40,4 +40,8 @@ config PHY_REALTEK
     bool
     default y
 
+config TFTP_FILE_NAME_MAX_LEN
+    int "Maximum length of TFTP file name"
+    default 256
+
 endif
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c
index adeca3d040d..0970a2dd8ba 100644
--- a/drivers/net/pch_gbe.c
+++ b/drivers/net/pch_gbe.c
@@ -14,6 +14,7 @@
 #include <pci.h>
 #include <miiphy.h>
 #include <linux/delay.h>
+#include <asm/gpio.h>
 #include "pch_gbe.h"
 
 #if !defined(CONFIG_PHYLIB)
@@ -33,6 +34,13 @@ static void pch_gbe_mac_read(struct pch_gbe_regs *mac_regs, 
u8 *addr)
        macid_lo = readl(&mac_regs->mac_adr[0].low) & 0xffff;
        debug("pch_gbe: macid_hi %#x macid_lo %#x\n", macid_hi, macid_lo);
 
+       if (!macid_lo && !macid_hi) {
+               if (eth_env_get_enetaddr("ethaddr", addr))
+                       return;
+
+               printf("No MAC found in either EG20T H/W or environment");
+       }
+
        addr[0] = (u8)(macid_hi & 0xff);
        addr[1] = (u8)((macid_hi >> 8) & 0xff);
        addr[2] = (u8)((macid_hi >> 16) & 0xff);
@@ -74,6 +82,14 @@ static int pch_gbe_reset(struct udevice *dev)
        priv->rx_idx = 0;
        priv->tx_idx = 0;
 
+       if (dm_gpio_is_valid(&priv->gpio_phy_reset)) {
+               /* Reset the PHY */
+               dm_gpio_set_value(&priv->gpio_phy_reset, 1);
+               udelay(15000);
+               dm_gpio_set_value(&priv->gpio_phy_reset, 0);
+               udelay(5000);
+       }
+
        writel(PCH_GBE_ALL_RST, &mac_regs->reset);
 
        /*
@@ -450,6 +466,11 @@ static int pch_gbe_probe(struct udevice *dev)
        plat->iobase = (ulong)iobase;
        priv->mac_regs = (struct pch_gbe_regs *)iobase;
 
+       err = gpio_request_by_name(dev, "phy-reset-gpios", 0,
+                                  &priv->gpio_phy_reset, GPIOD_IS_OUT);
+       if (err && (err != -ENOENT))
+               return err;
+
        /* Read MAC address from SROM and initialize dev->enetaddr with it */
        pch_gbe_mac_read(priv->mac_regs, plat->enetaddr);
 
@@ -459,9 +480,17 @@ static int pch_gbe_probe(struct udevice *dev)
 
        err = pch_gbe_reset(dev);
        if (err)
-               return err;
+               goto out_err;
+
+       err = pch_gbe_phy_init(dev);
+       if (err)
+               goto out_err;
 
-       return pch_gbe_phy_init(dev);
+       return 0;
+out_err:
+       if (dm_gpio_is_valid(&priv->gpio_phy_reset))
+               dm_gpio_free(dev, &priv->gpio_phy_reset);
+       return err;
 }
 
 static int pch_gbe_remove(struct udevice *dev)
@@ -472,6 +501,9 @@ static int pch_gbe_remove(struct udevice *dev)
        mdio_unregister(priv->bus);
        mdio_free(priv->bus);
 
+       if (dm_gpio_is_valid(&priv->gpio_phy_reset))
+               dm_gpio_free(dev, &priv->gpio_phy_reset);
+
        return 0;
 }
 
diff --git a/drivers/net/pch_gbe.h b/drivers/net/pch_gbe.h
index 7e0fdbfd5a3..dcbb94094bc 100644
--- a/drivers/net/pch_gbe.h
+++ b/drivers/net/pch_gbe.h
@@ -292,6 +292,7 @@ struct pch_gbe_priv {
        struct udevice *dev;
        int rx_idx;
        int tx_idx;
+       struct gpio_desc gpio_phy_reset;
 };
 
 #endif /* _PCH_GBE_H_ */
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 5555f82f23e..c82e8b0a523 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -461,6 +461,8 @@ int eth_rx(void)
                        eth_get_ops(current)->free_pkt(current, packet, ret);
                if (ret <= 0)
                        break;
+               if (net_state == NETLOOP_FAIL)
+                       break;
        }
        if (ret == -EAGAIN)
                ret = 0;
-- 
2.34.1

Reply via email to