]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00279948 net: fec: add clock control to save power
authorFugang Duan <B38611@freescale.com>
Sun, 29 Sep 2013 06:56:16 +0000 (14:56 +0800)
committerJason Liu <r64343@freescale.com>
Wed, 30 Oct 2013 01:55:51 +0000 (09:55 +0800)
- After probe, disable all clocks incluing ipg, ahb, enet_out, ptp clock.
- Open ethx interface enable necessary clocks.
  Close ethx interface disable all clocks.
- Correct the MDIO clock source.

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

index 598d9ec8eea6e6199347a4fdb9a84c96af852837..93840d4456135ebd78345e97eb81dc1c60748544 100644 (file)
@@ -1263,6 +1263,27 @@ static int fec_enet_mdio_reset(struct mii_bus *bus)
        return 0;
 }
 
+static inline void fec_enet_clk_enable(struct net_device *ndev, bool enable)
+{
+       struct fec_enet_private *fep = netdev_priv(ndev);
+
+       if (enable) {
+               clk_prepare_enable(fep->clk_ahb);
+               clk_prepare_enable(fep->clk_ipg);
+               if (fep->clk_enet_out)
+                       clk_prepare_enable(fep->clk_enet_out);
+               if (fep->clk_ptp)
+                       clk_prepare_enable(fep->clk_ptp);
+       } else {
+               clk_disable_unprepare(fep->clk_ahb);
+               clk_disable_unprepare(fep->clk_ipg);
+               if (fep->clk_enet_out)
+                       clk_disable_unprepare(fep->clk_enet_out);
+               if (fep->clk_ptp)
+                       clk_disable_unprepare(fep->clk_ptp);
+       }
+}
+
 static int fec_enet_mii_probe(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
@@ -1372,7 +1393,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
         * Reference Manual has an error on this, and gets fixed on i.MX6Q
         * document.
         */
-       fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ahb), 5000000);
+       fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ipg), 5000000);
        if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
                fep->phy_speed--;
        fep->phy_speed <<= 1;
@@ -1779,6 +1800,8 @@ fec_enet_open(struct net_device *ndev)
 
        pm_runtime_get_sync(ndev->dev.parent);
 
+       fec_enet_clk_enable(ndev, true);
+
        napi_enable(&fep->napi);
 
        /* I should reset the ring buffers here, but I don't yet know
@@ -1822,6 +1845,8 @@ fec_enet_close(struct net_device *ndev)
                phy_disconnect(fep->phy_dev);
        }
 
+       fec_enet_clk_enable(ndev, false);
+
        pm_runtime_put_sync_suspend(ndev->dev.parent);
 
        fec_enet_free_buffers(ndev);
@@ -2178,17 +2203,14 @@ fec_probe(struct platform_device *pdev)
        fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
        fep->bufdesc_ex =
                pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
-       if (IS_ERR(fep->clk_ptp)) {
+       if (IS_ERR(fep->clk_ptp) || !fep->bufdesc_ex) {
                fep->clk_ptp = NULL;
                fep->bufdesc_ex = 0;
        }
 
        pm_runtime_enable(&pdev->dev);
 
-       clk_prepare_enable(fep->clk_ahb);
-       clk_prepare_enable(fep->clk_ipg);
-       clk_prepare_enable(fep->clk_enet_out);
-       clk_prepare_enable(fep->clk_ptp);
+       fec_enet_clk_enable(ndev, true);
 
        fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
        if (!IS_ERR(fep->reg_phy)) {
@@ -2233,6 +2255,7 @@ fec_probe(struct platform_device *pdev)
 
        /* Carrier starts down, phylib will bring it up */
        netif_carrier_off(ndev);
+       fec_enet_clk_enable(ndev, false);
 
        ret = register_netdev(ndev);
        if (ret)
@@ -2257,10 +2280,7 @@ failed_init:
        if (fep->reg_phy)
                regulator_disable(fep->reg_phy);
 failed_regulator:
-       clk_disable_unprepare(fep->clk_ahb);
-       clk_disable_unprepare(fep->clk_ipg);
-       clk_disable_unprepare(fep->clk_enet_out);
-       clk_disable_unprepare(fep->clk_ptp);
+       fec_enet_clk_enable(ndev, false);
 failed_clk:
 failed_ioremap:
        free_netdev(ndev);
@@ -2290,13 +2310,10 @@ fec_drv_remove(struct platform_device *pdev)
        if (fep->reg_phy)
                regulator_disable(fep->reg_phy);
        if (fep->bufdesc_ex) {
-               clk_disable_unprepare(fep->clk_ptp);
                if (fep->ptp_clock)
                        ptp_clock_unregister(fep->ptp_clock);
        }
-       clk_disable_unprepare(fep->clk_enet_out);
-       clk_disable_unprepare(fep->clk_ahb);
-       clk_disable_unprepare(fep->clk_ipg);
+       fec_enet_clk_enable(ndev, false);
        free_netdev(ndev);
 
        return 0;
@@ -2313,10 +2330,8 @@ fec_suspend(struct device *dev)
                fec_stop(ndev);
                netif_device_detach(ndev);
        }
-       clk_disable_unprepare(fep->clk_enet_out);
-       clk_disable_unprepare(fep->clk_ahb);
-       clk_disable_unprepare(fep->clk_ipg);
 
+       fec_enet_clk_enable(ndev, false);
        if (fep->reg_phy)
                regulator_disable(fep->reg_phy);
 
@@ -2336,9 +2351,7 @@ fec_resume(struct device *dev)
                        return ret;
        }
 
-       clk_prepare_enable(fep->clk_enet_out);
-       clk_prepare_enable(fep->clk_ahb);
-       clk_prepare_enable(fep->clk_ipg);
+       fec_enet_clk_enable(ndev, true);
        if (netif_running(ndev)) {
                fec_restart(ndev, fep->full_duplex);
                netif_device_attach(ndev);