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) \ 17*756c3ef9SArnd 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 dentry *base_dir; 42305aebefSGustavo Pimentel static struct dw_edma *dw; 43*756c3ef9SArnd Bergmann static struct dw_edma_v0_regs __iomem *regs; 44305aebefSGustavo Pimentel 45305aebefSGustavo Pimentel static struct { 46*756c3ef9SArnd Bergmann void __iomem *start; 47*756c3ef9SArnd Bergmann void __iomem *end; 48305aebefSGustavo Pimentel } lim[2][EDMA_V0_MAX_NR_CH]; 49305aebefSGustavo Pimentel 50305aebefSGustavo Pimentel struct debugfs_entries { 51f0414087SArnd Bergmann const char *name; 52305aebefSGustavo Pimentel dma_addr_t *reg; 53305aebefSGustavo Pimentel }; 54305aebefSGustavo Pimentel 55305aebefSGustavo Pimentel static int dw_edma_debugfs_u32_get(void *data, u64 *val) 56305aebefSGustavo Pimentel { 57*756c3ef9SArnd Bergmann void __iomem *reg = (void __force __iomem *)data; 58305aebefSGustavo Pimentel if (dw->mode == EDMA_MODE_LEGACY && 59*756c3ef9SArnd Bergmann reg >= (void __iomem *)®s->type.legacy.ch) { 60*756c3ef9SArnd Bergmann void __iomem *ptr = ®s->type.legacy.ch; 61305aebefSGustavo Pimentel u32 viewport_sel = 0; 62305aebefSGustavo Pimentel unsigned long flags; 63305aebefSGustavo Pimentel u16 ch; 64305aebefSGustavo Pimentel 65305aebefSGustavo Pimentel for (ch = 0; ch < dw->wr_ch_cnt; ch++) 66*756c3ef9SArnd Bergmann if (lim[0][ch].start >= reg && reg < lim[0][ch].end) { 67*756c3ef9SArnd Bergmann ptr += (reg - lim[0][ch].start); 68305aebefSGustavo Pimentel goto legacy_sel_wr; 69305aebefSGustavo Pimentel } 70305aebefSGustavo Pimentel 71305aebefSGustavo Pimentel for (ch = 0; ch < dw->rd_ch_cnt; ch++) 72*756c3ef9SArnd Bergmann if (lim[1][ch].start >= reg && reg < lim[1][ch].end) { 73*756c3ef9SArnd Bergmann ptr += (reg - lim[1][ch].start); 74305aebefSGustavo Pimentel goto legacy_sel_rd; 75305aebefSGustavo Pimentel } 76305aebefSGustavo Pimentel 77305aebefSGustavo Pimentel return 0; 78305aebefSGustavo Pimentel legacy_sel_rd: 79305aebefSGustavo Pimentel viewport_sel = BIT(31); 80305aebefSGustavo Pimentel legacy_sel_wr: 81305aebefSGustavo Pimentel viewport_sel |= FIELD_PREP(EDMA_V0_VIEWPORT_MASK, ch); 82305aebefSGustavo Pimentel 83305aebefSGustavo Pimentel raw_spin_lock_irqsave(&dw->lock, flags); 84305aebefSGustavo Pimentel 85305aebefSGustavo Pimentel writel(viewport_sel, ®s->type.legacy.viewport_sel); 86305aebefSGustavo Pimentel *val = readl(ptr); 87305aebefSGustavo Pimentel 88305aebefSGustavo Pimentel raw_spin_unlock_irqrestore(&dw->lock, flags); 89305aebefSGustavo Pimentel } else { 90*756c3ef9SArnd Bergmann *val = readl(reg); 91305aebefSGustavo Pimentel } 92305aebefSGustavo Pimentel 93305aebefSGustavo Pimentel return 0; 94305aebefSGustavo Pimentel } 95305aebefSGustavo Pimentel DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_edma_debugfs_u32_get, NULL, "0x%08llx\n"); 96305aebefSGustavo Pimentel 97305aebefSGustavo Pimentel static void dw_edma_debugfs_create_x32(const struct debugfs_entries entries[], 98305aebefSGustavo Pimentel int nr_entries, struct dentry *dir) 99305aebefSGustavo Pimentel { 100305aebefSGustavo Pimentel int i; 101305aebefSGustavo Pimentel 102305aebefSGustavo Pimentel for (i = 0; i < nr_entries; i++) { 103305aebefSGustavo Pimentel if (!debugfs_create_file_unsafe(entries[i].name, 0444, dir, 104305aebefSGustavo Pimentel entries[i].reg, &fops_x32)) 105305aebefSGustavo Pimentel break; 106305aebefSGustavo Pimentel } 107305aebefSGustavo Pimentel } 108305aebefSGustavo Pimentel 109*756c3ef9SArnd Bergmann static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs, 110305aebefSGustavo Pimentel struct dentry *dir) 111305aebefSGustavo Pimentel { 112305aebefSGustavo Pimentel int nr_entries; 113305aebefSGustavo Pimentel const struct debugfs_entries debugfs_regs[] = { 114305aebefSGustavo Pimentel REGISTER(ch_control1), 115305aebefSGustavo Pimentel REGISTER(ch_control2), 116305aebefSGustavo Pimentel REGISTER(transfer_size), 117305aebefSGustavo Pimentel REGISTER(sar_low), 118305aebefSGustavo Pimentel REGISTER(sar_high), 119305aebefSGustavo Pimentel REGISTER(dar_low), 120305aebefSGustavo Pimentel REGISTER(dar_high), 121305aebefSGustavo Pimentel REGISTER(llp_low), 122305aebefSGustavo Pimentel REGISTER(llp_high), 123305aebefSGustavo Pimentel }; 124305aebefSGustavo Pimentel 125305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_regs); 126305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, dir); 127305aebefSGustavo Pimentel } 128305aebefSGustavo Pimentel 129305aebefSGustavo Pimentel static void dw_edma_debugfs_regs_wr(struct dentry *dir) 130305aebefSGustavo Pimentel { 131305aebefSGustavo Pimentel const struct debugfs_entries debugfs_regs[] = { 132305aebefSGustavo Pimentel /* eDMA global registers */ 133305aebefSGustavo Pimentel WR_REGISTER(engine_en), 134305aebefSGustavo Pimentel WR_REGISTER(doorbell), 135305aebefSGustavo Pimentel WR_REGISTER(ch_arb_weight_low), 136305aebefSGustavo Pimentel WR_REGISTER(ch_arb_weight_high), 137305aebefSGustavo Pimentel /* eDMA interrupts registers */ 138305aebefSGustavo Pimentel WR_REGISTER(int_status), 139305aebefSGustavo Pimentel WR_REGISTER(int_mask), 140305aebefSGustavo Pimentel WR_REGISTER(int_clear), 141305aebefSGustavo Pimentel WR_REGISTER(err_status), 142305aebefSGustavo Pimentel WR_REGISTER(done_imwr_low), 143305aebefSGustavo Pimentel WR_REGISTER(done_imwr_high), 144305aebefSGustavo Pimentel WR_REGISTER(abort_imwr_low), 145305aebefSGustavo Pimentel WR_REGISTER(abort_imwr_high), 146305aebefSGustavo Pimentel WR_REGISTER(ch01_imwr_data), 147305aebefSGustavo Pimentel WR_REGISTER(ch23_imwr_data), 148305aebefSGustavo Pimentel WR_REGISTER(ch45_imwr_data), 149305aebefSGustavo Pimentel WR_REGISTER(ch67_imwr_data), 150305aebefSGustavo Pimentel WR_REGISTER(linked_list_err_en), 151305aebefSGustavo Pimentel }; 152305aebefSGustavo Pimentel const struct debugfs_entries debugfs_unroll_regs[] = { 153305aebefSGustavo Pimentel /* eDMA channel context grouping */ 154305aebefSGustavo Pimentel WR_REGISTER_UNROLL(engine_chgroup), 155305aebefSGustavo Pimentel WR_REGISTER_UNROLL(engine_hshake_cnt_low), 156305aebefSGustavo Pimentel WR_REGISTER_UNROLL(engine_hshake_cnt_high), 157305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch0_pwr_en), 158305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch1_pwr_en), 159305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch2_pwr_en), 160305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch3_pwr_en), 161305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch4_pwr_en), 162305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch5_pwr_en), 163305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch6_pwr_en), 164305aebefSGustavo Pimentel WR_REGISTER_UNROLL(ch7_pwr_en), 165305aebefSGustavo Pimentel }; 166305aebefSGustavo Pimentel struct dentry *regs_dir, *ch_dir; 167305aebefSGustavo Pimentel int nr_entries, i; 168305aebefSGustavo Pimentel char name[16]; 169305aebefSGustavo Pimentel 170305aebefSGustavo Pimentel regs_dir = debugfs_create_dir(WRITE_STR, dir); 171305aebefSGustavo Pimentel if (!regs_dir) 172305aebefSGustavo Pimentel return; 173305aebefSGustavo Pimentel 174305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_regs); 175305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir); 176305aebefSGustavo Pimentel 177305aebefSGustavo Pimentel if (dw->mode == EDMA_MODE_UNROLL) { 178305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_unroll_regs); 179305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries, 180305aebefSGustavo Pimentel regs_dir); 181305aebefSGustavo Pimentel } 182305aebefSGustavo Pimentel 183305aebefSGustavo Pimentel for (i = 0; i < dw->wr_ch_cnt; i++) { 184305aebefSGustavo Pimentel snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i); 185305aebefSGustavo Pimentel 186305aebefSGustavo Pimentel ch_dir = debugfs_create_dir(name, regs_dir); 187305aebefSGustavo Pimentel if (!ch_dir) 188305aebefSGustavo Pimentel return; 189305aebefSGustavo Pimentel 190305aebefSGustavo Pimentel dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].wr, ch_dir); 191305aebefSGustavo Pimentel 192305aebefSGustavo Pimentel lim[0][i].start = ®s->type.unroll.ch[i].wr; 193305aebefSGustavo Pimentel lim[0][i].end = ®s->type.unroll.ch[i].padding_1[0]; 194305aebefSGustavo Pimentel } 195305aebefSGustavo Pimentel } 196305aebefSGustavo Pimentel 197305aebefSGustavo Pimentel static void dw_edma_debugfs_regs_rd(struct dentry *dir) 198305aebefSGustavo Pimentel { 199305aebefSGustavo Pimentel const struct debugfs_entries debugfs_regs[] = { 200305aebefSGustavo Pimentel /* eDMA global registers */ 201305aebefSGustavo Pimentel RD_REGISTER(engine_en), 202305aebefSGustavo Pimentel RD_REGISTER(doorbell), 203305aebefSGustavo Pimentel RD_REGISTER(ch_arb_weight_low), 204305aebefSGustavo Pimentel RD_REGISTER(ch_arb_weight_high), 205305aebefSGustavo Pimentel /* eDMA interrupts registers */ 206305aebefSGustavo Pimentel RD_REGISTER(int_status), 207305aebefSGustavo Pimentel RD_REGISTER(int_mask), 208305aebefSGustavo Pimentel RD_REGISTER(int_clear), 209305aebefSGustavo Pimentel RD_REGISTER(err_status_low), 210305aebefSGustavo Pimentel RD_REGISTER(err_status_high), 211305aebefSGustavo Pimentel RD_REGISTER(linked_list_err_en), 212305aebefSGustavo Pimentel RD_REGISTER(done_imwr_low), 213305aebefSGustavo Pimentel RD_REGISTER(done_imwr_high), 214305aebefSGustavo Pimentel RD_REGISTER(abort_imwr_low), 215305aebefSGustavo Pimentel RD_REGISTER(abort_imwr_high), 216305aebefSGustavo Pimentel RD_REGISTER(ch01_imwr_data), 217305aebefSGustavo Pimentel RD_REGISTER(ch23_imwr_data), 218305aebefSGustavo Pimentel RD_REGISTER(ch45_imwr_data), 219305aebefSGustavo Pimentel RD_REGISTER(ch67_imwr_data), 220305aebefSGustavo Pimentel }; 221305aebefSGustavo Pimentel const struct debugfs_entries debugfs_unroll_regs[] = { 222305aebefSGustavo Pimentel /* eDMA channel context grouping */ 223305aebefSGustavo Pimentel RD_REGISTER_UNROLL(engine_chgroup), 224305aebefSGustavo Pimentel RD_REGISTER_UNROLL(engine_hshake_cnt_low), 225305aebefSGustavo Pimentel RD_REGISTER_UNROLL(engine_hshake_cnt_high), 226305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch0_pwr_en), 227305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch1_pwr_en), 228305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch2_pwr_en), 229305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch3_pwr_en), 230305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch4_pwr_en), 231305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch5_pwr_en), 232305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch6_pwr_en), 233305aebefSGustavo Pimentel RD_REGISTER_UNROLL(ch7_pwr_en), 234305aebefSGustavo Pimentel }; 235305aebefSGustavo Pimentel struct dentry *regs_dir, *ch_dir; 236305aebefSGustavo Pimentel int nr_entries, i; 237305aebefSGustavo Pimentel char name[16]; 238305aebefSGustavo Pimentel 239305aebefSGustavo Pimentel regs_dir = debugfs_create_dir(READ_STR, dir); 240305aebefSGustavo Pimentel if (!regs_dir) 241305aebefSGustavo Pimentel return; 242305aebefSGustavo Pimentel 243305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_regs); 244305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir); 245305aebefSGustavo Pimentel 246305aebefSGustavo Pimentel if (dw->mode == EDMA_MODE_UNROLL) { 247305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_unroll_regs); 248305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries, 249305aebefSGustavo Pimentel regs_dir); 250305aebefSGustavo Pimentel } 251305aebefSGustavo Pimentel 252305aebefSGustavo Pimentel for (i = 0; i < dw->rd_ch_cnt; i++) { 253305aebefSGustavo Pimentel snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i); 254305aebefSGustavo Pimentel 255305aebefSGustavo Pimentel ch_dir = debugfs_create_dir(name, regs_dir); 256305aebefSGustavo Pimentel if (!ch_dir) 257305aebefSGustavo Pimentel return; 258305aebefSGustavo Pimentel 259305aebefSGustavo Pimentel dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].rd, ch_dir); 260305aebefSGustavo Pimentel 261305aebefSGustavo Pimentel lim[1][i].start = ®s->type.unroll.ch[i].rd; 262305aebefSGustavo Pimentel lim[1][i].end = ®s->type.unroll.ch[i].padding_2[0]; 263305aebefSGustavo Pimentel } 264305aebefSGustavo Pimentel } 265305aebefSGustavo Pimentel 266305aebefSGustavo Pimentel static void dw_edma_debugfs_regs(void) 267305aebefSGustavo Pimentel { 268305aebefSGustavo Pimentel const struct debugfs_entries debugfs_regs[] = { 269305aebefSGustavo Pimentel REGISTER(ctrl_data_arb_prior), 270305aebefSGustavo Pimentel REGISTER(ctrl), 271305aebefSGustavo Pimentel }; 272305aebefSGustavo Pimentel struct dentry *regs_dir; 273305aebefSGustavo Pimentel int nr_entries; 274305aebefSGustavo Pimentel 275305aebefSGustavo Pimentel regs_dir = debugfs_create_dir(REGISTERS_STR, base_dir); 276305aebefSGustavo Pimentel if (!regs_dir) 277305aebefSGustavo Pimentel return; 278305aebefSGustavo Pimentel 279305aebefSGustavo Pimentel nr_entries = ARRAY_SIZE(debugfs_regs); 280305aebefSGustavo Pimentel dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir); 281305aebefSGustavo Pimentel 282305aebefSGustavo Pimentel dw_edma_debugfs_regs_wr(regs_dir); 283305aebefSGustavo Pimentel dw_edma_debugfs_regs_rd(regs_dir); 284305aebefSGustavo Pimentel } 285305aebefSGustavo Pimentel 286305aebefSGustavo Pimentel void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip) 287305aebefSGustavo Pimentel { 288305aebefSGustavo Pimentel dw = chip->dw; 289305aebefSGustavo Pimentel if (!dw) 290305aebefSGustavo Pimentel return; 291305aebefSGustavo Pimentel 292*756c3ef9SArnd Bergmann regs = dw->rg_region.vaddr; 293305aebefSGustavo Pimentel if (!regs) 294305aebefSGustavo Pimentel return; 295305aebefSGustavo Pimentel 296305aebefSGustavo Pimentel base_dir = debugfs_create_dir(dw->name, 0); 297305aebefSGustavo Pimentel if (!base_dir) 298305aebefSGustavo Pimentel return; 299305aebefSGustavo Pimentel 300305aebefSGustavo Pimentel debugfs_create_u32("version", 0444, base_dir, &dw->version); 301305aebefSGustavo Pimentel debugfs_create_u32("mode", 0444, base_dir, &dw->mode); 302305aebefSGustavo Pimentel debugfs_create_u16("wr_ch_cnt", 0444, base_dir, &dw->wr_ch_cnt); 303305aebefSGustavo Pimentel debugfs_create_u16("rd_ch_cnt", 0444, base_dir, &dw->rd_ch_cnt); 304305aebefSGustavo Pimentel 305305aebefSGustavo Pimentel dw_edma_debugfs_regs(); 306305aebefSGustavo Pimentel } 307305aebefSGustavo Pimentel 308305aebefSGustavo Pimentel void dw_edma_v0_debugfs_off(void) 309305aebefSGustavo Pimentel { 310305aebefSGustavo Pimentel debugfs_remove_recursive(base_dir); 311305aebefSGustavo Pimentel } 312