1 /*******************************************************************************
2 **+--------------------------------------------------------------------------+**
3 **| **** |**
4 **| **** |**
5 **| ******o*** |**
6 **| ********_///_**** |**
7 **| ***** /_//_/ **** |**
8 **| ** ** (__/ **** |**
9 **| ********* |**
10 **| **** |**
11 **| *** |**
12 **| |**
13 **| Copyright (c) 1998-2006 Texas Instruments Incorporated |**
14 **| ALL RIGHTS RESERVED |**
15 **| |**
16 **| Permission is hereby granted to licensees of Texas Instruments |**
17 **| Incorporated (TI) products to use this computer program for the sole |**
18 **| purpose of implementing a licensee product based on TI products. |**
19 **| No other rights to reproduce, use, or disseminate this computer |**
20 **| program, whether in part or in whole, are granted. |**
21 **| |**
22 **| TI makes no representation or warranties with respect to the |**
23 **| performance of this computer program, and specifically disclaims |**
24 **| any responsibility for any damages, special or consequential, |**
25 **| connected with the use of this program. |**
26 **| |**
27 **+--------------------------------------------------------------------------+**
28 *******************************************************************************/
30 /**
31 * \file edma3_drv_init.c
32 *
33 * \brief EDMA3 Driver Initialization Interface Implementation
34 * This file contains EDMA3 Driver APIs used to:
35 * a) Create/delete EDMA3 Driver Object
36 * b) Open/close EDMA3 Driver Instance.
37 * These APIs are required to initialize EDMA3 properly.
38 *
39 * @author: PSP Team, TII
40 *
41 */
44 /* EDMa3 Driver Internal Header Files */
45 #include <ti/sdo/edma3/drv/src/edma3.h>
46 /* Resource Manager Internal Header Files */
47 #include <ti/sdo/edma3/rm/src/edma3resmgr.h>
49 /* For assert() */
50 /**
51 * Define NDEBUG to ignore assert().
52 * NDEBUG should be defined before including assert.h header file.
53 */
54 #include <assert.h>
57 /* Externel Variables */
58 /*---------------------------------------------------------------------------*/
59 /**
60 * Maximum Resource Manager Instances supported by the EDMA3 Package.
61 */
62 extern const unsigned int EDMA3_MAX_RM_INSTANCES;
65 /**
66 * \brief EDMA3 Resource Manager Objects, tied to each EDMA3 HW Controller.
67 *
68 * Typically one RM object will cater to one EDMA3 HW controller
69 * and will have all the global config information.
70 */
71 extern EDMA3_RM_Obj resMgrObj[EDMA3_MAX_EDMA3_INSTANCES];
74 /**
75 * \brief Region Specific Configuration structure for
76 * EDMA3 controller, to provide region specific Information.
77 *
78 * This configuration info can also be provided by the user at run-time,
79 * while calling EDMA3_RM_open (). If not provided at run-time,
80 * this info will be taken from the config file "edma3_<PLATFORM_NAME>_cfg.c",
81 * for the specified platform.
82 */
83 extern EDMA3_RM_InstanceInitConfig *ptrInitCfgArray;
86 /**
87 * Handles of EDMA3 Resource Manager Instances.
88 *
89 * Used to maintain information of the EDMA3 RM Instances
90 * for each HW controller.
91 * There could be a maximum of EDMA3_MAX_RM_INSTANCES instances per
92 * EDMA3 HW.
93 */
94 extern EDMA3_RM_Instance *ptrRMIArray;
96 /** Local MemSet function */
97 extern void edma3MemSet(void *dst, unsigned char data, unsigned int len);
98 /** Local MemCpy function */
99 extern void edma3MemCpy(void *dst, const void *src, unsigned int len);
101 /**
102 * \brief EDMA3 Driver Objects, tied to each EDMA3 HW Controller.
103 *
104 * Typically one object will cater to one EDMA3 HW controller
105 * and will have all regions' (ARM, DSP etc) specific config information.
106 */
107 EDMA3_DRV_Object drvObj [EDMA3_MAX_EDMA3_INSTANCES];
110 /**
111 * Handles of EDMA3 Driver Instances.
112 *
113 * Used to maintain information of the EDMA3 Driver Instances for
114 * each region, for each HW controller.
115 * There could be as many Driver Instances as there are shadow
116 * regions. Multiple EDMA3 Driver instances on the same shadow
117 * region are NOT allowed.
118 */
119 EDMA3_DRV_Instance drvInstance [EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_REGIONS];
122 /**
123 * \brief Resources bound to a Channel
124 *
125 * When a request for a channel is made, the resources PaRAM Set and TCC
126 * get bound to that channel. This information is needed internally by the
127 * driver when a request is made to free the channel (Since it is the
128 * responsibility of the driver to free up the channel-associated resources
129 * from the Resource Manager layer).
130 */
131 EDMA3_DRV_ChBoundResources edma3DrvChBoundRes [EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_LOGICAL_CH];
134 /**
135 * \brief Event Queue Number for DMA/QDMA Channels.
136 *
137 * If EDMA3_PROGRAM_QUEUE_NUM_REGISTER_INIT_TIME is defined, then the queue
138 * number registers for DMA/QDMA channels will be programmed during init time
139 * only; the queue number registers will NOT be changed during run-time to
140 * avoid (potential) race conditions. The following arrays will be used to
141 * program the DMA/QDMA queue number registers.
142 *
143 * User has to provide the array values depending on the resources'
144 * availability and the system requirements.
145 *
146 */
147 #ifdef EDMA3_PROGRAM_QUEUE_NUM_REGISTER_INIT_TIME
148 EDMA3_DRV_DmaQdmaQueueNum edma3DmaQdmaQueueNumConfig = {
149 {
150 /* DMA Channels 0-63 */
151 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
152 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
153 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
154 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
155 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
156 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
157 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
158 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
159 },
161 {
162 /* QDMA Channels 0-7 */
163 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
164 },
165 };
166 #endif
169 /* Local functions prototypes */
170 /*---------------------------------------------------------------------------*/
171 /**
172 * Local function to prepare the init config structure for
173 * open of Resource Manager
174 */
175 static EDMA3_DRV_Result edma3OpenResMgr (unsigned int instId,
176 unsigned int regionId,
177 unsigned short flag);
179 /*---------------------------------------------------------------------------*/
183 /**
184 * \brief Create EDMA3 Driver Object
185 *
186 * This API is used to create the EDMA3 Driver Object. It should be
187 * called only ONCE for each EDMA3 hardware instance.
188 *
189 * Init-time Configuration structure for EDMA3 hardware is provided to pass the
190 * SoC specific information. This configuration information could be provided
191 * by the user at init-time. In case user doesn't provide it, this information
192 * could be taken from the SoC specific configuration file
193 * edma3_<SOC_NAME>_cfg.c, in case it is available.
194 *
195 * This API clears the error specific registers (EMCR/EMCRh, QEMCR, CCERRCLR)
196 * and sets the TCs priorities and Event Queues' watermark levels, if the 'miscParam'
197 * argument is NULL. User can avoid these registers' programming (in some specific
198 * use cases) by SETTING the 'isSlave' field of 'EDMA3_RM_MiscParam' configuration
199 * structure and passing this structure as the third argument (miscParam).
200 *
201 * After successful completion of this API, Driver Object's state
202 * changes to EDMA3_DRV_CREATED from EDMA3_DRV_DELETED.
203 *
204 * \param phyCtrllerInstId [IN] EDMA3 Controller Instance Id
205 * (Hardware instance id, starting from 0).
206 * \param gblCfgParams [IN] SoC specific configuration structure for the
207 * EDMA3 Hardware.
208 * \param miscParam [IN] Misc configuration options provided in the
209 * structure 'EDMA3_DRV_MiscParam'.
210 * For default options, user can pass NULL
211 * in this argument.
212 *
213 * \return EDMA3_DRV_SOK or EDMA3_DRV Error code
214 */
215 EDMA3_DRV_Result EDMA3_DRV_create (unsigned int phyCtrllerInstId,
216 const EDMA3_DRV_GblConfigParams *gblCfgParams,
217 const void *miscParam)
218 {
219 unsigned int count = 0;
220 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
221 EDMA3_RM_GblConfigParams rmGblCfgParams;
222 /**
223 * Used to reset the Internal EDMA3 Driver Data Structures for the first time.
224 */
225 static unsigned short drvInitDone = FALSE;
227 /**
228 * We are NOT checking 'gblCfgParams' for NULL. Whatever user has passed
229 * is given to RM. If user passed NULL, config info from config file will be
230 * taken else user specific info will be passed to the RM.
231 * Similarly, 'miscParam' is not being checked and passed as it is to the
232 * Resource Manager layer.
233 */
234 /* If parameter checking is enabled... */
235 #ifndef EDMA3_DRV_PARAM_CHECK_DISABLE
236 if (phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES)
237 {
238 result = EDMA3_DRV_E_INVALID_PARAM;
239 }
240 #endif
242 /* Check if the parameters are OK. */
243 if (EDMA3_DRV_SOK == result)
244 {
245 /* Initialize the global variables for the first time */
246 if (FALSE == drvInitDone)
247 {
248 for (count = 0; count < EDMA3_MAX_EDMA3_INSTANCES; count++)
249 {
250 edma3MemSet((void *)&(drvObj[count]) , 0x00u,
251 sizeof(EDMA3_DRV_Object));
252 }
253 drvInitDone = TRUE;
254 }
256 /* Initialization has been done */
257 if (drvObj[phyCtrllerInstId].state != EDMA3_DRV_DELETED)
258 {
259 result = EDMA3_DRV_E_OBJ_NOT_DELETED;
260 }
261 else
262 {
263 if (NULL != gblCfgParams)
264 {
265 /* User has passed the configuration info */
266 /* copy the global info */
267 edma3MemCpy((void *)(&drvObj[phyCtrllerInstId].gblCfgParams),
268 (const void *)(gblCfgParams),
269 sizeof (EDMA3_DRV_GblConfigParams));
271 /* Reset the RM global info struct first */
272 edma3MemSet((void *)&(rmGblCfgParams) ,
273 0x00u,
274 sizeof (EDMA3_RM_GblConfigParams));
276 /* Fill the RM global info struct with the DRV global info */
277 edma3MemCpy((void *)(&rmGblCfgParams),
278 (const void *)(&drvObj[phyCtrllerInstId].gblCfgParams),
279 sizeof (EDMA3_RM_GblConfigParams));
281 result = EDMA3_RM_create(phyCtrllerInstId, (EDMA3_RM_GblConfigParams *)&rmGblCfgParams, miscParam);
282 }
283 else
284 {
285 /* User has not passed any global info. */
286 result = EDMA3_RM_create(phyCtrllerInstId, NULL, miscParam);
288 if (EDMA3_RM_SOK == result)
289 {
290 /**
291 * Copy the global config info from the RM object to the
292 * driver object for future use.
293 */
294 /* Fill the RM global info struct with the DRV global info */
295 edma3MemCpy((void *)(&drvObj[phyCtrllerInstId].gblCfgParams),
296 (const void *)(&resMgrObj[phyCtrllerInstId].gblCfgParams),
297 sizeof (EDMA3_RM_GblConfigParams));
298 }
299 }
301 if (EDMA3_RM_SOK == result)
302 {
303 drvObj[phyCtrllerInstId].state = EDMA3_DRV_CREATED;
304 drvObj[phyCtrllerInstId].numOpens = 0;
305 drvObj[phyCtrllerInstId].phyCtrllerInstId = phyCtrllerInstId;
307 /* Make all the Driver instances for this EDMA3 HW NULL */
308 for (count = 0; count < drvObj[phyCtrllerInstId].gblCfgParams.numRegions; count++)
309 {
310 edma3MemSet((void *)&(drvInstance[phyCtrllerInstId][count]) , 0x00u,
311 sizeof(EDMA3_DRV_Instance));
312 }
314 /* Reset edma3DrvChBoundRes Array*/
315 for (count = 0; count < EDMA3_MAX_LOGICAL_CH; count++)
316 {
317 edma3DrvChBoundRes[phyCtrllerInstId][count].paRAMId = -1;
318 edma3DrvChBoundRes[phyCtrllerInstId][count].tcc = EDMA3_MAX_TCC;
319 edma3DrvChBoundRes[phyCtrllerInstId][count].trigMode =
320 EDMA3_DRV_TRIG_MODE_NONE;
321 }
322 }
325 /* Initialize the Queue Number Registers, if required. */
326 #ifdef EDMA3_PROGRAM_QUEUE_NUM_REGISTER_INIT_TIME
327 if (EDMA3_RM_SOK == result)
328 {
329 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
331 globalRegs = (volatile EDMA3_CCRL_Regs *)(drvObj[phyCtrllerInstId].gblCfgParams.globalRegs);
333 if (NULL != globalRegs)
334 {
335 /* Initialize DMA Queue Num Registers */
336 for (count = 0;
337 count < drvObj[phyCtrllerInstId].gblCfgParams.numDmaChannels;
338 count++)
339 {
340 globalRegs->DMAQNUM[count >> 3u] &= EDMA3_DRV_DMAQNUM_CLR_MASK(count);
341 globalRegs->DMAQNUM[count >> 3u] |= EDMA3_DRV_DMAQNUM_SET_MASK(count,
342 edma3DmaQdmaQueueNumConfig.dmaChannelQueueNum[count]);
343 }
345 /* Initialize QDMA Queue Num Registers */
346 for (count = 0;
347 count < drvObj[phyCtrllerInstId].gblCfgParams.numQdmaChannels;
348 count++)
349 {
350 globalRegs->QDMAQNUM &= EDMA3_DRV_QDMAQNUM_CLR_MASK(count);
351 globalRegs->QDMAQNUM |= EDMA3_DRV_QDMAQNUM_SET_MASK(count,
352 edma3DmaQdmaQueueNumConfig.qdmaChannelQueueNum[count]);
353 }
354 }
355 }
356 #endif
357 }
358 }
360 return result;
361 }
365 /**
366 * \brief Delete EDMA3 Driver Object
367 *
368 * Use this API to delete the EDMA3 Driver Object. It should be called only
369 * ONCE for each EDMA3 hardware instance. It should be called ONLY after
370 * closing all the EDMA3 Driver Instances.
371 *
372 * This API is used to delete the EDMA3 Driver Object. It should be called
373 * once for each EDMA3 hardware instance, ONLY after closing all the
374 * previously opened EDMA3 Driver Instances.
375 *
376 * After successful completion of this API, Driver Object's state
377 * changes to EDMA3_DRV_DELETED.
378 *
379 * \param phyCtrllerInstId [IN] EDMA3 Phy Controller Instance Id (Hardware
380 * instance id, starting from 0).
381 * \param param [IN] For possible future use.
382 *
383 * \return EDMA3_DRV_SOK or EDMA3_DRV Error code
384 */
385 EDMA3_DRV_Result EDMA3_DRV_delete(unsigned int phyCtrllerInstId,
386 const void *param)
387 {
388 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
390 /*to remove CCS remark: parameter "param" was never referenced */
391 (void)param;
393 /* If parameter checking is enabled... */
394 #ifndef EDMA3_DRV_PARAM_CHECK_DISABLE
395 if (phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES)
396 {
397 result = EDMA3_DRV_E_INVALID_PARAM;
398 }
399 #endif
401 /* Check if the parameters are OK. */
402 if (EDMA3_DRV_SOK == result)
403 {
404 /**
405 * If number of Driver Instances is 0, then state should be
406 * EDMA3_DRV_CLOSED OR EDMA3_DRV_CREATED.
407 */
408 if ((NULL == drvObj[phyCtrllerInstId].numOpens)
409 && ((drvObj[phyCtrllerInstId].state != EDMA3_DRV_CLOSED)
410 && (drvObj[phyCtrllerInstId].state != EDMA3_DRV_CREATED)))
411 {
412 result = EDMA3_DRV_E_OBJ_NOT_CLOSED;
413 }
414 else
415 {
416 /**
417 * If number of Driver Instances is NOT 0, then this function
418 * SHOULD NOT be called by anybody.
419 */
420 if (NULL != drvObj[phyCtrllerInstId].numOpens)
421 {
422 result = EDMA3_DRV_E_INVALID_STATE;
423 }
424 else
425 {
426 /**
427 * State is correct. Delete the RM Object.
428 */
429 result = EDMA3_RM_delete (phyCtrllerInstId, NULL);
431 if (EDMA3_RM_SOK == result)
432 {
433 /** Change state to EDMA3_DRV_DELETED */
434 drvObj[phyCtrllerInstId].state = EDMA3_DRV_DELETED;
436 /* Also, reset the Driver Object Global Config Info */
437 edma3MemSet((void *)&(drvObj[phyCtrllerInstId].gblCfgParams) , 0x00u,
438 sizeof(EDMA3_DRV_GblConfigParams));
439 }
440 }
441 }
442 }
444 return result;
445 }
448 /**
449 * \brief Open EDMA3 Driver Instance
450 *
451 * This API is used to open an EDMA3 Driver Instance. It could be
452 * called multiple times, for each possible EDMA3 shadow region. Maximum
453 * EDMA3_MAX_REGIONS instances are allowed for each EDMA3 hardware
454 * instance. Multiple instances on the same shadow region are NOT allowed.
455 *
456 * Also, only ONE Master Driver Instance is permitted. This master
457 * instance (and hence the region to which it belongs) will only receive the
458 * EDMA3 interrupts, if enabled.
459 *
460 * User could pass the instance specific configuration structure
461 * (initCfg.drvInstInitConfig) as a part of the 'initCfg' structure,
462 * during init-time. In case user doesn't provide it, this information could
463 * be taken from the SoC specific configuration file edma3_<SOC_NAME>_cfg.c,
464 * in case it is available.
465 *
466 * \param phyCtrllerInstId [IN] EDMA3 Controller Instance Id (Hardware
467 * instance id, starting from 0).
468 * \param initCfg [IN] Used to Initialize the EDMA3 Driver
469 * Instance (Master or Slave).
470 * \param errorCode [OUT] Error code while opening DRV instance.
471 *
472 * \return EDMA3_DRV_Handle : If successfully opened, the API will return the
473 * associated driver's instance handle.
474 *
475 * \note This function disables the global interrupts (by calling API
476 * edma3OsProtectEntry with protection level
477 * EDMA3_OS_PROTECT_INTERRUPT) while modifying the global data
478 * structures, to make it re-entrant.
479 */
480 EDMA3_DRV_Handle EDMA3_DRV_open (unsigned int phyCtrllerInstId,
481 const EDMA3_DRV_InitConfig *initCfg,
482 EDMA3_DRV_Result *errorCode)
483 {
484 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
485 EDMA3_DRV_Object *drvObject = NULL;
486 EDMA3_DRV_Instance *drvInstanceHandle = NULL;
487 unsigned int intState = 0;
488 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
489 unsigned short flag = 0;
491 /* If parameter checking is enabled... */
492 #ifndef EDMA3_DRV_PARAM_CHECK_DISABLE
493 if (((initCfg == NULL) || (phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES))
494 || (errorCode == NULL))
495 {
496 result = EDMA3_DRV_E_INVALID_PARAM;
497 }
498 #endif
500 /* Check if the parameters are OK. */
501 if (EDMA3_DRV_SOK == result)
502 {
503 /* Check whether the semaphore handle is null or not */
504 if (NULL== initCfg->drvSemHandle)
505 {
506 result = EDMA3_DRV_E_INVALID_PARAM;
507 }
508 else
509 {
510 drvObject = &drvObj[phyCtrllerInstId];
511 if (NULL == drvObject)
512 {
513 result = EDMA3_DRV_E_INVALID_PARAM;
514 }
515 else
516 {
517 if (initCfg->regionId >= drvObject->gblCfgParams.numRegions)
518 {
519 result = EDMA3_DRV_E_INVALID_PARAM;
520 }
521 else
522 {
523 /* if no instance is opened and this is the first one,
524 * then state should be created/closed.
525 */
526 if (((drvObject->numOpens == NULL) && (drvObject->state != EDMA3_DRV_CREATED))
527 && (drvObject->state != EDMA3_DRV_CLOSED))
528 {
529 result = EDMA3_DRV_E_INVALID_STATE;
530 }
531 else
532 {
533 /* if num of instances opened is more than 0 and less than no of regions,
534 * then state should be opened.
535 */
536 if (((drvObject->numOpens > 0) && (drvObject->numOpens < drvObject->gblCfgParams.numRegions))
537 && (drvObject->state != EDMA3_DRV_OPENED))
538 {
539 result = EDMA3_DRV_E_INVALID_STATE;
540 }
541 else
542 {
543 /* if a driver instance is already there for a specific region,
544 * it should return an error.
545 */
546 drvInstanceHandle = &drvInstance[phyCtrllerInstId][initCfg->regionId];
547 if (drvInstanceHandle->pDrvObjectHandle != NULL)
548 {
549 drvInstanceHandle = NULL;
550 result = EDMA3_DRV_E_INST_ALREADY_EXISTS;
551 }
552 }
553 }
554 }
555 }
556 }
557 }
559 if (EDMA3_DRV_SOK == result)
560 {
561 /* Save the region specific information in the region specific drv instance*/
562 drvInstanceHandle->regionId = initCfg->regionId;
563 drvInstanceHandle->isMaster = initCfg->isMaster;
564 drvInstanceHandle->drvSemHandle = initCfg->drvSemHandle;
565 drvInstanceHandle->gblerrCbParams.gblerrCb = initCfg->gblerrCb;
566 drvInstanceHandle->gblerrCbParams.gblerrData = initCfg->gblerrData;
568 if (NULL != initCfg->drvInstInitConfig)
569 {
570 edma3MemCpy((void *)(&drvInstanceHandle->drvInstInitConfig),
571 (const void *)(initCfg->drvInstInitConfig),
572 sizeof (EDMA3_DRV_InstanceInitConfig));
574 /* Flag to remember that driver has passed config info to RM */
575 flag = 1u;
576 }
578 if (NULL == drvObject->gblCfgParams.globalRegs)
579 {
580 drvInstanceHandle = NULL;
581 result = EDMA3_DRV_E_INVALID_PARAM;
582 }
583 else
584 {
585 globalRegs = (volatile EDMA3_CCRL_Regs *)drvObject->gblCfgParams.globalRegs;
587 /* Update shadowRegs */
588 drvInstanceHandle->shadowRegs = (EDMA3_CCRL_ShadowRegs *)
589 (&(globalRegs->SHADOW[initCfg->regionId]));
591 result = edma3OpenResMgr (phyCtrllerInstId, initCfg->regionId, flag);
592 if (EDMA3_DRV_SOK != result)
593 {
594 drvInstanceHandle = NULL;
595 }
596 else
597 {
598 drvObject->state = EDMA3_DRV_OPENED;
599 edma3OsProtectEntry (EDMA3_OS_PROTECT_INTERRUPT, &intState);
600 drvObject->numOpens++;
601 edma3OsProtectExit (EDMA3_OS_PROTECT_INTERRUPT, intState);
602 }
603 }
604 }
606 *errorCode = result;
607 return (EDMA3_DRV_Handle)drvInstanceHandle;
608 }
611 /**
612 * \brief Close the EDMA3 Driver Instance.
613 *
614 * This API is used to close a previously opened EDMA3 Driver Instance.
615 *
616 * \param hEdma [IN] Handle to the previously opened EDMA3
617 * Driver Instance.
618 * \param param [IN] For possible future use
619 *
620 * \return EDMA3_DRV_SOK or EDMA3_DRV Error code
621 *
622 * \note This function disables the global interrupts (by calling API
623 * edma3OsProtectEntry with protection level
624 * EDMA3_OS_PROTECT_INTERRUPT) while modifying the global data
625 * structures, to make it re-entrant.
626 */
627 EDMA3_DRV_Result EDMA3_DRV_close(EDMA3_DRV_Handle hEdma,
628 const void *param)
629 {
630 unsigned int intState = 0;
631 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
632 EDMA3_DRV_Instance *drvInst = NULL;
633 EDMA3_DRV_Object *drvObject = NULL;
635 /*to remove CCS remark: parameter "param" was never referenced */
636 (void)param;
638 /* If parameter checking is enabled... */
639 #ifndef EDMA3_DRV_PARAM_CHECK_DISABLE
640 if (hEdma == NULL)
641 {
642 result = EDMA3_DRV_E_INVALID_PARAM;
643 }
644 #endif
646 /* Check if the parameters are OK. */
647 if (EDMA3_DRV_SOK == result)
648 {
649 drvInst = (EDMA3_DRV_Instance *)hEdma;
650 drvObject = drvInst->pDrvObjectHandle;
652 if (drvObject == NULL)
653 {
654 result = EDMA3_DRV_E_INVALID_PARAM;
655 }
656 else
657 {
658 /* Check state of driver */
659 if (drvObject->state != EDMA3_DRV_OPENED)
660 {
661 result = EDMA3_DRV_E_OBJ_NOT_OPENED;
662 }
663 else
664 {
665 result = EDMA3_RM_close (drvInst->resMgrInstance, NULL);
667 if (result != EDMA3_RM_SOK)
668 {
669 result = EDMA3_DRV_E_RM_CLOSE_FAIL;
670 }
671 else
672 {
673 /* Set the driver instance specific info null */
674 drvInst->resMgrInstance = NULL;
675 drvInst->pDrvObjectHandle = NULL;
676 edma3MemSet((void *)&(drvInst->drvInstInitConfig), 0x00,
677 sizeof (EDMA3_DRV_InstanceInitConfig));
678 drvInst->shadowRegs = NULL;
680 edma3OsProtectEntry (EDMA3_OS_PROTECT_INTERRUPT, &intState);
681 /* Decrease the Number of Opens */
682 --drvObject->numOpens;
683 if (NULL == drvObject->numOpens)
684 {
685 drvObject->state = EDMA3_DRV_CLOSED;
686 }
687 edma3OsProtectExit (EDMA3_OS_PROTECT_INTERRUPT, intState);
688 }
689 }
690 }
691 }
693 return (result);
694 }
697 /* Definitions of Local functions - Start */
698 /* Local function to prepare the init config structure for open of Resource Manager */
699 static EDMA3_DRV_Result edma3OpenResMgr (unsigned int instId,
700 unsigned int regionId,
701 unsigned short flag)
702 {
703 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
704 EDMA3_RM_Param initParam;
705 EDMA3_RM_InstanceInitConfig rmInstanceCfg;
706 EDMA3_RM_Handle hResMgr = NULL;
707 EDMA3_RM_Result rmResult;
708 unsigned int resMgrIdx = 0u;
709 EDMA3_RM_Instance *temp_rm_instance = NULL;
711 assert ((instId < EDMA3_MAX_EDMA3_INSTANCES)
712 && (regionId < drvObj[instId].gblCfgParams.numRegions));
714 initParam.regionId = regionId;
715 initParam.rmSemHandle = drvInstance[instId][regionId].drvSemHandle;
716 /*
717 * If the EDMA driver instance is MASTER, do the
718 * (global + region_specific) init. For all other instances,
719 * only do the (region_specific) init.
720 */
721 initParam.isMaster = drvInstance[instId][regionId].isMaster;
722 initParam.regionInitEnable = TRUE;
724 initParam.gblerrCbParams.gblerrCb = drvInstance[instId][regionId].gblerrCbParams.gblerrCb;
725 initParam.gblerrCbParams.gblerrData = drvInstance[instId][regionId].gblerrCbParams.gblerrData;
727 if (flag == 1u)
728 {
729 /**
730 * User has passed the instance initialization specific info,
731 * which we have saved previously too, so use it.
732 */
733 edma3MemCpy((void *)(&rmInstanceCfg),
734 (const void *)(&drvInstance[instId][regionId].drvInstInitConfig),
735 sizeof (EDMA3_RM_InstanceInitConfig));
737 initParam.rmInstInitConfig = &rmInstanceCfg;
739 hResMgr = EDMA3_RM_open (instId, (EDMA3_RM_Param *)&initParam, &rmResult);
741 if (NULL == hResMgr)
742 {
743 result = rmResult;
744 }
745 }
746 else
747 {
748 /**
749 * User has NOT passed the instance initialization specific info.
750 * Pass NULL to the Resource Manager.
751 */
752 initParam.rmInstInitConfig = NULL;
754 hResMgr = EDMA3_RM_open (instId, (EDMA3_RM_Param *)&initParam, &rmResult);
756 if (NULL == hResMgr)
757 {
758 result = rmResult;
759 }
760 else
761 {
762 /**
763 * Save the RM Instance specific information in the driver.
764 * Earlier this was easier, now a bit tricky.
765 * Search for the RM instance number based on the handle
766 * just returned, to fetch the correct config info from the
767 * userInitConfig[].
768 */
769 for (resMgrIdx = 0u; resMgrIdx < EDMA3_MAX_RM_INSTANCES; resMgrIdx++)
770 {
771 temp_rm_instance = ((EDMA3_RM_Instance *)(ptrRMIArray) + (instId*EDMA3_MAX_RM_INSTANCES) + resMgrIdx);
773 if (hResMgr == temp_rm_instance)
774 {
775 /* RM Id found. Copy the specific config info to the drvInstance [] */
776 edma3MemCpy((void *)(&drvInstance[instId][regionId].drvInstInitConfig),
777 (const void *)((EDMA3_RM_InstanceInitConfig *)(ptrInitCfgArray) + (instId*EDMA3_MAX_RM_INSTANCES) + resMgrIdx),
778 sizeof (EDMA3_RM_InstanceInitConfig));
779 break;
780 }
781 }
783 if (EDMA3_MAX_RM_INSTANCES == resMgrIdx)
784 {
785 /* RM Id not found, report error... */
786 result = EDMA3_DRV_E_INVALID_PARAM;
787 }
788 }
789 }
792 if (EDMA3_RM_SOK == result)
793 {
794 /* Save handle to Resource Manager Instance */
795 drvInstance[instId][regionId].resMgrInstance = hResMgr;
796 /* Save handle to EDMA Driver Object */
797 drvInstance[instId][regionId].pDrvObjectHandle = &drvObj[instId];
798 }
800 return result;
801 }
803 /* Definitions of Local functions - End */
805 /* End of File */