.. | .. |
---|
185 | 185 | NETIF_MSG_TX_ERR) |
---|
186 | 186 | |
---|
187 | 187 | /* Parameter for descriptor */ |
---|
188 | | -#define AVE_NR_TXDESC 32 /* Tx descriptor */ |
---|
189 | | -#define AVE_NR_RXDESC 64 /* Rx descriptor */ |
---|
| 188 | +#define AVE_NR_TXDESC 64 /* Tx descriptor */ |
---|
| 189 | +#define AVE_NR_RXDESC 256 /* Rx descriptor */ |
---|
190 | 190 | |
---|
191 | 191 | #define AVE_DESC_OFS_CMDSTS 0 |
---|
192 | 192 | #define AVE_DESC_OFS_ADDRL 4 |
---|
.. | .. |
---|
262 | 262 | struct regmap *regmap; |
---|
263 | 263 | unsigned int pinmode_mask; |
---|
264 | 264 | unsigned int pinmode_val; |
---|
| 265 | + u32 wolopts; |
---|
265 | 266 | |
---|
266 | 267 | /* stats */ |
---|
267 | 268 | struct ave_stats stats_rx; |
---|
.. | .. |
---|
423 | 424 | phy_ethtool_get_wol(ndev->phydev, wol); |
---|
424 | 425 | } |
---|
425 | 426 | |
---|
| 427 | +static int __ave_ethtool_set_wol(struct net_device *ndev, |
---|
| 428 | + struct ethtool_wolinfo *wol) |
---|
| 429 | +{ |
---|
| 430 | + if (!ndev->phydev || |
---|
| 431 | + (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))) |
---|
| 432 | + return -EOPNOTSUPP; |
---|
| 433 | + |
---|
| 434 | + return phy_ethtool_set_wol(ndev->phydev, wol); |
---|
| 435 | +} |
---|
| 436 | + |
---|
426 | 437 | static int ave_ethtool_set_wol(struct net_device *ndev, |
---|
427 | 438 | struct ethtool_wolinfo *wol) |
---|
428 | 439 | { |
---|
429 | 440 | int ret; |
---|
430 | 441 | |
---|
431 | | - if (!ndev->phydev || |
---|
432 | | - (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))) |
---|
433 | | - return -EOPNOTSUPP; |
---|
434 | | - |
---|
435 | | - ret = phy_ethtool_set_wol(ndev->phydev, wol); |
---|
| 442 | + ret = __ave_ethtool_set_wol(ndev, wol); |
---|
436 | 443 | if (!ret) |
---|
437 | 444 | device_set_wakeup_enable(&ndev->dev, !!wol->wolopts); |
---|
438 | 445 | |
---|
.. | .. |
---|
462 | 469 | priv->pause_rx = pause->rx_pause; |
---|
463 | 470 | priv->pause_tx = pause->tx_pause; |
---|
464 | 471 | |
---|
465 | | - phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); |
---|
466 | | - if (pause->rx_pause) |
---|
467 | | - phydev->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause; |
---|
468 | | - if (pause->tx_pause) |
---|
469 | | - phydev->advertising ^= ADVERTISED_Asym_Pause; |
---|
470 | | - |
---|
471 | | - if (pause->autoneg) { |
---|
472 | | - if (netif_running(ndev)) |
---|
473 | | - phy_start_aneg(phydev); |
---|
474 | | - } |
---|
| 472 | + phy_set_asym_pause(phydev, pause->rx_pause, pause->tx_pause); |
---|
475 | 473 | |
---|
476 | 474 | return 0; |
---|
477 | 475 | } |
---|
.. | .. |
---|
1127 | 1125 | rmt_adv |= LPA_PAUSE_CAP; |
---|
1128 | 1126 | if (phydev->asym_pause) |
---|
1129 | 1127 | rmt_adv |= LPA_PAUSE_ASYM; |
---|
1130 | | - if (phydev->advertising & ADVERTISED_Pause) |
---|
1131 | | - lcl_adv |= ADVERTISE_PAUSE_CAP; |
---|
1132 | | - if (phydev->advertising & ADVERTISED_Asym_Pause) |
---|
1133 | | - lcl_adv |= ADVERTISE_PAUSE_ASYM; |
---|
1134 | 1128 | |
---|
| 1129 | + lcl_adv = linkmode_adv_to_lcl_adv_t(phydev->advertising); |
---|
1135 | 1130 | cap = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); |
---|
1136 | 1131 | if (cap & FLOW_CTRL_TX) |
---|
1137 | 1132 | txcr |= AVE_TXCR_FLOCTR; |
---|
.. | .. |
---|
1222 | 1217 | |
---|
1223 | 1218 | priv->phydev = phydev; |
---|
1224 | 1219 | |
---|
1225 | | - phy_ethtool_get_wol(phydev, &wol); |
---|
| 1220 | + ave_ethtool_get_wol(ndev, &wol); |
---|
1226 | 1221 | device_set_wakeup_capable(&ndev->dev, !!wol.supported); |
---|
1227 | 1222 | |
---|
1228 | | - if (!phy_interface_is_rgmii(phydev)) { |
---|
1229 | | - phydev->supported &= ~PHY_GBIT_FEATURES; |
---|
1230 | | - phydev->supported |= PHY_BASIC_FEATURES; |
---|
1231 | | - } |
---|
1232 | | - phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; |
---|
| 1223 | + /* set wol initial state disabled */ |
---|
| 1224 | + wol.wolopts = 0; |
---|
| 1225 | + __ave_ethtool_set_wol(ndev, &wol); |
---|
| 1226 | + |
---|
| 1227 | + if (!phy_interface_is_rgmii(phydev)) |
---|
| 1228 | + phy_set_max_speed(phydev, SPEED_100); |
---|
| 1229 | + |
---|
| 1230 | + phy_support_asym_pause(phydev); |
---|
1233 | 1231 | |
---|
1234 | 1232 | phy_attached_info(phydev); |
---|
1235 | 1233 | |
---|
.. | .. |
---|
1396 | 1394 | return 0; |
---|
1397 | 1395 | } |
---|
1398 | 1396 | |
---|
1399 | | -static int ave_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
---|
| 1397 | +static netdev_tx_t ave_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
---|
1400 | 1398 | { |
---|
1401 | 1399 | struct ave_private *priv = netdev_priv(ndev); |
---|
1402 | 1400 | u32 proc_idx, done_idx, ndesc, cmdsts; |
---|
.. | .. |
---|
1561 | 1559 | struct ave_private *priv; |
---|
1562 | 1560 | struct net_device *ndev; |
---|
1563 | 1561 | struct device_node *np; |
---|
1564 | | - struct resource *res; |
---|
1565 | 1562 | const void *mac_addr; |
---|
1566 | 1563 | void __iomem *base; |
---|
1567 | 1564 | const char *name; |
---|
.. | .. |
---|
1574 | 1571 | return -EINVAL; |
---|
1575 | 1572 | |
---|
1576 | 1573 | np = dev->of_node; |
---|
1577 | | - phy_mode = of_get_phy_mode(np); |
---|
1578 | | - if ((int)phy_mode < 0) { |
---|
| 1574 | + ret = of_get_phy_mode(np, &phy_mode); |
---|
| 1575 | + if (ret) { |
---|
1579 | 1576 | dev_err(dev, "phy-mode not found\n"); |
---|
1580 | | - return -EINVAL; |
---|
| 1577 | + return ret; |
---|
1581 | 1578 | } |
---|
1582 | 1579 | |
---|
1583 | 1580 | irq = platform_get_irq(pdev, 0); |
---|
1584 | | - if (irq < 0) { |
---|
1585 | | - dev_err(dev, "IRQ not found\n"); |
---|
| 1581 | + if (irq < 0) |
---|
1586 | 1582 | return irq; |
---|
1587 | | - } |
---|
1588 | 1583 | |
---|
1589 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
1590 | | - base = devm_ioremap_resource(dev, res); |
---|
| 1584 | + base = devm_platform_ioremap_resource(pdev, 0); |
---|
1591 | 1585 | if (IS_ERR(base)) |
---|
1592 | 1586 | return PTR_ERR(base); |
---|
1593 | 1587 | |
---|
1594 | | - ndev = alloc_etherdev(sizeof(struct ave_private)); |
---|
| 1588 | + ndev = devm_alloc_etherdev(dev, sizeof(struct ave_private)); |
---|
1595 | 1589 | if (!ndev) { |
---|
1596 | 1590 | dev_err(dev, "can't allocate ethernet device\n"); |
---|
1597 | 1591 | return -ENOMEM; |
---|
.. | .. |
---|
1607 | 1601 | ndev->max_mtu = AVE_MAX_ETHFRAME - (ETH_HLEN + ETH_FCS_LEN); |
---|
1608 | 1602 | |
---|
1609 | 1603 | mac_addr = of_get_mac_address(np); |
---|
1610 | | - if (mac_addr) |
---|
| 1604 | + if (!IS_ERR(mac_addr)) |
---|
1611 | 1605 | ether_addr_copy(ndev->dev_addr, mac_addr); |
---|
1612 | 1606 | |
---|
1613 | 1607 | /* if the mac address is invalid, use random mac address */ |
---|
.. | .. |
---|
1638 | 1632 | } |
---|
1639 | 1633 | ret = dma_set_mask(dev, dma_mask); |
---|
1640 | 1634 | if (ret) |
---|
1641 | | - goto out_free_netdev; |
---|
| 1635 | + return ret; |
---|
1642 | 1636 | |
---|
1643 | 1637 | priv->tx.ndesc = AVE_NR_TXDESC; |
---|
1644 | 1638 | priv->rx.ndesc = AVE_NR_RXDESC; |
---|
.. | .. |
---|
1651 | 1645 | if (!name) |
---|
1652 | 1646 | break; |
---|
1653 | 1647 | priv->clk[i] = devm_clk_get(dev, name); |
---|
1654 | | - if (IS_ERR(priv->clk[i])) { |
---|
1655 | | - ret = PTR_ERR(priv->clk[i]); |
---|
1656 | | - goto out_free_netdev; |
---|
1657 | | - } |
---|
| 1648 | + if (IS_ERR(priv->clk[i])) |
---|
| 1649 | + return PTR_ERR(priv->clk[i]); |
---|
1658 | 1650 | priv->nclks++; |
---|
1659 | 1651 | } |
---|
1660 | 1652 | |
---|
.. | .. |
---|
1663 | 1655 | if (!name) |
---|
1664 | 1656 | break; |
---|
1665 | 1657 | priv->rst[i] = devm_reset_control_get_shared(dev, name); |
---|
1666 | | - if (IS_ERR(priv->rst[i])) { |
---|
1667 | | - ret = PTR_ERR(priv->rst[i]); |
---|
1668 | | - goto out_free_netdev; |
---|
1669 | | - } |
---|
| 1658 | + if (IS_ERR(priv->rst[i])) |
---|
| 1659 | + return PTR_ERR(priv->rst[i]); |
---|
1670 | 1660 | priv->nrsts++; |
---|
1671 | 1661 | } |
---|
1672 | 1662 | |
---|
.. | .. |
---|
1674 | 1664 | "socionext,syscon-phy-mode", |
---|
1675 | 1665 | 1, 0, &args); |
---|
1676 | 1666 | if (ret) { |
---|
1677 | | - netdev_err(ndev, "can't get syscon-phy-mode property\n"); |
---|
1678 | | - goto out_free_netdev; |
---|
| 1667 | + dev_err(dev, "can't get syscon-phy-mode property\n"); |
---|
| 1668 | + return ret; |
---|
1679 | 1669 | } |
---|
1680 | 1670 | priv->regmap = syscon_node_to_regmap(args.np); |
---|
1681 | 1671 | of_node_put(args.np); |
---|
1682 | 1672 | if (IS_ERR(priv->regmap)) { |
---|
1683 | | - netdev_err(ndev, "can't map syscon-phy-mode\n"); |
---|
1684 | | - ret = PTR_ERR(priv->regmap); |
---|
1685 | | - goto out_free_netdev; |
---|
| 1673 | + dev_err(dev, "can't map syscon-phy-mode\n"); |
---|
| 1674 | + return PTR_ERR(priv->regmap); |
---|
1686 | 1675 | } |
---|
1687 | 1676 | ret = priv->data->get_pinmode(priv, phy_mode, args.args[0]); |
---|
1688 | 1677 | if (ret) { |
---|
1689 | | - netdev_err(ndev, "invalid phy-mode setting\n"); |
---|
1690 | | - goto out_free_netdev; |
---|
| 1678 | + dev_err(dev, "invalid phy-mode setting\n"); |
---|
| 1679 | + return ret; |
---|
1691 | 1680 | } |
---|
1692 | 1681 | |
---|
1693 | 1682 | priv->mdio = devm_mdiobus_alloc(dev); |
---|
1694 | | - if (!priv->mdio) { |
---|
1695 | | - ret = -ENOMEM; |
---|
1696 | | - goto out_free_netdev; |
---|
1697 | | - } |
---|
| 1683 | + if (!priv->mdio) |
---|
| 1684 | + return -ENOMEM; |
---|
1698 | 1685 | priv->mdio->priv = ndev; |
---|
1699 | 1686 | priv->mdio->parent = dev; |
---|
1700 | 1687 | priv->mdio->read = ave_mdiobus_read; |
---|
.. | .. |
---|
1704 | 1691 | pdev->name, pdev->id); |
---|
1705 | 1692 | |
---|
1706 | 1693 | /* Register as a NAPI supported driver */ |
---|
1707 | | - netif_napi_add(ndev, &priv->napi_rx, ave_napi_poll_rx, priv->rx.ndesc); |
---|
| 1694 | + netif_napi_add(ndev, &priv->napi_rx, ave_napi_poll_rx, |
---|
| 1695 | + NAPI_POLL_WEIGHT); |
---|
1708 | 1696 | netif_tx_napi_add(ndev, &priv->napi_tx, ave_napi_poll_tx, |
---|
1709 | | - priv->tx.ndesc); |
---|
| 1697 | + NAPI_POLL_WEIGHT); |
---|
1710 | 1698 | |
---|
1711 | 1699 | platform_set_drvdata(pdev, ndev); |
---|
1712 | 1700 | |
---|
.. | .. |
---|
1730 | 1718 | out_del_napi: |
---|
1731 | 1719 | netif_napi_del(&priv->napi_rx); |
---|
1732 | 1720 | netif_napi_del(&priv->napi_tx); |
---|
1733 | | -out_free_netdev: |
---|
1734 | | - free_netdev(ndev); |
---|
1735 | 1721 | |
---|
1736 | 1722 | return ret; |
---|
1737 | 1723 | } |
---|
.. | .. |
---|
1744 | 1730 | unregister_netdev(ndev); |
---|
1745 | 1731 | netif_napi_del(&priv->napi_rx); |
---|
1746 | 1732 | netif_napi_del(&priv->napi_tx); |
---|
1747 | | - free_netdev(ndev); |
---|
1748 | 1733 | |
---|
1749 | 1734 | return 0; |
---|
1750 | 1735 | } |
---|
| 1736 | + |
---|
| 1737 | +#ifdef CONFIG_PM_SLEEP |
---|
| 1738 | +static int ave_suspend(struct device *dev) |
---|
| 1739 | +{ |
---|
| 1740 | + struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; |
---|
| 1741 | + struct net_device *ndev = dev_get_drvdata(dev); |
---|
| 1742 | + struct ave_private *priv = netdev_priv(ndev); |
---|
| 1743 | + int ret = 0; |
---|
| 1744 | + |
---|
| 1745 | + if (netif_running(ndev)) { |
---|
| 1746 | + ret = ave_stop(ndev); |
---|
| 1747 | + netif_device_detach(ndev); |
---|
| 1748 | + } |
---|
| 1749 | + |
---|
| 1750 | + ave_ethtool_get_wol(ndev, &wol); |
---|
| 1751 | + priv->wolopts = wol.wolopts; |
---|
| 1752 | + |
---|
| 1753 | + return ret; |
---|
| 1754 | +} |
---|
| 1755 | + |
---|
| 1756 | +static int ave_resume(struct device *dev) |
---|
| 1757 | +{ |
---|
| 1758 | + struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; |
---|
| 1759 | + struct net_device *ndev = dev_get_drvdata(dev); |
---|
| 1760 | + struct ave_private *priv = netdev_priv(ndev); |
---|
| 1761 | + int ret = 0; |
---|
| 1762 | + |
---|
| 1763 | + ave_global_reset(ndev); |
---|
| 1764 | + |
---|
| 1765 | + ave_ethtool_get_wol(ndev, &wol); |
---|
| 1766 | + wol.wolopts = priv->wolopts; |
---|
| 1767 | + __ave_ethtool_set_wol(ndev, &wol); |
---|
| 1768 | + |
---|
| 1769 | + if (ndev->phydev) { |
---|
| 1770 | + ret = phy_resume(ndev->phydev); |
---|
| 1771 | + if (ret) |
---|
| 1772 | + return ret; |
---|
| 1773 | + } |
---|
| 1774 | + |
---|
| 1775 | + if (netif_running(ndev)) { |
---|
| 1776 | + ret = ave_open(ndev); |
---|
| 1777 | + netif_device_attach(ndev); |
---|
| 1778 | + } |
---|
| 1779 | + |
---|
| 1780 | + return ret; |
---|
| 1781 | +} |
---|
| 1782 | + |
---|
| 1783 | +static SIMPLE_DEV_PM_OPS(ave_pm_ops, ave_suspend, ave_resume); |
---|
| 1784 | +#define AVE_PM_OPS (&ave_pm_ops) |
---|
| 1785 | +#else |
---|
| 1786 | +#define AVE_PM_OPS NULL |
---|
| 1787 | +#endif |
---|
1751 | 1788 | |
---|
1752 | 1789 | static int ave_pro4_get_pinmode(struct ave_private *priv, |
---|
1753 | 1790 | phy_interface_t phy_mode, u32 arg) |
---|
.. | .. |
---|
1763 | 1800 | break; |
---|
1764 | 1801 | case PHY_INTERFACE_MODE_MII: |
---|
1765 | 1802 | case PHY_INTERFACE_MODE_RGMII: |
---|
| 1803 | + case PHY_INTERFACE_MODE_RGMII_ID: |
---|
| 1804 | + case PHY_INTERFACE_MODE_RGMII_RXID: |
---|
| 1805 | + case PHY_INTERFACE_MODE_RGMII_TXID: |
---|
1766 | 1806 | priv->pinmode_val = 0; |
---|
1767 | 1807 | break; |
---|
1768 | 1808 | default: |
---|
.. | .. |
---|
1807 | 1847 | priv->pinmode_val = SG_ETPINMODE_RMII(0); |
---|
1808 | 1848 | break; |
---|
1809 | 1849 | case PHY_INTERFACE_MODE_RGMII: |
---|
| 1850 | + case PHY_INTERFACE_MODE_RGMII_ID: |
---|
| 1851 | + case PHY_INTERFACE_MODE_RGMII_RXID: |
---|
| 1852 | + case PHY_INTERFACE_MODE_RGMII_TXID: |
---|
1810 | 1853 | priv->pinmode_val = 0; |
---|
1811 | 1854 | break; |
---|
1812 | 1855 | default: |
---|
.. | .. |
---|
1829 | 1872 | priv->pinmode_val = SG_ETPINMODE_RMII(arg); |
---|
1830 | 1873 | break; |
---|
1831 | 1874 | case PHY_INTERFACE_MODE_RGMII: |
---|
| 1875 | + case PHY_INTERFACE_MODE_RGMII_ID: |
---|
| 1876 | + case PHY_INTERFACE_MODE_RGMII_RXID: |
---|
| 1877 | + case PHY_INTERFACE_MODE_RGMII_TXID: |
---|
1832 | 1878 | priv->pinmode_val = 0; |
---|
1833 | 1879 | break; |
---|
1834 | 1880 | default: |
---|
.. | .. |
---|
1923 | 1969 | .remove = ave_remove, |
---|
1924 | 1970 | .driver = { |
---|
1925 | 1971 | .name = "ave", |
---|
| 1972 | + .pm = AVE_PM_OPS, |
---|
1926 | 1973 | .of_match_table = of_ave_match, |
---|
1927 | 1974 | }, |
---|
1928 | 1975 | }; |
---|
1929 | 1976 | module_platform_driver(ave_driver); |
---|
1930 | 1977 | |
---|
| 1978 | +MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); |
---|
1931 | 1979 | MODULE_DESCRIPTION("Socionext UniPhier AVE ethernet driver"); |
---|
1932 | 1980 | MODULE_LICENSE("GPL v2"); |
---|