aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/socionext/netsec.c
diff options
context:
space:
mode:
authorMasahisa Kojima <masahisa.kojima@linaro.org>2018-10-23 07:24:26 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-23 13:55:34 -0400
commit8e850f25b5812aefedec6732732eb10e7b47cb5c (patch)
treed7cf4b8e7be570e205fae49f1657ec3f78b0fc9b /drivers/net/ethernet/socionext/netsec.c
parent487e2e22ab7968f2c0c82f37b5ca5883efd1a354 (diff)
net: socionext: Stop PHY before resetting netsec
In ndo_stop, driver resets the netsec ethernet controller IP. When the netsec IP is reset, HW running mode turns to NRM mode and driver has to wait until this mode transition completes. But mode transition to NRM will not complete if the PHY is in normal operation state. Netsec IP requires PHY is in power down state when it is reset. This modification stops the PHY before resetting netsec. Together with this modification, phy_addr is stored in netsec_priv structure because ndev->phydev is not yet ready in ndo_init. Fixes: 533dd11a12f6 ("net: socionext: Add Synquacer NetSec driver") Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> Signed-off-by: Yoshitoyo Osaki <osaki.yoshitoyo@socionext.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/socionext/netsec.c')
-rw-r--r--drivers/net/ethernet/socionext/netsec.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 4289ccb26e4e..bd9660ab0701 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -274,6 +274,7 @@ struct netsec_priv {
274 struct clk *clk; 274 struct clk *clk;
275 u32 msg_enable; 275 u32 msg_enable;
276 u32 freq; 276 u32 freq;
277 u32 phy_addr;
277 bool rx_cksum_offload_flag; 278 bool rx_cksum_offload_flag;
278}; 279};
279 280
@@ -1343,11 +1344,11 @@ static int netsec_netdev_stop(struct net_device *ndev)
1343 netsec_uninit_pkt_dring(priv, NETSEC_RING_TX); 1344 netsec_uninit_pkt_dring(priv, NETSEC_RING_TX);
1344 netsec_uninit_pkt_dring(priv, NETSEC_RING_RX); 1345 netsec_uninit_pkt_dring(priv, NETSEC_RING_RX);
1345 1346
1346 ret = netsec_reset_hardware(priv, false);
1347
1348 phy_stop(ndev->phydev); 1347 phy_stop(ndev->phydev);
1349 phy_disconnect(ndev->phydev); 1348 phy_disconnect(ndev->phydev);
1350 1349
1350 ret = netsec_reset_hardware(priv, false);
1351
1351 pm_runtime_put_sync(priv->dev); 1352 pm_runtime_put_sync(priv->dev);
1352 1353
1353 return ret; 1354 return ret;
@@ -1357,6 +1358,7 @@ static int netsec_netdev_init(struct net_device *ndev)
1357{ 1358{
1358 struct netsec_priv *priv = netdev_priv(ndev); 1359 struct netsec_priv *priv = netdev_priv(ndev);
1359 int ret; 1360 int ret;
1361 u16 data;
1360 1362
1361 ret = netsec_alloc_dring(priv, NETSEC_RING_TX); 1363 ret = netsec_alloc_dring(priv, NETSEC_RING_TX);
1362 if (ret) 1364 if (ret)
@@ -1366,6 +1368,11 @@ static int netsec_netdev_init(struct net_device *ndev)
1366 if (ret) 1368 if (ret)
1367 goto err1; 1369 goto err1;
1368 1370
1371 /* set phy power down */
1372 data = netsec_phy_read(priv->mii_bus, priv->phy_addr, MII_BMCR) |
1373 BMCR_PDOWN;
1374 netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR, data);
1375
1369 ret = netsec_reset_hardware(priv, true); 1376 ret = netsec_reset_hardware(priv, true);
1370 if (ret) 1377 if (ret)
1371 goto err2; 1378 goto err2;
@@ -1415,7 +1422,7 @@ static const struct net_device_ops netsec_netdev_ops = {
1415}; 1422};
1416 1423
1417static int netsec_of_probe(struct platform_device *pdev, 1424static int netsec_of_probe(struct platform_device *pdev,
1418 struct netsec_priv *priv) 1425 struct netsec_priv *priv, u32 *phy_addr)
1419{ 1426{
1420 priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); 1427 priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
1421 if (!priv->phy_np) { 1428 if (!priv->phy_np) {
@@ -1423,6 +1430,8 @@ static int netsec_of_probe(struct platform_device *pdev,
1423 return -EINVAL; 1430 return -EINVAL;
1424 } 1431 }
1425 1432
1433 *phy_addr = of_mdio_parse_addr(&pdev->dev, priv->phy_np);
1434
1426 priv->clk = devm_clk_get(&pdev->dev, NULL); /* get by 'phy_ref_clk' */ 1435 priv->clk = devm_clk_get(&pdev->dev, NULL); /* get by 'phy_ref_clk' */
1427 if (IS_ERR(priv->clk)) { 1436 if (IS_ERR(priv->clk)) {
1428 dev_err(&pdev->dev, "phy_ref_clk not found\n"); 1437 dev_err(&pdev->dev, "phy_ref_clk not found\n");
@@ -1623,12 +1632,14 @@ static int netsec_probe(struct platform_device *pdev)
1623 } 1632 }
1624 1633
1625 if (dev_of_node(&pdev->dev)) 1634 if (dev_of_node(&pdev->dev))
1626 ret = netsec_of_probe(pdev, priv); 1635 ret = netsec_of_probe(pdev, priv, &phy_addr);
1627 else 1636 else
1628 ret = netsec_acpi_probe(pdev, priv, &phy_addr); 1637 ret = netsec_acpi_probe(pdev, priv, &phy_addr);
1629 if (ret) 1638 if (ret)
1630 goto free_ndev; 1639 goto free_ndev;
1631 1640
1641 priv->phy_addr = phy_addr;
1642
1632 if (!priv->freq) { 1643 if (!priv->freq) {
1633 dev_err(&pdev->dev, "missing PHY reference clock frequency\n"); 1644 dev_err(&pdev->dev, "missing PHY reference clock frequency\n");
1634 ret = -ENODEV; 1645 ret = -ENODEV;