162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2023 Cai Huoqing 462306a36Sopenharmony_ci * Synopsys DesignWare HDMA v0 debugfs 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Author: Cai Huoqing <cai.huoqing@linux.dev> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/debugfs.h> 1062306a36Sopenharmony_ci#include <linux/bitfield.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "dw-hdma-v0-debugfs.h" 1362306a36Sopenharmony_ci#include "dw-hdma-v0-regs.h" 1462306a36Sopenharmony_ci#include "dw-edma-core.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define REGS_ADDR(dw, name) \ 1762306a36Sopenharmony_ci ({ \ 1862306a36Sopenharmony_ci struct dw_hdma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \ 1962306a36Sopenharmony_ci \ 2062306a36Sopenharmony_ci (void __iomem *)&__regs->name; \ 2162306a36Sopenharmony_ci }) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define REGS_CH_ADDR(dw, name, _dir, _ch) \ 2462306a36Sopenharmony_ci ({ \ 2562306a36Sopenharmony_ci struct dw_hdma_v0_ch_regs __iomem *__ch_regs; \ 2662306a36Sopenharmony_ci \ 2762306a36Sopenharmony_ci if (_dir == EDMA_DIR_READ) \ 2862306a36Sopenharmony_ci __ch_regs = REGS_ADDR(dw, ch[_ch].rd); \ 2962306a36Sopenharmony_ci else \ 3062306a36Sopenharmony_ci __ch_regs = REGS_ADDR(dw, ch[_ch].wr); \ 3162306a36Sopenharmony_ci \ 3262306a36Sopenharmony_ci (void __iomem *)&__ch_regs->name; \ 3362306a36Sopenharmony_ci }) 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define CTX_REGISTER(dw, name, dir, ch) \ 3662306a36Sopenharmony_ci {#name, REGS_CH_ADDR(dw, name, dir, ch)} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define WRITE_STR "write" 3962306a36Sopenharmony_ci#define READ_STR "read" 4062306a36Sopenharmony_ci#define CHANNEL_STR "channel" 4162306a36Sopenharmony_ci#define REGISTERS_STR "registers" 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistruct dw_hdma_debugfs_entry { 4462306a36Sopenharmony_ci const char *name; 4562306a36Sopenharmony_ci void __iomem *reg; 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic int dw_hdma_debugfs_u32_get(void *data, u64 *val) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci struct dw_hdma_debugfs_entry *entry = data; 5162306a36Sopenharmony_ci void __iomem *reg = entry->reg; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci *val = readl(reg); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci return 0; 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_hdma_debugfs_u32_get, NULL, "0x%08llx\n"); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic void dw_hdma_debugfs_create_x32(struct dw_edma *dw, 6062306a36Sopenharmony_ci const struct dw_hdma_debugfs_entry ini[], 6162306a36Sopenharmony_ci int nr_entries, struct dentry *dent) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci struct dw_hdma_debugfs_entry *entries; 6462306a36Sopenharmony_ci int i; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci entries = devm_kcalloc(dw->chip->dev, nr_entries, sizeof(*entries), 6762306a36Sopenharmony_ci GFP_KERNEL); 6862306a36Sopenharmony_ci if (!entries) 6962306a36Sopenharmony_ci return; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci for (i = 0; i < nr_entries; i++) { 7262306a36Sopenharmony_ci entries[i] = ini[i]; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci debugfs_create_file_unsafe(entries[i].name, 0444, dent, 7562306a36Sopenharmony_ci &entries[i], &fops_x32); 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic void dw_hdma_debugfs_regs_ch(struct dw_edma *dw, enum dw_edma_dir dir, 8062306a36Sopenharmony_ci u16 ch, struct dentry *dent) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci const struct dw_hdma_debugfs_entry debugfs_regs[] = { 8362306a36Sopenharmony_ci CTX_REGISTER(dw, ch_en, dir, ch), 8462306a36Sopenharmony_ci CTX_REGISTER(dw, doorbell, dir, ch), 8562306a36Sopenharmony_ci CTX_REGISTER(dw, prefetch, dir, ch), 8662306a36Sopenharmony_ci CTX_REGISTER(dw, handshake, dir, ch), 8762306a36Sopenharmony_ci CTX_REGISTER(dw, llp.lsb, dir, ch), 8862306a36Sopenharmony_ci CTX_REGISTER(dw, llp.msb, dir, ch), 8962306a36Sopenharmony_ci CTX_REGISTER(dw, cycle_sync, dir, ch), 9062306a36Sopenharmony_ci CTX_REGISTER(dw, transfer_size, dir, ch), 9162306a36Sopenharmony_ci CTX_REGISTER(dw, sar.lsb, dir, ch), 9262306a36Sopenharmony_ci CTX_REGISTER(dw, sar.msb, dir, ch), 9362306a36Sopenharmony_ci CTX_REGISTER(dw, dar.lsb, dir, ch), 9462306a36Sopenharmony_ci CTX_REGISTER(dw, dar.msb, dir, ch), 9562306a36Sopenharmony_ci CTX_REGISTER(dw, watermark_en, dir, ch), 9662306a36Sopenharmony_ci CTX_REGISTER(dw, control1, dir, ch), 9762306a36Sopenharmony_ci CTX_REGISTER(dw, func_num, dir, ch), 9862306a36Sopenharmony_ci CTX_REGISTER(dw, qos, dir, ch), 9962306a36Sopenharmony_ci CTX_REGISTER(dw, ch_stat, dir, ch), 10062306a36Sopenharmony_ci CTX_REGISTER(dw, int_stat, dir, ch), 10162306a36Sopenharmony_ci CTX_REGISTER(dw, int_setup, dir, ch), 10262306a36Sopenharmony_ci CTX_REGISTER(dw, int_clear, dir, ch), 10362306a36Sopenharmony_ci CTX_REGISTER(dw, msi_stop.lsb, dir, ch), 10462306a36Sopenharmony_ci CTX_REGISTER(dw, msi_stop.msb, dir, ch), 10562306a36Sopenharmony_ci CTX_REGISTER(dw, msi_watermark.lsb, dir, ch), 10662306a36Sopenharmony_ci CTX_REGISTER(dw, msi_watermark.msb, dir, ch), 10762306a36Sopenharmony_ci CTX_REGISTER(dw, msi_abort.lsb, dir, ch), 10862306a36Sopenharmony_ci CTX_REGISTER(dw, msi_abort.msb, dir, ch), 10962306a36Sopenharmony_ci CTX_REGISTER(dw, msi_msgdata, dir, ch), 11062306a36Sopenharmony_ci }; 11162306a36Sopenharmony_ci int nr_entries = ARRAY_SIZE(debugfs_regs); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci dw_hdma_debugfs_create_x32(dw, debugfs_regs, nr_entries, dent); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic void dw_hdma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci struct dentry *regs_dent, *ch_dent; 11962306a36Sopenharmony_ci char name[32]; 12062306a36Sopenharmony_ci int i; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci regs_dent = debugfs_create_dir(WRITE_STR, dent); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci for (i = 0; i < dw->wr_ch_cnt; i++) { 12562306a36Sopenharmony_ci snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci ch_dent = debugfs_create_dir(name, regs_dent); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci dw_hdma_debugfs_regs_ch(dw, EDMA_DIR_WRITE, i, ch_dent); 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic void dw_hdma_debugfs_regs_rd(struct dw_edma *dw, struct dentry *dent) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct dentry *regs_dent, *ch_dent; 13662306a36Sopenharmony_ci char name[32]; 13762306a36Sopenharmony_ci int i; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci regs_dent = debugfs_create_dir(READ_STR, dent); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci for (i = 0; i < dw->rd_ch_cnt; i++) { 14262306a36Sopenharmony_ci snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci ch_dent = debugfs_create_dir(name, regs_dent); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci dw_hdma_debugfs_regs_ch(dw, EDMA_DIR_READ, i, ch_dent); 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic void dw_hdma_debugfs_regs(struct dw_edma *dw) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci struct dentry *regs_dent; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci regs_dent = debugfs_create_dir(REGISTERS_STR, dw->dma.dbg_dev_root); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci dw_hdma_debugfs_regs_wr(dw, regs_dent); 15762306a36Sopenharmony_ci dw_hdma_debugfs_regs_rd(dw, regs_dent); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_civoid dw_hdma_v0_debugfs_on(struct dw_edma *dw) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci if (!debugfs_initialized()) 16362306a36Sopenharmony_ci return; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci debugfs_create_u32("mf", 0444, dw->dma.dbg_dev_root, &dw->chip->mf); 16662306a36Sopenharmony_ci debugfs_create_u16("wr_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->wr_ch_cnt); 16762306a36Sopenharmony_ci debugfs_create_u16("rd_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->rd_ch_cnt); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci dw_hdma_debugfs_regs(dw); 17062306a36Sopenharmony_ci} 171