xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/altera/altera_tse_ethtool.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /* Ethtool support for Altera Triple-Speed Ethernet MAC driver
3*4882a593Smuzhiyun  * Copyright (C) 2008-2014 Altera Corporation. All rights reserved
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Contributors:
6*4882a593Smuzhiyun  *   Dalon Westergreen
7*4882a593Smuzhiyun  *   Thomas Chou
8*4882a593Smuzhiyun  *   Ian Abbott
9*4882a593Smuzhiyun  *   Yuriy Kozlov
10*4882a593Smuzhiyun  *   Tobias Klauser
11*4882a593Smuzhiyun  *   Andriy Smolskyy
12*4882a593Smuzhiyun  *   Roman Bulgakov
13*4882a593Smuzhiyun  *   Dmytro Mytarchuk
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * Original driver contributed by SLS.
16*4882a593Smuzhiyun  * Major updates contributed by GlobalLogic
17*4882a593Smuzhiyun  */
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <linux/ethtool.h>
20*4882a593Smuzhiyun #include <linux/kernel.h>
21*4882a593Smuzhiyun #include <linux/netdevice.h>
22*4882a593Smuzhiyun #include <linux/phy.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include "altera_tse.h"
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define TSE_STATS_LEN	31
27*4882a593Smuzhiyun #define TSE_NUM_REGS	128
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun static char const stat_gstrings[][ETH_GSTRING_LEN] = {
30*4882a593Smuzhiyun 	"tx_packets",
31*4882a593Smuzhiyun 	"rx_packets",
32*4882a593Smuzhiyun 	"rx_crc_errors",
33*4882a593Smuzhiyun 	"rx_align_errors",
34*4882a593Smuzhiyun 	"tx_bytes",
35*4882a593Smuzhiyun 	"rx_bytes",
36*4882a593Smuzhiyun 	"tx_pause",
37*4882a593Smuzhiyun 	"rx_pause",
38*4882a593Smuzhiyun 	"rx_errors",
39*4882a593Smuzhiyun 	"tx_errors",
40*4882a593Smuzhiyun 	"rx_unicast",
41*4882a593Smuzhiyun 	"rx_multicast",
42*4882a593Smuzhiyun 	"rx_broadcast",
43*4882a593Smuzhiyun 	"tx_discards",
44*4882a593Smuzhiyun 	"tx_unicast",
45*4882a593Smuzhiyun 	"tx_multicast",
46*4882a593Smuzhiyun 	"tx_broadcast",
47*4882a593Smuzhiyun 	"ether_drops",
48*4882a593Smuzhiyun 	"rx_total_bytes",
49*4882a593Smuzhiyun 	"rx_total_packets",
50*4882a593Smuzhiyun 	"rx_undersize",
51*4882a593Smuzhiyun 	"rx_oversize",
52*4882a593Smuzhiyun 	"rx_64_bytes",
53*4882a593Smuzhiyun 	"rx_65_127_bytes",
54*4882a593Smuzhiyun 	"rx_128_255_bytes",
55*4882a593Smuzhiyun 	"rx_256_511_bytes",
56*4882a593Smuzhiyun 	"rx_512_1023_bytes",
57*4882a593Smuzhiyun 	"rx_1024_1518_bytes",
58*4882a593Smuzhiyun 	"rx_gte_1519_bytes",
59*4882a593Smuzhiyun 	"rx_jabbers",
60*4882a593Smuzhiyun 	"rx_runts",
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun 
tse_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)63*4882a593Smuzhiyun static void tse_get_drvinfo(struct net_device *dev,
64*4882a593Smuzhiyun 			    struct ethtool_drvinfo *info)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	struct altera_tse_private *priv = netdev_priv(dev);
67*4882a593Smuzhiyun 	u32 rev = ioread32(&priv->mac_dev->megacore_revision);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	strcpy(info->driver, "altera_tse");
70*4882a593Smuzhiyun 	snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d",
71*4882a593Smuzhiyun 		 rev & 0xFFFF, (rev & 0xFFFF0000) >> 16);
72*4882a593Smuzhiyun 	sprintf(info->bus_info, "platform");
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun /* Fill in a buffer with the strings which correspond to the
76*4882a593Smuzhiyun  * stats
77*4882a593Smuzhiyun  */
tse_gstrings(struct net_device * dev,u32 stringset,u8 * buf)78*4882a593Smuzhiyun static void tse_gstrings(struct net_device *dev, u32 stringset, u8 *buf)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	memcpy(buf, stat_gstrings, TSE_STATS_LEN * ETH_GSTRING_LEN);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
tse_fill_stats(struct net_device * dev,struct ethtool_stats * dummy,u64 * buf)83*4882a593Smuzhiyun static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
84*4882a593Smuzhiyun 			   u64 *buf)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	struct altera_tse_private *priv = netdev_priv(dev);
87*4882a593Smuzhiyun 	u64 ext;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	buf[0] = csrrd32(priv->mac_dev,
90*4882a593Smuzhiyun 			 tse_csroffs(frames_transmitted_ok));
91*4882a593Smuzhiyun 	buf[1] = csrrd32(priv->mac_dev,
92*4882a593Smuzhiyun 			 tse_csroffs(frames_received_ok));
93*4882a593Smuzhiyun 	buf[2] = csrrd32(priv->mac_dev,
94*4882a593Smuzhiyun 			 tse_csroffs(frames_check_sequence_errors));
95*4882a593Smuzhiyun 	buf[3] = csrrd32(priv->mac_dev,
96*4882a593Smuzhiyun 			 tse_csroffs(alignment_errors));
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	/* Extended aOctetsTransmittedOK counter */
99*4882a593Smuzhiyun 	ext = (u64) csrrd32(priv->mac_dev,
100*4882a593Smuzhiyun 			    tse_csroffs(msb_octets_transmitted_ok)) << 32;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	ext |= csrrd32(priv->mac_dev,
103*4882a593Smuzhiyun 		       tse_csroffs(octets_transmitted_ok));
104*4882a593Smuzhiyun 	buf[4] = ext;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	/* Extended aOctetsReceivedOK counter */
107*4882a593Smuzhiyun 	ext = (u64) csrrd32(priv->mac_dev,
108*4882a593Smuzhiyun 			    tse_csroffs(msb_octets_received_ok)) << 32;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	ext |= csrrd32(priv->mac_dev,
111*4882a593Smuzhiyun 		       tse_csroffs(octets_received_ok));
112*4882a593Smuzhiyun 	buf[5] = ext;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	buf[6] = csrrd32(priv->mac_dev,
115*4882a593Smuzhiyun 			 tse_csroffs(tx_pause_mac_ctrl_frames));
116*4882a593Smuzhiyun 	buf[7] = csrrd32(priv->mac_dev,
117*4882a593Smuzhiyun 			 tse_csroffs(rx_pause_mac_ctrl_frames));
118*4882a593Smuzhiyun 	buf[8] = csrrd32(priv->mac_dev,
119*4882a593Smuzhiyun 			 tse_csroffs(if_in_errors));
120*4882a593Smuzhiyun 	buf[9] = csrrd32(priv->mac_dev,
121*4882a593Smuzhiyun 			 tse_csroffs(if_out_errors));
122*4882a593Smuzhiyun 	buf[10] = csrrd32(priv->mac_dev,
123*4882a593Smuzhiyun 			  tse_csroffs(if_in_ucast_pkts));
124*4882a593Smuzhiyun 	buf[11] = csrrd32(priv->mac_dev,
125*4882a593Smuzhiyun 			  tse_csroffs(if_in_multicast_pkts));
126*4882a593Smuzhiyun 	buf[12] = csrrd32(priv->mac_dev,
127*4882a593Smuzhiyun 			  tse_csroffs(if_in_broadcast_pkts));
128*4882a593Smuzhiyun 	buf[13] = csrrd32(priv->mac_dev,
129*4882a593Smuzhiyun 			  tse_csroffs(if_out_discards));
130*4882a593Smuzhiyun 	buf[14] = csrrd32(priv->mac_dev,
131*4882a593Smuzhiyun 			  tse_csroffs(if_out_ucast_pkts));
132*4882a593Smuzhiyun 	buf[15] = csrrd32(priv->mac_dev,
133*4882a593Smuzhiyun 			  tse_csroffs(if_out_multicast_pkts));
134*4882a593Smuzhiyun 	buf[16] = csrrd32(priv->mac_dev,
135*4882a593Smuzhiyun 			  tse_csroffs(if_out_broadcast_pkts));
136*4882a593Smuzhiyun 	buf[17] = csrrd32(priv->mac_dev,
137*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_drop_events));
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	/* Extended etherStatsOctets counter */
140*4882a593Smuzhiyun 	ext = (u64) csrrd32(priv->mac_dev,
141*4882a593Smuzhiyun 			    tse_csroffs(msb_ether_stats_octets)) << 32;
142*4882a593Smuzhiyun 	ext |= csrrd32(priv->mac_dev,
143*4882a593Smuzhiyun 		       tse_csroffs(ether_stats_octets));
144*4882a593Smuzhiyun 	buf[18] = ext;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	buf[19] = csrrd32(priv->mac_dev,
147*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_pkts));
148*4882a593Smuzhiyun 	buf[20] = csrrd32(priv->mac_dev,
149*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_undersize_pkts));
150*4882a593Smuzhiyun 	buf[21] = csrrd32(priv->mac_dev,
151*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_oversize_pkts));
152*4882a593Smuzhiyun 	buf[22] = csrrd32(priv->mac_dev,
153*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_pkts_64_octets));
154*4882a593Smuzhiyun 	buf[23] = csrrd32(priv->mac_dev,
155*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_pkts_65to127_octets));
156*4882a593Smuzhiyun 	buf[24] = csrrd32(priv->mac_dev,
157*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_pkts_128to255_octets));
158*4882a593Smuzhiyun 	buf[25] = csrrd32(priv->mac_dev,
159*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_pkts_256to511_octets));
160*4882a593Smuzhiyun 	buf[26] = csrrd32(priv->mac_dev,
161*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_pkts_512to1023_octets));
162*4882a593Smuzhiyun 	buf[27] = csrrd32(priv->mac_dev,
163*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_pkts_1024to1518_octets));
164*4882a593Smuzhiyun 	buf[28] = csrrd32(priv->mac_dev,
165*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_pkts_1519tox_octets));
166*4882a593Smuzhiyun 	buf[29] = csrrd32(priv->mac_dev,
167*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_jabbers));
168*4882a593Smuzhiyun 	buf[30] = csrrd32(priv->mac_dev,
169*4882a593Smuzhiyun 			  tse_csroffs(ether_stats_fragments));
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
tse_sset_count(struct net_device * dev,int sset)172*4882a593Smuzhiyun static int tse_sset_count(struct net_device *dev, int sset)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	switch (sset) {
175*4882a593Smuzhiyun 	case ETH_SS_STATS:
176*4882a593Smuzhiyun 		return TSE_STATS_LEN;
177*4882a593Smuzhiyun 	default:
178*4882a593Smuzhiyun 		return -EOPNOTSUPP;
179*4882a593Smuzhiyun 	}
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
tse_get_msglevel(struct net_device * dev)182*4882a593Smuzhiyun static u32 tse_get_msglevel(struct net_device *dev)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	struct altera_tse_private *priv = netdev_priv(dev);
185*4882a593Smuzhiyun 	return priv->msg_enable;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
tse_set_msglevel(struct net_device * dev,uint32_t data)188*4882a593Smuzhiyun static void tse_set_msglevel(struct net_device *dev, uint32_t data)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	struct altera_tse_private *priv = netdev_priv(dev);
191*4882a593Smuzhiyun 	priv->msg_enable = data;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
tse_reglen(struct net_device * dev)194*4882a593Smuzhiyun static int tse_reglen(struct net_device *dev)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	return TSE_NUM_REGS * sizeof(u32);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
tse_get_regs(struct net_device * dev,struct ethtool_regs * regs,void * regbuf)199*4882a593Smuzhiyun static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs,
200*4882a593Smuzhiyun 			 void *regbuf)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	int i;
203*4882a593Smuzhiyun 	struct altera_tse_private *priv = netdev_priv(dev);
204*4882a593Smuzhiyun 	u32 *buf = regbuf;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	/* Set version to a known value, so ethtool knows
207*4882a593Smuzhiyun 	 * how to do any special formatting of this data.
208*4882a593Smuzhiyun 	 * This version number will need to change if and
209*4882a593Smuzhiyun 	 * when this register table is changed.
210*4882a593Smuzhiyun 	 *
211*4882a593Smuzhiyun 	 * version[31:0] = 1: Dump the first 128 TSE Registers
212*4882a593Smuzhiyun 	 *      Upper bits are all 0 by default
213*4882a593Smuzhiyun 	 *
214*4882a593Smuzhiyun 	 * Upper 16-bits will indicate feature presence for
215*4882a593Smuzhiyun 	 * Ethtool register decoding in future version.
216*4882a593Smuzhiyun 	 */
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	regs->version = 1;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	for (i = 0; i < TSE_NUM_REGS; i++)
221*4882a593Smuzhiyun 		buf[i] = csrrd32(priv->mac_dev, i * 4);
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun static const struct ethtool_ops tse_ethtool_ops = {
225*4882a593Smuzhiyun 	.get_drvinfo = tse_get_drvinfo,
226*4882a593Smuzhiyun 	.get_regs_len = tse_reglen,
227*4882a593Smuzhiyun 	.get_regs = tse_get_regs,
228*4882a593Smuzhiyun 	.get_link = ethtool_op_get_link,
229*4882a593Smuzhiyun 	.get_strings = tse_gstrings,
230*4882a593Smuzhiyun 	.get_sset_count = tse_sset_count,
231*4882a593Smuzhiyun 	.get_ethtool_stats = tse_fill_stats,
232*4882a593Smuzhiyun 	.get_msglevel = tse_get_msglevel,
233*4882a593Smuzhiyun 	.set_msglevel = tse_set_msglevel,
234*4882a593Smuzhiyun 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
235*4882a593Smuzhiyun 	.set_link_ksettings = phy_ethtool_set_link_ksettings,
236*4882a593Smuzhiyun };
237*4882a593Smuzhiyun 
altera_tse_set_ethtool_ops(struct net_device * netdev)238*4882a593Smuzhiyun void altera_tse_set_ethtool_ops(struct net_device *netdev)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	netdev->ethtool_ops = &tse_ethtool_ops;
241*4882a593Smuzhiyun }
242