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