1305aebefSGustavo Pimentel // SPDX-License-Identifier: GPL-2.0 2305aebefSGustavo Pimentel /* 3305aebefSGustavo Pimentel * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates. 4305aebefSGustavo Pimentel * Synopsys DesignWare eDMA v0 core 5305aebefSGustavo Pimentel * 6305aebefSGustavo Pimentel * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com> 7305aebefSGustavo Pimentel */ 8305aebefSGustavo Pimentel 9305aebefSGustavo Pimentel #include <linux/debugfs.h> 10305aebefSGustavo Pimentel #include <linux/bitfield.h> 11305aebefSGustavo Pimentel 12305aebefSGustavo Pimentel #include "dw-edma-v0-debugfs.h" 13305aebefSGustavo Pimentel #include "dw-edma-v0-regs.h" 14305aebefSGustavo Pimentel #include "dw-edma-core.h" 15305aebefSGustavo Pimentel 16305aebefSGustavo Pimentel #define REGS_ADDR(name) \ 17756c3ef9SArnd Bergmann ((void __force *)®s->name) 18305aebefSGustavo Pimentel #define REGISTER(name) \ 19305aebefSGustavo Pimentel { #name, REGS_ADDR(name) } 20305aebefSGustavo Pimentel 21305aebefSGustavo Pimentel #define WR_REGISTER(name) \ 22305aebefSGustavo Pimentel { #name, REGS_ADDR(wr_##name) } 23305aebefSGustavo Pimentel #define RD_REGISTER(name) \ 24305aebefSGustavo Pimentel { #name, REGS_ADDR(rd_##name) } 25305aebefSGustavo Pimentel 26305aebefSGustavo Pimentel #define WR_REGISTER_LEGACY(name) \ 27305aebefSGustavo Pimentel { #name, REGS_ADDR(type.legacy.wr_##name) } 28305aebefSGustavo Pimentel #define RD_REGISTER_LEGACY(name) \ 29305aebefSGustavo Pimentel { #name, REGS_ADDR(type.legacy.rd_##name) } 30305aebefSGustavo Pimentel 31305aebefSGustavo Pimentel #define WR_REGISTER_UNROLL(name) \ 32305aebefSGustavo Pimentel { #name, REGS_ADDR(type.unroll.wr_##name) } 33305aebefSGustavo Pimentel #define RD_REGISTER_UNROLL(name) \ 34305aebefSGustavo Pimentel { #name, REGS_ADDR(type.unroll.rd_##name) } 35305aebefSGustavo Pimentel 36305aebefSGustavo Pimentel #define WRITE_STR "write" 37305aebefSGustavo Pimentel #define READ_STR "read" 38305aebefSGustavo Pimentel #define CHANNEL_STR "channel" 39305aebefSGustavo Pimentel #define REGISTERS_STR "registers" 40305aebefSGustavo Pimentel 41305aebefSGustavo Pimentel static struct dw_edma *dw; 42756c3ef9SArnd Bergmann static struct dw_edma_v0_regs __iomem *regs; 43305aebefSGustavo Pimentel 44305aebefSGustavo Pimentel static struct { 45756c3ef9SArnd Bergmann void __iomem *start; 46756c3ef9SArnd Bergmann void __iomem *end; 47305aebefSGustavo Pimentel } lim[2][EDMA_V0_MAX_NR_CH]; 48305aebefSGustavo Pimentel 49305aebefSGustavo Pimentel struct debugfs_entries { 50f0414087SArnd Bergmann const char *name; 51305aebefSGustavo Pimentel dma_addr_t *reg; 52305aebefSGustavo Pimentel }; 53305aebefSGustavo Pimentel 54305aebefSGustavo Pimentel static int dw_edma_debugfs_u32_get(void *data, u64 *val) 55305aebefSGustavo Pimentel { 56756c3ef9SArnd Bergmann void __iomem *reg = (void __force __iomem *)data; 57*20318457SFrank Li if (dw->chip->mf == EDMA_MF_EDMA_LEGACY && 58756c3ef9SArnd Bergmann reg >= (void __iomem *)®s->type.legacy.ch) { 59756c3ef9SArnd Bergmann void __iomem *ptr = ®s->type.legacy.ch; 60305aebefSGustavo Pimentel u32 viewport_sel = 0; 61305aebefSGustavo Pimentel unsigned long flags; 62305aebefSGustavo Pimentel u16 ch; 63305aebefSGustavo Pimentel 64305aebefSGustavo Pimentel for (ch = 0; ch < dw->wr_ch_cnt; ch++) 65756c3ef9SArnd Bergmann if (lim[0][ch].start >= reg && reg < lim[0][ch].end) { 66756c3ef9SArnd Bergmann ptr += (reg - lim[0][ch].start); 67305aebefSGustavo Pimentel goto legacy_sel_wr; 68305aebefSGustavo Pimentel } 69305aebefSGustavo Pimentel 70305aebefSGustavo Pimentel for (ch = 0; ch < dw->rd_ch_cnt; ch++) 71756c3ef9SArnd Bergmann if (lim[1][ch].start >= reg && reg < lim[1][ch].end) { 72756c3ef9SArnd Bergmann ptr += (reg - lim[1][ch].start); 73305aebefSGustavo Pimentel goto legacy_sel_rd; 74305aebefSGustavo Pimentel } 75305aebefSGustavo Pimentel 76305aebefSGustavo Pimentel return 0; 77305aebefSGustavo Pimentel legacy_sel_rd: 78305aebefSGustavo Pimentel viewport_sel = BIT(31); 79305aebefSGustavo Pimentel legacy_sel_wr: 80305aebefSGustavo Pimentel viewport_sel |= FIELD_PREP(EDMA_V0_VIEWPORT_MASK, ch); 81305aebefSGustavo Pimentel 82305aebefSGustavo Pimentel raw_spin_lock_irqsave(&dw->lock, flags); 83305aebefSGustavo Pimentel 84305aebefSGustavo Pimentel writel(viewport_sel, ®s->type.legacy.viewport_sel); 85305aebefSGustavo Pimentel *val = readl(ptr); 86305aebefSGustavo Pimentel 87305aebefSGustavo Pimentel raw_spin_unlock_irqrestore(&dw->lock, flags); 88305aebefSGustavo Pimentel } else { 89756c3ef9SArnd Bergmann *val = readl(reg); 90305aebefSGustavo Pimentel } 91305aebefSGustavo Pimentel 92305aebefSGustavo Pimentel return 0; 93305aebefSGustavo Pimentel } 94305aebefSGustavo Pimentel DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_edma_debugfs_u32_get, NULL, "0x%08llx\n"); 95305aebefSGustavo Pimentel 96305aebefSGustavo Pimentel static void dw_edma_debugfs_create_x32(const struct debugfs_entries entries[], 97305aebefSGustavo Pimentel int nr_entries, struct dentry *dir) 98305aebefSGustavo Pimentel { 99305aebefSGustavo Pimentel int i; 100305aebefSGustavo Pimentel 101305aebefSGustavo Pimentel for (i = 0; i < nr_entries; i++) { 102305aebefSGustavo Pimentel if (!debugfs_create_file_unsafe(entries[i].name, 0444, dir, 103305aebefSGustavo Pimentel entries[i].reg, &fops_x32)) 104305aebefSGustavo Pimentel break; 105305aebefSGustavo Pimentel } 106305aebefSGustavo Pimentel } 107305aebefSGustavo Pimentel 108756c3ef9SArnd Bergmann static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs, 109305aebefSGustavo Pimentel struct dentry *dir) 110305aebefSGustavo Pimentel { 111305aebefSGustavo Pimentel int nr_entries; 112305aebefSGustavo Pimentel const struct debugfs_entries debugfs_regs[] = { 113305aebefSGustavo Pimentel REGISTER(ch_control1), 114305aebefSGustavo Pimentel REGISTER(ch_control2), 115305aebefSGustavo Pimentel REGISTER(transfer_size), 11604e0a39fSGustavo Pimentel REGISTER(sar.lsb), 11704e0a39fSGustavo Pimentel REGISTER(sar.msb), 11804e0a39fSGustavo Pimentel REGISTER(dar.lsb), 11904e0a39fSGustavo Pimentel REGISTER(dar.msb), 12004e0a39fSGustavo Pimentel REGISTER(llp.lsb), 12104e0a39fSGustavo Pimentel REGISTER(llp.msb), 122305aebefSGustavo Pimentel }; 123305aebefSGustavo Pimentel 124305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_regs); 125305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, dir); 126305aebefSGustavo Pimentel } 127305aebefSGustavo Pimentel 128305aebefSGustavo Pimentel static void dw_edma_debugfs_regs_wr(struct dentry *dir) 129305aebefSGustavo Pimentel { 130305aebefSGustavo Pimentel const struct debugfs_entries debugfs_regs[] = { 131305aebefSGustavo Pimentel /* eDMA global registers */ 132305aebefSGustavo Pimentel WR_REGISTER(engine_en), 133305aebefSGustavo Pimentel WR_REGISTER(doorbell), 13404e0a39fSGustavo Pimentel WR_REGISTER(ch_arb_weight.lsb), 13504e0a39fSGustavo Pimentel WR_REGISTER(ch_arb_weight.msb), 136305aebefSGustavo Pimentel /* eDMA interrupts registers */ 137305aebefSGustavo Pimentel WR_REGISTER(int_status), 138305aebefSGustavo Pimentel WR_REGISTER(int_mask), 139305aebefSGustavo Pimentel WR_REGISTER(int_clear), 140305aebefSGustavo Pimentel WR_REGISTER(err_status), 14104e0a39fSGustavo Pimentel WR_REGISTER(done_imwr.lsb), 14204e0a39fSGustavo Pimentel WR_REGISTER(done_imwr.msb), 14304e0a39fSGustavo Pimentel WR_REGISTER(abort_imwr.lsb), 14404e0a39fSGustavo Pimentel WR_REGISTER(abort_imwr.msb), 145305aebefSGustavo Pimentel WR_REGISTER(ch01_imwr_data), 146305aebefSGustavo Pimentel WR_REGISTER(ch23_imwr_data), 147305aebefSGustavo Pimentel WR_REGISTER(ch45_imwr_data), 148305aebefSGustavo Pimentel WR_REGISTER(ch67_imwr_data), 149305aebefSGustavo Pimentel WR_REGISTER(linked_list_err_en), 150305aebefSGustavo Pimentel }; 151305aebefSGustavo Pimentel const struct debugfs_entries debugfs_unroll_regs[] = { 152305aebefSGustavo Pimentel /* eDMA channel context grouping */ 153305aebefSGustavo Pimentel WR_REGISTER_UNROLL(engine_chgroup), 15404e0a39fSGustavo Pimentel WR_REGISTER_UNROLL(engine_hshake_cnt.lsb), 15504e0a39fSGustavo Pimentel WR_REGISTER_UNROLL(engine_hshake_cnt.msb), 156305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch0_pwr_en), 157305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch1_pwr_en), 158305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch2_pwr_en), 159305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch3_pwr_en), 160305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch4_pwr_en), 161305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch5_pwr_en), 162305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch6_pwr_en), 163305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch7_pwr_en), 164305aebefSGustavo Pimentel }; 165305aebefSGustavo Pimentel struct dentry *regs_dir, *ch_dir; 166305aebefSGustavo Pimentel int nr_entries, i; 167305aebefSGustavo Pimentel char name[16]; 168305aebefSGustavo Pimentel 169305aebefSGustavo Pimentel regs_dir = debugfs_create_dir(WRITE_STR, dir); 170305aebefSGustavo Pimentel if (!regs_dir) 171305aebefSGustavo Pimentel return; 172305aebefSGustavo Pimentel 173305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_regs); 174305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir); 175305aebefSGustavo Pimentel 176*20318457SFrank Li if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) { 177305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_unroll_regs); 178305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries, 179305aebefSGustavo Pimentel regs_dir); 180305aebefSGustavo Pimentel } 181305aebefSGustavo Pimentel 182305aebefSGustavo Pimentel for (i = 0; i < dw->wr_ch_cnt; i++) { 183305aebefSGustavo Pimentel snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i); 184305aebefSGustavo Pimentel 185305aebefSGustavo Pimentel ch_dir = debugfs_create_dir(name, regs_dir); 186305aebefSGustavo Pimentel if (!ch_dir) 187305aebefSGustavo Pimentel return; 188305aebefSGustavo Pimentel 189305aebefSGustavo Pimentel dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].wr, ch_dir); 190305aebefSGustavo Pimentel 191305aebefSGustavo Pimentel lim[0][i].start = ®s->type.unroll.ch[i].wr; 192305aebefSGustavo Pimentel lim[0][i].end = ®s->type.unroll.ch[i].padding_1[0]; 193305aebefSGustavo Pimentel } 194305aebefSGustavo Pimentel } 195305aebefSGustavo Pimentel 196305aebefSGustavo Pimentel static void dw_edma_debugfs_regs_rd(struct dentry *dir) 197305aebefSGustavo Pimentel { 198305aebefSGustavo Pimentel const struct debugfs_entries debugfs_regs[] = { 199305aebefSGustavo Pimentel /* eDMA global registers */ 200305aebefSGustavo Pimentel RD_REGISTER(engine_en), 201305aebefSGustavo Pimentel RD_REGISTER(doorbell), 20204e0a39fSGustavo Pimentel RD_REGISTER(ch_arb_weight.lsb), 20304e0a39fSGustavo Pimentel RD_REGISTER(ch_arb_weight.msb), 204305aebefSGustavo Pimentel /* eDMA interrupts registers */ 205305aebefSGustavo Pimentel RD_REGISTER(int_status), 206305aebefSGustavo Pimentel RD_REGISTER(int_mask), 207305aebefSGustavo Pimentel RD_REGISTER(int_clear), 20804e0a39fSGustavo Pimentel RD_REGISTER(err_status.lsb), 20904e0a39fSGustavo Pimentel RD_REGISTER(err_status.msb), 210305aebefSGustavo Pimentel RD_REGISTER(linked_list_err_en), 21104e0a39fSGustavo Pimentel RD_REGISTER(done_imwr.lsb), 21204e0a39fSGustavo Pimentel RD_REGISTER(done_imwr.msb), 21304e0a39fSGustavo Pimentel RD_REGISTER(abort_imwr.lsb), 21404e0a39fSGustavo Pimentel RD_REGISTER(abort_imwr.msb), 215305aebefSGustavo Pimentel RD_REGISTER(ch01_imwr_data), 216305aebefSGustavo Pimentel RD_REGISTER(ch23_imwr_data), 217305aebefSGustavo Pimentel RD_REGISTER(ch45_imwr_data), 218305aebefSGustavo Pimentel RD_REGISTER(ch67_imwr_data), 219305aebefSGustavo Pimentel }; 220305aebefSGustavo Pimentel const struct debugfs_entries debugfs_unroll_regs[] = { 221305aebefSGustavo Pimentel /* eDMA channel context grouping */ 222305aebefSGustavo Pimentel RD_REGISTER_UNROLL(engine_chgroup), 22304e0a39fSGustavo Pimentel RD_REGISTER_UNROLL(engine_hshake_cnt.lsb), 22404e0a39fSGustavo Pimentel RD_REGISTER_UNROLL(engine_hshake_cnt.msb), 225305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch0_pwr_en), 226305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch1_pwr_en), 227305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch2_pwr_en), 228305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch3_pwr_en), 229305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch4_pwr_en), 230305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch5_pwr_en), 231305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch6_pwr_en), 232305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch7_pwr_en), 233305aebefSGustavo Pimentel }; 234305aebefSGustavo Pimentel struct dentry *regs_dir, *ch_dir; 235305aebefSGustavo Pimentel int nr_entries, i; 236305aebefSGustavo Pimentel char name[16]; 237305aebefSGustavo Pimentel 238305aebefSGustavo Pimentel regs_dir = debugfs_create_dir(READ_STR, dir); 239305aebefSGustavo Pimentel if (!regs_dir) 240305aebefSGustavo Pimentel return; 241305aebefSGustavo Pimentel 242305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_regs); 243305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir); 244305aebefSGustavo Pimentel 245*20318457SFrank Li if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) { 246305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_unroll_regs); 247305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries, 248305aebefSGustavo Pimentel regs_dir); 249305aebefSGustavo Pimentel } 250305aebefSGustavo Pimentel 251305aebefSGustavo Pimentel for (i = 0; i < dw->rd_ch_cnt; i++) { 252305aebefSGustavo Pimentel snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i); 253305aebefSGustavo Pimentel 254305aebefSGustavo Pimentel ch_dir = debugfs_create_dir(name, regs_dir); 255305aebefSGustavo Pimentel if (!ch_dir) 256305aebefSGustavo Pimentel return; 257305aebefSGustavo Pimentel 258305aebefSGustavo Pimentel dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].rd, ch_dir); 259305aebefSGustavo Pimentel 260305aebefSGustavo Pimentel lim[1][i].start = ®s->type.unroll.ch[i].rd; 261305aebefSGustavo Pimentel lim[1][i].end = ®s->type.unroll.ch[i].padding_2[0]; 262305aebefSGustavo Pimentel } 263305aebefSGustavo Pimentel } 264305aebefSGustavo Pimentel 265305aebefSGustavo Pimentel static void dw_edma_debugfs_regs(void) 266305aebefSGustavo Pimentel { 267305aebefSGustavo Pimentel const struct debugfs_entries debugfs_regs[] = { 268305aebefSGustavo Pimentel REGISTER(ctrl_data_arb_prior), 269305aebefSGustavo Pimentel REGISTER(ctrl), 270305aebefSGustavo Pimentel }; 271305aebefSGustavo Pimentel struct dentry *regs_dir; 272305aebefSGustavo Pimentel int nr_entries; 273305aebefSGustavo Pimentel 2745244ac2eSGustavo Pimentel regs_dir = debugfs_create_dir(REGISTERS_STR, dw->debugfs); 275305aebefSGustavo Pimentel if (!regs_dir) 276305aebefSGustavo Pimentel return; 277305aebefSGustavo Pimentel 278305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_regs); 279305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir); 280305aebefSGustavo Pimentel 281305aebefSGustavo Pimentel dw_edma_debugfs_regs_wr(regs_dir); 282305aebefSGustavo Pimentel dw_edma_debugfs_regs_rd(regs_dir); 283305aebefSGustavo Pimentel } 284305aebefSGustavo Pimentel 285*20318457SFrank Li void dw_edma_v0_debugfs_on(struct dw_edma *_dw) 286305aebefSGustavo Pimentel { 287*20318457SFrank Li dw = _dw; 288305aebefSGustavo Pimentel if (!dw) 289305aebefSGustavo Pimentel return; 290305aebefSGustavo Pimentel 291*20318457SFrank Li regs = dw->chip->rg_region.vaddr; 292305aebefSGustavo Pimentel if (!regs) 293305aebefSGustavo Pimentel return; 294305aebefSGustavo Pimentel 2955244ac2eSGustavo Pimentel dw->debugfs = debugfs_create_dir(dw->name, NULL); 2965244ac2eSGustavo Pimentel if (!dw->debugfs) 297305aebefSGustavo Pimentel return; 298305aebefSGustavo Pimentel 299*20318457SFrank Li debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf); 3005244ac2eSGustavo Pimentel debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt); 3015244ac2eSGustavo Pimentel debugfs_create_u16("rd_ch_cnt", 0444, dw->debugfs, &dw->rd_ch_cnt); 302305aebefSGustavo Pimentel 303305aebefSGustavo Pimentel dw_edma_debugfs_regs(); 304305aebefSGustavo Pimentel } 305305aebefSGustavo Pimentel 306*20318457SFrank Li void dw_edma_v0_debugfs_off(struct dw_edma *_dw) 307305aebefSGustavo Pimentel { 308*20318457SFrank Li dw = _dw; 3095244ac2eSGustavo Pimentel if (!dw) 3105244ac2eSGustavo Pimentel return; 3115244ac2eSGustavo Pimentel 3125244ac2eSGustavo Pimentel debugfs_remove_recursive(dw->debugfs); 3135244ac2eSGustavo Pimentel dw->debugfs = NULL; 314305aebefSGustavo Pimentel } 315