.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Faraday FTGMAC100 Gigabit Ethernet |
---|
3 | 4 | * |
---|
4 | 5 | * (C) Copyright 2009-2011 Faraday Technology |
---|
5 | 6 | * Po-Yu Chuang <ratbert@faraday-tech.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License as published by |
---|
9 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
10 | | - * (at your option) any later version. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, |
---|
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | | - * |
---|
17 | | - * You should have received a copy of the GNU General Public License |
---|
18 | | - * along with this program; if not, write to the Free Software |
---|
19 | | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
20 | 7 | */ |
---|
21 | 8 | |
---|
22 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
30 | 17 | #include <linux/module.h> |
---|
31 | 18 | #include <linux/netdevice.h> |
---|
32 | 19 | #include <linux/of.h> |
---|
| 20 | +#include <linux/of_mdio.h> |
---|
33 | 21 | #include <linux/phy.h> |
---|
34 | 22 | #include <linux/platform_device.h> |
---|
35 | 23 | #include <linux/property.h> |
---|
.. | .. |
---|
42 | 30 | #include "ftgmac100.h" |
---|
43 | 31 | |
---|
44 | 32 | #define DRV_NAME "ftgmac100" |
---|
45 | | -#define DRV_VERSION "0.7" |
---|
46 | 33 | |
---|
47 | 34 | /* Arbitrary values, I am not sure the HW has limits */ |
---|
48 | 35 | #define MAX_RX_QUEUE_ENTRIES 1024 |
---|
.. | .. |
---|
101 | 88 | struct work_struct reset_task; |
---|
102 | 89 | struct mii_bus *mii_bus; |
---|
103 | 90 | struct clk *clk; |
---|
| 91 | + |
---|
| 92 | + /* AST2500/AST2600 RMII ref clock gate */ |
---|
| 93 | + struct clk *rclk; |
---|
104 | 94 | |
---|
105 | 95 | /* Link management */ |
---|
106 | 96 | int cur_speed; |
---|
.. | .. |
---|
786 | 776 | for (i = 0; i < nfrags; i++) { |
---|
787 | 777 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
---|
788 | 778 | |
---|
789 | | - len = frag->size; |
---|
| 779 | + len = skb_frag_size(frag); |
---|
790 | 780 | |
---|
791 | 781 | /* Map it */ |
---|
792 | 782 | map = skb_frag_dma_map(priv->dev, frag, 0, len, |
---|
.. | .. |
---|
934 | 924 | return -ENOMEM; |
---|
935 | 925 | |
---|
936 | 926 | /* Allocate descriptors */ |
---|
937 | | - priv->rxdes = dma_zalloc_coherent(priv->dev, |
---|
938 | | - MAX_RX_QUEUE_ENTRIES * |
---|
939 | | - sizeof(struct ftgmac100_rxdes), |
---|
940 | | - &priv->rxdes_dma, GFP_KERNEL); |
---|
| 927 | + priv->rxdes = dma_alloc_coherent(priv->dev, |
---|
| 928 | + MAX_RX_QUEUE_ENTRIES * sizeof(struct ftgmac100_rxdes), |
---|
| 929 | + &priv->rxdes_dma, GFP_KERNEL); |
---|
941 | 930 | if (!priv->rxdes) |
---|
942 | 931 | return -ENOMEM; |
---|
943 | | - priv->txdes = dma_zalloc_coherent(priv->dev, |
---|
944 | | - MAX_TX_QUEUE_ENTRIES * |
---|
945 | | - sizeof(struct ftgmac100_txdes), |
---|
946 | | - &priv->txdes_dma, GFP_KERNEL); |
---|
| 932 | + priv->txdes = dma_alloc_coherent(priv->dev, |
---|
| 933 | + MAX_TX_QUEUE_ENTRIES * sizeof(struct ftgmac100_txdes), |
---|
| 934 | + &priv->txdes_dma, GFP_KERNEL); |
---|
947 | 935 | if (!priv->txdes) |
---|
948 | 936 | return -ENOMEM; |
---|
949 | 937 | |
---|
.. | .. |
---|
1076 | 1064 | } |
---|
1077 | 1065 | |
---|
1078 | 1066 | /* Indicate that we support PAUSE frames (see comment in |
---|
1079 | | - * Documentation/networking/phy.txt) |
---|
| 1067 | + * Documentation/networking/phy.rst) |
---|
1080 | 1068 | */ |
---|
1081 | | - phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; |
---|
1082 | | - phydev->advertising = phydev->supported; |
---|
| 1069 | + phy_support_asym_pause(phydev); |
---|
1083 | 1070 | |
---|
1084 | 1071 | /* Display what we found */ |
---|
1085 | 1072 | phy_attached_info(phydev); |
---|
.. | .. |
---|
1162 | 1149 | struct ethtool_drvinfo *info) |
---|
1163 | 1150 | { |
---|
1164 | 1151 | strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); |
---|
1165 | | - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); |
---|
1166 | 1152 | strlcpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info)); |
---|
1167 | 1153 | } |
---|
1168 | 1154 | |
---|
.. | .. |
---|
1219 | 1205 | priv->tx_pause = pause->tx_pause; |
---|
1220 | 1206 | priv->rx_pause = pause->rx_pause; |
---|
1221 | 1207 | |
---|
1222 | | - if (phydev) { |
---|
1223 | | - phydev->advertising &= ~ADVERTISED_Pause; |
---|
1224 | | - phydev->advertising &= ~ADVERTISED_Asym_Pause; |
---|
| 1208 | + if (phydev) |
---|
| 1209 | + phy_set_asym_pause(phydev, pause->rx_pause, pause->tx_pause); |
---|
1225 | 1210 | |
---|
1226 | | - if (pause->rx_pause) { |
---|
1227 | | - phydev->advertising |= ADVERTISED_Pause; |
---|
1228 | | - phydev->advertising |= ADVERTISED_Asym_Pause; |
---|
1229 | | - } |
---|
1230 | | - |
---|
1231 | | - if (pause->tx_pause) |
---|
1232 | | - phydev->advertising ^= ADVERTISED_Asym_Pause; |
---|
1233 | | - } |
---|
1234 | 1211 | if (netif_running(netdev)) { |
---|
1235 | | - if (phydev && priv->aneg_pause) |
---|
1236 | | - phy_start_aneg(phydev); |
---|
1237 | | - else |
---|
| 1212 | + if (!(phydev && priv->aneg_pause)) |
---|
1238 | 1213 | ftgmac100_config_pause(priv); |
---|
1239 | 1214 | } |
---|
1240 | 1215 | |
---|
.. | .. |
---|
1560 | 1535 | return 0; |
---|
1561 | 1536 | } |
---|
1562 | 1537 | |
---|
1563 | | -/* optional */ |
---|
1564 | | -static int ftgmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) |
---|
1565 | | -{ |
---|
1566 | | - if (!netdev->phydev) |
---|
1567 | | - return -ENXIO; |
---|
1568 | | - |
---|
1569 | | - return phy_mii_ioctl(netdev->phydev, ifr, cmd); |
---|
1570 | | -} |
---|
1571 | | - |
---|
1572 | | -static void ftgmac100_tx_timeout(struct net_device *netdev) |
---|
| 1538 | +static void ftgmac100_tx_timeout(struct net_device *netdev, unsigned int txqueue) |
---|
1573 | 1539 | { |
---|
1574 | 1540 | struct ftgmac100 *priv = netdev_priv(netdev); |
---|
1575 | 1541 | |
---|
.. | .. |
---|
1621 | 1587 | .ndo_start_xmit = ftgmac100_hard_start_xmit, |
---|
1622 | 1588 | .ndo_set_mac_address = ftgmac100_set_mac_addr, |
---|
1623 | 1589 | .ndo_validate_addr = eth_validate_addr, |
---|
1624 | | - .ndo_do_ioctl = ftgmac100_do_ioctl, |
---|
| 1590 | + .ndo_do_ioctl = phy_do_ioctl, |
---|
1625 | 1591 | .ndo_tx_timeout = ftgmac100_tx_timeout, |
---|
1626 | 1592 | .ndo_set_rx_mode = ftgmac100_set_rx_mode, |
---|
1627 | 1593 | .ndo_set_features = ftgmac100_set_features, |
---|
.. | .. |
---|
1636 | 1602 | { |
---|
1637 | 1603 | struct ftgmac100 *priv = netdev_priv(netdev); |
---|
1638 | 1604 | struct platform_device *pdev = to_platform_device(priv->dev); |
---|
1639 | | - int phy_intf = PHY_INTERFACE_MODE_RGMII; |
---|
| 1605 | + phy_interface_t phy_intf = PHY_INTERFACE_MODE_RGMII; |
---|
1640 | 1606 | struct device_node *np = pdev->dev.of_node; |
---|
1641 | 1607 | int i, err = 0; |
---|
1642 | 1608 | u32 reg; |
---|
.. | .. |
---|
1646 | 1612 | if (!priv->mii_bus) |
---|
1647 | 1613 | return -EIO; |
---|
1648 | 1614 | |
---|
1649 | | - if (priv->is_aspeed) { |
---|
1650 | | - /* This driver supports the old MDIO interface */ |
---|
| 1615 | + if (of_device_is_compatible(np, "aspeed,ast2400-mac") || |
---|
| 1616 | + of_device_is_compatible(np, "aspeed,ast2500-mac")) { |
---|
| 1617 | + /* The AST2600 has a separate MDIO controller */ |
---|
| 1618 | + |
---|
| 1619 | + /* For the AST2400 and AST2500 this driver only supports the |
---|
| 1620 | + * old MDIO interface |
---|
| 1621 | + */ |
---|
1651 | 1622 | reg = ioread32(priv->base + FTGMAC100_OFFSET_REVR); |
---|
1652 | 1623 | reg &= ~FTGMAC100_REVR_NEW_MDIO_INTERFACE; |
---|
1653 | 1624 | iowrite32(reg, priv->base + FTGMAC100_OFFSET_REVR); |
---|
1654 | | - }; |
---|
| 1625 | + } |
---|
1655 | 1626 | |
---|
1656 | 1627 | /* Get PHY mode from device-tree */ |
---|
1657 | 1628 | if (np) { |
---|
1658 | 1629 | /* Default to RGMII. It's a gigabit part after all */ |
---|
1659 | | - phy_intf = of_get_phy_mode(np); |
---|
1660 | | - if (phy_intf < 0) |
---|
| 1630 | + err = of_get_phy_mode(np, &phy_intf); |
---|
| 1631 | + if (err) |
---|
1661 | 1632 | phy_intf = PHY_INTERFACE_MODE_RGMII; |
---|
1662 | 1633 | |
---|
1663 | 1634 | /* Aspeed only supports these. I don't know about other IP |
---|
.. | .. |
---|
1739 | 1710 | nd->link_up ? "up" : "down"); |
---|
1740 | 1711 | } |
---|
1741 | 1712 | |
---|
1742 | | -static void ftgmac100_setup_clk(struct ftgmac100 *priv) |
---|
| 1713 | +static int ftgmac100_setup_clk(struct ftgmac100 *priv) |
---|
1743 | 1714 | { |
---|
1744 | | - priv->clk = devm_clk_get(priv->dev, NULL); |
---|
1745 | | - if (IS_ERR(priv->clk)) |
---|
1746 | | - return; |
---|
| 1715 | + struct clk *clk; |
---|
| 1716 | + int rc; |
---|
1747 | 1717 | |
---|
1748 | | - clk_prepare_enable(priv->clk); |
---|
| 1718 | + clk = devm_clk_get(priv->dev, NULL /* MACCLK */); |
---|
| 1719 | + if (IS_ERR(clk)) |
---|
| 1720 | + return PTR_ERR(clk); |
---|
| 1721 | + priv->clk = clk; |
---|
| 1722 | + rc = clk_prepare_enable(priv->clk); |
---|
| 1723 | + if (rc) |
---|
| 1724 | + return rc; |
---|
1749 | 1725 | |
---|
1750 | 1726 | /* Aspeed specifies a 100MHz clock is required for up to |
---|
1751 | 1727 | * 1000Mbit link speeds. As NCSI is limited to 100Mbit, 25MHz |
---|
1752 | 1728 | * is sufficient |
---|
1753 | 1729 | */ |
---|
1754 | | - clk_set_rate(priv->clk, priv->use_ncsi ? FTGMAC_25MHZ : |
---|
1755 | | - FTGMAC_100MHZ); |
---|
| 1730 | + rc = clk_set_rate(priv->clk, priv->use_ncsi ? FTGMAC_25MHZ : |
---|
| 1731 | + FTGMAC_100MHZ); |
---|
| 1732 | + if (rc) |
---|
| 1733 | + goto cleanup_clk; |
---|
| 1734 | + |
---|
| 1735 | + /* RCLK is for RMII, typically used for NCSI. Optional because it's not |
---|
| 1736 | + * necessary if it's the AST2400 MAC, or the MAC is configured for |
---|
| 1737 | + * RGMII, or the controller is not an ASPEED-based controller. |
---|
| 1738 | + */ |
---|
| 1739 | + priv->rclk = devm_clk_get_optional(priv->dev, "RCLK"); |
---|
| 1740 | + rc = clk_prepare_enable(priv->rclk); |
---|
| 1741 | + if (!rc) |
---|
| 1742 | + return 0; |
---|
| 1743 | + |
---|
| 1744 | +cleanup_clk: |
---|
| 1745 | + clk_disable_unprepare(priv->clk); |
---|
| 1746 | + |
---|
| 1747 | + return rc; |
---|
| 1748 | +} |
---|
| 1749 | + |
---|
| 1750 | +static bool ftgmac100_has_child_node(struct device_node *np, const char *name) |
---|
| 1751 | +{ |
---|
| 1752 | + struct device_node *child_np = of_get_child_by_name(np, name); |
---|
| 1753 | + bool ret = false; |
---|
| 1754 | + |
---|
| 1755 | + if (child_np) { |
---|
| 1756 | + ret = true; |
---|
| 1757 | + of_node_put(child_np); |
---|
| 1758 | + } |
---|
| 1759 | + |
---|
| 1760 | + return ret; |
---|
1756 | 1761 | } |
---|
1757 | 1762 | |
---|
1758 | 1763 | static int ftgmac100_probe(struct platform_device *pdev) |
---|
.. | .. |
---|
1763 | 1768 | struct ftgmac100 *priv; |
---|
1764 | 1769 | struct device_node *np; |
---|
1765 | 1770 | int err = 0; |
---|
1766 | | - |
---|
1767 | | - if (!pdev) |
---|
1768 | | - return -ENODEV; |
---|
1769 | 1771 | |
---|
1770 | 1772 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
1771 | 1773 | if (!res) |
---|
.. | .. |
---|
1824 | 1826 | |
---|
1825 | 1827 | np = pdev->dev.of_node; |
---|
1826 | 1828 | if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac") || |
---|
1827 | | - of_device_is_compatible(np, "aspeed,ast2500-mac"))) { |
---|
| 1829 | + of_device_is_compatible(np, "aspeed,ast2500-mac") || |
---|
| 1830 | + of_device_is_compatible(np, "aspeed,ast2600-mac"))) { |
---|
1828 | 1831 | priv->rxdes0_edorr_mask = BIT(30); |
---|
1829 | 1832 | priv->txdes0_edotr_mask = BIT(30); |
---|
1830 | 1833 | priv->is_aspeed = true; |
---|
| 1834 | + /* Disable ast2600 problematic HW arbitration */ |
---|
| 1835 | + if (of_device_is_compatible(np, "aspeed,ast2600-mac")) { |
---|
| 1836 | + iowrite32(FTGMAC100_TM_DEFAULT, |
---|
| 1837 | + priv->base + FTGMAC100_OFFSET_TM); |
---|
| 1838 | + } |
---|
1831 | 1839 | } else { |
---|
1832 | 1840 | priv->rxdes0_edorr_mask = BIT(15); |
---|
1833 | 1841 | priv->txdes0_edotr_mask = BIT(15); |
---|
.. | .. |
---|
1836 | 1844 | if (np && of_get_property(np, "use-ncsi", NULL)) { |
---|
1837 | 1845 | if (!IS_ENABLED(CONFIG_NET_NCSI)) { |
---|
1838 | 1846 | dev_err(&pdev->dev, "NCSI stack not enabled\n"); |
---|
| 1847 | + err = -EINVAL; |
---|
1839 | 1848 | goto err_ncsi_dev; |
---|
1840 | 1849 | } |
---|
1841 | 1850 | |
---|
1842 | 1851 | dev_info(&pdev->dev, "Using NCSI interface\n"); |
---|
1843 | 1852 | priv->use_ncsi = true; |
---|
1844 | 1853 | priv->ndev = ncsi_register_dev(netdev, ftgmac100_ncsi_handler); |
---|
1845 | | - if (!priv->ndev) |
---|
| 1854 | + if (!priv->ndev) { |
---|
| 1855 | + err = -EINVAL; |
---|
1846 | 1856 | goto err_ncsi_dev; |
---|
1847 | | - } else { |
---|
| 1857 | + } |
---|
| 1858 | + } else if (np && of_get_property(np, "phy-handle", NULL)) { |
---|
| 1859 | + struct phy_device *phy; |
---|
| 1860 | + |
---|
| 1861 | + phy = of_phy_get_and_connect(priv->netdev, np, |
---|
| 1862 | + &ftgmac100_adjust_link); |
---|
| 1863 | + if (!phy) { |
---|
| 1864 | + dev_err(&pdev->dev, "Failed to connect to phy\n"); |
---|
| 1865 | + err = -EINVAL; |
---|
| 1866 | + goto err_setup_mdio; |
---|
| 1867 | + } |
---|
| 1868 | + |
---|
| 1869 | + /* Indicate that we support PAUSE frames (see comment in |
---|
| 1870 | + * Documentation/networking/phy.rst) |
---|
| 1871 | + */ |
---|
| 1872 | + phy_support_asym_pause(phy); |
---|
| 1873 | + |
---|
| 1874 | + /* Display what we found */ |
---|
| 1875 | + phy_attached_info(phy); |
---|
| 1876 | + } else if (np && !ftgmac100_has_child_node(np, "mdio")) { |
---|
| 1877 | + /* Support legacy ASPEED devicetree descriptions that decribe a |
---|
| 1878 | + * MAC with an embedded MDIO controller but have no "mdio" |
---|
| 1879 | + * child node. Automatically scan the MDIO bus for available |
---|
| 1880 | + * PHYs. |
---|
| 1881 | + */ |
---|
1848 | 1882 | priv->use_ncsi = false; |
---|
1849 | 1883 | err = ftgmac100_setup_mdio(netdev); |
---|
1850 | 1884 | if (err) |
---|
1851 | 1885 | goto err_setup_mdio; |
---|
1852 | 1886 | } |
---|
1853 | 1887 | |
---|
1854 | | - if (priv->is_aspeed) |
---|
1855 | | - ftgmac100_setup_clk(priv); |
---|
| 1888 | + if (priv->is_aspeed) { |
---|
| 1889 | + err = ftgmac100_setup_clk(priv); |
---|
| 1890 | + if (err) |
---|
| 1891 | + goto err_ncsi_dev; |
---|
| 1892 | + } |
---|
1856 | 1893 | |
---|
1857 | 1894 | /* Default ring sizes */ |
---|
1858 | 1895 | priv->rx_q_entries = priv->new_rx_q_entries = DEF_RX_QUEUE_ENTRIES; |
---|
.. | .. |
---|
1869 | 1906 | /* AST2400 doesn't have working HW checksum generation */ |
---|
1870 | 1907 | if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac"))) |
---|
1871 | 1908 | netdev->hw_features &= ~NETIF_F_HW_CSUM; |
---|
| 1909 | + |
---|
| 1910 | + /* AST2600 tx checksum with NCSI is broken */ |
---|
| 1911 | + if (priv->use_ncsi && of_device_is_compatible(np, "aspeed,ast2600-mac")) |
---|
| 1912 | + netdev->hw_features &= ~NETIF_F_HW_CSUM; |
---|
| 1913 | + |
---|
1872 | 1914 | if (np && of_get_property(np, "no-hw-checksum", NULL)) |
---|
1873 | 1915 | netdev->hw_features &= ~(NETIF_F_HW_CSUM | NETIF_F_RXCSUM); |
---|
1874 | 1916 | netdev->features |= netdev->hw_features; |
---|
.. | .. |
---|
1884 | 1926 | |
---|
1885 | 1927 | return 0; |
---|
1886 | 1928 | |
---|
| 1929 | +err_register_netdev: |
---|
| 1930 | + clk_disable_unprepare(priv->rclk); |
---|
| 1931 | + clk_disable_unprepare(priv->clk); |
---|
1887 | 1932 | err_ncsi_dev: |
---|
1888 | 1933 | if (priv->ndev) |
---|
1889 | 1934 | ncsi_unregister_dev(priv->ndev); |
---|
1890 | | -err_register_netdev: |
---|
1891 | 1935 | ftgmac100_destroy_mdio(netdev); |
---|
1892 | 1936 | err_setup_mdio: |
---|
1893 | 1937 | iounmap(priv->base); |
---|
.. | .. |
---|
1911 | 1955 | ncsi_unregister_dev(priv->ndev); |
---|
1912 | 1956 | unregister_netdev(netdev); |
---|
1913 | 1957 | |
---|
| 1958 | + clk_disable_unprepare(priv->rclk); |
---|
1914 | 1959 | clk_disable_unprepare(priv->clk); |
---|
1915 | 1960 | |
---|
1916 | 1961 | /* There's a small chance the reset task will have been re-queued, |
---|