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>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
13 #include "am65-cpsw-nuss.h"
15 #include "am65-cpts.h"
17 #define AM65_CPSW_REGDUMP_VER 0x1
20 AM65_CPSW_REGDUMP_MOD_NUSS
= 1,
21 AM65_CPSW_REGDUMP_MOD_RGMII_STATUS
= 2,
22 AM65_CPSW_REGDUMP_MOD_MDIO
= 3,
23 AM65_CPSW_REGDUMP_MOD_CPSW
= 4,
24 AM65_CPSW_REGDUMP_MOD_CPSW_P0
= 5,
25 AM65_CPSW_REGDUMP_MOD_CPSW_P1
= 6,
26 AM65_CPSW_REGDUMP_MOD_CPSW_CPTS
= 7,
27 AM65_CPSW_REGDUMP_MOD_CPSW_ALE
= 8,
28 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
= 9,
29 AM65_CPSW_REGDUMP_MOD_LAST
,
33 * struct am65_cpsw_regdump_hdr - regdump record header
35 * @module_id: CPSW module ID
36 * @len: CPSW module registers space length in u32
39 struct am65_cpsw_regdump_hdr
{
45 * struct am65_cpsw_regdump_item - regdump module description
47 * @hdr: CPSW module header
48 * @start_ofs: CPSW module registers start addr
49 * @end_ofs: CPSW module registers end addr
51 * Registers dump provided in the format:
54 * u32[..len]: registers values
56 struct am65_cpsw_regdump_item
{
57 struct am65_cpsw_regdump_hdr hdr
;
62 #define AM65_CPSW_REGDUMP_REC(mod, start, end) { \
63 .hdr.module_id = (mod), \
64 .hdr.len = (((u32 *)(end)) - ((u32 *)(start)) + 1) * sizeof(u32) * 2 + \
65 sizeof(struct am65_cpsw_regdump_hdr), \
66 .start_ofs = (start), \
70 static const struct am65_cpsw_regdump_item am65_cpsw_regdump
[] = {
71 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_NUSS
, 0x0, 0x1c),
72 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_RGMII_STATUS
, 0x30, 0x4c),
73 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_MDIO
, 0xf00, 0xffc),
74 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW
, 0x20000, 0x2011c),
75 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P0
, 0x21000, 0x21320),
76 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P1
, 0x22000, 0x223a4),
77 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_CPTS
,
79 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE
, 0x3e000, 0x3e13c),
80 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
, 0, 0),
83 struct am65_cpsw_stats_regs
{
85 u32 rx_broadcast_frames
;
86 u32 rx_multicast_frames
;
87 u32 rx_pause_frames
; /* slave */
89 u32 rx_align_code_errors
; /* slave */
90 u32 rx_oversized_frames
;
91 u32 rx_jabber_frames
; /* slave */
92 u32 rx_undersized_frames
;
93 u32 rx_fragments
; /* slave */
98 u32 tx_broadcast_frames
;
99 u32 tx_multicast_frames
;
100 u32 tx_pause_frames
; /* slave */
101 u32 tx_deferred_frames
; /* slave */
102 u32 tx_collision_frames
; /* slave */
103 u32 tx_single_coll_frames
; /* slave */
104 u32 tx_mult_coll_frames
; /* slave */
105 u32 tx_excessive_collisions
; /* slave */
106 u32 tx_late_collisions
; /* slave */
107 u32 rx_ipg_error
; /* slave 10G only */
108 u32 tx_carrier_sense_errors
; /* slave */
111 u32 tx_65_to_127B_frames
;
112 u32 tx_128_to_255B_frames
;
113 u32 tx_256_to_511B_frames
;
114 u32 tx_512_to_1023B_frames
;
117 u32 rx_bottom_fifo_drop
;
118 u32 rx_port_mask_drop
;
119 u32 rx_top_fifo_drop
;
120 u32 ale_rate_limit_drop
;
121 u32 ale_vid_ingress_drop
;
122 u32 ale_da_eq_sa_drop
;
123 u32 ale_block_drop
; /* K3 */
124 u32 ale_secure_drop
; /* K3 */
125 u32 ale_auth_drop
; /* K3 */
126 u32 ale_unknown_ucast
;
127 u32 ale_unknown_ucast_bytes
;
128 u32 ale_unknown_mcast
;
129 u32 ale_unknown_mcast_bytes
;
130 u32 ale_unknown_bcast
;
131 u32 ale_unknown_bcast_bytes
;
133 u32 ale_pol_match_red
;
134 u32 ale_pol_match_yellow
;
135 u32 ale_mcast_sa_drop
; /* K3 */
136 u32 ale_dual_vlan_drop
; /* K3 */
137 u32 ale_len_err_drop
; /* K3 */
138 u32 ale_ip_next_hdr_drop
; /* K3 */
139 u32 ale_ipv4_frag_drop
; /* K3 */
141 u32 iet_rx_assembly_err
; /* K3 slave */
142 u32 iet_rx_assembly_ok
; /* K3 slave */
143 u32 iet_rx_smd_err
; /* K3 slave */
144 u32 iet_rx_frag
; /* K3 slave */
145 u32 iet_tx_hold
; /* K3 slave */
146 u32 iet_tx_frag
; /* K3 slave */
148 u32 tx_mem_protect_err
;
149 /* following NU only */
174 u32 tx_pri0_drop_bcnt
;
175 u32 tx_pri1_drop_bcnt
;
176 u32 tx_pri2_drop_bcnt
;
177 u32 tx_pri3_drop_bcnt
;
178 u32 tx_pri4_drop_bcnt
;
179 u32 tx_pri5_drop_bcnt
;
180 u32 tx_pri6_drop_bcnt
;
181 u32 tx_pri7_drop_bcnt
;
184 struct am65_cpsw_ethtool_stat
{
185 char desc
[ETH_GSTRING_LEN
];
189 #define AM65_CPSW_STATS(prefix, field) \
192 offsetof(struct am65_cpsw_stats_regs, field) \
195 static const struct am65_cpsw_ethtool_stat am65_host_stats
[] = {
196 AM65_CPSW_STATS(p0_
, rx_good_frames
),
197 AM65_CPSW_STATS(p0_
, rx_broadcast_frames
),
198 AM65_CPSW_STATS(p0_
, rx_multicast_frames
),
199 AM65_CPSW_STATS(p0_
, rx_crc_errors
),
200 AM65_CPSW_STATS(p0_
, rx_oversized_frames
),
201 AM65_CPSW_STATS(p0_
, rx_undersized_frames
),
202 AM65_CPSW_STATS(p0_
, ale_drop
),
203 AM65_CPSW_STATS(p0_
, ale_overrun_drop
),
204 AM65_CPSW_STATS(p0_
, rx_octets
),
205 AM65_CPSW_STATS(p0_
, tx_good_frames
),
206 AM65_CPSW_STATS(p0_
, tx_broadcast_frames
),
207 AM65_CPSW_STATS(p0_
, tx_multicast_frames
),
208 AM65_CPSW_STATS(p0_
, tx_octets
),
209 AM65_CPSW_STATS(p0_
, tx_64B_frames
),
210 AM65_CPSW_STATS(p0_
, tx_65_to_127B_frames
),
211 AM65_CPSW_STATS(p0_
, tx_128_to_255B_frames
),
212 AM65_CPSW_STATS(p0_
, tx_256_to_511B_frames
),
213 AM65_CPSW_STATS(p0_
, tx_512_to_1023B_frames
),
214 AM65_CPSW_STATS(p0_
, tx_1024B_frames
),
215 AM65_CPSW_STATS(p0_
, net_octets
),
216 AM65_CPSW_STATS(p0_
, rx_bottom_fifo_drop
),
217 AM65_CPSW_STATS(p0_
, rx_port_mask_drop
),
218 AM65_CPSW_STATS(p0_
, rx_top_fifo_drop
),
219 AM65_CPSW_STATS(p0_
, ale_rate_limit_drop
),
220 AM65_CPSW_STATS(p0_
, ale_vid_ingress_drop
),
221 AM65_CPSW_STATS(p0_
, ale_da_eq_sa_drop
),
222 AM65_CPSW_STATS(p0_
, ale_block_drop
),
223 AM65_CPSW_STATS(p0_
, ale_secure_drop
),
224 AM65_CPSW_STATS(p0_
, ale_auth_drop
),
225 AM65_CPSW_STATS(p0_
, ale_unknown_ucast
),
226 AM65_CPSW_STATS(p0_
, ale_unknown_ucast_bytes
),
227 AM65_CPSW_STATS(p0_
, ale_unknown_mcast
),
228 AM65_CPSW_STATS(p0_
, ale_unknown_mcast_bytes
),
229 AM65_CPSW_STATS(p0_
, ale_unknown_bcast
),
230 AM65_CPSW_STATS(p0_
, ale_unknown_bcast_bytes
),
231 AM65_CPSW_STATS(p0_
, ale_pol_match
),
232 AM65_CPSW_STATS(p0_
, ale_pol_match_red
),
233 AM65_CPSW_STATS(p0_
, ale_pol_match_yellow
),
234 AM65_CPSW_STATS(p0_
, ale_mcast_sa_drop
),
235 AM65_CPSW_STATS(p0_
, ale_dual_vlan_drop
),
236 AM65_CPSW_STATS(p0_
, ale_len_err_drop
),
237 AM65_CPSW_STATS(p0_
, ale_ip_next_hdr_drop
),
238 AM65_CPSW_STATS(p0_
, ale_ipv4_frag_drop
),
239 AM65_CPSW_STATS(p0_
, tx_mem_protect_err
),
240 AM65_CPSW_STATS(p0_
, tx_pri0
),
241 AM65_CPSW_STATS(p0_
, tx_pri1
),
242 AM65_CPSW_STATS(p0_
, tx_pri2
),
243 AM65_CPSW_STATS(p0_
, tx_pri3
),
244 AM65_CPSW_STATS(p0_
, tx_pri4
),
245 AM65_CPSW_STATS(p0_
, tx_pri5
),
246 AM65_CPSW_STATS(p0_
, tx_pri6
),
247 AM65_CPSW_STATS(p0_
, tx_pri7
),
248 AM65_CPSW_STATS(p0_
, tx_pri0_bcnt
),
249 AM65_CPSW_STATS(p0_
, tx_pri1_bcnt
),
250 AM65_CPSW_STATS(p0_
, tx_pri2_bcnt
),
251 AM65_CPSW_STATS(p0_
, tx_pri3_bcnt
),
252 AM65_CPSW_STATS(p0_
, tx_pri4_bcnt
),
253 AM65_CPSW_STATS(p0_
, tx_pri5_bcnt
),
254 AM65_CPSW_STATS(p0_
, tx_pri6_bcnt
),
255 AM65_CPSW_STATS(p0_
, tx_pri7_bcnt
),
256 AM65_CPSW_STATS(p0_
, tx_pri0_drop
),
257 AM65_CPSW_STATS(p0_
, tx_pri1_drop
),
258 AM65_CPSW_STATS(p0_
, tx_pri2_drop
),
259 AM65_CPSW_STATS(p0_
, tx_pri3_drop
),
260 AM65_CPSW_STATS(p0_
, tx_pri4_drop
),
261 AM65_CPSW_STATS(p0_
, tx_pri5_drop
),
262 AM65_CPSW_STATS(p0_
, tx_pri6_drop
),
263 AM65_CPSW_STATS(p0_
, tx_pri7_drop
),
264 AM65_CPSW_STATS(p0_
, tx_pri0_drop_bcnt
),
265 AM65_CPSW_STATS(p0_
, tx_pri1_drop_bcnt
),
266 AM65_CPSW_STATS(p0_
, tx_pri2_drop_bcnt
),
267 AM65_CPSW_STATS(p0_
, tx_pri3_drop_bcnt
),
268 AM65_CPSW_STATS(p0_
, tx_pri4_drop_bcnt
),
269 AM65_CPSW_STATS(p0_
, tx_pri5_drop_bcnt
),
270 AM65_CPSW_STATS(p0_
, tx_pri6_drop_bcnt
),
271 AM65_CPSW_STATS(p0_
, tx_pri7_drop_bcnt
),
274 static const struct am65_cpsw_ethtool_stat am65_slave_stats
[] = {
275 AM65_CPSW_STATS(, rx_good_frames
),
276 AM65_CPSW_STATS(, rx_broadcast_frames
),
277 AM65_CPSW_STATS(, rx_multicast_frames
),
278 AM65_CPSW_STATS(, rx_pause_frames
),
279 AM65_CPSW_STATS(, rx_crc_errors
),
280 AM65_CPSW_STATS(, rx_align_code_errors
),
281 AM65_CPSW_STATS(, rx_oversized_frames
),
282 AM65_CPSW_STATS(, rx_jabber_frames
),
283 AM65_CPSW_STATS(, rx_undersized_frames
),
284 AM65_CPSW_STATS(, rx_fragments
),
285 AM65_CPSW_STATS(, ale_drop
),
286 AM65_CPSW_STATS(, ale_overrun_drop
),
287 AM65_CPSW_STATS(, rx_octets
),
288 AM65_CPSW_STATS(, tx_good_frames
),
289 AM65_CPSW_STATS(, tx_broadcast_frames
),
290 AM65_CPSW_STATS(, tx_multicast_frames
),
291 AM65_CPSW_STATS(, tx_pause_frames
),
292 AM65_CPSW_STATS(, tx_deferred_frames
),
293 AM65_CPSW_STATS(, tx_collision_frames
),
294 AM65_CPSW_STATS(, tx_single_coll_frames
),
295 AM65_CPSW_STATS(, tx_mult_coll_frames
),
296 AM65_CPSW_STATS(, tx_excessive_collisions
),
297 AM65_CPSW_STATS(, tx_late_collisions
),
298 AM65_CPSW_STATS(, rx_ipg_error
),
299 AM65_CPSW_STATS(, tx_carrier_sense_errors
),
300 AM65_CPSW_STATS(, tx_octets
),
301 AM65_CPSW_STATS(, tx_64B_frames
),
302 AM65_CPSW_STATS(, tx_65_to_127B_frames
),
303 AM65_CPSW_STATS(, tx_128_to_255B_frames
),
304 AM65_CPSW_STATS(, tx_256_to_511B_frames
),
305 AM65_CPSW_STATS(, tx_512_to_1023B_frames
),
306 AM65_CPSW_STATS(, tx_1024B_frames
),
307 AM65_CPSW_STATS(, net_octets
),
308 AM65_CPSW_STATS(, rx_bottom_fifo_drop
),
309 AM65_CPSW_STATS(, rx_port_mask_drop
),
310 AM65_CPSW_STATS(, rx_top_fifo_drop
),
311 AM65_CPSW_STATS(, ale_rate_limit_drop
),
312 AM65_CPSW_STATS(, ale_vid_ingress_drop
),
313 AM65_CPSW_STATS(, ale_da_eq_sa_drop
),
314 AM65_CPSW_STATS(, ale_block_drop
),
315 AM65_CPSW_STATS(, ale_secure_drop
),
316 AM65_CPSW_STATS(, ale_auth_drop
),
317 AM65_CPSW_STATS(, ale_unknown_ucast
),
318 AM65_CPSW_STATS(, ale_unknown_ucast_bytes
),
319 AM65_CPSW_STATS(, ale_unknown_mcast
),
320 AM65_CPSW_STATS(, ale_unknown_mcast_bytes
),
321 AM65_CPSW_STATS(, ale_unknown_bcast
),
322 AM65_CPSW_STATS(, ale_unknown_bcast_bytes
),
323 AM65_CPSW_STATS(, ale_pol_match
),
324 AM65_CPSW_STATS(, ale_pol_match_red
),
325 AM65_CPSW_STATS(, ale_pol_match_yellow
),
326 AM65_CPSW_STATS(, ale_mcast_sa_drop
),
327 AM65_CPSW_STATS(, ale_dual_vlan_drop
),
328 AM65_CPSW_STATS(, ale_len_err_drop
),
329 AM65_CPSW_STATS(, ale_ip_next_hdr_drop
),
330 AM65_CPSW_STATS(, ale_ipv4_frag_drop
),
331 AM65_CPSW_STATS(, iet_rx_assembly_err
),
332 AM65_CPSW_STATS(, iet_rx_assembly_ok
),
333 AM65_CPSW_STATS(, iet_rx_smd_err
),
334 AM65_CPSW_STATS(, iet_rx_frag
),
335 AM65_CPSW_STATS(, iet_tx_hold
),
336 AM65_CPSW_STATS(, iet_tx_frag
),
337 AM65_CPSW_STATS(, tx_mem_protect_err
),
338 AM65_CPSW_STATS(, tx_pri0
),
339 AM65_CPSW_STATS(, tx_pri1
),
340 AM65_CPSW_STATS(, tx_pri2
),
341 AM65_CPSW_STATS(, tx_pri3
),
342 AM65_CPSW_STATS(, tx_pri4
),
343 AM65_CPSW_STATS(, tx_pri5
),
344 AM65_CPSW_STATS(, tx_pri6
),
345 AM65_CPSW_STATS(, tx_pri7
),
346 AM65_CPSW_STATS(, tx_pri0_bcnt
),
347 AM65_CPSW_STATS(, tx_pri1_bcnt
),
348 AM65_CPSW_STATS(, tx_pri2_bcnt
),
349 AM65_CPSW_STATS(, tx_pri3_bcnt
),
350 AM65_CPSW_STATS(, tx_pri4_bcnt
),
351 AM65_CPSW_STATS(, tx_pri5_bcnt
),
352 AM65_CPSW_STATS(, tx_pri6_bcnt
),
353 AM65_CPSW_STATS(, tx_pri7_bcnt
),
354 AM65_CPSW_STATS(, tx_pri0_drop
),
355 AM65_CPSW_STATS(, tx_pri1_drop
),
356 AM65_CPSW_STATS(, tx_pri2_drop
),
357 AM65_CPSW_STATS(, tx_pri3_drop
),
358 AM65_CPSW_STATS(, tx_pri4_drop
),
359 AM65_CPSW_STATS(, tx_pri5_drop
),
360 AM65_CPSW_STATS(, tx_pri6_drop
),
361 AM65_CPSW_STATS(, tx_pri7_drop
),
362 AM65_CPSW_STATS(, tx_pri0_drop_bcnt
),
363 AM65_CPSW_STATS(, tx_pri1_drop_bcnt
),
364 AM65_CPSW_STATS(, tx_pri2_drop_bcnt
),
365 AM65_CPSW_STATS(, tx_pri3_drop_bcnt
),
366 AM65_CPSW_STATS(, tx_pri4_drop_bcnt
),
367 AM65_CPSW_STATS(, tx_pri5_drop_bcnt
),
368 AM65_CPSW_STATS(, tx_pri6_drop_bcnt
),
369 AM65_CPSW_STATS(, tx_pri7_drop_bcnt
),
372 /* Ethtool priv_flags */
373 static const char am65_cpsw_ethtool_priv_flags
[][ETH_GSTRING_LEN
] = {
374 #define AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN BIT(0)
375 "p0-rx-ptype-rrobin",
378 static int am65_cpsw_ethtool_op_begin(struct net_device
*ndev
)
380 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
383 ret
= pm_runtime_get_sync(common
->dev
);
385 dev_err(common
->dev
, "ethtool begin failed %d\n", ret
);
386 pm_runtime_put_noidle(common
->dev
);
392 static void am65_cpsw_ethtool_op_complete(struct net_device
*ndev
)
394 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
397 ret
= pm_runtime_put(common
->dev
);
398 if (ret
< 0 && ret
!= -EBUSY
)
399 dev_err(common
->dev
, "ethtool complete failed %d\n", ret
);
402 static void am65_cpsw_get_drvinfo(struct net_device
*ndev
,
403 struct ethtool_drvinfo
*info
)
405 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
407 strlcpy(info
->driver
, dev_driver_string(common
->dev
),
408 sizeof(info
->driver
));
409 strlcpy(info
->bus_info
, dev_name(common
->dev
), sizeof(info
->bus_info
));
412 static u32
am65_cpsw_get_msglevel(struct net_device
*ndev
)
414 struct am65_cpsw_ndev_priv
*priv
= am65_ndev_to_priv(ndev
);
416 return priv
->msg_enable
;
419 static void am65_cpsw_set_msglevel(struct net_device
*ndev
, u32 value
)
421 struct am65_cpsw_ndev_priv
*priv
= am65_ndev_to_priv(ndev
);
423 priv
->msg_enable
= value
;
426 static void am65_cpsw_get_channels(struct net_device
*ndev
,
427 struct ethtool_channels
*ch
)
429 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
431 ch
->max_rx
= AM65_CPSW_MAX_RX_QUEUES
;
432 ch
->max_tx
= AM65_CPSW_MAX_TX_QUEUES
;
433 ch
->rx_count
= AM65_CPSW_MAX_RX_QUEUES
;
434 ch
->tx_count
= common
->tx_ch_num
;
437 static int am65_cpsw_set_channels(struct net_device
*ndev
,
438 struct ethtool_channels
*chs
)
440 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
442 if (!chs
->rx_count
|| !chs
->tx_count
)
445 /* Check if interface is up. Can change the num queues when
446 * the interface is down.
448 if (common
->usage_count
)
451 am65_cpsw_nuss_remove_tx_chns(common
);
453 return am65_cpsw_nuss_update_tx_chns(common
, chs
->tx_count
);
456 static void am65_cpsw_get_ringparam(struct net_device
*ndev
,
457 struct ethtool_ringparam
*ering
)
459 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
462 ering
->tx_pending
= common
->tx_chns
[0].descs_num
;
463 ering
->rx_pending
= common
->rx_chns
.descs_num
;
466 static void am65_cpsw_get_pauseparam(struct net_device
*ndev
,
467 struct ethtool_pauseparam
*pause
)
469 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
471 pause
->autoneg
= AUTONEG_DISABLE
;
472 pause
->rx_pause
= salve
->rx_pause
? true : false;
473 pause
->tx_pause
= salve
->tx_pause
? true : false;
476 static int am65_cpsw_set_pauseparam(struct net_device
*ndev
,
477 struct ethtool_pauseparam
*pause
)
479 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
484 if (!phy_validate_pause(salve
->phy
, pause
))
487 salve
->rx_pause
= pause
->rx_pause
? true : false;
488 salve
->tx_pause
= pause
->tx_pause
? true : false;
490 phy_set_asym_pause(salve
->phy
, salve
->rx_pause
, salve
->tx_pause
);
495 static void am65_cpsw_get_wol(struct net_device
*ndev
,
496 struct ethtool_wolinfo
*wol
)
498 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
504 phy_ethtool_get_wol(salve
->phy
, wol
);
507 static int am65_cpsw_set_wol(struct net_device
*ndev
,
508 struct ethtool_wolinfo
*wol
)
510 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
515 return phy_ethtool_set_wol(salve
->phy
, wol
);
518 static int am65_cpsw_get_link_ksettings(struct net_device
*ndev
,
519 struct ethtool_link_ksettings
*ecmd
)
521 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
526 phy_ethtool_ksettings_get(salve
->phy
, ecmd
);
531 am65_cpsw_set_link_ksettings(struct net_device
*ndev
,
532 const struct ethtool_link_ksettings
*ecmd
)
534 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
536 if (!salve
->phy
|| phy_is_pseudo_fixed_link(salve
->phy
))
539 return phy_ethtool_ksettings_set(salve
->phy
, ecmd
);
542 static int am65_cpsw_get_eee(struct net_device
*ndev
, struct ethtool_eee
*edata
)
544 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
546 if (!salve
->phy
|| phy_is_pseudo_fixed_link(salve
->phy
))
549 return phy_ethtool_get_eee(salve
->phy
, edata
);
552 static int am65_cpsw_set_eee(struct net_device
*ndev
, struct ethtool_eee
*edata
)
554 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
556 if (!salve
->phy
|| phy_is_pseudo_fixed_link(salve
->phy
))
559 return phy_ethtool_set_eee(salve
->phy
, edata
);
562 static int am65_cpsw_nway_reset(struct net_device
*ndev
)
564 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
566 if (!salve
->phy
|| phy_is_pseudo_fixed_link(salve
->phy
))
569 return phy_restart_aneg(salve
->phy
);
572 static int am65_cpsw_get_regs_len(struct net_device
*ndev
)
574 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
575 u32 ale_entries
, i
, regdump_len
= 0;
577 ale_entries
= cpsw_ale_get_num_entries(common
->ale
);
578 for (i
= 0; i
< ARRAY_SIZE(am65_cpsw_regdump
); i
++) {
579 if (am65_cpsw_regdump
[i
].hdr
.module_id
==
580 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
) {
581 regdump_len
+= sizeof(struct am65_cpsw_regdump_hdr
);
582 regdump_len
+= ale_entries
*
583 ALE_ENTRY_WORDS
* sizeof(u32
);
586 regdump_len
+= am65_cpsw_regdump
[i
].hdr
.len
;
592 static void am65_cpsw_get_regs(struct net_device
*ndev
,
593 struct ethtool_regs
*regs
, void *p
)
595 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
596 u32 ale_entries
, i
, j
, pos
, *reg
= p
;
598 /* update CPSW IP version */
599 regs
->version
= AM65_CPSW_REGDUMP_VER
;
600 ale_entries
= cpsw_ale_get_num_entries(common
->ale
);
603 for (i
= 0; i
< ARRAY_SIZE(am65_cpsw_regdump
); i
++) {
604 reg
[pos
++] = am65_cpsw_regdump
[i
].hdr
.module_id
;
606 if (am65_cpsw_regdump
[i
].hdr
.module_id
==
607 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
) {
608 u32 ale_tbl_len
= ale_entries
*
609 ALE_ENTRY_WORDS
* sizeof(u32
) +
610 sizeof(struct am65_cpsw_regdump_hdr
);
611 reg
[pos
++] = ale_tbl_len
;
612 cpsw_ale_dump(common
->ale
, ®
[pos
]);
617 reg
[pos
++] = am65_cpsw_regdump
[i
].hdr
.len
;
619 j
= am65_cpsw_regdump
[i
].start_ofs
;
622 reg
[pos
++] = readl_relaxed(common
->ss_base
+ j
);
624 } while (j
<= am65_cpsw_regdump
[i
].end_ofs
);
628 static int am65_cpsw_get_sset_count(struct net_device
*ndev
, int sset
)
632 return ARRAY_SIZE(am65_host_stats
) +
633 ARRAY_SIZE(am65_slave_stats
);
634 case ETH_SS_PRIV_FLAGS
:
635 return ARRAY_SIZE(am65_cpsw_ethtool_priv_flags
);
641 static void am65_cpsw_get_strings(struct net_device
*ndev
,
642 u32 stringset
, u8
*data
)
644 const struct am65_cpsw_ethtool_stat
*hw_stats
;
650 num_stats
= ARRAY_SIZE(am65_host_stats
);
651 hw_stats
= am65_host_stats
;
652 for (i
= 0; i
< num_stats
; i
++) {
653 memcpy(p
, hw_stats
[i
].desc
, ETH_GSTRING_LEN
);
654 p
+= ETH_GSTRING_LEN
;
657 num_stats
= ARRAY_SIZE(am65_slave_stats
);
658 hw_stats
= am65_slave_stats
;
659 for (i
= 0; i
< num_stats
; i
++) {
660 memcpy(p
, hw_stats
[i
].desc
, ETH_GSTRING_LEN
);
661 p
+= ETH_GSTRING_LEN
;
664 case ETH_SS_PRIV_FLAGS
:
665 num_stats
= ARRAY_SIZE(am65_cpsw_ethtool_priv_flags
);
667 for (i
= 0; i
< num_stats
; i
++) {
668 memcpy(p
, am65_cpsw_ethtool_priv_flags
[i
],
670 p
+= ETH_GSTRING_LEN
;
676 static void am65_cpsw_get_ethtool_stats(struct net_device
*ndev
,
677 struct ethtool_stats
*stats
, u64
*data
)
679 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
680 const struct am65_cpsw_ethtool_stat
*hw_stats
;
681 struct am65_cpsw_host
*host_p
;
682 struct am65_cpsw_port
*port
;
685 host_p
= am65_common_get_host(common
);
686 port
= am65_ndev_to_port(ndev
);
687 num_stats
= ARRAY_SIZE(am65_host_stats
);
688 hw_stats
= am65_host_stats
;
689 for (i
= 0; i
< num_stats
; i
++)
690 *data
++ = readl_relaxed(host_p
->stat_base
+
693 num_stats
= ARRAY_SIZE(am65_slave_stats
);
694 hw_stats
= am65_slave_stats
;
695 for (i
= 0; i
< num_stats
; i
++)
696 *data
++ = readl_relaxed(port
->stat_base
+
700 static int am65_cpsw_get_ethtool_ts_info(struct net_device
*ndev
,
701 struct ethtool_ts_info
*info
)
703 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
705 if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS
))
706 return ethtool_op_get_ts_info(ndev
, info
);
708 info
->so_timestamping
=
709 SOF_TIMESTAMPING_TX_HARDWARE
|
710 SOF_TIMESTAMPING_TX_SOFTWARE
|
711 SOF_TIMESTAMPING_RX_HARDWARE
|
712 SOF_TIMESTAMPING_RX_SOFTWARE
|
713 SOF_TIMESTAMPING_SOFTWARE
|
714 SOF_TIMESTAMPING_RAW_HARDWARE
;
715 info
->phc_index
= am65_cpts_phc_index(common
->cpts
);
716 info
->tx_types
= BIT(HWTSTAMP_TX_OFF
) | BIT(HWTSTAMP_TX_ON
);
717 info
->rx_filters
= BIT(HWTSTAMP_FILTER_NONE
) | BIT(HWTSTAMP_FILTER_ALL
);
721 static u32
am65_cpsw_get_ethtool_priv_flags(struct net_device
*ndev
)
723 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
726 if (common
->pf_p0_rx_ptype_rrobin
)
727 priv_flags
|= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN
;
732 static int am65_cpsw_set_ethtool_priv_flags(struct net_device
*ndev
, u32 flags
)
734 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
737 rrobin
= !!(flags
& AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN
);
739 if (common
->usage_count
)
742 if (common
->est_enabled
&& rrobin
) {
744 "p0-rx-ptype-rrobin flag conflicts with QOS\n");
748 common
->pf_p0_rx_ptype_rrobin
= rrobin
;
753 const struct ethtool_ops am65_cpsw_ethtool_ops_slave
= {
754 .begin
= am65_cpsw_ethtool_op_begin
,
755 .complete
= am65_cpsw_ethtool_op_complete
,
756 .get_drvinfo
= am65_cpsw_get_drvinfo
,
757 .get_msglevel
= am65_cpsw_get_msglevel
,
758 .set_msglevel
= am65_cpsw_set_msglevel
,
759 .get_channels
= am65_cpsw_get_channels
,
760 .set_channels
= am65_cpsw_set_channels
,
761 .get_ringparam
= am65_cpsw_get_ringparam
,
762 .get_regs_len
= am65_cpsw_get_regs_len
,
763 .get_regs
= am65_cpsw_get_regs
,
764 .get_sset_count
= am65_cpsw_get_sset_count
,
765 .get_strings
= am65_cpsw_get_strings
,
766 .get_ethtool_stats
= am65_cpsw_get_ethtool_stats
,
767 .get_ts_info
= am65_cpsw_get_ethtool_ts_info
,
768 .get_priv_flags
= am65_cpsw_get_ethtool_priv_flags
,
769 .set_priv_flags
= am65_cpsw_set_ethtool_priv_flags
,
771 .get_link
= ethtool_op_get_link
,
772 .get_link_ksettings
= am65_cpsw_get_link_ksettings
,
773 .set_link_ksettings
= am65_cpsw_set_link_ksettings
,
774 .get_pauseparam
= am65_cpsw_get_pauseparam
,
775 .set_pauseparam
= am65_cpsw_set_pauseparam
,
776 .get_wol
= am65_cpsw_get_wol
,
777 .set_wol
= am65_cpsw_set_wol
,
778 .get_eee
= am65_cpsw_get_eee
,
779 .set_eee
= am65_cpsw_set_eee
,
780 .nway_reset
= am65_cpsw_nway_reset
,