]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/freescale/fec_main.c
Merge branch 'karo-tx6-mainline' into stable
[karo-tx-linux.git] / drivers / net / ethernet / freescale / fec_main.c
index f6147ffc7fbca76f4f6f512caa9e9612a32cf00a..68012c0a311cf972131a35814759e1520ec12d1e 100644 (file)
@@ -66,6 +66,7 @@
 
 static void set_multicast_list(struct net_device *ndev);
 static void fec_enet_itr_coal_init(struct net_device *ndev);
+static void fec_reset_phy(struct platform_device *pdev);
 
 #define DRIVER_NAME    "fec"
 
@@ -1867,6 +1868,8 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
                        ret = clk_prepare_enable(fep->clk_enet_out);
                        if (ret)
                                goto failed_clk_enet_out;
+
+                       fec_reset_phy(fep->pdev);
                }
                if (fep->clk_ptp) {
                        mutex_lock(&fep->ptp_clk_mutex);
@@ -1879,35 +1882,30 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
                        }
                        mutex_unlock(&fep->ptp_clk_mutex);
                }
-               if (fep->clk_ref) {
-                       ret = clk_prepare_enable(fep->clk_ref);
-                       if (ret)
-                               goto failed_clk_ref;
-               }
+
+               ret = clk_prepare_enable(fep->clk_ref);
+               if (ret)
+                       goto failed_clk_ref;
        } else {
                clk_disable_unprepare(fep->clk_ahb);
-               if (fep->clk_enet_out)
-                       clk_disable_unprepare(fep->clk_enet_out);
+               clk_disable_unprepare(fep->clk_enet_out);
                if (fep->clk_ptp) {
                        mutex_lock(&fep->ptp_clk_mutex);
                        clk_disable_unprepare(fep->clk_ptp);
                        fep->ptp_clk_on = false;
                        mutex_unlock(&fep->ptp_clk_mutex);
                }
-               if (fep->clk_ref)
-                       clk_disable_unprepare(fep->clk_ref);
+               clk_disable_unprepare(fep->clk_ref);
        }
 
        return 0;
 
 failed_clk_ref:
-       if (fep->clk_ref)
-               clk_disable_unprepare(fep->clk_ref);
+       clk_disable_unprepare(fep->clk_ref);
 failed_clk_ptp:
-       if (fep->clk_enet_out)
-               clk_disable_unprepare(fep->clk_enet_out);
+       clk_disable_unprepare(fep->clk_enet_out);
 failed_clk_enet_out:
-               clk_disable_unprepare(fep->clk_ahb);
+       clk_disable_unprepare(fep->clk_ahb);
 
        return ret;
 }
@@ -3244,30 +3242,43 @@ 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 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)
+       if (!gpio_is_valid(fep->phy_reset_gpio))
                return;
 
-       of_property_read_u32(np, "phy-reset-duration", &msec);
-       /* A sane reset duration should not be longer than 1s */
-       if (msec > 1000)
-               msec = 1;
+       gpio_set_value_cansleep(fep->phy_reset_gpio, 0);
+       msleep(fep->phy_reset_duration);
+       gpio_set_value_cansleep(fep->phy_reset_gpio, 1);
+}
+
+static int fec_get_reset_gpio(struct platform_device *pdev)
+{
+       int err, phy_reset;
+       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);
 
        phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
        if (!gpio_is_valid(phy_reset))
-               return;
+               return phy_reset;
 
        err = devm_gpio_request_one(&pdev->dev, phy_reset,
                                    GPIOF_OUT_INIT_LOW, "phy-reset");
        if (err) {
                dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
-               return;
+               return err;
        }
-       msleep(msec);
-       gpio_set_value_cansleep(phy_reset, 1);
+
+       of_property_read_u32(np, "phy-reset-duration", &msec);
+       /* A sane reset duration should not be longer than 1s */
+       if (msec > 1000)
+               msec = 1;
+       fep->phy_reset_duration = msec;
+
+       return phy_reset;
 }
 #else /* CONFIG_OF */
 static void fec_reset_phy(struct platform_device *pdev)
@@ -3277,6 +3288,11 @@ static void fec_reset_phy(struct platform_device *pdev)
         * by machine code.
         */
 }
+
+static inline int fec_get_reset_gpio(struct platform_device *pdev)
+{
+       return -EINVAL;
+}
 #endif /* CONFIG_OF */
 
 static void
@@ -3372,6 +3388,11 @@ fec_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, ndev);
 
+       ret = fec_get_reset_gpio(pdev);
+       if (ret == -EPROBE_DEFER)
+               goto gpio_defer;
+       fep->phy_reset_gpio = ret;
+
        if (of_get_property(np, "fsl,magic-packet", NULL))
                fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;
 
@@ -3526,6 +3547,7 @@ failed_clk_ipg:
 failed_clk:
 failed_phy:
        of_node_put(phy_node);
+gpio_defer:
 failed_ioremap:
        free_netdev(ndev);