xref: /linux/drivers/dma/dw-edma/dw-edma-core.h (revision 66498c75b4f8017f62d720d9b59675bdf3abce91)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
4  * Synopsys DesignWare eDMA core driver
5  *
6  * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
7  */
8 
9 #ifndef _DW_EDMA_CORE_H
10 #define _DW_EDMA_CORE_H
11 
12 #include <linux/atomic.h>
13 #include <linux/msi.h>
14 #include <linux/dma/edma.h>
15 #include <linux/workqueue.h>
16 
17 #include "../virt-dma.h"
18 
19 #define EDMA_LL_SZ					24
20 
21 enum dw_edma_dir {
22 	EDMA_DIR_WRITE = 0,
23 	EDMA_DIR_READ
24 };
25 
26 enum dw_edma_request {
27 	EDMA_REQ_NONE = 0,
28 	EDMA_REQ_STOP,
29 	EDMA_REQ_PAUSE
30 };
31 
32 enum dw_edma_status {
33 	EDMA_ST_IDLE = 0,
34 	EDMA_ST_PAUSE,
35 	EDMA_ST_BUSY
36 };
37 
38 enum dw_edma_xfer_type {
39 	EDMA_XFER_SCATTER_GATHER = 0,
40 	EDMA_XFER_CYCLIC,
41 	EDMA_XFER_INTERLEAVED
42 };
43 
44 struct dw_edma_chan;
45 struct dw_edma_chunk;
46 
47 struct dw_edma_burst {
48 	u64				sar;
49 	u64				dar;
50 	u32				sz;
51 	/* precalulate summary of previous burst total size */
52 	u32				xfer_sz;
53 };
54 
55 struct dw_edma_desc {
56 	struct virt_dma_desc		vd;
57 	struct dw_edma_chan		*chan;
58 
59 	u32				alloc_sz;
60 
61 	size_t				done_burst;
62 	size_t				start_burst;
63 	u8				cb;
64 	size_t				nburst;
65 	struct dw_edma_burst            burst[] __counted_by(nburst);
66 };
67 
68 struct dw_edma_chan {
69 	struct virt_dma_chan		vc;
70 	struct dw_edma			*dw;
71 	int				id;
72 	enum dw_edma_dir		dir;
73 	u8				func_no;
74 
75 	u32				ll_max;
76 	struct dw_edma_region		ll_region;	/* Linked list */
77 
78 	struct msi_msg			msi;
79 
80 	enum dw_edma_ch_irq_mode	irq_mode;
81 
82 	enum dw_edma_request		request;
83 	enum dw_edma_status		status;
84 	u8				configured;
85 
86 	struct dma_slave_config		config;
87 	bool				non_ll;
88 
89 	struct work_struct		irq_work;
90 	atomic_t			irq_pending;
91 };
92 
93 struct dw_edma_irq {
94 	struct msi_msg                  msi;
95 	struct dw_edma			*dw;
96 
97 	DECLARE_BITMAP(wr_mask, HDMA_MAX_WR_CH);
98 	DECLARE_BITMAP(rd_mask, HDMA_MAX_RD_CH);
99 };
100 
101 struct dw_edma {
102 	char				name[32];
103 
104 	struct dma_device		dma;
105 
106 	u16				wr_ch_cnt;
107 	u16				rd_ch_cnt;
108 
109 	struct dw_edma_irq		*irq;
110 	int				nr_irqs;
111 
112 	struct dw_edma_chan		*chan;
113 
114 	/*
115 	 * WQ_HIGHPRI keeps completion processing responsive under heavy load;
116 	 * WQ_UNBOUND lets different channels run on different CPUs.
117 	 */
118 	struct workqueue_struct		*wq;
119 
120 	raw_spinlock_t			lock;		/* Protect v0 shared registers */
121 
122 	struct dw_edma_chip             *chip;
123 
124 	const struct dw_edma_core_ops	*core;
125 };
126 
127 typedef void (*dw_edma_handler_t)(struct dw_edma_chan *);
128 
129 struct dw_edma_core_ops {
130 	void (*off)(struct dw_edma *dw);
131 	int (*quiesce)(struct dw_edma *dw);
132 	int (*ch_quiesce)(struct dw_edma_chan *chan);
133 	u16 (*ch_count)(struct dw_edma *dw, enum dw_edma_dir dir);
134 	enum dma_status (*ch_status)(struct dw_edma_chan *chan);
135 	irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
136 				  dw_edma_handler_t done, dw_edma_handler_t abort);
137 	void (*non_ll_start)(struct dw_edma_chan *chan, struct dw_edma_burst *child);
138 	void (*ll_data)(struct dw_edma_chan *chan, struct dw_edma_burst *burst,
139 			u32 idx, bool cb, bool irq);
140 	void (*ll_link)(struct dw_edma_chan *chan, u32 idx, bool cb, u64 addr);
141 	void (*ch_doorbell)(struct dw_edma_chan *chan);
142 	void (*ch_enable)(struct dw_edma_chan *chan);
143 	void (*ch_config)(struct dw_edma_chan *chan);
144 	void (*debugfs_on)(struct dw_edma *dw);
145 	void (*ack_emulated_irq)(struct dw_edma *dw);
146 	resource_size_t (*db_offset)(struct dw_edma *dw);
147 };
148 
149 struct dw_edma_sg {
150 	struct scatterlist		*sgl;
151 	unsigned int			len;
152 };
153 
154 struct dw_edma_cyclic {
155 	dma_addr_t			paddr;
156 	size_t				len;
157 	size_t				cnt;
158 };
159 
160 struct dw_edma_transfer {
161 	struct dma_chan			*dchan;
162 	union dw_edma_xfer {
163 		struct dw_edma_sg		sg;
164 		struct dw_edma_cyclic		cyclic;
165 		struct dma_interleaved_template *il;
166 	} xfer;
167 	enum dma_transfer_direction	direction;
168 	unsigned long			flags;
169 	enum dw_edma_xfer_type		type;
170 };
171 
172 static inline
vc2dw_edma_chan(struct virt_dma_chan * vc)173 struct dw_edma_chan *vc2dw_edma_chan(struct virt_dma_chan *vc)
174 {
175 	return container_of(vc, struct dw_edma_chan, vc);
176 }
177 
178 static inline
dchan2dw_edma_chan(struct dma_chan * dchan)179 struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan)
180 {
181 	return vc2dw_edma_chan(to_virt_chan(dchan));
182 }
183 
dw_edma_core_get_ll_paddr(struct dw_edma_chan * chan)184 static inline u64 dw_edma_core_get_ll_paddr(struct dw_edma_chan *chan)
185 {
186 	if (chan->dir == EDMA_DIR_WRITE)
187 		return chan->dw->chip->ll_region_wr[chan->id].paddr;
188 
189 	return chan->dw->chip->ll_region_rd[chan->id].paddr;
190 }
191 
192 static inline
dw_edma_core_off(struct dw_edma * dw)193 void dw_edma_core_off(struct dw_edma *dw)
194 {
195 	dw->core->off(dw);
196 }
197 
198 static inline
dw_edma_core_quiesce(struct dw_edma * dw)199 int dw_edma_core_quiesce(struct dw_edma *dw)
200 {
201 	return dw->core->quiesce(dw);
202 }
203 
204 static inline
dw_edma_core_ch_quiesce(struct dw_edma_chan * chan)205 int dw_edma_core_ch_quiesce(struct dw_edma_chan *chan)
206 {
207 	return chan->dw->core->ch_quiesce(chan);
208 }
209 
210 static inline
dw_edma_core_ch_count(struct dw_edma * dw,enum dw_edma_dir dir)211 u16 dw_edma_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
212 {
213 	return dw->core->ch_count(dw, dir);
214 }
215 
216 static inline
dw_edma_core_ch_status(struct dw_edma_chan * chan)217 enum dma_status dw_edma_core_ch_status(struct dw_edma_chan *chan)
218 {
219 	return chan->dw->core->ch_status(chan);
220 }
221 
222 static inline irqreturn_t
dw_edma_core_handle_int(struct dw_edma_irq * dw_irq,enum dw_edma_dir dir,dw_edma_handler_t done,dw_edma_handler_t abort)223 dw_edma_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
224 			dw_edma_handler_t done, dw_edma_handler_t abort)
225 {
226 	return dw_irq->dw->core->handle_int(dw_irq, dir, done, abort);
227 }
228 
229 static inline
dw_edma_core_ch_config(struct dw_edma_chan * chan)230 void dw_edma_core_ch_config(struct dw_edma_chan *chan)
231 {
232 	chan->dw->core->ch_config(chan);
233 }
234 
235 static inline void
dw_edma_core_ll_data(struct dw_edma_chan * chan,struct dw_edma_burst * burst,u32 idx,bool cb,bool irq)236 dw_edma_core_ll_data(struct dw_edma_chan *chan, struct dw_edma_burst *burst,
237 		     u32 idx, bool cb, bool irq)
238 {
239 	chan->dw->core->ll_data(chan, burst, idx, cb, irq);
240 }
241 
242 static inline void
dw_edma_core_ll_link(struct dw_edma_chan * chan,u32 idx,bool cb,u64 addr)243 dw_edma_core_ll_link(struct dw_edma_chan *chan, u32 idx, bool cb, u64 addr)
244 {
245 	chan->dw->core->ll_link(chan, idx, cb, addr);
246 }
247 
dw_edma_core_ch_doorbell(struct dw_edma_chan * chan)248 static inline void dw_edma_core_ch_doorbell(struct dw_edma_chan *chan)
249 {
250 	chan->dw->core->ch_doorbell(chan);
251 }
252 
dw_edma_core_ch_enable(struct dw_edma_chan * chan)253 static inline void dw_edma_core_ch_enable(struct dw_edma_chan *chan)
254 {
255 	chan->dw->core->ch_enable(chan);
256 }
257 
258 static inline
dw_edma_core_debugfs_on(struct dw_edma * dw)259 void dw_edma_core_debugfs_on(struct dw_edma *dw)
260 {
261 	dw->core->debugfs_on(dw);
262 }
263 
dw_edma_core_ack_emulated_irq(struct dw_edma * dw)264 static inline int dw_edma_core_ack_emulated_irq(struct dw_edma *dw)
265 {
266 	if (!dw->core->ack_emulated_irq)
267 		return -EOPNOTSUPP;
268 
269 	dw->core->ack_emulated_irq(dw);
270 	return 0;
271 }
272 
273 static inline resource_size_t
dw_edma_core_db_offset(struct dw_edma * dw)274 dw_edma_core_db_offset(struct dw_edma *dw)
275 {
276 	return dw->core->db_offset(dw);
277 }
278 
279 static inline bool
dw_edma_core_ch_ignore_irq(struct dw_edma_chan * chan)280 dw_edma_core_ch_ignore_irq(struct dw_edma_chan *chan)
281 {
282 	struct dw_edma *dw = chan->dw;
283 
284 	if (dw->chip->flags & DW_EDMA_CHIP_LOCAL)
285 		return chan->irq_mode == DW_EDMA_CH_IRQ_REMOTE;
286 	else
287 		return chan->irq_mode == DW_EDMA_CH_IRQ_LOCAL;
288 }
289 
290 #endif /* _DW_EDMA_CORE_H */
291