Add support for watchdog timer interrupts on DRA7xx IPU
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / Ipc.c
1 /*
2  *  Copyright (c) 2008-2014, Texas Instruments Incorporated
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *  *  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *  *  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  *  Neither the name of Texas Instruments Incorporated nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
33 /*  ----------------------------------- Standard headers   */
34 #include <ti/syslink/Std.h>
36 /*  ----------------------------------- SysLink IPC module Headers   */
37 #include <ti/ipc/Ipc.h>
38 #include <_Ipc.h>
39 #include <IpcKnl.h>
40 #include <Platform.h>
41 #include <Bitops.h>
42 #include <RscTable.h>
43 #include <_MessageQCopy.h>
44 #include <ti/ipc/MessageQCopy.h>
46 #if defined(SYSLINK_PLATFORM_VAYU)
47 #include <gptimers.h>
48 #endif
50 /*  ----------------------------------- SysLink utils Headers   */
51 #include <ti/syslink/inc/_MultiProc.h>
52 #include <ti/ipc/MultiProc.h>
53 #include <ti/syslink/utils/Gate.h>
54 #include <ti/syslink/utils/Trace.h>
55 #include <ti/syslink/utils/Cache.h>
56 #include <ti/syslink/utils/Memory.h>
58 #if defined(SYSLINK_USE_IPU_PM)
59 #include <ipu_pm.h>
60 #endif
62 #if defined  (__cplusplus)
63 extern "C" {
64 #endif
67 /* =============================================================================
68  * Macros
69  * =============================================================================
70  */
71 /* Macro to make a correct module magic number with refCount */
72 #define Ipc_MAKE_MAGICSTAMP(x) ((SharedRegion_MODULEID << 16u) | (x))
75 /* =============================================================================
76  * Enums & Structures
77  * =============================================================================
78  */
80 /* The structure used for reserving memory in SharedRegion */
81 typedef struct Ipc_Reserved {
82     volatile Bits32    startedKey;
83 //    SharedRegion_SRPtr ipu_pm_sr_ptr; //Ramesh: Port from WinCe.
84 } Ipc_Reserved;
87 /*!
88  *  head of the config list
89  */
90 typedef struct Ipc_ConfigHead {
91     volatile Bits32 first;
92     /* Address of first config entry */
93 } Ipc_ConfigHead;
96 /*!
97  *   This structure captures Configuration details of a module/instance
98  *   written by a slave to synchornize with a remote slave/HOST
99  */
100 typedef struct Ipc_ConfigEntry {
101     volatile Bits32 remoteProcId;
102     /* Remote processor identifier */
103     volatile Bits32 localProcId;
104     /* Config Entry owner processor identifier */
105     volatile Bits32 tag;
106     /* Unique tag to distinguish config from other config entries */
107     volatile Bits32 size;
108     /* Size of the config pointer */
109     volatile Bits32 next;
110     /* Address of next config entry  (In SRPtr format) */
111 } Ipc_ConfigEntry;
113 /*
114  *  This structure defines the fields that are to be configured
115  *  between the executing processor and a remote processor.
116  */
117 typedef struct Ipc_Entry {
118     UInt16 remoteProcId;            /* the remote processor id   */
119     Bool    setup_ipu_pm;          //Ramesh: port from WinCE
120 } Ipc_Entry;
122 /*!
123  *   Ipc instance structure.
124  */
125 typedef struct Ipc_ProcEntry {
126     Ptr        localConfigList;
127     Ptr        remoteConfigList;
128     Ptr        userObj;
129     Bool       slave;
130     Ipc_Entry  entry;
131     Bool       isAttached;
132 } Ipc_ProcEntry;
135 /*!
136  *  Module state structure
137  */
138 typedef struct Ipc_Module_State {
139     Int32         refCount;
140     Ipc_Config    cfg;
141     Ipc_ProcEntry procEntry [MultiProc_MAXPROCESSORS];
142 } Ipc_Module_State;
145 /* =============================================================================
146  * Globals
147  * =============================================================================
148  */
149 static Ipc_Module_State Ipc_module_state = {
150                                              .refCount = 0,
151                                            };
152 static Ipc_Module_State * Ipc_module = &Ipc_module_state;
155 /* =============================================================================
156  * APIs
157  * =============================================================================
158  */
160 /* attaches to a remote processor */
161 Int Ipc_attach (UInt16 remoteProcId)
163     Int                     status = 0;
164     IArg                    key;
165     UInt32                  numVrings = 0;
166     UInt32                  vringAddr = 0;
167     ProcMgr_Handle          procHandle = NULL;
169     GT_1trace (curTrace, GT_ENTER, "Ipc_attach", remoteProcId);
171     GT_assert(curTrace,remoteProcId < MultiProc_INVALIDID);
172     GT_assert(curTrace,remoteProcId != MultiProc_self());
174     key = Gate_enterSystem ();
175    /* Make sure its not already attached */
176     if (Ipc_module->procEntry[remoteProcId].isAttached) {
177         Ipc_module->procEntry[remoteProcId].isAttached++;
178         Gate_leaveSystem (key);
179         status = Ipc_S_ALREADYSETUP;
180     }
181     else {
182         Gate_leaveSystem (key);
184         status = ProcMgr_open(&procHandle, remoteProcId);
185         if (status >= 0) {
186             /* get IPC VRING information */
187             status = RscTable_getInfo(remoteProcId, TYPE_VDEV, 0, NULL,
188                                       NULL, &numVrings);
189             if (status >= 0) {
190                 status = RscTable_getInfo(remoteProcId, TYPE_VDEV, 1,
191                                           &vringAddr, NULL, NULL);
192                 if (status >= 0) {
193                     status = MessageQCopy_attach(remoteProcId,
194                                                  (Ptr)vringAddr, 0);
195                     if (status >= 0) {
196                         status = RscTable_setStatus(remoteProcId, 7);
197                     }
198                 }
199             }
201             if (status >= 0) {
202                 status = RscTable_update(remoteProcId, procHandle);
203             }
204             ProcMgr_close(&procHandle);
205         }
207 #if defined(SYSLINK_USE_IPU_PM) && defined(SYSLINK_PLATFORM_OMAP5)
208         if (status >= 0) {
209             status = ipu_pm_attach(remoteProcId);
210             if (status < 0) {
211                 MessageQCopy_detach(remoteProcId);
212             }
213         }
214 #endif
216 #if defined(SYSLINK_PLATFORM_VAYU)
217         if (status >= 0) {
218             status = gpt_wdt_attach(remoteProcId);
219             if (status < 0) {
220                 MessageQCopy_detach(remoteProcId);
221             }
222         }
223 #endif
225         if (status >= 0) {
226             key = Gate_enterSystem ();
227             Ipc_module->procEntry[remoteProcId].isAttached++;
228             Gate_leaveSystem (key);
229         }
230     }
231     GT_1trace (curTrace, GT_LEAVE, "Ipc_attach", status);
233     return  (status);
237 /* detaches from a remote processor */
238 Int Ipc_detach (UInt16 remoteProcId)
240     Int                     status = 0;
241     IArg                    key;
242     GT_1trace (curTrace, GT_ENTER, "Ipc_detach", remoteProcId);
244     key = Gate_enterSystem ();
245     if (Ipc_module->procEntry[remoteProcId].isAttached > 1) {
246         /* Only detach if attach count reaches 1 */
247         Ipc_module->procEntry[remoteProcId].isAttached--;
248         Gate_leaveSystem (key);
249         status = Ipc_S_BUSY;
250     }
251     else if (Ipc_module->procEntry[remoteProcId].isAttached == 0) {
252         /* If already detached, then return fail */
253         Gate_leaveSystem (key);
254         status = Ipc_E_FAIL;
255     }
256     else {
257         Gate_leaveSystem (key);
259 #if defined(SYSLINK_USE_IPU_PM) && defined(SYSLINK_PLATFORM_OMAP5)
260         status = ipu_pm_detach (remoteProcId);
261 #endif
263 #if defined(SYSLINK_PLATFORM_VAYU)
264         status = gpt_wdt_detach(remoteProcId);
265 #endif
267         status = MessageQCopy_detach (remoteProcId);
269         key = Gate_enterSystem ();
270         Ipc_module->procEntry[remoteProcId].isAttached--;
271         Gate_leaveSystem (key);
272     }
274     GT_1trace (curTrace, GT_LEAVE, "Ipc_detach", status);
276     return  (status);
279 /*
280  *  ======== Ipc_getConfig ========
281  */
282 Void Ipc_getConfig (Ipc_Config * cfgParams)
284     IArg key;
286     GT_1trace (curTrace, GT_ENTER, "Ipc_getConfig", cfgParams);
288     GT_assert (curTrace, (cfgParams != NULL));
290 #if !defined(SYSLINK_BUILD_OPTIMIZE)
291     if (cfgParams == NULL) {
292         /* No retVal since this is a Void function. */
293         GT_setFailureReason (curTrace,
294                              GT_4CLASS,
295                              "Ipc_getConfig",
296                              Ipc_E_INVALIDARG,
297                              "Argument of type (Ipc_Config *) passed "
298                              "is null!");
299     }
300     else {
301 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
302         key = Gate_enterSystem ();
303         if (Ipc_module->refCount != 0) {
304             Memory_copy ((Ptr) cfgParams,
305                          (Ptr) &Ipc_module->cfg,
306                          sizeof (Ipc_Config));
307         }
308         Gate_leaveSystem (key);
309 #if !defined(SYSLINK_BUILD_OPTIMIZE)
310     }
311 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
313     GT_0trace (curTrace, GT_LEAVE, "Ipc_getConfig");
317 /* Sets up Ipc for this processor. */
318 Int Ipc_setup (const Ipc_Config * cfg)
320     Int             status = Ipc_S_SUCCESS;
321     Ipc_Config      tmpCfg;
322     IArg            key;
323     Int             i;
325     GT_1trace (curTrace, GT_ENTER, "Ipc_setup", cfg);
327     key = Gate_enterSystem ();
328     Ipc_module->refCount++;
330     /* This sets the refCount variable is not initialized, upper 16 bits is
331      * written with module Id to ensure correctness of refCount variable.
332      */
333     if (Ipc_module->refCount > 1) {
334         status = Ipc_S_ALREADYSETUP;
335         GT_0trace (curTrace,
336                    GT_2CLASS,
337                    "Ipc Module already initialized!");
338         Gate_leaveSystem (key);
339     }
340     else {
341         Gate_leaveSystem (key);
342         if (cfg == NULL) {
343             Ipc_getConfig (&tmpCfg);
344             cfg = &tmpCfg;
345         }
347         /* Copy the cfg */
348         Memory_copy ((Ptr) &Ipc_module->cfg,
349                      (Ptr) cfg,
350                      sizeof (Ipc_Config));
352         status = Platform_setup ((Ipc_Config *)cfg);
353         if (status < 0) {
354             key = Gate_enterSystem ();
355             Ipc_module->refCount--;
356             Gate_leaveSystem (key);
357             status = Ipc_E_FAIL;
358             GT_setFailureReason (curTrace,
359                                  GT_4CLASS,
360                                  "Ipc_setup",
361                                  status,
362                                  "Platform_setup failed!");
363         }
365         /* Following can be done regardless of status */
366         for (i = 0; i < MultiProc_getNumProcessors (); i++) {
367             Ipc_module->procEntry [i].isAttached = FALSE;
368         }
369     }
371     GT_1trace (curTrace, GT_LEAVE, "Ipc_setup", status);
373     /*! @retval Ipc_S_SUCCESS Operation successful */
374     return status;
378 /* Destroys Ipc for this processor. */
379 Int
380 Ipc_destroy (Void)
382     Int status = Ipc_S_SUCCESS;
383     IArg  key;
385     GT_0trace (curTrace, GT_ENTER, "Ipc_destroy");
387     key = Gate_enterSystem ();
388     Ipc_module->refCount--;
389 #if !defined(SYSLINK_BUILD_OPTIMIZE)
390     if (Ipc_module->refCount < 0) {
391         Gate_leaveSystem (key);
392         /*! @retval Ipc_E_INVALIDSTATE Module was not initialized */
393         status = Ipc_E_INVALIDSTATE;
394         GT_setFailureReason (curTrace,
395                              GT_4CLASS,
396                              "Ipc_destroy",
397                              status,
398                              "Module was not initialized!");
399     }
400     else {
401 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
402         if (Ipc_module->refCount == 0) {
403             Gate_leaveSystem (key);
404             status = Platform_destroy ();
405             if (status < 0) {
406                 status = Ipc_E_FAIL;
407                 GT_setFailureReason (curTrace,
408                                      GT_4CLASS,
409                                      "Ipc_destroy",
410                                      status,
411                                      "Platform_destroy failed!");
412             }
413         }
414         else {
415             Gate_leaveSystem (key);
416         }
417 #if !defined(SYSLINK_BUILD_OPTIMIZE)
418     }
419 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
421     GT_1trace (curTrace, GT_LEAVE, "Ipc_destroy", status);
423     /*! @retval Ipc_S_SUCCESS Operation successful */
424     return status;
428 #if defined (__cplusplus)
430 #endif /* defined (__cplusplus) */