162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Texas Instruments ICSSG Ethernet driver 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "icssg_prueth.h" 962306a36Sopenharmony_ci#include "icssg_stats.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistatic void emac_get_drvinfo(struct net_device *ndev, 1262306a36Sopenharmony_ci struct ethtool_drvinfo *info) 1362306a36Sopenharmony_ci{ 1462306a36Sopenharmony_ci struct prueth_emac *emac = netdev_priv(ndev); 1562306a36Sopenharmony_ci struct prueth *prueth = emac->prueth; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci strscpy(info->driver, dev_driver_string(prueth->dev), 1862306a36Sopenharmony_ci sizeof(info->driver)); 1962306a36Sopenharmony_ci strscpy(info->bus_info, dev_name(prueth->dev), sizeof(info->bus_info)); 2062306a36Sopenharmony_ci} 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic u32 emac_get_msglevel(struct net_device *ndev) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci struct prueth_emac *emac = netdev_priv(ndev); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci return emac->msg_enable; 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic void emac_set_msglevel(struct net_device *ndev, u32 value) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci struct prueth_emac *emac = netdev_priv(ndev); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci emac->msg_enable = value; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic int emac_get_link_ksettings(struct net_device *ndev, 3762306a36Sopenharmony_ci struct ethtool_link_ksettings *ecmd) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci return phy_ethtool_get_link_ksettings(ndev, ecmd); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic int emac_set_link_ksettings(struct net_device *ndev, 4362306a36Sopenharmony_ci const struct ethtool_link_ksettings *ecmd) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci return phy_ethtool_set_link_ksettings(ndev, ecmd); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic int emac_get_eee(struct net_device *ndev, struct ethtool_eee *edata) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci if (!ndev->phydev) 5162306a36Sopenharmony_ci return -EOPNOTSUPP; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci return phy_ethtool_get_eee(ndev->phydev, edata); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic int emac_set_eee(struct net_device *ndev, struct ethtool_eee *edata) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci if (!ndev->phydev) 5962306a36Sopenharmony_ci return -EOPNOTSUPP; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return phy_ethtool_set_eee(ndev->phydev, edata); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic int emac_nway_reset(struct net_device *ndev) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci return phy_ethtool_nway_reset(ndev); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic int emac_get_sset_count(struct net_device *ndev, int stringset) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci switch (stringset) { 7262306a36Sopenharmony_ci case ETH_SS_STATS: 7362306a36Sopenharmony_ci return ICSSG_NUM_ETHTOOL_STATS; 7462306a36Sopenharmony_ci default: 7562306a36Sopenharmony_ci return -EOPNOTSUPP; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic void emac_get_strings(struct net_device *ndev, u32 stringset, u8 *data) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci u8 *p = data; 8262306a36Sopenharmony_ci int i; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci switch (stringset) { 8562306a36Sopenharmony_ci case ETH_SS_STATS: 8662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { 8762306a36Sopenharmony_ci if (!icssg_all_stats[i].standard_stats) { 8862306a36Sopenharmony_ci memcpy(p, icssg_all_stats[i].name, 8962306a36Sopenharmony_ci ETH_GSTRING_LEN); 9062306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci break; 9462306a36Sopenharmony_ci default: 9562306a36Sopenharmony_ci break; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic void emac_get_ethtool_stats(struct net_device *ndev, 10062306a36Sopenharmony_ci struct ethtool_stats *stats, u64 *data) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci struct prueth_emac *emac = netdev_priv(ndev); 10362306a36Sopenharmony_ci int i; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci emac_update_hardware_stats(emac); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) 10862306a36Sopenharmony_ci if (!icssg_all_stats[i].standard_stats) 10962306a36Sopenharmony_ci *(data++) = emac->stats[i]; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic int emac_get_ts_info(struct net_device *ndev, 11362306a36Sopenharmony_ci struct ethtool_ts_info *info) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct prueth_emac *emac = netdev_priv(ndev); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci info->so_timestamping = 11862306a36Sopenharmony_ci SOF_TIMESTAMPING_TX_HARDWARE | 11962306a36Sopenharmony_ci SOF_TIMESTAMPING_TX_SOFTWARE | 12062306a36Sopenharmony_ci SOF_TIMESTAMPING_RX_HARDWARE | 12162306a36Sopenharmony_ci SOF_TIMESTAMPING_RX_SOFTWARE | 12262306a36Sopenharmony_ci SOF_TIMESTAMPING_SOFTWARE | 12362306a36Sopenharmony_ci SOF_TIMESTAMPING_RAW_HARDWARE; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci info->phc_index = icss_iep_get_ptp_clock_idx(emac->iep); 12662306a36Sopenharmony_ci info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); 12762306a36Sopenharmony_ci info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci return 0; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic int emac_set_channels(struct net_device *ndev, 13362306a36Sopenharmony_ci struct ethtool_channels *ch) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct prueth_emac *emac = netdev_priv(ndev); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* Check if interface is up. Can change the num queues when 13862306a36Sopenharmony_ci * the interface is down. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_ci if (netif_running(emac->ndev)) 14162306a36Sopenharmony_ci return -EBUSY; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci emac->tx_ch_num = ch->tx_count; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci return 0; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic void emac_get_channels(struct net_device *ndev, 14962306a36Sopenharmony_ci struct ethtool_channels *ch) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci struct prueth_emac *emac = netdev_priv(ndev); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci ch->max_rx = 1; 15462306a36Sopenharmony_ci ch->max_tx = PRUETH_MAX_TX_QUEUES; 15562306a36Sopenharmony_ci ch->rx_count = 1; 15662306a36Sopenharmony_ci ch->tx_count = emac->tx_ch_num; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic const struct ethtool_rmon_hist_range emac_rmon_ranges[] = { 16062306a36Sopenharmony_ci { 0, 64}, 16162306a36Sopenharmony_ci { 65, 128}, 16262306a36Sopenharmony_ci { 129, 256}, 16362306a36Sopenharmony_ci { 257, 512}, 16462306a36Sopenharmony_ci { 513, PRUETH_MAX_PKT_SIZE}, 16562306a36Sopenharmony_ci {} 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic void emac_get_rmon_stats(struct net_device *ndev, 16962306a36Sopenharmony_ci struct ethtool_rmon_stats *rmon_stats, 17062306a36Sopenharmony_ci const struct ethtool_rmon_hist_range **ranges) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct prueth_emac *emac = netdev_priv(ndev); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci *ranges = emac_rmon_ranges; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci rmon_stats->undersize_pkts = emac_get_stat_by_name(emac, "rx_bucket1_frames") - 17762306a36Sopenharmony_ci emac_get_stat_by_name(emac, "rx_64B_frames"); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci rmon_stats->hist[0] = emac_get_stat_by_name(emac, "rx_bucket1_frames"); 18062306a36Sopenharmony_ci rmon_stats->hist[1] = emac_get_stat_by_name(emac, "rx_bucket2_frames"); 18162306a36Sopenharmony_ci rmon_stats->hist[2] = emac_get_stat_by_name(emac, "rx_bucket3_frames"); 18262306a36Sopenharmony_ci rmon_stats->hist[3] = emac_get_stat_by_name(emac, "rx_bucket4_frames"); 18362306a36Sopenharmony_ci rmon_stats->hist[4] = emac_get_stat_by_name(emac, "rx_bucket5_frames"); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci rmon_stats->hist_tx[0] = emac_get_stat_by_name(emac, "tx_bucket1_frames"); 18662306a36Sopenharmony_ci rmon_stats->hist_tx[1] = emac_get_stat_by_name(emac, "tx_bucket2_frames"); 18762306a36Sopenharmony_ci rmon_stats->hist_tx[2] = emac_get_stat_by_name(emac, "tx_bucket3_frames"); 18862306a36Sopenharmony_ci rmon_stats->hist_tx[3] = emac_get_stat_by_name(emac, "tx_bucket4_frames"); 18962306a36Sopenharmony_ci rmon_stats->hist_tx[4] = emac_get_stat_by_name(emac, "tx_bucket5_frames"); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ciconst struct ethtool_ops icssg_ethtool_ops = { 19362306a36Sopenharmony_ci .get_drvinfo = emac_get_drvinfo, 19462306a36Sopenharmony_ci .get_msglevel = emac_get_msglevel, 19562306a36Sopenharmony_ci .set_msglevel = emac_set_msglevel, 19662306a36Sopenharmony_ci .get_sset_count = emac_get_sset_count, 19762306a36Sopenharmony_ci .get_ethtool_stats = emac_get_ethtool_stats, 19862306a36Sopenharmony_ci .get_strings = emac_get_strings, 19962306a36Sopenharmony_ci .get_ts_info = emac_get_ts_info, 20062306a36Sopenharmony_ci .get_channels = emac_get_channels, 20162306a36Sopenharmony_ci .set_channels = emac_set_channels, 20262306a36Sopenharmony_ci .get_link_ksettings = emac_get_link_ksettings, 20362306a36Sopenharmony_ci .set_link_ksettings = emac_set_link_ksettings, 20462306a36Sopenharmony_ci .get_link = ethtool_op_get_link, 20562306a36Sopenharmony_ci .get_eee = emac_get_eee, 20662306a36Sopenharmony_ci .set_eee = emac_set_eee, 20762306a36Sopenharmony_ci .nway_reset = emac_nway_reset, 20862306a36Sopenharmony_ci .get_rmon_stats = emac_get_rmon_stats, 20962306a36Sopenharmony_ci}; 210