1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
4 * Synopsys DesignWare eDMA v0 core
6 * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
9 #include <linux/debugfs.h>
10 #include <linux/bitfield.h>
12 #include "dw-edma-v0-debugfs.h"
13 #include "dw-edma-v0-regs.h"
14 #include "dw-edma-core.h"
16 #define REGS_ADDR(dw, name) \
18 struct dw_edma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \
20 (void __iomem *)&__regs->name; \
23 #define REGS_CH_ADDR(dw, name, _dir, _ch) \
25 struct dw_edma_v0_ch_regs __iomem *__ch_regs; \
27 if ((dw)->chip->mf == EDMA_MF_EDMA_LEGACY) \
28 __ch_regs = REGS_ADDR(dw, type.legacy.ch); \
29 else if (_dir == EDMA_DIR_READ) \
30 __ch_regs = REGS_ADDR(dw, type.unroll.ch[_ch].rd); \
32 __ch_regs = REGS_ADDR(dw, type.unroll.ch[_ch].wr); \
34 (void __iomem *)&__ch_regs->name; \
37 #define REGISTER(dw, name) \
38 { dw, #name, REGS_ADDR(dw, name) }
40 #define CTX_REGISTER(dw, name, dir, ch) \
41 { dw, #name, REGS_CH_ADDR(dw, name, dir, ch), dir, ch }
43 #define WR_REGISTER(dw, name) \
44 { dw, #name, REGS_ADDR(dw, wr_##name) }
45 #define RD_REGISTER(dw, name) \
46 { dw, #name, REGS_ADDR(dw, rd_##name) }
48 #define WR_REGISTER_LEGACY(dw, name) \
49 { dw, #name, REGS_ADDR(dw, type.legacy.wr_##name) }
50 #define RD_REGISTER_LEGACY(name) \
51 { dw, #name, REGS_ADDR(dw, type.legacy.rd_##name) }
53 #define WR_REGISTER_UNROLL(dw, name) \
54 { dw, #name, REGS_ADDR(dw, type.unroll.wr_##name) }
55 #define RD_REGISTER_UNROLL(dw, name) \
56 { dw, #name, REGS_ADDR(dw, type.unroll.rd_##name) }
58 #define WRITE_STR "write"
59 #define READ_STR "read"
60 #define CHANNEL_STR "channel"
61 #define REGISTERS_STR "registers"
63 struct dw_edma_debugfs_entry
{
71 static int dw_edma_debugfs_u32_get(void *data
, u64
*val
)
73 struct dw_edma_debugfs_entry
*entry
= data
;
74 struct dw_edma
*dw
= entry
->dw
;
75 void __iomem
*reg
= entry
->reg
;
77 if (dw
->chip
->mf
== EDMA_MF_EDMA_LEGACY
&&
78 reg
>= REGS_ADDR(dw
, type
.legacy
.ch
)) {
82 viewport_sel
= entry
->dir
== EDMA_DIR_READ
? BIT(31) : 0;
83 viewport_sel
|= FIELD_PREP(EDMA_V0_VIEWPORT_MASK
, entry
->ch
);
85 raw_spin_lock_irqsave(&dw
->lock
, flags
);
87 writel(viewport_sel
, REGS_ADDR(dw
, type
.legacy
.viewport_sel
));
90 raw_spin_unlock_irqrestore(&dw
->lock
, flags
);
97 DEFINE_DEBUGFS_ATTRIBUTE(fops_x32
, dw_edma_debugfs_u32_get
, NULL
, "0x%08llx\n");
99 static void dw_edma_debugfs_create_x32(struct dw_edma
*dw
,
100 const struct dw_edma_debugfs_entry ini
[],
101 int nr_entries
, struct dentry
*dent
)
103 struct dw_edma_debugfs_entry
*entries
;
106 entries
= devm_kcalloc(dw
->chip
->dev
, nr_entries
, sizeof(*entries
),
111 for (i
= 0; i
< nr_entries
; i
++) {
114 debugfs_create_file_unsafe(entries
[i
].name
, 0444, dent
,
115 &entries
[i
], &fops_x32
);
119 static void dw_edma_debugfs_regs_ch(struct dw_edma
*dw
, enum dw_edma_dir dir
,
120 u16 ch
, struct dentry
*dent
)
122 struct dw_edma_debugfs_entry debugfs_regs
[] = {
123 CTX_REGISTER(dw
, ch_control1
, dir
, ch
),
124 CTX_REGISTER(dw
, ch_control2
, dir
, ch
),
125 CTX_REGISTER(dw
, transfer_size
, dir
, ch
),
126 CTX_REGISTER(dw
, sar
.lsb
, dir
, ch
),
127 CTX_REGISTER(dw
, sar
.msb
, dir
, ch
),
128 CTX_REGISTER(dw
, dar
.lsb
, dir
, ch
),
129 CTX_REGISTER(dw
, dar
.msb
, dir
, ch
),
130 CTX_REGISTER(dw
, llp
.lsb
, dir
, ch
),
131 CTX_REGISTER(dw
, llp
.msb
, dir
, ch
),
135 nr_entries
= ARRAY_SIZE(debugfs_regs
);
136 dw_edma_debugfs_create_x32(dw
, debugfs_regs
, nr_entries
, dent
);
139 static noinline_for_stack
void
140 dw_edma_debugfs_regs_wr(struct dw_edma
*dw
, struct dentry
*dent
)
142 const struct dw_edma_debugfs_entry debugfs_regs
[] = {
143 /* eDMA global registers */
144 WR_REGISTER(dw
, engine_en
),
145 WR_REGISTER(dw
, doorbell
),
146 WR_REGISTER(dw
, ch_arb_weight
.lsb
),
147 WR_REGISTER(dw
, ch_arb_weight
.msb
),
148 /* eDMA interrupts registers */
149 WR_REGISTER(dw
, int_status
),
150 WR_REGISTER(dw
, int_mask
),
151 WR_REGISTER(dw
, int_clear
),
152 WR_REGISTER(dw
, err_status
),
153 WR_REGISTER(dw
, done_imwr
.lsb
),
154 WR_REGISTER(dw
, done_imwr
.msb
),
155 WR_REGISTER(dw
, abort_imwr
.lsb
),
156 WR_REGISTER(dw
, abort_imwr
.msb
),
157 WR_REGISTER(dw
, ch01_imwr_data
),
158 WR_REGISTER(dw
, ch23_imwr_data
),
159 WR_REGISTER(dw
, ch45_imwr_data
),
160 WR_REGISTER(dw
, ch67_imwr_data
),
161 WR_REGISTER(dw
, linked_list_err_en
),
163 const struct dw_edma_debugfs_entry debugfs_unroll_regs
[] = {
164 /* eDMA channel context grouping */
165 WR_REGISTER_UNROLL(dw
, engine_chgroup
),
166 WR_REGISTER_UNROLL(dw
, engine_hshake_cnt
.lsb
),
167 WR_REGISTER_UNROLL(dw
, engine_hshake_cnt
.msb
),
168 WR_REGISTER_UNROLL(dw
, ch0_pwr_en
),
169 WR_REGISTER_UNROLL(dw
, ch1_pwr_en
),
170 WR_REGISTER_UNROLL(dw
, ch2_pwr_en
),
171 WR_REGISTER_UNROLL(dw
, ch3_pwr_en
),
172 WR_REGISTER_UNROLL(dw
, ch4_pwr_en
),
173 WR_REGISTER_UNROLL(dw
, ch5_pwr_en
),
174 WR_REGISTER_UNROLL(dw
, ch6_pwr_en
),
175 WR_REGISTER_UNROLL(dw
, ch7_pwr_en
),
177 struct dentry
*regs_dent
, *ch_dent
;
181 regs_dent
= debugfs_create_dir(WRITE_STR
, dent
);
183 nr_entries
= ARRAY_SIZE(debugfs_regs
);
184 dw_edma_debugfs_create_x32(dw
, debugfs_regs
, nr_entries
, regs_dent
);
186 if (dw
->chip
->mf
== EDMA_MF_HDMA_COMPAT
) {
187 nr_entries
= ARRAY_SIZE(debugfs_unroll_regs
);
188 dw_edma_debugfs_create_x32(dw
, debugfs_unroll_regs
, nr_entries
,
192 for (i
= 0; i
< dw
->wr_ch_cnt
; i
++) {
193 snprintf(name
, sizeof(name
), "%s:%d", CHANNEL_STR
, i
);
195 ch_dent
= debugfs_create_dir(name
, regs_dent
);
197 dw_edma_debugfs_regs_ch(dw
, EDMA_DIR_WRITE
, i
, ch_dent
);
201 static noinline_for_stack
void dw_edma_debugfs_regs_rd(struct dw_edma
*dw
,
204 const struct dw_edma_debugfs_entry debugfs_regs
[] = {
205 /* eDMA global registers */
206 RD_REGISTER(dw
, engine_en
),
207 RD_REGISTER(dw
, doorbell
),
208 RD_REGISTER(dw
, ch_arb_weight
.lsb
),
209 RD_REGISTER(dw
, ch_arb_weight
.msb
),
210 /* eDMA interrupts registers */
211 RD_REGISTER(dw
, int_status
),
212 RD_REGISTER(dw
, int_mask
),
213 RD_REGISTER(dw
, int_clear
),
214 RD_REGISTER(dw
, err_status
.lsb
),
215 RD_REGISTER(dw
, err_status
.msb
),
216 RD_REGISTER(dw
, linked_list_err_en
),
217 RD_REGISTER(dw
, done_imwr
.lsb
),
218 RD_REGISTER(dw
, done_imwr
.msb
),
219 RD_REGISTER(dw
, abort_imwr
.lsb
),
220 RD_REGISTER(dw
, abort_imwr
.msb
),
221 RD_REGISTER(dw
, ch01_imwr_data
),
222 RD_REGISTER(dw
, ch23_imwr_data
),
223 RD_REGISTER(dw
, ch45_imwr_data
),
224 RD_REGISTER(dw
, ch67_imwr_data
),
226 const struct dw_edma_debugfs_entry debugfs_unroll_regs
[] = {
227 /* eDMA channel context grouping */
228 RD_REGISTER_UNROLL(dw
, engine_chgroup
),
229 RD_REGISTER_UNROLL(dw
, engine_hshake_cnt
.lsb
),
230 RD_REGISTER_UNROLL(dw
, engine_hshake_cnt
.msb
),
231 RD_REGISTER_UNROLL(dw
, ch0_pwr_en
),
232 RD_REGISTER_UNROLL(dw
, ch1_pwr_en
),
233 RD_REGISTER_UNROLL(dw
, ch2_pwr_en
),
234 RD_REGISTER_UNROLL(dw
, ch3_pwr_en
),
235 RD_REGISTER_UNROLL(dw
, ch4_pwr_en
),
236 RD_REGISTER_UNROLL(dw
, ch5_pwr_en
),
237 RD_REGISTER_UNROLL(dw
, ch6_pwr_en
),
238 RD_REGISTER_UNROLL(dw
, ch7_pwr_en
),
240 struct dentry
*regs_dent
, *ch_dent
;
244 regs_dent
= debugfs_create_dir(READ_STR
, dent
);
246 nr_entries
= ARRAY_SIZE(debugfs_regs
);
247 dw_edma_debugfs_create_x32(dw
, debugfs_regs
, nr_entries
, regs_dent
);
249 if (dw
->chip
->mf
== EDMA_MF_HDMA_COMPAT
) {
250 nr_entries
= ARRAY_SIZE(debugfs_unroll_regs
);
251 dw_edma_debugfs_create_x32(dw
, debugfs_unroll_regs
, nr_entries
,
255 for (i
= 0; i
< dw
->rd_ch_cnt
; i
++) {
256 snprintf(name
, sizeof(name
), "%s:%d", CHANNEL_STR
, i
);
258 ch_dent
= debugfs_create_dir(name
, regs_dent
);
260 dw_edma_debugfs_regs_ch(dw
, EDMA_DIR_READ
, i
, ch_dent
);
264 static void dw_edma_debugfs_regs(struct dw_edma
*dw
)
266 const struct dw_edma_debugfs_entry debugfs_regs
[] = {
267 REGISTER(dw
, ctrl_data_arb_prior
),
270 struct dentry
*regs_dent
;
273 regs_dent
= debugfs_create_dir(REGISTERS_STR
, dw
->dma
.dbg_dev_root
);
275 nr_entries
= ARRAY_SIZE(debugfs_regs
);
276 dw_edma_debugfs_create_x32(dw
, debugfs_regs
, nr_entries
, regs_dent
);
278 dw_edma_debugfs_regs_wr(dw
, regs_dent
);
279 dw_edma_debugfs_regs_rd(dw
, regs_dent
);
282 void dw_edma_v0_debugfs_on(struct dw_edma
*dw
)
284 if (!debugfs_initialized())
287 debugfs_create_u32("mf", 0444, dw
->dma
.dbg_dev_root
, &dw
->chip
->mf
);
288 debugfs_create_u16("wr_ch_cnt", 0444, dw
->dma
.dbg_dev_root
, &dw
->wr_ch_cnt
);
289 debugfs_create_u16("rd_ch_cnt", 0444, dw
->dma
.dbg_dev_root
, &dw
->rd_ch_cnt
);
291 dw_edma_debugfs_regs(dw
);