aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFugang Duan <B38611@freescale.com>2013-09-29 02:56:16 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:05:43 -0400
commit139b7a73aead3044b1542ef9fc103038f7c868ea (patch)
tree248ba9be746f28e2521ccc17ddff8b863348ef71
parentdfa506835ddae328e40f6bf50765037f457b4876 (diff)
ENGR00279948 net: fec: add clock control to save power
- 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>
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c53
1 files changed, 33 insertions, 20 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 4c9bdb444907..5b3a8f615ed9 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1263,6 +1263,27 @@ static int fec_enet_mdio_reset(struct mii_bus *bus)
1263 return 0; 1263 return 0;
1264} 1264}
1265 1265
1266static inline void fec_enet_clk_enable(struct net_device *ndev, bool enable)
1267{
1268 struct fec_enet_private *fep = netdev_priv(ndev);
1269
1270 if (enable) {
1271 clk_prepare_enable(fep->clk_ahb);
1272 clk_prepare_enable(fep->clk_ipg);
1273 if (fep->clk_enet_out)
1274 clk_prepare_enable(fep->clk_enet_out);
1275 if (fep->clk_ptp)
1276 clk_prepare_enable(fep->clk_ptp);
1277 } else {
1278 clk_disable_unprepare(fep->clk_ahb);
1279 clk_disable_unprepare(fep->clk_ipg);
1280 if (fep->clk_enet_out)
1281 clk_disable_unprepare(fep->clk_enet_out);
1282 if (fep->clk_ptp)
1283 clk_disable_unprepare(fep->clk_ptp);
1284 }
1285}
1286
1266static int fec_enet_mii_probe(struct net_device *ndev) 1287static int fec_enet_mii_probe(struct net_device *ndev)
1267{ 1288{
1268 struct fec_enet_private *fep = netdev_priv(ndev); 1289 struct fec_enet_private *fep = netdev_priv(ndev);
@@ -1372,7 +1393,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
1372 * Reference Manual has an error on this, and gets fixed on i.MX6Q 1393 * Reference Manual has an error on this, and gets fixed on i.MX6Q
1373 * document. 1394 * document.
1374 */ 1395 */
1375 fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ahb), 5000000); 1396 fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ipg), 5000000);
1376 if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) 1397 if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
1377 fep->phy_speed--; 1398 fep->phy_speed--;
1378 fep->phy_speed <<= 1; 1399 fep->phy_speed <<= 1;
@@ -1779,6 +1800,8 @@ fec_enet_open(struct net_device *ndev)
1779 1800
1780 pm_runtime_get_sync(ndev->dev.parent); 1801 pm_runtime_get_sync(ndev->dev.parent);
1781 1802
1803 fec_enet_clk_enable(ndev, true);
1804
1782 napi_enable(&fep->napi); 1805 napi_enable(&fep->napi);
1783 1806
1784 /* I should reset the ring buffers here, but I don't yet know 1807 /* I should reset the ring buffers here, but I don't yet know
@@ -1822,6 +1845,8 @@ fec_enet_close(struct net_device *ndev)
1822 phy_disconnect(fep->phy_dev); 1845 phy_disconnect(fep->phy_dev);
1823 } 1846 }
1824 1847
1848 fec_enet_clk_enable(ndev, false);
1849
1825 pm_runtime_put_sync_suspend(ndev->dev.parent); 1850 pm_runtime_put_sync_suspend(ndev->dev.parent);
1826 1851
1827 fec_enet_free_buffers(ndev); 1852 fec_enet_free_buffers(ndev);
@@ -2178,17 +2203,14 @@ fec_probe(struct platform_device *pdev)
2178 fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp"); 2203 fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
2179 fep->bufdesc_ex = 2204 fep->bufdesc_ex =
2180 pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX; 2205 pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
2181 if (IS_ERR(fep->clk_ptp)) { 2206 if (IS_ERR(fep->clk_ptp) || !fep->bufdesc_ex) {
2182 fep->clk_ptp = NULL; 2207 fep->clk_ptp = NULL;
2183 fep->bufdesc_ex = 0; 2208 fep->bufdesc_ex = 0;
2184 } 2209 }
2185 2210
2186 pm_runtime_enable(&pdev->dev); 2211 pm_runtime_enable(&pdev->dev);
2187 2212
2188 clk_prepare_enable(fep->clk_ahb); 2213 fec_enet_clk_enable(ndev, true);
2189 clk_prepare_enable(fep->clk_ipg);
2190 clk_prepare_enable(fep->clk_enet_out);
2191 clk_prepare_enable(fep->clk_ptp);
2192 2214
2193 fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); 2215 fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
2194 if (!IS_ERR(fep->reg_phy)) { 2216 if (!IS_ERR(fep->reg_phy)) {
@@ -2233,6 +2255,7 @@ fec_probe(struct platform_device *pdev)
2233 2255
2234 /* Carrier starts down, phylib will bring it up */ 2256 /* Carrier starts down, phylib will bring it up */
2235 netif_carrier_off(ndev); 2257 netif_carrier_off(ndev);
2258 fec_enet_clk_enable(ndev, false);
2236 2259
2237 ret = register_netdev(ndev); 2260 ret = register_netdev(ndev);
2238 if (ret) 2261 if (ret)
@@ -2257,10 +2280,7 @@ failed_init:
2257 if (fep->reg_phy) 2280 if (fep->reg_phy)
2258 regulator_disable(fep->reg_phy); 2281 regulator_disable(fep->reg_phy);
2259failed_regulator: 2282failed_regulator:
2260 clk_disable_unprepare(fep->clk_ahb); 2283 fec_enet_clk_enable(ndev, false);
2261 clk_disable_unprepare(fep->clk_ipg);
2262 clk_disable_unprepare(fep->clk_enet_out);
2263 clk_disable_unprepare(fep->clk_ptp);
2264failed_clk: 2284failed_clk:
2265failed_ioremap: 2285failed_ioremap:
2266 free_netdev(ndev); 2286 free_netdev(ndev);
@@ -2290,13 +2310,10 @@ fec_drv_remove(struct platform_device *pdev)
2290 if (fep->reg_phy) 2310 if (fep->reg_phy)
2291 regulator_disable(fep->reg_phy); 2311 regulator_disable(fep->reg_phy);
2292 if (fep->bufdesc_ex) { 2312 if (fep->bufdesc_ex) {
2293 clk_disable_unprepare(fep->clk_ptp);
2294 if (fep->ptp_clock) 2313 if (fep->ptp_clock)
2295 ptp_clock_unregister(fep->ptp_clock); 2314 ptp_clock_unregister(fep->ptp_clock);
2296 } 2315 }
2297 clk_disable_unprepare(fep->clk_enet_out); 2316 fec_enet_clk_enable(ndev, false);
2298 clk_disable_unprepare(fep->clk_ahb);
2299 clk_disable_unprepare(fep->clk_ipg);
2300 free_netdev(ndev); 2317 free_netdev(ndev);
2301 2318
2302 return 0; 2319 return 0;
@@ -2313,10 +2330,8 @@ fec_suspend(struct device *dev)
2313 fec_stop(ndev); 2330 fec_stop(ndev);
2314 netif_device_detach(ndev); 2331 netif_device_detach(ndev);
2315 } 2332 }
2316 clk_disable_unprepare(fep->clk_enet_out);
2317 clk_disable_unprepare(fep->clk_ahb);
2318 clk_disable_unprepare(fep->clk_ipg);
2319 2333
2334 fec_enet_clk_enable(ndev, false);
2320 if (fep->reg_phy) 2335 if (fep->reg_phy)
2321 regulator_disable(fep->reg_phy); 2336 regulator_disable(fep->reg_phy);
2322 2337
@@ -2336,9 +2351,7 @@ fec_resume(struct device *dev)
2336 return ret; 2351 return ret;
2337 } 2352 }
2338 2353
2339 clk_prepare_enable(fep->clk_enet_out); 2354 fec_enet_clk_enable(ndev, true);
2340 clk_prepare_enable(fep->clk_ahb);
2341 clk_prepare_enable(fep->clk_ipg);
2342 if (netif_running(ndev)) { 2355 if (netif_running(ndev)) {
2343 fec_restart(ndev, fep->full_duplex); 2356 fec_restart(ndev, fep->full_duplex);
2344 netif_device_attach(ndev); 2357 netif_device_attach(ndev);