df6375f1b808a4a02cbf2557d2bb3137db4e0521
[ipc/ipcdev.git] / qnx / src / api / gates / GateHWSpinlock.c
1 /*
2  * Copyright (c) 2013, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 /*
34  *  ======== GateHWSpinlock.c ========
35  */
37 /* Standard headers */
38 #include <ti/ipc/Std.h>
40 /* Utilities & OSAL headers */
41 #include <ti/ipc/MultiProc.h>
42 #include <ti/ipc/GateMP.h>
44 #include <ti/syslink/inc/GateHWSpinlock.h>
46 #include <ti/syslink/utils/IGateProvider.h>
48 /*
49  * TODO: does this belong in ti/ipc/Std.h? We should consider getting rid of
50  *       error blocks from the GateMutex.h interface.
51  */
52 typedef UInt32            Error_Block;
53 #include <ti/syslink/utils/GateMutex.h>
55 /* Module level headers */
56 #include <ti/syslink/utils/String.h>
58 #include <_IpcLog.h>
60 #include <assert.h>
61 #include <string.h>
62 #include <stdlib.h>
63 #include <sys/mman.h>
65 /*
66  * TODO: Hardcoding these for now. In daemon, we should ideally pass these in
67  * through config in GateHWSpinlock_setup and user lib can query the daemon.
68  */
69 #define HWSPINLOCK_BASE             0x4A0F6000
70 #define HWSPINLOCK_SIZE             0x1000
71 #define HWSPINLOCK_OFFSET           0x800
74 /* =============================================================================
75  * Structures & Enums
76  * =============================================================================
77  */
78 /* GateHWSpinlock Module Local State */
79 typedef struct {
80     UInt32 *                        baseAddr;   /* base addr lock registers */
81     GateMutex_Handle                gmHandle;   /* handle to gate mutex */
82 } GateHWSpinlock_Module_State;
84 /* GateHWSpinlock instance object */
85 struct GateHWSpinlock_Object {
86     IGateProvider_SuperObject; /* For inheritance from IGateProvider */
87     UInt                        lockNum;
88     UInt                        nested;
89     IGateProvider_Handle        localGate;
90     int                         token;  /* HWSpinlock token */
91 };
94 /* =============================================================================
95  * Globals
96  * =============================================================================
97  */
98 static GateHWSpinlock_Module_State GateHWSpinlock_state =
99 {
100     .baseAddr = NULL,
101     .gmHandle = NULL
102 };
104 static GateHWSpinlock_Module_State *Mod = &GateHWSpinlock_state;
106 static GateHWSpinlock_Params GateHWSpinlock_defInstParams =
108     .resourceId = 0,
109     .openFlag   = FALSE,
110     .regionId   = 0,
111     .sharedAddr = NULL
112 };
114 static Bool verbose = FALSE;
116 /* =============================================================================
117  * APIS
118  * =============================================================================
119  */
120 /*
121  *  Function to start the GateHWSpinlock module.
122  */
123 Int32 GateHWSpinlock_start(Void)
125     Int32               status = GateHWSpinlock_S_SUCCESS;
126     UInt32              dst;
128     /* map the hardware lock registers into the local address space */
129     if (status == GateHWSpinlock_S_SUCCESS) {
130         dst = (UInt32)mmap(NULL, HWSPINLOCK_SIZE,
131                             (PROT_READ | PROT_WRITE | PROT_NOCACHE),
132                             (MAP_PHYS|MAP_SHARED), NOFD,
133                             (off_t)HWSPINLOCK_BASE);
135         if (dst == (UInt32)MAP_FAILED) {
136             PRINTVERBOSE0("GateHWSpinlock_start: Memory map failed")
137             status = GateHWSpinlock_E_OSFAILURE;
138         }
139         else {
140             Mod->baseAddr = (UInt32 *)(dst + HWSPINLOCK_OFFSET);
141             status = GateHWSpinlock_S_SUCCESS;
142         }
143     }
145     /* create GateMutex for local protection*/
146     if (status == GateHWSpinlock_S_SUCCESS) {
147         Mod->gmHandle = GateMutex_create(NULL, NULL);
149         if (Mod->gmHandle == NULL) {
150             PRINTVERBOSE0("GateHWSpinlock_start: GateMutex create failed")
151             status = GateHWSpinlock_E_FAIL;
152             GateHWSpinlock_stop();
153         }
154     }
156     return (status);
159 /*
160  *  Function to stop the GateHWSpinlock module.
161  */
162 Int GateHWSpinlock_stop(Void)
164     Int32               status = GateHWSpinlock_S_SUCCESS;
166     /* delete GateMutex */
167     if (Mod->gmHandle != NULL) {
168         status = GateMutex_delete(&Mod->gmHandle);
169     }
171     /* release lock register mapping */
172     if (Mod->baseAddr != NULL) {
173         munmap((void *)HWSPINLOCK_BASE, HWSPINLOCK_SIZE);
174     }
176     return(status);
179 /*
180  *  Initialize parameter structure
181  */
182 Void GateHWSpinlock_Params_init(GateHWSpinlock_Params *params)
184     assert(params != NULL);
186     memcpy(params, &GateHWSpinlock_defInstParams,
187         sizeof(GateHWSpinlock_Params));
190 /*
191  * Create a GateHWSpinlock instance
192  */
193 /* TODO: change the function to accept a local gate. Do this on all platforms */
194 GateHWSpinlock_Handle GateHWSpinlock_create(GateHWSpinlock_LocalProtect
195     localProtect, const GateHWSpinlock_Params * params)
197     GateHWSpinlock_Object * obj = (GateHWSpinlock_Object *)calloc(1,
198         sizeof (GateHWSpinlock_Object));
200     if (!obj) {
201         PRINTVERBOSE0("GateHWSpinlock_create: memory allocation failure")
202         return NULL;
203     }
205     IGateProvider_ObjectInitializer(obj, GateHWSpinlock);
206     /* TODO: handle more local protection types */
207     obj->localGate = (IGateProvider_Handle)Mod->gmHandle;
208     obj->lockNum = params->resourceId;
209     obj->nested = 0;
211     return (GateHWSpinlock_Handle)obj;
214 /*
215  * Delete a GateHWSpinlock instance
216  */
217 Int GateHWSpinlock_delete (GateHWSpinlock_Handle * handle)
219     GateHWSpinlock_Object * obj;
220     Int  status = GateHWSpinlock_S_SUCCESS;
222     if (handle == NULL) {
223         return GateHWSpinlock_E_INVALIDARG;
224     }
225     if (*handle == NULL) {
226         return GateHWSpinlock_E_INVALIDARG;
227     }
229     obj = (GateHWSpinlock_Object *)(*handle);
231     free(obj);
232     *handle = NULL;
234     return (status);
237 /*
238  *  Enter a GateHWSpinlock instance
239  */
240 IArg GateHWSpinlock_enter(GateHWSpinlock_Object *obj)
242     volatile UInt32 *baseAddr = Mod->baseAddr;
243     IArg key;
245     key = IGateProvider_enter(obj->localGate);
247     /* if gate already entered, just return with current key */
248     obj->nested++;
249     if (obj->nested > 1) {
250         return(key);
251     }
253     /* enter the spinlock */
254     while (1) {
255         /* read the spinlock, returns non-zero when we get it */
256         if (baseAddr[obj->lockNum] == 0) {
257             break;
258         }
259         obj->nested--;
260         IGateProvider_leave(obj->localGate, key);
261         key = IGateProvider_enter(obj->localGate);
262         obj->nested++; /* re-nest the gate */
263     }
265     return (key);
268 /*
269  *  Leave a GateHWSpinlock instance
270  */
271 Int GateHWSpinlock_leave(GateHWSpinlock_Object *obj, IArg key)
273     volatile UInt32 *baseAddr = Mod->baseAddr;
275     obj->nested--;
277     /* release the spinlock if not nested */
278     if (obj->nested == 0) {
279         baseAddr[obj->lockNum] = 0;
280     }
282     IGateProvider_leave(obj->localGate, key);
284     return GateHWSpinlock_S_SUCCESS;