1 /*
2 * Copyright (c) Texas Instruments Incorporated 2020
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the
14 * distribution.
15 *
16 * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
33 /**
34 * \file edma.c
35 *
36 * \brief This file contains implementation of the EDMA driver APIs in edma.h.
37 * It uses at a lower level the edma_low_level.h APIs
38 */
40 /* ========================================================================== */
41 /* Include Files */
42 /* ========================================================================== */
44 #include <stdint.h>
45 #include <string.h>
46 #include <ti/csl/hw_types.h>
47 #include <ti/drv/edma/edma.h>
48 #include <ti/drv/edma/soc/edma_soc_priv.h>
49 #include <ti/osal/osal.h>
51 /* ========================================================================== */
52 /* Macros & Typedefs */
53 /* ========================================================================== */
55 #define EDMA_PARAM_CHECK
56 #define EDMA_DBG
58 #define EDMA_READ_RATE_RANGE_CHECK_MAX (EDMA_TC_RDRATE_RDRATE_READEVERY32CYCLES)
59 #define EDMA_QUEUE_PRIORITIY_RANGE_CHECK_MAX ((uint8_t)EDMA_TPCC_QUEPRI_PRIQ0_PRIORITY7)
61 /* ========================================================================== */
62 /* Structure Declarations */
63 /* ========================================================================== */
65 /**
66 @defgroup EDMA_INTERNAL_DATA_STRUCTURE EDMA Driver Internal Data Structures
67 @ingroup EDMA_INTERNAL
68 */
70 /** @addtogroup EDMA_INTERNAL_DATA_STRUCTURE
71 @{ */
73 /*! @brief QDMA object (state) information used to trigger the QDMA channel
74 after configuring. */
75 typedef struct EDMA_qdmaObject_t_
76 {
77 /*! @brief Trigger word address. */
78 uint32_t triggerWordAddress;
80 /*! @brief Trigger word value. */
81 uint32_t triggerWordValue;
82 } EDMA_qdmaObject_t;
84 /*! @brief Transfer controller error Isr argument information storage. */
85 typedef struct EDMA_transferControllerErrorIsrArgInfo_t_
86 {
87 /*! @brief handle to EDMA obtained from call to @ref EDMA_open. */
88 EDMA_Handle handle;
90 /*! @brief Id of transfer controller. */
91 uint8_t transferControllerId;
92 } EDMA_transferControllerErrorIsrArgInfo_t;
94 /*! @brief EDMA internal object (state) information structure that is required
95 to be preserved between calls to EDMA APIs. */
96 typedef struct EDMA_Object_t_
97 {
98 /*! @brief true if EDMA is used else false. */
99 bool isUsed;
101 /*! @brief handle for transfer completion interrupt object of the OS.
102 Required to be stored to be able to delete during @ref EDMA_close API */
103 HwiP_Handle hwiTransferCompleteHandle;
105 /*! @brief handle for CC error interrupt object of the OS.
106 Required to be stored to be able to delete during @ref EDMA_close API */
107 HwiP_Handle hwiErrorHandle;
109 /*! @brief handles for TC error interrupt object of the OS for each tc Id.
110 Required to be stored to be able to delete during @ref EDMA_close API */
111 HwiP_Handle hwiTransferControllerErrorHandle[EDMA_MAX_NUM_TC];
113 /*! @brief Transfer completion call back function storage for each transfer completion code. */
114 EDMA_transferCompletionCallbackFxn_t transferCompleteCallbackFxn[EDMA_NUM_TCC];
116 /*! @brief Storage for argument to be returned when calling transfer completion call back
117 in addition to transfer completion code, for each transfer completion code. */
118 uintptr_t transferCompleteCallbackFxnArg[EDMA_NUM_TCC];
120 /*! @brief QDMA object storage for each QDMA channel. */
121 EDMA_qdmaObject_t qdmaObj[EDMA_NUM_QDMA_CHANNELS];
123 /*! @brief CC Error call back function. */
124 EDMA_errorCallbackFxn_t errorCallbackFxn;
126 /*! @brief Transfer controller error call back function. */
127 edmaTransferControllerErrorCallbackFxn_t transferControllerErrorCallbackFxn;
129 /*! Transfer controller error Isr argument storage for each tc. */
130 EDMA_transferControllerErrorIsrArgInfo_t transferControllerErrorIsrArgInfo[EDMA_MAX_NUM_TC];
131 } EDMA_Object_t;
133 /*! @brief Config structure containing object and hardware attributes. This
134 will be casted to the EDMA's handle and returned in open API */
135 typedef struct EDMA_Config_t_
136 {
137 /*! @brief Pointer to EDMA object (state). */
138 EDMA_Object_t *object;
140 /*! @brief Pointer to EDMA Hardware attributes structure. */
141 EDMA_hwAttrs_t const *hwAttrs;
142 } EDMA_Config_t;
144 #ifdef EDMA_DBG
145 typedef struct edmaDbg_t_
146 {
147 uint32_t transCompIsrCount;
148 uint32_t transCompIsrIevalCount;
149 uint32_t errorIsrCount;
150 uint32_t transCompErrorIsrCount;
151 uint32_t aggregatedErrorTransCompErrorIsrCount;
152 EDMA_Object_t *edmaObj;
153 } edmaDbg_t;
154 edmaDbg_t edmaDbg;
155 #endif
157 /** @} */ /* end of @addtogroup EDMA_INTERNAL_DATA_STRUCTURE */
159 /* ========================================================================== */
160 /* Function Declarations */
161 /* ========================================================================== */
163 /**
164 @defgroup EDMA_INTERNAL_FUNCTION EDMA Driver Internal Functions
165 @ingroup EDMA_INTERNAL
166 */
168 /* Private function prototype definitions */
169 #ifdef EDMA_PARAM_CHECK
170 static int32_t EDMA_validate_channelIdchannelType(uint8_t channelId, uint8_t channelType);
172 static int32_t EDMA_validate_channel_config(
173 EDMA_Handle handle,
174 EDMA_hwAttrs_t const *hwAttrs,
175 EDMA_channelConfig_t const *config);
177 static inline int32_t EDMA_validate_param_config(EDMA_Handle handle,
178 EDMA_hwAttrs_t const *hwAttrs, uint16_t paramId,
179 EDMA_paramSetConfig_t const *config,
180 EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn
181 );
182 #endif
183 static void EDMA_paramSetConfig_assist (uint32_t ccBaseAddr, uint16_t paramId,
184 EDMA_paramSetConfig_t const *pSetCfg);
186 static void EDMA_paramConfig_assist(uint32_t ccBaseAddr, uint16_t paramId,
187 EDMA_paramSetConfig_t const *pSetCfg,
188 EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn,
189 uintptr_t transferCompletionCallbackFxnArg, EDMA_Object_t *edmaObj);
191 static inline int32_t EDMA_startTransfer_assist(EDMA_Handle handle, uint8_t channelId,
192 uint8_t channelType, bool isStaticSet);
194 static void EDMA_transferComplete_isr (uintptr_t arg);
196 static void EDMA_update_queue_entries (
197 uint32_t qEntry0Addr,
198 uint32_t qEntryAddrJump,
199 uint8_t numEntries,
200 uint8_t *qEntryIndx,
201 EDMA_queueEntryInfo_t *qEntry);
203 static void EDMA_transferController_error_isr (uintptr_t arg);
205 static void EDMA_error_isr (uintptr_t arg);
207 #ifdef SOC_TPR12
208 static void EDMA_aggregated_error_transferController_error_isr (uintptr_t arg);
209 #endif
211 static void EDMA_configQueueThreshold(uint32_t ccBaseAddr, uint8_t queueId,
212 uint8_t threshold);
214 static void EDMA_configQueuePriority(uint32_t ccBaseAddr, uint8_t transferController,
215 uint8_t priority);
217 static bool EDMA_isError(uint32_t ccBaseAddr);
219 static void EDMA_getErrorStatusInfo(EDMA_hwAttrs_t const *hwAttrs, uint32_t ccBaseAddr,
220 EDMA_errorInfo_t *errorInfo);
222 static void EDMA_clearErrors(EDMA_hwAttrs_t const *hwAttrs, uint32_t ccBaseAddr,
223 EDMA_errorInfo_t const *errorInfo);
225 static bool EDMA_isTransferControllerError(uint32_t tcBaseAddr);
227 static void EDMA_getTransferControllerErrorStatusInfo(uint32_t tcBaseAddr,
228 EDMA_transferControllerErrorInfo_t *errorInfo);
230 static void EDMA_clearTransferControllerErrors(uint32_t tcBaseAddr,
231 EDMA_transferControllerErrorInfo_t *errorInfo);
233 static EDMA_Object_t* EDMA_getFreeEdmaObj(void);
235 /* ========================================================================== */
236 /* Global Variables */
237 /* ========================================================================== */
239 /* EDMA configuration structure */
240 static EDMA_Config_t EDMA_config[EDMA_DRV_INST_MAX + 1U] = {0U};
242 /*! @brief EDMA objects storage for each CC. */
243 static EDMA_Object_t EDMA_object[EDMA_NUM_CC] = {0U};
245 /* ========================================================================== */
246 /* Function Definitions */
247 /* ========================================================================== */
249 #ifdef EDMA_PARAM_CHECK
250 /**
251 * @b Description
252 * @n
253 * Utility function for validating channel Id and channel Type parameters.
254 *
255 * @param[in] channelId channel Id
256 * @param[in] channelType channed Type
257 *
258 * \ingroup EDMA_INTERNAL_FUNCTION
259 *
260 * @retval
261 * one of @ref EDMA_ERROR_CODES
262 */
263 static int32_t EDMA_validate_channelIdchannelType(uint8_t channelId, uint8_t channelType)
264 {
265 int32_t errorCode = EDMA_NO_ERROR;
267 if ((channelType != (uint8_t)EDMA3_CHANNEL_TYPE_DMA) &&
268 (channelType != (uint8_t)EDMA3_CHANNEL_TYPE_QDMA))
269 {
270 errorCode = EDMA_E_INVALID__DMA_CHANNEL_TYPE;
271 }
273 if ((errorCode == EDMA_NO_ERROR) &&
274 ((channelType == (uint8_t)EDMA3_CHANNEL_TYPE_DMA) &&
275 (channelId >= (uint8_t)EDMA_NUM_DMA_CHANNELS)))
276 {
277 errorCode = EDMA_E_INVALID__DMA_CHANNEL_ID;
278 }
280 if ((errorCode == EDMA_NO_ERROR) &&
281 ((channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA) &&
282 (channelId >= EDMA_NUM_QDMA_CHANNELS)))
283 {
284 errorCode = EDMA_E_INVALID__QDMA_CHANNEL_ID;
285 }
286 return(errorCode);
287 }
289 /**
290 * @b Description
291 * @n
292 * Utility function for validating parameters in @ref EDMA_channelConfig_t.
293 *
294 * @param[in] handle EDMA handle.
295 * @param[in] hwAttrs Pointer to hardware attributes.
296 * @param[in] config Pointer to EDMA channel configuration structure.
297 *
298 * \ingroup EDMA_INTERNAL_FUNCTION
299 *
300 * @retval
301 * one of @ref EDMA_ERROR_CODES
302 */
303 static int32_t EDMA_validate_channel_config(
304 EDMA_Handle handle,
305 EDMA_hwAttrs_t const *hwAttrs,
306 EDMA_channelConfig_t const *config)
307 {
308 int32_t errorCode = EDMA_NO_ERROR;
310 if (handle == NULL)
311 {
312 errorCode = EDMA_E_INVALID__HANDLE_NULL;
313 }
315 if ((errorCode == EDMA_NO_ERROR) &&
316 (config == NULL))
317 {
318 errorCode = EDMA_E_INVALID__CONFIG_POINTER_NULL;
319 }
321 if (errorCode == EDMA_NO_ERROR)
322 {
323 errorCode = EDMA_validate_channelIdchannelType(config->channelId,
324 config->channelType);
325 }
327 if ((errorCode == EDMA_NO_ERROR) &&
328 (config->channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA))
329 {
330 if (config->qdmaParamTriggerWordOffset > 7)
331 {
332 errorCode = EDMA_E_INVALID__QDMA_TRIGGER_WORD;
333 }
334 }
336 /* if channel mappping is not supported, paramId must be same as channelId
337 for DMA channel */
338 if ((errorCode == EDMA_NO_ERROR) &&
339 (hwAttrs->isChannelMapExist == false) &&
340 (config->channelType == (uint8_t)EDMA3_CHANNEL_TYPE_DMA) &&
341 (config->paramId != (uint16_t)config->channelId))
342 {
343 errorCode = EDMA_E_INVALID__PARAM_ID_NOT_SAME_AS_CHANNEL_ID;
344 }
346 if ((errorCode == EDMA_NO_ERROR) &&
347 (config->eventQueueId >= hwAttrs->numEventQueues))
348 {
349 errorCode = EDMA_E_INVALID__EVENT_QUEUE_ID;
350 }
352 if (errorCode == EDMA_NO_ERROR)
353 {
354 errorCode = EDMA_validate_param_config(handle, hwAttrs, config->paramId, &config->paramSetConfig,
355 config->transferCompletionCallbackFxn);
356 }
358 return(errorCode);
359 }
361 /**
362 * @b Description
363 * @n
364 * Utility function for validating parameters relalted to param configuration.
365 *
366 * @param[in] handle EDMA handle.
367 * @param[in] hwAttrs Pointer to hardware attributes.
368 * @param[in] paramId PaRAM Set Id.
369 * @param[in] config Pointer to PaRAM Set configuration structure.
370 * @param[in] transferCompletionCallbackFxn transfer completion call-back function configuration.
371 *
372 * \ingroup EDMA_INTERNAL_FUNCTION
373 *
374 * @retval
375 * one of @ref EDMA_ERROR_CODES
376 */
377 static inline int32_t EDMA_validate_param_config(
378 EDMA_Handle handle,
379 EDMA_hwAttrs_t const *hwAttrs,
380 uint16_t paramId,
381 EDMA_paramSetConfig_t const *config,
382 EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn
383 )
384 {
385 int32_t errorCode = EDMA_NO_ERROR;
387 if (handle == NULL)
388 {
389 errorCode = EDMA_E_INVALID__HANDLE_NULL;
390 }
392 if ((errorCode == EDMA_NO_ERROR) &&
393 (paramId >= hwAttrs->numParamSets))
394 {
395 errorCode = EDMA_E_INVALID__PARAM_ID;
396 }
398 if ((errorCode == EDMA_NO_ERROR) &&
399 (config->transferCompletionCode >= EDMA_NUM_TCC))
400 {
401 errorCode = EDMA_E_INVALID__TRANSFER_COMPLETION_CODE;
402 }
404 /* if all of interrupt completion flags are false, then transfer completion
405 call back function must be NULL */
406 if ((errorCode == EDMA_NO_ERROR) &&
407 ((transferCompletionCallbackFxn != NULL) &&
408 ((config->isFinalTransferInterruptEnabled == false) &&
409 (config->isIntermediateTransferInterruptEnabled == false))))
410 {
411 errorCode = EDMA_E_INVALID__TRNSFR_COMPLETION_PARAMS;
412 }
414 /* if completion interrupt not connected and transfer completion call back
415 * is not NULL, then generate error
416 */
417 if ((errorCode == EDMA_NO_ERROR) &&
418 ((hwAttrs->transferCompletionInterruptNum == EDMA_INTERRUPT_NOT_CONNECTED_ID) &&
419 (transferCompletionCallbackFxn != NULL)))
420 {
421 errorCode = EDMA_E_INVALID__TRNSFR_COMPLETION_PARAMS;
422 }
424 if ((errorCode == EDMA_NO_ERROR) &&
425 ((config->transferType != (uint8_t)EDMA3_SYNC_A) &&
426 (config->transferType != (uint8_t)EDMA3_SYNC_AB)))
427 {
428 errorCode = EDMA_E_INVALID__TRANSFER_TYPE;
429 }
431 #ifdef EDMA_EXTENDED_B_INDICES
432 if ((errorCode == EDMA_NO_ERROR) &&
433 ((config->sourceBindex > EDMA_EXTENDED_B_INDEX_MAX) ||
434 (config->sourceBindex < EDMA_EXTENDED_B_INDEX_MIN)))
435 {
436 errorCode = EDMA_E_INVALID__SOURCE_B_INDEX;
437 }
439 if ((errorCode == EDMA_NO_ERROR) &&
440 ((config->destinationBindex > EDMA_EXTENDED_B_INDEX_MAX) ||
441 (config->destinationBindex < EDMA_EXTENDED_B_INDEX_MIN)))
442 {
443 errorCode = EDMA_E_INVALID__DESTINATION_B_INDEX;
444 }
445 #endif
447 return(errorCode);
448 }
449 #endif
451 /**
452 * @b Description
453 * @n
454 * Utility function for configuring a PaRAM Set.
455 * Note: HW_WR_FIELD32 APIs are avoided for (assumed) efficiency when writing
456 * param fields (avoid unnecessary masking because fields are defined to be right
457 * sized (e.g aCount is uint16_t, matching Param ACNT size).
458 *
459 * @param[in] ccBaseAddr CC base address.
460 * @param[in] paramId PaRAM Set Id.
461 * @param[in] pSetCfg Pointer to PaRAM Set configuration.
462 *
463 * \ingroup EDMA_INTERNAL_FUNCTION
464 *
465 * @retval
466 * None.
467 */
468 #if 1
469 #ifdef EDMA_EXTENDED_B_INDICES
470 /*! Returns the 8-bit extension beyond 16-bits of the 32-bit b-index */
471 #define EDMA_B_INDX_EXTENSION(x) (((x) >> 16U) & 0x000000FFU)
472 #endif
474 static void EDMA_paramSetConfig_assist (uint32_t ccBaseAddr, uint16_t paramId,
475 EDMA_paramSetConfig_t const *pSetCfg)
476 {
477 EDMA3CCPaRAMEntry paramSet;
479 /* program PaRAM set */
480 paramSet.srcAddr = pSetCfg->sourceAddress;
481 paramSet.destAddr = pSetCfg->destinationAddress;
482 paramSet.aCnt = pSetCfg->aCount;
483 paramSet.bCnt = pSetCfg->bCount;
484 paramSet.cCnt = pSetCfg->cCount;
485 paramSet.srcBIdx = (uint16_t) pSetCfg->sourceBindex;
486 paramSet.destBIdx = (uint16_t) pSetCfg->destinationBindex;
487 paramSet.srcCIdx = pSetCfg->sourceCindex;
488 paramSet.destCIdx = pSetCfg->destinationCindex;
489 paramSet.linkAddr = pSetCfg->linkAddress;
490 paramSet.bCntReload = pSetCfg->bCountReload;
491 #ifdef EDMA_EXTENDED_B_INDICES
492 paramSet.bidxExtn = EDMA_B_INDX_EXTENSION(pSetCfg->sourceBindex) |
493 EDMA_B_INDX_EXTENSION(pSetCfg->sourceCindex) << (EDMA_TPCC_CCNT_DSTEBIDX_SHIFT - EDMA_TPCC_CCNT_SRCEBIDX_SHIFT);
494 #endif
496 /* Parameters not programmed are : PRIV = 0; PRIVID = 0; */
497 paramSet.opt = 0;
498 paramSet.opt |= (
499 ((uint32_t)(pSetCfg->transferType == (uint8_t)EDMA3_SYNC_AB) << EDMA_TPCC_OPT_SYNCDIM_SHIFT) |
500 ((uint32_t)(pSetCfg->sourceAddressingMode == (uint8_t)EDMA3_ADDRESSING_MODE_FIFO_WRAP) <<
501 EDMA_TPCC_OPT_SAM_SHIFT) |
502 ((uint32_t)(pSetCfg->destinationAddressingMode == (uint8_t)EDMA3_ADDRESSING_MODE_FIFO_WRAP) <<
503 EDMA_TPCC_OPT_DAM_SHIFT) |
504 ((uint32_t)pSetCfg->fifoWidth << EDMA_TPCC_OPT_FWID_SHIFT) |
505 ((uint32_t)pSetCfg->transferCompletionCode << EDMA_TPCC_OPT_TCC_SHIFT) |
506 ((uint32_t)pSetCfg->isStaticSet << EDMA_TPCC_OPT_STATIC_SHIFT) |
507 ((uint32_t)pSetCfg->isEarlyCompletion << EDMA_TPCC_OPT_TCCMODE_SHIFT) |
508 ((uint32_t)pSetCfg->isFinalTransferInterruptEnabled << EDMA_TPCC_OPT_TCINTEN_SHIFT) |
509 ((uint32_t)pSetCfg->isIntermediateTransferInterruptEnabled << EDMA_TPCC_OPT_ITCINTEN_SHIFT) |
510 ((uint32_t)pSetCfg->isFinalChainingEnabled << EDMA_TPCC_OPT_TCCHEN_SHIFT) |
511 ((uint32_t)pSetCfg->isIntermediateChainingEnabled << EDMA_TPCC_OPT_ITCCHEN_SHIFT)
512 );
513 EDMA3SetPaRAM(ccBaseAddr, paramId, ¶mSet);
514 }
515 #else
516 /**
517 * @b Description
518 * @n
519 * Utility function for configuring a PaRAM Set.
520 * Note: HW_WR_FIELD32 APIs are avoided for (assumed) efficiency when writing
521 * param fields (avoid unnecessary masking because fields are defined to be right
522 * sized (e.g aCount is uint16_t, matching Param ACNT size).
523 *
524 * @param[in] ccBaseAddr CC base address.
525 * @param[in] paramId PaRAM Set Id.
526 * @param[in] pSetCfg Pointer to PaRAM Set configuration.
527 *
528 * \ingroup EDMA_INTERNAL_FUNCTION
529 *
530 * @retval
531 * None.
532 */
533 #ifdef EDMA_EXTENDED_B_INDICES
534 /*! Returns the 8-bit extension beyond 16-bits of the 32-bit b-index */
535 #define EDMA_B_INDX_EXTENSION(x) (((x) >> 16U) & 0x000000FFU)
536 #endif
538 static void EDMA_paramSetConfig_assist (uint32_t ccBaseAddr, uint16_t paramId,
539 EDMA_paramSetConfig_t const *pSetCfg)
540 {
541 uint32_t opt;
542 uint32_t paramStartAddr = ccBaseAddr + EDMA_TPCC_OPT((uint32_t)paramId);
543 uint32_t paramFieldAddr;
545 paramFieldAddr = paramStartAddr;
547 /* opt parameters not programmed are : PRIV = 0; PRIVID = 0; */
548 opt = (
549 ((uint32_t)(pSetCfg->transferType == (uint8_t)EDMA3_SYNC_AB) << EDMA_TPCC_OPT_SYNCDIM_SHIFT) |
550 ((uint32_t)(pSetCfg->sourceAddressingMode == (uint8_t)EDMA3_ADDRESSING_MODE_FIFO_WRAP) <<
551 EDMA_TPCC_OPT_SAM_SHIFT) |
552 ((uint32_t)(pSetCfg->destinationAddressingMode == (uint8_t)EDMA3_ADDRESSING_MODE_FIFO_WRAP) <<
553 EDMA_TPCC_OPT_DAM_SHIFT) |
554 ((uint32_t)pSetCfg->fifoWidth << EDMA_TPCC_OPT_FWID_SHIFT) |
555 ((uint32_t)pSetCfg->transferCompletionCode << EDMA_TPCC_OPT_TCC_SHIFT) |
556 ((uint32_t)pSetCfg->isStaticSet << EDMA_TPCC_OPT_STATIC_SHIFT) |
557 ((uint32_t)pSetCfg->isEarlyCompletion << EDMA_TPCC_OPT_TCCMODE_SHIFT) |
558 ((uint32_t)pSetCfg->isFinalTransferInterruptEnabled << EDMA_TPCC_OPT_TCINTEN_SHIFT) |
559 ((uint32_t)pSetCfg->isIntermediateTransferInterruptEnabled << EDMA_TPCC_OPT_ITCINTEN_SHIFT) |
560 ((uint32_t)pSetCfg->isFinalChainingEnabled << EDMA_TPCC_OPT_TCCHEN_SHIFT) |
561 ((uint32_t)pSetCfg->isIntermediateChainingEnabled << EDMA_TPCC_OPT_ITCCHEN_SHIFT)
562 );
563 HW_WR_REG32(paramFieldAddr, opt);
564 paramFieldAddr += sizeof(uint32_t);
566 /* SRC */
567 HW_WR_REG32(paramFieldAddr, pSetCfg->sourceAddress);
568 paramFieldAddr += sizeof(uint32_t);
570 /* BCNT_ACNT */
571 HW_WR_REG32(paramFieldAddr, ((uint32_t)pSetCfg->bCount << EDMA_TPCC_ABCNT_BCNT_SHIFT) |
572 ((uint32_t)pSetCfg->aCount << EDMA_TPCC_ABCNT_ACNT_SHIFT));
573 paramFieldAddr += sizeof(uint32_t);
575 /* DST */
576 HW_WR_REG32(paramFieldAddr, pSetCfg->destinationAddress);
577 paramFieldAddr += sizeof(uint32_t);
579 /* DSTBIDX_SRCBIDX */
580 /* Note: the cast to uint16_t must be done for source index because it is signed 16
581 and simply casting to unsigned 32-bit does not make it signed, it simply extends
582 the sign to 32-bit. For extended B indices feature, the indices are 32-bit signed
583 but this code will work as expected i.e it will read the 16 LSbits of the indices */
584 HW_WR_REG32(paramFieldAddr,
585 ((uint32_t)((uint16_t)pSetCfg->destinationBindex) << EDMA_TPCC_BIDX_DBIDX_SHIFT) |
586 ((uint32_t)((uint16_t)pSetCfg->sourceBindex) << EDMA_TPCC_BIDX_SBIDX_SHIFT));
587 paramFieldAddr += sizeof(uint32_t);
589 /* BCNTRLD_LINK */
590 HW_WR_REG32(paramFieldAddr, ((uint32_t)pSetCfg->bCountReload << EDMA_TPCC_LNK_BCNTRLD_SHIFT) |
591 ((uint32_t)pSetCfg->linkAddress << EDMA_TPCC_LNK_LINK_SHIFT));
592 paramFieldAddr += sizeof(uint32_t);
594 /* DSTCIDX_SRCCIDX */
595 /* Note: the cast to uint16_t must be done for source index because it is signed 16
596 and simply casting to unsigned 32-bit does not make it signed, it simply extends
597 the sign to 32-bit */
598 HW_WR_REG32(paramFieldAddr,
599 ((uint32_t)((uint16_t)pSetCfg->destinationCindex) << EDMA_TPCC_CIDX_DCIDX_SHIFT) |
600 ((uint32_t)((uint16_t)pSetCfg->sourceCindex) << EDMA_TPCC_CIDX_SCIDX_SHIFT));
601 paramFieldAddr += sizeof(uint32_t);
603 #ifdef EDMA_EXTENDED_B_INDICES
604 /* CCNT, SRCEBIDX, DSTEBIDX */
605 HW_WR_REG32(paramFieldAddr,
606 ((uint32_t)pSetCfg->cCount << EDMA_TPCC_CCNT_CCNT_SHIFT) |
607 (EDMA_B_INDX_EXTENSION(pSetCfg->sourceBindex) << EDMA_TPCC_CCNT_SRCEBIDX_SHIFT) |
608 (EDMA_B_INDX_EXTENSION(pSetCfg->destinationBindex) << EDMA_TPCC_CCNT_DSTEBIDX_SHIFT)
609 );
610 #else
611 /* CCNT */
612 HW_WR_REG32(paramFieldAddr, (uint32_t)pSetCfg->cCount << EDMA_TPCC_CCNT_CCNT_SHIFT);
613 #endif
614 }
615 #endif
617 /**
618 * @b Description
619 * @n
620 * Transfer Completion Isr which will trigger when a channel transfer completes
621 * and if the channel is configured for a non-NULL completion call back function
622 * during channel configuration.
623 * Checks which transfer completion codes are set and
624 * calls the corresponding registered application call back function.
625 *
626 * @param[in] arg EDMA handle which was set when Isr was registered using
627 * HwiP_create OSAL API.
628 *
629 * \ingroup EDMA_INTERNAL_FUNCTION
630 *
631 * @retval
632 * None.
633 */
634 static void EDMA_transferComplete_isr (uintptr_t arg)
635 {
636 EDMA_Handle handle = (EDMA_Handle) arg;
637 EDMA_Config_t *edmaConfig;
638 EDMA_Object_t *edmaObj;
639 EDMA_hwAttrs_t const *hwAttrs;
640 uint32_t ccBaseAddr;
641 uint32_t lowIntrStatus, highIntrStatus;
642 uint8_t transCompCode;
643 uint8_t half, full;
645 #ifdef EDMA_DBG
646 edmaDbg.transCompIsrCount++;
647 #endif
649 edmaConfig = (EDMA_Config_t *) handle;
650 edmaObj = edmaConfig->object;
652 hwAttrs = edmaConfig->hwAttrs;
653 ccBaseAddr = hwAttrs->CCbaseAddress;
655 #ifdef SOC_TPR12
656 /* Global interrupt must be set in the status */
657 // DebugP_assert((HW_RD_REG32(hwAttrs->CCcompletionInterruptsAggregatorStatusRegAddress) &
658 // (1U << EDMA_TPCC_INTAGG_TPCC_INTG__POS)) == (1U << EDMA_TPCC_INTAGG_TPCC_INTG__POS));
659 #endif
661 half = EDMA_NUM_DMA_CHANNELS/2U;
662 full = EDMA_NUM_DMA_CHANNELS;
664 /* scan only whose interrupts are enabled */
665 lowIntrStatus = EDMA3GetIntrStatus(ccBaseAddr) & HW_RD_REG32(ccBaseAddr + EDMA_TPCC_IER);
666 highIntrStatus = EDMA3IntrStatusHighGet(ccBaseAddr) & HW_RD_REG32(ccBaseAddr + EDMA_TPCC_IERH);
667 if ((lowIntrStatus != 0U) || (highIntrStatus != 0U))
668 {
669 /* scan low status */
670 for (transCompCode = 0U; transCompCode < half; transCompCode++)
671 {
672 if ((lowIntrStatus & ((uint32_t)1 << transCompCode)) == ((uint32_t)1 << transCompCode))
673 {
674 /* clear interrupt */
675 EDMA3ClrIntr(ccBaseAddr, (uint32_t)transCompCode);
677 /* call registered call back function for the transferCompletionCode */
678 if (edmaObj->transferCompleteCallbackFxn[transCompCode] != NULL)
679 {
680 (*edmaObj->transferCompleteCallbackFxn[transCompCode])(
681 edmaObj->transferCompleteCallbackFxnArg[transCompCode],
682 transCompCode);
683 }
684 else
685 {
686 /* interrupt indicated but no call back function */
687 // DebugP_assert(0);
688 }
689 }
690 }
692 /* scan high status */
693 for (transCompCode = half; transCompCode < full; transCompCode++)
694 {
695 if ((highIntrStatus & ((uint32_t)1 << (transCompCode -half))) ==
696 ((uint32_t)1 << (transCompCode - half)))
697 {
698 /* clear interrupt */
699 EDMA3ClrIntr(ccBaseAddr, (uint32_t)transCompCode);
701 /* call registered call back function for the transferCompletionCode */
702 if (edmaObj->transferCompleteCallbackFxn[transCompCode] != NULL)
703 {
704 (*edmaObj->transferCompleteCallbackFxn[transCompCode])(
705 edmaObj->transferCompleteCallbackFxnArg[transCompCode],
706 transCompCode);
707 }
708 else
709 {
710 /* interrupt indicated but no call back function */
711 // DebugP_assert(0);
712 }
713 }
714 }
715 }
717 #ifdef SOC_TPR12
718 /* clear interrupt */
719 HW_WR_REG32(hwAttrs->CCcompletionInterruptsAggregatorStatusRegAddress, (1U << EDMA_TPCC_INTAGG_TPCC_INTG__POS));
720 #endif
722 /* check conditions again, if any detected, then notify hardware.
723 The alternative is to do the above code in a loop but this can hold up
724 other interrupts in the system as multiple transfers could complete
725 in this time given the pocessing of call-back functions also, so the IEVAL
726 approach is preferred. For more details,
727 see EDMA User Guide section "EDMA3 Interrupt Servicing" */
728 lowIntrStatus = EDMA3GetIntrStatus(ccBaseAddr) & HW_RD_REG32(ccBaseAddr + EDMA_TPCC_IER);
729 highIntrStatus = EDMA3IntrStatusHighGet(ccBaseAddr) & HW_RD_REG32(ccBaseAddr + EDMA_TPCC_IERH);
730 if ((lowIntrStatus != 0) || (highIntrStatus != 0))
731 {
732 #ifdef EDMA_DBG
733 edmaDbg.transCompIsrIevalCount++;
734 #endif
735 /* Based on GINT (Global interrupt) */
736 HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_IEVAL, EDMA_TPCC_IEVAL_EVAL, 1);
737 }
738 }
740 /**
741 * @b Description
742 * @n
743 * Utility function to update queue entry event number and event type
744 * information as read from the QxEy registers. Exploits the symmetric structure
745 * of these registers.
746 *
747 * @param[in] qEntry0Addr Address of queue entry 0.
748 * @param[in] qEntryAddrJump Queue entry address jump.
749 * @param[in] numEntries Number of entries to iterate on.
750 * @param[in,out] qEntryIndx Pointer to queue entry index. Will be incremented
751 * in a circular manner.
752 * @param[out] qEntry Pointer to queue Entry array which needs to be populated.
753 *
754 * \ingroup EDMA_INTERNAL_FUNCTION
755 *
756 * @retval
757 * None.
758 */
759 static void EDMA_update_queue_entries (
760 uint32_t qEntry0Addr,
761 uint32_t qEntryAddrJump,
762 uint8_t numEntries,
763 uint8_t *qEntryIndx,
764 EDMA_queueEntryInfo_t *qEntry)
765 {
766 uint8_t qEntryCount;
767 uint32_t qEntryAddr;
769 for (qEntryCount = 0; qEntryCount < numEntries; qEntryCount++)
770 {
771 qEntryAddr = qEntry0Addr + *qEntryIndx * qEntryAddrJump;
773 qEntry[qEntryCount].eventNumber =
774 HW_RD_FIELD32(qEntryAddr, EDMA_TPCC_QNE0_ENUM);
776 qEntry[qEntryCount].eventType =
777 HW_RD_FIELD32(qEntryAddr, EDMA_TPCC_QNE0_ETYPE);
779 *qEntryIndx += 1U;
780 if (*qEntryIndx >= EDMA_NUM_QUEUE_ENTRIES)
781 {
782 *qEntryIndx = 0U;
783 }
784 }
785 }
787 /**
788 * @b Description
789 * @n
790 * Utility function to check if any of the EDMA errors happened. Suitable
791 * for polling purposes.
792 *
793 * @param[in] ccBaseAddr CC base address.
794 *
795 * \ingroup EDMA_INTERNAL_FUNCTION
796 *
797 * @retval
798 * true if any EDMA error else false
799 */
800 static bool EDMA_isError(uint32_t ccBaseAddr)
801 {
802 return((EDMA3GetErrIntrStatus(ccBaseAddr) != 0U) ||
803 (EDMA3ErrIntrHighStatusGet(ccBaseAddr) != 0U) ||
804 (EDMA3QdmaGetErrIntrStatus(ccBaseAddr) != 0U) ||
805 (EDMA3GetCCErrStatus(ccBaseAddr) != 0U));
806 }
808 /**
809 * @b Description
810 * @n
811 * Utility function to get error status information.
812 *
813 * @param[in] hwAttrs pointer to hardware attributes.
814 * @param[in] ccBaseAddr cc base address.
815 * @param[out] errorInfo pointer to error information in with status of errors
816 * will be populated.
817 *
818 * \ingroup EDMA_INTERNAL_FUNCTION
819 *
820 * @retval
821 * None.
822 */
823 static void EDMA_getErrorStatusInfo(EDMA_hwAttrs_t const *hwAttrs, uint32_t ccBaseAddr,
824 EDMA_errorInfo_t *errorInfo)
825 {
826 uint8_t queueId;
827 uint8_t channelId;
828 uint8_t half, full;
829 uint32_t shift;
830 uint32_t errorStatus;
832 errorInfo->numEventQueues = hwAttrs->numEventQueues;
834 /* DMA channels status processing */
835 half = EDMA_NUM_DMA_CHANNELS/2U;
836 full = EDMA_NUM_DMA_CHANNELS;
838 /* low processing */
839 errorStatus = EDMA3GetErrIntrStatus(ccBaseAddr);
840 for (channelId = 0U; channelId < half; channelId++)
841 {
842 errorInfo->isDmaChannelEventMiss[channelId] = (bool)((errorStatus >> channelId) & 1U);
843 }
844 /* high processing */
845 errorStatus = EDMA3ErrIntrHighStatusGet(ccBaseAddr);
846 for (channelId = half; channelId < full; channelId++)
847 {
848 errorInfo->isDmaChannelEventMiss[channelId] =
849 (bool)((errorStatus >> (channelId - half)) & 1U);
850 }
852 /* QDMA channels status processing */
853 errorStatus = EDMA3QdmaGetErrIntrStatus(ccBaseAddr);
854 for (channelId = 0U; channelId < EDMA_NUM_QDMA_CHANNELS; channelId++)
855 {
856 errorInfo->isQdmaChannelEventMiss[channelId] = (bool)((errorStatus >> channelId) & 1U);
857 }
859 /* CC error status processing */
860 errorStatus = EDMA3GetCCErrStatus(ccBaseAddr);
861 for(queueId = 0U; queueId < hwAttrs->numEventQueues; queueId++)
862 {
863 shift = (uint32_t)queueId * (uint32_t)(EDMA_TPCC_CCERR_QTHRXCD1_SHIFT -
864 EDMA_TPCC_CCERR_QTHRXCD0_SHIFT);
865 errorInfo->isEventQueueThresholdExceeded[queueId] = (bool)((errorStatus >> shift) & 1U);
866 }
867 errorInfo->isOutstandingTransferCompletionTransfersExceededLimit =
868 (bool)((errorStatus >> EDMA_TPCC_CCERR_TCERR_SHIFT) & 1U);
869 }
871 /**
872 * @b Description
873 * @n
874 * Utility function to clear EDMA errors.
875 *
876 * @param[in] hwAttrs pointer to hardware attributes.
877 * @param[in] ccBaseAddr cc base address.
878 * @param[in] errorInfo pointer to error information which is used to determine
879 * what errors will be cleared so that hardware can detect
880 * new errors.
881 *
882 * \ingroup EDMA_INTERNAL_FUNCTION
883 *
884 * @retval
885 * None.
886 */
887 static void EDMA_clearErrors(EDMA_hwAttrs_t const *hwAttrs, uint32_t ccBaseAddr,
888 EDMA_errorInfo_t const *errorInfo)
889 {
890 uint8_t queueId;
891 uint8_t channelId;
892 uint8_t full;
893 uint32_t shift;
895 full = EDMA_NUM_DMA_CHANNELS;
897 /* clear conditions that were detected */
898 /* dma */
899 for (channelId = 0U; channelId < full; channelId++)
900 {
901 if (errorInfo->isDmaChannelEventMiss[channelId] == true)
902 {
903 EDMA3ClrMissEvt(ccBaseAddr, (uint32_t)channelId);
904 }
905 }
906 /* qdma */
907 for (channelId = 0U; channelId < EDMA_NUM_QDMA_CHANNELS; channelId++)
908 {
909 if (errorInfo->isQdmaChannelEventMiss[channelId] == true)
910 {
911 EDMA3QdmaClrMissEvt(ccBaseAddr, (uint32_t)channelId);
912 }
913 }
914 /* queues */
915 for (queueId = 0U; queueId < hwAttrs->numEventQueues; queueId++)
916 {
917 shift = (uint32_t)queueId * (EDMA_TPCC_CCERRCLR_QTHRXCD1_SHIFT - EDMA_TPCC_CCERRCLR_QTHRXCD0_SHIFT);
918 if (errorInfo->isEventQueueThresholdExceeded[queueId] == true)
919 {
920 EDMA3ClrCCErr(ccBaseAddr, ((uint32_t)1 << shift));
921 }
922 }
923 /* outstanding transfer completion error */
924 if (errorInfo->isOutstandingTransferCompletionTransfersExceededLimit == true)
925 {
926 EDMA3ClrCCErr(ccBaseAddr, ((uint32_t)1 << EDMA_TPCC_CCERRCLR_TCERR_SHIFT));
927 }
928 }
930 int32_t EDMA_getErrorStatus(EDMA_Handle handle, bool *isAnyError, EDMA_errorInfo_t *errorInfo)
931 {
932 EDMA_Config_t *edmaConfig;
933 EDMA_hwAttrs_t const *hwAttrs;
934 uint32_t ccBaseAddr;
935 int32_t errorCode = EDMA_NO_ERROR;
937 #ifdef EDMA_PARAM_CHECK
938 if (handle == NULL)
939 {
940 errorCode = EDMA_E_INVALID__HANDLE_NULL;
941 }
942 #endif
943 if (errorCode == EDMA_NO_ERROR)
944 {
945 edmaConfig = (EDMA_Config_t *) handle;
946 hwAttrs = edmaConfig->hwAttrs;
947 ccBaseAddr = hwAttrs->CCbaseAddress;
949 if (*isAnyError = EDMA_isError(ccBaseAddr))
950 {
951 EDMA_getErrorStatusInfo(hwAttrs, ccBaseAddr, errorInfo);
952 EDMA_clearErrors(hwAttrs, ccBaseAddr, errorInfo);
953 }
954 }
956 return(errorCode);
957 }
959 /**
960 * @b Description
961 * @n
962 * CC error isr which will trigger when any CC errors happen. It will call
963 * application registered error call back function with the error information.
964 *
965 * @param[out] arg @ref EDMA_Handle which was set when Isr was registered
966 * using OSAL API HwiP_create.
967 *
968 * \ingroup EDMA_INTERNAL_FUNCTION
969 *
970 * @retval
971 * None.
972 */
973 static void EDMA_error_isr (uintptr_t arg)
974 {
975 EDMA_Handle handle = (EDMA_Handle) arg;
976 EDMA_Config_t *edmaConfig;
977 EDMA_Object_t *edmaObj;
978 EDMA_hwAttrs_t const *hwAttrs;
979 uint32_t ccBaseAddr;
980 EDMA_errorInfo_t errorInfo;
982 #ifdef EDMA_DBG
983 edmaDbg.errorIsrCount++;
984 #endif
986 edmaConfig = (EDMA_Config_t *) handle;
987 edmaObj = edmaConfig->object;
988 hwAttrs = edmaConfig->hwAttrs;
989 ccBaseAddr = hwAttrs->CCbaseAddress;
991 EDMA_getErrorStatusInfo(hwAttrs, ccBaseAddr, &errorInfo);
993 /* application call back processing */
994 if (edmaObj->errorCallbackFxn != NULL)
995 {
996 (*edmaObj->errorCallbackFxn)(handle, &errorInfo);
997 }
999 EDMA_clearErrors(hwAttrs, ccBaseAddr, &errorInfo);
1001 /* Check conditions again and set EEVAL if any detected, this procedure is
1002 similar to the transfer completion isr's (EEVAL similar to IEVAL) */
1003 if (EDMA_isError(ccBaseAddr))
1004 {
1005 HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_EEVAL, EDMA_TPCC_EEVAL_EVAL, (uint32_t)1);
1006 }
1007 }
1009 static bool EDMA_isTransferControllerError(uint32_t tcBaseAddr)
1010 {
1011 uint32_t errStatRegAddr = tcBaseAddr + EDMA_TC_ERRSTAT;
1013 return(HW_RD_REG32(errStatRegAddr) != 0);
1014 }
1016 static void EDMA_getTransferControllerErrorStatusInfo(uint32_t tcBaseAddr,
1017 EDMA_transferControllerErrorInfo_t *errorInfo)
1018 {
1019 uint32_t errStatRegAddr, errDetRegAddr;
1020 EDMA_transferControllerBusErrorInfo_t *busErrorInfo;
1022 busErrorInfo = &errorInfo->busErrorInfo;
1024 /* ERRSTAT processing */
1025 errStatRegAddr = tcBaseAddr + EDMA_TC_ERRSTAT;
1026 errorInfo->isTransferRequestError =
1027 HW_RD_FIELD32(errStatRegAddr, EDMA_TC_ERRSTAT_TRERR);
1029 errorInfo->isWriteToReservedConfigMemoryMap =
1030 HW_RD_FIELD32(errStatRegAddr, EDMA_TC_ERRSTAT_MMRAERR);
1032 errorInfo->isBusError =
1033 HW_RD_FIELD32(errStatRegAddr, EDMA_TC_ERRSTAT_BUSERR);
1035 /* ERRDET processing */
1036 errDetRegAddr = tcBaseAddr + EDMA_TC_ERRDET;
1037 if (errorInfo->isBusError == true)
1038 {
1039 busErrorInfo->errorCode =
1040 HW_RD_FIELD32(errDetRegAddr, EDMA_TC_ERRDET_STAT);
1042 busErrorInfo->transferCompletionCode =
1043 HW_RD_FIELD32(errDetRegAddr, EDMA_TC_ERRDET_TCC);
1045 busErrorInfo->isFinalChainingEnabled =
1046 HW_RD_FIELD32(errDetRegAddr, EDMA_TC_ERRDET_TCCHEN);
1048 busErrorInfo->isFinalTransferInterruptEnabled =
1049 HW_RD_FIELD32(errDetRegAddr, EDMA_TC_ERRDET_TCINTEN);
1050 }
1051 }
1053 static void EDMA_clearTransferControllerErrors(uint32_t tcBaseAddr,
1054 EDMA_transferControllerErrorInfo_t *errorInfo)
1055 {
1056 uint32_t errClrRegAddr;
1058 errClrRegAddr = tcBaseAddr + EDMA_TC_ERRCLR;
1059 HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_TRERR, errorInfo->isTransferRequestError);
1060 HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_MMRAERR, errorInfo->isWriteToReservedConfigMemoryMap);
1061 HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_BUSERR, errorInfo->isBusError);
1062 }
1064 int32_t EDMA_getTransferControllerErrorStatus(EDMA_Handle handle, uint8_t transferControllerId,
1065 bool *isAnyError, EDMA_transferControllerErrorInfo_t *errorInfo)
1066 {
1067 EDMA_Config_t *edmaConfig;
1068 EDMA_hwAttrs_t const *hwAttrs;
1069 uint32_t tcBaseAddr;
1070 int32_t errorCode = EDMA_NO_ERROR;
1072 #ifdef EDMA_PARAM_CHECK
1073 if (handle == NULL)
1074 {
1075 errorCode = EDMA_E_INVALID__HANDLE_NULL;
1076 }
1077 #endif
1079 if (errorCode == EDMA_NO_ERROR)
1080 {
1081 edmaConfig = (EDMA_Config_t *) handle;
1082 hwAttrs = edmaConfig->hwAttrs;
1083 tcBaseAddr = hwAttrs->TCbaseAddress[transferControllerId];
1085 if (*isAnyError = EDMA_isTransferControllerError(tcBaseAddr))
1086 {
1087 EDMA_getTransferControllerErrorStatusInfo(tcBaseAddr, errorInfo);
1088 EDMA_clearTransferControllerErrors(tcBaseAddr, errorInfo);
1089 errorInfo->transferControllerId = transferControllerId;
1090 }
1091 }
1093 return(errorCode);
1094 }
1096 /**
1097 * @b Description
1098 * @n
1099 * TC error isr which will trigger when any TC errors happen. It will call
1100 * application registered error call back function with the error information,
1101 * the error information will also report which transfer controller Id was
1102 * triggered.
1103 *
1104 * @param[out] arg pointer to @ref EDMA_transferControllerErrorIsrArgInfo_t which
1105 * was set when the ISR was registered using HwiP_create OSAL API.
1106 *
1107 * \ingroup EDMA_INTERNAL_FUNCTION
1108 *
1109 * @retval
1110 * None.
1111 */
1112 static void EDMA_transferController_error_isr (uintptr_t arg)
1113 {
1114 EDMA_transferControllerErrorIsrArgInfo_t *argInfo =
1115 (EDMA_transferControllerErrorIsrArgInfo_t *) arg;
1116 EDMA_Handle handle = (EDMA_Handle) argInfo->handle;
1117 uint8_t transferControllerId = argInfo->transferControllerId;
1118 EDMA_Config_t *edmaConfig;
1119 EDMA_Object_t *edmaObj;
1120 EDMA_hwAttrs_t const *hwAttrs;
1121 EDMA_transferControllerErrorInfo_t errorInfo;
1122 uint32_t tcBaseAddr;
1124 #ifdef EDMA_DBG
1125 edmaDbg.transCompErrorIsrCount++;
1126 #endif
1128 edmaConfig = (EDMA_Config_t *) handle;
1129 edmaObj = edmaConfig->object;
1130 hwAttrs = edmaConfig->hwAttrs;
1131 tcBaseAddr = hwAttrs->TCbaseAddress[transferControllerId];
1133 errorInfo.transferControllerId = transferControllerId;
1135 EDMA_getTransferControllerErrorStatusInfo(tcBaseAddr, &errorInfo);
1137 /* application call back */
1138 if (edmaObj->transferControllerErrorCallbackFxn != NULL)
1139 {
1140 (*edmaObj->transferControllerErrorCallbackFxn)(handle, &errorInfo);
1141 }
1143 /* clear conditions */
1144 EDMA_clearTransferControllerErrors(tcBaseAddr, &errorInfo);
1146 /* Check conditions again and set EVAL if any detected, this procedure is
1147 similar to the transfer completion isr's (EVAL similar to IEVAL) */
1148 if (EDMA_isTransferControllerError(tcBaseAddr))
1149 {
1150 HW_WR_FIELD32(tcBaseAddr + EDMA_TC_ERRCMD, EDMA_TC_ERRCMD_EVAL, (uint32_t)1);
1151 }
1152 }
1154 /**
1155 * @b Description
1156 * @n
1157 * Aggregated CC and TC error isr which will trigger when any CC or TC errors happen. It will call
1158 * corresponding application registered error call back functions with the error information.
1159 *
1160 * @param[out] arg @ref EDMA_Handle which was set when Isr was registered
1161 * using OSAL API HwiP_create.
1162 *
1163 * \ingroup EDMA_INTERNAL_FUNCTION
1164 *
1165 * @retval
1166 * None.
1167 */
1168 #ifdef SOC_TPR12
1169 static void EDMA_aggregated_error_transferController_error_isr (uintptr_t arg)
1170 {
1171 uint32_t errInt, tc, tcErr;
1172 EDMA_Handle handle = (EDMA_Handle) arg;
1173 EDMA_Config_t *edmaConfig;
1174 EDMA_hwAttrs_t const *hwAttrs;
1175 EDMA_transferControllerErrorIsrArgInfo_t argInfo;
1177 edmaConfig = (EDMA_Config_t *) handle;
1178 hwAttrs = edmaConfig->hwAttrs;
1180 #ifdef EDMA_DBG
1181 edmaDbg.aggregatedErrorTransCompErrorIsrCount++;
1182 #endif
1184 /* CC error processing */
1185 errInt = HW_RD_REG32(hwAttrs->CCerrorInterruptsAggregatorStatusRegAddress) & (1U << EDMA_TPCC_ERRAGG_TPCC_EERINT__POS);
1186 if (errInt != 0U)
1187 {
1188 /* clear error. This is done before processing the error because there is the
1189 * EEVAL processing there so this clearance needs to be done before-hand
1190 * TODO: Is the ideal sequence to clear this one inside the error_isr
1191 * at the time of its clearing the conditions? */
1192 HW_WR_REG32(hwAttrs->CCerrorInterruptsAggregatorStatusRegAddress, (1U << EDMA_TPCC_ERRAGG_TPCC_EERINT__POS));
1194 EDMA_error_isr(arg);
1195 }
1197 /* TC error processing */
1198 argInfo.handle = handle;
1199 for(tc = 0; tc < hwAttrs->numEventQueues; tc++)
1200 {
1201 tcErr = HW_RD_REG32(hwAttrs->CCerrorInterruptsAggregatorStatusRegAddress) &
1202 (1U << (EDMA_TPCC_ERRAGG_TPTC_MIN_ERR__POS + tc));
1204 if (tcErr != 0U)
1205 {
1206 /* clear error. This is done before processing the error because there is the
1207 * EEVAL processing there so this clearance needs to be done before-hand
1208 * TODO_TPR12: Is the ideal sequence to clear this one inside the error_isr
1209 * at the time of its clearing the conditions? */
1210 HW_WR_REG32(hwAttrs->CCerrorInterruptsAggregatorStatusRegAddress, tcErr);
1212 argInfo.transferControllerId = tc;
1213 EDMA_transferController_error_isr((uintptr_t) &argInfo);
1214 }
1215 }
1216 }
1217 #endif
1219 /**
1220 * @b Description
1221 * @n
1222 * Utility API to configure queue threshold. It exploits the symmetric
1223 * structure of QWMTHR(A/B) registers.
1224 *
1225 * @param[in] ccBaseAddr CC base address.
1226 * @param[in] queueId Queue Id of the queue to be configured.
1227 * @param[in] threshold Queue threshold to be configured.
1228 *
1229 * \ingroup EDMA_INTERNAL_FUNCTION
1230 *
1231 * @retval
1232 * None.
1233 */
1234 static void EDMA_configQueueThreshold(uint32_t ccBaseAddr, uint8_t queueId,
1235 uint8_t threshold)
1236 {
1237 uint32_t shift, mask;
1239 shift = (uint32_t)queueId * (EDMA_TPCC_QWMTHRA_Q1_SHIFT - EDMA_TPCC_QWMTHRA_Q0_SHIFT);
1240 mask = (uint32_t)EDMA_TPCC_QWMTHRA_Q0_MASK << shift;
1242 if (queueId <= 3U)
1243 {
1244 /* program queue threshold A reg */
1245 HW_WR_FIELD32_RAW(ccBaseAddr + EDMA_TPCC_QWMTHRA, mask, shift, (uint32_t)threshold);
1246 }
1247 else
1248 {
1249 /* program queue threshold B reg, note the B in QWMTHRB below */
1250 HW_WR_FIELD32_RAW(ccBaseAddr + EDMA_TPCC_QWMTHRB, mask, shift, (uint32_t)threshold);
1251 }
1252 }
1254 /**
1255 * @b Description
1256 * @n
1257 * Utility API to configure queue priority. It exploits the symmetric
1258 * structure of QUEPRI registers.
1259 *
1260 * @param[in] ccBaseAddr CC base address.
1261 * @param[in] transferController TC (or queue) Id.
1262 * @param[in] priority Queue priority to be configured.
1263 *
1264 * \ingroup EDMA_INTERNAL_FUNCTION
1265 *
1266 * @retval
1267 * None.
1268 */
1269 static void EDMA_configQueuePriority(uint32_t ccBaseAddr, uint8_t transferController,
1270 uint8_t priority)
1271 {
1272 uint32_t shift, mask;
1274 shift = (uint32_t)transferController * (EDMA_TPCC_QUEPRI_PRIQ1_SHIFT - EDMA_TPCC_QUEPRI_PRIQ0_SHIFT);
1275 mask = (uint32_t)EDMA_TPCC_QUEPRI_PRIQ0_MASK << shift;
1276 HW_WR_FIELD32_RAW(ccBaseAddr + EDMA_TPCC_QUEPRI, mask, shift, (uint32_t)priority);
1277 }
1279 /**
1280 * @b Description
1281 * @n
1282 * Utility API to configure a transfer controller's error detection settings.
1283 *
1284 * @param[in] tcBaseAddr TC base address.
1285 * @param[in] isEnableAllErrors true if all error checking is to be enabled.
1286 * @param[in] config Pointer to @ref EDMA_transferControllerErrorConfig_t when
1287 * selective errors are to be configured.
1288 *
1289 * \ingroup EDMA_INTERNAL_FUNCTION
1290 *
1291 * @retval
1292 * None.
1293 */
1294 static void EDMA_configTransferControllerError(uint32_t tcBaseAddr,
1295 bool isEnableAllErrors, EDMA_transferControllerErrorConfig_t const *config)
1296 {
1297 uint32_t errenRegAddr;
1298 bool isBusErrorEnabled, isTransferRequestErrorEnabled,
1299 isWriteToReservedConfigMemoryMapEnabled;
1301 errenRegAddr = tcBaseAddr + EDMA_TC_ERREN;
1302 if (isEnableAllErrors == true)
1303 {
1304 isBusErrorEnabled = true;
1305 isTransferRequestErrorEnabled = true;
1306 isWriteToReservedConfigMemoryMapEnabled = true;
1307 }
1308 else
1309 {
1310 isBusErrorEnabled = config->isBusErrorEnabled;
1311 isTransferRequestErrorEnabled = config->isTransferRequestErrorEnabled;
1312 isWriteToReservedConfigMemoryMapEnabled =
1313 config->isWriteToReservedConfigMemoryMapEnabled;
1314 }
1315 HW_WR_FIELD32(errenRegAddr, EDMA_TC_ERREN_BUSERR, isBusErrorEnabled);
1316 HW_WR_FIELD32(errenRegAddr, EDMA_TC_ERREN_TRERR, isTransferRequestErrorEnabled);
1317 HW_WR_FIELD32(errenRegAddr, EDMA_TC_ERREN_MMRAERR, isWriteToReservedConfigMemoryMapEnabled);
1318 }
1320 /**
1321 * @b Description
1322 * @n
1323 * Utility function for starting a transfer.
1324 *
1325 * @param[in] handle EDMA handle.
1326 * @param[in] channelId channel Id.
1327 * @param[in] channelType channed Type.
1328 * @param[in] isStaticSet true if STATIC bit is to be set else false.
1329 *
1330 * \ingroup EDMA_INTERNAL_FUNCTION
1331 *
1332 * @retval
1333 * one of @ref EDMA_ERROR_CODES
1334 */
1335 static inline int32_t EDMA_startTransfer_assist(EDMA_Handle handle, uint8_t channelId,
1336 uint8_t channelType, bool isStaticSet)
1337 {
1338 EDMA_Config_t *edmaConfig;
1339 EDMA_Object_t *edmaObj;
1340 EDMA_hwAttrs_t const *hwAttrs;
1341 uint32_t ccBaseAddr;
1342 int32_t errorCode = EDMA_NO_ERROR;
1343 uint16_t paramId;
1345 #ifdef EDMA_PARAM_CHECK
1346 if (handle == NULL)
1347 {
1348 errorCode = EDMA_E_INVALID__HANDLE_NULL;
1349 }
1350 if ((channelType != (uint8_t)EDMA3_CHANNEL_TYPE_DMA) &&
1351 (channelType != (uint8_t)EDMA3_CHANNEL_TYPE_QDMA))
1352 {
1353 errorCode = EDMA_E_INVALID__DMA_CHANNEL_TYPE;
1354 }
1355 #endif
1357 if (errorCode == EDMA_NO_ERROR)
1358 {
1359 edmaConfig = (EDMA_Config_t *) handle;
1360 edmaObj = edmaConfig->object;
1361 hwAttrs = edmaConfig->hwAttrs;
1362 ccBaseAddr = hwAttrs->CCbaseAddress;
1363 }
1365 if ((errorCode == EDMA_NO_ERROR) &&
1366 (channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA))
1367 {
1368 #ifdef EDMA_PARAM_CHECK
1369 /* error checking */
1370 if (channelId >= EDMA_NUM_QDMA_CHANNELS)
1371 {
1372 errorCode = EDMA_E_INVALID__QDMA_CHANNEL_ID;
1373 }
1374 #endif
1376 if (EDMA3QdmaGetErrIntrStatus(ccBaseAddr) & ((uint32_t)1 << channelId))
1377 {
1378 errorCode = EDMA_E_UNEXPECTED__QDMA_EVENT_MISS_DETECTED;
1379 /* clear previous missed events : QSECR and QEMCR */
1380 EDMA3QdmaClrMissEvt(ccBaseAddr, (uint32_t)channelId);
1381 }
1383 if (errorCode == EDMA_NO_ERROR)
1384 {
1385 if (isStaticSet == true)
1386 {
1387 if (HW_RD_FIELD32(ccBaseAddr + EDMA_TPCC_QCHMAPN((uint32_t)channelId),
1388 EDMA_TPCC_QCHMAPN_TRWORD) == EDMA_QDMA_TRIG_WORD_OFFSET_OPT)
1389 {
1390 /* modify triggerWordValue before triggering */
1391 HW_WR_FIELD32(&edmaObj->qdmaObj[channelId].triggerWordValue,
1392 EDMA_TPCC_OPT_STATIC, 1);
1393 }
1394 else
1395 {
1396 /* update OPT field */
1397 paramId = HW_RD_FIELD32(ccBaseAddr + EDMA_TPCC_QCHMAPN((uint32_t)channelId),
1398 EDMA_TPCC_QCHMAPN_PAENTRY);
1399 HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_OPT((uint32_t)paramId), EDMA_TPCC_OPT_STATIC, 1);
1401 }
1402 }
1403 /* start transfer of specified Qdma channel, trigger word was programmed in config API */
1404 HW_WR_REG32(edmaObj->qdmaObj[channelId].triggerWordAddress,
1405 edmaObj->qdmaObj[channelId].triggerWordValue);
1406 }
1407 }
1408 if ((errorCode == EDMA_NO_ERROR) &&
1409 (channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA))
1410 {
1411 #ifdef EDMA_PARAM_CHECK
1412 /* error checking */
1413 if (channelId >= EDMA_NUM_DMA_CHANNELS)
1414 {
1415 errorCode = EDMA_E_INVALID__DMA_CHANNEL_ID;
1416 }
1417 #endif
1419 if (errorCode == EDMA_NO_ERROR)
1420 {
1421 if (channelId < 32U) {
1422 if (EDMA3GetErrIntrStatus(ccBaseAddr) & ((uint32_t)1 << channelId))
1423 {
1424 errorCode = EDMA_E_UNEXPECTED__DMA_EVENT_MISS_DETECTED;
1425 }
1426 }
1427 else
1428 {
1429 if (EDMA3ErrIntrHighStatusGet(ccBaseAddr) & ((uint32_t)1 << ((uint32_t)channelId-32U)))
1430 {
1431 errorCode = EDMA_E_UNEXPECTED__DMA_EVENT_MISS_DETECTED;
1432 }
1433 }
1435 if (errorCode != EDMA_NO_ERROR)
1436 {
1437 /* clear missed events */
1438 EDMA3ClrMissEvt(ccBaseAddr, (uint32_t)channelId);
1439 }
1440 }
1442 if (errorCode == EDMA_NO_ERROR)
1443 {
1444 /* trigger the event */
1445 EDMA3SetEvt(ccBaseAddr, (uint32_t)channelId);
1446 }
1447 }
1449 return(errorCode);
1450 }
1452 int32_t EDMA_configChannel(EDMA_Handle handle, EDMA_channelConfig_t const *config,
1453 bool isEnableChannel)
1454 {
1455 EDMA_Config_t *edmaConfig = (EDMA_Config_t *) handle;
1456 EDMA_Object_t *edmaObj;
1457 EDMA_hwAttrs_t const *hwAttrs;
1458 uint32_t ccBaseAddr;
1459 int32_t errorCode = EDMA_NO_ERROR;
1460 EDMA_paramSetConfig_t const *pSetCfg;
1461 uint8_t channelId = config->channelId;
1462 uint16_t paramId = config->paramId;
1464 edmaObj = edmaConfig->object;
1465 hwAttrs = edmaConfig->hwAttrs;
1466 ccBaseAddr = hwAttrs->CCbaseAddress;
1468 #ifdef EDMA_PARAM_CHECK
1469 /* validate configuration */
1470 errorCode = EDMA_validate_channel_config(handle, hwAttrs, config);
1471 #endif
1473 if (errorCode == EDMA_NO_ERROR)
1474 {
1475 pSetCfg = &config->paramSetConfig;
1477 EDMA3EnableChInShadowReg(ccBaseAddr, (uint32_t)config->channelType, (uint32_t)channelId);
1478 EDMA3MapChToEvtQ(ccBaseAddr, (uint32_t)config->channelType, (uint32_t)channelId,
1479 (uint32_t)config->eventQueueId);
1481 /* disable channel (event) first */
1482 errorCode = EDMA_disableChannel(handle, channelId, config->channelType);
1483 }
1484 if (errorCode == EDMA_NO_ERROR)
1485 {
1486 if (config->channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA)
1487 {
1488 /* map channel to param set */
1489 {
1490 uint32_t temp = (uint32_t) paramId;
1491 EDMA3MapQdmaChToPaRAM(ccBaseAddr, (uint32_t)channelId, &temp);
1492 }
1494 /* set trigger word */
1495 EDMA3SetQdmaTrigWord(ccBaseAddr, (uint32_t)channelId, config->qdmaParamTriggerWordOffset);
1497 edmaObj->qdmaObj[channelId].triggerWordAddress = ccBaseAddr +
1498 EDMA_TPCC_OPT((uint32_t)paramId) + config->qdmaParamTriggerWordOffset * sizeof(uint32_t);
1499 }
1500 else
1501 { /* config->channelType is EDMA3_CHANNEL_TYPE_DMA */
1502 if (hwAttrs->isChannelMapExist == true)
1503 {
1504 /* map channel to param set */
1505 EDMA3ChannelToParamMap(ccBaseAddr, (uint32_t)channelId, (uint32_t)paramId);
1506 }
1507 }
1509 EDMA3ClrIntr(ccBaseAddr, (uint32_t)pSetCfg->transferCompletionCode);
1511 EDMA_paramConfig_assist(ccBaseAddr, paramId, pSetCfg, config->transferCompletionCallbackFxn,
1512 config->transferCompletionCallbackFxnArg, edmaObj);
1514 /* store trigger word param value for Qdma channel */
1515 if (config->channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA)
1516 {
1517 uint32_t *pArray; /* param Set as array of uint32_t */
1519 pArray = (uint32_t *)(ccBaseAddr + EDMA_TPCC_OPT((uint32_t)paramId));
1520 edmaObj->qdmaObj[channelId].triggerWordValue = pArray[config->qdmaParamTriggerWordOffset];
1521 }
1523 if (isEnableChannel == true)
1524 {
1525 errorCode = EDMA_enableChannel(handle, channelId, config->channelType);
1526 }
1527 }
1529 return(errorCode);
1530 }
1532 int32_t EDMA_enableChannel(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1533 {
1534 EDMA_Config_t *edmaConfig = (EDMA_Config_t *) handle;
1535 EDMA_hwAttrs_t const *hwAttrs;
1536 uint32_t ccBaseAddr;
1537 int32_t errorCode = EDMA_NO_ERROR;
1539 hwAttrs = edmaConfig->hwAttrs;
1540 ccBaseAddr = hwAttrs->CCbaseAddress;
1542 #ifdef EDMA_PARAM_CHECK
1543 if (handle == NULL)
1544 {
1545 errorCode = EDMA_E_INVALID__HANDLE_NULL;
1546 }
1547 if (errorCode == EDMA_NO_ERROR)
1548 {
1549 errorCode = EDMA_validate_channelIdchannelType(channelId, channelType);
1550 }
1551 #endif
1553 if (errorCode == EDMA_NO_ERROR)
1554 {
1555 /* enable events, clear if applicable */
1556 if (channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA)
1557 {
1558 /* clears QSECR and QEMCR */
1559 EDMA3QdmaClrMissEvt(ccBaseAddr, (uint32_t)channelId);
1561 /* enable the Qdma event */
1562 EDMA3EnableQdmaEvt(ccBaseAddr, (uint32_t)channelId);
1564 /* From this point onwards, QDMA channel is armed and ready to be
1565 triggered by either through @ref EDMA_startTransfer API or
1566 through @ref EDMA_startTransferQdmaTrigWordWrite API */
1567 }
1568 else /* config->channelType is EDMA3_CHANNEL_TYPE_DMA */
1569 {
1570 /* clear SECR & EMCR to clean any previous NULL request */
1571 EDMA3ClrMissEvt(ccBaseAddr, (uint32_t)channelId);
1573 /* Set EESR to enable event */
1574 EDMA3EnableDmaEvt(ccBaseAddr, (uint32_t)channelId);
1576 /* From this point onwards, DMA channel is armed and ready to be
1577 triggered by the event happening in the SoC using
1578 the @ref edmaStartTransfer API */
1580 /* Note: For manual trigger we don't need to clear/enable DMA event as it is
1581 ignored when triggering channel manual (through a write to ESR) but not
1582 doing these additional operations above would require a config parameter
1583 to distinguish manual or event triggered (or both) just to serve the purpose
1584 of not executing code that is harmless/don't care for the manual trigger */
1586 }
1587 }
1588 return(errorCode);
1589 }
1591 int32_t EDMA_disableChannel(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1592 {
1593 EDMA_Config_t *edmaConfig = (EDMA_Config_t *) handle;
1594 EDMA_hwAttrs_t const *hwAttrs;
1595 uint32_t ccBaseAddr;
1596 int32_t errorCode = EDMA_NO_ERROR;
1598 hwAttrs = edmaConfig->hwAttrs;
1599 ccBaseAddr = hwAttrs->CCbaseAddress;
1601 #ifdef EDMA_PARAM_CHECK
1602 if (handle == NULL)
1603 {
1604 errorCode = EDMA_E_INVALID__HANDLE_NULL;
1605 }
1606 if (errorCode == EDMA_NO_ERROR)
1607 {
1608 errorCode = EDMA_validate_channelIdchannelType(channelId, channelType);
1609 }
1610 #endif
1612 if (errorCode == EDMA_NO_ERROR)
1613 {
1614 /* enable events, clear if applicable */
1615 if (channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA)
1616 {
1617 /* disable the Qdma event */
1618 EDMA3DisableQdmaEvt(ccBaseAddr, (uint32_t)channelId);
1620 /* clears QSECR and QEMCR */
1621 EDMA3QdmaClrMissEvt(ccBaseAddr, (uint32_t)channelId);
1623 /* From this point onwards, QDMA channel is armed and ready to be
1624 triggered by either through @ref EDMA_startTransfer API or
1625 through @ref EDMA_startTransferQdmaTrigWordWrite API */
1626 }
1627 else /* config->channelType is EDMA3_CHANNEL_TYPE_DMA */
1628 {
1629 /* disable DMA event */
1630 EDMA3DisableDmaEvt(ccBaseAddr, (uint32_t)channelId);
1632 /* clear SECR & EMCR to clean any previous NULL request */
1633 EDMA3ClrMissEvt(ccBaseAddr, (uint32_t)channelId);
1635 }
1636 }
1637 return(errorCode);
1638 }
1640 int32_t EDMA_configParamSet(EDMA_Handle handle, uint16_t paramId,
1641 EDMA_paramConfig_t const *config)
1642 {
1643 EDMA_Config_t *edmaConfig = (EDMA_Config_t *) handle;
1644 EDMA_Object_t *edmaObj;
1645 EDMA_hwAttrs_t const *hwAttrs;
1646 uint32_t ccBaseAddr;
1647 int32_t errorCode = EDMA_NO_ERROR;
1649 edmaObj = edmaConfig->object;
1650 hwAttrs = edmaConfig->hwAttrs;
1651 ccBaseAddr = hwAttrs->CCbaseAddress;
1653 #ifdef EDMA_PARAM_CHECK
1654 if (config == NULL)
1655 {
1656 errorCode = EDMA_E_INVALID__CONFIG_POINTER_NULL;
1657 }
1658 if (errorCode == EDMA_NO_ERROR)
1659 {
1660 /* validate configuration */
1661 errorCode = EDMA_validate_param_config(handle, hwAttrs, paramId, &config->paramSetConfig,
1662 config->transferCompletionCallbackFxn);
1663 }
1664 #endif
1666 if (errorCode == EDMA_NO_ERROR)
1667 {
1668 EDMA_paramConfig_assist(ccBaseAddr, paramId, &config->paramSetConfig,
1669 config->transferCompletionCallbackFxn, config->transferCompletionCallbackFxnArg,
1670 edmaObj);
1671 }
1673 return(errorCode);
1674 }
1676 static void EDMA_paramConfig_assist(uint32_t ccBaseAddr, uint16_t paramId,
1677 EDMA_paramSetConfig_t const *pSetCfg,
1678 EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn,
1679 uintptr_t transferCompletionCallbackFxnArg, EDMA_Object_t *edmaObj
1680 )
1681 {
1682 EDMA_paramSetConfig_assist(ccBaseAddr, paramId, pSetCfg);
1684 /* Register transfer completion call back function */
1685 if (transferCompletionCallbackFxn != NULL)
1686 {
1687 edmaObj->transferCompleteCallbackFxn[pSetCfg->transferCompletionCode] =
1688 transferCompletionCallbackFxn;
1690 edmaObj->transferCompleteCallbackFxnArg[pSetCfg->transferCompletionCode] =
1691 transferCompletionCallbackFxnArg;
1693 /* enable interrupt */
1694 EDMA3EnableEvtIntr(ccBaseAddr, (uint32_t)pSetCfg->transferCompletionCode);
1695 }
1696 else
1697 {
1698 /* disable interrupt, this is important for polled mode transfers we don't
1699 want interrupt to trigger (there is an assert in the interrupt to capture
1700 this situation) */
1701 EDMA3DisableEvtIntr(ccBaseAddr, (uint32_t)pSetCfg->transferCompletionCode);
1703 edmaObj->transferCompleteCallbackFxn[pSetCfg->transferCompletionCode] =
1704 NULL;
1705 }
1706 }
1708 int32_t EDMA_linkParamSets(EDMA_Handle handle, uint16_t fromParamId, uint16_t toParamId)
1709 {
1710 EDMA_Config_t *edmaConfig;
1711 EDMA_hwAttrs_t const *hwAttrs;
1712 uint32_t ccBaseAddr;
1713 int32_t errorCode = EDMA_NO_ERROR;
1715 #ifdef EDMA_PARAM_CHECK
1716 if (handle == NULL)
1717 {
1718 errorCode = EDMA_E_INVALID__HANDLE_NULL;
1719 }
1720 #endif
1722 if (errorCode == EDMA_NO_ERROR)
1723 {
1724 edmaConfig = (EDMA_Config_t *) handle;
1725 hwAttrs = edmaConfig->hwAttrs;
1726 ccBaseAddr = hwAttrs->CCbaseAddress;
1728 #ifdef EDMA_PARAM_CHECK
1729 if ((fromParamId >= hwAttrs->numParamSets) ||
1730 (toParamId >= hwAttrs->numParamSets))
1731 {
1732 errorCode = EDMA_E_INVALID__PARAM_ID;
1733 }
1734 #endif
1735 }
1736 if (errorCode == EDMA_NO_ERROR)
1737 {
1738 /* Do not use LinkChannel API, it changes toParamId's TCC to that of
1739 fromParamId and also has issue JIRA: PRSDK-1055 */
1740 #if 0
1741 EDMA3LinkChannel(ccBaseAddr, (uint32_t)fromParamId, (uint32_t)toParamId);
1742 #else
1743 HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_LNK((uint32_t)fromParamId), EDMA_TPCC_LNK_LINK,
1744 ccBaseAddr + EDMA_TPCC_OPT((uint32_t)toParamId));
1745 #endif
1746 }
1748 return(errorCode);
1749 }
1751 int32_t EDMA_chainChannels(EDMA_Handle handle, uint16_t fromParamId, uint8_t toChannelId)
1752 {
1753 EDMA_Config_t *edmaConfig;
1754 EDMA_hwAttrs_t const *hwAttrs;
1755 uint32_t ccBaseAddr;
1756 int32_t errorCode = EDMA_NO_ERROR;
1758 #ifdef EDMA_PARAM_CHECK
1759 if (handle == NULL)
1760 {
1761 errorCode = EDMA_E_INVALID__HANDLE_NULL;
1762 }
1763 if ((errorCode == EDMA_NO_ERROR) && (toChannelId >= EDMA_NUM_DMA_CHANNELS))
1764 {
1765 errorCode = EDMA_E_INVALID__DMA_CHANNEL_ID;
1766 }
1767 #endif
1769 if (errorCode == EDMA_NO_ERROR)
1770 {
1771 edmaConfig = (EDMA_Config_t *) handle;
1772 hwAttrs = edmaConfig->hwAttrs;
1773 ccBaseAddr = hwAttrs->CCbaseAddress;
1774 }
1776 #ifdef EDMA_PARAM_CHECK
1777 if ((errorCode == EDMA_NO_ERROR) && (fromParamId >= hwAttrs->numParamSets))
1778 {
1779 errorCode = EDMA_E_INVALID__PARAM_ID;
1780 }
1781 #endif
1783 if (errorCode == EDMA_NO_ERROR)
1784 {
1785 HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_OPT((uint32_t)fromParamId), EDMA_TPCC_OPT_TCC,
1786 toChannelId);
1787 }
1789 return(errorCode);
1790 }
1792 int32_t EDMA_startTransfer(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1793 {
1794 return(EDMA_startTransfer_assist(handle, channelId, channelType, false));
1795 }
1797 int32_t EDMA_startDmaTransfer(EDMA_Handle handle, uint8_t channelId)
1798 {
1799 return(EDMA_startTransfer_assist(handle, channelId,
1800 (uint8_t)EDMA3_CHANNEL_TYPE_DMA, false));
1801 }
1803 int32_t EDMA_startQdmaTransfer(EDMA_Handle handle, uint8_t channelId)
1804 {
1805 return(EDMA_startTransfer_assist(handle, channelId,
1806 (uint8_t)EDMA3_CHANNEL_TYPE_QDMA, false));
1807 }
1809 int32_t EDMA_startFinalQdmaTransfer(EDMA_Handle handle, uint8_t channelId)
1810 {
1811 return(EDMA_startTransfer_assist(handle, channelId,
1812 (uint8_t)EDMA3_CHANNEL_TYPE_QDMA, true));
1813 }
1815 int32_t EDMA_isTransferComplete(EDMA_Handle handle, uint8_t transferCompletionCode,
1816 bool *isTransferComplete)
1817 {
1818 EDMA_Config_t *edmaConfig;
1819 EDMA_Object_t *edmaObj;
1820 EDMA_hwAttrs_t const *hwAttrs;
1821 uint32_t ccBaseAddr;
1822 int32_t errorCode = EDMA_NO_ERROR;
1824 #ifdef EDMA_PARAM_CHECK
1825 if (handle == NULL)
1826 {
1827 errorCode = EDMA_E_INVALID__HANDLE_NULL;
1828 }
1829 if ((errorCode == EDMA_NO_ERROR) && (transferCompletionCode >= EDMA_NUM_TCC))
1830 {
1831 errorCode = EDMA_E_INVALID__TRANSFER_COMPLETION_CODE;
1832 }
1833 #endif
1835 if (errorCode == EDMA_NO_ERROR)
1836 {
1837 edmaConfig = (EDMA_Config_t *) handle;
1838 edmaObj = edmaConfig->object;
1840 /* Transfer completion call back function must not be registered for the
1841 transfer completion code */
1842 if (edmaObj->transferCompleteCallbackFxn[transferCompletionCode] != NULL)
1843 {
1844 errorCode = EDMA_E_UNEXPECTED__ATTEMPT_TO_TEST_COMPLETION;
1846 /* Additional protection in case user does not check for error code,
1847 make the transfer never succeed. */
1848 *isTransferComplete = false;
1849 }
1850 }
1852 if (errorCode == EDMA_NO_ERROR)
1853 {
1854 hwAttrs = edmaConfig->hwAttrs;
1855 ccBaseAddr = hwAttrs->CCbaseAddress;
1857 if (transferCompletionCode < 32U)
1858 {
1859 *isTransferComplete = (bool)((EDMA3GetIntrStatus(ccBaseAddr) &
1860 ((uint32_t)1 << transferCompletionCode)) != 0U);
1861 }
1862 else
1863 {
1864 *isTransferComplete = (bool)((EDMA3IntrStatusHighGet(ccBaseAddr) &
1865 ((uint32_t)1 << (transferCompletionCode-32U))) != 0U);
1866 }
1868 /* if transfer is complete, clear IPR(H) bit to allow new transfer */
1869 if (*isTransferComplete == true)
1870 {
1871 EDMA3ClrIntr(ccBaseAddr, (uint32_t)transferCompletionCode);
1872 }
1873 }
1875 return(errorCode);
1876 }
1878 int32_t EDMA_setDestinationAddress(EDMA_Handle handle,
1879 uint16_t paramId,
1880 uint32_t destinationAddress)
1881 {
1882 EDMA_Config_t *edmaConfig;
1883 EDMA_hwAttrs_t const *hwAttrs;
1884 uint32_t ccBaseAddr;
1885 int32_t errorCode = EDMA_NO_ERROR;
1887 #ifdef EDMA_PARAM_CHECK
1888 if (handle == NULL)
1889 {
1890 errorCode = EDMA_E_INVALID__HANDLE_NULL;
1891 }
1892 #endif
1893 if (errorCode == EDMA_NO_ERROR)
1894 {
1895 edmaConfig = (EDMA_Config_t *) handle;
1896 hwAttrs = edmaConfig->hwAttrs;
1897 ccBaseAddr = hwAttrs->CCbaseAddress;
1898 }
1900 #ifdef EDMA_PARAM_CHECK
1901 if ((errorCode == EDMA_NO_ERROR) && (paramId >= hwAttrs->numParamSets))
1902 {
1903 errorCode = EDMA_E_INVALID__PARAM_ID;
1904 }
1905 #endif
1906 if (errorCode == EDMA_NO_ERROR)
1907 {
1908 HW_WR_REG32(ccBaseAddr + EDMA_TPCC_DST((uint32_t)paramId), destinationAddress);
1909 }
1910 return(errorCode);
1911 }
1913 int32_t EDMA_setSourceAddress(EDMA_Handle handle,
1914 uint16_t paramId,
1915 uint32_t sourceAddress)
1916 {
1917 EDMA_Config_t *edmaConfig;
1918 EDMA_hwAttrs_t const *hwAttrs;
1919 uint32_t ccBaseAddr;
1920 int32_t errorCode = EDMA_NO_ERROR;
1922 #ifdef EDMA_PARAM_CHECK
1923 if (handle == NULL)
1924 {
1925 errorCode = EDMA_E_INVALID__HANDLE_NULL;
1926 }
1927 #endif
1929 if (errorCode == EDMA_NO_ERROR)
1930 {
1931 edmaConfig = (EDMA_Config_t *) handle;
1932 hwAttrs = edmaConfig->hwAttrs;
1933 ccBaseAddr = hwAttrs->CCbaseAddress;
1934 }
1936 #ifdef EDMA_PARAM_CHECK
1937 if ((errorCode == EDMA_NO_ERROR) && (paramId >= hwAttrs->numParamSets))
1938 {
1939 errorCode = EDMA_E_INVALID__PARAM_ID;
1940 }
1941 #endif
1942 if (errorCode == EDMA_NO_ERROR)
1943 {
1944 HW_WR_REG32(ccBaseAddr + EDMA_TPCC_SRC((uint32_t)paramId), sourceAddress);
1945 }
1946 return(errorCode);
1947 }
1949 static void EDMA_unregisterInterrupts(EDMA_Handle handle)
1950 {
1951 EDMA_Config_t *edmaConfig;
1952 EDMA_Object_t *edmaObj;
1953 EDMA_hwAttrs_t const *hwAttrs;
1954 uint8_t tc;
1955 bool isUnifiedErrorInterrupts;
1956 int32_t interruptNum, corepacEvent;
1958 edmaConfig = (EDMA_Config_t *) handle;
1959 edmaObj = edmaConfig->object;
1960 hwAttrs = edmaConfig->hwAttrs;
1962 /*if (edmaObj->isUsed == false) {
1963 generate error
1964 }*/
1966 if (hwAttrs->transferCompletionInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID)
1967 {
1968 #if defined(_TMS320C6X)
1969 corepacEvent = (int32_t)hwAttrs->transferCompletionInterruptNum; /* Event going in to CPU */
1970 interruptNum = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
1971 #else
1972 interruptNum = (int32_t)hwAttrs->transferCompletionInterruptNum; /* Host Interrupt vector */
1973 corepacEvent = (int32_t)hwAttrs->transferCompletionInterruptNum;
1974 #endif
1976 Osal_DisableInterrupt(corepacEvent, interruptNum);
1977 Osal_DeleteInterrupt(edmaObj->hwiTransferCompleteHandle, corepacEvent);
1978 }
1980 isUnifiedErrorInterrupts = (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID) &&
1981 (hwAttrs->errorInterruptNum == hwAttrs->transferControllerErrorInterruptNum[0]);
1982 #if defined(_TMS320C6X)
1983 corepacEvent = (int32_t)hwAttrs->errorInterruptNum; /* Event going in to CPU */
1984 interruptNum = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
1985 #else
1986 interruptNum = (int32_t)hwAttrs->errorInterruptNum; /* Host Interrupt vector */
1987 corepacEvent = (int32_t)hwAttrs->errorInterruptNum;
1988 #endif
1990 if (isUnifiedErrorInterrupts == true)
1991 {
1992 Osal_DisableInterrupt(corepacEvent, interruptNum);
1993 Osal_DeleteInterrupt(edmaObj->hwiErrorHandle, corepacEvent);
1994 }
1995 else
1996 {
1997 if (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID)
1998 {
1999 Osal_DisableInterrupt(corepacEvent, interruptNum);
2000 Osal_DeleteInterrupt(edmaObj->hwiErrorHandle, corepacEvent);
2001 }
2003 for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2004 {
2005 if (hwAttrs->transferControllerErrorInterruptNum[tc] != EDMA_INTERRUPT_NOT_CONNECTED_ID)
2006 {
2007 #if defined(_TMS320C6X)
2008 corepacEvent = (int32_t)hwAttrs->transferControllerErrorInterruptNum[tc]; /* Event going in to CPU */
2009 interruptNum = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
2010 #else
2011 interruptNum = (int32_t)hwAttrs->transferControllerErrorInterruptNum[tc]; /* Host Interrupt vector */
2012 corepacEvent = (int32_t)hwAttrs->transferControllerErrorInterruptNum[tc];
2013 #endif
2015 Osal_DisableInterrupt(corepacEvent, interruptNum);
2016 Osal_DeleteInterrupt(edmaObj->hwiTransferControllerErrorHandle[tc], corepacEvent);
2017 }
2018 }
2019 }
2021 }
2023 int32_t EDMA_close(EDMA_Handle handle)
2024 {
2025 EDMA_Config_t *edmaConfig;
2026 EDMA_Object_t *edmaObj;
2027 int32_t errorCode = EDMA_NO_ERROR;
2029 #ifdef EDMA_PARAM_CHECK
2030 if (handle == NULL)
2031 {
2032 errorCode = EDMA_E_INVALID__HANDLE_NULL;
2033 }
2034 #endif
2036 if (errorCode == EDMA_NO_ERROR)
2037 {
2038 EDMA_unregisterInterrupts(handle);
2039 edmaConfig = (EDMA_Config_t *) handle;
2040 edmaObj = edmaConfig->object;
2041 edmaObj->isUsed = false;
2042 }
2044 return(errorCode);
2045 }
2047 uint8_t EDMA_getNumInstances(void)
2048 {
2049 return((uint8_t)EDMA_NUM_CC);
2050 }
2052 int32_t EDMA_init(uint8_t instanceId)
2053 {
2054 uint32_t ccBaseAddr, tcBaseAddr, errClrRegAddr;
2055 uint8_t transCompCode, tc;
2056 uint16_t paramId;
2057 uint8_t channelId;
2058 EDMA3CCPaRAMEntry paramSet;
2059 int32_t errorCode = EDMA_NO_ERROR;
2060 const EDMA_hwAttrs_t *hwAttrs = NULL;
2062 #if (true != 1)
2063 #error define "true" is not 1
2064 #endif
2066 #ifdef EDMA_PARAM_CHECK
2067 if (instanceId > EDMA_DRV_INST_MAX)
2068 {
2069 errorCode = EDMA_E_INVALID__INSTANCE_ID;
2070 }
2071 #endif
2073 if (errorCode == EDMA_NO_ERROR)
2074 {
2075 hwAttrs = EDMA_getHwAttrs(instanceId);
2076 if (hwAttrs == NULL)
2077 {
2078 errorCode = EDMA_E_INVALID__INSTANCE_ID;
2079 }
2080 }
2082 if (errorCode == EDMA_NO_ERROR)
2083 {
2084 /* h/w reset values of param set */
2085 memset(¶mSet, 0, sizeof(paramSet));
2087 #ifdef EDMA_DBG
2088 memset(&edmaDbg, 0, sizeof(edmaDbg));
2089 #endif
2091 /* All AR devices have no-region, although internally regionId variable
2092 is initialized to 0, intentionally indicate this through API */
2093 EDMAsetRegion(0);
2095 ccBaseAddr = hwAttrs->CCbaseAddress;
2096 EDMA3Init(ccBaseAddr, (uint32_t)0);
2097 /* do things now that EDMA3Init is (unfortunately not doing) */
2098 /* disable DMA events */
2099 for (channelId = 0; channelId < EDMA_NUM_DMA_CHANNELS; channelId++)
2100 {
2101 EDMA3DisableDmaEvt(ccBaseAddr, (uint32_t)channelId);
2102 EDMA3ClrEvt(ccBaseAddr, (uint32_t)channelId);
2103 EDMA3ClrMissEvt(ccBaseAddr, (uint32_t)channelId);
2104 }
2105 /* disable and clear event interrupts */
2106 for (transCompCode = 0; transCompCode < EDMA_NUM_TCC; transCompCode++)
2107 {
2108 EDMA3DisableEvtIntr(ccBaseAddr, (uint32_t)transCompCode);
2109 EDMA3ClrIntr(ccBaseAddr, (uint32_t)transCompCode);
2110 }
2111 for (channelId = 0; channelId < EDMA_NUM_QDMA_CHANNELS; channelId++)
2112 {
2113 EDMA3DisableQdmaEvt(ccBaseAddr, (uint32_t)channelId);
2114 EDMA3QdmaClrMissEvt(ccBaseAddr, (uint32_t)channelId);
2115 }
2116 /* clear tansfer controller errors */
2117 for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2118 {
2119 tcBaseAddr = hwAttrs->TCbaseAddress[tc];
2120 errClrRegAddr = tcBaseAddr + EDMA_TC_ERRCLR;
2121 HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_TRERR, 1);
2122 HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_MMRAERR, 1);
2123 HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_BUSERR, 1);
2124 }
2125 /* cleanup Params, note h/w reset state is all 0s, must be done after
2126 disabling/clearning channel events (in particular QDMA) */
2127 for (paramId = 0; paramId < hwAttrs->numParamSets; paramId++)
2128 {
2129 EDMA3SetPaRAM(ccBaseAddr, (uint32_t)paramId, ¶mSet);
2130 }
2131 }
2133 return(errorCode);
2134 }
2136 int32_t EDMA_getStatusInfo(EDMA_Handle handle, EDMA_statusInfo_t *status)
2137 {
2138 EDMA_Config_t *edmaConfig;
2139 EDMA_hwAttrs_t const *hwAttrs;
2140 uint32_t ccBaseAddr;
2141 uint8_t queueId;
2142 EDMA_queueStatusInfo_t *qStatus;
2143 uint8_t qEntryIndx, numOutstandingEntries;
2144 uint32_t qStatRegAddr, qEntry0Addr, qEntryAddrJump, ccStatRegAddr;
2145 int32_t errorCode = EDMA_NO_ERROR;
2147 #ifdef EDMA_PARAM_CHECK
2148 if (handle == NULL)
2149 {
2150 errorCode = EDMA_E_INVALID__HANDLE_NULL;
2151 }
2152 if ((errorCode == EDMA_NO_ERROR) && (status == NULL))
2153 {
2154 errorCode = EDMA_E_INVALID__STATUS_POINTER_NULL;
2155 }
2156 #endif
2158 if (errorCode == EDMA_NO_ERROR)
2159 {
2160 edmaConfig = (EDMA_Config_t *) handle;
2161 hwAttrs = edmaConfig->hwAttrs;
2162 ccBaseAddr = hwAttrs->CCbaseAddress;
2164 /* queue status processing */
2165 for (queueId = 0; queueId < hwAttrs->numEventQueues; queueId++)
2166 {
2167 qStatRegAddr = ccBaseAddr + EDMA_TPCC_QSTATN((uint32_t)queueId);
2168 qStatus = &status->queue[queueId];
2170 qStatus->isThresholdExceeded =
2171 (bool) HW_RD_FIELD32(qStatRegAddr, EDMA_TPCC_QSTATN_THRXCD);
2173 qStatus->maxQueueEntries =
2174 (uint8_t) HW_RD_FIELD32(qStatRegAddr, EDMA_TPCC_QSTATN_WM);
2176 numOutstandingEntries =
2177 (uint8_t) HW_RD_FIELD32(qStatRegAddr, EDMA_TPCC_QSTATN_NUMVAL);
2178 qStatus->numOutstandingEntries = numOutstandingEntries;
2180 /* process outstanding queue entries first,
2181 starting from position indicated by the h/w, note queue circularity */
2182 qEntryIndx = (uint8_t) HW_RD_FIELD32(qStatRegAddr, EDMA_TPCC_QSTATN_STRTPTR);
2183 qEntry0Addr = ccBaseAddr + EDMA_TPCC_QNE0((uint8_t)queueId);
2184 qEntryAddrJump = EDMA_TPCC_QNE1(0U) - EDMA_TPCC_QNE0(0U);
2185 EDMA_update_queue_entries(qEntry0Addr, qEntryAddrJump,
2186 numOutstandingEntries,
2187 &qEntryIndx, qStatus->outstandingEntries);
2188 /* process non-outstanding entries */
2189 EDMA_update_queue_entries(qEntry0Addr, qEntryAddrJump,
2190 EDMA_NUM_QUEUE_ENTRIES - numOutstandingEntries,
2191 &qEntryIndx, qStatus->dequeuedEntries);
2192 }
2194 /* CCSTAT processing */
2195 ccStatRegAddr = ccBaseAddr + EDMA_TPCC_CCSTAT;
2197 status->numOutstandingCompletionRequests =
2198 HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_COMPACTV);
2200 status->isAnyDmaChannelActive =
2201 HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_EVTACTV);
2203 status->isAnyQdmaChannelActive =
2204 HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_QEVTACTV);
2206 status->isWriteStatusActive =
2207 HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_WSTATACTV);
2209 status->isAnyTransferActive =
2210 HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_TRACTV);
2212 status->isAnythingActive =
2213 HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_ACTV);
2214 }
2216 return(errorCode);
2217 }
2219 static EDMA_Object_t* EDMA_getFreeEdmaObj(void)
2220 {
2221 uint32_t i;
2222 EDMA_Object_t *edmaObj = NULL;
2223 for(i=0; i<EDMA_NUM_CC; i++)
2224 {
2225 if (EDMA_object[i].isUsed == FALSE)
2226 {
2227 edmaObj = &EDMA_object[i];
2228 }
2229 }
2230 return edmaObj;
2231 }
2233 EDMA_Handle EDMA_open(uint8_t instanceId, int32_t *errorCode,
2234 EDMA_instanceInfo_t *instanceInfo)
2235 {
2236 EDMA_Handle handle = NULL;
2237 EDMA_Config_t *edmaConfig = NULL;
2238 EDMA_Object_t *edmaObj = NULL;
2239 const EDMA_hwAttrs_t *hwAttrs;
2240 OsalRegisterIntrParams_t interruptRegParams;
2241 uint8_t tc;
2242 bool isUnifiedErrorInterrupts;
2243 uint32_t key;
2244 int32_t retVal = EDMA_NO_ERROR;
2246 #ifdef EDMA_PARAM_CHECK
2247 /* error checking */
2248 if (errorCode == NULL)
2249 {
2250 handle = NULL;
2251 retVal = EDMA_E_INVALID__CONFIG_POINTER_NULL;
2252 }
2253 if ((retVal == EDMA_NO_ERROR) && (instanceId > EDMA_DRV_INST_MAX))
2254 {
2255 retVal = EDMA_E_INVALID__INSTANCE_ID;
2256 handle = NULL;
2257 }
2258 if ((retVal == EDMA_NO_ERROR) && (instanceInfo == NULL))
2259 {
2260 retVal = EDMA_E_INVALID__INSTANCEINFO_POINTER_NULL;
2261 handle = NULL;
2262 }
2263 #endif
2265 if ((retVal == EDMA_NO_ERROR) &&
2266 ((EDMA_config[instanceId].hwAttrs != NULL) ||
2267 (EDMA_config[instanceId].object != NULL)))
2268 {
2269 /* Instance is already opened. */
2270 retVal = EDMA_E_UNEXPECTED__EDMA_INSTANCE_REOPEN;
2271 }
2272 if (retVal == EDMA_NO_ERROR)
2273 {
2274 hwAttrs = EDMA_getHwAttrs(instanceId);
2275 if (hwAttrs == NULL)
2276 {
2277 retVal = EDMA_E_INVALID__INSTANCE_ID;
2278 handle = NULL;
2279 }
2280 }
2282 if (retVal == EDMA_NO_ERROR)
2283 {
2284 key = HwiP_disable();
2285 edmaObj = EDMA_getFreeEdmaObj();
2286 if (edmaObj == NULL)
2287 {
2288 retVal = EDMA_E_INVALID__INSTANCE_ID;
2289 handle = NULL;
2290 }
2291 else
2292 {
2293 edmaObj->isUsed = true;
2294 }
2295 HwiP_restore(key);
2296 }
2298 if (retVal == EDMA_NO_ERROR)
2299 {
2300 EDMA_config[instanceId].hwAttrs = hwAttrs;
2301 EDMA_config[instanceId].object = edmaObj;
2302 /* Get handle for this driver instance */
2303 handle = (EDMA_Handle)&(EDMA_config[instanceId]);
2305 edmaConfig = (EDMA_Config_t *) handle;
2306 edmaObj = edmaConfig->object;
2308 #ifdef EDMA_DBG
2309 edmaDbg.edmaObj = edmaObj;
2310 #endif
2312 hwAttrs = edmaConfig->hwAttrs;
2313 instanceInfo->numEventQueues = hwAttrs->numEventQueues;
2314 instanceInfo->numParamSets = hwAttrs->numParamSets;
2315 instanceInfo->isChannelMapExist = hwAttrs->isChannelMapExist;
2316 instanceInfo->isTransferCompletionInterruptConnected =
2317 (hwAttrs->transferCompletionInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2318 instanceInfo->isErrorInterruptConnected = (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2319 for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2320 {
2321 instanceInfo->isTransferControllerErrorInterruptConnected[tc] =
2322 (hwAttrs->transferControllerErrorInterruptNum[tc] != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2323 }
2325 /* register transfer complete interrupt handler */
2326 if (hwAttrs->transferCompletionInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID)
2327 {
2328 #ifdef SOC_TPR12
2329 uint32_t mask = ~0U;
2331 //printf("status reg = %x\n", HW_RD_REG32(hwAttrs->CCcompletionInterruptsAggregatorMaskRegAddress));
2333 /* Clear all status */
2334 HW_WR_REG32(hwAttrs->CCcompletionInterruptsAggregatorStatusRegAddress, ~0U);
2336 /* Mask all interrupts except global interrupt in the aggregator */
2337 mask &= (~(1U << EDMA_TPCC_INTAGG_TPCC_INTG__POS));
2339 //printf("mask = %x\n", mask);
2341 HW_WR_REG32(hwAttrs->CCcompletionInterruptsAggregatorMaskRegAddress, mask);
2342 #endif
2344 /* Initialize with defaults */
2345 Osal_RegisterInterrupt_initParams(&interruptRegParams);
2346 /* Populate the interrupt parameters */
2347 interruptRegParams.corepacConfig.arg=(uintptr_t)handle;
2348 interruptRegParams.corepacConfig.name=(char *)("EDMA_transferComplete_isr");
2349 interruptRegParams.corepacConfig.isrRoutine=EDMA_transferComplete_isr;
2350 #if defined(_TMS320C6X)
2351 interruptRegParams.corepacConfig.corepacEventNum=(int32_t)hwAttrs->transferCompletionInterruptNum; /* Event going in to CPU */
2352 interruptRegParams.corepacConfig.intVecNum = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
2353 #else
2354 interruptRegParams.corepacConfig.priority = 0x1U;
2355 interruptRegParams.corepacConfig.intVecNum=(int32_t)hwAttrs->transferCompletionInterruptNum; /* Host Interrupt vector */
2356 interruptRegParams.corepacConfig.corepacEventNum = (int32_t)hwAttrs->transferCompletionInterruptNum;
2357 #endif
2358 /* Register interrupts */
2359 Osal_RegisterInterrupt(&interruptRegParams, &edmaObj->hwiTransferCompleteHandle);
2361 Osal_EnableInterrupt(interruptRegParams.corepacConfig.corepacEventNum, interruptRegParams.corepacConfig.intVecNum);
2363 if (edmaObj->hwiTransferCompleteHandle == NULL)
2364 {
2365 retVal = EDMA_E_OSAL__HWIP_CREATE_TRANSFER_COMPLETION_ISR_RETURNED_NULL;
2366 }
2367 }
2368 }
2370 if (retVal == EDMA_NO_ERROR)
2371 {
2372 isUnifiedErrorInterrupts = (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID) &&
2373 (hwAttrs->errorInterruptNum == hwAttrs->transferControllerErrorInterruptNum[0]);
2375 if (isUnifiedErrorInterrupts == true)
2376 {
2377 for(tc = 1; tc < hwAttrs->numEventQueues; tc++)
2378 {
2379 if (hwAttrs->errorInterruptNum != hwAttrs->transferControllerErrorInterruptNum[tc])
2380 {
2381 retVal = EDMA_E_INVALID__PARTIAL_UNIFICATION_OF_ERROR_INTERRUPTS;
2382 }
2383 }
2384 }
2385 }
2387 if (retVal == EDMA_NO_ERROR)
2388 {
2389 /* register error interrupt handler */
2390 if (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID)
2391 {
2392 /* Initialize with defaults */
2393 Osal_RegisterInterrupt_initParams(&interruptRegParams);
2394 /* Populate the interrupt parameters */
2395 interruptRegParams.corepacConfig.arg=(uintptr_t)handle;
2396 #if defined(_TMS320C6X)
2397 interruptRegParams.corepacConfig.corepacEventNum=(int32_t)hwAttrs->errorInterruptNum; /* Event going in to CPU */
2398 interruptRegParams.corepacConfig.intVecNum = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
2399 #else
2400 interruptRegParams.corepacConfig.priority = 0x1U;
2401 interruptRegParams.corepacConfig.intVecNum=(int32_t)hwAttrs->errorInterruptNum; /* Host Interrupt vector */
2402 interruptRegParams.corepacConfig.corepacEventNum = (int32_t)hwAttrs->errorInterruptNum;
2403 #endif
2406 #ifdef SOC_TPR12 //TODO_TPR12 Currently using #ifdef due to *ERR__POS defines, should they be in platform file or overkill?
2407 if (isUnifiedErrorInterrupts == true)
2408 {
2409 uint32_t mask = ~0U;
2411 //printf("status reg = %x\n", HW_RD_REG32(hwAttrs->CCerrorInterruptsAggregatorMaskRegAddress));
2413 /* Clear all status */
2414 HW_WR_REG32(hwAttrs->CCerrorInterruptsAggregatorMaskRegAddress, ~0U);
2416 /* Mask all interrupts except errors in the aggregator */
2417 mask &= (~(1U << EDMA_TPCC_ERRAGG_TPCC_EERINT__POS));
2419 for(tc = 0; tc < hwAttrs->numEventQueues; tc++)
2420 {
2421 mask &= (~(1U << (EDMA_TPCC_ERRAGG_TPTC_MIN_ERR__POS + tc)));
2422 }
2424 //printf("mask = %x\n", mask);
2426 HW_WR_REG32(hwAttrs->CCerrorInterruptsAggregatorMaskRegAddress, mask);
2428 //printf("mask written, read back = %x\n", HW_RD_REG32(hwAttrs->CCintAggMaskRegAddress));
2429 //exit(0);
2430 interruptRegParams.corepacConfig.name=(char *)("EDMA_aggregated_error_transferController_error_isr");
2431 interruptRegParams.corepacConfig.isrRoutine=EDMA_aggregated_error_transferController_error_isr;
2433 }
2434 else
2435 #endif
2436 {
2437 interruptRegParams.corepacConfig.name=(char *)("EDMA_error_isr");
2438 interruptRegParams.corepacConfig.isrRoutine=EDMA_error_isr;
2439 }
2440 /* Register interrupts */
2441 Osal_RegisterInterrupt(&interruptRegParams, &edmaObj->hwiErrorHandle);
2443 Osal_EnableInterrupt(interruptRegParams.corepacConfig.corepacEventNum, interruptRegParams.corepacConfig.intVecNum);
2446 if (edmaObj->hwiErrorHandle == NULL)
2447 {
2448 retVal = EDMA_E_OSAL__HWIP_CREATE_ERROR_ISR_RETURNED_NULL;
2449 }
2450 }
2451 }
2453 if (retVal == EDMA_NO_ERROR)
2454 {
2455 /* register transfer controller error handler */
2456 if (isUnifiedErrorInterrupts == false)
2457 {
2458 /* Initialize with defaults */
2459 Osal_RegisterInterrupt_initParams(&interruptRegParams);
2460 /* Populate the interrupt parameters */
2461 interruptRegParams.corepacConfig.arg=(uintptr_t)handle;
2462 interruptRegParams.corepacConfig.name=(char *)("EDMA_transferController_error_isr");
2463 interruptRegParams.corepacConfig.isrRoutine=EDMA_transferController_error_isr;
2465 for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2466 {
2467 if (hwAttrs->transferControllerErrorInterruptNum[tc] != EDMA_INTERRUPT_NOT_CONNECTED_ID)
2468 {
2469 edmaObj->transferControllerErrorIsrArgInfo[tc].handle = handle;
2470 edmaObj->transferControllerErrorIsrArgInfo[tc].transferControllerId = tc;
2471 interruptRegParams.corepacConfig.arg=(uintptr_t)&edmaObj->transferControllerErrorIsrArgInfo[tc];;
2472 #if defined(_TMS320C6X)
2473 interruptRegParams.corepacConfig.corepacEventNum=(int32_t)hwAttrs->transferControllerErrorInterruptNum[tc]; /* Event going in to CPU */
2474 interruptRegParams.corepacConfig.intVecNum = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
2475 #else
2476 interruptRegParams.corepacConfig.priority = 0x1U;
2477 interruptRegParams.corepacConfig.intVecNum=(int32_t)hwAttrs->transferControllerErrorInterruptNum[tc]; /* Host Interrupt vector */
2478 interruptRegParams.corepacConfig.corepacEventNum = (int32_t)hwAttrs->transferControllerErrorInterruptNum[tc];
2479 #endif
2480 /* Register interrupts */
2481 Osal_RegisterInterrupt(&interruptRegParams, &edmaObj->hwiTransferControllerErrorHandle[tc]);
2483 Osal_EnableInterrupt(interruptRegParams.corepacConfig.corepacEventNum, interruptRegParams.corepacConfig.intVecNum);
2486 if (edmaObj->hwiTransferControllerErrorHandle[tc] == NULL)
2487 {
2488 retVal = EDMA_E_OSAL__HWIP_CREATE_TRANSFER_CONTROLLER_ERROR_ISRS_RETURNED_NULL;
2489 }
2490 }
2491 }
2492 }
2493 }
2495 if (retVal != EDMA_NO_ERROR)
2496 {
2497 /* Some error occured, If the interrupts are registered then unregister it. */
2498 if (handle != NULL)
2499 {
2500 EDMA_unregisterInterrupts(handle);
2501 handle = NULL;
2502 }
2503 if (edmaObj != NULL)
2504 {
2505 key = HwiP_disable();
2506 edmaObj->isUsed = false;
2507 HwiP_restore(key);
2508 EDMA_config[instanceId].hwAttrs = NULL;
2509 EDMA_config[instanceId].object = NULL;
2510 }
2511 }
2513 if (errorCode != NULL)
2514 {
2515 *errorCode = retVal;
2516 }
2518 return(handle);
2519 }
2521 int32_t EDMA_configErrorMonitoring(EDMA_Handle handle, EDMA_errorConfig_t const *config)
2522 {
2523 EDMA_Config_t *edmaConfig;
2524 EDMA_Object_t *edmaObj;
2525 EDMA_hwAttrs_t const *hwAttrs;
2526 uint32_t ccBaseAddr;
2527 uint8_t threshold;
2528 uint8_t queueId, tc;
2529 int32_t errorCode = EDMA_NO_ERROR;
2531 edmaConfig = (EDMA_Config_t *) handle;
2532 edmaObj = edmaConfig->object;
2533 hwAttrs = edmaConfig->hwAttrs;
2534 ccBaseAddr = hwAttrs->CCbaseAddress;
2536 #ifdef EDMA_PARAM_CHECK
2537 if (handle == NULL)
2538 {
2539 errorCode = EDMA_E_INVALID__HANDLE_NULL;
2540 }
2542 if ((errorCode == EDMA_NO_ERROR) && (config == NULL))
2543 {
2544 errorCode = EDMA_E_INVALID__CONFIG_POINTER_NULL;
2545 }
2546 #endif
2548 /* event queue threshold configuration */
2549 if (config->isEventQueueThresholdingEnabled == true)
2550 {
2551 #ifdef EDMA_PARAM_CHECK
2552 if (config->eventQueueThreshold > EDMA_EVENT_QUEUE_THRESHOLD_MAX)
2553 {
2554 errorCode = EDMA_E_INVALID__EVENT_QUEUE_THRESHOLD;
2555 }
2556 else
2557 {
2558 threshold = config->eventQueueThreshold;
2559 }
2560 #endif
2561 }
2562 else
2563 {
2564 threshold = EDMA_EVENT_QUEUE_THRESHOLDING_DISABLED;
2565 }
2567 if (errorCode == EDMA_NO_ERROR)
2568 {
2569 if (config->isConfigAllEventQueues == true)
2570 {
2571 for (queueId = 0; queueId < hwAttrs->numEventQueues; queueId++)
2572 {
2573 EDMA_configQueueThreshold(ccBaseAddr, queueId, threshold);
2574 }
2575 }
2576 else
2577 {
2578 #ifdef EDMA_PARAM_CHECK
2579 if (config->eventQueueId >= hwAttrs->numEventQueues)
2580 {
2581 errorCode = EDMA_E_INVALID__EVENT_QUEUE_ID;
2582 }
2583 #endif
2584 if (errorCode == EDMA_NO_ERROR)
2585 {
2586 EDMA_configQueueThreshold(ccBaseAddr, config->eventQueueId, threshold);
2587 }
2588 }
2589 }
2591 if (errorCode == EDMA_NO_ERROR)
2592 {
2593 /* transfer controller error configuration */
2594 if (config->isConfigAllTransferControllers == true)
2595 {
2596 for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2597 {
2598 EDMA_configTransferControllerError(hwAttrs->TCbaseAddress[tc],
2599 config->isEnableAllTransferControllerErrors,
2600 &config->transferControllerErrorConfig);
2601 }
2602 }
2603 else
2604 {
2605 #ifdef EDMA_PARAM_CHECK
2606 if (config->transferControllerId >= hwAttrs->numEventQueues)
2607 {
2608 errorCode = EDMA_E_INVALID__TRANSFER_CONTROLLER_ID;
2609 }
2610 #endif
2611 if (errorCode == EDMA_NO_ERROR)
2612 {
2613 EDMA_configTransferControllerError(hwAttrs->TCbaseAddress[config->transferControllerId],
2614 config->isEnableAllTransferControllerErrors,
2615 &config->transferControllerErrorConfig);
2616 }
2617 }
2618 }
2620 if (errorCode == EDMA_NO_ERROR)
2621 {
2622 /* if error interrupt is not hooked, declare error if call back is populated */
2623 if (hwAttrs->errorInterruptNum == EDMA_INTERRUPT_NOT_CONNECTED_ID)
2624 {
2625 if (config->callbackFxn != NULL)
2626 {
2627 errorCode = EDMA_E_INVALID__ERROR_CALL_BACK_FN_NON_NULL;
2628 }
2629 }
2630 edmaObj->errorCallbackFxn = config->callbackFxn;
2631 }
2633 if (errorCode == EDMA_NO_ERROR)
2634 {
2635 /* if any of the tc error interrupts are not hooked, declare error if call back is populated */
2636 for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2637 {
2638 if (hwAttrs->transferControllerErrorInterruptNum[tc] == EDMA_INTERRUPT_NOT_CONNECTED_ID)
2639 {
2640 if (config->transferControllerCallbackFxn)
2641 {
2642 errorCode = EDMA_E_INVALID__TC_ERROR_CALL_BACK_FN_NON_NULL;
2643 }
2644 }
2645 }
2647 edmaObj->transferControllerErrorCallbackFxn = config->transferControllerCallbackFxn;
2648 }
2650 return(errorCode);
2651 }
2653 int32_t EDMA_configPerformance(EDMA_Handle handle,
2654 EDMA_performanceConfig_t const *config)
2655 {
2656 EDMA_Config_t *edmaConfig;
2657 EDMA_hwAttrs_t const *hwAttrs;
2658 uint32_t tcBaseAddr;
2659 uint8_t tc;
2660 uint32_t ccBaseAddr;
2661 int32_t errorCode = EDMA_NO_ERROR;
2663 #ifdef EDMA_PARAM_CHECK
2664 if (handle == NULL)
2665 {
2666 errorCode = EDMA_E_INVALID__HANDLE_NULL;
2667 }
2669 if ((errorCode == EDMA_NO_ERROR) && (config == NULL))
2670 {
2671 errorCode = EDMA_E_INVALID__CONFIG_POINTER_NULL;
2672 }
2673 #endif
2675 if (errorCode == EDMA_NO_ERROR)
2676 {
2677 edmaConfig = (EDMA_Config_t *) handle;
2678 hwAttrs = edmaConfig->hwAttrs;
2679 ccBaseAddr = hwAttrs->CCbaseAddress;
2681 #ifdef EDMA_PARAM_CHECK
2682 if (config->transferControllerReadRate > EDMA_READ_RATE_RANGE_CHECK_MAX)
2683 {
2684 errorCode = EDMA_E_INVALID__TRANSFER_CONTROLLER_READ_RATE;
2685 }
2687 if (config->queuePriority > EDMA_QUEUE_PRIORITIY_RANGE_CHECK_MAX)
2688 {
2689 errorCode = EDMA_E_INVALID__QUEUE_PRIORITY;
2690 }
2691 #endif
2692 }
2694 if (errorCode == EDMA_NO_ERROR)
2695 {
2696 if (config->isConfigAllTransferControllers == true)
2697 {
2698 for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2699 {
2700 tcBaseAddr = hwAttrs->TCbaseAddress[tc];
2701 HW_WR_FIELD32(tcBaseAddr + EDMA_TC_RDRATE, EDMA_TC_RDRATE_RDRATE,
2702 config->transferControllerReadRate);
2704 EDMA_configQueuePriority(ccBaseAddr, tc, config->queuePriority);
2705 }
2706 }
2707 else
2708 {
2709 #ifdef EDMA_PARAM_CHECK
2710 if (config->transferControllerId >= hwAttrs->numEventQueues)
2711 {
2712 errorCode = EDMA_E_INVALID__TRANSFER_CONTROLLER_ID;
2713 }
2714 #endif
2715 if (errorCode == EDMA_NO_ERROR)
2716 {
2717 tcBaseAddr = hwAttrs->TCbaseAddress[config->transferControllerId];
2718 HW_WR_FIELD32(tcBaseAddr + EDMA_TC_RDRATE, EDMA_TC_RDRATE_RDRATE,
2719 config->transferControllerReadRate);
2721 EDMA_configQueuePriority(ccBaseAddr, config->transferControllerId,
2722 config->queuePriority);
2723 }
2724 }
2725 }
2727 return(errorCode);
2728 }
2731 EDMA_Handle EDMA_getHandle(uint8_t instanceId, EDMA_instanceInfo_t *instanceInfo)
2732 {
2733 EDMA_Handle handle = NULL;
2734 EDMA_Config_t *edmaConfig;
2735 EDMA_Object_t *edmaObj;
2736 EDMA_hwAttrs_t const *hwAttrs;
2737 int32_t status = EDMA_NO_ERROR;
2738 uint8_t tc;
2740 #ifdef EDMA_PARAM_CHECK
2741 if (instanceInfo == NULL)
2742 {
2743 status = EDMA_E_INVALID__INSTANCEINFO_POINTER_NULL;
2744 handle = NULL;
2745 }
2746 #endif
2748 if (EDMA_NO_ERROR == status)
2749 {
2750 /* Get handle for this driver instance */
2751 handle = (EDMA_Handle)&(EDMA_config[instanceId]);
2752 edmaConfig = (EDMA_Config_t *) handle;
2753 edmaObj = edmaConfig->object;
2755 if (edmaObj == NULL) {
2756 handle = NULL;
2757 }
2758 }
2760 if (handle != NULL)
2761 {
2762 hwAttrs = edmaConfig->hwAttrs;
2763 instanceInfo->numEventQueues = hwAttrs->numEventQueues;
2764 instanceInfo->numParamSets = hwAttrs->numParamSets;
2765 instanceInfo->isChannelMapExist = hwAttrs->isChannelMapExist;
2766 instanceInfo->isTransferCompletionInterruptConnected =
2767 (hwAttrs->transferCompletionInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2768 instanceInfo->isErrorInterruptConnected = (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2769 for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2770 {
2771 instanceInfo->isTransferControllerErrorInterruptConnected[tc] =
2772 (hwAttrs->transferControllerErrorInterruptNum[tc] != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2773 }
2774 }
2775 return handle;
2776 }