xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/ti/am65-cpsw-ethtool.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver ethtool ops
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/net_tstamp.h>
9*4882a593Smuzhiyun #include <linux/phy.h>
10*4882a593Smuzhiyun #include <linux/platform_device.h>
11*4882a593Smuzhiyun #include <linux/pm_runtime.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "am65-cpsw-nuss.h"
14*4882a593Smuzhiyun #include "cpsw_ale.h"
15*4882a593Smuzhiyun #include "am65-cpts.h"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define AM65_CPSW_REGDUMP_VER 0x1
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun enum {
20*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_NUSS = 1,
21*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_RGMII_STATUS = 2,
22*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_MDIO = 3,
23*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_CPSW = 4,
24*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_CPSW_P0 = 5,
25*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_CPSW_P1 = 6,
26*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_CPSW_CPTS = 7,
27*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_CPSW_ALE = 8,
28*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL = 9,
29*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_MOD_LAST,
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /**
33*4882a593Smuzhiyun  * struct am65_cpsw_regdump_hdr - regdump record header
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  * @module_id: CPSW module ID
36*4882a593Smuzhiyun  * @len: CPSW module registers space length in u32
37*4882a593Smuzhiyun  */
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun struct am65_cpsw_regdump_hdr {
40*4882a593Smuzhiyun 	u32 module_id;
41*4882a593Smuzhiyun 	u32 len;
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /**
45*4882a593Smuzhiyun  * struct am65_cpsw_regdump_item - regdump module description
46*4882a593Smuzhiyun  *
47*4882a593Smuzhiyun  * @hdr: CPSW module header
48*4882a593Smuzhiyun  * @start_ofs: CPSW module registers start addr
49*4882a593Smuzhiyun  * @end_ofs: CPSW module registers end addr
50*4882a593Smuzhiyun  *
51*4882a593Smuzhiyun  * Registers dump provided in the format:
52*4882a593Smuzhiyun  *  u32 : module ID
53*4882a593Smuzhiyun  *  u32 : dump length
54*4882a593Smuzhiyun  *  u32[..len]: registers values
55*4882a593Smuzhiyun  */
56*4882a593Smuzhiyun struct am65_cpsw_regdump_item {
57*4882a593Smuzhiyun 	struct am65_cpsw_regdump_hdr hdr;
58*4882a593Smuzhiyun 	u32 start_ofs;
59*4882a593Smuzhiyun 	u32 end_ofs;
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #define AM65_CPSW_REGDUMP_REC(mod, start, end) { \
63*4882a593Smuzhiyun 	.hdr.module_id = (mod), \
64*4882a593Smuzhiyun 	.hdr.len = (((u32 *)(end)) - ((u32 *)(start)) + 1) * sizeof(u32) * 2 + \
65*4882a593Smuzhiyun 		   sizeof(struct am65_cpsw_regdump_hdr), \
66*4882a593Smuzhiyun 	.start_ofs = (start), \
67*4882a593Smuzhiyun 	.end_ofs = end, \
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static const struct am65_cpsw_regdump_item am65_cpsw_regdump[] = {
71*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_NUSS, 0x0, 0x1c),
72*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_RGMII_STATUS, 0x30, 0x4c),
73*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_MDIO, 0xf00, 0xffc),
74*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW, 0x20000, 0x2011c),
75*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P0, 0x21000, 0x21320),
76*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P1, 0x22000, 0x223a4),
77*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_CPTS,
78*4882a593Smuzhiyun 			      0x3d000, 0x3d048),
79*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE, 0x3e000, 0x3e13c),
80*4882a593Smuzhiyun 	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL, 0, 0),
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun struct am65_cpsw_stats_regs {
84*4882a593Smuzhiyun 	u32	rx_good_frames;
85*4882a593Smuzhiyun 	u32	rx_broadcast_frames;
86*4882a593Smuzhiyun 	u32	rx_multicast_frames;
87*4882a593Smuzhiyun 	u32	rx_pause_frames;		/* slave */
88*4882a593Smuzhiyun 	u32	rx_crc_errors;
89*4882a593Smuzhiyun 	u32	rx_align_code_errors;		/* slave */
90*4882a593Smuzhiyun 	u32	rx_oversized_frames;
91*4882a593Smuzhiyun 	u32	rx_jabber_frames;		/* slave */
92*4882a593Smuzhiyun 	u32	rx_undersized_frames;
93*4882a593Smuzhiyun 	u32	rx_fragments;			/* slave */
94*4882a593Smuzhiyun 	u32	ale_drop;
95*4882a593Smuzhiyun 	u32	ale_overrun_drop;
96*4882a593Smuzhiyun 	u32	rx_octets;
97*4882a593Smuzhiyun 	u32	tx_good_frames;
98*4882a593Smuzhiyun 	u32	tx_broadcast_frames;
99*4882a593Smuzhiyun 	u32	tx_multicast_frames;
100*4882a593Smuzhiyun 	u32	tx_pause_frames;		/* slave */
101*4882a593Smuzhiyun 	u32	tx_deferred_frames;		/* slave */
102*4882a593Smuzhiyun 	u32	tx_collision_frames;		/* slave */
103*4882a593Smuzhiyun 	u32	tx_single_coll_frames;		/* slave */
104*4882a593Smuzhiyun 	u32	tx_mult_coll_frames;		/* slave */
105*4882a593Smuzhiyun 	u32	tx_excessive_collisions;	/* slave */
106*4882a593Smuzhiyun 	u32	tx_late_collisions;		/* slave */
107*4882a593Smuzhiyun 	u32	rx_ipg_error;			/* slave 10G only */
108*4882a593Smuzhiyun 	u32	tx_carrier_sense_errors;	/* slave */
109*4882a593Smuzhiyun 	u32	tx_octets;
110*4882a593Smuzhiyun 	u32	tx_64B_frames;
111*4882a593Smuzhiyun 	u32	tx_65_to_127B_frames;
112*4882a593Smuzhiyun 	u32	tx_128_to_255B_frames;
113*4882a593Smuzhiyun 	u32	tx_256_to_511B_frames;
114*4882a593Smuzhiyun 	u32	tx_512_to_1023B_frames;
115*4882a593Smuzhiyun 	u32	tx_1024B_frames;
116*4882a593Smuzhiyun 	u32	net_octets;
117*4882a593Smuzhiyun 	u32	rx_bottom_fifo_drop;
118*4882a593Smuzhiyun 	u32	rx_port_mask_drop;
119*4882a593Smuzhiyun 	u32	rx_top_fifo_drop;
120*4882a593Smuzhiyun 	u32	ale_rate_limit_drop;
121*4882a593Smuzhiyun 	u32	ale_vid_ingress_drop;
122*4882a593Smuzhiyun 	u32	ale_da_eq_sa_drop;
123*4882a593Smuzhiyun 	u32	ale_block_drop;			/* K3 */
124*4882a593Smuzhiyun 	u32	ale_secure_drop;		/* K3 */
125*4882a593Smuzhiyun 	u32	ale_auth_drop;			/* K3 */
126*4882a593Smuzhiyun 	u32	ale_unknown_ucast;
127*4882a593Smuzhiyun 	u32	ale_unknown_ucast_bytes;
128*4882a593Smuzhiyun 	u32	ale_unknown_mcast;
129*4882a593Smuzhiyun 	u32	ale_unknown_mcast_bytes;
130*4882a593Smuzhiyun 	u32	ale_unknown_bcast;
131*4882a593Smuzhiyun 	u32	ale_unknown_bcast_bytes;
132*4882a593Smuzhiyun 	u32	ale_pol_match;
133*4882a593Smuzhiyun 	u32	ale_pol_match_red;
134*4882a593Smuzhiyun 	u32	ale_pol_match_yellow;
135*4882a593Smuzhiyun 	u32	ale_mcast_sa_drop;		/* K3 */
136*4882a593Smuzhiyun 	u32	ale_dual_vlan_drop;		/* K3 */
137*4882a593Smuzhiyun 	u32	ale_len_err_drop;		/* K3 */
138*4882a593Smuzhiyun 	u32	ale_ip_next_hdr_drop;		/* K3 */
139*4882a593Smuzhiyun 	u32	ale_ipv4_frag_drop;		/* K3 */
140*4882a593Smuzhiyun 	u32	__rsvd_1[24];
141*4882a593Smuzhiyun 	u32	iet_rx_assembly_err;		/* K3 slave */
142*4882a593Smuzhiyun 	u32	iet_rx_assembly_ok;		/* K3 slave */
143*4882a593Smuzhiyun 	u32	iet_rx_smd_err;			/* K3 slave */
144*4882a593Smuzhiyun 	u32	iet_rx_frag;			/* K3 slave */
145*4882a593Smuzhiyun 	u32	iet_tx_hold;			/* K3 slave */
146*4882a593Smuzhiyun 	u32	iet_tx_frag;			/* K3 slave */
147*4882a593Smuzhiyun 	u32	__rsvd_2[9];
148*4882a593Smuzhiyun 	u32	tx_mem_protect_err;
149*4882a593Smuzhiyun 	/* following NU only */
150*4882a593Smuzhiyun 	u32	tx_pri0;
151*4882a593Smuzhiyun 	u32	tx_pri1;
152*4882a593Smuzhiyun 	u32	tx_pri2;
153*4882a593Smuzhiyun 	u32	tx_pri3;
154*4882a593Smuzhiyun 	u32	tx_pri4;
155*4882a593Smuzhiyun 	u32	tx_pri5;
156*4882a593Smuzhiyun 	u32	tx_pri6;
157*4882a593Smuzhiyun 	u32	tx_pri7;
158*4882a593Smuzhiyun 	u32	tx_pri0_bcnt;
159*4882a593Smuzhiyun 	u32	tx_pri1_bcnt;
160*4882a593Smuzhiyun 	u32	tx_pri2_bcnt;
161*4882a593Smuzhiyun 	u32	tx_pri3_bcnt;
162*4882a593Smuzhiyun 	u32	tx_pri4_bcnt;
163*4882a593Smuzhiyun 	u32	tx_pri5_bcnt;
164*4882a593Smuzhiyun 	u32	tx_pri6_bcnt;
165*4882a593Smuzhiyun 	u32	tx_pri7_bcnt;
166*4882a593Smuzhiyun 	u32	tx_pri0_drop;
167*4882a593Smuzhiyun 	u32	tx_pri1_drop;
168*4882a593Smuzhiyun 	u32	tx_pri2_drop;
169*4882a593Smuzhiyun 	u32	tx_pri3_drop;
170*4882a593Smuzhiyun 	u32	tx_pri4_drop;
171*4882a593Smuzhiyun 	u32	tx_pri5_drop;
172*4882a593Smuzhiyun 	u32	tx_pri6_drop;
173*4882a593Smuzhiyun 	u32	tx_pri7_drop;
174*4882a593Smuzhiyun 	u32	tx_pri0_drop_bcnt;
175*4882a593Smuzhiyun 	u32	tx_pri1_drop_bcnt;
176*4882a593Smuzhiyun 	u32	tx_pri2_drop_bcnt;
177*4882a593Smuzhiyun 	u32	tx_pri3_drop_bcnt;
178*4882a593Smuzhiyun 	u32	tx_pri4_drop_bcnt;
179*4882a593Smuzhiyun 	u32	tx_pri5_drop_bcnt;
180*4882a593Smuzhiyun 	u32	tx_pri6_drop_bcnt;
181*4882a593Smuzhiyun 	u32	tx_pri7_drop_bcnt;
182*4882a593Smuzhiyun };
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun struct am65_cpsw_ethtool_stat {
185*4882a593Smuzhiyun 	char desc[ETH_GSTRING_LEN];
186*4882a593Smuzhiyun 	int offset;
187*4882a593Smuzhiyun };
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun #define AM65_CPSW_STATS(prefix, field)			\
190*4882a593Smuzhiyun {							\
191*4882a593Smuzhiyun 	#prefix#field,					\
192*4882a593Smuzhiyun 	offsetof(struct am65_cpsw_stats_regs, field)	\
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun static const struct am65_cpsw_ethtool_stat am65_host_stats[] = {
196*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_good_frames),
197*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_broadcast_frames),
198*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_multicast_frames),
199*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_crc_errors),
200*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_oversized_frames),
201*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_undersized_frames),
202*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_drop),
203*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_overrun_drop),
204*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_octets),
205*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_good_frames),
206*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_broadcast_frames),
207*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_multicast_frames),
208*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_octets),
209*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_64B_frames),
210*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_65_to_127B_frames),
211*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_128_to_255B_frames),
212*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_256_to_511B_frames),
213*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_512_to_1023B_frames),
214*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_1024B_frames),
215*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, net_octets),
216*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_bottom_fifo_drop),
217*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_port_mask_drop),
218*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, rx_top_fifo_drop),
219*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_rate_limit_drop),
220*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_vid_ingress_drop),
221*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_da_eq_sa_drop),
222*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_block_drop),
223*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_secure_drop),
224*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_auth_drop),
225*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_unknown_ucast),
226*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_unknown_ucast_bytes),
227*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_unknown_mcast),
228*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_unknown_mcast_bytes),
229*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_unknown_bcast),
230*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_unknown_bcast_bytes),
231*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_pol_match),
232*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_pol_match_red),
233*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_pol_match_yellow),
234*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_mcast_sa_drop),
235*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_dual_vlan_drop),
236*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_len_err_drop),
237*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_ip_next_hdr_drop),
238*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, ale_ipv4_frag_drop),
239*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_mem_protect_err),
240*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri0),
241*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri1),
242*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri2),
243*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri3),
244*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri4),
245*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri5),
246*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri6),
247*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri7),
248*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri0_bcnt),
249*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri1_bcnt),
250*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri2_bcnt),
251*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri3_bcnt),
252*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri4_bcnt),
253*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri5_bcnt),
254*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri6_bcnt),
255*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri7_bcnt),
256*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri0_drop),
257*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri1_drop),
258*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri2_drop),
259*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri3_drop),
260*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri4_drop),
261*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri5_drop),
262*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri6_drop),
263*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri7_drop),
264*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri0_drop_bcnt),
265*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri1_drop_bcnt),
266*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri2_drop_bcnt),
267*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri3_drop_bcnt),
268*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri4_drop_bcnt),
269*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri5_drop_bcnt),
270*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri6_drop_bcnt),
271*4882a593Smuzhiyun 	AM65_CPSW_STATS(p0_, tx_pri7_drop_bcnt),
272*4882a593Smuzhiyun };
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun static const struct am65_cpsw_ethtool_stat am65_slave_stats[] = {
275*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_good_frames),
276*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_broadcast_frames),
277*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_multicast_frames),
278*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_pause_frames),
279*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_crc_errors),
280*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_align_code_errors),
281*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_oversized_frames),
282*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_jabber_frames),
283*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_undersized_frames),
284*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_fragments),
285*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_drop),
286*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_overrun_drop),
287*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_octets),
288*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_good_frames),
289*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_broadcast_frames),
290*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_multicast_frames),
291*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pause_frames),
292*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_deferred_frames),
293*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_collision_frames),
294*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_single_coll_frames),
295*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_mult_coll_frames),
296*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_excessive_collisions),
297*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_late_collisions),
298*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_ipg_error),
299*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_carrier_sense_errors),
300*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_octets),
301*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_64B_frames),
302*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_65_to_127B_frames),
303*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_128_to_255B_frames),
304*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_256_to_511B_frames),
305*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_512_to_1023B_frames),
306*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_1024B_frames),
307*4882a593Smuzhiyun 	AM65_CPSW_STATS(, net_octets),
308*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_bottom_fifo_drop),
309*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_port_mask_drop),
310*4882a593Smuzhiyun 	AM65_CPSW_STATS(, rx_top_fifo_drop),
311*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_rate_limit_drop),
312*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_vid_ingress_drop),
313*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_da_eq_sa_drop),
314*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_block_drop),
315*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_secure_drop),
316*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_auth_drop),
317*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_unknown_ucast),
318*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_unknown_ucast_bytes),
319*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_unknown_mcast),
320*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_unknown_mcast_bytes),
321*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_unknown_bcast),
322*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_unknown_bcast_bytes),
323*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_pol_match),
324*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_pol_match_red),
325*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_pol_match_yellow),
326*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_mcast_sa_drop),
327*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_dual_vlan_drop),
328*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_len_err_drop),
329*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_ip_next_hdr_drop),
330*4882a593Smuzhiyun 	AM65_CPSW_STATS(, ale_ipv4_frag_drop),
331*4882a593Smuzhiyun 	AM65_CPSW_STATS(, iet_rx_assembly_err),
332*4882a593Smuzhiyun 	AM65_CPSW_STATS(, iet_rx_assembly_ok),
333*4882a593Smuzhiyun 	AM65_CPSW_STATS(, iet_rx_smd_err),
334*4882a593Smuzhiyun 	AM65_CPSW_STATS(, iet_rx_frag),
335*4882a593Smuzhiyun 	AM65_CPSW_STATS(, iet_tx_hold),
336*4882a593Smuzhiyun 	AM65_CPSW_STATS(, iet_tx_frag),
337*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_mem_protect_err),
338*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri0),
339*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri1),
340*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri2),
341*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri3),
342*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri4),
343*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri5),
344*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri6),
345*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri7),
346*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri0_bcnt),
347*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri1_bcnt),
348*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri2_bcnt),
349*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri3_bcnt),
350*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri4_bcnt),
351*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri5_bcnt),
352*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri6_bcnt),
353*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri7_bcnt),
354*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri0_drop),
355*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri1_drop),
356*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri2_drop),
357*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri3_drop),
358*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri4_drop),
359*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri5_drop),
360*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri6_drop),
361*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri7_drop),
362*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri0_drop_bcnt),
363*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri1_drop_bcnt),
364*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri2_drop_bcnt),
365*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri3_drop_bcnt),
366*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri4_drop_bcnt),
367*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri5_drop_bcnt),
368*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri6_drop_bcnt),
369*4882a593Smuzhiyun 	AM65_CPSW_STATS(, tx_pri7_drop_bcnt),
370*4882a593Smuzhiyun };
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun /* Ethtool priv_flags */
373*4882a593Smuzhiyun static const char am65_cpsw_ethtool_priv_flags[][ETH_GSTRING_LEN] = {
374*4882a593Smuzhiyun #define	AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN	BIT(0)
375*4882a593Smuzhiyun 	"p0-rx-ptype-rrobin",
376*4882a593Smuzhiyun };
377*4882a593Smuzhiyun 
am65_cpsw_ethtool_op_begin(struct net_device * ndev)378*4882a593Smuzhiyun static int am65_cpsw_ethtool_op_begin(struct net_device *ndev)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
381*4882a593Smuzhiyun 	int ret;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	ret = pm_runtime_get_sync(common->dev);
384*4882a593Smuzhiyun 	if (ret < 0) {
385*4882a593Smuzhiyun 		dev_err(common->dev, "ethtool begin failed %d\n", ret);
386*4882a593Smuzhiyun 		pm_runtime_put_noidle(common->dev);
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	return ret;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun 
am65_cpsw_ethtool_op_complete(struct net_device * ndev)392*4882a593Smuzhiyun static void am65_cpsw_ethtool_op_complete(struct net_device *ndev)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
395*4882a593Smuzhiyun 	int ret;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	ret = pm_runtime_put(common->dev);
398*4882a593Smuzhiyun 	if (ret < 0 && ret != -EBUSY)
399*4882a593Smuzhiyun 		dev_err(common->dev, "ethtool complete failed %d\n", ret);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun 
am65_cpsw_get_drvinfo(struct net_device * ndev,struct ethtool_drvinfo * info)402*4882a593Smuzhiyun static void am65_cpsw_get_drvinfo(struct net_device *ndev,
403*4882a593Smuzhiyun 				  struct ethtool_drvinfo *info)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	strlcpy(info->driver, dev_driver_string(common->dev),
408*4882a593Smuzhiyun 		sizeof(info->driver));
409*4882a593Smuzhiyun 	strlcpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info));
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
am65_cpsw_get_msglevel(struct net_device * ndev)412*4882a593Smuzhiyun static u32 am65_cpsw_get_msglevel(struct net_device *ndev)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun 	struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	return priv->msg_enable;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun 
am65_cpsw_set_msglevel(struct net_device * ndev,u32 value)419*4882a593Smuzhiyun static void am65_cpsw_set_msglevel(struct net_device *ndev, u32 value)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun 	struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	priv->msg_enable = value;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
am65_cpsw_get_channels(struct net_device * ndev,struct ethtool_channels * ch)426*4882a593Smuzhiyun static void am65_cpsw_get_channels(struct net_device *ndev,
427*4882a593Smuzhiyun 				   struct ethtool_channels *ch)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	ch->max_rx = AM65_CPSW_MAX_RX_QUEUES;
432*4882a593Smuzhiyun 	ch->max_tx = AM65_CPSW_MAX_TX_QUEUES;
433*4882a593Smuzhiyun 	ch->rx_count = AM65_CPSW_MAX_RX_QUEUES;
434*4882a593Smuzhiyun 	ch->tx_count = common->tx_ch_num;
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun 
am65_cpsw_set_channels(struct net_device * ndev,struct ethtool_channels * chs)437*4882a593Smuzhiyun static int am65_cpsw_set_channels(struct net_device *ndev,
438*4882a593Smuzhiyun 				  struct ethtool_channels *chs)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	if (!chs->rx_count || !chs->tx_count)
443*4882a593Smuzhiyun 		return -EINVAL;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	/* Check if interface is up. Can change the num queues when
446*4882a593Smuzhiyun 	 * the interface is down.
447*4882a593Smuzhiyun 	 */
448*4882a593Smuzhiyun 	if (common->usage_count)
449*4882a593Smuzhiyun 		return -EBUSY;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	am65_cpsw_nuss_remove_tx_chns(common);
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	return am65_cpsw_nuss_update_tx_chns(common, chs->tx_count);
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun 
am65_cpsw_get_ringparam(struct net_device * ndev,struct ethtool_ringparam * ering)456*4882a593Smuzhiyun static void am65_cpsw_get_ringparam(struct net_device *ndev,
457*4882a593Smuzhiyun 				    struct ethtool_ringparam *ering)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	/* not supported */
462*4882a593Smuzhiyun 	ering->tx_pending = common->tx_chns[0].descs_num;
463*4882a593Smuzhiyun 	ering->rx_pending = common->rx_chns.descs_num;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun 
am65_cpsw_get_pauseparam(struct net_device * ndev,struct ethtool_pauseparam * pause)466*4882a593Smuzhiyun static void am65_cpsw_get_pauseparam(struct net_device *ndev,
467*4882a593Smuzhiyun 				     struct ethtool_pauseparam *pause)
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun 	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	pause->autoneg = AUTONEG_DISABLE;
472*4882a593Smuzhiyun 	pause->rx_pause = salve->rx_pause ? true : false;
473*4882a593Smuzhiyun 	pause->tx_pause = salve->tx_pause ? true : false;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun 
am65_cpsw_set_pauseparam(struct net_device * ndev,struct ethtool_pauseparam * pause)476*4882a593Smuzhiyun static int am65_cpsw_set_pauseparam(struct net_device *ndev,
477*4882a593Smuzhiyun 				    struct ethtool_pauseparam *pause)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun 	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	if (!salve->phy)
482*4882a593Smuzhiyun 		return -EINVAL;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	if (!phy_validate_pause(salve->phy, pause))
485*4882a593Smuzhiyun 		return -EINVAL;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	salve->rx_pause = pause->rx_pause ? true : false;
488*4882a593Smuzhiyun 	salve->tx_pause = pause->tx_pause ? true : false;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	phy_set_asym_pause(salve->phy, salve->rx_pause, salve->tx_pause);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	return 0;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun 
am65_cpsw_get_wol(struct net_device * ndev,struct ethtool_wolinfo * wol)495*4882a593Smuzhiyun static void am65_cpsw_get_wol(struct net_device *ndev,
496*4882a593Smuzhiyun 			      struct ethtool_wolinfo *wol)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun 	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	wol->supported = 0;
501*4882a593Smuzhiyun 	wol->wolopts = 0;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	if (salve->phy)
504*4882a593Smuzhiyun 		phy_ethtool_get_wol(salve->phy, wol);
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun 
am65_cpsw_set_wol(struct net_device * ndev,struct ethtool_wolinfo * wol)507*4882a593Smuzhiyun static int am65_cpsw_set_wol(struct net_device *ndev,
508*4882a593Smuzhiyun 			     struct ethtool_wolinfo *wol)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun 	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	if (!salve->phy)
513*4882a593Smuzhiyun 		return -EOPNOTSUPP;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	return phy_ethtool_set_wol(salve->phy, wol);
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun 
am65_cpsw_get_link_ksettings(struct net_device * ndev,struct ethtool_link_ksettings * ecmd)518*4882a593Smuzhiyun static int am65_cpsw_get_link_ksettings(struct net_device *ndev,
519*4882a593Smuzhiyun 					struct ethtool_link_ksettings *ecmd)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun 	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	if (!salve->phy)
524*4882a593Smuzhiyun 		return -EOPNOTSUPP;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	phy_ethtool_ksettings_get(salve->phy, ecmd);
527*4882a593Smuzhiyun 	return 0;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun static int
am65_cpsw_set_link_ksettings(struct net_device * ndev,const struct ethtool_link_ksettings * ecmd)531*4882a593Smuzhiyun am65_cpsw_set_link_ksettings(struct net_device *ndev,
532*4882a593Smuzhiyun 			     const struct ethtool_link_ksettings *ecmd)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun 	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
537*4882a593Smuzhiyun 		return -EOPNOTSUPP;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	return phy_ethtool_ksettings_set(salve->phy, ecmd);
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun 
am65_cpsw_get_eee(struct net_device * ndev,struct ethtool_eee * edata)542*4882a593Smuzhiyun static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun 	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
547*4882a593Smuzhiyun 		return -EOPNOTSUPP;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	return phy_ethtool_get_eee(salve->phy, edata);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun 
am65_cpsw_set_eee(struct net_device * ndev,struct ethtool_eee * edata)552*4882a593Smuzhiyun static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun 	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
557*4882a593Smuzhiyun 		return -EOPNOTSUPP;
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	return phy_ethtool_set_eee(salve->phy, edata);
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun 
am65_cpsw_nway_reset(struct net_device * ndev)562*4882a593Smuzhiyun static int am65_cpsw_nway_reset(struct net_device *ndev)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun 	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
567*4882a593Smuzhiyun 		return -EOPNOTSUPP;
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	return phy_restart_aneg(salve->phy);
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun 
am65_cpsw_get_regs_len(struct net_device * ndev)572*4882a593Smuzhiyun static int am65_cpsw_get_regs_len(struct net_device *ndev)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
575*4882a593Smuzhiyun 	u32 ale_entries, i, regdump_len = 0;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	ale_entries = cpsw_ale_get_num_entries(common->ale);
578*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
579*4882a593Smuzhiyun 		if (am65_cpsw_regdump[i].hdr.module_id ==
580*4882a593Smuzhiyun 		    AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
581*4882a593Smuzhiyun 			regdump_len += sizeof(struct am65_cpsw_regdump_hdr);
582*4882a593Smuzhiyun 			regdump_len += ale_entries *
583*4882a593Smuzhiyun 				       ALE_ENTRY_WORDS * sizeof(u32);
584*4882a593Smuzhiyun 			continue;
585*4882a593Smuzhiyun 		}
586*4882a593Smuzhiyun 		regdump_len += am65_cpsw_regdump[i].hdr.len;
587*4882a593Smuzhiyun 	}
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	return regdump_len;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun 
am65_cpsw_get_regs(struct net_device * ndev,struct ethtool_regs * regs,void * p)592*4882a593Smuzhiyun static void am65_cpsw_get_regs(struct net_device *ndev,
593*4882a593Smuzhiyun 			       struct ethtool_regs *regs, void *p)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
596*4882a593Smuzhiyun 	u32 ale_entries, i, j, pos, *reg = p;
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	/* update CPSW IP version */
599*4882a593Smuzhiyun 	regs->version = AM65_CPSW_REGDUMP_VER;
600*4882a593Smuzhiyun 	ale_entries = cpsw_ale_get_num_entries(common->ale);
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	pos = 0;
603*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
604*4882a593Smuzhiyun 		reg[pos++] = am65_cpsw_regdump[i].hdr.module_id;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 		if (am65_cpsw_regdump[i].hdr.module_id ==
607*4882a593Smuzhiyun 		    AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
608*4882a593Smuzhiyun 			u32 ale_tbl_len = ale_entries *
609*4882a593Smuzhiyun 					  ALE_ENTRY_WORDS * sizeof(u32) +
610*4882a593Smuzhiyun 					  sizeof(struct am65_cpsw_regdump_hdr);
611*4882a593Smuzhiyun 			reg[pos++] = ale_tbl_len;
612*4882a593Smuzhiyun 			cpsw_ale_dump(common->ale, &reg[pos]);
613*4882a593Smuzhiyun 			pos += ale_tbl_len;
614*4882a593Smuzhiyun 			continue;
615*4882a593Smuzhiyun 		}
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 		reg[pos++] = am65_cpsw_regdump[i].hdr.len;
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 		j = am65_cpsw_regdump[i].start_ofs;
620*4882a593Smuzhiyun 		do {
621*4882a593Smuzhiyun 			reg[pos++] = j;
622*4882a593Smuzhiyun 			reg[pos++] = readl_relaxed(common->ss_base + j);
623*4882a593Smuzhiyun 			j += sizeof(u32);
624*4882a593Smuzhiyun 		} while (j <= am65_cpsw_regdump[i].end_ofs);
625*4882a593Smuzhiyun 	}
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun 
am65_cpsw_get_sset_count(struct net_device * ndev,int sset)628*4882a593Smuzhiyun static int am65_cpsw_get_sset_count(struct net_device *ndev, int sset)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun 	switch (sset) {
631*4882a593Smuzhiyun 	case ETH_SS_STATS:
632*4882a593Smuzhiyun 		return ARRAY_SIZE(am65_host_stats) +
633*4882a593Smuzhiyun 		       ARRAY_SIZE(am65_slave_stats);
634*4882a593Smuzhiyun 	case ETH_SS_PRIV_FLAGS:
635*4882a593Smuzhiyun 		return ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
636*4882a593Smuzhiyun 	default:
637*4882a593Smuzhiyun 		return -EOPNOTSUPP;
638*4882a593Smuzhiyun 	}
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun 
am65_cpsw_get_strings(struct net_device * ndev,u32 stringset,u8 * data)641*4882a593Smuzhiyun static void am65_cpsw_get_strings(struct net_device *ndev,
642*4882a593Smuzhiyun 				  u32 stringset, u8 *data)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun 	const struct am65_cpsw_ethtool_stat *hw_stats;
645*4882a593Smuzhiyun 	u32 i, num_stats;
646*4882a593Smuzhiyun 	u8 *p = data;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	switch (stringset) {
649*4882a593Smuzhiyun 	case ETH_SS_STATS:
650*4882a593Smuzhiyun 		num_stats = ARRAY_SIZE(am65_host_stats);
651*4882a593Smuzhiyun 		hw_stats = am65_host_stats;
652*4882a593Smuzhiyun 		for (i = 0; i < num_stats; i++) {
653*4882a593Smuzhiyun 			memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
654*4882a593Smuzhiyun 			p += ETH_GSTRING_LEN;
655*4882a593Smuzhiyun 		}
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 		num_stats = ARRAY_SIZE(am65_slave_stats);
658*4882a593Smuzhiyun 		hw_stats = am65_slave_stats;
659*4882a593Smuzhiyun 		for (i = 0; i < num_stats; i++) {
660*4882a593Smuzhiyun 			memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
661*4882a593Smuzhiyun 			p += ETH_GSTRING_LEN;
662*4882a593Smuzhiyun 		}
663*4882a593Smuzhiyun 		break;
664*4882a593Smuzhiyun 	case ETH_SS_PRIV_FLAGS:
665*4882a593Smuzhiyun 		num_stats = ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 		for (i = 0; i < num_stats; i++) {
668*4882a593Smuzhiyun 			memcpy(p, am65_cpsw_ethtool_priv_flags[i],
669*4882a593Smuzhiyun 			       ETH_GSTRING_LEN);
670*4882a593Smuzhiyun 			p += ETH_GSTRING_LEN;
671*4882a593Smuzhiyun 		}
672*4882a593Smuzhiyun 		break;
673*4882a593Smuzhiyun 	}
674*4882a593Smuzhiyun }
675*4882a593Smuzhiyun 
am65_cpsw_get_ethtool_stats(struct net_device * ndev,struct ethtool_stats * stats,u64 * data)676*4882a593Smuzhiyun static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
677*4882a593Smuzhiyun 					struct ethtool_stats *stats, u64 *data)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
680*4882a593Smuzhiyun 	const struct am65_cpsw_ethtool_stat *hw_stats;
681*4882a593Smuzhiyun 	struct am65_cpsw_host *host_p;
682*4882a593Smuzhiyun 	struct am65_cpsw_port *port;
683*4882a593Smuzhiyun 	u32 i, num_stats;
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	host_p = am65_common_get_host(common);
686*4882a593Smuzhiyun 	port = am65_ndev_to_port(ndev);
687*4882a593Smuzhiyun 	num_stats = ARRAY_SIZE(am65_host_stats);
688*4882a593Smuzhiyun 	hw_stats = am65_host_stats;
689*4882a593Smuzhiyun 	for (i = 0; i < num_stats; i++)
690*4882a593Smuzhiyun 		*data++ = readl_relaxed(host_p->stat_base +
691*4882a593Smuzhiyun 					hw_stats[i].offset);
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	num_stats = ARRAY_SIZE(am65_slave_stats);
694*4882a593Smuzhiyun 	hw_stats = am65_slave_stats;
695*4882a593Smuzhiyun 	for (i = 0; i < num_stats; i++)
696*4882a593Smuzhiyun 		*data++ = readl_relaxed(port->stat_base +
697*4882a593Smuzhiyun 					hw_stats[i].offset);
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun 
am65_cpsw_get_ethtool_ts_info(struct net_device * ndev,struct ethtool_ts_info * info)700*4882a593Smuzhiyun static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
701*4882a593Smuzhiyun 					 struct ethtool_ts_info *info)
702*4882a593Smuzhiyun {
703*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
706*4882a593Smuzhiyun 		return ethtool_op_get_ts_info(ndev, info);
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 	info->so_timestamping =
709*4882a593Smuzhiyun 		SOF_TIMESTAMPING_TX_HARDWARE |
710*4882a593Smuzhiyun 		SOF_TIMESTAMPING_TX_SOFTWARE |
711*4882a593Smuzhiyun 		SOF_TIMESTAMPING_RX_HARDWARE |
712*4882a593Smuzhiyun 		SOF_TIMESTAMPING_RX_SOFTWARE |
713*4882a593Smuzhiyun 		SOF_TIMESTAMPING_SOFTWARE |
714*4882a593Smuzhiyun 		SOF_TIMESTAMPING_RAW_HARDWARE;
715*4882a593Smuzhiyun 	info->phc_index = am65_cpts_phc_index(common->cpts);
716*4882a593Smuzhiyun 	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
717*4882a593Smuzhiyun 	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
718*4882a593Smuzhiyun 	return 0;
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun 
am65_cpsw_get_ethtool_priv_flags(struct net_device * ndev)721*4882a593Smuzhiyun static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
724*4882a593Smuzhiyun 	u32 priv_flags = 0;
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	if (common->pf_p0_rx_ptype_rrobin)
727*4882a593Smuzhiyun 		priv_flags |= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN;
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	return priv_flags;
730*4882a593Smuzhiyun }
731*4882a593Smuzhiyun 
am65_cpsw_set_ethtool_priv_flags(struct net_device * ndev,u32 flags)732*4882a593Smuzhiyun static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
735*4882a593Smuzhiyun 	int rrobin;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	rrobin = !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	if (common->usage_count)
740*4882a593Smuzhiyun 		return -EBUSY;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	if (common->est_enabled && rrobin) {
743*4882a593Smuzhiyun 		netdev_err(ndev,
744*4882a593Smuzhiyun 			   "p0-rx-ptype-rrobin flag conflicts with QOS\n");
745*4882a593Smuzhiyun 		return -EINVAL;
746*4882a593Smuzhiyun 	}
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	common->pf_p0_rx_ptype_rrobin = rrobin;
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 	return 0;
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
754*4882a593Smuzhiyun 	.begin			= am65_cpsw_ethtool_op_begin,
755*4882a593Smuzhiyun 	.complete		= am65_cpsw_ethtool_op_complete,
756*4882a593Smuzhiyun 	.get_drvinfo		= am65_cpsw_get_drvinfo,
757*4882a593Smuzhiyun 	.get_msglevel		= am65_cpsw_get_msglevel,
758*4882a593Smuzhiyun 	.set_msglevel		= am65_cpsw_set_msglevel,
759*4882a593Smuzhiyun 	.get_channels		= am65_cpsw_get_channels,
760*4882a593Smuzhiyun 	.set_channels		= am65_cpsw_set_channels,
761*4882a593Smuzhiyun 	.get_ringparam		= am65_cpsw_get_ringparam,
762*4882a593Smuzhiyun 	.get_regs_len		= am65_cpsw_get_regs_len,
763*4882a593Smuzhiyun 	.get_regs		= am65_cpsw_get_regs,
764*4882a593Smuzhiyun 	.get_sset_count		= am65_cpsw_get_sset_count,
765*4882a593Smuzhiyun 	.get_strings		= am65_cpsw_get_strings,
766*4882a593Smuzhiyun 	.get_ethtool_stats	= am65_cpsw_get_ethtool_stats,
767*4882a593Smuzhiyun 	.get_ts_info		= am65_cpsw_get_ethtool_ts_info,
768*4882a593Smuzhiyun 	.get_priv_flags		= am65_cpsw_get_ethtool_priv_flags,
769*4882a593Smuzhiyun 	.set_priv_flags		= am65_cpsw_set_ethtool_priv_flags,
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 	.get_link		= ethtool_op_get_link,
772*4882a593Smuzhiyun 	.get_link_ksettings	= am65_cpsw_get_link_ksettings,
773*4882a593Smuzhiyun 	.set_link_ksettings	= am65_cpsw_set_link_ksettings,
774*4882a593Smuzhiyun 	.get_pauseparam		= am65_cpsw_get_pauseparam,
775*4882a593Smuzhiyun 	.set_pauseparam		= am65_cpsw_set_pauseparam,
776*4882a593Smuzhiyun 	.get_wol		= am65_cpsw_get_wol,
777*4882a593Smuzhiyun 	.set_wol		= am65_cpsw_set_wol,
778*4882a593Smuzhiyun 	.get_eee		= am65_cpsw_get_eee,
779*4882a593Smuzhiyun 	.set_eee		= am65_cpsw_set_eee,
780*4882a593Smuzhiyun 	.nway_reset		= am65_cpsw_nway_reset,
781*4882a593Smuzhiyun };
782