19952f691SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 26c3324a9SVince Bridgers /* Ethtool support for Altera Triple-Speed Ethernet MAC driver 36c3324a9SVince Bridgers * Copyright (C) 2008-2014 Altera Corporation. All rights reserved 46c3324a9SVince Bridgers * 56c3324a9SVince Bridgers * Contributors: 66c3324a9SVince Bridgers * Dalon Westergreen 76c3324a9SVince Bridgers * Thomas Chou 86c3324a9SVince Bridgers * Ian Abbott 96c3324a9SVince Bridgers * Yuriy Kozlov 106c3324a9SVince Bridgers * Tobias Klauser 116c3324a9SVince Bridgers * Andriy Smolskyy 126c3324a9SVince Bridgers * Roman Bulgakov 136c3324a9SVince Bridgers * Dmytro Mytarchuk 146c3324a9SVince Bridgers * 156c3324a9SVince Bridgers * Original driver contributed by SLS. 166c3324a9SVince Bridgers * Major updates contributed by GlobalLogic 176c3324a9SVince Bridgers */ 186c3324a9SVince Bridgers 196c3324a9SVince Bridgers #include <linux/ethtool.h> 206c3324a9SVince Bridgers #include <linux/kernel.h> 216c3324a9SVince Bridgers #include <linux/netdevice.h> 226c3324a9SVince Bridgers #include <linux/phy.h> 236c3324a9SVince Bridgers 246c3324a9SVince Bridgers #include "altera_tse.h" 256c3324a9SVince Bridgers 266c3324a9SVince Bridgers #define TSE_STATS_LEN 31 276c3324a9SVince Bridgers #define TSE_NUM_REGS 128 286c3324a9SVince Bridgers 296c3324a9SVince Bridgers static char const stat_gstrings[][ETH_GSTRING_LEN] = { 306c3324a9SVince Bridgers "tx_packets", 316c3324a9SVince Bridgers "rx_packets", 326c3324a9SVince Bridgers "rx_crc_errors", 336c3324a9SVince Bridgers "rx_align_errors", 346c3324a9SVince Bridgers "tx_bytes", 356c3324a9SVince Bridgers "rx_bytes", 366c3324a9SVince Bridgers "tx_pause", 376c3324a9SVince Bridgers "rx_pause", 386c3324a9SVince Bridgers "rx_errors", 396c3324a9SVince Bridgers "tx_errors", 406c3324a9SVince Bridgers "rx_unicast", 416c3324a9SVince Bridgers "rx_multicast", 426c3324a9SVince Bridgers "rx_broadcast", 436c3324a9SVince Bridgers "tx_discards", 446c3324a9SVince Bridgers "tx_unicast", 456c3324a9SVince Bridgers "tx_multicast", 466c3324a9SVince Bridgers "tx_broadcast", 476c3324a9SVince Bridgers "ether_drops", 486c3324a9SVince Bridgers "rx_total_bytes", 496c3324a9SVince Bridgers "rx_total_packets", 506c3324a9SVince Bridgers "rx_undersize", 516c3324a9SVince Bridgers "rx_oversize", 526c3324a9SVince Bridgers "rx_64_bytes", 536c3324a9SVince Bridgers "rx_65_127_bytes", 546c3324a9SVince Bridgers "rx_128_255_bytes", 556c3324a9SVince Bridgers "rx_256_511_bytes", 566c3324a9SVince Bridgers "rx_512_1023_bytes", 576c3324a9SVince Bridgers "rx_1024_1518_bytes", 586c3324a9SVince Bridgers "rx_gte_1519_bytes", 596c3324a9SVince Bridgers "rx_jabbers", 606c3324a9SVince Bridgers "rx_runts", 616c3324a9SVince Bridgers }; 626c3324a9SVince Bridgers 636c3324a9SVince Bridgers static void tse_get_drvinfo(struct net_device *dev, 646c3324a9SVince Bridgers struct ethtool_drvinfo *info) 656c3324a9SVince Bridgers { 666c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 676c3324a9SVince Bridgers u32 rev = ioread32(&priv->mac_dev->megacore_revision); 686c3324a9SVince Bridgers 6999514e11SVince Bridgers strcpy(info->driver, "altera_tse"); 706c3324a9SVince Bridgers snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d", 716c3324a9SVince Bridgers rev & 0xFFFF, (rev & 0xFFFF0000) >> 16); 726c3324a9SVince Bridgers sprintf(info->bus_info, "platform"); 736c3324a9SVince Bridgers } 746c3324a9SVince Bridgers 756c3324a9SVince Bridgers /* Fill in a buffer with the strings which correspond to the 766c3324a9SVince Bridgers * stats 776c3324a9SVince Bridgers */ 786c3324a9SVince Bridgers static void tse_gstrings(struct net_device *dev, u32 stringset, u8 *buf) 796c3324a9SVince Bridgers { 806c3324a9SVince Bridgers memcpy(buf, stat_gstrings, TSE_STATS_LEN * ETH_GSTRING_LEN); 816c3324a9SVince Bridgers } 826c3324a9SVince Bridgers 836c3324a9SVince Bridgers static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, 846c3324a9SVince Bridgers u64 *buf) 856c3324a9SVince Bridgers { 866c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 876c3324a9SVince Bridgers u64 ext; 886c3324a9SVince Bridgers 8989830580SVince Bridgers buf[0] = csrrd32(priv->mac_dev, 9089830580SVince Bridgers tse_csroffs(frames_transmitted_ok)); 9189830580SVince Bridgers buf[1] = csrrd32(priv->mac_dev, 9289830580SVince Bridgers tse_csroffs(frames_received_ok)); 9389830580SVince Bridgers buf[2] = csrrd32(priv->mac_dev, 9489830580SVince Bridgers tse_csroffs(frames_check_sequence_errors)); 9589830580SVince Bridgers buf[3] = csrrd32(priv->mac_dev, 9689830580SVince Bridgers tse_csroffs(alignment_errors)); 976c3324a9SVince Bridgers 986c3324a9SVince Bridgers /* Extended aOctetsTransmittedOK counter */ 9989830580SVince Bridgers ext = (u64) csrrd32(priv->mac_dev, 10089830580SVince Bridgers tse_csroffs(msb_octets_transmitted_ok)) << 32; 10189830580SVince Bridgers 10289830580SVince Bridgers ext |= csrrd32(priv->mac_dev, 10389830580SVince Bridgers tse_csroffs(octets_transmitted_ok)); 1046c3324a9SVince Bridgers buf[4] = ext; 1056c3324a9SVince Bridgers 1066c3324a9SVince Bridgers /* Extended aOctetsReceivedOK counter */ 10789830580SVince Bridgers ext = (u64) csrrd32(priv->mac_dev, 10889830580SVince Bridgers tse_csroffs(msb_octets_received_ok)) << 32; 10989830580SVince Bridgers 11089830580SVince Bridgers ext |= csrrd32(priv->mac_dev, 11189830580SVince Bridgers tse_csroffs(octets_received_ok)); 1126c3324a9SVince Bridgers buf[5] = ext; 1136c3324a9SVince Bridgers 11489830580SVince Bridgers buf[6] = csrrd32(priv->mac_dev, 11589830580SVince Bridgers tse_csroffs(tx_pause_mac_ctrl_frames)); 11689830580SVince Bridgers buf[7] = csrrd32(priv->mac_dev, 11789830580SVince Bridgers tse_csroffs(rx_pause_mac_ctrl_frames)); 11889830580SVince Bridgers buf[8] = csrrd32(priv->mac_dev, 11989830580SVince Bridgers tse_csroffs(if_in_errors)); 12089830580SVince Bridgers buf[9] = csrrd32(priv->mac_dev, 12189830580SVince Bridgers tse_csroffs(if_out_errors)); 12289830580SVince Bridgers buf[10] = csrrd32(priv->mac_dev, 12389830580SVince Bridgers tse_csroffs(if_in_ucast_pkts)); 12489830580SVince Bridgers buf[11] = csrrd32(priv->mac_dev, 12589830580SVince Bridgers tse_csroffs(if_in_multicast_pkts)); 12689830580SVince Bridgers buf[12] = csrrd32(priv->mac_dev, 12789830580SVince Bridgers tse_csroffs(if_in_broadcast_pkts)); 12889830580SVince Bridgers buf[13] = csrrd32(priv->mac_dev, 12989830580SVince Bridgers tse_csroffs(if_out_discards)); 13089830580SVince Bridgers buf[14] = csrrd32(priv->mac_dev, 13189830580SVince Bridgers tse_csroffs(if_out_ucast_pkts)); 13289830580SVince Bridgers buf[15] = csrrd32(priv->mac_dev, 13389830580SVince Bridgers tse_csroffs(if_out_multicast_pkts)); 13489830580SVince Bridgers buf[16] = csrrd32(priv->mac_dev, 13589830580SVince Bridgers tse_csroffs(if_out_broadcast_pkts)); 13689830580SVince Bridgers buf[17] = csrrd32(priv->mac_dev, 13789830580SVince Bridgers tse_csroffs(ether_stats_drop_events)); 1386c3324a9SVince Bridgers 1396c3324a9SVince Bridgers /* Extended etherStatsOctets counter */ 14089830580SVince Bridgers ext = (u64) csrrd32(priv->mac_dev, 14189830580SVince Bridgers tse_csroffs(msb_ether_stats_octets)) << 32; 14289830580SVince Bridgers ext |= csrrd32(priv->mac_dev, 14389830580SVince Bridgers tse_csroffs(ether_stats_octets)); 1446c3324a9SVince Bridgers buf[18] = ext; 1456c3324a9SVince Bridgers 14689830580SVince Bridgers buf[19] = csrrd32(priv->mac_dev, 14789830580SVince Bridgers tse_csroffs(ether_stats_pkts)); 14889830580SVince Bridgers buf[20] = csrrd32(priv->mac_dev, 14989830580SVince Bridgers tse_csroffs(ether_stats_undersize_pkts)); 15089830580SVince Bridgers buf[21] = csrrd32(priv->mac_dev, 15189830580SVince Bridgers tse_csroffs(ether_stats_oversize_pkts)); 15289830580SVince Bridgers buf[22] = csrrd32(priv->mac_dev, 15389830580SVince Bridgers tse_csroffs(ether_stats_pkts_64_octets)); 15489830580SVince Bridgers buf[23] = csrrd32(priv->mac_dev, 15589830580SVince Bridgers tse_csroffs(ether_stats_pkts_65to127_octets)); 15689830580SVince Bridgers buf[24] = csrrd32(priv->mac_dev, 15789830580SVince Bridgers tse_csroffs(ether_stats_pkts_128to255_octets)); 15889830580SVince Bridgers buf[25] = csrrd32(priv->mac_dev, 15989830580SVince Bridgers tse_csroffs(ether_stats_pkts_256to511_octets)); 16089830580SVince Bridgers buf[26] = csrrd32(priv->mac_dev, 16189830580SVince Bridgers tse_csroffs(ether_stats_pkts_512to1023_octets)); 16289830580SVince Bridgers buf[27] = csrrd32(priv->mac_dev, 16389830580SVince Bridgers tse_csroffs(ether_stats_pkts_1024to1518_octets)); 16489830580SVince Bridgers buf[28] = csrrd32(priv->mac_dev, 16589830580SVince Bridgers tse_csroffs(ether_stats_pkts_1519tox_octets)); 16689830580SVince Bridgers buf[29] = csrrd32(priv->mac_dev, 16789830580SVince Bridgers tse_csroffs(ether_stats_jabbers)); 16889830580SVince Bridgers buf[30] = csrrd32(priv->mac_dev, 16989830580SVince Bridgers tse_csroffs(ether_stats_fragments)); 1706c3324a9SVince Bridgers } 1716c3324a9SVince Bridgers 1726c3324a9SVince Bridgers static int tse_sset_count(struct net_device *dev, int sset) 1736c3324a9SVince Bridgers { 1746c3324a9SVince Bridgers switch (sset) { 1756c3324a9SVince Bridgers case ETH_SS_STATS: 1766c3324a9SVince Bridgers return TSE_STATS_LEN; 1776c3324a9SVince Bridgers default: 1786c3324a9SVince Bridgers return -EOPNOTSUPP; 1796c3324a9SVince Bridgers } 1806c3324a9SVince Bridgers } 1816c3324a9SVince Bridgers 1826c3324a9SVince Bridgers static u32 tse_get_msglevel(struct net_device *dev) 1836c3324a9SVince Bridgers { 1846c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 1856c3324a9SVince Bridgers return priv->msg_enable; 1866c3324a9SVince Bridgers } 1876c3324a9SVince Bridgers 1886c3324a9SVince Bridgers static void tse_set_msglevel(struct net_device *dev, uint32_t data) 1896c3324a9SVince Bridgers { 1906c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 1916c3324a9SVince Bridgers priv->msg_enable = data; 1926c3324a9SVince Bridgers } 1936c3324a9SVince Bridgers 1946c3324a9SVince Bridgers static int tse_reglen(struct net_device *dev) 1956c3324a9SVince Bridgers { 1966c3324a9SVince Bridgers return TSE_NUM_REGS * sizeof(u32); 1976c3324a9SVince Bridgers } 1986c3324a9SVince Bridgers 1996c3324a9SVince Bridgers static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs, 2006c3324a9SVince Bridgers void *regbuf) 2016c3324a9SVince Bridgers { 2026c3324a9SVince Bridgers struct altera_tse_private *priv = netdev_priv(dev); 2036c3324a9SVince Bridgers u32 *buf = regbuf; 2045adb0ed0SMaxime Chevallier int i; 2056c3324a9SVince Bridgers 2068adfc3aeSVince Bridgers /* Set version to a known value, so ethtool knows 2078adfc3aeSVince Bridgers * how to do any special formatting of this data. 2088adfc3aeSVince Bridgers * This version number will need to change if and 2098adfc3aeSVince Bridgers * when this register table is changed. 21099514e11SVince Bridgers * 21199514e11SVince Bridgers * version[31:0] = 1: Dump the first 128 TSE Registers 21299514e11SVince Bridgers * Upper bits are all 0 by default 21399514e11SVince Bridgers * 21499514e11SVince Bridgers * Upper 16-bits will indicate feature presence for 21599514e11SVince Bridgers * Ethtool register decoding in future version. 2168adfc3aeSVince Bridgers */ 2178adfc3aeSVince Bridgers 2188adfc3aeSVince Bridgers regs->version = 1; 2198adfc3aeSVince Bridgers 2206c3324a9SVince Bridgers for (i = 0; i < TSE_NUM_REGS; i++) 22189830580SVince Bridgers buf[i] = csrrd32(priv->mac_dev, i * 4); 2226c3324a9SVince Bridgers } 2236c3324a9SVince Bridgers 224*fef29982SMaxime Chevallier static int tse_ethtool_set_link_ksettings(struct net_device *dev, 225*fef29982SMaxime Chevallier const struct ethtool_link_ksettings *cmd) 226*fef29982SMaxime Chevallier { 227*fef29982SMaxime Chevallier struct altera_tse_private *priv = netdev_priv(dev); 228*fef29982SMaxime Chevallier 229*fef29982SMaxime Chevallier return phylink_ethtool_ksettings_set(priv->phylink, cmd); 230*fef29982SMaxime Chevallier } 231*fef29982SMaxime Chevallier 232*fef29982SMaxime Chevallier static int tse_ethtool_get_link_ksettings(struct net_device *dev, 233*fef29982SMaxime Chevallier struct ethtool_link_ksettings *cmd) 234*fef29982SMaxime Chevallier { 235*fef29982SMaxime Chevallier struct altera_tse_private *priv = netdev_priv(dev); 236*fef29982SMaxime Chevallier 237*fef29982SMaxime Chevallier return phylink_ethtool_ksettings_get(priv->phylink, cmd); 238*fef29982SMaxime Chevallier } 239*fef29982SMaxime Chevallier 2406c3324a9SVince Bridgers static const struct ethtool_ops tse_ethtool_ops = { 2416c3324a9SVince Bridgers .get_drvinfo = tse_get_drvinfo, 2426c3324a9SVince Bridgers .get_regs_len = tse_reglen, 2436c3324a9SVince Bridgers .get_regs = tse_get_regs, 2446c3324a9SVince Bridgers .get_link = ethtool_op_get_link, 2456c3324a9SVince Bridgers .get_strings = tse_gstrings, 2466c3324a9SVince Bridgers .get_sset_count = tse_sset_count, 2476c3324a9SVince Bridgers .get_ethtool_stats = tse_fill_stats, 2486c3324a9SVince Bridgers .get_msglevel = tse_get_msglevel, 2496c3324a9SVince Bridgers .set_msglevel = tse_set_msglevel, 250*fef29982SMaxime Chevallier .get_link_ksettings = tse_ethtool_get_link_ksettings, 251*fef29982SMaxime Chevallier .set_link_ksettings = tse_ethtool_set_link_ksettings, 252fb8d784bSMaxime Chevallier .get_ts_info = ethtool_op_get_ts_info, 2536c3324a9SVince Bridgers }; 2546c3324a9SVince Bridgers 2556c3324a9SVince Bridgers void altera_tse_set_ethtool_ops(struct net_device *netdev) 2566c3324a9SVince Bridgers { 2577ad24ea4SWilfried Klaebe netdev->ethtool_ops = &tse_ethtool_ops; 2586c3324a9SVince Bridgers } 259