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 u64 ext; 1006c3324a9SVince Bridgers 101*89830580SVince Bridgers buf[0] = csrrd32(priv->mac_dev, 102*89830580SVince Bridgers tse_csroffs(frames_transmitted_ok)); 103*89830580SVince Bridgers buf[1] = csrrd32(priv->mac_dev, 104*89830580SVince Bridgers tse_csroffs(frames_received_ok)); 105*89830580SVince Bridgers buf[2] = csrrd32(priv->mac_dev, 106*89830580SVince Bridgers tse_csroffs(frames_check_sequence_errors)); 107*89830580SVince Bridgers buf[3] = csrrd32(priv->mac_dev, 108*89830580SVince Bridgers tse_csroffs(alignment_errors)); 1096c3324a9SVince Bridgers 1106c3324a9SVince Bridgers /* Extended aOctetsTransmittedOK counter */ 111*89830580SVince Bridgers ext = (u64) csrrd32(priv->mac_dev, 112*89830580SVince Bridgers tse_csroffs(msb_octets_transmitted_ok)) << 32; 113*89830580SVince Bridgers 114*89830580SVince Bridgers ext |= csrrd32(priv->mac_dev, 115*89830580SVince Bridgers tse_csroffs(octets_transmitted_ok)); 1166c3324a9SVince Bridgers buf[4] = ext; 1176c3324a9SVince Bridgers 1186c3324a9SVince Bridgers /* Extended aOctetsReceivedOK counter */ 119*89830580SVince Bridgers ext = (u64) csrrd32(priv->mac_dev, 120*89830580SVince Bridgers tse_csroffs(msb_octets_received_ok)) << 32; 121*89830580SVince Bridgers 122*89830580SVince Bridgers ext |= csrrd32(priv->mac_dev, 123*89830580SVince Bridgers tse_csroffs(octets_received_ok)); 1246c3324a9SVince Bridgers buf[5] = ext; 1256c3324a9SVince Bridgers 126*89830580SVince Bridgers buf[6] = csrrd32(priv->mac_dev, 127*89830580SVince Bridgers tse_csroffs(tx_pause_mac_ctrl_frames)); 128*89830580SVince Bridgers buf[7] = csrrd32(priv->mac_dev, 129*89830580SVince Bridgers tse_csroffs(rx_pause_mac_ctrl_frames)); 130*89830580SVince Bridgers buf[8] = csrrd32(priv->mac_dev, 131*89830580SVince Bridgers tse_csroffs(if_in_errors)); 132*89830580SVince Bridgers buf[9] = csrrd32(priv->mac_dev, 133*89830580SVince Bridgers tse_csroffs(if_out_errors)); 134*89830580SVince Bridgers buf[10] = csrrd32(priv->mac_dev, 135*89830580SVince Bridgers tse_csroffs(if_in_ucast_pkts)); 136*89830580SVince Bridgers buf[11] = csrrd32(priv->mac_dev, 137*89830580SVince Bridgers tse_csroffs(if_in_multicast_pkts)); 138*89830580SVince Bridgers buf[12] = csrrd32(priv->mac_dev, 139*89830580SVince Bridgers tse_csroffs(if_in_broadcast_pkts)); 140*89830580SVince Bridgers buf[13] = csrrd32(priv->mac_dev, 141*89830580SVince Bridgers tse_csroffs(if_out_discards)); 142*89830580SVince Bridgers buf[14] = csrrd32(priv->mac_dev, 143*89830580SVince Bridgers tse_csroffs(if_out_ucast_pkts)); 144*89830580SVince Bridgers buf[15] = csrrd32(priv->mac_dev, 145*89830580SVince Bridgers tse_csroffs(if_out_multicast_pkts)); 146*89830580SVince Bridgers buf[16] = csrrd32(priv->mac_dev, 147*89830580SVince Bridgers tse_csroffs(if_out_broadcast_pkts)); 148*89830580SVince Bridgers buf[17] = csrrd32(priv->mac_dev, 149*89830580SVince Bridgers tse_csroffs(ether_stats_drop_events)); 1506c3324a9SVince Bridgers 1516c3324a9SVince Bridgers /* Extended etherStatsOctets counter */ 152*89830580SVince Bridgers ext = (u64) csrrd32(priv->mac_dev, 153*89830580SVince Bridgers tse_csroffs(msb_ether_stats_octets)) << 32; 154*89830580SVince Bridgers ext |= csrrd32(priv->mac_dev, 155*89830580SVince Bridgers tse_csroffs(ether_stats_octets)); 1566c3324a9SVince Bridgers buf[18] = ext; 1576c3324a9SVince Bridgers 158*89830580SVince Bridgers buf[19] = csrrd32(priv->mac_dev, 159*89830580SVince Bridgers tse_csroffs(ether_stats_pkts)); 160*89830580SVince Bridgers buf[20] = csrrd32(priv->mac_dev, 161*89830580SVince Bridgers tse_csroffs(ether_stats_undersize_pkts)); 162*89830580SVince Bridgers buf[21] = csrrd32(priv->mac_dev, 163*89830580SVince Bridgers tse_csroffs(ether_stats_oversize_pkts)); 164*89830580SVince Bridgers buf[22] = csrrd32(priv->mac_dev, 165*89830580SVince Bridgers tse_csroffs(ether_stats_pkts_64_octets)); 166*89830580SVince Bridgers buf[23] = csrrd32(priv->mac_dev, 167*89830580SVince Bridgers tse_csroffs(ether_stats_pkts_65to127_octets)); 168*89830580SVince Bridgers buf[24] = csrrd32(priv->mac_dev, 169*89830580SVince Bridgers tse_csroffs(ether_stats_pkts_128to255_octets)); 170*89830580SVince Bridgers buf[25] = csrrd32(priv->mac_dev, 171*89830580SVince Bridgers tse_csroffs(ether_stats_pkts_256to511_octets)); 172*89830580SVince Bridgers buf[26] = csrrd32(priv->mac_dev, 173*89830580SVince Bridgers tse_csroffs(ether_stats_pkts_512to1023_octets)); 174*89830580SVince Bridgers buf[27] = csrrd32(priv->mac_dev, 175*89830580SVince Bridgers tse_csroffs(ether_stats_pkts_1024to1518_octets)); 176*89830580SVince Bridgers buf[28] = csrrd32(priv->mac_dev, 177*89830580SVince Bridgers tse_csroffs(ether_stats_pkts_1519tox_octets)); 178*89830580SVince Bridgers buf[29] = csrrd32(priv->mac_dev, 179*89830580SVince Bridgers tse_csroffs(ether_stats_jabbers)); 180*89830580SVince Bridgers buf[30] = csrrd32(priv->mac_dev, 181*89830580SVince Bridgers tse_csroffs(ether_stats_fragments)); 1826c3324a9SVince Bridgers } 1836c3324a9SVince Bridgers 1846c3324a9SVince Bridgers static int tse_sset_count(struct net_device *dev, int sset) 1856c3324a9SVince Bridgers { 1866c3324a9SVince Bridgers switch (sset) { 1876c3324a9SVince Bridgers case ETH_SS_STATS: 1886c3324a9SVince Bridgers return TSE_STATS_LEN; 1896c3324a9SVince Bridgers default: 1906c3324a9SVince Bridgers return -EOPNOTSUPP; 1916c3324a9SVince Bridgers } 1926c3324a9SVince Bridgers } 1936c3324a9SVince Bridgers 1946c3324a9SVince Bridgers static u32 tse_get_msglevel(struct net_device *dev) 1956c3324a9SVince Bridgers { 1966c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 1976c3324a9SVince Bridgers return priv->msg_enable; 1986c3324a9SVince Bridgers } 1996c3324a9SVince Bridgers 2006c3324a9SVince Bridgers static void tse_set_msglevel(struct net_device *dev, uint32_t data) 2016c3324a9SVince Bridgers { 2026c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 2036c3324a9SVince Bridgers priv->msg_enable = data; 2046c3324a9SVince Bridgers } 2056c3324a9SVince Bridgers 2066c3324a9SVince Bridgers static int tse_reglen(struct net_device *dev) 2076c3324a9SVince Bridgers { 2086c3324a9SVince Bridgers return TSE_NUM_REGS * sizeof(u32); 2096c3324a9SVince Bridgers } 2106c3324a9SVince Bridgers 2116c3324a9SVince Bridgers static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs, 2126c3324a9SVince Bridgers void *regbuf) 2136c3324a9SVince Bridgers { 2146c3324a9SVince Bridgers int i; 2156c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 2166c3324a9SVince Bridgers u32 *buf = regbuf; 2176c3324a9SVince Bridgers 2188adfc3aeSVince Bridgers /* Set version to a known value, so ethtool knows 2198adfc3aeSVince Bridgers * how to do any special formatting of this data. 2208adfc3aeSVince Bridgers * This version number will need to change if and 2218adfc3aeSVince Bridgers * when this register table is changed. 22299514e11SVince Bridgers * 22399514e11SVince Bridgers * version[31:0] = 1: Dump the first 128 TSE Registers 22499514e11SVince Bridgers * Upper bits are all 0 by default 22599514e11SVince Bridgers * 22699514e11SVince Bridgers * Upper 16-bits will indicate feature presence for 22799514e11SVince Bridgers * Ethtool register decoding in future version. 2288adfc3aeSVince Bridgers */ 2298adfc3aeSVince Bridgers 2308adfc3aeSVince Bridgers regs->version = 1; 2318adfc3aeSVince Bridgers 2326c3324a9SVince Bridgers for (i = 0; i < TSE_NUM_REGS; i++) 233*89830580SVince Bridgers buf[i] = csrrd32(priv->mac_dev, i * 4); 2346c3324a9SVince Bridgers } 2356c3324a9SVince Bridgers 2366c3324a9SVince Bridgers static int tse_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 2376c3324a9SVince Bridgers { 2386c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 2396c3324a9SVince Bridgers struct phy_device *phydev = priv->phydev; 2406c3324a9SVince Bridgers 2416c3324a9SVince Bridgers if (phydev == NULL) 2426c3324a9SVince Bridgers return -ENODEV; 2436c3324a9SVince Bridgers 2446c3324a9SVince Bridgers return phy_ethtool_gset(phydev, cmd); 2456c3324a9SVince Bridgers } 2466c3324a9SVince Bridgers 2476c3324a9SVince Bridgers static int tse_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 2486c3324a9SVince Bridgers { 2496c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 2506c3324a9SVince Bridgers struct phy_device *phydev = priv->phydev; 2516c3324a9SVince Bridgers 2526c3324a9SVince Bridgers if (phydev == NULL) 2536c3324a9SVince Bridgers return -ENODEV; 2546c3324a9SVince Bridgers 2556c3324a9SVince Bridgers return phy_ethtool_sset(phydev, cmd); 2566c3324a9SVince Bridgers } 2576c3324a9SVince Bridgers 2586c3324a9SVince Bridgers static const struct ethtool_ops tse_ethtool_ops = { 2596c3324a9SVince Bridgers .get_drvinfo = tse_get_drvinfo, 2606c3324a9SVince Bridgers .get_regs_len = tse_reglen, 2616c3324a9SVince Bridgers .get_regs = tse_get_regs, 2626c3324a9SVince Bridgers .get_link = ethtool_op_get_link, 2636c3324a9SVince Bridgers .get_settings = tse_get_settings, 2646c3324a9SVince Bridgers .set_settings = tse_set_settings, 2656c3324a9SVince Bridgers .get_strings = tse_gstrings, 2666c3324a9SVince Bridgers .get_sset_count = tse_sset_count, 2676c3324a9SVince Bridgers .get_ethtool_stats = tse_fill_stats, 2686c3324a9SVince Bridgers .get_msglevel = tse_get_msglevel, 2696c3324a9SVince Bridgers .set_msglevel = tse_set_msglevel, 2706c3324a9SVince Bridgers }; 2716c3324a9SVince Bridgers 2726c3324a9SVince Bridgers void altera_tse_set_ethtool_ops(struct net_device *netdev) 2736c3324a9SVince Bridgers { 2746c3324a9SVince Bridgers SET_ETHTOOL_OPS(netdev, &tse_ethtool_ops); 2756c3324a9SVince Bridgers } 276