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 - 2019 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 */
42 #include <ti/sysbios/hal/Cache.h>
44 #include <ti/sysbios/hal/Hwi.h>
45 #include <ti/sysbios/knl/Task.h>
46 #include <ti/sysbios/knl/Semaphore.h>
48 #include <ti/sdo/edma3/drv/sample/bios6_edma3_drv_sample.h>
50 extern uint32_t ccXferCompInt[EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_REGIONS];
51 extern uint32_t ccErrorInt[EDMA3_MAX_EDMA3_INSTANCES];
52 extern uint32_t tcErrorInt[EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_TC];
54 /**
55  * Shadow Region on which the executable is running. Its value is
56  * populated with the DSP Instance Number here in this case.
57  */
58 extern uint32_t region_id;
60 /**
61  * \brief   EDMA3 OS Protect Entry
62  *
63  *      This function saves the current state of protection in 'intState'
64  *      variable passed by caller, if the protection level is
65  *      EDMA3_OS_PROTECT_INTERRUPT. It then applies the requested level of
66  *      protection.
67  *      For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
68  *      EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
69  *      and the requested interrupt is disabled.
70  *      For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, '*intState' specifies the
71  *      Transfer Controller number whose interrupt needs to be disabled.
72  *
73  * \param   level is numeric identifier of the desired degree of protection.
74  * \param   intState is memory location where current state of protection is
75  *      saved for future use while restoring it via edma3OsProtectExit() (Only
76  *      for EDMA3_OS_PROTECT_INTERRUPT protection level).
77  * \return  None
78  */
79 void edma3OsProtectEntry (uint32_t edma3InstanceId,
80                             int32_t level, uint32_t *intState)
81     {
82     if (((level == EDMA3_OS_PROTECT_INTERRUPT)
83         || (level == EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR))
84         && (intState == NULL))
85         {
86             /* Nothing to be done here */
87         }
88     else
89         {
90         switch (level)
91             {
92             /* Disable all (global) interrupts */
93             case EDMA3_OS_PROTECT_INTERRUPT :
94                 *intState = Hwi_disable();
95                 break;
97             /* Disable scheduler */
98             case EDMA3_OS_PROTECT_SCHEDULER :
99                         Task_disable();
100                 break;
102             /* Disable EDMA3 transfer completion interrupt only */
103             case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
104                 Hwi_disableInterrupt(ccXferCompInt[edma3InstanceId][region_id]);
105                 break;
107             /* Disable EDMA3 CC error interrupt only */
108             case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
109                 Hwi_disableInterrupt(ccErrorInt[edma3InstanceId]);
110                 break;
112             /* Disable EDMA3 TC error interrupt only */
113             case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
114                 switch (*intState)
115                     {
116                     case 0:
117                     case 1:
118                     case 2:
119                     case 3:
120                     case 4:
121                     case 5:
122                     case 6:
123                     case 7:
124                         /* Fall through... */
125                         /* Disable the corresponding interrupt */
126                         Hwi_disableInterrupt(tcErrorInt[edma3InstanceId][*intState]);
127                         break;
129                      default:
130                         break;
131                     }
133                 break;
135             default:
136                 break;
137             }
138         }
139         return;
140     }
143 /**
144  * \brief   EDMA3 OS Protect Exit
145  *
146  *      This function undoes the protection enforced to original state
147  *      as is specified by the variable 'intState' passed, if the protection
148  *      level is EDMA3_OS_PROTECT_INTERRUPT.
149  *      For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
150  *      EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
151  *      and the requested interrupt is enabled.
152  *      For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, 'intState' specifies the
153  *      Transfer Controller number whose interrupt needs to be enabled.
154  * \param   level is numeric identifier of the desired degree of protection.
155  * \param   intState is original state of protection at time when the
156  *      corresponding edma3OsProtectEntry() was called (Only
157  *      for EDMA3_OS_PROTECT_INTERRUPT protection level).
158  * \return  None
159  */
160 void edma3OsProtectExit (uint32_t edma3InstanceId,
161                         int32_t level, uint32_t intState)
162     {
163     switch (level)
164         {
165         /* Enable all (global) interrupts */
166         case EDMA3_OS_PROTECT_INTERRUPT :
167             Hwi_restore(intState);
168             break;
170         /* Enable scheduler */
171         case EDMA3_OS_PROTECT_SCHEDULER :
172             Task_enable();
173             break;
175         /* Enable EDMA3 transfer completion interrupt only */
176         case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
177             Hwi_enableInterrupt(ccXferCompInt[edma3InstanceId][region_id]);
178             break;
180         /* Enable EDMA3 CC error interrupt only */
181         case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
182             Hwi_enableInterrupt(ccErrorInt[edma3InstanceId]);
183             break;
185         /* Enable EDMA3 TC error interrupt only */
186         case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
187             switch ((int32_t)intState)
188                 {
189                 case 0:
190                 case 1:
191                 case 2:
192                 case 3:
193                 case 4:
194                 case 5:
195                 case 6:
196                 case 7:
197                     /* Fall through... */
198                     /* Enable the corresponding interrupt */
199                     Hwi_enableInterrupt(tcErrorInt[edma3InstanceId][intState]);
200                     break;
202                  default:
203                     break;
204                 }
206             break;
208         default:
209             break;
210         }
211     }
214 /**
215  *  \brief   EDMA3 Cache Invalidate
216  *
217  *  This function invalidates the D cache.
218  *
219  *  \param  mem_start_ptr [IN]      Starting address of memory.
220  *                                  Please note that this should be
221  *                                  aligned according to the cache line size.
222  *  \param  num_bytes [IN]          length of buffer
223  *  \return  EDMA3_DRV_SOK if success, else error code in case of error
224  *          or non-alignment of buffers.
225  *
226  * Note: This function is required if the buffer is in DDR.
227  * For other cases, where buffer is NOT in DDR, user
228  * may or may not require the below implementation and
229  * should modify it according to her need.
230  */
231 EDMA3_DRV_Result Edma3_CacheInvalidate(uint32_t mem_start_ptr,
232                            uint32_t    num_bytes)
233     {
234     EDMA3_DRV_Result cacheInvResult = EDMA3_DRV_SOK;
236     /* Verify whether the start address is cache aligned or not */
237     if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U))    !=    0)
238         {
239 #ifdef EDMA3_DRV_DEBUG
240         EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
241                             EDMA3_CACHE_LINE_SIZE_IN_BYTES);
242 #endif
243         cacheInvResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
244         }
245     else
246         {
247             Cache_inv((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
248         }
250     return cacheInvResult;
255 /**
256  * \brief   EDMA3 Cache Flush
257  *
258  *  This function flushes (cleans) the Cache
259  *
260  *  \param  mem_start_ptr [IN]      Starting address of memory.
261  *                                  Please note that this should be
262  *                                  aligned according to the cache line size.
263  *  \param  num_bytes [IN]          length of buffer
264  *  \return  EDMA3_DRV_SOK if success, else error code in case of error
265  *          or non-alignment of buffers.
266  *
267  * Note: This function is required if the buffer is in DDR.
268  * For other cases, where buffer is NOT in DDR, user
269  * may or may not require the below implementation and
270  * should modify it according to her need.
271  */
272 EDMA3_DRV_Result Edma3_CacheFlush(uint32_t mem_start_ptr,
273                       uint32_t num_bytes)
274     {
275     EDMA3_DRV_Result cacheFlushResult = EDMA3_DRV_SOK;
277     /* Verify whether the start address is cache aligned or not */
278     if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U))    !=    0)
279         {
280 #ifdef EDMA3_DRV_DEBUG
281         EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
282                             EDMA3_CACHE_LINE_SIZE_IN_BYTES);
283 #endif
284         cacheFlushResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
285         }
286     else
287         {
288             Cache_wb((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
289         }
291     return cacheFlushResult;
295 /**
296   * Counting Semaphore related functions (OS dependent) should be
297   * called/implemented by the application. A handle to the semaphore
298   * is required while opening the driver/resource manager instance.
299   */
301 /**
302  * \brief   EDMA3 OS Semaphore Create
303  *
304  *      This function creates a counting semaphore with specified
305  *      attributes and initial value. It should be used to create a semaphore
306  *      with initial value as '1'. The semaphore is then passed by the user
307  *      to the EDMA3 driver/RM for proper sharing of resources.
308  * \param   initVal [IN] is initial value for semaphore
309  * \param   semParams [IN] is the semaphore attributes.
310  * \param   hSem [OUT] is location to recieve the handle to just created
311  *      semaphore
312  * \return  EDMA3_DRV_SOK if succesful, else a suitable error code.
313  */
314 EDMA3_DRV_Result edma3OsSemCreate(int32_t initVal,
315                                                         const Semaphore_Params *semParams,
316                                 EDMA3_OS_Sem_Handle *hSem)
317     {
318     EDMA3_DRV_Result semCreateResult = EDMA3_DRV_SOK;
320     if(NULL == hSem)
321         {
322         semCreateResult = EDMA3_DRV_E_INVALID_PARAM;
323         }
324     else
325         {
326         *hSem = (EDMA3_OS_Sem_Handle)Semaphore_create(initVal, semParams, NULL);
327         if ( (*hSem) == NULL )
328             {
329             semCreateResult = EDMA3_DRV_E_SEMAPHORE;
330             }
331         }
333     return semCreateResult;
334     }
337 /**
338  * \brief   EDMA3 OS Semaphore Delete
339  *
340  *      This function deletes or removes the specified semaphore
341  *      from the system. Associated dynamically allocated memory
342  *      if any is also freed up.
343  * \param   hSem [IN] handle to the semaphore to be deleted
344  * \return  EDMA3_DRV_SOK if succesful else a suitable error code
345  */
346 EDMA3_DRV_Result edma3OsSemDelete(EDMA3_OS_Sem_Handle hSem)
347     {
348     EDMA3_DRV_Result semDeleteResult = EDMA3_DRV_SOK;
350     if(NULL == hSem)
351         {
352         semDeleteResult = EDMA3_DRV_E_INVALID_PARAM;
353         }
354     else
355         {
356                 Semaphore_delete((Semaphore_Handle *)&hSem);
357         }
359     return semDeleteResult;
360     }
363 /**
364  * \brief   EDMA3 OS Semaphore Take
365  *
366  *      This function takes a semaphore token if available.
367  *      If a semaphore is unavailable, it blocks currently
368  *      running thread in wait (for specified duration) for
369  *      a free semaphore.
370  * \param   hSem [IN] is the handle of the specified semaphore
371  * \param   mSecTimeout [IN] is wait time in milliseconds
372  * \return  EDMA3_Result if successful else a suitable error code
373  */
374 EDMA3_Result edma3OsSemTake(EDMA3_OS_Sem_Handle hSem, int32_t mSecTimeout)
375     {
376     EDMA3_Result semTakeResult = EDMA3_DRV_SOK;
378     if(NULL == hSem)
379         {
380         semTakeResult = EDMA3_DRV_E_INVALID_PARAM;
381         }
382     else
383         {
384         if((Semaphore_pend((Semaphore_Handle)hSem, (uint32_t)mSecTimeout)) == FALSE)
385             {
386             semTakeResult = EDMA3_DRV_E_SEMAPHORE;
387             }
388         }
390     return semTakeResult;
391     }
394 /**
395  * \brief   EDMA3 OS Semaphore Give
396  *
397  *      This function gives or relinquishes an already
398  *      acquired semaphore token
399  * \param   hSem [IN] is the handle of the specified semaphore
400  * \return  EDMA3_Result if successful else a suitable error code
401  */
402 EDMA3_Result edma3OsSemGive(EDMA3_OS_Sem_Handle hSem)
403     {
404     EDMA3_Result semGiveResult = EDMA3_DRV_SOK;
406     if(NULL == hSem)
407         {
408         semGiveResult = EDMA3_DRV_E_INVALID_PARAM;
409         }
410     else
411         {
412                 Semaphore_post((Semaphore_Handle)hSem);
413         }
415     return semGiveResult;
416     }
418 /* End of File */