1 /*
2 * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "plat_addr_map.h"
16 #include "cmsis_nvic.h"
17 #include "hal_chipid.h"
18 #include "hal_cmu.h"
19 #include "hal_dma.h"
20 #include "hal_location.h"
21 #include "hal_timer.h"
22 #include "hal_trace.h"
23 #include "reg_dma.h"
24
25 #if (defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST2300)) && !(defined(ROM_BUILD) || defined(PROGRAMMER))
26 #define DMA_REMAP
27 #endif
28
29 #if (defined(CHIP_BEST1501SIMU) && !defined(__FPGA_1501P__)) || defined(CHIP_BEST1600SIMU)
30 enum HAL_DMA_INST_T {
31 HAL_DMA_INST_AUDMA = 1,
32 HAL_DMA_INST_GPDMA = HAL_DMA_INST_AUDMA,
33 HAL_DMA_INST_QTY
34 };
35 #else
36 enum HAL_DMA_INST_T {
37 HAL_DMA_INST_AUDMA = 0,
38 #if (CHIP_HAS_DMA == 1)
39 HAL_DMA_INST_GPDMA = HAL_DMA_INST_AUDMA,
40 #else
41 HAL_DMA_INST_GPDMA,
42 #endif
43
44 HAL_DMA_INST_QTY
45 };
46 #endif
47
48 struct HAL_DMA_FIFO_ADDR_T {
49 uint32_t count;
50 const uint32_t *addr;
51 };
52
53 struct HAL_DMA_FIFO_PERIPH_T {
54 uint32_t count;
55 const enum HAL_DMA_PERIPH_T *periph;
56 #ifdef DMA_REMAP
57 const enum HAL_DMA_PERIPH_T *periph_remap;
58 #endif
59 };
60
61 /*****************************************************************************
62 * Private types/enumerations/variables
63 ****************************************************************************/
64
65 #include CHIP_SPECIFIC_HDR(hal_dmacfg)
66
67 static struct DMA_T * const dma[HAL_DMA_INST_QTY] = {
68 (struct DMA_T *)AUDMA_BASE,
69 #if (CHIP_HAS_DMA > 1)
70 (struct DMA_T *)GPDMA_BASE,
71 #endif
72 };
73
74 static const IRQn_Type irq_type[HAL_DMA_INST_QTY] = {
75 AUDMA_IRQn,
76 #if (CHIP_HAS_DMA > 1)
77 GPDMA_IRQn,
78 #endif
79 };
80
81 static void hal_audma_irq_handler(void);
82 #if (CHIP_HAS_DMA > 1)
83 static void hal_gpdma_irq_handler(void);
84 #endif
85
86 static const uint32_t irq_entry[HAL_DMA_INST_QTY] = {
87 (uint32_t)hal_audma_irq_handler,
88 #if (CHIP_HAS_DMA > 1)
89 (uint32_t)hal_gpdma_irq_handler,
90 #endif
91 };
92
93 static const struct HAL_DMA_FIFO_ADDR_T fifo_addr[HAL_DMA_INST_QTY] = {
94 {
95 .count = ARRAY_SIZE(audma_fifo_addr),
96 .addr = audma_fifo_addr,
97 },
98 #if (CHIP_HAS_DMA > 1)
99 {
100 .count = ARRAY_SIZE(gpdma_fifo_addr),
101 .addr = gpdma_fifo_addr,
102 },
103 #endif
104 };
105
106 static const struct HAL_DMA_FIFO_PERIPH_T fifo_periph[HAL_DMA_INST_QTY] = {
107 {
108 .count = ARRAY_SIZE(audma_fifo_periph),
109 .periph = audma_fifo_periph,
110 #ifdef DMA_REMAP
111 .periph_remap = audma_fifo_periph_remap,
112 #endif
113 },
114 #if (CHIP_HAS_DMA > 1)
115 {
116 .count = ARRAY_SIZE(gpdma_fifo_periph),
117 .periph = gpdma_fifo_periph,
118 #ifdef DMA_REMAP
119 .periph_remap = gpdma_fifo_periph_remap,
120 #endif
121 },
122 #endif
123 };
124
125 static const uint8_t chan_start[HAL_DMA_INST_QTY] = {
126 AUDMA_CHAN_START,
127 #if (CHIP_HAS_DMA > 1)
128 GPDMA_CHAN_START,
129 #endif
130 };
131
132 static const uint8_t chan_num[HAL_DMA_INST_QTY] = {
133 AUDMA_CHAN_NUM,
134 #if (CHIP_HAS_DMA > 1)
135 GPDMA_CHAN_NUM,
136 #endif
137 };
138
139 /* Channel array to monitor free channel */
140 static bool chan_enabled[HAL_DMA_INST_QTY][DMA_NUMBER_CHANNELS];
141
142 static HAL_DMA_IRQ_HANDLER_T handler[HAL_DMA_INST_QTY][DMA_NUMBER_CHANNELS];
143
144 #ifdef DMA_REMAP
145 static uint32_t periph_remap_bitmap[HAL_DMA_INST_QTY];
146 #endif
147
148 #ifdef CORE_SLEEP_POWER_DOWN
149 static uint32_t saved_dma_regs[HAL_DMA_INST_QTY];
150 #endif
151
152 static const char * const err_invalid_inst = "Invalid DMA inst: %u";
153
154 static const char * const err_invalid_chan[HAL_DMA_INST_QTY] = {
155 "Invalid AUDMA chan: %u",
156 #if (CHIP_HAS_DMA > 1)
157 "Invalid GPDMA chan: %u",
158 #endif
159 };
160
161 static bool dma_opened = false;
162
163 static HAL_DMA_DELAY_FUNC dma_delay = NULL;
164
165 #ifdef DMA_DEBUG
166 #if (CHIP_HAS_DMA > 1) && (GPDMA_CHAN_NUM > AUDMA_CHAN_NUM)
167 #define MAX_CHAN_NUM_PER_INST GPDMA_CHAN_NUM
168 #else
169 #define MAX_CHAN_NUM_PER_INST AUDMA_CHAN_NUM
170 #endif
171 static void *chan_user[HAL_DMA_INST_QTY][MAX_CHAN_NUM_PER_INST];
172 static uint32_t debug_user_map[HAL_DMA_INST_QTY];
173 STATIC_ASSERT(sizeof(debug_user_map[0]) * 8 >= MAX_CHAN_NUM_PER_INST, "debug_user_map size too small");
174 #endif
175
176 /*****************************************************************************
177 * Public types/enumerations/variables
178 ****************************************************************************/
179
180 /*****************************************************************************
181 * Private functions
182 ****************************************************************************/
hal_dma_delay(uint32_t ms)183 static void hal_dma_delay(uint32_t ms)
184 {
185 if (dma_delay && !in_isr()) {
186 dma_delay(ms);
187 } else {
188 hal_sys_timer_delay(MS_TO_TICKS(ms));
189 }
190 }
191
generate_chan(enum HAL_DMA_INST_T inst,uint8_t hwch)192 static inline uint8_t generate_chan(enum HAL_DMA_INST_T inst, uint8_t hwch)
193 {
194 return ((inst << 4) | (hwch & 0xF));
195 }
196
get_inst_from_chan(uint8_t ch)197 static inline enum HAL_DMA_INST_T get_inst_from_chan(uint8_t ch)
198 {
199 return (enum HAL_DMA_INST_T)(ch >> 4);
200 }
201
get_hwch_from_chan(uint8_t ch)202 static inline uint8_t get_hwch_from_chan(uint8_t ch)
203 {
204 return (ch & 0xF);
205 }
206
get_index_from_periph(enum HAL_DMA_PERIPH_T periph,enum HAL_DMA_INST_T * pinst,uint8_t * pidx)207 static inline int get_index_from_periph(enum HAL_DMA_PERIPH_T periph, enum HAL_DMA_INST_T *pinst, uint8_t *pidx)
208 {
209 enum HAL_DMA_INST_T inst;
210 int i;
211
212 for (inst = 0; inst < HAL_DMA_INST_QTY; inst++) {
213 for (i = 0; i < fifo_periph[inst].count; i++) {
214 if (fifo_periph[inst].periph[i] == periph) {
215 *pinst = inst;
216 *pidx = i;
217 return 0;
218 }
219 }
220 }
221
222 return 1;
223 }
224
225 #ifdef DMA_REMAP
get_remap_index_from_periph(enum HAL_DMA_INST_T inst,enum HAL_DMA_PERIPH_T periph,uint8_t * pidx)226 static inline int get_remap_index_from_periph(enum HAL_DMA_INST_T inst, enum HAL_DMA_PERIPH_T periph, uint8_t *pidx)
227 {
228 int i;
229
230 if (fifo_periph[inst].periph_remap == NULL) {
231 return 1;
232 }
233
234 for (i = 0; i < fifo_periph[inst].count; i++) {
235 if (fifo_periph[inst].periph_remap[i] == periph) {
236 *pidx = i;
237 return 0;
238 }
239 }
240
241 return 2;
242 }
243 #endif
244
hal_dma_get_periph_addr(enum HAL_DMA_PERIPH_T periph)245 static inline uint32_t hal_dma_get_periph_addr(enum HAL_DMA_PERIPH_T periph)
246 {
247 int ret;
248 enum HAL_DMA_INST_T inst;
249 uint8_t index;
250
251 ret = get_index_from_periph(periph, &inst, &index);
252 if (ret) {
253 return 0;
254 }
255
256 return fifo_addr[inst].addr[index];
257 }
258
259 /* Initialize the DMA */
hal_dma_open_inst(enum HAL_DMA_INST_T inst)260 static void hal_dma_open_inst(enum HAL_DMA_INST_T inst)
261 {
262 uint8_t i;
263
264 /* Reset all channel configuration register */
265 for (i = 0; i < DMA_NUMBER_CHANNELS; i++) {
266 dma[inst]->CH[i].CONFIG = 0;
267 }
268
269 /* Clear all DMA interrupt and error flag */
270 dma[inst]->INTTCCLR = ~0UL;
271 dma[inst]->INTERRCLR = ~0UL;
272
273 dma[inst]->DMACONFIG = (dma[inst]->DMACONFIG & ~(DMA_DMACONFIG_AHB1_BIGENDIAN |
274 DMA_DMACONFIG_AHB2_BIGENDIAN | DMA_DMACONFIG_CLK_EN_MASK)) |
275 DMA_DMACONFIG_EN | DMA_DMACONFIG_CROSS_1KB_EN |
276 #ifdef CHIP_BEST3001
277 DMA_DMACONFIG_TC_IRQ_EN_MASK |
278 #endif
279 0;
280
281 #ifdef CHIP_BEST1400
282 dma[inst]->DMACONFIG &= ~DMA_DMACONFIG_TC_IRQ_EN_MASK;
283 #endif
284
285 /* Reset all channels are free */
286 for (i = 0; i < DMA_NUMBER_CHANNELS; i++) {
287 chan_enabled[inst][i] = false;
288 }
289
290 NVIC_SetVector(irq_type[inst], irq_entry[inst]);
291 if (inst == HAL_DMA_INST_AUDMA) {
292 NVIC_SetPriority(irq_type[inst], IRQ_PRIORITY_ABOVENORMAL);
293 } else {
294 NVIC_SetPriority(irq_type[inst], IRQ_PRIORITY_NORMAL);
295 }
296 NVIC_ClearPendingIRQ(irq_type[inst]);
297 NVIC_EnableIRQ(irq_type[inst]);
298 }
299
300 /* Shutdown the DMA */
hal_dma_close_inst(enum HAL_DMA_INST_T inst)301 static void hal_dma_close_inst(enum HAL_DMA_INST_T inst)
302 {
303 NVIC_DisableIRQ(irq_type[inst]);
304 dma[inst]->DMACONFIG = 0;
305 }
306
hal_dma_chan_busy_inst(enum HAL_DMA_INST_T inst,uint8_t hwch)307 static bool hal_dma_chan_busy_inst(enum HAL_DMA_INST_T inst, uint8_t hwch)
308 {
309 return !!(dma[inst]->ENBLDCHNS & DMA_STAT_CHAN(hwch));
310 }
311
hal_dma_handle_chan_irq(enum HAL_DMA_INST_T inst,uint8_t hwch)312 static void hal_dma_handle_chan_irq(enum HAL_DMA_INST_T inst, uint8_t hwch)
313 {
314 uint32_t remains;
315 struct HAL_DMA_DESC_T *lli;
316 bool tcint, errint;
317
318 /* Check counter terminal status */
319 tcint = !!(dma[inst]->INTTCSTAT & DMA_STAT_CHAN(hwch));
320 /* Check error terminal status */
321 errint = !!(dma[inst]->INTERRSTAT & DMA_STAT_CHAN(hwch));
322
323 if (tcint || errint) {
324 if (tcint) {
325 /* Clear terminate counter Interrupt pending */
326 dma[inst]->INTTCCLR = DMA_STAT_CHAN(hwch);
327 }
328 if (errint) {
329 /* Clear error counter Interrupt pending */
330 dma[inst]->INTERRCLR = DMA_STAT_CHAN(hwch);
331 }
332
333 if (handler[inst][hwch]) {
334 remains = GET_BITFIELD(dma[inst]->CH[hwch].CONTROL, DMA_CONTROL_TRANSFERSIZE);
335 lli = (struct HAL_DMA_DESC_T *)dma[inst]->CH[hwch].LLI;
336 handler[inst][hwch](generate_chan(inst, hwch), remains, errint, lli);
337 }
338 }
339 }
340
hal_dma_irq_handler(enum HAL_DMA_INST_T inst)341 static void hal_dma_irq_handler(enum HAL_DMA_INST_T inst)
342 {
343 uint8_t hwch;
344
345 for (hwch = 0; hwch < DMA_NUMBER_CHANNELS; hwch++) {
346 if ((dma[inst]->INTSTAT & DMA_STAT_CHAN(hwch)) == 0) {
347 continue;
348 }
349 hal_dma_handle_chan_irq(inst, hwch);
350 }
351 }
352
hal_audma_irq_handler(void)353 static void hal_audma_irq_handler(void)
354 {
355 hal_dma_irq_handler(HAL_DMA_INST_AUDMA);
356 }
357
358 #if (CHIP_HAS_DMA > 1)
hal_gpdma_irq_handler(void)359 static void hal_gpdma_irq_handler(void)
360 {
361 hal_dma_irq_handler(HAL_DMA_INST_GPDMA);
362 }
363 #endif
364
hal_dma_init_control(uint32_t * ctrl,const struct HAL_DMA_CH_CFG_T * cfg,int tc_irq)365 static enum HAL_DMA_RET_T hal_dma_init_control(uint32_t *ctrl,
366 const struct HAL_DMA_CH_CFG_T *cfg,
367 int tc_irq)
368 {
369 uint32_t addr_inc;
370 enum HAL_DMA_FLOW_CONTROL_T type;
371
372 if (cfg->src_tsize > HAL_DMA_MAX_DESC_XFER_SIZE) {
373 return HAL_DMA_ERR;
374 }
375
376 #ifdef CHIP_BEST1000
377 type = cfg->type;
378 #else
379 type = cfg->type & ~HAL_DMA_FLOW_FLAG_MASK;
380 #endif
381
382 switch (type) {
383 case HAL_DMA_FLOW_M2M_DMA:
384 addr_inc = DMA_CONTROL_SI | DMA_CONTROL_DI;
385 break;
386 case HAL_DMA_FLOW_M2P_DMA:
387 case HAL_DMA_FLOW_M2P_PERIPH:
388 addr_inc = DMA_CONTROL_SI;
389 break;
390 case HAL_DMA_FLOW_P2M_DMA:
391 case HAL_DMA_FLOW_P2M_PERIPH:
392 addr_inc = DMA_CONTROL_DI;
393 break;
394 case HAL_DMA_FLOW_P2P_DMA:
395 case HAL_DMA_FLOW_P2P_DSTPERIPH:
396 case HAL_DMA_FLOW_P2P_SRCPERIPH:
397 addr_inc = 0;
398 break;
399 default:
400 return HAL_DMA_ERR;
401 }
402
403 #ifndef CHIP_BEST1000
404 if (cfg->type & HAL_DMA_FLOW_FLAG_SI) {
405 addr_inc |= DMA_CONTROL_SI;
406 }
407 if (cfg->type & HAL_DMA_FLOW_FLAG_DI) {
408 addr_inc |= DMA_CONTROL_DI;
409 }
410 #endif
411
412 *ctrl = DMA_CONTROL_TRANSFERSIZE(cfg->src_tsize) |
413 DMA_CONTROL_SBSIZE(cfg->src_bsize) |
414 DMA_CONTROL_DBSIZE(cfg->dst_bsize) |
415 DMA_CONTROL_SWIDTH(cfg->src_width) |
416 DMA_CONTROL_DWIDTH(cfg->dst_width) |
417 (tc_irq ? DMA_CONTROL_TC_IRQ : 0) |
418 addr_inc;
419
420 return HAL_DMA_OK;
421 }
422
423 /*****************************************************************************
424 * Generic Public functions
425 ****************************************************************************/
426
hal_dma_init_desc(struct HAL_DMA_DESC_T * desc,const struct HAL_DMA_CH_CFG_T * cfg,const struct HAL_DMA_DESC_T * next,int tc_irq)427 enum HAL_DMA_RET_T hal_dma_init_desc(struct HAL_DMA_DESC_T *desc,
428 const struct HAL_DMA_CH_CFG_T *cfg,
429 const struct HAL_DMA_DESC_T *next,
430 int tc_irq)
431 {
432 uint32_t ctrl;
433 enum HAL_DMA_RET_T ret;
434 enum HAL_DMA_FLOW_CONTROL_T type;
435
436 ret = hal_dma_init_control(&ctrl, cfg, tc_irq);
437 if (ret != HAL_DMA_OK) {
438 return ret;
439 }
440
441 #ifdef CHIP_BEST1000
442 type = cfg->type;
443 #else
444 type = cfg->type & ~HAL_DMA_FLOW_FLAG_MASK;
445 #endif
446
447 if (type == HAL_DMA_FLOW_M2M_DMA || type == HAL_DMA_FLOW_M2P_DMA ||
448 type == HAL_DMA_FLOW_M2P_PERIPH) {
449 desc->src = cfg->src;
450 } else {
451 desc->src = hal_dma_get_periph_addr(cfg->src_periph);
452 }
453 if (type == HAL_DMA_FLOW_M2M_DMA || type == HAL_DMA_FLOW_P2M_DMA ||
454 type == HAL_DMA_FLOW_P2M_PERIPH) {
455 desc->dst = cfg->dst;
456 } else {
457 desc->dst = hal_dma_get_periph_addr(cfg->dst_periph);
458 }
459 desc->lli = (uint32_t)next;
460 desc->ctrl = ctrl;
461
462 return HAL_DMA_OK;
463 }
464
hal_dma_sg_2d_start(const struct HAL_DMA_DESC_T * desc,const struct HAL_DMA_CH_CFG_T * cfg,const struct HAL_DMA_2D_CFG_T * src_2d,const struct HAL_DMA_2D_CFG_T * dst_2d)465 enum HAL_DMA_RET_T hal_dma_sg_2d_start(const struct HAL_DMA_DESC_T *desc,
466 const struct HAL_DMA_CH_CFG_T *cfg,
467 const struct HAL_DMA_2D_CFG_T *src_2d,
468 const struct HAL_DMA_2D_CFG_T *dst_2d)
469 {
470 enum HAL_DMA_INST_T inst;
471 uint8_t hwch;
472 enum HAL_DMA_FLOW_CONTROL_T type;
473 uint8_t src_periph, dst_periph;
474 enum HAL_DMA_INST_T periph_inst;
475 int ret;
476 uint32_t irq_mask, try_burst;
477 uint32_t lock;
478
479 inst = get_inst_from_chan(cfg->ch);
480 hwch = get_hwch_from_chan(cfg->ch);
481
482 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
483 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
484
485 #ifdef CHIP_BEST1000
486 type = cfg->type;
487 #else
488 type = cfg->type & ~HAL_DMA_FLOW_FLAG_MASK;
489 #endif
490
491 if (type == HAL_DMA_FLOW_M2M_DMA || type == HAL_DMA_FLOW_M2P_DMA ||
492 type == HAL_DMA_FLOW_M2P_PERIPH) {
493 src_periph = 0;
494 } else {
495 ret = get_index_from_periph(cfg->src_periph, &periph_inst, &src_periph);
496 ASSERT(ret == 0, "Failed to get src periph: %d", cfg->src_periph);
497 #ifdef DMA_REMAP
498 if (periph_remap_bitmap[periph_inst] & (1 << src_periph)) {
499 periph_inst ^= 1;
500 ret = get_remap_index_from_periph(periph_inst, cfg->src_periph, &src_periph);
501 ASSERT(ret == 0, "Failed to get remap src periph: %d", cfg->src_periph);
502 }
503 #endif
504 ASSERT(inst == periph_inst, "Mismatch inst in chan=0x%02x and src periph %d", cfg->ch, cfg->src_periph);
505 }
506 if (type == HAL_DMA_FLOW_M2M_DMA || type == HAL_DMA_FLOW_P2M_DMA ||
507 type == HAL_DMA_FLOW_P2M_PERIPH) {
508 dst_periph = 0;
509 } else {
510 ret = get_index_from_periph(cfg->dst_periph, &periph_inst, &dst_periph);
511 ASSERT(ret == 0, "Failed to get dst periph: %d", cfg->dst_periph);
512 #ifdef DMA_REMAP
513 if (periph_remap_bitmap[periph_inst] & (1 << dst_periph)) {
514 periph_inst ^= 1;
515 ret = get_remap_index_from_periph(periph_inst, cfg->dst_periph, &dst_periph);
516 ASSERT(ret == 0, "Failed to get remap dst periph: %d", cfg->dst_periph);
517 }
518 #endif
519 ASSERT(inst == periph_inst, "Mismatch inst in chan=0x%02x and dst periph %d", cfg->ch, cfg->dst_periph);
520 }
521
522 if (!chan_enabled[inst][hwch]) {
523 // Not acquired
524 return HAL_DMA_ERR;
525 }
526 if (hal_dma_chan_busy_inst(inst, hwch)) {
527 // Busy
528 return HAL_DMA_ERR;
529 }
530
531 if (cfg->handler == NULL) {
532 irq_mask = 0;
533 } else {
534 irq_mask = DMA_CONFIG_ERR_IRQMASK | DMA_CONFIG_TC_IRQMASK;
535 handler[inst][hwch] = cfg->handler;
536 }
537
538 try_burst = cfg->try_burst ? DMA_CONFIG_TRY_BURST : 0;
539
540 /* Reset the Interrupt status */
541 dma[inst]->INTTCCLR = DMA_STAT_CHAN(hwch);
542 dma[inst]->INTERRCLR = DMA_STAT_CHAN(hwch);
543
544 dma[inst]->CH[hwch].SRCADDR = desc->src;
545 dma[inst]->CH[hwch].DSTADDR = desc->dst;
546 dma[inst]->CH[hwch].LLI = desc->lli;
547 dma[inst]->CH[hwch].CONTROL = desc->ctrl;
548 dma[inst]->CH[hwch].CONFIG = DMA_CONFIG_SRCPERIPH(src_periph) |
549 DMA_CONFIG_DSTPERIPH(dst_periph) |
550 DMA_CONFIG_TRANSFERTYPE(type) |
551 irq_mask |
552 try_burst;
553
554 #ifndef CHIP_BEST1000
555 if (src_2d) {
556 dma[inst]->_2D[hwch].SRCX = DMA_2D_MODIFY(src_2d->xmodify) | DMA_2D_COUNT(src_2d->xcount);
557 dma[inst]->_2D[hwch].SRCY = DMA_2D_MODIFY(src_2d->ymodify) | DMA_2D_COUNT(src_2d->ycount);
558 dma[inst]->_2D[hwch].CTRL |= DMA_2D_CTRL_SRC_EN;
559 } else {
560 dma[inst]->_2D[hwch].CTRL &= ~DMA_2D_CTRL_SRC_EN;
561 }
562 if (dst_2d) {
563 dma[inst]->_2D[hwch].DSTX = DMA_2D_MODIFY(dst_2d->xmodify) | DMA_2D_COUNT(dst_2d->xcount);
564 dma[inst]->_2D[hwch].DSTY = DMA_2D_MODIFY(dst_2d->ymodify) | DMA_2D_COUNT(dst_2d->ycount);
565 dma[inst]->_2D[hwch].CTRL |= DMA_2D_CTRL_DST_EN;
566 } else {
567 dma[inst]->_2D[hwch].CTRL &= ~DMA_2D_CTRL_DST_EN;
568 }
569 #endif
570
571 lock = int_lock();
572 if (cfg->start_cb) {
573 cfg->start_cb(cfg->ch);
574 }
575 dma[inst]->CH[hwch].CONFIG |= DMA_CONFIG_EN;
576 int_unlock(lock);
577
578 return HAL_DMA_OK;
579 }
580
hal_dma_sg_start(const struct HAL_DMA_DESC_T * desc,const struct HAL_DMA_CH_CFG_T * cfg)581 enum HAL_DMA_RET_T hal_dma_sg_start(const struct HAL_DMA_DESC_T *desc,
582 const struct HAL_DMA_CH_CFG_T *cfg)
583 {
584 return hal_dma_sg_2d_start(desc, cfg, NULL, NULL);
585 }
586
hal_dma_start(const struct HAL_DMA_CH_CFG_T * cfg)587 enum HAL_DMA_RET_T hal_dma_start(const struct HAL_DMA_CH_CFG_T *cfg)
588 {
589 struct HAL_DMA_DESC_T desc;
590 enum HAL_DMA_RET_T ret;
591
592 ret = hal_dma_init_desc(&desc, cfg, NULL, 1);
593 if (ret != HAL_DMA_OK) {
594 return ret;
595 }
596
597 ret = hal_dma_sg_start(&desc, cfg);
598 if (ret != HAL_DMA_OK) {
599 return ret;
600 }
601
602 return HAL_DMA_OK;
603 }
604
hal_dma_cancel(uint8_t ch)605 void hal_dma_cancel(uint8_t ch)
606 {
607 enum HAL_DMA_INST_T inst;
608 uint8_t hwch;
609
610 inst = get_inst_from_chan(ch);
611 hwch = get_hwch_from_chan(ch);
612
613 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
614 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
615
616 dma[inst]->CH[hwch].CONFIG &= ~DMA_CONFIG_EN;
617 dma[inst]->INTTCCLR = DMA_STAT_CHAN(hwch);
618 dma[inst]->INTERRCLR = DMA_STAT_CHAN(hwch);
619 }
620
hal_dma_stop(uint8_t ch)621 void hal_dma_stop(uint8_t ch)
622 {
623 enum HAL_DMA_INST_T inst;
624 uint8_t hwch;
625 uint8_t retry = 0;
626 const uint8_t max_retry = 10;
627
628 inst = get_inst_from_chan(ch);
629 hwch = get_hwch_from_chan(ch);
630
631 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
632 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
633
634 dma[inst]->CH[hwch].CONFIG |= DMA_CONFIG_HALT;
635 #if 1
636 while ((dma[inst]->CH[hwch].CONFIG & DMA_CONFIG_ACTIVE) && (++retry < max_retry)) {
637 if (retry <= 3) {
638 hal_sys_timer_delay_us(10);
639 } else {
640 hal_dma_delay(1);
641 }
642 }
643 #else
644 while (dma[inst]->CH[hwch].CONFIG & DMA_CONFIG_ACTIVE);
645 #endif
646
647 hal_dma_cancel(ch);
648 }
649
hal_dma_get_chan(enum HAL_DMA_PERIPH_T periph,enum HAL_DMA_GET_CHAN_T policy)650 uint8_t hal_dma_get_chan(enum HAL_DMA_PERIPH_T periph, enum HAL_DMA_GET_CHAN_T policy)
651 {
652 enum HAL_DMA_INST_T inst;
653 int ret;
654 uint8_t i, hwch;
655 uint8_t got = HAL_DMA_CHAN_NONE;
656 uint32_t lock;
657
658 ASSERT(policy == HAL_DMA_HIGH_PRIO || policy == HAL_DMA_LOW_PRIO || policy == HAL_DMA_LOW_PRIO_ONLY,
659 "Invalid DMA policy: %d", policy);
660
661 if (periph == HAL_GPDMA_MEM) {
662 inst = HAL_DMA_INST_GPDMA;
663 } else if (periph == HAL_AUDMA_MEM) {
664 inst = HAL_DMA_INST_AUDMA;
665 } else {
666 ret = get_index_from_periph(periph, &inst, &i);
667 ASSERT(ret == 0, "Invalid DMA periph: %d", periph);
668 #ifdef DMA_REMAP
669 if (periph_remap_bitmap[inst] & (1 << i)) {
670 inst ^= 1;
671 }
672 #endif
673 }
674
675 lock = int_lock();
676 for (i = 0; i < DMA_NUMBER_CHANNELS; i++) {
677 if (policy == HAL_DMA_HIGH_PRIO) {
678 hwch = i;
679 } else if (policy == HAL_DMA_LOW_PRIO) {
680 hwch = DMA_NUMBER_CHANNELS - 1 - i;
681 } else {
682 hwch = DMA_NUMBER_CHANNELS - 1 - i;
683 if (hwch < 6) {
684 break;
685 }
686 }
687
688 if (!chan_enabled[inst][hwch] && !hal_dma_chan_busy_inst(inst, hwch)) {
689 chan_enabled[inst][hwch] = true;
690 got = generate_chan(inst, hwch);
691 dma[inst]->DMACONFIG |= DMA_DMACONFIG_CLK_EN(1 << hwch);
692 break;
693 }
694 }
695 int_unlock(lock);
696
697 #ifdef DMA_DEBUG
698 if (got != HAL_DMA_CHAN_NONE) {
699 chan_user[inst][hwch] = __builtin_return_address(0);
700 }
701 #endif
702
703 return got;
704 }
705
hal_dma_free_chan(uint8_t ch)706 void hal_dma_free_chan(uint8_t ch)
707 {
708 enum HAL_DMA_INST_T inst;
709 uint8_t hwch;
710 uint32_t lock;
711
712 inst = get_inst_from_chan(ch);
713 hwch = get_hwch_from_chan(ch);
714
715 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
716 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
717 ASSERT(chan_enabled[inst][hwch], "DMA chan not enabled: inst=%u hwch=%u", inst, hwch);
718
719 hal_dma_cancel(ch);
720
721 lock = int_lock();
722 chan_enabled[inst][hwch] = false;
723 dma[inst]->DMACONFIG &= ~DMA_DMACONFIG_CLK_EN(1 << hwch);
724 int_unlock(lock);
725 }
726
hal_dma_get_cur_src_addr(uint8_t ch)727 uint32_t hal_dma_get_cur_src_addr(uint8_t ch)
728 {
729 enum HAL_DMA_INST_T inst;
730 uint8_t hwch;
731
732 inst = get_inst_from_chan(ch);
733 hwch = get_hwch_from_chan(ch);
734
735 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
736 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
737
738 return dma[inst]->CH[hwch].SRCADDR;
739 }
740
hal_dma_get_cur_dst_addr(uint8_t ch)741 uint32_t hal_dma_get_cur_dst_addr(uint8_t ch)
742 {
743 enum HAL_DMA_INST_T inst;
744 uint8_t hwch;
745
746 inst = get_inst_from_chan(ch);
747 hwch = get_hwch_from_chan(ch);
748
749 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
750 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
751
752 return dma[inst]->CH[hwch].DSTADDR;
753 }
754
hal_dma_get_cur_src_remain_and_addr(uint8_t ch,uint32_t * remain,uint32_t * src)755 void SRAM_TEXT_LOC hal_dma_get_cur_src_remain_and_addr(uint8_t ch, uint32_t *remain, uint32_t *src)
756 {
757 enum HAL_DMA_INST_T inst;
758 uint8_t hwch;
759 uint32_t lock;
760 uint32_t size[2];
761 uint32_t srcaddr[2];
762
763 inst = get_inst_from_chan(ch);
764 hwch = get_hwch_from_chan(ch);
765
766 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
767 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
768
769 lock = int_lock();
770 size[0] = dma[inst]->CH[hwch].CONTROL;
771 srcaddr[0] = dma[inst]->CH[hwch].SRCADDR;
772 size[1] = dma[inst]->CH[hwch].CONTROL;
773 srcaddr[1] = dma[inst]->CH[hwch].SRCADDR;
774 int_unlock(lock);
775
776 size[0] = GET_BITFIELD(size[0], DMA_CONTROL_TRANSFERSIZE);
777 size[1] = GET_BITFIELD(size[1], DMA_CONTROL_TRANSFERSIZE);
778
779 if (size[0] == size[1]) {
780 *remain = size[0];
781 *src = srcaddr[0];
782 } else {
783 *remain = size[1];
784 *src = srcaddr[1];
785 }
786
787 return;
788 }
789
hal_dma_irq_run_chan(uint8_t ch)790 enum HAL_DMA_RET_T hal_dma_irq_run_chan(uint8_t ch)
791 {
792 enum HAL_DMA_INST_T inst;
793 uint8_t hwch;
794
795 inst = get_inst_from_chan(ch);
796 hwch = get_hwch_from_chan(ch);
797
798 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
799 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
800
801 if ((dma[inst]->INTSTAT & DMA_STAT_CHAN(hwch)) == 0) {
802 return HAL_DMA_ERR;
803 }
804
805 hal_dma_handle_chan_irq(inst, hwch);
806
807 return HAL_DMA_OK;
808 }
809
hal_dma_chan_busy(uint8_t ch)810 bool hal_dma_chan_busy(uint8_t ch)
811 {
812 enum HAL_DMA_INST_T inst;
813 uint8_t hwch;
814
815 inst = get_inst_from_chan(ch);
816 hwch = get_hwch_from_chan(ch);
817
818 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
819 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
820
821 return hal_dma_chan_busy_inst(inst, hwch);
822 }
823
hal_dma_busy(void)824 bool hal_dma_busy(void)
825 {
826 enum HAL_DMA_INST_T inst;
827 int hwch;
828
829 for (inst = HAL_DMA_INST_AUDMA; inst < HAL_DMA_INST_QTY; inst++) {
830 for (hwch = chan_start[inst]; hwch < chan_num[inst]; hwch++) {
831 if (hal_dma_chan_busy_inst(inst, hwch)) {
832 return true;
833 }
834 }
835 }
836
837 return false;
838 }
839
hal_dma_get_sg_remain_size(uint8_t ch)840 uint32_t hal_dma_get_sg_remain_size(uint8_t ch)
841 {
842 enum HAL_DMA_INST_T inst;
843 uint8_t hwch;
844 uint32_t remains;
845 const struct HAL_DMA_DESC_T *desc, *first;
846
847 inst = get_inst_from_chan(ch);
848 hwch = get_hwch_from_chan(ch);
849
850 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
851 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
852
853 remains = GET_BITFIELD(dma[inst]->CH[hwch].CONTROL, DMA_CONTROL_TRANSFERSIZE);
854 first = (const struct HAL_DMA_DESC_T *)dma[inst]->CH[hwch].LLI;
855 desc = first;
856 while (desc) {
857 remains += GET_BITFIELD(desc->ctrl, DMA_CONTROL_TRANSFERSIZE);
858 desc = (const struct HAL_DMA_DESC_T *)desc->lli;
859 if (desc == first) {
860 break;
861 }
862 }
863
864 return remains;
865 }
866
hal_dma_tc_irq_enable(uint8_t ch)867 void hal_dma_tc_irq_enable(uint8_t ch)
868 {
869 #if !(defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST3001) || defined(CHIP_BEST3005))
870 enum HAL_DMA_INST_T inst;
871 uint8_t hwch;
872 uint32_t lock;
873
874 inst = get_inst_from_chan(ch);
875 hwch = get_hwch_from_chan(ch);
876
877 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
878 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
879
880 lock = int_lock();
881 #ifdef CHIP_BEST2300
882 if (inst == HAL_DMA_INST_AUDMA) {
883 hal_cmu_dma_tc_irq_set_chan(hwch);
884 }
885 #else
886 dma[inst]->DMACONFIG |= DMA_DMACONFIG_TC_IRQ_EN(1 << hwch);
887 #endif
888 int_unlock(lock);
889 #endif
890 }
891
hal_dma_tc_irq_disable(uint8_t ch)892 void hal_dma_tc_irq_disable(uint8_t ch)
893 {
894 #if !(defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST3001) || defined(CHIP_BEST3005))
895 enum HAL_DMA_INST_T inst;
896 uint8_t hwch;
897 uint32_t lock;
898
899 inst = get_inst_from_chan(ch);
900 hwch = get_hwch_from_chan(ch);
901
902 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
903 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
904
905 lock = int_lock();
906 #ifdef CHIP_BEST2300
907 if (inst == HAL_DMA_INST_AUDMA) {
908 hal_cmu_dma_tc_irq_clear_chan(hwch);
909 }
910 #else
911 dma[inst]->DMACONFIG &= ~DMA_DMACONFIG_TC_IRQ_EN(1 << hwch);
912 #endif
913 int_unlock(lock);
914 #endif
915 }
916
hal_dma_set_burst_addr_inc(uint8_t ch,const struct HAL_DMA_BURST_ADDR_INC_T * inc)917 void hal_dma_set_burst_addr_inc(uint8_t ch, const struct HAL_DMA_BURST_ADDR_INC_T *inc)
918 {
919 #if !(defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST3001) || defined(CHIP_BEST3005))
920 enum HAL_DMA_INST_T inst;
921 uint8_t hwch;
922 uint32_t lock;
923
924 inst = get_inst_from_chan(ch);
925 hwch = get_hwch_from_chan(ch);
926
927 ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
928 ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
929
930 lock = int_lock();
931 if (inc && inc->src_inc_en) {
932 dma[inst]->CH[hwch].CONTROL |= DMA_CONTROL_BURST_SI;
933 dma[inst]->_2D[hwch].SRC_INC = SET_BITFIELD(dma[inst]->_2D[hwch].SRC_INC, DMA_BURST_SRC_INC_VAL, inc->src_inc_val);
934 } else {
935 dma[inst]->CH[hwch].CONTROL &= ~DMA_CONTROL_BURST_SI;
936 }
937 if (inc && inc->dst_inc_en) {
938 dma[inst]->CH[hwch].CONTROL |= DMA_CONTROL_BURST_DI;
939 dma[inst]->_2D[hwch].DST_INC = SET_BITFIELD(dma[inst]->_2D[hwch].DST_INC, DMA_BURST_DST_INC_VAL, inc->dst_inc_val);
940 } else {
941 dma[inst]->CH[hwch].CONTROL &= ~DMA_CONTROL_BURST_DI;
942 }
943 int_unlock(lock);
944 #endif
945 }
946
hal_dma_clear_burst_addr_inc(uint8_t ch)947 void hal_dma_clear_burst_addr_inc(uint8_t ch)
948 {
949 hal_dma_set_burst_addr_inc(ch, NULL);
950 }
951
hal_dma_set_desc_burst_addr_inc(struct HAL_DMA_DESC_T * desc,const struct HAL_DMA_BURST_ADDR_INC_T * inc)952 void hal_dma_set_desc_burst_addr_inc(struct HAL_DMA_DESC_T *desc, const struct HAL_DMA_BURST_ADDR_INC_T *inc)
953 {
954 #if !(defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST3001) || defined(CHIP_BEST3005))
955 if (inc && inc->src_inc_en) {
956 desc->ctrl |= DMA_CONTROL_BURST_SI;
957 } else {
958 desc->ctrl &= ~DMA_CONTROL_BURST_SI;
959 }
960 if (inc && inc->dst_inc_en) {
961 desc->ctrl |= DMA_CONTROL_BURST_DI;
962 } else {
963 desc->ctrl &= ~DMA_CONTROL_BURST_DI;
964 }
965 #endif
966 }
967
hal_dma_clear_desc_burst_addr_inc(struct HAL_DMA_DESC_T * desc)968 void hal_dma_clear_desc_burst_addr_inc(struct HAL_DMA_DESC_T *desc)
969 {
970 hal_dma_set_desc_burst_addr_inc(desc, NULL);
971 }
972
973 #ifdef DMA_REMAP
hal_dma_remap_periph(enum HAL_DMA_PERIPH_T periph,int enable)974 void hal_dma_remap_periph(enum HAL_DMA_PERIPH_T periph, int enable)
975 {
976 enum HAL_DMA_INST_T inst1, inst2;
977 uint8_t index1, index2;
978 int ret;
979 uint32_t lock;
980
981 // Tag the periph
982 ret = get_index_from_periph(periph, &inst1, &index1);
983 ASSERT(ret == 0, "Invalid DMA periph for remap1: %d", periph);
984
985 // Tag the peer periph
986 inst2 = inst1 ^ 1;
987 ret = get_remap_index_from_periph(inst2, periph, &index2);
988 ASSERT(ret == 0, "Invalid DMA periph for remap2: %d", periph);
989
990 lock = int_lock();
991 if (enable) {
992 periph_remap_bitmap[inst1] |= (1 << index1);
993 periph_remap_bitmap[inst2] |= (1 << index2);
994 #ifndef CHIP_BEST1000
995 // For best2000, index1 == index2
996 hal_cmu_dma_swap_enable(index1);
997 #endif
998 } else {
999 periph_remap_bitmap[inst1] &= ~(1 << index1);
1000 periph_remap_bitmap[inst2] &= ~(1 << index2);
1001 #ifndef CHIP_BEST1000
1002 hal_cmu_dma_swap_disable(index1);
1003 #endif
1004 }
1005 int_unlock(lock);
1006 }
1007 #endif
1008
hal_dma_open(void)1009 void hal_dma_open(void)
1010 {
1011 enum HAL_DMA_INST_T inst;
1012
1013 if (dma_opened) {
1014 return;
1015 }
1016
1017 for (inst = HAL_DMA_INST_AUDMA; inst < HAL_DMA_INST_QTY; inst++) {
1018 hal_dma_open_inst(inst);
1019 }
1020
1021 #ifdef DMA_REMAP
1022 #ifdef CHIP_BEST1000
1023 if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_4) {
1024 hal_dma_remap_periph(HAL_AUDMA_I2S0_RX, 1);
1025 hal_dma_remap_periph(HAL_AUDMA_I2S0_TX, 1);
1026 hal_dma_remap_periph(HAL_AUDMA_SPDIF0_RX, 1);
1027 hal_dma_remap_periph(HAL_AUDMA_SPDIF0_TX, 1);
1028 }
1029 #endif
1030 #endif
1031
1032 dma_opened = true;
1033 }
1034
hal_dma_close(void)1035 void hal_dma_close(void)
1036 {
1037 enum HAL_DMA_INST_T inst;
1038
1039 if (!dma_opened) {
1040 return;
1041 }
1042
1043 for (inst = 0; inst < HAL_DMA_INST_QTY; inst++) {
1044 hal_dma_close_inst(inst);
1045 }
1046
1047 dma_opened = false;
1048 }
1049
1050 #ifdef CORE_SLEEP_POWER_DOWN
hal_dma_sleep(void)1051 void hal_dma_sleep(void)
1052 {
1053 enum HAL_DMA_INST_T inst;
1054
1055 for (inst = 0; inst < HAL_DMA_INST_QTY; inst++) {
1056 saved_dma_regs[inst] = dma[inst]->DMACONFIG;
1057 }
1058 }
1059
hal_dma_wakeup(void)1060 void hal_dma_wakeup(void)
1061 {
1062 enum HAL_DMA_INST_T inst;
1063
1064 for (inst = 0; inst < HAL_DMA_INST_QTY; inst++) {
1065 dma[inst]->DMACONFIG = saved_dma_regs[inst];
1066 }
1067 }
1068 #endif
1069
hal_dma_set_delay_func(HAL_DMA_DELAY_FUNC new_func)1070 HAL_DMA_DELAY_FUNC hal_dma_set_delay_func(HAL_DMA_DELAY_FUNC new_func)
1071 {
1072 HAL_DMA_DELAY_FUNC old_func = dma_delay;
1073 dma_delay = new_func;
1074 return old_func;
1075 }
1076
hal_dma_record_busy_chan(void)1077 void hal_dma_record_busy_chan(void)
1078 {
1079 #ifdef DMA_DEBUG
1080 enum HAL_DMA_INST_T inst;
1081 int hwch;
1082
1083 for (inst = HAL_DMA_INST_AUDMA; inst < HAL_DMA_INST_QTY; inst++) {
1084 debug_user_map[inst] = 0;
1085 for (hwch = chan_start[inst]; hwch < chan_num[inst]; hwch++) {
1086 if (hal_dma_chan_busy_inst(inst, hwch)) {
1087 debug_user_map[inst] |= (1 << hwch);
1088 }
1089 }
1090 }
1091 #endif
1092 }
1093
hal_dma_print_busy_chan(void)1094 void hal_dma_print_busy_chan(void)
1095 {
1096 #ifdef DMA_DEBUG
1097 enum HAL_DMA_INST_T inst;
1098 int hwch;
1099
1100 for (inst = HAL_DMA_INST_AUDMA; inst < HAL_DMA_INST_QTY; inst++) {
1101 for (hwch = chan_start[inst]; hwch < chan_num[inst]; hwch++) {
1102 if (debug_user_map[inst] & (1 << hwch)) {
1103 TRACE(0, "*** DMA CHAN BUSY: %u-%u %8X", inst, hwch, (uint32_t)chan_user[inst][hwch]);
1104 }
1105 }
1106 }
1107 #endif
1108 }
1109
1110