1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Texas Instruments ICSSG Ethernet driver |
3 | * |
4 | * Copyright (C) 2018-2021 Texas Instruments Incorporated - https://www.ti.com/ |
5 | * |
6 | */ |
7 | |
8 | #include "icssg_prueth.h" |
9 | #include "icssg_stats.h" |
10 | #include <linux/regmap.h> |
11 | |
12 | #define ICSSG_TX_PACKET_OFFSET 0xA0 |
13 | #define ICSSG_TX_BYTE_OFFSET 0xEC |
14 | |
15 | static u32 stats_base[] = { 0x54c, /* Slice 0 stats start */ |
16 | 0xb18, /* Slice 1 stats start */ |
17 | }; |
18 | |
19 | void emac_update_hardware_stats(struct prueth_emac *emac) |
20 | { |
21 | struct prueth *prueth = emac->prueth; |
22 | int slice = prueth_emac_slice(emac); |
23 | u32 base = stats_base[slice]; |
24 | u32 tx_pkt_cnt = 0; |
25 | u32 val; |
26 | int i; |
27 | |
28 | for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { |
29 | regmap_read(map: prueth->miig_rt, |
30 | reg: base + icssg_all_stats[i].offset, |
31 | val: &val); |
32 | regmap_write(map: prueth->miig_rt, |
33 | reg: base + icssg_all_stats[i].offset, |
34 | val); |
35 | |
36 | if (icssg_all_stats[i].offset == ICSSG_TX_PACKET_OFFSET) |
37 | tx_pkt_cnt = val; |
38 | |
39 | emac->stats[i] += val; |
40 | if (icssg_all_stats[i].offset == ICSSG_TX_BYTE_OFFSET) |
41 | emac->stats[i] -= tx_pkt_cnt * 8; |
42 | } |
43 | } |
44 | |
45 | void emac_stats_work_handler(struct work_struct *work) |
46 | { |
47 | struct prueth_emac *emac = container_of(work, struct prueth_emac, |
48 | stats_work.work); |
49 | emac_update_hardware_stats(emac); |
50 | |
51 | queue_delayed_work(wq: system_long_wq, dwork: &emac->stats_work, |
52 | delay: msecs_to_jiffies(m: (STATS_TIME_LIMIT_1G_MS * 1000) / emac->speed)); |
53 | } |
54 | |
55 | int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name) |
56 | { |
57 | int i; |
58 | |
59 | for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { |
60 | if (!strcmp(icssg_all_stats[i].name, stat_name)) |
61 | return emac->stats[icssg_all_stats[i].offset / sizeof(u32)]; |
62 | } |
63 | |
64 | netdev_err(dev: emac->ndev, format: "Invalid stats %s\n" , stat_name); |
65 | return -EINVAL; |
66 | } |
67 | |