net: socionext: Stop PHY before resetting netsec
[muen/linux.git] / drivers / net / ethernet / socionext / netsec.c
index 4289ccb26e4ec3045aee380144196150ca198f08..bd9660ab0701ffc36d6c089e6568eb346b17d880 100644 (file)
@@ -274,6 +274,7 @@ struct netsec_priv {
        struct clk *clk;
        u32 msg_enable;
        u32 freq;
+       u32 phy_addr;
        bool rx_cksum_offload_flag;
 };
 
@@ -1343,11 +1344,11 @@ static int netsec_netdev_stop(struct net_device *ndev)
        netsec_uninit_pkt_dring(priv, NETSEC_RING_TX);
        netsec_uninit_pkt_dring(priv, NETSEC_RING_RX);
 
-       ret = netsec_reset_hardware(priv, false);
-
        phy_stop(ndev->phydev);
        phy_disconnect(ndev->phydev);
 
+       ret = netsec_reset_hardware(priv, false);
+
        pm_runtime_put_sync(priv->dev);
 
        return ret;
@@ -1357,6 +1358,7 @@ static int netsec_netdev_init(struct net_device *ndev)
 {
        struct netsec_priv *priv = netdev_priv(ndev);
        int ret;
+       u16 data;
 
        ret = netsec_alloc_dring(priv, NETSEC_RING_TX);
        if (ret)
@@ -1366,6 +1368,11 @@ static int netsec_netdev_init(struct net_device *ndev)
        if (ret)
                goto err1;
 
+       /* set phy power down */
+       data = netsec_phy_read(priv->mii_bus, priv->phy_addr, MII_BMCR) |
+               BMCR_PDOWN;
+       netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR, data);
+
        ret = netsec_reset_hardware(priv, true);
        if (ret)
                goto err2;
@@ -1415,7 +1422,7 @@ static const struct net_device_ops netsec_netdev_ops = {
 };
 
 static int netsec_of_probe(struct platform_device *pdev,
-                          struct netsec_priv *priv)
+                          struct netsec_priv *priv, u32 *phy_addr)
 {
        priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
        if (!priv->phy_np) {
@@ -1423,6 +1430,8 @@ static int netsec_of_probe(struct platform_device *pdev,
                return -EINVAL;
        }
 
+       *phy_addr = of_mdio_parse_addr(&pdev->dev, priv->phy_np);
+
        priv->clk = devm_clk_get(&pdev->dev, NULL); /* get by 'phy_ref_clk' */
        if (IS_ERR(priv->clk)) {
                dev_err(&pdev->dev, "phy_ref_clk not found\n");
@@ -1623,12 +1632,14 @@ static int netsec_probe(struct platform_device *pdev)
        }
 
        if (dev_of_node(&pdev->dev))
-               ret = netsec_of_probe(pdev, priv);
+               ret = netsec_of_probe(pdev, priv, &phy_addr);
        else
                ret = netsec_acpi_probe(pdev, priv, &phy_addr);
        if (ret)
                goto free_ndev;
 
+       priv->phy_addr = phy_addr;
+
        if (!priv->freq) {
                dev_err(&pdev->dev, "missing PHY reference clock frequency\n");
                ret = -ENODEV;