Revert "PRSDK-5267 Add support to enable SMP mode"
[keystone-rtos/edma3_lld.git] / packages / ti / sdo / edma3 / drv / sample / src / sample_arm_cs.c
1 /*
2  * sample_cs.c
3  *
4  * Sample functions showing the implementation of critical section entry/exit
5  * routines and various semaphore related routines (all BIOS6 depenedent).
6  * These implementations MUST be provided by the user / application, using the
7  * EDMA3 driver, for its correct functioning.
8  *
9  * Copyright (C) 2009 - 2016 Texas Instruments Incorporated - http://www.ti.com/
10  *
11  *
12  *  Redistribution and use in source and binary forms, with or without
13  *  modification, are permitted provided that the following conditions
14  *  are met:
15  *
16  *    Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  *
19  *    Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the
22  *    distribution.
23  *
24  *    Neither the name of Texas Instruments Incorporated nor the names of
25  *    its contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *
40 */
41 #ifdef GCC_BUILD
42 #if (defined(BUILD_TDA2XX_MPU) || defined(BUILD_DRA72X_MPU) || defined(BUILD_AM572X_MPU) || defined(BUILD_AM571X_MPU) || defined(BUILD_K2H_MPU) || defined(BUILD_K2K_MPU) || defined(BUILD_K2E_MPU) || defined(BUILD_K2L_MPU) || defined(BUILD_K2G_MPU))
43 #include <ti/sysbios/family/arm/a15/Cache.h>
44 #elif (defined (BUILD_CENTAURUS_A8) || defined (BUILD_AM335X_A8))
45 #include <ti/sysbios/family/arm/a8/Cache.h>
46 #elif defined (BUILD_AM437X_A9)
47 #include <ti/sysbios/family/arm/a9/Cache.h>
48 #endif
49 #else
50 #include <ti/sysbios/hal/Cache.h>
51 #endif
52 #include <ti/sysbios/hal/Hwi.h>
53 #include <ti/sysbios/knl/Task.h>
54 #include <ti/sysbios/knl/Semaphore.h>
56 #include <ti/sdo/edma3/drv/sample/bios6_edma3_drv_sample.h>
58 extern uint32_t ccXferCompInt[EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_REGIONS];
59 extern uint32_t ccErrorInt[EDMA3_MAX_EDMA3_INSTANCES];
60 extern uint32_t tcErrorInt[EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_TC];
62 /**
63  * Shadow Region on which the executable is running. Its value is
64  * populated with the DSP Instance Number here in this case.
65  */
66 extern uint32_t region_id;
68 /**
69  * \brief   EDMA3 OS Protect Entry
70  *
71  *      This function saves the current state of protection in 'intState'
72  *      variable passed by caller, if the protection level is
73  *      EDMA3_OS_PROTECT_INTERRUPT. It then applies the requested level of
74  *      protection.
75  *      For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
76  *      EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
77  *      and the requested interrupt is disabled.
78  *      For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, '*intState' specifies the
79  *      Transfer Controller number whose interrupt needs to be disabled.
80  *
81  * \param   level is numeric identifier of the desired degree of protection.
82  * \param   intState is memory location where current state of protection is
83  *      saved for future use while restoring it via edma3OsProtectExit() (Only
84  *      for EDMA3_OS_PROTECT_INTERRUPT protection level).
85  * \return  None
86  */
87 void edma3OsProtectEntry (uint32_t edma3InstanceId,
88                             int32_t level, uint32_t *intState)
89     {
90     if (((level == EDMA3_OS_PROTECT_INTERRUPT)
91         || (level == EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR))
92         && (intState == NULL))
93         {
94             /* Nothing to be done here */
95         }
96     else
97         {
98         switch (level)
99             {
100             /* Disable all (global) interrupts */
101             case EDMA3_OS_PROTECT_INTERRUPT :
102                 *intState = Hwi_disable();
103                 break;
105             /* Disable scheduler */
106             case EDMA3_OS_PROTECT_SCHEDULER :
107                         Task_disable();
108                 break;
110             /* Disable EDMA3 transfer completion interrupt only */
111             case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
112                 Hwi_disableInterrupt(ccXferCompInt[edma3InstanceId][region_id]);
113                 break;
115             /* Disable EDMA3 CC error interrupt only */
116             case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
117                 Hwi_disableInterrupt(ccErrorInt[edma3InstanceId]);
118                 break;
120             /* Disable EDMA3 TC error interrupt only */
121             case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
122                 switch (*intState)
123                     {
124                     case 0:
125                     case 1:
126                     case 2:
127                     case 3:
128                     case 4:
129                     case 5:
130                     case 6:
131                     case 7:
132                         /* Fall through... */
133                         /* Disable the corresponding interrupt */
134                         Hwi_disableInterrupt(tcErrorInt[edma3InstanceId][*intState]);
135                         break;
137                      default:
138                         break;
139                     }
141                 break;
143             default:
144                 break;
145             }
146         }
147         return;
148     }
151 /**
152  * \brief   EDMA3 OS Protect Exit
153  *
154  *      This function undoes the protection enforced to original state
155  *      as is specified by the variable 'intState' passed, if the protection
156  *      level is EDMA3_OS_PROTECT_INTERRUPT.
157  *      For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
158  *      EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
159  *      and the requested interrupt is enabled.
160  *      For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, 'intState' specifies the
161  *      Transfer Controller number whose interrupt needs to be enabled.
162  * \param   level is numeric identifier of the desired degree of protection.
163  * \param   intState is original state of protection at time when the
164  *      corresponding edma3OsProtectEntry() was called (Only
165  *      for EDMA3_OS_PROTECT_INTERRUPT protection level).
166  * \return  None
167  */
168 void edma3OsProtectExit (uint32_t edma3InstanceId,
169                         int32_t level, uint32_t intState)
170     {
171     switch (level)
172         {
173         /* Enable all (global) interrupts */
174         case EDMA3_OS_PROTECT_INTERRUPT :
175             Hwi_restore(intState);
176             break;
178         /* Enable scheduler */
179         case EDMA3_OS_PROTECT_SCHEDULER :
180             Task_enable();
181             break;
183         /* Enable EDMA3 transfer completion interrupt only */
184         case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
185             Hwi_enableInterrupt(ccXferCompInt[edma3InstanceId][region_id]);
186             break;
188         /* Enable EDMA3 CC error interrupt only */
189         case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
190             Hwi_enableInterrupt(ccErrorInt[edma3InstanceId]);
191             break;
193         /* Enable EDMA3 TC error interrupt only */
194         case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
195             switch ((int32_t)intState)
196                 {
197                 case 0:
198                 case 1:
199                 case 2:
200                 case 3:
201                 case 4:
202                 case 5:
203                 case 6:
204                 case 7:
205                     /* Fall through... */
206                     /* Enable the corresponding interrupt */
207                     Hwi_enableInterrupt(tcErrorInt[edma3InstanceId][intState]);
208                     break;
210                  default:
211                     break;
212                 }
214             break;
216         default:
217             break;
218         }
219     }
222 /**
223  *  \brief   EDMA3 Cache Invalidate
224  *
225  *  This function invalidates the D cache.
226  *
227  *  \param  mem_start_ptr [IN]      Starting address of memory.
228  *                                  Please note that this should be
229  *                                  aligned according to the cache line size.
230  *  \param  num_bytes [IN]          length of buffer
231  *  \return  EDMA3_DRV_SOK if success, else error code in case of error
232  *          or non-alignment of buffers.
233  *
234  * Note: This function is required if the buffer is in DDR.
235  * For other cases, where buffer is NOT in DDR, user
236  * may or may not require the below implementation and
237  * should modify it according to her need.
238  */
239 EDMA3_DRV_Result Edma3_CacheInvalidate(uint32_t mem_start_ptr,
240                            uint32_t    num_bytes)
241     {
242     EDMA3_DRV_Result cacheInvResult = EDMA3_DRV_SOK;
244     /* Verify whether the start address is cache aligned or not */
245     if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U))    !=    0)
246         {
247 #ifdef EDMA3_DRV_DEBUG
248         EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
249                             EDMA3_CACHE_LINE_SIZE_IN_BYTES);
250 #endif
251         cacheInvResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
252         }
253     else
254         {
255             Cache_inv((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
256         }
258     return cacheInvResult;
263 /**
264  * \brief   EDMA3 Cache Flush
265  *
266  *  This function flushes (cleans) the Cache
267  *
268  *  \param  mem_start_ptr [IN]      Starting address of memory.
269  *                                  Please note that this should be
270  *                                  aligned according to the cache line size.
271  *  \param  num_bytes [IN]          length of buffer
272  *  \return  EDMA3_DRV_SOK if success, else error code in case of error
273  *          or non-alignment of buffers.
274  *
275  * Note: This function is required if the buffer is in DDR.
276  * For other cases, where buffer is NOT in DDR, user
277  * may or may not require the below implementation and
278  * should modify it according to her need.
279  */
280 EDMA3_DRV_Result Edma3_CacheFlush(uint32_t mem_start_ptr,
281                       uint32_t num_bytes)
282     {
283     EDMA3_DRV_Result cacheFlushResult = EDMA3_DRV_SOK;
285     /* Verify whether the start address is cache aligned or not */
286     if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U))    !=    0)
287         {
288 #ifdef EDMA3_DRV_DEBUG
289         EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
290                             EDMA3_CACHE_LINE_SIZE_IN_BYTES);
291 #endif
292         cacheFlushResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
293         }
294     else
295         {
296             Cache_wb((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
297         }
299     return cacheFlushResult;
303 /**
304   * Counting Semaphore related functions (OS dependent) should be
305   * called/implemented by the application. A handle to the semaphore
306   * is required while opening the driver/resource manager instance.
307   */
309 /**
310  * \brief   EDMA3 OS Semaphore Create
311  *
312  *      This function creates a counting semaphore with specified
313  *      attributes and initial value. It should be used to create a semaphore
314  *      with initial value as '1'. The semaphore is then passed by the user
315  *      to the EDMA3 driver/RM for proper sharing of resources.
316  * \param   initVal [IN] is initial value for semaphore
317  * \param   semParams [IN] is the semaphore attributes.
318  * \param   hSem [OUT] is location to recieve the handle to just created
319  *      semaphore
320  * \return  EDMA3_DRV_SOK if succesful, else a suitable error code.
321  */
322 EDMA3_DRV_Result edma3OsSemCreate(int32_t initVal,
323                                                         const Semaphore_Params *semParams,
324                                 EDMA3_OS_Sem_Handle *hSem)
325     {
326     EDMA3_DRV_Result semCreateResult = EDMA3_DRV_SOK;
328     if(NULL == hSem)
329         {
330         semCreateResult = EDMA3_DRV_E_INVALID_PARAM;
331         }
332     else
333         {
334         *hSem = (EDMA3_OS_Sem_Handle)Semaphore_create(initVal, semParams, NULL);
335         if ( (*hSem) == NULL )
336             {
337             semCreateResult = EDMA3_DRV_E_SEMAPHORE;
338             }
339         }
341     return semCreateResult;
342     }
345 /**
346  * \brief   EDMA3 OS Semaphore Delete
347  *
348  *      This function deletes or removes the specified semaphore
349  *      from the system. Associated dynamically allocated memory
350  *      if any is also freed up.
351  * \param   hSem [IN] handle to the semaphore to be deleted
352  * \return  EDMA3_DRV_SOK if succesful else a suitable error code
353  */
354 EDMA3_DRV_Result edma3OsSemDelete(EDMA3_OS_Sem_Handle hSem)
355     {
356     EDMA3_DRV_Result semDeleteResult = EDMA3_DRV_SOK;
358     if(NULL == hSem)
359         {
360         semDeleteResult = EDMA3_DRV_E_INVALID_PARAM;
361         }
362     else
363         {
364                 Semaphore_delete((Semaphore_Handle *)&hSem);
365         }
367     return semDeleteResult;
368     }
371 /**
372  * \brief   EDMA3 OS Semaphore Take
373  *
374  *      This function takes a semaphore token if available.
375  *      If a semaphore is unavailable, it blocks currently
376  *      running thread in wait (for specified duration) for
377  *      a free semaphore.
378  * \param   hSem [IN] is the handle of the specified semaphore
379  * \param   mSecTimeout [IN] is wait time in milliseconds
380  * \return  EDMA3_Result if successful else a suitable error code
381  */
382 EDMA3_Result edma3OsSemTake(EDMA3_OS_Sem_Handle hSem, int32_t mSecTimeout)
383     {
384     EDMA3_Result semTakeResult = EDMA3_DRV_SOK;
386     if(NULL == hSem)
387         {
388         semTakeResult = EDMA3_DRV_E_INVALID_PARAM;
389         }
390     else
391         {
392         if((Semaphore_pend((Semaphore_Handle)hSem, (uint32_t)mSecTimeout)) == FALSE)
393             {
394             semTakeResult = EDMA3_DRV_E_SEMAPHORE;
395             }
396         }
398     return semTakeResult;
399     }
402 /**
403  * \brief   EDMA3 OS Semaphore Give
404  *
405  *      This function gives or relinquishes an already
406  *      acquired semaphore token
407  * \param   hSem [IN] is the handle of the specified semaphore
408  * \return  EDMA3_Result if successful else a suitable error code
409  */
410 EDMA3_Result edma3OsSemGive(EDMA3_OS_Sem_Handle hSem)
411     {
412     EDMA3_Result semGiveResult = EDMA3_DRV_SOK;
414     if(NULL == hSem)
415         {
416         semGiveResult = EDMA3_DRV_E_INVALID_PARAM;
417         }
418     else
419         {
420                 Semaphore_post((Semaphore_Handle)hSem);
421         }
423     return semGiveResult;
424     }
426 /* End of File */