18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> 38c2ecf20Sopenharmony_ci */ 48c2ecf20Sopenharmony_ci#include "sja1105.h" 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#define SJA1105_SIZE_MAC_AREA (0x02 * 4) 78c2ecf20Sopenharmony_ci#define SJA1105_SIZE_HL1_AREA (0x10 * 4) 88c2ecf20Sopenharmony_ci#define SJA1105_SIZE_HL2_AREA (0x4 * 4) 98c2ecf20Sopenharmony_ci#define SJA1105_SIZE_QLEVEL_AREA (0x8 * 4) /* 0x4 to 0xB */ 108c2ecf20Sopenharmony_ci#define SJA1105_SIZE_ETHER_AREA (0x17 * 4) 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistruct sja1105_port_status_mac { 138c2ecf20Sopenharmony_ci u64 n_runt; 148c2ecf20Sopenharmony_ci u64 n_soferr; 158c2ecf20Sopenharmony_ci u64 n_alignerr; 168c2ecf20Sopenharmony_ci u64 n_miierr; 178c2ecf20Sopenharmony_ci u64 typeerr; 188c2ecf20Sopenharmony_ci u64 sizeerr; 198c2ecf20Sopenharmony_ci u64 tctimeout; 208c2ecf20Sopenharmony_ci u64 priorerr; 218c2ecf20Sopenharmony_ci u64 nomaster; 228c2ecf20Sopenharmony_ci u64 memov; 238c2ecf20Sopenharmony_ci u64 memerr; 248c2ecf20Sopenharmony_ci u64 invtyp; 258c2ecf20Sopenharmony_ci u64 intcyov; 268c2ecf20Sopenharmony_ci u64 domerr; 278c2ecf20Sopenharmony_ci u64 pcfbagdrop; 288c2ecf20Sopenharmony_ci u64 spcprior; 298c2ecf20Sopenharmony_ci u64 ageprior; 308c2ecf20Sopenharmony_ci u64 portdrop; 318c2ecf20Sopenharmony_ci u64 lendrop; 328c2ecf20Sopenharmony_ci u64 bagdrop; 338c2ecf20Sopenharmony_ci u64 policeerr; 348c2ecf20Sopenharmony_ci u64 drpnona664err; 358c2ecf20Sopenharmony_ci u64 spcerr; 368c2ecf20Sopenharmony_ci u64 agedrp; 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct sja1105_port_status_hl1 { 408c2ecf20Sopenharmony_ci u64 n_n664err; 418c2ecf20Sopenharmony_ci u64 n_vlanerr; 428c2ecf20Sopenharmony_ci u64 n_unreleased; 438c2ecf20Sopenharmony_ci u64 n_sizeerr; 448c2ecf20Sopenharmony_ci u64 n_crcerr; 458c2ecf20Sopenharmony_ci u64 n_vlnotfound; 468c2ecf20Sopenharmony_ci u64 n_ctpolerr; 478c2ecf20Sopenharmony_ci u64 n_polerr; 488c2ecf20Sopenharmony_ci u64 n_rxfrmsh; 498c2ecf20Sopenharmony_ci u64 n_rxfrm; 508c2ecf20Sopenharmony_ci u64 n_rxbytesh; 518c2ecf20Sopenharmony_ci u64 n_rxbyte; 528c2ecf20Sopenharmony_ci u64 n_txfrmsh; 538c2ecf20Sopenharmony_ci u64 n_txfrm; 548c2ecf20Sopenharmony_ci u64 n_txbytesh; 558c2ecf20Sopenharmony_ci u64 n_txbyte; 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistruct sja1105_port_status_hl2 { 598c2ecf20Sopenharmony_ci u64 n_qfull; 608c2ecf20Sopenharmony_ci u64 n_part_drop; 618c2ecf20Sopenharmony_ci u64 n_egr_disabled; 628c2ecf20Sopenharmony_ci u64 n_not_reach; 638c2ecf20Sopenharmony_ci u64 qlevel_hwm[8]; /* Only for P/Q/R/S */ 648c2ecf20Sopenharmony_ci u64 qlevel[8]; /* Only for P/Q/R/S */ 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct sja1105_port_status_ether { 688c2ecf20Sopenharmony_ci u64 n_drops_nolearn; 698c2ecf20Sopenharmony_ci u64 n_drops_noroute; 708c2ecf20Sopenharmony_ci u64 n_drops_ill_dtag; 718c2ecf20Sopenharmony_ci u64 n_drops_dtag; 728c2ecf20Sopenharmony_ci u64 n_drops_sotag; 738c2ecf20Sopenharmony_ci u64 n_drops_sitag; 748c2ecf20Sopenharmony_ci u64 n_drops_utag; 758c2ecf20Sopenharmony_ci u64 n_tx_bytes_1024_2047; 768c2ecf20Sopenharmony_ci u64 n_tx_bytes_512_1023; 778c2ecf20Sopenharmony_ci u64 n_tx_bytes_256_511; 788c2ecf20Sopenharmony_ci u64 n_tx_bytes_128_255; 798c2ecf20Sopenharmony_ci u64 n_tx_bytes_65_127; 808c2ecf20Sopenharmony_ci u64 n_tx_bytes_64; 818c2ecf20Sopenharmony_ci u64 n_tx_mcast; 828c2ecf20Sopenharmony_ci u64 n_tx_bcast; 838c2ecf20Sopenharmony_ci u64 n_rx_bytes_1024_2047; 848c2ecf20Sopenharmony_ci u64 n_rx_bytes_512_1023; 858c2ecf20Sopenharmony_ci u64 n_rx_bytes_256_511; 868c2ecf20Sopenharmony_ci u64 n_rx_bytes_128_255; 878c2ecf20Sopenharmony_ci u64 n_rx_bytes_65_127; 888c2ecf20Sopenharmony_ci u64 n_rx_bytes_64; 898c2ecf20Sopenharmony_ci u64 n_rx_mcast; 908c2ecf20Sopenharmony_ci u64 n_rx_bcast; 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistruct sja1105_port_status { 948c2ecf20Sopenharmony_ci struct sja1105_port_status_mac mac; 958c2ecf20Sopenharmony_ci struct sja1105_port_status_hl1 hl1; 968c2ecf20Sopenharmony_ci struct sja1105_port_status_hl2 hl2; 978c2ecf20Sopenharmony_ci struct sja1105_port_status_ether ether; 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic void 1018c2ecf20Sopenharmony_cisja1105_port_status_mac_unpack(void *buf, 1028c2ecf20Sopenharmony_ci struct sja1105_port_status_mac *status) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci /* Make pointer arithmetic work on 4 bytes */ 1058c2ecf20Sopenharmony_ci u32 *p = buf; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0, &status->n_runt, 31, 24, 4); 1088c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0, &status->n_soferr, 23, 16, 4); 1098c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0, &status->n_alignerr, 15, 8, 4); 1108c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0, &status->n_miierr, 7, 0, 4); 1118c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->typeerr, 27, 27, 4); 1128c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->sizeerr, 26, 26, 4); 1138c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->tctimeout, 25, 25, 4); 1148c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->priorerr, 24, 24, 4); 1158c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->nomaster, 23, 23, 4); 1168c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->memov, 22, 22, 4); 1178c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->memerr, 21, 21, 4); 1188c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->invtyp, 19, 19, 4); 1198c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->intcyov, 18, 18, 4); 1208c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->domerr, 17, 17, 4); 1218c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->pcfbagdrop, 16, 16, 4); 1228c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->spcprior, 15, 12, 4); 1238c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->ageprior, 11, 8, 4); 1248c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->portdrop, 6, 6, 4); 1258c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->lendrop, 5, 5, 4); 1268c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->bagdrop, 4, 4, 4); 1278c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->policeerr, 3, 3, 4); 1288c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->drpnona664err, 2, 2, 4); 1298c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->spcerr, 1, 1, 4); 1308c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->agedrp, 0, 0, 4); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic void 1348c2ecf20Sopenharmony_cisja1105_port_status_hl1_unpack(void *buf, 1358c2ecf20Sopenharmony_ci struct sja1105_port_status_hl1 *status) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci /* Make pointer arithmetic work on 4 bytes */ 1388c2ecf20Sopenharmony_ci u32 *p = buf; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci sja1105_unpack(p + 0xF, &status->n_n664err, 31, 0, 4); 1418c2ecf20Sopenharmony_ci sja1105_unpack(p + 0xE, &status->n_vlanerr, 31, 0, 4); 1428c2ecf20Sopenharmony_ci sja1105_unpack(p + 0xD, &status->n_unreleased, 31, 0, 4); 1438c2ecf20Sopenharmony_ci sja1105_unpack(p + 0xC, &status->n_sizeerr, 31, 0, 4); 1448c2ecf20Sopenharmony_ci sja1105_unpack(p + 0xB, &status->n_crcerr, 31, 0, 4); 1458c2ecf20Sopenharmony_ci sja1105_unpack(p + 0xA, &status->n_vlnotfound, 31, 0, 4); 1468c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x9, &status->n_ctpolerr, 31, 0, 4); 1478c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x8, &status->n_polerr, 31, 0, 4); 1488c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x7, &status->n_rxfrmsh, 31, 0, 4); 1498c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x6, &status->n_rxfrm, 31, 0, 4); 1508c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x5, &status->n_rxbytesh, 31, 0, 4); 1518c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x4, &status->n_rxbyte, 31, 0, 4); 1528c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x3, &status->n_txfrmsh, 31, 0, 4); 1538c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x2, &status->n_txfrm, 31, 0, 4); 1548c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->n_txbytesh, 31, 0, 4); 1558c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0, &status->n_txbyte, 31, 0, 4); 1568c2ecf20Sopenharmony_ci status->n_rxfrm += status->n_rxfrmsh << 32; 1578c2ecf20Sopenharmony_ci status->n_rxbyte += status->n_rxbytesh << 32; 1588c2ecf20Sopenharmony_ci status->n_txfrm += status->n_txfrmsh << 32; 1598c2ecf20Sopenharmony_ci status->n_txbyte += status->n_txbytesh << 32; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic void 1638c2ecf20Sopenharmony_cisja1105_port_status_hl2_unpack(void *buf, 1648c2ecf20Sopenharmony_ci struct sja1105_port_status_hl2 *status) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci /* Make pointer arithmetic work on 4 bytes */ 1678c2ecf20Sopenharmony_ci u32 *p = buf; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x3, &status->n_qfull, 31, 0, 4); 1708c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x2, &status->n_part_drop, 31, 0, 4); 1718c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x1, &status->n_egr_disabled, 31, 0, 4); 1728c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0, &status->n_not_reach, 31, 0, 4); 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic void 1768c2ecf20Sopenharmony_cisja1105pqrs_port_status_qlevel_unpack(void *buf, 1778c2ecf20Sopenharmony_ci struct sja1105_port_status_hl2 *status) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci /* Make pointer arithmetic work on 4 bytes */ 1808c2ecf20Sopenharmony_ci u32 *p = buf; 1818c2ecf20Sopenharmony_ci int i; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 1848c2ecf20Sopenharmony_ci sja1105_unpack(p + i, &status->qlevel_hwm[i], 24, 16, 4); 1858c2ecf20Sopenharmony_ci sja1105_unpack(p + i, &status->qlevel[i], 8, 0, 4); 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic void 1908c2ecf20Sopenharmony_cisja1105pqrs_port_status_ether_unpack(void *buf, 1918c2ecf20Sopenharmony_ci struct sja1105_port_status_ether *status) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci /* Make pointer arithmetic work on 4 bytes */ 1948c2ecf20Sopenharmony_ci u32 *p = buf; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x16, &status->n_drops_nolearn, 31, 0, 4); 1978c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x15, &status->n_drops_noroute, 31, 0, 4); 1988c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x14, &status->n_drops_ill_dtag, 31, 0, 4); 1998c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x13, &status->n_drops_dtag, 31, 0, 4); 2008c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x12, &status->n_drops_sotag, 31, 0, 4); 2018c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x11, &status->n_drops_sitag, 31, 0, 4); 2028c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x10, &status->n_drops_utag, 31, 0, 4); 2038c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0F, &status->n_tx_bytes_1024_2047, 31, 0, 4); 2048c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0E, &status->n_tx_bytes_512_1023, 31, 0, 4); 2058c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0D, &status->n_tx_bytes_256_511, 31, 0, 4); 2068c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0C, &status->n_tx_bytes_128_255, 31, 0, 4); 2078c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0B, &status->n_tx_bytes_65_127, 31, 0, 4); 2088c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x0A, &status->n_tx_bytes_64, 31, 0, 4); 2098c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x09, &status->n_tx_mcast, 31, 0, 4); 2108c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x08, &status->n_tx_bcast, 31, 0, 4); 2118c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x07, &status->n_rx_bytes_1024_2047, 31, 0, 4); 2128c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x06, &status->n_rx_bytes_512_1023, 31, 0, 4); 2138c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x05, &status->n_rx_bytes_256_511, 31, 0, 4); 2148c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x04, &status->n_rx_bytes_128_255, 31, 0, 4); 2158c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x03, &status->n_rx_bytes_65_127, 31, 0, 4); 2168c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x02, &status->n_rx_bytes_64, 31, 0, 4); 2178c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x01, &status->n_rx_mcast, 31, 0, 4); 2188c2ecf20Sopenharmony_ci sja1105_unpack(p + 0x00, &status->n_rx_bcast, 31, 0, 4); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic int 2228c2ecf20Sopenharmony_cisja1105pqrs_port_status_get_ether(struct sja1105_private *priv, 2238c2ecf20Sopenharmony_ci struct sja1105_port_status_ether *ether, 2248c2ecf20Sopenharmony_ci int port) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci const struct sja1105_regs *regs = priv->info->regs; 2278c2ecf20Sopenharmony_ci u8 packed_buf[SJA1105_SIZE_ETHER_AREA] = {0}; 2288c2ecf20Sopenharmony_ci int rc; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* Ethernet statistics area */ 2318c2ecf20Sopenharmony_ci rc = sja1105_xfer_buf(priv, SPI_READ, regs->ether_stats[port], 2328c2ecf20Sopenharmony_ci packed_buf, SJA1105_SIZE_ETHER_AREA); 2338c2ecf20Sopenharmony_ci if (rc < 0) 2348c2ecf20Sopenharmony_ci return rc; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci sja1105pqrs_port_status_ether_unpack(packed_buf, ether); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci return 0; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic int sja1105_port_status_get_mac(struct sja1105_private *priv, 2428c2ecf20Sopenharmony_ci struct sja1105_port_status_mac *status, 2438c2ecf20Sopenharmony_ci int port) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci const struct sja1105_regs *regs = priv->info->regs; 2468c2ecf20Sopenharmony_ci u8 packed_buf[SJA1105_SIZE_MAC_AREA] = {0}; 2478c2ecf20Sopenharmony_ci int rc; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* MAC area */ 2508c2ecf20Sopenharmony_ci rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac[port], packed_buf, 2518c2ecf20Sopenharmony_ci SJA1105_SIZE_MAC_AREA); 2528c2ecf20Sopenharmony_ci if (rc < 0) 2538c2ecf20Sopenharmony_ci return rc; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci sja1105_port_status_mac_unpack(packed_buf, status); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci return 0; 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic int sja1105_port_status_get_hl1(struct sja1105_private *priv, 2618c2ecf20Sopenharmony_ci struct sja1105_port_status_hl1 *status, 2628c2ecf20Sopenharmony_ci int port) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci const struct sja1105_regs *regs = priv->info->regs; 2658c2ecf20Sopenharmony_ci u8 packed_buf[SJA1105_SIZE_HL1_AREA] = {0}; 2668c2ecf20Sopenharmony_ci int rc; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl1[port], packed_buf, 2698c2ecf20Sopenharmony_ci SJA1105_SIZE_HL1_AREA); 2708c2ecf20Sopenharmony_ci if (rc < 0) 2718c2ecf20Sopenharmony_ci return rc; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci sja1105_port_status_hl1_unpack(packed_buf, status); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci return 0; 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistatic int sja1105_port_status_get_hl2(struct sja1105_private *priv, 2798c2ecf20Sopenharmony_ci struct sja1105_port_status_hl2 *status, 2808c2ecf20Sopenharmony_ci int port) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci const struct sja1105_regs *regs = priv->info->regs; 2838c2ecf20Sopenharmony_ci u8 packed_buf[SJA1105_SIZE_QLEVEL_AREA] = {0}; 2848c2ecf20Sopenharmony_ci int rc; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl2[port], packed_buf, 2878c2ecf20Sopenharmony_ci SJA1105_SIZE_HL2_AREA); 2888c2ecf20Sopenharmony_ci if (rc < 0) 2898c2ecf20Sopenharmony_ci return rc; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci sja1105_port_status_hl2_unpack(packed_buf, status); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* Code below is strictly P/Q/R/S specific. */ 2948c2ecf20Sopenharmony_ci if (priv->info->device_id == SJA1105E_DEVICE_ID || 2958c2ecf20Sopenharmony_ci priv->info->device_id == SJA1105T_DEVICE_ID) 2968c2ecf20Sopenharmony_ci return 0; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci rc = sja1105_xfer_buf(priv, SPI_READ, regs->qlevel[port], packed_buf, 2998c2ecf20Sopenharmony_ci SJA1105_SIZE_QLEVEL_AREA); 3008c2ecf20Sopenharmony_ci if (rc < 0) 3018c2ecf20Sopenharmony_ci return rc; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci sja1105pqrs_port_status_qlevel_unpack(packed_buf, status); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci return 0; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic int sja1105_port_status_get(struct sja1105_private *priv, 3098c2ecf20Sopenharmony_ci struct sja1105_port_status *status, 3108c2ecf20Sopenharmony_ci int port) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci int rc; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci rc = sja1105_port_status_get_mac(priv, &status->mac, port); 3158c2ecf20Sopenharmony_ci if (rc < 0) 3168c2ecf20Sopenharmony_ci return rc; 3178c2ecf20Sopenharmony_ci rc = sja1105_port_status_get_hl1(priv, &status->hl1, port); 3188c2ecf20Sopenharmony_ci if (rc < 0) 3198c2ecf20Sopenharmony_ci return rc; 3208c2ecf20Sopenharmony_ci rc = sja1105_port_status_get_hl2(priv, &status->hl2, port); 3218c2ecf20Sopenharmony_ci if (rc < 0) 3228c2ecf20Sopenharmony_ci return rc; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (priv->info->device_id == SJA1105E_DEVICE_ID || 3258c2ecf20Sopenharmony_ci priv->info->device_id == SJA1105T_DEVICE_ID) 3268c2ecf20Sopenharmony_ci return 0; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci return sja1105pqrs_port_status_get_ether(priv, &status->ether, port); 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic char sja1105_port_stats[][ETH_GSTRING_LEN] = { 3328c2ecf20Sopenharmony_ci /* MAC-Level Diagnostic Counters */ 3338c2ecf20Sopenharmony_ci "n_runt", 3348c2ecf20Sopenharmony_ci "n_soferr", 3358c2ecf20Sopenharmony_ci "n_alignerr", 3368c2ecf20Sopenharmony_ci "n_miierr", 3378c2ecf20Sopenharmony_ci /* MAC-Level Diagnostic Flags */ 3388c2ecf20Sopenharmony_ci "typeerr", 3398c2ecf20Sopenharmony_ci "sizeerr", 3408c2ecf20Sopenharmony_ci "tctimeout", 3418c2ecf20Sopenharmony_ci "priorerr", 3428c2ecf20Sopenharmony_ci "nomaster", 3438c2ecf20Sopenharmony_ci "memov", 3448c2ecf20Sopenharmony_ci "memerr", 3458c2ecf20Sopenharmony_ci "invtyp", 3468c2ecf20Sopenharmony_ci "intcyov", 3478c2ecf20Sopenharmony_ci "domerr", 3488c2ecf20Sopenharmony_ci "pcfbagdrop", 3498c2ecf20Sopenharmony_ci "spcprior", 3508c2ecf20Sopenharmony_ci "ageprior", 3518c2ecf20Sopenharmony_ci "portdrop", 3528c2ecf20Sopenharmony_ci "lendrop", 3538c2ecf20Sopenharmony_ci "bagdrop", 3548c2ecf20Sopenharmony_ci "policeerr", 3558c2ecf20Sopenharmony_ci "drpnona664err", 3568c2ecf20Sopenharmony_ci "spcerr", 3578c2ecf20Sopenharmony_ci "agedrp", 3588c2ecf20Sopenharmony_ci /* High-Level Diagnostic Counters */ 3598c2ecf20Sopenharmony_ci "n_n664err", 3608c2ecf20Sopenharmony_ci "n_vlanerr", 3618c2ecf20Sopenharmony_ci "n_unreleased", 3628c2ecf20Sopenharmony_ci "n_sizeerr", 3638c2ecf20Sopenharmony_ci "n_crcerr", 3648c2ecf20Sopenharmony_ci "n_vlnotfound", 3658c2ecf20Sopenharmony_ci "n_ctpolerr", 3668c2ecf20Sopenharmony_ci "n_polerr", 3678c2ecf20Sopenharmony_ci "n_rxfrm", 3688c2ecf20Sopenharmony_ci "n_rxbyte", 3698c2ecf20Sopenharmony_ci "n_txfrm", 3708c2ecf20Sopenharmony_ci "n_txbyte", 3718c2ecf20Sopenharmony_ci "n_qfull", 3728c2ecf20Sopenharmony_ci "n_part_drop", 3738c2ecf20Sopenharmony_ci "n_egr_disabled", 3748c2ecf20Sopenharmony_ci "n_not_reach", 3758c2ecf20Sopenharmony_ci}; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_cistatic char sja1105pqrs_extra_port_stats[][ETH_GSTRING_LEN] = { 3788c2ecf20Sopenharmony_ci /* Queue Levels */ 3798c2ecf20Sopenharmony_ci "qlevel_hwm_0", 3808c2ecf20Sopenharmony_ci "qlevel_hwm_1", 3818c2ecf20Sopenharmony_ci "qlevel_hwm_2", 3828c2ecf20Sopenharmony_ci "qlevel_hwm_3", 3838c2ecf20Sopenharmony_ci "qlevel_hwm_4", 3848c2ecf20Sopenharmony_ci "qlevel_hwm_5", 3858c2ecf20Sopenharmony_ci "qlevel_hwm_6", 3868c2ecf20Sopenharmony_ci "qlevel_hwm_7", 3878c2ecf20Sopenharmony_ci "qlevel_0", 3888c2ecf20Sopenharmony_ci "qlevel_1", 3898c2ecf20Sopenharmony_ci "qlevel_2", 3908c2ecf20Sopenharmony_ci "qlevel_3", 3918c2ecf20Sopenharmony_ci "qlevel_4", 3928c2ecf20Sopenharmony_ci "qlevel_5", 3938c2ecf20Sopenharmony_ci "qlevel_6", 3948c2ecf20Sopenharmony_ci "qlevel_7", 3958c2ecf20Sopenharmony_ci /* Ether Stats */ 3968c2ecf20Sopenharmony_ci "n_drops_nolearn", 3978c2ecf20Sopenharmony_ci "n_drops_noroute", 3988c2ecf20Sopenharmony_ci "n_drops_ill_dtag", 3998c2ecf20Sopenharmony_ci "n_drops_dtag", 4008c2ecf20Sopenharmony_ci "n_drops_sotag", 4018c2ecf20Sopenharmony_ci "n_drops_sitag", 4028c2ecf20Sopenharmony_ci "n_drops_utag", 4038c2ecf20Sopenharmony_ci "n_tx_bytes_1024_2047", 4048c2ecf20Sopenharmony_ci "n_tx_bytes_512_1023", 4058c2ecf20Sopenharmony_ci "n_tx_bytes_256_511", 4068c2ecf20Sopenharmony_ci "n_tx_bytes_128_255", 4078c2ecf20Sopenharmony_ci "n_tx_bytes_65_127", 4088c2ecf20Sopenharmony_ci "n_tx_bytes_64", 4098c2ecf20Sopenharmony_ci "n_tx_mcast", 4108c2ecf20Sopenharmony_ci "n_tx_bcast", 4118c2ecf20Sopenharmony_ci "n_rx_bytes_1024_2047", 4128c2ecf20Sopenharmony_ci "n_rx_bytes_512_1023", 4138c2ecf20Sopenharmony_ci "n_rx_bytes_256_511", 4148c2ecf20Sopenharmony_ci "n_rx_bytes_128_255", 4158c2ecf20Sopenharmony_ci "n_rx_bytes_65_127", 4168c2ecf20Sopenharmony_ci "n_rx_bytes_64", 4178c2ecf20Sopenharmony_ci "n_rx_mcast", 4188c2ecf20Sopenharmony_ci "n_rx_bcast", 4198c2ecf20Sopenharmony_ci}; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_civoid sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci struct sja1105_private *priv = ds->priv; 4248c2ecf20Sopenharmony_ci struct sja1105_port_status *status; 4258c2ecf20Sopenharmony_ci int rc, i, k = 0; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci status = kzalloc(sizeof(*status), GFP_KERNEL); 4288c2ecf20Sopenharmony_ci if (!status) 4298c2ecf20Sopenharmony_ci goto out; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci rc = sja1105_port_status_get(priv, status, port); 4328c2ecf20Sopenharmony_ci if (rc < 0) { 4338c2ecf20Sopenharmony_ci dev_err(ds->dev, "Failed to read port %d counters: %d\n", 4348c2ecf20Sopenharmony_ci port, rc); 4358c2ecf20Sopenharmony_ci goto out; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci memset(data, 0, ARRAY_SIZE(sja1105_port_stats) * sizeof(u64)); 4388c2ecf20Sopenharmony_ci data[k++] = status->mac.n_runt; 4398c2ecf20Sopenharmony_ci data[k++] = status->mac.n_soferr; 4408c2ecf20Sopenharmony_ci data[k++] = status->mac.n_alignerr; 4418c2ecf20Sopenharmony_ci data[k++] = status->mac.n_miierr; 4428c2ecf20Sopenharmony_ci data[k++] = status->mac.typeerr; 4438c2ecf20Sopenharmony_ci data[k++] = status->mac.sizeerr; 4448c2ecf20Sopenharmony_ci data[k++] = status->mac.tctimeout; 4458c2ecf20Sopenharmony_ci data[k++] = status->mac.priorerr; 4468c2ecf20Sopenharmony_ci data[k++] = status->mac.nomaster; 4478c2ecf20Sopenharmony_ci data[k++] = status->mac.memov; 4488c2ecf20Sopenharmony_ci data[k++] = status->mac.memerr; 4498c2ecf20Sopenharmony_ci data[k++] = status->mac.invtyp; 4508c2ecf20Sopenharmony_ci data[k++] = status->mac.intcyov; 4518c2ecf20Sopenharmony_ci data[k++] = status->mac.domerr; 4528c2ecf20Sopenharmony_ci data[k++] = status->mac.pcfbagdrop; 4538c2ecf20Sopenharmony_ci data[k++] = status->mac.spcprior; 4548c2ecf20Sopenharmony_ci data[k++] = status->mac.ageprior; 4558c2ecf20Sopenharmony_ci data[k++] = status->mac.portdrop; 4568c2ecf20Sopenharmony_ci data[k++] = status->mac.lendrop; 4578c2ecf20Sopenharmony_ci data[k++] = status->mac.bagdrop; 4588c2ecf20Sopenharmony_ci data[k++] = status->mac.policeerr; 4598c2ecf20Sopenharmony_ci data[k++] = status->mac.drpnona664err; 4608c2ecf20Sopenharmony_ci data[k++] = status->mac.spcerr; 4618c2ecf20Sopenharmony_ci data[k++] = status->mac.agedrp; 4628c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_n664err; 4638c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_vlanerr; 4648c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_unreleased; 4658c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_sizeerr; 4668c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_crcerr; 4678c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_vlnotfound; 4688c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_ctpolerr; 4698c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_polerr; 4708c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_rxfrm; 4718c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_rxbyte; 4728c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_txfrm; 4738c2ecf20Sopenharmony_ci data[k++] = status->hl1.n_txbyte; 4748c2ecf20Sopenharmony_ci data[k++] = status->hl2.n_qfull; 4758c2ecf20Sopenharmony_ci data[k++] = status->hl2.n_part_drop; 4768c2ecf20Sopenharmony_ci data[k++] = status->hl2.n_egr_disabled; 4778c2ecf20Sopenharmony_ci data[k++] = status->hl2.n_not_reach; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (priv->info->device_id == SJA1105E_DEVICE_ID || 4808c2ecf20Sopenharmony_ci priv->info->device_id == SJA1105T_DEVICE_ID) 4818c2ecf20Sopenharmony_ci goto out; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci memset(data + k, 0, ARRAY_SIZE(sja1105pqrs_extra_port_stats) * 4848c2ecf20Sopenharmony_ci sizeof(u64)); 4858c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 4868c2ecf20Sopenharmony_ci data[k++] = status->hl2.qlevel_hwm[i]; 4878c2ecf20Sopenharmony_ci data[k++] = status->hl2.qlevel[i]; 4888c2ecf20Sopenharmony_ci } 4898c2ecf20Sopenharmony_ci data[k++] = status->ether.n_drops_nolearn; 4908c2ecf20Sopenharmony_ci data[k++] = status->ether.n_drops_noroute; 4918c2ecf20Sopenharmony_ci data[k++] = status->ether.n_drops_ill_dtag; 4928c2ecf20Sopenharmony_ci data[k++] = status->ether.n_drops_dtag; 4938c2ecf20Sopenharmony_ci data[k++] = status->ether.n_drops_sotag; 4948c2ecf20Sopenharmony_ci data[k++] = status->ether.n_drops_sitag; 4958c2ecf20Sopenharmony_ci data[k++] = status->ether.n_drops_utag; 4968c2ecf20Sopenharmony_ci data[k++] = status->ether.n_tx_bytes_1024_2047; 4978c2ecf20Sopenharmony_ci data[k++] = status->ether.n_tx_bytes_512_1023; 4988c2ecf20Sopenharmony_ci data[k++] = status->ether.n_tx_bytes_256_511; 4998c2ecf20Sopenharmony_ci data[k++] = status->ether.n_tx_bytes_128_255; 5008c2ecf20Sopenharmony_ci data[k++] = status->ether.n_tx_bytes_65_127; 5018c2ecf20Sopenharmony_ci data[k++] = status->ether.n_tx_bytes_64; 5028c2ecf20Sopenharmony_ci data[k++] = status->ether.n_tx_mcast; 5038c2ecf20Sopenharmony_ci data[k++] = status->ether.n_tx_bcast; 5048c2ecf20Sopenharmony_ci data[k++] = status->ether.n_rx_bytes_1024_2047; 5058c2ecf20Sopenharmony_ci data[k++] = status->ether.n_rx_bytes_512_1023; 5068c2ecf20Sopenharmony_ci data[k++] = status->ether.n_rx_bytes_256_511; 5078c2ecf20Sopenharmony_ci data[k++] = status->ether.n_rx_bytes_128_255; 5088c2ecf20Sopenharmony_ci data[k++] = status->ether.n_rx_bytes_65_127; 5098c2ecf20Sopenharmony_ci data[k++] = status->ether.n_rx_bytes_64; 5108c2ecf20Sopenharmony_ci data[k++] = status->ether.n_rx_mcast; 5118c2ecf20Sopenharmony_ci data[k++] = status->ether.n_rx_bcast; 5128c2ecf20Sopenharmony_ciout: 5138c2ecf20Sopenharmony_ci kfree(status); 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_civoid sja1105_get_strings(struct dsa_switch *ds, int port, 5178c2ecf20Sopenharmony_ci u32 stringset, u8 *data) 5188c2ecf20Sopenharmony_ci{ 5198c2ecf20Sopenharmony_ci struct sja1105_private *priv = ds->priv; 5208c2ecf20Sopenharmony_ci u8 *p = data; 5218c2ecf20Sopenharmony_ci int i; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci switch (stringset) { 5248c2ecf20Sopenharmony_ci case ETH_SS_STATS: 5258c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sja1105_port_stats); i++) { 5268c2ecf20Sopenharmony_ci strlcpy(p, sja1105_port_stats[i], ETH_GSTRING_LEN); 5278c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci if (priv->info->device_id == SJA1105E_DEVICE_ID || 5308c2ecf20Sopenharmony_ci priv->info->device_id == SJA1105T_DEVICE_ID) 5318c2ecf20Sopenharmony_ci return; 5328c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sja1105pqrs_extra_port_stats); i++) { 5338c2ecf20Sopenharmony_ci strlcpy(p, sja1105pqrs_extra_port_stats[i], 5348c2ecf20Sopenharmony_ci ETH_GSTRING_LEN); 5358c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 5368c2ecf20Sopenharmony_ci } 5378c2ecf20Sopenharmony_ci break; 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ciint sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci int count = ARRAY_SIZE(sja1105_port_stats); 5448c2ecf20Sopenharmony_ci struct sja1105_private *priv = ds->priv; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci if (sset != ETH_SS_STATS) 5478c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci if (priv->info->device_id == SJA1105PR_DEVICE_ID || 5508c2ecf20Sopenharmony_ci priv->info->device_id == SJA1105QS_DEVICE_ID) 5518c2ecf20Sopenharmony_ci count += ARRAY_SIZE(sja1105pqrs_extra_port_stats); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci return count; 5548c2ecf20Sopenharmony_ci} 555