18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Applied Micro X-Gene SoC Ethernet v2 Driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2017, Applied Micro Circuits Corporation
68c2ecf20Sopenharmony_ci * Author(s): Iyappan Subramanian <isubramanian@apm.com>
78c2ecf20Sopenharmony_ci *	      Keyur Chudgar <kchudgar@apm.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include "main.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#define XGE_STAT(m)		{ #m, offsetof(struct xge_pdata, stats.m) }
138c2ecf20Sopenharmony_ci#define XGE_EXTD_STAT(m, n)					\
148c2ecf20Sopenharmony_ci	{							\
158c2ecf20Sopenharmony_ci		#m,						\
168c2ecf20Sopenharmony_ci		n,						\
178c2ecf20Sopenharmony_ci		0						\
188c2ecf20Sopenharmony_ci	}
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic const struct xge_gstrings_stats gstrings_stats[] = {
218c2ecf20Sopenharmony_ci	XGE_STAT(rx_packets),
228c2ecf20Sopenharmony_ci	XGE_STAT(tx_packets),
238c2ecf20Sopenharmony_ci	XGE_STAT(rx_bytes),
248c2ecf20Sopenharmony_ci	XGE_STAT(tx_bytes),
258c2ecf20Sopenharmony_ci	XGE_STAT(rx_errors)
268c2ecf20Sopenharmony_ci};
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic struct xge_gstrings_extd_stats gstrings_extd_stats[] = {
298c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64),
308c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127),
318c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255),
328c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511),
338c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K),
348c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX),
358c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV),
368c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_fcs_error_cntr, RFCS),
378c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA),
388c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA),
398c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF),
408c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF),
418c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_unk_opcode_cntr, RXUO),
428c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_align_err_cntr, RALN),
438c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_frame_len_err_cntr, RFLR),
448c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_code_err_cntr, RCDE),
458c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE),
468c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_undersize_pkt_cntr, RUND),
478c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR),
488c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_fragments_cntr, RFRG),
498c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_jabber_cntr, RJBR),
508c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP),
518c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA),
528c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA),
538c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF),
548c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_defer_pkt_cntr, TDFR),
558c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF),
568c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL),
578c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL),
588c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL),
598c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL),
608c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_total_col_cntr, TNCL),
618c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH),
628c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_drop_frame_cntr, TDRP),
638c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_jabber_frame_cntr, TJBR),
648c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_fcs_error_cntr, TFCS),
658c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF),
668c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_oversize_frame_cntr, TOVR),
678c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_undersize_frame_cntr, TUND),
688c2ecf20Sopenharmony_ci	XGE_EXTD_STAT(tx_fragments_cntr, TFRG)
698c2ecf20Sopenharmony_ci};
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci#define XGE_STATS_LEN		ARRAY_SIZE(gstrings_stats)
728c2ecf20Sopenharmony_ci#define XGE_EXTD_STATS_LEN	ARRAY_SIZE(gstrings_extd_stats)
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic void xge_mac_get_extd_stats(struct xge_pdata *pdata)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	u32 data;
778c2ecf20Sopenharmony_ci	int i;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	for (i = 0; i < XGE_EXTD_STATS_LEN; i++) {
808c2ecf20Sopenharmony_ci		data = xge_rd_csr(pdata, gstrings_extd_stats[i].addr);
818c2ecf20Sopenharmony_ci		gstrings_extd_stats[i].value += data;
828c2ecf20Sopenharmony_ci	}
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistatic void xge_get_drvinfo(struct net_device *ndev,
868c2ecf20Sopenharmony_ci			    struct ethtool_drvinfo *info)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	struct xge_pdata *pdata = netdev_priv(ndev);
898c2ecf20Sopenharmony_ci	struct platform_device *pdev = pdata->pdev;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	strcpy(info->driver, "xgene-enet-v2");
928c2ecf20Sopenharmony_ci	sprintf(info->bus_info, "%s", pdev->name);
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic void xge_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	u8 *p = data;
988c2ecf20Sopenharmony_ci	int i;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	if (stringset != ETH_SS_STATS)
1018c2ecf20Sopenharmony_ci		return;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	for (i = 0; i < XGE_STATS_LEN; i++) {
1048c2ecf20Sopenharmony_ci		memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
1058c2ecf20Sopenharmony_ci		p += ETH_GSTRING_LEN;
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	for (i = 0; i < XGE_EXTD_STATS_LEN; i++) {
1098c2ecf20Sopenharmony_ci		memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN);
1108c2ecf20Sopenharmony_ci		p += ETH_GSTRING_LEN;
1118c2ecf20Sopenharmony_ci	}
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistatic int xge_get_sset_count(struct net_device *ndev, int sset)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	if (sset != ETH_SS_STATS)
1178c2ecf20Sopenharmony_ci		return -EINVAL;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	return XGE_STATS_LEN + XGE_EXTD_STATS_LEN;
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic void xge_get_ethtool_stats(struct net_device *ndev,
1238c2ecf20Sopenharmony_ci				  struct ethtool_stats *dummy,
1248c2ecf20Sopenharmony_ci				  u64 *data)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	void *pdata = netdev_priv(ndev);
1278c2ecf20Sopenharmony_ci	int i;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	for (i = 0; i < XGE_STATS_LEN; i++)
1308c2ecf20Sopenharmony_ci		*data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	xge_mac_get_extd_stats(pdata);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	for (i = 0; i < XGE_EXTD_STATS_LEN; i++)
1358c2ecf20Sopenharmony_ci		*data++ = gstrings_extd_stats[i].value;
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic int xge_get_link_ksettings(struct net_device *ndev,
1398c2ecf20Sopenharmony_ci				  struct ethtool_link_ksettings *cmd)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	struct phy_device *phydev = ndev->phydev;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	if (!phydev)
1448c2ecf20Sopenharmony_ci		return -ENODEV;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	phy_ethtool_ksettings_get(phydev, cmd);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	return 0;
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic int xge_set_link_ksettings(struct net_device *ndev,
1528c2ecf20Sopenharmony_ci				  const struct ethtool_link_ksettings *cmd)
1538c2ecf20Sopenharmony_ci{
1548c2ecf20Sopenharmony_ci	struct phy_device *phydev = ndev->phydev;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	if (!phydev)
1578c2ecf20Sopenharmony_ci		return -ENODEV;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	return phy_ethtool_ksettings_set(phydev, cmd);
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic const struct ethtool_ops xge_ethtool_ops = {
1638c2ecf20Sopenharmony_ci	.get_drvinfo = xge_get_drvinfo,
1648c2ecf20Sopenharmony_ci	.get_link = ethtool_op_get_link,
1658c2ecf20Sopenharmony_ci	.get_strings = xge_get_strings,
1668c2ecf20Sopenharmony_ci	.get_sset_count = xge_get_sset_count,
1678c2ecf20Sopenharmony_ci	.get_ethtool_stats = xge_get_ethtool_stats,
1688c2ecf20Sopenharmony_ci	.get_link_ksettings = xge_get_link_ksettings,
1698c2ecf20Sopenharmony_ci	.set_link_ksettings = xge_set_link_ksettings,
1708c2ecf20Sopenharmony_ci};
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_civoid xge_set_ethtool_ops(struct net_device *ndev)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	ndev->ethtool_ops = &xge_ethtool_ops;
1758c2ecf20Sopenharmony_ci}
176