diff options
author | David S. Miller <davem@davemloft.net> | 2013-07-23 03:50:38 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-07-23 03:50:38 +0400 |
commit | c3f51d5f387b552b9d9fd7f41e19b84929712f82 (patch) | |
tree | 8d5d903de54a8ab5d31605d5077fa3b5fc8934f7 | |
parent | eda297729171fe16bf34fe5b0419dfb69060f623 (diff) | |
parent | 0d9b2ab1c3760a7ca28293c0ae48c2302d71ce96 (diff) | |
download | linux-c3f51d5f387b552b9d9fd7f41e19b84929712f82.tar.xz |
Merge branch 'fec'
Fabio Estevam says:
====================
This series improves clock handling in the driver by not enabling/disabling
the optional ptp and enet_out clocks unconditionally, check for the return value
of clk_prepare_enable and also handle clk_ptp in suspend/resume.
Remove an unneeded check in platform_get_resource() and also use
devm_request_irq() that can help to simplify the code.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Acked-by: Frank Li <lznuaa@gmail.com>
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 110 |
1 files changed, 73 insertions, 37 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index d3ad5ea711d3..92d34d9e1046 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2033,10 +2033,6 @@ fec_probe(struct platform_device *pdev) if (of_id) pdev->id_entry = of_id->data; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) - return -ENXIO; - /* Init network device */ ndev = alloc_etherdev(sizeof(struct fec_enet_private)); if (!ndev) @@ -2054,6 +2050,7 @@ fec_probe(struct platform_device *pdev) fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG; #endif + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); fep->hwp = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(fep->hwp)) { ret = PTR_ERR(fep->hwp); @@ -2103,10 +2100,25 @@ fec_probe(struct platform_device *pdev) fep->bufdesc_ex = 0; } - 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); + ret = clk_prepare_enable(fep->clk_ahb); + if (ret) + goto failed_clk; + + ret = clk_prepare_enable(fep->clk_ipg); + if (ret) + goto failed_clk_ipg; + + if (fep->clk_enet_out) { + ret = clk_prepare_enable(fep->clk_enet_out); + if (ret) + goto failed_clk_enet_out; + } + + if (fep->clk_ptp) { + ret = clk_prepare_enable(fep->clk_ptp); + if (ret) + goto failed_clk_ptp; + } fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); if (!IS_ERR(fep->reg_phy)) { @@ -2137,14 +2149,10 @@ fec_probe(struct platform_device *pdev) ret = irq; goto failed_irq; } - ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev); - if (ret) { - while (--i >= 0) { - irq = platform_get_irq(pdev, i); - free_irq(irq, ndev); - } + ret = devm_request_irq(&pdev->dev, irq, fec_enet_interrupt, + IRQF_DISABLED, pdev->name, ndev); + if (ret) goto failed_irq; - } } ret = fec_enet_mii_init(pdev); @@ -2168,19 +2176,19 @@ failed_register: fec_enet_mii_remove(fep); failed_mii_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_init: if (fep->reg_phy) regulator_disable(fep->reg_phy); failed_regulator: - clk_disable_unprepare(fep->clk_ahb); + if (fep->clk_ptp) + clk_disable_unprepare(fep->clk_ptp); +failed_clk_ptp: + if (fep->clk_enet_out) + clk_disable_unprepare(fep->clk_enet_out); +failed_clk_enet_out: clk_disable_unprepare(fep->clk_ipg); - clk_disable_unprepare(fep->clk_enet_out); - clk_disable_unprepare(fep->clk_ptp); +failed_clk_ipg: + clk_disable_unprepare(fep->clk_ahb); failed_clk: failed_ioremap: free_netdev(ndev); @@ -2193,25 +2201,21 @@ fec_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct fec_enet_private *fep = netdev_priv(ndev); - int i; cancel_delayed_work_sync(&(fep->delay_work.delay_work)); 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->clk_ptp) + 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); + if (fep->clk_enet_out) + clk_disable_unprepare(fep->clk_enet_out); clk_disable_unprepare(fep->clk_ipg); + clk_disable_unprepare(fep->clk_ahb); free_netdev(ndev); return 0; @@ -2228,9 +2232,12 @@ 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); + if (fep->clk_ptp) + clk_disable_unprepare(fep->clk_ptp); + if (fep->clk_enet_out) + clk_disable_unprepare(fep->clk_enet_out); clk_disable_unprepare(fep->clk_ipg); + clk_disable_unprepare(fep->clk_ahb); if (fep->reg_phy) regulator_disable(fep->reg_phy); @@ -2251,15 +2258,44 @@ 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); + ret = clk_prepare_enable(fep->clk_ahb); + if (ret) + goto failed_clk_ahb; + + ret = clk_prepare_enable(fep->clk_ipg); + if (ret) + goto failed_clk_ipg; + + if (fep->clk_enet_out) { + ret = clk_prepare_enable(fep->clk_enet_out); + if (ret) + goto failed_clk_enet_out; + } + + if (fep->clk_ptp) { + ret = clk_prepare_enable(fep->clk_ptp); + if (ret) + goto failed_clk_ptp; + } + if (netif_running(ndev)) { fec_restart(ndev, fep->full_duplex); netif_device_attach(ndev); } return 0; + +failed_clk_ptp: + if (fep->clk_enet_out) + clk_disable_unprepare(fep->clk_enet_out); +failed_clk_enet_out: + clk_disable_unprepare(fep->clk_ipg); +failed_clk_ipg: + clk_disable_unprepare(fep->clk_ahb); +failed_clk_ahb: + if (fep->reg_phy) + regulator_disable(fep->reg_phy); + return ret; } #endif /* CONFIG_PM_SLEEP */ |