162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/seq_file.h>
562306a36Sopenharmony_ci#include <linux/soc/mediatek/mtk_wed.h>
662306a36Sopenharmony_ci#include "mtk_wed.h"
762306a36Sopenharmony_ci#include "mtk_wed_regs.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistruct reg_dump {
1062306a36Sopenharmony_ci	const char *name;
1162306a36Sopenharmony_ci	u16 offset;
1262306a36Sopenharmony_ci	u8 type;
1362306a36Sopenharmony_ci	u8 base;
1462306a36Sopenharmony_ci};
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cienum {
1762306a36Sopenharmony_ci	DUMP_TYPE_STRING,
1862306a36Sopenharmony_ci	DUMP_TYPE_WED,
1962306a36Sopenharmony_ci	DUMP_TYPE_WDMA,
2062306a36Sopenharmony_ci	DUMP_TYPE_WPDMA_TX,
2162306a36Sopenharmony_ci	DUMP_TYPE_WPDMA_TXFREE,
2262306a36Sopenharmony_ci	DUMP_TYPE_WPDMA_RX,
2362306a36Sopenharmony_ci	DUMP_TYPE_WED_RRO,
2462306a36Sopenharmony_ci};
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING }
2762306a36Sopenharmony_ci#define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ }
2862306a36Sopenharmony_ci#define DUMP_RING(_prefix, _base, ...)				\
2962306a36Sopenharmony_ci	{ _prefix " BASE", _base, __VA_ARGS__ },		\
3062306a36Sopenharmony_ci	{ _prefix " CNT",  _base + 0x4, __VA_ARGS__ },	\
3162306a36Sopenharmony_ci	{ _prefix " CIDX", _base + 0x8, __VA_ARGS__ },	\
3262306a36Sopenharmony_ci	{ _prefix " DIDX", _base + 0xc, __VA_ARGS__ }
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED)
3562306a36Sopenharmony_ci#define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA)
3862306a36Sopenharmony_ci#define DUMP_WDMA_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WDMA)
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define DUMP_WPDMA_TX_RING(_n) DUMP_RING("WPDMA_TX" #_n, 0, DUMP_TYPE_WPDMA_TX, _n)
4162306a36Sopenharmony_ci#define DUMP_WPDMA_TXFREE_RING DUMP_RING("WPDMA_RX1", 0, DUMP_TYPE_WPDMA_TXFREE)
4262306a36Sopenharmony_ci#define DUMP_WPDMA_RX_RING(_n)	DUMP_RING("WPDMA_RX" #_n, 0, DUMP_TYPE_WPDMA_RX, _n)
4362306a36Sopenharmony_ci#define DUMP_WED_RRO_RING(_base)DUMP_RING("WED_RRO_MIOD", MTK_##_base, DUMP_TYPE_WED_RRO)
4462306a36Sopenharmony_ci#define DUMP_WED_RRO_FDBK(_base)DUMP_RING("WED_RRO_FDBK", MTK_##_base, DUMP_TYPE_WED_RRO)
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic void
4762306a36Sopenharmony_ciprint_reg_val(struct seq_file *s, const char *name, u32 val)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	seq_printf(s, "%-32s %08x\n", name, val);
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic void
5362306a36Sopenharmony_cidump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
5462306a36Sopenharmony_ci	      const struct reg_dump *regs, int n_regs)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	const struct reg_dump *cur;
5762306a36Sopenharmony_ci	u32 val;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	for (cur = regs; cur < &regs[n_regs]; cur++) {
6062306a36Sopenharmony_ci		switch (cur->type) {
6162306a36Sopenharmony_ci		case DUMP_TYPE_STRING:
6262306a36Sopenharmony_ci			seq_printf(s, "%s======== %s:\n",
6362306a36Sopenharmony_ci				   cur > regs ? "\n" : "",
6462306a36Sopenharmony_ci				   cur->name);
6562306a36Sopenharmony_ci			continue;
6662306a36Sopenharmony_ci		case DUMP_TYPE_WED_RRO:
6762306a36Sopenharmony_ci		case DUMP_TYPE_WED:
6862306a36Sopenharmony_ci			val = wed_r32(dev, cur->offset);
6962306a36Sopenharmony_ci			break;
7062306a36Sopenharmony_ci		case DUMP_TYPE_WDMA:
7162306a36Sopenharmony_ci			val = wdma_r32(dev, cur->offset);
7262306a36Sopenharmony_ci			break;
7362306a36Sopenharmony_ci		case DUMP_TYPE_WPDMA_TX:
7462306a36Sopenharmony_ci			val = wpdma_tx_r32(dev, cur->base, cur->offset);
7562306a36Sopenharmony_ci			break;
7662306a36Sopenharmony_ci		case DUMP_TYPE_WPDMA_TXFREE:
7762306a36Sopenharmony_ci			val = wpdma_txfree_r32(dev, cur->offset);
7862306a36Sopenharmony_ci			break;
7962306a36Sopenharmony_ci		case DUMP_TYPE_WPDMA_RX:
8062306a36Sopenharmony_ci			val = wpdma_rx_r32(dev, cur->base, cur->offset);
8162306a36Sopenharmony_ci			break;
8262306a36Sopenharmony_ci		}
8362306a36Sopenharmony_ci		print_reg_val(s, cur->name, val);
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic int
8862306a36Sopenharmony_ciwed_txinfo_show(struct seq_file *s, void *data)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	static const struct reg_dump regs[] = {
9162306a36Sopenharmony_ci		DUMP_STR("WED TX"),
9262306a36Sopenharmony_ci		DUMP_WED(WED_TX_MIB(0)),
9362306a36Sopenharmony_ci		DUMP_WED_RING(WED_RING_TX(0)),
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci		DUMP_WED(WED_TX_MIB(1)),
9662306a36Sopenharmony_ci		DUMP_WED_RING(WED_RING_TX(1)),
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci		DUMP_STR("WPDMA TX"),
9962306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_TX_MIB(0)),
10062306a36Sopenharmony_ci		DUMP_WED_RING(WED_WPDMA_RING_TX(0)),
10162306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_TX_COHERENT_MIB(0)),
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_TX_MIB(1)),
10462306a36Sopenharmony_ci		DUMP_WED_RING(WED_WPDMA_RING_TX(1)),
10562306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_TX_COHERENT_MIB(1)),
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci		DUMP_STR("WPDMA TX"),
10862306a36Sopenharmony_ci		DUMP_WPDMA_TX_RING(0),
10962306a36Sopenharmony_ci		DUMP_WPDMA_TX_RING(1),
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		DUMP_STR("WED WDMA RX"),
11262306a36Sopenharmony_ci		DUMP_WED(WED_WDMA_RX_MIB(0)),
11362306a36Sopenharmony_ci		DUMP_WED_RING(WED_WDMA_RING_RX(0)),
11462306a36Sopenharmony_ci		DUMP_WED(WED_WDMA_RX_THRES(0)),
11562306a36Sopenharmony_ci		DUMP_WED(WED_WDMA_RX_RECYCLE_MIB(0)),
11662306a36Sopenharmony_ci		DUMP_WED(WED_WDMA_RX_PROCESSED_MIB(0)),
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci		DUMP_WED(WED_WDMA_RX_MIB(1)),
11962306a36Sopenharmony_ci		DUMP_WED_RING(WED_WDMA_RING_RX(1)),
12062306a36Sopenharmony_ci		DUMP_WED(WED_WDMA_RX_THRES(1)),
12162306a36Sopenharmony_ci		DUMP_WED(WED_WDMA_RX_RECYCLE_MIB(1)),
12262306a36Sopenharmony_ci		DUMP_WED(WED_WDMA_RX_PROCESSED_MIB(1)),
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci		DUMP_STR("WDMA RX"),
12562306a36Sopenharmony_ci		DUMP_WDMA(WDMA_GLO_CFG),
12662306a36Sopenharmony_ci		DUMP_WDMA_RING(WDMA_RING_RX(0)),
12762306a36Sopenharmony_ci		DUMP_WDMA_RING(WDMA_RING_RX(1)),
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		DUMP_STR("WED TX FREE"),
13062306a36Sopenharmony_ci		DUMP_WED(WED_RX_MIB(0)),
13162306a36Sopenharmony_ci		DUMP_WED_RING(WED_RING_RX(0)),
13262306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)),
13362306a36Sopenharmony_ci		DUMP_WED(WED_RX_MIB(1)),
13462306a36Sopenharmony_ci		DUMP_WED_RING(WED_RING_RX(1)),
13562306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)),
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci		DUMP_STR("WED WPDMA TX FREE"),
13862306a36Sopenharmony_ci		DUMP_WED_RING(WED_WPDMA_RING_RX(0)),
13962306a36Sopenharmony_ci		DUMP_WED_RING(WED_WPDMA_RING_RX(1)),
14062306a36Sopenharmony_ci	};
14162306a36Sopenharmony_ci	struct mtk_wed_hw *hw = s->private;
14262306a36Sopenharmony_ci	struct mtk_wed_device *dev = hw->wed_dev;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	if (dev)
14562306a36Sopenharmony_ci		dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	return 0;
14862306a36Sopenharmony_ci}
14962306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(wed_txinfo);
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic int
15262306a36Sopenharmony_ciwed_rxinfo_show(struct seq_file *s, void *data)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	static const struct reg_dump regs[] = {
15562306a36Sopenharmony_ci		DUMP_STR("WPDMA RX"),
15662306a36Sopenharmony_ci		DUMP_WPDMA_RX_RING(0),
15762306a36Sopenharmony_ci		DUMP_WPDMA_RX_RING(1),
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci		DUMP_STR("WPDMA RX"),
16062306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_RX_D_MIB(0)),
16162306a36Sopenharmony_ci		DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(0)),
16262306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(0)),
16362306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_RX_D_MIB(1)),
16462306a36Sopenharmony_ci		DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(1)),
16562306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(1)),
16662306a36Sopenharmony_ci		DUMP_WED(WED_WPDMA_RX_D_COHERENT_MIB),
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci		DUMP_STR("WED RX"),
16962306a36Sopenharmony_ci		DUMP_WED_RING(WED_RING_RX_DATA(0)),
17062306a36Sopenharmony_ci		DUMP_WED_RING(WED_RING_RX_DATA(1)),
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci		DUMP_STR("WED RRO"),
17362306a36Sopenharmony_ci		DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0),
17462306a36Sopenharmony_ci		DUMP_WED(WED_RROQM_MID_MIB),
17562306a36Sopenharmony_ci		DUMP_WED(WED_RROQM_MOD_MIB),
17662306a36Sopenharmony_ci		DUMP_WED(WED_RROQM_MOD_COHERENT_MIB),
17762306a36Sopenharmony_ci		DUMP_WED_RRO_FDBK(WED_RROQM_FDBK_CTRL0),
17862306a36Sopenharmony_ci		DUMP_WED(WED_RROQM_FDBK_IND_MIB),
17962306a36Sopenharmony_ci		DUMP_WED(WED_RROQM_FDBK_ENQ_MIB),
18062306a36Sopenharmony_ci		DUMP_WED(WED_RROQM_FDBK_ANC_MIB),
18162306a36Sopenharmony_ci		DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB),
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci		DUMP_STR("WED Route QM"),
18462306a36Sopenharmony_ci		DUMP_WED(WED_RTQM_R2H_MIB(0)),
18562306a36Sopenharmony_ci		DUMP_WED(WED_RTQM_R2Q_MIB(0)),
18662306a36Sopenharmony_ci		DUMP_WED(WED_RTQM_Q2H_MIB(0)),
18762306a36Sopenharmony_ci		DUMP_WED(WED_RTQM_R2H_MIB(1)),
18862306a36Sopenharmony_ci		DUMP_WED(WED_RTQM_R2Q_MIB(1)),
18962306a36Sopenharmony_ci		DUMP_WED(WED_RTQM_Q2H_MIB(1)),
19062306a36Sopenharmony_ci		DUMP_WED(WED_RTQM_Q2N_MIB),
19162306a36Sopenharmony_ci		DUMP_WED(WED_RTQM_Q2B_MIB),
19262306a36Sopenharmony_ci		DUMP_WED(WED_RTQM_PFDBK_MIB),
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci		DUMP_STR("WED WDMA TX"),
19562306a36Sopenharmony_ci		DUMP_WED(WED_WDMA_TX_MIB),
19662306a36Sopenharmony_ci		DUMP_WED_RING(WED_WDMA_RING_TX),
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci		DUMP_STR("WDMA TX"),
19962306a36Sopenharmony_ci		DUMP_WDMA(WDMA_GLO_CFG),
20062306a36Sopenharmony_ci		DUMP_WDMA_RING(WDMA_RING_TX(0)),
20162306a36Sopenharmony_ci		DUMP_WDMA_RING(WDMA_RING_TX(1)),
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci		DUMP_STR("WED RX BM"),
20462306a36Sopenharmony_ci		DUMP_WED(WED_RX_BM_BASE),
20562306a36Sopenharmony_ci		DUMP_WED(WED_RX_BM_RX_DMAD),
20662306a36Sopenharmony_ci		DUMP_WED(WED_RX_BM_PTR),
20762306a36Sopenharmony_ci		DUMP_WED(WED_RX_BM_TKID_MIB),
20862306a36Sopenharmony_ci		DUMP_WED(WED_RX_BM_BLEN),
20962306a36Sopenharmony_ci		DUMP_WED(WED_RX_BM_STS),
21062306a36Sopenharmony_ci		DUMP_WED(WED_RX_BM_INTF2),
21162306a36Sopenharmony_ci		DUMP_WED(WED_RX_BM_INTF),
21262306a36Sopenharmony_ci		DUMP_WED(WED_RX_BM_ERR_STS),
21362306a36Sopenharmony_ci	};
21462306a36Sopenharmony_ci	struct mtk_wed_hw *hw = s->private;
21562306a36Sopenharmony_ci	struct mtk_wed_device *dev = hw->wed_dev;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	if (dev)
21862306a36Sopenharmony_ci		dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	return 0;
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(wed_rxinfo);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic int
22562306a36Sopenharmony_cimtk_wed_reg_set(void *data, u64 val)
22662306a36Sopenharmony_ci{
22762306a36Sopenharmony_ci	struct mtk_wed_hw *hw = data;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	regmap_write(hw->regs, hw->debugfs_reg, val);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	return 0;
23262306a36Sopenharmony_ci}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic int
23562306a36Sopenharmony_cimtk_wed_reg_get(void *data, u64 *val)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	struct mtk_wed_hw *hw = data;
23862306a36Sopenharmony_ci	unsigned int regval;
23962306a36Sopenharmony_ci	int ret;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	ret = regmap_read(hw->regs, hw->debugfs_reg, &regval);
24262306a36Sopenharmony_ci	if (ret)
24362306a36Sopenharmony_ci		return ret;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	*val = regval;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	return 0;
24862306a36Sopenharmony_ci}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mtk_wed_reg_get, mtk_wed_reg_set,
25162306a36Sopenharmony_ci             "0x%08llx\n");
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_civoid mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	struct dentry *dir;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	snprintf(hw->dirname, sizeof(hw->dirname), "wed%d", hw->index);
25862306a36Sopenharmony_ci	dir = debugfs_create_dir(hw->dirname, NULL);
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	hw->debugfs_dir = dir;
26162306a36Sopenharmony_ci	debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg);
26262306a36Sopenharmony_ci	debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval);
26362306a36Sopenharmony_ci	debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops);
26462306a36Sopenharmony_ci	if (hw->version != 1)
26562306a36Sopenharmony_ci		debugfs_create_file_unsafe("rxinfo", 0400, dir, hw,
26662306a36Sopenharmony_ci					   &wed_rxinfo_fops);
26762306a36Sopenharmony_ci}
268