16c3324a9SVince Bridgers /* Ethtool support for Altera Triple-Speed Ethernet MAC driver 26c3324a9SVince Bridgers * Copyright (C) 2008-2014 Altera Corporation. All rights reserved 36c3324a9SVince Bridgers * 46c3324a9SVince Bridgers * Contributors: 56c3324a9SVince Bridgers * Dalon Westergreen 66c3324a9SVince Bridgers * Thomas Chou 76c3324a9SVince Bridgers * Ian Abbott 86c3324a9SVince Bridgers * Yuriy Kozlov 96c3324a9SVince Bridgers * Tobias Klauser 106c3324a9SVince Bridgers * Andriy Smolskyy 116c3324a9SVince Bridgers * Roman Bulgakov 126c3324a9SVince Bridgers * Dmytro Mytarchuk 136c3324a9SVince Bridgers * 146c3324a9SVince Bridgers * Original driver contributed by SLS. 156c3324a9SVince Bridgers * Major updates contributed by GlobalLogic 166c3324a9SVince Bridgers * 176c3324a9SVince Bridgers * This program is free software; you can redistribute it and/or modify it 186c3324a9SVince Bridgers * under the terms and conditions of the GNU General Public License, 196c3324a9SVince Bridgers * version 2, as published by the Free Software Foundation. 206c3324a9SVince Bridgers * 216c3324a9SVince Bridgers * This program is distributed in the hope it will be useful, but WITHOUT 226c3324a9SVince Bridgers * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 236c3324a9SVince Bridgers * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 246c3324a9SVince Bridgers * more details. 256c3324a9SVince Bridgers * 266c3324a9SVince Bridgers * You should have received a copy of the GNU General Public License along with 276c3324a9SVince Bridgers * this program. If not, see <http://www.gnu.org/licenses/>. 286c3324a9SVince Bridgers */ 296c3324a9SVince Bridgers 306c3324a9SVince Bridgers #include <linux/ethtool.h> 316c3324a9SVince Bridgers #include <linux/kernel.h> 326c3324a9SVince Bridgers #include <linux/netdevice.h> 336c3324a9SVince Bridgers #include <linux/phy.h> 346c3324a9SVince Bridgers 356c3324a9SVince Bridgers #include "altera_tse.h" 366c3324a9SVince Bridgers 376c3324a9SVince Bridgers #define TSE_STATS_LEN 31 386c3324a9SVince Bridgers #define TSE_NUM_REGS 128 396c3324a9SVince Bridgers 406c3324a9SVince Bridgers static char const stat_gstrings[][ETH_GSTRING_LEN] = { 416c3324a9SVince Bridgers "tx_packets", 426c3324a9SVince Bridgers "rx_packets", 436c3324a9SVince Bridgers "rx_crc_errors", 446c3324a9SVince Bridgers "rx_align_errors", 456c3324a9SVince Bridgers "tx_bytes", 466c3324a9SVince Bridgers "rx_bytes", 476c3324a9SVince Bridgers "tx_pause", 486c3324a9SVince Bridgers "rx_pause", 496c3324a9SVince Bridgers "rx_errors", 506c3324a9SVince Bridgers "tx_errors", 516c3324a9SVince Bridgers "rx_unicast", 526c3324a9SVince Bridgers "rx_multicast", 536c3324a9SVince Bridgers "rx_broadcast", 546c3324a9SVince Bridgers "tx_discards", 556c3324a9SVince Bridgers "tx_unicast", 566c3324a9SVince Bridgers "tx_multicast", 576c3324a9SVince Bridgers "tx_broadcast", 586c3324a9SVince Bridgers "ether_drops", 596c3324a9SVince Bridgers "rx_total_bytes", 606c3324a9SVince Bridgers "rx_total_packets", 616c3324a9SVince Bridgers "rx_undersize", 626c3324a9SVince Bridgers "rx_oversize", 636c3324a9SVince Bridgers "rx_64_bytes", 646c3324a9SVince Bridgers "rx_65_127_bytes", 656c3324a9SVince Bridgers "rx_128_255_bytes", 666c3324a9SVince Bridgers "rx_256_511_bytes", 676c3324a9SVince Bridgers "rx_512_1023_bytes", 686c3324a9SVince Bridgers "rx_1024_1518_bytes", 696c3324a9SVince Bridgers "rx_gte_1519_bytes", 706c3324a9SVince Bridgers "rx_jabbers", 716c3324a9SVince Bridgers "rx_runts", 726c3324a9SVince Bridgers }; 736c3324a9SVince Bridgers 746c3324a9SVince Bridgers static void tse_get_drvinfo(struct net_device *dev, 756c3324a9SVince Bridgers struct ethtool_drvinfo *info) 766c3324a9SVince Bridgers { 776c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 786c3324a9SVince Bridgers u32 rev = ioread32(&priv->mac_dev->megacore_revision); 796c3324a9SVince Bridgers 8099514e11SVince Bridgers strcpy(info->driver, "altera_tse"); 816c3324a9SVince Bridgers strcpy(info->version, "v8.0"); 826c3324a9SVince Bridgers snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d", 836c3324a9SVince Bridgers rev & 0xFFFF, (rev & 0xFFFF0000) >> 16); 846c3324a9SVince Bridgers sprintf(info->bus_info, "platform"); 856c3324a9SVince Bridgers } 866c3324a9SVince Bridgers 876c3324a9SVince Bridgers /* Fill in a buffer with the strings which correspond to the 886c3324a9SVince Bridgers * stats 896c3324a9SVince Bridgers */ 906c3324a9SVince Bridgers static void tse_gstrings(struct net_device *dev, u32 stringset, u8 *buf) 916c3324a9SVince Bridgers { 926c3324a9SVince Bridgers memcpy(buf, stat_gstrings, TSE_STATS_LEN * ETH_GSTRING_LEN); 936c3324a9SVince Bridgers } 946c3324a9SVince Bridgers 956c3324a9SVince Bridgers static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, 966c3324a9SVince Bridgers u64 *buf) 976c3324a9SVince Bridgers { 986c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 996c3324a9SVince Bridgers struct altera_tse_mac *mac = priv->mac_dev; 1006c3324a9SVince Bridgers u64 ext; 1016c3324a9SVince Bridgers 1026c3324a9SVince Bridgers buf[0] = ioread32(&mac->frames_transmitted_ok); 1036c3324a9SVince Bridgers buf[1] = ioread32(&mac->frames_received_ok); 1046c3324a9SVince Bridgers buf[2] = ioread32(&mac->frames_check_sequence_errors); 1056c3324a9SVince Bridgers buf[3] = ioread32(&mac->alignment_errors); 1066c3324a9SVince Bridgers 1076c3324a9SVince Bridgers /* Extended aOctetsTransmittedOK counter */ 1086c3324a9SVince Bridgers ext = (u64) ioread32(&mac->msb_octets_transmitted_ok) << 32; 1096c3324a9SVince Bridgers ext |= ioread32(&mac->octets_transmitted_ok); 1106c3324a9SVince Bridgers buf[4] = ext; 1116c3324a9SVince Bridgers 1126c3324a9SVince Bridgers /* Extended aOctetsReceivedOK counter */ 1136c3324a9SVince Bridgers ext = (u64) ioread32(&mac->msb_octets_received_ok) << 32; 1146c3324a9SVince Bridgers ext |= ioread32(&mac->octets_received_ok); 1156c3324a9SVince Bridgers buf[5] = ext; 1166c3324a9SVince Bridgers 1176c3324a9SVince Bridgers buf[6] = ioread32(&mac->tx_pause_mac_ctrl_frames); 1186c3324a9SVince Bridgers buf[7] = ioread32(&mac->rx_pause_mac_ctrl_frames); 1196c3324a9SVince Bridgers buf[8] = ioread32(&mac->if_in_errors); 1206c3324a9SVince Bridgers buf[9] = ioread32(&mac->if_out_errors); 1216c3324a9SVince Bridgers buf[10] = ioread32(&mac->if_in_ucast_pkts); 1226c3324a9SVince Bridgers buf[11] = ioread32(&mac->if_in_multicast_pkts); 1236c3324a9SVince Bridgers buf[12] = ioread32(&mac->if_in_broadcast_pkts); 1246c3324a9SVince Bridgers buf[13] = ioread32(&mac->if_out_discards); 1256c3324a9SVince Bridgers buf[14] = ioread32(&mac->if_out_ucast_pkts); 1266c3324a9SVince Bridgers buf[15] = ioread32(&mac->if_out_multicast_pkts); 1276c3324a9SVince Bridgers buf[16] = ioread32(&mac->if_out_broadcast_pkts); 1286c3324a9SVince Bridgers buf[17] = ioread32(&mac->ether_stats_drop_events); 1296c3324a9SVince Bridgers 1306c3324a9SVince Bridgers /* Extended etherStatsOctets counter */ 1316c3324a9SVince Bridgers ext = (u64) ioread32(&mac->msb_ether_stats_octets) << 32; 1326c3324a9SVince Bridgers ext |= ioread32(&mac->ether_stats_octets); 1336c3324a9SVince Bridgers buf[18] = ext; 1346c3324a9SVince Bridgers 1356c3324a9SVince Bridgers buf[19] = ioread32(&mac->ether_stats_pkts); 1366c3324a9SVince Bridgers buf[20] = ioread32(&mac->ether_stats_undersize_pkts); 1376c3324a9SVince Bridgers buf[21] = ioread32(&mac->ether_stats_oversize_pkts); 1386c3324a9SVince Bridgers buf[22] = ioread32(&mac->ether_stats_pkts_64_octets); 1396c3324a9SVince Bridgers buf[23] = ioread32(&mac->ether_stats_pkts_65to127_octets); 1406c3324a9SVince Bridgers buf[24] = ioread32(&mac->ether_stats_pkts_128to255_octets); 1416c3324a9SVince Bridgers buf[25] = ioread32(&mac->ether_stats_pkts_256to511_octets); 1426c3324a9SVince Bridgers buf[26] = ioread32(&mac->ether_stats_pkts_512to1023_octets); 1436c3324a9SVince Bridgers buf[27] = ioread32(&mac->ether_stats_pkts_1024to1518_octets); 1446c3324a9SVince Bridgers buf[28] = ioread32(&mac->ether_stats_pkts_1519tox_octets); 1456c3324a9SVince Bridgers buf[29] = ioread32(&mac->ether_stats_jabbers); 1466c3324a9SVince Bridgers buf[30] = ioread32(&mac->ether_stats_fragments); 1476c3324a9SVince Bridgers } 1486c3324a9SVince Bridgers 1496c3324a9SVince Bridgers static int tse_sset_count(struct net_device *dev, int sset) 1506c3324a9SVince Bridgers { 1516c3324a9SVince Bridgers switch (sset) { 1526c3324a9SVince Bridgers case ETH_SS_STATS: 1536c3324a9SVince Bridgers return TSE_STATS_LEN; 1546c3324a9SVince Bridgers default: 1556c3324a9SVince Bridgers return -EOPNOTSUPP; 1566c3324a9SVince Bridgers } 1576c3324a9SVince Bridgers } 1586c3324a9SVince Bridgers 1596c3324a9SVince Bridgers static u32 tse_get_msglevel(struct net_device *dev) 1606c3324a9SVince Bridgers { 1616c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 1626c3324a9SVince Bridgers return priv->msg_enable; 1636c3324a9SVince Bridgers } 1646c3324a9SVince Bridgers 1656c3324a9SVince Bridgers static void tse_set_msglevel(struct net_device *dev, uint32_t data) 1666c3324a9SVince Bridgers { 1676c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 1686c3324a9SVince Bridgers priv->msg_enable = data; 1696c3324a9SVince Bridgers } 1706c3324a9SVince Bridgers 1716c3324a9SVince Bridgers static int tse_reglen(struct net_device *dev) 1726c3324a9SVince Bridgers { 1736c3324a9SVince Bridgers return TSE_NUM_REGS * sizeof(u32); 1746c3324a9SVince Bridgers } 1756c3324a9SVince Bridgers 1766c3324a9SVince Bridgers static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs, 1776c3324a9SVince Bridgers void *regbuf) 1786c3324a9SVince Bridgers { 1796c3324a9SVince Bridgers int i; 1806c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 1816c3324a9SVince Bridgers u32 *tse_mac_regs = (u32 *)priv->mac_dev; 1826c3324a9SVince Bridgers u32 *buf = regbuf; 1836c3324a9SVince Bridgers 1848adfc3aeSVince Bridgers /* Set version to a known value, so ethtool knows 1858adfc3aeSVince Bridgers * how to do any special formatting of this data. 1868adfc3aeSVince Bridgers * This version number will need to change if and 1878adfc3aeSVince Bridgers * when this register table is changed. 18899514e11SVince Bridgers * 18999514e11SVince Bridgers * version[31:0] = 1: Dump the first 128 TSE Registers 19099514e11SVince Bridgers * Upper bits are all 0 by default 19199514e11SVince Bridgers * 19299514e11SVince Bridgers * Upper 16-bits will indicate feature presence for 19399514e11SVince Bridgers * Ethtool register decoding in future version. 1948adfc3aeSVince Bridgers */ 1958adfc3aeSVince Bridgers 1968adfc3aeSVince Bridgers regs->version = 1; 1978adfc3aeSVince Bridgers 1986c3324a9SVince Bridgers for (i = 0; i < TSE_NUM_REGS; i++) 1996c3324a9SVince Bridgers buf[i] = ioread32(&tse_mac_regs[i]); 2006c3324a9SVince Bridgers } 2016c3324a9SVince Bridgers 2026c3324a9SVince Bridgers static int tse_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 2036c3324a9SVince Bridgers { 2046c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 2056c3324a9SVince Bridgers struct phy_device *phydev = priv->phydev; 2066c3324a9SVince Bridgers 2076c3324a9SVince Bridgers if (phydev == NULL) 2086c3324a9SVince Bridgers return -ENODEV; 2096c3324a9SVince Bridgers 2106c3324a9SVince Bridgers return phy_ethtool_gset(phydev, cmd); 2116c3324a9SVince Bridgers } 2126c3324a9SVince Bridgers 2136c3324a9SVince Bridgers static int tse_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 2146c3324a9SVince Bridgers { 2156c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 2166c3324a9SVince Bridgers struct phy_device *phydev = priv->phydev; 2176c3324a9SVince Bridgers 2186c3324a9SVince Bridgers if (phydev == NULL) 2196c3324a9SVince Bridgers return -ENODEV; 2206c3324a9SVince Bridgers 2216c3324a9SVince Bridgers return phy_ethtool_sset(phydev, cmd); 2226c3324a9SVince Bridgers } 2236c3324a9SVince Bridgers 2246c3324a9SVince Bridgers static const struct ethtool_ops tse_ethtool_ops = { 2256c3324a9SVince Bridgers .get_drvinfo = tse_get_drvinfo, 2266c3324a9SVince Bridgers .get_regs_len = tse_reglen, 2276c3324a9SVince Bridgers .get_regs = tse_get_regs, 2286c3324a9SVince Bridgers .get_link = ethtool_op_get_link, 2296c3324a9SVince Bridgers .get_settings = tse_get_settings, 2306c3324a9SVince Bridgers .set_settings = tse_set_settings, 2316c3324a9SVince Bridgers .get_strings = tse_gstrings, 2326c3324a9SVince Bridgers .get_sset_count = tse_sset_count, 2336c3324a9SVince Bridgers .get_ethtool_stats = tse_fill_stats, 2346c3324a9SVince Bridgers .get_msglevel = tse_get_msglevel, 2356c3324a9SVince Bridgers .set_msglevel = tse_set_msglevel, 2366c3324a9SVince Bridgers }; 2376c3324a9SVince Bridgers 2386c3324a9SVince Bridgers void altera_tse_set_ethtool_ops(struct net_device *netdev) 2396c3324a9SVince Bridgers { 240*7ad24ea4SWilfried Klaebe netdev->ethtool_ops = &tse_ethtool_ops; 2416c3324a9SVince Bridgers } 242