diff options
author | David S. Miller <davem@davemloft.net> | 2013-05-27 22:30:23 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-27 22:30:23 -0700 |
commit | 3acfeac351c6ab2fe1139ee13d780729af0c8145 (patch) | |
tree | fb6e0796574966738c80cc68cabfd00319283383 | |
parent | 3904dcc4a7af8e28e45a8d123cef3f7653847a51 (diff) | |
parent | 238f7bc74cde96e285e59a84e0c7bbd37faa8c07 (diff) | |
download | linux-3acfeac351c6ab2fe1139ee13d780729af0c8145.tar.bz2 |
Merge branch 'fec_regulator_suspend_resume'
Fabio Estevam says:
====================
This series provides support for controlling the PHY regulator in suspend/resume.
Fabio Estevam (5):
fec: Place the phy regulator in the private structure
fec: Invert the order of error path sequence
fec: Disable the PHY regulator on error and removal
fec: Remove irqs first
fec: Handle the regulator in suspend/resume
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/freescale/fec.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 37 |
2 files changed, 27 insertions, 11 deletions
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 9ce5b7185fda..b11cdbcc04ff 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -272,6 +272,7 @@ struct fec_enet_private { int hwts_tx_en; struct timer_list time_keep; struct fec_enet_delayed_work delay_work; + struct regulator *reg_phy; }; void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 0936b26b5e1e..866b92220c15 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1840,7 +1840,6 @@ fec_probe(struct platform_device *pdev) struct resource *r; const struct of_device_id *of_id; static int dev_id; - struct regulator *reg_phy; of_id = of_match_device(fec_dt_ids, &pdev->dev); if (of_id) @@ -1919,14 +1918,16 @@ fec_probe(struct platform_device *pdev) clk_prepare_enable(fep->clk_enet_out); clk_prepare_enable(fep->clk_ptp); - reg_phy = devm_regulator_get(&pdev->dev, "phy"); - if (!IS_ERR(reg_phy)) { - ret = regulator_enable(reg_phy); + fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); + if (!IS_ERR(fep->reg_phy)) { + ret = regulator_enable(fep->reg_phy); if (ret) { dev_err(&pdev->dev, "Failed to enable phy regulator: %d\n", ret); goto failed_regulator; } + } else { + fep->reg_phy = NULL; } fec_reset_phy(pdev); @@ -1976,13 +1977,15 @@ fec_probe(struct platform_device *pdev) failed_register: fec_enet_mii_remove(fep); failed_mii_init: -failed_init: +failed_irq: for (i = 0; i < FEC_IRQ_NUM; i++) { irq = platform_get_irq(pdev, i); if (irq > 0) free_irq(irq, ndev); } -failed_irq: +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); @@ -2006,17 +2009,19 @@ fec_drv_remove(struct platform_device *pdev) unregister_netdev(ndev); fec_enet_mii_remove(fep); del_timer_sync(&fep->time_keep); + for (i = 0; i < FEC_IRQ_NUM; i++) { + int irq = platform_get_irq(pdev, i); + if (irq > 0) + free_irq(irq, ndev); + } + if (fep->reg_phy) + regulator_disable(fep->reg_phy); 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); - for (i = 0; i < FEC_IRQ_NUM; i++) { - int irq = platform_get_irq(pdev, i); - if (irq > 0) - free_irq(irq, ndev); - } free_netdev(ndev); platform_set_drvdata(pdev, NULL); @@ -2039,6 +2044,9 @@ fec_suspend(struct device *dev) clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); + if (fep->reg_phy) + regulator_disable(fep->reg_phy); + return 0; } @@ -2047,6 +2055,13 @@ fec_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); struct fec_enet_private *fep = netdev_priv(ndev); + int ret; + + if (fep->reg_phy) { + ret = regulator_enable(fep->reg_phy); + if (ret) + return ret; + } clk_prepare_enable(fep->clk_enet_out); clk_prepare_enable(fep->clk_ahb); |