xref: /OK3568_Linux_fs/kernel/drivers/dma/dw-edma/dw-edma-v0-debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
4*4882a593Smuzhiyun  * Synopsys DesignWare eDMA v0 core
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/debugfs.h>
10*4882a593Smuzhiyun #include <linux/bitfield.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include "dw-edma-v0-debugfs.h"
13*4882a593Smuzhiyun #include "dw-edma-v0-regs.h"
14*4882a593Smuzhiyun #include "dw-edma-core.h"
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define REGS_ADDR(name) \
17*4882a593Smuzhiyun 	((void __force *)&regs->name)
18*4882a593Smuzhiyun #define REGISTER(name) \
19*4882a593Smuzhiyun 	{ #name, REGS_ADDR(name) }
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define WR_REGISTER(name) \
22*4882a593Smuzhiyun 	{ #name, REGS_ADDR(wr_##name) }
23*4882a593Smuzhiyun #define RD_REGISTER(name) \
24*4882a593Smuzhiyun 	{ #name, REGS_ADDR(rd_##name) }
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define WR_REGISTER_LEGACY(name) \
27*4882a593Smuzhiyun 	{ #name, REGS_ADDR(type.legacy.wr_##name) }
28*4882a593Smuzhiyun #define RD_REGISTER_LEGACY(name) \
29*4882a593Smuzhiyun 	{ #name, REGS_ADDR(type.legacy.rd_##name) }
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define WR_REGISTER_UNROLL(name) \
32*4882a593Smuzhiyun 	{ #name, REGS_ADDR(type.unroll.wr_##name) }
33*4882a593Smuzhiyun #define RD_REGISTER_UNROLL(name) \
34*4882a593Smuzhiyun 	{ #name, REGS_ADDR(type.unroll.rd_##name) }
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define WRITE_STR				"write"
37*4882a593Smuzhiyun #define READ_STR				"read"
38*4882a593Smuzhiyun #define CHANNEL_STR				"channel"
39*4882a593Smuzhiyun #define REGISTERS_STR				"registers"
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun static struct dentry				*base_dir;
42*4882a593Smuzhiyun static struct dw_edma				*dw;
43*4882a593Smuzhiyun static struct dw_edma_v0_regs			__iomem *regs;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun static struct {
46*4882a593Smuzhiyun 	void					__iomem *start;
47*4882a593Smuzhiyun 	void					__iomem *end;
48*4882a593Smuzhiyun } lim[2][EDMA_V0_MAX_NR_CH];
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun struct debugfs_entries {
51*4882a593Smuzhiyun 	const char				*name;
52*4882a593Smuzhiyun 	dma_addr_t				*reg;
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun 
dw_edma_debugfs_u32_get(void * data,u64 * val)55*4882a593Smuzhiyun static int dw_edma_debugfs_u32_get(void *data, u64 *val)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	void __iomem *reg = (void __force __iomem *)data;
58*4882a593Smuzhiyun 	if (dw->mode == EDMA_MODE_LEGACY &&
59*4882a593Smuzhiyun 	    reg >= (void __iomem *)&regs->type.legacy.ch) {
60*4882a593Smuzhiyun 		void __iomem *ptr = &regs->type.legacy.ch;
61*4882a593Smuzhiyun 		u32 viewport_sel = 0;
62*4882a593Smuzhiyun 		unsigned long flags;
63*4882a593Smuzhiyun 		u16 ch;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 		for (ch = 0; ch < dw->wr_ch_cnt; ch++)
66*4882a593Smuzhiyun 			if (lim[0][ch].start >= reg && reg < lim[0][ch].end) {
67*4882a593Smuzhiyun 				ptr += (reg - lim[0][ch].start);
68*4882a593Smuzhiyun 				goto legacy_sel_wr;
69*4882a593Smuzhiyun 			}
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 		for (ch = 0; ch < dw->rd_ch_cnt; ch++)
72*4882a593Smuzhiyun 			if (lim[1][ch].start >= reg && reg < lim[1][ch].end) {
73*4882a593Smuzhiyun 				ptr += (reg - lim[1][ch].start);
74*4882a593Smuzhiyun 				goto legacy_sel_rd;
75*4882a593Smuzhiyun 			}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 		return 0;
78*4882a593Smuzhiyun legacy_sel_rd:
79*4882a593Smuzhiyun 		viewport_sel = BIT(31);
80*4882a593Smuzhiyun legacy_sel_wr:
81*4882a593Smuzhiyun 		viewport_sel |= FIELD_PREP(EDMA_V0_VIEWPORT_MASK, ch);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 		raw_spin_lock_irqsave(&dw->lock, flags);
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 		writel(viewport_sel, &regs->type.legacy.viewport_sel);
86*4882a593Smuzhiyun 		*val = readl(ptr);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 		raw_spin_unlock_irqrestore(&dw->lock, flags);
89*4882a593Smuzhiyun 	} else {
90*4882a593Smuzhiyun 		*val = readl(reg);
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	return 0;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_edma_debugfs_u32_get, NULL, "0x%08llx\n");
96*4882a593Smuzhiyun 
dw_edma_debugfs_create_x32(const struct debugfs_entries entries[],int nr_entries,struct dentry * dir)97*4882a593Smuzhiyun static void dw_edma_debugfs_create_x32(const struct debugfs_entries entries[],
98*4882a593Smuzhiyun 				       int nr_entries, struct dentry *dir)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	int i;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	for (i = 0; i < nr_entries; i++) {
103*4882a593Smuzhiyun 		if (!debugfs_create_file_unsafe(entries[i].name, 0444, dir,
104*4882a593Smuzhiyun 						entries[i].reg,	&fops_x32))
105*4882a593Smuzhiyun 			break;
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem * regs,struct dentry * dir)109*4882a593Smuzhiyun static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,
110*4882a593Smuzhiyun 				    struct dentry *dir)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	int nr_entries;
113*4882a593Smuzhiyun 	const struct debugfs_entries debugfs_regs[] = {
114*4882a593Smuzhiyun 		REGISTER(ch_control1),
115*4882a593Smuzhiyun 		REGISTER(ch_control2),
116*4882a593Smuzhiyun 		REGISTER(transfer_size),
117*4882a593Smuzhiyun 		REGISTER(sar_low),
118*4882a593Smuzhiyun 		REGISTER(sar_high),
119*4882a593Smuzhiyun 		REGISTER(dar_low),
120*4882a593Smuzhiyun 		REGISTER(dar_high),
121*4882a593Smuzhiyun 		REGISTER(llp_low),
122*4882a593Smuzhiyun 		REGISTER(llp_high),
123*4882a593Smuzhiyun 	};
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	nr_entries = ARRAY_SIZE(debugfs_regs);
126*4882a593Smuzhiyun 	dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, dir);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
dw_edma_debugfs_regs_wr(struct dentry * dir)129*4882a593Smuzhiyun static void dw_edma_debugfs_regs_wr(struct dentry *dir)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	const struct debugfs_entries debugfs_regs[] = {
132*4882a593Smuzhiyun 		/* eDMA global registers */
133*4882a593Smuzhiyun 		WR_REGISTER(engine_en),
134*4882a593Smuzhiyun 		WR_REGISTER(doorbell),
135*4882a593Smuzhiyun 		WR_REGISTER(ch_arb_weight_low),
136*4882a593Smuzhiyun 		WR_REGISTER(ch_arb_weight_high),
137*4882a593Smuzhiyun 		/* eDMA interrupts registers */
138*4882a593Smuzhiyun 		WR_REGISTER(int_status),
139*4882a593Smuzhiyun 		WR_REGISTER(int_mask),
140*4882a593Smuzhiyun 		WR_REGISTER(int_clear),
141*4882a593Smuzhiyun 		WR_REGISTER(err_status),
142*4882a593Smuzhiyun 		WR_REGISTER(done_imwr_low),
143*4882a593Smuzhiyun 		WR_REGISTER(done_imwr_high),
144*4882a593Smuzhiyun 		WR_REGISTER(abort_imwr_low),
145*4882a593Smuzhiyun 		WR_REGISTER(abort_imwr_high),
146*4882a593Smuzhiyun 		WR_REGISTER(ch01_imwr_data),
147*4882a593Smuzhiyun 		WR_REGISTER(ch23_imwr_data),
148*4882a593Smuzhiyun 		WR_REGISTER(ch45_imwr_data),
149*4882a593Smuzhiyun 		WR_REGISTER(ch67_imwr_data),
150*4882a593Smuzhiyun 		WR_REGISTER(linked_list_err_en),
151*4882a593Smuzhiyun 	};
152*4882a593Smuzhiyun 	const struct debugfs_entries debugfs_unroll_regs[] = {
153*4882a593Smuzhiyun 		/* eDMA channel context grouping */
154*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(engine_chgroup),
155*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(engine_hshake_cnt_low),
156*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(engine_hshake_cnt_high),
157*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(ch0_pwr_en),
158*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(ch1_pwr_en),
159*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(ch2_pwr_en),
160*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(ch3_pwr_en),
161*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(ch4_pwr_en),
162*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(ch5_pwr_en),
163*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(ch6_pwr_en),
164*4882a593Smuzhiyun 		WR_REGISTER_UNROLL(ch7_pwr_en),
165*4882a593Smuzhiyun 	};
166*4882a593Smuzhiyun 	struct dentry *regs_dir, *ch_dir;
167*4882a593Smuzhiyun 	int nr_entries, i;
168*4882a593Smuzhiyun 	char name[16];
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	regs_dir = debugfs_create_dir(WRITE_STR, dir);
171*4882a593Smuzhiyun 	if (!regs_dir)
172*4882a593Smuzhiyun 		return;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	nr_entries = ARRAY_SIZE(debugfs_regs);
175*4882a593Smuzhiyun 	dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	if (dw->mode == EDMA_MODE_UNROLL) {
178*4882a593Smuzhiyun 		nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
179*4882a593Smuzhiyun 		dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
180*4882a593Smuzhiyun 					   regs_dir);
181*4882a593Smuzhiyun 	}
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	for (i = 0; i < dw->wr_ch_cnt; i++) {
184*4882a593Smuzhiyun 		snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 		ch_dir = debugfs_create_dir(name, regs_dir);
187*4882a593Smuzhiyun 		if (!ch_dir)
188*4882a593Smuzhiyun 			return;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 		dw_edma_debugfs_regs_ch(&regs->type.unroll.ch[i].wr, ch_dir);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 		lim[0][i].start = &regs->type.unroll.ch[i].wr;
193*4882a593Smuzhiyun 		lim[0][i].end = &regs->type.unroll.ch[i].padding_1[0];
194*4882a593Smuzhiyun 	}
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
dw_edma_debugfs_regs_rd(struct dentry * dir)197*4882a593Smuzhiyun static void dw_edma_debugfs_regs_rd(struct dentry *dir)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	const struct debugfs_entries debugfs_regs[] = {
200*4882a593Smuzhiyun 		/* eDMA global registers */
201*4882a593Smuzhiyun 		RD_REGISTER(engine_en),
202*4882a593Smuzhiyun 		RD_REGISTER(doorbell),
203*4882a593Smuzhiyun 		RD_REGISTER(ch_arb_weight_low),
204*4882a593Smuzhiyun 		RD_REGISTER(ch_arb_weight_high),
205*4882a593Smuzhiyun 		/* eDMA interrupts registers */
206*4882a593Smuzhiyun 		RD_REGISTER(int_status),
207*4882a593Smuzhiyun 		RD_REGISTER(int_mask),
208*4882a593Smuzhiyun 		RD_REGISTER(int_clear),
209*4882a593Smuzhiyun 		RD_REGISTER(err_status_low),
210*4882a593Smuzhiyun 		RD_REGISTER(err_status_high),
211*4882a593Smuzhiyun 		RD_REGISTER(linked_list_err_en),
212*4882a593Smuzhiyun 		RD_REGISTER(done_imwr_low),
213*4882a593Smuzhiyun 		RD_REGISTER(done_imwr_high),
214*4882a593Smuzhiyun 		RD_REGISTER(abort_imwr_low),
215*4882a593Smuzhiyun 		RD_REGISTER(abort_imwr_high),
216*4882a593Smuzhiyun 		RD_REGISTER(ch01_imwr_data),
217*4882a593Smuzhiyun 		RD_REGISTER(ch23_imwr_data),
218*4882a593Smuzhiyun 		RD_REGISTER(ch45_imwr_data),
219*4882a593Smuzhiyun 		RD_REGISTER(ch67_imwr_data),
220*4882a593Smuzhiyun 	};
221*4882a593Smuzhiyun 	const struct debugfs_entries debugfs_unroll_regs[] = {
222*4882a593Smuzhiyun 		/* eDMA channel context grouping */
223*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(engine_chgroup),
224*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(engine_hshake_cnt_low),
225*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(engine_hshake_cnt_high),
226*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(ch0_pwr_en),
227*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(ch1_pwr_en),
228*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(ch2_pwr_en),
229*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(ch3_pwr_en),
230*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(ch4_pwr_en),
231*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(ch5_pwr_en),
232*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(ch6_pwr_en),
233*4882a593Smuzhiyun 		RD_REGISTER_UNROLL(ch7_pwr_en),
234*4882a593Smuzhiyun 	};
235*4882a593Smuzhiyun 	struct dentry *regs_dir, *ch_dir;
236*4882a593Smuzhiyun 	int nr_entries, i;
237*4882a593Smuzhiyun 	char name[16];
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	regs_dir = debugfs_create_dir(READ_STR, dir);
240*4882a593Smuzhiyun 	if (!regs_dir)
241*4882a593Smuzhiyun 		return;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	nr_entries = ARRAY_SIZE(debugfs_regs);
244*4882a593Smuzhiyun 	dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	if (dw->mode == EDMA_MODE_UNROLL) {
247*4882a593Smuzhiyun 		nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
248*4882a593Smuzhiyun 		dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
249*4882a593Smuzhiyun 					   regs_dir);
250*4882a593Smuzhiyun 	}
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	for (i = 0; i < dw->rd_ch_cnt; i++) {
253*4882a593Smuzhiyun 		snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 		ch_dir = debugfs_create_dir(name, regs_dir);
256*4882a593Smuzhiyun 		if (!ch_dir)
257*4882a593Smuzhiyun 			return;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 		dw_edma_debugfs_regs_ch(&regs->type.unroll.ch[i].rd, ch_dir);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 		lim[1][i].start = &regs->type.unroll.ch[i].rd;
262*4882a593Smuzhiyun 		lim[1][i].end = &regs->type.unroll.ch[i].padding_2[0];
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
dw_edma_debugfs_regs(void)266*4882a593Smuzhiyun static void dw_edma_debugfs_regs(void)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	const struct debugfs_entries debugfs_regs[] = {
269*4882a593Smuzhiyun 		REGISTER(ctrl_data_arb_prior),
270*4882a593Smuzhiyun 		REGISTER(ctrl),
271*4882a593Smuzhiyun 	};
272*4882a593Smuzhiyun 	struct dentry *regs_dir;
273*4882a593Smuzhiyun 	int nr_entries;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	regs_dir = debugfs_create_dir(REGISTERS_STR, base_dir);
276*4882a593Smuzhiyun 	if (!regs_dir)
277*4882a593Smuzhiyun 		return;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	nr_entries = ARRAY_SIZE(debugfs_regs);
280*4882a593Smuzhiyun 	dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	dw_edma_debugfs_regs_wr(regs_dir);
283*4882a593Smuzhiyun 	dw_edma_debugfs_regs_rd(regs_dir);
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
dw_edma_v0_debugfs_on(struct dw_edma_chip * chip)286*4882a593Smuzhiyun void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun 	dw = chip->dw;
289*4882a593Smuzhiyun 	if (!dw)
290*4882a593Smuzhiyun 		return;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	regs = dw->rg_region.vaddr;
293*4882a593Smuzhiyun 	if (!regs)
294*4882a593Smuzhiyun 		return;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	base_dir = debugfs_create_dir(dw->name, NULL);
297*4882a593Smuzhiyun 	if (!base_dir)
298*4882a593Smuzhiyun 		return;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	debugfs_create_u32("version", 0444, base_dir, &dw->version);
301*4882a593Smuzhiyun 	debugfs_create_u32("mode", 0444, base_dir, &dw->mode);
302*4882a593Smuzhiyun 	debugfs_create_u16("wr_ch_cnt", 0444, base_dir, &dw->wr_ch_cnt);
303*4882a593Smuzhiyun 	debugfs_create_u16("rd_ch_cnt", 0444, base_dir, &dw->rd_ch_cnt);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	dw_edma_debugfs_regs();
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
dw_edma_v0_debugfs_off(void)308*4882a593Smuzhiyun void dw_edma_v0_debugfs_off(void)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	debugfs_remove_recursive(base_dir);
311*4882a593Smuzhiyun }
312