Skip to content

Commit 1b0a83a

Browse files
g0hl1ndavem330
authored andcommitted
net: fec: add phy_reset_after_clk_enable() support
Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow turning the refclk on and off again during operation (according to their datasheet). Nonetheless exactly this behaviour was introduced for power saving reasons by commit e8fcfcd ("net: fec: optimize the clock management to save power"). Therefore add support for the phy_reset_after_clk_enable function from phylib to mitigate this issue. Generally speaking this issue is only relevant if the ref clk for the PHY is generated by the SoC and therefore the PHY is configured to "REF_CLK In Mode". In our specific case (PCB) this problem does occur at about every 10th to 50th POR of an LAN8710 connected to an i.MX6SOLO SoC. The typical symptom of this problem is a "swinging" ethernet link. Similar issues were reported by users of the NXP forum: https://community.nxp.com/thread/389902 https://community.nxp.com/message/309354 With this patch applied the issue didn't occur for at least a few hundret PORs of our board. Fixes: e8fcfcd ("net: fec: optimize the clock management to save power") Signed-off-by: Richard Leitner <richard.leitner@skidata.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 7f64e5b commit 1b0a83a

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

drivers/net/ethernet/freescale/fec_main.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,8 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
18621862
ret = clk_prepare_enable(fep->clk_ref);
18631863
if (ret)
18641864
goto failed_clk_ref;
1865+
1866+
phy_reset_after_clk_enable(ndev->phydev);
18651867
} else {
18661868
clk_disable_unprepare(fep->clk_ahb);
18671869
clk_disable_unprepare(fep->clk_enet_out);
@@ -2834,6 +2836,7 @@ fec_enet_open(struct net_device *ndev)
28342836
{
28352837
struct fec_enet_private *fep = netdev_priv(ndev);
28362838
int ret;
2839+
bool reset_again;
28372840

28382841
ret = pm_runtime_get_sync(&fep->pdev->dev);
28392842
if (ret < 0)
@@ -2844,6 +2847,17 @@ fec_enet_open(struct net_device *ndev)
28442847
if (ret)
28452848
goto clk_enable;
28462849

2850+
/* During the first fec_enet_open call the PHY isn't probed at this
2851+
* point. Therefore the phy_reset_after_clk_enable() call within
2852+
* fec_enet_clk_enable() fails. As we need this reset in order to be
2853+
* sure the PHY is working correctly we check if we need to reset again
2854+
* later when the PHY is probed
2855+
*/
2856+
if (ndev->phydev && ndev->phydev->drv)
2857+
reset_again = false;
2858+
else
2859+
reset_again = true;
2860+
28472861
/* I should reset the ring buffers here, but I don't yet know
28482862
* a simple way to do that.
28492863
*/
@@ -2860,6 +2874,12 @@ fec_enet_open(struct net_device *ndev)
28602874
if (ret)
28612875
goto err_enet_mii_probe;
28622876

2877+
/* Call phy_reset_after_clk_enable() again if it failed during
2878+
* phy_reset_after_clk_enable() before because the PHY wasn't probed.
2879+
*/
2880+
if (reset_again)
2881+
phy_reset_after_clk_enable(ndev->phydev);
2882+
28632883
if (fep->quirks & FEC_QUIRK_ERR006687)
28642884
imx6q_cpuidle_fec_irqs_used();
28652885

0 commit comments

Comments
 (0)