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_
137 {
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_
150 {
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)
268 {
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);
291 }
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)
311 {
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);
363 }
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 )
388 {
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);
452 }
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)
479 {
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, ¶mSet);
517 }
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)
537 {
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 }
644 }
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)
671 {
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 }
691 }
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)
707 {
708 return((EDMA3GetErrIntrStatus(ccBaseAddr) != 0U) ||
709 (EDMA3ErrIntrHighStatusGet(ccBaseAddr) != 0U) ||
710 (EDMA3QdmaGetErrIntrStatus(ccBaseAddr) != 0U) ||
711 (EDMA3GetCCErrStatus(ccBaseAddr) != 0U));
712 }
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)
731 {
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);
775 }
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)
795 {
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 }
834 }
836 int32_t EDMA_getErrorStatus(EDMA_Handle handle, bool *isAnyError, EDMA_errorInfo_t *errorInfo)
837 {
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);
864 }
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)
881 {
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 }
914 }
916 static bool EDMA_isTransferControllerError(uint32_t tcBaseAddr)
917 {
918 uint32_t errStatRegAddr = tcBaseAddr + EDMA_TC_ERRSTAT;
920 return(HW_RD_REG32(errStatRegAddr) != 0);
921 }
923 static void EDMA_getTransferControllerErrorStatusInfo(uint32_t tcBaseAddr,
924 EDMA_transferControllerErrorInfo_t *errorInfo)
925 {
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 }
958 }
960 static void EDMA_clearTransferControllerErrors(uint32_t tcBaseAddr,
961 EDMA_transferControllerErrorInfo_t *errorInfo)
962 {
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);
969 }
971 int32_t EDMA_getTransferControllerErrorStatus(EDMA_Handle handle, uint8_t transferControllerId,
972 bool *isAnyError, EDMA_transferControllerErrorInfo_t *errorInfo)
973 {
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);
1002 }
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)
1021 {
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 }
1060 }
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)
1078 {
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 }
1124 }
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)
1144 {
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 }
1160 }
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)
1179 {
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);
1185 }
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)
1204 {
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);
1226 }
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)
1245 {
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);
1358 }
1360 int32_t EDMA_configChannel(EDMA_Handle handle, EDMA_channelConfig_t const *config,
1361 bool isEnableChannel)
1362 {
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);
1438 }
1440 int32_t EDMA_enableChannel(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1441 {
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);
1497 }
1499 int32_t EDMA_disableChannel(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1500 {
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);
1546 }
1548 int32_t EDMA_configParamSet(EDMA_Handle handle, uint16_t paramId,
1549 EDMA_paramConfig_t const *config)
1550 {
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);
1582 }
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 )
1589 {
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 }
1614 }
1616 int32_t EDMA_linkParamSets(EDMA_Handle handle, uint16_t fromParamId, uint16_t toParamId)
1617 {
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);
1657 }
1659 int32_t EDMA_chainChannels(EDMA_Handle handle, uint16_t fromParamId, uint8_t toChannelId)
1660 {
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);
1698 }
1700 int32_t EDMA_startTransfer(EDMA_Handle handle, uint8_t channelId, uint8_t channelType)
1701 {
1702 return(EDMA_startTransfer_assist(handle, channelId, channelType, false));
1703 }
1705 int32_t EDMA_startDmaTransfer(EDMA_Handle handle, uint8_t channelId)
1706 {
1707 return(EDMA_startTransfer_assist(handle, channelId,
1708 (uint8_t)EDMA3_CHANNEL_TYPE_DMA, false));
1709 }
1711 int32_t EDMA_startQdmaTransfer(EDMA_Handle handle, uint8_t channelId)
1712 {
1713 return(EDMA_startTransfer_assist(handle, channelId,
1714 (uint8_t)EDMA3_CHANNEL_TYPE_QDMA, false));
1715 }
1717 int32_t EDMA_startFinalQdmaTransfer(EDMA_Handle handle, uint8_t channelId)
1718 {
1719 return(EDMA_startTransfer_assist(handle, channelId,
1720 (uint8_t)EDMA3_CHANNEL_TYPE_QDMA, true));
1721 }
1723 int32_t EDMA_isTransferComplete(EDMA_Handle handle, uint8_t transferCompletionCode,
1724 bool *isTransferComplete)
1725 {
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);
1784 }
1786 int32_t EDMA_setDestinationAddress(EDMA_Handle handle,
1787 uint16_t paramId,
1788 uint32_t destinationAddress)
1789 {
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);
1819 }
1821 int32_t EDMA_setSourceAddress(EDMA_Handle handle,
1822 uint16_t paramId,
1823 uint32_t sourceAddress)
1824 {
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);
1855 }
1857 static void EDMA_unregisterInterrupts(EDMA_Handle handle)
1858 {
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 }
1938 }
1940 int32_t EDMA_close(EDMA_Handle handle)
1941 {
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);
1964 }
1966 uint8_t EDMA_getNumInstances(void)
1967 {
1968 return((uint8_t)EDMA_NUM_CC);
1969 }
1971 int32_t EDMA_init(uint8_t instanceId, const EDMA3CCInitParams *initParam)
1972 {
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);
2023 }
2025 int32_t EDMA_getStatusInfo(EDMA_Handle handle, EDMA_statusInfo_t *status)
2026 {
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);
2106 }
2108 static EDMA_Object_t* EDMA_getFreeEdmaObj(void)
2109 {
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;
2120 }
2122 EDMA_Handle EDMA_open(uint8_t instanceId, int32_t *errorCode,
2123 EDMA_instanceInfo_t *instanceInfo)
2124 {
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);
2403 }
2405 int32_t EDMA_configErrorMonitoring(EDMA_Handle handle, EDMA_errorConfig_t const *config)
2406 {
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);
2535 }
2537 int32_t EDMA_configPerformance(EDMA_Handle handle,
2538 EDMA_performanceConfig_t const *config)
2539 {
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);
2612 }
2615 EDMA_Handle EDMA_getHandle(uint8_t instanceId, EDMA_instanceInfo_t *instanceInfo)
2616 {
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;
2660 }