diff options
-rw-r--r-- | drivers/net/ethernet/socionext/netsec.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c index 4289ccb26e4e..d9d0d03e4ce7 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 | ||
@@ -431,9 +432,12 @@ static int netsec_mac_update_to_phy_state(struct netsec_priv *priv) | |||
431 | return 0; | 432 | return 0; |
432 | } | 433 | } |
433 | 434 | ||
435 | static int netsec_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr); | ||
436 | |||
434 | static int netsec_phy_write(struct mii_bus *bus, | 437 | static int netsec_phy_write(struct mii_bus *bus, |
435 | int phy_addr, int reg, u16 val) | 438 | int phy_addr, int reg, u16 val) |
436 | { | 439 | { |
440 | int status; | ||
437 | struct netsec_priv *priv = bus->priv; | 441 | struct netsec_priv *priv = bus->priv; |
438 | 442 | ||
439 | if (netsec_mac_write(priv, GMAC_REG_GDR, val)) | 443 | if (netsec_mac_write(priv, GMAC_REG_GDR, val)) |
@@ -446,8 +450,19 @@ static int netsec_phy_write(struct mii_bus *bus, | |||
446 | GMAC_REG_SHIFT_CR_GAR))) | 450 | GMAC_REG_SHIFT_CR_GAR))) |
447 | return -ETIMEDOUT; | 451 | return -ETIMEDOUT; |
448 | 452 | ||
449 | return netsec_mac_wait_while_busy(priv, GMAC_REG_GAR, | 453 | status = netsec_mac_wait_while_busy(priv, GMAC_REG_GAR, |
450 | NETSEC_GMAC_GAR_REG_GB); | 454 | NETSEC_GMAC_GAR_REG_GB); |
455 | |||
456 | /* Developerbox implements RTL8211E PHY and there is | ||
457 | * a compatibility problem with F_GMAC4. | ||
458 | * RTL8211E expects MDC clock must be kept toggling for several | ||
459 | * clock cycle with MDIO high before entering the IDLE state. | ||
460 | * To meet this requirement, netsec driver needs to issue dummy | ||
461 | * read(e.g. read PHYID1(offset 0x2) register) right after write. | ||
462 | */ | ||
463 | netsec_phy_read(bus, phy_addr, MII_PHYSID1); | ||
464 | |||
465 | return status; | ||
451 | } | 466 | } |
452 | 467 | ||
453 | static int netsec_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr) | 468 | static int netsec_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr) |
@@ -940,6 +955,9 @@ static void netsec_uninit_pkt_dring(struct netsec_priv *priv, int id) | |||
940 | dring->head = 0; | 955 | dring->head = 0; |
941 | dring->tail = 0; | 956 | dring->tail = 0; |
942 | dring->pkt_cnt = 0; | 957 | dring->pkt_cnt = 0; |
958 | |||
959 | if (id == NETSEC_RING_TX) | ||
960 | netdev_reset_queue(priv->ndev); | ||
943 | } | 961 | } |
944 | 962 | ||
945 | static void netsec_free_dring(struct netsec_priv *priv, int id) | 963 | static void netsec_free_dring(struct netsec_priv *priv, int id) |
@@ -1343,11 +1361,11 @@ static int netsec_netdev_stop(struct net_device *ndev) | |||
1343 | netsec_uninit_pkt_dring(priv, NETSEC_RING_TX); | 1361 | netsec_uninit_pkt_dring(priv, NETSEC_RING_TX); |
1344 | netsec_uninit_pkt_dring(priv, NETSEC_RING_RX); | 1362 | netsec_uninit_pkt_dring(priv, NETSEC_RING_RX); |
1345 | 1363 | ||
1346 | ret = netsec_reset_hardware(priv, false); | ||
1347 | |||
1348 | phy_stop(ndev->phydev); | 1364 | phy_stop(ndev->phydev); |
1349 | phy_disconnect(ndev->phydev); | 1365 | phy_disconnect(ndev->phydev); |
1350 | 1366 | ||
1367 | ret = netsec_reset_hardware(priv, false); | ||
1368 | |||
1351 | pm_runtime_put_sync(priv->dev); | 1369 | pm_runtime_put_sync(priv->dev); |
1352 | 1370 | ||
1353 | return ret; | 1371 | return ret; |
@@ -1357,6 +1375,7 @@ static int netsec_netdev_init(struct net_device *ndev) | |||
1357 | { | 1375 | { |
1358 | struct netsec_priv *priv = netdev_priv(ndev); | 1376 | struct netsec_priv *priv = netdev_priv(ndev); |
1359 | int ret; | 1377 | int ret; |
1378 | u16 data; | ||
1360 | 1379 | ||
1361 | ret = netsec_alloc_dring(priv, NETSEC_RING_TX); | 1380 | ret = netsec_alloc_dring(priv, NETSEC_RING_TX); |
1362 | if (ret) | 1381 | if (ret) |
@@ -1366,6 +1385,11 @@ static int netsec_netdev_init(struct net_device *ndev) | |||
1366 | if (ret) | 1385 | if (ret) |
1367 | goto err1; | 1386 | goto err1; |
1368 | 1387 | ||
1388 | /* set phy power down */ | ||
1389 | data = netsec_phy_read(priv->mii_bus, priv->phy_addr, MII_BMCR) | | ||
1390 | BMCR_PDOWN; | ||
1391 | netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR, data); | ||
1392 | |||
1369 | ret = netsec_reset_hardware(priv, true); | 1393 | ret = netsec_reset_hardware(priv, true); |
1370 | if (ret) | 1394 | if (ret) |
1371 | goto err2; | 1395 | goto err2; |
@@ -1415,7 +1439,7 @@ static const struct net_device_ops netsec_netdev_ops = { | |||
1415 | }; | 1439 | }; |
1416 | 1440 | ||
1417 | static int netsec_of_probe(struct platform_device *pdev, | 1441 | static int netsec_of_probe(struct platform_device *pdev, |
1418 | struct netsec_priv *priv) | 1442 | struct netsec_priv *priv, u32 *phy_addr) |
1419 | { | 1443 | { |
1420 | priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); | 1444 | priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); |
1421 | if (!priv->phy_np) { | 1445 | if (!priv->phy_np) { |
@@ -1423,6 +1447,8 @@ static int netsec_of_probe(struct platform_device *pdev, | |||
1423 | return -EINVAL; | 1447 | return -EINVAL; |
1424 | } | 1448 | } |
1425 | 1449 | ||
1450 | *phy_addr = of_mdio_parse_addr(&pdev->dev, priv->phy_np); | ||
1451 | |||
1426 | priv->clk = devm_clk_get(&pdev->dev, NULL); /* get by 'phy_ref_clk' */ | 1452 | priv->clk = devm_clk_get(&pdev->dev, NULL); /* get by 'phy_ref_clk' */ |
1427 | if (IS_ERR(priv->clk)) { | 1453 | if (IS_ERR(priv->clk)) { |
1428 | dev_err(&pdev->dev, "phy_ref_clk not found\n"); | 1454 | dev_err(&pdev->dev, "phy_ref_clk not found\n"); |
@@ -1623,12 +1649,14 @@ static int netsec_probe(struct platform_device *pdev) | |||
1623 | } | 1649 | } |
1624 | 1650 | ||
1625 | if (dev_of_node(&pdev->dev)) | 1651 | if (dev_of_node(&pdev->dev)) |
1626 | ret = netsec_of_probe(pdev, priv); | 1652 | ret = netsec_of_probe(pdev, priv, &phy_addr); |
1627 | else | 1653 | else |
1628 | ret = netsec_acpi_probe(pdev, priv, &phy_addr); | 1654 | ret = netsec_acpi_probe(pdev, priv, &phy_addr); |
1629 | if (ret) | 1655 | if (ret) |
1630 | goto free_ndev; | 1656 | goto free_ndev; |
1631 | 1657 | ||
1658 | priv->phy_addr = phy_addr; | ||
1659 | |||
1632 | if (!priv->freq) { | 1660 | if (!priv->freq) { |
1633 | dev_err(&pdev->dev, "missing PHY reference clock frequency\n"); | 1661 | dev_err(&pdev->dev, "missing PHY reference clock frequency\n"); |
1634 | ret = -ENODEV; | 1662 | ret = -ENODEV; |