1 /*
2 * edma3resmgr.c
3 *
4 * EDMA3 Controller Resource Manager Interface Implementation
5 *
6 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the
19 * distribution.
20 *
21 * Neither the name of Texas Instruments Incorporated nor the names of
22 * its contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 */
39 /* Resource Manager Internal Header Files */
40 #include <ti/sdo/edma3/rm/src/edma3resmgr.h>
42 /* Instrumentation Header File */
43 #ifdef EDMA3_INSTRUMENTATION_ENABLED
44 #include <ti/sdo/edma3/rm/src/edma3_log.h>
45 #endif
47 /* For assert() */
48 /**
49 * Define NDEBUG to ignore assert().
50 * NDEBUG should be defined before including assert.h header file.
51 */
52 #include <assert.h>
55 /* Global Defines, need to re-compile if values are changed */
56 /*---------------------------------------------------------------------------*/
57 /**
58 * \brief EDMA3 Resource Manager behaviour of clearing CC ERROR interrupts.
59 * This macro controls the driver to enable/disable clearing of error
60 * status of all channels.
61 *
62 * On disabling this (with value 0x0), the channels owned by the region
63 * is cleared and its expected that some other entity is responsible for
64 * clearing the error status for channels not owned.
65 *
66 * Its recomended that this flag is a positive value, to ensure that
67 * error flags are cleared for all the channels.
68 */
69 #define EDMA3_RM_RES_CLEAR_ERROR_STATUS_FOR_ALL_CHANNELS (TRUE)
71 /**
72 * \brief EDMA3 Resource Manager retry count to check the pending interrupts inside ISR.
73 * This macro controls the driver to check the pending interrupt for
74 * 'n' number of times.
75 * Minumum value is 1.
76 */
77 #define EDMA3_RM_COMPL_HANDLER_RETRY_COUNT (10u)
79 /**
80 * \brief EDMA3 Resource Manager retry count to check the pending CC Error Interrupt inside ISR
81 * This macro controls the driver to check the pending CC Error
82 * interrupt for 'n' number of times.
83 * Minumum value is 1.
84 */
85 #define EDMA3_RM_CCERR_HANDLER_RETRY_COUNT (10u)
89 /* Externel Variables */
90 /*---------------------------------------------------------------------------*/
91 /**
92 * Maximum Resource Manager Instances supported by the EDMA3 Package.
93 */
94 extern const unsigned int EDMA3_MAX_RM_INSTANCES;
97 /**
98 * \brief Static Configuration structure for EDMA3
99 * controller, to provide Global SoC specific Information.
100 *
101 * This configuration info can also be provided by the user at run-time,
102 * while calling EDMA3_RM_create (). If not provided at run-time,
103 * this info will be taken from the config file "edma3_<PLATFORM_NAME>_cfg.c",
104 * for the specified platform.
105 */
106 extern EDMA3_RM_GblConfigParams edma3GblCfgParams [EDMA3_MAX_EDMA3_INSTANCES];
108 /**
109 * \brief Default Static Region Specific Configuration structure for
110 * EDMA3 controller, to provide region specific Information.
111 */
112 extern EDMA3_RM_InstanceInitConfig defInstInitConfig [EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_REGIONS];
115 /**
116 * \brief Region Specific Configuration structure for
117 * EDMA3 controller, to provide region specific Information.
118 *
119 * This configuration info can also be provided by the user at run-time,
120 * while calling EDMA3_RM_open (). If not provided at run-time,
121 * this info will be taken from the config file "edma3_<PLATFORM_NAME>_cfg.c",
122 * for the specified platform.
123 */
124 extern EDMA3_RM_InstanceInitConfig *userInitConfig;
125 extern EDMA3_RM_InstanceInitConfig *ptrInitCfgArray;
128 /**
129 * Handles of EDMA3 Resource Manager Instances.
130 *
131 * Used to maintain information of the EDMA3 RM Instances
132 * for each HW controller.
133 * There could be a maximum of EDMA3_MAX_RM_INSTANCES instances per
134 * EDMA3 HW.
135 */
136 extern EDMA3_RM_Instance *resMgrInstance;
137 extern EDMA3_RM_Instance *ptrRMIArray;
139 /** Max of DMA Channels */
140 unsigned int edma3_dma_ch_max_val[EDMA3_MAX_EDMA3_INSTANCES];
141 /** Min of Link Channels */
142 unsigned int edma3_link_ch_min_val[EDMA3_MAX_EDMA3_INSTANCES];
143 /** Max of Link Channels */
144 unsigned int edma3_link_ch_max_val[EDMA3_MAX_EDMA3_INSTANCES];
145 /** Min of QDMA Channels */
146 unsigned int edma3_qdma_ch_min_val[EDMA3_MAX_EDMA3_INSTANCES];
147 /** Max of QDMA Channels */
148 unsigned int edma3_qdma_ch_max_val[EDMA3_MAX_EDMA3_INSTANCES];
149 /** Max of Logical Channels */
150 unsigned int edma3_log_ch_max_val[EDMA3_MAX_EDMA3_INSTANCES];
152 /* Globals */
153 /*---------------------------------------------------------------------------*/
154 /**
155 * \brief EDMA3 Resource Manager Objects, tied to each EDMA3 HW Controller.
156 *
157 * Typically one RM object will cater to one EDMA3 HW controller
158 * and will have all the global config information.
159 */
160 EDMA3_RM_Obj resMgrObj[EDMA3_MAX_EDMA3_INSTANCES];
163 /**
164 * Global Array to store the mapping between DMA channels and Interrupt
165 * channels i.e. TCCs.
166 * DMA channel X can use any TCC Y. Transfer completion
167 * interrupt will occur on the TCC Y (IPR/IPRH Register, bit Y), but error
168 * interrupt will occur on DMA channel X (EMR/EMRH register, bit X). In that
169 * scenario, this DMA channel <-> TCC mapping will be used to point to
170 * the correct callback function.
171 */
172 static unsigned int edma3DmaChTccMapping [EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_DMA_CH];
175 /**
176 * Global Array to store the mapping between QDMA channels and Interrupt
177 * channels i.e. TCCs.
178 * QDMA channel X can use any TCC Y. Transfer completion
179 * interrupt will occur on the TCC Y (IPR/IPRH Register, bit Y), but error
180 * interrupt will occur on QDMA channel X (QEMR register, bit X). In that
181 * scenario, this QDMA channel <-> TCC mapping will be used to point to
182 * the correct callback function.
183 */
184 static unsigned int edma3QdmaChTccMapping [EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_QDMA_CH];
187 /**
188 * Global Array to maintain the Callback details registered
189 * against a particular TCC. Used to call the callback
190 * functions linked to the particular channel.
191 */
192 static EDMA3_RM_TccCallbackParams edma3IntrParams [EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_TCC];
195 /** edma3RegionId will be updated ONCE using the parameter regionId passed to
196 * the EDMA3_RM_open() function, for the Master RM instance (one who
197 * configures the Global Registers).
198 * This global variable will be used within the Interrupt handlers to know
199 * which shadow region registers to access. All other interrupts coming
200 * from other shadow regions will not be handled.
201 */
202 static EDMA3_RM_RegionId edma3RegionId = EDMA3_MAX_REGIONS;
204 /** masterExists[] will be updated when the Master RM Instance modifies the
205 * Global EDMA3 configuration registers. It is used to prevent any other
206 * Master RM Instance creation.
207 * masterExists[] is per EDMA3 hardware, hence it is created
208 * as an array.
209 */
210 static unsigned short masterExists [EDMA3_MAX_EDMA3_INSTANCES] = {FALSE,FALSE,FALSE};
212 /**
213 * Number of PaRAM Sets actually present on the SoC. This will be updated
214 * while creating the Resource Manager Object.
215 */
216 unsigned int edma3NumPaRAMSets = EDMA3_MAX_PARAM_SETS;
219 /**
220 * The list of Interrupt Channels which get allocated while requesting the
221 * TCC. It will be used while checking the IPR/IPRH bits in the RM ISR.
222 */
223 static unsigned int allocatedTCCs[EDMA3_MAX_EDMA3_INSTANCES][2u] =
224 {
225 {0x0u, 0x0u},
226 {0x0u, 0x0u},
227 {0x0u, 0x0u},
228 };
231 /**
232 * Arrays ownDmaChannels[], resvdDmaChannels and avlblDmaChannels will be ANDed
233 * and stored in this array. It will be referenced in
234 * EDMA3_RM_allocContiguousResource () to look for contiguous resources.
235 */
236 static unsigned int contiguousDmaRes[EDMA3_MAX_DMA_CHAN_DWRDS] = {0x0u, 0x0u};
238 /**
239 * Arrays ownDmaChannels[], resvdDmaChannels and avlblDmaChannels will be ANDed
240 * and stored in this array. It will be referenced in
241 * EDMA3_RM_allocContiguousResource () to look for contiguous resources.
242 */
243 static unsigned int contiguousQdmaRes[EDMA3_MAX_QDMA_CHAN_DWRDS] = {0x0u};
245 /**
246 * Arrays ownDmaChannels[], resvdDmaChannels and avlblDmaChannels will be ANDed
247 * and stored in this array. It will be referenced in
248 * EDMA3_RM_allocContiguousResource () to look for contiguous resources.
249 */
250 static unsigned int contiguousTccRes[EDMA3_MAX_TCC_DWRDS] = {0x0u, 0x0u};
252 /**
253 * Arrays ownDmaChannels[], resvdDmaChannels and avlblDmaChannels will be ANDed
254 * and stored in this array. It will be referenced in
255 * EDMA3_RM_allocContiguousResource () to look for contiguous resources.
256 */
257 static unsigned int contiguousParamRes[EDMA3_MAX_PARAM_DWRDS];
260 /**
261 * \brief Resources bound to a Channel
262 *
263 * When a request for a channel is made, the resources PaRAM Set and TCC
264 * get bound to that channel. This information is needed internally by the
265 * resource manager, when a request is made to free the channel,
266 * to free up the channel-associated resources.
267 */
268 static EDMA3_RM_ChBoundResources edma3RmChBoundRes [EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_LOGICAL_CH];
272 /*---------------------------------------------------------------------------*/
274 /* Local functions prototypes */
275 /*---------------------------------------------------------------------------*/
276 /** EDMA3 Instance 0 Completion Handler Interrupt Service Routine */
277 void lisrEdma3ComplHandler0(unsigned int arg);
278 /** EDMA3 Instance 0 CC Error Interrupt Service Routine */
279 void lisrEdma3CCErrHandler0(unsigned int arg);
280 /**
281 * EDMA3 Instance 0 TC[0-7] Error Interrupt Service Routines
282 * for a maximum of 8 TCs (Transfer Controllers).
283 */
284 void lisrEdma3TC0ErrHandler0(unsigned int arg);
285 void lisrEdma3TC1ErrHandler0(unsigned int arg);
286 void lisrEdma3TC2ErrHandler0(unsigned int arg);
287 void lisrEdma3TC3ErrHandler0(unsigned int arg);
288 void lisrEdma3TC4ErrHandler0(unsigned int arg);
289 void lisrEdma3TC5ErrHandler0(unsigned int arg);
290 void lisrEdma3TC6ErrHandler0(unsigned int arg);
291 void lisrEdma3TC7ErrHandler0(unsigned int arg);
294 /** Interrupt Handler for the Transfer Completion interrupt */
295 static void edma3ComplHandler (const EDMA3_RM_Obj *rmObj);
296 /** Interrupt Handler for the Channel Controller Error interrupt */
297 static void edma3CCErrHandler (const EDMA3_RM_Obj *rmObj);
298 /** Interrupt Handler for the Transfer Controller Error interrupt */
299 static void edma3TCErrHandler (const EDMA3_RM_Obj *rmObj, unsigned int tcNum);
302 /** Local MemZero function */
303 void edma3MemZero(void *dst, unsigned int len);
304 /** Local MemCpy function */
305 void edma3MemCpy(void *dst, const void *src, unsigned int len);
306 /* Local MemCopy function to copy Param Set ONLY */
307 void edma3ParamCpy(void *dst, const void *src);
309 /** Initialization of the Global region registers of the EDMA3 Controller */
310 static void edma3GlobalRegionInit (unsigned int phyCtrllerInstId);
311 /** Initialization of the Shadow region registers of the EDMA3 Controller */
312 static void edma3ShadowRegionInit (const EDMA3_RM_Instance *pRMInstance);
316 /* Internal functions for contiguous resource allocation */
317 /**
318 * Finds a particular bit ('0' or '1') in the particular word from 'start'.
319 * If found, returns the position, else return -1.
320 */
321 static int findBitInWord (int source, unsigned int start, unsigned short bit);
323 /**
324 * Finds a particular bit ('0' or '1') in the specified resources' array
325 * from 'start' to 'end'. If found, returns the position, else return -1.
326 */
327 static int findBit (EDMA3_RM_ResType resType,
328 unsigned int start,
329 unsigned int end,
330 unsigned short bit);
332 /**
333 * If successful, this function returns EDMA3_RM_SOK and the position
334 * of first available resource in 'positionRes'. Else returns error.
335 */
336 static EDMA3_RM_Result allocAnyContigRes(EDMA3_RM_ResType resType,
337 unsigned int numResources,
338 unsigned int *positionRes);
340 /**
341 * Starting from 'firstResIdObj', this function makes the next 'numResources'
342 * Resources non-available for future. Also, it does some global resisters'
343 * setting also.
344 */
345 static EDMA3_RM_Result gblChngAllocContigRes(EDMA3_RM_Instance *rmInstance,
346 const EDMA3_RM_ResDesc *firstResIdObj,
347 unsigned int numResources);
349 /*---------------------------------------------------------------------------*/
351 /**\fn EDMA3_RM_Result EDMA3_RM_create (unsigned int phyCtrllerInstId,
352 * const EDMA3_RM_GblConfigParams *gblCfgParams,
353 * const void *miscParam)
354 * \brief Create EDMA3 Resource Manager Object
355 *
356 * This API is used to create the EDMA3 Resource Manager Object. It should be
357 * called only ONCE for each EDMA3 hardware instance.
358 *
359 * Init-time Configuration structure for EDMA3 hardware is provided to pass the
360 * SoC specific information. This configuration information could be provided
361 * by the user at init-time. In case user doesn't provide it, this information
362 * could be taken from the SoC specific configuration file
363 * edma3_<SOC_NAME>_cfg.c, in case it is available.
364 *
365 * This API clears the error specific registers (EMCR/EMCRh, QEMCR, CCERRCLR)
366 * and sets the TCs priorities and Event Queues' watermark levels, if the 'miscParam'
367 * argument is NULL. User can avoid these registers' programming (in some specific
368 * use cases) by SETTING the 'isSlave' field of 'EDMA3_RM_MiscParam' configuration
369 * structure and passing this structure as the third argument (miscParam).
370 *
371 * After successful completion of this API, Resource Manager Object's state
372 * changes to EDMA3_RM_CREATED from EDMA3_RM_DELETED.
373 *
374 * \param phyCtrllerInstId [IN] EDMA3 Controller Instance Id
375 * (Hardware instance id, starting from 0).
376 * \param gblCfgParams [IN] SoC specific configuration structure for the
377 * EDMA3 Hardware.
378 * \param miscParam [IN] Misc configuration options provided in the
379 * structure 'EDMA3_RM_MiscParam'.
380 * For default options, user can pass NULL
381 * in this argument.
382 *
383 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
384 */
385 EDMA3_RM_Result EDMA3_RM_create (unsigned int phyCtrllerInstId,
386 const EDMA3_RM_GblConfigParams *gblCfgParams,
387 const void *miscParam)
388 {
389 unsigned int count = 0u;
390 EDMA3_RM_Result result = EDMA3_RM_SOK;
391 /**
392 * Used to reset the Internal EDMA3 Resource Manager Data Structures for the first time.
393 */
394 static unsigned short rmInitDone = FALSE;
395 const EDMA3_RM_MiscParam *miscOpt = (const EDMA3_RM_MiscParam *)miscParam;
397 /**
398 * We are NOT checking 'gblCfgParams' for NULL.
399 * If user has passed NULL, default config info will be
400 * taken from config file.
401 * 'param' is also not being checked because it could be
402 * NULL also.
403 */
405 /* If parameter checking is enabled... */
406 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
407 if (phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES)
408 {
409 result = EDMA3_RM_E_INVALID_PARAM;
410 }
411 #endif
413 /* Check if the parameters are OK. */
414 if (EDMA3_RM_SOK == result)
415 {
416 /* Initialize the global variables for the first time */
417 if (FALSE == rmInitDone)
418 {
419 edma3MemZero((void *)&(resMgrObj[count]),
420 sizeof(resMgrObj));
421 edma3MemZero((void *)(&(edma3IntrParams[0u])),
422 sizeof(edma3IntrParams));
424 rmInitDone = TRUE;
425 }
427 /* Initialization has been done */
428 if (resMgrObj[phyCtrllerInstId].state != EDMA3_RM_DELETED)
429 {
430 result = EDMA3_RM_E_OBJ_NOT_DELETED;
431 }
432 else
433 {
434 /**
435 * Check whether user has passed the Global Config Info.
436 * If yes, copy it to the driver data structures. Else, use the
437 * info from the config file edma3Cfg.c
438 */
439 if (NULL == gblCfgParams)
440 {
441 /* Take info from the specific config file */
442 edma3MemCpy((void *)(&resMgrObj[phyCtrllerInstId].gblCfgParams),
443 (const void *)(&edma3GblCfgParams[phyCtrllerInstId]),
444 sizeof (EDMA3_RM_GblConfigParams));
445 }
446 else
447 {
448 /* User passed the info, save it in the RM object first */
449 edma3MemCpy((void *)(&resMgrObj[phyCtrllerInstId].gblCfgParams),
450 (const void *)(gblCfgParams),
451 sizeof (EDMA3_RM_GblConfigParams));
452 }
455 /**
456 * Check whether DMA channel to PaRAM Set mapping exists or not.
457 * If it does not exist, set the mapping array as 1-to-1 mapped.
458 */
459 if (FALSE == resMgrObj[phyCtrllerInstId].gblCfgParams.dmaChPaRAMMapExists)
460 {
461 for (count = 0u; count < resMgrObj[phyCtrllerInstId].gblCfgParams.numDmaChannels; count++)
462 {
463 resMgrObj[phyCtrllerInstId].gblCfgParams.dmaChannelPaRAMMap[count] = count;
464 }
465 }
468 /**
469 * Update the actual number of PaRAM sets and
470 * Initialize Boundary Values for Logical Channel Ranges.
471 */
472 edma3NumPaRAMSets = resMgrObj[phyCtrllerInstId].gblCfgParams.numPaRAMSets;
473 edma3_dma_ch_max_val[phyCtrllerInstId] = resMgrObj[phyCtrllerInstId].gblCfgParams.numDmaChannels - 1u;
474 edma3_link_ch_min_val[phyCtrllerInstId] = edma3_dma_ch_max_val[phyCtrllerInstId] + 1u;
475 edma3_link_ch_max_val[phyCtrllerInstId] = edma3_link_ch_min_val[phyCtrllerInstId] + resMgrObj[phyCtrllerInstId].gblCfgParams.numPaRAMSets - 1u;
476 edma3_qdma_ch_min_val[phyCtrllerInstId] = edma3_link_ch_max_val[phyCtrllerInstId] + 1u;
477 edma3_qdma_ch_max_val[phyCtrllerInstId] = edma3_qdma_ch_min_val[phyCtrllerInstId] + resMgrObj[phyCtrllerInstId].gblCfgParams.numQdmaChannels - 1u;
478 edma3_log_ch_max_val[phyCtrllerInstId] = edma3_qdma_ch_max_val[phyCtrllerInstId];
480 resMgrObj[phyCtrllerInstId].phyCtrllerInstId = phyCtrllerInstId;
481 resMgrObj[phyCtrllerInstId].state = EDMA3_RM_CREATED;
482 resMgrObj[phyCtrllerInstId].numOpens = 0u;
484 /* Make all the RM instances for this EDMA3 HW NULL */
485 for (count = 0u; count < EDMA3_MAX_RM_INSTANCES; count++)
486 {
487 edma3MemZero((void *)((EDMA3_RM_Instance *)(ptrRMIArray) + (phyCtrllerInstId*EDMA3_MAX_RM_INSTANCES) + count),
488 sizeof(EDMA3_RM_Instance));
490 /* Also make this data structure NULL */
491 edma3MemZero((void *)((EDMA3_RM_InstanceInitConfig *)(ptrInitCfgArray) + (phyCtrllerInstId*EDMA3_MAX_RM_INSTANCES) + count),
492 sizeof(EDMA3_RM_InstanceInitConfig));
493 }
495 /* Initialize the global edma3DmaChTccMapping array with EDMA3_MAX_TCC */
496 for ( count = 0u;
497 count < resMgrObj[phyCtrllerInstId].gblCfgParams.numDmaChannels;
498 count++
499 )
500 {
501 edma3DmaChTccMapping[phyCtrllerInstId][count] = EDMA3_MAX_TCC;
502 }
504 /* Initialize the global edma3QdmaChTccMapping array with EDMA3_MAX_TCC */
505 for ( count = 0u;
506 count < resMgrObj[phyCtrllerInstId].gblCfgParams.numQdmaChannels;
507 count++
508 )
509 {
510 edma3QdmaChTccMapping[phyCtrllerInstId][count] = EDMA3_MAX_TCC;
511 }
513 /* Reset edma3RmChBoundRes Array*/
514 for (count = 0u; count < EDMA3_MAX_LOGICAL_CH; count++)
515 {
516 edma3RmChBoundRes[phyCtrllerInstId][count].paRAMId = -1;
517 edma3RmChBoundRes[phyCtrllerInstId][count].tcc = EDMA3_MAX_TCC;
518 }
520 /* Make the contiguousParamRes array NULL */
521 edma3MemZero((void *)(&(contiguousParamRes[0u])),
522 sizeof(contiguousParamRes));
525 /**
526 * Check the misc configuration options structure.
527 * Check whether the global registers' initialization
528 * is required or not.
529 * It is required ONLY if RM is running on the Master Processor.
530 */
531 if (NULL != miscOpt)
532 {
533 if (miscOpt->isSlave == FALSE)
534 {
535 /* It is a master. */
536 edma3GlobalRegionInit(phyCtrllerInstId);
537 }
538 }
539 else
540 {
541 /* By default, global registers will be initialized. */
542 edma3GlobalRegionInit(phyCtrllerInstId);
543 }
544 }
545 }
547 return result;
548 }
552 /**\fn EDMA3_RM_Result EDMA3_RM_delete (unsigned int phyCtrllerInstId,
553 * const void *param)
554 * \brief Delete EDMA3 Resource Manager Object
555 *
556 * This API is used to delete the EDMA3 RM Object. It should be called
557 * once for each EDMA3 hardware instance, ONLY after closing all the
558 * previously opened EDMA3 RM Instances.
559 *
560 * After successful completion of this API, Resource Manager Object's state
561 * changes to EDMA3_RM_DELETED.
562 *
563 * \param phyCtrllerInstId [IN] EDMA3 Phy Controller Instance Id (Hardware
564 * instance id, starting from 0).
565 * \param param [IN] For possible future use.
566 *
567 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
568 */
569 EDMA3_RM_Result EDMA3_RM_delete (unsigned int phyCtrllerInstId,
570 const void *param)
571 {
572 EDMA3_RM_Result result = EDMA3_RM_SOK;
574 /* If parameter checking is enabled... */
575 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
576 if (phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES)
577 {
578 result = EDMA3_RM_E_INVALID_PARAM;
579 }
580 #endif
582 /* Check if the parameters are OK. */
583 if (EDMA3_RM_SOK == result)
584 {
585 /*to remove CCS remark: parameter "param" was never referenced */
586 (void)param;
588 /**
589 * If number of RM Instances is 0, then state should be
590 * EDMA3_RM_CLOSED OR EDMA3_RM_CREATED.
591 */
592 if ((NULL == resMgrObj[phyCtrllerInstId].numOpens)
593 && ((resMgrObj[phyCtrllerInstId].state != EDMA3_RM_CLOSED)
594 && (resMgrObj[phyCtrllerInstId].state != EDMA3_RM_CREATED)))
595 {
596 result = EDMA3_RM_E_OBJ_NOT_CLOSED;
597 }
598 else
599 {
600 /**
601 * If number of RM Instances is NOT 0, then this function
602 * SHOULD NOT be called by anybody.
603 */
604 if (NULL != resMgrObj[phyCtrllerInstId].numOpens)
605 {
606 result = EDMA3_RM_E_INVALID_STATE;
607 }
608 else
609 {
610 /** Change state to EDMA3_RM_DELETED */
611 resMgrObj[phyCtrllerInstId].state = EDMA3_RM_DELETED;
613 /* Reset the Allocated TCCs Array also. */
614 allocatedTCCs[phyCtrllerInstId][0u] = 0x0u;
615 allocatedTCCs[phyCtrllerInstId][1u] = 0x0u;
617 /* Also, reset the RM Object Global Config Info */
618 edma3MemZero((void *)&(resMgrObj[phyCtrllerInstId].gblCfgParams),
619 sizeof(EDMA3_RM_GblConfigParams));
620 }
621 }
622 }
624 return result;
625 }
628 /**\fn EDMA3_RM_Handle EDMA3_RM_open (unsigned int phyCtrllerInstId,
629 * const EDMA3_RM_Param *initParam,
630 * EDMA3_RM_Result *errorCode)
631 * \brief Open EDMA3 Resource Manager Instance
632 *
633 * This API is used to open an EDMA3 Resource Manager Instance. It could be
634 * called multiple times, for each possible EDMA3 shadow region. Maximum
635 * EDMA3_MAX_RM_INSTANCES instances are allowed for each EDMA3 hardware
636 * instance.
637 *
638 * Also, only ONE Master Resource Manager Instance is permitted. This master
639 * instance (and hence the region to which it belongs) will only receive the
640 * EDMA3 interrupts, if enabled.
641 *
642 * User could pass the instance specific configuration structure
643 * (initParam->rmInstInitConfig) as a part of the 'initParam' structure,
644 * during init-time. In case user doesn't provide it, this information could
645 * be taken from the SoC specific configuration file edma3_<SOC_NAME>_cfg.c,
646 * in case it is available.
647 *
648 * \param phyCtrllerInstId [IN] EDMA3 Controller Instance Id (Hardware
649 * instance id, starting from 0).
650 * \param initParam [IN] Used to Initialize the Resource Manager
651 * Instance (Master or Slave).
652 * \param errorCode [OUT] Error code while opening RM instance.
653 *
654 * \return Handle to the opened Resource Manager instance Or NULL in case of
655 * error.
656 *
657 * \note This function disables the global interrupts (by calling API
658 * edma3OsProtectEntry with protection level
659 * EDMA3_OS_PROTECT_INTERRUPT) while modifying the global RM data
660 * structures, to make it re-entrant.
661 */
662 EDMA3_RM_Handle EDMA3_RM_open (unsigned int phyCtrllerInstId,
663 const EDMA3_RM_Param *initParam,
664 EDMA3_RM_Result *errorCode)
665 {
666 unsigned int intState = 0u;
667 unsigned int resMgrIdx = 0u;
668 EDMA3_RM_Result result = EDMA3_RM_SOK;
669 EDMA3_RM_Obj *rmObj = NULL;
670 EDMA3_RM_Instance *rmInstance = NULL;
671 EDMA3_RM_Instance *temp_ptr_rm_inst = NULL;
672 EDMA3_RM_Handle retVal = NULL;
673 unsigned int dmaChDwrds = 0u;
674 unsigned int paramSetDwrds = 0u;
675 unsigned int tccDwrds = 0u;
676 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
678 /* If parameter checking is enabled... */
679 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
680 if (((initParam == NULL)
681 || (phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES))
682 || (errorCode == NULL))
683 {
684 result = EDMA3_RM_E_INVALID_PARAM;
685 }
686 #endif
688 /* Check if the parameters are OK. */
689 if (EDMA3_RM_SOK == result)
690 {
691 /* Check whether the semaphore handle is null or not */
692 if (NULL == initParam->rmSemHandle)
693 {
694 result = EDMA3_RM_E_INVALID_PARAM;
695 }
696 else
697 {
698 rmObj = &resMgrObj[phyCtrllerInstId];
699 if (
700 (NULL == rmObj)
701 || (initParam->regionId >=
702 resMgrObj[phyCtrllerInstId].gblCfgParams.numRegions)
703 )
704 {
705 result = EDMA3_RM_E_INVALID_PARAM;
706 }
707 else
708 {
709 edma3OsProtectEntry (phyCtrllerInstId,
710 EDMA3_OS_PROTECT_INTERRUPT,
711 &intState);
713 /** Check state of RM Object.
714 * If no RM instance is opened and this is the first one,
715 * then state should be created/closed.
716 */
717 if ((rmObj->numOpens == NULL) &&
718 ((rmObj->state != EDMA3_RM_CREATED) &&
719 (rmObj->state != EDMA3_RM_CLOSED)))
720 {
721 result = EDMA3_RM_E_INVALID_STATE;
722 edma3OsProtectExit (phyCtrllerInstId,
723 EDMA3_OS_PROTECT_INTERRUPT,
724 intState);
725 }
726 else
727 {
728 /**
729 * If num of instances opened is more than 0 and less than
730 * max allowed, then state should be opened.
731 */
732 if (((rmObj->numOpens > 0) &&
733 (rmObj->numOpens < EDMA3_MAX_RM_INSTANCES))
734 && (rmObj->state != EDMA3_RM_OPENED))
735 {
736 result = EDMA3_RM_E_INVALID_STATE;
737 edma3OsProtectExit (phyCtrllerInstId,
738 EDMA3_OS_PROTECT_INTERRUPT,
739 intState);
740 }
741 else
742 {
743 /* Check if max opens have passed */
744 if (rmObj->numOpens >= EDMA3_MAX_RM_INSTANCES)
745 {
746 result = EDMA3_RM_E_MAX_RM_INST_OPENED;
747 edma3OsProtectExit (phyCtrllerInstId,
748 EDMA3_OS_PROTECT_INTERRUPT,
749 intState);
750 }
751 }
752 }
753 }
754 }
755 }
757 if (EDMA3_RM_SOK == result)
758 {
759 /*
760 * Check whether the RM instance is Master or not.
761 * If it is master, check whether a master already exists
762 * or not. There should NOT be more than 1 master.
763 * Return error code if master already exists
764 */
765 if ((TRUE == masterExists[phyCtrllerInstId]) && (TRUE == initParam->isMaster))
766 {
767 /* No two masters should exist, return error */
768 result = EDMA3_RM_E_RM_MASTER_ALREADY_EXISTS;
769 edma3OsProtectExit (phyCtrllerInstId,
770 EDMA3_OS_PROTECT_INTERRUPT,
771 intState);
772 }
773 else
774 {
775 /* Create Res Mgr Instance */
776 for (resMgrIdx = 0u; resMgrIdx < EDMA3_MAX_RM_INSTANCES; resMgrIdx++)
777 {
778 temp_ptr_rm_inst = ((EDMA3_RM_Instance *)(ptrRMIArray) + (phyCtrllerInstId*EDMA3_MAX_RM_INSTANCES) + resMgrIdx);
780 if (NULL != temp_ptr_rm_inst)
781 {
782 if (NULL == temp_ptr_rm_inst->pResMgrObjHandle)
783 {
784 /* Handle to the EDMA3 HW Object */
785 temp_ptr_rm_inst->pResMgrObjHandle = rmObj;
786 /* Handle of the Res Mgr Instance */
787 rmInstance = temp_ptr_rm_inst;
789 /* Also make this data structure NULL, just for safety. */
790 edma3MemZero((void *)((EDMA3_RM_InstanceInitConfig *)(ptrInitCfgArray) + (phyCtrllerInstId*EDMA3_MAX_RM_INSTANCES) + resMgrIdx),
791 sizeof(EDMA3_RM_InstanceInitConfig));
793 break;
794 }
795 }
796 }
798 /* Check whether a RM instance has been created or not */
799 if (NULL == rmInstance)
800 {
801 result = EDMA3_RM_E_MAX_RM_INST_OPENED;
802 edma3OsProtectExit (phyCtrllerInstId,
803 EDMA3_OS_PROTECT_INTERRUPT,
804 intState);
805 }
806 else
807 {
808 /* Copy the InitPaRAM first */
809 edma3MemCpy((void *)(&rmInstance->initParam),
810 (const void *)(initParam),
811 sizeof (EDMA3_RM_Param));
813 if (rmObj->gblCfgParams.globalRegs != NULL)
814 {
815 globalRegs = (volatile EDMA3_CCRL_Regs *)
816 (rmObj->gblCfgParams.globalRegs);
817 rmInstance->shadowRegs = (EDMA3_CCRL_ShadowRegs *)
818 &(globalRegs->SHADOW[rmInstance->initParam.regionId]);
820 /* copy the instance specific semaphore handle */
821 rmInstance->initParam.rmSemHandle = initParam->rmSemHandle;
823 /**
824 * Check whether user has passed information about resources
825 * owned and reserved by this instance. This is region specific
826 * information. If he has not passed, dafault static config info will be taken
827 * from the config file edma3Cfg.c, according to the regionId specified.
828 *
829 * resMgrIdx specifies the RM instance number created just now.
830 * Use it to populate the userInitConfig [].
831 */
832 if (NULL == initParam->rmInstInitConfig)
833 {
834 /* Take the info from the specific config file */
835 edma3MemCpy((void *)((EDMA3_RM_InstanceInitConfig *)(ptrInitCfgArray) + (phyCtrllerInstId*EDMA3_MAX_RM_INSTANCES) + resMgrIdx),
836 (const void *)(&defInstInitConfig[phyCtrllerInstId][initParam->regionId]),
837 sizeof (EDMA3_RM_InstanceInitConfig));
838 }
839 else
840 {
841 /* User has passed the region specific info. */
842 edma3MemCpy((void *)((EDMA3_RM_InstanceInitConfig *)(ptrInitCfgArray) + (phyCtrllerInstId*EDMA3_MAX_RM_INSTANCES) + resMgrIdx),
843 (const void *)(initParam->rmInstInitConfig),
844 sizeof (EDMA3_RM_InstanceInitConfig));
845 }
847 rmInstance->initParam.rmInstInitConfig =
848 ((EDMA3_RM_InstanceInitConfig *)(ptrInitCfgArray) + (phyCtrllerInstId*EDMA3_MAX_RM_INSTANCES) + resMgrIdx);
850 dmaChDwrds = rmObj->gblCfgParams.numDmaChannels / 32u;
851 if (dmaChDwrds == 0)
852 {
853 /* In case DMA channels are < 32 */
854 dmaChDwrds = 1;
855 }
857 paramSetDwrds = rmObj->gblCfgParams.numPaRAMSets / 32u;
858 if (paramSetDwrds == 0)
859 {
860 /* In case PaRAM Sets are < 32 */
861 paramSetDwrds = 1;
862 }
864 tccDwrds = rmObj->gblCfgParams.numTccs / 32u;
865 if (tccDwrds == 0)
866 {
867 /* In case TCCs are < 32 */
868 tccDwrds = 1;
869 }
871 for (resMgrIdx = 0u; resMgrIdx < dmaChDwrds; ++resMgrIdx)
872 {
873 rmInstance->avlblDmaChannels[resMgrIdx]
874 = rmInstance->initParam.rmInstInitConfig->ownDmaChannels[resMgrIdx];
875 }
877 rmInstance->avlblQdmaChannels[0u]
878 = rmInstance->initParam.rmInstInitConfig->ownQdmaChannels[0u];
880 for (resMgrIdx = 0u; resMgrIdx < paramSetDwrds; ++resMgrIdx)
881 {
882 rmInstance->avlblPaRAMSets[resMgrIdx]
883 = rmInstance->initParam.rmInstInitConfig->ownPaRAMSets[resMgrIdx];
884 }
886 for (resMgrIdx = 0u; resMgrIdx < tccDwrds; ++resMgrIdx)
887 {
888 rmInstance->avlblTccs [resMgrIdx]
889 = rmInstance->initParam.rmInstInitConfig->ownTccs[resMgrIdx];
890 }
892 /*
893 * If mapping exists b/w DMA channel and PaRAM set (i.e. programmable),
894 * then mark those PaRAM sets which are mapped to some specific
895 * DMA channels as RESERVED. If NO mapping (ie ch 0 is tied to PaRAM 0,
896 * ch 1 is tied to PaRAM 1), mark all as RESERVED.
897 */
898 if (rmObj->gblCfgParams.dmaChPaRAMMapExists == TRUE)
899 {
900 /* Mapping Exists */
901 for (resMgrIdx = 0u; resMgrIdx < rmObj->gblCfgParams.numDmaChannels; ++resMgrIdx)
902 {
903 mappedPaRAMId = rmObj->gblCfgParams.dmaChannelPaRAMMap[resMgrIdx];
904 if (mappedPaRAMId != EDMA3_RM_CH_NO_PARAM_MAP)
905 {
906 /* Channel is mapped to a particular PaRAM Set, mark it as Reserved. */
907 rmInstance->initParam.rmInstInitConfig->resvdPaRAMSets[mappedPaRAMId/32u] |= (1u<<(mappedPaRAMId%32u));
908 }
909 }
910 }
911 else
912 {
913 /* Mapping Doesnot Exist, PaRAM Sets are 1-to-1 mapped, mark all as Reserved */
914 for (resMgrIdx = 0u; resMgrIdx < dmaChDwrds; ++resMgrIdx)
915 {
916 rmInstance->initParam.rmInstInitConfig->resvdPaRAMSets[resMgrIdx] = 0xFFFFFFFFu;
917 }
918 }
920 /*
921 * If the EDMA RM instance is MASTER (ie. initParam->isMaster
922 * is TRUE), save the region ID.
923 * Only this shadow region will receive the
924 * EDMA3 interrupts, if enabled.
925 */
926 if (TRUE == initParam->isMaster)
927 {
928 /* Store the region id to use it in the ISRs */
929 edma3RegionId = rmInstance->initParam.regionId;
930 masterExists[phyCtrllerInstId] = TRUE;
931 }
933 if (TRUE == initParam->regionInitEnable)
934 {
935 edma3ShadowRegionInit (rmInstance);
936 }
938 /**
939 * By default, PaRAM Sets allocated using this RM Instance
940 * will get cleared during their allocation.
941 * User can stop their clearing by calling specific IOCTL
942 * command.
943 */
944 rmInstance->paramInitRequired = TRUE;
947 /**
948 * By default, during the EDMA3_RM_allocLogicalChannel (),
949 * global EDMA3 registers (DCHMAP/QCHMAP) and the allocated
950 * PaRAM Set will be programmed accordingly, for users using this
951 * RM Instance.
952 * User can stop their pre-programming by calling
953 * EDMA3_RM_IOCTL_SET_GBL_REG_MODIFY_OPTION
954 * IOCTL command.
955 */
956 rmInstance->regModificationRequired = TRUE;
959 if (EDMA3_RM_SOK == result)
960 {
961 rmObj->state = EDMA3_RM_OPENED;
962 /* Increase the Instance count */
963 resMgrObj[phyCtrllerInstId].numOpens++;
964 retVal = rmInstance;
965 }
966 }
967 else
968 {
969 result = EDMA3_RM_E_INVALID_PARAM;
970 }
972 edma3OsProtectExit (phyCtrllerInstId,
973 EDMA3_OS_PROTECT_INTERRUPT,
974 intState);
975 }
976 }
977 }
979 *errorCode = result;
980 return (EDMA3_RM_Handle)retVal;
981 }
984 /**\fn EDMA3_RM_Result EDMA3_RM_close (EDMA3_RM_Handle hEdmaResMgr,
985 * const void *param)
986 * \brief Close EDMA3 Resource Manager Instance
987 *
988 * This API is used to close a previously opened EDMA3 RM Instance.
989 *
990 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
991 * Manager Instance.
992 * \param param [IN] For possible future use.
993 *
994 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
995 *
996 * \note This function disables the global interrupts (by calling API
997 * edma3OsProtectEntry with protection level
998 * EDMA3_OS_PROTECT_INTERRUPT) while modifying the global RM data
999 * structures, to make it re-entrant.
1000 */
1001 EDMA3_RM_Result EDMA3_RM_close (EDMA3_RM_Handle hEdmaResMgr,
1002 const void *param)
1003 {
1004 EDMA3_RM_Result result = EDMA3_RM_SOK;
1005 unsigned int intState = 0u;
1006 unsigned int resMgrIdx = 0u;
1007 EDMA3_RM_Obj *rmObj = NULL;
1008 EDMA3_RM_Instance *rmInstance = NULL;
1009 unsigned int dmaChDwrds;
1010 unsigned int paramSetDwrds;
1011 unsigned int tccDwrds;
1013 /*to remove CCS remark: parameter "param" was never referenced */
1014 (void)param;
1016 /* If parameter checking is enabled... */
1017 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
1018 if (NULL == hEdmaResMgr)
1019 {
1020 result = EDMA3_RM_E_INVALID_PARAM;
1021 }
1022 #endif
1024 /* Check if the parameters are OK. */
1025 if (EDMA3_RM_SOK == result)
1026 {
1027 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
1028 rmObj = rmInstance->pResMgrObjHandle;
1030 if (rmObj == NULL)
1031 {
1032 result = (EDMA3_RM_E_INVALID_PARAM);
1033 }
1034 else
1035 {
1036 /* Check state of driver, state should be opened */
1037 if (rmObj->state != EDMA3_RM_OPENED)
1038 {
1039 result = (EDMA3_RM_E_OBJ_NOT_OPENED);
1040 }
1041 else
1042 {
1043 dmaChDwrds = rmObj->gblCfgParams.numDmaChannels / 32u;
1044 paramSetDwrds = rmObj->gblCfgParams.numPaRAMSets / 32u;
1045 tccDwrds = rmObj->gblCfgParams.numTccs / 32u;
1047 /* Set the instance config as NULL*/
1048 for (resMgrIdx = 0u; resMgrIdx < dmaChDwrds; ++resMgrIdx)
1049 {
1050 rmInstance->avlblDmaChannels[resMgrIdx] = 0x0u;
1051 }
1052 for (resMgrIdx = 0u; resMgrIdx < paramSetDwrds; ++resMgrIdx)
1053 {
1054 rmInstance->avlblPaRAMSets[resMgrIdx] = 0x0u;
1055 }
1056 rmInstance->avlblQdmaChannels[0u] = 0x0u;
1057 for (resMgrIdx = 0u; resMgrIdx < tccDwrds; ++resMgrIdx)
1058 {
1059 rmInstance->avlblTccs[resMgrIdx] = 0x0u;
1060 }
1062 /**
1063 * If this is the Master Instance, reset the static variable
1064 * 'masterExists[]'.
1065 */
1066 if (TRUE == rmInstance->initParam.isMaster)
1067 {
1068 masterExists[rmObj->phyCtrllerInstId] = FALSE;
1069 edma3RegionId = EDMA3_MAX_REGIONS;
1070 }
1072 /* Reset the Initparam for this RM Instance */
1073 edma3MemZero((void *)&(rmInstance->initParam),
1074 sizeof(EDMA3_RM_Param));
1076 /* Critical section starts */
1077 edma3OsProtectEntry (rmObj->phyCtrllerInstId,
1078 EDMA3_OS_PROTECT_INTERRUPT,
1079 &intState);
1081 /* Decrease the Number of Opens */
1082 --rmObj->numOpens;
1083 if (NULL == rmObj->numOpens)
1084 {
1085 edma3MemZero((void *)&(edma3RmChBoundRes[rmObj->phyCtrllerInstId]),
1086 sizeof(edma3RmChBoundRes[rmObj->phyCtrllerInstId]));
1088 rmObj->state = EDMA3_RM_CLOSED;
1089 }
1091 /* Critical section ends */
1092 edma3OsProtectExit (rmObj->phyCtrllerInstId,
1093 EDMA3_OS_PROTECT_INTERRUPT,
1094 intState);
1096 rmInstance->pResMgrObjHandle = NULL;
1097 rmInstance->shadowRegs = NULL;
1098 rmInstance = NULL;
1099 }
1100 }
1101 }
1103 return result;
1104 }
1107 /**\fn EDMA3_RM_Result EDMA3_RM_allocResource (EDMA3_RM_Handle hEdmaResMgr,
1108 * EDMA3_RM_ResDesc *resObj)
1109 * \brief This API is used to allocate specified EDMA3 Resources like
1110 * DMA/QDMA channel, PaRAM Set or TCC.
1111 *
1112 * Note: To free the resources allocated by this API, user should call
1113 * EDMA3_RM_freeResource () ONLY to de-allocate all the allocated resources.
1114 *
1115 * User can either request a specific resource by passing the resource id
1116 * in 'resObj->resId' OR request ANY available resource of the type
1117 * 'resObj->type'.
1118 *
1119 * ANY types of resources are those resources when user doesn't care about the
1120 * actual resource allocated; user just wants a resource of the type specified.
1121 * One use-case is to perform memory-to-memory data transfer operation. This
1122 * operation can be performed using any available DMA or QDMA channel.
1123 * User doesn't need any specific channel for the same.
1124 *
1125 * To allocate a specific resource, first this API checks whether that resource
1126 * is OWNED by the Resource Manager instance. Then it checks the current
1127 * availability of that resource.
1128 *
1129 * To allocate ANY available resource, this API tries to allocate a resource
1130 * from the pool of (owned && non_reserved && available_right_now) resources.
1131 *
1132 * After allocating a DMA/QDMA channel or TCC, the same resource is enabled in
1133 * the shadow region specific register (DRAE/DRAEH/QRAE).
1134 *
1135 * Allocated PaRAM Set is initialized to NULL before this API returns if user
1136 * has requested for one.
1137 *
1138 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
1139 * Manager Instance.
1140 * \param resObj [IN/OUT] Handle to the resource descriptor
1141 * object, which needs to be allocated.
1142 * In case user passes a specific resource
1143 * Id, resObj value is left unchanged.
1144 * In case user requests ANY available
1145 * resource, the allocated resource id is
1146 * returned in resObj.
1147 *
1148 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
1149 *
1150 * \note This function acquires a RM Instance specific semaphore
1151 * to prevent simultaneous access to the global pool of resources.
1152 * It is re-entrant, but should not be called from the user callback
1153 * function (ISR context).
1154 */
1155 EDMA3_RM_Result EDMA3_RM_allocResource(EDMA3_RM_Handle hEdmaResMgr,
1156 EDMA3_RM_ResDesc *resObj)
1157 {
1158 EDMA3_RM_Instance *rmInstance = NULL;
1159 EDMA3_RM_Obj *rmObj = NULL;
1160 EDMA3_RM_Result result = EDMA3_RM_SOK;
1161 EDMA3_RM_Result semResult = EDMA3_RM_SOK;
1162 unsigned int avlblIdx = 0u;
1163 unsigned int resIdClr = 0x0;
1164 unsigned int resIdSet = 0x0;
1165 unsigned int resId;
1166 volatile EDMA3_CCRL_Regs *gblRegs = NULL;
1168 #ifdef EDMA3_INSTRUMENTATION_ENABLED
1169 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
1170 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
1171 EDMA3_DVT_dCOUNTER,
1172 EDMA3_DVT_dNONE,
1173 EDMA3_DVT_dNONE));
1174 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
1176 /* If parameter checking is enabled... */
1177 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
1178 if ((hEdmaResMgr == NULL) || (resObj == NULL))
1179 {
1180 result = (EDMA3_RM_E_INVALID_PARAM);
1181 }
1182 #endif
1184 /* Check if the parameters are OK. */
1185 if (EDMA3_RM_SOK == result)
1186 {
1187 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
1188 rmObj = rmInstance->pResMgrObjHandle;
1190 if ((rmObj == NULL) ||
1191 (rmObj->gblCfgParams.globalRegs == NULL))
1192 {
1193 result = (EDMA3_RM_E_INVALID_PARAM);
1194 }
1195 else
1196 {
1197 gblRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
1199 resId = resObj->resId;
1201 resIdClr = (unsigned int)(~(1u << (resId%32u)));
1202 resIdSet = (1u << (resId%32u));
1204 /**
1205 * Take the instance specific semaphore, to prevent simultaneous
1206 * access to the shared resources.
1207 */
1208 semResult = edma3OsSemTake(rmInstance->initParam.rmSemHandle,
1209 EDMA3_OSSEM_NO_TIMEOUT);
1210 if (EDMA3_RM_SOK == semResult)
1211 {
1212 switch (resObj->type)
1213 {
1214 case EDMA3_RM_RES_DMA_CHANNEL :
1215 {
1216 if (resId == EDMA3_RM_RES_ANY)
1217 {
1218 for (avlblIdx=0u;
1219 avlblIdx <
1220 rmObj->gblCfgParams.numDmaChannels;
1221 ++avlblIdx)
1222 {
1223 if (((rmInstance->initParam.rmInstInitConfig->ownDmaChannels[avlblIdx/32u])
1224 &
1225 (rmInstance->avlblDmaChannels[avlblIdx/32u])
1226 &
1227 ~(rmInstance->initParam.rmInstInitConfig->resvdDmaChannels[avlblIdx/32u])
1228 &
1229 (1u << (avlblIdx%32u))) != FALSE)
1230 {
1231 /*
1232 * Match found.
1233 * A resource which is owned by this instance of the
1234 * Resource Manager and which is presently available
1235 * and which has not been reserved - is found.
1236 */
1237 resObj->resId = avlblIdx;
1238 /*
1239 * Mark the 'match found' resource as "Not Available"
1240 * for future requests
1241 */
1242 rmInstance->avlblDmaChannels[avlblIdx/32u] &= (unsigned int)(~(1u << (avlblIdx%32u)));
1244 /**
1245 * Check if the register modification flag is
1246 * set or not.
1247 */
1248 if (TRUE == rmInstance->regModificationRequired)
1249 {
1250 /**
1251 * Enable the DMA channel in the
1252 * DRAE/DRAEH registers also.
1253 */
1254 if (avlblIdx < 32u)
1255 {
1256 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
1257 |= (0x1u << avlblIdx);
1258 }
1259 else
1260 {
1261 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
1262 |= (0x1u << (avlblIdx - 32u));
1263 }
1264 }
1266 result = EDMA3_RM_SOK;
1267 break;
1268 }
1269 }
1270 /*
1271 * If none of the owned resources of this type is available
1272 * then report "All Resources of this type not available" error
1273 */
1274 if (avlblIdx == rmObj->gblCfgParams.numDmaChannels)
1275 {
1276 result = EDMA3_RM_E_ALL_RES_NOT_AVAILABLE;
1277 }
1278 }
1279 else
1280 {
1281 if (resId < rmObj->gblCfgParams.numDmaChannels)
1282 {
1283 /*
1284 * Check if specified resource is owned
1285 * by this instance of the resource manager
1286 */
1287 if (((rmInstance->initParam.rmInstInitConfig->ownDmaChannels[resId/32u])&(resIdSet))!=FALSE)
1288 {
1289 /* Now check if specified resource is available presently*/
1290 if (((rmInstance->avlblDmaChannels[resId/32u])&(resIdSet))!=FALSE)
1291 {
1292 /*
1293 * Mark the specified channel as "Not Available"
1294 * for future requests
1295 */
1296 rmInstance->avlblDmaChannels[resId/32u] &= resIdClr;
1298 /**
1299 * Check if the register modification flag is
1300 * set or not.
1301 */
1302 if (TRUE == rmInstance->regModificationRequired)
1303 {
1304 if (resId < 32u)
1305 {
1306 rmInstance->shadowRegs->EECR = (1UL << resId);
1308 /**
1309 * Enable the DMA channel in the
1310 * DRAE registers also.
1311 */
1312 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
1313 |= (0x1u << resId);
1314 }
1315 else
1316 {
1317 rmInstance->shadowRegs->EECRH = (1UL << resId);
1319 /**
1320 * Enable the DMA channel in the
1321 * DRAEH registers also.
1322 */
1323 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
1324 |= (0x1u << (resId - 32u));
1325 }
1326 }
1328 result = EDMA3_RM_SOK;
1329 }
1330 else
1331 {
1332 /* Specified resource is owned but is already booked */
1333 result = EDMA3_RM_E_SPECIFIED_RES_NOT_AVAILABLE;
1334 }
1335 }
1336 else
1337 {
1338 /*
1339 * Specified resource is not owned by this instance
1340 * of the Resource Manager
1341 */
1342 result = EDMA3_RM_E_RES_NOT_OWNED;
1343 }
1344 }
1345 else
1346 {
1347 result = EDMA3_RM_E_INVALID_PARAM;
1348 }
1349 }
1350 }
1351 break;
1353 case EDMA3_RM_RES_QDMA_CHANNEL :
1354 {
1355 if (resId == EDMA3_RM_RES_ANY)
1356 {
1357 for (avlblIdx=0u; avlblIdx<rmObj->gblCfgParams.numQdmaChannels; ++avlblIdx)
1358 {
1359 if (((rmInstance->initParam.rmInstInitConfig->ownQdmaChannels[avlblIdx/32u])
1360 &
1361 (rmInstance->avlblQdmaChannels[avlblIdx/32u])
1362 &
1363 ~(rmInstance->initParam.rmInstInitConfig->resvdQdmaChannels[avlblIdx/32u])
1364 &
1365 (1u << (avlblIdx%32u))) != FALSE)
1366 {
1367 resObj->resId = avlblIdx;
1368 rmInstance->avlblQdmaChannels[avlblIdx/32u] &= (unsigned int)(~(1u << (avlblIdx%32u)));
1370 /**
1371 * Check if the register modification flag is
1372 * set or not.
1373 */
1374 if (TRUE == rmInstance->regModificationRequired)
1375 {
1376 /**
1377 * Enable the QDMA channel in the
1378 * QRAE register also.
1379 */
1380 gblRegs->QRAE[rmInstance->initParam.regionId]
1381 |= (0x1u << avlblIdx);
1382 }
1384 result = EDMA3_RM_SOK;
1385 break;
1386 }
1387 }
1388 /*
1389 * If none of the owned resources of this type is available
1390 * then report "All Resources of this type not available" error
1391 */
1392 if (avlblIdx == rmObj->gblCfgParams.numQdmaChannels)
1393 {
1394 result = EDMA3_RM_E_ALL_RES_NOT_AVAILABLE;
1395 }
1396 }
1397 else
1398 {
1399 if (resId < rmObj->gblCfgParams.numQdmaChannels)
1400 {
1401 if (((rmInstance->initParam.rmInstInitConfig->ownQdmaChannels [resId/32u])&(resIdSet))!=FALSE)
1402 {
1403 if (((rmInstance->avlblQdmaChannels [resId/32u])&(resIdSet))!=FALSE)
1404 {
1405 rmInstance->avlblQdmaChannels [resId/32u] &= resIdClr;
1407 /**
1408 * Check if the register modification flag is
1409 * set or not.
1410 */
1411 if (TRUE == rmInstance->regModificationRequired)
1412 {
1413 /**
1414 * Enable the QDMA channel in the
1415 * QRAE register also.
1416 */
1417 gblRegs->QRAE[rmInstance->initParam.regionId]
1418 |= (0x1u << resId);
1419 }
1421 result = EDMA3_RM_SOK;
1422 }
1423 else
1424 {
1425 /* Specified resource is owned but is already booked */
1426 result = EDMA3_RM_E_SPECIFIED_RES_NOT_AVAILABLE;
1427 }
1428 }
1429 else
1430 {
1431 /*
1432 * Specified resource is not owned by this instance
1433 * of the Resource Manager
1434 */
1435 result = EDMA3_RM_E_RES_NOT_OWNED;
1436 }
1437 }
1438 else
1439 {
1440 result = EDMA3_RM_E_INVALID_PARAM;
1441 }
1442 }
1443 }
1444 break;
1446 case EDMA3_RM_RES_TCC :
1447 {
1448 if (resId == EDMA3_RM_RES_ANY)
1449 {
1450 for (avlblIdx=0u; avlblIdx<rmObj->gblCfgParams.numTccs; ++avlblIdx)
1451 {
1452 if (((rmInstance->initParam.rmInstInitConfig->ownTccs [avlblIdx/32u])
1453 & (rmInstance->avlblTccs [avlblIdx/32u])
1454 & ~(rmInstance->initParam.rmInstInitConfig->resvdTccs [avlblIdx/32u])
1455 & (1u << (avlblIdx%32u)))!=FALSE)
1456 {
1457 resObj->resId = avlblIdx;
1458 rmInstance->avlblTccs [avlblIdx/32u] &= (unsigned int)(~(1u << (avlblIdx%32u)));
1460 /**
1461 * Check if the register modification flag is
1462 * set or not.
1463 */
1464 if (TRUE == rmInstance->regModificationRequired)
1465 {
1466 /**
1467 * Enable the Interrupt channel in the
1468 * DRAE/DRAEH registers also.
1469 * Also, If the region id coming from this
1470 * RM instance is same as the Master RM
1471 * Instance's region id, only then we will be
1472 * getting the interrupts on the same side.
1473 * So save the TCC in the allocatedTCCs[] array.
1474 */
1475 if (avlblIdx < 32u)
1476 {
1477 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
1478 |= (0x1u << avlblIdx);
1480 /**
1481 * Do not modify this global array if the register
1482 * modificatio flag is not set.
1483 * Reason being is based on this flag, the IPR/ICR
1484 * or error bit is cleared in the completion or
1485 * error handler ISR.
1486 */
1487 if (edma3RegionId == rmInstance->initParam.regionId)
1488 {
1489 allocatedTCCs[0u] |= (0x1u << avlblIdx);
1490 }
1491 }
1492 else
1493 {
1494 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
1495 |= (0x1u << (avlblIdx - 32u));
1497 /**
1498 * Do not modify this global array if the register
1499 * modificatio flag is not set.
1500 * Reason being is based on this flag, the IPR/ICR
1501 * or error bit is cleared in the completion or
1502 * error handler ISR.
1503 */
1504 if (edma3RegionId == rmInstance->initParam.regionId)
1505 {
1506 allocatedTCCs[1u] |= (0x1u << (avlblIdx - 32u));
1507 }
1508 }
1509 }
1512 result = EDMA3_RM_SOK;
1513 break;
1514 }
1515 }
1516 /*
1517 * If none of the owned resources of this type is available
1518 * then report "All Resources of this type not available" error
1519 */
1520 if ( avlblIdx == rmObj->gblCfgParams.numTccs)
1521 {
1522 result = EDMA3_RM_E_ALL_RES_NOT_AVAILABLE;
1523 }
1524 }
1525 else
1526 {
1527 if (resId < rmObj->gblCfgParams.numTccs)
1528 {
1529 if (((rmInstance->initParam.rmInstInitConfig->ownTccs [resId/32u])&(resIdSet))!=FALSE)
1530 {
1531 if (((rmInstance->avlblTccs [resId/32u])&(resIdSet))!=FALSE)
1532 {
1533 rmInstance->avlblTccs [resId/32u] &= resIdClr;
1535 /**
1536 * Check if the register modification flag is
1537 * set or not.
1538 */
1539 if (TRUE == rmInstance->regModificationRequired)
1540 {
1541 /**
1542 * Enable the Interrupt channel in the
1543 * DRAE/DRAEH registers also.
1544 * Also, If the region id coming from this
1545 * RM instance is same as the Master RM
1546 * Instance's region id, only then we will be
1547 * getting the interrupts on the same side.
1548 * So save the TCC in the allocatedTCCs[] array.
1549 */
1550 if (resId < 32u)
1551 {
1552 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
1553 |= (0x1u << resId);
1555 /**
1556 * Do not modify this global array if the register
1557 * modificatio flag is not set.
1558 * Reason being is based on this flag, the IPR/ICR
1559 * or error bit is cleared in the completion or
1560 * error handler ISR.
1561 */
1562 if (edma3RegionId == rmInstance->initParam.regionId)
1563 {
1564 allocatedTCCs[0u] |= (0x1u << resId);
1565 }
1566 }
1567 else
1568 {
1569 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
1570 |= (0x1u << (resId - 32u));
1572 /**
1573 * Do not modify this global array if the register
1574 * modificatio flag is not set.
1575 * Reason being is based on this flag, the IPR/ICR
1576 * or error bit is cleared in the completion or
1577 * error handler ISR.
1578 */
1579 if (edma3RegionId == rmInstance->initParam.regionId)
1580 {
1581 allocatedTCCs[1u] |= (0x1u << (resId - 32u));
1582 }
1583 }
1584 }
1586 result = EDMA3_RM_SOK;
1587 }
1588 else
1589 {
1590 /* Specified resource is owned but is already booked */
1591 result = EDMA3_RM_E_SPECIFIED_RES_NOT_AVAILABLE;
1592 }
1593 }
1594 else
1595 {
1596 /*
1597 * Specified resource is not owned by this instance
1598 * of the Resource Manager
1599 */
1600 result = EDMA3_RM_E_RES_NOT_OWNED;
1601 }
1602 }
1603 else
1604 {
1605 result = EDMA3_RM_E_INVALID_PARAM;
1606 }
1607 }
1608 }
1609 break;
1611 case EDMA3_RM_RES_PARAM_SET :
1612 {
1613 if (resId == EDMA3_RM_RES_ANY)
1614 {
1615 for (avlblIdx=0u; avlblIdx<rmObj->gblCfgParams.numPaRAMSets; ++avlblIdx)
1616 {
1617 if (((rmInstance->initParam.rmInstInitConfig->ownPaRAMSets [avlblIdx/32u])
1618 &
1619 (rmInstance->avlblPaRAMSets [avlblIdx/32u])
1620 &
1621 ~(rmInstance->initParam.rmInstInitConfig->resvdPaRAMSets [avlblIdx/32u])
1622 &
1623 (1u << (avlblIdx%32u)))!=FALSE)
1624 {
1625 resObj->resId = avlblIdx;
1626 rmInstance->avlblPaRAMSets [avlblIdx/32u] &= (unsigned int)(~(1u << (avlblIdx%32u)));
1628 /**
1629 * Also, make the actual PARAM Set NULL, checking the flag
1630 * whether it is required or not.
1631 */
1632 if ((TRUE == rmInstance->regModificationRequired)
1633 && (TRUE == rmInstance->paramInitRequired))
1634 {
1635 edma3MemZero((void *)(&gblRegs->PARAMENTRY[avlblIdx]),
1636 sizeof(gblRegs->PARAMENTRY[avlblIdx]));
1637 }
1639 result = EDMA3_RM_SOK;
1640 break;
1641 }
1642 }
1643 /*
1644 * If none of the owned resources of this type is available
1645 * then report "All Resources of this type not available" error
1646 */
1647 if ( avlblIdx == rmObj->gblCfgParams.numPaRAMSets)
1648 {
1649 result = EDMA3_RM_E_ALL_RES_NOT_AVAILABLE;
1650 }
1651 }
1652 else
1653 {
1654 if (resId < rmObj->gblCfgParams.numPaRAMSets)
1655 {
1656 if (((rmInstance->initParam.rmInstInitConfig->ownPaRAMSets [resId/32u])&(resIdSet))!=FALSE)
1657 {
1658 if (((rmInstance->avlblPaRAMSets [resId/32u])&(resIdSet)) !=FALSE)
1659 {
1660 rmInstance->avlblPaRAMSets [resId/32u] &= resIdClr;
1662 /**
1663 * Also, make the actual PARAM Set NULL, checking the flag
1664 * whether it is required or not.
1665 */
1666 if ((TRUE == rmInstance->regModificationRequired)
1667 && (TRUE == rmInstance->paramInitRequired))
1668 {
1669 edma3MemZero((void *)(&gblRegs->PARAMENTRY[resId]),
1670 sizeof(gblRegs->PARAMENTRY[resId]));
1671 }
1673 result = EDMA3_RM_SOK;
1674 }
1675 else
1676 {
1677 /* Specified resource is owned but is already booked */
1678 result = EDMA3_RM_E_SPECIFIED_RES_NOT_AVAILABLE;
1679 }
1680 }
1681 else
1682 {
1683 /*
1684 * Specified resource is not owned by this instance
1685 * of the Resource Manager
1686 */
1687 result = EDMA3_RM_E_RES_NOT_OWNED;
1688 }
1689 }
1690 else
1691 {
1692 result = EDMA3_RM_E_INVALID_PARAM;
1693 }
1694 }
1695 }
1696 break;
1698 default:
1699 result = EDMA3_RM_E_INVALID_PARAM;
1700 break;
1701 }
1703 /* Return the semaphore back */
1704 semResult = edma3OsSemGive(rmInstance->initParam.rmSemHandle);
1705 }
1706 }
1707 }
1709 /**
1710 * Check the Resource Allocation Result 'result' first. If Resource
1711 * Allocation has resulted in an error, return it (having more priority than
1712 * semResult.
1713 * Else, return semResult.
1714 */
1715 if (EDMA3_RM_SOK == result)
1716 {
1717 /**
1718 * Resource Allocation successful, return semResult for returning
1719 * semaphore.
1720 */
1721 result = semResult;
1722 }
1724 #ifdef EDMA3_INSTRUMENTATION_ENABLED
1725 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
1726 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
1727 EDMA3_DVT_dCOUNTER,
1728 EDMA3_DVT_dNONE,
1729 EDMA3_DVT_dNONE));
1730 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
1732 return result;
1733 }
1737 /**\fn EDMA3_RM_Result EDMA3_RM_freeResource(EDMA3_RM_Handle hEdmaResMgr,
1738 * const EDMA3_RM_ResDesc *resObj)
1739 * \brief This API is used to free previously allocated EDMA3 Resources like
1740 * DMA/QDMA channel, PaRAM Set or TCC.
1741 *
1742 * To free a specific resource, first this API checks whether that resource is
1743 * OWNED by the Resource Manager Instance. Then it checks whether that resource
1744 * has been allocated by the Resource Manager instance or not.
1745 *
1746 * After freeing a DMA/QDMA channel or TCC, the same resource is disabled in
1747 * the shadow region specific register (DRAE/DRAEH/QRAE).
1748 *
1749 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
1750 * Manager Instance.
1751 * \param resObj [IN] Handle to the resource descriptor
1752 * object, which needs to be freed.
1753 *
1754 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
1755 *
1756 * \note This function disables the global interrupts to prevent
1757 * simultaneous access to the global pool of resources.
1758 * It is re-entrant.
1759 */
1760 EDMA3_RM_Result EDMA3_RM_freeResource(EDMA3_RM_Handle hEdmaResMgr,
1761 const EDMA3_RM_ResDesc *resObj)
1762 {
1763 unsigned int intState;
1764 EDMA3_RM_Instance *rmInstance = NULL;
1765 EDMA3_RM_Obj *rmObj = NULL;
1766 EDMA3_RM_Result result = EDMA3_RM_SOK;
1767 unsigned int resId;
1768 unsigned int resIdSet = 0x0;
1769 volatile EDMA3_CCRL_Regs *gblRegs = NULL;
1771 #ifdef EDMA3_INSTRUMENTATION_ENABLED
1772 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
1773 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
1774 EDMA3_DVT_dCOUNTER,
1775 EDMA3_DVT_dNONE,
1776 EDMA3_DVT_dNONE));
1777 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
1779 /* If parameter checking is enabled... */
1780 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
1781 if ((hEdmaResMgr == NULL) || (resObj == NULL))
1782 {
1783 result = EDMA3_RM_E_INVALID_PARAM;
1784 }
1785 #endif
1787 /* Check if the parameters are OK. */
1788 if (EDMA3_RM_SOK == result)
1789 {
1790 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
1791 rmObj = rmInstance->pResMgrObjHandle;
1793 if ((rmObj == NULL) ||
1794 (rmObj->gblCfgParams.globalRegs == NULL))
1795 {
1796 result = EDMA3_RM_E_INVALID_PARAM;
1797 }
1798 else
1799 {
1800 gblRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
1802 resId = resObj->resId;
1804 resIdSet = 1u << (resId%32u);
1806 edma3OsProtectEntry (rmObj->phyCtrllerInstId,
1807 EDMA3_OS_PROTECT_INTERRUPT,
1808 &intState);
1810 if (EDMA3_RM_SOK == result)
1811 {
1812 switch (resObj->type)
1813 {
1814 case EDMA3_RM_RES_DMA_CHANNEL :
1815 {
1816 if (resId < rmObj->gblCfgParams.numDmaChannels)
1817 {
1818 if (((rmInstance->initParam.rmInstInitConfig->ownDmaChannels [resId/32u]) & (resIdSet))!=FALSE)
1819 {
1820 if (((~(rmInstance->avlblDmaChannels[resId/32u]))&(resIdSet))!=FALSE)
1821 {
1822 /*
1823 * Mark the specified channel as "Available"
1824 * for future requests
1825 */
1826 rmInstance->avlblDmaChannels[resId/32u] |= resIdSet;
1828 /**
1829 * Check if the register modification flag is
1830 * set or not.
1831 */
1832 if (TRUE == rmInstance->regModificationRequired)
1833 {
1834 /**
1835 * DMA Channel is freed.
1836 * Reset the bit specific to the DMA channel
1837 * in the DRAE/DRAEH register also.
1838 */
1839 if (resId < 32u)
1840 {
1841 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
1842 &= (~(0x1u << resId));
1843 }
1844 else
1845 {
1846 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
1847 &= (~(0x1u << (resId-32u)));
1848 }
1849 }
1851 result = EDMA3_RM_SOK;
1852 }
1853 else
1854 {
1855 result = EDMA3_RM_E_RES_ALREADY_FREE;
1856 }
1857 }
1858 else
1859 {
1860 /*
1861 * Specified resource is not owned by this instance
1862 * of the Resource Manager
1863 */
1864 result = EDMA3_RM_E_RES_NOT_OWNED;
1865 }
1866 }
1867 else
1868 {
1869 result = EDMA3_RM_E_INVALID_PARAM;
1870 }
1871 }
1872 break;
1874 case EDMA3_RM_RES_QDMA_CHANNEL :
1875 {
1876 if (resId < rmObj->gblCfgParams.numQdmaChannels)
1877 {
1878 if (((rmInstance->initParam.rmInstInitConfig->ownQdmaChannels [resId/32u]) & (resIdSet))!=FALSE)
1879 {
1880 if (((~(rmInstance->avlblQdmaChannels [resId/32u])) & (resIdSet))!=FALSE)
1881 {
1882 rmInstance->avlblQdmaChannels [resId/32u] |= resIdSet;
1884 /**
1885 * Check if the register modification flag is
1886 * set or not.
1887 */
1888 if (TRUE == rmInstance->regModificationRequired)
1889 {
1890 /**
1891 * QDMA Channel is freed.
1892 * Reset the bit specific to the QDMA channel
1893 * in the QRAE register also.
1894 */
1895 gblRegs->QRAE[rmInstance->initParam.regionId]
1896 &= (~(0x1u << resId));
1897 }
1899 result = EDMA3_RM_SOK;
1900 }
1901 else
1902 {
1903 result = EDMA3_RM_E_RES_ALREADY_FREE;
1904 }
1905 }
1906 else
1907 {
1908 /*
1909 * Specified resource is not owned by this instance
1910 * of the Resource Manager
1911 */
1912 result = EDMA3_RM_E_RES_NOT_OWNED;
1913 }
1914 }
1915 else
1916 {
1917 result = EDMA3_RM_E_INVALID_PARAM;
1918 }
1919 }
1920 break;
1922 case EDMA3_RM_RES_TCC :
1923 {
1924 if (resId < rmObj->gblCfgParams.numTccs)
1925 {
1926 if (((rmInstance->initParam.rmInstInitConfig->ownTccs [resId/32u]) & (resIdSet))!=FALSE)
1927 {
1928 if (((~(rmInstance->avlblTccs [resId/32u])) & (resIdSet))!=FALSE)
1929 {
1930 rmInstance->avlblTccs [resId/32u] |= resIdSet;
1932 /**
1933 * Check if the register modification flag is
1934 * set or not.
1935 */
1936 if (TRUE == rmInstance->regModificationRequired)
1937 {
1938 /**
1939 * Interrupt Channel is freed.
1940 * Reset the bit specific to the Interrupt
1941 * channel in the DRAE/DRAEH register also.
1942 * Also, if we have earlier saved this
1943 * TCC in allocatedTCCs[] array,
1944 * remove it from there too.
1945 */
1946 if (resId < 32u)
1947 {
1948 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
1949 &= (~(0x1u << resId));
1951 if (edma3RegionId == rmInstance->initParam.regionId)
1952 {
1953 allocatedTCCs[0u] &= (~(0x1u << resId));
1954 }
1955 }
1956 else
1957 {
1958 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
1959 &= (~(0x1u << (resId-32u)));
1961 if (edma3RegionId == rmInstance->initParam.regionId)
1962 {
1963 allocatedTCCs[1u] &= (~(0x1u << (resId -32u)));
1964 }
1965 }
1966 }
1968 result = EDMA3_RM_SOK;
1969 }
1970 else
1971 {
1972 result = EDMA3_RM_E_RES_ALREADY_FREE;
1973 }
1974 }
1975 else
1976 {
1977 /*
1978 * Specified resource is not owned by this instance
1979 * of the Resource Manager
1980 */
1981 result = EDMA3_RM_E_RES_NOT_OWNED;
1982 }
1983 }
1984 else
1985 {
1986 result = EDMA3_RM_E_INVALID_PARAM;
1987 }
1988 }
1989 break;
1991 case EDMA3_RM_RES_PARAM_SET :
1992 {
1993 if (resId < rmObj->gblCfgParams.numPaRAMSets)
1994 {
1995 if (((rmInstance->initParam.rmInstInitConfig->ownPaRAMSets [resId/32u])&(resIdSet))!=FALSE)
1996 {
1997 if (((~(rmInstance->avlblPaRAMSets [resId/32u]))&(resIdSet))!=FALSE)
1998 {
1999 rmInstance->avlblPaRAMSets [resId/32u] |= resIdSet;
2001 result = EDMA3_RM_SOK;
2002 }
2003 else
2004 {
2005 result = EDMA3_RM_E_RES_ALREADY_FREE;
2006 }
2007 }
2008 else
2009 {
2010 /*
2011 * Specified resource is not owned by this instance
2012 * of the Resource Manager
2013 */
2014 result = EDMA3_RM_E_RES_NOT_OWNED;
2015 }
2016 }
2017 else
2018 {
2019 result = EDMA3_RM_E_INVALID_PARAM;
2020 }
2021 }
2022 break;
2024 default:
2025 result = EDMA3_RM_E_INVALID_PARAM;
2026 break;
2027 }
2029 }
2031 edma3OsProtectExit (rmObj->phyCtrllerInstId,
2032 EDMA3_OS_PROTECT_INTERRUPT,
2033 intState);
2034 }
2035 }
2037 #ifdef EDMA3_INSTRUMENTATION_ENABLED
2038 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
2039 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
2040 EDMA3_DVT_dCOUNTER,
2041 EDMA3_DVT_dNONE,
2042 EDMA3_DVT_dNONE));
2043 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
2045 return result;
2046 }
2050 /**
2051 * \fn EDMA3_RM_Result EDMA3_RM_allocLogicalChannel(EDMA3_RM_Handle
2052 * hEdmaResMgr, EDMA3_RM_ResDesc *lChObj,
2053 * unsigned int *pParam, unsigned int *pTcc)
2054 * \brief Request a DMA/QDMA/Link channel.
2055 *
2056 * This API is used to allocate a logical channel (DMA/QDMA/Link) along with
2057 * the associated resources. For DMA and QDMA channels, TCC and PaRAM Set are
2058 * also allocated along with the requested channel. For Link channel, ONLY a
2059 * PaRAM Set is allocated.
2060 *
2061 * Note: To free the logical channel allocated by this API, user should call
2062 * EDMA3_RM_freeLogicalChannel () ONLY to de-allocate all the allocated resources
2063 * and remove certain mappings.
2064 *
2065 * User can request a specific logical channel by passing the channel id in
2066 * 'lChObj->resId' and channel type in 'lChObj->type'. Note that the channel
2067 * id is the same as the actual resource id. For e.g. in the case of QDMA
2068 * channels, valid channel ids are from 0 to 7 only.
2069 *
2070 * User can also request ANY available logical channel of the type
2071 * 'lChObj->type' by specifying 'lChObj->resId' as:
2072 * a) EDMA3_RM_DMA_CHANNEL_ANY: For DMA channels
2073 * b) EDMA3_RM_QDMA_CHANNEL_ANY: For QDMA channels, and
2074 * c) EDMA3_RM_PARAM_ANY: For Link channels. Normally user should use this
2075 * value to request link channels (PaRAM Sets used for linking purpose
2076 * only), unless he wants to use some specific link channels (PaRAM Sets)
2077 * which is also allowed.
2078 *
2079 * This API internally uses EDMA3_RM_allocResource () to allocate the desired
2080 * resources (DMA/QDMA channel, PaRAM Set and TCC).
2081 *
2082 * For DMA/QDMA channels, after allocating all the EDMA3 resources, this API
2083 * sets the TCC field of the OPT PaRAM Word with the allocated TCC.
2084 *
2085 * For DMA channel, it also sets the DCHMAP register, if required.
2086 *
2087 * For QDMA channel, it sets the QCHMAP register and CCNT as trigger word and
2088 * enables the QDMA channel by writing to the QEESR register.
2089 *
2090 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
2091 * Manager Instance.
2092 * \param lChObj [IN/OUT] Handle to the requested logical channel
2093 * object, which needs to be allocated.
2094 * It could be a specific logical channel
2095 * or ANY available logical channel of the
2096 * requested type.
2097 * In case user passes a specific resource
2098 * Id, lChObj value is left unchanged. In
2099 * case user requests ANY available
2100 * resource, the allocated resource id is
2101 * returned in lChObj->resId.
2102 *
2103 * \param pParam [IN/OUT] PaRAM Set for a particular logical
2104 * (DMA/QDMA) channel. Not used if user
2105 * requested for a Link channel.
2106 * In case user passes a specific PaRAM
2107 * Set value, pParam value is left
2108 * unchanged. In case user requests ANY
2109 * available PaRAM Set, the allocated one
2110 * is returned in pParam.
2111 *
2112 * \param pTcc [IN/OUT] TCC for a particular logical (DMA/QDMA)
2113 * channel. Not used if user requested for
2114 * a Link channel.
2115 * In case user passes a specific TCC
2116 * value, pTcc value is left unchanged.
2117 * In case user requests ANY available TCC,
2118 * the allocated one is returned in pTcc
2119 *
2120 * \return EDMA3_RM_SOK or EDMA_RM Error Code
2121 *
2122 * \note This function internally calls EDMA3_RM_allocResource (), which
2123 * acquires a RM Instance specific semaphore to prevent simultaneous
2124 * access to the global pool of resources. It is re-entrant for unique
2125 * logical channel values, but SHOULD NOT be called from the user
2126 * callback function (ISR context).
2127 */
2128 EDMA3_RM_Result EDMA3_RM_allocLogicalChannel(EDMA3_RM_Handle hEdmaResMgr,
2129 EDMA3_RM_ResDesc *lChObj,
2130 unsigned int *pParam,
2131 unsigned int *pTcc)
2132 {
2133 EDMA3_RM_ResDesc *chObj;
2134 EDMA3_RM_ResDesc resObj;
2135 EDMA3_RM_Result result = EDMA3_RM_SOK;
2136 EDMA3_RM_Instance *rmInstance = NULL;
2137 EDMA3_RM_Obj *rmObj = NULL;
2138 unsigned int mappedPaRAMId=0u;
2139 unsigned int mappedTcc = EDMA3_RM_CH_NO_TCC_MAP;
2140 int paRAMId = (int)EDMA3_RM_RES_ANY;
2141 volatile EDMA3_CCRL_Regs *gblRegs = NULL;
2142 unsigned int qdmaChId = EDMA3_MAX_PARAM_SETS;
2143 unsigned int edma3Id;
2145 #ifdef EDMA3_INSTRUMENTATION_ENABLED
2146 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
2147 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
2148 EDMA3_DVT_dCOUNTER,
2149 EDMA3_DVT_dNONE,
2150 EDMA3_DVT_dNONE));
2151 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
2153 /* If parameter checking is enabled... */
2154 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
2155 if ((lChObj == NULL) || (hEdmaResMgr == NULL))
2156 {
2157 result = EDMA3_RM_E_INVALID_PARAM;
2158 }
2159 #endif
2161 /* Check if the parameters are OK. */
2162 if (EDMA3_RM_SOK == result)
2163 {
2164 chObj = lChObj;
2166 if ((chObj->type == EDMA3_RM_RES_DMA_CHANNEL)
2167 || (chObj->type == EDMA3_RM_RES_QDMA_CHANNEL))
2168 {
2169 /**
2170 * If the request is for a DMA or QDMA channel, check the
2171 * pParam and pTcc objects also.
2172 * For the Link channel request, they could be NULL.
2173 */
2174 /* If parameter checking is enabled... */
2175 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
2176 if ((pParam == NULL) || (pTcc == NULL))
2177 {
2178 result = EDMA3_RM_E_INVALID_PARAM;
2179 }
2180 #endif
2181 }
2182 }
2184 if (result == EDMA3_RM_SOK)
2185 {
2186 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
2188 if (rmInstance == NULL)
2189 {
2190 result = EDMA3_RM_E_INVALID_PARAM;
2191 }
2192 }
2194 if (result == EDMA3_RM_SOK)
2195 {
2196 rmObj = rmInstance->pResMgrObjHandle;
2198 if (rmObj == NULL)
2199 {
2200 result = EDMA3_RM_E_INVALID_PARAM;
2201 }
2202 else
2203 {
2204 if (rmObj->gblCfgParams.globalRegs == NULL)
2205 {
2206 result = EDMA3_RM_E_INVALID_PARAM;
2207 }
2208 }
2209 }
2211 if (result == EDMA3_RM_SOK)
2212 {
2213 edma3Id = rmObj->phyCtrllerInstId;
2214 gblRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
2216 switch (chObj->type)
2217 {
2218 case EDMA3_RM_RES_DMA_CHANNEL:
2219 {
2220 if ((chObj->resId == EDMA3_RM_DMA_CHANNEL_ANY)
2221 || (chObj->resId == EDMA3_RM_RES_ANY))
2222 {
2223 /* Request for ANY DMA channel. */
2224 resObj.type = EDMA3_RM_RES_DMA_CHANNEL;
2225 resObj.resId = EDMA3_RM_RES_ANY;
2226 result = EDMA3_RM_allocResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2228 if (result == EDMA3_RM_SOK)
2229 {
2230 /* DMA channel allocated successfully. */
2231 chObj->resId = resObj.resId;
2233 /**
2234 * Check the PaRAM Set user has specified for this DMA channel.
2235 * Two cases exist:
2236 * a) DCHMAP exists: Any PaRAM Set can be used
2237 * b) DCHMAP does not exist: Should not be possible
2238 * only if the channel allocated (ANY) and PaRAM requested
2239 * are same.
2240 */
2241 if ((*pParam) == EDMA3_RM_PARAM_ANY)
2242 {
2243 /* User specified ANY PaRAM Set; Check the mapping. */
2244 mappedPaRAMId = rmObj->gblCfgParams.dmaChannelPaRAMMap[resObj.resId];
2245 if (mappedPaRAMId != EDMA3_RM_CH_NO_PARAM_MAP)
2246 {
2247 /** If some PaRAM set is statically mapped to the returned
2248 * channel number, use that.
2249 */
2250 paRAMId = (int)mappedPaRAMId;
2251 }
2252 }
2253 else
2254 {
2255 /* User specified some PaRAM Set; check that can be used or not. */
2256 if (TRUE == rmObj->gblCfgParams.dmaChPaRAMMapExists)
2257 {
2258 paRAMId = (int)(*pParam);
2259 }
2260 else
2261 {
2262 /**
2263 * Channel mapping does not exist. If the PaRAM Set requested
2264 * is the same as dma channel allocated (coincidentally), it is fine.
2265 * Else return error.
2266 */
2267 if ((*pParam) != (resObj.resId))
2268 {
2269 result = EDMA3_RM_E_INVALID_PARAM;
2271 /**
2272 * Free the previously allocated DMA channel also.
2273 */
2274 EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2275 }
2276 else
2277 {
2278 paRAMId = (int)(*pParam);
2279 }
2280 }
2281 }
2283 mappedTcc = rmObj->gblCfgParams.dmaChannelTccMap[resObj.resId];
2284 }
2285 }
2286 else
2287 {
2288 if (chObj->resId <= edma3_dma_ch_max_val[edma3Id])
2289 {
2290 /* Request for a specific DMA channel */
2291 resObj.type = EDMA3_RM_RES_DMA_CHANNEL;
2292 resObj.resId = chObj->resId;
2293 result = EDMA3_RM_allocResource(hEdmaResMgr,
2294 (EDMA3_RM_ResDesc *)&resObj);
2296 if (result == EDMA3_RM_SOK)
2297 {
2298 /**
2299 * Check the PaRAM Set user has specified for this DMA channel.
2300 * Two cases exist:
2301 * a) DCHMAP exists: Any PaRAM Set can be used
2302 * b) DCHMAP does not exist: Should not be possible
2303 * only if the channel allocated (ANY) and PaRAM requested
2304 * are same.
2305 */
2306 if ((*pParam) == EDMA3_RM_PARAM_ANY)
2307 {
2308 /* User specified ANY PaRAM Set; Check the mapping. */
2309 mappedPaRAMId = rmObj->gblCfgParams.dmaChannelPaRAMMap[resObj.resId];
2310 if (mappedPaRAMId != EDMA3_RM_CH_NO_PARAM_MAP)
2311 {
2312 /** If some PaRAM set is statically mapped to the returned
2313 * channel number, use that.
2314 */
2315 paRAMId = (int)mappedPaRAMId;
2316 }
2317 }
2318 else
2319 {
2320 /* User specified some PaRAM Set; check that can be used or not. */
2321 if (TRUE == rmObj->gblCfgParams.dmaChPaRAMMapExists)
2322 {
2323 paRAMId = (int)(*pParam);
2324 }
2325 else
2326 {
2327 /**
2328 * Channel mapping does not exist. If the PaRAM Set requested
2329 * is the same as dma channel allocated (coincidentally), it is fine.
2330 * Else return error.
2331 */
2332 if ((*pParam) != (resObj.resId))
2333 {
2334 result = EDMA3_RM_E_INVALID_PARAM;
2336 /**
2337 * Free the previously allocated DMA channel also.
2338 */
2339 EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2340 }
2341 else
2342 {
2343 paRAMId = (int)(*pParam);
2344 }
2345 }
2346 }
2348 mappedTcc = rmObj->gblCfgParams.dmaChannelTccMap[chObj->resId];
2349 }
2350 }
2351 else
2352 {
2353 result = EDMA3_RM_E_INVALID_PARAM;
2354 }
2355 }
2356 }
2357 break;
2360 case EDMA3_RM_RES_QDMA_CHANNEL:
2361 {
2362 if ((chObj->resId == EDMA3_RM_QDMA_CHANNEL_ANY)
2363 || (chObj->resId == EDMA3_RM_RES_ANY))
2364 {
2365 /* First request for any available QDMA channel */
2366 resObj.type = EDMA3_RM_RES_QDMA_CHANNEL;
2367 resObj.resId = EDMA3_RM_RES_ANY;
2368 result = EDMA3_RM_allocResource(hEdmaResMgr,
2369 (EDMA3_RM_ResDesc *)&resObj);
2371 if (result == EDMA3_RM_SOK)
2372 {
2373 /* Return the actual QDMA channel id. */
2374 chObj->resId = resObj.resId;
2376 /* Save the Logical-QDMA channel id for future use. */
2377 qdmaChId = resObj.resId + edma3_qdma_ch_min_val[edma3Id];
2379 /**
2380 * Check the PaRAM Set user has specified for this QDMA channel.
2381 * If he has specified any particular PaRAM Set, use that.
2382 */
2383 if ((*pParam) != EDMA3_RM_PARAM_ANY)
2384 {
2385 /* User specified ANY PaRAM Set; Check the mapping. */
2386 paRAMId = (int)(*pParam);
2387 }
2388 }
2389 }
2390 else
2391 {
2392 if (chObj->resId < rmObj->gblCfgParams.numQdmaChannels)
2393 {
2394 /* Request for a specific QDMA channel */
2395 resObj.type = EDMA3_RM_RES_QDMA_CHANNEL;
2396 resObj.resId = chObj->resId;
2397 result = EDMA3_RM_allocResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2399 if (result == EDMA3_RM_SOK)
2400 {
2401 /* Save the Logical-QDMA channel id for future use. */
2402 qdmaChId = chObj->resId + edma3_qdma_ch_min_val[edma3Id];
2404 /**
2405 * Check the PaRAM Set user has specified for this QDMA channel.
2406 * If he has specified any particular PaRAM Set, use that.
2407 */
2408 if ((*pParam) != EDMA3_RM_PARAM_ANY)
2409 {
2410 /* User specified ANY PaRAM Set; Check the mapping. */
2411 paRAMId = (int)(*pParam);
2412 }
2413 }
2414 }
2415 else
2416 {
2417 result = EDMA3_RM_E_INVALID_PARAM;
2418 }
2419 }
2420 }
2421 break;
2423 case EDMA3_RM_RES_PARAM_SET:
2424 {
2425 /* Request for a LINK channel. */
2426 if ((chObj->resId == EDMA3_RM_PARAM_ANY)
2427 || (chObj->resId == EDMA3_RM_RES_ANY))
2428 {
2429 /* Request for ANY LINK channel. */
2430 paRAMId = (int)EDMA3_RM_RES_ANY;
2431 }
2432 else
2433 {
2434 if (chObj->resId < edma3NumPaRAMSets)
2435 {
2436 /* Request for a Specific LINK channel. */
2437 paRAMId = (int)(chObj->resId);
2438 }
2439 else
2440 {
2441 result = EDMA3_RM_E_INVALID_PARAM;
2442 }
2443 }
2445 if (result == EDMA3_RM_SOK)
2446 {
2447 /* Try to allocate the link channel */
2448 resObj.type = EDMA3_RM_RES_PARAM_SET;
2449 resObj.resId = (unsigned int)paRAMId;
2450 result = EDMA3_RM_allocResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2452 if (result == EDMA3_RM_SOK)
2453 {
2454 unsigned int linkCh = edma3_link_ch_min_val[edma3Id];
2456 /* Return the actual PaRAM Id. */
2457 chObj->resId = resObj.resId;
2459 /*
2460 * Search for the next Link channel place-holder available,
2461 * starting from EDMA3_RM_LINK_CH_MIN_VAL.
2462 * It will be used for future operations on the Link channel.
2463 */
2464 while ((edma3RmChBoundRes[rmObj->phyCtrllerInstId][linkCh].paRAMId != -1)
2465 && (linkCh <= edma3_link_ch_max_val[edma3Id]))
2466 {
2467 /* Move to the next place-holder. */
2468 linkCh++;
2469 }
2471 /* Verify the returned handle, it should lie in the correct range */
2472 if (linkCh > edma3_link_ch_max_val[edma3Id])
2473 {
2474 result = EDMA3_RM_E_INVALID_PARAM;
2476 /* Free the PaRAM Set now. */
2477 resObj.type = EDMA3_RM_RES_PARAM_SET;
2478 resObj.resId = chObj->resId;
2479 result = EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2480 }
2481 else
2482 {
2483 /* Save the PaRAM Id for the Link Channel. */
2484 edma3RmChBoundRes[rmObj->phyCtrllerInstId][linkCh].paRAMId = (int)(chObj->resId);
2486 /**
2487 * Remove any linking. Before doing that, check
2488 * whether it is permitted or not.
2489 */
2490 if (TRUE == rmInstance->regModificationRequired)
2491 {
2492 *((&gblRegs->PARAMENTRY[chObj->resId].OPT)
2493 + (unsigned int)EDMA3_RM_PARAM_ENTRY_LINK_BCNTRLD) = 0xFFFFu;
2494 }
2495 }
2496 }
2497 }
2498 }
2499 break;
2501 default:
2502 result = EDMA3_RM_E_INVALID_PARAM;
2503 }
2504 }
2507 if (result == EDMA3_RM_SOK)
2508 {
2509 /**
2510 * For DMA/QDMA channels, we still have to allocate more resources like
2511 * TCC, PaRAM Set etc.
2512 * For Link channel, only the PaRAMSet is required and that has been
2513 * allocated so no further operations required.
2514 */
2516 /* Further resources' allocation for DMA channel. */
2517 if (chObj->type == EDMA3_RM_RES_DMA_CHANNEL)
2518 {
2519 /* First allocate a PaRAM Set */
2520 resObj.type = EDMA3_RM_RES_PARAM_SET;
2521 /* Use the saved param id now. */
2522 resObj.resId = (unsigned int)paRAMId;
2523 result = EDMA3_RM_allocResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2524 if (result == EDMA3_RM_SOK)
2525 {
2526 /**
2527 * PaRAM Set allocation succeeded.
2528 * Save the PaRAM Set first.
2529 */
2530 *pParam = resObj.resId;
2531 edma3RmChBoundRes[rmObj->phyCtrllerInstId][chObj->resId].paRAMId = (int)(resObj.resId);
2533 /* Allocate the TCC now. */
2534 resObj.type = EDMA3_RM_RES_TCC;
2535 if ((*pTcc) == EDMA3_RM_TCC_ANY)
2536 {
2537 if (mappedTcc == EDMA3_RM_CH_NO_TCC_MAP)
2538 {
2539 resObj.resId = EDMA3_RM_RES_ANY;
2540 }
2541 else
2542 {
2543 resObj.resId = mappedTcc;
2544 }
2545 }
2546 else
2547 {
2548 resObj.resId = *pTcc;
2549 }
2551 result = EDMA3_RM_allocResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2552 if (result == EDMA3_RM_SOK)
2553 {
2554 /* TCC allocation succeeded. Save it first. */
2555 *pTcc = resObj.resId;
2556 edma3RmChBoundRes[rmObj->phyCtrllerInstId][chObj->resId].tcc = resObj.resId;
2558 /**
2559 * Check first whether the global registers and the allocated
2560 * PaRAM Set can be modified or not. If yes, do the needful.
2561 * Else leave this for the user.
2562 */
2563 if (TRUE == rmInstance->regModificationRequired)
2564 {
2565 /* Set TCC of the allocated Param Set. */
2566 gblRegs->PARAMENTRY[*pParam].OPT &= EDMA3_RM_OPT_TCC_CLR_MASK;
2567 gblRegs->PARAMENTRY[*pParam].OPT |= EDMA3_RM_OPT_TCC_SET_MASK(*pTcc);
2569 /**
2570 * Do the mapping between DMA channel and PaRAM Set.
2571 * Do this for the EDMA3 Controllers which have a register for mapping
2572 * DMA Channel to a particular PaRAM Set.
2573 */
2574 if (TRUE == rmObj->gblCfgParams.dmaChPaRAMMapExists)
2575 {
2576 gblRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
2578 /* Map Parameter RAM Set Number for specified channelId */
2579 gblRegs->DCHMAP[chObj->resId] &= EDMA3_RM_DCH_PARAM_CLR_MASK;
2580 gblRegs->DCHMAP[chObj->resId] |= EDMA3_RM_DCH_PARAM_SET_MASK(*pParam);
2581 }
2583 /* Remove any linking */
2584 *((&gblRegs->PARAMENTRY[*pParam].OPT)
2585 + (unsigned int)EDMA3_RM_PARAM_ENTRY_LINK_BCNTRLD) = 0xFFFFu;
2586 }
2587 }
2588 else
2589 {
2590 /**
2591 * TCC allocation failed, free the previously allocated
2592 * PaRAM Set and DMA channel.
2593 */
2594 resObj.type = EDMA3_RM_RES_PARAM_SET;
2595 resObj.resId = *pParam;
2596 EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2598 /* Reset the book-keeping data structure also. */
2599 edma3RmChBoundRes[rmObj->phyCtrllerInstId][chObj->resId].paRAMId = -1;
2601 resObj.type = chObj->type;
2602 resObj.resId = chObj->resId;
2603 EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2604 }
2605 }
2606 else
2607 {
2608 /**
2609 * PaRAM Set allocation failed, free the previously allocated
2610 * DMA channel also.
2611 */
2612 resObj.type = chObj->type;
2613 resObj.resId = chObj->resId;
2614 EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2615 }
2616 }
2619 /* Further resources' allocation for QDMA channel. */
2620 if (chObj->type == EDMA3_RM_RES_QDMA_CHANNEL)
2621 {
2622 /* First allocate a PaRAM Set */
2623 resObj.type = EDMA3_RM_RES_PARAM_SET;
2624 /* Use the saved param id now. */
2625 resObj.resId = (unsigned int)paRAMId;
2626 result = EDMA3_RM_allocResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2627 if (result == EDMA3_RM_SOK)
2628 {
2629 /**
2630 * PaRAM Set allocation succeeded.
2631 * Save the PaRAM Set first.
2632 */
2633 *pParam = resObj.resId;
2634 edma3RmChBoundRes[rmObj->phyCtrllerInstId][qdmaChId].paRAMId = (int)(resObj.resId);
2636 /* Allocate the TCC now. */
2637 resObj.type = EDMA3_RM_RES_TCC;
2638 if ((*pTcc) == EDMA3_RM_TCC_ANY)
2639 {
2640 if (mappedTcc == EDMA3_RM_CH_NO_TCC_MAP)
2641 {
2642 resObj.resId = EDMA3_RM_RES_ANY;
2643 }
2644 else
2645 {
2646 resObj.resId = mappedTcc;
2647 }
2648 }
2649 else
2650 {
2651 resObj.resId = *pTcc;
2652 }
2654 result = EDMA3_RM_allocResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2655 if (result == EDMA3_RM_SOK)
2656 {
2657 /* TCC allocation succeeded. Save it first. */
2658 *pTcc = resObj.resId;
2659 edma3RmChBoundRes[rmObj->phyCtrllerInstId][qdmaChId].tcc = resObj.resId;
2661 /**
2662 * Check first whether the global registers and the allocated
2663 * PaRAM Set can be modified or not. If yes, do the needful.
2664 * Else leave this for the user.
2665 */
2666 if (TRUE == rmInstance->regModificationRequired)
2667 {
2668 /* Set TCC of the allocated Param Set. */
2669 gblRegs->PARAMENTRY[*pParam].OPT &= EDMA3_RM_OPT_TCC_CLR_MASK;
2670 gblRegs->PARAMENTRY[*pParam].OPT |= EDMA3_RM_OPT_TCC_SET_MASK(*pTcc);
2672 /* Do the mapping between QDMA channel and PaRAM Set. */
2673 /* Map Parameter RAM Set Number for specified channelId */
2674 gblRegs->QCHMAP[chObj->resId]
2675 &= EDMA3_RM_QCH_PARAM_CLR_MASK;
2676 gblRegs->QCHMAP[chObj->resId]
2677 |= EDMA3_RM_QCH_PARAM_SET_MASK(*pParam);
2679 /* Set the Trigger Word */
2680 gblRegs->QCHMAP[chObj->resId]
2681 &= EDMA3_RM_QCH_TRWORD_CLR_MASK;
2682 gblRegs->QCHMAP[chObj->resId]
2683 |= EDMA3_RM_QCH_TRWORD_SET_MASK(EDMA3_RM_QDMA_TRIG_DEFAULT);
2685 /* Remove any linking */
2686 *((&gblRegs->PARAMENTRY[*pParam].OPT)
2687 + (unsigned int)EDMA3_RM_PARAM_ENTRY_LINK_BCNTRLD) = 0xFFFFu;
2689 /* Enable the transfer also. */
2690 rmInstance->shadowRegs->QEESR = (1u << chObj->resId);
2691 }
2692 }
2693 else
2694 {
2695 /**
2696 * TCC allocation failed, free the previously allocated
2697 * PaRAM Set and QDMA channel.
2698 */
2699 resObj.type = EDMA3_RM_RES_PARAM_SET;
2700 resObj.resId = *pParam;
2701 EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2703 /* Reset the book-keeping data structure also. */
2704 edma3RmChBoundRes[rmObj->phyCtrllerInstId][qdmaChId].paRAMId = -1;
2706 resObj.type = chObj->type;
2707 resObj.resId = chObj->resId;
2708 EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2709 }
2710 }
2711 else
2712 {
2713 /**
2714 * PaRAM Set allocation failed, free the previously allocated
2715 * QDMA channel also.
2716 */
2717 resObj.type = chObj->type;
2718 resObj.resId = chObj->resId;
2719 EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2720 }
2721 }
2722 }
2725 #ifdef EDMA3_INSTRUMENTATION_ENABLED
2726 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
2727 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
2728 EDMA3_DVT_dCOUNTER,
2729 EDMA3_DVT_dNONE,
2730 EDMA3_DVT_dNONE));
2731 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
2734 return result;
2735 }
2738 /** \fn EDMA3_RM_Result EDMA3_RM_freeLogicalChannel (EDMA3_RM_Handle
2739 * hEdmaResMgr, EDMA3_RM_ResDesc *lChObj)
2740 * \brief This API is used to free the specified channel (DMA/QDMA/Link) and
2741 * its associated resources (PaRAM Set, TCC etc).
2742 *
2743 * This API internally uses EDMA3_RM_freeResource () to free the desired
2744 * resources.
2745 *
2746 * For DMA/QDMA channels, it also clears the DCHMAP/QCHMAP registers
2747 *
2748 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
2749 * Manager Instance.
2750 * \param lChObj [IN] Handle to the logical channel object,
2751 * which needs to be freed
2752 *
2753 * \return EDMA3_RM_SOK or EDMA_RM Error Code
2754 *
2755 * \note This is a re-entrant function which internally calls
2756 * EDMA3_RM_freeResource () for resource de-allocation.
2757 */
2758 EDMA3_RM_Result EDMA3_RM_freeLogicalChannel (EDMA3_RM_Handle hEdmaResMgr,
2759 EDMA3_RM_ResDesc *lChObj)
2760 {
2761 EDMA3_RM_ResDesc *chObj;
2762 EDMA3_RM_ResDesc resObj;
2763 EDMA3_RM_Result result = EDMA3_RM_SOK;
2764 EDMA3_RM_Instance *rmInstance = NULL;
2765 EDMA3_RM_Obj *rmObj = NULL;
2766 int paRAMId;
2767 unsigned int tcc;
2768 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
2769 unsigned int qdmaChId;
2770 unsigned int dmaChId;
2771 EDMA3_RM_InstanceInitConfig *rmConfig = NULL;
2772 unsigned int edma3Id;
2774 #ifdef EDMA3_INSTRUMENTATION_ENABLED
2775 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
2776 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
2777 EDMA3_DVT_dCOUNTER,
2778 EDMA3_DVT_dNONE,
2779 EDMA3_DVT_dNONE));
2780 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
2783 /* If parameter checking is enabled... */
2784 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
2785 if ((lChObj == NULL) || (hEdmaResMgr == NULL))
2786 {
2787 result = (EDMA3_RM_E_INVALID_PARAM);
2788 }
2789 #endif
2791 /* Check if the parameters are OK. */
2792 if (result == EDMA3_RM_SOK)
2793 {
2794 chObj = lChObj;
2796 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
2798 if (rmInstance == NULL)
2799 {
2800 result = EDMA3_RM_E_INVALID_PARAM;
2801 }
2802 }
2804 if (result == EDMA3_RM_SOK)
2805 {
2806 rmConfig = rmInstance->initParam.rmInstInitConfig;
2807 rmObj = rmInstance->pResMgrObjHandle;
2809 if (rmObj == NULL)
2810 {
2811 result = EDMA3_RM_E_INVALID_PARAM;
2812 }
2813 else
2814 {
2815 if (rmObj->gblCfgParams.globalRegs == NULL)
2816 {
2817 result = EDMA3_RM_E_INVALID_PARAM;
2818 }
2819 else
2820 {
2821 edma3Id = rmObj->phyCtrllerInstId;
2822 globalRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
2823 }
2824 }
2825 }
2828 if (result == EDMA3_RM_SOK)
2829 {
2830 switch (chObj->type)
2831 {
2832 case EDMA3_RM_RES_DMA_CHANNEL:
2833 {
2834 /* Save the DMA channel first. */
2835 dmaChId = chObj->resId;
2837 /**
2838 * Validate DMA channel id first.
2839 * It should be a valid channel id.
2840 */
2841 if (dmaChId >= EDMA3_MAX_DMA_CH)
2842 {
2843 result = EDMA3_RM_E_INVALID_PARAM;
2844 }
2846 /* It should be owned and allocated by this RM only. */
2847 if (result == EDMA3_RM_SOK)
2848 {
2849 if (((rmConfig->ownDmaChannels[dmaChId/32u])
2850 &
2851 (~(rmInstance->avlblDmaChannels[dmaChId/32u]))
2852 &
2853 (1u << (dmaChId%32u))) != FALSE)
2854 {
2855 /** Perfectly valid channel id.
2856 * Clear some channel specific registers, if it is permitted.
2857 */
2858 if (TRUE == rmInstance->regModificationRequired)
2859 {
2860 if (dmaChId < 32u)
2861 {
2862 if((rmInstance->shadowRegs->SER & (1u<<dmaChId))!=FALSE)
2863 {
2864 rmInstance->shadowRegs->SECR = (1u<<dmaChId);
2865 }
2866 if((globalRegs->EMR & (1u<<dmaChId))!=FALSE)
2867 {
2868 globalRegs->EMCR = (1u<<dmaChId);
2869 }
2870 }
2871 else
2872 {
2873 if((rmInstance->shadowRegs->SERH & (1u<<(dmaChId-32u)))!=FALSE)
2874 {
2875 rmInstance->shadowRegs->SECRH = (1u<<(dmaChId-32u));
2876 }
2877 if((globalRegs->EMRH & (1u<<(dmaChId-32u)))!=FALSE)
2878 {
2879 globalRegs->EMCRH = (1u<<(dmaChId-32u));
2880 }
2881 }
2883 /* Clear DCHMAP register also. */
2884 if (TRUE == rmObj->gblCfgParams.dmaChPaRAMMapExists)
2885 {
2886 globalRegs->DCHMAP[dmaChId] &=
2887 EDMA3_RM_DCH_PARAM_CLR_MASK;
2888 }
2889 }
2891 /* Free the PaRAM Set Now. */
2892 paRAMId = edma3RmChBoundRes[rmObj->phyCtrllerInstId][dmaChId].paRAMId;
2893 resObj.type = EDMA3_RM_RES_PARAM_SET;
2894 resObj.resId = (unsigned int)paRAMId;
2895 result = EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2896 }
2897 else
2898 {
2899 /* Channel id has some problem. */
2900 result = EDMA3_RM_E_INVALID_PARAM;
2901 }
2902 }
2905 if (result == EDMA3_RM_SOK)
2906 {
2907 /* PaRAM Set Freed */
2908 edma3RmChBoundRes[rmObj->phyCtrllerInstId][dmaChId].paRAMId = -1;
2910 /* Free the TCC */
2911 tcc = edma3RmChBoundRes[rmObj->phyCtrllerInstId][dmaChId].tcc;
2912 resObj.type = EDMA3_RM_RES_TCC;
2913 resObj.resId = tcc;
2914 result = EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2915 }
2917 if (result == EDMA3_RM_SOK)
2918 {
2919 /* TCC Freed */
2920 edma3RmChBoundRes[rmObj->phyCtrllerInstId][dmaChId].tcc = EDMA3_MAX_TCC;
2922 /**
2923 * Try to free the DMA Channel now. DMA Channel should
2924 * be freed only in the end because while freeing, DRAE
2925 * registers will be RESET.
2926 * After that, no shadow region specific DMA channel
2927 * register can be modified. So reset that DRAE register
2928 * ONLY in the end.
2929 */
2930 resObj.type = EDMA3_RM_RES_DMA_CHANNEL;
2931 resObj.resId = dmaChId;
2932 result = EDMA3_RM_freeResource(hEdmaResMgr,
2933 (EDMA3_RM_ResDesc *)&resObj);
2934 }
2935 }
2936 break;
2939 case EDMA3_RM_RES_QDMA_CHANNEL:
2940 {
2941 /**
2942 * Calculate QDMA Logical Channel Id first.
2943 * User has given the actual QDMA channel id.
2944 * So we have to convert it to make the logical
2945 * QDMA channel id first.
2946 */
2947 qdmaChId = chObj->resId + edma3_qdma_ch_min_val[edma3Id];
2949 /**
2950 * Validate QDMA channel id first.
2951 * It should be a valid channel id.
2952 */
2953 if (chObj->resId >= EDMA3_MAX_QDMA_CH)
2954 {
2955 result = EDMA3_RM_E_INVALID_PARAM;
2956 }
2958 /* It should be owned and allocated by this RM only. */
2959 if (result == EDMA3_RM_SOK)
2960 {
2961 if (((rmConfig->ownQdmaChannels[0u])
2962 &
2963 (~(rmInstance->avlblQdmaChannels[0u]))
2964 &
2965 (1u << chObj->resId)) != FALSE)
2966 {
2967 /** Perfectly valid channel id.
2968 * Clear some channel specific registers, if
2969 * it is permitted.
2970 */
2971 if (TRUE == rmInstance->regModificationRequired)
2972 {
2973 rmInstance->shadowRegs->QEECR = (1u<<chObj->resId);
2975 if((globalRegs->QEMR & (1u<<chObj->resId))!=FALSE)
2976 {
2977 globalRegs->QEMCR = (1u<<chObj->resId);
2978 }
2980 /* Unmap PARAM Set Number for specified channelId */
2981 globalRegs->QCHMAP[chObj->resId] &=
2982 EDMA3_RM_QCH_PARAM_CLR_MASK;
2984 /* Reset the Trigger Word */
2985 globalRegs->QCHMAP[chObj->resId] &=
2986 EDMA3_RM_QCH_TRWORD_CLR_MASK;
2987 }
2989 /* Free the PaRAM Set now */
2990 paRAMId = edma3RmChBoundRes[rmObj->phyCtrllerInstId][qdmaChId].paRAMId;
2991 resObj.type = EDMA3_RM_RES_PARAM_SET;
2992 resObj.resId = (int)paRAMId;
2993 result = EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
2994 }
2995 else
2996 {
2997 /* Channel id has some problem. */
2998 result = EDMA3_RM_E_INVALID_PARAM;
2999 }
3000 }
3003 if (result == EDMA3_RM_SOK)
3004 {
3005 /* PaRAM Set Freed */
3006 edma3RmChBoundRes[rmObj->phyCtrllerInstId][qdmaChId].paRAMId = -1;
3008 /* Free the TCC */
3009 tcc = edma3RmChBoundRes[rmObj->phyCtrllerInstId][qdmaChId].tcc;
3010 resObj.type = EDMA3_RM_RES_TCC;
3011 resObj.resId = tcc;
3012 result = EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
3013 }
3015 if (result == EDMA3_RM_SOK)
3016 {
3017 /* TCC Freed */
3018 edma3RmChBoundRes[rmObj->phyCtrllerInstId][qdmaChId].tcc = EDMA3_MAX_TCC;
3020 /**
3021 * Try to free the QDMA Channel now. QDMA Channel should
3022 * be freed only in the end because while freeing, QRAE
3023 * registers will be RESET.
3024 * After that, no shadow region specific QDMA channel
3025 * register can be modified. So reset that QDRAE register
3026 * ONLY in the end.
3027 */
3028 resObj.type = EDMA3_RM_RES_QDMA_CHANNEL;
3029 resObj.resId = chObj->resId;
3030 result = EDMA3_RM_freeResource(hEdmaResMgr,
3031 (EDMA3_RM_ResDesc *)&resObj);
3032 }
3033 }
3034 break;
3037 case EDMA3_RM_RES_PARAM_SET:
3038 {
3039 /* Link Channel */
3040 if (chObj->resId < edma3NumPaRAMSets)
3041 {
3042 resObj.type = EDMA3_RM_RES_PARAM_SET;
3043 resObj.resId = chObj->resId;
3045 result = EDMA3_RM_freeResource(hEdmaResMgr, (EDMA3_RM_ResDesc *)&resObj);
3046 if (result == EDMA3_RM_SOK)
3047 {
3048 /* PaRAM Set freed successfully. */
3049 unsigned int linkCh = edma3_link_ch_min_val[edma3Id];
3051 /* Reset the Logical-Link channel */
3052 /* Search for the Logical-Link channel first */
3053 for (linkCh = edma3_link_ch_min_val[edma3Id];
3054 linkCh < edma3_link_ch_max_val[edma3Id];
3055 linkCh++)
3056 {
3057 if (edma3RmChBoundRes[rmObj->phyCtrllerInstId][linkCh].paRAMId == chObj->resId)
3058 {
3059 edma3RmChBoundRes[rmObj->phyCtrllerInstId][linkCh].paRAMId = -1;
3060 break;
3061 }
3062 }
3063 }
3064 }
3065 else
3066 {
3067 result = EDMA3_RM_E_INVALID_PARAM;
3068 }
3069 }
3070 break;
3072 default:
3073 result = EDMA3_RM_E_INVALID_PARAM;
3074 }
3075 }
3078 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3079 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3080 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
3081 EDMA3_DVT_dCOUNTER,
3082 EDMA3_DVT_dNONE,
3083 EDMA3_DVT_dNONE));
3084 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3086 return result;
3087 }
3091 /**\fn EDMA3_RM_Result EDMA3_RM_mapEdmaChannel (EDMA3_RM_Handle
3092 * hEdmaResMgr, unsigned int channelId, unsigned int paRAMId)
3093 * \brief Bind the resources DMA Channel and PaRAM Set. Both the DMA channel
3094 * and the PaRAM set should be previously allocated. If they are not,
3095 * this API will result in error.
3096 *
3097 * This API sets the DCHMAP register for a specific DMA channel. This register
3098 * is used to specify the PaRAM Set associated with that particular DMA Channel.
3099 *
3100 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
3101 * Manager Instance.
3102 * \param channelId [IN] Previously allocated DMA Channel on which
3103 * Transfer will occur.
3104 * \param paRAMId [IN] Previously allocated PaRAM Set which
3105 * needs to be associated with the dma channel.
3106 *
3107 * \return EDMA3_RM_SOK or EDMA_RM Error Code
3108 *
3109 * \note This API is useful only for the EDMA3 Controllers which have a
3110 * register for mapping a DMA Channel to a particular PaRAM Set
3111 * (DCHMAP register).
3112 * On platforms where this feature is not supported, this API
3113 * returns error code: EDMA3_RM_E_FEATURE_UNSUPPORTED.
3114 * This function is re-entrant for unique channelId. It is
3115 * non-re-entrant for same channelId values.
3116 */
3117 EDMA3_RM_Result EDMA3_RM_mapEdmaChannel (EDMA3_RM_Handle hEdmaResMgr,
3118 unsigned int channelId,
3119 unsigned int paRAMId)
3120 {
3121 EDMA3_RM_Instance *rmInstance = NULL;
3122 EDMA3_RM_Obj *rmObj = NULL;
3123 EDMA3_RM_Result result = EDMA3_RM_SOK;
3124 volatile EDMA3_CCRL_Regs *gblRegs = NULL;
3126 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3127 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3128 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
3129 EDMA3_DVT_dCOUNTER,
3130 EDMA3_DVT_dNONE,
3131 EDMA3_DVT_dNONE));
3132 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3134 /* If parameter checking is enabled... */
3135 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
3136 if (hEdmaResMgr == NULL)
3137 {
3138 result = EDMA3_RM_E_INVALID_PARAM;
3139 }
3140 #endif
3142 if (result == EDMA3_RM_SOK)
3143 {
3144 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
3146 if (rmInstance == NULL)
3147 {
3148 result = EDMA3_RM_E_INVALID_PARAM;
3149 }
3150 }
3152 if (result == EDMA3_RM_SOK)
3153 {
3154 rmObj = rmInstance->pResMgrObjHandle;
3156 if (rmObj == NULL)
3157 {
3158 result = EDMA3_RM_E_INVALID_PARAM;
3159 }
3160 else
3161 {
3162 if (rmObj->gblCfgParams.globalRegs == NULL)
3163 {
3164 result = EDMA3_RM_E_INVALID_PARAM;
3165 }
3166 }
3167 }
3169 if (result == EDMA3_RM_SOK)
3170 {
3171 gblRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
3173 /* If parameter checking is enabled... */
3174 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
3175 if ((paRAMId >= rmObj->gblCfgParams.numPaRAMSets)
3176 || (channelId >= rmObj->gblCfgParams.numDmaChannels))
3177 {
3178 result = EDMA3_RM_E_INVALID_PARAM;
3179 }
3180 #endif
3181 }
3183 /* DMA channel and PaRAM Set should be previously allocated. */
3184 if (result == EDMA3_RM_SOK)
3185 {
3186 if (((rmInstance->initParam.rmInstInitConfig->ownDmaChannels[channelId/32u])
3187 &
3188 (~(rmInstance->avlblDmaChannels[channelId/32u]))
3189 &
3190 (1u << (channelId%32u))) != FALSE)
3191 {
3192 /* DMA channel allocated, check for the PaRAM Set */
3193 if (((rmInstance->initParam.rmInstInitConfig->ownPaRAMSets[paRAMId/32u])
3194 &
3195 (~(rmInstance->avlblPaRAMSets[paRAMId/32u]))
3196 &
3197 (1u << (paRAMId%32u))) == FALSE)
3198 {
3199 /* PaRAM Set NOT allocated, return error */
3200 result = EDMA3_RM_E_RES_NOT_ALLOCATED;
3201 }
3202 }
3203 else
3204 {
3205 /* DMA channel NOT allocated, return error */
3206 result = EDMA3_RM_E_RES_NOT_ALLOCATED;
3207 }
3208 }
3211 if (result == EDMA3_RM_SOK)
3212 {
3213 /* Map the Dma Channel to the PaRAM Set corresponding to paramId */
3214 /**
3215 * Do this for the EDMA3 Controllers which have a register for mapping
3216 * DMA Channel to a particular PaRAM Set. So check
3217 * dmaChPaRAMMapExists first.
3218 */
3219 if (TRUE == rmObj->gblCfgParams.dmaChPaRAMMapExists)
3220 {
3221 /* Map Parameter RAM Set Number for specified channelId */
3222 gblRegs->DCHMAP[channelId] &= EDMA3_RM_DCH_PARAM_CLR_MASK;
3223 gblRegs->DCHMAP[channelId] |= EDMA3_RM_DCH_PARAM_SET_MASK(paRAMId);
3224 }
3225 else
3226 {
3227 /* Feature NOT supported on the current platform, return error. */
3228 result = EDMA3_RM_E_FEATURE_UNSUPPORTED;
3229 }
3230 }
3232 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3233 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3234 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
3235 EDMA3_DVT_dCOUNTER,
3236 EDMA3_DVT_dNONE,
3237 EDMA3_DVT_dNONE));
3238 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3240 return result;
3241 }
3246 /**\fn EDMA3_RM_Result EDMA3_RM_mapQdmaChannel (EDMA3_RM_Handle
3247 * hEdmaResMgr, unsigned int channelId,
3248 * unsigned int paRAMId,
3249 * EDMA3_RM_QdmaTrigWord trigWord)
3250 * \brief Bind the resources QDMA Channel and PaRAM Set. Also, Set the
3251 * trigger word for the QDMA channel. Both the QDMA channel and the PaRAM set
3252 * should be previously allocated. If they are not, this API will result in error.
3253 *
3254 * This API sets the QCHMAP register for a specific QDMA channel. This register
3255 * is used to specify the PaRAM Set associated with that particular QDMA
3256 * Channel along with the trigger word.
3257 *
3258 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
3259 * Manager Instance.
3260 * \param channelId [IN] Previously allocated QDMA Channel on which
3261 * Transfer will occur.
3262 * \param paRAMId [IN] Previously allocated PaRAM Set, which needs to
3263 * be associated with channelId
3264 * \param trigWord [IN] The Trigger Word for the channel.
3265 * Trigger Word is the word in the PaRAM
3266 * Register Set which - when written to by CPU
3267 * -will start the QDMA transfer automatically
3268 *
3269 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
3270 *
3271 * \note This function is re-entrant for unique channelId. It is non-re-entrant
3272 * for same channelId values.
3273 */
3274 EDMA3_RM_Result EDMA3_RM_mapQdmaChannel (EDMA3_RM_Handle hEdmaResMgr,
3275 unsigned int channelId,
3276 unsigned int paRAMId,
3277 EDMA3_RM_QdmaTrigWord trigWord)
3278 {
3279 EDMA3_RM_Instance *rmInstance = NULL;
3280 EDMA3_RM_Obj *rmObj = NULL;
3281 EDMA3_RM_Result result = EDMA3_RM_SOK;
3282 volatile EDMA3_CCRL_Regs *gblRegs = NULL;
3284 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3285 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3286 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
3287 EDMA3_DVT_dCOUNTER,
3288 EDMA3_DVT_dNONE,
3289 EDMA3_DVT_dNONE));
3290 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3292 /* If parameter checking is enabled... */
3293 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
3294 if ((hEdmaResMgr == NULL)
3295 || ((trigWord < EDMA3_RM_QDMA_TRIG_OPT)
3296 || (trigWord > EDMA3_RM_QDMA_TRIG_CCNT)))
3297 {
3298 result = EDMA3_RM_E_INVALID_PARAM;
3299 }
3300 #endif
3302 if (result == EDMA3_RM_SOK)
3303 {
3304 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
3306 if (rmInstance == NULL)
3307 {
3308 result = EDMA3_RM_E_INVALID_PARAM;
3309 }
3310 }
3312 if (result == EDMA3_RM_SOK)
3313 {
3314 rmObj = rmInstance->pResMgrObjHandle;
3316 if (rmObj == NULL)
3317 {
3318 result = EDMA3_RM_E_INVALID_PARAM;
3319 }
3320 else
3321 {
3322 if (rmObj->gblCfgParams.globalRegs == NULL)
3323 {
3324 result = EDMA3_RM_E_INVALID_PARAM;
3325 }
3326 }
3327 }
3329 if (result == EDMA3_RM_SOK)
3330 {
3331 gblRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
3333 /* If parameter checking is enabled... */
3334 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
3335 if ((paRAMId >= rmObj->gblCfgParams.numPaRAMSets)
3336 || (channelId >= rmObj->gblCfgParams.numQdmaChannels))
3337 {
3338 result = EDMA3_RM_E_INVALID_PARAM;
3339 }
3340 #endif
3341 }
3343 /* QDMA channel and PaRAM Set should be previously allocated. */
3344 if (result == EDMA3_RM_SOK)
3345 {
3346 if (((rmInstance->initParam.rmInstInitConfig->ownQdmaChannels[channelId/32u])
3347 &
3348 (~(rmInstance->avlblQdmaChannels[channelId/32u]))
3349 &
3350 (1u << (channelId%32u))) != FALSE)
3351 {
3352 /* QDMA channel allocated, check for the PaRAM Set */
3353 if (((rmInstance->initParam.rmInstInitConfig->ownPaRAMSets[paRAMId/32u])
3354 &
3355 (~(rmInstance->avlblPaRAMSets[paRAMId/32u]))
3356 &
3357 (1u << (paRAMId%32u))) == FALSE)
3358 {
3359 /* PaRAM Set NOT allocated, return error */
3360 result = EDMA3_RM_E_RES_NOT_ALLOCATED;
3361 }
3362 }
3363 else
3364 {
3365 /* QDMA channel NOT allocated, return error */
3366 result = EDMA3_RM_E_RES_NOT_ALLOCATED;
3367 }
3368 }
3370 if (result == EDMA3_RM_SOK)
3371 {
3372 /* Map Parameter RAM Set Number for specified channelId */
3373 gblRegs->QCHMAP[channelId] &= EDMA3_RM_QCH_PARAM_CLR_MASK;
3374 gblRegs->QCHMAP[channelId] |= EDMA3_RM_QCH_PARAM_SET_MASK(paRAMId);
3376 /* Set the Trigger Word */
3377 gblRegs->QCHMAP[channelId] &= EDMA3_RM_QCH_TRWORD_CLR_MASK;
3378 gblRegs->QCHMAP[channelId] |= EDMA3_RM_QCH_TRWORD_SET_MASK(trigWord);
3379 }
3382 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3383 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3384 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
3385 EDMA3_DVT_dCOUNTER,
3386 EDMA3_DVT_dNONE,
3387 EDMA3_DVT_dNONE));
3388 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3390 return result;
3391 }
3395 /**
3396 * \fn EDMA3_RM_Result EDMA3_RM_registerTccCb(EDMA3_RM_Handle hEdmaResMgr,
3397 * const EDMA3_RM_ResDesc *channelObj, unsigned int tcc,
3398 * EDMA3_RM_TccCallback tccCb, void *cbData);
3399 * \brief Register Interrupt / Completion Handler for a given TCC.
3400 *
3401 * This function enables the interrupts in IESR/IESRH, only if the callback
3402 * function provided by the user is NON-NULL. Moreover, if a call-back function
3403 * is already registered against that TCC, the API fails with the error code
3404 * EDMA3_RM_E_CALLBACK_ALREADY_REGISTERED. For a NULL callback function,
3405 * this API returns error.
3406 *
3407 * \param hEdmaResMgr [IN] Handle to the previously opened
3408 * EDMA3 Resource Manager Instance
3409 * \param channelObj [IN] Channel ID and type (DMA or QDMA
3410 * Channel), allocated earlier, and
3411 * corresponding to which a callback
3412 * function needs to be registered
3413 * against the associated TCC.
3414 * \param tcc [IN] TCC against which the handler needs to
3415 * be registered.
3416 * \param tccCb [IN] The Callback function to be registered
3417 * against the TCC.
3418 * \param cbData [IN] Callback data to be passed while calling
3419 * the callback function.
3420 *
3421 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
3422 *
3423 * \note This function is re-entrant for unique tcc values. It is non-
3424 * re-entrant for same tcc value.
3425 */
3426 EDMA3_RM_Result EDMA3_RM_registerTccCb(EDMA3_RM_Handle hEdmaResMgr,
3427 const EDMA3_RM_ResDesc *channelObj,
3428 unsigned int tcc,
3429 EDMA3_RM_TccCallback tccCb,
3430 void *cbData)
3431 {
3432 EDMA3_RM_Instance *rmInstance = NULL;
3433 EDMA3_RM_Obj *rmObj = NULL;
3434 EDMA3_RM_Result result = EDMA3_RM_SOK;
3436 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3437 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3438 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
3439 EDMA3_DVT_dCOUNTER,
3440 EDMA3_DVT_dNONE,
3441 EDMA3_DVT_dNONE));
3442 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3444 /* If parameter checking is enabled... */
3445 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
3446 if ((NULL == hEdmaResMgr) || (NULL == channelObj))
3447 {
3448 result = EDMA3_RM_E_INVALID_PARAM;
3449 }
3451 /* Callback function should NOT be NULL */
3452 if (NULL == tccCb)
3453 {
3454 result = EDMA3_RM_E_INVALID_PARAM;
3455 }
3456 #endif
3458 if (result == EDMA3_RM_SOK)
3459 {
3460 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
3461 rmObj = rmInstance->pResMgrObjHandle;
3463 if (rmObj == NULL)
3464 {
3465 result = EDMA3_RM_E_INVALID_PARAM;
3466 }
3468 /* If parameter checking is enabled... */
3469 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
3470 if ((EDMA3_RM_SOK == result) && (tcc >= rmObj->gblCfgParams.numTccs))
3471 {
3472 result = EDMA3_RM_E_INVALID_PARAM;
3473 }
3474 #endif
3476 /* Check if the parameters are OK. */
3477 if (EDMA3_RM_SOK == result)
3478 {
3479 /* Check whether the callback has already registered. */
3480 if (NULL != edma3IntrParams[tcc].tccCb)
3481 {
3482 result = EDMA3_RM_E_CALLBACK_ALREADY_REGISTERED;
3483 }
3484 else
3485 {
3486 /* Store the mapping b/w DMA/QDMA channel and TCC first. */
3487 if (channelObj->type == EDMA3_RM_RES_DMA_CHANNEL)
3488 {
3489 /* DMA channel */
3490 if (channelObj->resId < rmObj->gblCfgParams.numDmaChannels)
3491 {
3492 /* Save the TCC */
3493 edma3DmaChTccMapping[channelObj->resId] = tcc;
3494 }
3495 else
3496 {
3497 /* Error!!! */
3498 result = EDMA3_RM_E_INVALID_PARAM;
3499 }
3500 }
3501 else
3502 {
3503 if (channelObj->type == EDMA3_RM_RES_QDMA_CHANNEL)
3504 {
3505 /* QDMA channel */
3506 if (channelObj->resId < rmObj->gblCfgParams.numQdmaChannels)
3507 {
3508 /* Save the TCC */
3509 edma3QdmaChTccMapping[channelObj->resId] = tcc;
3510 }
3511 else
3512 {
3513 /* Error!!! */
3514 result = EDMA3_RM_E_INVALID_PARAM;
3515 }
3516 }
3517 else
3518 {
3519 /* Error!!! */
3520 result = EDMA3_RM_E_INVALID_PARAM;
3521 }
3522 }
3523 }
3525 if (EDMA3_RM_SOK == result)
3526 {
3527 /**
3528 * Enable the interrupts in IESR/IESRH, only if the Callback
3529 * function is NOT NULL.
3530 */
3531 if (tcc < 32u)
3532 {
3533 rmInstance->shadowRegs->IESR = (1UL << tcc);
3534 }
3535 else
3536 {
3537 rmInstance->shadowRegs->IESRH = (1UL << (tcc-32u));
3538 }
3540 /* Save the callback functions also */
3541 edma3IntrParams[tcc].cbData = cbData;
3542 edma3IntrParams[tcc].tccCb = tccCb;
3543 }
3544 }
3545 }
3547 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3548 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3549 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
3550 EDMA3_DVT_dCOUNTER,
3551 EDMA3_DVT_dNONE,
3552 EDMA3_DVT_dNONE));
3553 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3555 return result;
3556 }
3558 /**
3559 * \fn EDMA3_RM_Result EDMA3_RM_unregisterTccCb(EDMA3_RM_Handle
3560 * hEdmaResMgr, const EDMA3_RM_ResDesc *channelObj);
3561 * \brief Unregister the previously registered callback function against a
3562 * DMA/QDMA channel.
3563 *
3564 * This function unregisters the previously registered callback function against
3565 * a DMA/QDMA channel by removing any stored callback function. Moreover, it
3566 * clears the interrupt enable register (IESR/IESRH) by writing to the IECR/
3567 * IECRH register, for the TCC associated with that particular channel.
3568 *
3569 * \param hEdmaResMgr [IN] Handle to the previously opened
3570 * EDMA3 Resource Manager Instance
3571 * \param channelObj [IN] Channel ID and type, allocated earlier
3572 * (DMA or QDMA Channel ONLY), and
3573 * corresponding to which a TCC is there.
3574 * Against that TCC, the callback needs
3575 * to be un-registered.
3576 *
3577 * \return EDMA3_RM_SOK or EDMA3_RM Error Code.
3578 *
3579 * \note This function is re-entrant for unique (channelObj->type +
3580 * channelObj->resId) combination. It is non-re-entrant for same
3581 * channelObj Resource.
3582 */
3583 EDMA3_RM_Result EDMA3_RM_unregisterTccCb(EDMA3_RM_Handle hEdmaResMgr,
3584 const EDMA3_RM_ResDesc *channelObj)
3585 {
3586 EDMA3_RM_Instance *rmInstance = NULL;
3587 EDMA3_RM_Obj *rmObj = NULL;
3588 EDMA3_RM_Result result = EDMA3_RM_SOK;
3589 unsigned int mappedTcc = EDMA3_MAX_TCC;
3591 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3592 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3593 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
3594 EDMA3_DVT_dCOUNTER,
3595 EDMA3_DVT_dNONE,
3596 EDMA3_DVT_dNONE));
3597 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3599 /* If parameter checking is enabled... */
3600 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
3601 if ((NULL == hEdmaResMgr) || (NULL == channelObj))
3602 {
3603 result = EDMA3_RM_E_INVALID_PARAM;
3604 }
3605 #endif
3607 /* Check if the parameters are OK. */
3608 if (EDMA3_RM_SOK == result)
3609 {
3610 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
3611 rmObj = rmInstance->pResMgrObjHandle;
3613 if (rmObj == NULL)
3614 {
3615 result = EDMA3_RM_E_INVALID_PARAM;
3616 }
3617 else
3618 {
3619 if (channelObj->type == EDMA3_RM_RES_DMA_CHANNEL)
3620 {
3621 /* DMA channel */
3622 if (channelObj->resId < rmObj->gblCfgParams.numDmaChannels)
3623 {
3624 /* Save the mapped TCC */
3625 mappedTcc = edma3DmaChTccMapping[channelObj->resId];
3627 /* Remove the mapping now. */
3628 edma3DmaChTccMapping[channelObj->resId] = EDMA3_MAX_TCC;
3629 }
3630 else
3631 {
3632 /* Error!!! */
3633 result = EDMA3_RM_E_INVALID_PARAM;
3634 }
3635 }
3636 else
3637 {
3638 if (channelObj->type == EDMA3_RM_RES_QDMA_CHANNEL)
3639 {
3640 /* QDMA channel */
3641 if (channelObj->resId < rmObj->gblCfgParams.numQdmaChannels)
3642 {
3643 /* Save the mapped TCC */
3644 mappedTcc = edma3QdmaChTccMapping[channelObj->resId];
3646 /* Remove the mapping now. */
3647 edma3QdmaChTccMapping[channelObj->resId] = EDMA3_MAX_TCC;
3648 }
3649 else
3650 {
3651 /* Error!!! */
3652 result = EDMA3_RM_E_INVALID_PARAM;
3653 }
3654 }
3655 else
3656 {
3657 /* Error!!! */
3658 result = EDMA3_RM_E_INVALID_PARAM;
3659 }
3660 }
3662 if (EDMA3_RM_SOK == result)
3663 {
3664 /* Remove the callback function too */
3665 if (mappedTcc < 32u)
3666 {
3667 rmInstance->shadowRegs->IECR = (1UL << mappedTcc);
3668 }
3669 else
3670 {
3671 rmInstance->shadowRegs->IECRH = (1UL << (mappedTcc-32u));
3672 }
3674 edma3IntrParams[mappedTcc].cbData = NULL;
3675 edma3IntrParams[mappedTcc].tccCb = NULL;
3676 }
3677 }
3678 }
3680 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3681 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3682 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
3683 EDMA3_DVT_dCOUNTER,
3684 EDMA3_DVT_dNONE,
3685 EDMA3_DVT_dNONE));
3686 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3688 return result;
3689 }
3692 /**\fn EDMA3_RM_Result EDMA3_RM_allocContiguousResource(EDMA3_RM_Handle
3693 * hEdmaResMgr, EDMA3_RM_ResDesc *firstResIdObj,
3694 * unsigned int numResources)
3695 * \brief Allocate a contiguous region of specified EDMA3 Resource
3696 * like DMA channel, QDMA channel, PaRAM Set or TCC.
3697 *
3698 * This API is used to allocate a contiguous region of specified EDMA3
3699 * Resources like DMA channel, QDMA channel, PaRAM Set or TCC.
3700 *
3701 * User can specify a particular resource Id to start with and go up to the
3702 * number of resources requested. The specific resource id to start from could
3703 * be passed in 'firstResIdObject->resId' and the number of resources requested
3704 * in 'numResources'.
3705 *
3706 * User can also request ANY available resource(s) of the type
3707 * 'firstResIdObject->type' by specifying 'firstResIdObject->resId' as
3708 * EDMA3_RM_RES_ANY.
3709 *
3710 * ANY types of resources are those resources when user doesn't care about the
3711 * actual resource allocated; user just wants a resource of the type specified.
3712 * One use-case is to perform memory-to-memory data transfer operation. This
3713 * operation can be performed using any available DMA or QDMA channel. User
3714 * doesn't need any specific channel for the same.
3715 *
3716 * To allocate specific contiguous resources, first this API checks whether
3717 * those requested resources are OWNED by the Resource Manager instance. Then
3718 * it checks the current availability of those resources.
3719 *
3720 * To allocate ANY available contiguous resources, this API tries to allocate
3721 * resources from the pool of (owned && non_reserved && available_right_now)
3722 * resources.
3723 *
3724 * After allocating DMA/QDMA channels or TCCs, the same resources are enabled in
3725 * the shadow region specific register (DRAE/DRAEH/QRAE). Allocated PaRAM Sets
3726 * are initialized to NULL before this API returns.
3727 *
3728 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
3729 * Manager Instance.
3730 * \param firstResIdObj [IN] Handle to the first resource descriptor
3731 * object, which needs to be allocated.
3732 * firstResIdObject->resId could be a valid
3733 * resource id in case user wants to
3734 * allocate specific resources OR it could
3735 * be EDMA3_RM_RES_ANY in case user wants
3736 * only the required number of resources
3737 * and doesn't care about which resources
3738 * were allocated.
3739 * \param numResources [IN] Number of contiguous resources user
3740 * wants to allocate.
3741 *
3742 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
3743 *
3744 * \note This function acquires a RM Instance specific semaphore
3745 * to prevent simultaneous access to the global pool of resources.
3746 * It is re-entrant, but should not be called from the user callback
3747 * function (ISR context).
3748 */
3749 EDMA3_RM_Result EDMA3_RM_allocContiguousResource(EDMA3_RM_Handle hEdmaResMgr,
3750 EDMA3_RM_ResDesc *firstResIdObj,
3751 unsigned int numResources)
3752 {
3753 EDMA3_RM_Instance *rmInstance = NULL;
3754 EDMA3_RM_Obj *rmObj = NULL;
3755 EDMA3_RM_Result result = EDMA3_RM_SOK;
3756 EDMA3_RM_ResDesc *resObj = NULL;
3757 unsigned int resAllocIdx = 0u;
3758 unsigned int firstResId;
3759 unsigned int lastResId = 0u;
3760 unsigned int maxNumResources = 0u;
3761 EDMA3_RM_Result semResult = EDMA3_RM_SOK;
3762 unsigned int resIdClr = 0x0;
3763 unsigned int resIdSet = 0x0;
3764 volatile EDMA3_CCRL_Regs *gblRegs = NULL;
3765 unsigned int i = 0u;
3766 unsigned int position = 0u;
3767 unsigned int edma3Id;
3769 #ifdef EDMA3_INSTRUMENTATION_ENABLED
3770 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
3771 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
3772 EDMA3_DVT_dCOUNTER,
3773 EDMA3_DVT_dNONE,
3774 EDMA3_DVT_dNONE));
3775 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
3778 /* If parameter checking is enabled... */
3779 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
3780 if ((hEdmaResMgr == NULL) || (firstResIdObj == NULL))
3781 {
3782 result = EDMA3_RM_E_INVALID_PARAM;
3783 }
3784 #endif
3786 if (EDMA3_RM_SOK == result)
3787 {
3788 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
3789 if (rmInstance == NULL)
3790 {
3791 result = EDMA3_RM_E_INVALID_PARAM;
3792 }
3793 }
3795 if (EDMA3_RM_SOK == result)
3796 {
3797 rmObj = rmInstance->pResMgrObjHandle;
3799 if (rmObj == NULL)
3800 {
3801 result = EDMA3_RM_E_INVALID_PARAM;
3802 }
3803 }
3805 if (EDMA3_RM_SOK == result)
3806 {
3807 edma3Id = rmObj->phyCtrllerInstId;
3808 gblRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
3810 if (rmInstance->initParam.rmSemHandle == NULL)
3811 {
3812 result = EDMA3_RM_E_INVALID_PARAM;
3813 }
3814 }
3816 if (EDMA3_RM_SOK == result)
3817 {
3818 resObj = firstResIdObj;
3819 if (resObj != NULL)
3820 {
3821 firstResId = resObj->resId;
3822 }
3824 switch (resObj->type)
3825 {
3826 case EDMA3_RM_RES_DMA_CHANNEL :
3827 maxNumResources = rmObj->gblCfgParams.numDmaChannels;
3828 break;
3829 case EDMA3_RM_RES_QDMA_CHANNEL :
3830 maxNumResources = rmObj->gblCfgParams.numQdmaChannels;
3831 break;
3832 case EDMA3_RM_RES_TCC :
3833 maxNumResources = rmObj->gblCfgParams.numTccs;
3834 break;
3835 case EDMA3_RM_RES_PARAM_SET :
3836 maxNumResources = rmObj->gblCfgParams.numPaRAMSets;
3837 break;
3838 default:
3839 result = EDMA3_RM_E_INVALID_PARAM;
3840 break;
3841 }
3842 }
3845 if (EDMA3_RM_SOK == result)
3846 {
3847 /* First resource id (firstResId) can be a valid Resource ID as well as
3848 * 'EDMA3_RM_RES_ANY', in case user does not want to
3849 * start from a specific resource. For eg, user allocating link channels.
3850 */
3851 if (firstResId != EDMA3_RM_RES_ANY)
3852 {
3853 /* User want specific resources. */
3854 lastResId = firstResId + numResources;
3856 if (((firstResId >= maxNumResources) || (firstResId > lastResId))
3857 || (lastResId > maxNumResources))
3858 {
3859 result = EDMA3_RM_E_INVALID_PARAM;
3860 }
3861 }
3862 else
3863 {
3864 /* (firstResId == EDMA3_RM_RES_ANY)
3865 * So just check whether the number of resources
3866 * requested does not cross the limit.
3867 */
3868 if (numResources > maxNumResources)
3869 {
3870 result = EDMA3_RM_E_INVALID_PARAM;
3871 }
3872 }
3873 }
3876 if (result == EDMA3_RM_SOK)
3877 {
3878 /* Now try to allocate resources for the first case */
3879 if (firstResId != EDMA3_RM_RES_ANY)
3880 {
3881 /* Request for specific resources */
3883 /**
3884 * Take the instance specific semaphore, to prevent simultaneous
3885 * access to the shared resources.
3886 */
3887 semResult = edma3OsSemTake(rmInstance->initParam.rmSemHandle,
3888 EDMA3_OSSEM_NO_TIMEOUT);
3890 if (EDMA3_RM_SOK == semResult)
3891 {
3892 switch (resObj->type)
3893 {
3894 case EDMA3_RM_RES_DMA_CHANNEL :
3895 {
3896 for (resAllocIdx = firstResId; resAllocIdx < lastResId; ++resAllocIdx)
3897 {
3898 resIdClr = (unsigned int)(~(1u << (resAllocIdx%32u)));
3899 resIdSet = (1u << (resAllocIdx%32u));
3901 /* Check whether it is owned or not */
3902 if (((rmInstance->initParam.rmInstInitConfig->ownDmaChannels[resAllocIdx/32u])&(resIdSet)) != FALSE)
3903 {
3904 /* Now check if specified resource is available presently*/
3905 if (((rmInstance->avlblDmaChannels[resAllocIdx/32u])&(resIdSet)) != FALSE)
3906 {
3907 /*
3908 * Mark the specified resource as "Not Available"
3909 * for future requests
3910 */
3911 rmInstance->avlblDmaChannels[resAllocIdx/32u] &= resIdClr;
3913 if (resAllocIdx < 32u)
3914 {
3915 rmInstance->shadowRegs->EECR = (1UL << resAllocIdx);
3917 /**
3918 * Enable the DMA channel in the
3919 * DRAE registers also.
3920 */
3921 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
3922 |= (0x1u << resAllocIdx);
3923 }
3924 else
3925 {
3926 rmInstance->shadowRegs->EECRH = (1UL << (resAllocIdx - 32u));
3928 /**
3929 * Enable the DMA channel in the
3930 * DRAEH registers also.
3931 */
3932 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
3933 |= (0x1u << (resAllocIdx - 32u));
3934 }
3936 result = EDMA3_RM_SOK;
3937 }
3938 else
3939 {
3940 /* Specified resource is owned but is already booked */
3941 result = EDMA3_RM_E_SPECIFIED_RES_NOT_AVAILABLE;
3942 break;
3943 }
3944 }
3945 else
3946 {
3947 /*
3948 * Specified resource is not owned by this instance
3949 * of the Resource Manager
3950 */
3951 result = EDMA3_RM_E_RES_NOT_OWNED;
3952 break;
3953 }
3954 }
3956 break;
3957 }
3959 case EDMA3_RM_RES_QDMA_CHANNEL:
3960 {
3961 for (resAllocIdx = firstResId; resAllocIdx < lastResId; ++resAllocIdx)
3962 {
3963 resIdClr = (unsigned int)(~(1u << resAllocIdx));
3964 resIdSet = (1u << resAllocIdx);
3966 /* Check whether it is owned or not */
3967 if (((rmInstance->initParam.rmInstInitConfig->ownQdmaChannels[0u])&(resIdSet))!=FALSE)
3968 {
3969 /* Now check if specified resource is available presently*/
3970 if (((rmInstance->avlblQdmaChannels[0u])&(resIdSet))!=FALSE)
3971 {
3972 /*
3973 * Mark the specified resource as "Not Available"
3974 * for future requests
3975 */
3976 rmInstance->avlblQdmaChannels[0u] &= resIdClr;
3978 /**
3979 * Enable the QDMA channel in the
3980 * QRAE register also.
3981 */
3982 gblRegs->QRAE[rmInstance->initParam.regionId]
3983 |= (0x1u << resAllocIdx);
3985 result = EDMA3_RM_SOK;
3986 }
3987 else
3988 {
3989 /* Specified resource is owned but is already booked */
3990 result = EDMA3_RM_E_SPECIFIED_RES_NOT_AVAILABLE;
3991 break;
3992 }
3993 }
3994 else
3995 {
3996 /*
3997 * Specified resource is not owned by this instance
3998 * of the Resource Manager
3999 */
4000 result = EDMA3_RM_E_RES_NOT_OWNED;
4001 break;
4002 }
4003 }
4005 break;
4006 }
4008 case EDMA3_RM_RES_TCC:
4009 {
4010 for (resAllocIdx = firstResId; resAllocIdx < lastResId; ++resAllocIdx)
4011 {
4012 resIdClr = (unsigned int)(~(1u << (resAllocIdx%32u)));
4013 resIdSet = (1u << (resAllocIdx%32u));
4015 /* Check whether it is owned or not */
4016 if (((rmInstance->initParam.rmInstInitConfig->ownTccs[resAllocIdx/32u])&(resIdSet))!=FALSE)
4017 {
4018 /* Now check if specified resource is available presently*/
4019 if (((rmInstance->avlblTccs[resAllocIdx/32u])&(resIdSet))!=FALSE)
4020 {
4021 /*
4022 * Mark the specified resource as "Not Available"
4023 * for future requests
4024 */
4025 rmInstance->avlblTccs[resAllocIdx/32u] &= resIdClr;
4027 /**
4028 * Enable the Interrupt channel in the
4029 * DRAE/DRAEH registers also.
4030 * Also, If the region id coming from this
4031 * RM instance is same as the Master RM
4032 * Instance's region id, only then we will be
4033 * getting the interrupts on the same side.
4034 * So save the TCC in the allocatedTCCs[] array.
4035 */
4036 if (resAllocIdx < 32u)
4037 {
4038 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
4039 |= (0x1u << resAllocIdx);
4041 if (edma3RegionId == rmInstance->initParam.regionId)
4042 {
4043 allocatedTCCs[0u] |= (0x1u << resAllocIdx);
4044 }
4045 }
4046 else
4047 {
4048 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
4049 |= (0x1u << (resAllocIdx - 32u));
4051 if (edma3RegionId == rmInstance->initParam.regionId)
4052 {
4053 allocatedTCCs[1u] |= (0x1u << (resAllocIdx - 32u));
4054 }
4055 }
4057 result = EDMA3_RM_SOK;
4058 }
4059 else
4060 {
4061 /* Specified resource is owned but is already booked */
4062 result = EDMA3_RM_E_SPECIFIED_RES_NOT_AVAILABLE;
4063 break;
4064 }
4065 }
4066 else
4067 {
4068 /*
4069 * Specified resource is not owned by this instance
4070 * of the Resource Manager
4071 */
4072 result = EDMA3_RM_E_RES_NOT_OWNED;
4073 break;
4074 }
4075 }
4077 break;
4078 }
4080 case EDMA3_RM_RES_PARAM_SET:
4081 {
4082 for (resAllocIdx = firstResId; resAllocIdx < lastResId; ++resAllocIdx)
4083 {
4084 resIdClr = (unsigned int)(~(1u << (resAllocIdx%32u)));
4085 resIdSet = (1u << (resAllocIdx%32u));
4087 /* Check whether it is owned or not */
4088 if (((rmInstance->initParam.rmInstInitConfig->ownPaRAMSets[resAllocIdx/32u])&(resIdSet))!=FALSE)
4089 {
4090 /* Now check if specified resource is available presently*/
4091 if (((rmInstance->avlblPaRAMSets[resAllocIdx/32u])&(resIdSet))!=FALSE)
4092 {
4093 /*
4094 * Mark the specified resource as "Not Available"
4095 * for future requests
4096 */
4097 rmInstance->avlblPaRAMSets[resAllocIdx/32u] &= resIdClr;
4099 /**
4100 * Also, make the actual PARAM Set NULL, checking the flag
4101 * whether it is required or not.
4102 */
4103 if (TRUE == rmInstance->paramInitRequired)
4104 {
4105 edma3MemZero((void *)(&gblRegs->PARAMENTRY[resAllocIdx]),
4106 sizeof(gblRegs->PARAMENTRY[resAllocIdx]));
4107 }
4109 result = EDMA3_RM_SOK;
4110 }
4111 else
4112 {
4113 /* Specified resource is owned but is already booked */
4114 result = EDMA3_RM_E_SPECIFIED_RES_NOT_AVAILABLE;
4115 break;
4116 }
4117 }
4118 else
4119 {
4120 /*
4121 * Specified resource is not owned by this instance
4122 * of the Resource Manager
4123 */
4124 result = EDMA3_RM_E_RES_NOT_OWNED;
4125 break;
4126 }
4127 }
4129 break;
4130 }
4132 default:
4133 {
4134 result = EDMA3_RM_E_INVALID_PARAM;
4135 break;
4136 }
4137 }
4139 /* resource allocation completed, release the semaphore first */
4140 semResult = edma3OsSemGive(rmInstance->initParam.rmSemHandle);
4141 }
4143 }
4144 else
4145 {
4146 /* (firstResId == EDMA3_RM_RES_ANY) */
4147 /**
4148 * Take the instance specific semaphore, to prevent simultaneous
4149 * access to the shared resources.
4150 */
4151 semResult = edma3OsSemTake(rmInstance->initParam.rmSemHandle,
4152 EDMA3_OSSEM_NO_TIMEOUT);
4154 if (EDMA3_RM_SOK == semResult)
4155 {
4156 /**
4157 * We have to search three different arrays, namely ownedResoures,
4158 * avlblResources and resvdResources, to find the 'common' contiguous
4159 * resources. For this, take an 'AND' of all three arrays in one single
4160 * array and use your algorithm on that array.
4161 */
4162 switch (resObj->type)
4163 {
4164 case EDMA3_RM_RES_DMA_CHANNEL:
4165 {
4166 /* AND all the arrays to look into */
4167 contiguousDmaRes[0u] = ((rmInstance->initParam.rmInstInitConfig->ownDmaChannels[0u]
4168 & rmInstance->avlblDmaChannels[0u])
4169 & (~(rmInstance->initParam.rmInstInitConfig->resvdDmaChannels[0u]))
4170 );
4171 contiguousDmaRes[1u] = ((rmInstance->initParam.rmInstInitConfig->ownDmaChannels[1u]
4172 & rmInstance->avlblDmaChannels[1u])
4173 & (~(rmInstance->initParam.rmInstInitConfig->resvdDmaChannels[1u]))
4174 );
4175 }
4176 break;
4178 case EDMA3_RM_RES_QDMA_CHANNEL:
4179 {
4180 /* AND all the arrays to look into */
4181 contiguousQdmaRes[0u] = ((rmInstance->initParam.rmInstInitConfig->ownQdmaChannels[0u]
4182 & rmInstance->avlblQdmaChannels[0u])
4183 & (~(rmInstance->initParam.rmInstInitConfig->resvdQdmaChannels[0u]))
4184 );
4185 }
4186 break;
4188 case EDMA3_RM_RES_TCC:
4189 {
4190 /* AND all the arrays to look into */
4191 contiguousTccRes[0u] = ((rmInstance->initParam.rmInstInitConfig->ownTccs[0u]
4192 & rmInstance->avlblTccs[0u])
4193 & (~(rmInstance->initParam.rmInstInitConfig->resvdTccs[0u]))
4194 );
4195 contiguousTccRes[1u] = ((rmInstance->initParam.rmInstInitConfig->ownTccs[1u]
4196 & rmInstance->avlblTccs[1u])
4197 & (~(rmInstance->initParam.rmInstInitConfig->resvdTccs[1u]))
4198 );
4199 }
4200 break;
4202 case EDMA3_RM_RES_PARAM_SET:
4203 {
4204 /* AND all the arrays to look into */
4205 for (i = 0u; i < (maxNumResources/32u); ++i)
4206 {
4207 contiguousParamRes[i] = ((rmInstance->initParam.rmInstInitConfig->ownPaRAMSets[i]
4208 & rmInstance->avlblPaRAMSets[i])
4209 & (~(rmInstance->initParam.rmInstInitConfig->resvdPaRAMSets[i]))
4210 );
4211 }
4212 }
4213 break;
4215 default:
4216 {
4217 result = EDMA3_RM_E_INVALID_PARAM;
4218 }
4219 break;
4220 }
4222 if (EDMA3_RM_SOK == result)
4223 {
4224 /**
4225 * Try to allocate 'numResources' contiguous resources
4226 * of type RES_ANY.
4227 */
4228 result = allocAnyContigRes (resObj->type, numResources, &position);
4230 /**
4231 * If result != EDMA3_RM_SOK, resource allocation failed.
4232 * Else resources successfully allocated.
4233 */
4234 if (result == EDMA3_RM_SOK)
4235 {
4236 /* Update the first resource id with the position returned. */
4237 resObj->resId = position;
4239 /*
4240 * Do some further changes in the book-keeping
4241 * data structures and global registers accordingly.
4242 */
4243 result = gblChngAllocContigRes(rmInstance, resObj, numResources);
4244 }
4245 }
4247 /* resource allocation completed, release the semaphore first */
4248 semResult = edma3OsSemGive(rmInstance->initParam.rmSemHandle);
4249 }
4250 }
4251 }
4254 /**
4255 * Check the Resource Allocation Result 'result' first. If Resource
4256 * Allocation has resulted in an error, return it (having more priority than
4257 * semResult. Else, return semResult.
4258 */
4259 if (EDMA3_RM_SOK == result)
4260 {
4261 /**
4262 * Resource Allocation successful, return semResult for returning
4263 * semaphore.
4264 */
4265 result = semResult;
4266 }
4269 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4270 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4271 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
4272 EDMA3_DVT_dCOUNTER,
4273 EDMA3_DVT_dNONE,
4274 EDMA3_DVT_dNONE));
4275 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4277 return result;
4278 }
4282 /**
4283 * \fn EDMA3_RM_Result EDMA3_RM_freeContiguousResource(EDMA3_RM_Handle
4284 * hEdmaResMgr, EDMA3_RM_ResDesc *firstResIdObj,
4285 * unsigned int numResources)
4286 * \brief Free a contiguous region of specified EDMA3 Resource
4287 * like DMA channel, QDMA channel, PaRAM Set or TCC, previously allocated.
4288 *
4289 * This API frees a contiguous region of specified EDMA3 Resources
4290 * like DMA channel, QDMA channel, PaRAM Set or TCC, which have been previously
4291 * allocated. In case of an error during the freeing of any specific resource,
4292 * user can check the 'firstResIdObj' object to know the last resource id
4293 * whose freeing has failed. In case of success, there is no need to check this
4294 * object.
4295 *
4296 * \param hEdmaResMgr [IN] Handle to the previously opened
4297 * Resource Manager Instance.
4298 * \param firstResIdObj [IN/OUT] Handle to the first resource
4299 * descriptor object, which needs to be
4300 * freed. In case of an error while
4301 * freeing any particular resource,
4302 * the last resource id whose freeing has
4303 * failed is returned in this resource
4304 * descriptor object.
4305 * \param numResources [IN] Number of contiguous resources allocated
4306 * previously which user wants to release
4307 *
4308 * \note This is a re-entrant function which internally calls
4309 * EDMA3_RM_freeResource() for resource de-allocation.
4310 */
4311 EDMA3_RM_Result EDMA3_RM_freeContiguousResource(EDMA3_RM_Handle hEdmaResMgr,
4312 EDMA3_RM_ResDesc *firstResIdObj,
4313 unsigned int numResources)
4314 {
4315 EDMA3_RM_Instance *rmInstance = NULL;
4316 EDMA3_RM_Obj *rmObj = NULL;
4317 EDMA3_RM_Result result = EDMA3_RM_SOK;
4318 EDMA3_RM_ResDesc *resObj;
4319 unsigned int resFreeIdx = 0u;
4320 unsigned int firstResId;
4321 unsigned int lastResId;
4322 unsigned int maxNumResources = 0u;
4324 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4325 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4326 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
4327 EDMA3_DVT_dCOUNTER,
4328 EDMA3_DVT_dNONE,
4329 EDMA3_DVT_dNONE));
4330 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4332 /* If parameter checking is enabled... */
4333 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
4334 if ((hEdmaResMgr == NULL) || (firstResIdObj == NULL))
4335 {
4336 result = EDMA3_RM_E_INVALID_PARAM;
4337 }
4338 #endif
4340 /* Check if the parameters are OK. */
4341 if (EDMA3_RM_SOK == result)
4342 {
4343 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
4344 rmObj = rmInstance->pResMgrObjHandle;
4346 if (rmObj == NULL)
4347 {
4348 result = EDMA3_RM_E_INVALID_PARAM;
4349 }
4350 else
4351 {
4352 resObj = firstResIdObj;
4353 if (resObj != NULL)
4354 {
4355 firstResId = resObj->resId;
4356 lastResId = firstResId + (numResources - 1u);
4357 }
4359 switch (resObj->type)
4360 {
4361 case EDMA3_RM_RES_DMA_CHANNEL :
4362 maxNumResources = rmObj->gblCfgParams.numDmaChannels;
4363 break;
4364 case EDMA3_RM_RES_QDMA_CHANNEL :
4365 maxNumResources = rmObj->gblCfgParams.numQdmaChannels;
4366 break;
4367 case EDMA3_RM_RES_TCC :
4368 maxNumResources = rmObj->gblCfgParams.numTccs;
4369 break;
4370 case EDMA3_RM_RES_PARAM_SET :
4371 maxNumResources = rmObj->gblCfgParams.numPaRAMSets;
4372 break;
4373 default:
4374 result = EDMA3_RM_E_INVALID_PARAM;
4375 break;
4376 }
4378 if (result == EDMA3_RM_SOK)
4379 {
4380 if ((firstResId > lastResId) || (lastResId >= maxNumResources))
4381 {
4382 result = EDMA3_RM_E_INVALID_PARAM;
4383 }
4384 else
4385 {
4386 for (resFreeIdx = firstResId; resFreeIdx <= lastResId; ++resFreeIdx)
4387 {
4388 resObj->resId = resFreeIdx;
4389 result = EDMA3_RM_freeResource(rmInstance, resObj);
4391 if (result != EDMA3_RM_SOK)
4392 {
4393 break;
4394 }
4395 }
4396 }
4397 }
4398 }
4399 }
4401 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4402 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4403 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
4404 EDMA3_DVT_dCOUNTER,
4405 EDMA3_DVT_dNONE,
4406 EDMA3_DVT_dNONE));
4407 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4409 return result;
4410 }
4415 /**\fn EDMA3_RM_Result EDMA3_RM_setCCRegister (EDMA3_RM_Handle hEdmaResMgr,
4416 * unsigned int regOffset,
4417 * unsigned int newRegValue)
4418 * \brief Set the Channel Controller (CC) Register value
4419 *
4420 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
4421 * Manager Instance.
4422 * \param regOffset [IN] CC Register offset whose value needs to be
4423 * set. It should be word-aligned.
4424 * \param newRegValue [IN] New CC Register Value
4425 *
4426 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
4427 *
4428 * \note This function is non re-entrant for users using the same
4429 * Resource Manager handle.
4430 * Before modifying a register, it tries to acquire a semaphore
4431 * (RM instance specific), to protect simultaneous
4432 * modification of the same register by two different users.
4433 * After the successful change, it releases the semaphore.
4434 * For users using different RM handles, this function is re-entrant.
4435 */
4436 EDMA3_RM_Result EDMA3_RM_setCCRegister (EDMA3_RM_Handle hEdmaResMgr,
4437 unsigned int regOffset,
4438 unsigned int newRegValue)
4439 {
4440 EDMA3_RM_Result result = EDMA3_RM_SOK;
4441 EDMA3_RM_Instance *rmInstance = NULL;
4442 EDMA3_RM_Obj *rmObj = NULL;
4443 volatile unsigned int regPhyAddr = 0x0u;
4446 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4447 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4448 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
4449 EDMA3_DVT_dCOUNTER,
4450 EDMA3_DVT_dNONE,
4451 EDMA3_DVT_dNONE));
4452 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4455 /* If parameter checking is enabled... */
4456 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
4457 if ((hEdmaResMgr == NULL) || ((regOffset % 4u) != 0))
4458 {
4459 result = (EDMA3_RM_E_INVALID_PARAM);
4460 }
4461 #endif
4463 /* Check if the parameters are OK. */
4464 if (EDMA3_RM_SOK == result)
4465 {
4466 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
4467 rmObj = rmInstance->pResMgrObjHandle;
4469 if (rmObj == NULL)
4470 {
4471 result = (EDMA3_RM_E_INVALID_PARAM);
4472 }
4473 else
4474 {
4475 if (rmObj->gblCfgParams.globalRegs != NULL)
4476 {
4477 /**
4478 * Take the instance specific semaphore, to prevent simultaneous
4479 * access to the shared resources.
4480 */
4481 result = edma3OsSemTake(rmInstance->initParam.rmSemHandle,
4482 EDMA3_OSSEM_NO_TIMEOUT);
4484 if (EDMA3_RM_SOK == result)
4485 {
4486 /* Semaphore taken successfully, modify the registers. */
4487 regPhyAddr = (unsigned int)(rmObj->gblCfgParams.globalRegs) + regOffset;
4489 *(unsigned int *)regPhyAddr = newRegValue;
4491 /* Return the semaphore back */
4492 result = edma3OsSemGive(rmInstance->initParam.rmSemHandle);
4493 }
4494 }
4495 }
4496 }
4499 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4500 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4501 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
4502 EDMA3_DVT_dCOUNTER,
4503 EDMA3_DVT_dNONE,
4504 EDMA3_DVT_dNONE));
4505 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4508 return result;
4509 }
4514 /**\fn EDMA3_RM_Result EDMA3_RM_getCCRegister (EDMA3_RM_Handle hEdmaResMgr,
4515 * unsigned int regOffset,
4516 * unsigned int *regValue)
4517 * \brief Get the Channel Controller (CC) Register value
4518 *
4519 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
4520 * Manager Instance.
4521 * \param regOffset [IN] CC Register offset whose value is
4522 * needed. It should be word-aligned.
4523 * \param regValue [IN/OUT] Fetched CC Register Value
4524 *
4525 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
4526 *
4527 * \note This function is re-entrant.
4528 */
4529 EDMA3_RM_Result EDMA3_RM_getCCRegister (EDMA3_RM_Handle hEdmaResMgr,
4530 unsigned int regOffset,
4531 unsigned int *regValue)
4532 {
4533 EDMA3_RM_Result result = EDMA3_RM_SOK;
4534 EDMA3_RM_Instance *rmInstance = NULL;
4535 EDMA3_RM_Obj *rmObj = NULL;
4536 volatile unsigned int regPhyAddr = 0x0u;
4539 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4540 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4541 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
4542 EDMA3_DVT_dCOUNTER,
4543 EDMA3_DVT_dNONE,
4544 EDMA3_DVT_dNONE));
4545 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4548 /* If parameter checking is enabled... */
4549 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
4550 if (((hEdmaResMgr == NULL) || (regValue == NULL))
4551 || ((regOffset % 4u) != 0))
4552 {
4553 result = (EDMA3_RM_E_INVALID_PARAM);
4554 }
4555 #endif
4557 /* Check if the parameters are OK. */
4558 if (EDMA3_RM_SOK == result)
4559 {
4560 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
4561 rmObj = rmInstance->pResMgrObjHandle;
4563 if (rmObj == NULL)
4564 {
4565 result = (EDMA3_RM_E_INVALID_PARAM);
4566 }
4567 else
4568 {
4569 if (rmObj->gblCfgParams.globalRegs != NULL)
4570 {
4571 regPhyAddr = (unsigned int)(rmObj->gblCfgParams.globalRegs) + regOffset;
4573 *regValue = *(unsigned int *)regPhyAddr;
4574 }
4575 }
4576 }
4579 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4580 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4581 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
4582 EDMA3_DVT_dCOUNTER,
4583 EDMA3_DVT_dNONE,
4584 EDMA3_DVT_dNONE));
4585 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4588 return result;
4589 }
4593 /**\fn EDMA3_RM_Result EDMA3_RM_waitAndClearTcc (EDMA3_RM_Handle
4594 * hEdmaResMgr, unsigned int tccNo)
4595 * \brief Wait for a transfer completion interrupt to occur and clear it.
4596 *
4597 * This is a blocking function that returns when the IPR/IPRH bit corresponding
4598 * to the tccNo specified, is SET. It clears the corresponding bit while
4599 * returning also.
4600 *
4601 * This function waits for the specific bit indefinitely in a tight loop, with
4602 * out any delay in between. USE IT CAUTIOUSLY.
4603 *
4604 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
4605 * Manager Instance.
4606 * \param tccNo [IN] TCC, specific to which the function
4607 * waits on a IPR/IPRH bit.
4608 *
4609 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
4610 *
4611 * \note This function is re-entrant for different tccNo.
4612 *
4613 */
4614 EDMA3_RM_Result EDMA3_RM_waitAndClearTcc (EDMA3_RM_Handle hEdmaResMgr,
4615 unsigned int tccNo)
4616 {
4617 EDMA3_RM_Result result = EDMA3_RM_SOK;
4618 EDMA3_RM_Instance *rmInstance = NULL;
4619 EDMA3_RM_Obj *rmObj = NULL;
4620 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
4621 volatile EDMA3_CCRL_ShadowRegs *shadowRegs = NULL;
4622 unsigned int tccBitMask = 0x0u;
4625 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4626 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4627 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
4628 EDMA3_DVT_dCOUNTER,
4629 EDMA3_DVT_dNONE,
4630 EDMA3_DVT_dNONE));
4631 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4634 /* If parameter checking is enabled... */
4635 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
4636 if (hEdmaResMgr == NULL)
4637 {
4638 result = (EDMA3_RM_E_INVALID_PARAM);
4639 }
4640 #endif
4642 /* Check if the parameters are OK. */
4643 if (EDMA3_RM_SOK == result)
4644 {
4645 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
4646 rmObj = rmInstance->pResMgrObjHandle;
4648 if ((rmObj == NULL) || (rmObj->gblCfgParams.globalRegs == NULL))
4649 {
4650 result = (EDMA3_RM_E_INVALID_PARAM);
4651 }
4652 else
4653 {
4654 /* If parameter checking is enabled... */
4655 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
4656 if (tccNo >= rmObj->gblCfgParams.numTccs)
4657 {
4658 result = (EDMA3_RM_E_INVALID_PARAM);
4659 }
4660 #endif
4662 /* Check if the parameters are OK. */
4663 if (EDMA3_RM_SOK == result)
4664 {
4665 globalRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
4666 shadowRegs = (volatile EDMA3_CCRL_ShadowRegs *)
4667 (&globalRegs->SHADOW[rmInstance->initParam.regionId]);
4670 if (shadowRegs != NULL)
4671 {
4672 if(tccNo < 32u)
4673 {
4674 tccBitMask = (1u << tccNo);
4676 /* Check the status of the IPR[tccNo] bit. */
4677 while (FALSE == (shadowRegs->IPR & tccBitMask))
4678 {
4679 /* Transfer not yet completed, bit not SET */
4680 }
4682 /**
4683 * Bit found SET, transfer is completed,
4684 * clear the pending interrupt and return.
4685 */
4686 shadowRegs->ICR = tccBitMask;
4687 }
4688 else
4689 {
4690 tccBitMask = (1u << (tccNo - 32u));
4692 /* Check the status of the IPRH[tccNo-32] bit. */
4693 while (FALSE == (shadowRegs->IPRH & tccBitMask))
4694 {
4695 /* Transfer not yet completed, bit not SET */
4696 }
4698 /**
4699 * Bit found SET, transfer is completed,
4700 * clear the pending interrupt and return.
4701 */
4702 shadowRegs->ICRH = tccBitMask;
4703 }
4704 }
4705 }
4706 }
4707 }
4710 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4711 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4712 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
4713 EDMA3_DVT_dCOUNTER,
4714 EDMA3_DVT_dNONE,
4715 EDMA3_DVT_dNONE));
4716 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4719 return result;
4720 }
4725 /**\fn EDMA3_RM_Result EDMA3_RM_checkAndClearTcc (EDMA3_RM_Handle
4726 * hEdmaResMgr, unsigned int tccNo,
4727 * unsigned short *tccStatus)
4728 * \brief Returns the status of a previously initiated transfer.
4729 *
4730 * This is a non-blocking function that returns the status of a previously
4731 * initiated transfer, based on the IPR/IPRH bit. This bit corresponds to
4732 * the tccNo specified by the user. It clears the corresponding bit, if SET,
4733 * while returning also.
4734 *
4735 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
4736 * Manager Instance.
4737 * \param tccNo [IN] TCC, specific to which the function
4738 * checks the status of the IPR/IPRH bit.
4739 * \param tccStatus [IN/OUT] Status of the transfer is returned here.
4740 * Returns "TRUE" if the transfer has
4741 * completed (IPR/IPRH bit SET),
4742 * "FALSE" if the transfer has not
4743 * completed successfully (IPR/IPRH bit
4744 * NOT SET).
4745 *
4746 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
4747 *
4748 * \note This function is re-entrant for different tccNo.
4749 */
4750 EDMA3_RM_Result EDMA3_RM_checkAndClearTcc (EDMA3_RM_Handle hEdmaResMgr,
4751 unsigned int tccNo,
4752 unsigned short *tccStatus)
4753 {
4754 EDMA3_RM_Result result = EDMA3_RM_SOK;
4755 EDMA3_RM_Instance *rmInstance = NULL;
4756 EDMA3_RM_Obj *rmObj = NULL;
4757 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
4758 volatile EDMA3_CCRL_ShadowRegs *shadowRegs = NULL;
4759 unsigned int tccBitMask = 0x0u;
4762 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4763 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4764 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
4765 EDMA3_DVT_dCOUNTER,
4766 EDMA3_DVT_dNONE,
4767 EDMA3_DVT_dNONE));
4768 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4771 /* If parameter checking is enabled... */
4772 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
4773 if ((hEdmaResMgr == NULL) || (tccStatus == NULL))
4774 {
4775 result = (EDMA3_RM_E_INVALID_PARAM);
4776 }
4777 #endif
4779 /* Check if the parameters are OK. */
4780 if (EDMA3_RM_SOK == result)
4781 {
4782 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
4783 rmObj = rmInstance->pResMgrObjHandle;
4785 if ((rmObj == NULL) || (rmObj->gblCfgParams.globalRegs == NULL))
4786 {
4787 result = (EDMA3_RM_E_INVALID_PARAM);
4788 }
4789 else
4790 {
4791 /* If parameter checking is enabled... */
4792 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
4793 if (tccNo >= rmObj->gblCfgParams.numTccs)
4794 {
4795 result = (EDMA3_RM_E_INVALID_PARAM);
4796 }
4797 #endif
4799 /* Check if the parameters are OK. */
4800 if (EDMA3_RM_SOK == result)
4801 {
4802 globalRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
4803 shadowRegs = (volatile EDMA3_CCRL_ShadowRegs *)
4804 (&globalRegs->SHADOW[rmInstance->initParam.regionId]);
4806 /* Reset the tccStatus */
4807 *tccStatus = FALSE;
4809 if (shadowRegs != NULL)
4810 {
4811 if(tccNo < 32u)
4812 {
4813 tccBitMask = (1u << tccNo);
4815 /* Check the status of the IPR[tccNo] bit. */
4816 if ((shadowRegs->IPR & tccBitMask) != FALSE)
4817 {
4818 /* Transfer completed, bit found SET */
4819 *tccStatus = TRUE;
4821 /* Clear the pending interrupt also. */
4822 shadowRegs->ICR = tccBitMask;
4823 }
4824 }
4825 else
4826 {
4827 tccBitMask = (1u << (tccNo - 32u));
4829 /* Check the status of the IPRH[tccNo-32] bit. */
4830 if ((shadowRegs->IPRH & tccBitMask) != FALSE)
4831 {
4832 /* Transfer completed, bit found SET */
4833 *tccStatus = TRUE;
4835 /* Clear the pending interrupt also. */
4836 shadowRegs->ICRH = tccBitMask;
4837 }
4838 }
4839 }
4840 }
4841 }
4842 }
4845 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4846 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4847 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
4848 EDMA3_DVT_dCOUNTER,
4849 EDMA3_DVT_dNONE,
4850 EDMA3_DVT_dNONE));
4851 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4854 return result;
4855 }
4859 /**\fn EDMA3_RM_Result EDMA3_RM_setPaRAM (EDMA3_RM_Handle hEdmaResMgr,
4860 * EDMA3_RM_ResDesc *lChObj,
4861 * const EDMA3_RM_PaRAMRegs *newPaRAM)
4862 * \brief Copy the user specified PaRAM Set onto the PaRAM Set
4863 * associated with the logical channel (DMA/QDMA/Link).
4864 *
4865 * This API takes a PaRAM Set as input and copies it onto the actual PaRAM Set
4866 * associated with the logical channel. OPT field of the PaRAM Set is written
4867 * first and the CCNT field is written last.
4868 *
4869 * Caution: It should be used carefully when programming the QDMA channels whose
4870 * trigger words are not CCNT field.
4871 *
4872 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
4873 * Manager Instance.
4874 * \param lChObj [IN] Logical Channel object for which new
4875 * PaRAM set is specified. User should pass
4876 * the resource type and id in this object.
4877 * \param newPaRAM [IN] PaRAM set to be copied onto existing one
4878 *
4879 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
4880 *
4881 * \note This function is re-entrant for unique lChObj values. It is non-
4882 * re-entrant for same lChObj value.
4883 */
4884 EDMA3_RM_Result EDMA3_RM_setPaRAM (EDMA3_RM_Handle hEdmaResMgr,
4885 EDMA3_RM_ResDesc *lChObj,
4886 const EDMA3_RM_PaRAMRegs *newPaRAM)
4887 {
4888 EDMA3_RM_Result result = EDMA3_RM_SOK;
4889 EDMA3_RM_Instance *rmInstance = NULL;
4890 EDMA3_RM_Obj *rmObj = NULL;
4891 int paRAMId = 0u;
4892 unsigned int qdmaChId = 0u;
4893 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
4894 unsigned int edma3Id;
4896 #ifdef EDMA3_INSTRUMENTATION_ENABLED
4897 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
4898 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
4899 EDMA3_DVT_dCOUNTER,
4900 EDMA3_DVT_dNONE,
4901 EDMA3_DVT_dNONE));
4902 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
4904 /* If parameter checking is enabled... */
4905 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
4906 if (hEdmaResMgr == NULL)
4907 {
4908 result = EDMA3_RM_E_INVALID_PARAM;
4909 }
4911 if ((lChObj == NULL) || (newPaRAM == NULL))
4912 {
4913 result = EDMA3_RM_E_INVALID_PARAM;
4914 }
4915 #endif
4917 /* Check if the parameters are OK. */
4918 if (result == EDMA3_RM_SOK)
4919 {
4920 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
4922 if (rmInstance == NULL)
4923 {
4924 result = EDMA3_RM_E_INVALID_PARAM;
4925 }
4926 }
4928 if (result == EDMA3_RM_SOK)
4929 {
4930 rmObj = rmInstance->pResMgrObjHandle;
4932 if (rmObj == NULL)
4933 {
4934 result = EDMA3_RM_E_INVALID_PARAM;
4935 }
4936 else
4937 {
4938 if (rmObj->gblCfgParams.globalRegs == NULL)
4939 {
4940 result = EDMA3_RM_E_INVALID_PARAM;
4941 }
4942 }
4943 }
4945 if (result == EDMA3_RM_SOK)
4946 {
4947 edma3Id = rmObj->phyCtrllerInstId;
4948 globalRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
4950 switch (lChObj->type)
4951 {
4952 case EDMA3_RM_RES_DMA_CHANNEL:
4953 {
4954 if (lChObj->resId <= edma3_dma_ch_max_val[edma3Id])
4955 {
4956 paRAMId = edma3RmChBoundRes[edma3Id][lChObj->resId].paRAMId;
4957 }
4958 else
4959 {
4960 result = EDMA3_RM_E_INVALID_PARAM;
4961 }
4962 }
4963 break;
4965 case EDMA3_RM_RES_QDMA_CHANNEL:
4966 {
4967 if (lChObj->resId < EDMA3_MAX_QDMA_CH)
4968 {
4969 qdmaChId = lChObj->resId + edma3_qdma_ch_min_val[edma3Id];
4970 paRAMId = edma3RmChBoundRes[edma3Id][qdmaChId].paRAMId;
4971 }
4972 else
4973 {
4974 result = EDMA3_RM_E_INVALID_PARAM;
4975 }
4976 }
4977 break;
4979 case EDMA3_RM_RES_PARAM_SET:
4980 {
4981 if (lChObj->resId < edma3NumPaRAMSets)
4982 {
4983 /**
4984 * User has passed the actual param set value here.
4985 * Use this value only
4986 */
4987 paRAMId = (int)(lChObj->resId);
4988 }
4989 else
4990 {
4991 result = EDMA3_RM_E_INVALID_PARAM;
4992 }
4993 }
4994 break;
4996 default:
4997 result = EDMA3_RM_E_INVALID_PARAM;
4998 }
4999 }
5002 if (result == EDMA3_RM_SOK)
5003 {
5004 /* Check the param id first. */
5005 if ((paRAMId != -1) && ((unsigned int)paRAMId < edma3NumPaRAMSets))
5006 {
5007 /* Set the PaRAM Set now. */
5008 edma3ParamCpy ((void *)(&(globalRegs->PARAMENTRY[paRAMId].OPT)),
5009 (const void *)newPaRAM);
5010 }
5011 else
5012 {
5013 result = EDMA3_RM_E_INVALID_PARAM;
5014 }
5015 }
5018 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5019 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5020 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
5021 EDMA3_DVT_dCOUNTER,
5022 EDMA3_DVT_dNONE,
5023 EDMA3_DVT_dNONE));
5024 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5026 return result;
5027 }
5031 /**\fn EDMA3_RM_Result EDMA3_RM_getPaRAM (EDMA3_RM_Handle hEdmaResMgr,
5032 * EDMA3_RM_ResDesc *lChObj,
5033 * EDMA3_RM_PaRAMRegs *currPaRAM)
5034 * \brief Retrieve existing PaRAM set associated with specified logical
5035 * channel (DMA/QDMA/Link).
5036 *
5037 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
5038 * Manager Instance.
5039 * \param lChObj [IN] Logical Channel object for which the
5040 * PaRAM set is requested. User should pass
5041 * the resource type and id in this object.
5042 * \param currPaRAM [IN/OUT] User gets the existing PaRAM here.
5043 *
5044 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
5045 *
5046 * \note This function is re-entrant.
5047 */
5048 EDMA3_RM_Result EDMA3_RM_getPaRAM (EDMA3_RM_Handle hEdmaResMgr,
5049 EDMA3_RM_ResDesc *lChObj,
5050 EDMA3_RM_PaRAMRegs *currPaRAM)
5051 {
5052 EDMA3_RM_Result result = EDMA3_RM_SOK;
5053 EDMA3_RM_Instance *rmInstance = NULL;
5054 EDMA3_RM_Obj *rmObj = NULL;
5055 int paRAMId = 0u;
5056 unsigned int qdmaChId = 0u;
5057 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
5058 unsigned int edma3Id;
5060 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5061 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5062 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
5063 EDMA3_DVT_dCOUNTER,
5064 EDMA3_DVT_dNONE,
5065 EDMA3_DVT_dNONE));
5066 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5068 /* If parameter checking is enabled... */
5069 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5070 if (hEdmaResMgr == NULL)
5071 {
5072 result = EDMA3_RM_E_INVALID_PARAM;
5073 }
5075 if ((lChObj == NULL) || (currPaRAM == NULL))
5076 {
5077 result = EDMA3_RM_E_INVALID_PARAM;
5078 }
5079 #endif
5081 /* Check if the parameters are OK. */
5082 if (result == EDMA3_RM_SOK)
5083 {
5084 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
5086 if (rmInstance == NULL)
5087 {
5088 result = EDMA3_RM_E_INVALID_PARAM;
5089 }
5090 }
5092 if (result == EDMA3_RM_SOK)
5093 {
5094 rmObj = rmInstance->pResMgrObjHandle;
5096 if (rmObj == NULL)
5097 {
5098 result = EDMA3_RM_E_INVALID_PARAM;
5099 }
5100 else
5101 {
5102 if (rmObj->gblCfgParams.globalRegs == NULL)
5103 {
5104 result = EDMA3_RM_E_INVALID_PARAM;
5105 }
5106 }
5107 }
5109 if (result == EDMA3_RM_SOK)
5110 {
5111 edma3Id = rmObj->phyCtrllerInstId;
5112 globalRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
5114 switch (lChObj->type)
5115 {
5116 case EDMA3_RM_RES_DMA_CHANNEL:
5117 {
5118 if (lChObj->resId <= edma3_dma_ch_max_val[edma3Id])
5119 {
5120 paRAMId = edma3RmChBoundRes[rmObj->phyCtrllerInstId][lChObj->resId].paRAMId;
5121 }
5122 else
5123 {
5124 result = EDMA3_RM_E_INVALID_PARAM;
5125 }
5126 }
5127 break;
5129 case EDMA3_RM_RES_QDMA_CHANNEL:
5130 {
5131 if (lChObj->resId < EDMA3_MAX_QDMA_CH)
5132 {
5133 qdmaChId = lChObj->resId + edma3_qdma_ch_min_val[edma3Id];
5134 paRAMId = edma3RmChBoundRes[rmObj->phyCtrllerInstId][qdmaChId].paRAMId;
5135 }
5136 else
5137 {
5138 result = EDMA3_RM_E_INVALID_PARAM;
5139 }
5140 }
5141 break;
5143 case EDMA3_RM_RES_PARAM_SET:
5144 {
5145 if (lChObj->resId < edma3NumPaRAMSets)
5146 {
5147 /**
5148 * User has passed the actual param set value here.
5149 * Use this value only
5150 */
5151 paRAMId = (int)(lChObj->resId);
5152 }
5153 else
5154 {
5155 result = EDMA3_RM_E_INVALID_PARAM;
5156 }
5157 }
5158 break;
5160 default:
5161 result = EDMA3_RM_E_INVALID_PARAM;
5162 }
5163 }
5166 if (result == EDMA3_RM_SOK)
5167 {
5168 /* Check the param id first. */
5169 if ((paRAMId != -1) && (paRAMId < edma3NumPaRAMSets))
5170 {
5171 /* Get the PaRAM Set now. */
5172 edma3ParamCpy ((void *)currPaRAM ,
5173 (const void *)(&(globalRegs->PARAMENTRY [paRAMId].OPT)));
5174 }
5175 else
5176 {
5177 result = EDMA3_RM_E_INVALID_PARAM;
5178 }
5179 }
5182 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5183 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5184 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
5185 EDMA3_DVT_dCOUNTER,
5186 EDMA3_DVT_dNONE,
5187 EDMA3_DVT_dNONE));
5188 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5191 return result;
5192 }
5195 /**\fn EDMA3_RM_Result EDMA3_RM_getPaRAMPhyAddr(EDMA3_RM_Handle
5196 * hEdmaResMgr, EDMA3_RM_ResDesc *lChObj,
5197 * unsigned int *paramPhyAddr)
5198 * \brief Get the PaRAM Set Physical Address associated with a logical channel
5199 *
5200 * This function returns the PaRAM Set Phy Address (unsigned 32 bits).
5201 * The returned address could be used by the advanced users to program the
5202 * PaRAM Set directly without using any APIs.
5203 *
5204 * Least significant 16 bits of this address could be used to program
5205 * the LINK field in the PaRAM Set.
5206 * Users which program the LINK field directly SHOULD use this API
5207 * to get the associated PaRAM Set address with the LINK channel.
5208 *
5209 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
5210 * Manager Instance.
5211 * \param lChObj [IN] Logical Channel object for which the
5212 * PaRAM set physical address is required.
5213 * User should pass the resource type and
5214 * id in this object.
5215 * \param paramPhyAddr [IN/OUT] PaRAM Set physical address is returned
5216 * here.
5217 *
5218 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
5219 *
5220 * \note This function is re-entrant.
5221 */
5222 EDMA3_RM_Result EDMA3_RM_getPaRAMPhyAddr(EDMA3_RM_Handle hEdmaResMgr,
5223 EDMA3_RM_ResDesc *lChObj,
5224 unsigned int *paramPhyAddr)
5225 {
5226 EDMA3_RM_Result result = EDMA3_RM_SOK;
5227 EDMA3_RM_Instance *rmInstance = NULL;
5228 EDMA3_RM_Obj *rmObj = NULL;
5229 int paRAMId = 0u;
5230 unsigned int qdmaChId = 0u;
5231 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
5232 unsigned int edma3Id;
5234 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5235 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5236 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
5237 EDMA3_DVT_dCOUNTER,
5238 EDMA3_DVT_dNONE,
5239 EDMA3_DVT_dNONE));
5240 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5243 /* If parameter checking is enabled... */
5244 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5245 if (hEdmaResMgr == NULL)
5246 {
5247 result = EDMA3_RM_E_INVALID_PARAM;
5248 }
5250 if ((lChObj == NULL) || (paramPhyAddr == NULL))
5251 {
5252 result = EDMA3_RM_E_INVALID_PARAM;
5253 }
5254 #endif
5256 if (result == EDMA3_RM_SOK)
5257 {
5258 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
5260 if (rmInstance == NULL)
5261 {
5262 result = EDMA3_RM_E_INVALID_PARAM;
5263 }
5264 }
5266 if (result == EDMA3_RM_SOK)
5267 {
5268 rmObj = rmInstance->pResMgrObjHandle;
5270 if (rmObj == NULL)
5271 {
5272 result = EDMA3_RM_E_INVALID_PARAM;
5273 }
5274 else
5275 {
5276 if (rmObj->gblCfgParams.globalRegs == NULL)
5277 {
5278 result = EDMA3_RM_E_INVALID_PARAM;
5279 }
5280 }
5281 }
5283 if (result == EDMA3_RM_SOK)
5284 {
5285 edma3Id = rmObj->phyCtrllerInstId;
5286 globalRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
5288 switch (lChObj->type)
5289 {
5290 case EDMA3_RM_RES_DMA_CHANNEL:
5291 {
5292 if (lChObj->resId <= edma3_dma_ch_max_val[edma3Id])
5293 {
5294 paRAMId = edma3RmChBoundRes[edma3Id][lChObj->resId].paRAMId;
5295 }
5296 else
5297 {
5298 result = EDMA3_RM_E_INVALID_PARAM;
5299 }
5300 }
5301 break;
5303 case EDMA3_RM_RES_QDMA_CHANNEL:
5304 {
5305 if (lChObj->resId < EDMA3_MAX_QDMA_CH)
5306 {
5307 qdmaChId = lChObj->resId + edma3_qdma_ch_min_val[edma3Id];
5308 paRAMId = edma3RmChBoundRes[edma3Id][qdmaChId].paRAMId;
5309 }
5310 else
5311 {
5312 result = EDMA3_RM_E_INVALID_PARAM;
5313 }
5314 }
5315 break;
5317 case EDMA3_RM_RES_PARAM_SET:
5318 {
5319 if (lChObj->resId < edma3NumPaRAMSets)
5320 {
5321 /**
5322 * User has passed the actual param set value here.
5323 * Use this value only
5324 */
5325 paRAMId = (int)(lChObj->resId);
5326 }
5327 else
5328 {
5329 result = EDMA3_RM_E_INVALID_PARAM;
5330 }
5331 }
5332 break;
5334 default:
5335 result = EDMA3_RM_E_INVALID_PARAM;
5336 }
5337 }
5341 if (result == EDMA3_RM_SOK)
5342 {
5343 /* Check the param id first. */
5344 if ((paRAMId != -1) && (paRAMId < edma3NumPaRAMSets))
5345 {
5346 /* Get the PaRAM Set Address now. */
5347 *paramPhyAddr = (unsigned int)(&(globalRegs->PARAMENTRY [paRAMId].OPT));
5348 }
5349 else
5350 {
5351 result = EDMA3_RM_E_INVALID_PARAM;
5352 }
5353 }
5355 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5356 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5357 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
5358 EDMA3_DVT_dCOUNTER,
5359 EDMA3_DVT_dNONE,
5360 EDMA3_DVT_dNONE));
5361 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5363 return result;
5364 }
5367 /**\fn EDMA3_RM_Result EDMA3_RM_getBaseAddress (EDMA3_RM_Handle
5368 * hEdmaResMgr, EDMA3_RM_Cntrlr_PhyAddr controllerId,
5369 * unsigned int *phyAddress)
5370 * \brief Get the Channel Controller or Transfer Controller (n) Physical
5371 * Address.
5372 *
5373 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
5374 * Manager Instance.
5375 * \param controllerId [IN] Channel Controller or Transfer
5376 * Controller (n) for which the physical
5377 * address is required.
5378 * \param phyAddress [IN/OUT] Physical address is returned here.
5379 *
5380 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
5381 *
5382 * \note This function is re-entrant.
5383 */
5384 EDMA3_RM_Result EDMA3_RM_getBaseAddress (EDMA3_RM_Handle hEdmaResMgr,
5385 EDMA3_RM_Cntrlr_PhyAddr controllerId,
5386 unsigned int *phyAddress)
5387 {
5388 EDMA3_RM_Result result = EDMA3_RM_SOK;
5389 EDMA3_RM_Instance *rmInstance = NULL;
5390 EDMA3_RM_Obj *rmObj = NULL;
5392 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5393 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5394 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
5395 EDMA3_DVT_dCOUNTER,
5396 EDMA3_DVT_dNONE,
5397 EDMA3_DVT_dNONE));
5398 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5401 /* If parameter checking is enabled... */
5402 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5403 if ((hEdmaResMgr == NULL) || (phyAddress == NULL))
5404 {
5405 result = EDMA3_RM_E_INVALID_PARAM;
5406 }
5407 #endif
5409 if (result == EDMA3_RM_SOK)
5410 {
5411 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
5413 if (rmInstance == NULL)
5414 {
5415 result = EDMA3_RM_E_INVALID_PARAM;
5416 }
5417 }
5419 if (result == EDMA3_RM_SOK)
5420 {
5421 rmObj = rmInstance->pResMgrObjHandle;
5423 if (rmObj == NULL)
5424 {
5425 result = EDMA3_RM_E_INVALID_PARAM;
5426 }
5427 }
5429 if (result == EDMA3_RM_SOK)
5430 {
5431 /* If parameter checking is enabled... */
5432 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5433 /* Verify the 'controllerId' */
5434 if ((controllerId < ((EDMA3_RM_Cntrlr_PhyAddr)(EDMA3_RM_CC_PHY_ADDR)))
5435 || (controllerId > (EDMA3_RM_Cntrlr_PhyAddr)(rmObj->gblCfgParams.numTcs)))
5436 {
5437 /* Invalid controllerId */
5438 result = EDMA3_RM_E_INVALID_PARAM;
5439 }
5440 #endif
5442 /* Check if the parameters are OK. */
5443 if (EDMA3_RM_SOK == result)
5444 {
5445 if (controllerId == EDMA3_RM_CC_PHY_ADDR)
5446 {
5447 /* EDMA3 Channel Controller Address */
5448 *phyAddress = (unsigned int)(rmObj->gblCfgParams.globalRegs);
5449 }
5450 else
5451 {
5452 /**
5453 * Since the TCs enum start from 1, and TCs start from 0,
5454 * subtract 1 from the enum to get the actual address.
5455 */
5456 *phyAddress = (unsigned int)(rmObj->gblCfgParams.tcRegs[controllerId-1u]);
5457 }
5458 }
5459 }
5461 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5462 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5463 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
5464 EDMA3_DVT_dCOUNTER,
5465 EDMA3_DVT_dNONE,
5466 EDMA3_DVT_dNONE));
5467 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5469 return result;
5470 }
5475 /**\fn EDMA3_RM_Result EDMA3_RM_getGblConfigParams (unsigned int phyCtrllerInstId,
5476 * EDMA3_RM_GblConfigParams *gblCfgParams)
5477 * \brief Get the SoC specific configuration structure for the EDMA3 Hardware.
5478 *
5479 * This API is used to fetch the global SoC specific configuration structure
5480 * for the EDMA3 Hardware. It is useful for the user who has not passed
5481 * this information during EDMA3_RM_create() and taken the default configuration
5482 * coming along with the package.
5483 *
5484 * \param phyCtrllerInstId [IN] EDMA3 Controller Instance Id
5485 * (Hardware instance id, starting from 0).
5486 * \param gblCfgParams [IN/OUT] SoC specific configuration structure for the
5487 * EDMA3 Hardware will be returned here.
5488 *
5489 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
5490 *
5491 * \note This function is re-entrant.
5492 */
5493 EDMA3_RM_Result EDMA3_RM_getGblConfigParams (
5494 unsigned int phyCtrllerInstId,
5495 EDMA3_RM_GblConfigParams *gblCfgParams)
5496 {
5497 EDMA3_RM_Result result = EDMA3_RM_SOK;
5499 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5500 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5501 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
5502 EDMA3_DVT_dCOUNTER,
5503 EDMA3_DVT_dNONE,
5504 EDMA3_DVT_dNONE));
5505 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5507 /* If parameter checking is enabled... */
5508 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5509 if ((phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES)
5510 || (NULL == gblCfgParams))
5511 {
5512 result = EDMA3_RM_E_INVALID_PARAM;
5513 }
5514 #endif
5516 if (EDMA3_RM_SOK == result)
5517 {
5518 /* Return the previously saved global config information for the EDMA3 HW */
5519 edma3MemCpy((void *)(gblCfgParams),
5520 (const void *)(&resMgrObj[phyCtrllerInstId].gblCfgParams),
5521 sizeof (EDMA3_RM_GblConfigParams));
5522 }
5524 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5525 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5526 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
5527 EDMA3_DVT_dCOUNTER,
5528 EDMA3_DVT_dNONE,
5529 EDMA3_DVT_dNONE));
5530 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5532 return result;
5533 }
5537 /**\fn EDMA3_RM_Result EDMA3_RM_getInstanceInitCfg (EDMA3_RM_Handle hEdmaResMgr,
5538 * EDMA3_RM_InstanceInitConfig *instanceInitConfig)
5539 * \brief Get the RM Instance specific configuration structure for different
5540 * EDMA3 resources' usage (owned resources, reserved resources etc).
5541 *
5542 * This API is used to fetch the Resource Manager Instance specific configuration
5543 * structure, for a specific shadow region. It is useful for the user who has not passed
5544 * this information during EDMA3_RM_opn() and taken the default configuration
5545 * coming along with the package. EDMA3 resources, owned and reserved by this RM
5546 * instance, will be returned from this API.
5547 *
5548 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
5549 * Manager Instance.
5550 * \param instanceInitConfig [IN/OUT] RM Instance specific configuration
5551 * structure will be returned here.
5552 *
5553 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
5554 *
5555 * \note This function is re-entrant.
5556 */
5557 EDMA3_RM_Result EDMA3_RM_getInstanceInitCfg (
5558 EDMA3_RM_Handle hEdmaResMgr,
5559 EDMA3_RM_InstanceInitConfig *instanceInitConfig)
5560 {
5561 EDMA3_RM_Result result = EDMA3_RM_SOK;
5562 EDMA3_RM_Instance *rmInstance = NULL;
5563 EDMA3_RM_Obj *rmObj = NULL;
5564 unsigned int resMgrIdx = 0u;
5565 unsigned int hwId;
5567 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5568 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5569 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
5570 EDMA3_DVT_dCOUNTER,
5571 EDMA3_DVT_dNONE,
5572 EDMA3_DVT_dNONE));
5573 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5575 /* If parameter checking is enabled... */
5576 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5577 if ((hEdmaResMgr == NULL) || (instanceInitConfig == NULL))
5578 {
5579 result = EDMA3_RM_E_INVALID_PARAM;
5580 }
5581 #endif
5583 if (result == EDMA3_RM_SOK)
5584 {
5585 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
5587 if (rmInstance == NULL)
5588 {
5589 result = EDMA3_RM_E_INVALID_PARAM;
5590 }
5591 }
5593 if (result == EDMA3_RM_SOK)
5594 {
5595 rmObj = rmInstance->pResMgrObjHandle;
5597 if (rmObj == NULL)
5598 {
5599 result = EDMA3_RM_E_INVALID_PARAM;
5600 }
5601 }
5603 if (result == EDMA3_RM_SOK)
5604 {
5605 hwId = rmObj->phyCtrllerInstId;
5607 for (resMgrIdx = 0u; resMgrIdx < EDMA3_MAX_RM_INSTANCES; resMgrIdx++)
5608 {
5609 if (rmInstance == ((EDMA3_RM_Instance *)(ptrRMIArray) +
5610 (hwId*EDMA3_MAX_RM_INSTANCES) +
5611 resMgrIdx))
5612 {
5613 /* RM Id found. Return the specific config info to the user. */
5614 edma3MemCpy((void *)(instanceInitConfig),
5615 (const void *)((EDMA3_RM_InstanceInitConfig *)(ptrInitCfgArray) +
5616 (hwId*EDMA3_MAX_RM_INSTANCES) +
5617 resMgrIdx),
5618 sizeof (EDMA3_RM_InstanceInitConfig));
5619 break;
5620 }
5621 }
5623 if (EDMA3_MAX_RM_INSTANCES == resMgrIdx)
5624 {
5625 /* RM Id not found, report error... */
5626 result = EDMA3_RM_E_INVALID_PARAM;
5627 }
5628 }
5630 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5631 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5632 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
5633 EDMA3_DVT_dCOUNTER,
5634 EDMA3_DVT_dNONE,
5635 EDMA3_DVT_dNONE));
5636 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5638 return result;
5639 }
5643 /**
5644 * \brief EDMA3 Resource Manager IOCTL
5645 *
5646 * This function provides IOCTL functionality for EDMA3 Resource Manager
5647 *
5648 * \param hEdmaResMgr [IN] Handle to the previously opened Resource
5649 * Manager Instance.
5650 * \param cmd [IN] IOCTL command to be performed
5651 * \param cmdArg [IN/OUT] IOCTL command argument (if any)
5652 * \param param [IN/OUT] Device/Cmd specific argument
5653 *
5654 * \return EDMA3_RM_SOK or EDMA3_RM Error Code
5655 */
5656 EDMA3_RM_Result EDMA3_RM_Ioctl(
5657 EDMA3_RM_Handle hEdmaResMgr,
5658 EDMA3_RM_IoctlCmd cmd,
5659 void *cmdArg,
5660 void *param
5661 )
5662 {
5663 EDMA3_RM_Result result = EDMA3_RM_SOK;
5664 EDMA3_RM_Instance *rmInstance = NULL;
5665 unsigned int paramInitRequired = 0xFFu;
5666 unsigned int regModificationRequired = 0xFFu;
5667 unsigned int *ret_val = NULL;
5669 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5670 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5671 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_START,
5672 EDMA3_DVT_dCOUNTER,
5673 EDMA3_DVT_dNONE,
5674 EDMA3_DVT_dNONE));
5675 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5677 /* If parameter checking is enabled... */
5678 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5679 if (hEdmaResMgr == NULL)
5680 {
5681 result = EDMA3_RM_E_INVALID_PARAM;
5682 }
5684 if ((cmd <= EDMA3_RM_IOCTL_MIN_IOCTL)
5685 || (cmd >= EDMA3_RM_IOCTL_MAX_IOCTL))
5686 {
5687 result = EDMA3_RM_E_INVALID_PARAM;
5688 }
5689 #endif
5691 if (result == EDMA3_RM_SOK)
5692 {
5693 rmInstance = (EDMA3_RM_Instance *)hEdmaResMgr;
5695 if (rmInstance == NULL)
5696 {
5697 result = EDMA3_RM_E_INVALID_PARAM;
5698 }
5699 }
5701 /* To remove CCS warnings */
5702 (void)param;
5704 if (result == EDMA3_RM_SOK)
5705 {
5706 switch (cmd)
5707 {
5708 case EDMA3_RM_IOCTL_SET_PARAM_CLEAR_OPTION:
5709 {
5710 paramInitRequired = (unsigned int)cmdArg;
5712 /* If parameter checking is enabled... */
5713 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5714 if ((paramInitRequired != 0u)
5715 && (paramInitRequired != 1u))
5716 {
5717 result = EDMA3_RM_E_INVALID_PARAM;
5718 }
5719 #endif
5721 /* Check if the parameters are OK. */
5722 if (EDMA3_RM_SOK == result)
5723 {
5724 /* Set/Reset the flag which is being used to do the PaRAM clearing. */
5725 rmInstance->paramInitRequired = paramInitRequired;
5726 }
5728 break;
5729 }
5731 case EDMA3_RM_IOCTL_GET_PARAM_CLEAR_OPTION:
5732 {
5733 /* If parameter checking is enabled... */
5734 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5735 if (NULL == cmdArg)
5736 {
5737 result = EDMA3_RM_E_INVALID_PARAM;
5738 }
5739 #endif
5741 /* Check if the parameters are OK. */
5742 if (EDMA3_RM_SOK == result)
5743 {
5744 ret_val = (unsigned int *)cmdArg;
5746 /* Get the flag which is being used to do the PaRAM clearing. */
5747 *ret_val = rmInstance->paramInitRequired;
5748 }
5750 break;
5751 }
5753 case EDMA3_RM_IOCTL_SET_GBL_REG_MODIFY_OPTION:
5754 {
5755 regModificationRequired = (unsigned int)cmdArg;
5757 /* If parameter checking is enabled... */
5758 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5759 if ((regModificationRequired != 0u)
5760 && (regModificationRequired != 1u))
5761 {
5762 /* All other values are invalid. */
5763 result = EDMA3_RM_E_INVALID_PARAM;
5764 }
5765 #endif
5767 /* Check if the parameters are OK. */
5768 if (EDMA3_RM_SOK == result)
5769 {
5770 /**
5771 * Set/Reset the flag which is being used to do the global
5772 * registers and PaRAM modification.
5773 */
5774 rmInstance->regModificationRequired = regModificationRequired;
5775 }
5777 break;
5778 }
5780 case EDMA3_RM_IOCTL_GET_GBL_REG_MODIFY_OPTION:
5781 {
5782 /* If parameter checking is enabled... */
5783 #ifndef EDMA3_RM_PARAM_CHECK_DISABLE
5784 if (NULL == cmdArg)
5785 {
5786 result = EDMA3_RM_E_INVALID_PARAM;
5787 }
5788 #endif
5790 /* Check if the parameters are OK. */
5791 if (EDMA3_RM_SOK == result)
5792 {
5793 ret_val = (unsigned int *)cmdArg;
5795 /**
5796 * Get the flag which is being used to do the global
5797 * registers and PaRAM modification.
5798 */
5799 *ret_val = rmInstance->regModificationRequired;
5800 }
5802 break;
5803 }
5805 default:
5806 /* Hey dude! you passed invalid IOCTL cmd */
5807 result = EDMA3_RM_E_INVALID_PARAM;
5809 }
5810 }
5813 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5814 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5815 EDMA3_DVT_DESC(EDMA3_DVT_eFUNC_END,
5816 EDMA3_DVT_dCOUNTER,
5817 EDMA3_DVT_dNONE,
5818 EDMA3_DVT_dNONE));
5819 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5821 return result;
5823 }
5827 /**
5828 * edma3ComplHandler
5829 * \brief Interrupt handler for successful transfer completion.
5830 *
5831 * \note This function first disables its own interrupt to make it non-
5832 * entrant. Later, after calling all the callback functions, it
5833 * re-enables its own interrupt.
5834 *
5835 * \return None.
5836 */
5837 static void edma3ComplHandler (const EDMA3_RM_Obj *rmObj)
5838 {
5839 unsigned int Cnt;
5840 volatile EDMA3_CCRL_Regs *ptrEdmaccRegs = NULL;
5841 volatile EDMA3_CCRL_ShadowRegs *shadowRegs = NULL;
5842 volatile unsigned int pendingIrqs;
5843 unsigned int indexl;
5844 unsigned int indexh;
5845 unsigned int edma3Id;
5847 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5848 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5849 EDMA3_DVT_DESC(EDMA3_DVT_eINT_START,
5850 EDMA3_DVT_dNONE,
5851 EDMA3_DVT_dNONE,
5852 EDMA3_DVT_dNONE));
5853 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5855 assert (NULL != rmObj);
5857 edma3Id = rmObj->phyCtrllerInstId;
5858 ptrEdmaccRegs =
5859 (volatile EDMA3_CCRL_Regs *)rmObj->gblCfgParams.globalRegs;
5860 if (ptrEdmaccRegs != NULL)
5861 {
5862 shadowRegs = (volatile EDMA3_CCRL_ShadowRegs *)
5863 (&ptrEdmaccRegs->SHADOW[edma3RegionId]);
5864 }
5866 Cnt = 0u;
5867 pendingIrqs = 0u;
5868 indexl = 1u;
5869 indexh = 1u;
5871 if((shadowRegs->IPR !=0 ) || (shadowRegs->IPRH !=0 ))
5872 {
5873 /**
5874 * Since an interrupt has found, we have to make sure that this
5875 * interrupt (TCC) belongs to the TCCs allocated by us only.
5876 * It might happen that someone else, who is using EDMA3 also,
5877 * is the owner of this interrupt channel i.e. the TCC.
5878 * For this, use the allocatedTCCs[], to check which all interrupt
5879 * channels are owned by the EDMA3 RM Instances.
5880 */
5882 edma3OsProtectEntry (edma3Id,
5883 EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION,
5884 NULL);
5886 /* Loop for EDMA3_RM_COMPL_HANDLER_RETRY_COUNT number of time,
5887 breaks when no pending interrupt is found */
5888 while ((Cnt < EDMA3_RM_COMPL_HANDLER_RETRY_COUNT)
5889 && ((indexl != 0u) || (indexh != 0u)))
5890 {
5891 indexl = 0u;
5892 pendingIrqs = shadowRegs->IPR;
5894 /**
5895 * Choose interrupts coming from our allocated TCCs
5896 * and MASK remaining ones.
5897 */
5898 pendingIrqs = (pendingIrqs & allocatedTCCs[edma3Id][0u]);
5900 while (pendingIrqs)
5901 {
5902 /*Process all the pending interrupts*/
5903 if((pendingIrqs & 1u) == TRUE)
5904 {
5905 /**
5906 * If the user has not given any callback function
5907 * while requesting the TCC, its TCC specific bit
5908 * in the IPR register will NOT be cleared.
5909 */
5910 if(edma3IntrParams[edma3Id][indexl].tccCb != NULL)
5911 {
5912 /* here write to ICR to clear the corresponding IPR bits*/
5913 shadowRegs->ICR = (1u << indexl);
5915 edma3IntrParams[edma3Id][indexl].tccCb (indexl,
5916 EDMA3_RM_XFER_COMPLETE,
5917 edma3IntrParams[edma3Id][indexl].cbData);
5918 }
5919 }
5920 ++indexl;
5921 pendingIrqs >>= 1u;
5922 }
5924 indexh = 0u;
5925 pendingIrqs = shadowRegs->IPRH;
5927 /**
5928 * Choose interrupts coming from our allocated TCCs
5929 * and MASK remaining ones.
5930 */
5931 pendingIrqs = (pendingIrqs & allocatedTCCs[edma3Id][1u]);
5933 while (pendingIrqs)
5934 {
5935 /*Process all the pending interrupts*/
5936 if((pendingIrqs & 1u)==TRUE)
5937 {
5938 /**
5939 * If the user has not given any callback function
5940 * while requesting the TCC, its TCC specific bit
5941 * in the IPRH register will NOT be cleared.
5942 */
5943 if(edma3IntrParams[edma3Id][32u+indexh].tccCb!=NULL)
5944 {
5945 /* here write to ICR to clear the corresponding IPR bits*/
5946 shadowRegs->ICRH = (1u << indexh);
5948 edma3IntrParams[edma3Id][32u+indexh].tccCb(32u+indexh,
5949 EDMA3_RM_XFER_COMPLETE,
5950 edma3IntrParams[edma3Id][32u+indexh].cbData);
5951 }
5952 }
5953 ++indexh;
5954 pendingIrqs >>= 1u;
5955 }
5957 Cnt++;
5958 }
5960 indexl = (shadowRegs->IPR & allocatedTCCs[edma3Id][0u]);
5961 indexh = (shadowRegs->IPRH & allocatedTCCs[edma3Id][1u]);
5963 if((indexl !=0 ) || (indexh !=0 ))
5964 {
5965 shadowRegs->IEVAL=0x1u;
5966 }
5968 edma3OsProtectExit (rmObj->phyCtrllerInstId,
5969 EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION,
5970 NULL);
5971 }
5973 #ifdef EDMA3_INSTRUMENTATION_ENABLED
5974 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3",
5975 EDMA3_DVT_DESC(EDMA3_DVT_eINT_END,
5976 EDMA3_DVT_dNONE,
5977 EDMA3_DVT_dNONE,
5978 EDMA3_DVT_dNONE));
5979 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
5980 }
5983 void lisrEdma3ComplHandler0(unsigned int edma3InstanceId)
5984 {
5985 /* Invoke Completion Handler ISR */
5986 edma3ComplHandler(&resMgrObj[edma3InstanceId]);
5987 }
5990 /**
5991 * \brief Interrupt handler for Channel Controller Error.
5992 *
5993 * \note This function first disables its own interrupt to make it non-
5994 * entrant. Later, after calling all the callback functions, it
5995 * re-enables its own interrupt.
5996 *
5997 * \return None.
5998 */
5999 static void edma3CCErrHandler(const EDMA3_RM_Obj *rmObj)
6000 {
6001 unsigned int Cnt = 0u;
6002 unsigned int resMgrInstIdx = 0u;
6003 volatile EDMA3_CCRL_Regs *ptrEdmaccRegs = NULL;
6004 volatile EDMA3_CCRL_ShadowRegs *shadowRegs = NULL;
6005 volatile unsigned int pendingIrqs;
6006 unsigned int index;
6007 unsigned int evtqueNum;
6008 EDMA3_RM_Instance *rm_instance = NULL;
6009 unsigned int edma3Id;
6010 unsigned int num_rm_instances_opened;
6011 EDMA3_RM_Instance *rmInstance = NULL;
6012 unsigned int ownedDmaError = 0;
6013 unsigned int ownedDmaHError = 0;
6014 unsigned int ownedQdmaError = 0;
6016 #ifdef EDMA3_INSTRUMENTATION_ENABLED
6017 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3_CCERR",
6018 EDMA3_DVT_DESC(EDMA3_DVT_eINT_START,
6019 EDMA3_DVT_dNONE,
6020 EDMA3_DVT_dNONE,
6021 EDMA3_DVT_dNONE));
6022 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
6024 assert (rmObj != NULL);
6026 edma3Id = rmObj->phyCtrllerInstId;
6027 ptrEdmaccRegs = (volatile EDMA3_CCRL_Regs *)rmObj->gblCfgParams.globalRegs;
6028 if (ptrEdmaccRegs != NULL)
6029 {
6030 shadowRegs = (volatile EDMA3_CCRL_ShadowRegs *)&ptrEdmaccRegs->SHADOW[edma3RegionId];
6031 rmInstance = ((EDMA3_RM_Instance *)(ptrRMIArray)
6032 + (edma3Id*EDMA3_MAX_RM_INSTANCES)
6033 + edma3RegionId);
6035 pendingIrqs = 0u;
6036 index = 1u;
6038 if(((ptrEdmaccRegs->EMR != 0 )
6039 || (ptrEdmaccRegs->EMRH != 0 ))
6040 || ((ptrEdmaccRegs->QEMR != 0)
6041 || (ptrEdmaccRegs->CCERR != 0)))
6042 {
6043 edma3OsProtectEntry (edma3Id,
6044 EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR,
6045 NULL);
6047 /* Loop for EDMA3_RM_CCERR_HANDLER_RETRY_COUNT number of time,
6048 breaks when no pending interrupt is found */
6049 while ((Cnt < EDMA3_RM_CCERR_HANDLER_RETRY_COUNT)
6050 && (index != 0u))
6051 {
6052 index = 0u;
6053 pendingIrqs = ptrEdmaccRegs->EMR;
6055 while (pendingIrqs)
6056 {
6057 /*Process all the pending interrupts*/
6058 if((pendingIrqs & 1u)==TRUE)
6059 {
6060 unsigned int mappedTcc = 0u;
6062 /**
6063 * Using the 'index' value (basically the DMA
6064 * channel), fetch the corresponding TCC
6065 * value, mapped to this DMA channel.
6066 */
6067 mappedTcc = edma3DmaChTccMapping[edma3Id][index];
6069 /**
6070 * Ensure that the mapped tcc is valid and the call
6071 * back is not NULL
6072 */
6073 if (mappedTcc < EDMA3_MAX_TCC)
6074 {
6075 /**
6076 * TCC owned and allocated by RM.
6077 * Write to EMCR to clear the corresponding EMR bits.
6078 */
6079 ptrEdmaccRegs->EMCR = (1u<<index);
6080 /*Clear any SER*/
6081 shadowRegs->SECR = (1u<<index);
6083 /* Call the callback function if registered earlier. */
6084 if((edma3IntrParams[edma3Id][mappedTcc].tccCb) != NULL)
6085 {
6086 edma3IntrParams[edma3Id][mappedTcc].tccCb (
6087 mappedTcc,
6088 EDMA3_RM_E_CC_DMA_EVT_MISS,
6089 edma3IntrParams[edma3Id][mappedTcc].cbData
6090 );
6091 }
6092 }
6093 else
6094 {
6095 /**
6096 * DMA channel not owned by the RM instance.
6097 * Check the global error interrupt clearing option.
6098 * If it is TRUE, clear the error interupt else leave
6099 * it like that.
6100 */
6101 #if (EDMA3_RM_RES_CLEAR_ERROR_STATUS_FOR_ALL_CHANNELS == TRUE)
6102 /* here write to EMCR to clear the corresponding EMR bits. */
6103 ptrEdmaccRegs->EMCR = (1u<<index);
6104 /*Clear any SER*/
6105 ptrEdmaccRegs->SECR = (1u<<index);
6106 #endif
6107 }
6108 }
6109 ++index;
6110 pendingIrqs >>= 1u;
6111 }
6113 index = 0u;
6114 pendingIrqs = ptrEdmaccRegs->EMRH;
6115 while (pendingIrqs)
6116 {
6117 /*Process all the pending interrupts*/
6118 if((pendingIrqs & 1u)==TRUE)
6119 {
6120 unsigned int mappedTcc = 0u;
6122 /**
6123 * Using the 'index' value (basically the DMA
6124 * channel), fetch the corresponding TCC
6125 * value, mapped to this DMA channel.
6126 */
6127 mappedTcc = edma3DmaChTccMapping[edma3Id][32u+index];
6129 /**
6130 * Ensure that the mapped tcc is valid and the call
6131 * back is not NULL
6132 */
6133 if (mappedTcc < EDMA3_MAX_TCC)
6134 {
6135 /**
6136 * TCC owned and allocated by RM.
6137 * Write to EMCR to clear the corresponding EMR bits.
6138 */
6139 ptrEdmaccRegs->EMCRH = (1u<<index);
6140 /*Clear any SERH*/
6141 shadowRegs->SECRH = (1u<<index);
6143 /* Call the callback function if registered earlier. */
6144 if((edma3IntrParams[edma3Id][mappedTcc].tccCb) != NULL)
6145 {
6146 edma3IntrParams[edma3Id][mappedTcc].tccCb (
6147 mappedTcc,
6148 EDMA3_RM_E_CC_DMA_EVT_MISS,
6149 edma3IntrParams[edma3Id][mappedTcc].cbData
6150 );
6151 }
6152 }
6153 else
6154 {
6155 /**
6156 * DMA channel not owned by the RM instance.
6157 * Check the global error interrupt clearing option.
6158 * If it is TRUE, clear the error interupt else leave
6159 * it like that.
6160 */
6161 #if (EDMA3_RM_RES_CLEAR_ERROR_STATUS_FOR_ALL_CHANNELS == TRUE)
6162 /**
6163 * TCC NOT owned by RM.
6164 * Write to EMCRH to clear the corresponding EMRH bits.
6165 */
6166 ptrEdmaccRegs->EMCRH = (1u<<index);
6167 /*Clear any SERH*/
6168 shadowRegs->SECRH = (1u<<index);
6169 #endif
6170 }
6171 }
6172 ++index;
6173 pendingIrqs >>= 1u;
6174 }
6176 index = 0u;
6177 pendingIrqs = ptrEdmaccRegs->QEMR;
6178 while (pendingIrqs)
6179 {
6180 /*Process all the pending interrupts*/
6181 if((pendingIrqs & 1u)==TRUE)
6182 {
6183 unsigned int mappedTcc = 0u;
6185 /**
6186 * Using the 'index' value (basically the QDMA
6187 * channel), fetch the corresponding TCC
6188 * value, mapped to this QDMA channel.
6189 */
6190 mappedTcc = edma3QdmaChTccMapping[edma3Id][index];
6192 if (mappedTcc < EDMA3_MAX_TCC)
6193 {
6194 /* here write to QEMCR to clear the corresponding QEMR bits*/
6195 ptrEdmaccRegs->QEMCR = (1u<<index);
6196 /*Clear any QSER*/
6197 shadowRegs->QSECR = (1u<<index);
6199 if((edma3IntrParams[edma3Id][mappedTcc].tccCb) != NULL)
6200 {
6201 edma3IntrParams[edma3Id][mappedTcc].tccCb (
6202 mappedTcc,
6203 EDMA3_RM_E_CC_QDMA_EVT_MISS,
6204 edma3IntrParams[edma3Id][mappedTcc].cbData
6205 );
6206 }
6207 }
6208 else
6209 {
6210 /**
6211 * QDMA channel not owned by the RM instance.
6212 * Check the global error interrupt clearing option.
6213 * If it is TRUE, clear the error interupt else leave
6214 * the ISR.
6215 */
6216 #if (EDMA3_RM_RES_CLEAR_ERROR_STATUS_FOR_ALL_CHANNELS == TRUE)
6217 /* here write to QEMCR to clear the corresponding QEMR bits*/
6218 ptrEdmaccRegs->QEMCR = (1u<<index);
6220 /*Clear any QSER*/
6221 ptrEdmaccRegs->QSECR = (1u<<index);
6222 #endif
6223 }
6224 }
6225 ++index;
6226 pendingIrqs >>= 1u;
6227 }
6229 index = 0u;
6230 pendingIrqs = ptrEdmaccRegs->CCERR;
6231 if (pendingIrqs!=NULL)
6232 {
6233 /* Process all the pending CC error interrupts. */
6235 /* Queue threshold error for different event queues.*/
6236 for (evtqueNum = 0u; evtqueNum < rmObj->gblCfgParams.numEvtQueue; evtqueNum++)
6237 {
6238 if((pendingIrqs & (1u << evtqueNum)) != NULL)
6239 {
6240 /**
6241 * Queue threshold error for queue 'evtqueNum' raised.
6242 * Inform all the RM instances working on this region
6243 * about the error by calling their global callback functions.
6244 */
6245 num_rm_instances_opened = resMgrObj[edma3Id].numOpens;
6246 for (resMgrInstIdx = 0u; num_rm_instances_opened; ++resMgrInstIdx)
6247 {
6248 /* Check whether the RM instance opened working on this region */
6249 rm_instance = ((EDMA3_RM_Instance *)(ptrRMIArray) + (edma3Id*EDMA3_MAX_RM_INSTANCES) + resMgrInstIdx);
6250 if (NULL != rm_instance)
6251 {
6252 if (rm_instance->initParam.regionId == edma3RegionId)
6253 {
6254 /* Region id matches, call the callback function */
6255 if (rm_instance->initParam.gblerrCbParams.gblerrCb != NULL)
6256 {
6257 rm_instance->initParam.gblerrCbParams.gblerrCb(
6258 EDMA3_RM_E_CC_QUE_THRES_EXCEED,
6259 evtqueNum,
6260 rm_instance->initParam.gblerrCbParams.gblerrData);
6261 }
6262 }
6263 }
6265 /* Check next opened instance */
6266 num_rm_instances_opened--;
6267 }
6269 /* Clear the error interrupt. */
6270 ptrEdmaccRegs->CCERRCLR = (1u << evtqueNum);
6271 }
6272 }
6275 /* Transfer completion code error. */
6276 if ((pendingIrqs & (1 << EDMA3_CCRL_CCERR_TCCERR_SHIFT))!=NULL)
6277 {
6278 /**
6279 * Transfer completion code error raised.
6280 * Inform all the RM instances working on this region
6281 * about the error by calling their global callback functions.
6282 */
6283 num_rm_instances_opened = resMgrObj[edma3Id].numOpens;
6284 for (resMgrInstIdx = 0u; num_rm_instances_opened; ++resMgrInstIdx)
6285 {
6286 /* Check whether the RM instance opened working on this region */
6287 rm_instance = ((EDMA3_RM_Instance *)(ptrRMIArray) + (edma3Id*EDMA3_MAX_RM_INSTANCES) + resMgrInstIdx);
6288 if (NULL != rm_instance)
6289 {
6290 if (rm_instance->initParam.regionId == edma3RegionId)
6291 {
6292 /* Region id matches, call the callback function */
6293 if (rm_instance->initParam.gblerrCbParams.gblerrCb != NULL)
6294 {
6295 rm_instance->initParam.gblerrCbParams.gblerrCb(
6296 EDMA3_RM_E_CC_TCC,
6297 NULL,
6298 rm_instance->initParam.gblerrCbParams.gblerrData);
6299 }
6300 }
6301 }
6303 /* Check next opened instance */
6304 num_rm_instances_opened--;
6305 }
6307 ptrEdmaccRegs->CCERRCLR = (1<<EDMA3_CCRL_CCERR_TCCERR_SHIFT);
6308 }
6310 ++index;
6311 }
6313 Cnt++;
6314 }
6317 /**
6318 * Read the error registers again. If any interrupt is pending,
6319 * write the EEVAL register.
6320 * Moreover, according to the global error interrupt clearing
6321 * option, check either error bits associated with all the
6322 * DMA/QDMA channels (option is SET) OR check error bits
6323 * associated with owned DMA/QDMA channels.
6324 */
6325 #if (EDMA3_RM_RES_CLEAR_ERROR_STATUS_FOR_ALL_CHANNELS == TRUE)
6326 /* To remove warning. */
6327 rmInstance = rmInstance;
6329 /* Check all the error bits. */
6330 ownedDmaError = ptrEdmaccRegs->EMR;
6331 ownedDmaHError = ptrEdmaccRegs->EMRH;
6332 ownedQdmaError = ptrEdmaccRegs->QEMR;
6333 #else
6334 /* Check ONLY owned error bits. */
6335 ownedDmaError = (ptrEdmaccRegs->EMR & rmInstance->initParam.rmInstInitConfig->ownDmaChannels[0u]);
6336 ownedDmaHError = (ptrEdmaccRegs->EMRH & rmInstance->initParam.rmInstInitConfig->ownDmaChannels[1u]);
6337 ownedQdmaError = (ptrEdmaccRegs->QEMR & rmInstance->initParam.rmInstInitConfig->ownQdmaChannels[0u]);
6338 #endif
6340 if (((ownedDmaError != 0 ) || (ownedDmaHError != 0 ))
6341 || ((ownedQdmaError != 0) || (ptrEdmaccRegs->CCERR != 0)))
6342 {
6343 ptrEdmaccRegs->EEVAL=0x1u;
6344 }
6346 edma3OsProtectExit (rmObj->phyCtrllerInstId,
6347 EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR,
6348 NULL);
6349 }
6350 }
6352 #ifdef EDMA3_INSTRUMENTATION_ENABLED
6353 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3_CCERR",
6354 EDMA3_DVT_DESC(EDMA3_DVT_eINT_END,
6355 EDMA3_DVT_dNONE,
6356 EDMA3_DVT_dNONE,
6357 EDMA3_DVT_dNONE));
6358 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
6359 }
6361 void lisrEdma3CCErrHandler0(unsigned int edma3InstanceId)
6362 {
6363 /* Invoke CC Error Handler ISR */
6364 edma3CCErrHandler(&resMgrObj[edma3InstanceId]);
6365 }
6369 /**
6370 * \brief Interrupt handler for Transfer Controller Error.
6371 *
6372 * \note This function first disables its own interrupt to make it non-
6373 * entrant. Later, after calling all the callback functions, it
6374 * re-enables its own interrupt.
6375 *
6376 * \return None.
6377 */
6378 static void edma3TCErrHandler (const EDMA3_RM_Obj *rmObj, unsigned int tcNum)
6379 {
6380 volatile EDMA3_TCRL_Regs *tcRegs = NULL;
6381 unsigned int tcMemErrRdWr = 0u;
6382 unsigned int resMgrInstIdx = 0u;
6383 EDMA3_RM_Instance *rm_instance = NULL;
6384 unsigned int edma3Id;
6385 unsigned int num_rm_instances_opened;
6387 #ifdef EDMA3_INSTRUMENTATION_ENABLED
6388 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3_TCERR",
6389 EDMA3_DVT_DESC(EDMA3_DVT_eINT_START,
6390 EDMA3_DVT_dNONE,
6391 EDMA3_DVT_dNONE,
6392 EDMA3_DVT_dNONE));
6393 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
6395 assert ((rmObj != NULL) && (tcNum < rmObj->gblCfgParams.numTcs));
6397 if (rmObj->gblCfgParams.tcRegs[tcNum] != NULL)
6398 {
6399 tcRegs = (volatile EDMA3_TCRL_Regs *)(rmObj->gblCfgParams.tcRegs[tcNum]);
6400 edma3Id = rmObj->phyCtrllerInstId;
6401 }
6403 if (tcRegs != NULL)
6404 {
6405 if(tcRegs->ERRSTAT != 0)
6406 {
6407 edma3OsProtectEntry (rmObj->phyCtrllerInstId,
6408 EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR,
6409 &tcNum);
6411 if((tcRegs->ERRSTAT & (1 << EDMA3_TCRL_ERRSTAT_BUSERR_SHIFT))!=NULL)
6412 {
6413 /* Bus error event. */
6414 /**
6415 * EDMA3TC has detected an error at source or destination
6416 * address. Error information can be read from the error
6417 * details register (ERRDET).
6418 */
6419 tcMemErrRdWr = tcRegs->ERRDET & (EDMA3_TCRL_ERRDET_STAT_MASK);
6420 if ((tcMemErrRdWr > 0u) && (tcMemErrRdWr < 8u))
6421 {
6422 /**
6423 * Inform all the RM instances working on this region
6424 * about the error by calling their global callback functions.
6425 */
6426 num_rm_instances_opened = resMgrObj[edma3Id].numOpens;
6427 for (resMgrInstIdx = 0u; num_rm_instances_opened; ++resMgrInstIdx)
6428 {
6429 /* Check whether the RM instance opened working on this region */
6430 rm_instance = ((EDMA3_RM_Instance *)(ptrRMIArray) + (edma3Id*EDMA3_MAX_RM_INSTANCES) + resMgrInstIdx);
6431 if (NULL != rm_instance)
6432 {
6433 if (rm_instance->initParam.regionId == edma3RegionId)
6434 {
6435 /* Region id matches, call the callback function */
6436 if (rm_instance->initParam.gblerrCbParams.gblerrCb != NULL)
6437 {
6438 rm_instance->initParam.gblerrCbParams.gblerrCb(
6439 EDMA3_RM_E_TC_MEM_LOCATION_READ_ERROR,
6440 tcNum,
6441 rm_instance->initParam.gblerrCbParams.gblerrData);
6442 }
6443 }
6444 }
6446 /* Check next opened instance */
6447 num_rm_instances_opened--;
6448 }
6449 }
6450 else
6451 {
6452 if ((tcMemErrRdWr >= 8u) && (tcMemErrRdWr <= 0xFu))
6453 {
6454 /**
6455 * Inform all the RM instances working on this region
6456 * about the error by calling their global callback functions.
6457 */
6458 num_rm_instances_opened = resMgrObj[edma3Id].numOpens;
6459 for (resMgrInstIdx = 0u; num_rm_instances_opened; ++resMgrInstIdx)
6460 {
6461 /* Check whether the RM instance opened working on this region */
6462 rm_instance = ((EDMA3_RM_Instance *)(ptrRMIArray) + (edma3Id*EDMA3_MAX_RM_INSTANCES) + resMgrInstIdx);
6463 if (NULL != rm_instance)
6464 {
6465 if (rm_instance->initParam.regionId == edma3RegionId)
6466 {
6467 /* Region id matches, call the callback function */
6468 if (rm_instance->initParam.gblerrCbParams.gblerrCb != NULL)
6469 {
6470 rm_instance->initParam.gblerrCbParams.gblerrCb(
6471 EDMA3_RM_E_TC_MEM_LOCATION_WRITE_ERROR,
6472 tcNum,
6473 rm_instance->initParam.gblerrCbParams.gblerrData);
6474 }
6475 }
6476 }
6478 /* Check next opened instance */
6479 num_rm_instances_opened--;
6480 }
6481 }
6482 }
6483 tcRegs->ERRCLR = (1<<EDMA3_TCRL_ERRSTAT_BUSERR_SHIFT);
6484 }
6485 else
6486 {
6487 /* Transfer request (TR) error event. */
6488 if((tcRegs->ERRSTAT & (1 << EDMA3_TCRL_ERRSTAT_TRERR_SHIFT))!=NULL)
6489 {
6490 num_rm_instances_opened = resMgrObj[edma3Id].numOpens;
6491 for (resMgrInstIdx = 0u; num_rm_instances_opened; ++resMgrInstIdx)
6492 {
6493 /* Check whether the RM instance opened working on this region */
6494 rm_instance = ((EDMA3_RM_Instance *)(ptrRMIArray) + (edma3Id*EDMA3_MAX_RM_INSTANCES) + resMgrInstIdx);
6495 if (NULL != rm_instance)
6496 {
6497 if (rm_instance->initParam.regionId == edma3RegionId)
6498 {
6499 /* Region id matches, call the callback function */
6500 if (rm_instance->initParam.gblerrCbParams.gblerrCb != NULL)
6501 {
6502 rm_instance->initParam.gblerrCbParams.gblerrCb(
6503 EDMA3_RM_E_TC_TR_ERROR,
6504 tcNum,
6505 rm_instance->initParam.gblerrCbParams.gblerrData);
6506 }
6507 }
6508 }
6510 /* Check next opened instance */
6511 num_rm_instances_opened--;
6512 }
6514 tcRegs->ERRCLR = (1<<EDMA3_TCRL_ERRSTAT_TRERR_SHIFT);
6515 }
6516 else
6517 {
6518 if((tcRegs->ERRSTAT & (1 << EDMA3_TCRL_ERRSTAT_MMRAERR_SHIFT))!=NULL)
6519 {
6520 num_rm_instances_opened = resMgrObj[edma3Id].numOpens;
6521 for (resMgrInstIdx = 0u; num_rm_instances_opened; ++resMgrInstIdx)
6522 {
6523 /* Check whether the RM instance opened working on this region */
6524 rm_instance = ((EDMA3_RM_Instance *)(ptrRMIArray) + (edma3Id*EDMA3_MAX_RM_INSTANCES) + resMgrInstIdx);
6525 if (NULL != rm_instance)
6526 {
6527 if (rm_instance->initParam.regionId == edma3RegionId)
6528 {
6529 /* Region id matches, call the callback function */
6530 if (rm_instance->initParam.gblerrCbParams.gblerrCb != NULL)
6531 {
6532 rm_instance->initParam.gblerrCbParams.gblerrCb(
6533 EDMA3_RM_E_TC_INVALID_ADDR,
6534 tcNum,
6535 rm_instance->initParam.gblerrCbParams.gblerrData);
6536 }
6537 }
6538 }
6540 /* Check next opened instance */
6541 num_rm_instances_opened--;
6542 }
6544 tcRegs->ERRCLR = (1<<EDMA3_TCRL_ERRSTAT_MMRAERR_SHIFT);
6545 }
6546 }
6547 }
6549 edma3OsProtectExit (rmObj->phyCtrllerInstId,
6550 EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR,
6551 tcNum);
6552 }
6553 }
6555 #ifdef EDMA3_INSTRUMENTATION_ENABLED
6556 EDMA3_LOG_EVENT(&DVTEvent_Log,"EDMA3_TCERR",
6557 EDMA3_DVT_DESC(EDMA3_DVT_eINT_END,
6558 EDMA3_DVT_dNONE,
6559 EDMA3_DVT_dNONE,
6560 EDMA3_DVT_dNONE));
6561 #endif /* EDMA3_INSTRUMENTATION_ENABLED */
6562 }
6566 /*
6567 * ======== lisrEdma3TC0ErrHandler0 ========
6568 * EDMA3 instance 0 TC0 Error Interrupt Service Routine
6569 */
6570 void lisrEdma3TC0ErrHandler0(unsigned int edma3InstanceId)
6571 {
6572 /* Invoke Error Handler ISR for TC0*/
6573 edma3TCErrHandler(&resMgrObj[edma3InstanceId], 0u);
6574 }
6577 /*
6578 * ======== lisrEdma3TC1ErrHandler0 ========
6579 * EDMA3 instance 0 TC1 Error Interrupt Service Routine
6580 */
6581 void lisrEdma3TC1ErrHandler0(unsigned int edma3InstanceId)
6582 {
6583 /* Invoke Error Handler ISR for TC1*/
6584 edma3TCErrHandler(&resMgrObj[edma3InstanceId], 1u);
6585 }
6587 /*
6588 * ======== lisrEdma3TC2ErrHandler0 ========
6589 * EDMA3 instance 0 TC2 Error Interrupt Service Routine
6590 */
6591 void lisrEdma3TC2ErrHandler0(unsigned int edma3InstanceId)
6592 {
6593 /* Invoke Error Handler ISR for TC2*/
6594 edma3TCErrHandler(&resMgrObj[edma3InstanceId], 2u);
6595 }
6597 /*
6598 * ======== lisrEdma3TC3ErrHandler0 ========
6599 * EDMA3 instance 0 TC3 Error Interrupt Service Routine
6600 */
6601 void lisrEdma3TC3ErrHandler0(unsigned int edma3InstanceId)
6602 {
6603 /* Invoke Error Handler ISR for TC3*/
6604 edma3TCErrHandler(&resMgrObj[edma3InstanceId], 3u);
6605 }
6607 /*
6608 * ======== lisrEdma3TC4ErrHandler0 ========
6609 * EDMA3 instance 0 TC4 Error Interrupt Service Routine
6610 */
6611 void lisrEdma3TC4ErrHandler0(unsigned int edma3InstanceId)
6612 {
6613 /* Invoke Error Handler ISR for TC4*/
6614 edma3TCErrHandler(&resMgrObj[edma3InstanceId], 4u);
6615 }
6618 /*
6619 * ======== lisrEdma3TC5ErrHandler0 ========
6620 * EDMA3 instance 0 TC5 Error Interrupt Service Routine
6621 */
6622 void lisrEdma3TC5ErrHandler0(unsigned int edma3InstanceId)
6623 {
6624 /* Invoke Error Handler ISR for TC5*/
6625 edma3TCErrHandler(&resMgrObj[edma3InstanceId], 5u);
6626 }
6628 /*
6629 * ======== lisrEdma3TC6ErrHandler0 ========
6630 * EDMA3 instance 0 TC6 Error Interrupt Service Routine
6631 */
6632 /* ARGSUSED */
6633 void lisrEdma3TC6ErrHandler0(unsigned int edma3InstanceId)
6634 {
6635 /* Invoke Error Handler ISR for TC6*/
6636 edma3TCErrHandler(&resMgrObj[edma3InstanceId], 6u);
6637 }
6639 /*
6640 * ======== lisrEdma3TC7ErrHandler0 ========
6641 * EDMA3 instance 0 TC7 Error Interrupt Service Routine
6642 */
6643 void lisrEdma3TC7ErrHandler0(unsigned int edma3InstanceId)
6644 {
6645 /* Invoke Error Handler ISR for TC7*/
6646 edma3TCErrHandler(&resMgrObj[edma3InstanceId], 7u);
6647 }
6651 /* Resource Manager Internal functions - Start */
6653 /** Initialization of the Global region registers of the EDMA3 Controller */
6654 static void edma3GlobalRegionInit (unsigned int phyCtrllerInstId)
6655 {
6656 unsigned int evtQNum = 0u;
6657 volatile EDMA3_CCRL_Regs *ptrEdmaccRegs = NULL;
6659 assert (phyCtrllerInstId < EDMA3_MAX_EDMA3_INSTANCES);
6661 ptrEdmaccRegs = (volatile EDMA3_CCRL_Regs *)
6662 (resMgrObj[phyCtrllerInstId].gblCfgParams.globalRegs);
6664 if (ptrEdmaccRegs != NULL)
6665 {
6666 ptrEdmaccRegs->EMCR = EDMA3_RM_SET_ALL_BITS;
6667 ptrEdmaccRegs->EMCRH = EDMA3_RM_SET_ALL_BITS;
6668 ptrEdmaccRegs->QEMCR = EDMA3_RM_SET_ALL_BITS;
6670 /*
6671 * Set all Instance-wide EDMA3 parameters (not channel-specific)
6672 */
6674 /**
6675 * Set TC Priority among system-wide bus-masters and Queue
6676 * Watermark Level
6677 */
6678 while (evtQNum <
6679 resMgrObj[phyCtrllerInstId].gblCfgParams.numEvtQueue)
6680 {
6681 ptrEdmaccRegs->QUEPRI &= EDMA3_RM_QUEPRI_CLR_MASK(evtQNum);
6682 ptrEdmaccRegs->QUEPRI |= EDMA3_RM_QUEPRI_SET_MASK(evtQNum,
6683 resMgrObj[phyCtrllerInstId].gblCfgParams.evtQPri[evtQNum]);
6685 ptrEdmaccRegs->QWMTHRA |= EDMA3_RM_QUEWMTHR_SET_MASK(evtQNum,
6686 resMgrObj[phyCtrllerInstId].gblCfgParams.evtQueueWaterMarkLvl[evtQNum]);
6688 evtQNum++;
6689 }
6691 /* Clear CCERR register */
6692 ptrEdmaccRegs ->CCERRCLR = 0xFFFFu;
6693 }
6695 return;
6696 }
6701 /** Initialization of the Shadow region registers of the EDMA3 Controller */
6702 static void edma3ShadowRegionInit (const EDMA3_RM_Instance *pRMInstance)
6703 {
6704 unsigned int intState = 0u;
6705 volatile EDMA3_CCRL_Regs *ptrEdmaccRegs = NULL;
6706 volatile EDMA3_CCRL_ShadowRegs *ptrEdmaShadowRegs = NULL;
6707 unsigned int phyCtrllerInstId;
6708 unsigned int regionId;
6709 const EDMA3_RM_InstanceInitConfig *rmInstInitConfig = pRMInstance->initParam.rmInstInitConfig;
6711 assert (pRMInstance != NULL);
6713 if (rmInstInitConfig != NULL)
6714 {
6715 phyCtrllerInstId = pRMInstance->pResMgrObjHandle->phyCtrllerInstId;
6716 regionId = pRMInstance->initParam.regionId;
6718 ptrEdmaccRegs = (volatile EDMA3_CCRL_Regs *)
6719 (resMgrObj[phyCtrllerInstId].gblCfgParams.globalRegs);
6721 if (ptrEdmaccRegs != NULL)
6722 {
6723 ptrEdmaShadowRegs = (volatile EDMA3_CCRL_ShadowRegs *)
6724 (&ptrEdmaccRegs->SHADOW[regionId]);
6726 ptrEdmaShadowRegs->ECR = (rmInstInitConfig->ownDmaChannels[0u]
6727 | rmInstInitConfig->ownTccs[0u]);
6728 ptrEdmaShadowRegs->ECRH = (rmInstInitConfig->ownDmaChannels[1u]
6729 | rmInstInitConfig->ownTccs[1u]);
6730 ptrEdmaShadowRegs->EECR = (rmInstInitConfig->ownDmaChannels[0u]
6731 | rmInstInitConfig->ownTccs[0u]);
6732 ptrEdmaShadowRegs->SECR = (rmInstInitConfig->ownDmaChannels[0u]
6733 | rmInstInitConfig->ownTccs[0u]);
6734 ptrEdmaShadowRegs->SECRH = (rmInstInitConfig->ownDmaChannels[1u]
6735 | rmInstInitConfig->ownTccs[1u]);
6736 ptrEdmaShadowRegs->EECR = (rmInstInitConfig->ownDmaChannels[0u]
6737 | rmInstInitConfig->ownTccs[0u]);
6738 ptrEdmaShadowRegs->EECRH = (rmInstInitConfig->ownDmaChannels[1u]
6739 | rmInstInitConfig->ownTccs[1u]);
6741 ptrEdmaShadowRegs->QEECR = rmInstInitConfig->ownQdmaChannels[0u];
6743 ptrEdmaShadowRegs->IECR = (rmInstInitConfig->ownDmaChannels[0u]
6744 | rmInstInitConfig->ownTccs[0u]);
6745 ptrEdmaShadowRegs->IECRH = (rmInstInitConfig->ownDmaChannels[1u]
6746 | rmInstInitConfig->ownTccs[1u]);
6747 ptrEdmaShadowRegs->ICR = (rmInstInitConfig->ownDmaChannels[0u]
6748 | rmInstInitConfig->ownTccs[0u]);
6749 ptrEdmaShadowRegs->ICRH = (rmInstInitConfig->ownDmaChannels[1u]
6750 | rmInstInitConfig->ownTccs[1u]);
6752 ptrEdmaShadowRegs->QSECR = rmInstInitConfig->ownQdmaChannels[0u];
6754 /*
6755 * Set all EDMA3 Resource<->Region mapping parameters
6756 */
6758 /* 1. Dma Channel (and TCC) <-> Region */
6759 edma3OsProtectEntry (phyCtrllerInstId,
6760 EDMA3_OS_PROTECT_INTERRUPT,
6761 &intState);
6762 ptrEdmaccRegs->DRA[regionId].DRAE = 0u;
6763 ptrEdmaccRegs->DRA[regionId].DRAEH = 0u;
6764 edma3OsProtectExit (phyCtrllerInstId,
6765 EDMA3_OS_PROTECT_INTERRUPT,
6766 intState);
6768 /* 2. Qdma Channel <-> Region */
6769 edma3OsProtectEntry (phyCtrllerInstId,
6770 EDMA3_OS_PROTECT_INTERRUPT,
6771 &intState);
6772 ptrEdmaccRegs->QRAE[regionId] = 0u;
6773 edma3OsProtectExit (phyCtrllerInstId,
6774 EDMA3_OS_PROTECT_INTERRUPT,
6775 intState);
6776 }
6777 }
6779 return;
6780 }
6784 /** Local MemZero function */
6785 void edma3MemZero(void *dst, unsigned int len)
6786 {
6787 unsigned int i = 0u;
6788 unsigned int *ds = NULL;
6790 assert (dst != NULL);
6792 ds = (unsigned int *)dst;
6794 for (i = 0 ; i < len/4 ; i++)
6795 {
6796 *ds = 0x0;
6797 ds++;
6798 }
6800 return;
6801 }
6804 /* Local MemCopy function */
6805 void edma3MemCpy(void *dst, const void *src, unsigned int len)
6806 {
6807 unsigned int i=0u;
6808 const unsigned int *sr;
6809 unsigned int *ds;
6811 assert ((src != NULL) && (dst != NULL) && ((len)%4 == 0));
6813 sr = (const unsigned int *)src;
6814 ds = (unsigned int *)dst;
6816 for (i = 0 ; i < len/4 ; i++)
6817 {
6818 *ds = *sr;
6819 ds++;
6820 sr++;
6821 }
6823 return;
6824 }
6827 /* Local MemCopy function to copy Param Set ONLY */
6828 void edma3ParamCpy(void *dst, const void *src)
6829 {
6830 unsigned int i = 0u;
6831 const unsigned int *sr;
6832 unsigned int *ds;
6834 assert ((src != NULL) && (dst != NULL));
6836 sr = (const unsigned int *)src;
6837 ds = (unsigned int *)dst;
6839 for (i = 0; i < 8; i++)
6840 {
6841 *ds = *sr;
6842 ds++;
6843 sr++;
6844 }
6846 return;
6847 }
6850 /**
6851 * Finds a particular bit ('0' or '1') in the particular word from 'start'.
6852 * If found, returns the position, else return -1.
6853 */
6854 static int findBitInWord (int source, unsigned int start, unsigned short bit)
6855 {
6856 unsigned int position = start;
6857 unsigned short found = 0;
6858 unsigned int iterations_left = 0;
6860 switch (bit)
6861 {
6862 case 1:
6863 {
6864 source >>= (start%32u);
6866 while ((found==0u) && (source!=0))
6867 {
6868 if ((source & 0x1) == 0x1)
6869 {
6870 /* 1 */
6871 found++;
6872 }
6873 else
6874 {
6875 /* 0 */
6876 source >>= 1;
6877 position++;
6878 }
6879 }
6881 }
6882 break;
6884 case 0:
6885 {
6886 source >>= (start%32u);
6887 iterations_left = 32u - (start%32u);
6889 while ((found==0u) && (iterations_left>0u))
6890 {
6891 if ((source & 0x1) == 0x1)
6892 {
6893 /* 1 */
6894 source >>= 1;
6895 position++;
6896 iterations_left--;
6897 }
6898 else
6899 {
6900 /* 0 */
6901 found++;
6902 }
6903 }
6904 }
6905 break;
6907 default:
6908 break;
6909 }
6911 return (found ? (int)position : -1);
6912 }
6915 /**
6916 * Finds a particular bit ('0' or '1') in the specified resources' array
6917 * from 'start' to 'end'. If found, returns the position, else return -1.
6918 */
6919 static int findBit (EDMA3_RM_ResType resType,
6920 unsigned int start,
6921 unsigned int end,
6922 unsigned short bit)
6923 {
6924 int position = -1;
6925 unsigned int start_index = start / 32u;
6926 unsigned int end_index = end / 32u;
6927 int i;
6928 unsigned int *resPtr = 0x0;
6929 int ret = -1;
6930 EDMA3_RM_Result result = EDMA3_RM_SOK;
6932 assert (start <= end);
6934 /**
6935 * job is to find 'bit' in an array[start_index:end_index]
6936 * algo used:
6937 * first search in array[start_index]
6938 * then search in array[start_index + 1 : end_index - 1]
6939 * then search in array[end_index]
6940 */
6941 switch (resType)
6942 {
6943 case EDMA3_RM_RES_DMA_CHANNEL:
6944 resPtr = &contiguousDmaRes[0];
6945 break;
6947 case EDMA3_RM_RES_QDMA_CHANNEL:
6948 resPtr = &contiguousQdmaRes[0];
6949 break;
6951 case EDMA3_RM_RES_TCC:
6952 resPtr = &contiguousTccRes[0];
6953 break;
6955 case EDMA3_RM_RES_PARAM_SET:
6956 resPtr = &contiguousParamRes[0];
6957 break;
6959 default:
6960 result = EDMA3_RM_E_INVALID_PARAM;
6961 break;
6962 }
6964 if (EDMA3_RM_SOK == result)
6965 {
6966 switch (bit)
6967 {
6968 case 1:
6969 {
6970 /* Find '1' in first word. */
6971 position = findBitInWord (resPtr[start_index], start, 1u);
6973 if (position != -1)
6974 {
6975 ret = position;
6976 }
6977 else
6978 {
6979 /* '1' NOT found, look into other words. */
6980 for (i = (int)(start_index + 1u); i <= (int)(end_index - 1u); i++)
6981 {
6982 position = findBitInWord (resPtr[i], 0u, 1u);
6983 if (position != -1)
6984 {
6985 /* '1' Found... */
6986 ret = (position + (i*32));
6987 break;
6988 }
6989 }
6991 /* First check whether we have found '1' or not. */
6992 if (ret == -1)
6993 {
6994 /* Still not found, look in the last word. */
6995 position = findBitInWord(resPtr[end_index], 0u, 1u);
6996 if (position != -1)
6997 {
6998 /* Finally got it. */
6999 ret = (position + (end_index*32u));
7000 }
7001 else
7002 {
7003 /* Sorry, could not find it, return -1. */
7004 ret = -1;
7005 }
7006 }
7007 }
7008 }
7009 break;
7011 case 0:
7012 {
7013 /* Find '0' in first word. */
7014 position = findBitInWord(resPtr[start_index], start, 0u);
7015 if (position != -1)
7016 {
7017 ret = position;
7018 }
7019 else
7020 {
7021 /* '0' NOT found, look into other words. */
7022 for (i = (start_index + 1u); i <= (end_index - 1u); i++)
7023 {
7024 position = findBitInWord(resPtr[i], 0u, 0u);
7025 if (position != -1)
7026 {
7027 /* '0' found... */
7028 ret = (position + (i*32));
7029 break;
7030 }
7031 }
7033 /* First check whether we have found '0' or not. */
7034 if (ret == -1)
7035 {
7036 position = findBitInWord(resPtr[end_index], 0u, 0u);
7037 if (position != -1)
7038 {
7039 /* Finally got it. */
7040 ret = (position + (end_index*32u));
7041 }
7042 else
7043 {
7044 /* Sorry, could not find it, return -1. */
7045 ret = -1;
7046 }
7047 }
7048 }
7049 }
7050 break;
7052 default:
7053 break;
7054 }
7055 }
7059 return ((ret >= start) ? ret : -1);
7060 }
7064 /**
7065 * If successful, this function returns EDMA3_RM_SOK and the position
7066 * of first available resource in 'positionRes'. Else returns error.
7067 */
7068 static EDMA3_RM_Result allocAnyContigRes(EDMA3_RM_ResType resType,
7069 unsigned int numResources,
7070 unsigned int *positionRes)
7071 {
7072 unsigned short found = 0u;
7073 int first_one, next_zero;
7074 unsigned int num_available;
7075 int ret = -1;
7076 unsigned int start = 0;
7077 unsigned int end;
7078 EDMA3_RM_Result result = EDMA3_RM_SOK;
7080 assert (positionRes != NULL);
7082 switch (resType)
7083 {
7084 case EDMA3_RM_RES_DMA_CHANNEL:
7085 end = EDMA3_MAX_DMA_CH - 1u;
7086 break;
7088 case EDMA3_RM_RES_QDMA_CHANNEL:
7089 end = EDMA3_MAX_QDMA_CH - 1u;
7090 break;
7092 case EDMA3_RM_RES_TCC:
7093 end = EDMA3_MAX_TCC - 1u;
7094 break;
7096 case EDMA3_RM_RES_PARAM_SET:
7097 end = edma3NumPaRAMSets - 1u;
7098 break;
7100 default:
7101 result = EDMA3_RM_E_INVALID_PARAM;
7102 break;
7103 }
7105 if (result == EDMA3_RM_SOK)
7106 {
7107 /**
7108 * Algorithm used for finding N contiguous resources.
7109 * In the resources' array, '1' means available and '0' means
7110 * not-available.
7111 * Step a) Find first '1' starting from 'start'. If successful,
7112 * store it in first_one, else return error.
7113 * Step b) Find first '0' starting from (first_one+1) to 'end'.
7114 * If successful, store returned value in next_zero. If '0' could
7115 * not be located, it means all the resources are available.
7116 * Store 'end' (i.e. the last resource id) in next_zero.
7117 * Step c) Count the number of contiguous resources available
7118 * by subtracting first_one from next_zero.
7119 * Step d) If result < N, do the whole process again untill you
7120 * reach end. Else you have found enough resources, return success.
7121 */
7122 while((found == 0) && (((end-start)+1u) >= numResources))
7123 {
7124 /* Find first '1' starting from 'start' till 'end'. */
7125 first_one = findBit (resType, start, end, 1u);
7126 if (first_one != -1)
7127 {
7128 /* Got first 1, search for first '0' now. */
7129 next_zero = findBit (resType, first_one+1, end, 0u);
7130 if (next_zero == -1)
7131 {
7132 /* Unable to find next zero, all 1' are there */
7133 next_zero = end + 1u;
7134 }
7136 /* check no of resources available */
7137 num_available = next_zero - first_one;
7138 if (num_available >= numResources)
7139 {
7140 /* hurrah..., we have found enough resources. */
7141 found = 1u;
7142 ret = first_one;
7143 }
7144 else
7145 {
7146 /* Not enough resources, try again */
7147 start = next_zero + 1;
7148 }
7149 }
7150 else
7151 {
7152 /* do nothing, first 1 is not there, return. */
7153 break;
7154 }
7155 }
7156 }
7159 if (result == EDMA3_RM_SOK)
7160 {
7161 if (found == 1u)
7162 {
7163 /* required resources found, retrun the first available res id. */
7164 *positionRes = (unsigned int)ret;
7165 }
7166 else
7167 {
7168 /* No resources allocated */
7169 result = EDMA3_RM_E_SPECIFIED_RES_NOT_AVAILABLE;
7170 }
7171 }
7173 return result;
7174 }
7178 /**
7179 * Starting from 'firstResIdObj', this function makes the next 'numResources'
7180 * Resources non-available for future. Also, it does some global resisters'
7181 * setting also.
7182 */
7183 static EDMA3_RM_Result gblChngAllocContigRes(EDMA3_RM_Instance *rmInstance,
7184 const EDMA3_RM_ResDesc *firstResIdObj,
7185 unsigned int numResources)
7186 {
7187 EDMA3_RM_Result result = EDMA3_RM_SOK;
7188 volatile EDMA3_CCRL_Regs *gblRegs = NULL;
7189 EDMA3_RM_Obj *rmObj = NULL;
7190 unsigned int avlblIdx = 0u;
7191 unsigned int firstResId=0u;
7192 unsigned int lastResId=0u;
7193 unsigned int edma3Id;
7195 assert ((rmInstance != NULL) && (firstResIdObj != NULL));
7197 rmObj = rmInstance->pResMgrObjHandle;
7199 if (rmObj == NULL)
7200 {
7201 result = EDMA3_RM_E_INVALID_PARAM;
7202 }
7204 if (EDMA3_RM_SOK == result)
7205 {
7206 edma3Id = rmObj->phyCtrllerInstId;
7207 gblRegs = (volatile EDMA3_CCRL_Regs *)(rmObj->gblCfgParams.globalRegs);
7209 if (gblRegs == NULL)
7210 {
7211 result = EDMA3_RM_E_INVALID_PARAM;
7212 }
7213 }
7215 if (result == EDMA3_RM_SOK)
7216 {
7217 switch (firstResIdObj->type)
7218 {
7219 case EDMA3_RM_RES_DMA_CHANNEL:
7220 {
7221 firstResId = firstResIdObj->resId;
7222 lastResId = firstResId + (numResources - 1u);
7224 for (avlblIdx=firstResId; avlblIdx <= lastResId; ++avlblIdx)
7225 {
7226 rmInstance->avlblDmaChannels[avlblIdx/32u] &= (unsigned int)(~(1u << (avlblIdx%32u)));
7228 /**
7229 * Enable the DMA channel in the DRAE/DRAEH registers also.
7230 */
7231 if (avlblIdx < 32u)
7232 {
7233 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
7234 |= (0x1u << avlblIdx);
7235 }
7236 else
7237 {
7238 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
7239 |= (0x1u << (avlblIdx - 32u));
7240 }
7241 }
7242 }
7243 break;
7245 case EDMA3_RM_RES_QDMA_CHANNEL:
7246 {
7247 firstResId = firstResIdObj->resId;
7248 lastResId = firstResId + (numResources - 1u);
7250 for (avlblIdx=firstResId; avlblIdx <= lastResId; ++avlblIdx)
7251 {
7252 rmInstance->avlblQdmaChannels[avlblIdx/32u] &= (unsigned int)(~(1u << (avlblIdx%32u)));
7254 /**
7255 * Enable the QDMA channel in the QRAE register also.
7256 */
7257 gblRegs->QRAE[rmInstance->initParam.regionId]
7258 |= (0x1u << avlblIdx);
7259 }
7260 }
7261 break;
7263 case EDMA3_RM_RES_TCC:
7264 {
7265 firstResId = firstResIdObj->resId;
7266 lastResId = firstResId + (numResources - 1u);
7268 for (avlblIdx=firstResId; avlblIdx <= lastResId; ++avlblIdx)
7269 {
7270 rmInstance->avlblTccs[avlblIdx/32u] &= (unsigned int)(~(1u << (avlblIdx%32u)));
7272 /**
7273 * Enable the Interrupt channel in the DRAE/DRAEH registers.
7274 * Also, If the region id coming from this
7275 * RM instance is same as the Master RM
7276 * Instance's region id, only then we will be
7277 * getting the interrupts on the same side.
7278 * So save the TCC in the allocatedTCCs[] array.
7279 */
7280 if (avlblIdx < 32u)
7281 {
7282 gblRegs->DRA[rmInstance->initParam.regionId].DRAE
7283 |= (0x1u << avlblIdx);
7285 if (edma3RegionId == rmInstance->initParam.regionId)
7286 {
7287 allocatedTCCs[0u] |= (0x1u << avlblIdx);
7288 }
7289 }
7290 else
7291 {
7292 gblRegs->DRA[rmInstance->initParam.regionId].DRAEH
7293 |= (0x1u << (avlblIdx - 32u));
7295 if (edma3RegionId == rmInstance->initParam.regionId)
7296 {
7297 allocatedTCCs[1u] |= (0x1u << (avlblIdx - 32u));
7298 }
7299 }
7300 }
7301 }
7302 break;
7304 case EDMA3_RM_RES_PARAM_SET:
7305 {
7306 firstResId = firstResIdObj->resId;
7307 lastResId = firstResId + (numResources - 1u);
7309 for (avlblIdx=firstResId; avlblIdx <= lastResId; ++avlblIdx)
7310 {
7311 rmInstance->avlblPaRAMSets [avlblIdx/32u] &= (unsigned int)(~(1u << (avlblIdx%32u)));
7313 /**
7314 * Also, make the actual PARAM Set NULL, checking the flag
7315 * whether it is required or not.
7316 */
7317 if (TRUE == rmInstance->paramInitRequired)
7318 {
7319 edma3MemZero((void *)(&gblRegs->PARAMENTRY[avlblIdx]),
7320 sizeof(gblRegs->PARAMENTRY[avlblIdx]));
7321 }
7322 }
7323 }
7324 break;
7326 default:
7327 result = EDMA3_RM_E_INVALID_PARAM;
7328 break;
7329 }
7330 }
7333 return result;
7334 }
7336 /* Resource Manager Internal functions - End */
7338 /* End of File */