]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/pdk.git/blob - packages/ti/drv/edma/src/edma.c
[BugFix] PDK-9298
[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];
132 } EDMA_Object_t;
134 /*! @brief Config structure containing object and hardware attributes. This
135        will be casted to the EDMA's handle and returned in open API */
136 typedef struct EDMA_Config_t_
138     /*! @brief Pointer to EDMA object (state). */
139     EDMA_Object_t *object;
141     /*! @brief Pointer to EDMA Hardware attributes structure. */
142     EDMA_hwAttrs_t const *hwAttrs;
144     /*! Init params for the edma instance. */
145     EDMA3CCInitParams   initParams;
146 } EDMA_Config_t;
148 #ifdef EDMA_DBG
149 typedef struct edmaDbg_t_
151     uint32_t transCompIsrCount;
152     uint32_t transCompIsrIevalCount;
153     uint32_t errorIsrCount;
154     uint32_t transCompErrorIsrCount;
155     uint32_t aggregatedErrorTransCompErrorIsrCount;
156     EDMA_Object_t *edmaObj;
157 } edmaDbg_t;
158 edmaDbg_t edmaDbg;
159 #endif
161 /** @} */ /* end of @addtogroup EDMA_INTERNAL_DATA_STRUCTURE */
163 /* ========================================================================== */
164 /*                          Function Declarations                             */
165 /* ========================================================================== */
167 /**
168 @defgroup EDMA_INTERNAL_FUNCTION            EDMA Driver Internal Functions
169 @ingroup EDMA_INTERNAL
170 */
172 /* Private function prototype definitions */
173 #ifdef EDMA_PARAM_CHECK
174 static int32_t EDMA_validate_channelIdchannelType(uint8_t channelId, uint8_t channelType);
176 static int32_t EDMA_validate_channel_config(
177     EDMA_Handle handle,
178     EDMA_hwAttrs_t const *hwAttrs,
179     EDMA_channelConfig_t const *config);
181 static inline int32_t EDMA_validate_param_config(EDMA_Handle handle,
182     EDMA_hwAttrs_t const *hwAttrs, uint16_t paramId,
183     EDMA_paramSetConfig_t const *config,
184     EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn
185 );
186 #endif
187 static void EDMA_paramSetConfig_assist (uint32_t ccBaseAddr, uint16_t paramId,
188                                 EDMA_paramSetConfig_t const *pSetCfg);
190 static void EDMA_paramConfig_assist(uint32_t ccBaseAddr, uint32_t regionId, uint16_t paramId,
191     EDMA_paramSetConfig_t const *pSetCfg,
192     EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn,
193     uintptr_t transferCompletionCallbackFxnArg, EDMA_Object_t *edmaObj);
195 static inline int32_t EDMA_startTransfer_assist(EDMA_Handle handle, uint8_t channelId,
196     uint8_t channelType, bool isStaticSet);
198 static void EDMA_transferComplete_isr (uintptr_t arg);
200 static void EDMA_update_queue_entries (
201     uint32_t qEntry0Addr,
202     uint32_t qEntryAddrJump,
203     uint8_t  numEntries,
204     uint8_t  *qEntryIndx,
205     EDMA_queueEntryInfo_t *qEntry);
207 static void EDMA_transferController_error_isr (uintptr_t arg);
209 static void EDMA_error_isr (uintptr_t arg);
211 #if defined (SOC_TPR12) || defined (SOC_AWR294X)
212 static void EDMA_aggregated_error_transferController_error_isr (uintptr_t arg);
213 #endif
215 static void EDMA_configQueueThreshold(uint32_t ccBaseAddr, uint8_t queueId,
216                                uint8_t threshold);
218 static void EDMA_configQueuePriority(uint32_t ccBaseAddr, uint8_t transferController,
219                                uint8_t priority);
221 static bool EDMA_isError(uint32_t ccBaseAddr);
223 static void EDMA_getErrorStatusInfo(EDMA_hwAttrs_t const *hwAttrs, uint32_t ccBaseAddr,
224                                     EDMA_errorInfo_t *errorInfo);
226 static void EDMA_clearErrors(EDMA_hwAttrs_t const *hwAttrs, uint32_t ccBaseAddr, uint32_t regionId,
227                              EDMA_errorInfo_t const *errorInfo);
229 static bool EDMA_isTransferControllerError(uint32_t tcBaseAddr);
231 static void EDMA_getTransferControllerErrorStatusInfo(uint32_t tcBaseAddr,
232                 EDMA_transferControllerErrorInfo_t *errorInfo);
234 static void EDMA_clearTransferControllerErrors(uint32_t tcBaseAddr,
235                 EDMA_transferControllerErrorInfo_t *errorInfo);
237 static EDMA_Object_t* EDMA_getFreeEdmaObj(void);
239 /* ========================================================================== */
240 /*                            Global Variables                                */
241 /* ========================================================================== */
243 /* EDMA configuration structure */
244 static EDMA_Config_t EDMA_config[EDMA_DRV_INST_MAX + 1U] = {0U};
246 /*! @brief EDMA objects storage for each CC. */
247 static EDMA_Object_t EDMA_object[EDMA_NUM_CC] = {0U};
249 /* ========================================================================== */
250 /*                          Function Definitions                              */
251 /* ========================================================================== */
253 #ifdef EDMA_PARAM_CHECK
254 /**
255  *  @b Description
256  *  @n
257  *      Utility function for validating channel Id and channel Type parameters.
258  *
259  *  @param[in]  channelId  channel Id
260  *  @param[in]  channelType channed Type
261  *
262  *  \ingroup EDMA_INTERNAL_FUNCTION
263  *
264  *  @retval
265  *      one of @ref EDMA_ERROR_CODES
266  */
267 static int32_t EDMA_validate_channelIdchannelType(uint8_t channelId, uint8_t channelType)
269     int32_t errorCode = EDMA_NO_ERROR;
271     if ((channelType != (uint8_t)EDMA3_CHANNEL_TYPE_DMA) &&
272         (channelType != (uint8_t)EDMA3_CHANNEL_TYPE_QDMA))
273     {
274         errorCode = EDMA_E_INVALID__DMA_CHANNEL_TYPE;
275     }
277     if ((errorCode == EDMA_NO_ERROR) &&
278         ((channelType == (uint8_t)EDMA3_CHANNEL_TYPE_DMA) &&
279          (channelId >= (uint8_t)EDMA_NUM_DMA_CHANNELS)))
280     {
281         errorCode = EDMA_E_INVALID__DMA_CHANNEL_ID;
282     }
284     if ((errorCode == EDMA_NO_ERROR) &&
285         ((channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA) &&
286          (channelId >= EDMA_NUM_QDMA_CHANNELS)))
287     {
288         errorCode = EDMA_E_INVALID__QDMA_CHANNEL_ID;
289     }
290     return(errorCode);
293 /**
294  *  @b Description
295  *  @n
296  *      Utility function for validating parameters in @ref EDMA_channelConfig_t.
297  *
298  *  @param[in]  handle  EDMA handle.
299  *  @param[in]  hwAttrs Pointer to hardware attributes.
300  *  @param[in]  config Pointer to EDMA channel configuration structure.
301  *
302  *  \ingroup EDMA_INTERNAL_FUNCTION
303  *
304  *  @retval
305  *      one of @ref EDMA_ERROR_CODES
306  */
307 static int32_t EDMA_validate_channel_config(
308     EDMA_Handle handle,
309     EDMA_hwAttrs_t const *hwAttrs,
310     EDMA_channelConfig_t const *config)
312     int32_t errorCode = EDMA_NO_ERROR;
314     if (handle == NULL)
315     {
316         errorCode = EDMA_E_INVALID__HANDLE_NULL;
317     }
319     if ((errorCode == EDMA_NO_ERROR) &&
320         (config == NULL))
321     {
322         errorCode = EDMA_E_INVALID__CONFIG_POINTER_NULL;
323     }
325     if (errorCode == EDMA_NO_ERROR)
326     {
327         errorCode = EDMA_validate_channelIdchannelType(config->channelId,
328             config->channelType);
329     }
331     if ((errorCode == EDMA_NO_ERROR) &&
332         (config->channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA))
333     {
334         if (config->qdmaParamTriggerWordOffset > 7)
335         {
336             errorCode = EDMA_E_INVALID__QDMA_TRIGGER_WORD;
337         }
338     }
340     /* if channel mappping is not supported, paramId must be same as channelId
341        for DMA channel */
342     if ((errorCode == EDMA_NO_ERROR) &&
343         (hwAttrs->isChannelMapExist == false) &&
344         (config->channelType == (uint8_t)EDMA3_CHANNEL_TYPE_DMA) &&
345         (config->paramId != (uint16_t)config->channelId))
346     {
347         errorCode = EDMA_E_INVALID__PARAM_ID_NOT_SAME_AS_CHANNEL_ID;
348     }
350     if ((errorCode == EDMA_NO_ERROR) &&
351         (config->eventQueueId >= hwAttrs->numEventQueues))
352     {
353         errorCode = EDMA_E_INVALID__EVENT_QUEUE_ID;
354     }
356     if (errorCode == EDMA_NO_ERROR)
357     {
358         errorCode = EDMA_validate_param_config(handle, hwAttrs, config->paramId, &config->paramSetConfig,
359             config->transferCompletionCallbackFxn);
360     }
362     return(errorCode);
365 /**
366  *  @b Description
367  *  @n
368  *      Utility function for validating parameters relalted to param configuration.
369  *
370  *  @param[in]  handle  EDMA handle.
371  *  @param[in]  hwAttrs Pointer to hardware attributes.
372  *  @param[in]  paramId PaRAM Set Id.
373  *  @param[in]  config Pointer to PaRAM Set configuration structure.
374  *  @param[in]  transferCompletionCallbackFxn transfer completion call-back function configuration.
375  *
376  *  \ingroup EDMA_INTERNAL_FUNCTION
377  *
378  *  @retval
379  *      one of @ref EDMA_ERROR_CODES
380  */
381 static inline int32_t EDMA_validate_param_config(
382     EDMA_Handle handle,
383     EDMA_hwAttrs_t const *hwAttrs,
384     uint16_t paramId,
385     EDMA_paramSetConfig_t const *config,
386     EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn
387     )
389     int32_t errorCode = EDMA_NO_ERROR;
391     if (handle == NULL)
392     {
393         errorCode = EDMA_E_INVALID__HANDLE_NULL;
394     }
396     if ((errorCode == EDMA_NO_ERROR) &&
397         (paramId >= hwAttrs->numParamSets))
398     {
399         errorCode = EDMA_E_INVALID__PARAM_ID;
400     }
402     if ((errorCode == EDMA_NO_ERROR) &&
403         (config->transferCompletionCode >= EDMA_NUM_TCC))
404     {
405         errorCode = EDMA_E_INVALID__TRANSFER_COMPLETION_CODE;
406     }
408     /* if all of interrupt completion flags are false, then transfer completion
409        call back function must be NULL */
410     if ((errorCode == EDMA_NO_ERROR) &&
411         ((transferCompletionCallbackFxn != NULL) &&
412          ((config->isFinalTransferInterruptEnabled == false) &&
413           (config->isIntermediateTransferInterruptEnabled == false))))
414     {
415         errorCode = EDMA_E_INVALID__TRNSFR_COMPLETION_PARAMS;
416     }
418     /* if completion interrupt not connected and transfer completion call back
419      * is not NULL, then generate error
420      */
421     if ((errorCode == EDMA_NO_ERROR) &&
422         ((hwAttrs->transferCompletionInterruptNum == EDMA_INTERRUPT_NOT_CONNECTED_ID) &&
423          (transferCompletionCallbackFxn != NULL)))
424     {
425         errorCode = EDMA_E_INVALID__TRNSFR_COMPLETION_PARAMS;
426     }
428     if ((errorCode == EDMA_NO_ERROR) &&
429         ((config->transferType != (uint8_t)EDMA3_SYNC_A) &&
430          (config->transferType != (uint8_t)EDMA3_SYNC_AB)))
431     {
432         errorCode = EDMA_E_INVALID__TRANSFER_TYPE;
433     }
435 #ifdef EDMA_EXTENDED_B_INDICES
436     if ((errorCode == EDMA_NO_ERROR) &&
437         ((config->sourceBindex > EDMA_EXTENDED_B_INDEX_MAX) ||
438          (config->sourceBindex < EDMA_EXTENDED_B_INDEX_MIN)))
439     {
440         errorCode = EDMA_E_INVALID__SOURCE_B_INDEX;
441     }
443     if ((errorCode == EDMA_NO_ERROR) &&
444         ((config->destinationBindex > EDMA_EXTENDED_B_INDEX_MAX) ||
445          (config->destinationBindex < EDMA_EXTENDED_B_INDEX_MIN)))
446     {
447         errorCode = EDMA_E_INVALID__DESTINATION_B_INDEX;
448     }
449 #endif
451     return(errorCode);
453 #endif
455 /**
456  *  @b Description
457  *  @n
458  *      Utility function for configuring a PaRAM Set.
459  *      Note: HW_WR_FIELD32 APIs are avoided for (assumed) efficiency when writing
460  *      param fields (avoid unnecessary masking because fields are defined to be right
461  *      sized (e.g aCount is uint16_t, matching Param ACNT size).
462  *
463  *  @param[in]  ccBaseAddr  CC base address.
464  *  @param[in]  paramId PaRAM Set Id.
465  *  @param[in]  pSetCfg Pointer to PaRAM Set configuration.
466  *
467  *  \ingroup EDMA_INTERNAL_FUNCTION
468  *
469  *  @retval
470  *      None.
471  */
472 #ifdef EDMA_EXTENDED_B_INDICES
473 /*! Returns the 8-bit extension beyond 16-bits of the 32-bit b-index */
474 #define EDMA_B_INDX_EXTENSION(x) (((x) >> 16U) & 0x000000FFU)
475 #endif
477 static void EDMA_paramSetConfig_assist (uint32_t ccBaseAddr, uint16_t paramId,
478                                 EDMA_paramSetConfig_t const *pSetCfg)
480     EDMA3CCPaRAMEntry paramSet;
482     /* program PaRAM set */
483     paramSet.srcAddr  = pSetCfg->sourceAddress;
484     paramSet.destAddr = pSetCfg->destinationAddress;
485     paramSet.aCnt     = pSetCfg->aCount;
486     paramSet.bCnt     = pSetCfg->bCount;
487     paramSet.cCnt     = pSetCfg->cCount;
488     paramSet.srcBIdx  = (uint16_t) pSetCfg->sourceBindex;
489     paramSet.destBIdx = (uint16_t) pSetCfg->destinationBindex;
490     paramSet.srcCIdx  = pSetCfg->sourceCindex;
491     paramSet.destCIdx = pSetCfg->destinationCindex;
492     paramSet.linkAddr = pSetCfg->linkAddress;
493     paramSet.bCntReload = pSetCfg->bCountReload;
494 #ifdef EDMA_EXTENDED_B_INDICES
495     paramSet.bidxExtn = EDMA_B_INDX_EXTENSION(pSetCfg->sourceBindex) |
496                         EDMA_B_INDX_EXTENSION(pSetCfg->sourceCindex) << (EDMA_TPCC_CCNT_DSTEBIDX_SHIFT - EDMA_TPCC_CCNT_SRCEBIDX_SHIFT);
497 #endif
499     /* Parameters not programmed are : PRIV = 0; PRIVID = 0; */
500     paramSet.opt = 0;
501     paramSet.opt |= (
502     ((uint32_t)(pSetCfg->transferType == (uint8_t)EDMA3_SYNC_AB) << EDMA_TPCC_OPT_SYNCDIM_SHIFT) |
503     ((uint32_t)(pSetCfg->sourceAddressingMode == (uint8_t)EDMA3_ADDRESSING_MODE_FIFO_WRAP) <<
504         EDMA_TPCC_OPT_SAM_SHIFT) |
505     ((uint32_t)(pSetCfg->destinationAddressingMode == (uint8_t)EDMA3_ADDRESSING_MODE_FIFO_WRAP) <<
506         EDMA_TPCC_OPT_DAM_SHIFT) |
507     ((uint32_t)pSetCfg->fifoWidth << EDMA_TPCC_OPT_FWID_SHIFT) |
508     ((uint32_t)pSetCfg->transferCompletionCode << EDMA_TPCC_OPT_TCC_SHIFT) |
509     ((uint32_t)pSetCfg->isStaticSet << EDMA_TPCC_OPT_STATIC_SHIFT) |
510     ((uint32_t)pSetCfg->isEarlyCompletion << EDMA_TPCC_OPT_TCCMODE_SHIFT) |
511     ((uint32_t)pSetCfg->isFinalTransferInterruptEnabled << EDMA_TPCC_OPT_TCINTEN_SHIFT) |
512     ((uint32_t)pSetCfg->isIntermediateTransferInterruptEnabled << EDMA_TPCC_OPT_ITCINTEN_SHIFT) |
513     ((uint32_t)pSetCfg->isFinalChainingEnabled << EDMA_TPCC_OPT_TCCHEN_SHIFT) |
514     ((uint32_t)pSetCfg->isIntermediateChainingEnabled << EDMA_TPCC_OPT_ITCCHEN_SHIFT)
515     );
516     EDMA3SetPaRAM(ccBaseAddr, paramId, &paramSet);
519 /**
520  *  @b Description
521  *  @n
522  *      Transfer Completion Isr which will trigger when a channel transfer completes
523  *      and if the channel is configured for a non-NULL completion call back function
524  *      during channel configuration.
525  *      Checks which transfer completion codes are set and
526  *      calls the corresponding registered application call back function.
527  *
528  *  @param[in]  arg  EDMA handle which was set when Isr was registered using
529  *                   HwiP_create OSAL API.
530  *
531  *  \ingroup EDMA_INTERNAL_FUNCTION
532  *
533  *  @retval
534  *      None.
535  */
536 static void EDMA_transferComplete_isr (uintptr_t arg)
538     EDMA_Handle handle = (EDMA_Handle) arg;
539     EDMA_Config_t *edmaConfig;
540     EDMA_Object_t *edmaObj;
541     EDMA_hwAttrs_t const *hwAttrs;
542     uint32_t ccBaseAddr;
543     uint32_t lowIntrStatus, highIntrStatus;
544     uint8_t transCompCode;
545     uint8_t half, full;
547 #ifdef EDMA_DBG
548     edmaDbg.transCompIsrCount++;
549 #endif
551     edmaConfig = (EDMA_Config_t *) handle;
552     edmaObj = edmaConfig->object;
554     hwAttrs =  edmaConfig->hwAttrs;
555     ccBaseAddr = hwAttrs->CCbaseAddress;
557 #if defined (SOC_TPR12) || defined (SOC_AWR294X)
558     /* Global interrupt must be set in the status */
559     // DebugP_assert((HW_RD_REG32(hwAttrs->CCcompletionInterruptsAggregatorStatusRegAddress) &
560     //               (1U << EDMA_TPCC_INTAGG_TPCC_INTG__POS)) == (1U << EDMA_TPCC_INTAGG_TPCC_INTG__POS));
561 #endif
563     half = EDMA_NUM_DMA_CHANNELS/2U;
564     full = EDMA_NUM_DMA_CHANNELS;
566     /* scan only whose interrupts are enabled */
567     lowIntrStatus = EDMA3GetIntrStatusRegion(ccBaseAddr, edmaConfig->initParams.regionId) &
568                     EDMA3GetEnabledIntrRegion(ccBaseAddr, edmaConfig->initParams.regionId);
569     highIntrStatus = EDMA3IntrStatusHighGetRegion(ccBaseAddr, edmaConfig->initParams.regionId) &
570                      EDMA3GetEnabledIntrHighRegion(ccBaseAddr, edmaConfig->initParams.regionId);
571     if ((lowIntrStatus != 0U) || (highIntrStatus != 0U))
572     {
573         /* scan low status */
574         for (transCompCode = 0U; transCompCode < half; transCompCode++)
575         {
576             if ((lowIntrStatus & ((uint32_t)1 << transCompCode)) == ((uint32_t)1 << transCompCode))
577             {
578                 /* clear interrupt */
579                 EDMA3ClrIntrRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)transCompCode);
581                 /* call registered call back function for the transferCompletionCode */
582                 if (edmaObj->transferCompleteCallbackFxn[transCompCode] != NULL)
583                 {
584                     (*edmaObj->transferCompleteCallbackFxn[transCompCode])(
585                         edmaObj->transferCompleteCallbackFxnArg[transCompCode],
586                         transCompCode);
587                 }
588                 else
589                 {
590                     /* interrupt indicated but no call back function */
591                     DebugP_assert(0);
592                 }
593             }
594         }
596         /* scan high status */
597         for (transCompCode = half; transCompCode < full; transCompCode++)
598         {
599             if ((highIntrStatus & ((uint32_t)1 << (transCompCode -half))) ==
600                 ((uint32_t)1 << (transCompCode - half)))
601             {
602                 /* clear interrupt */
603                 EDMA3ClrIntrRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)transCompCode);
605                 /* call registered call back function for the transferCompletionCode */
606                 if (edmaObj->transferCompleteCallbackFxn[transCompCode] != NULL)
607                 {
608                     (*edmaObj->transferCompleteCallbackFxn[transCompCode])(
609                         edmaObj->transferCompleteCallbackFxnArg[transCompCode],
610                         transCompCode);
611                 }
612                 else
613                 {
614                     /* interrupt indicated but no call back function */
615                     DebugP_assert(0);
616                 }
617             }
618         }
619     }
621 #if defined (SOC_TPR12) || defined (SOC_AWR294X)
622     /* clear interrupt */
623     HW_WR_REG32(hwAttrs->CCcompletionInterruptsAggregatorStatusRegAddress, (1U << EDMA_TPCC_INTAGG_TPCC_INTG__POS));
624 #endif
626     /* check conditions again, if any detected, then notify hardware.
627        The alternative is to do the above code in a loop but this can hold up
628        other interrupts in the system as multiple transfers could complete
629        in this time given the pocessing of call-back functions also, so the IEVAL
630        approach is preferred. For more details,
631        see EDMA User Guide section "EDMA3 Interrupt Servicing" */
632     lowIntrStatus = EDMA3GetIntrStatusRegion(ccBaseAddr, edmaConfig->initParams.regionId) &
633                     EDMA3GetEnabledIntrRegion(ccBaseAddr, edmaConfig->initParams.regionId);
634     highIntrStatus = EDMA3IntrStatusHighGetRegion(ccBaseAddr, edmaConfig->initParams.regionId) &
635                      EDMA3GetEnabledIntrHighRegion(ccBaseAddr, edmaConfig->initParams.regionId);
636     if ((lowIntrStatus != 0) || (highIntrStatus != 0))
637     {
638 #ifdef EDMA_DBG
639         edmaDbg.transCompIsrIevalCount++;
640 #endif
641         /* Based on GINT (Global interrupt) */
642         HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_IEVAL, EDMA_TPCC_IEVAL_EVAL, 1);
643     }
646 /**
647  *  @b Description
648  *  @n
649  *      Utility function to update queue entry event number and event type
650  *        information as read from the QxEy registers. Exploits the symmetric structure
651  *        of these registers.
652  *
653  *  @param[in]  qEntry0Addr  Address of queue entry 0.
654  *  @param[in]  qEntryAddrJump Queue entry address jump.
655  *  @param[in]  numEntries Number of entries to iterate on.
656  *  @param[in,out]  qEntryIndx Pointer to queue entry index. Will be incremented
657  *                  in a circular manner.
658  *  @param[out] qEntry Pointer to queue Entry array which needs to be populated.
659  *
660  *  \ingroup EDMA_INTERNAL_FUNCTION
661  *
662  *  @retval
663  *      None.
664  */
665 static void EDMA_update_queue_entries (
666     uint32_t qEntry0Addr,
667     uint32_t qEntryAddrJump,
668     uint8_t  numEntries,
669     uint8_t  *qEntryIndx,
670     EDMA_queueEntryInfo_t *qEntry)
672     uint8_t qEntryCount;
673     uint32_t qEntryAddr;
675     for (qEntryCount = 0; qEntryCount < numEntries; qEntryCount++)
676     {
677         qEntryAddr = qEntry0Addr + *qEntryIndx * qEntryAddrJump;
679         qEntry[qEntryCount].eventNumber =
680             HW_RD_FIELD32(qEntryAddr, EDMA_TPCC_QNE0_ENUM);
682         qEntry[qEntryCount].eventType =
683             HW_RD_FIELD32(qEntryAddr, EDMA_TPCC_QNE0_ETYPE);
685         *qEntryIndx += 1U;
686         if (*qEntryIndx >= EDMA_NUM_QUEUE_ENTRIES)
687         {
688             *qEntryIndx = 0U;
689         }
690     }
693 /**
694  *  @b Description
695  *  @n
696  *      Utility function to check if any of the EDMA errors happened. Suitable
697  *      for polling purposes.
698  *
699  *  @param[in]  ccBaseAddr CC base address.
700  *
701  *  \ingroup EDMA_INTERNAL_FUNCTION
702  *
703  *  @retval
704  *      true if any EDMA error else false
705  */
706 static bool EDMA_isError(uint32_t ccBaseAddr)
708     return((EDMA3GetErrIntrStatus(ccBaseAddr) != 0U) ||
709             (EDMA3ErrIntrHighStatusGet(ccBaseAddr) != 0U) ||
710             (EDMA3QdmaGetErrIntrStatus(ccBaseAddr) != 0U) ||
711             (EDMA3GetCCErrStatus(ccBaseAddr) != 0U));
714 /**
715  *  @b Description
716  *  @n
717  *      Utility function to get error status information.
718  *
719  *  @param[in]  hwAttrs pointer to hardware attributes.
720  *  @param[in]  ccBaseAddr cc base address.
721  *  @param[out] errorInfo pointer to error information in with status of errors
722  *                         will be populated.
723  *
724  *  \ingroup EDMA_INTERNAL_FUNCTION
725  *
726  *  @retval
727  *      None.
728  */
729 static void EDMA_getErrorStatusInfo(EDMA_hwAttrs_t const *hwAttrs, uint32_t ccBaseAddr,
730                                     EDMA_errorInfo_t *errorInfo)
732     uint8_t queueId;
733     uint8_t channelId;
734     uint8_t half, full;
735     uint32_t shift;
736     uint32_t errorStatus;
738     errorInfo->numEventQueues = hwAttrs->numEventQueues;
740     /* DMA channels status processing */
741     half = EDMA_NUM_DMA_CHANNELS/2U;
742     full = EDMA_NUM_DMA_CHANNELS;
744     /* low processing */
745     errorStatus = EDMA3GetErrIntrStatus(ccBaseAddr);
746     for (channelId = 0U; channelId < half; channelId++)
747     {
748         errorInfo->isDmaChannelEventMiss[channelId] = (bool)((errorStatus >> channelId) & 1U);
749     }
750     /* high processing */
751     errorStatus = EDMA3ErrIntrHighStatusGet(ccBaseAddr);
752     for (channelId = half; channelId < full; channelId++)
753     {
754         errorInfo->isDmaChannelEventMiss[channelId] =
755             (bool)((errorStatus >> (channelId - half)) & 1U);
756     }
758     /* QDMA channels status processing */
759     errorStatus = EDMA3QdmaGetErrIntrStatus(ccBaseAddr);
760     for (channelId = 0U; channelId < EDMA_NUM_QDMA_CHANNELS; channelId++)
761     {
762         errorInfo->isQdmaChannelEventMiss[channelId] = (bool)((errorStatus >> channelId) & 1U);
763     }
765     /* CC error status processing */
766     errorStatus = EDMA3GetCCErrStatus(ccBaseAddr);
767     for(queueId = 0U; queueId < hwAttrs->numEventQueues; queueId++)
768     {
769         shift = (uint32_t)queueId * (uint32_t)(EDMA_TPCC_CCERR_QTHRXCD1_SHIFT -
770                                                EDMA_TPCC_CCERR_QTHRXCD0_SHIFT);
771         errorInfo->isEventQueueThresholdExceeded[queueId] = (bool)((errorStatus >> shift) & 1U);
772     }
773     errorInfo->isOutstandingTransferCompletionTransfersExceededLimit =
774         (bool)((errorStatus >> EDMA_TPCC_CCERR_TCERR_SHIFT) & 1U);
777 /**
778  *  @b Description
779  *  @n
780  *      Utility function to clear EDMA errors.
781  *
782  *  @param[in]  hwAttrs pointer to hardware attributes.
783  *  @param[in]  ccBaseAddr cc base address.
784  *  @param[in]  errorInfo pointer to error information which is used to determine
785  *                        what errors will be cleared so that hardware can detect
786  *                        new errors.
787  *
788  *  \ingroup EDMA_INTERNAL_FUNCTION
789  *
790  *  @retval
791  *      None.
792  */
793 static void EDMA_clearErrors(EDMA_hwAttrs_t const *hwAttrs, uint32_t ccBaseAddr, uint32_t regionId,
794                              EDMA_errorInfo_t const *errorInfo)
796     uint8_t queueId;
797     uint8_t channelId;
798     uint8_t full;
799     uint32_t shift;
801     full = EDMA_NUM_DMA_CHANNELS;
803     /* clear conditions that were detected */
804     /* dma */
805     for (channelId = 0U; channelId < full; channelId++)
806     {
807         if (errorInfo->isDmaChannelEventMiss[channelId] == true)
808         {
809             EDMA3ClrMissEvtRegion(ccBaseAddr, regionId, (uint32_t)channelId);
810         }
811     }
812     /* qdma */
813     for (channelId = 0U; channelId < EDMA_NUM_QDMA_CHANNELS; channelId++)
814     {
815         if (errorInfo->isQdmaChannelEventMiss[channelId] == true)
816         {
817             EDMA3QdmaClrMissEvtRegion(ccBaseAddr, regionId, (uint32_t)channelId);
818         }
819     }
820     /* queues */
821     for (queueId = 0U; queueId < hwAttrs->numEventQueues; queueId++)
822     {
823         shift = (uint32_t)queueId * (EDMA_TPCC_CCERRCLR_QTHRXCD1_SHIFT - EDMA_TPCC_CCERRCLR_QTHRXCD0_SHIFT);
824         if (errorInfo->isEventQueueThresholdExceeded[queueId] == true)
825         {
826             EDMA3ClrCCErr(ccBaseAddr, ((uint32_t)1 << shift));
827         }
828     }
829     /* outstanding transfer completion error */
830     if (errorInfo->isOutstandingTransferCompletionTransfersExceededLimit == true)
831     {
832         EDMA3ClrCCErr(ccBaseAddr, ((uint32_t)1 << EDMA_TPCC_CCERRCLR_TCERR_SHIFT));
833     }
836 int32_t EDMA_getErrorStatus(EDMA_Handle handle, bool *isAnyError, EDMA_errorInfo_t *errorInfo)
838     EDMA_Config_t *edmaConfig;
839     EDMA_hwAttrs_t const *hwAttrs;
840     uint32_t ccBaseAddr;
841     int32_t errorCode = EDMA_NO_ERROR;
843 #ifdef EDMA_PARAM_CHECK
844     if (handle == NULL)
845     {
846         errorCode = EDMA_E_INVALID__HANDLE_NULL;
847     }
848 #endif
849     if (errorCode == EDMA_NO_ERROR)
850     {
851         edmaConfig = (EDMA_Config_t *) handle;
852         hwAttrs = edmaConfig->hwAttrs;
853         ccBaseAddr = hwAttrs->CCbaseAddress;
855         *isAnyError = EDMA_isError(ccBaseAddr);
856         if (*isAnyError == TRUE)
857         {
858             EDMA_getErrorStatusInfo(hwAttrs, ccBaseAddr, errorInfo);
859             EDMA_clearErrors(hwAttrs, ccBaseAddr, edmaConfig->initParams.regionId, errorInfo);
860         }
861     }
863     return(errorCode);
866 /**
867  *  @b Description
868  *  @n
869  *      CC error isr which will trigger when any CC errors happen. It will call
870  *      application registered error call back function with the error information.
871  *
872  *  @param[out]  arg  @ref EDMA_Handle which was set when Isr was registered
873  *                    using OSAL API HwiP_create.
874  *
875  *  \ingroup EDMA_INTERNAL_FUNCTION
876  *
877  *  @retval
878  *      None.
879  */
880 static void EDMA_error_isr (uintptr_t arg)
882     EDMA_Handle handle = (EDMA_Handle) arg;
883     EDMA_Config_t *edmaConfig;
884     EDMA_Object_t *edmaObj;
885     EDMA_hwAttrs_t const *hwAttrs;
886     uint32_t ccBaseAddr;
887     EDMA_errorInfo_t errorInfo;
889 #ifdef EDMA_DBG
890     edmaDbg.errorIsrCount++;
891 #endif
893     edmaConfig = (EDMA_Config_t *) handle;
894     edmaObj = edmaConfig->object;
895     hwAttrs = edmaConfig->hwAttrs;
896     ccBaseAddr = hwAttrs->CCbaseAddress;
898     EDMA_getErrorStatusInfo(hwAttrs, ccBaseAddr, &errorInfo);
900     /* application call back processing */
901     if (edmaObj->errorCallbackFxn != NULL)
902     {
903         (*edmaObj->errorCallbackFxn)(handle, &errorInfo);
904     }
906     EDMA_clearErrors(hwAttrs, ccBaseAddr, edmaConfig->initParams.regionId, &errorInfo);
908     /* Check conditions again and set EEVAL if any detected, this procedure is
909        similar to the transfer completion isr's (EEVAL similar to IEVAL) */
910     if (EDMA_isError(ccBaseAddr))
911     {
912         HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_EEVAL, EDMA_TPCC_EEVAL_EVAL, (uint32_t)1);
913     }
916 static bool EDMA_isTransferControllerError(uint32_t tcBaseAddr)
918     uint32_t errStatRegAddr = tcBaseAddr + EDMA_TC_ERRSTAT;
920     return(HW_RD_REG32(errStatRegAddr) != 0);
923 static void EDMA_getTransferControllerErrorStatusInfo(uint32_t tcBaseAddr,
924                 EDMA_transferControllerErrorInfo_t *errorInfo)
926     uint32_t errStatRegAddr, errDetRegAddr;
927     EDMA_transferControllerBusErrorInfo_t *busErrorInfo;
929     busErrorInfo = &errorInfo->busErrorInfo;
931     /* ERRSTAT processing */
932     errStatRegAddr = tcBaseAddr + EDMA_TC_ERRSTAT;
933     errorInfo->isTransferRequestError =
934         HW_RD_FIELD32(errStatRegAddr, EDMA_TC_ERRSTAT_TRERR);
936     errorInfo->isWriteToReservedConfigMemoryMap =
937         HW_RD_FIELD32(errStatRegAddr, EDMA_TC_ERRSTAT_MMRAERR);
939     errorInfo->isBusError =
940         HW_RD_FIELD32(errStatRegAddr, EDMA_TC_ERRSTAT_BUSERR);
942     /* ERRDET processing */
943     errDetRegAddr = tcBaseAddr + EDMA_TC_ERRDET;
944     if (errorInfo->isBusError == true)
945     {
946         busErrorInfo->errorCode =
947             HW_RD_FIELD32(errDetRegAddr, EDMA_TC_ERRDET_STAT);
949         busErrorInfo->transferCompletionCode =
950             HW_RD_FIELD32(errDetRegAddr, EDMA_TC_ERRDET_TCC);
952         busErrorInfo->isFinalChainingEnabled =
953             HW_RD_FIELD32(errDetRegAddr, EDMA_TC_ERRDET_TCCHEN);
955         busErrorInfo->isFinalTransferInterruptEnabled =
956             HW_RD_FIELD32(errDetRegAddr, EDMA_TC_ERRDET_TCINTEN);
957     }
960 static void EDMA_clearTransferControllerErrors(uint32_t tcBaseAddr,
961                 EDMA_transferControllerErrorInfo_t *errorInfo)
963     uint32_t errClrRegAddr;
965     errClrRegAddr = tcBaseAddr + EDMA_TC_ERRCLR;
966     HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_TRERR, errorInfo->isTransferRequestError);
967     HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_MMRAERR, errorInfo->isWriteToReservedConfigMemoryMap);
968     HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_BUSERR, errorInfo->isBusError);
971 int32_t EDMA_getTransferControllerErrorStatus(EDMA_Handle handle, uint8_t transferControllerId,
972     bool *isAnyError, EDMA_transferControllerErrorInfo_t *errorInfo)
974     EDMA_Config_t *edmaConfig;
975     EDMA_hwAttrs_t const *hwAttrs;
976     uint32_t tcBaseAddr;
977     int32_t errorCode = EDMA_NO_ERROR;
979 #ifdef EDMA_PARAM_CHECK
980     if (handle == NULL)
981     {
982         errorCode = EDMA_E_INVALID__HANDLE_NULL;
983     }
984 #endif
986     if (errorCode == EDMA_NO_ERROR)
987     {
988         edmaConfig = (EDMA_Config_t *) handle;
989         hwAttrs = edmaConfig->hwAttrs;
990         tcBaseAddr = hwAttrs->TCbaseAddress[transferControllerId];
991         *isAnyError = EDMA_isTransferControllerError(tcBaseAddr);
993         if (*isAnyError == TRUE)
994         {
995             EDMA_getTransferControllerErrorStatusInfo(tcBaseAddr, errorInfo);
996             EDMA_clearTransferControllerErrors(tcBaseAddr, errorInfo);
997             errorInfo->transferControllerId = transferControllerId;
998         }
999     }
1001     return(errorCode);
1004 /**
1005  *  @b Description
1006  *  @n
1007  *      TC error isr which will trigger when any TC errors happen. It will call
1008  *      application registered error call back function with the error information,
1009  *      the error information will also report which transfer controller Id was
1010  *      triggered.
1011  *
1012  *  @param[out]  arg pointer to @ref EDMA_transferControllerErrorIsrArgInfo_t which
1013  *               was set when the ISR was registered using HwiP_create OSAL API.
1014  *
1015  *  \ingroup EDMA_INTERNAL_FUNCTION
1016  *
1017  *  @retval
1018  *      None.
1019  */
1020 static void EDMA_transferController_error_isr (uintptr_t arg)
1022     EDMA_transferControllerErrorIsrArgInfo_t *argInfo =
1023         (EDMA_transferControllerErrorIsrArgInfo_t *) arg;
1024     EDMA_Handle handle = (EDMA_Handle) argInfo->handle;
1025     uint8_t transferControllerId = argInfo->transferControllerId;
1026     EDMA_Config_t *edmaConfig;
1027     EDMA_Object_t *edmaObj;
1028     EDMA_hwAttrs_t const *hwAttrs;
1029     EDMA_transferControllerErrorInfo_t errorInfo;
1030     uint32_t tcBaseAddr;
1032 #ifdef EDMA_DBG
1033     edmaDbg.transCompErrorIsrCount++;
1034 #endif
1036     edmaConfig = (EDMA_Config_t *) handle;
1037     edmaObj = edmaConfig->object;
1038     hwAttrs = edmaConfig->hwAttrs;
1039     tcBaseAddr = hwAttrs->TCbaseAddress[transferControllerId];
1041     errorInfo.transferControllerId = transferControllerId;
1043     EDMA_getTransferControllerErrorStatusInfo(tcBaseAddr, &errorInfo);
1045     /* application call back */
1046     if (edmaObj->transferControllerErrorCallbackFxn != NULL)
1047     {
1048         (*edmaObj->transferControllerErrorCallbackFxn)(handle, &errorInfo);
1049     }
1051     /* clear conditions */
1052     EDMA_clearTransferControllerErrors(tcBaseAddr, &errorInfo);
1054     /* Check conditions again and set EVAL if any detected, this procedure is
1055        similar to the transfer completion isr's (EVAL similar to IEVAL) */
1056     if (EDMA_isTransferControllerError(tcBaseAddr))
1057     {
1058         HW_WR_FIELD32(tcBaseAddr + EDMA_TC_ERRCMD, EDMA_TC_ERRCMD_EVAL, (uint32_t)1);
1059     }
1062 /**
1063  *  @b Description
1064  *  @n
1065  *      Aggregated CC and TC error isr which will trigger when any CC or TC errors happen. It will call
1066  *      corresponding application registered error call back functions with the error information.
1067  *
1068  *  @param[out]  arg  @ref EDMA_Handle which was set when Isr was registered
1069  *                    using OSAL API HwiP_create.
1070  *
1071  *  \ingroup EDMA_INTERNAL_FUNCTION
1072  *
1073  *  @retval
1074  *      None.
1075  */
1076 #if defined (SOC_TPR12) || defined (SOC_AWR294X)
1077 static void EDMA_aggregated_error_transferController_error_isr (uintptr_t arg)
1079     uint32_t errInt, tc, tcErr;
1080     EDMA_Handle handle = (EDMA_Handle) arg;
1081     EDMA_Config_t *edmaConfig;
1082     EDMA_hwAttrs_t const *hwAttrs;
1083     EDMA_transferControllerErrorIsrArgInfo_t argInfo;
1085     edmaConfig = (EDMA_Config_t *) handle;
1086     hwAttrs = edmaConfig->hwAttrs;
1088 #ifdef EDMA_DBG
1089     edmaDbg.aggregatedErrorTransCompErrorIsrCount++;
1090 #endif
1092     /* CC error processing */
1093     errInt = HW_RD_REG32(hwAttrs->CCerrorInterruptsAggregatorStatusRegAddress) & (1U << EDMA_TPCC_ERRAGG_TPCC_EERINT__POS);
1094     if (errInt != 0U)
1095     {
1096         /* clear error. This is done before processing the error because there is the
1097          * EEVAL processing there so this clearance needs to be done before-hand
1098          * TODO: Is the ideal sequence to clear this one inside the error_isr
1099          * at the time of its clearing the conditions? */
1100         HW_WR_REG32(hwAttrs->CCerrorInterruptsAggregatorStatusRegAddress, (1U << EDMA_TPCC_ERRAGG_TPCC_EERINT__POS));
1102         EDMA_error_isr(arg);
1103     }
1105     /* TC error processing */
1106     argInfo.handle = handle;
1107     for(tc = 0; tc < hwAttrs->numEventQueues; tc++)
1108     {
1109         tcErr = HW_RD_REG32(hwAttrs->CCerrorInterruptsAggregatorStatusRegAddress) &
1110                             (1U << (EDMA_TPCC_ERRAGG_TPTC_MIN_ERR__POS + tc));
1112         if (tcErr != 0U)
1113         {
1114             /* clear error. This is done before processing the error because there is the
1115              * EEVAL processing there so this clearance needs to be done before-hand
1116              * TODO_TPR12: Is the ideal sequence to clear this one inside the error_isr
1117              * at the time of its clearing the conditions? */
1118             HW_WR_REG32(hwAttrs->CCerrorInterruptsAggregatorStatusRegAddress, tcErr);
1120             argInfo.transferControllerId = tc;
1121             EDMA_transferController_error_isr((uintptr_t) &argInfo);
1122         }
1123     }
1125 #endif
1127 /**
1128  *  @b Description
1129  *  @n
1130  *      Utility API to configure queue threshold. It exploits the symmetric
1131  *      structure of QWMTHR(A/B) registers.
1132  *
1133  *  @param[in]  ccBaseAddr CC base address.
1134  *  @param[in]  queueId    Queue Id of the queue to be configured.
1135  *  @param[in]  threshold  Queue threshold to be configured.
1136  *
1137  *  \ingroup EDMA_INTERNAL_FUNCTION
1138  *
1139  *  @retval
1140  *      None.
1141  */
1142 static void EDMA_configQueueThreshold(uint32_t ccBaseAddr, uint8_t queueId,
1143                                uint8_t threshold)
1145     uint32_t shift, mask;
1147     shift = (uint32_t)queueId * (EDMA_TPCC_QWMTHRA_Q1_SHIFT - EDMA_TPCC_QWMTHRA_Q0_SHIFT);
1148     mask = (uint32_t)EDMA_TPCC_QWMTHRA_Q0_MASK << shift;
1150     if (queueId <= 3U)
1151     {
1152         /* program queue threshold A reg */
1153         HW_WR_FIELD32_RAW(ccBaseAddr + EDMA_TPCC_QWMTHRA, mask, shift, (uint32_t)threshold);
1154     }
1155     else
1156     {
1157         /* program queue threshold B reg, note the B in QWMTHRB below */
1158         HW_WR_FIELD32_RAW(ccBaseAddr + EDMA_TPCC_QWMTHRB, mask, shift, (uint32_t)threshold);
1159     }
1162 /**
1163  *  @b Description
1164  *  @n
1165  *      Utility API to configure queue priority. It exploits the symmetric
1166  *      structure of QUEPRI registers.
1167  *
1168  *  @param[in]  ccBaseAddr CC base address.
1169  *  @param[in]  transferController  TC (or queue) Id.
1170  *  @param[in]  priority  Queue priority to be configured.
1171  *
1172  *  \ingroup EDMA_INTERNAL_FUNCTION
1173  *
1174  *  @retval
1175  *      None.
1176  */
1177 static void EDMA_configQueuePriority(uint32_t ccBaseAddr, uint8_t transferController,
1178                                uint8_t priority)
1180     uint32_t shift, mask;
1182     shift = (uint32_t)transferController * (EDMA_TPCC_QUEPRI_PRIQ1_SHIFT - EDMA_TPCC_QUEPRI_PRIQ0_SHIFT);
1183     mask = (uint32_t)EDMA_TPCC_QUEPRI_PRIQ0_MASK << shift;
1184     HW_WR_FIELD32_RAW(ccBaseAddr + EDMA_TPCC_QUEPRI, mask, shift, (uint32_t)priority);
1187 /**
1188  *  @b Description
1189  *  @n
1190  *      Utility API to configure a transfer controller's error detection settings.
1191  *
1192  *  @param[in]  tcBaseAddr TC base address.
1193  *  @param[in]  isEnableAllErrors   true if all error checking is to be enabled.
1194  *  @param[in]  config Pointer to @ref EDMA_transferControllerErrorConfig_t when
1195  *                     selective errors are to be configured.
1196  *
1197  *  \ingroup EDMA_INTERNAL_FUNCTION
1198  *
1199  *  @retval
1200  *      None.
1201  */
1202 static void EDMA_configTransferControllerError(uint32_t tcBaseAddr,
1203     bool isEnableAllErrors, EDMA_transferControllerErrorConfig_t const *config)
1205     uint32_t errenRegAddr;
1206     bool isBusErrorEnabled, isTransferRequestErrorEnabled,
1207          isWriteToReservedConfigMemoryMapEnabled;
1209     errenRegAddr = tcBaseAddr + EDMA_TC_ERREN;
1210     if (isEnableAllErrors == true)
1211     {
1212         isBusErrorEnabled = true;
1213         isTransferRequestErrorEnabled = true;
1214         isWriteToReservedConfigMemoryMapEnabled = true;
1215     }
1216     else
1217     {
1218         isBusErrorEnabled = config->isBusErrorEnabled;
1219         isTransferRequestErrorEnabled = config->isTransferRequestErrorEnabled;
1220         isWriteToReservedConfigMemoryMapEnabled =
1221             config->isWriteToReservedConfigMemoryMapEnabled;
1222     }
1223     HW_WR_FIELD32(errenRegAddr, EDMA_TC_ERREN_BUSERR, isBusErrorEnabled);
1224     HW_WR_FIELD32(errenRegAddr, EDMA_TC_ERREN_TRERR, isTransferRequestErrorEnabled);
1225     HW_WR_FIELD32(errenRegAddr, EDMA_TC_ERREN_MMRAERR, isWriteToReservedConfigMemoryMapEnabled);
1228 /**
1229  *  @b Description
1230  *  @n
1231  *      Utility function for starting a transfer.
1232  *
1233  *  @param[in]  handle  EDMA handle.
1234  *  @param[in]  channelId  channel Id.
1235  *  @param[in]  channelType channed Type.
1236  *  @param[in]  isStaticSet true if STATIC bit is to be set else false.
1237  *
1238  *  \ingroup EDMA_INTERNAL_FUNCTION
1239  *
1240  *  @retval
1241  *      one of @ref EDMA_ERROR_CODES
1242  */
1243 static inline int32_t EDMA_startTransfer_assist(EDMA_Handle handle, uint8_t channelId,
1244     uint8_t channelType, bool isStaticSet)
1246     EDMA_Config_t *edmaConfig;
1247     EDMA_Object_t *edmaObj;
1248     EDMA_hwAttrs_t const *hwAttrs;
1249     uint32_t ccBaseAddr;
1250     int32_t errorCode = EDMA_NO_ERROR;
1251     uint16_t paramId;
1253 #ifdef EDMA_PARAM_CHECK
1254     if (handle == NULL)
1255     {
1256         errorCode = EDMA_E_INVALID__HANDLE_NULL;
1257     }
1258     if ((channelType != (uint8_t)EDMA3_CHANNEL_TYPE_DMA) &&
1259         (channelType != (uint8_t)EDMA3_CHANNEL_TYPE_QDMA))
1260     {
1261         errorCode = EDMA_E_INVALID__DMA_CHANNEL_TYPE;
1262     }
1263 #endif
1265     if (errorCode == EDMA_NO_ERROR)
1266     {
1267         edmaConfig = (EDMA_Config_t *) handle;
1268         edmaObj = edmaConfig->object;
1269         hwAttrs = edmaConfig->hwAttrs;
1270         ccBaseAddr = hwAttrs->CCbaseAddress;
1271     }
1273     if ((errorCode == EDMA_NO_ERROR) &&
1274         (channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA))
1275     {
1276 #ifdef EDMA_PARAM_CHECK
1277         /* error checking */
1278         if (channelId >= EDMA_NUM_QDMA_CHANNELS)
1279         {
1280             errorCode = EDMA_E_INVALID__QDMA_CHANNEL_ID;
1281         }
1282 #endif
1284         if (EDMA3QdmaGetErrIntrStatus(ccBaseAddr) & ((uint32_t)1 << channelId))
1285         {
1286             errorCode = EDMA_E_UNEXPECTED__QDMA_EVENT_MISS_DETECTED;
1287             /* clear previous missed events : QSECR and QEMCR */
1288             EDMA3QdmaClrMissEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1289         }
1291         if (errorCode == EDMA_NO_ERROR)
1292         {
1293             if (isStaticSet == true)
1294             {
1295                 if (HW_RD_FIELD32(ccBaseAddr + EDMA_TPCC_QCHMAPN((uint32_t)channelId),
1296                         EDMA_TPCC_QCHMAPN_TRWORD)  == EDMA_QDMA_TRIG_WORD_OFFSET_OPT)
1297                 {
1298                     /* modify triggerWordValue before triggering */
1299                     HW_WR_FIELD32(&edmaObj->qdmaObj[channelId].triggerWordValue,
1300                         EDMA_TPCC_OPT_STATIC, 1);
1301                 }
1302                 else
1303                 {
1304                     /* update OPT field */
1305                     paramId = HW_RD_FIELD32(ccBaseAddr + EDMA_TPCC_QCHMAPN((uint32_t)channelId),
1306                         EDMA_TPCC_QCHMAPN_PAENTRY);
1307                     HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_OPT((uint32_t)paramId), EDMA_TPCC_OPT_STATIC, 1);
1309                 }
1310             }
1311             /* start transfer of specified Qdma channel, trigger word was programmed in config API */
1312             HW_WR_REG32(edmaObj->qdmaObj[channelId].triggerWordAddress,
1313                                             edmaObj->qdmaObj[channelId].triggerWordValue);
1314         }
1315     }
1316     if ((errorCode == EDMA_NO_ERROR) &&
1317         (channelType == (uint8_t)EDMA3_CHANNEL_TYPE_DMA))
1318     {
1319 #ifdef EDMA_PARAM_CHECK
1320         /* error checking */
1321         if (channelId >= EDMA_NUM_DMA_CHANNELS)
1322         {
1323             errorCode = EDMA_E_INVALID__DMA_CHANNEL_ID;
1324         }
1325 #endif
1327         if (errorCode == EDMA_NO_ERROR)
1328         {
1329             if (channelId < 32U) {
1330                 if (EDMA3GetErrIntrStatus(ccBaseAddr) & ((uint32_t)1 << channelId))
1331                 {
1332                     errorCode = EDMA_E_UNEXPECTED__DMA_EVENT_MISS_DETECTED;
1333                 }
1334             }
1335             else
1336             {
1337                 if (EDMA3ErrIntrHighStatusGet(ccBaseAddr) & ((uint32_t)1 << ((uint32_t)channelId-32U)))
1338                 {
1339                     errorCode = EDMA_E_UNEXPECTED__DMA_EVENT_MISS_DETECTED;
1340                 }
1341             }
1343             if (errorCode != EDMA_NO_ERROR)
1344             {
1345                 /* clear missed events */
1346                 EDMA3ClrMissEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1347             }
1348         }
1350         if (errorCode == EDMA_NO_ERROR)
1351         {
1352             /* trigger the event */
1353             EDMA3SetEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1354         }
1355     }
1357     return(errorCode);
1360 int32_t EDMA_configChannel(EDMA_Handle handle, EDMA_channelConfig_t const *config,
1361     bool isEnableChannel)
1363     EDMA_Config_t *edmaConfig = (EDMA_Config_t *) handle;
1364     EDMA_Object_t *edmaObj;
1365     EDMA_hwAttrs_t const *hwAttrs;
1366     uint32_t ccBaseAddr;
1367     int32_t errorCode = EDMA_NO_ERROR;
1368     EDMA_paramSetConfig_t const *pSetCfg;
1369     uint8_t channelId = config->channelId;
1370     uint16_t paramId = config->paramId;
1372     edmaObj = edmaConfig->object;
1373     hwAttrs = edmaConfig->hwAttrs;
1374     ccBaseAddr = hwAttrs->CCbaseAddress;
1376 #ifdef EDMA_PARAM_CHECK
1377     /* validate configuration */
1378     errorCode = EDMA_validate_channel_config(handle, hwAttrs, config);
1379 #endif
1381     if (errorCode == EDMA_NO_ERROR)
1382     {
1383         pSetCfg = &config->paramSetConfig;
1385         EDMA3EnableChInShadowRegRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)config->channelType, (uint32_t)channelId);
1386         EDMA3MapChToEvtQ(ccBaseAddr, (uint32_t)config->channelType, (uint32_t)channelId,
1387             (uint32_t)config->eventQueueId);
1389         /* disable channel (event) first */
1390         errorCode = EDMA_disableChannel(handle, channelId, config->channelType);
1391     }
1392     if (errorCode == EDMA_NO_ERROR)
1393     {
1394         if (config->channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA)
1395         {
1396             /* map channel to param set */
1397             {
1398                 uint32_t temp = (uint32_t) paramId;
1399                 EDMA3MapQdmaChToPaRAM(ccBaseAddr, (uint32_t)channelId, &temp);
1400             }
1402             /* set trigger word */
1403             EDMA3SetQdmaTrigWord(ccBaseAddr, (uint32_t)channelId, config->qdmaParamTriggerWordOffset);
1405             edmaObj->qdmaObj[channelId].triggerWordAddress = ccBaseAddr +
1406                 EDMA_TPCC_OPT((uint32_t)paramId) + config->qdmaParamTriggerWordOffset * sizeof(uint32_t);
1407         }
1408         else
1409         {   /* config->channelType is EDMA3_CHANNEL_TYPE_DMA */
1410             if (hwAttrs->isChannelMapExist == true)
1411             {
1412                 /* map channel to param set */
1413                 EDMA3ChannelToParamMap(ccBaseAddr, (uint32_t)channelId, (uint32_t)paramId);
1414             }
1415         }
1417         EDMA3ClrIntrRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)pSetCfg->transferCompletionCode);
1419         EDMA_paramConfig_assist(ccBaseAddr, edmaConfig->initParams.regionId, paramId, pSetCfg, config->transferCompletionCallbackFxn,
1420             config->transferCompletionCallbackFxnArg, edmaObj);
1422         /* store trigger word param value for Qdma channel */
1423         if (config->channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA)
1424         {
1425             uint32_t *pArray; /* param Set as array of uint32_t */
1427             pArray = (uint32_t *)(ccBaseAddr + EDMA_TPCC_OPT((uint32_t)paramId));
1428             edmaObj->qdmaObj[channelId].triggerWordValue = pArray[config->qdmaParamTriggerWordOffset];
1429         }
1431         if (isEnableChannel == true)
1432         {
1433             errorCode = EDMA_enableChannel(handle, channelId, config->channelType);
1434         }
1435     }
1437     return(errorCode);
1440 int32_t EDMA_enableChannel(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1442     EDMA_Config_t *edmaConfig = (EDMA_Config_t *) handle;
1443     EDMA_hwAttrs_t const *hwAttrs;
1444     uint32_t ccBaseAddr;
1445     int32_t errorCode = EDMA_NO_ERROR;
1447     hwAttrs =  edmaConfig->hwAttrs;
1448     ccBaseAddr = hwAttrs->CCbaseAddress;
1450 #ifdef EDMA_PARAM_CHECK
1451     if (handle == NULL)
1452     {
1453         errorCode = EDMA_E_INVALID__HANDLE_NULL;
1454     }
1455     if (errorCode == EDMA_NO_ERROR)
1456     {
1457         errorCode = EDMA_validate_channelIdchannelType(channelId, channelType);
1458     }
1459 #endif
1461     if (errorCode == EDMA_NO_ERROR)
1462     {
1463         /* enable events, clear if applicable */
1464         if (channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA)
1465         {
1466             /* clears QSECR and QEMCR */
1467             EDMA3QdmaClrMissEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1469             /* enable the Qdma event */
1470             EDMA3EnableQdmaEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1472             /* From this point onwards, QDMA channel is armed and ready to be
1473             triggered by either through @ref EDMA_startTransfer API or
1474             through @ref EDMA_startTransferQdmaTrigWordWrite API */
1475         }
1476         else /* config->channelType is EDMA3_CHANNEL_TYPE_DMA */
1477         {
1478             /* clear SECR & EMCR to clean any previous NULL request */
1479             EDMA3ClrMissEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1481             /* Set EESR to enable event */
1482             EDMA3EnableDmaEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1484             /* From this point onwards, DMA channel is armed and ready to be
1485             triggered by the event happening in the SoC using
1486             the @ref edmaStartTransfer API */
1488             /* Note: For manual trigger we don't need to clear/enable DMA event as it is
1489             ignored when triggering channel manual (through a write to ESR) but not
1490             doing these additional operations above would require a config parameter
1491             to distinguish manual or event triggered (or both) just to serve the purpose
1492             of not executing code that is harmless/don't care for the manual trigger */
1494         }
1495     }
1496     return(errorCode);
1499 int32_t EDMA_disableChannel(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1501     EDMA_Config_t *edmaConfig = (EDMA_Config_t *) handle;
1502     EDMA_hwAttrs_t const *hwAttrs;
1503     uint32_t ccBaseAddr;
1504     int32_t errorCode = EDMA_NO_ERROR;
1506     hwAttrs =  edmaConfig->hwAttrs;
1507     ccBaseAddr = hwAttrs->CCbaseAddress;
1509 #ifdef EDMA_PARAM_CHECK
1510     if (handle == NULL)
1511     {
1512         errorCode = EDMA_E_INVALID__HANDLE_NULL;
1513     }
1514     if (errorCode == EDMA_NO_ERROR)
1515     {
1516         errorCode = EDMA_validate_channelIdchannelType(channelId, channelType);
1517     }
1518 #endif
1520     if (errorCode == EDMA_NO_ERROR)
1521     {
1522         /* enable events, clear if applicable */
1523         if (channelType == (uint8_t)EDMA3_CHANNEL_TYPE_QDMA)
1524         {
1525             /* disable the Qdma event */
1526             EDMA3DisableQdmaEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1528             /* clears QSECR and QEMCR */
1529             EDMA3QdmaClrMissEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1531             /* From this point onwards, QDMA channel is armed and ready to be
1532             triggered by either through @ref EDMA_startTransfer API or
1533             through @ref EDMA_startTransferQdmaTrigWordWrite API */
1534         }
1535         else /* config->channelType is EDMA3_CHANNEL_TYPE_DMA */
1536         {
1537             /* disable DMA event */
1538             EDMA3DisableDmaEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1540             /* clear SECR & EMCR to clean any previous NULL request */
1541             EDMA3ClrMissEvtRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)channelId);
1543         }
1544     }
1545     return(errorCode);
1548 int32_t EDMA_configParamSet(EDMA_Handle handle, uint16_t paramId,
1549     EDMA_paramConfig_t const *config)
1551     EDMA_Config_t *edmaConfig = (EDMA_Config_t *) handle;
1552     EDMA_Object_t *edmaObj;
1553     EDMA_hwAttrs_t const *hwAttrs;
1554     uint32_t ccBaseAddr;
1555     int32_t errorCode = EDMA_NO_ERROR;
1557     edmaObj = edmaConfig->object;
1558     hwAttrs = edmaConfig->hwAttrs;
1559     ccBaseAddr = hwAttrs->CCbaseAddress;
1561 #ifdef EDMA_PARAM_CHECK
1562     if (config == NULL)
1563     {
1564         errorCode = EDMA_E_INVALID__CONFIG_POINTER_NULL;
1565     }
1566     if (errorCode == EDMA_NO_ERROR)
1567     {
1568         /* validate configuration */
1569         errorCode = EDMA_validate_param_config(handle, hwAttrs, paramId, &config->paramSetConfig,
1570             config->transferCompletionCallbackFxn);
1571     }
1572 #endif
1574     if (errorCode == EDMA_NO_ERROR)
1575     {
1576         EDMA_paramConfig_assist(ccBaseAddr, edmaConfig->initParams.regionId, paramId, &config->paramSetConfig,
1577             config->transferCompletionCallbackFxn, config->transferCompletionCallbackFxnArg,
1578             edmaObj);
1579     }
1581     return(errorCode);
1584 static void EDMA_paramConfig_assist(uint32_t ccBaseAddr, uint32_t regionId, uint16_t paramId,
1585     EDMA_paramSetConfig_t const *pSetCfg,
1586     EDMA_transferCompletionCallbackFxn_t transferCompletionCallbackFxn,
1587     uintptr_t transferCompletionCallbackFxnArg, EDMA_Object_t *edmaObj
1588     )
1590     EDMA_paramSetConfig_assist(ccBaseAddr, paramId, pSetCfg);
1592     /* Register transfer completion call back function */
1593     if (transferCompletionCallbackFxn != NULL)
1594     {
1595         edmaObj->transferCompleteCallbackFxn[pSetCfg->transferCompletionCode] =
1596             transferCompletionCallbackFxn;
1598         edmaObj->transferCompleteCallbackFxnArg[pSetCfg->transferCompletionCode] =
1599             transferCompletionCallbackFxnArg;
1601         /* enable interrupt */
1602         EDMA3EnableEvtIntrRegion(ccBaseAddr, regionId, (uint32_t)pSetCfg->transferCompletionCode);
1603     }
1604     else
1605     {
1606         /* disable interrupt, this is important for polled mode transfers we don't
1607            want interrupt to trigger (there is an assert in the interrupt to capture
1608            this situation) */
1609         EDMA3DisableEvtIntrRegion(ccBaseAddr, regionId, (uint32_t)pSetCfg->transferCompletionCode);
1611         edmaObj->transferCompleteCallbackFxn[pSetCfg->transferCompletionCode] =
1612             NULL;
1613     }
1616 int32_t EDMA_linkParamSets(EDMA_Handle handle, uint16_t fromParamId, uint16_t toParamId)
1618     EDMA_Config_t *edmaConfig;
1619     EDMA_hwAttrs_t const *hwAttrs;
1620     uint32_t ccBaseAddr;
1621     int32_t errorCode = EDMA_NO_ERROR;
1623 #ifdef EDMA_PARAM_CHECK
1624     if (handle == NULL)
1625     {
1626         errorCode = EDMA_E_INVALID__HANDLE_NULL;
1627     }
1628 #endif
1630     if (errorCode == EDMA_NO_ERROR)
1631     {
1632         edmaConfig = (EDMA_Config_t *) handle;
1633         hwAttrs =  edmaConfig->hwAttrs;
1634         ccBaseAddr = hwAttrs->CCbaseAddress;
1636     #ifdef EDMA_PARAM_CHECK
1637         if ((fromParamId >= hwAttrs->numParamSets) ||
1638             (toParamId >= hwAttrs->numParamSets))
1639         {
1640             errorCode = EDMA_E_INVALID__PARAM_ID;
1641         }
1642     #endif
1643     }
1644     if (errorCode == EDMA_NO_ERROR)
1645     {
1646     /* Do not use LinkChannel API, it changes toParamId's TCC to that of
1647     fromParamId and also has issue JIRA: PRSDK-1055 */
1648     #if 0
1649         EDMA3LinkChannel(ccBaseAddr, (uint32_t)fromParamId, (uint32_t)toParamId);
1650     #else
1651         HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_LNK((uint32_t)fromParamId), EDMA_TPCC_LNK_LINK,
1652             ccBaseAddr + EDMA_TPCC_OPT((uint32_t)toParamId));
1653     #endif
1654     }
1656     return(errorCode);
1659 int32_t EDMA_chainChannels(EDMA_Handle handle, uint16_t fromParamId, uint8_t toChannelId)
1661     EDMA_Config_t *edmaConfig;
1662     EDMA_hwAttrs_t const *hwAttrs;
1663     uint32_t ccBaseAddr;
1664     int32_t errorCode = EDMA_NO_ERROR;
1666 #ifdef EDMA_PARAM_CHECK
1667     if (handle == NULL)
1668     {
1669         errorCode = EDMA_E_INVALID__HANDLE_NULL;
1670     }
1671     if ((errorCode == EDMA_NO_ERROR) && (toChannelId >= EDMA_NUM_DMA_CHANNELS))
1672     {
1673         errorCode = EDMA_E_INVALID__DMA_CHANNEL_ID;
1674     }
1675 #endif
1677     if (errorCode == EDMA_NO_ERROR)
1678     {
1679         edmaConfig = (EDMA_Config_t *) handle;
1680         hwAttrs =  edmaConfig->hwAttrs;
1681         ccBaseAddr = hwAttrs->CCbaseAddress;
1682     }
1684 #ifdef EDMA_PARAM_CHECK
1685     if ((errorCode == EDMA_NO_ERROR) && (fromParamId >= hwAttrs->numParamSets))
1686     {
1687         errorCode = EDMA_E_INVALID__PARAM_ID;
1688     }
1689 #endif
1691     if (errorCode == EDMA_NO_ERROR)
1692     {
1693         HW_WR_FIELD32(ccBaseAddr + EDMA_TPCC_OPT((uint32_t)fromParamId), EDMA_TPCC_OPT_TCC,
1694             toChannelId);
1695     }
1697     return(errorCode);
1700 int32_t EDMA_startTransfer(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1702     return(EDMA_startTransfer_assist(handle, channelId, channelType, false));
1705 int32_t EDMA_startDmaTransfer(EDMA_Handle handle, uint8_t channelId)
1707     return(EDMA_startTransfer_assist(handle, channelId,
1708         (uint8_t)EDMA3_CHANNEL_TYPE_DMA, false));
1711 int32_t EDMA_startQdmaTransfer(EDMA_Handle handle, uint8_t channelId)
1713     return(EDMA_startTransfer_assist(handle, channelId,
1714         (uint8_t)EDMA3_CHANNEL_TYPE_QDMA, false));
1717 int32_t EDMA_startFinalQdmaTransfer(EDMA_Handle handle, uint8_t channelId)
1719     return(EDMA_startTransfer_assist(handle, channelId,
1720         (uint8_t)EDMA3_CHANNEL_TYPE_QDMA, true));
1723 int32_t EDMA_isTransferComplete(EDMA_Handle handle, uint8_t transferCompletionCode,
1724     bool *isTransferComplete)
1726     EDMA_Config_t *edmaConfig;
1727     EDMA_Object_t *edmaObj;
1728     EDMA_hwAttrs_t const *hwAttrs;
1729     uint32_t ccBaseAddr;
1730     int32_t errorCode = EDMA_NO_ERROR;
1732 #ifdef EDMA_PARAM_CHECK
1733     if (handle == NULL)
1734     {
1735         errorCode = EDMA_E_INVALID__HANDLE_NULL;
1736     }
1737     if ((errorCode == EDMA_NO_ERROR) && (transferCompletionCode >= EDMA_NUM_TCC))
1738     {
1739         errorCode = EDMA_E_INVALID__TRANSFER_COMPLETION_CODE;
1740     }
1741 #endif
1743     if (errorCode == EDMA_NO_ERROR)
1744     {
1745         edmaConfig = (EDMA_Config_t *) handle;
1746         edmaObj = edmaConfig->object;
1748         /* Transfer completion call back function must not be registered for the
1749         transfer completion code */
1750         if (edmaObj->transferCompleteCallbackFxn[transferCompletionCode] != NULL)
1751         {
1752             errorCode = EDMA_E_UNEXPECTED__ATTEMPT_TO_TEST_COMPLETION;
1754             /* Additional protection in case user does not check for error code,
1755             make the transfer never succeed. */
1756             *isTransferComplete = false;
1757         }
1758     }
1760     if (errorCode == EDMA_NO_ERROR)
1761     {
1762         hwAttrs =  edmaConfig->hwAttrs;
1763         ccBaseAddr = hwAttrs->CCbaseAddress;
1765         if (transferCompletionCode < 32U)
1766         {
1767             *isTransferComplete = (bool)((EDMA3GetIntrStatusRegion(ccBaseAddr, edmaConfig->initParams.regionId) &
1768                                     ((uint32_t)1 << transferCompletionCode)) != 0U);
1769         }
1770         else
1771         {
1772             *isTransferComplete = (bool)((EDMA3IntrStatusHighGetRegion(ccBaseAddr, edmaConfig->initParams.regionId) &
1773                                     ((uint32_t)1 << (transferCompletionCode-32U))) != 0U);
1774         }
1776         /* if transfer is complete, clear IPR(H) bit to allow new transfer */
1777         if (*isTransferComplete == true)
1778         {
1779             EDMA3ClrIntrRegion(ccBaseAddr, edmaConfig->initParams.regionId, (uint32_t)transferCompletionCode);
1780         }
1781     }
1783     return(errorCode);
1786 int32_t EDMA_setDestinationAddress(EDMA_Handle handle,
1787     uint16_t paramId,
1788     uint32_t destinationAddress)
1790     EDMA_Config_t *edmaConfig;
1791     EDMA_hwAttrs_t const *hwAttrs;
1792     uint32_t ccBaseAddr;
1793     int32_t errorCode = EDMA_NO_ERROR;
1795 #ifdef EDMA_PARAM_CHECK
1796     if (handle == NULL)
1797     {
1798         errorCode = EDMA_E_INVALID__HANDLE_NULL;
1799     }
1800 #endif
1801     if (errorCode == EDMA_NO_ERROR)
1802     {
1803         edmaConfig = (EDMA_Config_t *) handle;
1804         hwAttrs =  edmaConfig->hwAttrs;
1805         ccBaseAddr = hwAttrs->CCbaseAddress;
1806     }
1808 #ifdef EDMA_PARAM_CHECK
1809     if ((errorCode == EDMA_NO_ERROR) && (paramId >= hwAttrs->numParamSets))
1810     {
1811         errorCode = EDMA_E_INVALID__PARAM_ID;
1812     }
1813 #endif
1814     if (errorCode == EDMA_NO_ERROR)
1815     {
1816         HW_WR_REG32(ccBaseAddr + EDMA_TPCC_DST((uint32_t)paramId), destinationAddress);
1817     }
1818     return(errorCode);
1821 int32_t EDMA_setSourceAddress(EDMA_Handle handle,
1822     uint16_t paramId,
1823     uint32_t sourceAddress)
1825     EDMA_Config_t *edmaConfig;
1826     EDMA_hwAttrs_t const *hwAttrs;
1827     uint32_t ccBaseAddr;
1828     int32_t errorCode = EDMA_NO_ERROR;
1830 #ifdef EDMA_PARAM_CHECK
1831     if (handle == NULL)
1832     {
1833         errorCode = EDMA_E_INVALID__HANDLE_NULL;
1834     }
1835 #endif
1837     if (errorCode == EDMA_NO_ERROR)
1838     {
1839         edmaConfig = (EDMA_Config_t *) handle;
1840         hwAttrs =  edmaConfig->hwAttrs;
1841         ccBaseAddr = hwAttrs->CCbaseAddress;
1842     }
1844 #ifdef EDMA_PARAM_CHECK
1845     if ((errorCode == EDMA_NO_ERROR) && (paramId >= hwAttrs->numParamSets))
1846     {
1847         errorCode = EDMA_E_INVALID__PARAM_ID;
1848     }
1849 #endif
1850     if (errorCode == EDMA_NO_ERROR)
1851     {
1852         HW_WR_REG32(ccBaseAddr + EDMA_TPCC_SRC((uint32_t)paramId), sourceAddress);
1853     }
1854     return(errorCode);
1857 static void EDMA_unregisterInterrupts(EDMA_Handle handle)
1859     EDMA_Config_t *edmaConfig;
1860     EDMA_Object_t *edmaObj;
1861     EDMA_hwAttrs_t const *hwAttrs;
1862     uint8_t tc;
1863     bool isUnifiedErrorInterrupts;
1864     int32_t interruptNum, corepacEvent;
1866     edmaConfig = (EDMA_Config_t *) handle;
1867     edmaObj = edmaConfig->object;
1868     hwAttrs = edmaConfig->hwAttrs;
1870     /*if (edmaObj->isUsed == false) {
1871         generate error
1872     }*/
1874     if ((hwAttrs->transferCompletionInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID) &&
1875         (edmaObj->hwiTransferCompleteHandle != NULL))
1876     {
1877     #if defined(_TMS320C6X)
1878         corepacEvent = (int32_t)hwAttrs->transferCompletionInterruptNum; /* Event going in to CPU */
1879         interruptNum = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
1880     #else
1881         interruptNum = (int32_t)hwAttrs->transferCompletionInterruptNum; /* Host Interrupt vector */
1882         corepacEvent = (int32_t)hwAttrs->transferCompletionInterruptNum;
1883     #endif
1885         Osal_DisableInterrupt(corepacEvent, interruptNum);
1886         Osal_DeleteInterrupt(edmaObj->hwiTransferCompleteHandle, corepacEvent);
1887         edmaObj->hwiTransferCompleteHandle = NULL;
1888     }
1890     isUnifiedErrorInterrupts = (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID) &&
1891                             (hwAttrs->errorInterruptNum == hwAttrs->transferControllerErrorInterruptNum[0]);
1892     #if defined(_TMS320C6X)
1893         corepacEvent = (int32_t)hwAttrs->errorInterruptNum; /* Event going in to CPU */
1894         interruptNum = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
1895     #else
1896         interruptNum = (int32_t)hwAttrs->errorInterruptNum; /* Host Interrupt vector */
1897         corepacEvent = (int32_t)hwAttrs->errorInterruptNum;
1898     #endif
1900     if (isUnifiedErrorInterrupts == true)
1901     {
1902         if (edmaObj->hwiErrorHandle != NULL)
1903         {
1904             Osal_DisableInterrupt(corepacEvent, interruptNum);
1905             Osal_DeleteInterrupt(edmaObj->hwiErrorHandle, corepacEvent);
1906             edmaObj->hwiErrorHandle = NULL;
1907         }
1908     }
1909     else
1910     {
1911         if ((hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID) &&
1912             (edmaObj->hwiErrorHandle != NULL))
1913         {
1914             Osal_DisableInterrupt(corepacEvent, interruptNum);
1915             Osal_DeleteInterrupt(edmaObj->hwiErrorHandle, corepacEvent);
1916             edmaObj->hwiErrorHandle = NULL;
1917         }
1919         for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
1920         {
1921             if ((hwAttrs->transferControllerErrorInterruptNum[tc] != EDMA_INTERRUPT_NOT_CONNECTED_ID) &&
1922                 (edmaObj->hwiTransferControllerErrorHandle[tc] != NULL))
1923             {
1924             #if defined(_TMS320C6X)
1925                 corepacEvent = (int32_t)hwAttrs->transferControllerErrorInterruptNum[tc]; /* Event going in to CPU */
1926                 interruptNum = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
1927             #else
1928                 interruptNum = (int32_t)hwAttrs->transferControllerErrorInterruptNum[tc]; /* Host Interrupt vector */
1929                 corepacEvent = (int32_t)hwAttrs->transferControllerErrorInterruptNum[tc];
1930             #endif
1932                 Osal_DisableInterrupt(corepacEvent, interruptNum);
1933                 Osal_DeleteInterrupt(edmaObj->hwiTransferControllerErrorHandle[tc], corepacEvent);
1934                 edmaObj->hwiTransferControllerErrorHandle[tc] = NULL;
1935             }
1936         }
1937     }
1940 int32_t EDMA_close(EDMA_Handle handle)
1942     EDMA_Config_t *edmaConfig;
1943     EDMA_Object_t *edmaObj;
1944     int32_t errorCode = EDMA_NO_ERROR;
1946 #ifdef EDMA_PARAM_CHECK
1947     if (handle == NULL)
1948     {
1949         errorCode = EDMA_E_INVALID__HANDLE_NULL;
1950     }
1951 #endif
1953     if (errorCode == EDMA_NO_ERROR)
1954     {
1955         EDMA_unregisterInterrupts(handle);
1956         edmaConfig = (EDMA_Config_t *) handle;
1957         edmaObj = edmaConfig->object;
1958         edmaObj->isUsed = false;
1959         edmaConfig->hwAttrs = NULL;
1960         edmaConfig->object  = NULL;
1961     }
1963     return(errorCode);
1966 uint8_t EDMA_getNumInstances(void)
1968     return((uint8_t)EDMA_NUM_CC);
1971 int32_t EDMA_init(uint8_t instanceId, const EDMA3CCInitParams *initParam)
1973     uint32_t ccBaseAddr, tcBaseAddr, errClrRegAddr;
1974     uint8_t tc;
1975     int32_t errorCode = EDMA_NO_ERROR;
1976     const EDMA_hwAttrs_t *hwAttrs = NULL;
1978 #if (true != 1)
1979 #error define "true" is not 1
1980 #endif
1982 #ifdef EDMA_PARAM_CHECK
1983     if (instanceId > EDMA_DRV_INST_MAX)
1984     {
1985         errorCode = EDMA_E_INVALID__INSTANCE_ID;
1986     }
1987 #endif
1989     if (errorCode == EDMA_NO_ERROR)
1990     {
1991         hwAttrs = EDMA_getHwAttrs(instanceId);
1992         if (hwAttrs == NULL)
1993         {
1994             errorCode = EDMA_E_INVALID__INSTANCE_ID;
1995         }
1996     }
1998     if (errorCode == EDMA_NO_ERROR)
1999     {
2000     #ifdef EDMA_DBG
2001         memset(&edmaDbg, 0, sizeof(edmaDbg));
2002     #endif
2004         ccBaseAddr = hwAttrs->CCbaseAddress;
2005         errorCode = EDMA3Initialize(ccBaseAddr, initParam);
2006         /* clear tansfer controller errors */
2007         for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2008         {
2009             tcBaseAddr = hwAttrs->TCbaseAddress[tc];
2010             errClrRegAddr = tcBaseAddr + EDMA_TC_ERRCLR;
2011             HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_TRERR, 1);
2012             HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_MMRAERR, 1);
2013             HW_WR_FIELD32(errClrRegAddr, EDMA_TC_ERRCLR_BUSERR, 1);
2014         }
2015     }
2016     if (errorCode == EDMA_NO_ERROR)
2017     {
2018         /* Copy the init params in driver object. */
2019         memcpy(&(EDMA_config[instanceId].initParams), initParam, sizeof(EDMA3CCInitParams));
2020     }
2022     return(errorCode);
2025 int32_t EDMA_getStatusInfo(EDMA_Handle handle, EDMA_statusInfo_t *status)
2027     EDMA_Config_t *edmaConfig;
2028     EDMA_hwAttrs_t const *hwAttrs;
2029     uint32_t ccBaseAddr;
2030     uint8_t queueId;
2031     EDMA_queueStatusInfo_t *qStatus;
2032     uint8_t qEntryIndx, numOutstandingEntries;
2033     uint32_t qStatRegAddr, qEntry0Addr, qEntryAddrJump, ccStatRegAddr;
2034     int32_t errorCode = EDMA_NO_ERROR;
2036 #ifdef EDMA_PARAM_CHECK
2037     if (handle == NULL)
2038     {
2039         errorCode = EDMA_E_INVALID__HANDLE_NULL;
2040     }
2041     if ((errorCode == EDMA_NO_ERROR) && (status == NULL))
2042     {
2043         errorCode = EDMA_E_INVALID__STATUS_POINTER_NULL;
2044     }
2045 #endif
2047     if (errorCode == EDMA_NO_ERROR)
2048     {
2049         edmaConfig = (EDMA_Config_t *) handle;
2050         hwAttrs =  edmaConfig->hwAttrs;
2051         ccBaseAddr = hwAttrs->CCbaseAddress;
2053         /* queue status processing */
2054         for (queueId = 0; queueId < hwAttrs->numEventQueues; queueId++)
2055         {
2056             qStatRegAddr = ccBaseAddr + EDMA_TPCC_QSTATN((uint32_t)queueId);
2057             qStatus = &status->queue[queueId];
2059             qStatus->isThresholdExceeded =
2060                 (bool) HW_RD_FIELD32(qStatRegAddr, EDMA_TPCC_QSTATN_THRXCD);
2062             qStatus->maxQueueEntries =
2063                 (uint8_t) HW_RD_FIELD32(qStatRegAddr, EDMA_TPCC_QSTATN_WM);
2065             numOutstandingEntries =
2066                 (uint8_t) HW_RD_FIELD32(qStatRegAddr, EDMA_TPCC_QSTATN_NUMVAL);
2067             qStatus->numOutstandingEntries = numOutstandingEntries;
2069             /* process outstanding queue entries first,
2070             starting from position indicated by the h/w, note queue circularity */
2071             qEntryIndx = (uint8_t) HW_RD_FIELD32(qStatRegAddr, EDMA_TPCC_QSTATN_STRTPTR);
2072             qEntry0Addr = ccBaseAddr + EDMA_TPCC_QNE0((uint8_t)queueId);
2073             qEntryAddrJump = EDMA_TPCC_QNE1(0U) - EDMA_TPCC_QNE0(0U);
2074             EDMA_update_queue_entries(qEntry0Addr, qEntryAddrJump,
2075                                     numOutstandingEntries,
2076                                     &qEntryIndx, qStatus->outstandingEntries);
2077             /* process non-outstanding entries */
2078             EDMA_update_queue_entries(qEntry0Addr, qEntryAddrJump,
2079                                     EDMA_NUM_QUEUE_ENTRIES - numOutstandingEntries,
2080                                     &qEntryIndx, qStatus->dequeuedEntries);
2081         }
2083         /* CCSTAT processing */
2084         ccStatRegAddr = ccBaseAddr + EDMA_TPCC_CCSTAT;
2086         status->numOutstandingCompletionRequests =
2087             HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_COMPACTV);
2089         status->isAnyDmaChannelActive =
2090             HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_EVTACTV);
2092         status->isAnyQdmaChannelActive =
2093             HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_QEVTACTV);
2095         status->isWriteStatusActive =
2096             HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_WSTATACTV);
2098         status->isAnyTransferActive =
2099             HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_TRACTV);
2101         status->isAnythingActive =
2102             HW_RD_FIELD32(ccStatRegAddr, EDMA_TPCC_CCSTAT_ACTV);
2103     }
2105     return(errorCode);
2108 static EDMA_Object_t* EDMA_getFreeEdmaObj(void)
2110     uint32_t i;
2111     EDMA_Object_t *edmaObj = NULL;
2112     for(i=0; i<EDMA_NUM_CC; i++)
2113     {
2114         if (EDMA_object[i].isUsed == FALSE)
2115         {
2116             edmaObj = &EDMA_object[i];
2117         }
2118     }
2119     return edmaObj;
2122 EDMA_Handle EDMA_open(uint8_t instanceId, int32_t *errorCode,
2123     EDMA_instanceInfo_t *instanceInfo)
2125     EDMA_Handle handle = NULL;
2126     EDMA_Config_t *edmaConfig = NULL;
2127     EDMA_Object_t *edmaObj = NULL;
2128     const EDMA_hwAttrs_t *hwAttrs;
2129     OsalRegisterIntrParams_t interruptRegParams;
2130     uint8_t tc;
2131     bool isUnifiedErrorInterrupts;
2132     uint32_t key;
2133     int32_t retVal = EDMA_NO_ERROR;
2135 #ifdef EDMA_PARAM_CHECK
2136     /* error checking */
2137     if (errorCode == NULL)
2138     {
2139         handle = NULL;
2140         retVal = EDMA_E_INVALID__CONFIG_POINTER_NULL;
2141     }
2142     if ((retVal == EDMA_NO_ERROR) && (instanceId > EDMA_DRV_INST_MAX))
2143     {
2144         retVal = EDMA_E_INVALID__INSTANCE_ID;
2145         handle = NULL;
2146     }
2147     if ((retVal == EDMA_NO_ERROR) && (instanceInfo == NULL))
2148     {
2149         retVal = EDMA_E_INVALID__INSTANCEINFO_POINTER_NULL;
2150         handle = NULL;
2151     }
2152 #endif
2154     if ((retVal == EDMA_NO_ERROR) &&
2155         ((EDMA_config[instanceId].hwAttrs != NULL) ||
2156          (EDMA_config[instanceId].object != NULL)))
2157     {
2158         /* Instance is already opened. */
2159         retVal = EDMA_E_UNEXPECTED__EDMA_INSTANCE_REOPEN;
2160     }
2161     if (retVal == EDMA_NO_ERROR)
2162     {
2163         hwAttrs = EDMA_getHwAttrs(instanceId);
2164         if (hwAttrs == NULL)
2165         {
2166             retVal = EDMA_E_INVALID__INSTANCE_ID;
2167             handle = NULL;
2168         }
2169     }
2171     if (retVal == EDMA_NO_ERROR)
2172     {
2173         key = HwiP_disable();
2174         edmaObj = EDMA_getFreeEdmaObj();
2175         if (edmaObj == NULL)
2176         {
2177             retVal = EDMA_E_INVALID__INSTANCE_ID;
2178             handle = NULL;
2179         }
2180         else
2181         {
2182             edmaObj->isUsed = true;
2183         }
2184         HwiP_restore(key);
2185     }
2187     if (retVal == EDMA_NO_ERROR)
2188     {
2189         EDMA_config[instanceId].hwAttrs = hwAttrs;
2190         EDMA_config[instanceId].object  = edmaObj;
2191         /* Get handle for this driver instance */
2192         handle = (EDMA_Handle)&(EDMA_config[instanceId]);
2194         edmaConfig = (EDMA_Config_t *) handle;
2195         edmaObj = edmaConfig->object;
2197     #ifdef EDMA_DBG
2198         edmaDbg.edmaObj = edmaObj;
2199     #endif
2201         hwAttrs =  edmaConfig->hwAttrs;
2202         instanceInfo->numEventQueues = hwAttrs->numEventQueues;
2203         instanceInfo->numParamSets = hwAttrs->numParamSets;
2204         instanceInfo->isChannelMapExist = hwAttrs->isChannelMapExist;
2205         instanceInfo->isTransferCompletionInterruptConnected =
2206             (hwAttrs->transferCompletionInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2207         instanceInfo->isErrorInterruptConnected = (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2208         for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2209         {
2210             instanceInfo->isTransferControllerErrorInterruptConnected[tc] =
2211                 (hwAttrs->transferControllerErrorInterruptNum[tc] != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2212         }
2214         /* register transfer complete interrupt handler */
2215         if (hwAttrs->transferCompletionInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID)
2216         {
2217     #if defined (SOC_TPR12) || defined (SOC_AWR294X)
2218             uint32_t mask = ~0U;
2220             /* Clear all status */
2221             HW_WR_REG32(hwAttrs->CCcompletionInterruptsAggregatorStatusRegAddress, ~0U);
2223             /* Mask all interrupts except global interrupt in the aggregator */
2224             mask &= (~(1U << EDMA_TPCC_INTAGG_TPCC_INTG__POS));
2226             HW_WR_REG32(hwAttrs->CCcompletionInterruptsAggregatorMaskRegAddress, mask);
2227     #endif
2229             /* Initialize with defaults */
2230             Osal_RegisterInterrupt_initParams(&interruptRegParams);
2231             /* Populate the interrupt parameters */
2232             interruptRegParams.corepacConfig.arg=(uintptr_t)handle;
2233             interruptRegParams.corepacConfig.name=(char *)("EDMA_transferComplete_isr");
2234             interruptRegParams.corepacConfig.isrRoutine=EDMA_transferComplete_isr;
2235         #if defined(_TMS320C6X)
2236             interruptRegParams.corepacConfig.corepacEventNum=(int32_t)hwAttrs->transferCompletionInterruptNum; /* Event going in to CPU */
2237             interruptRegParams.corepacConfig.intVecNum      = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
2238         #else
2239             interruptRegParams.corepacConfig.priority = 0x1U;
2240             interruptRegParams.corepacConfig.intVecNum=(int32_t)hwAttrs->transferCompletionInterruptNum; /* Host Interrupt vector */
2241             interruptRegParams.corepacConfig.corepacEventNum = (int32_t)hwAttrs->transferCompletionInterruptNum;
2242         #endif
2243             /* Register interrupts */
2244             Osal_RegisterInterrupt(&interruptRegParams, &edmaObj->hwiTransferCompleteHandle);
2246             if (edmaObj->hwiTransferCompleteHandle == NULL)
2247             {
2248                 retVal = EDMA_E_OSAL__HWIP_CREATE_TRANSFER_COMPLETION_ISR_RETURNED_NULL;
2249             }
2250             else
2251             {
2252                 Osal_EnableInterrupt(interruptRegParams.corepacConfig.corepacEventNum, interruptRegParams.corepacConfig.intVecNum);
2253             }
2254         }
2255     }
2257     if (retVal == EDMA_NO_ERROR)
2258     {
2259         isUnifiedErrorInterrupts = (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID) &&
2260                                 (hwAttrs->errorInterruptNum == hwAttrs->transferControllerErrorInterruptNum[0]);
2262         if (isUnifiedErrorInterrupts == true)
2263         {
2264             for(tc = 1; tc < hwAttrs->numEventQueues; tc++)
2265             {
2266                 if (hwAttrs->errorInterruptNum != hwAttrs->transferControllerErrorInterruptNum[tc])
2267                 {
2268                     retVal = EDMA_E_INVALID__PARTIAL_UNIFICATION_OF_ERROR_INTERRUPTS;
2269                 }
2270             }
2271         }
2272     }
2274     if (retVal == EDMA_NO_ERROR)
2275     {
2276         /* register error interrupt handler */
2277         if (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID)
2278         {
2279             /* Initialize with defaults */
2280             Osal_RegisterInterrupt_initParams(&interruptRegParams);
2281             /* Populate the interrupt parameters */
2282             interruptRegParams.corepacConfig.arg=(uintptr_t)handle;
2283         #if defined(_TMS320C6X)
2284             interruptRegParams.corepacConfig.corepacEventNum=(int32_t)hwAttrs->errorInterruptNum; /* Event going in to CPU */
2285             interruptRegParams.corepacConfig.intVecNum      = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
2286         #else
2287             interruptRegParams.corepacConfig.priority = 0x1U;
2288             interruptRegParams.corepacConfig.intVecNum=(int32_t)hwAttrs->errorInterruptNum; /* Host Interrupt vector */
2289             interruptRegParams.corepacConfig.corepacEventNum = (int32_t)hwAttrs->errorInterruptNum;
2290         #endif
2293     #if defined (SOC_TPR12) || defined (SOC_AWR294X) //TODO_TPR12 Currently using #ifdef due to *ERR__POS defines, should they be in platform file or overkill?
2294             if (isUnifiedErrorInterrupts == true)
2295             {
2296                 uint32_t mask = ~0U;
2298                 /* Clear all status */
2299                 HW_WR_REG32(hwAttrs->CCerrorInterruptsAggregatorStatusRegAddress, ~0U);
2301                 /* Mask all interrupts except errors in the aggregator */
2302                 mask &= (~(1U << EDMA_TPCC_ERRAGG_TPCC_EERINT__POS));
2304                 for(tc = 0; tc < hwAttrs->numEventQueues; tc++)
2305                 {
2306                     mask &= (~(1U << (EDMA_TPCC_ERRAGG_TPTC_MIN_ERR__POS + tc)));
2307                 }
2309                 HW_WR_REG32(hwAttrs->CCerrorInterruptsAggregatorMaskRegAddress, mask);
2311                 interruptRegParams.corepacConfig.name=(char *)("EDMA_aggregated_error_transferController_error_isr");
2312                 interruptRegParams.corepacConfig.isrRoutine=EDMA_aggregated_error_transferController_error_isr;
2314             }
2315             else
2316     #endif
2317             {
2318                 interruptRegParams.corepacConfig.name=(char *)("EDMA_error_isr");
2319                 interruptRegParams.corepacConfig.isrRoutine=EDMA_error_isr;
2320             }
2321             /* Register interrupts */
2322             Osal_RegisterInterrupt(&interruptRegParams, &edmaObj->hwiErrorHandle);
2324             if (edmaObj->hwiErrorHandle == NULL)
2325             {
2326                 retVal = EDMA_E_OSAL__HWIP_CREATE_ERROR_ISR_RETURNED_NULL;
2327             }
2328             else
2329             {
2330                 Osal_EnableInterrupt(interruptRegParams.corepacConfig.corepacEventNum, interruptRegParams.corepacConfig.intVecNum);
2331             }
2332         }
2333     }
2335     if (retVal == EDMA_NO_ERROR)
2336     {
2337         /* register transfer controller error handler */
2338         if (isUnifiedErrorInterrupts == false)
2339         {
2340             /* Initialize with defaults */
2341             Osal_RegisterInterrupt_initParams(&interruptRegParams);
2342             /* Populate the interrupt parameters */
2343             interruptRegParams.corepacConfig.arg=(uintptr_t)handle;
2344             interruptRegParams.corepacConfig.name=(char *)("EDMA_transferController_error_isr");
2345             interruptRegParams.corepacConfig.isrRoutine=EDMA_transferController_error_isr;
2347             for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2348             {
2349                 if (hwAttrs->transferControllerErrorInterruptNum[tc] != EDMA_INTERRUPT_NOT_CONNECTED_ID)
2350                 {
2351                     edmaObj->transferControllerErrorIsrArgInfo[tc].handle = handle;
2352                     edmaObj->transferControllerErrorIsrArgInfo[tc].transferControllerId = tc;
2353                     interruptRegParams.corepacConfig.arg=(uintptr_t)&edmaObj->transferControllerErrorIsrArgInfo[tc];;
2354                 #if defined(_TMS320C6X)
2355                     interruptRegParams.corepacConfig.corepacEventNum=(int32_t)hwAttrs->transferControllerErrorInterruptNum[tc]; /* Event going in to CPU */
2356                     interruptRegParams.corepacConfig.intVecNum      = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
2357                 #else
2358                     interruptRegParams.corepacConfig.priority = 0x1U;
2359                     interruptRegParams.corepacConfig.intVecNum=(int32_t)hwAttrs->transferControllerErrorInterruptNum[tc]; /* Host Interrupt vector */
2360                     interruptRegParams.corepacConfig.corepacEventNum = (int32_t)hwAttrs->transferControllerErrorInterruptNum[tc];
2361                 #endif
2362                     /* Register interrupts */
2363                     Osal_RegisterInterrupt(&interruptRegParams, &edmaObj->hwiTransferControllerErrorHandle[tc]);
2365                     if (edmaObj->hwiTransferControllerErrorHandle[tc] == NULL)
2366                     {
2367                         retVal = EDMA_E_OSAL__HWIP_CREATE_TRANSFER_CONTROLLER_ERROR_ISRS_RETURNED_NULL;
2368                         break;
2369                     }
2370                     else
2371                     {
2372                         Osal_EnableInterrupt(interruptRegParams.corepacConfig.corepacEventNum, interruptRegParams.corepacConfig.intVecNum);
2373                     }
2374                 }
2375             }
2376         }
2377     }
2379     if (retVal != EDMA_NO_ERROR)
2380     {
2381         /* Some error occured, If the interrupts are registered then unregister it. */
2382         if (handle != NULL)
2383         {
2384             EDMA_unregisterInterrupts(handle);
2385             handle = NULL;
2386         }
2387         if (edmaObj != NULL)
2388         {
2389             key = HwiP_disable();
2390             edmaObj->isUsed = false;
2391             HwiP_restore(key);
2392             EDMA_config[instanceId].hwAttrs = NULL;
2393             EDMA_config[instanceId].object = NULL;
2394         }
2395     }
2397     if (errorCode != NULL)
2398     {
2399         *errorCode = retVal;
2400     }
2402     return(handle);
2405 int32_t EDMA_configErrorMonitoring(EDMA_Handle handle, EDMA_errorConfig_t const *config)
2407     EDMA_Config_t *edmaConfig;
2408     EDMA_Object_t *edmaObj;
2409     EDMA_hwAttrs_t const *hwAttrs;
2410     uint32_t ccBaseAddr;
2411     uint8_t threshold;
2412     uint8_t queueId, tc;
2413     int32_t errorCode = EDMA_NO_ERROR;
2415     edmaConfig = (EDMA_Config_t *) handle;
2416     edmaObj = edmaConfig->object;
2417     hwAttrs = edmaConfig->hwAttrs;
2418     ccBaseAddr = hwAttrs->CCbaseAddress;
2420 #ifdef EDMA_PARAM_CHECK
2421     if (handle == NULL)
2422     {
2423         errorCode = EDMA_E_INVALID__HANDLE_NULL;
2424     }
2426     if ((errorCode == EDMA_NO_ERROR) && (config == NULL))
2427     {
2428         errorCode = EDMA_E_INVALID__CONFIG_POINTER_NULL;
2429     }
2430 #endif
2432     /* event queue threshold configuration */
2433     if ((errorCode == EDMA_NO_ERROR) && (config->isEventQueueThresholdingEnabled == true))
2434     {
2435 #ifdef EDMA_PARAM_CHECK
2436         if (config->eventQueueThreshold > EDMA_EVENT_QUEUE_THRESHOLD_MAX)
2437         {
2438             errorCode = EDMA_E_INVALID__EVENT_QUEUE_THRESHOLD;
2439         }
2440         else
2441         {
2442             threshold = config->eventQueueThreshold;
2443         }
2444 #endif
2445     }
2446     else
2447     {
2448         threshold = EDMA_EVENT_QUEUE_THRESHOLDING_DISABLED;
2449     }
2451     if (errorCode == EDMA_NO_ERROR)
2452     {
2453         if (config->isConfigAllEventQueues == true)
2454         {
2455             for (queueId = 0; queueId < hwAttrs->numEventQueues; queueId++)
2456             {
2457                 EDMA_configQueueThreshold(ccBaseAddr, queueId, threshold);
2458             }
2459         }
2460         else
2461         {
2462     #ifdef EDMA_PARAM_CHECK
2463             if (config->eventQueueId >= hwAttrs->numEventQueues)
2464             {
2465                 errorCode = EDMA_E_INVALID__EVENT_QUEUE_ID;
2466             }
2467     #endif
2468             if (errorCode == EDMA_NO_ERROR)
2469             {
2470                 EDMA_configQueueThreshold(ccBaseAddr, config->eventQueueId, threshold);
2471             }
2472         }
2473     }
2475     if (errorCode == EDMA_NO_ERROR)
2476     {
2477         /* transfer controller error configuration */
2478         if (config->isConfigAllTransferControllers == true)
2479         {
2480             for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2481             {
2482                 EDMA_configTransferControllerError(hwAttrs->TCbaseAddress[tc],
2483                     config->isEnableAllTransferControllerErrors,
2484                     &config->transferControllerErrorConfig);
2485             }
2486         }
2487         else
2488         {
2489     #ifdef EDMA_PARAM_CHECK
2490             if (config->transferControllerId >= hwAttrs->numEventQueues)
2491             {
2492                 errorCode = EDMA_E_INVALID__TRANSFER_CONTROLLER_ID;
2493             }
2494     #endif
2495             if (errorCode == EDMA_NO_ERROR)
2496             {
2497                 EDMA_configTransferControllerError(hwAttrs->TCbaseAddress[config->transferControllerId],
2498                     config->isEnableAllTransferControllerErrors,
2499                     &config->transferControllerErrorConfig);
2500             }
2501         }
2502     }
2504     if (errorCode == EDMA_NO_ERROR)
2505     {
2506         /* if error interrupt is not hooked, declare error if call back is populated */
2507         if (hwAttrs->errorInterruptNum == EDMA_INTERRUPT_NOT_CONNECTED_ID)
2508         {
2509             if (config->callbackFxn != NULL)
2510             {
2511                 errorCode = EDMA_E_INVALID__ERROR_CALL_BACK_FN_NON_NULL;
2512             }
2513         }
2514         edmaObj->errorCallbackFxn = config->callbackFxn;
2515     }
2517     if (errorCode == EDMA_NO_ERROR)
2518     {
2519         /* if any of the tc error interrupts are not hooked, declare error if call back is populated */
2520         for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2521         {
2522             if (hwAttrs->transferControllerErrorInterruptNum[tc] == EDMA_INTERRUPT_NOT_CONNECTED_ID)
2523             {
2524                 if (config->transferControllerCallbackFxn)
2525                 {
2526                     errorCode = EDMA_E_INVALID__TC_ERROR_CALL_BACK_FN_NON_NULL;
2527                 }
2528             }
2529         }
2531         edmaObj->transferControllerErrorCallbackFxn = config->transferControllerCallbackFxn;
2532     }
2534     return(errorCode);
2537 int32_t EDMA_configPerformance(EDMA_Handle handle,
2538     EDMA_performanceConfig_t const *config)
2540     EDMA_Config_t *edmaConfig;
2541     EDMA_hwAttrs_t const *hwAttrs;
2542     uint32_t tcBaseAddr;
2543     uint8_t tc;
2544     uint32_t ccBaseAddr;
2545     int32_t errorCode = EDMA_NO_ERROR;
2547 #ifdef EDMA_PARAM_CHECK
2548     if (handle == NULL)
2549     {
2550         errorCode = EDMA_E_INVALID__HANDLE_NULL;
2551     }
2553     if ((errorCode == EDMA_NO_ERROR) && (config == NULL))
2554     {
2555         errorCode = EDMA_E_INVALID__CONFIG_POINTER_NULL;
2556     }
2557 #endif
2559     if (errorCode == EDMA_NO_ERROR)
2560     {
2561         edmaConfig = (EDMA_Config_t *) handle;
2562         hwAttrs =  edmaConfig->hwAttrs;
2563         ccBaseAddr = hwAttrs->CCbaseAddress;
2565     #ifdef EDMA_PARAM_CHECK
2566         if (config->transferControllerReadRate > EDMA_READ_RATE_RANGE_CHECK_MAX)
2567         {
2568             errorCode = EDMA_E_INVALID__TRANSFER_CONTROLLER_READ_RATE;
2569         }
2571         if (config->queuePriority > EDMA_QUEUE_PRIORITIY_RANGE_CHECK_MAX)
2572         {
2573             errorCode = EDMA_E_INVALID__QUEUE_PRIORITY;
2574         }
2575     #endif
2576     }
2578     if (errorCode == EDMA_NO_ERROR)
2579     {
2580         if (config->isConfigAllTransferControllers == true)
2581         {
2582             for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2583             {
2584                 tcBaseAddr = hwAttrs->TCbaseAddress[tc];
2585                 HW_WR_FIELD32(tcBaseAddr + EDMA_TC_RDRATE, EDMA_TC_RDRATE_RDRATE,
2586                             config->transferControllerReadRate);
2588                 EDMA_configQueuePriority(ccBaseAddr, tc, config->queuePriority);
2589             }
2590         }
2591         else
2592         {
2593     #ifdef EDMA_PARAM_CHECK
2594             if (config->transferControllerId >= hwAttrs->numEventQueues)
2595             {
2596                 errorCode = EDMA_E_INVALID__TRANSFER_CONTROLLER_ID;
2597             }
2598     #endif
2599             if (errorCode == EDMA_NO_ERROR)
2600             {
2601                 tcBaseAddr = hwAttrs->TCbaseAddress[config->transferControllerId];
2602                 HW_WR_FIELD32(tcBaseAddr + EDMA_TC_RDRATE, EDMA_TC_RDRATE_RDRATE,
2603                             config->transferControllerReadRate);
2605                 EDMA_configQueuePriority(ccBaseAddr, config->transferControllerId,
2606                                         config->queuePriority);
2607             }
2608         }
2609     }
2611     return(errorCode);
2615 EDMA_Handle EDMA_getHandle(uint8_t instanceId, EDMA_instanceInfo_t *instanceInfo)
2617     EDMA_Handle handle = NULL;
2618     EDMA_Config_t *edmaConfig;
2619     EDMA_Object_t *edmaObj;
2620     EDMA_hwAttrs_t const *hwAttrs;
2621     int32_t status = EDMA_NO_ERROR;
2622     uint8_t tc;
2624 #ifdef EDMA_PARAM_CHECK
2625     if (instanceInfo == NULL)
2626     {
2627         status = EDMA_E_INVALID__INSTANCEINFO_POINTER_NULL;
2628         handle = NULL;
2629     }
2630 #endif
2632     if (EDMA_NO_ERROR == status)
2633     {
2634         /* Get handle for this driver instance */
2635         handle = (EDMA_Handle)&(EDMA_config[instanceId]);
2636         edmaConfig = (EDMA_Config_t *) handle;
2637         edmaObj = edmaConfig->object;
2639         if (edmaObj == NULL) {
2640             handle = NULL;
2641         }
2642     }
2644     if (handle != NULL)
2645     {
2646         hwAttrs =  edmaConfig->hwAttrs;
2647         instanceInfo->numEventQueues = hwAttrs->numEventQueues;
2648         instanceInfo->numParamSets = hwAttrs->numParamSets;
2649         instanceInfo->isChannelMapExist = hwAttrs->isChannelMapExist;
2650         instanceInfo->isTransferCompletionInterruptConnected =
2651             (hwAttrs->transferCompletionInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2652         instanceInfo->isErrorInterruptConnected = (hwAttrs->errorInterruptNum != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2653         for (tc = 0; tc < hwAttrs->numEventQueues; tc++)
2654         {
2655             instanceInfo->isTransferControllerErrorInterruptConnected[tc] =
2656                 (hwAttrs->transferControllerErrorInterruptNum[tc] != EDMA_INTERRUPT_NOT_CONNECTED_ID);
2657         }
2658     }
2659     return handle;