162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Texas Instruments ICSSG Ethernet driver 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2018-2021 Texas Instruments Incorporated - https://www.ti.com/ 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "icssg_prueth.h" 962306a36Sopenharmony_ci#include "icssg_stats.h" 1062306a36Sopenharmony_ci#include <linux/regmap.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define ICSSG_TX_PACKET_OFFSET 0xA0 1362306a36Sopenharmony_ci#define ICSSG_TX_BYTE_OFFSET 0xEC 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic u32 stats_base[] = { 0x54c, /* Slice 0 stats start */ 1662306a36Sopenharmony_ci 0xb18, /* Slice 1 stats start */ 1762306a36Sopenharmony_ci}; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_civoid emac_update_hardware_stats(struct prueth_emac *emac) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci struct prueth *prueth = emac->prueth; 2262306a36Sopenharmony_ci int slice = prueth_emac_slice(emac); 2362306a36Sopenharmony_ci u32 base = stats_base[slice]; 2462306a36Sopenharmony_ci u32 tx_pkt_cnt = 0; 2562306a36Sopenharmony_ci u32 val; 2662306a36Sopenharmony_ci int i; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { 2962306a36Sopenharmony_ci regmap_read(prueth->miig_rt, 3062306a36Sopenharmony_ci base + icssg_all_stats[i].offset, 3162306a36Sopenharmony_ci &val); 3262306a36Sopenharmony_ci regmap_write(prueth->miig_rt, 3362306a36Sopenharmony_ci base + icssg_all_stats[i].offset, 3462306a36Sopenharmony_ci val); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci if (icssg_all_stats[i].offset == ICSSG_TX_PACKET_OFFSET) 3762306a36Sopenharmony_ci tx_pkt_cnt = val; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci emac->stats[i] += val; 4062306a36Sopenharmony_ci if (icssg_all_stats[i].offset == ICSSG_TX_BYTE_OFFSET) 4162306a36Sopenharmony_ci emac->stats[i] -= tx_pkt_cnt * 8; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_civoid emac_stats_work_handler(struct work_struct *work) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci struct prueth_emac *emac = container_of(work, struct prueth_emac, 4862306a36Sopenharmony_ci stats_work.work); 4962306a36Sopenharmony_ci emac_update_hardware_stats(emac); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci queue_delayed_work(system_long_wq, &emac->stats_work, 5262306a36Sopenharmony_ci msecs_to_jiffies((STATS_TIME_LIMIT_1G_MS * 1000) / emac->speed)); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciint emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci int i; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { 6062306a36Sopenharmony_ci if (!strcmp(icssg_all_stats[i].name, stat_name)) 6162306a36Sopenharmony_ci return emac->stats[icssg_all_stats[i].offset / sizeof(u32)]; 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci netdev_err(emac->ndev, "Invalid stats %s\n", stat_name); 6562306a36Sopenharmony_ci return -EINVAL; 6662306a36Sopenharmony_ci} 67