1 /*
2 * Copyright (c) 2023 Andes Technology Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <errno.h>
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <zephyr/init.h>
13 #include <zephyr/drivers/dma.h>
14
15 #define DT_DRV_COMPAT andestech_atcdmac300
16
17 #define LOG_LEVEL CONFIG_DMA_LOG_LEVEL
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(dma_andes_atcdmac300);
20
21 #define ATCDMAC100_MAX_CHAN 8
22
23 #define DMA_ABORT(dev) (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x24)
24 #define DMA_INT_STATUS(dev) \
25 (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x30)
26
27 #define DMA_CH_OFFSET(ch) (ch * 0x20)
28 #define DMA_CH_CTRL(dev, ch) \
29 (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x40 + DMA_CH_OFFSET(ch))
30 #define DMA_CH_TRANSIZE(dev, ch) \
31 (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x44 + DMA_CH_OFFSET(ch))
32 #define DMA_CH_SRC_ADDR_L(dev, ch) \
33 (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x48 + DMA_CH_OFFSET(ch))
34 #define DMA_CH_SRC_ADDR_H(dev, ch) \
35 (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x4C + DMA_CH_OFFSET(ch))
36 #define DMA_CH_DST_ADDR_L(dev, ch) \
37 (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x50 + DMA_CH_OFFSET(ch))
38 #define DMA_CH_DST_ADDR_H(dev, ch) \
39 (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x54 + DMA_CH_OFFSET(ch))
40 #define DMA_CH_LL_PTR_L(dev, ch) \
41 (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x58 + DMA_CH_OFFSET(ch))
42 #define DMA_CH_LL_PTR_H(dev, ch) \
43 (((struct dma_atcdmac300_cfg *)dev->config)->base + 0x5C + DMA_CH_OFFSET(ch))
44
45 /* Source burst size options */
46 #define DMA_BSIZE_1 (0)
47 #define DMA_BSIZE_2 (1)
48 #define DMA_BSIZE_4 (2)
49 #define DMA_BSIZE_8 (3)
50 #define DMA_BSIZE_16 (4)
51 #define DMA_BSIZE_32 (5)
52 #define DMA_BSIZE_64 (6)
53 #define DMA_BSIZE_128 (7)
54 #define DMA_BSIZE_256 (8)
55 #define DMA_BSIZE_512 (9)
56 #define DMA_BSIZE_1024 (10)
57
58 /* Source/Destination transfer width options */
59 #define DMA_WIDTH_BYTE (0)
60 #define DMA_WIDTH_HALFWORD (1)
61 #define DMA_WIDTH_WORD (2)
62 #define DMA_WIDTH_DWORD (3)
63 #define DMA_WIDTH_QWORD (4)
64 #define DMA_WIDTH_EWORD (5)
65
66 /* Bus interface index */
67 #define DMA_INF_IDX0 (0)
68 #define DMA_INF_IDX1 (1)
69
70 /* DMA Channel Control Register Definition */
71 #define DMA_CH_CTRL_SBINF_MASK BIT(31)
72 #define DMA_CH_CTRL_DBINF_MASK BIT(30)
73 #define DMA_CH_CTRL_PRIORITY_HIGH BIT(29)
74 #define DMA_CH_CTRL_SBSIZE_MASK GENMASK(27, 24)
75 #define DMA_CH_CTRL_SBSIZE(n) FIELD_PREP(DMA_CH_CTRL_SBSIZE_MASK, (n))
76 #define DMA_CH_CTRL_SWIDTH_MASK GENMASK(23, 21)
77 #define DMA_CH_CTRL_SWIDTH(n) FIELD_PREP(DMA_CH_CTRL_SWIDTH_MASK, (n))
78 #define DMA_CH_CTRL_DWIDTH_MASK GENMASK(20, 18)
79 #define DMA_CH_CTRL_DWIDTH(n) FIELD_PREP(DMA_CH_CTRL_DWIDTH_MASK, (n))
80 #define DMA_CH_CTRL_SMODE_HANDSHAKE BIT(17)
81 #define DMA_CH_CTRL_DMODE_HANDSHAKE BIT(16)
82 #define DMA_CH_CTRL_SRCADDRCTRL_MASK GENMASK(15, 14)
83 #define DMA_CH_CTRL_SRCADDR_INC FIELD_PREP(DMA_CH_CTRL_SRCADDRCTRL_MASK, (0))
84 #define DMA_CH_CTRL_SRCADDR_DEC FIELD_PREP(DMA_CH_CTRL_SRCADDRCTRL_MASK, (1))
85 #define DMA_CH_CTRL_SRCADDR_FIX FIELD_PREP(DMA_CH_CTRL_SRCADDRCTRL_MASK, (2))
86 #define DMA_CH_CTRL_DSTADDRCTRL_MASK GENMASK(13, 12)
87 #define DMA_CH_CTRL_DSTADDR_INC FIELD_PREP(DMA_CH_CTRL_DSTADDRCTRL_MASK, (0))
88 #define DMA_CH_CTRL_DSTADDR_DEC FIELD_PREP(DMA_CH_CTRL_DSTADDRCTRL_MASK, (1))
89 #define DMA_CH_CTRL_DSTADDR_FIX FIELD_PREP(DMA_CH_CTRL_DSTADDRCTRL_MASK, (2))
90 #define DMA_CH_CTRL_SRCREQ_MASK GENMASK(11, 8)
91 #define DMA_CH_CTRL_SRCREQ(n) FIELD_PREP(DMA_CH_CTRL_SRCREQ_MASK, (n))
92 #define DMA_CH_CTRL_DSTREQ_MASK GENMASK(7, 4)
93 #define DMA_CH_CTRL_DSTREQ(n) FIELD_PREP(DMA_CH_CTRL_DSTREQ_MASK, (n))
94 #define DMA_CH_CTRL_INTABT BIT(3)
95 #define DMA_CH_CTRL_INTERR BIT(2)
96 #define DMA_CH_CTRL_INTTC BIT(1)
97 #define DMA_CH_CTRL_ENABLE BIT(0)
98
99 /* DMA Interrupt Status Register Definition */
100 #define DMA_INT_STATUS_TC_MASK GENMASK(23, 16)
101 #define DMA_INT_STATUS_ABORT_MASK GENMASK(15, 8)
102 #define DMA_INT_STATUS_ERROR_MASK GENMASK(7, 0)
103 #define DMA_INT_STATUS_TC_VAL(x) FIELD_GET(DMA_INT_STATUS_TC_MASK, (x))
104 #define DMA_INT_STATUS_ABORT_VAL(x) FIELD_GET(DMA_INT_STATUS_ABORT_MASK, (x))
105 #define DMA_INT_STATUS_ERROR_VAL(x) FIELD_GET(DMA_INT_STATUS_ERROR_MASK, (x))
106 #define DMA_INT_STATUS_CH_MSK(ch) (0x111 << ch)
107
108 typedef void (*atcdmac300_cfg_func_t)(void);
109
110 struct chain_block {
111 uint32_t ctrl;
112 uint32_t transize;
113 uint32_t srcaddrl;
114 uint32_t srcaddrh;
115 uint32_t dstaddrl;
116 uint32_t dstaddrh;
117 uint32_t llpointerl;
118 uint32_t llpointerh;
119 #if __riscv_xlen == 32
120 uint32_t reserved;
121 #endif
122 struct chain_block *next_block;
123 };
124
125 /* data for each DMA channel */
126 struct dma_chan_data {
127 void *blkuser_data;
128 dma_callback_t blkcallback;
129 struct chain_block *head_block;
130 struct dma_status status;
131 };
132
133 /* Device run time data */
134 struct dma_atcdmac300_data {
135 struct dma_chan_data chan[ATCDMAC100_MAX_CHAN];
136 struct k_spinlock lock;
137 };
138
139 /* Device constant configuration parameters */
140 struct dma_atcdmac300_cfg {
141 atcdmac300_cfg_func_t irq_config;
142 uint32_t base;
143 uint32_t irq_num;
144 };
145
146 static struct __aligned(64)
147 chain_block dma_chain[ATCDMAC100_MAX_CHAN][sizeof(struct chain_block) * 16];
148
dma_atcdmac300_isr(const struct device * dev)149 static void dma_atcdmac300_isr(const struct device *dev)
150 {
151 uint32_t int_status, int_ch_status, channel;
152 struct dma_atcdmac300_data *const data = dev->data;
153 struct dma_chan_data *ch_data;
154 k_spinlock_key_t key;
155
156 key = k_spin_lock(&data->lock);
157 int_status = sys_read32(DMA_INT_STATUS(dev));
158 /* Clear interrupt*/
159 sys_write32(int_status, DMA_INT_STATUS(dev));
160
161 k_spin_unlock(&data->lock, key);
162
163 /* Handle terminal count status */
164 int_ch_status = DMA_INT_STATUS_TC_VAL(int_status);
165 while (int_ch_status) {
166 channel = find_msb_set(int_ch_status) - 1;
167 int_ch_status &= ~(BIT(channel));
168
169 ch_data = &data->chan[channel];
170 if (ch_data->blkcallback) {
171 ch_data->blkcallback(dev, ch_data->blkuser_data, channel, 0);
172 }
173 data->chan[channel].status.busy = false;
174 }
175
176 /* Handle error status */
177 int_ch_status = DMA_INT_STATUS_ERROR_VAL(int_status);
178 while (int_ch_status) {
179 channel = find_msb_set(int_ch_status) - 1;
180 int_ch_status &= ~(BIT(channel));
181
182 ch_data = &data->chan[channel];
183 if (ch_data->blkcallback) {
184 ch_data->blkcallback(dev, ch_data->blkuser_data, channel, -EIO);
185 }
186 }
187 }
188
dma_atcdmac300_config(const struct device * dev,uint32_t channel,struct dma_config * cfg)189 static int dma_atcdmac300_config(const struct device *dev, uint32_t channel,
190 struct dma_config *cfg)
191 {
192 struct dma_atcdmac300_data *const data = dev->data;
193 uint32_t src_width, dst_width, src_burst_size, ch_ctrl, tfr_size;
194 int32_t ret = 0;
195 struct dma_block_config *cfg_blocks;
196 k_spinlock_key_t key;
197
198 if (channel >= ATCDMAC100_MAX_CHAN) {
199 return -EINVAL;
200 }
201
202 __ASSERT_NO_MSG(cfg->source_data_size == cfg->dest_data_size);
203 __ASSERT_NO_MSG(cfg->source_burst_length == cfg->dest_burst_length);
204
205 if (cfg->source_data_size != 1 && cfg->source_data_size != 2 &&
206 cfg->source_data_size != 4) {
207 LOG_ERR("Invalid 'source_data_size' value");
208 ret = -EINVAL;
209 goto end;
210 }
211
212 cfg_blocks = cfg->head_block;
213 if (cfg_blocks == NULL) {
214 ret = -EINVAL;
215 goto end;
216 }
217
218 tfr_size = cfg_blocks->block_size/cfg->source_data_size;
219 if (tfr_size == 0) {
220 ret = -EINVAL;
221 goto end;
222 }
223
224 ch_ctrl = 0;
225
226 switch (cfg->channel_direction) {
227 case MEMORY_TO_MEMORY:
228 break;
229 case MEMORY_TO_PERIPHERAL:
230 ch_ctrl |= DMA_CH_CTRL_DSTREQ(cfg->dma_slot);
231 ch_ctrl |= DMA_CH_CTRL_DMODE_HANDSHAKE;
232 break;
233 case PERIPHERAL_TO_MEMORY:
234 ch_ctrl |= DMA_CH_CTRL_SRCREQ(cfg->dma_slot);
235 ch_ctrl |= DMA_CH_CTRL_SMODE_HANDSHAKE;
236 break;
237 default:
238 ret = -EINVAL;
239 goto end;
240 }
241
242
243 switch (cfg_blocks->source_addr_adj) {
244 case DMA_ADDR_ADJ_INCREMENT:
245 ch_ctrl |= DMA_CH_CTRL_SRCADDR_INC;
246 break;
247 case DMA_ADDR_ADJ_DECREMENT:
248 ch_ctrl |= DMA_CH_CTRL_SRCADDR_DEC;
249 break;
250 case DMA_ADDR_ADJ_NO_CHANGE:
251 ch_ctrl |= DMA_CH_CTRL_SRCADDR_FIX;
252 break;
253 default:
254 ret = -EINVAL;
255 goto end;
256 }
257
258 switch (cfg_blocks->dest_addr_adj) {
259 case DMA_ADDR_ADJ_INCREMENT:
260 ch_ctrl |= DMA_CH_CTRL_DSTADDR_INC;
261 break;
262 case DMA_ADDR_ADJ_DECREMENT:
263 ch_ctrl |= DMA_CH_CTRL_DSTADDR_DEC;
264 break;
265 case DMA_ADDR_ADJ_NO_CHANGE:
266 ch_ctrl |= DMA_CH_CTRL_DSTADDR_FIX;
267 break;
268 default:
269 ret = -EINVAL;
270 goto end;
271 }
272
273 ch_ctrl |= DMA_CH_CTRL_INTABT;
274
275 /* Disable the error callback */
276 if (!cfg->error_callback_dis) {
277 ch_ctrl |= DMA_CH_CTRL_INTERR;
278 }
279
280 src_width = find_msb_set(cfg->source_data_size) - 1;
281 dst_width = find_msb_set(cfg->dest_data_size) - 1;
282 src_burst_size = find_msb_set(cfg->source_burst_length) - 1;
283
284 ch_ctrl |= DMA_CH_CTRL_SWIDTH(src_width) |
285 DMA_CH_CTRL_DWIDTH(dst_width) |
286 DMA_CH_CTRL_SBSIZE(src_burst_size);
287
288
289 /* Reset DMA channel configuration */
290 sys_write32(0, DMA_CH_CTRL(dev, channel));
291
292 key = k_spin_lock(&data->lock);
293 /* Clear DMA interrupts status */
294 sys_write32(DMA_INT_STATUS_CH_MSK(channel), DMA_INT_STATUS(dev));
295 k_spin_unlock(&data->lock, key);
296
297 /* Set transfer size */
298 sys_write32(tfr_size, DMA_CH_TRANSIZE(dev, channel));
299
300 /* Update the status of channel */
301 data->chan[channel].status.dir = cfg->channel_direction;
302 data->chan[channel].status.pending_length = cfg->source_data_size;
303
304 /* Configure a callback appropriately depending on whether the
305 * interrupt is requested at the end of transaction completion or
306 * at the end of each block.
307 */
308 data->chan[channel].blkcallback = cfg->dma_callback;
309 data->chan[channel].blkuser_data = cfg->user_data;
310
311 sys_write32(ch_ctrl, DMA_CH_CTRL(dev, channel));
312
313 /* Set source and destination address */
314 sys_write32(cfg_blocks->source_address,
315 DMA_CH_SRC_ADDR_L(dev, channel));
316 sys_write32(0, DMA_CH_SRC_ADDR_H(dev, channel));
317 sys_write32(cfg_blocks->dest_address,
318 DMA_CH_DST_ADDR_L(dev, channel));
319 sys_write32(0, DMA_CH_DST_ADDR_H(dev, channel));
320
321 if (cfg->dest_chaining_en == 1 && cfg_blocks->next_block) {
322 uint32_t current_block_idx = 0;
323
324 sys_write32((uint32_t)((long)&dma_chain[channel][current_block_idx]),
325 DMA_CH_LL_PTR_L(dev, channel));
326 sys_write32(0, DMA_CH_LL_PTR_H(dev, channel));
327
328 for (cfg_blocks = cfg_blocks->next_block; cfg_blocks != NULL;
329 cfg_blocks = cfg_blocks->next_block) {
330
331 ch_ctrl &= ~(DMA_CH_CTRL_SRCADDRCTRL_MASK |
332 DMA_CH_CTRL_DSTADDRCTRL_MASK);
333
334 switch (cfg_blocks->source_addr_adj) {
335 case DMA_ADDR_ADJ_INCREMENT:
336 ch_ctrl |= DMA_CH_CTRL_SRCADDR_INC;
337 break;
338 case DMA_ADDR_ADJ_DECREMENT:
339 ch_ctrl |= DMA_CH_CTRL_SRCADDR_DEC;
340 break;
341 case DMA_ADDR_ADJ_NO_CHANGE:
342 ch_ctrl |= DMA_CH_CTRL_SRCADDR_FIX;
343 break;
344 default:
345 ret = -EINVAL;
346 goto end;
347 }
348
349 switch (cfg_blocks->dest_addr_adj) {
350 case DMA_ADDR_ADJ_INCREMENT:
351 ch_ctrl |= DMA_CH_CTRL_DSTADDR_INC;
352 break;
353 case DMA_ADDR_ADJ_DECREMENT:
354 ch_ctrl |= DMA_CH_CTRL_DSTADDR_DEC;
355 break;
356 case DMA_ADDR_ADJ_NO_CHANGE:
357 ch_ctrl |= DMA_CH_CTRL_DSTADDR_FIX;
358 break;
359 default:
360 ret = -EINVAL;
361 goto end;
362 }
363 dma_chain[channel][current_block_idx].ctrl = ch_ctrl;
364 dma_chain[channel][current_block_idx].transize =
365 cfg_blocks->block_size/cfg->source_data_size;
366
367 dma_chain[channel][current_block_idx].srcaddrl =
368 (uint32_t)cfg_blocks->source_address;
369 dma_chain[channel][current_block_idx].srcaddrh = 0x0;
370
371 dma_chain[channel][current_block_idx].dstaddrl =
372 (uint32_t)((long)cfg_blocks->dest_address);
373 dma_chain[channel][current_block_idx].dstaddrh = 0x0;
374
375 if (cfg_blocks->next_block) {
376 dma_chain[channel][current_block_idx].llpointerl =
377 (uint32_t)&dma_chain[channel][current_block_idx + 1];
378 dma_chain[channel][current_block_idx].llpointerh = 0x0;
379
380 current_block_idx = current_block_idx + 1;
381
382 } else {
383 dma_chain[channel][current_block_idx].llpointerl = 0x0;
384 dma_chain[channel][current_block_idx].llpointerh = 0x0;
385 dma_chain[channel][current_block_idx].next_block = NULL;
386 }
387 }
388 } else {
389 /* Single transfer is supported, but Chain transfer is still
390 * not supported. Therefore, set LLPointer to zero
391 */
392 sys_write32(0, DMA_CH_LL_PTR_L(dev, channel));
393 sys_write32(0, DMA_CH_LL_PTR_H(dev, channel));
394 }
395
396 end:
397 return ret;
398 }
399
dma_atcdmac300_reload(const struct device * dev,uint32_t channel,uint32_t src,uint32_t dst,size_t size)400 static int dma_atcdmac300_reload(const struct device *dev, uint32_t channel,
401 uint32_t src, uint32_t dst, size_t size)
402 {
403 uint32_t src_width;
404
405 if (channel >= ATCDMAC100_MAX_CHAN) {
406 return -EINVAL;
407 }
408
409 /* Set source and destination address */
410 sys_write32(src, DMA_CH_SRC_ADDR_L(dev, channel));
411 sys_write32(0, DMA_CH_SRC_ADDR_H(dev, channel));
412 sys_write32(dst, DMA_CH_DST_ADDR_L(dev, channel));
413 sys_write32(0, DMA_CH_DST_ADDR_H(dev, channel));
414
415 src_width = FIELD_GET(DMA_CH_CTRL_SWIDTH_MASK, sys_read32(DMA_CH_CTRL(dev, channel)));
416 src_width = BIT(src_width);
417
418 /* Set transfer size */
419 sys_write32(size/src_width, DMA_CH_TRANSIZE(dev, channel));
420
421 return 0;
422 }
423
dma_atcdmac300_transfer_start(const struct device * dev,uint32_t channel)424 static int dma_atcdmac300_transfer_start(const struct device *dev,
425 uint32_t channel)
426 {
427 struct dma_atcdmac300_data *const data = dev->data;
428
429 if (channel >= ATCDMAC100_MAX_CHAN) {
430 return -EINVAL;
431 }
432
433 sys_write32(sys_read32(DMA_CH_CTRL(dev, channel)) | DMA_CH_CTRL_ENABLE,
434 DMA_CH_CTRL(dev, channel));
435
436 data->chan[channel].status.busy = true;
437
438 return 0;
439 }
440
dma_atcdmac300_transfer_stop(const struct device * dev,uint32_t channel)441 static int dma_atcdmac300_transfer_stop(const struct device *dev,
442 uint32_t channel)
443 {
444 struct dma_atcdmac300_data *const data = dev->data;
445 k_spinlock_key_t key;
446
447 if (channel >= ATCDMAC100_MAX_CHAN) {
448 return -EINVAL;
449 }
450
451 key = k_spin_lock(&data->lock);
452
453 sys_write32(BIT(channel), DMA_ABORT(dev));
454 sys_write32(0, DMA_CH_CTRL(dev, channel));
455 sys_write32(FIELD_GET(DMA_INT_STATUS_ABORT_MASK, (channel)), DMA_INT_STATUS(dev));
456 data->chan[channel].status.busy = false;
457
458 k_spin_unlock(&data->lock, key);
459
460 return 0;
461 }
462
dma_atcdmac300_init(const struct device * dev)463 static int dma_atcdmac300_init(const struct device *dev)
464 {
465 const struct dma_atcdmac300_cfg *const config = (struct dma_atcdmac300_cfg *)dev->config;
466 uint32_t ch_num;
467
468 /* Disable all channels and Channel interrupts */
469 for (ch_num = 0; ch_num < ATCDMAC100_MAX_CHAN; ch_num++) {
470 sys_write32(0, DMA_CH_CTRL(dev, ch_num));
471 }
472
473 sys_write32(0xFFFFFF, DMA_INT_STATUS(dev));
474
475 /* Configure interrupts */
476 config->irq_config();
477
478 irq_enable(config->irq_num);
479
480 return 0;
481 }
482
dma_atcdmac300_get_status(const struct device * dev,uint32_t channel,struct dma_status * stat)483 static int dma_atcdmac300_get_status(const struct device *dev,
484 uint32_t channel,
485 struct dma_status *stat)
486 {
487 struct dma_atcdmac300_data *const data = dev->data;
488
489 stat->busy = data->chan[channel].status.busy;
490 stat->dir = data->chan[channel].status.dir;
491 stat->pending_length = data->chan[channel].status.pending_length;
492
493 return 0;
494 }
495
496 static const struct dma_driver_api dma_atcdmac300_api = {
497 .config = dma_atcdmac300_config,
498 .reload = dma_atcdmac300_reload,
499 .start = dma_atcdmac300_transfer_start,
500 .stop = dma_atcdmac300_transfer_stop,
501 .get_status = dma_atcdmac300_get_status
502 };
503
504 #define ATCDMAC300_INIT(n) \
505 \
506 static void dma_atcdmac300_irq_config_##n(void); \
507 \
508 static const struct dma_atcdmac300_cfg dma_config_##n = { \
509 .irq_config = dma_atcdmac300_irq_config_##n, \
510 .base = DT_INST_REG_ADDR(n), \
511 .irq_num = DT_INST_IRQN(n), \
512 }; \
513 \
514 static struct dma_atcdmac300_data dma_data_##n; \
515 \
516 DEVICE_DT_INST_DEFINE(0, \
517 dma_atcdmac300_init, \
518 NULL, \
519 &dma_data_##n, \
520 &dma_config_##n, \
521 POST_KERNEL, \
522 CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
523 &dma_atcdmac300_api); \
524 \
525 static void dma_atcdmac300_irq_config_##n(void) \
526 { \
527 IRQ_CONNECT(DT_INST_IRQN(n), \
528 1, \
529 dma_atcdmac300_isr, \
530 DEVICE_DT_INST_GET(n), \
531 0); \
532 }
533
534
535 DT_INST_FOREACH_STATUS_OKAY(ATCDMAC300_INIT)
536