1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
6 #define SJA1105_SIZE_MAC_AREA (0x02 * 4)
7 #define SJA1105_SIZE_HL1_AREA (0x10 * 4)
8 #define SJA1105_SIZE_HL2_AREA (0x4 * 4)
9 #define SJA1105_SIZE_QLEVEL_AREA (0x8 * 4) /* 0x4 to 0xB */
10 #define SJA1105_SIZE_ETHER_AREA (0x17 * 4)
12 struct sja1105_port_status_mac
{
39 struct sja1105_port_status_hl1
{
58 struct sja1105_port_status_hl2
{
63 u64 qlevel_hwm
[8]; /* Only for P/Q/R/S */
64 u64 qlevel
[8]; /* Only for P/Q/R/S */
67 struct sja1105_port_status_ether
{
75 u64 n_tx_bytes_1024_2047
;
76 u64 n_tx_bytes_512_1023
;
77 u64 n_tx_bytes_256_511
;
78 u64 n_tx_bytes_128_255
;
79 u64 n_tx_bytes_65_127
;
83 u64 n_rx_bytes_1024_2047
;
84 u64 n_rx_bytes_512_1023
;
85 u64 n_rx_bytes_256_511
;
86 u64 n_rx_bytes_128_255
;
87 u64 n_rx_bytes_65_127
;
93 struct sja1105_port_status
{
94 struct sja1105_port_status_mac mac
;
95 struct sja1105_port_status_hl1 hl1
;
96 struct sja1105_port_status_hl2 hl2
;
97 struct sja1105_port_status_ether ether
;
101 sja1105_port_status_mac_unpack(void *buf
,
102 struct sja1105_port_status_mac
*status
)
104 /* Make pointer arithmetic work on 4 bytes */
107 sja1105_unpack(p
+ 0x0, &status
->n_runt
, 31, 24, 4);
108 sja1105_unpack(p
+ 0x0, &status
->n_soferr
, 23, 16, 4);
109 sja1105_unpack(p
+ 0x0, &status
->n_alignerr
, 15, 8, 4);
110 sja1105_unpack(p
+ 0x0, &status
->n_miierr
, 7, 0, 4);
111 sja1105_unpack(p
+ 0x1, &status
->typeerr
, 27, 27, 4);
112 sja1105_unpack(p
+ 0x1, &status
->sizeerr
, 26, 26, 4);
113 sja1105_unpack(p
+ 0x1, &status
->tctimeout
, 25, 25, 4);
114 sja1105_unpack(p
+ 0x1, &status
->priorerr
, 24, 24, 4);
115 sja1105_unpack(p
+ 0x1, &status
->nomaster
, 23, 23, 4);
116 sja1105_unpack(p
+ 0x1, &status
->memov
, 22, 22, 4);
117 sja1105_unpack(p
+ 0x1, &status
->memerr
, 21, 21, 4);
118 sja1105_unpack(p
+ 0x1, &status
->invtyp
, 19, 19, 4);
119 sja1105_unpack(p
+ 0x1, &status
->intcyov
, 18, 18, 4);
120 sja1105_unpack(p
+ 0x1, &status
->domerr
, 17, 17, 4);
121 sja1105_unpack(p
+ 0x1, &status
->pcfbagdrop
, 16, 16, 4);
122 sja1105_unpack(p
+ 0x1, &status
->spcprior
, 15, 12, 4);
123 sja1105_unpack(p
+ 0x1, &status
->ageprior
, 11, 8, 4);
124 sja1105_unpack(p
+ 0x1, &status
->portdrop
, 6, 6, 4);
125 sja1105_unpack(p
+ 0x1, &status
->lendrop
, 5, 5, 4);
126 sja1105_unpack(p
+ 0x1, &status
->bagdrop
, 4, 4, 4);
127 sja1105_unpack(p
+ 0x1, &status
->policeerr
, 3, 3, 4);
128 sja1105_unpack(p
+ 0x1, &status
->drpnona664err
, 2, 2, 4);
129 sja1105_unpack(p
+ 0x1, &status
->spcerr
, 1, 1, 4);
130 sja1105_unpack(p
+ 0x1, &status
->agedrp
, 0, 0, 4);
134 sja1105_port_status_hl1_unpack(void *buf
,
135 struct sja1105_port_status_hl1
*status
)
137 /* Make pointer arithmetic work on 4 bytes */
140 sja1105_unpack(p
+ 0xF, &status
->n_n664err
, 31, 0, 4);
141 sja1105_unpack(p
+ 0xE, &status
->n_vlanerr
, 31, 0, 4);
142 sja1105_unpack(p
+ 0xD, &status
->n_unreleased
, 31, 0, 4);
143 sja1105_unpack(p
+ 0xC, &status
->n_sizeerr
, 31, 0, 4);
144 sja1105_unpack(p
+ 0xB, &status
->n_crcerr
, 31, 0, 4);
145 sja1105_unpack(p
+ 0xA, &status
->n_vlnotfound
, 31, 0, 4);
146 sja1105_unpack(p
+ 0x9, &status
->n_ctpolerr
, 31, 0, 4);
147 sja1105_unpack(p
+ 0x8, &status
->n_polerr
, 31, 0, 4);
148 sja1105_unpack(p
+ 0x7, &status
->n_rxfrmsh
, 31, 0, 4);
149 sja1105_unpack(p
+ 0x6, &status
->n_rxfrm
, 31, 0, 4);
150 sja1105_unpack(p
+ 0x5, &status
->n_rxbytesh
, 31, 0, 4);
151 sja1105_unpack(p
+ 0x4, &status
->n_rxbyte
, 31, 0, 4);
152 sja1105_unpack(p
+ 0x3, &status
->n_txfrmsh
, 31, 0, 4);
153 sja1105_unpack(p
+ 0x2, &status
->n_txfrm
, 31, 0, 4);
154 sja1105_unpack(p
+ 0x1, &status
->n_txbytesh
, 31, 0, 4);
155 sja1105_unpack(p
+ 0x0, &status
->n_txbyte
, 31, 0, 4);
156 status
->n_rxfrm
+= status
->n_rxfrmsh
<< 32;
157 status
->n_rxbyte
+= status
->n_rxbytesh
<< 32;
158 status
->n_txfrm
+= status
->n_txfrmsh
<< 32;
159 status
->n_txbyte
+= status
->n_txbytesh
<< 32;
163 sja1105_port_status_hl2_unpack(void *buf
,
164 struct sja1105_port_status_hl2
*status
)
166 /* Make pointer arithmetic work on 4 bytes */
169 sja1105_unpack(p
+ 0x3, &status
->n_qfull
, 31, 0, 4);
170 sja1105_unpack(p
+ 0x2, &status
->n_part_drop
, 31, 0, 4);
171 sja1105_unpack(p
+ 0x1, &status
->n_egr_disabled
, 31, 0, 4);
172 sja1105_unpack(p
+ 0x0, &status
->n_not_reach
, 31, 0, 4);
176 sja1105pqrs_port_status_qlevel_unpack(void *buf
,
177 struct sja1105_port_status_hl2
*status
)
179 /* Make pointer arithmetic work on 4 bytes */
183 for (i
= 0; i
< 8; i
++) {
184 sja1105_unpack(p
+ i
, &status
->qlevel_hwm
[i
], 24, 16, 4);
185 sja1105_unpack(p
+ i
, &status
->qlevel
[i
], 8, 0, 4);
190 sja1105pqrs_port_status_ether_unpack(void *buf
,
191 struct sja1105_port_status_ether
*status
)
193 /* Make pointer arithmetic work on 4 bytes */
196 sja1105_unpack(p
+ 0x16, &status
->n_drops_nolearn
, 31, 0, 4);
197 sja1105_unpack(p
+ 0x15, &status
->n_drops_noroute
, 31, 0, 4);
198 sja1105_unpack(p
+ 0x14, &status
->n_drops_ill_dtag
, 31, 0, 4);
199 sja1105_unpack(p
+ 0x13, &status
->n_drops_dtag
, 31, 0, 4);
200 sja1105_unpack(p
+ 0x12, &status
->n_drops_sotag
, 31, 0, 4);
201 sja1105_unpack(p
+ 0x11, &status
->n_drops_sitag
, 31, 0, 4);
202 sja1105_unpack(p
+ 0x10, &status
->n_drops_utag
, 31, 0, 4);
203 sja1105_unpack(p
+ 0x0F, &status
->n_tx_bytes_1024_2047
, 31, 0, 4);
204 sja1105_unpack(p
+ 0x0E, &status
->n_tx_bytes_512_1023
, 31, 0, 4);
205 sja1105_unpack(p
+ 0x0D, &status
->n_tx_bytes_256_511
, 31, 0, 4);
206 sja1105_unpack(p
+ 0x0C, &status
->n_tx_bytes_128_255
, 31, 0, 4);
207 sja1105_unpack(p
+ 0x0B, &status
->n_tx_bytes_65_127
, 31, 0, 4);
208 sja1105_unpack(p
+ 0x0A, &status
->n_tx_bytes_64
, 31, 0, 4);
209 sja1105_unpack(p
+ 0x09, &status
->n_tx_mcast
, 31, 0, 4);
210 sja1105_unpack(p
+ 0x08, &status
->n_tx_bcast
, 31, 0, 4);
211 sja1105_unpack(p
+ 0x07, &status
->n_rx_bytes_1024_2047
, 31, 0, 4);
212 sja1105_unpack(p
+ 0x06, &status
->n_rx_bytes_512_1023
, 31, 0, 4);
213 sja1105_unpack(p
+ 0x05, &status
->n_rx_bytes_256_511
, 31, 0, 4);
214 sja1105_unpack(p
+ 0x04, &status
->n_rx_bytes_128_255
, 31, 0, 4);
215 sja1105_unpack(p
+ 0x03, &status
->n_rx_bytes_65_127
, 31, 0, 4);
216 sja1105_unpack(p
+ 0x02, &status
->n_rx_bytes_64
, 31, 0, 4);
217 sja1105_unpack(p
+ 0x01, &status
->n_rx_mcast
, 31, 0, 4);
218 sja1105_unpack(p
+ 0x00, &status
->n_rx_bcast
, 31, 0, 4);
222 sja1105pqrs_port_status_get_ether(struct sja1105_private
*priv
,
223 struct sja1105_port_status_ether
*ether
,
226 const struct sja1105_regs
*regs
= priv
->info
->regs
;
227 u8 packed_buf
[SJA1105_SIZE_ETHER_AREA
] = {0};
230 /* Ethernet statistics area */
231 rc
= sja1105_xfer_buf(priv
, SPI_READ
, regs
->ether_stats
[port
],
232 packed_buf
, SJA1105_SIZE_ETHER_AREA
);
236 sja1105pqrs_port_status_ether_unpack(packed_buf
, ether
);
241 static int sja1105_port_status_get_mac(struct sja1105_private
*priv
,
242 struct sja1105_port_status_mac
*status
,
245 const struct sja1105_regs
*regs
= priv
->info
->regs
;
246 u8 packed_buf
[SJA1105_SIZE_MAC_AREA
] = {0};
250 rc
= sja1105_xfer_buf(priv
, SPI_READ
, regs
->mac
[port
], packed_buf
,
251 SJA1105_SIZE_MAC_AREA
);
255 sja1105_port_status_mac_unpack(packed_buf
, status
);
260 static int sja1105_port_status_get_hl1(struct sja1105_private
*priv
,
261 struct sja1105_port_status_hl1
*status
,
264 const struct sja1105_regs
*regs
= priv
->info
->regs
;
265 u8 packed_buf
[SJA1105_SIZE_HL1_AREA
] = {0};
268 rc
= sja1105_xfer_buf(priv
, SPI_READ
, regs
->mac_hl1
[port
], packed_buf
,
269 SJA1105_SIZE_HL1_AREA
);
273 sja1105_port_status_hl1_unpack(packed_buf
, status
);
278 static int sja1105_port_status_get_hl2(struct sja1105_private
*priv
,
279 struct sja1105_port_status_hl2
*status
,
282 const struct sja1105_regs
*regs
= priv
->info
->regs
;
283 u8 packed_buf
[SJA1105_SIZE_QLEVEL_AREA
] = {0};
286 rc
= sja1105_xfer_buf(priv
, SPI_READ
, regs
->mac_hl2
[port
], packed_buf
,
287 SJA1105_SIZE_HL2_AREA
);
291 sja1105_port_status_hl2_unpack(packed_buf
, status
);
293 /* Code below is strictly P/Q/R/S specific. */
294 if (priv
->info
->device_id
== SJA1105E_DEVICE_ID
||
295 priv
->info
->device_id
== SJA1105T_DEVICE_ID
)
298 rc
= sja1105_xfer_buf(priv
, SPI_READ
, regs
->qlevel
[port
], packed_buf
,
299 SJA1105_SIZE_QLEVEL_AREA
);
303 sja1105pqrs_port_status_qlevel_unpack(packed_buf
, status
);
308 static int sja1105_port_status_get(struct sja1105_private
*priv
,
309 struct sja1105_port_status
*status
,
314 rc
= sja1105_port_status_get_mac(priv
, &status
->mac
, port
);
317 rc
= sja1105_port_status_get_hl1(priv
, &status
->hl1
, port
);
320 rc
= sja1105_port_status_get_hl2(priv
, &status
->hl2
, port
);
324 if (priv
->info
->device_id
== SJA1105E_DEVICE_ID
||
325 priv
->info
->device_id
== SJA1105T_DEVICE_ID
)
328 return sja1105pqrs_port_status_get_ether(priv
, &status
->ether
, port
);
331 static char sja1105_port_stats
[][ETH_GSTRING_LEN
] = {
332 /* MAC-Level Diagnostic Counters */
337 /* MAC-Level Diagnostic Flags */
358 /* High-Level Diagnostic Counters */
377 static char sja1105pqrs_extra_port_stats
[][ETH_GSTRING_LEN
] = {
403 "n_tx_bytes_1024_2047",
404 "n_tx_bytes_512_1023",
405 "n_tx_bytes_256_511",
406 "n_tx_bytes_128_255",
411 "n_rx_bytes_1024_2047",
412 "n_rx_bytes_512_1023",
413 "n_rx_bytes_256_511",
414 "n_rx_bytes_128_255",
421 void sja1105_get_ethtool_stats(struct dsa_switch
*ds
, int port
, u64
*data
)
423 struct sja1105_private
*priv
= ds
->priv
;
424 struct sja1105_port_status
*status
;
427 status
= kzalloc(sizeof(*status
), GFP_KERNEL
);
431 rc
= sja1105_port_status_get(priv
, status
, port
);
433 dev_err(ds
->dev
, "Failed to read port %d counters: %d\n",
437 memset(data
, 0, ARRAY_SIZE(sja1105_port_stats
) * sizeof(u64
));
438 data
[k
++] = status
->mac
.n_runt
;
439 data
[k
++] = status
->mac
.n_soferr
;
440 data
[k
++] = status
->mac
.n_alignerr
;
441 data
[k
++] = status
->mac
.n_miierr
;
442 data
[k
++] = status
->mac
.typeerr
;
443 data
[k
++] = status
->mac
.sizeerr
;
444 data
[k
++] = status
->mac
.tctimeout
;
445 data
[k
++] = status
->mac
.priorerr
;
446 data
[k
++] = status
->mac
.nomaster
;
447 data
[k
++] = status
->mac
.memov
;
448 data
[k
++] = status
->mac
.memerr
;
449 data
[k
++] = status
->mac
.invtyp
;
450 data
[k
++] = status
->mac
.intcyov
;
451 data
[k
++] = status
->mac
.domerr
;
452 data
[k
++] = status
->mac
.pcfbagdrop
;
453 data
[k
++] = status
->mac
.spcprior
;
454 data
[k
++] = status
->mac
.ageprior
;
455 data
[k
++] = status
->mac
.portdrop
;
456 data
[k
++] = status
->mac
.lendrop
;
457 data
[k
++] = status
->mac
.bagdrop
;
458 data
[k
++] = status
->mac
.policeerr
;
459 data
[k
++] = status
->mac
.drpnona664err
;
460 data
[k
++] = status
->mac
.spcerr
;
461 data
[k
++] = status
->mac
.agedrp
;
462 data
[k
++] = status
->hl1
.n_n664err
;
463 data
[k
++] = status
->hl1
.n_vlanerr
;
464 data
[k
++] = status
->hl1
.n_unreleased
;
465 data
[k
++] = status
->hl1
.n_sizeerr
;
466 data
[k
++] = status
->hl1
.n_crcerr
;
467 data
[k
++] = status
->hl1
.n_vlnotfound
;
468 data
[k
++] = status
->hl1
.n_ctpolerr
;
469 data
[k
++] = status
->hl1
.n_polerr
;
470 data
[k
++] = status
->hl1
.n_rxfrm
;
471 data
[k
++] = status
->hl1
.n_rxbyte
;
472 data
[k
++] = status
->hl1
.n_txfrm
;
473 data
[k
++] = status
->hl1
.n_txbyte
;
474 data
[k
++] = status
->hl2
.n_qfull
;
475 data
[k
++] = status
->hl2
.n_part_drop
;
476 data
[k
++] = status
->hl2
.n_egr_disabled
;
477 data
[k
++] = status
->hl2
.n_not_reach
;
479 if (priv
->info
->device_id
== SJA1105E_DEVICE_ID
||
480 priv
->info
->device_id
== SJA1105T_DEVICE_ID
)
483 memset(data
+ k
, 0, ARRAY_SIZE(sja1105pqrs_extra_port_stats
) *
485 for (i
= 0; i
< 8; i
++) {
486 data
[k
++] = status
->hl2
.qlevel_hwm
[i
];
487 data
[k
++] = status
->hl2
.qlevel
[i
];
489 data
[k
++] = status
->ether
.n_drops_nolearn
;
490 data
[k
++] = status
->ether
.n_drops_noroute
;
491 data
[k
++] = status
->ether
.n_drops_ill_dtag
;
492 data
[k
++] = status
->ether
.n_drops_dtag
;
493 data
[k
++] = status
->ether
.n_drops_sotag
;
494 data
[k
++] = status
->ether
.n_drops_sitag
;
495 data
[k
++] = status
->ether
.n_drops_utag
;
496 data
[k
++] = status
->ether
.n_tx_bytes_1024_2047
;
497 data
[k
++] = status
->ether
.n_tx_bytes_512_1023
;
498 data
[k
++] = status
->ether
.n_tx_bytes_256_511
;
499 data
[k
++] = status
->ether
.n_tx_bytes_128_255
;
500 data
[k
++] = status
->ether
.n_tx_bytes_65_127
;
501 data
[k
++] = status
->ether
.n_tx_bytes_64
;
502 data
[k
++] = status
->ether
.n_tx_mcast
;
503 data
[k
++] = status
->ether
.n_tx_bcast
;
504 data
[k
++] = status
->ether
.n_rx_bytes_1024_2047
;
505 data
[k
++] = status
->ether
.n_rx_bytes_512_1023
;
506 data
[k
++] = status
->ether
.n_rx_bytes_256_511
;
507 data
[k
++] = status
->ether
.n_rx_bytes_128_255
;
508 data
[k
++] = status
->ether
.n_rx_bytes_65_127
;
509 data
[k
++] = status
->ether
.n_rx_bytes_64
;
510 data
[k
++] = status
->ether
.n_rx_mcast
;
511 data
[k
++] = status
->ether
.n_rx_bcast
;
516 void sja1105_get_strings(struct dsa_switch
*ds
, int port
,
517 u32 stringset
, u8
*data
)
519 struct sja1105_private
*priv
= ds
->priv
;
525 for (i
= 0; i
< ARRAY_SIZE(sja1105_port_stats
); i
++) {
526 strlcpy(p
, sja1105_port_stats
[i
], ETH_GSTRING_LEN
);
527 p
+= ETH_GSTRING_LEN
;
529 if (priv
->info
->device_id
== SJA1105E_DEVICE_ID
||
530 priv
->info
->device_id
== SJA1105T_DEVICE_ID
)
532 for (i
= 0; i
< ARRAY_SIZE(sja1105pqrs_extra_port_stats
); i
++) {
533 strlcpy(p
, sja1105pqrs_extra_port_stats
[i
],
535 p
+= ETH_GSTRING_LEN
;
541 int sja1105_get_sset_count(struct dsa_switch
*ds
, int port
, int sset
)
543 int count
= ARRAY_SIZE(sja1105_port_stats
);
544 struct sja1105_private
*priv
= ds
->priv
;
546 if (sset
!= ETH_SS_STATS
)
549 if (priv
->info
->device_id
== SJA1105PR_DEVICE_ID
||
550 priv
->info
->device_id
== SJA1105QS_DEVICE_ID
)
551 count
+= ARRAY_SIZE(sja1105pqrs_extra_port_stats
);