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"
16 #define AM65_CPSW_REGDUMP_VER 0x1
19 AM65_CPSW_REGDUMP_MOD_NUSS
= 1,
20 AM65_CPSW_REGDUMP_MOD_RGMII_STATUS
= 2,
21 AM65_CPSW_REGDUMP_MOD_MDIO
= 3,
22 AM65_CPSW_REGDUMP_MOD_CPSW
= 4,
23 AM65_CPSW_REGDUMP_MOD_CPSW_P0
= 5,
24 AM65_CPSW_REGDUMP_MOD_CPSW_P1
= 6,
25 AM65_CPSW_REGDUMP_MOD_CPSW_CPTS
= 7,
26 AM65_CPSW_REGDUMP_MOD_CPSW_ALE
= 8,
27 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
= 9,
28 AM65_CPSW_REGDUMP_MOD_LAST
,
32 * struct am65_cpsw_regdump_hdr - regdump record header
34 * @module_id: CPSW module ID
35 * @len: CPSW module registers space length in u32
38 struct am65_cpsw_regdump_hdr
{
44 * struct am65_cpsw_regdump_item - regdump module description
46 * @hdr: CPSW module header
47 * @start_ofs: CPSW module registers start addr
48 * @end_ofs: CPSW module registers end addr
50 * Registers dump provided in the format:
53 * u32[..len]: registers values
55 struct am65_cpsw_regdump_item
{
56 struct am65_cpsw_regdump_hdr hdr
;
61 #define AM65_CPSW_REGDUMP_REC(mod, start, end) { \
62 .hdr.module_id = (mod), \
63 .hdr.len = (((u32 *)(end)) - ((u32 *)(start)) + 1) * sizeof(u32) * 2 + \
64 sizeof(struct am65_cpsw_regdump_hdr), \
65 .start_ofs = (start), \
69 static const struct am65_cpsw_regdump_item am65_cpsw_regdump
[] = {
70 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_NUSS
, 0x0, 0x1c),
71 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_RGMII_STATUS
, 0x30, 0x4c),
72 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_MDIO
, 0xf00, 0xffc),
73 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW
, 0x20000, 0x2011c),
74 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P0
, 0x21000, 0x21320),
75 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P1
, 0x22000, 0x223a4),
76 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_CPTS
,
78 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE
, 0x3e000, 0x3e13c),
79 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
, 0, 0),
82 struct am65_cpsw_stats_regs
{
84 u32 rx_broadcast_frames
;
85 u32 rx_multicast_frames
;
86 u32 rx_pause_frames
; /* slave */
88 u32 rx_align_code_errors
; /* slave */
89 u32 rx_oversized_frames
;
90 u32 rx_jabber_frames
; /* slave */
91 u32 rx_undersized_frames
;
92 u32 rx_fragments
; /* slave */
97 u32 tx_broadcast_frames
;
98 u32 tx_multicast_frames
;
99 u32 tx_pause_frames
; /* slave */
100 u32 tx_deferred_frames
; /* slave */
101 u32 tx_collision_frames
; /* slave */
102 u32 tx_single_coll_frames
; /* slave */
103 u32 tx_mult_coll_frames
; /* slave */
104 u32 tx_excessive_collisions
; /* slave */
105 u32 tx_late_collisions
; /* slave */
106 u32 rx_ipg_error
; /* slave 10G only */
107 u32 tx_carrier_sense_errors
; /* slave */
110 u32 tx_65_to_127B_frames
;
111 u32 tx_128_to_255B_frames
;
112 u32 tx_256_to_511B_frames
;
113 u32 tx_512_to_1023B_frames
;
116 u32 rx_bottom_fifo_drop
;
117 u32 rx_port_mask_drop
;
118 u32 rx_top_fifo_drop
;
119 u32 ale_rate_limit_drop
;
120 u32 ale_vid_ingress_drop
;
121 u32 ale_da_eq_sa_drop
;
122 u32 ale_block_drop
; /* K3 */
123 u32 ale_secure_drop
; /* K3 */
124 u32 ale_auth_drop
; /* K3 */
125 u32 ale_unknown_ucast
;
126 u32 ale_unknown_ucast_bytes
;
127 u32 ale_unknown_mcast
;
128 u32 ale_unknown_mcast_bytes
;
129 u32 ale_unknown_bcast
;
130 u32 ale_unknown_bcast_bytes
;
132 u32 ale_pol_match_red
;
133 u32 ale_pol_match_yellow
;
134 u32 ale_mcast_sa_drop
; /* K3 */
135 u32 ale_dual_vlan_drop
; /* K3 */
136 u32 ale_len_err_drop
; /* K3 */
137 u32 ale_ip_next_hdr_drop
; /* K3 */
138 u32 ale_ipv4_frag_drop
; /* K3 */
140 u32 iet_rx_assembly_err
; /* K3 slave */
141 u32 iet_rx_assembly_ok
; /* K3 slave */
142 u32 iet_rx_smd_err
; /* K3 slave */
143 u32 iet_rx_frag
; /* K3 slave */
144 u32 iet_tx_hold
; /* K3 slave */
145 u32 iet_tx_frag
; /* K3 slave */
147 u32 tx_mem_protect_err
;
148 /* following NU only */
173 u32 tx_pri0_drop_bcnt
;
174 u32 tx_pri1_drop_bcnt
;
175 u32 tx_pri2_drop_bcnt
;
176 u32 tx_pri3_drop_bcnt
;
177 u32 tx_pri4_drop_bcnt
;
178 u32 tx_pri5_drop_bcnt
;
179 u32 tx_pri6_drop_bcnt
;
180 u32 tx_pri7_drop_bcnt
;
183 struct am65_cpsw_ethtool_stat
{
184 char desc
[ETH_GSTRING_LEN
];
188 #define AM65_CPSW_STATS(prefix, field) \
191 offsetof(struct am65_cpsw_stats_regs, field) \
194 static const struct am65_cpsw_ethtool_stat am65_host_stats
[] = {
195 AM65_CPSW_STATS(p0_
, rx_good_frames
),
196 AM65_CPSW_STATS(p0_
, rx_broadcast_frames
),
197 AM65_CPSW_STATS(p0_
, rx_multicast_frames
),
198 AM65_CPSW_STATS(p0_
, rx_crc_errors
),
199 AM65_CPSW_STATS(p0_
, rx_oversized_frames
),
200 AM65_CPSW_STATS(p0_
, rx_undersized_frames
),
201 AM65_CPSW_STATS(p0_
, ale_drop
),
202 AM65_CPSW_STATS(p0_
, ale_overrun_drop
),
203 AM65_CPSW_STATS(p0_
, rx_octets
),
204 AM65_CPSW_STATS(p0_
, tx_good_frames
),
205 AM65_CPSW_STATS(p0_
, tx_broadcast_frames
),
206 AM65_CPSW_STATS(p0_
, tx_multicast_frames
),
207 AM65_CPSW_STATS(p0_
, tx_octets
),
208 AM65_CPSW_STATS(p0_
, tx_64B_frames
),
209 AM65_CPSW_STATS(p0_
, tx_65_to_127B_frames
),
210 AM65_CPSW_STATS(p0_
, tx_128_to_255B_frames
),
211 AM65_CPSW_STATS(p0_
, tx_256_to_511B_frames
),
212 AM65_CPSW_STATS(p0_
, tx_512_to_1023B_frames
),
213 AM65_CPSW_STATS(p0_
, tx_1024B_frames
),
214 AM65_CPSW_STATS(p0_
, net_octets
),
215 AM65_CPSW_STATS(p0_
, rx_bottom_fifo_drop
),
216 AM65_CPSW_STATS(p0_
, rx_port_mask_drop
),
217 AM65_CPSW_STATS(p0_
, rx_top_fifo_drop
),
218 AM65_CPSW_STATS(p0_
, ale_rate_limit_drop
),
219 AM65_CPSW_STATS(p0_
, ale_vid_ingress_drop
),
220 AM65_CPSW_STATS(p0_
, ale_da_eq_sa_drop
),
221 AM65_CPSW_STATS(p0_
, ale_block_drop
),
222 AM65_CPSW_STATS(p0_
, ale_secure_drop
),
223 AM65_CPSW_STATS(p0_
, ale_auth_drop
),
224 AM65_CPSW_STATS(p0_
, ale_unknown_ucast
),
225 AM65_CPSW_STATS(p0_
, ale_unknown_ucast_bytes
),
226 AM65_CPSW_STATS(p0_
, ale_unknown_mcast
),
227 AM65_CPSW_STATS(p0_
, ale_unknown_mcast_bytes
),
228 AM65_CPSW_STATS(p0_
, ale_unknown_bcast
),
229 AM65_CPSW_STATS(p0_
, ale_unknown_bcast_bytes
),
230 AM65_CPSW_STATS(p0_
, ale_pol_match
),
231 AM65_CPSW_STATS(p0_
, ale_pol_match_red
),
232 AM65_CPSW_STATS(p0_
, ale_pol_match_yellow
),
233 AM65_CPSW_STATS(p0_
, ale_mcast_sa_drop
),
234 AM65_CPSW_STATS(p0_
, ale_dual_vlan_drop
),
235 AM65_CPSW_STATS(p0_
, ale_len_err_drop
),
236 AM65_CPSW_STATS(p0_
, ale_ip_next_hdr_drop
),
237 AM65_CPSW_STATS(p0_
, ale_ipv4_frag_drop
),
238 AM65_CPSW_STATS(p0_
, tx_mem_protect_err
),
239 AM65_CPSW_STATS(p0_
, tx_pri0
),
240 AM65_CPSW_STATS(p0_
, tx_pri1
),
241 AM65_CPSW_STATS(p0_
, tx_pri2
),
242 AM65_CPSW_STATS(p0_
, tx_pri3
),
243 AM65_CPSW_STATS(p0_
, tx_pri4
),
244 AM65_CPSW_STATS(p0_
, tx_pri5
),
245 AM65_CPSW_STATS(p0_
, tx_pri6
),
246 AM65_CPSW_STATS(p0_
, tx_pri7
),
247 AM65_CPSW_STATS(p0_
, tx_pri0_bcnt
),
248 AM65_CPSW_STATS(p0_
, tx_pri1_bcnt
),
249 AM65_CPSW_STATS(p0_
, tx_pri2_bcnt
),
250 AM65_CPSW_STATS(p0_
, tx_pri3_bcnt
),
251 AM65_CPSW_STATS(p0_
, tx_pri4_bcnt
),
252 AM65_CPSW_STATS(p0_
, tx_pri5_bcnt
),
253 AM65_CPSW_STATS(p0_
, tx_pri6_bcnt
),
254 AM65_CPSW_STATS(p0_
, tx_pri7_bcnt
),
255 AM65_CPSW_STATS(p0_
, tx_pri0_drop
),
256 AM65_CPSW_STATS(p0_
, tx_pri1_drop
),
257 AM65_CPSW_STATS(p0_
, tx_pri2_drop
),
258 AM65_CPSW_STATS(p0_
, tx_pri3_drop
),
259 AM65_CPSW_STATS(p0_
, tx_pri4_drop
),
260 AM65_CPSW_STATS(p0_
, tx_pri5_drop
),
261 AM65_CPSW_STATS(p0_
, tx_pri6_drop
),
262 AM65_CPSW_STATS(p0_
, tx_pri7_drop
),
263 AM65_CPSW_STATS(p0_
, tx_pri0_drop_bcnt
),
264 AM65_CPSW_STATS(p0_
, tx_pri1_drop_bcnt
),
265 AM65_CPSW_STATS(p0_
, tx_pri2_drop_bcnt
),
266 AM65_CPSW_STATS(p0_
, tx_pri3_drop_bcnt
),
267 AM65_CPSW_STATS(p0_
, tx_pri4_drop_bcnt
),
268 AM65_CPSW_STATS(p0_
, tx_pri5_drop_bcnt
),
269 AM65_CPSW_STATS(p0_
, tx_pri6_drop_bcnt
),
270 AM65_CPSW_STATS(p0_
, tx_pri7_drop_bcnt
),
273 static const struct am65_cpsw_ethtool_stat am65_slave_stats
[] = {
274 AM65_CPSW_STATS(, rx_good_frames
),
275 AM65_CPSW_STATS(, rx_broadcast_frames
),
276 AM65_CPSW_STATS(, rx_multicast_frames
),
277 AM65_CPSW_STATS(, rx_pause_frames
),
278 AM65_CPSW_STATS(, rx_crc_errors
),
279 AM65_CPSW_STATS(, rx_align_code_errors
),
280 AM65_CPSW_STATS(, rx_oversized_frames
),
281 AM65_CPSW_STATS(, rx_jabber_frames
),
282 AM65_CPSW_STATS(, rx_undersized_frames
),
283 AM65_CPSW_STATS(, rx_fragments
),
284 AM65_CPSW_STATS(, ale_drop
),
285 AM65_CPSW_STATS(, ale_overrun_drop
),
286 AM65_CPSW_STATS(, rx_octets
),
287 AM65_CPSW_STATS(, tx_good_frames
),
288 AM65_CPSW_STATS(, tx_broadcast_frames
),
289 AM65_CPSW_STATS(, tx_multicast_frames
),
290 AM65_CPSW_STATS(, tx_pause_frames
),
291 AM65_CPSW_STATS(, tx_deferred_frames
),
292 AM65_CPSW_STATS(, tx_collision_frames
),
293 AM65_CPSW_STATS(, tx_single_coll_frames
),
294 AM65_CPSW_STATS(, tx_mult_coll_frames
),
295 AM65_CPSW_STATS(, tx_excessive_collisions
),
296 AM65_CPSW_STATS(, tx_late_collisions
),
297 AM65_CPSW_STATS(, rx_ipg_error
),
298 AM65_CPSW_STATS(, tx_carrier_sense_errors
),
299 AM65_CPSW_STATS(, tx_octets
),
300 AM65_CPSW_STATS(, tx_64B_frames
),
301 AM65_CPSW_STATS(, tx_65_to_127B_frames
),
302 AM65_CPSW_STATS(, tx_128_to_255B_frames
),
303 AM65_CPSW_STATS(, tx_256_to_511B_frames
),
304 AM65_CPSW_STATS(, tx_512_to_1023B_frames
),
305 AM65_CPSW_STATS(, tx_1024B_frames
),
306 AM65_CPSW_STATS(, net_octets
),
307 AM65_CPSW_STATS(, rx_bottom_fifo_drop
),
308 AM65_CPSW_STATS(, rx_port_mask_drop
),
309 AM65_CPSW_STATS(, rx_top_fifo_drop
),
310 AM65_CPSW_STATS(, ale_rate_limit_drop
),
311 AM65_CPSW_STATS(, ale_vid_ingress_drop
),
312 AM65_CPSW_STATS(, ale_da_eq_sa_drop
),
313 AM65_CPSW_STATS(, ale_block_drop
),
314 AM65_CPSW_STATS(, ale_secure_drop
),
315 AM65_CPSW_STATS(, ale_auth_drop
),
316 AM65_CPSW_STATS(, ale_unknown_ucast
),
317 AM65_CPSW_STATS(, ale_unknown_ucast_bytes
),
318 AM65_CPSW_STATS(, ale_unknown_mcast
),
319 AM65_CPSW_STATS(, ale_unknown_mcast_bytes
),
320 AM65_CPSW_STATS(, ale_unknown_bcast
),
321 AM65_CPSW_STATS(, ale_unknown_bcast_bytes
),
322 AM65_CPSW_STATS(, ale_pol_match
),
323 AM65_CPSW_STATS(, ale_pol_match_red
),
324 AM65_CPSW_STATS(, ale_pol_match_yellow
),
325 AM65_CPSW_STATS(, ale_mcast_sa_drop
),
326 AM65_CPSW_STATS(, ale_dual_vlan_drop
),
327 AM65_CPSW_STATS(, ale_len_err_drop
),
328 AM65_CPSW_STATS(, ale_ip_next_hdr_drop
),
329 AM65_CPSW_STATS(, ale_ipv4_frag_drop
),
330 AM65_CPSW_STATS(, iet_rx_assembly_err
),
331 AM65_CPSW_STATS(, iet_rx_assembly_ok
),
332 AM65_CPSW_STATS(, iet_rx_smd_err
),
333 AM65_CPSW_STATS(, iet_rx_frag
),
334 AM65_CPSW_STATS(, iet_tx_hold
),
335 AM65_CPSW_STATS(, iet_tx_frag
),
336 AM65_CPSW_STATS(, tx_mem_protect_err
),
337 AM65_CPSW_STATS(, tx_pri0
),
338 AM65_CPSW_STATS(, tx_pri1
),
339 AM65_CPSW_STATS(, tx_pri2
),
340 AM65_CPSW_STATS(, tx_pri3
),
341 AM65_CPSW_STATS(, tx_pri4
),
342 AM65_CPSW_STATS(, tx_pri5
),
343 AM65_CPSW_STATS(, tx_pri6
),
344 AM65_CPSW_STATS(, tx_pri7
),
345 AM65_CPSW_STATS(, tx_pri0_bcnt
),
346 AM65_CPSW_STATS(, tx_pri1_bcnt
),
347 AM65_CPSW_STATS(, tx_pri2_bcnt
),
348 AM65_CPSW_STATS(, tx_pri3_bcnt
),
349 AM65_CPSW_STATS(, tx_pri4_bcnt
),
350 AM65_CPSW_STATS(, tx_pri5_bcnt
),
351 AM65_CPSW_STATS(, tx_pri6_bcnt
),
352 AM65_CPSW_STATS(, tx_pri7_bcnt
),
353 AM65_CPSW_STATS(, tx_pri0_drop
),
354 AM65_CPSW_STATS(, tx_pri1_drop
),
355 AM65_CPSW_STATS(, tx_pri2_drop
),
356 AM65_CPSW_STATS(, tx_pri3_drop
),
357 AM65_CPSW_STATS(, tx_pri4_drop
),
358 AM65_CPSW_STATS(, tx_pri5_drop
),
359 AM65_CPSW_STATS(, tx_pri6_drop
),
360 AM65_CPSW_STATS(, tx_pri7_drop
),
361 AM65_CPSW_STATS(, tx_pri0_drop_bcnt
),
362 AM65_CPSW_STATS(, tx_pri1_drop_bcnt
),
363 AM65_CPSW_STATS(, tx_pri2_drop_bcnt
),
364 AM65_CPSW_STATS(, tx_pri3_drop_bcnt
),
365 AM65_CPSW_STATS(, tx_pri4_drop_bcnt
),
366 AM65_CPSW_STATS(, tx_pri5_drop_bcnt
),
367 AM65_CPSW_STATS(, tx_pri6_drop_bcnt
),
368 AM65_CPSW_STATS(, tx_pri7_drop_bcnt
),
371 /* Ethtool priv_flags */
372 static const char am65_cpsw_ethtool_priv_flags
[][ETH_GSTRING_LEN
] = {
373 #define AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN BIT(0)
374 "p0-rx-ptype-rrobin",
377 static int am65_cpsw_ethtool_op_begin(struct net_device
*ndev
)
379 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
382 ret
= pm_runtime_get_sync(common
->dev
);
384 dev_err(common
->dev
, "ethtool begin failed %d\n", ret
);
385 pm_runtime_put_noidle(common
->dev
);
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 strlcpy(info
->driver
, dev_driver_string(common
->dev
),
407 sizeof(info
->driver
));
408 strlcpy(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_RX_QUEUES
;
431 ch
->max_tx
= AM65_CPSW_MAX_TX_QUEUES
;
432 ch
->rx_count
= AM65_CPSW_MAX_RX_QUEUES
;
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 (netif_running(ndev
))
450 am65_cpsw_nuss_remove_tx_chns(common
);
452 return am65_cpsw_nuss_update_tx_chns(common
, chs
->tx_count
);
455 static void am65_cpsw_get_ringparam(struct net_device
*ndev
,
456 struct ethtool_ringparam
*ering
)
458 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
461 ering
->tx_pending
= common
->tx_chns
[0].descs_num
;
462 ering
->rx_pending
= common
->rx_chns
.descs_num
;
465 static void am65_cpsw_get_pauseparam(struct net_device
*ndev
,
466 struct ethtool_pauseparam
*pause
)
468 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
470 pause
->autoneg
= AUTONEG_DISABLE
;
471 pause
->rx_pause
= salve
->rx_pause
? true : false;
472 pause
->tx_pause
= salve
->tx_pause
? true : false;
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
);
483 if (!phy_validate_pause(salve
->phy
, pause
))
486 salve
->rx_pause
= pause
->rx_pause
? true : false;
487 salve
->tx_pause
= pause
->tx_pause
? true : false;
489 phy_set_asym_pause(salve
->phy
, salve
->rx_pause
, salve
->tx_pause
);
494 static void am65_cpsw_get_wol(struct net_device
*ndev
,
495 struct ethtool_wolinfo
*wol
)
497 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
503 phy_ethtool_get_wol(salve
->phy
, wol
);
506 static int am65_cpsw_set_wol(struct net_device
*ndev
,
507 struct ethtool_wolinfo
*wol
)
509 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
514 return phy_ethtool_set_wol(salve
->phy
, wol
);
517 static int am65_cpsw_get_link_ksettings(struct net_device
*ndev
,
518 struct ethtool_link_ksettings
*ecmd
)
520 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
525 phy_ethtool_ksettings_get(salve
->phy
, ecmd
);
530 am65_cpsw_set_link_ksettings(struct net_device
*ndev
,
531 const struct ethtool_link_ksettings
*ecmd
)
533 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
535 if (!salve
->phy
|| phy_is_pseudo_fixed_link(salve
->phy
))
538 return phy_ethtool_ksettings_set(salve
->phy
, ecmd
);
541 static int am65_cpsw_get_eee(struct net_device
*ndev
, struct ethtool_eee
*edata
)
543 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
545 if (!salve
->phy
|| phy_is_pseudo_fixed_link(salve
->phy
))
548 return phy_ethtool_get_eee(salve
->phy
, edata
);
551 static int am65_cpsw_set_eee(struct net_device
*ndev
, struct ethtool_eee
*edata
)
553 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
555 if (!salve
->phy
|| phy_is_pseudo_fixed_link(salve
->phy
))
558 return phy_ethtool_set_eee(salve
->phy
, edata
);
561 static int am65_cpsw_nway_reset(struct net_device
*ndev
)
563 struct am65_cpsw_slave_data
*salve
= am65_ndev_to_slave(ndev
);
565 if (!salve
->phy
|| phy_is_pseudo_fixed_link(salve
->phy
))
568 return phy_restart_aneg(salve
->phy
);
571 static int am65_cpsw_get_regs_len(struct net_device
*ndev
)
573 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
574 u32 i
, regdump_len
= 0;
576 for (i
= 0; i
< ARRAY_SIZE(am65_cpsw_regdump
); i
++) {
577 if (am65_cpsw_regdump
[i
].hdr
.module_id
==
578 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
) {
579 regdump_len
+= sizeof(struct am65_cpsw_regdump_hdr
);
580 regdump_len
+= common
->ale
->params
.ale_entries
*
581 ALE_ENTRY_WORDS
* sizeof(u32
);
584 regdump_len
+= am65_cpsw_regdump
[i
].hdr
.len
;
590 static void am65_cpsw_get_regs(struct net_device
*ndev
,
591 struct ethtool_regs
*regs
, void *p
)
593 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
594 u32 i
, j
, pos
, *reg
= p
;
596 /* update CPSW IP version */
597 regs
->version
= AM65_CPSW_REGDUMP_VER
;
600 for (i
= 0; i
< ARRAY_SIZE(am65_cpsw_regdump
); i
++) {
601 reg
[pos
++] = am65_cpsw_regdump
[i
].hdr
.module_id
;
603 if (am65_cpsw_regdump
[i
].hdr
.module_id
==
604 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL
) {
605 u32 ale_tbl_len
= common
->ale
->params
.ale_entries
*
606 ALE_ENTRY_WORDS
* sizeof(u32
) +
607 sizeof(struct am65_cpsw_regdump_hdr
);
608 reg
[pos
++] = ale_tbl_len
;
609 cpsw_ale_dump(common
->ale
, ®
[pos
]);
614 reg
[pos
++] = am65_cpsw_regdump
[i
].hdr
.len
;
616 j
= am65_cpsw_regdump
[i
].start_ofs
;
619 reg
[pos
++] = readl_relaxed(common
->ss_base
+ j
);
621 } while (j
<= am65_cpsw_regdump
[i
].end_ofs
);
625 static int am65_cpsw_get_sset_count(struct net_device
*ndev
, int sset
)
629 return ARRAY_SIZE(am65_host_stats
) +
630 ARRAY_SIZE(am65_slave_stats
);
631 case ETH_SS_PRIV_FLAGS
:
632 return ARRAY_SIZE(am65_cpsw_ethtool_priv_flags
);
638 static void am65_cpsw_get_strings(struct net_device
*ndev
,
639 u32 stringset
, u8
*data
)
641 const struct am65_cpsw_ethtool_stat
*hw_stats
;
647 num_stats
= ARRAY_SIZE(am65_host_stats
);
648 hw_stats
= am65_host_stats
;
649 for (i
= 0; i
< num_stats
; i
++) {
650 memcpy(p
, hw_stats
[i
].desc
, ETH_GSTRING_LEN
);
651 p
+= ETH_GSTRING_LEN
;
654 num_stats
= ARRAY_SIZE(am65_slave_stats
);
655 hw_stats
= am65_slave_stats
;
656 for (i
= 0; i
< num_stats
; i
++) {
657 memcpy(p
, hw_stats
[i
].desc
, ETH_GSTRING_LEN
);
658 p
+= ETH_GSTRING_LEN
;
661 case ETH_SS_PRIV_FLAGS
:
662 num_stats
= ARRAY_SIZE(am65_cpsw_ethtool_priv_flags
);
664 for (i
= 0; i
< num_stats
; i
++) {
665 memcpy(p
, am65_cpsw_ethtool_priv_flags
[i
],
667 p
+= ETH_GSTRING_LEN
;
673 static void am65_cpsw_get_ethtool_stats(struct net_device
*ndev
,
674 struct ethtool_stats
*stats
, u64
*data
)
676 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
677 const struct am65_cpsw_ethtool_stat
*hw_stats
;
678 struct am65_cpsw_host
*host_p
;
679 struct am65_cpsw_port
*port
;
682 host_p
= am65_common_get_host(common
);
683 port
= am65_ndev_to_port(ndev
);
684 num_stats
= ARRAY_SIZE(am65_host_stats
);
685 hw_stats
= am65_host_stats
;
686 for (i
= 0; i
< num_stats
; i
++)
687 *data
++ = readl_relaxed(host_p
->stat_base
+
690 num_stats
= ARRAY_SIZE(am65_slave_stats
);
691 hw_stats
= am65_slave_stats
;
692 for (i
= 0; i
< num_stats
; i
++)
693 *data
++ = readl_relaxed(port
->stat_base
+
697 static u32
am65_cpsw_get_ethtool_priv_flags(struct net_device
*ndev
)
699 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
702 if (common
->pf_p0_rx_ptype_rrobin
)
703 priv_flags
|= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN
;
708 static int am65_cpsw_set_ethtool_priv_flags(struct net_device
*ndev
, u32 flags
)
710 struct am65_cpsw_common
*common
= am65_ndev_to_common(ndev
);
712 common
->pf_p0_rx_ptype_rrobin
=
713 !!(flags
& AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN
);
714 am65_cpsw_nuss_set_p0_ptype(common
);
719 const struct ethtool_ops am65_cpsw_ethtool_ops_slave
= {
720 .begin
= am65_cpsw_ethtool_op_begin
,
721 .complete
= am65_cpsw_ethtool_op_complete
,
722 .get_drvinfo
= am65_cpsw_get_drvinfo
,
723 .get_msglevel
= am65_cpsw_get_msglevel
,
724 .set_msglevel
= am65_cpsw_set_msglevel
,
725 .get_channels
= am65_cpsw_get_channels
,
726 .set_channels
= am65_cpsw_set_channels
,
727 .get_ringparam
= am65_cpsw_get_ringparam
,
728 .get_regs_len
= am65_cpsw_get_regs_len
,
729 .get_regs
= am65_cpsw_get_regs
,
730 .get_sset_count
= am65_cpsw_get_sset_count
,
731 .get_strings
= am65_cpsw_get_strings
,
732 .get_ethtool_stats
= am65_cpsw_get_ethtool_stats
,
733 .get_ts_info
= ethtool_op_get_ts_info
,
734 .get_priv_flags
= am65_cpsw_get_ethtool_priv_flags
,
735 .set_priv_flags
= am65_cpsw_set_ethtool_priv_flags
,
737 .get_link
= ethtool_op_get_link
,
738 .get_link_ksettings
= am65_cpsw_get_link_ksettings
,
739 .set_link_ksettings
= am65_cpsw_set_link_ksettings
,
740 .get_pauseparam
= am65_cpsw_get_pauseparam
,
741 .set_pauseparam
= am65_cpsw_set_pauseparam
,
742 .get_wol
= am65_cpsw_get_wol
,
743 .set_wol
= am65_cpsw_set_wol
,
744 .get_eee
= am65_cpsw_get_eee
,
745 .set_eee
= am65_cpsw_set_eee
,
746 .nway_reset
= am65_cpsw_nway_reset
,