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) \ 17305aebefSGustavo Pimentel ((dma_addr_t *)®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; 43305aebefSGustavo Pimentel static struct dw_edma_v0_regs *regs; 44305aebefSGustavo Pimentel 45305aebefSGustavo Pimentel static struct { 46305aebefSGustavo Pimentel void *start; 47305aebefSGustavo Pimentel void *end; 48305aebefSGustavo Pimentel } lim[2][EDMA_V0_MAX_NR_CH]; 49305aebefSGustavo Pimentel 50305aebefSGustavo Pimentel struct debugfs_entries { 51*f0414087SArnd 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 { 57305aebefSGustavo Pimentel if (dw->mode == EDMA_MODE_LEGACY && 58305aebefSGustavo Pimentel data >= (void *)®s->type.legacy.ch) { 59305aebefSGustavo Pimentel void *ptr = (void *)®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++) 65305aebefSGustavo Pimentel if (lim[0][ch].start >= data && data < lim[0][ch].end) { 66305aebefSGustavo Pimentel ptr += (data - 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++) 71305aebefSGustavo Pimentel if (lim[1][ch].start >= data && data < lim[1][ch].end) { 72305aebefSGustavo Pimentel ptr += (data - 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 { 89305aebefSGustavo Pimentel *val = readl(data); 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 108305aebefSGustavo Pimentel static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs *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), 116305aebefSGustavo Pimentel REGISTER(sar_low), 117305aebefSGustavo Pimentel REGISTER(sar_high), 118305aebefSGustavo Pimentel REGISTER(dar_low), 119305aebefSGustavo Pimentel REGISTER(dar_high), 120305aebefSGustavo Pimentel REGISTER(llp_low), 121305aebefSGustavo Pimentel REGISTER(llp_high), 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), 134305aebefSGustavo Pimentel WR_REGISTER(ch_arb_weight_low), 135305aebefSGustavo Pimentel WR_REGISTER(ch_arb_weight_high), 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), 141305aebefSGustavo Pimentel WR_REGISTER(done_imwr_low), 142305aebefSGustavo Pimentel WR_REGISTER(done_imwr_high), 143305aebefSGustavo Pimentel WR_REGISTER(abort_imwr_low), 144305aebefSGustavo Pimentel WR_REGISTER(abort_imwr_high), 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), 154305aebefSGustavo Pimentel WR_REGISTER_UNROLL(engine_hshake_cnt_low), 155305aebefSGustavo Pimentel WR_REGISTER_UNROLL(engine_hshake_cnt_high), 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 176305aebefSGustavo Pimentel if (dw->mode == EDMA_MODE_UNROLL) { 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), 202305aebefSGustavo Pimentel RD_REGISTER(ch_arb_weight_low), 203305aebefSGustavo Pimentel RD_REGISTER(ch_arb_weight_high), 204305aebefSGustavo Pimentel /* eDMA interrupts registers */ 205305aebefSGustavo Pimentel RD_REGISTER(int_status), 206305aebefSGustavo Pimentel RD_REGISTER(int_mask), 207305aebefSGustavo Pimentel RD_REGISTER(int_clear), 208305aebefSGustavo Pimentel RD_REGISTER(err_status_low), 209305aebefSGustavo Pimentel RD_REGISTER(err_status_high), 210305aebefSGustavo Pimentel RD_REGISTER(linked_list_err_en), 211305aebefSGustavo Pimentel RD_REGISTER(done_imwr_low), 212305aebefSGustavo Pimentel RD_REGISTER(done_imwr_high), 213305aebefSGustavo Pimentel RD_REGISTER(abort_imwr_low), 214305aebefSGustavo Pimentel RD_REGISTER(abort_imwr_high), 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), 223305aebefSGustavo Pimentel RD_REGISTER_UNROLL(engine_hshake_cnt_low), 224305aebefSGustavo Pimentel RD_REGISTER_UNROLL(engine_hshake_cnt_high), 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 245305aebefSGustavo Pimentel if (dw->mode == EDMA_MODE_UNROLL) { 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 274305aebefSGustavo Pimentel regs_dir = debugfs_create_dir(REGISTERS_STR, base_dir); 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 285305aebefSGustavo Pimentel void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip) 286305aebefSGustavo Pimentel { 287305aebefSGustavo Pimentel dw = chip->dw; 288305aebefSGustavo Pimentel if (!dw) 289305aebefSGustavo Pimentel return; 290305aebefSGustavo Pimentel 291305aebefSGustavo Pimentel regs = (struct dw_edma_v0_regs *)dw->rg_region.vaddr; 292305aebefSGustavo Pimentel if (!regs) 293305aebefSGustavo Pimentel return; 294305aebefSGustavo Pimentel 295305aebefSGustavo Pimentel base_dir = debugfs_create_dir(dw->name, 0); 296305aebefSGustavo Pimentel if (!base_dir) 297305aebefSGustavo Pimentel return; 298305aebefSGustavo Pimentel 299305aebefSGustavo Pimentel debugfs_create_u32("version", 0444, base_dir, &dw->version); 300305aebefSGustavo Pimentel debugfs_create_u32("mode", 0444, base_dir, &dw->mode); 301305aebefSGustavo Pimentel debugfs_create_u16("wr_ch_cnt", 0444, base_dir, &dw->wr_ch_cnt); 302305aebefSGustavo Pimentel debugfs_create_u16("rd_ch_cnt", 0444, base_dir, &dw->rd_ch_cnt); 303305aebefSGustavo Pimentel 304305aebefSGustavo Pimentel dw_edma_debugfs_regs(); 305305aebefSGustavo Pimentel } 306305aebefSGustavo Pimentel 307305aebefSGustavo Pimentel void dw_edma_v0_debugfs_off(void) 308305aebefSGustavo Pimentel { 309305aebefSGustavo Pimentel debugfs_remove_recursive(base_dir); 310305aebefSGustavo Pimentel } 311