]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/pdk.git/blob - packages/ti/drv/edma/src/edma.c
PDK-4989: edma driver clean up for tpr12
[processor-sdk/pdk.git] / packages / ti / drv / edma / src / edma.c
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_
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_
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)
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);
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)
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);
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     )
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);
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)
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, &paramSet);
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)
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
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)
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     }
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)
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     }
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)
802     return((EDMA3GetErrIntrStatus(ccBaseAddr) != 0U) ||
803             (EDMA3ErrIntrHighStatusGet(ccBaseAddr) != 0U) ||
804             (EDMA3QdmaGetErrIntrStatus(ccBaseAddr) != 0U) ||
805             (EDMA3GetCCErrStatus(ccBaseAddr) != 0U));
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)
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);
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)
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     }
930 int32_t EDMA_getErrorStatus(EDMA_Handle handle, bool *isAnyError, EDMA_errorInfo_t *errorInfo)
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);
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)
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     }
1009 static bool EDMA_isTransferControllerError(uint32_t tcBaseAddr)
1011     uint32_t errStatRegAddr = tcBaseAddr + EDMA_TC_ERRSTAT;
1013     return(HW_RD_REG32(errStatRegAddr) != 0);
1016 static void EDMA_getTransferControllerErrorStatusInfo(uint32_t tcBaseAddr,
1017                 EDMA_transferControllerErrorInfo_t *errorInfo)
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     }
1053 static void EDMA_clearTransferControllerErrors(uint32_t tcBaseAddr,
1054                 EDMA_transferControllerErrorInfo_t *errorInfo)
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);
1064 int32_t EDMA_getTransferControllerErrorStatus(EDMA_Handle handle, uint8_t transferControllerId,
1065     bool *isAnyError, EDMA_transferControllerErrorInfo_t *errorInfo)
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);
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)
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     }
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)
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     }
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)
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     }
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)
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);
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)
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);
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)
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);
1452 int32_t EDMA_configChannel(EDMA_Handle handle, EDMA_channelConfig_t const *config,
1453     bool isEnableChannel)
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);
1532 int32_t EDMA_enableChannel(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
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);
1591 int32_t EDMA_disableChannel(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
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);
1640 int32_t EDMA_configParamSet(EDMA_Handle handle, uint16_t paramId,
1641     EDMA_paramConfig_t const *config)
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);
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     )
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     }
1708 int32_t EDMA_linkParamSets(EDMA_Handle handle, uint16_t fromParamId, uint16_t toParamId)
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);
1751 int32_t EDMA_chainChannels(EDMA_Handle handle, uint16_t fromParamId, uint8_t toChannelId)
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);
1792 int32_t EDMA_startTransfer(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1794     return(EDMA_startTransfer_assist(handle, channelId, channelType, false));
1797 int32_t EDMA_startDmaTransfer(EDMA_Handle handle, uint8_t channelId)
1799     return(EDMA_startTransfer_assist(handle, channelId,
1800         (uint8_t)EDMA3_CHANNEL_TYPE_DMA, false));
1803 int32_t EDMA_startQdmaTransfer(EDMA_Handle handle, uint8_t channelId)
1805     return(EDMA_startTransfer_assist(handle, channelId,
1806         (uint8_t)EDMA3_CHANNEL_TYPE_QDMA, false));
1809 int32_t EDMA_startFinalQdmaTransfer(EDMA_Handle handle, uint8_t channelId)
1811     return(EDMA_startTransfer_assist(handle, channelId,
1812         (uint8_t)EDMA3_CHANNEL_TYPE_QDMA, true));
1815 int32_t EDMA_isTransferComplete(EDMA_Handle handle, uint8_t transferCompletionCode,
1816     bool *isTransferComplete)
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);
1878 int32_t EDMA_setDestinationAddress(EDMA_Handle handle,
1879     uint16_t paramId,
1880     uint32_t destinationAddress)
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);
1913 int32_t EDMA_setSourceAddress(EDMA_Handle handle,
1914     uint16_t paramId,
1915     uint32_t sourceAddress)
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);
1949 static void EDMA_unregisterInterrupts(EDMA_Handle handle)
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     }
2023 int32_t EDMA_close(EDMA_Handle handle)
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);
2047 uint8_t EDMA_getNumInstances(void)
2049     return((uint8_t)EDMA_NUM_CC);
2052 int32_t EDMA_init(uint8_t instanceId)
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(&paramSet, 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, &paramSet);
2130         }
2131     }
2133     return(errorCode);
2136 int32_t EDMA_getStatusInfo(EDMA_Handle handle, EDMA_statusInfo_t *status)
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);
2219 static EDMA_Object_t* EDMA_getFreeEdmaObj(void)
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;
2233 EDMA_Handle EDMA_open(uint8_t instanceId, int32_t *errorCode,
2234     EDMA_instanceInfo_t *instanceInfo)
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);
2521 int32_t EDMA_configErrorMonitoring(EDMA_Handle handle, EDMA_errorConfig_t const *config)
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);
2653 int32_t EDMA_configPerformance(EDMA_Handle handle,
2654     EDMA_performanceConfig_t const *config)
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);
2731 EDMA_Handle EDMA_getHandle(uint8_t instanceId, EDMA_instanceInfo_t *instanceInfo)
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;