0001
0002
0003
0004 #include <linux/seq_file.h>
0005 #include "mtk_wed.h"
0006 #include "mtk_wed_regs.h"
0007
0008 struct reg_dump {
0009 const char *name;
0010 u16 offset;
0011 u8 type;
0012 u8 base;
0013 };
0014
0015 enum {
0016 DUMP_TYPE_STRING,
0017 DUMP_TYPE_WED,
0018 DUMP_TYPE_WDMA,
0019 DUMP_TYPE_WPDMA_TX,
0020 DUMP_TYPE_WPDMA_TXFREE,
0021 };
0022
0023 #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING }
0024 #define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ }
0025 #define DUMP_RING(_prefix, _base, ...) \
0026 { _prefix " BASE", _base, __VA_ARGS__ }, \
0027 { _prefix " CNT", _base + 0x4, __VA_ARGS__ }, \
0028 { _prefix " CIDX", _base + 0x8, __VA_ARGS__ }, \
0029 { _prefix " DIDX", _base + 0xc, __VA_ARGS__ }
0030
0031 #define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED)
0032 #define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED)
0033
0034 #define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA)
0035 #define DUMP_WDMA_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WDMA)
0036
0037 #define DUMP_WPDMA_TX_RING(_n) DUMP_RING("WPDMA_TX" #_n, 0, DUMP_TYPE_WPDMA_TX, _n)
0038 #define DUMP_WPDMA_TXFREE_RING DUMP_RING("WPDMA_RX1", 0, DUMP_TYPE_WPDMA_TXFREE)
0039
0040 static void
0041 print_reg_val(struct seq_file *s, const char *name, u32 val)
0042 {
0043 seq_printf(s, "%-32s %08x\n", name, val);
0044 }
0045
0046 static void
0047 dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
0048 const struct reg_dump *regs, int n_regs)
0049 {
0050 const struct reg_dump *cur;
0051 u32 val;
0052
0053 for (cur = regs; cur < ®s[n_regs]; cur++) {
0054 switch (cur->type) {
0055 case DUMP_TYPE_STRING:
0056 seq_printf(s, "%s======== %s:\n",
0057 cur > regs ? "\n" : "",
0058 cur->name);
0059 continue;
0060 case DUMP_TYPE_WED:
0061 val = wed_r32(dev, cur->offset);
0062 break;
0063 case DUMP_TYPE_WDMA:
0064 val = wdma_r32(dev, cur->offset);
0065 break;
0066 case DUMP_TYPE_WPDMA_TX:
0067 val = wpdma_tx_r32(dev, cur->base, cur->offset);
0068 break;
0069 case DUMP_TYPE_WPDMA_TXFREE:
0070 val = wpdma_txfree_r32(dev, cur->offset);
0071 break;
0072 }
0073 print_reg_val(s, cur->name, val);
0074 }
0075 }
0076
0077
0078 static int
0079 wed_txinfo_show(struct seq_file *s, void *data)
0080 {
0081 static const struct reg_dump regs[] = {
0082 DUMP_STR("WED TX"),
0083 DUMP_WED(WED_TX_MIB(0)),
0084 DUMP_WED_RING(WED_RING_TX(0)),
0085
0086 DUMP_WED(WED_TX_MIB(1)),
0087 DUMP_WED_RING(WED_RING_TX(1)),
0088
0089 DUMP_STR("WPDMA TX"),
0090 DUMP_WED(WED_WPDMA_TX_MIB(0)),
0091 DUMP_WED_RING(WED_WPDMA_RING_TX(0)),
0092 DUMP_WED(WED_WPDMA_TX_COHERENT_MIB(0)),
0093
0094 DUMP_WED(WED_WPDMA_TX_MIB(1)),
0095 DUMP_WED_RING(WED_WPDMA_RING_TX(1)),
0096 DUMP_WED(WED_WPDMA_TX_COHERENT_MIB(1)),
0097
0098 DUMP_STR("WPDMA TX"),
0099 DUMP_WPDMA_TX_RING(0),
0100 DUMP_WPDMA_TX_RING(1),
0101
0102 DUMP_STR("WED WDMA RX"),
0103 DUMP_WED(WED_WDMA_RX_MIB(0)),
0104 DUMP_WED_RING(WED_WDMA_RING_RX(0)),
0105 DUMP_WED(WED_WDMA_RX_THRES(0)),
0106 DUMP_WED(WED_WDMA_RX_RECYCLE_MIB(0)),
0107 DUMP_WED(WED_WDMA_RX_PROCESSED_MIB(0)),
0108
0109 DUMP_WED(WED_WDMA_RX_MIB(1)),
0110 DUMP_WED_RING(WED_WDMA_RING_RX(1)),
0111 DUMP_WED(WED_WDMA_RX_THRES(1)),
0112 DUMP_WED(WED_WDMA_RX_RECYCLE_MIB(1)),
0113 DUMP_WED(WED_WDMA_RX_PROCESSED_MIB(1)),
0114
0115 DUMP_STR("WDMA RX"),
0116 DUMP_WDMA(WDMA_GLO_CFG),
0117 DUMP_WDMA_RING(WDMA_RING_RX(0)),
0118 DUMP_WDMA_RING(WDMA_RING_RX(1)),
0119 };
0120 struct mtk_wed_hw *hw = s->private;
0121 struct mtk_wed_device *dev = hw->wed_dev;
0122
0123 if (!dev)
0124 return 0;
0125
0126 dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
0127
0128 return 0;
0129 }
0130 DEFINE_SHOW_ATTRIBUTE(wed_txinfo);
0131
0132
0133 static int
0134 mtk_wed_reg_set(void *data, u64 val)
0135 {
0136 struct mtk_wed_hw *hw = data;
0137
0138 regmap_write(hw->regs, hw->debugfs_reg, val);
0139
0140 return 0;
0141 }
0142
0143 static int
0144 mtk_wed_reg_get(void *data, u64 *val)
0145 {
0146 struct mtk_wed_hw *hw = data;
0147 unsigned int regval;
0148 int ret;
0149
0150 ret = regmap_read(hw->regs, hw->debugfs_reg, ®val);
0151 if (ret)
0152 return ret;
0153
0154 *val = regval;
0155
0156 return 0;
0157 }
0158
0159 DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mtk_wed_reg_get, mtk_wed_reg_set,
0160 "0x%08llx\n");
0161
0162 void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
0163 {
0164 struct dentry *dir;
0165
0166 snprintf(hw->dirname, sizeof(hw->dirname), "wed%d", hw->index);
0167 dir = debugfs_create_dir(hw->dirname, NULL);
0168 if (!dir)
0169 return;
0170
0171 hw->debugfs_dir = dir;
0172 debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg);
0173 debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval);
0174 debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops);
0175 }