1 /*
2  * Copyright (c) 2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_DMA_DMA_DW_COMMON_H_
8 #define ZEPHYR_DRIVERS_DMA_DMA_DW_COMMON_H_
9 
10 #include <zephyr/sys/atomic.h>
11 #include <zephyr/drivers/dma.h>
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 #define MASK(b_hi, b_lo)					\
18 	(((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo))
19 #define SET_BIT(b, x) (((x) & 1) << (b))
20 #define SET_BITS(b_hi, b_lo, x)	\
21 	(((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo))
22 
23 #define DW_MAX_CHAN		8
24 #define DW_CHAN_COUNT		CONFIG_DMA_DW_CHANNEL_COUNT
25 #define DW_CH_SIZE		0x58
26 #define DW_CHAN_OFFSET(chan)	(DW_CH_SIZE * chan)
27 #define DW_ADDR_MASK_32		BIT_MASK(32)
28 #define DW_ADDR_RIGHT_SHIFT	32
29 
30 #define DW_SAR(chan)	\
31 	(0x0000 + DW_CHAN_OFFSET(chan))
32 #define DW_DAR(chan) \
33 	(0x0008 + DW_CHAN_OFFSET(chan))
34 #define DW_LLP(chan) \
35 	(0x0010 + DW_CHAN_OFFSET(chan))
36 #define DW_CTRL_LOW(chan) \
37 	(0x0018 + DW_CHAN_OFFSET(chan))
38 #define DW_CTRL_HIGH(chan) \
39 	(0x001C + DW_CHAN_OFFSET(chan))
40 #define DW_CFG_LOW(chan) \
41 	(0x0040 + DW_CHAN_OFFSET(chan))
42 #define DW_CFG_HIGH(chan) \
43 	(0x0044 + DW_CHAN_OFFSET(chan))
44 #define DW_DSR(chan) \
45 	(0x0050 + DW_CHAN_OFFSET(chan))
46 
47 #ifdef CONFIG_DMA_64BIT
48 #define DW_SAR_HI(chan) \
49 	(0x0004 + DW_CHAN_OFFSET(chan))
50 #define DW_DAR_HI(chan) \
51 	(0x000C + DW_CHAN_OFFSET(chan))
52 #endif
53 
54 /* registers */
55 #define DW_RAW_TFR		0x02C0
56 #define DW_RAW_BLOCK		0x02C8
57 #define DW_RAW_SRC_TRAN		0x02D0
58 #define DW_RAW_DST_TRAN		0x02D8
59 #define DW_RAW_ERR		0x02E0
60 #define DW_STATUS_TFR		0x02E8
61 #define DW_STATUS_BLOCK		0x02F0
62 #define DW_STATUS_SRC_TRAN	0x02F8
63 #define DW_STATUS_DST_TRAN	0x0300
64 #define DW_STATUS_ERR		0x0308
65 #define DW_MASK_TFR		0x0310
66 #define DW_MASK_BLOCK		0x0318
67 #define DW_MASK_SRC_TRAN	0x0320
68 #define DW_MASK_DST_TRAN	0x0328
69 #define DW_MASK_ERR		0x0330
70 #define DW_CLEAR_TFR		0x0338
71 #define DW_CLEAR_BLOCK		0x0340
72 #define DW_CLEAR_SRC_TRAN	0x0348
73 #define DW_CLEAR_DST_TRAN	0x0350
74 #define DW_CLEAR_ERR		0x0358
75 #define DW_INTR_STATUS		0x0360
76 #define DW_DMA_CFG		0x0398
77 #define DW_DMA_CHAN_EN		0x03A0
78 #define DW_FIFO_PART0_LO	0x400
79 #define DW_FIFO_PART0_HI	0x404
80 #define DW_FIFO_PART1_LO	0x408
81 #define DW_FIFO_PART1_HI	0x40C
82 
83 /* channel bits */
84 #define DW_CHAN_WRITE_EN_ALL	MASK(2 * DW_MAX_CHAN - 1, DW_MAX_CHAN)
85 #define DW_CHAN_WRITE_EN(chan)	BIT((chan) + DW_MAX_CHAN)
86 #define DW_CHAN_ALL		MASK(DW_MAX_CHAN - 1, 0)
87 #define DW_CHAN(chan)		BIT(chan)
88 #define DW_CHAN_MASK_ALL	DW_CHAN_WRITE_EN_ALL
89 #define DW_CHAN_MASK(chan)	DW_CHAN_WRITE_EN(chan)
90 #define DW_CHAN_UNMASK_ALL	(DW_CHAN_WRITE_EN_ALL | DW_CHAN_ALL)
91 #define DW_CHAN_UNMASK(chan)	(DW_CHAN_WRITE_EN(chan) | DW_CHAN(chan))
92 
93 /* CFG_LO */
94 #define DW_CFGL_RELOAD_DST	BIT(31)
95 #define DW_CFGL_RELOAD_SRC	BIT(30)
96 #define DW_CFGL_DRAIN		BIT(10) /* For Intel GPDMA variant only */
97 #define DW_CFGL_SRC_SW_HS       BIT(10) /* For Synopsys variant only */
98 #define DW_CFGL_DST_SW_HS       BIT(11) /* For Synopsys variant only */
99 #define DW_CFGL_FIFO_EMPTY	BIT(9)
100 #define DW_CFGL_SUSPEND		BIT(8)
101 #define DW_CFGL_CTL_HI_UPD_EN	BIT(5)
102 
103 /* CFG_HI */
104 #define DW_CFGH_DST_PER_EXT(x)		SET_BITS(31, 30, x)
105 #define DW_CFGH_SRC_PER_EXT(x)		SET_BITS(29, 28, x)
106 #define DW_CFGH_DST_PER(x)		SET_BITS(7, 4, x)
107 #define DW_CFGH_SRC_PER(x)		SET_BITS(3, 0, x)
108 #define DW_CFGH_DST(x) \
109 	(DW_CFGH_DST_PER_EXT((x) >> 4) | DW_CFGH_DST_PER(x))
110 #define DW_CFGH_SRC(x) \
111 	(DW_CFGH_SRC_PER_EXT((x) >> 4) | DW_CFGH_SRC_PER(x))
112 
113 /* CTL_LO */
114 #define DW_CTLL_RELOAD_DST	BIT(31)
115 #define DW_CTLL_RELOAD_SRC	BIT(30)
116 #define DW_CTLL_LLP_S_EN	BIT(28)
117 #define DW_CTLL_LLP_D_EN	BIT(27)
118 #define DW_CTLL_SMS(x)		SET_BIT(25, x)
119 #define DW_CTLL_DMS(x)		SET_BIT(23, x)
120 #define DW_CTLL_FC_P2P		SET_BITS(21, 20, 3)
121 #define DW_CTLL_FC_P2M		SET_BITS(21, 20, 2)
122 #define DW_CTLL_FC_M2P		SET_BITS(21, 20, 1)
123 #define DW_CTLL_FC_M2M		SET_BITS(21, 20, 0)
124 #define DW_CTLL_D_SCAT_EN	BIT(18)
125 #define DW_CTLL_S_GATH_EN	BIT(17)
126 #define DW_CTLL_SRC_MSIZE(x)	SET_BITS(16, 14, x)
127 #define DW_CTLL_DST_MSIZE(x)	SET_BITS(13, 11, x)
128 #define DW_CTLL_SRC_FIX		SET_BITS(10, 9, 2)
129 #define DW_CTLL_SRC_DEC		SET_BITS(10, 9, 1)
130 #define DW_CTLL_SRC_INC		SET_BITS(10, 9, 0)
131 #define DW_CTLL_DST_FIX		SET_BITS(8, 7, 2)
132 #define DW_CTLL_DST_DEC		SET_BITS(8, 7, 1)
133 #define DW_CTLL_DST_INC		SET_BITS(8, 7, 0)
134 #define DW_CTLL_SRC_WIDTH(x)	SET_BITS(6, 4, x)
135 #define DW_CTLL_DST_WIDTH(x)	SET_BITS(3, 1, x)
136 #define DW_CTLL_INT_EN		BIT(0)
137 #define DW_CTLL_SRC_WIDTH_MASK	MASK(6, 4)
138 #define DW_CTLL_SRC_WIDTH_SHIFT	4
139 #define DW_CTLL_DST_WIDTH_MASK	MASK(3, 1)
140 #define DW_CTLL_DST_WIDTH_SHIFT	1
141 
142 /* CTL_HI */
143 #define DW_CTLH_CLASS(x)	SET_BITS(31, 29, x)
144 #define DW_CTLH_WEIGHT(x)	SET_BITS(28, 18, x)
145 #define DW_CTLH_DONE(x)		SET_BIT(17, x)
146 #define DW_CTLH_BLOCK_TS_MASK	MASK(16, 0)
147 
148 /* DSR */
149 #define DW_DSR_DSC(x)		SET_BITS(31, 20, x)
150 #define DW_DSR_DSI(x)		SET_BITS(19, 0, x)
151 
152 /* FIFO_PART */
153 #define DW_FIFO_SIZE 0x80
154 #define DW_FIFO_UPD		BIT(26)
155 #define DW_FIFO_CHx(x)		SET_BITS(25, 13, x)
156 #define DW_FIFO_CHy(x)		SET_BITS(12, 0, x)
157 
158 /* number of tries to wait for reset */
159 #define DW_DMA_CFG_TRIES	10000
160 
161 /* channel drain timeout in microseconds */
162 #define DW_DMA_TIMEOUT	1333
163 
164 /* min number of elems for config with irq disabled */
165 #define DW_DMA_CFG_NO_IRQ_MIN_ELEMS	3
166 
167 #define DW_DMA_CHANNEL_REGISTER_OFFSET_END	0x50
168 #define DW_DMA_IP_REGISTER_OFFSET_END		0x418
169 #define DW_DMA_IP_REGISTER_OFFSET_START	0x2C0
170 
171 /* linked list item address */
172 #define DW_DMA_LLI_ADDRESS(lli, dir) \
173 	(((dir) == MEMORY_TO_PERIPHERAL) ? ((lli)->sar) : ((lli)->dar))
174 
175 /* TODO: add FIFO sizes */
176 struct dw_chan_arbit_data {
177 	uint16_t class;
178 	uint16_t weight;
179 };
180 
181 struct dw_drv_plat_data {
182 	struct dw_chan_arbit_data chan[DW_CHAN_COUNT];
183 };
184 
185 /* DMA descriptor used by HW */
186 struct dw_lli {
187 #ifdef CONFIG_DMA_64BIT
188 	uint64_t sar;
189 	uint64_t dar;
190 #else
191 	uint32_t sar;
192 	uint32_t dar;
193 #endif
194 	uint32_t llp;
195 	uint32_t ctrl_lo;
196 	uint32_t ctrl_hi;
197 	uint32_t sstat;
198 	uint32_t dstat;
199 
200 	/* align to 32 bytes to not cross cache line
201 	 * in case of more than two items
202 	 */
203 	uint32_t reserved;
204 } __packed;
205 
206 /* pointer data for DW DMA buffer */
207 struct dw_dma_ptr_data {
208 	uint32_t current_ptr;
209 	uint32_t start_ptr;
210 	uint32_t end_ptr;
211 	uint32_t hw_ptr;
212 	uint32_t buffer_bytes;
213 };
214 
215 /* State tracking for each channel */
216 enum dw_dma_state {
217 	DW_DMA_IDLE,
218 	DW_DMA_PREPARED,
219 	DW_DMA_SUSPENDED,
220 	DW_DMA_ACTIVE,
221 };
222 
223 /* data for each DMA channel */
224 struct dw_dma_chan_data {
225 	uint32_t direction;
226 	enum dw_dma_state state;
227 	struct dw_lli *lli; /* allocated array of LLI's */
228 	uint32_t lli_count; /* number of lli's in the allocation */
229 	struct dw_lli *lli_current; /* current LLI being used */
230 	uint32_t cfg_lo;
231 	uint32_t cfg_hi;
232 	struct dw_dma_ptr_data ptr_data;	/* pointer data */
233 	dma_callback_t dma_blkcallback;
234 	void *blkuser_data;
235 	dma_callback_t dma_tfrcallback;
236 	void *tfruser_data;
237 };
238 
239 /* use array to get burst_elems for specific slot number setting.
240  * the relation between msize and burst_elems should be
241  * 2 ^ msize = burst_elems
242  */
243 static const uint32_t burst_elems[] = {1, 2, 4, 8};
244 
245 /* Device run time data */
246 struct dw_dma_dev_data {
247 	struct dma_context dma_ctx;
248 	struct dw_drv_plat_data *channel_data;
249 	struct dw_dma_chan_data chan[DW_CHAN_COUNT];
250 	struct dw_lli lli_pool[DW_CHAN_COUNT][CONFIG_DMA_DW_LLI_POOL_SIZE] __aligned(64);
251 
252 	ATOMIC_DEFINE(channels_atomic, DW_CHAN_COUNT);
253 };
254 
255 /* Device constant configuration parameters */
256 struct dw_dma_dev_cfg {
257 	uintptr_t base;
258 	void (*irq_config)(void);
259 };
260 
dw_write(uintptr_t dma_base,uint32_t reg,uint32_t value)261 static ALWAYS_INLINE void dw_write(uintptr_t dma_base, uint32_t reg, uint32_t value)
262 {
263 	*((volatile uint32_t *)(dma_base + reg)) = value;
264 }
265 
dw_read(uintptr_t dma_base,uint32_t reg)266 static ALWAYS_INLINE uint32_t dw_read(uintptr_t dma_base, uint32_t reg)
267 {
268 	return *((volatile uint32_t *)(dma_base + reg));
269 }
270 
271 int dw_dma_setup(const struct device *dev);
272 
273 int dw_dma_config(const struct device *dev, uint32_t channel,
274 		  struct dma_config *cfg);
275 
276 int dw_dma_reload(const struct device *dev, uint32_t channel,
277 		  uint32_t src, uint32_t dst, size_t size);
278 
279 int dw_dma_start(const struct device *dev, uint32_t channel);
280 
281 int dw_dma_stop(const struct device *dev, uint32_t channel);
282 
283 int dw_dma_suspend(const struct device *dev, uint32_t channel);
284 
285 int dw_dma_resume(const struct device *dev, uint32_t channel);
286 
287 void dw_dma_isr(const struct device *dev);
288 
289 int dw_dma_get_status(const struct device *dev, uint32_t channel,
290 		      struct dma_status *stat);
291 
292 #ifdef __cplusplus
293 }
294 #endif
295 
296 #endif /* ZEPHYR_DRIVERS_DMA_DMA_DW_COMMON_H_ */
297