net: ethernet: ti: introduce am65x/j721e gigabit eth subsystem driver
[platform/kernel/linux-starfive.git] / drivers / net / ethernet / ti / am65-cpsw-ethtool.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver ethtool ops
3  *
4  * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
5  *
6  */
7
8 #include <linux/net_tstamp.h>
9 #include <linux/phy.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
12
13 #include "am65-cpsw-nuss.h"
14 #include "cpsw_ale.h"
15
16 #define AM65_CPSW_REGDUMP_VER 0x1
17
18 enum {
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,
29 };
30
31 /**
32  * struct am65_cpsw_regdump_hdr - regdump record header
33  *
34  * @module_id: CPSW module ID
35  * @len: CPSW module registers space length in u32
36  */
37
38 struct am65_cpsw_regdump_hdr {
39         u32 module_id;
40         u32 len;
41 };
42
43 /**
44  * struct am65_cpsw_regdump_item - regdump module description
45  *
46  * @hdr: CPSW module header
47  * @start_ofs: CPSW module registers start addr
48  * @end_ofs: CPSW module registers end addr
49  *
50  * Registers dump provided in the format:
51  *  u32 : module ID
52  *  u32 : dump length
53  *  u32[..len]: registers values
54  */
55 struct am65_cpsw_regdump_item {
56         struct am65_cpsw_regdump_hdr hdr;
57         u32 start_ofs;
58         u32 end_ofs;
59 };
60
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), \
66         .end_ofs = end, \
67 }
68
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,
77                               0x3d000, 0x3d048),
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),
80 };
81
82 struct am65_cpsw_stats_regs {
83         u32     rx_good_frames;
84         u32     rx_broadcast_frames;
85         u32     rx_multicast_frames;
86         u32     rx_pause_frames;                /* slave */
87         u32     rx_crc_errors;
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 */
93         u32     ale_drop;
94         u32     ale_overrun_drop;
95         u32     rx_octets;
96         u32     tx_good_frames;
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 */
108         u32     tx_octets;
109         u32     tx_64B_frames;
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;
114         u32     tx_1024B_frames;
115         u32     net_octets;
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;
131         u32     ale_pol_match;
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 */
139         u32     __rsvd_1[24];
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 */
146         u32     __rsvd_2[9];
147         u32     tx_mem_protect_err;
148         /* following NU only */
149         u32     tx_pri0;
150         u32     tx_pri1;
151         u32     tx_pri2;
152         u32     tx_pri3;
153         u32     tx_pri4;
154         u32     tx_pri5;
155         u32     tx_pri6;
156         u32     tx_pri7;
157         u32     tx_pri0_bcnt;
158         u32     tx_pri1_bcnt;
159         u32     tx_pri2_bcnt;
160         u32     tx_pri3_bcnt;
161         u32     tx_pri4_bcnt;
162         u32     tx_pri5_bcnt;
163         u32     tx_pri6_bcnt;
164         u32     tx_pri7_bcnt;
165         u32     tx_pri0_drop;
166         u32     tx_pri1_drop;
167         u32     tx_pri2_drop;
168         u32     tx_pri3_drop;
169         u32     tx_pri4_drop;
170         u32     tx_pri5_drop;
171         u32     tx_pri6_drop;
172         u32     tx_pri7_drop;
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;
181 };
182
183 struct am65_cpsw_ethtool_stat {
184         char desc[ETH_GSTRING_LEN];
185         int offset;
186 };
187
188 #define AM65_CPSW_STATS(prefix, field)                  \
189 {                                                       \
190         #prefix#field,                                  \
191         offsetof(struct am65_cpsw_stats_regs, field)    \
192 }
193
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),
271 };
272
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),
369 };
370
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",
375 };
376
377 static int am65_cpsw_ethtool_op_begin(struct net_device *ndev)
378 {
379         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
380         int ret;
381
382         ret = pm_runtime_get_sync(common->dev);
383         if (ret < 0) {
384                 dev_err(common->dev, "ethtool begin failed %d\n", ret);
385                 pm_runtime_put_noidle(common->dev);
386         }
387
388         return ret;
389 }
390
391 static void am65_cpsw_ethtool_op_complete(struct net_device *ndev)
392 {
393         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
394         int ret;
395
396         ret = pm_runtime_put(common->dev);
397         if (ret < 0 && ret != -EBUSY)
398                 dev_err(common->dev, "ethtool complete failed %d\n", ret);
399 }
400
401 static void am65_cpsw_get_drvinfo(struct net_device *ndev,
402                                   struct ethtool_drvinfo *info)
403 {
404         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
405
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));
409 }
410
411 static u32 am65_cpsw_get_msglevel(struct net_device *ndev)
412 {
413         struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
414
415         return priv->msg_enable;
416 }
417
418 static void am65_cpsw_set_msglevel(struct net_device *ndev, u32 value)
419 {
420         struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
421
422         priv->msg_enable = value;
423 }
424
425 static void am65_cpsw_get_channels(struct net_device *ndev,
426                                    struct ethtool_channels *ch)
427 {
428         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
429
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;
434 }
435
436 static int am65_cpsw_set_channels(struct net_device *ndev,
437                                   struct ethtool_channels *chs)
438 {
439         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
440
441         if (!chs->rx_count || !chs->tx_count)
442                 return -EINVAL;
443
444         /* Check if interface is up. Can change the num queues when
445          * the interface is down.
446          */
447         if (netif_running(ndev))
448                 return -EBUSY;
449
450         am65_cpsw_nuss_remove_tx_chns(common);
451
452         return am65_cpsw_nuss_update_tx_chns(common, chs->tx_count);
453 }
454
455 static void am65_cpsw_get_ringparam(struct net_device *ndev,
456                                     struct ethtool_ringparam *ering)
457 {
458         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
459
460         /* not supported */
461         ering->tx_pending = common->tx_chns[0].descs_num;
462         ering->rx_pending = common->rx_chns.descs_num;
463 }
464
465 static void am65_cpsw_get_pauseparam(struct net_device *ndev,
466                                      struct ethtool_pauseparam *pause)
467 {
468         struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
469
470         pause->autoneg = AUTONEG_DISABLE;
471         pause->rx_pause = salve->rx_pause ? true : false;
472         pause->tx_pause = salve->tx_pause ? true : false;
473 }
474
475 static int am65_cpsw_set_pauseparam(struct net_device *ndev,
476                                     struct ethtool_pauseparam *pause)
477 {
478         struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
479
480         if (!salve->phy)
481                 return -EINVAL;
482
483         if (!phy_validate_pause(salve->phy, pause))
484                 return -EINVAL;
485
486         salve->rx_pause = pause->rx_pause ? true : false;
487         salve->tx_pause = pause->tx_pause ? true : false;
488
489         phy_set_asym_pause(salve->phy, salve->rx_pause, salve->tx_pause);
490
491         return 0;
492 }
493
494 static void am65_cpsw_get_wol(struct net_device *ndev,
495                               struct ethtool_wolinfo *wol)
496 {
497         struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
498
499         wol->supported = 0;
500         wol->wolopts = 0;
501
502         if (salve->phy)
503                 phy_ethtool_get_wol(salve->phy, wol);
504 }
505
506 static int am65_cpsw_set_wol(struct net_device *ndev,
507                              struct ethtool_wolinfo *wol)
508 {
509         struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
510
511         if (!salve->phy)
512                 return -EOPNOTSUPP;
513
514         return phy_ethtool_set_wol(salve->phy, wol);
515 }
516
517 static int am65_cpsw_get_link_ksettings(struct net_device *ndev,
518                                         struct ethtool_link_ksettings *ecmd)
519 {
520         struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
521
522         if (!salve->phy)
523                 return -EOPNOTSUPP;
524
525         phy_ethtool_ksettings_get(salve->phy, ecmd);
526         return 0;
527 }
528
529 static int
530 am65_cpsw_set_link_ksettings(struct net_device *ndev,
531                              const struct ethtool_link_ksettings *ecmd)
532 {
533         struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
534
535         if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
536                 return -EOPNOTSUPP;
537
538         return phy_ethtool_ksettings_set(salve->phy, ecmd);
539 }
540
541 static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata)
542 {
543         struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
544
545         if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
546                 return -EOPNOTSUPP;
547
548         return phy_ethtool_get_eee(salve->phy, edata);
549 }
550
551 static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata)
552 {
553         struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
554
555         if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
556                 return -EOPNOTSUPP;
557
558         return phy_ethtool_set_eee(salve->phy, edata);
559 }
560
561 static int am65_cpsw_nway_reset(struct net_device *ndev)
562 {
563         struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
564
565         if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
566                 return -EOPNOTSUPP;
567
568         return phy_restart_aneg(salve->phy);
569 }
570
571 static int am65_cpsw_get_regs_len(struct net_device *ndev)
572 {
573         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
574         u32 i, regdump_len = 0;
575
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);
582                         continue;
583                 }
584                 regdump_len += am65_cpsw_regdump[i].hdr.len;
585         }
586
587         return regdump_len;
588 }
589
590 static void am65_cpsw_get_regs(struct net_device *ndev,
591                                struct ethtool_regs *regs, void *p)
592 {
593         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
594         u32 i, j, pos, *reg = p;
595
596         /* update CPSW IP version */
597         regs->version = AM65_CPSW_REGDUMP_VER;
598
599         pos = 0;
600         for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
601                 reg[pos++] = am65_cpsw_regdump[i].hdr.module_id;
602
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, &reg[pos]);
610                         pos += ale_tbl_len;
611                         continue;
612                 }
613
614                 reg[pos++] = am65_cpsw_regdump[i].hdr.len;
615
616                 j = am65_cpsw_regdump[i].start_ofs;
617                 do {
618                         reg[pos++] = j;
619                         reg[pos++] = readl_relaxed(common->ss_base + j);
620                         j += sizeof(u32);
621                 } while (j <= am65_cpsw_regdump[i].end_ofs);
622         }
623 }
624
625 static int am65_cpsw_get_sset_count(struct net_device *ndev, int sset)
626 {
627         switch (sset) {
628         case ETH_SS_STATS:
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);
633         default:
634                 return -EOPNOTSUPP;
635         }
636 }
637
638 static void am65_cpsw_get_strings(struct net_device *ndev,
639                                   u32 stringset, u8 *data)
640 {
641         const struct am65_cpsw_ethtool_stat *hw_stats;
642         u32 i, num_stats;
643         u8 *p = data;
644
645         switch (stringset) {
646         case ETH_SS_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;
652                 }
653
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;
659                 }
660                 break;
661         case ETH_SS_PRIV_FLAGS:
662                 num_stats = ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
663
664                 for (i = 0; i < num_stats; i++) {
665                         memcpy(p, am65_cpsw_ethtool_priv_flags[i],
666                                ETH_GSTRING_LEN);
667                         p += ETH_GSTRING_LEN;
668                 }
669                 break;
670         }
671 }
672
673 static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
674                                         struct ethtool_stats *stats, u64 *data)
675 {
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;
680         u32 i, num_stats;
681
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 +
688                                         hw_stats[i].offset);
689
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 +
694                                         hw_stats[i].offset);
695 }
696
697 static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
698 {
699         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
700         u32 priv_flags = 0;
701
702         if (common->pf_p0_rx_ptype_rrobin)
703                 priv_flags |= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN;
704
705         return priv_flags;
706 }
707
708 static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
709 {
710         struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
711
712         common->pf_p0_rx_ptype_rrobin =
713                         !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
714         am65_cpsw_nuss_set_p0_ptype(common);
715
716         return 0;
717 }
718
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,
736
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,
747 };