d9d35b462247c2ea4a81b338fbee9e818c7e11f2
1 /*
2 * Copyright (c) 2014, 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 */
32 /*
33 * ======== NotifyDriverCirc.c ========
34 */
36 #include <xdc/std.h>
38 #include <xdc/runtime/Assert.h>
39 #include <xdc/runtime/Timestamp.h>
41 #include <ti/sysbios/family/c28/Hwi.h>
43 #include <ti/sdo/ipc/family/f2837x/IpcMgr.h>
44 #include <ti/sdo/ipc/interfaces/INotifyDriver.h>
46 #include "package/internal/NotifyDriverCirc.xdc.h"
48 #include <ti/sdo/ipc/_Notify.h>
49 #include <ti/sdo/utils/_MultiProc.h>
51 /* Bit mask operations */
52 #define SET_BIT(num,pos) ((num) |= (1u << (pos)))
53 #define CLEAR_BIT(num,pos) ((num) &= ~(1u << (pos)))
54 #define TEST_BIT(num,pos) ((num) & (1u << (pos)))
56 #define IPCACK (0x50000)
57 #define IPCSTS (IPCACK + 0x2)
58 #define IPCSET (IPCACK + 0x4)
59 #define IPCCLR (IPCACK + 0x6)
60 #define IPCFLG (IPCACK + 0x8)
63 /*
64 **************************************************************
65 * Instance functions
66 **************************************************************
67 */
69 /*
70 * ======== NotifyDriverCirc_Instance_init ========
71 */
72 Void NotifyDriverCirc_Instance_init(NotifyDriverCirc_Object *obj,
73 const NotifyDriverCirc_Params *params)
74 {
75 SizeT ctrlSize, circBufSize;
76 Hwi_Params hwiParams;
78 /*
79 * This code assumes that the device's C28 and M3 MultiProc Ids
80 * are next to each other (e.g. n and n + 1) and that the first
81 * one is even (e.g. n is even).
82 */
83 /* set the remote processor's id */
84 if (MultiProc_self() & 1) {
85 /* I'm odd */
86 obj->remoteProcId = MultiProc_self() - 1;
87 }
88 else {
89 /* I'm even */
90 obj->remoteProcId = MultiProc_self() + 1;
91 }
93 /* calculate the circular buffer size one-way */
94 circBufSize = sizeof(NotifyDriverCirc_EventEntry) *
95 NotifyDriverCirc_numMsgs;
97 /* calculate the control size one-way */
98 ctrlSize = sizeof(Bits32);
100 /*
101 * Init put/get buffer and index pointers.
102 */
103 obj->putBuffer = params->writeAddr;
105 obj->putWriteIndex = (Bits32 *)((UInt32)obj->putBuffer + circBufSize);
107 obj->getReadIndex = (Bits32 *)((UInt32)obj->putWriteIndex + ctrlSize);
109 obj->getBuffer = params->readAddr;
111 obj->getWriteIndex = (Bits32 *)((UInt32)obj->getBuffer + circBufSize);
113 obj->putReadIndex = (Bits32 *)((UInt32)obj->getWriteIndex + ctrlSize);
115 /* init the putWrite and getRead Index to 0 */
116 obj->putWriteIndex[0] = 0;
117 obj->getReadIndex[0] = 0;
119 /* clear interrupt */
120 NotifyDriverCirc_intClear();
122 /* plugged interrupt */
123 Hwi_Params_init(&hwiParams);
124 hwiParams.arg = (UArg)obj;
125 Hwi_create(NotifyDriverCirc_localIntId,
126 (Hwi_FuncPtr)NotifyDriverCirc_isr,
127 &hwiParams,
128 NULL);
130 /* Enable the interrupt */
131 Hwi_enableInterrupt(NotifyDriverCirc_localIntId);
132 }
134 /*
135 * ======== NotifyDriverCirc_Instance_finalize ========
136 */
137 Void NotifyDriverCirc_Instance_finalize(NotifyDriverCirc_Object *obj)
138 {
139 Hwi_Handle hwiHandle;
141 /* Disable the interrupt source */
142 NotifyDriverCirc_intDisable();
144 /* Delete the Hwi */
145 hwiHandle = Hwi_getHandle(NotifyDriverCirc_localIntId);
146 Hwi_delete(&hwiHandle);
147 }
149 /*
150 * ======== NotifyDriverCirc_registerEvent ========
151 */
152 Void NotifyDriverCirc_registerEvent(NotifyDriverCirc_Object *obj,
153 UInt32 eventId)
154 {
155 UInt hwiKey;
157 /*
158 * Disable interrupt line to ensure that isr doesn't
159 * preempt registerEvent and encounter corrupt state
160 */
161 hwiKey = Hwi_disable();
163 /* Set the 'registered' bit */
164 SET_BIT(obj->evtRegMask, eventId);
166 /* Restore the interrupt line */
167 Hwi_restore(hwiKey);
168 }
170 /*
171 * ======== NotifyDriverCirc_unregisterEvent ========
172 */
173 Void NotifyDriverCirc_unregisterEvent(NotifyDriverCirc_Object *obj,
174 UInt32 eventId)
175 {
176 UInt hwiKey;
178 /*
179 * Disable interrupt line to ensure that isr doesn't
180 * preempt registerEvent and encounter corrupt state
181 */
182 hwiKey = Hwi_disable();
184 /* Clear the registered bit */
185 CLEAR_BIT(obj->evtRegMask, eventId);
187 /* Restore the interrupt line */
188 Hwi_restore(hwiKey);
189 }
191 /*
192 * ======== NotifyDriverCirc_sendEvent ========
193 */
194 Int NotifyDriverCirc_sendEvent(NotifyDriverCirc_Object *obj,
195 UInt32 eventId,
196 UInt32 payload,
197 Bool waitClear)
198 {
199 Bool loop = FALSE;
200 UInt hwiKey;
201 UInt32 writeIndex, readIndex;
202 NotifyDriverCirc_EventEntry *eventEntry;
204 /* Retrieve the get Index. */
205 readIndex = obj->putReadIndex[0];
207 do {
208 /* disable interrupts */
209 hwiKey = Hwi_disable();
211 /* retrieve the put index */
212 writeIndex = obj->putWriteIndex[0];
214 /* if slot available 'break' out of loop */
215 if (((writeIndex + 1) & NotifyDriverCirc_maxIndex) != readIndex) {
216 break;
217 }
219 /* restore interrupts */
220 Hwi_restore(hwiKey);
222 /* check to make sure code has looped */
223 if (loop && !waitClear) {
224 /* if no slot available and waitClear is 'FALSE' */
225 return (Notify_E_FAIL);
226 }
228 /* re-read the get count */
229 readIndex = obj->putReadIndex[0];
231 /* convey that the code has looped around */
232 loop = TRUE;
234 } while (1);
236 /* interrupts are disabled at this point */
238 /* calculate the next available entry */
239 eventEntry = (NotifyDriverCirc_EventEntry *)((UInt32)obj->putBuffer +
240 (writeIndex * sizeof(NotifyDriverCirc_EventEntry)));
242 /* Set the eventId field and payload for the entry */
243 eventEntry->eventid = eventId;
244 eventEntry->payload = payload;
246 /* update the putWriteIndex */
247 obj->putWriteIndex[0] = (writeIndex + 1) & NotifyDriverCirc_maxIndex;
249 /* restore interrupts */
250 Hwi_restore(hwiKey);
252 /* Send an interrupt to the Remote Processor */
253 NotifyDriverCirc_intSend();
255 return (Notify_S_SUCCESS);
256 }
258 /*
259 * ======== NotifyDriverCirc_disable ========
260 */
261 Void NotifyDriverCirc_disable(NotifyDriverCirc_Object *obj)
262 {
263 /* Disable the incoming interrupt line */
264 NotifyDriverCirc_intDisable();
265 }
267 /*
268 * ======== NotifyDriverCirc_enable ========
269 */
270 Void NotifyDriverCirc_enable(NotifyDriverCirc_Object *obj)
271 {
272 /* Enable the incoming interrupt line */
273 NotifyDriverCirc_intEnable();
274 }
276 /*
277 * ======== NotifyDriverCirc_disableEvent ========
278 * This function disbales all events.
279 */
280 Void NotifyDriverCirc_disableEvent(NotifyDriverCirc_Object *obj,
281 UInt32 eventId)
282 {
283 /* NotifyDriverCirc_disableEvent not supported by this driver */
284 Assert_isTrue(FALSE, NotifyDriverCirc_A_notSupported);
285 }
287 /*
288 * ======== NotifyDriverCirc_enableEvent ========
289 * This function enables all events.
290 */
291 Void NotifyDriverCirc_enableEvent(NotifyDriverCirc_Object *obj,
292 UInt32 eventId)
293 {
294 /* NotifyDriverCirc_enableEvent not supported by this driver */
295 Assert_isTrue(FALSE, NotifyDriverCirc_A_notSupported);
296 }
298 /*
299 *************************************************************************
300 * Module functions
301 *************************************************************************
302 */
304 /*
305 * ======== NotifyDriverCirc_sharedMemReq ========
306 */
307 SizeT NotifyDriverCirc_sharedMemReq(const NotifyDriverCirc_Params *params)
308 {
309 SizeT memReq;
311 /* Ensure that params is non-NULL */
312 Assert_isTrue(params != NULL, IpcMgr_A_internal);
314 /*
315 * Amount of shared memory:
316 * 1 putBuffer with numMsgs +
317 * 1 putWriteIndex ptr +
318 * 1 putReadIndex ptr
319 */
320 memReq =
321 (sizeof(NotifyDriverCirc_EventEntry) * NotifyDriverCirc_numMsgs)
322 + (2 * sizeof(Bits32));
324 return (memReq);
325 }
327 /*
328 *************************************************************************
329 * Internal functions
330 *************************************************************************
331 */
332 /*
333 * ======== NotifyDriverCirc_intEnable ========
334 * Enable remote processor interrupt
335 */
336 Void NotifyDriverCirc_intEnable()
337 {
338 Hwi_enableInterrupt(NotifyDriverCirc_localIntId);
339 }
341 /*
342 * ======== NotifyDriverCirc_intDisable ========
343 * Disables remote processor interrupt
344 */
345 Void NotifyDriverCirc_intDisable()
346 {
347 Hwi_disableInterrupt(NotifyDriverCirc_localIntId);
348 }
350 /*
351 * ======== NotifyDriverCirc_intSend ========
352 * Send interrupt to the remote processor
353 */
354 Void NotifyDriverCirc_intSend()
355 {
356 volatile UInt16 *set = (volatile UInt16 *)IPCSET;
357 volatile UInt32 *clear = (volatile UInt32 *)IPCCLR;
358 UInt hwiKey;
360 /* Make sure multiple threads are not hitting this at the same time */
361 hwiKey = Hwi_disable();
363 /* Make sure we get a leading edge... */
364 *clear = 1 << IpcMgr_ipcSetFlag;
366 /* Signal the other side */
367 *set = 1 << IpcMgr_ipcSetFlag;
369 /* Restore the interrupt line */
370 Hwi_restore(hwiKey);
371 }
373 /*
374 * ======== NotifyDriverCirc_intClear ========
375 * Clear interrupt
376 */
377 UInt NotifyDriverCirc_intClear()
378 {
379 volatile UInt16 *ack = (volatile UInt16 *)IPCACK;
381 *ack = 1 << IpcMgr_ipcSetFlag;
383 return (0);
384 }
386 /*
387 * ======== NotifyDriverCirc_isr ========
388 */
389 Void NotifyDriverCirc_isr(UArg arg)
390 {
391 NotifyDriverCirc_EventEntry *eventEntry;
392 NotifyDriverCirc_Object *obj;
393 UInt32 writeIndex, readIndex;
395 obj = (NotifyDriverCirc_Object *)arg;
397 /* Make sure the NotifyDriverCirc_Object is not NULL */
398 Assert_isTrue(obj != NULL, IpcMgr_A_internal);
400 /* get the writeIndex and readIndex */
401 writeIndex = obj->getWriteIndex[0];
402 readIndex = obj->getReadIndex[0];
404 /* get the event */
405 eventEntry = &(obj->getBuffer[readIndex]);
407 /* if writeIndex != readIndex then there is an event to process */
408 while (writeIndex != readIndex) {
409 /*
410 * Check to make sure event is registered. If the event
411 * is not registered, the event is not processed and is lost.
412 */
413 if (TEST_BIT(obj->evtRegMask, eventEntry->eventid)) {
414 /* Execute the callback function */
415 ti_sdo_ipc_Notify_exec(obj->notifyHandle,
416 eventEntry->eventid,
417 eventEntry->payload);
418 }
420 /* update the readIndex. */
421 readIndex = ((readIndex + 1) & NotifyDriverCirc_maxIndex);
423 /* set the getReadIndex */
424 obj->getReadIndex[0] = readIndex;
426 /* get the next event */
427 eventEntry = &(obj->getBuffer[readIndex]);
428 }
429 }
431 /*
432 * ======== NotifyDriverCirc_setNotifyHandle ========
433 */
434 Void NotifyDriverCirc_setNotifyHandle(NotifyDriverCirc_Object *obj,
435 Ptr notifyHandle)
436 {
437 /* Internally used, so no Assert needed */
438 obj->notifyHandle = (ti_sdo_ipc_Notify_Handle)notifyHandle;
439 }