1 /*
2 * edma3_drv_init.c
3 *
4 * EDMA3 Driver Initialization Interface Implementation. This file contains
5 * EDMA3 Driver APIs used to:
6 * a) Create/delete EDMA3 Driver Object
7 * b) Open/close EDMA3 Driver Instance.
8 * These APIs are required to initialize EDMA3 properly.
9 *
10 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
11 *
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the
23 * distribution.
24 *
25 * Neither the name of Texas Instruments Incorporated nor the names of
26 * its contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 */
43 /* EDMA3 Driver Internal Header Files */
44 #include <ti/sdo/edma3/drv/src/edma3.h>
45 /* Resource Manager Internal Header Files */
46 #include <ti/sdo/edma3/rm/src/edma3resmgr.h>
48 /* For assert() */
49 /**
50 * Define NDEBUG to ignore assert().
51 * NDEBUG should be defined before including assert.h header file.
52 */
53 #include <assert.h>
56 /* Externel Variables */
57 /*---------------------------------------------------------------------------*/
58 /**
59 * Maximum Resource Manager Instances supported by the EDMA3 Package.
60 */
61 extern const unsigned int EDMA3_MAX_RM_INSTANCES;
64 /**
65 * \brief EDMA3 Resource Manager Objects, tied to each EDMA3 HW Controller.
66 *
67 * Typically one RM object will cater to one EDMA3 HW controller
68 * and will have all the global config information.
69 */
70 extern EDMA3_RM_Obj resMgrObj[EDMA3_MAX_EDMA3_INSTANCES];
73 /**
74 * \brief Region Specific Configuration structure for
75 * EDMA3 controller, to provide region specific Information.
76 *
77 * This configuration info can also be provided by the user at run-time,
78 * while calling EDMA3_RM_open (). If not provided at run-time,
79 * this info will be taken from the config file "edma3_<PLATFORM_NAME>_cfg.c",
80 * for the specified platform.
81 */
82 extern EDMA3_RM_InstanceInitConfig *ptrInitCfgArray;
85 /**
86 * Handles of EDMA3 Resource Manager Instances.
87 *
88 * Used to maintain information of the EDMA3 RM Instances
89 * for each HW controller.
90 * There could be a maximum of EDMA3_MAX_RM_INSTANCES instances per
91 * EDMA3 HW.
92 */
93 extern EDMA3_RM_Instance *ptrRMIArray;
95 /** Local MemZero function */
96 extern void edma3MemZero(void *dst, unsigned int len);
97 /** Local MemCpy function */
98 extern void edma3MemCpy(void *dst, const void *src, unsigned int len);
100 /**
101 * \brief EDMA3 Driver Objects, tied to each EDMA3 HW Controller.
102 *
103 * Typically one object will cater to one EDMA3 HW controller
104 * and will have all regions' (ARM, DSP etc) specific config information.
105 */
106 EDMA3_DRV_Object drvObj [EDMA3_MAX_EDMA3_INSTANCES];
109 /**
110 * Handles of EDMA3 Driver Instances.
111 *
112 * Used to maintain information of the EDMA3 Driver Instances for
113 * each region, for each HW controller.
114 * There could be as many Driver Instances as there are shadow
115 * regions. Multiple EDMA3 Driver instances on the same shadow
116 * region are NOT allowed.
117 */
118 EDMA3_DRV_Instance drvInstance [EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_REGIONS];
121 /**
122 * \brief Resources bound to a Channel
123 *
124 * When a request for a channel is made, the resources PaRAM Set and TCC
125 * get bound to that channel. This information is needed internally by the
126 * driver when a request is made to free the channel (Since it is the
127 * responsibility of the driver to free up the channel-associated resources
128 * from the Resource Manager layer).
129 */
130 EDMA3_DRV_ChBoundResources edma3DrvChBoundRes [EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_LOGICAL_CH];
133 /**
134 * \brief Event Queue Number for DMA/QDMA Channels.
135 *
136 * If EDMA3_PROGRAM_QUEUE_NUM_REGISTER_INIT_TIME is defined, then the queue
137 * number registers for DMA/QDMA channels will be programmed during init time
138 * only; the queue number registers will NOT be changed during run-time to
139 * avoid (potential) race conditions. The following arrays will be used to
140 * program the DMA/QDMA queue number registers.
141 *
142 * User has to provide the array values depending on the resources'
143 * availability and the system requirements.
144 *
145 */
146 #ifdef EDMA3_PROGRAM_QUEUE_NUM_REGISTER_INIT_TIME
147 EDMA3_DRV_DmaQdmaQueueNum edma3DmaQdmaQueueNumConfig = {
148 {
149 /* DMA Channels 0-63 */
150 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
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 },
160 {
161 /* QDMA Channels 0-7 */
162 0u, 1u, 0u, 1u, 0u, 1u, 0u, 1u,
163 },
164 };
165 #endif
168 /* Local functions prototypes */
169 /*---------------------------------------------------------------------------*/
170 /**
171 * Local function to prepare the init config structure for
172 * open of Resource Manager
173 */
174 static EDMA3_DRV_Result edma3OpenResMgr (unsigned int instId,
175 unsigned int regionId,
176 unsigned short flag);
178 /*---------------------------------------------------------------------------*/
182 /**
183 * \brief Create EDMA3 Driver Object
184 *
185 * This API is used to create the EDMA3 Driver Object. It should be
186 * called only ONCE for each EDMA3 hardware instance.
187 *
188 * Init-time Configuration structure for EDMA3 hardware is provided to pass the
189 * SoC specific information. This configuration information could be provided
190 * by the user at init-time. In case user doesn't provide it, this information
191 * could be taken from the SoC specific configuration file
192 * edma3_<SOC_NAME>_cfg.c, in case it is available.
193 *
194 * This API clears the error specific registers (EMCR/EMCRh, QEMCR, CCERRCLR)
195 * and sets the TCs priorities and Event Queues' watermark levels, if the 'miscParam'
196 * argument is NULL. User can avoid these registers' programming (in some specific
197 * use cases) by SETTING the 'isSlave' field of 'EDMA3_RM_MiscParam' configuration
198 * structure and passing this structure as the third argument (miscParam).
199 *
200 * After successful completion of this API, Driver Object's state
201 * changes to EDMA3_DRV_CREATED from EDMA3_DRV_DELETED.
202 *
203 * \param phyCtrllerInstId [IN] EDMA3 Controller Instance Id
204 * (Hardware instance id, starting from 0).
205 * \param gblCfgParams [IN] SoC specific configuration structure for the
206 * EDMA3 Hardware.
207 * \param miscParam [IN] Misc configuration options provided in the
208 * structure 'EDMA3_DRV_MiscParam'.
209 * For default options, user can pass NULL
210 * in this argument.
211 *
212 * \return EDMA3_DRV_SOK or EDMA3_DRV Error code
213 */
214 EDMA3_DRV_Result EDMA3_DRV_create (unsigned int phyCtrllerInstId,
215 const EDMA3_DRV_GblConfigParams *gblCfgParams,
216 const void *miscParam)
217 {
218 unsigned int count = 0;
219 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
220 EDMA3_RM_GblConfigParams rmGblCfgParams;
221 /**
222 * Used to reset the Internal EDMA3 Driver Data Structures for the first time.
223 */
224 static unsigned short drvInitDone = FALSE;
226 /**
227 * We are NOT checking 'gblCfgParams' for NULL. Whatever user has passed
228 * is given to RM. If user passed NULL, config info from config file will be
229 * taken else user specific info will be passed to the RM.
230 * Similarly, 'miscParam' is not being checked and passed as it is to the
231 * Resource Manager layer.
232 */
233 /* If parameter checking is enabled... */
234 #ifndef EDMA3_DRV_PARAM_CHECK_DISABLE
235 if (phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES)
236 {
237 result = EDMA3_DRV_E_INVALID_PARAM;
238 }
239 #endif
241 /* Check if the parameters are OK. */
242 if (EDMA3_DRV_SOK == result)
243 {
244 /* Initialize the global variables for the first time */
245 if (FALSE == drvInitDone)
246 {
247 for (count = 0; count < EDMA3_MAX_EDMA3_INSTANCES; count++)
248 {
249 edma3MemZero((void *)&(drvObj[count]),
250 sizeof(EDMA3_DRV_Object));
251 }
252 drvInitDone = TRUE;
253 }
255 /* Initialization has been done */
256 if (drvObj[phyCtrllerInstId].state != EDMA3_DRV_DELETED)
257 {
258 result = EDMA3_DRV_E_OBJ_NOT_DELETED;
259 }
260 else
261 {
262 if (NULL != gblCfgParams)
263 {
264 /* User has passed the configuration info */
265 /* copy the global info */
266 edma3MemCpy((void *)(&drvObj[phyCtrllerInstId].gblCfgParams),
267 (const void *)(gblCfgParams),
268 sizeof (EDMA3_DRV_GblConfigParams));
270 /* Reset the RM global info struct first */
271 edma3MemZero((void *)&(rmGblCfgParams) ,
272 sizeof (EDMA3_RM_GblConfigParams));
274 /* Fill the RM global info struct with the DRV global info */
275 edma3MemCpy((void *)(&rmGblCfgParams),
276 (const void *)(&drvObj[phyCtrllerInstId].gblCfgParams),
277 sizeof (EDMA3_RM_GblConfigParams));
279 result = EDMA3_RM_create(phyCtrllerInstId, (EDMA3_RM_GblConfigParams *)&rmGblCfgParams, miscParam);
280 }
281 else
282 {
283 /* User has not passed any global info. */
284 result = EDMA3_RM_create(phyCtrllerInstId, NULL, miscParam);
286 if (EDMA3_RM_SOK == result)
287 {
288 /**
289 * Copy the global config info from the RM object to the
290 * driver object for future use.
291 */
292 /* Fill the RM global info struct with the DRV global info */
293 edma3MemCpy((void *)(&drvObj[phyCtrllerInstId].gblCfgParams),
294 (const void *)(&resMgrObj[phyCtrllerInstId].gblCfgParams),
295 sizeof (EDMA3_RM_GblConfigParams));
296 }
297 }
299 if (EDMA3_RM_SOK == result)
300 {
301 drvObj[phyCtrllerInstId].state = EDMA3_DRV_CREATED;
302 drvObj[phyCtrllerInstId].numOpens = 0;
303 drvObj[phyCtrllerInstId].phyCtrllerInstId = phyCtrllerInstId;
305 /* Make all the Driver instances for this EDMA3 HW NULL */
306 for (count = 0; count < drvObj[phyCtrllerInstId].gblCfgParams.numRegions; count++)
307 {
308 edma3MemZero((void *)&(drvInstance[phyCtrllerInstId][count]),
309 sizeof(EDMA3_DRV_Instance));
310 }
312 /* Reset edma3DrvChBoundRes Array*/
313 for (count = 0; count < EDMA3_MAX_LOGICAL_CH; count++)
314 {
315 edma3DrvChBoundRes[phyCtrllerInstId][count].paRAMId = -1;
316 edma3DrvChBoundRes[phyCtrllerInstId][count].tcc = EDMA3_MAX_TCC;
317 edma3DrvChBoundRes[phyCtrllerInstId][count].trigMode =
318 EDMA3_DRV_TRIG_MODE_NONE;
319 }
320 }
323 /* Initialize the Queue Number Registers, if required. */
324 #ifdef EDMA3_PROGRAM_QUEUE_NUM_REGISTER_INIT_TIME
325 if (EDMA3_RM_SOK == result)
326 {
327 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
329 globalRegs = (volatile EDMA3_CCRL_Regs *)(drvObj[phyCtrllerInstId].gblCfgParams.globalRegs);
331 if (NULL != globalRegs)
332 {
333 /* Initialize DMA Queue Num Registers */
334 for (count = 0;
335 count < drvObj[phyCtrllerInstId].gblCfgParams.numDmaChannels;
336 count++)
337 {
338 globalRegs->DMAQNUM[count >> 3u] &= EDMA3_DRV_DMAQNUM_CLR_MASK(count);
339 globalRegs->DMAQNUM[count >> 3u] |= EDMA3_DRV_DMAQNUM_SET_MASK(count,
340 edma3DmaQdmaQueueNumConfig.dmaChannelQueueNum[count]);
341 }
343 /* Initialize QDMA Queue Num Registers */
344 for (count = 0;
345 count < drvObj[phyCtrllerInstId].gblCfgParams.numQdmaChannels;
346 count++)
347 {
348 globalRegs->QDMAQNUM &= EDMA3_DRV_QDMAQNUM_CLR_MASK(count);
349 globalRegs->QDMAQNUM |= EDMA3_DRV_QDMAQNUM_SET_MASK(count,
350 edma3DmaQdmaQueueNumConfig.qdmaChannelQueueNum[count]);
351 }
352 }
353 }
354 #endif
355 }
356 }
358 return result;
359 }
363 /**
364 * \brief Delete EDMA3 Driver Object
365 *
366 * Use this API to delete the EDMA3 Driver Object. It should be called only
367 * ONCE for each EDMA3 hardware instance. It should be called ONLY after
368 * closing all the EDMA3 Driver Instances.
369 *
370 * This API is used to delete the EDMA3 Driver Object. It should be called
371 * once for each EDMA3 hardware instance, ONLY after closing all the
372 * previously opened EDMA3 Driver Instances.
373 *
374 * After successful completion of this API, Driver Object's state
375 * changes to EDMA3_DRV_DELETED.
376 *
377 * \param phyCtrllerInstId [IN] EDMA3 Phy Controller Instance Id (Hardware
378 * instance id, starting from 0).
379 * \param param [IN] For possible future use.
380 *
381 * \return EDMA3_DRV_SOK or EDMA3_DRV Error code
382 */
383 EDMA3_DRV_Result EDMA3_DRV_delete(unsigned int phyCtrllerInstId,
384 const void *param)
385 {
386 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
388 /*to remove CCS remark: parameter "param" was never referenced */
389 (void)param;
391 /* If parameter checking is enabled... */
392 #ifndef EDMA3_DRV_PARAM_CHECK_DISABLE
393 if (phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES)
394 {
395 result = EDMA3_DRV_E_INVALID_PARAM;
396 }
397 #endif
399 /* Check if the parameters are OK. */
400 if (EDMA3_DRV_SOK == result)
401 {
402 /**
403 * If number of Driver Instances is 0, then state should be
404 * EDMA3_DRV_CLOSED OR EDMA3_DRV_CREATED.
405 */
406 if ((NULL == drvObj[phyCtrllerInstId].numOpens)
407 && ((drvObj[phyCtrllerInstId].state != EDMA3_DRV_CLOSED)
408 && (drvObj[phyCtrllerInstId].state != EDMA3_DRV_CREATED)))
409 {
410 result = EDMA3_DRV_E_OBJ_NOT_CLOSED;
411 }
412 else
413 {
414 /**
415 * If number of Driver Instances is NOT 0, then this function
416 * SHOULD NOT be called by anybody.
417 */
418 if (NULL != drvObj[phyCtrllerInstId].numOpens)
419 {
420 result = EDMA3_DRV_E_INVALID_STATE;
421 }
422 else
423 {
424 /**
425 * State is correct. Delete the RM Object.
426 */
427 result = EDMA3_RM_delete (phyCtrllerInstId, NULL);
429 if (EDMA3_RM_SOK == result)
430 {
431 /** Change state to EDMA3_DRV_DELETED */
432 drvObj[phyCtrllerInstId].state = EDMA3_DRV_DELETED;
434 /* Also, reset the Driver Object Global Config Info */
435 edma3MemZero((void *)&(drvObj[phyCtrllerInstId].gblCfgParams),
436 sizeof(EDMA3_DRV_GblConfigParams));
437 }
438 }
439 }
440 }
442 return result;
443 }
446 /**
447 * \brief Open EDMA3 Driver Instance
448 *
449 * This API is used to open an EDMA3 Driver Instance. It could be
450 * called multiple times, for each possible EDMA3 shadow region. Maximum
451 * EDMA3_MAX_REGIONS instances are allowed for each EDMA3 hardware
452 * instance. Multiple instances on the same shadow region are NOT allowed.
453 *
454 * Also, only ONE Master Driver Instance is permitted. This master
455 * instance (and hence the region to which it belongs) will only receive the
456 * EDMA3 interrupts, if enabled.
457 *
458 * User could pass the instance specific configuration structure
459 * (initCfg.drvInstInitConfig) as a part of the 'initCfg' structure,
460 * during init-time. In case user doesn't provide it, this information could
461 * be taken from the SoC specific configuration file edma3_<SOC_NAME>_cfg.c,
462 * in case it is available.
463 *
464 * \param phyCtrllerInstId [IN] EDMA3 Controller Instance Id (Hardware
465 * instance id, starting from 0).
466 * \param initCfg [IN] Used to Initialize the EDMA3 Driver
467 * Instance (Master or Slave).
468 * \param errorCode [OUT] Error code while opening DRV instance.
469 *
470 * \return EDMA3_DRV_Handle : If successfully opened, the API will return the
471 * associated driver's instance handle.
472 *
473 * \note This function disables the global interrupts (by calling API
474 * edma3OsProtectEntry with protection level
475 * EDMA3_OS_PROTECT_INTERRUPT) while modifying the global data
476 * structures, to make it re-entrant.
477 */
478 EDMA3_DRV_Handle EDMA3_DRV_open (unsigned int phyCtrllerInstId,
479 const EDMA3_DRV_InitConfig *initCfg,
480 EDMA3_DRV_Result *errorCode)
481 {
482 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
483 EDMA3_DRV_Object *drvObject = NULL;
484 EDMA3_DRV_Instance *drvInstanceHandle = NULL;
485 unsigned int intState = 0;
486 volatile EDMA3_CCRL_Regs *globalRegs = NULL;
487 unsigned short flag = 0;
489 /* If parameter checking is enabled... */
490 #ifndef EDMA3_DRV_PARAM_CHECK_DISABLE
491 if (((initCfg == NULL) || (phyCtrllerInstId >= EDMA3_MAX_EDMA3_INSTANCES))
492 || (errorCode == NULL))
493 {
494 result = EDMA3_DRV_E_INVALID_PARAM;
495 }
496 #endif
498 /* Check if the parameters are OK. */
499 if (EDMA3_DRV_SOK == result)
500 {
501 /* Check whether the semaphore handle is null or not */
502 if (NULL== initCfg->drvSemHandle)
503 {
504 result = EDMA3_DRV_E_INVALID_PARAM;
505 }
506 else
507 {
508 drvObject = &drvObj[phyCtrllerInstId];
509 if (NULL == drvObject)
510 {
511 result = EDMA3_DRV_E_INVALID_PARAM;
512 }
513 else
514 {
515 if (initCfg->regionId >= drvObject->gblCfgParams.numRegions)
516 {
517 result = EDMA3_DRV_E_INVALID_PARAM;
518 }
519 else
520 {
521 /* if no instance is opened and this is the first one,
522 * then state should be created/closed.
523 */
524 if (((drvObject->numOpens == NULL) && (drvObject->state != EDMA3_DRV_CREATED))
525 && (drvObject->state != EDMA3_DRV_CLOSED))
526 {
527 result = EDMA3_DRV_E_INVALID_STATE;
528 }
529 else
530 {
531 /* if num of instances opened is more than 0 and less than no of regions,
532 * then state should be opened.
533 */
534 if (((drvObject->numOpens > 0) && (drvObject->numOpens < drvObject->gblCfgParams.numRegions))
535 && (drvObject->state != EDMA3_DRV_OPENED))
536 {
537 result = EDMA3_DRV_E_INVALID_STATE;
538 }
539 else
540 {
541 /* if a driver instance is already there for a specific region,
542 * it should return an error.
543 */
544 drvInstanceHandle = &drvInstance[phyCtrllerInstId][initCfg->regionId];
545 if (drvInstanceHandle->pDrvObjectHandle != NULL)
546 {
547 drvInstanceHandle = NULL;
548 result = EDMA3_DRV_E_INST_ALREADY_EXISTS;
549 }
550 }
551 }
552 }
553 }
554 }
555 }
557 if (EDMA3_DRV_SOK == result)
558 {
559 /* Save the region specific information in the region specific drv instance*/
560 drvInstanceHandle->regionId = initCfg->regionId;
561 drvInstanceHandle->isMaster = initCfg->isMaster;
562 drvInstanceHandle->drvSemHandle = initCfg->drvSemHandle;
563 drvInstanceHandle->gblerrCbParams.gblerrCb = initCfg->gblerrCb;
564 drvInstanceHandle->gblerrCbParams.gblerrData = initCfg->gblerrData;
566 if (NULL != initCfg->drvInstInitConfig)
567 {
568 edma3MemCpy((void *)(&drvInstanceHandle->drvInstInitConfig),
569 (const void *)(initCfg->drvInstInitConfig),
570 sizeof (EDMA3_DRV_InstanceInitConfig));
572 /* Flag to remember that driver has passed config info to RM */
573 flag = 1u;
574 }
576 if (NULL == drvObject->gblCfgParams.globalRegs)
577 {
578 drvInstanceHandle = NULL;
579 result = EDMA3_DRV_E_INVALID_PARAM;
580 }
581 else
582 {
583 globalRegs = (volatile EDMA3_CCRL_Regs *)drvObject->gblCfgParams.globalRegs;
585 /* Update shadowRegs */
586 drvInstanceHandle->shadowRegs = (EDMA3_CCRL_ShadowRegs *)
587 (&(globalRegs->SHADOW[initCfg->regionId]));
589 result = edma3OpenResMgr (phyCtrllerInstId, initCfg->regionId, flag);
590 if (EDMA3_DRV_SOK != result)
591 {
592 drvInstanceHandle = NULL;
593 }
594 else
595 {
596 drvObject->state = EDMA3_DRV_OPENED;
597 edma3OsProtectEntry (phyCtrllerInstId,
598 EDMA3_OS_PROTECT_INTERRUPT,
599 &intState);
600 drvObject->numOpens++;
601 edma3OsProtectExit (phyCtrllerInstId,
602 EDMA3_OS_PROTECT_INTERRUPT,
603 intState);
604 }
605 }
606 }
608 if (errorCode)
609 *errorCode = result;
610 return (EDMA3_DRV_Handle)drvInstanceHandle;
611 }
614 /**
615 * \brief Close the EDMA3 Driver Instance.
616 *
617 * This API is used to close a previously opened EDMA3 Driver Instance.
618 *
619 * \param hEdma [IN] Handle to the previously opened EDMA3
620 * Driver Instance.
621 * \param param [IN] For possible future use
622 *
623 * \return EDMA3_DRV_SOK or EDMA3_DRV Error code
624 *
625 * \note This function disables the global interrupts (by calling API
626 * edma3OsProtectEntry with protection level
627 * EDMA3_OS_PROTECT_INTERRUPT) while modifying the global data
628 * structures, to make it re-entrant.
629 */
630 EDMA3_DRV_Result EDMA3_DRV_close(EDMA3_DRV_Handle hEdma,
631 const void *param)
632 {
633 unsigned int intState = 0;
634 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
635 EDMA3_DRV_Instance *drvInst = NULL;
636 EDMA3_DRV_Object *drvObject = NULL;
638 /*to remove CCS remark: parameter "param" was never referenced */
639 (void)param;
641 /* If parameter checking is enabled... */
642 #ifndef EDMA3_DRV_PARAM_CHECK_DISABLE
643 if (hEdma == NULL)
644 {
645 result = EDMA3_DRV_E_INVALID_PARAM;
646 }
647 #endif
649 /* Check if the parameters are OK. */
650 if (EDMA3_DRV_SOK == result)
651 {
652 drvInst = (EDMA3_DRV_Instance *)hEdma;
653 drvObject = drvInst->pDrvObjectHandle;
655 if (drvObject == NULL)
656 {
657 result = EDMA3_DRV_E_INVALID_PARAM;
658 }
659 else
660 {
661 /* Check state of driver */
662 if (drvObject->state != EDMA3_DRV_OPENED)
663 {
664 result = EDMA3_DRV_E_OBJ_NOT_OPENED;
665 }
666 else
667 {
668 result = EDMA3_RM_close (drvInst->resMgrInstance, NULL);
670 if (result != EDMA3_RM_SOK)
671 {
672 result = EDMA3_DRV_E_RM_CLOSE_FAIL;
673 }
674 else
675 {
676 /* Set the driver instance specific info null */
677 drvInst->resMgrInstance = NULL;
678 drvInst->pDrvObjectHandle = NULL;
679 edma3MemZero((void *)&(drvInst->drvInstInitConfig),
680 sizeof (EDMA3_DRV_InstanceInitConfig));
681 drvInst->shadowRegs = NULL;
683 edma3OsProtectEntry (drvObject->phyCtrllerInstId,
684 EDMA3_OS_PROTECT_INTERRUPT,
685 &intState);
686 /* Decrease the Number of Opens */
687 --drvObject->numOpens;
688 if (NULL == drvObject->numOpens)
689 {
690 drvObject->state = EDMA3_DRV_CLOSED;
691 }
692 edma3OsProtectExit (drvObject->phyCtrllerInstId,
693 EDMA3_OS_PROTECT_INTERRUPT,
694 intState);
695 }
696 }
697 }
698 }
700 return (result);
701 }
704 /* Definitions of Local functions - Start */
705 /* Local function to prepare the init config structure for open of Resource Manager */
706 static EDMA3_DRV_Result edma3OpenResMgr (unsigned int instId,
707 unsigned int regionId,
708 unsigned short flag)
709 {
710 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
711 EDMA3_RM_Param initParam;
712 EDMA3_RM_InstanceInitConfig rmInstanceCfg;
713 EDMA3_RM_Handle hResMgr = NULL;
714 EDMA3_RM_Result rmResult;
715 unsigned int resMgrIdx = 0u;
716 EDMA3_RM_Instance *temp_rm_instance = NULL;
718 assert ((instId < EDMA3_MAX_EDMA3_INSTANCES)
719 && (regionId < drvObj[instId].gblCfgParams.numRegions));
721 initParam.regionId = regionId;
722 initParam.rmSemHandle = drvInstance[instId][regionId].drvSemHandle;
723 /*
724 * If the EDMA driver instance is MASTER, do the
725 * (global + region_specific) init. For all other instances,
726 * only do the (region_specific) init.
727 */
728 initParam.isMaster = drvInstance[instId][regionId].isMaster;
729 initParam.regionInitEnable = TRUE;
731 initParam.gblerrCbParams.gblerrCb = drvInstance[instId][regionId].gblerrCbParams.gblerrCb;
732 initParam.gblerrCbParams.gblerrData = drvInstance[instId][regionId].gblerrCbParams.gblerrData;
734 if (flag == 1u)
735 {
736 /**
737 * User has passed the instance initialization specific info,
738 * which we have saved previously too, so use it.
739 */
740 edma3MemCpy((void *)(&rmInstanceCfg),
741 (const void *)(&drvInstance[instId][regionId].drvInstInitConfig),
742 sizeof (EDMA3_RM_InstanceInitConfig));
744 initParam.rmInstInitConfig = &rmInstanceCfg;
746 hResMgr = EDMA3_RM_open (instId, (EDMA3_RM_Param *)&initParam, &rmResult);
748 if (NULL == hResMgr)
749 {
750 result = rmResult;
751 }
752 }
753 else
754 {
755 /**
756 * User has NOT passed the instance initialization specific info.
757 * Pass NULL to the Resource Manager.
758 */
759 initParam.rmInstInitConfig = NULL;
761 hResMgr = EDMA3_RM_open (instId, (EDMA3_RM_Param *)&initParam, &rmResult);
763 if (NULL == hResMgr)
764 {
765 result = rmResult;
766 }
767 else
768 {
769 /**
770 * Save the RM Instance specific information in the driver.
771 * Earlier this was easier, now a bit tricky.
772 * Search for the RM instance number based on the handle
773 * just returned, to fetch the correct config info from the
774 * userInitConfig[].
775 */
776 for (resMgrIdx = 0u; resMgrIdx < EDMA3_MAX_RM_INSTANCES; resMgrIdx++)
777 {
778 temp_rm_instance = ((EDMA3_RM_Instance *)(ptrRMIArray) + (instId*EDMA3_MAX_RM_INSTANCES) + resMgrIdx);
780 if (hResMgr == temp_rm_instance)
781 {
782 /* RM Id found. Copy the specific config info to the drvInstance [] */
783 edma3MemCpy((void *)(&drvInstance[instId][regionId].drvInstInitConfig),
784 (const void *)((EDMA3_RM_InstanceInitConfig *)(ptrInitCfgArray) + (instId*EDMA3_MAX_RM_INSTANCES) + resMgrIdx),
785 sizeof (EDMA3_RM_InstanceInitConfig));
786 break;
787 }
788 }
790 if (EDMA3_MAX_RM_INSTANCES == resMgrIdx)
791 {
792 /* RM Id not found, report error... */
793 result = EDMA3_DRV_E_INVALID_PARAM;
794 }
795 }
796 }
799 if (EDMA3_RM_SOK == result)
800 {
801 /* Save handle to Resource Manager Instance */
802 drvInstance[instId][regionId].resMgrInstance = hResMgr;
803 /* Save handle to EDMA Driver Object */
804 drvInstance[instId][regionId].pDrvObjectHandle = &drvObj[instId];
805 }
807 return result;
808 }
810 /* Definitions of Local functions - End */
812 /* End of File */