diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
| -rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 99 |
1 files changed, 81 insertions, 18 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 1f89c59b4353..271bb5862346 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
| 27 | #include <linux/pm_runtime.h> | ||
| 27 | #include <linux/ptrace.h> | 28 | #include <linux/ptrace.h> |
| 28 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
| 29 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
| @@ -77,6 +78,7 @@ static void fec_enet_itr_coal_init(struct net_device *ndev); | |||
| 77 | #define FEC_ENET_RAEM_V 0x8 | 78 | #define FEC_ENET_RAEM_V 0x8 |
| 78 | #define FEC_ENET_RAFL_V 0x8 | 79 | #define FEC_ENET_RAFL_V 0x8 |
| 79 | #define FEC_ENET_OPD_V 0xFFF0 | 80 | #define FEC_ENET_OPD_V 0xFFF0 |
| 81 | #define FEC_MDIO_PM_TIMEOUT 100 /* ms */ | ||
| 80 | 82 | ||
| 81 | static struct platform_device_id fec_devtype[] = { | 83 | static struct platform_device_id fec_devtype[] = { |
| 82 | { | 84 | { |
| @@ -1767,7 +1769,13 @@ static void fec_enet_adjust_link(struct net_device *ndev) | |||
| 1767 | static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | 1769 | static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) |
| 1768 | { | 1770 | { |
| 1769 | struct fec_enet_private *fep = bus->priv; | 1771 | struct fec_enet_private *fep = bus->priv; |
| 1772 | struct device *dev = &fep->pdev->dev; | ||
| 1770 | unsigned long time_left; | 1773 | unsigned long time_left; |
| 1774 | int ret = 0; | ||
| 1775 | |||
| 1776 | ret = pm_runtime_get_sync(dev); | ||
| 1777 | if (IS_ERR_VALUE(ret)) | ||
| 1778 | return ret; | ||
| 1771 | 1779 | ||
| 1772 | fep->mii_timeout = 0; | 1780 | fep->mii_timeout = 0; |
| 1773 | init_completion(&fep->mdio_done); | 1781 | init_completion(&fep->mdio_done); |
| @@ -1783,18 +1791,30 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | |||
| 1783 | if (time_left == 0) { | 1791 | if (time_left == 0) { |
| 1784 | fep->mii_timeout = 1; | 1792 | fep->mii_timeout = 1; |
| 1785 | netdev_err(fep->netdev, "MDIO read timeout\n"); | 1793 | netdev_err(fep->netdev, "MDIO read timeout\n"); |
| 1786 | return -ETIMEDOUT; | 1794 | ret = -ETIMEDOUT; |
| 1795 | goto out; | ||
| 1787 | } | 1796 | } |
| 1788 | 1797 | ||
| 1789 | /* return value */ | 1798 | ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); |
| 1790 | return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); | 1799 | |
| 1800 | out: | ||
| 1801 | pm_runtime_mark_last_busy(dev); | ||
| 1802 | pm_runtime_put_autosuspend(dev); | ||
| 1803 | |||
| 1804 | return ret; | ||
| 1791 | } | 1805 | } |
| 1792 | 1806 | ||
| 1793 | static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, | 1807 | static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, |
| 1794 | u16 value) | 1808 | u16 value) |
| 1795 | { | 1809 | { |
| 1796 | struct fec_enet_private *fep = bus->priv; | 1810 | struct fec_enet_private *fep = bus->priv; |
| 1811 | struct device *dev = &fep->pdev->dev; | ||
| 1797 | unsigned long time_left; | 1812 | unsigned long time_left; |
| 1813 | int ret = 0; | ||
| 1814 | |||
| 1815 | ret = pm_runtime_get_sync(dev); | ||
| 1816 | if (IS_ERR_VALUE(ret)) | ||
| 1817 | return ret; | ||
| 1798 | 1818 | ||
| 1799 | fep->mii_timeout = 0; | 1819 | fep->mii_timeout = 0; |
| 1800 | init_completion(&fep->mdio_done); | 1820 | init_completion(&fep->mdio_done); |
| @@ -1811,10 +1831,13 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, | |||
| 1811 | if (time_left == 0) { | 1831 | if (time_left == 0) { |
| 1812 | fep->mii_timeout = 1; | 1832 | fep->mii_timeout = 1; |
| 1813 | netdev_err(fep->netdev, "MDIO write timeout\n"); | 1833 | netdev_err(fep->netdev, "MDIO write timeout\n"); |
| 1814 | return -ETIMEDOUT; | 1834 | ret = -ETIMEDOUT; |
| 1815 | } | 1835 | } |
| 1816 | 1836 | ||
| 1817 | return 0; | 1837 | pm_runtime_mark_last_busy(dev); |
| 1838 | pm_runtime_put_autosuspend(dev); | ||
| 1839 | |||
| 1840 | return ret; | ||
| 1818 | } | 1841 | } |
| 1819 | 1842 | ||
| 1820 | static int fec_enet_clk_enable(struct net_device *ndev, bool enable) | 1843 | static int fec_enet_clk_enable(struct net_device *ndev, bool enable) |
| @@ -1826,9 +1849,6 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) | |||
| 1826 | ret = clk_prepare_enable(fep->clk_ahb); | 1849 | ret = clk_prepare_enable(fep->clk_ahb); |
| 1827 | if (ret) | 1850 | if (ret) |
| 1828 | return ret; | 1851 | return ret; |
| 1829 | ret = clk_prepare_enable(fep->clk_ipg); | ||
| 1830 | if (ret) | ||
| 1831 | goto failed_clk_ipg; | ||
| 1832 | if (fep->clk_enet_out) { | 1852 | if (fep->clk_enet_out) { |
| 1833 | ret = clk_prepare_enable(fep->clk_enet_out); | 1853 | ret = clk_prepare_enable(fep->clk_enet_out); |
| 1834 | if (ret) | 1854 | if (ret) |
| @@ -1852,7 +1872,6 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) | |||
| 1852 | } | 1872 | } |
| 1853 | } else { | 1873 | } else { |
| 1854 | clk_disable_unprepare(fep->clk_ahb); | 1874 | clk_disable_unprepare(fep->clk_ahb); |
| 1855 | clk_disable_unprepare(fep->clk_ipg); | ||
| 1856 | if (fep->clk_enet_out) | 1875 | if (fep->clk_enet_out) |
| 1857 | clk_disable_unprepare(fep->clk_enet_out); | 1876 | clk_disable_unprepare(fep->clk_enet_out); |
| 1858 | if (fep->clk_ptp) { | 1877 | if (fep->clk_ptp) { |
| @@ -1874,8 +1893,6 @@ failed_clk_ptp: | |||
| 1874 | if (fep->clk_enet_out) | 1893 | if (fep->clk_enet_out) |
| 1875 | clk_disable_unprepare(fep->clk_enet_out); | 1894 | clk_disable_unprepare(fep->clk_enet_out); |
| 1876 | failed_clk_enet_out: | 1895 | failed_clk_enet_out: |
| 1877 | clk_disable_unprepare(fep->clk_ipg); | ||
| 1878 | failed_clk_ipg: | ||
| 1879 | clk_disable_unprepare(fep->clk_ahb); | 1896 | clk_disable_unprepare(fep->clk_ahb); |
| 1880 | 1897 | ||
| 1881 | return ret; | 1898 | return ret; |
| @@ -2847,10 +2864,14 @@ fec_enet_open(struct net_device *ndev) | |||
| 2847 | struct fec_enet_private *fep = netdev_priv(ndev); | 2864 | struct fec_enet_private *fep = netdev_priv(ndev); |
| 2848 | int ret; | 2865 | int ret; |
| 2849 | 2866 | ||
| 2867 | ret = pm_runtime_get_sync(&fep->pdev->dev); | ||
| 2868 | if (IS_ERR_VALUE(ret)) | ||
| 2869 | return ret; | ||
| 2870 | |||
| 2850 | pinctrl_pm_select_default_state(&fep->pdev->dev); | 2871 | pinctrl_pm_select_default_state(&fep->pdev->dev); |
| 2851 | ret = fec_enet_clk_enable(ndev, true); | 2872 | ret = fec_enet_clk_enable(ndev, true); |
| 2852 | if (ret) | 2873 | if (ret) |
| 2853 | return ret; | 2874 | goto clk_enable; |
| 2854 | 2875 | ||
| 2855 | /* I should reset the ring buffers here, but I don't yet know | 2876 | /* I should reset the ring buffers here, but I don't yet know |
| 2856 | * a simple way to do that. | 2877 | * a simple way to do that. |
| @@ -2881,6 +2902,9 @@ err_enet_mii_probe: | |||
| 2881 | fec_enet_free_buffers(ndev); | 2902 | fec_enet_free_buffers(ndev); |
| 2882 | err_enet_alloc: | 2903 | err_enet_alloc: |
| 2883 | fec_enet_clk_enable(ndev, false); | 2904 | fec_enet_clk_enable(ndev, false); |
| 2905 | clk_enable: | ||
| 2906 | pm_runtime_mark_last_busy(&fep->pdev->dev); | ||
| 2907 | pm_runtime_put_autosuspend(&fep->pdev->dev); | ||
| 2884 | pinctrl_pm_select_sleep_state(&fep->pdev->dev); | 2908 | pinctrl_pm_select_sleep_state(&fep->pdev->dev); |
| 2885 | return ret; | 2909 | return ret; |
| 2886 | } | 2910 | } |
| @@ -2903,6 +2927,9 @@ fec_enet_close(struct net_device *ndev) | |||
| 2903 | 2927 | ||
| 2904 | fec_enet_clk_enable(ndev, false); | 2928 | fec_enet_clk_enable(ndev, false); |
| 2905 | pinctrl_pm_select_sleep_state(&fep->pdev->dev); | 2929 | pinctrl_pm_select_sleep_state(&fep->pdev->dev); |
| 2930 | pm_runtime_mark_last_busy(&fep->pdev->dev); | ||
| 2931 | pm_runtime_put_autosuspend(&fep->pdev->dev); | ||
| 2932 | |||
| 2906 | fec_enet_free_buffers(ndev); | 2933 | fec_enet_free_buffers(ndev); |
| 2907 | 2934 | ||
| 2908 | return 0; | 2935 | return 0; |
| @@ -3115,8 +3142,8 @@ static int fec_enet_init(struct net_device *ndev) | |||
| 3115 | fep->bufdesc_size; | 3142 | fep->bufdesc_size; |
| 3116 | 3143 | ||
| 3117 | /* Allocate memory for buffer descriptors. */ | 3144 | /* Allocate memory for buffer descriptors. */ |
| 3118 | cbd_base = dma_alloc_coherent(NULL, bd_size, &bd_dma, | 3145 | cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma, |
| 3119 | GFP_KERNEL); | 3146 | GFP_KERNEL); |
| 3120 | if (!cbd_base) { | 3147 | if (!cbd_base) { |
| 3121 | return -ENOMEM; | 3148 | return -ENOMEM; |
| 3122 | } | 3149 | } |
| @@ -3388,6 +3415,10 @@ fec_probe(struct platform_device *pdev) | |||
| 3388 | if (ret) | 3415 | if (ret) |
| 3389 | goto failed_clk; | 3416 | goto failed_clk; |
| 3390 | 3417 | ||
| 3418 | ret = clk_prepare_enable(fep->clk_ipg); | ||
| 3419 | if (ret) | ||
| 3420 | goto failed_clk_ipg; | ||
| 3421 | |||
| 3391 | fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); | 3422 | fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); |
| 3392 | if (!IS_ERR(fep->reg_phy)) { | 3423 | if (!IS_ERR(fep->reg_phy)) { |
| 3393 | ret = regulator_enable(fep->reg_phy); | 3424 | ret = regulator_enable(fep->reg_phy); |
| @@ -3400,6 +3431,12 @@ fec_probe(struct platform_device *pdev) | |||
| 3400 | fep->reg_phy = NULL; | 3431 | fep->reg_phy = NULL; |
| 3401 | } | 3432 | } |
| 3402 | 3433 | ||
| 3434 | pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT); | ||
| 3435 | pm_runtime_use_autosuspend(&pdev->dev); | ||
| 3436 | pm_runtime_get_noresume(&pdev->dev); | ||
| 3437 | pm_runtime_set_active(&pdev->dev); | ||
| 3438 | pm_runtime_enable(&pdev->dev); | ||
| 3439 | |||
| 3403 | fec_reset_phy(pdev); | 3440 | fec_reset_phy(pdev); |
| 3404 | 3441 | ||
| 3405 | if (fep->bufdesc_ex) | 3442 | if (fep->bufdesc_ex) |
| @@ -3447,6 +3484,10 @@ fec_probe(struct platform_device *pdev) | |||
| 3447 | 3484 | ||
| 3448 | fep->rx_copybreak = COPYBREAK_DEFAULT; | 3485 | fep->rx_copybreak = COPYBREAK_DEFAULT; |
| 3449 | INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work); | 3486 | INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work); |
| 3487 | |||
| 3488 | pm_runtime_mark_last_busy(&pdev->dev); | ||
| 3489 | pm_runtime_put_autosuspend(&pdev->dev); | ||
| 3490 | |||
| 3450 | return 0; | 3491 | return 0; |
| 3451 | 3492 | ||
| 3452 | failed_register: | 3493 | failed_register: |
| @@ -3454,9 +3495,12 @@ failed_register: | |||
| 3454 | failed_mii_init: | 3495 | failed_mii_init: |
| 3455 | failed_irq: | 3496 | failed_irq: |
| 3456 | failed_init: | 3497 | failed_init: |
| 3498 | fec_ptp_stop(pdev); | ||
| 3457 | if (fep->reg_phy) | 3499 | if (fep->reg_phy) |
| 3458 | regulator_disable(fep->reg_phy); | 3500 | regulator_disable(fep->reg_phy); |
| 3459 | failed_regulator: | 3501 | failed_regulator: |
| 3502 | clk_disable_unprepare(fep->clk_ipg); | ||
| 3503 | failed_clk_ipg: | ||
| 3460 | fec_enet_clk_enable(ndev, false); | 3504 | fec_enet_clk_enable(ndev, false); |
| 3461 | failed_clk: | 3505 | failed_clk: |
| 3462 | failed_phy: | 3506 | failed_phy: |
| @@ -3473,14 +3517,12 @@ fec_drv_remove(struct platform_device *pdev) | |||
| 3473 | struct net_device *ndev = platform_get_drvdata(pdev); | 3517 | struct net_device *ndev = platform_get_drvdata(pdev); |
| 3474 | struct fec_enet_private *fep = netdev_priv(ndev); | 3518 | struct fec_enet_private *fep = netdev_priv(ndev); |
| 3475 | 3519 | ||
| 3476 | cancel_delayed_work_sync(&fep->time_keep); | ||
| 3477 | cancel_work_sync(&fep->tx_timeout_work); | 3520 | cancel_work_sync(&fep->tx_timeout_work); |
| 3521 | fec_ptp_stop(pdev); | ||
| 3478 | unregister_netdev(ndev); | 3522 | unregister_netdev(ndev); |
| 3479 | fec_enet_mii_remove(fep); | 3523 | fec_enet_mii_remove(fep); |
| 3480 | if (fep->reg_phy) | 3524 | if (fep->reg_phy) |
| 3481 | regulator_disable(fep->reg_phy); | 3525 | regulator_disable(fep->reg_phy); |
| 3482 | if (fep->ptp_clock) | ||
| 3483 | ptp_clock_unregister(fep->ptp_clock); | ||
| 3484 | of_node_put(fep->phy_node); | 3526 | of_node_put(fep->phy_node); |
| 3485 | free_netdev(ndev); | 3527 | free_netdev(ndev); |
| 3486 | 3528 | ||
| @@ -3568,7 +3610,28 @@ failed_clk: | |||
| 3568 | return ret; | 3610 | return ret; |
| 3569 | } | 3611 | } |
| 3570 | 3612 | ||
| 3571 | static SIMPLE_DEV_PM_OPS(fec_pm_ops, fec_suspend, fec_resume); | 3613 | static int __maybe_unused fec_runtime_suspend(struct device *dev) |
| 3614 | { | ||
| 3615 | struct net_device *ndev = dev_get_drvdata(dev); | ||
| 3616 | struct fec_enet_private *fep = netdev_priv(ndev); | ||
| 3617 | |||
| 3618 | clk_disable_unprepare(fep->clk_ipg); | ||
| 3619 | |||
| 3620 | return 0; | ||
| 3621 | } | ||
| 3622 | |||
| 3623 | static int __maybe_unused fec_runtime_resume(struct device *dev) | ||
| 3624 | { | ||
| 3625 | struct net_device *ndev = dev_get_drvdata(dev); | ||
| 3626 | struct fec_enet_private *fep = netdev_priv(ndev); | ||
| 3627 | |||
| 3628 | return clk_prepare_enable(fep->clk_ipg); | ||
| 3629 | } | ||
| 3630 | |||
| 3631 | static const struct dev_pm_ops fec_pm_ops = { | ||
| 3632 | SET_SYSTEM_SLEEP_PM_OPS(fec_suspend, fec_resume) | ||
| 3633 | SET_RUNTIME_PM_OPS(fec_runtime_suspend, fec_runtime_resume, NULL) | ||
| 3634 | }; | ||
| 3572 | 3635 | ||
| 3573 | static struct platform_driver fec_driver = { | 3636 | static struct platform_driver fec_driver = { |
| 3574 | .driver = { | 3637 | .driver = { |
