1 // SPDX-License-Identifier: GPL-2.0
2 /* Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver ethtool ops
4 * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
8 #include <linux/net_tstamp.h>
9 #include <linux/phylink.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
13 #include "am65-cpsw-nuss.h"
14 #include "am65-cpsw-qos.h"
16 #include "am65-cpts.h"
18 #define AM65_CPSW_REGDUMP_VER 0x1
21 AM65_CPSW_REGDUMP_MOD_NUSS
= 1,
22 AM65_CPSW_REGDUMP_MOD_RGMII_STATUS
= 2,
23 AM65_CPSW_REGDUMP_MOD_MDIO
= 3,
24 AM65_CPSW_REGDUMP_MOD_CPSW
= 4,
25 AM65_CPSW_REGDUMP_MOD_CPSW_P0
= 5,
26 AM65_CPSW_REGDUMP_MOD_CPSW_P1
= 6,
27 AM65_CPSW_REGDUMP_MOD_CPSW_CPTS
= 7,
28 AM65_CPSW_REGDUMP_MOD_CPSW_ALE
= 8,
29 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
= 9,
30 AM65_CPSW_REGDUMP_MOD_LAST
,
34 * struct am65_cpsw_regdump_hdr - regdump record header
36 * @module_id: CPSW module ID
37 * @len: CPSW module registers space length in u32
40 struct am65_cpsw_regdump_hdr
{
46 * struct am65_cpsw_regdump_item - regdump module description
48 * @hdr: CPSW module header
49 * @start_ofs: CPSW module registers start addr
50 * @end_ofs: CPSW module registers end addr
52 * Registers dump provided in the format:
55 * u32[..len]: registers values
57 struct am65_cpsw_regdump_item
{
58 struct am65_cpsw_regdump_hdr hdr
;
63 #define AM65_CPSW_REGDUMP_REC(mod, start, end) { \
64 .hdr.module_id = (mod), \
65 .hdr.len = (end + 4 - start) * 2 + \
66 sizeof(struct am65_cpsw_regdump_hdr), \
67 .start_ofs = (start), \
71 static const struct am65_cpsw_regdump_item am65_cpsw_regdump
[] = {
72 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_NUSS
, 0x0, 0x1c),
73 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_RGMII_STATUS
, 0x30, 0x4c),
74 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_MDIO
, 0xf00, 0xffc),
75 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW
, 0x20000, 0x2011c),
76 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P0
, 0x21000, 0x21320),
77 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P1
, 0x22000, 0x223a4),
78 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_CPTS
,
80 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE
, 0x3e000, 0x3e13c),
81 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
, 0, 0),
84 struct am65_cpsw_stats_regs
{
86 u32 rx_broadcast_frames
;
87 u32 rx_multicast_frames
;
88 u32 rx_pause_frames
; /* slave */
90 u32 rx_align_code_errors
; /* slave */
91 u32 rx_oversized_frames
;
92 u32 rx_jabber_frames
; /* slave */
93 u32 rx_undersized_frames
;
94 u32 rx_fragments
; /* slave */
99 u32 tx_broadcast_frames
;
100 u32 tx_multicast_frames
;
101 u32 tx_pause_frames
; /* slave */
102 u32 tx_deferred_frames
; /* slave */
103 u32 tx_collision_frames
; /* slave */
104 u32 tx_single_coll_frames
; /* slave */
105 u32 tx_mult_coll_frames
; /* slave */
106 u32 tx_excessive_collisions
; /* slave */
107 u32 tx_late_collisions
; /* slave */
108 u32 rx_ipg_error
; /* slave 10G only */
109 u32 tx_carrier_sense_errors
; /* slave */
112 u32 tx_65_to_127B_frames
;
113 u32 tx_128_to_255B_frames
;
114 u32 tx_256_to_511B_frames
;
115 u32 tx_512_to_1023B_frames
;
118 u32 rx_bottom_fifo_drop
;
119 u32 rx_port_mask_drop
;
120 u32 rx_top_fifo_drop
;
121 u32 ale_rate_limit_drop
;
122 u32 ale_vid_ingress_drop
;
123 u32 ale_da_eq_sa_drop
;
124 u32 ale_block_drop
; /* K3 */
125 u32 ale_secure_drop
; /* K3 */
126 u32 ale_auth_drop
; /* K3 */
127 u32 ale_unknown_ucast
;
128 u32 ale_unknown_ucast_bytes
;
129 u32 ale_unknown_mcast
;
130 u32 ale_unknown_mcast_bytes
;
131 u32 ale_unknown_bcast
;
132 u32 ale_unknown_bcast_bytes
;
134 u32 ale_pol_match_red
;
135 u32 ale_pol_match_yellow
;
136 u32 ale_mcast_sa_drop
; /* K3 */
137 u32 ale_dual_vlan_drop
; /* K3 */
138 u32 ale_len_err_drop
; /* K3 */
139 u32 ale_ip_next_hdr_drop
; /* K3 */
140 u32 ale_ipv4_frag_drop
; /* K3 */
142 u32 iet_rx_assembly_err
; /* K3 slave */
143 u32 iet_rx_assembly_ok
; /* K3 slave */
144 u32 iet_rx_smd_err
; /* K3 slave */
145 u32 iet_rx_frag
; /* K3 slave */
146 u32 iet_tx_hold
; /* K3 slave */
147 u32 iet_tx_frag
; /* K3 slave */
149 u32 tx_mem_protect_err
;
150 /* following NU only */
175 u32 tx_pri0_drop_bcnt
;
176 u32 tx_pri1_drop_bcnt
;
177 u32 tx_pri2_drop_bcnt
;
178 u32 tx_pri3_drop_bcnt
;
179 u32 tx_pri4_drop_bcnt
;
180 u32 tx_pri5_drop_bcnt
;
181 u32 tx_pri6_drop_bcnt
;
182 u32 tx_pri7_drop_bcnt
;
185 struct am65_cpsw_ethtool_stat
{
186 char desc
[ETH_GSTRING_LEN
];
190 #define AM65_CPSW_STATS(prefix, field) \
193 offsetof(struct am65_cpsw_stats_regs, field) \
196 static const struct am65_cpsw_ethtool_stat am65_host_stats
[] = {
197 AM65_CPSW_STATS(p0_
, rx_good_frames
),
198 AM65_CPSW_STATS(p0_
, rx_broadcast_frames
),
199 AM65_CPSW_STATS(p0_
, rx_multicast_frames
),
200 AM65_CPSW_STATS(p0_
, rx_crc_errors
),
201 AM65_CPSW_STATS(p0_
, rx_oversized_frames
),
202 AM65_CPSW_STATS(p0_
, rx_undersized_frames
),
203 AM65_CPSW_STATS(p0_
, ale_drop
),
204 AM65_CPSW_STATS(p0_
, ale_overrun_drop
),
205 AM65_CPSW_STATS(p0_
, rx_octets
),
206 AM65_CPSW_STATS(p0_
, tx_good_frames
),
207 AM65_CPSW_STATS(p0_
, tx_broadcast_frames
),
208 AM65_CPSW_STATS(p0_
, tx_multicast_frames
),
209 AM65_CPSW_STATS(p0_
, tx_octets
),
210 AM65_CPSW_STATS(p0_
, tx_64B_frames
),
211 AM65_CPSW_STATS(p0_
, tx_65_to_127B_frames
),
212 AM65_CPSW_STATS(p0_
, tx_128_to_255B_frames
),
213 AM65_CPSW_STATS(p0_
, tx_256_to_511B_frames
),
214 AM65_CPSW_STATS(p0_
, tx_512_to_1023B_frames
),
215 AM65_CPSW_STATS(p0_
, tx_1024B_frames
),
216 AM65_CPSW_STATS(p0_
, net_octets
),
217 AM65_CPSW_STATS(p0_
, rx_bottom_fifo_drop
),
218 AM65_CPSW_STATS(p0_
, rx_port_mask_drop
),
219 AM65_CPSW_STATS(p0_
, rx_top_fifo_drop
),
220 AM65_CPSW_STATS(p0_
, ale_rate_limit_drop
),
221 AM65_CPSW_STATS(p0_
, ale_vid_ingress_drop
),
222 AM65_CPSW_STATS(p0_
, ale_da_eq_sa_drop
),
223 AM65_CPSW_STATS(p0_
, ale_block_drop
),
224 AM65_CPSW_STATS(p0_
, ale_secure_drop
),
225 AM65_CPSW_STATS(p0_
, ale_auth_drop
),
226 AM65_CPSW_STATS(p0_
, ale_unknown_ucast
),
227 AM65_CPSW_STATS(p0_
, ale_unknown_ucast_bytes
),
228 AM65_CPSW_STATS(p0_
, ale_unknown_mcast
),
229 AM65_CPSW_STATS(p0_
, ale_unknown_mcast_bytes
),
230 AM65_CPSW_STATS(p0_
, ale_unknown_bcast
),
231 AM65_CPSW_STATS(p0_
, ale_unknown_bcast_bytes
),
232 AM65_CPSW_STATS(p0_
, ale_pol_match
),
233 AM65_CPSW_STATS(p0_
, ale_pol_match_red
),
234 AM65_CPSW_STATS(p0_
, ale_pol_match_yellow
),
235 AM65_CPSW_STATS(p0_
, ale_mcast_sa_drop
),
236 AM65_CPSW_STATS(p0_
, ale_dual_vlan_drop
),
237 AM65_CPSW_STATS(p0_
, ale_len_err_drop
),
238 AM65_CPSW_STATS(p0_
, ale_ip_next_hdr_drop
),
239 AM65_CPSW_STATS(p0_
, ale_ipv4_frag_drop
),
240 AM65_CPSW_STATS(p0_
, tx_mem_protect_err
),
241 AM65_CPSW_STATS(p0_
, tx_pri0
),
242 AM65_CPSW_STATS(p0_
, tx_pri1
),
243 AM65_CPSW_STATS(p0_
, tx_pri2
),
244 AM65_CPSW_STATS(p0_
, tx_pri3
),
245 AM65_CPSW_STATS(p0_
, tx_pri4
),
246 AM65_CPSW_STATS(p0_
, tx_pri5
),
247 AM65_CPSW_STATS(p0_
, tx_pri6
),
248 AM65_CPSW_STATS(p0_
, tx_pri7
),
249 AM65_CPSW_STATS(p0_
, tx_pri0_bcnt
),
250 AM65_CPSW_STATS(p0_
, tx_pri1_bcnt
),
251 AM65_CPSW_STATS(p0_
, tx_pri2_bcnt
),
252 AM65_CPSW_STATS(p0_
, tx_pri3_bcnt
),
253 AM65_CPSW_STATS(p0_
, tx_pri4_bcnt
),
254 AM65_CPSW_STATS(p0_
, tx_pri5_bcnt
),
255 AM65_CPSW_STATS(p0_
, tx_pri6_bcnt
),
256 AM65_CPSW_STATS(p0_
, tx_pri7_bcnt
),
257 AM65_CPSW_STATS(p0_
, tx_pri0_drop
),
258 AM65_CPSW_STATS(p0_
, tx_pri1_drop
),
259 AM65_CPSW_STATS(p0_
, tx_pri2_drop
),
260 AM65_CPSW_STATS(p0_
, tx_pri3_drop
),
261 AM65_CPSW_STATS(p0_
, tx_pri4_drop
),
262 AM65_CPSW_STATS(p0_
, tx_pri5_drop
),
263 AM65_CPSW_STATS(p0_
, tx_pri6_drop
),
264 AM65_CPSW_STATS(p0_
, tx_pri7_drop
),
265 AM65_CPSW_STATS(p0_
, tx_pri0_drop_bcnt
),
266 AM65_CPSW_STATS(p0_
, tx_pri1_drop_bcnt
),
267 AM65_CPSW_STATS(p0_
, tx_pri2_drop_bcnt
),
268 AM65_CPSW_STATS(p0_
, tx_pri3_drop_bcnt
),
269 AM65_CPSW_STATS(p0_
, tx_pri4_drop_bcnt
),
270 AM65_CPSW_STATS(p0_
, tx_pri5_drop_bcnt
),
271 AM65_CPSW_STATS(p0_
, tx_pri6_drop_bcnt
),
272 AM65_CPSW_STATS(p0_
, tx_pri7_drop_bcnt
),
275 static const struct am65_cpsw_ethtool_stat am65_slave_stats
[] = {
276 AM65_CPSW_STATS(, rx_good_frames
),
277 AM65_CPSW_STATS(, rx_broadcast_frames
),
278 AM65_CPSW_STATS(, rx_multicast_frames
),
279 AM65_CPSW_STATS(, rx_pause_frames
),
280 AM65_CPSW_STATS(, rx_crc_errors
),
281 AM65_CPSW_STATS(, rx_align_code_errors
),
282 AM65_CPSW_STATS(, rx_oversized_frames
),
283 AM65_CPSW_STATS(, rx_jabber_frames
),
284 AM65_CPSW_STATS(, rx_undersized_frames
),
285 AM65_CPSW_STATS(, rx_fragments
),
286 AM65_CPSW_STATS(, ale_drop
),
287 AM65_CPSW_STATS(, ale_overrun_drop
),
288 AM65_CPSW_STATS(, rx_octets
),
289 AM65_CPSW_STATS(, tx_good_frames
),
290 AM65_CPSW_STATS(, tx_broadcast_frames
),
291 AM65_CPSW_STATS(, tx_multicast_frames
),
292 AM65_CPSW_STATS(, tx_pause_frames
),
293 AM65_CPSW_STATS(, tx_deferred_frames
),
294 AM65_CPSW_STATS(, tx_collision_frames
),
295 AM65_CPSW_STATS(, tx_single_coll_frames
),
296 AM65_CPSW_STATS(, tx_mult_coll_frames
),
297 AM65_CPSW_STATS(, tx_excessive_collisions
),
298 AM65_CPSW_STATS(, tx_late_collisions
),
299 AM65_CPSW_STATS(, rx_ipg_error
),
300 AM65_CPSW_STATS(, tx_carrier_sense_errors
),
301 AM65_CPSW_STATS(, tx_octets
),
302 AM65_CPSW_STATS(, tx_64B_frames
),
303 AM65_CPSW_STATS(, tx_65_to_127B_frames
),
304 AM65_CPSW_STATS(, tx_128_to_255B_frames
),
305 AM65_CPSW_STATS(, tx_256_to_511B_frames
),
306 AM65_CPSW_STATS(, tx_512_to_1023B_frames
),
307 AM65_CPSW_STATS(, tx_1024B_frames
),
308 AM65_CPSW_STATS(, net_octets
),
309 AM65_CPSW_STATS(, rx_bottom_fifo_drop
),
310 AM65_CPSW_STATS(, rx_port_mask_drop
),
311 AM65_CPSW_STATS(, rx_top_fifo_drop
),
312 AM65_CPSW_STATS(, ale_rate_limit_drop
),
313 AM65_CPSW_STATS(, ale_vid_ingress_drop
),
314 AM65_CPSW_STATS(, ale_da_eq_sa_drop
),
315 AM65_CPSW_STATS(, ale_block_drop
),
316 AM65_CPSW_STATS(, ale_secure_drop
),
317 AM65_CPSW_STATS(, ale_auth_drop
),
318 AM65_CPSW_STATS(, ale_unknown_ucast
),
319 AM65_CPSW_STATS(, ale_unknown_ucast_bytes
),
320 AM65_CPSW_STATS(, ale_unknown_mcast
),
321 AM65_CPSW_STATS(, ale_unknown_mcast_bytes
),
322 AM65_CPSW_STATS(, ale_unknown_bcast
),
323 AM65_CPSW_STATS(, ale_unknown_bcast_bytes
),
324 AM65_CPSW_STATS(, ale_pol_match
),
325 AM65_CPSW_STATS(, ale_pol_match_red
),
326 AM65_CPSW_STATS(, ale_pol_match_yellow
),
327 AM65_CPSW_STATS(, ale_mcast_sa_drop
),
328 AM65_CPSW_STATS(, ale_dual_vlan_drop
),
329 AM65_CPSW_STATS(, ale_len_err_drop
),
330 AM65_CPSW_STATS(, ale_ip_next_hdr_drop
),
331 AM65_CPSW_STATS(, ale_ipv4_frag_drop
),
332 AM65_CPSW_STATS(, iet_rx_assembly_err
),
333 AM65_CPSW_STATS(, iet_rx_assembly_ok
),
334 AM65_CPSW_STATS(, iet_rx_smd_err
),
335 AM65_CPSW_STATS(, iet_rx_frag
),
336 AM65_CPSW_STATS(, iet_tx_hold
),
337 AM65_CPSW_STATS(, iet_tx_frag
),
338 AM65_CPSW_STATS(, tx_mem_protect_err
),
339 AM65_CPSW_STATS(, tx_pri0
),
340 AM65_CPSW_STATS(, tx_pri1
),
341 AM65_CPSW_STATS(, tx_pri2
),
342 AM65_CPSW_STATS(, tx_pri3
),
343 AM65_CPSW_STATS(, tx_pri4
),
344 AM65_CPSW_STATS(, tx_pri5
),
345 AM65_CPSW_STATS(, tx_pri6
),
346 AM65_CPSW_STATS(, tx_pri7
),
347 AM65_CPSW_STATS(, tx_pri0_bcnt
),
348 AM65_CPSW_STATS(, tx_pri1_bcnt
),
349 AM65_CPSW_STATS(, tx_pri2_bcnt
),
350 AM65_CPSW_STATS(, tx_pri3_bcnt
),
351 AM65_CPSW_STATS(, tx_pri4_bcnt
),
352 AM65_CPSW_STATS(, tx_pri5_bcnt
),
353 AM65_CPSW_STATS(, tx_pri6_bcnt
),
354 AM65_CPSW_STATS(, tx_pri7_bcnt
),
355 AM65_CPSW_STATS(, tx_pri0_drop
),
356 AM65_CPSW_STATS(, tx_pri1_drop
),
357 AM65_CPSW_STATS(, tx_pri2_drop
),
358 AM65_CPSW_STATS(, tx_pri3_drop
),
359 AM65_CPSW_STATS(, tx_pri4_drop
),
360 AM65_CPSW_STATS(, tx_pri5_drop
),
361 AM65_CPSW_STATS(, tx_pri6_drop
),
362 AM65_CPSW_STATS(, tx_pri7_drop
),
363 AM65_CPSW_STATS(, tx_pri0_drop_bcnt
),
364 AM65_CPSW_STATS(, tx_pri1_drop_bcnt
),
365 AM65_CPSW_STATS(, tx_pri2_drop_bcnt
),
366 AM65_CPSW_STATS(, tx_pri3_drop_bcnt
),
367 AM65_CPSW_STATS(, tx_pri4_drop_bcnt
),
368 AM65_CPSW_STATS(, tx_pri5_drop_bcnt
),
369 AM65_CPSW_STATS(, tx_pri6_drop_bcnt
),
370 AM65_CPSW_STATS(, tx_pri7_drop_bcnt
),
373 /* Ethtool priv_flags */
374 static const char am65_cpsw_ethtool_priv_flags
[][ETH_GSTRING_LEN
] = {
375 #define AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN BIT(0)
376 "p0-rx-ptype-rrobin",
379 static int am65_cpsw_ethtool_op_begin(struct net_device
*ndev
)
381 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
384 ret
= pm_runtime_resume_and_get(common
->dev
);
386 dev_err(common
->dev
, "ethtool begin failed %d\n", ret
);
391 static void am65_cpsw_ethtool_op_complete(struct net_device
*ndev
)
393 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
396 ret
= pm_runtime_put(common
->dev
);
397 if (ret
< 0 && ret
!= -EBUSY
)
398 dev_err(common
->dev
, "ethtool complete failed %d\n", ret
);
401 static void am65_cpsw_get_drvinfo(struct net_device
*ndev
,
402 struct ethtool_drvinfo
*info
)
404 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
406 strscpy(info
->driver
, dev_driver_string(common
->dev
),
407 sizeof(info
->driver
));
408 strscpy(info
->bus_info
, dev_name(common
->dev
), sizeof(info
->bus_info
));
411 static u32
am65_cpsw_get_msglevel(struct net_device
*ndev
)
413 struct am65_cpsw_ndev_priv
*priv
= am65_ndev_to_priv(ndev
);
415 return priv
->msg_enable
;
418 static void am65_cpsw_set_msglevel(struct net_device
*ndev
, u32 value
)
420 struct am65_cpsw_ndev_priv
*priv
= am65_ndev_to_priv(ndev
);
422 priv
->msg_enable
= value
;
425 static void am65_cpsw_get_channels(struct net_device
*ndev
,
426 struct ethtool_channels
*ch
)
428 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
430 ch
->max_rx
= AM65_CPSW_MAX_QUEUES
;
431 ch
->max_tx
= AM65_CPSW_MAX_QUEUES
;
432 ch
->rx_count
= common
->rx_ch_num_flows
;
433 ch
->tx_count
= common
->tx_ch_num
;
436 static int am65_cpsw_set_channels(struct net_device
*ndev
,
437 struct ethtool_channels
*chs
)
439 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
441 if (!chs
->rx_count
|| !chs
->tx_count
)
444 /* Check if interface is up. Can change the num queues when
445 * the interface is down.
447 if (common
->usage_count
)
450 return am65_cpsw_nuss_update_tx_rx_chns(common
, chs
->tx_count
,
455 am65_cpsw_get_ringparam(struct net_device
*ndev
,
456 struct ethtool_ringparam
*ering
,
457 struct kernel_ethtool_ringparam
*kernel_ering
,
458 struct netlink_ext_ack
*extack
)
460 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
463 ering
->tx_pending
= common
->tx_chns
[0].descs_num
;
464 ering
->rx_pending
= common
->rx_chns
.descs_num
;
467 static void am65_cpsw_get_pauseparam(struct net_device
*ndev
,
468 struct ethtool_pauseparam
*pause
)
470 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
472 phylink_ethtool_get_pauseparam(salve
->phylink
, pause
);
475 static int am65_cpsw_set_pauseparam(struct net_device
*ndev
,
476 struct ethtool_pauseparam
*pause
)
478 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
480 return phylink_ethtool_set_pauseparam(salve
->phylink
, pause
);
483 static void am65_cpsw_get_wol(struct net_device
*ndev
,
484 struct ethtool_wolinfo
*wol
)
486 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
488 phylink_ethtool_get_wol(salve
->phylink
, wol
);
491 static int am65_cpsw_set_wol(struct net_device
*ndev
,
492 struct ethtool_wolinfo
*wol
)
494 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
496 return phylink_ethtool_set_wol(salve
->phylink
, wol
);
499 static int am65_cpsw_get_link_ksettings(struct net_device
*ndev
,
500 struct ethtool_link_ksettings
*ecmd
)
502 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
504 return phylink_ethtool_ksettings_get(salve
->phylink
, ecmd
);
508 am65_cpsw_set_link_ksettings(struct net_device
*ndev
,
509 const struct ethtool_link_ksettings
*ecmd
)
511 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
513 return phylink_ethtool_ksettings_set(salve
->phylink
, ecmd
);
516 static int am65_cpsw_get_eee(struct net_device
*ndev
, struct ethtool_keee
*edata
)
518 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
520 return phylink_ethtool_get_eee(salve
->phylink
, edata
);
523 static int am65_cpsw_set_eee(struct net_device
*ndev
, struct ethtool_keee
*edata
)
525 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
527 return phylink_ethtool_set_eee(salve
->phylink
, edata
);
530 static int am65_cpsw_nway_reset(struct net_device
*ndev
)
532 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
534 return phylink_ethtool_nway_reset(salve
->phylink
);
537 static int am65_cpsw_get_regs_len(struct net_device
*ndev
)
539 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
540 u32 ale_entries
, i
, regdump_len
= 0;
542 ale_entries
= cpsw_ale_get_num_entries(common
->ale
);
543 for (i
= 0; i
< ARRAY_SIZE(am65_cpsw_regdump
); i
++) {
544 if (am65_cpsw_regdump
[i
].hdr
.module_id
==
545 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
) {
546 regdump_len
+= sizeof(struct am65_cpsw_regdump_hdr
);
547 regdump_len
+= ale_entries
*
548 ALE_ENTRY_WORDS
* sizeof(u32
);
551 regdump_len
+= am65_cpsw_regdump
[i
].hdr
.len
;
557 static void am65_cpsw_get_regs(struct net_device
*ndev
,
558 struct ethtool_regs
*regs
, void *p
)
560 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
561 u32 ale_entries
, i
, j
, pos
, *reg
= p
;
563 /* update CPSW IP version */
564 regs
->version
= AM65_CPSW_REGDUMP_VER
;
565 ale_entries
= cpsw_ale_get_num_entries(common
->ale
);
568 for (i
= 0; i
< ARRAY_SIZE(am65_cpsw_regdump
); i
++) {
569 reg
[pos
++] = am65_cpsw_regdump
[i
].hdr
.module_id
;
571 if (am65_cpsw_regdump
[i
].hdr
.module_id
==
572 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
) {
573 u32 ale_tbl_len
= ale_entries
*
574 ALE_ENTRY_WORDS
* sizeof(u32
) +
575 sizeof(struct am65_cpsw_regdump_hdr
);
576 reg
[pos
++] = ale_tbl_len
;
577 cpsw_ale_dump(common
->ale
, ®
[pos
]);
582 reg
[pos
++] = am65_cpsw_regdump
[i
].hdr
.len
;
584 j
= am65_cpsw_regdump
[i
].start_ofs
;
587 reg
[pos
++] = readl_relaxed(common
->ss_base
+ j
);
589 } while (j
<= am65_cpsw_regdump
[i
].end_ofs
);
593 static int am65_cpsw_get_sset_count(struct net_device
*ndev
, int sset
)
597 return ARRAY_SIZE(am65_host_stats
) +
598 ARRAY_SIZE(am65_slave_stats
);
599 case ETH_SS_PRIV_FLAGS
:
600 return ARRAY_SIZE(am65_cpsw_ethtool_priv_flags
);
606 static void am65_cpsw_get_strings(struct net_device
*ndev
,
607 u32 stringset
, u8
*data
)
609 const struct am65_cpsw_ethtool_stat
*hw_stats
;
615 num_stats
= ARRAY_SIZE(am65_host_stats
);
616 hw_stats
= am65_host_stats
;
617 for (i
= 0; i
< num_stats
; i
++) {
618 memcpy(p
, hw_stats
[i
].desc
, ETH_GSTRING_LEN
);
619 p
+= ETH_GSTRING_LEN
;
622 num_stats
= ARRAY_SIZE(am65_slave_stats
);
623 hw_stats
= am65_slave_stats
;
624 for (i
= 0; i
< num_stats
; i
++) {
625 memcpy(p
, hw_stats
[i
].desc
, ETH_GSTRING_LEN
);
626 p
+= ETH_GSTRING_LEN
;
629 case ETH_SS_PRIV_FLAGS
:
630 num_stats
= ARRAY_SIZE(am65_cpsw_ethtool_priv_flags
);
632 for (i
= 0; i
< num_stats
; i
++) {
633 memcpy(p
, am65_cpsw_ethtool_priv_flags
[i
],
635 p
+= ETH_GSTRING_LEN
;
641 static void am65_cpsw_get_ethtool_stats(struct net_device
*ndev
,
642 struct ethtool_stats
*stats
, u64
*data
)
644 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
645 const struct am65_cpsw_ethtool_stat
*hw_stats
;
646 struct am65_cpsw_host
*host_p
;
647 struct am65_cpsw_port
*port
;
650 host_p
= am65_common_get_host(common
);
651 port
= am65_ndev_to_port(ndev
);
652 num_stats
= ARRAY_SIZE(am65_host_stats
);
653 hw_stats
= am65_host_stats
;
654 for (i
= 0; i
< num_stats
; i
++)
655 *data
++ = readl_relaxed(host_p
->stat_base
+
658 num_stats
= ARRAY_SIZE(am65_slave_stats
);
659 hw_stats
= am65_slave_stats
;
660 for (i
= 0; i
< num_stats
; i
++)
661 *data
++ = readl_relaxed(port
->stat_base
+
665 static void am65_cpsw_get_eth_mac_stats(struct net_device
*ndev
,
666 struct ethtool_eth_mac_stats
*s
)
668 struct am65_cpsw_port
*port
= am65_ndev_to_port(ndev
);
669 struct am65_cpsw_stats_regs __iomem
*stats
;
671 stats
= port
->stat_base
;
673 if (s
->src
!= ETHTOOL_MAC_STATS_SRC_AGGREGATE
)
676 s
->FramesTransmittedOK
= readl_relaxed(&stats
->tx_good_frames
);
677 s
->SingleCollisionFrames
= readl_relaxed(&stats
->tx_single_coll_frames
);
678 s
->MultipleCollisionFrames
= readl_relaxed(&stats
->tx_mult_coll_frames
);
679 s
->FramesReceivedOK
= readl_relaxed(&stats
->rx_good_frames
);
680 s
->FrameCheckSequenceErrors
= readl_relaxed(&stats
->rx_crc_errors
);
681 s
->AlignmentErrors
= readl_relaxed(&stats
->rx_align_code_errors
);
682 s
->OctetsTransmittedOK
= readl_relaxed(&stats
->tx_octets
);
683 s
->FramesWithDeferredXmissions
= readl_relaxed(&stats
->tx_deferred_frames
);
684 s
->LateCollisions
= readl_relaxed(&stats
->tx_late_collisions
);
685 s
->CarrierSenseErrors
= readl_relaxed(&stats
->tx_carrier_sense_errors
);
686 s
->OctetsReceivedOK
= readl_relaxed(&stats
->rx_octets
);
687 s
->MulticastFramesXmittedOK
= readl_relaxed(&stats
->tx_multicast_frames
);
688 s
->BroadcastFramesXmittedOK
= readl_relaxed(&stats
->tx_broadcast_frames
);
689 s
->MulticastFramesReceivedOK
= readl_relaxed(&stats
->rx_multicast_frames
);
690 s
->BroadcastFramesReceivedOK
= readl_relaxed(&stats
->rx_broadcast_frames
);
693 static int am65_cpsw_get_ethtool_ts_info(struct net_device
*ndev
,
694 struct kernel_ethtool_ts_info
*info
)
696 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
697 unsigned int ptp_v2_filter
;
699 ptp_v2_filter
= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT
) |
700 BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC
) |
701 BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ
) |
702 BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT
) |
703 BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC
) |
704 BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ
) |
705 BIT(HWTSTAMP_FILTER_PTP_V2_EVENT
) |
706 BIT(HWTSTAMP_FILTER_PTP_V2_SYNC
) |
707 BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ
);
709 if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS
))
710 return ethtool_op_get_ts_info(ndev
, info
);
712 info
->so_timestamping
=
713 SOF_TIMESTAMPING_TX_HARDWARE
|
714 SOF_TIMESTAMPING_TX_SOFTWARE
|
715 SOF_TIMESTAMPING_RX_HARDWARE
|
716 SOF_TIMESTAMPING_RAW_HARDWARE
;
717 info
->phc_index
= am65_cpts_phc_index(common
->cpts
);
718 info
->tx_types
= BIT(HWTSTAMP_TX_OFF
) | BIT(HWTSTAMP_TX_ON
);
719 info
->rx_filters
= BIT(HWTSTAMP_FILTER_NONE
) | ptp_v2_filter
;
723 static u32
am65_cpsw_get_ethtool_priv_flags(struct net_device
*ndev
)
725 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
728 if (common
->pf_p0_rx_ptype_rrobin
)
729 priv_flags
|= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN
;
734 static int am65_cpsw_set_ethtool_priv_flags(struct net_device
*ndev
, u32 flags
)
736 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
739 rrobin
= !!(flags
& AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN
);
741 if (common
->usage_count
)
744 if (common
->est_enabled
&& rrobin
) {
746 "p0-rx-ptype-rrobin flag conflicts with QOS\n");
750 common
->pf_p0_rx_ptype_rrobin
= rrobin
;
755 static void am65_cpsw_port_iet_rx_enable(struct am65_cpsw_port
*port
, bool enable
)
759 val
= readl(port
->port_base
+ AM65_CPSW_PN_REG_CTL
);
761 val
|= AM65_CPSW_PN_CTL_IET_PORT_EN
;
763 val
&= ~AM65_CPSW_PN_CTL_IET_PORT_EN
;
765 writel(val
, port
->port_base
+ AM65_CPSW_PN_REG_CTL
);
766 am65_cpsw_iet_common_enable(port
->common
);
769 static void am65_cpsw_port_iet_tx_enable(struct am65_cpsw_port
*port
, bool enable
)
773 val
= readl(port
->port_base
+ AM65_CPSW_PN_REG_IET_CTRL
);
775 val
|= AM65_CPSW_PN_IET_MAC_PENABLE
;
777 val
&= ~AM65_CPSW_PN_IET_MAC_PENABLE
;
779 writel(val
, port
->port_base
+ AM65_CPSW_PN_REG_IET_CTRL
);
782 static int am65_cpsw_get_mm(struct net_device
*ndev
, struct ethtool_mm_state
*state
)
784 struct am65_cpsw_port
*port
= am65_ndev_to_port(ndev
);
785 struct am65_cpsw_ndev_priv
*priv
= netdev_priv(ndev
);
786 u32 port_ctrl
, iet_ctrl
, iet_status
;
789 if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS
))
792 mutex_lock(&priv
->mm_lock
);
794 iet_ctrl
= readl(port
->port_base
+ AM65_CPSW_PN_REG_IET_CTRL
);
795 port_ctrl
= readl(port
->port_base
+ AM65_CPSW_PN_REG_CTL
);
797 state
->tx_enabled
= !!(iet_ctrl
& AM65_CPSW_PN_IET_MAC_PENABLE
);
798 state
->pmac_enabled
= !!(port_ctrl
& AM65_CPSW_PN_CTL_IET_PORT_EN
);
800 iet_status
= readl(port
->port_base
+ AM65_CPSW_PN_REG_IET_STATUS
);
802 if (iet_ctrl
& AM65_CPSW_PN_IET_MAC_DISABLEVERIFY
)
803 state
->verify_status
= ETHTOOL_MM_VERIFY_STATUS_DISABLED
;
804 else if (iet_status
& AM65_CPSW_PN_MAC_VERIFIED
)
805 state
->verify_status
= ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED
;
806 else if (iet_status
& AM65_CPSW_PN_MAC_VERIFY_FAIL
)
807 state
->verify_status
= ETHTOOL_MM_VERIFY_STATUS_FAILED
;
809 state
->verify_status
= ETHTOOL_MM_VERIFY_STATUS_UNKNOWN
;
811 add_frag_size
= AM65_CPSW_PN_IET_MAC_GET_ADDFRAGSIZE(iet_ctrl
);
812 state
->tx_min_frag_size
= ethtool_mm_frag_size_add_to_min(add_frag_size
);
814 /* Errata i2208: RX min fragment size cannot be less than 124 */
815 state
->rx_min_frag_size
= 124;
817 /* FPE active if common tx_enabled and verification success or disabled (forced) */
818 state
->tx_active
= state
->tx_enabled
&&
819 (state
->verify_status
== ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED
||
820 state
->verify_status
== ETHTOOL_MM_VERIFY_STATUS_DISABLED
);
821 state
->verify_enabled
= !(iet_ctrl
& AM65_CPSW_PN_IET_MAC_DISABLEVERIFY
);
823 state
->verify_time
= port
->qos
.iet
.verify_time_ms
;
825 /* 802.3-2018 clause 30.14.1.6, says that the aMACMergeVerifyTime
826 * variable has a range between 1 and 128 ms inclusive. Limit to that.
828 state
->max_verify_time
= 128;
830 mutex_unlock(&priv
->mm_lock
);
835 static int am65_cpsw_set_mm(struct net_device
*ndev
, struct ethtool_mm_cfg
*cfg
,
836 struct netlink_ext_ack
*extack
)
838 struct am65_cpsw_port
*port
= am65_ndev_to_port(ndev
);
839 struct am65_cpsw_ndev_priv
*priv
= netdev_priv(ndev
);
840 struct am65_cpsw_iet
*iet
= &port
->qos
.iet
;
841 u32 val
, add_frag_size
;
844 if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS
))
847 err
= ethtool_mm_frag_size_min_to_add(cfg
->tx_min_frag_size
, &add_frag_size
, extack
);
851 mutex_lock(&priv
->mm_lock
);
853 if (cfg
->pmac_enabled
) {
854 /* change TX & RX FIFO MAX_BLKS as per TRM recommendation */
855 if (!iet
->original_max_blks
)
856 iet
->original_max_blks
= readl(port
->port_base
+ AM65_CPSW_PN_REG_MAX_BLKS
);
858 writel(AM65_CPSW_PN_TX_RX_MAX_BLKS_IET
,
859 port
->port_base
+ AM65_CPSW_PN_REG_MAX_BLKS
);
860 } else if (iet
->original_max_blks
) {
861 /* restore RX & TX FIFO MAX_BLKS */
862 writel(iet
->original_max_blks
,
863 port
->port_base
+ AM65_CPSW_PN_REG_MAX_BLKS
);
866 am65_cpsw_port_iet_rx_enable(port
, cfg
->pmac_enabled
);
867 am65_cpsw_port_iet_tx_enable(port
, cfg
->tx_enabled
);
869 val
= readl(port
->port_base
+ AM65_CPSW_PN_REG_IET_CTRL
);
870 if (cfg
->verify_enabled
) {
871 val
&= ~AM65_CPSW_PN_IET_MAC_DISABLEVERIFY
;
872 /* Reset Verify state machine. Verification won't start here.
873 * Verification will be done once link-up.
875 val
|= AM65_CPSW_PN_IET_MAC_LINKFAIL
;
877 val
|= AM65_CPSW_PN_IET_MAC_DISABLEVERIFY
;
878 /* Clear LINKFAIL to allow verify/response packets */
879 val
&= ~AM65_CPSW_PN_IET_MAC_LINKFAIL
;
882 val
&= ~AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK
;
883 val
|= AM65_CPSW_PN_IET_MAC_SET_ADDFRAGSIZE(add_frag_size
);
884 writel(val
, port
->port_base
+ AM65_CPSW_PN_REG_IET_CTRL
);
886 /* verify_timeout_count can only be set at valid link */
887 port
->qos
.iet
.verify_time_ms
= cfg
->verify_time
;
889 /* enable/disable preemption based on link status */
890 am65_cpsw_iet_commit_preemptible_tcs(port
);
892 mutex_unlock(&priv
->mm_lock
);
897 static void am65_cpsw_get_mm_stats(struct net_device
*ndev
,
898 struct ethtool_mm_stats
*s
)
900 struct am65_cpsw_port
*port
= am65_ndev_to_port(ndev
);
901 void __iomem
*base
= port
->stat_base
;
903 s
->MACMergeFrameAssOkCount
= readl(base
+ AM65_CPSW_STATN_IET_RX_ASSEMBLY_OK
);
904 s
->MACMergeFrameAssErrorCount
= readl(base
+ AM65_CPSW_STATN_IET_RX_ASSEMBLY_ERROR
);
905 s
->MACMergeFrameSmdErrorCount
= readl(base
+ AM65_CPSW_STATN_IET_RX_SMD_ERROR
);
906 /* CPSW Functional Spec states:
907 * "The IET stat aMACMergeFragCountRx is derived by adding the
908 * Receive Assembly Error count to this value. i.e. AM65_CPSW_STATN_IET_RX_FRAG"
910 s
->MACMergeFragCountRx
= readl(base
+ AM65_CPSW_STATN_IET_RX_FRAG
) + s
->MACMergeFrameAssErrorCount
;
911 s
->MACMergeFragCountTx
= readl(base
+ AM65_CPSW_STATN_IET_TX_FRAG
);
912 s
->MACMergeHoldCount
= readl(base
+ AM65_CPSW_STATN_IET_TX_HOLD
);
915 static int am65_cpsw_get_per_queue_coalesce(struct net_device
*ndev
, u32 queue
,
916 struct ethtool_coalesce
*coal
)
918 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
919 struct am65_cpsw_rx_flow
*rx_flow
;
920 struct am65_cpsw_tx_chn
*tx_chn
;
922 if (queue
>= AM65_CPSW_MAX_QUEUES
)
925 tx_chn
= &common
->tx_chns
[queue
];
926 coal
->tx_coalesce_usecs
= tx_chn
->tx_pace_timeout
/ 1000;
928 rx_flow
= &common
->rx_chns
.flows
[queue
];
929 coal
->rx_coalesce_usecs
= rx_flow
->rx_pace_timeout
/ 1000;
934 static int am65_cpsw_get_coalesce(struct net_device
*ndev
, struct ethtool_coalesce
*coal
,
935 struct kernel_ethtool_coalesce
*kernel_coal
,
936 struct netlink_ext_ack
*extack
)
938 return am65_cpsw_get_per_queue_coalesce(ndev
, 0, coal
);
941 static int am65_cpsw_set_per_queue_coalesce(struct net_device
*ndev
, u32 queue
,
942 struct ethtool_coalesce
*coal
)
944 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
945 struct am65_cpsw_rx_flow
*rx_flow
;
946 struct am65_cpsw_tx_chn
*tx_chn
;
948 if (queue
>= AM65_CPSW_MAX_QUEUES
)
951 tx_chn
= &common
->tx_chns
[queue
];
952 if (coal
->tx_coalesce_usecs
&& coal
->tx_coalesce_usecs
< 20)
955 tx_chn
->tx_pace_timeout
= coal
->tx_coalesce_usecs
* 1000;
957 rx_flow
= &common
->rx_chns
.flows
[queue
];
958 if (coal
->rx_coalesce_usecs
&& coal
->rx_coalesce_usecs
< 20)
961 rx_flow
->rx_pace_timeout
= coal
->rx_coalesce_usecs
* 1000;
966 static int am65_cpsw_set_coalesce(struct net_device
*ndev
, struct ethtool_coalesce
*coal
,
967 struct kernel_ethtool_coalesce
*kernel_coal
,
968 struct netlink_ext_ack
*extack
)
970 return am65_cpsw_set_per_queue_coalesce(ndev
, 0, coal
);
973 const struct ethtool_ops am65_cpsw_ethtool_ops_slave
= {
974 .begin
= am65_cpsw_ethtool_op_begin
,
975 .complete
= am65_cpsw_ethtool_op_complete
,
976 .get_drvinfo
= am65_cpsw_get_drvinfo
,
977 .get_msglevel
= am65_cpsw_get_msglevel
,
978 .set_msglevel
= am65_cpsw_set_msglevel
,
979 .get_channels
= am65_cpsw_get_channels
,
980 .set_channels
= am65_cpsw_set_channels
,
981 .get_ringparam
= am65_cpsw_get_ringparam
,
982 .get_regs_len
= am65_cpsw_get_regs_len
,
983 .get_regs
= am65_cpsw_get_regs
,
984 .get_sset_count
= am65_cpsw_get_sset_count
,
985 .get_strings
= am65_cpsw_get_strings
,
986 .get_ethtool_stats
= am65_cpsw_get_ethtool_stats
,
987 .get_eth_mac_stats
= am65_cpsw_get_eth_mac_stats
,
988 .get_ts_info
= am65_cpsw_get_ethtool_ts_info
,
989 .get_priv_flags
= am65_cpsw_get_ethtool_priv_flags
,
990 .set_priv_flags
= am65_cpsw_set_ethtool_priv_flags
,
991 .supported_coalesce_params
= ETHTOOL_COALESCE_USECS
,
992 .get_coalesce
= am65_cpsw_get_coalesce
,
993 .set_coalesce
= am65_cpsw_set_coalesce
,
994 .get_per_queue_coalesce
= am65_cpsw_get_per_queue_coalesce
,
995 .set_per_queue_coalesce
= am65_cpsw_set_per_queue_coalesce
,
997 .get_link
= ethtool_op_get_link
,
998 .get_link_ksettings
= am65_cpsw_get_link_ksettings
,
999 .set_link_ksettings
= am65_cpsw_set_link_ksettings
,
1000 .get_pauseparam
= am65_cpsw_get_pauseparam
,
1001 .set_pauseparam
= am65_cpsw_set_pauseparam
,
1002 .get_wol
= am65_cpsw_get_wol
,
1003 .set_wol
= am65_cpsw_set_wol
,
1004 .get_eee
= am65_cpsw_get_eee
,
1005 .set_eee
= am65_cpsw_set_eee
,
1006 .nway_reset
= am65_cpsw_nway_reset
,
1007 .get_mm
= am65_cpsw_get_mm
,
1008 .set_mm
= am65_cpsw_set_mm
,
1009 .get_mm_stats
= am65_cpsw_get_mm_stats
,