]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/family/f2837x/NotifyDriverCirc.c
d9d35b462247c2ea4a81b338fbee9e818c7e11f2
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / f2837x / NotifyDriverCirc.c
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);
134 /*
135  *  ======== NotifyDriverCirc_Instance_finalize ========
136  */
137 Void NotifyDriverCirc_Instance_finalize(NotifyDriverCirc_Object *obj)
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);
149 /*
150  *  ======== NotifyDriverCirc_registerEvent ========
151  */
152 Void NotifyDriverCirc_registerEvent(NotifyDriverCirc_Object *obj,
153                                     UInt32 eventId)
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);
170 /*
171  *  ======== NotifyDriverCirc_unregisterEvent ========
172  */
173 Void NotifyDriverCirc_unregisterEvent(NotifyDriverCirc_Object *obj,
174                                       UInt32 eventId)
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);
191 /*
192  *  ======== NotifyDriverCirc_sendEvent ========
193  */
194 Int NotifyDriverCirc_sendEvent(NotifyDriverCirc_Object *obj,
195                                UInt32 eventId,
196                                UInt32 payload,
197                                Bool  waitClear)
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);
258 /*
259  *  ======== NotifyDriverCirc_disable ========
260  */
261 Void NotifyDriverCirc_disable(NotifyDriverCirc_Object *obj)
263     /* Disable the incoming interrupt line */
264     NotifyDriverCirc_intDisable();
267 /*
268  *  ======== NotifyDriverCirc_enable ========
269  */
270 Void NotifyDriverCirc_enable(NotifyDriverCirc_Object *obj)
272     /* Enable the incoming interrupt line */
273     NotifyDriverCirc_intEnable();
276 /*
277  *  ======== NotifyDriverCirc_disableEvent ========
278  *  This function disbales all events.
279  */
280 Void NotifyDriverCirc_disableEvent(NotifyDriverCirc_Object *obj,
281                                    UInt32 eventId)
283     /* NotifyDriverCirc_disableEvent not supported by this driver */
284     Assert_isTrue(FALSE, NotifyDriverCirc_A_notSupported);
287 /*
288  *  ======== NotifyDriverCirc_enableEvent ========
289  *  This function enables all events.
290  */
291 Void NotifyDriverCirc_enableEvent(NotifyDriverCirc_Object *obj,
292                                   UInt32 eventId)
294     /* NotifyDriverCirc_enableEvent not supported by this driver */
295     Assert_isTrue(FALSE, NotifyDriverCirc_A_notSupported);
298 /*
299  *************************************************************************
300  *                       Module functions
301  *************************************************************************
302  */
304 /*
305  *  ======== NotifyDriverCirc_sharedMemReq ========
306  */
307 SizeT NotifyDriverCirc_sharedMemReq(const NotifyDriverCirc_Params *params)
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);
327 /*
328  *************************************************************************
329  *                       Internal functions
330  *************************************************************************
331  */
332 /*
333  *  ======== NotifyDriverCirc_intEnable ========
334  *  Enable remote processor interrupt
335  */
336 Void NotifyDriverCirc_intEnable()
338     Hwi_enableInterrupt(NotifyDriverCirc_localIntId);
341 /*
342  *  ======== NotifyDriverCirc_intDisable ========
343  *  Disables remote processor interrupt
344  */
345 Void NotifyDriverCirc_intDisable()
347     Hwi_disableInterrupt(NotifyDriverCirc_localIntId);
350 /*
351  *  ======== NotifyDriverCirc_intSend ========
352  *  Send interrupt to the remote processor
353  */
354 Void NotifyDriverCirc_intSend()
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);
373 /*
374  *  ======== NotifyDriverCirc_intClear ========
375  *  Clear interrupt
376  */
377 UInt NotifyDriverCirc_intClear()
379     volatile UInt16 *ack = (volatile UInt16 *)IPCACK;
381     *ack = 1 << IpcMgr_ipcSetFlag;
383     return (0);
386 /*
387  *  ======== NotifyDriverCirc_isr ========
388  */
389 Void NotifyDriverCirc_isr(UArg arg)
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     }
431 /*
432  *  ======== NotifyDriverCirc_setNotifyHandle ========
433  */
434 Void NotifyDriverCirc_setNotifyHandle(NotifyDriverCirc_Object *obj,
435                                       Ptr notifyHandle)
437     /* Internally used, so no Assert needed */
438     obj->notifyHandle = (ti_sdo_ipc_Notify_Handle)notifyHandle;