1 /*
2 * Copyright (c) 2013-2015, 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>
45 #include <ti/syslink/inc/usr/Qnx/GateHWSpinlockDrv.h>
46 #include <ti/syslink/inc/GateHWSpinlockDrvDefs.h>
47 #include <ti/syslink/inc/_GateHWSpinlock.h>
49 #include <ti/syslink/utils/IGateProvider.h>
51 #include <ti/syslink/utils/GateMutex.h>
53 /* Module level headers */
54 #include <ti/syslink/utils/String.h>
56 #include <_IpcLog.h>
58 #include <assert.h>
59 #include <string.h>
60 #include <stdlib.h>
61 #include <sys/mman.h>
64 /* =============================================================================
65 * Structures & Enums
66 * =============================================================================
67 */
68 /* GateHWSpinlock instance object */
69 struct GateHWSpinlock_Object {
70 IGateProvider_SuperObject; /* For inheritance from IGateProvider */
71 UInt lockNum;
72 UInt nested;
73 IGateProvider_Handle localGate;
74 int token; /* HWSpinlock token */
75 };
78 /* =============================================================================
79 * Globals
80 * =============================================================================
81 */
82 GateHWSpinlock_Module_State _GateHWSpinlock_state =
83 {
84 .vAddr = NULL,
85 .gmHandle = NULL,
86 .cfg.numLocks = 128,
87 .cfg.baseAddr = 0,
88 .cfg.offset = 0,
89 .cfg.size = 0,
90 .numLocks = 128u
91 };
93 static GateHWSpinlock_Module_State *Mod = &_GateHWSpinlock_state;
95 static GateHWSpinlock_Params GateHWSpinlock_defInstParams =
96 {
97 .resourceId = 0,
98 .openFlag = FALSE,
99 .regionId = 0,
100 .sharedAddr = NULL
101 };
103 /* traces in this file are controlled via _GateHWSpinlock_verbose */
104 Bool _GateHWSpinlock_verbose = FALSE;
105 #define verbose _GateHWSpinlock_verbose
107 /* =============================================================================
108 * APIS
109 * =============================================================================
110 */
111 /*
112 * Function to start the GateHWSpinlock module.
113 */
114 Int32 GateHWSpinlock_start(Void)
115 {
116 Int32 status = GateHWSpinlock_S_SUCCESS;
117 UInt32 dst;
119 GateHWSpinlock_getConfig(&Mod->cfg);
121 /* map the hardware lock registers into the local address space */
122 if (status == GateHWSpinlock_S_SUCCESS) {
123 dst = (UInt32)mmap(NULL, Mod->cfg.size,
124 (PROT_READ | PROT_WRITE | PROT_NOCACHE),
125 (MAP_PHYS|MAP_SHARED), NOFD,
126 (off_t)Mod->cfg.baseAddr);
128 if (dst == (UInt32)MAP_FAILED) {
129 PRINTVERBOSE0("GateHWSpinlock_start: Memory map failed")
130 status = GateHWSpinlock_E_OSFAILURE;
131 }
132 else {
133 Mod->vAddr = (UInt32 *)(dst + Mod->cfg.offset);
134 status = GateHWSpinlock_S_SUCCESS;
135 }
136 }
138 /* create GateMutex for local protection*/
139 if (status == GateHWSpinlock_S_SUCCESS) {
140 Mod->gmHandle = GateMutex_create(NULL, NULL);
142 if (Mod->gmHandle == NULL) {
143 PRINTVERBOSE0("GateHWSpinlock_start: GateMutex create failed")
144 status = GateHWSpinlock_E_FAIL;
145 GateHWSpinlock_stop();
146 }
147 }
149 return (status);
150 }
152 /*
153 * Function to stop the GateHWSpinlock module.
154 */
155 Int GateHWSpinlock_stop(Void)
156 {
157 Int32 status = GateHWSpinlock_S_SUCCESS;
159 /* delete GateMutex */
160 if (Mod->gmHandle != NULL) {
161 status = GateMutex_delete(&Mod->gmHandle);
162 }
164 /* release lock register mapping */
165 if (Mod->vAddr != NULL) {
166 munmap((void *)Mod->vAddr, Mod->cfg.size);
167 }
169 return(status);
170 }
172 /*
173 * Initialize parameter structure
174 */
175 Void GateHWSpinlock_Params_init(GateHWSpinlock_Params *params)
176 {
177 assert(params != NULL);
179 memcpy(params, &GateHWSpinlock_defInstParams,
180 sizeof(GateHWSpinlock_Params));
181 }
183 /*
184 * Create a GateHWSpinlock instance
185 */
186 /* TODO: change the function to accept a local gate. Do this on all platforms */
187 GateHWSpinlock_Handle GateHWSpinlock_create(GateHWSpinlock_LocalProtect
188 localProtect, const GateHWSpinlock_Params * params)
189 {
190 GateHWSpinlock_Object * obj = (GateHWSpinlock_Object *)calloc(1,
191 sizeof (GateHWSpinlock_Object));
193 if (!obj) {
194 PRINTVERBOSE0("GateHWSpinlock_create: memory allocation failure")
195 return NULL;
196 }
198 IGateProvider_ObjectInitializer(obj, GateHWSpinlock);
199 /* TODO: handle more local protection types */
200 obj->localGate = (IGateProvider_Handle)Mod->gmHandle;
201 obj->lockNum = params->resourceId;
202 obj->nested = 0;
204 return (GateHWSpinlock_Handle)obj;
205 }
207 /*
208 * Delete a GateHWSpinlock instance
209 */
210 Int GateHWSpinlock_delete (GateHWSpinlock_Handle * handle)
211 {
212 GateHWSpinlock_Object * obj;
213 Int status = GateHWSpinlock_S_SUCCESS;
215 if (handle == NULL) {
216 return GateHWSpinlock_E_INVALIDARG;
217 }
218 if (*handle == NULL) {
219 return GateHWSpinlock_E_INVALIDARG;
220 }
222 obj = (GateHWSpinlock_Object *)(*handle);
224 free(obj);
225 *handle = NULL;
227 return (status);
228 }
230 /*
231 * Enter a GateHWSpinlock instance
232 */
233 IArg GateHWSpinlock_enter(GateHWSpinlock_Object *obj)
234 {
235 volatile UInt32 *baseAddr = Mod->vAddr;
236 IArg key;
238 key = IGateProvider_enter(obj->localGate);
240 /* if gate already entered, just return with current key */
241 obj->nested++;
242 if (obj->nested > 1) {
243 return(key);
244 }
246 /* enter the spinlock */
247 while (1) {
248 /* read the spinlock, returns non-zero when we get it */
249 if (baseAddr[obj->lockNum] == 0) {
250 break;
251 }
252 obj->nested--;
253 IGateProvider_leave(obj->localGate, key);
254 key = IGateProvider_enter(obj->localGate);
255 obj->nested++; /* re-nest the gate */
256 }
258 return (key);
259 }
261 /*
262 * Leave a GateHWSpinlock instance
263 */
264 Int GateHWSpinlock_leave(GateHWSpinlock_Object *obj, IArg key)
265 {
266 volatile UInt32 *baseAddr = Mod->vAddr;
268 obj->nested--;
270 /* release the spinlock if not nested */
271 if (obj->nested == 0) {
272 baseAddr[obj->lockNum] = 0;
273 }
275 IGateProvider_leave(obj->localGate, key);
277 return GateHWSpinlock_S_SUCCESS;
278 }