]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ENGR00275246-04: net: fec: fix phy reset operation
authorFugang Duan <B38611@freescale.com>
Wed, 14 Aug 2013 09:55:25 +0000 (17:55 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Mon, 16 Jun 2014 15:08:16 +0000 (17:08 +0200)
Current driver only do phy reset in probe function, which is
not right. Since some phy clock is disabled after module probe,
the phy enter abnormal status, which needs do reset to recovery
the phy. And do ifconfig ethx up/down test, the phy also enter
abnormal status.

The log as:
libphy: 2188000.ethernet:04 - Link is Up - 10/Full
libphy: 2188000.ethernet:04 - Link is Up - 100/Full
libphy: 2188000.ethernet:04 - Link is Down
libphy: 2188000.ethernet:04 - Link is Up - 10/Half
libphy: 2188000.ethernet:04 - Link is Up - 10/Full
libphy: 2188000.ethernet:04 - Link is Up - 100/Full
...

So, do phy reset if ethx up/down or do clock enable/disable
operation.

Signed-off-by: Fugang Duan <B38611@freescale.com>
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c

index 671d080105a7e08c5e20456a5ad38b29f6704e19..7a3426c72699cf393e5548112b6a74eed060f2ab 100644 (file)
@@ -328,6 +328,8 @@ struct fec_enet_private {
        struct  napi_struct napi;
        int     csum_flags;
 
+       int     phy_reset_gpio;
+
        struct ptp_clock *ptp_clock;
        struct ptp_clock_info ptp_caps;
        unsigned long last_overflow_check;
index 38d9d276ab8b8c006fe13f1aa76eac2e55a2d775..5dce55a3156dc8ccb0952e0f67a78e3311140e7b 100644 (file)
@@ -18,7 +18,7 @@
  * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
  * Copyright (c) 2004-2006 Macq Electronique SA.
  *
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
  */
 
 #include <linux/module.h>
@@ -62,6 +62,8 @@
 #include "fec.h"
 
 static void set_multicast_list(struct net_device *ndev);
+static void fec_reset_phy(struct platform_device *pdev);
+static void fec_free_reset_gpio(struct platform_device *pdev);
 
 #if defined(CONFIG_ARM)
 #define FEC_ALIGNMENT  0xf
@@ -2159,6 +2161,10 @@ fec_enet_open(struct net_device *ndev)
        phy_start(fep->phy_dev);
        netif_start_queue(ndev);
        fep->opened = 1;
+
+       /* reset phy */
+       fec_reset_phy(fep->pdev);
+
        return 0;
 }
 
@@ -2181,6 +2187,7 @@ fec_enet_close(struct net_device *ndev)
        fec_enet_clk_enable(ndev, false);
        pinctrl_pm_select_sleep_state(&fep->pdev->dev);
        fec_enet_free_buffers(ndev);
+       fec_free_reset_gpio(fep->pdev);
 
        return 0;
 }
@@ -2434,9 +2441,11 @@ static int fec_enet_init(struct net_device *ndev)
 #ifdef CONFIG_OF
 static void fec_reset_phy(struct platform_device *pdev)
 {
-       int err, phy_reset;
+       int err;
        int msec = 1;
        struct device_node *np = pdev->dev.of_node;
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct fec_enet_private *fep = netdev_priv(ndev);
 
        if (!np)
                return;
@@ -2446,18 +2455,33 @@ static void fec_reset_phy(struct platform_device *pdev)
        if (msec > 1000)
                msec = 1;
 
-       phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
-       if (!gpio_is_valid(phy_reset))
+       fep->phy_reset_gpio = of_get_named_gpio(np, "phy-reset-gpios", 0);
+       if (!gpio_is_valid(fep->phy_reset_gpio))
                return;
 
-       err = devm_gpio_request_one(&pdev->dev, phy_reset,
+       err = devm_gpio_request_one(&pdev->dev, fep->phy_reset_gpio,
                                    GPIOF_OUT_INIT_LOW, "phy-reset");
        if (err) {
                dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
                return;
        }
        msleep(msec);
-       gpio_set_value(phy_reset, 1);
+       gpio_set_value(fep->phy_reset_gpio, 1);
+}
+
+static void fec_free_reset_gpio(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct fec_enet_private *fep = netdev_priv(ndev);
+       struct device_node *np = pdev->dev.of_node;
+       if (!np)
+               return;
+
+       fep->phy_reset_gpio = of_get_named_gpio(np, "phy-reset-gpios", 0);
+       if (!gpio_is_valid(fep->phy_reset_gpio))
+               return;
+
+       devm_gpio_free(&pdev->dev, fep->phy_reset_gpio);
 }
 #else /* CONFIG_OF */
 static void fec_reset_phy(struct platform_device *pdev)
@@ -2467,6 +2491,13 @@ static void fec_reset_phy(struct platform_device *pdev)
         * by machine code.
         */
 }
+
+static void fec_free_reset_gpio(struct platform_device *pdev)
+{
+       /*
+        * make pair as api "fec_reset_phy()"
+        */
+}
 #endif /* CONFIG_OF */
 
 static int
@@ -2570,8 +2601,6 @@ fec_probe(struct platform_device *pdev)
                fep->reg_phy = NULL;
        }
 
-       fec_reset_phy(pdev);
-
        if (fep->bufdesc_ex)
                fec_ptp_init(pdev);